commit 0c9dda2f0341591d8f30d6d4de1a7988c3f0d692 Author: HarpyWar Date: Sun Apr 5 21:28:01 2020 +0300 original game source as is diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..871b640 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +HELLFIRE.MPQ +*.COD +*.obj +*.MAP +*.PDB diff --git a/src/APPFAT.CPP b/src/APPFAT.CPP new file mode 100644 index 0000000..73355e9 --- /dev/null +++ b/src/APPFAT.CPP @@ -0,0 +1,785 @@ +//*********************************************************************** +// Assertion System +// +// Copyright (c) 1996 by Blizzard Entertainment. +// All rights reserved. +//*********************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include +#include "storm.h" +#include "resource.h" + + +//*********************************************************************** +// Externals +//*********************************************************************** +void cleanup(BOOL bNormalExit); + + +//*********************************************************************** +//*********************************************************************** +/* +void DebugDump2(const char * pszFmt,va_list args) { + static FILE * f = NULL; + if (! f) f = fopen("c:\\hellfr__.dbg","wt"); + if (! f) return; + vfprintf(f,pszFmt,args); + fflush(f); +} +void __cdecl DebugDump(const char * pszFmt, ...) { + va_list args; + va_start(args,pszFmt); + DebugDump2(pszFmt,args); + va_end(args); +} +*/ + + +//*********************************************************************** +// WARNING: the code below ONLY works on x86 compatible systems +//*********************************************************************** +#ifdef _X86_ +#ifndef NDEBUG +static LONG WINAPI BreakExceptionHdlr(struct _EXCEPTION_POINTERS *pep) { + // if we got a breakpoint exception, we expected it -- keep running + PEXCEPTION_RECORD per = pep->ExceptionRecord; + if (per && per->ExceptionCode == EXCEPTION_BREAKPOINT) { + // in windows 95, the int3 instruction will already be + // skipped by the time we get here. In windows NT, the + // Eip will still point to the int3 instruction. Therefore + // look at the offending byte, and if it is int3 (0xcc) then + // skip over the instruction + BYTE * pInst = (BYTE *) pep->ContextRecord->Eip; + if (*pInst == 0xcc) pep->ContextRecord->Eip += 1; + + // continue execution + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} +#endif +#endif + + +//*********************************************************************** +//*********************************************************************** +void myDebugBreak() { +#ifndef NDEBUG + // -- Save current exception handler and set it + // to a handler which expects a break to occur. + // -- If we are in the debugger, the debugger will + // override our exception handler, and we will + // drop into the debugger. + // -- If there is no debugger present, our exception + // handler will skip over the break instruction + // and allow normal execution of the program + LPTOP_LEVEL_EXCEPTION_FILTER lpLastHdlr; + lpLastHdlr = SetUnhandledExceptionFilter(BreakExceptionHdlr); + + // drop into the debugger + __asm int 3 + + // restore exception handler + SetUnhandledExceptionFilter(lpLastHdlr); +#endif +} + + +//*********************************************************************** +//*********************************************************************** +static void get_ddraw_error(HRESULT ddrval,TCHAR * pszBuf,DWORD dwMaxChars) { + const TCHAR * pszErr; + + // @@ eventually we should get these from our resource file + // so that they can be properly translated and so + // they don't have to stay loaded all the time + + switch (ddrval) { + case DD_OK: + pszErr = "DD_OK"; + break; + case DDERR_ALREADYINITIALIZED: + pszErr = "DDERR_ALREADYINITIALIZED"; + break; + case DDERR_BLTFASTCANTCLIP: + pszErr = "DDERR_BLTFASTCANTCLIP"; + break; + case DDERR_CANNOTATTACHSURFACE: + pszErr = "DDERR_CANNOTATTACHSURFACE"; + break; + case DDERR_CANNOTDETACHSURFACE: + pszErr = "DDERR_CANNOTDETACHSURFACE"; + break; + case DDERR_CANTCREATEDC: + pszErr = "DDERR_CANTCREATEDC"; + break; + case DDERR_CANTDUPLICATE: + pszErr = "DDERR_CANTDUPLICATE"; + break; + case DDERR_CLIPPERISUSINGHWND: + pszErr = "DDERR_CLIPPERISUSINGHWND"; + break; + case DDERR_COLORKEYNOTSET: + pszErr = "DDERR_COLORKEYNOTSET"; + break; + case DDERR_CURRENTLYNOTAVAIL: + pszErr = "DDERR_CURRENTLYNOTAVAIL"; + break; + case DDERR_DIRECTDRAWALREADYCREATED: + pszErr = "DDERR_DIRECTDRAWALREADYCREATED"; + break; + case DDERR_EXCEPTION: + pszErr = "DDERR_EXCEPTION"; + break; + case DDERR_EXCLUSIVEMODEALREADYSET: + pszErr = "DDERR_EXCLUSIVEMODEALREADYSET"; + break; + case DDERR_GENERIC: + pszErr = "DDERR_GENERIC"; + break; + case DDERR_HEIGHTALIGN: + pszErr = "DDERR_HEIGHTALIGN"; + break; + case DDERR_HWNDALREADYSET: + pszErr = "DDERR_HWNDALREADYSET"; + break; + case DDERR_HWNDSUBCLASSED: + pszErr = "DDERR_HWNDSUBCLASSED"; + break; + case DDERR_IMPLICITLYCREATED: + pszErr = "DDERR_IMPLICITLYCREATED"; + break; + case DDERR_INCOMPATIBLEPRIMARY: + pszErr = "DDERR_INCOMPATIBLEPRIMARY"; + break; + case DDERR_INVALIDCAPS: + pszErr = "DDERR_INVALIDCAPS"; + break; + case DDERR_INVALIDCLIPLIST: + pszErr = "DDERR_INVALIDCLIPLIST"; + break; + case DDERR_INVALIDDIRECTDRAWGUID: + pszErr = "DDERR_INVALIDDIRECTDRAWGUID"; + break; + case DDERR_INVALIDMODE: + pszErr = "DDERR_INVALIDMODE"; + break; + case DDERR_INVALIDOBJECT: + pszErr = "DDERR_INVALIDOBJECT"; + break; + case DDERR_INVALIDPARAMS: + pszErr = "DDERR_INVALIDPARAMS"; + break; + case DDERR_INVALIDPIXELFORMAT: + pszErr = "DDERR_INVALIDPIXELFORMAT"; + break; + case DDERR_INVALIDPOSITION: + pszErr = "DDERR_INVALIDPOSITION"; + break; + case DDERR_INVALIDRECT: + pszErr = "DDERR_INVALIDRECT"; + break; + case DDERR_LOCKEDSURFACES: + pszErr = "DDERR_LOCKEDSURFACES"; + break; + case DDERR_NO3D: + pszErr = "DDERR_NO3D"; + break; + case DDERR_NOALPHAHW: + pszErr = "DDERR_NOALPHAHW"; + break; + case DDERR_NOBLTHW: + pszErr = "DDERR_NOBLTHW"; + break; + case DDERR_NOCLIPLIST: + pszErr = "DDERR_NOCLIPLIST"; + break; + case DDERR_NOCLIPPERATTACHED: + pszErr = "DDERR_NOCLIPPERATTACHED"; + break; + case DDERR_NOCOLORCONVHW: + pszErr = "DDERR_NOCOLORCONVHW"; + break; + case DDERR_NOCOLORKEY: + pszErr = "DDERR_NOCOLORKEY"; + break; + case DDERR_NOCOLORKEYHW: + pszErr = "DDERR_NOCOLORKEYHW"; + break; + case DDERR_NOCOOPERATIVELEVELSET: + pszErr = "DDERR_NOCOOPERATIVELEVELSET"; + break; + case DDERR_NODC: + pszErr = "DDERR_NODC"; + break; + case DDERR_NODDROPSHW: + pszErr = "DDERR_NODDROPSHW"; + break; + case DDERR_NODIRECTDRAWHW: + pszErr = "DDERR_NODIRECTDRAWHW"; + break; + case DDERR_NOEMULATION: + pszErr = "DDERR_NOEMULATION"; + break; + case DDERR_NOEXCLUSIVEMODE: + pszErr = "DDERR_NOEXCLUSIVEMODE"; + break; + case DDERR_NOFLIPHW: + pszErr = "DDERR_NOFLIPHW"; + break; + case DDERR_NOGDI: + pszErr = "DDERR_NOGDI"; + break; + case DDERR_NOHWND: + pszErr = "DDERR_NOHWND"; + break; + case DDERR_NOMIRRORHW: + pszErr = "DDERR_NOMIRRORHW"; + break; + case DDERR_NOOVERLAYDEST: + pszErr = "DDERR_NOOVERLAYDEST"; + break; + case DDERR_NOOVERLAYHW: + pszErr = "DDERR_NOOVERLAYHW"; + break; + case DDERR_NOPALETTEATTACHED: + pszErr = "DDERR_NOPALETTEATTACHED"; + break; + case DDERR_NOPALETTEHW: + pszErr = "DDERR_NOPALETTEHW"; + break; + case DDERR_NORASTEROPHW: + pszErr = "DDERR_NORASTEROPHW"; + break; + case DDERR_NOROTATIONHW: + pszErr = "DDERR_NOROTATIONHW"; + break; + case DDERR_NOSTRETCHHW: + pszErr = "DDERR_NOSTRETCHHW"; + break; + case DDERR_NOT4BITCOLOR: + pszErr = "DDERR_NOT4BITCOLOR"; + break; + case DDERR_NOT4BITCOLORINDEX: + pszErr = "DDERR_NOT4BITCOLORINDEX"; + break; + case DDERR_NOT8BITCOLOR: + pszErr = "DDERR_NOT8BITCOLOR"; + break; + case DDERR_NOTAOVERLAYSURFACE: + pszErr = "DDERR_NOTAOVERLAYSURFACE"; + break; + case DDERR_NOTEXTUREHW: + pszErr = "DDERR_NOTEXTUREHW"; + break; + case DDERR_NOTFLIPPABLE: + pszErr = "DDERR_NOTFLIPPABLE"; + break; + case DDERR_NOTFOUND: + pszErr = "DDERR_NOTFOUND"; + break; + case DDERR_NOTLOCKED: + pszErr = "DDERR_NOTLOCKED"; + break; + case DDERR_NOTPALETTIZED: + pszErr = "DDERR_NOTPALETTIZED"; + break; + case DDERR_NOVSYNCHW: + pszErr = "DDERR_NOVSYNCHW"; + break; + case DDERR_NOZBUFFERHW: + pszErr = "DDERR_NOZBUFFERHW"; + break; + case DDERR_NOZOVERLAYHW: + pszErr = "DDERR_NOZOVERLAYHW"; + break; + case DDERR_OUTOFCAPS: + pszErr = "DDERR_OUTOFCAPS"; + break; + case DDERR_OUTOFMEMORY: + pszErr = "DDERR_OUTOFMEMORY"; + break; + case DDERR_OUTOFVIDEOMEMORY: + pszErr = "DDERR_OUTOFVIDEOMEMORY"; + break; + case DDERR_OVERLAYCANTCLIP: + pszErr = "DDERR_OVERLAYCANTCLIP"; + break; + case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: + pszErr = "DDERR_OVERLAYCOLORKEYONLYONEACTIVE"; + break; + case DDERR_OVERLAYNOTVISIBLE: + pszErr = "DDERR_OVERLAYNOTVISIBLE"; + break; + case DDERR_PALETTEBUSY: + pszErr = "DDERR_PALETTEBUSY"; + break; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + pszErr = "DDERR_PRIMARYSURFACEALREADYEXISTS"; + break; + case DDERR_REGIONTOOSMALL: + pszErr = "DDERR_REGIONTOOSMALL"; + break; + case DDERR_SURFACEALREADYATTACHED: + pszErr = "DDERR_SURFACEALREADYATTACHED"; + break; + case DDERR_SURFACEALREADYDEPENDENT: + pszErr = "DDERR_SURFACEALREADYDEPENDENT"; + break; + case DDERR_SURFACEBUSY: + pszErr = "DDERR_SURFACEBUSY"; + break; + case DDERR_SURFACEISOBSCURED: + pszErr = "DDERR_SURFACEISOBSCURED"; + break; + case DDERR_SURFACELOST: + pszErr = "DDERR_SURFACELOST"; + break; + case DDERR_SURFACENOTATTACHED: + pszErr = "DDERR_SURFACENOTATTACHED"; + break; + case DDERR_TOOBIGHEIGHT: + pszErr = "DDERR_TOOBIGHEIGHT"; + break; + case DDERR_TOOBIGSIZE: + pszErr = "DDERR_TOOBIGSIZE"; + break; + case DDERR_TOOBIGWIDTH: + pszErr = "DDERR_TOOBIGWIDTH"; + break; + case DDERR_UNSUPPORTED: + pszErr = "DDERR_UNSUPPORTED"; + break; + case DDERR_UNSUPPORTEDFORMAT: + pszErr = "DDERR_UNSUPPORTEDFORMAT"; + break; + case DDERR_UNSUPPORTEDMASK: + pszErr = "DDERR_UNSUPPORTEDMASK"; + break; + case DDERR_VERTICALBLANKINPROGRESS: + pszErr = "DDERR_VERTICALBLANKINPROGRESS"; + break; + case DDERR_WASSTILLDRAWING: + pszErr = "DDERR_WASSTILLDRAWING"; + break; + case DDERR_WRONGMODE: + pszErr = "DDERR_WRONGMODE"; + break; + case DDERR_XALIGN: + pszErr = "DDERR_XALIGN"; + break; + case DDERR_CANTLOCKSURFACE: + pszErr = "DDERR_CANTLOCKSURFACE"; + break; + case DDERR_CANTPAGELOCK: + pszErr = "DDERR_CANTPAGELOCK"; + break; + case DDERR_CANTPAGEUNLOCK: + pszErr = "DDERR_CANTPAGEUNLOCK"; + break; + case DDERR_DCALREADYCREATED: + pszErr = "DDERR_DCALREADYCREATED"; + break; + case DDERR_INVALIDSURFACETYPE: + pszErr = "DDERR_INVALIDSURFACETYPE"; + break; + case DDERR_NOMIPMAPHW: + pszErr = "DDERR_NOMIPMAPHW"; + break; + case DDERR_NOTPAGELOCKED: + pszErr = "DDERR_NOTPAGELOCKED"; + break; + + default: + const TCHAR szUnknown[] = "DDERR unknown 0x%x"; + app_assert(dwMaxChars >= sizeof(szUnknown) + 10); + sprintf(pszBuf,szUnknown,ddrval); + return; + } + + _tcsncpy(pszBuf,pszErr,dwMaxChars); +} + + +//*********************************************************************** +//*********************************************************************** +static void get_dsound_error(HRESULT dsrval,TCHAR * pszBuf,DWORD dwMaxChars) { + const TCHAR * pszErr; + + // @@ eventually we should get these from our resource file + // so that they can be properly translated and so + // they don't have to stay loaded all the time + + switch(dsrval) { + case DS_OK: + pszErr = "DS_OK"; + break; + case DSERR_ALLOCATED: + pszErr = "DSERR_ALLOCATED"; + break; + case DSERR_ALREADYINITIALIZED: + pszErr = "DSERR_ALREADYINITIALIZED"; + break; + case DSERR_BADFORMAT: + pszErr = "DSERR_BADFORMAT"; + break; + case DSERR_BUFFERLOST: + pszErr = "DSERR_BUFFERLOST"; + break; + case DSERR_CONTROLUNAVAIL: + pszErr = "DSERR_CONTROLUNAVAIL"; + break; + case DSERR_INVALIDCALL: + pszErr = "DSERR_INVALIDCALL"; + break; + case DSERR_INVALIDPARAM: + pszErr = "DSERR_INVALIDPARAM"; + break; + case DSERR_NOAGGREGATION: + pszErr = "DSERR_NOAGGREGATION"; + break; + case DSERR_NODRIVER: + pszErr = "DSERR_NODRIVER"; + break; + case DSERR_OUTOFMEMORY: + pszErr = "DSERR_OUTOFMEMORY"; + break; + case DSERR_PRIOLEVELNEEDED: + pszErr = "DSERR_PRIOLEVELNEEDED"; + break; + case E_NOINTERFACE: + pszErr = "E_NOINTERFACE"; + break; + + default: + const TCHAR szUnknown[] = "DSERR unknown 0x%x"; + app_assert(dwMaxChars >= sizeof(szUnknown) + 10); + sprintf(pszBuf,szUnknown,dsrval); + return; + } + + _tcsncpy(pszBuf,pszErr,dwMaxChars); +} + + +//*********************************************************************** +//*********************************************************************** +// pjw.patch3.start -- changes due to STORM error handling +const TCHAR * strGetError(DWORD dwErr) { + static TCHAR szBuf[256]; + + if (HRESULT_FACILITY(dwErr) == _FACDS) { + get_dsound_error(dwErr,szBuf,sizeof(szBuf) / sizeof(szBuf[0])); + } + else if (HRESULT_FACILITY(dwErr) == _FACDD) { + get_ddraw_error(dwErr,szBuf,sizeof(szBuf) / sizeof(szBuf[0])); + } + else if (SErrGetErrorStr(dwErr,szBuf,sizeof(szBuf) / sizeof(szBuf[0]))) { + // got storm message + } + else if (!FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwErr, + MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + szBuf, + sizeof(szBuf) / sizeof(szBuf[0]), + NULL + )) { + wsprintf(szBuf,"unknown error 0x%08x",dwErr); + } + + // remove trailing newline crap + int nLen = strlen(szBuf); + char * pszTemp = szBuf + nLen - 1; + while (nLen-- > 0) { + pszTemp--; + if (*pszTemp == '\r' || *pszTemp == '\n') + *pszTemp = 0; + else + break; + } + + return szBuf; +} +// pjw.patch3.end + + +//*********************************************************************** +//*********************************************************************** +const TCHAR * strGetLastError() { + return strGetError(GetLastError()); +} + + +//*********************************************************************** +//*********************************************************************** +static void app_debug_msg(const char * pszFmt,va_list args) { + char szBuf[256]; + wvsprintf(szBuf,pszFmt,args); + + #ifdef _DEBUG + OutputDebugString(szBuf); + OutputDebugString(TEXT("\n")); + #endif + + // turn off "topmost" flag so that we don't stick above debugger + if (ghMainWnd) SetWindowPos(ghMainWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + + + // can't use storm -- it might be dead + MessageBox(ghMainWnd,szBuf,"ERROR",MB_ICONERROR | MB_OK | MB_TASKMODAL); +} + + +//*********************************************************************** +//*********************************************************************** +static void pre_fatal_cleanup() { + // if we fatal from a subsidiary thread, it may kill + // off things which are needed by other threads, so + // if we are already fataling, give the other thread + // some time to die + static BOOL sbInFatal = 0; + static unsigned snThreadID = 0; + if (sbInFatal && snThreadID != GetCurrentThreadId()) + Sleep(20000); + sbInFatal = 1; + snThreadID = GetCurrentThreadId(); + + // kill off direct draw so that dialogs will be visible + void free_directx(); + free_directx(); + + // for multiplayer games, make sure our fatal + // handler doesn't cause other players to timeout + extern BYTE gbMaxPlayers; + if (gbMaxPlayers > 1) { + if (SNetLeaveGame(SNET_EXIT_AUTO_SHUTDOWN)) + Sleep(2000); + } + + // kill off network play + SNetDestroy(); + + // make sure cursor is visible for any dialog box we display + ShowCursor(TRUE); +} + + +//*********************************************************************** +//*********************************************************************** +void __cdecl app_fatal(const char * pszFmt,...) { + pre_fatal_cleanup(); + + // break into debugger + myDebugBreak(); + + if (pszFmt) { + va_list args; + va_start(args,pszFmt); + app_debug_msg(pszFmt,args); + va_end(args); + } + + cleanup(FALSE); + + exit(1); + ExitProcess(1); // just in case +} + + +//*********************************************************************** +//*********************************************************************** +void __cdecl app_warning(const char * pszFmt,...) { + app_assert(pszFmt); + + char szBuf[256]; + va_list args; + va_start(args,pszFmt); + wvsprintf(szBuf,pszFmt,args); + va_end(args); + SDrawMessageBox( + szBuf, + "Hellfire", + MB_ICONEXCLAMATION | MB_OK | MB_TASKMODAL + ); +} + + +//*********************************************************************** +//*********************************************************************** +#if EXTENDED_ASSERT +void assert_fail(int nLineNo, const char * pszFile, const char * pszFail) { + app_fatal("assertion failed (%d:%s)\n%s",nLineNo,pszFile,pszFail); +} +#else +void assert_fail(int nLineNo, const char * pszFile) { + app_fatal("assertion failed (%d:%s)",nLineNo,pszFile); +} +#endif + + +//*********************************************************************** +//*********************************************************************** +void ddraw_assert_fail(HRESULT ddrval, int nLineNo, const char * pszFile) { + if (ddrval == DD_OK) return; + app_fatal( + "Direct draw error (%s:%d)\n%s", + pszFile, + nLineNo, + strGetError(ddrval) + ); +} + + +//*********************************************************************** +//*********************************************************************** +void dsound_assert_fail(HRESULT dsrval, int nLineNo, const char * pszFile) { + if (dsrval == DS_OK) return; + app_fatal( + "Direct sound error (%s:%d)\n%s", + pszFile, + nLineNo, + strGetError(dsrval) + ); +} + + +//****************************************************************** +//****************************************************************** +void center_window(HWND hWnd) { + RECT r; + GetWindowRect(hWnd,&r); + int cxWnd = r.right - r.left; + int cyWnd = r.bottom - r.top; + + // get display limits + HDC hdc = GetDC(hWnd); + int cxScreen = GetDeviceCaps(hdc,HORZRES); + int cyScreen = GetDeviceCaps(hdc,VERTRES); + ReleaseDC(hWnd,hdc); + + // Calculate new X position, then adjust for screen + int xNew = (cxScreen - cxWnd) / 2; + if (! SetWindowPos( + hWnd, + NULL, + (cxScreen - cxWnd) / 2, + (cyScreen - cyWnd) / 2, + 0, + 0, + SWP_NOSIZE | SWP_NOZORDER + )) app_fatal("center_window: %s",strGetLastError()); +} + + +//****************************************************************** +//****************************************************************** +static void ErrorDlgInit(HWND hWnd,LPARAM lParam) { + center_window(hWnd); + if (lParam) SetDlgItemText(hWnd,IDC_ERROR_TAG,(LPCTSTR) lParam); +} + + +//****************************************************************** +//****************************************************************** +static BOOL CALLBACK ErrorDlgProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { + switch (uMsg) { + case WM_INITDIALOG: + ErrorDlgInit(hWnd,lParam); + break; + + case WM_COMMAND: + if (IDOK == GET_WM_COMMAND_ID(wParam,lParam)) + EndDialog(hWnd,TRUE); + else if (IDCANCEL == GET_WM_COMMAND_ID(wParam,lParam)) + EndDialog(hWnd,FALSE); + break; + + default: + return FALSE; + } + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine) { + pre_fatal_cleanup(); + char szBuf[512]; + const char * pszTemp = strrchr(pszFile,'\\'); + if (pszTemp) pszFile = pszTemp + 1; + wsprintf(szBuf,"%s\nat: %s line %d",strGetError(dwErr),pszFile,nLine); + + #ifdef _DEBUG + OutputDebugString(szBuf); + OutputDebugString(TEXT("\n")); + #endif + + if (-1 == DialogBoxParam( + ghInst, + MAKEINTRESOURCE(nDlgId), + ghMainWnd, + ErrorDlgProc, + (LPARAM) szBuf + )) app_fatal("ErrDlg: %d",nDlgId); + app_fatal(NULL); +} + + +//****************************************************************** +//****************************************************************** +void FileErrorDlg(const char * pszName) { + pre_fatal_cleanup(); + if (! pszName) pszName = ""; + + if (-1 == DialogBoxParam( + ghInst, + MAKEINTRESOURCE(IDD_FILE_ERR), + ghMainWnd, + ErrorDlgProc, + (LPARAM) pszName + )) app_fatal("FileErrDlg"); + app_fatal(NULL); +} + + +//****************************************************************** +//****************************************************************** +void DiskFreeErrorDlg(const char * pszDir) { + pre_fatal_cleanup(); + if (-1 == DialogBoxParam( + ghInst, + MAKEINTRESOURCE(IDD_DISKFREE_ERR), + ghMainWnd, + ErrorDlgProc, + (LPARAM) pszDir + )) app_fatal("DiskFreeDlg"); + app_fatal(NULL); +} + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start.1/13/97 +BOOL InsertCDDlg(void) { + ShowCursor(TRUE); + int nResult; + if (-1 == (nResult = DialogBoxParam( + ghInst, + MAKEINTRESOURCE(IDD_CDROM_ERR), + ghMainWnd, + ErrorDlgProc, + (LPARAM) "" + ))) app_fatal("InsertCDDlg"); + ShowCursor(FALSE); + return nResult == IDOK; +} +// pjw.patch1.end.1/13/97 diff --git a/src/AUTOMAP.CPP b/src/AUTOMAP.CPP new file mode 100644 index 0000000..1d6c0d5 --- /dev/null +++ b/src/AUTOMAP.CPP @@ -0,0 +1,839 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Automap file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/AUTOMAP.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "automap.h" +#include "engine.h" +#include "gendung.h" +#include "scrollrt.h" +#include "items.h" +#include "player.h" +#include "control.h" +#include "inv.h" +#include "quests.h" +#include "multi.h" +#include "setmaps.h" + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#define AUTOMAPMAX 200 +#define AUTOMAPMIN 50 +#define AUTOMAPADD 5 +#define AUTOMAPST ((AUTOMAPMAX-AUTOMAPMIN)/AUTOMAPADD)+1 + +#define MAXMEGA MAXTILES/4 + +#define AMDC 144 +#define AMLC 200 +#define AMPC 153 //129 + +#define AMS_DOORL 0x01 +#define AMS_DOORR 0x02 +#define AMS_ARCHL 0x04 +#define AMS_ARCHR 0x08 +#define AMS_GRATEL 0x10 +#define AMS_GRATER 0x20 +#define AMS_DIRT 0x40 +#define AMS_STAIRS 0x80 + +#define AMS_NONEL 0x15 +#define AMS_NONER 0x2a + +#define AMS_DIRT8 0x4000 // AMS_DIRT << 8 + +#define AMS_DIRTLR 0x4007 // Lower right dirt piece + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL automapflag; + +int automapscale; +int automaps1, automaps2, automaps3, automaps4, automaps5; +int automapx, automapy; +int amxadd, amyadd; + +char automapstbl[AUTOMAPST]; + +WORD automaptype[MAXMEGA]; + +BYTE automapview[AUTOMAPX][AUTOMAPY]; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitAutomapOnce() +{ + automapflag = FALSE; + automapscale = AUTOMAPMIN; + automaps1 = (automapscale << 6) / 100; + automaps2 = automaps1 >> 1; + automaps3 = automaps2 >> 1; + automaps4 = automaps3 >> 1; + automaps5 = automaps4 >> 1; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitAutomap() +{ + int i, j, a, v; + DWORD dwTiles; + byte *pAFile, *pTmp; + + a = AUTOMAPMIN; + for (i = 0; i < AUTOMAPST; i++) { + v = (a << 6) / 100; + automapstbl[i] = ((320 / v) << 1) + 1; + if ((320 % v) != 0) automapstbl[i]++; + if ((320 % v) >= ((a << 5) / 100)) automapstbl[i]++; + a += AUTOMAPADD; + } + + ZeroMemory(automaptype,sizeof(automaptype)); + + switch (leveltype) { + case 1: + if (currlevel < CRYPTSTART) + { + pAFile = LoadFileInMemSig("Levels\\L1Data\\L1.AMP",&dwTiles,'AMAP'); + dwTiles /= 2; + } + else + { + pAFile = LoadFileInMemSig("NLevels\\L5Data\\L5.AMP",&dwTiles,'AMAP'); + dwTiles /= 2; + } + + break; + + case 2: + pAFile = LoadFileInMemSig("Levels\\L2Data\\L2.AMP",&dwTiles,'AMAP'); + dwTiles /= 2; + break; + + case 3: + if (currlevel < HIVESTART) + { + pAFile = LoadFileInMemSig("Levels\\L3Data\\L3.AMP",&dwTiles,'AMAP'); + dwTiles /= 2; + } + else + { + pAFile = LoadFileInMemSig("NLevels\\L6Data\\L6.AMP",&dwTiles,'AMAP'); + dwTiles /= 2; + } + + break; + + case 4: + pAFile = LoadFileInMemSig("Levels\\L4Data\\L4.AMP",&dwTiles,'AMAP'); + dwTiles /= 2; + break; + default: + // get out! + return; + } + + pTmp = pAFile; + for (DWORD d = 1; d <= dwTiles; d++) { + byte b1 = *pTmp++; + byte b2 = *pTmp++; + automaptype[d] = b1 + (b2 << 8); + } + + DiabloFreePtr(pAFile); + + // Clear automap vision + ZeroMemory(automapview,sizeof(automapview)); + + // Get rid of any residue prevision calls + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) + dFlags[i][j] &= BFMASK_AUTOMAP; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void StartAutomap() +{ + amxadd = 0; + amyadd = 0; + automapflag = TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AutomapUp() +{ + amxadd--; + amyadd--; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AutomapDown() +{ + amxadd++; + amyadd++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AutomapLeft() +{ + amxadd--; + amyadd++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AutomapRight() +{ + amxadd++; + amyadd--; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AutomapZoomIn() +{ + if (automapscale < AUTOMAPMAX) { + automapscale += AUTOMAPADD; + automaps1 = (automapscale << 6) / 100; + automaps2 = automaps1 >> 1; + automaps3 = automaps2 >> 1; + automaps4 = automaps3 >> 1; + automaps5 = automaps4 >> 1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AutomapZoomOut() +{ + if (automapscale > AUTOMAPMIN) { + automapscale -= AUTOMAPADD; + automaps1 = (automapscale << 6) / 100; + automaps2 = automaps1 >> 1; + automaps3 = automaps2 >> 1; + automaps4 = automaps3 >> 1; + automaps5 = automaps4 >> 1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawAMSquare(int x, int y) +{ + int sx1, sy1, sx2, sy2; + + sx1 = x - automaps2; + sy1 = y - automaps3; + sx2 = sx1 + automaps1; + sy2 = sy1 + automaps2; + + DrawLine(x, sy1, sx1, y, 131); + DrawLine(x, sy1, sx2, y, 131); + DrawLine(x, sy2, sx1, y, 131); + DrawLine(x, sy2, sx2, y, 131); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DrawAMQuarterSquare(int x, int y, int color) +{ + int sx1, sy1, sx2, sy2; + + sx1 = x - (automaps2 / 2); + sy1 = y - (automaps3 / 2); + sx2 = sx1 + (automaps1 / 2); + sy2 = sy1 + (automaps2 / 2); + + DrawLine(x, sy1, sx1, y, color); + DrawLine(x, sy1, sx2, y, color); + DrawLine(x, sy2, sx1, y, color); + DrawLine(x, sy2, sx2, y, color); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawAMShape(int x, int y, WORD shape) +{ + int x1, y1, x2, y2; + BYTE f; + BOOL lwf, rwf, llwf, lrwf; + + //DrawAMSquare(x, y); + + f = (shape >> 8) & 0xff; + + if (f & AMS_DIRT) { + DrawPoint(x, y, AMLC); + DrawPoint(x - automaps4, y - automaps5, AMLC); + DrawPoint(x - automaps4, y + automaps5, AMLC); + DrawPoint(x + automaps4, y - automaps5, AMLC); + DrawPoint(x + automaps4, y + automaps5, AMLC); + DrawPoint(x - automaps3, y, AMLC); + DrawPoint(x + automaps3, y, AMLC); + DrawPoint(x, y - automaps4, AMLC); + DrawPoint(x, y + automaps4, AMLC); + + DrawPoint(x - automaps2 + automaps4, y + automaps5, AMLC); + DrawPoint(x + automaps2 - automaps4, y + automaps5, AMLC); + DrawPoint(x - automaps3, y + automaps4, AMLC); + DrawPoint(x + automaps3, y + automaps4, AMLC); + DrawPoint(x - automaps4, y + automaps3 - automaps5, AMLC); + DrawPoint(x + automaps4, y + automaps3 - automaps5, AMLC); + DrawPoint(x, y + automaps3, AMLC); + } + if (f & AMS_STAIRS) { + DrawLine(x-automaps4, y-automaps4-automaps5, x+automaps3+automaps4, y+automaps5, AMDC); + DrawLine(x-automaps3, y-automaps4, x+automaps3, y+automaps4, AMDC); + DrawLine(x-automaps3-automaps4, y-automaps5, x+automaps4, y+automaps4+automaps5, AMDC); + DrawLine(x-automaps2, y, x, y+automaps3, AMDC); + } + + lwf = FALSE; + rwf = FALSE; + llwf = FALSE; + lrwf = FALSE; + switch(shape & 0xf) { + case 1: + x1 = x - automaps3; // Column + y1 = y - automaps3; + x2 = x1 + automaps2; + y2 = y - automaps4; + DrawLine(x, y1, x1, y2, AMLC); + DrawLine(x, y1, x2, y2, AMLC); + DrawLine(x, y, x1, y2, AMLC); + DrawLine(x, y, x2, y2, AMLC); + break; + case 2: + case 5: + lwf = TRUE; + break; + case 3: + case 6: + rwf = TRUE; + break; + case 4: + lwf = TRUE; + rwf = TRUE; + break; + case 8: + lwf = TRUE; + llwf = TRUE; + break; + case 9: + rwf = TRUE; + lrwf = TRUE; + break; + case 10: + llwf = TRUE; + break; + case 11: + lrwf = TRUE; + break; + case 12: + llwf = TRUE; + lrwf = TRUE; + break; + } + if (lwf) { + if (f & AMS_DOORL) { + x1 = x - automaps2; + x2 = x - automaps3; + y1 = y - automaps3; + y2 = y - automaps4; + DrawLine(x, y1, x-automaps4, y1+automaps5, AMLC); + DrawLine(x1, y, x1+automaps4, y-automaps5, AMLC); + DrawLine(x2, y1, x1, y2, AMDC); + DrawLine(x2, y1, x, y2, AMDC); + DrawLine(x2, y, x1, y2, AMDC); + DrawLine(x2, y, x, y2, AMDC); + } + if (f & AMS_GRATEL) { + DrawLine(x-automaps3, y-automaps4, x-automaps2, y, AMLC); + f |= AMS_ARCHL; // Force arch square + } + if (f & AMS_ARCHL) { + x1 = x - automaps3; + y1 = y - automaps3; + x2 = x1 + automaps2; + y2 = y - automaps4; + DrawLine(x, y1, x1, y2, AMLC); + DrawLine(x, y1, x2, y2, AMLC); + DrawLine(x, y, x1, y2, AMLC); + DrawLine(x, y, x2, y2, AMLC); + } + if ((f & AMS_NONEL) == 0) DrawLine(x, y-automaps3, x-automaps2, y, AMLC); // Left wall + } + if (rwf) { + if (f & AMS_DOORR) { + x1 = x + automaps3; + x2 = x + automaps2; + y1 = y - automaps3; + y2 = y - automaps4; + DrawLine(x, y1, x+automaps4, y1+automaps5, AMLC); + DrawLine(x2, y, x2-automaps4, y-automaps5, AMLC); + DrawLine(x1, y1, x, y2, AMDC); + DrawLine(x1, y1, x2, y2, AMDC); + DrawLine(x1, y, x, y2, AMDC); + DrawLine(x1, y, x2, y2, AMDC); + } + if (f & AMS_GRATER) { + DrawLine(x+automaps3, y-automaps4, x+automaps2, y, AMLC); + f |= AMS_ARCHR; // Force arch square + } + if (f & AMS_ARCHR) { + x1 = x - automaps3; + y1 = y - automaps3; + x2 = x1 + automaps2; + y2 = y - automaps4; + DrawLine(x, y1, x1, y2, AMLC); + DrawLine(x, y1, x2, y2, AMLC); + DrawLine(x, y, x1, y2, AMLC); + DrawLine(x, y, x2, y2, AMLC); + } + if ((f & AMS_NONER) == 0) DrawLine(x, y-automaps3, x+automaps2, y, AMLC); // Right wall + } + if (llwf) { + if (f & AMS_DOORL) { + x1 = x - automaps2; + x2 = x - automaps3; + y1 = y + automaps3; + y2 = y + automaps4; + DrawLine(x, y1, x-automaps4, y1-automaps5, AMLC); + DrawLine(x1, y, x1+automaps4, y+automaps5, AMLC); + DrawLine(x2, y1, x1, y2, AMDC); + DrawLine(x2, y1, x, y2, AMDC); + DrawLine(x2, y, x1, y2, AMDC); + DrawLine(x2, y, x, y2, AMDC); + } else + DrawLine(x, y+automaps3, x-automaps2, y, AMLC); // Lower Left wall + } + if (lrwf) { + if (f & AMS_DOORR) { + x1 = x + automaps3; + x2 = x + automaps2; + y1 = y + automaps3; + y2 = y + automaps4; + DrawLine(x, y1, x+automaps4, y1-automaps5, AMLC); + DrawLine(x2, y, x2-automaps4, y+automaps5, AMLC); + DrawLine(x1, y1, x, y2, AMDC); + DrawLine(x1, y1, x2, y2, AMDC); + DrawLine(x1, y, x, y2, AMDC); + DrawLine(x1, y, x2, y2, AMDC); + } else + DrawLine(x, y+automaps3, x+automaps2, y, AMLC); // Lower Right wall + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawAllObjects() +{ + int px, py; + if (plr[myplr]._pmode == PM_WALK3) { + px = plr[myplr]._pfutx; + py = plr[myplr]._pfuty; + if (plr[myplr]._pdir == DIR_L) px++; + else py++; + } else { + px = plr[myplr]._px; + py = plr[myplr]._py; + } + + int beginx = px - 8; + if (beginx < 0) + beginx = 0; + else if (beginx > MAXDUNX) + beginx = MAXDUNX; + + int beginy = py - 8; + if (beginy < 0) + beginy = 0; + else if (beginy > MAXDUNY) + beginy = MAXDUNY; + + int endx = px + 8; + if (endx < 0) + endx = 0; + else if (endx > MAXDUNX) + endx = MAXDUNX; + + int endy = py + 8; + if (endy < 0) + endy = 0; + else if (endy > MAXDUNY) + endy = MAXDUNY; + + + for (int ix=beginx; ix < endx; ++ix) + { + for (int iy = beginy; iy < endy; ++iy) + { + if (dItem[ix][iy] != 0) + { + int dx = ix - ViewX - (amxadd << 1); + int dy = iy - ViewY - (amyadd << 1); + + int x = 384 + (dx * automaps3) - (dy * automaps3); + int y = 336 + (dx * automaps4) + (dy * automaps4); + + x += ((ScrollInfo._sxoff * automapscale) / 100) >> 1; + y += ((ScrollInfo._syoff * automapscale) / 100) >> 1; + + if (invflag || sbookflag) x -= 160; + if (chrflag || questlog) x += 160; + + y -= automaps4; + + DrawAMQuarterSquare(x,y, 129); + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawAutomapPlr() +{ + int px, py; + int dx, dy; + int x, y; + + if (plr[myplr]._pmode == PM_WALK3) { + px = plr[myplr]._pfutx; + py = plr[myplr]._pfuty; + if (plr[myplr]._pdir == DIR_L) px++; + else py++; + } else { + px = plr[myplr]._px; + py = plr[myplr]._py; + } + + dx = px - ViewX - (amxadd << 1); + dy = py - ViewY - (amyadd << 1); + + x = 384 + (dx * automaps3) - (dy * automaps3); + y = 336 + (dx * automaps4) + (dy * automaps4); + + x += ((plr[myplr]._pxoff * automapscale) / 100) >> 1; + y += ((plr[myplr]._pyoff * automapscale) / 100) >> 1; + + x += ((ScrollInfo._sxoff * automapscale) / 100) >> 1; + y += ((ScrollInfo._syoff * automapscale) / 100) >> 1; + + if (invflag || sbookflag) x -= 160; + if (chrflag || questlog) x += 160; + + y -= automaps4; + + switch (plr[myplr]._pdir) { + case DIR_U: + DrawLine(x, y, x, y-automaps3, AMPC); + DrawLine(x, y-automaps3, x-automaps5, y-automaps4, AMPC); + DrawLine(x, y-automaps3, x+automaps5, y-automaps4, AMPC); + break; + case DIR_UR: + DrawLine(x, y, x+automaps3, y-automaps4, AMPC); + DrawLine(x+automaps3, y-automaps4, x+automaps4, y-automaps4, AMPC); + DrawLine(x+automaps3, y-automaps4, x+automaps4+automaps5, y, AMPC); + break; + case DIR_R: + DrawLine(x, y, x+automaps3, y, AMPC); + DrawLine(x+automaps3, y, x+automaps4, y-automaps5, AMPC); + DrawLine(x+automaps3, y, x+automaps4, y+automaps5, AMPC); + break; + case DIR_DR: + DrawLine(x, y, x+automaps3, y+automaps4, AMPC); + DrawLine(x+automaps3, y+automaps4, x+automaps4+automaps5, y, AMPC); + DrawLine(x+automaps3, y+automaps4, x+automaps4, y+automaps4, AMPC); + break; + case DIR_D: + DrawLine(x, y, x, y+automaps3, AMPC); + DrawLine(x, y+automaps3, x+automaps5, y+automaps4, AMPC); + DrawLine(x, y+automaps3, x-automaps5, y+automaps4, AMPC); + break; + case DIR_DL: + DrawLine(x, y, x-automaps3, y+automaps4, AMPC); + DrawLine(x-automaps3, y+automaps4, x-automaps4-automaps5, y, AMPC); + DrawLine(x-automaps3, y+automaps4, x-automaps4, y+automaps4, AMPC); + break; + case DIR_L: + DrawLine(x, y, x-automaps3, y, AMPC); + DrawLine(x-automaps3, y, x-automaps4, y-automaps5, AMPC); + DrawLine(x-automaps3, y, x-automaps4, y+automaps5, AMPC); + break; + case DIR_UL: + DrawLine(x, y, x-automaps3, y-automaps4, AMPC); + DrawLine(x-automaps3, y-automaps4, x-automaps4, y-automaps4, AMPC); + DrawLine(x-automaps3, y-automaps4, x-automaps4-automaps5, y, AMPC); + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static WORD GetAutomapType(int x, int y, BOOL view) +{ + WORD rv, t; + + if ((view) && (x == -1) && (y >= 0) && (y < AUTOMAPY) && (automapview[0][y])) { + if (GetAutomapType(0, y, FALSE) & AMS_DIRT8) return(0); + else return(0x4000); + } + if ((view) && (y == -1) && (x >= 0) && (x < AUTOMAPX) && (automapview[x][0])) { + if (GetAutomapType(x, 0, FALSE) & AMS_DIRT8) return(0); + else return(0x4000); + } + if ((x < 0) || (x >= AUTOMAPX)) return(0); + if ((y < 0) || (y >= AUTOMAPY)) return(0); + if ((!automapview[x][y]) && (view)) return(0); + rv = automaptype[dungeon[x][y]]; + if (rv == 7) { + t = GetAutomapType(x-1,y,FALSE) >> 8; + if (t & AMS_ARCHR) { + t = GetAutomapType(x,y-1,FALSE) >> 8; + if (t & AMS_ARCHL) rv = 1; + } + } + return(rv); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +/* +void DrawAutomapTest() +{ + int i, j, x, y; + + y = 336; + x = 384 - (automaps1 * 2); + for (i = 1; i < 5; i++) { + DrawAMShape(x, y, 0x0300 + i); + x += automaps1; + } +} +*/ + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void draw_game_info() { + #define LINE_HGT 15 + char szBuf[256]; + int y = 20; + if (gbMaxPlayers > 1) { + strcat(strcpy(szBuf,"game: "),gszGameName); + PrintStringXY(8,y,szBuf,ICOLOR_GOLD); + y += LINE_HGT; + if (gszGamePass[0]) { + strcat(strcpy(szBuf,"password: "),gszGamePass); + PrintStringXY(8,y,szBuf,ICOLOR_GOLD); + y += LINE_HGT; + } + } + + if (setlevel) { + PrintStringXY(8,y,SetLevelName[setlvlnum],ICOLOR_GOLD); + } + else if (currlevel) { + if (currlevel >= HIVESTART && currlevel <= HIVEEND) + sprintf(szBuf, "Level: Nest %i", currlevel - HIVESTART + 1); + else if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND) + sprintf(szBuf, "Level: Crypt %i", currlevel - CRYPTSTART + 1); + else + sprintf(szBuf,"Level: %i", currlevel); + PrintStringXY(8,y,szBuf,ICOLOR_GOLD); + } + #undef LINE_HGT +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawAutomap() +{ + int i, j; + int x, y; + int xs, ys; + int mx, my; + int ams; + WORD s; + + if (leveltype == 0) { + draw_game_info(); + return; + } + + app_assert(gpBuffer); + glClipY = (long) gpBuffer + 393216; // (352 + 160) * 768 + + automapx = (ViewX - DIRTEDGED2) >> 1; + while ((automapx + amxadd) < 0) amxadd++; + while ((automapx + amxadd) >= AUTOMAPX) amxadd--; + automapx += amxadd; + automapy = (ViewY - DIRTEDGED2) >> 1; + while ((automapy + amyadd) < 0) amyadd++; + while ((automapy + amyadd) >= AUTOMAPY) amyadd--; + automapy += amyadd; + + ams = automapstbl[(automapscale - AUTOMAPMIN) / AUTOMAPADD]; + if ((ScrollInfo._sxoff + ScrollInfo._syoff) != 0) ams++; + + mx = automapx - ams; + my = automapy - 1; + if (ams & 1) { + xs = 384 - (automaps1 * ((ams-1) >> 1)); + ys = 336 - (automaps2 * ((ams+1) >> 1)); + } else { + xs = 384 - (automaps1 * (ams >> 1)) + automaps2; + ys = 336 - (automaps2 * (ams >> 1)) - automaps3; + } + if (ViewX & 1) { + xs -= automaps3; + ys -= automaps4; + } + if (ViewY & 1) { + xs += automaps3; + ys -= automaps4; + } + xs += ((ScrollInfo._sxoff * automapscale) / 100) >> 1; + ys += ((ScrollInfo._syoff * automapscale) / 100) >> 1; + + if (invflag || sbookflag) xs -= 160; + if (chrflag || questlog) xs += 160; + + for (j = 0; j <= (ams+1); j++) { + x = xs; + y = ys; + for (i = 0; i < ams; i++) { + s = GetAutomapType(mx+i,my-i,TRUE); + if (s != 0) DrawAMShape(x, y, s); + //else DrawAMSquare(x, y); + x += automaps1; + } + my++; + x = xs - automaps2; + y = ys + automaps3; + for (i = 0; i <= ams; i++) { + s = GetAutomapType(mx+i,my-i,TRUE); + if (s != 0) DrawAMShape(x, y, s); + //else DrawAMSquare(x, y); + x += automaps1; + } + mx++; + ys = ys + automaps2; + } + + DrawAutomapPlr(); + if (HighLightAllItems) + { + DrawAllObjects(); + } + draw_game_info(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetAutomapView(int x, int y) +{ + int xx, yy; + WORD s, d; + + xx = (x - DIRTEDGED2) >> 1; + yy = (y - DIRTEDGED2) >> 1; + if ((xx < 0) || (xx >= AUTOMAPX)) return; + if ((yy < 0) || (yy >= AUTOMAPY)) return; + automapview[xx][yy] = TRUE; + s = GetAutomapType(xx, yy, FALSE); + d = s & AMS_DIRT8; + s = s & 0xf; + switch (s) { + case 2: + if (d) { + if (GetAutomapType(xx, yy+1, FALSE) == AMS_DIRTLR) automapview[xx][yy+1] = TRUE; + } else { + if (GetAutomapType(xx-1, yy, FALSE) & AMS_DIRT8) automapview[xx-1][yy] = TRUE; + } + break; + case 3: + if (d) { + if (GetAutomapType(xx+1, yy, FALSE) == AMS_DIRTLR) automapview[xx+1][yy] = TRUE; + } else { + if (GetAutomapType(xx, yy-1, FALSE) & AMS_DIRT8) automapview[xx][yy-1] = TRUE; + } + break; + case 4: + if (d) { + if (GetAutomapType(xx, yy+1, FALSE) == AMS_DIRTLR) automapview[xx][yy+1] = TRUE; + if (GetAutomapType(xx+1, yy, FALSE) == AMS_DIRTLR) automapview[xx+1][yy] = TRUE; + } else { + if (GetAutomapType(xx-1, yy, FALSE) & AMS_DIRT8) automapview[xx-1][yy] = TRUE; + if (GetAutomapType(xx, yy-1, FALSE) & AMS_DIRT8) automapview[xx][yy-1] = TRUE; + if (GetAutomapType(xx-1, yy-1, FALSE) & AMS_DIRT8) automapview[xx-1][yy-1] = TRUE; + } + break; + case 5: + if (d) { + if (GetAutomapType(xx, yy-1, FALSE) & AMS_DIRT8) automapview[xx][yy-1] = TRUE; + if (GetAutomapType(xx, yy+1, FALSE) == AMS_DIRTLR) automapview[xx][yy+1] = TRUE; + } else { + if (GetAutomapType(xx-1, yy, FALSE) & AMS_DIRT8) automapview[xx-1][yy] = TRUE; + } + break; + case 6: + if (d) { + if (GetAutomapType(xx-1, yy, FALSE) & AMS_DIRT8) automapview[xx-1][yy] = TRUE; + if (GetAutomapType(xx+1, yy, FALSE) == AMS_DIRTLR) automapview[xx+1][yy] = TRUE; + } else { + if (GetAutomapType(xx, yy-1, FALSE) & AMS_DIRT8) automapview[xx][yy-1] = TRUE; + } + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SyncAutomap() +{ + automaps1 = (automapscale << 6) / 100; + automaps2 = automaps1 >> 1; + automaps3 = automaps2 >> 1; + automaps4 = automaps3 >> 1; + automaps5 = automaps4 >> 1; + amxadd = 0; + amyadd = 0; +} diff --git a/src/AUTOMAP.H b/src/AUTOMAP.H new file mode 100644 index 0000000..bcabd39 --- /dev/null +++ b/src/AUTOMAP.H @@ -0,0 +1,41 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/AUTOMAP.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ +#define AUTOMAPX 40 +#define AUTOMAPY 40 + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern BOOL automapflag; +extern BYTE automapview[AUTOMAPX][AUTOMAPY]; +extern int automapscale; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitAutomapOnce(); +void InitAutomap(); +void DrawAutomap(); + +void SetAutomapView(int, int); +void SyncAutomap(); + +void StartAutomap(); +void AutomapUp(); +void AutomapDown(); +void AutomapLeft(); +void AutomapRight(); +void AutomapZoomIn(); +void AutomapZoomOut(); diff --git a/src/AUTOPLAY.ICO b/src/AUTOPLAY.ICO new file mode 100644 index 0000000..b66a61e Binary files /dev/null and b/src/AUTOPLAY.ICO differ diff --git a/src/BUGS.TXT b/src/BUGS.TXT new file mode 100644 index 0000000..924bdbe --- /dev/null +++ b/src/BUGS.TXT @@ -0,0 +1,15 @@ +*) in MonsterStruct the field mArmorClass should be a short instead of a char. + Currently it overflows in HELL mode. + +*) Peril and Devastation can be on Bows but do nothing. Peril should be + removed from bows, Devastation damage should be added to the arrows. + +*) Items of Jester have a 0 to 600% damage, not 0-> to 500% either + change the text or the calculation. + +*) If you drop a weapon then pick it up (For a Barbarian anyway) half your + life pts come back. (Inventory bug) + +*) Doppelganger can clone a golem. (Should be prevented) + +*) Rage go to town, and back and you are in a permant rage. diff --git a/src/CAPTURE.CPP b/src/CAPTURE.CPP new file mode 100644 index 0000000..6b16f4b --- /dev/null +++ b/src/CAPTURE.CPP @@ -0,0 +1,263 @@ +//*************************************************************************** +// capture.c +// created 4.14.95 +// written by Patrick Wyatt +//*************************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include +#include +#include "engine.h" + + +//*************************************************************************** +// externs +//*************************************************************************** +void DrawAndBlit(); + + +//*************************************************************************** +// constants +//*************************************************************************** +#define PCX_HEADER 10 +#define PCX_VERSION 5 +#define PCX_ENCODE 1 + +#define PCX_MAX_REP 63 + +#define PCX_X_PAL 12 +#define PCX_COLORS 16 +#define X_PCX_COLORS 256 + + +//*************************************************************************** +// types +//*************************************************************************** +#pragma pack(push,1) +typedef struct PCXHeader { + BYTE nHeader; // 10 for valid PCX files + BYTE nVersion; // 5 for version 3.0 with palette + BYTE nEncode; // file encoding mode + BYTE nBits; // 8 for 256 color mode + WORD x1; + WORD y1; + WORD x2; + WORD y2; + WORD nScrWid; + WORD nScrHgt; +} PCXHeader; + +typedef struct PCXInfo { + BYTE nMode; // always 0 + BYTE nPlanes; // number of bit planes + WORD nLine; // bytes per line + BYTE unused[60]; // fill out to 128 bytes +} PCXInfo; + +typedef struct TPCX_RGB { + BYTE r; + BYTE g; + BYTE b; +} TPCX_RGB; + +typedef struct TPCX_XPal { + BYTE nPal; + TPCX_RGB rgb[X_PCX_COLORS]; +} TPCX_XPal; + +typedef struct TPCX { + PCXHeader Header; + TPCX_RGB Pal16[PCX_COLORS]; + PCXInfo Info; +} TPCX; +#pragma pack(pop) + + +//*************************************************************************** +//*************************************************************************** +static BOOL pcx_write_header(HANDLE hFile,WORD wWdt,WORD wHgt) { + TPCX pcx; + + ZeroMemory(&pcx,sizeof(pcx)); + + // initialize header + pcx.Header.nHeader = PCX_HEADER; + pcx.Header.nVersion = PCX_VERSION; + pcx.Header.nEncode = PCX_ENCODE; + pcx.Header.nBits = 8; + //pcx.Header.x1 = 0; + //pcx.Header.y1 = 0; + pcx.Header.x2 = wWdt - 1; + pcx.Header.y2 = wHgt - 1; + pcx.Header.nScrWid = wWdt; + pcx.Header.nScrHgt = wHgt; + + //pcx.Info.nMode = 0; + pcx.Info.nPlanes = 1; + pcx.Info.nLine = wWdt; + + DWORD dwBytes; + return WriteFile(hFile,&pcx,sizeof(pcx),&dwBytes,NULL) + && (dwBytes == sizeof(pcx)); +} + + +//*************************************************************************** +//*************************************************************************** +static BOOL pcx_write_pal(HANDLE hFile,const PALETTEENTRY pal[256]) { + // setup extended palette header + TPCX_XPal xpal; + xpal.nPal = PCX_X_PAL; + + // copy palette colors + for (int i = 0; i < X_PCX_COLORS; i++) { + xpal.rgb[i].r = pal[i].peRed; + xpal.rgb[i].g = pal[i].peGreen; + xpal.rgb[i].b = pal[i].peBlue; + } + + // write it + DWORD dwBytes; + return WriteFile(hFile,&xpal,sizeof(xpal),&dwBytes,NULL) + && (dwBytes == sizeof(xpal)); +} + + +//*************************************************************************** +//*************************************************************************** +static BYTE * pcx_compress_line(const BYTE * pSrc,BYTE * pDst,int nWdt) { + BYTE c; + int nCount; + + do { + // get next character + c = *pSrc++; + nCount = 1; + nWdt--; + + // see how long the sequence is + while ((c == *pSrc) && (nCount < PCX_MAX_REP) && nWdt) { + nCount++; + nWdt--; + pSrc++; + } + + // write repeat count (if needed) + if ((nCount > 1) || (c > 0xbf)) { + nCount |= 0xc0; + *pDst++ = (BYTE) nCount; + } + + *pDst++ = c; + } while (nWdt); + + return pDst; +} + + +//*************************************************************************** +//*************************************************************************** +static BOOL pcx_write_image(HANDLE hFile,WORD wDstWdt,WORD wDstHgt,WORD wSrcWdt,const BYTE * pSrc) { + BYTE * pDstEnd; + BYTE * pDstBase; + DWORD dwWrite; + DWORD dwBytes; + + // allocate line buffer -- line cannot be more than 2x larger + pDstBase = (BYTE *) DiabloAllocPtrSig(2 * wDstWdt,'CAPt'); + + while (wDstHgt--) { + pDstEnd = pcx_compress_line(pSrc,pDstBase,wDstWdt); + pSrc += wSrcWdt; + dwWrite = pDstEnd - pDstBase; + if (! WriteFile(hFile,pDstBase,dwWrite,&dwBytes,NULL)) return FALSE; + if (dwBytes != dwWrite) return FALSE; + } + + DiabloFreePtr(pDstBase); + return TRUE; +} + + +//*************************************************************************** +//*************************************************************************** +#define MAX_CAPTURE 100 +#define DIG_OFF 6 +static const char szCAPTURE[] = "screen??.PCX"; +static const char szCAPTUREfmt[] = "screen%02d.PCX"; +static HANDLE open_capture_file(char szFileName[MAX_PATH]) { + int nValue; + BYTE bUsedTbl[MAX_CAPTURE]; + + ZeroMemory(bUsedTbl,sizeof(bUsedTbl)); + struct _finddata_t ffblk; + long lHandle = _findfirst(szCAPTURE,&ffblk); + if (lHandle != -1) { + do { + if (! isdigit(ffblk.name[DIG_OFF+0])) + continue; + if (! isdigit(ffblk.name[DIG_OFF+1])) + continue; + + nValue = (ffblk.name[DIG_OFF + 0] - '0') * 10; + nValue += ffblk.name[DIG_OFF + 1] - '0'; + bUsedTbl[nValue] = 1; + } while (! _findnext(lHandle,&ffblk)); + } + + for (nValue = 0; nValue < MAX_CAPTURE; nValue++) { + if (bUsedTbl[nValue]) continue; + sprintf(szFileName,szCAPTUREfmt,nValue); + return CreateFile(szFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + } + + return INVALID_HANDLE_VALUE; +} + + +//*************************************************************************** +//*************************************************************************** +static void red_palette(const PALETTEENTRY src[256]) { + PALETTEENTRY dst[256]; + for (int i = 0; i < 256; i++) { + dst[i].peRed = src[i].peRed; + dst[i].peGreen = 0; + dst[i].peBlue = 0; + dst[i].peFlags = 0; + } + lpDDPal->SetEntries(0,0,256,dst); +} + + +//*************************************************************************** +//*************************************************************************** +void screen_capture(void) { + HANDLE hFile; + char szFileName[MAX_PATH]; + PALETTEENTRY pal[256]; + + if (INVALID_HANDLE_VALUE == (hFile = open_capture_file(szFileName))) + return; + + // get the current palette, then flash the screen red + DrawAndBlit(); + lpDDPal->GetEntries(0,0,256,pal); + red_palette(pal); + + lock_buf(2); + app_assert(gpBuffer); + BOOL bOK = pcx_write_header(hFile,TOTALX,TOTALY); + if (bOK) bOK = pcx_write_image(hFile,TOTALX,TOTALY,BUFFERX,gpBuffer + 122944); + if (bOK) bOK = pcx_write_pal(hFile,pal); + unlock_buf(2); + + CloseHandle(hFile); + if (! bOK) + DeleteFile(szFileName); + + // restore palette + Sleep(300); + lpDDPal->SetEntries(0,0,256,pal); +} diff --git a/src/CODEC.CPP b/src/CODEC.CPP new file mode 100644 index 0000000..ddea8b9 --- /dev/null +++ b/src/CODEC.CPP @@ -0,0 +1,317 @@ +//****************************************************************** +// codec.cpp +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "engine.h" + + +//****************************************************************** +// externs +//****************************************************************** +void DesDestroy (); +void DesEncrypt (int, const void *, void *); +void DesInitialize (int, BOOL, const void *); +void IdeaDestroy (); +void IdeaEncrypt (int, const void *, void *); +void IdeaInitialize (int, BOOL, const void *); +void ShaDestroy (); +void ShaGetLastHash (int, void *); +void ShaHash (int, const void *, void *); +void ShaInitialize (int); + + +//****************************************************************** +// set encryption methods +//****************************************************************** +#define IDEA 0 +#define DES 0 + + +//****************************************************************** +// private +//****************************************************************** +#define BLOCKSIZE 64 +#define VERSION 0 + +typedef struct _appendrec { + DWORD checkvalue; + BYTE version; + BYTE lastblocksize; + WORD reserved; +} appendrec, *appendptr; + +typedef struct _keyrec { + WORD ideakey[3][8]; + BYTE deskey[3][8]; + BYTE shainitvect[64]; +} keyrec, *keyptr; + + +//****************************************************************** +//****************************************************************** +static void DestroyKeys () { + #if DES + DesDestroy(); + #endif + #if IDEA + IdeaDestroy(); + #endif + ShaDestroy(); +} + + +//****************************************************************** +//****************************************************************** +static void InitializeKeys (BOOL encrypt, const char *password) { + keyrec keyset; + + // generate a key + srand(SAVE_GAME_KEY); + BYTE * pb = (BYTE *) &keyset; + for (int i = sizeof(keyset); i--; ) + *pb++ = (BYTE) rand(); + + // HASH THE PASSWORD AND MIX IT WITH THE KEY + { + BYTE originalpassword[64]; + BYTE hashedpassword[20]; + { + int passchar = 0; + for (int loop = 0; loop < 64; ++loop) { + if (!*(password+passchar)) + passchar = 0; + originalpassword[loop] = *(password+passchar++); + } + } + + ShaInitialize(0); + ShaHash(0,originalpassword,hashedpassword); + ShaDestroy(); + + { + LPBYTE keysptr = (LPBYTE)&keyset; + for (int loop = 0; loop < sizeof(keyset); ++loop) + *(keysptr+loop) ^= hashedpassword[loop % 20]; + } + + ZeroMemory(originalpassword, sizeof originalpassword); + ZeroMemory(hashedpassword, sizeof hashedpassword); + } + + // INITIALIZE THE ENCRYPTION ALGORITHMS + for (int loop = 0; loop < 3; ++loop) { + #if DES + DesInitialize(loop,encrypt,keyset.deskey[loop]); + #endif + #if IDEA + IdeaInitialize(loop,encrypt,keyset.ideakey[loop]); + #endif + ShaInitialize(loop); + ShaHash(loop,keyset.shainitvect,NULL); + } + + // WIPE OUT THE LOCAL COPY OF THE KEYS + ZeroMemory(&keyset,sizeof(keyrec)); +} + + +//****************************************************************** +//****************************************************************** +DWORD DecodeFile(BYTE * pbSrcDst,DWORD dwDstBytes,const char * pszPassword) { + app_assert(pbSrcDst); + app_assert(pszPassword); + + // initialize encryption keys + InitializeKeys(0,pszPassword); + + // make sure the length is correct + if (dwDstBytes <= sizeof(appendrec)) return 0; + dwDstBytes -= sizeof(appendrec); + if (dwDstBytes & (BLOCKSIZE-1)) return 0; + DWORD dwBytesLeft = dwDstBytes; + + // DECRYPT THE FILE BLOCK BY BLOCK + BYTE buffer[2][BLOCKSIZE]; + while (dwBytesLeft) { + + // get the next chunk + CopyMemory(&buffer[0][0],pbSrcDst,BLOCKSIZE); + + // DECRYPT THE BLOCK + { + BYTE hash[20]; + ShaGetLastHash(0,hash); + int loop; + + #if IDEA + for (loop = 0; loop < BLOCKSIZE; loop += 8) { + IdeaEncrypt(2,&buffer[0][loop],&buffer[1][loop]); + IdeaEncrypt(1,&buffer[1][loop],&buffer[0][loop]); + IdeaEncrypt(0,&buffer[0][loop],&buffer[1][loop]); + } + for (loop = 0; loop < BLOCKSIZE; loop++) + buffer[0][loop] = buffer[1][loop]-hash[(BLOCKSIZE-(loop+1)) % 20]; + #endif + + #if DES + for (loop = 0; loop < BLOCKSIZE; loop += 8) { + DesEncrypt(2,&buffer[0][loop],&buffer[1][loop]); + DesEncrypt(1,&buffer[1][loop],&buffer[0][loop]); + DesEncrypt(0,&buffer[0][loop],&buffer[1][loop]); + } + for (loop = 0; loop < BLOCKSIZE; loop++) + buffer[0][loop] = hash[loop % 20] ^ buffer[1][loop]; + #endif + + #if ! DES && ! IDEA + for (loop = 0; loop < BLOCKSIZE; loop++) + buffer[0][loop] = hash[loop % 20] ^ buffer[0][loop]; + #endif + + ShaHash(0,buffer[0],NULL); + ZeroMemory(hash,sizeof(hash)); + } + + + // WRITE THE BLOCK + CopyMemory(pbSrcDst,&buffer[0][0],BLOCKSIZE); + + // next block + pbSrcDst += BLOCKSIZE; + dwBytesLeft -= BLOCKSIZE; + } + + // hide buffer contents + ZeroMemory(buffer,sizeof(buffer)); + + // CHECK THE FILE TERMINATION RECORD + const appendrec * append = (const appendrec *) pbSrcDst; + + // CHECK THE ENCRYPTION VERSION + if (append->version > VERSION) + goto error; + + // CONFIRM THAT THE KEY AND PASSWORD WERE VALID + { + BYTE hash[20]; + ShaGetLastHash(0,hash); + if (append->checkvalue != * (LPDWORD) &hash[0]) { + ZeroMemory(hash,20); + goto error; + } + } + + // SET THE EXACT OUTPUT SIZE + dwDstBytes -= BLOCKSIZE - append->lastblocksize; + DestroyKeys(); + return dwDstBytes; + +error: + DestroyKeys(); + return 0; +} + + +//****************************************************************** +// CalcEncodeDstBytes() +// -- calculate the number of bytes required to hold the encoded +// file information including the append record +//****************************************************************** +DWORD CalcEncodeDstBytes(DWORD dwSrcBytes) { + app_assert(dwSrcBytes); + if (dwSrcBytes & (BLOCKSIZE-1)) + dwSrcBytes += BLOCKSIZE - (dwSrcBytes & (BLOCKSIZE-1)); + dwSrcBytes += sizeof(appendrec); + return dwSrcBytes; +} + + +//****************************************************************** +//****************************************************************** +void EncodeFile(BYTE * pbSrcDst,DWORD dwSrcBytes,DWORD dwDstBytes,const char * pszPassword) { + app_assert(pbSrcDst); + app_assert(pszPassword); + + // make sure the user allocated enough bytes for the destination + if (dwDstBytes != CalcEncodeDstBytes(dwSrcBytes)) + app_fatal("Invalid encode parameters"); + + // initialize encryption keys + InitializeKeys(1,pszPassword); + + // ENCRYPT THE FILE BLOCK BY BLOCK + DWORD lastblocksize = 0; + BYTE buffer[2][BLOCKSIZE]; + + while (dwSrcBytes) { + + // get the next src data chunk + DWORD blocksize = min(dwSrcBytes,BLOCKSIZE); + CopyMemory(&buffer[0][0],pbSrcDst,blocksize); + + // blank out any unused portion of the buffer + if (blocksize < BLOCKSIZE) + ZeroMemory(&buffer[0][blocksize],BLOCKSIZE - blocksize); + + // ENCRYPT THE BLOCK + { + BYTE hash[20]; + ShaGetLastHash(0,hash); + ShaHash(0,buffer[0],NULL); + int loop; + + #if ! DES && ! IDEA + for (loop = 0; loop < BLOCKSIZE; loop++) + buffer[0][loop] = hash[loop % 20] ^ buffer[0][loop]; + #endif + + #if DES + for (loop = 0; loop < BLOCKSIZE; loop++) + buffer[1][loop] = hash[loop % 20] ^ buffer[0][loop]; + for (loop = 0; loop < BLOCKSIZE; loop += 8) { + DesEncrypt(0,&buffer[1][loop],&buffer[0][loop]); + DesEncrypt(1,&buffer[0][loop],&buffer[1][loop]); + DesEncrypt(2,&buffer[1][loop],&buffer[0][loop]); + } + #endif + + #if IDEA + for (loop = 0; loop < BLOCKSIZE; loop++) + buffer[1][loop] = buffer[0][loop]+hash[(BLOCKSIZE-(loop+1)) % 20]; + for (loop = 0; loop < BLOCKSIZE; loop += 8) { + IdeaEncrypt(0,&buffer[1][loop],&buffer[0][loop]); + IdeaEncrypt(1,&buffer[0][loop],&buffer[1][loop]); + IdeaEncrypt(2,&buffer[1][loop],&buffer[0][loop]); + } + #endif + + // hide hash info + ZeroMemory(hash,sizeof(hash)); + } + + // write encrypted chunk to destination + CopyMemory(pbSrcDst,&buffer[0][0],BLOCKSIZE); + + // next block + pbSrcDst += BLOCKSIZE; + dwSrcBytes -= blocksize; + lastblocksize = blocksize; + } + + // hide buffer + ZeroMemory(buffer,sizeof(buffer)); + + // APPEND THE TERMINATION RECORD + BYTE hash[20]; + appendrec * append = (appendrec *) pbSrcDst; + ShaGetLastHash(0,hash); + append->checkvalue = * (LPDWORD) &hash[0]; + append->version = VERSION; + append->lastblocksize = (BYTE) lastblocksize; + append->reserved = 0; + + DestroyKeys(); +} diff --git a/src/CONTROL.CPP b/src/CONTROL.CPP new file mode 100644 index 0000000..a8a8dd8 --- /dev/null +++ b/src/CONTROL.CPP @@ -0,0 +1,2949 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Control panel file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/CONTROL.CPP 2 2/05/97 10:41a Dbrevik2 $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "engine.h" +#include "control.h" +#include "gendung.h" +#include "scrollrt.h" +#include "msg.h" + +#include "items.h" +#include "itemdat.h" +#include "player.h" +#include "monster.h" +#include "objects.h" +#include "cursor.h" +#include "spells.h" +#include "missiles.h" + +#include "town.h" +#include "towners.h" +#include "trigs.h" +#include "gamemenu.h" +#include "inv.h" +#include "minitext.h" +#include "lighting.h" +#include "stores.h" +#include "automap.h" +#include "quests.h" + +#include "multi.h" + +#include "error.h" +#include "spelldat.h" + +/*-----------------------------------------------------------------------** +** Registration info +**-----------------------------------------------------------------------*/ +#include "regconst.h" +char sgszRegSig5[REG_LEN] = "REGISTRATION_BLOCK"; + +/*-----------------------------------------------------------------------** +** Local defines +**-----------------------------------------------------------------------*/ + +#define MANABUFFSIZE 7744 // 88x88 +#define LIFEBUFFSIZE 7744 + +#define STRN_GOLD 0 +#define STRN_BLUE 1 +#define STRN_RED 2 +#define STRN_ORANGE 3 +#define STRN_GREY 4 + +// old version was 4/76 +#define NUMSPBKBTNS 5 +#define SPBKBTNWDTH 61 +/*-----------------------------------------------------------------------** +** Global variables +**-----------------------------------------------------------------------*/ + +BYTE *pBtmBuff; // Offscreen control panel buffer +BYTE *pStatusPanel; +BYTE *pPanelButtons; +BYTE *pPanelText; +BYTE *pManaBuff; +BYTE *pLifeBuff; +BYTE *pChrPanel; +BYTE *pChrButtons; +BYTE *pSpellCels; +BYTE *pGBoxBuff; + +char panelstr[4][64]; +int pstrjust[4]; +BOOL pinfoflag; +int pnumlines; + +char infostr[256]; +char infoclr; + +char tempstr[256]; + +int pentaspin; +int dropGoldValue; +int initialDropGoldValue; +int initialDropGoldIndex; + +const BYTE fonttrans[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 0, 54, 44, 57, 58, 56, 55, 47, 40, 41, 59, 39, 50, 37, 51, 52, // 32-47 + 36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 48, 49, 60, 38, 61, 53, // 48-63 + 62, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 64-79 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 63, 43, 64, 65, // 80-95 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 96-111 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 40, 66, 41, 67, 0 }; // 112-127 + +const BYTE fontkern[68] = { 8, // Space/Invalid + 10, 7, 9, 8, 7, 6, 8, 8, 3, 3, 8, 6, 11, 9, 10, 6, // a-p + 9, 9, 6, 9, 11, 10, 13, 10, 11, 7, // q-z + 5, 7, 7, 8, 7, 7, 7, 7, 7, 10, // 1-0 + 4, 5, 6, 3, 3, 4, 3, 6, 6, 3, 3, 3, 3, 3, 2, 7, 6, 3, 10, 10, 6, // misc + 6, 7, 4, 4, 9, 6, 6, 12, 3, 7 }; // misc + +static const long fontofs[5][5] = { + { 456433, 24576, 24576, 24576, 24756 }, + { 447217, 465649, 24576, 24576, 24576 }, + { 442609, 456433, 470257, 24576, 24576 }, + { 439537, 451057, 461809, 473329, 24576 }, + { 438001, 447217, 456433, 465649, 474097 } }; + +BOOL drawhpflag; +BOOL drawmanaflag; +BOOL chrflag; + +/*-----------------------------------------------------------------------*/ +typedef enum { + SI_INVALID, + SI_FIREBOLT, + SI_HEAL, + SI_LIGHTNING, + SI_FLASH, + SI_IDENTIFY, + SI_FIREWALL, + SI_TOWNPORTAL, + SI_STONECURSE, + SI_INFRAVISION, + SI_HEALOTHER, + SI_NOVA, + SI_FIREBALL, + SI_MANASHIELD, + SI_FLAMEWAVE, + SI_INFERNO, + SI_CHAINLIGHTNING, + SI_JABBERWOCK, // with eyes of flame... + SI_GUARDIAN, + SI_BLOODRITUAL, // unused, looks like Krull + SI_INVISIBILITY, + SI_GOLEM, + SI_ETHEREALIZE, + //SI_BLOODBOIL, // unused + SI_RAGE, // Replaced bloodboil. + SI_TELEPORT, + SI_APOCALYPSE, + SI_REPAIR, + SI_EMPTY, + SI_PHASE, + SI_RECHARGE, + SI_BONESPIRIT, + SI_REDSKULL, // unused + SI_PENTAGRAM, // unused + SI_FIRECLOUD, // unused + SI_LONGHORN, // unused + SI_PENTASTAR, // unused + SI_BLOODSTAR, + SI_DISARM, + SI_ELEMENTAL, + SI_CHARGEDBOLT, + SI_TELEKINESIS, + SI_RESURRECT, + SI_HOLYBOLT, + +#if 1 + // new icons + SI_WARP, + SI_SEARCH, + SI_REFLECT, + SI_LIGHTNINGWALL, + SI_IMMOLATION, + SI_BERSERK, + SI_RINGOFFIRE, + SI_JESTER, + SI_MANA, + + SI_LAST + +#else + // faked icons + SI_WARP = SI_PHASE, + SI_SEARCH = SI_INFRAVISION, + SI_REFLECT = SI_MANASHIELD, + SI_LIGHTNINGWALL = SI_FIREWALL, + SI_IMMOLATION = SI_NOVA, + SI_BERSERK = SI_REDSKULL, + SI_RINGOFFIRE = SI_PENTAGRAM, + SI_MANA = SI_BLOODRITUAL, + SI_JESTER = SI_ETHEREALIZE, + + SI_LAST = SI_HOLYBOLT+1 +#endif +} SPICONTYPE; + +BOOL spselflag = FALSE; +int pSpell, pSplType; +byte SpellTrans[256]; +static char SpellITbl[MAXSPELLS] = { + SI_EMPTY, // Invalid + SI_FIREBOLT, // SPL_FIREBOLT + SI_HEAL, // SPL_HEAL + SI_LIGHTNING, // SPL_LIGHTNING + SI_FLASH, // SPL_FLASH + SI_IDENTIFY, // SPL_IDENTIFY + SI_FIREWALL, // SPL_WALL + SI_TOWNPORTAL, // SPL_TOWN + SI_STONECURSE, // SPL_STONE + SI_INFRAVISION, // SPL_INFRA + SI_PHASE, // SPL_PHASE + SI_MANASHIELD, // SPL_MANASHLD + SI_FIREBALL, // SPL_FIREBALL + SI_GUARDIAN, // SPL_GUARDIAN + SI_CHAINLIGHTNING, // SPL_CHAIN + SI_FLAMEWAVE, // SPL_WAVE + SI_GUARDIAN, // SPL_DOOM + SI_BLOODRITUAL, // SPL_BLOODR + SI_NOVA, // SPL_NOVA + SI_INVISIBILITY, // SPL_INVIS + SI_INFERNO, // SPL_FLAME + SI_GOLEM, // SPL_GOLEM + //SI_BLOODBOIL, // SPL_BLOODB + SI_RAGE, // SPL_RAGE + SI_TELEPORT, // SPL_TELE + SI_APOCALYPSE, // SPL_APOCA + SI_ETHEREALIZE, // SPL_ETHER + SI_REPAIR, // SPL_REPAIR + SI_RECHARGE, // SPL_RECHARGE + SI_DISARM, // SPL_DISARM + SI_ELEMENTAL, // SPL_ELEMENT + SI_CHARGEDBOLT, // SPL_CBOLT + SI_HOLYBOLT, // SPL_HBOLT + SI_RESURRECT, // SPL_RESURRECT + SI_TELEKINESIS, // SPL_TELEKINESIS + SI_HEALOTHER, // SPL_HEALOTHER + SI_BLOODSTAR, // SPL_BSTAR + SI_BONESPIRIT, // SPL_BONESPIRT + SI_MANA, // SPL_MANA + SI_MANA, // SPL_FMANA + SI_JESTER, // SPL_RANDOM + SI_LIGHTNINGWALL, // SPL_LTWALL + SI_IMMOLATION, // SPL_IMMOLATION + SI_WARP, // SPL_TELESTAIRS + SI_REFLECT, // SPL_REFLECT + SI_BERSERK, // SPL_BERSERK + SI_RINGOFFIRE, // SPL_RINGOFFIRE + SI_SEARCH, // SPL_SHOWMAGITEMS + SI_PENTASTAR, // SPL_RUNEOFFIRE + SI_PENTASTAR, // SPL_RUNEOFLIGHT + SI_PENTASTAR, // SPL_RUNEOFNOVA + SI_PENTASTAR, // SPL_RUNEOFIMMOLATION + SI_PENTASTAR, // SPL_RUNEOFSTONE + +#if defined (HELLFIRE2) + SI_RINGOFFIRE, // SPL_RINGOFLIGHT + SI_REDSKULL, // SPL_AURA + SI_ETHERALIZE, // SPL_SPIRALFIREBALL +#endif + }; + +/*-----------------------------------------------------------------------*/ + +#define NUMPBTNS 8 +#define SINGLE_PBTNS 6 +#define MULTI_PBTNS NUMPBTNS + +#define PBTN_CHR 0 +#define PBTN_TPLR1 0 +#define PBTN_QUEST 1 +#define PBTN_AMAP 2 +#define PBTN_TPLR2 2 +#define PBTN_MENU 3 +#define PBTN_INV 4 +#define PBTN_TPLR3 4 +#define PBTN_SBOOK 5 +#define PBTN_TALK 6 +#define PBTN_ATTACK 7 + +// x1, y1, width, height, talk pushable +int PanBtnPos[NUMPBTNS][5] = { + { 9, 361, 71, 19, TRUE }, + { 9, 387, 71, 19, FALSE }, + { 9, 427, 71, 19, TRUE }, + { 9, 453, 71, 19, FALSE }, + { 560, 361, 71, 19, TRUE }, + { 560, 387, 71, 19, FALSE }, + { 87, 443, 33, 32, TRUE }, + { 527, 443, 33, 32, TRUE }, +}; + +char *PanBtnHotKey[NUMPBTNS] = { + "'c'", + "'q'", + "Tab", + "Esc", + "'i'", + "'b'", + "Enter", + NULL }; + +char *PanBtnStr[NUMPBTNS] = { + "Character Information", + "Quests log", + "Automap", + "Main Menu", + "Inventory", + "Spell book", + "Send Message", + "Player Attack" }; + +BOOL panbtn[NUMPBTNS]; +BOOL drawbtnflag, panbtndown; +BOOL panelflag; // panel info draw +int numpanbtns; + +BYTE *pDurIcons; + +BOOL drawdurflag; +BOOL dropGoldFlag; + +/*-----------------------------------------------------------------------*/ + +#define NUMCBTNS 4 + +#define CBTN_STR 0 +#define CBTN_MAG 1 +#define CBTN_DEX 2 +#define CBTN_VIT 3 + +// x1, y1, width, height +int ChrBtnPos[NUMCBTNS][4] = { + { 137, 138, 41, 22 }, + { 137, 166, 41, 22 }, + { 137, 195, 41, 22 }, + { 137, 223, 41, 22 } }; + +BOOL chrbtn[NUMCBTNS]; +BOOL chrbtndown; + +/*-----------------------------------------------------------------------*/ + +BOOL lvlbtndown; + +/*-----------------------------------------------------------------------*/ + +BYTE *pSpellBkCel; +BYTE *pSBkBtnCel; +BYTE *pSBkIconCels; + +int sbooktab; +BOOL sbookflag; + +// The first entry will be filled during init with the player types skill +int SpellPages[6][7] = { + { 0, SPL_FIREBOLT, SPL_CBOLT, SPL_HBOLT, SPL_HEAL, SPL_HEALOTHER, SPL_FLAME }, + { SPL_RESURRECT, SPL_WALL, SPL_TELEKINESIS, SPL_LIGHTNING, SPL_TOWN, SPL_FLASH, SPL_STONE }, + { SPL_PHASE, SPL_MANASHLD, SPL_ELEMENT, SPL_FIREBALL, SPL_WAVE, SPL_CHAIN, SPL_GUARDIAN}, + { SPL_NOVA, SPL_GOLEM, SPL_TELE, SPL_APOCA, SPL_BONESPIRIT, SPL_BSTAR, SPL_ETHER }, + { SPL_LTWALL, SPL_IMMOLATION, SPL_TELESTAIRS, SPL_REFLECT, SPL_BERSERK, SPL_RINGOFFIRE, SPL_SHOWMAGITEMS }, +#if defined (HELLFIRE2) + { SPL_RINGOFLIGHT, SPL_AURA, SPL_SPIRALFIREBALL, -1, -1, -1, -1 } +#else + { -1, -1, -1, -1, -1, -1, -1 } +#endif +}; + +/*-----------------------------------------------------------------------*/ +#define MAX_TALK_SAVES 8 // must be pow2 +BOOL talkflag; +static int tspin; +static long talkofs; +static char sgszTalkMsg[MAX_SEND_STR_LEN]; +static BYTE sgbTalkSavePos; +static BYTE sgbNextTalkSave; +static char sgszTalkSaveMsg[MAX_TALK_SAVES][MAX_SEND_STR_LEN]; +static BYTE sgbPlrTalkTbl[MAX_PLRS]; +static BYTE *pTalkPanel; +static BYTE *pMultiBtns; +static BYTE *pTalkBtns; +static BOOL talkbtndown[3]; + +void TalkStart(); +void TalkEnd(); +void PlrStringXY(int x1, int y, int x2,const char * pszStr,char col); + + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +void SetPlrHandItem(ItemStruct *h, int idata); +void GetPlrHandSeed(ItemStruct *h); +void GetGoldSeed(int pnum, ItemStruct *h); +void SetSpellTrans(char); + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawSpellCel(long xp, long yp, BYTE *pCels, long nCel, long w) +{ + BYTE *pTo; + byte *ttbl; + long RLELen; + + ttbl = &SpellTrans[0]; + app_assert(gpBuffer); + pTo = gpBuffer + nBuffWTbl[yp] + xp; + __asm { + mov ebx,dword ptr [pCels] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] + sub eax,dword ptr [ebx] + mov dword ptr [RLELen],eax + + mov esi,dword ptr [pCels] // Source + add esi,dword ptr [ebx] + + mov edi,dword ptr [pTo] // Dest + + mov eax,dword ptr [RLELen] + add eax,esi + mov dword ptr [RLELen],eax + + mov ebx,dword ptr [ttbl] + +_T1Lp1: mov edx,dword ptr [w] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + mov ecx,eax + shr ecx,1 + jnc _T1w + lodsb + xlatb + stosb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T1x +_T1Lp3: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T1Lp3 +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,768 + sub edi,dword ptr [w] + cmp esi,dword ptr [RLELen] + jnz _T1Lp1 + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetSpellTrans(char t) +{ + int i; + + if (t == STRN_GOLD) { + for (i = 0; i < 128; i++) SpellTrans[i] = i; + } + for (i = 128; i < 256; i++) SpellTrans[i] = i; + SpellTrans[255] = 0; + + switch (t) { + case STRN_BLUE : + SpellTrans[144] = 177; + SpellTrans[145] = 179; + SpellTrans[146] = 181; + for (i = 176; i < 192; i++) { + SpellTrans[i - 16] = i; // 160-175 + SpellTrans[i + 16] = i; // 192-207 + SpellTrans[i + 32] = i; // 208-223 + } + break; + case STRN_ORANGE : + SpellTrans[144] = 209; + SpellTrans[145] = 211; + SpellTrans[146] = 213; + for (i = 208; i < 224; i++) { + SpellTrans[i - 48] = i; // 160-175 + SpellTrans[i - 16] = i; // 192-207 + } + break; + case STRN_RED : + SpellTrans[144] = 161; + SpellTrans[145] = 163; + SpellTrans[146] = 165; + for (i = 160; i < 176; i++) { + SpellTrans[i + 32] = i; // 192-207 + SpellTrans[i + 48] = i; // 208-223 + } + break; + case STRN_GREY : + SpellTrans[144] = 241; + SpellTrans[145] = 243; + SpellTrans[146] = 245; + for (i = 240; i < 255; i++) { + SpellTrans[i - 80] = i; // 160-174 + SpellTrans[i - 48] = i; // 192-206 + SpellTrans[i - 32] = i; // 208-222 + } + SpellTrans[175] = 0; + SpellTrans[207] = 0; + SpellTrans[223] = 0; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawSpellIcon() { + char t, sn; + int sl; + + t = plr[myplr]._pRSplType; + sn = plr[myplr]._pRSpell; + sl = plr[myplr]._pSplLvl[sn] + plr[myplr]._pISplLvlAdd; + if ((t == SPT_MEMORIZED) && (sn != -1)) { + if (!CheckSpell(myplr, sn, t, TRUE)) t = STRN_GREY; + if (sl <= 0 ) t = STRN_GREY; + } + + if ((currlevel == 0) && (t != STRN_GREY) && (spelldata[sn].sTownSpell == FALSE)) t = STRN_GREY; + if (plr[myplr]._pRSpell < 0) t = STRN_GREY; + SetSpellTrans(t); + if (sn != -1) DrawSpellCel(629, 631, pSpellCels, SpellITbl[sn], 56); + else DrawSpellCel(629, 631, pSpellCels, 27, 56); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#define SPLICONSIZE 56 +#define SPLICONRIGHT 636 // (640 - (trunc(640 / 56) * 56)) / 2) + 640 + 64 - SPLICONSIZE +#define SPLICONLEFT 20 // SPLICONRIGHT - (trunc(640 / 56) * 56) - SPLICONSIZE + +#define SPELLICON_BLANK SI_LAST +#define SPELLICON_F5 (SI_LAST + 5) + +void DrawSpellList() +{ + int mx,my,x,y,i,j,t; + __int64 mask,spl; + int s,c,hk; + int v, selbox; + + x = SPLICONRIGHT; + y = 495; + + pSpell = -1; + infostr[0] = 0; + ClearPanel(); + for (j = 0; j < 4; j++) { + switch(j) { + case 0: + SetSpellTrans(STRN_GOLD); + spl = plr[myplr]._pAblSpells; + selbox = SPELLICON_BLANK + 3; + break; + case 1: + spl = plr[myplr]._pMemSpells; + selbox = SPELLICON_BLANK + 4; + break; + case 2: + SetSpellTrans(STRN_RED); + spl = plr[myplr]._pScrlSpells; + selbox = SPELLICON_BLANK + 1; + break; + case 3: + SetSpellTrans(STRN_ORANGE); + spl = plr[myplr]._pISpells; + selbox = SPELLICON_BLANK + 2; + break; + } + mask = 1; + for (i = 1; i < SPL_LAST; i++) { + if ((spl & mask) != 0) + { + if (j == 1) { + v = plr[myplr]._pSplLvl[i] + plr[myplr]._pISplLvlAdd; + if ( v < 0 ) v = 0; + if (v > 0) t = STRN_BLUE; + else t = STRN_GREY; + SetSpellTrans(t); + } + + if ((currlevel == 0) && (spelldata[i].sTownSpell == FALSE)) SetSpellTrans(STRN_GREY); + + DrawSpellCel(x, y, pSpellCels, SpellITbl[i], SPLICONSIZE); + mx = x - 64; + my = y - (160 + SPLICONSIZE); + if ((MouseX >= mx) && (MouseX < (mx+SPLICONSIZE)) && (MouseY >= my) && (MouseY < (my+SPLICONSIZE))) { + pSpell = i; + pSplType = j; + if (plr[myplr]._pClass == CLASS_MONK && i == SPL_SHOWMAGITEMS) + pSplType = 0; + DrawSpellCel(x, y, pSpellCels, selbox, SPLICONSIZE); + switch (pSplType) { + case 0: + sprintf(infostr, "%s Skill", spelldata[pSpell].sSkillText); + break; + case 1: + sprintf(infostr, "%s Spell", spelldata[pSpell].sNameText); + if (pSpell == SPL_HBOLT) { + sprintf(tempstr, "Damages undead only"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); + else sprintf(tempstr, "Spell Level %i", v); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 2: + sprintf(infostr, "Scroll of %s", spelldata[pSpell].sNameText); + c = 0; + for (s = 0; s < plr[myplr]._pNumInv; s++) { + if ((plr[myplr].InvList[s]._itype != -1) && + ((plr[myplr].InvList[s]._iMiscId == IMID_SCROLL) || + (plr[myplr].InvList[s]._iMiscId == IMID_TSCROLL))) { + if (plr[myplr].InvList[s]._iSpell == pSpell) c++; + } + } + for (s = 0; s < MAXSPD; s++) { + if ((plr[myplr].SpdList[s]._itype != -1) && + ((plr[myplr].SpdList[s]._iMiscId == IMID_SCROLL) || + (plr[myplr].SpdList[s]._iMiscId == IMID_TSCROLL))) { + if (plr[myplr].SpdList[s]._iSpell == pSpell) c++; + } + } + if (c == 1) strcpy(tempstr, "1 Scroll"); + else sprintf(tempstr, "%i Scrolls", c); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 3: + sprintf(infostr, "Staff of %s", spelldata[pSpell].sNameText); + if (plr[myplr].Hand1Item._iCharges == 1) strcpy(tempstr, "1 Charge"); + else sprintf(tempstr, "%i Charges", plr[myplr].Hand1Item._iCharges); + AddPanelString(tempstr, TEXT_CENTER); + break; + } + for (hk = 0; hk < 4; hk++) { + if ((plr[myplr]._pSplHotKey[hk] == pSpell) && (plr[myplr]._pSplTHotKey[hk] == pSplType)) { + DrawSpellCel(x, y, pSpellCels, SPELLICON_F5+hk, SPLICONSIZE); + sprintf(tempstr, "Spell Hot Key #F%i", hk+5); + AddPanelString(tempstr, TEXT_CENTER); + } + } + } + x -= SPLICONSIZE; + if (x == SPLICONLEFT) { + x = SPLICONRIGHT; + y -= SPLICONSIZE; + } + } + mask = mask << 1; + } + if (spl && (x != SPLICONRIGHT)) x -= SPLICONSIZE; + if (x == SPLICONLEFT) { + x = SPLICONRIGHT; + y -= SPLICONSIZE; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void SetSpell() +{ + spselflag = FALSE; + if (pSpell != -1) { + ClearPanel(); + plr[myplr]._pRSpell = pSpell; + plr[myplr]._pRSplType = pSplType; + force_redraw = FULLDRAW; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetSpellHK(int hk) +{ + if (pSpell != -1) { + for (int i = 0; i < 4; i++) { + if ((plr[myplr]._pSplHotKey[i] == pSpell) && (plr[myplr]._pSplTHotKey[i] == pSplType)) + plr[myplr]._pSplHotKey[i] = -1; + } + plr[myplr]._pSplHotKey[hk] = pSpell; + plr[myplr]._pSplTHotKey[hk] = pSplType; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void GetSpellHK(int hk) +{ + __int64 spl; + + if (plr[myplr]._pSplHotKey[hk] == -1) return; + + switch(plr[myplr]._pSplTHotKey[hk]) { + case 0: + spl = plr[myplr]._pAblSpells; + break; + case 1: + spl = plr[myplr]._pMemSpells; + break; + case 2: + spl = plr[myplr]._pScrlSpells; + break; + case 3: + spl = plr[myplr]._pISpells; + break; + } + spl &= (((__int64)1) << (plr[myplr]._pSplHotKey[hk]-1)); + if (spl) { + plr[myplr]._pRSpell = plr[myplr]._pSplHotKey[hk]; + plr[myplr]._pRSplType = plr[myplr]._pSplTHotKey[hk]; + force_redraw = FULLDRAW; + } +} + +/*-----------------------------------------------------------------------** +** Draws a small font letter +**-----------------------------------------------------------------------*/ + +void DrawPanelFont (long poffset, long nCel, char clr) +{ + app_assert(gpBuffer); + __asm { + mov ebx,dword ptr [pPanelText] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + + mov edx,dword ptr [ebx+4] // Length + sub edx,dword ptr [ebx] + + mov esi,dword ptr [pPanelText] // Source + add esi,dword ptr [ebx] + + mov edi,dword ptr [gpBuffer] // Dest + add edi,dword ptr [poffset] + + mov ebx,edx + add ebx,esi + + xor edx,edx + mov dl,byte ptr [clr] + cmp edx,ICOLOR_WHITE + jz _T1Lp1 // Normal / White + cmp edx,ICOLOR_BLUE + jz _T2Lp1 // Blue + cmp edx,ICOLOR_RED + jz _T3Lp1 // Red + jmp _T4Lp1 // Gold + +/*- White ---------------------------------------------------------------*/ + +_T1Lp1: mov edx,13 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax // Draw + mov ecx,eax + shr ecx,1 + jnc _T1w + movsb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + movsw + jecxz _T1x +_T1Lp3: rep movsd +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,781 + cmp ebx,esi + jnz _T1Lp1 + jmp _Done + +/*- Blue ----------------------------------------------------------------*/ + +_T2Lp1: mov edx,13 + +_T2Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T2J + + sub edx,eax // Draw + mov ecx,eax +_T2Lp3: lodsb + cmp al,253 + ja _T2F + cmp al,240 + jb _T2Sv + sub al,62 + jmp _T2Sv +_T2F: mov al,191 +_T2Sv: stosb + loop _T2Lp3 + or edx,edx + jz _T2Nxt + jmp _T2Lp2 + +_T2J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T2Lp2 +_T2Nxt: sub edi,781 + cmp ebx,esi + jnz _T2Lp1 + jmp _Done + +/*- Red -----------------------------------------------------------------*/ + +_T3Lp1: mov edx,13 + +_T3Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T3J + + sub edx,eax // Draw + mov ecx,eax +_T3Lp3: lodsb + cmp al,240 + jb _T3Sv + sub al,16 +_T3Sv: stosb + loop _T3Lp3 + or edx,edx + jz _T3Nxt + jmp _T3Lp2 + +_T3J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T3Lp2 +_T3Nxt: sub edi,781 + cmp ebx,esi + jnz _T3Lp1 + jmp _Done + +/*- Gold ----------------------------------------------------------------*/ + +_T4Lp1: mov edx,13 + +_T4Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T4J + + sub edx,eax // Draw + mov ecx,eax +_T4Lp3: lodsb + cmp al,240 + jb _T4Sv + cmp al,254 + jae _T4val + sub al,46 + jmp _T4Sv +_T4val: mov al,207 +_T4Sv: stosb + loop _T4Lp3 + or edx,edx + jz _T4Nxt + jmp _T4Lp2 + +_T4J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T4Lp2 +_T4Nxt: sub edi,781 + cmp ebx,esi + jnz _T4Lp1 + +/*-----------------------------------------------------------------------*/ + +_Done: + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AddPanelString(const char * str, int just) +{ + strcpy(panelstr[pnumlines],str); + pstrjust[pnumlines] = just; + if (pnumlines < 4) pnumlines++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ClearPanel() +{ + pnumlines = 0; + pinfoflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CopyCtrlPan(int sx, int sy, int deltax, int deltay, int dx, int dy) +{ + long src, dest; + + app_assert(gpBuffer); + src = (sy * 640) + sx; + dest = (dy * 768) + dx; + __asm { + mov esi,dword ptr [pBtmBuff] + add esi,dword ptr [src] + mov edi,dword ptr [gpBuffer] + add edi,dword ptr [dest] + + xor ebx,ebx + mov bx,word ptr [deltax] + xor edx,edx + mov dx,word ptr [deltay] +_CLp: mov ecx,ebx + shr ecx,1 + jnc _Tw + movsb + jecxz _Tx +_Tw: shr ecx,1 + jnc _TLp + movsw + jecxz _Tx +_TLp: rep movsd +_Tx: add esi,640 + sub esi,ebx + add edi,768 + sub edi,ebx + dec edx + jnz _CLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitPanelStr() +{ + ClearPanel(); + //AddPanelString("Welcome to Diablo", TEXT_CENTER); // This was ok (pre Demo) now its not + //AddPanelString("Press F1 for help", TEXT_CENTER); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void BuffCopy(BYTE *pSrc, int y1, int y2, int dx, int dy) +{ + long srco, desto, deltay; + + app_assert(gpBuffer); + srco = y1 * 88; + desto = (dy * 768) + dx; + deltay = y2 - y1; + __asm { + mov esi,dword ptr [pSrc] + add esi,dword ptr [srco] + mov edi,dword ptr [gpBuffer] + add edi,dword ptr [desto] + + mov edx,dword ptr [deltay] +_YLp: mov ecx,22 + rep movsd + add edi,680 + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TransBuffCopy(BYTE *pSrc, long srcwidth, long srcoff, BYTE *pDest, long destoff, long dy) +{ + __asm { + mov esi,dword ptr [pSrc] + add esi,dword ptr [srcoff] + mov edi,dword ptr [pDest] + add edi,dword ptr [destoff] + + mov edx,dword ptr [dy] +_YLp: mov ecx,59 +_XLp: lodsb + or al,al + jz _Skip + mov byte ptr [edi],al +_Skip: inc edi + loop _XLp + add esi,dword ptr [srcwidth] + sub esi,59 + add edi,709 + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawHealthTop() +{ + double v; + int dv; + + if (plr[myplr]._pMaxHP <= 0) + v = 0.0; + else + v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; + dv = (int)v; + plr[myplr]._pHPPer = dv; + + + long dy; + + dy = 80 - plr[myplr]._pHPPer; + if (dy > 11) dy = 11; + dy += 2; + + app_assert(gpBuffer); + TransBuffCopy(pLifeBuff, 88, 277, gpBuffer, 383405, dy); + if (dy != 13) TransBuffCopy(pBtmBuff, 640, (dy * 640) + 2029, gpBuffer, (dy * 768) + 383405, 13 - dy); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawHealthBar() +{ + double v; + int dv; + + if (plr[myplr]._pMaxHP <= 0) + v = 0.0; + else + v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; + dv = (int)v; + plr[myplr]._pHPPer = dv; + + if (dv > 69) dv = 69; + if (dv != 69) BuffCopy(pLifeBuff, 16, 85-dv, 160, 512); + if (dv != 0) CopyCtrlPan(96, 85-dv, 88, dv, 160, 581-dv); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawManaTop() +{ + long dy; + + dy = 80 - plr[myplr]._pManaPer; + if (dy > 11) dy = 11; + dy += 2; + + app_assert(gpBuffer); + TransBuffCopy(pManaBuff, 88, 277, gpBuffer, 383771, dy); + if (dy != 13) TransBuffCopy(pBtmBuff, 640, (dy * 640) + 2395, gpBuffer, (dy * 768) + 383771, 13 - dy); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CalcInitBallPer() +{ + double v; + int dv; + long m,mm; + + mm = plr[myplr]._pMaxMana; + m = plr[myplr]._pMana; + if (mm < 0) mm = 0; + if (m < 0) m = 0; + if (mm == 0) dv = 0; + else { + v = ((double)m / (double)mm) * 80; + dv = (int)v; + } + plr[myplr]._pManaPer = dv; + v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; + dv = (int)v; + plr[myplr]._pHPPer = dv; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawManaBar() +{ + double v; + int dv; + long m,mm; + + mm = plr[myplr]._pMaxMana; + m = plr[myplr]._pMana; + if (mm < 0) mm = 0; + if (m < 0) m = 0; + if (mm == 0) dv = 0; + else { + v = ((double)m / (double)mm) * 80; + dv = (int)v; + } + plr[myplr]._pManaPer = dv; + + if (dv > 69) dv = 69; + if (dv != 69) BuffCopy(pManaBuff, 16, 85-dv, 528, 512); + if (dv != 0) CopyCtrlPan(464, 85-dv, 88, dv, 528, 581-dv); + + DrawSpellIcon(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitControlPan() +{ + int i; + + app_assert(! pBtmBuff); + if (gbMaxPlayers == 1) { + pBtmBuff = DiabloAllocPtrSig(BTMBUFFSIZE,'CTRL'); + ZeroMemory(pBtmBuff,BTMBUFFSIZE); + } else { + pBtmBuff = DiabloAllocPtrSig(BTMBUFFMULTISIZE,'CTRL'); + ZeroMemory(pBtmBuff,BTMBUFFMULTISIZE); + } + pManaBuff = DiabloAllocPtrSig(MANABUFFSIZE,'CTRL'); + ZeroMemory(pManaBuff,MANABUFFSIZE); + pLifeBuff = DiabloAllocPtrSig(LIFEBUFFSIZE,'CTRL'); + ZeroMemory(pLifeBuff,LIFEBUFFSIZE); + pPanelText = LoadFileInMemSig("CtrlPan\\SmalText.CEL",NULL,'CTRL'); + pChrPanel = LoadFileInMemSig("Data\\Char.CEL",NULL,'CTRL'); + pSpellCels = LoadFileInMemSig("Data\\SpelIcon.CEL",NULL,'CTRL'); // was in CtrlPan + SetSpellTrans(STRN_GOLD); + + // Init Control panel offscreen buffer + pStatusPanel = LoadFileInMemSig("CtrlPan\\Panel8.CEL",NULL,'CTRL'); + DrawBuffCel(pBtmBuff, 0, 143, BTMBUFFX, pStatusPanel, 1, 640); + DiabloFreePtr (pStatusPanel); + pStatusPanel = LoadFileInMemSig("CtrlPan\\P8Bulbs.CEL",NULL,'CTRL'); + DrawBuffCel(pLifeBuff, 0, 87, 88, pStatusPanel, 1, 88); + DrawBuffCel(pManaBuff, 0, 87, 88, pStatusPanel, 2, 88); + DiabloFreePtr (pStatusPanel); + talkflag = FALSE; + if (gbMaxPlayers != 1) { + pTalkPanel = LoadFileInMemSig("CtrlPan\\TalkPanl.CEL",NULL,'CTRL'); + DrawBuffCel(pBtmBuff, 0, 287, BTMBUFFX, pTalkPanel, 1, 640); + DiabloFreePtr (pTalkPanel); + pMultiBtns = LoadFileInMemSig("CtrlPan\\P8But2.CEL",NULL,'CTRL'); + pTalkBtns = LoadFileInMemSig("CtrlPan\\TalkButt.CEL",NULL,'CTRL'); + talkofs = 0; + sgszTalkMsg[0] = 0; + for (i = 0; i < MAX_PLRS; i++) sgbPlrTalkTbl[i] = TRUE; + for (i = 0; i < 3; i++) talkbtndown[i] = FALSE; + } + panelflag = FALSE; + + lvlbtndown = FALSE; + + pPanelButtons = LoadFileInMemSig("CtrlPan\\Panel8bu.CEL",NULL,'CTRL'); + for (i = 0; i < NUMPBTNS; i++) panbtn[i] = FALSE; + panbtndown = FALSE; + if (gbMaxPlayers == 1) numpanbtns = SINGLE_PBTNS; + else numpanbtns = MULTI_PBTNS; + + pChrButtons = LoadFileInMemSig("Data\\CharBut.CEL",NULL,'CTRL'); + for (i = 0; i < NUMCBTNS; i++) chrbtn[i] = FALSE; + chrbtndown = FALSE; + + pDurIcons = LoadFileInMemSig("Items\\DurIcons.CEL",NULL,'CTRL'); + + strcpy(infostr,""); + InitPanelStr(); + drawhpflag = TRUE; + drawmanaflag = TRUE; + chrflag = FALSE; + spselflag = FALSE; + + pSpellBkCel = LoadFileInMemSig("Data\\SpellBk.CEL",NULL,'CTRL'); + pSBkBtnCel = LoadFileInMemSig("Data\\SpellBkB.CEL",NULL,'CTRL'); + pSBkIconCels = LoadFileInMemSig("Data\\SpellI2.CEL",NULL,'CTRL'); + sbooktab = 0; + sbookflag = FALSE; + if (plr[myplr]._pClass == CLASS_WARRIOR) SpellPages[0][0] = SPL_REPAIR; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) SpellPages[0][0] = SPL_DISARM; + else if (plr[myplr]._pClass == CLASS_SORCEROR) SpellPages[0][0] = SPL_RECHARGE; + else if (plr[myplr]._pClass == CLASS_MONK) SpellPages[0][0] = SPL_SHOWMAGITEMS; + else if (plr[myplr]._pClass == CLASS_BARD) SpellPages[0][0] = SPL_IDENTIFY; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) SpellPages[0][0] = SPL_RAGE; + #endif + + pQLogCel = LoadFileInMemSig("Data\\Quest.CEL",NULL,'CTRL'); + + pGBoxBuff = LoadFileInMemSig("CtrlPan\\Golddrop.cel",NULL,'CTRL'); + // Initialize gold drop variables + dropGoldFlag = FALSE; + dropGoldValue = 0; + initialDropGoldValue = 0; + initialDropGoldIndex = 0; + pentaspin = 1; + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawCtrlPan() { + CopyCtrlPan(0, 16+talkofs, 640, 128, 64, 512); + DrawInfoBox(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawButtons() +{ + for (int i = 0; i < SINGLE_PBTNS; i++) { + if (!panbtn[i]) + CopyCtrlPan(PanBtnPos[i][0], PanBtnPos[i][1]-336, 71, 20, PanBtnPos[i][0] + 64, PanBtnPos[i][1] + 160); + else + DrawCel(PanBtnPos[i][0]+64, PanBtnPos[i][1]+178, pPanelButtons, i+1, 71); + } + + if (numpanbtns == MULTI_PBTNS) { + // Draw talk button + DrawCel(151, 634, pMultiBtns, 1+panbtn[PBTN_TALK], 33); + // Draw Friend or foe button + if (FriendlyMode) { + DrawCel(591, 634, pMultiBtns, 3+panbtn[PBTN_ATTACK], 33); + } else { + DrawCel(591, 634, pMultiBtns, 5+panbtn[PBTN_ATTACK], 33); + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetupSpellSel() +{ + int x,y,i,j; + __int64 mask,spl; + int cx, cy; + + spselflag = TRUE; + x = SPLICONRIGHT; + y = 495; + cx = x - (64 - (SPLICONSIZE >> 1)); + cy = y - (160 + (SPLICONSIZE >> 1)); + if (plr[myplr]._pRSpell != -1) { + for (j = 0; j < 4; j++) { + switch(j) { + case 0: + spl = plr[myplr]._pAblSpells; + break; + case 1: + spl = plr[myplr]._pMemSpells; + break; + case 2: + spl = plr[myplr]._pScrlSpells; + break; + case 3: + spl = plr[myplr]._pISpells; + break; + } + mask = 1; + for (i = 1; i < SPL_LAST; i++) { + if ((spl & mask) != 0) { + if ((i == plr[myplr]._pRSpell) && (j == plr[myplr]._pRSplType)) { + cx = x - (64 - (SPLICONSIZE >> 1)); + cy = y - (160 + (SPLICONSIZE >> 1)); + } + x -= SPLICONSIZE; + if (x == SPLICONLEFT) { + x = SPLICONRIGHT; + y -= SPLICONSIZE; + } + } + mask = mask << 1; + } + if (spl && (x != SPLICONRIGHT)) x -= SPLICONSIZE; + if (x == SPLICONLEFT) { + x = SPLICONRIGHT; + y -= SPLICONSIZE; + } + } + } + SetCursorPos(cx,cy); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckPanelBtns() +{ + for (int i = 0; i < numpanbtns; i++) { + int x2 = PanBtnPos[i][0] + PanBtnPos[i][2]; + int y2 = PanBtnPos[i][1] + PanBtnPos[i][3]; + if ((MouseX >= PanBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[i][1]) && (MouseY <= y2)) { + panbtn[i] = TRUE; + drawbtnflag = TRUE; + panbtndown = TRUE; + } + } + + if (!spselflag) { + if (MouseX >= 565 && MouseX < 621 && MouseY >= 416 && MouseY < 472) { + SetupSpellSel(); + gamemenu_off(); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ActivatePanelBtn(int i) +{ + panbtn[i] = TRUE; + drawbtnflag = TRUE; + panbtndown = TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckDeadButtons() +{ + int x2, y2; + + x2 = PanBtnPos[PBTN_MENU][0] + PanBtnPos[PBTN_MENU][2]; + y2 = PanBtnPos[PBTN_MENU][1] + PanBtnPos[PBTN_MENU][3]; + if ((MouseX >= PanBtnPos[PBTN_MENU][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[PBTN_MENU][1]) && (MouseY <= y2)) + ActivatePanelBtn(PBTN_MENU); + x2 = PanBtnPos[PBTN_TALK][0] + PanBtnPos[PBTN_TALK][2]; + y2 = PanBtnPos[PBTN_TALK][1] + PanBtnPos[PBTN_TALK][3]; + if ((MouseX >= PanBtnPos[PBTN_TALK][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[PBTN_TALK][1]) && (MouseY <= y2)) + ActivatePanelBtn(PBTN_TALK); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DoAutoMap() { + // if we are multiplayer on the town level, DO NOT display + // the error message. Instead, the automap will show the + // game name and password + if (currlevel == 0 && gbMaxPlayers == 1) { + InitDiabloMsg(MSG_AMAPTWN); + return; + } + + // toggle automap + if (!automapflag) StartAutomap(); + else automapflag = FALSE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckPanelInfo() +{ + int i; + int x2, y2; + int pSpell, c, s; + int v; + + panelflag = FALSE; + ClearPanel(); + + for (i = 0; i < numpanbtns; i++) { + x2 = PanBtnPos[i][0] + PanBtnPos[i][2]; + y2 = PanBtnPos[i][1] + PanBtnPos[i][3]; + if ((MouseX >= PanBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[i][1]) && (MouseY <= y2)) { + if (i != PBTN_ATTACK) + strcpy(infostr, PanBtnStr[i]); + else if (FriendlyMode) + strcpy(infostr, "Player friendly"); + else + strcpy(infostr, "Player attack"); + if (PanBtnHotKey[i] != NULL) { + sprintf(tempstr, "Hotkey : %s", PanBtnHotKey[i]); + AddPanelString(tempstr, TEXT_CENTER); + } + infoclr = ICOLOR_WHITE; + panelflag = TRUE; + pinfoflag = TRUE; + } + } + + if (!spselflag) { + if ((MouseX >= 565) && (MouseX < 621) && (MouseY >= 416) && (MouseY < 472)) { + strcpy(infostr, "Select current spell button"); + infoclr = ICOLOR_WHITE; + panelflag = TRUE; + pinfoflag = TRUE; + strcpy(tempstr, "Hotkey : 's'"); + AddPanelString(tempstr, TEXT_CENTER); + pSpell = plr[myplr]._pRSpell; + if (pSpell != -1) { + switch (plr[myplr]._pRSplType) { + case 0: + sprintf(tempstr, "%s Skill", spelldata[pSpell].sSkillText); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 1: + sprintf(tempstr, "%s Spell", spelldata[pSpell].sNameText); + AddPanelString(tempstr, TEXT_CENTER); + v = plr[myplr]._pSplLvl[pSpell]+plr[myplr]._pISplLvlAdd; + if ( v < 0 ) v = 0; + if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); + else sprintf(tempstr, "Spell Level %i", v); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 2: + sprintf(tempstr, "Scroll of %s", spelldata[pSpell].sNameText); + AddPanelString(tempstr, TEXT_CENTER); + c = 0; + for (s = 0; s < plr[myplr]._pNumInv; s++) { + if ((plr[myplr].InvList[s]._itype != -1) && + ((plr[myplr].InvList[s]._iMiscId == IMID_SCROLL) || + (plr[myplr].InvList[s]._iMiscId == IMID_TSCROLL))) { + if (plr[myplr].InvList[s]._iSpell == pSpell) c++; + } + } + for (s = 0; s < MAXSPD; s++) { + if ((plr[myplr].SpdList[s]._itype != -1) && + ((plr[myplr].SpdList[s]._iMiscId == IMID_SCROLL) || + (plr[myplr].SpdList[s]._iMiscId == IMID_TSCROLL))) { + if (plr[myplr].SpdList[s]._iSpell == pSpell) c++; + } + } + if (c == 1) strcpy(tempstr, "1 Scroll"); + else sprintf(tempstr, "%i Scrolls", c); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 3: + sprintf(tempstr, "Staff of %s", spelldata[pSpell].sNameText); + AddPanelString(tempstr, TEXT_CENTER); + if (plr[myplr].Hand1Item._iCharges == 1) strcpy(tempstr, "1 Charge"); + else sprintf(tempstr, "%i Charges", plr[myplr].Hand1Item._iCharges); + AddPanelString(tempstr, TEXT_CENTER); + break; + } + } + } + } + + if ((MouseX > 190) && (MouseX < 437) && (MouseY > 356) && (MouseY < 385)) + cursinvitem = CheckInvHLight(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ReleasePanelBtn() { + BYTE bMenuOff = TRUE; + + drawbtnflag = TRUE; + panbtndown = FALSE; + for (int i = 0; i < NUMPBTNS; i++) { + if (! panbtn[i]) continue; + panbtn[i] = FALSE; + + // was the mouseup in this button? + if (MouseX < PanBtnPos[i][0]) continue; + if (MouseX > PanBtnPos[i][0] + PanBtnPos[i][2]) continue; + if (MouseY < PanBtnPos[i][1]) continue; + if (MouseY > PanBtnPos[i][1] + PanBtnPos[i][3]) continue; + + switch(i) { + case PBTN_CHR : + questlog = FALSE; + chrflag = !chrflag; + break; + case PBTN_QUEST: + chrflag = FALSE; + if (!questlog) StartQuestlog(); + else questlog = FALSE; + break; + case PBTN_AMAP : + DoAutoMap(); + break; + case PBTN_MENU : + qtextflag = FALSE; + gamemenu_toggle(); + bMenuOff = FALSE; + break; + case PBTN_INV : + sbookflag = FALSE; + invflag = !invflag; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + break; + case PBTN_SBOOK : + invflag = FALSE; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + sbookflag = !sbookflag; + break; + case PBTN_TALK: + if (talkflag) TalkEnd(); + else TalkStart(); + break; + case PBTN_ATTACK: + FriendlyMode = !FriendlyMode; + break; + } + } + + if (bMenuOff) gamemenu_off(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void FreeControlPan() +{ + DiabloFreePtr(pBtmBuff); + DiabloFreePtr(pManaBuff); + DiabloFreePtr(pLifeBuff); + DiabloFreePtr(pPanelText); + DiabloFreePtr(pChrPanel); + DiabloFreePtr(pSpellCels); + DiabloFreePtr(pPanelButtons); + DiabloFreePtr(pMultiBtns); + DiabloFreePtr(pTalkBtns); + DiabloFreePtr(pChrButtons); + DiabloFreePtr(pDurIcons); + DiabloFreePtr(pQLogCel); + DiabloFreePtr(pSpellBkCel); + DiabloFreePtr(pSBkBtnCel); + DiabloFreePtr(pSBkIconCels); + DiabloFreePtr(pGBoxBuff); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL InfoFit(const char * p) { + long tw = 0; + while (*p) { + BYTE c = char2print(*p++); + c = fonttrans[c]; + tw += fontkern[c]; + if (tw >= 125) return FALSE; + } + + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void CPrintString(int l,const char * pszStr, int just, int pnl) { + long boffset = fontofs[pnl][l]; + + int w = 0; + if (just == TEXT_CENTER) { + long tw = 0; + const char * pszTemp = pszStr; + while (*pszTemp) { + BYTE c = char2print(*pszTemp++); + c = fonttrans[c]; + tw += fontkern[c] + 2; + } + + if (tw < 288) w = (288 - tw) >> 1; + boffset += w; + } + + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + w += fontkern[c] + 2; + if (c && (w < 288)) DrawPanelFont(boffset, c, infoclr); + boffset += fontkern[c] + 2; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void PrintInfo() { + if (talkflag) return; + + int nOffset1 = 0; + int nOffset2 = 1; + if (infostr[0] != 0) { + CPrintString(0, infostr, TEXT_CENTER, pnumlines); + nOffset1 = 1; + nOffset2 = 0; + } + + for (int i = 0; i < pnumlines; i++) + CPrintString(i+nOffset1, panelstr[i], pstrjust[i], pnumlines-nOffset2); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawInfoBox() +{ + // Erase old box + CopyCtrlPan(177, 62, 288, 60, 241, 558); + + if ((!panelflag) && (!trigflag) && (cursinvitem == -1) && (!spselflag)) { + infostr[0] = 0; + infoclr = ICOLOR_WHITE; + ClearPanel(); + } + + if ((spselflag) || (trigflag)) { + infoclr = ICOLOR_WHITE; + } else { + if (curs >= ICSTART) { + if (plr[myplr].HoldItem._itype == IT_GOLD) { + int nGold = plr[myplr].HoldItem._ivalue; + const char * get_pieces_str(int nGold); + sprintf(infostr,"%i gold %s",nGold,get_pieces_str(nGold)); + } + else if (!plr[myplr].HoldItem._iStatFlag) { + ClearPanel(); + AddPanelString("Requirements not met", TEXT_CENTER); + pinfoflag = TRUE; + } + else { + if (plr[myplr].HoldItem._iIdentified) strcpy(infostr, plr[myplr].HoldItem._iIName); + else strcpy(infostr, plr[myplr].HoldItem._iName); + if (plr[myplr].HoldItem._iMagical == IMAGIC_MAGIC) infoclr = ICOLOR_BLUE; + if (plr[myplr].HoldItem._iMagical == IMAGIC_UNIQUE) infoclr = ICOLOR_GOLD; + } + } else { + // if cursinvitem != -1 then the string will already be in infostr + // if trigflag then the string will already be set as well + if (cursitem != -1) { + // @@@ drb debug +#if 0 + +int GetLDeltaItem(); + + ClearPanel(); + ItemStruct *pi = &item[cursitem]; + strcpy(infostr, pi->_iName); + sprintf(tempstr, "Delta # = %i", GetLDeltaItem()); + AddPanelString(tempstr, TEXT_CENTER); + //sprintf(tempstr, "seed = %i", pi->_iSeed); + //AddPanelString(tempstr, TEXT_CENTER); + // @@@ drb end debug +#else + GetItemStr(cursitem); +#endif + } + if (cursobj != -1) GetObjectStr(cursobj); + if (cursmonst != -1) { + if (leveltype != 0) { + infoclr = ICOLOR_WHITE; + strcpy(infostr, monster[cursmonst].mName); + ClearPanel(); +#if DISABLED_CHEATS + if (1) { + sprintf(tempstr, "HP: %08X/%08X", + monster[cursmonst]._mhitpoints, + monster[cursmonst]._mmaxhp); + AddPanelString(tempstr, TEXT_CENTER); + sprintf(tempstr, "Res: %02X", + monster[cursmonst].mMagicRes); + pinfoflag = TRUE; + } else +#endif + if (monster[cursmonst]._uniqtype != 0) { + infoclr = ICOLOR_GOLD; + void PrintUniqueHistory(); + PrintUniqueHistory(); + } else PrintMonstHistory(monster[cursmonst].MType->mtype); + } else strcpy(infostr, towner[cursmonst]._tName); + } + if (cursplr != -1) { + infoclr = ICOLOR_GOLD; + strcpy(infostr, plr[cursplr]._pName); + ClearPanel(); + sprintf(tempstr, "%s, Level : %i", ClassStrTbl[plr[cursplr]._pClass], plr[cursplr]._pLevel); + AddPanelString(tempstr, TEXT_CENTER); + sprintf(tempstr, "Hit Points %i of %i", (plr[cursplr]._pHitPoints >> HP_SHIFT), (plr[cursplr]._pMaxHP >> HP_SHIFT)); + AddPanelString(tempstr, TEXT_CENTER); + } + } + } + //if ((pinfoflag) && (cursmonst == -1) && (cursinvitem == -1) && (curs < ICSTART)) ClearPanel(); + if ((infostr[0] != 0) || (pnumlines != 0)) PrintInfo(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void PlrStringXY(int x1, int y, int x2,const char * pszStr,char col) { + long boffset = nBuffWTbl[y + 160] + x1 + 64; + int aw = x2 - x1 + 1; + int w = 0; + + // calculate string width + int tw = 0; + const char * pszTemp = pszStr; + while (*pszTemp) { + BYTE c = char2print(*pszTemp++); + c = fonttrans[c]; + tw += fontkern[c] + 1; + } + + if (tw < aw) w = (aw - tw) >> 1; + boffset += w; + + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + w += fontkern[c] + 1; + if (c && w < aw) DrawPanelFont(boffset, c, col); + boffset += fontkern[c] + 1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PrintStringXY(int x, int y,const char * pszStr, char col) { + long boffset = nBuffWTbl[y + 160] + x + 64; + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + if (c) DrawPanelFont(boffset, c, col); + boffset += fontkern[c] + 1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void PlrStringXY2(int x1, int y, int x2,const char * pszStr,char col,int a) { + long boffset = nBuffWTbl[y + 160] + x1 + 64; + int aw = x2 - x1 + 1; + int w = 0; + + // calculate string width + int tw = 0; + const char * pszTemp = pszStr; + while (*pszTemp) { + BYTE c = char2print(*pszTemp++); + c = fonttrans[c]; + tw += fontkern[c] + a; + } + + if (tw < aw) w = (aw - tw) >> 1; + boffset += w; + + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + w += fontkern[c] + a; + if (c && w < aw) DrawPanelFont(boffset, c, col); + boffset += fontkern[c] + a; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawChr() +{ + char c; + char chrstr[64]; + int pc; + long mind, maxd; + int hper, ac; + + DrawCel(64, 511, pChrPanel, 1, 320); + + PlrStringXY(20, 32, 151, plr[myplr]._pName, ICOLOR_WHITE); + + PlrStringXY(168, 32, 299, ClassStrTbl[plr[myplr]._pClass], ICOLOR_WHITE); + + #if 0 + if (plr[myplr]._pClass == CLASS_WARRIOR) PlrStringXY(168, 32, 299, "Warrior", ICOLOR_WHITE); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlrStringXY(168, 32, 299, "Rogue", ICOLOR_WHITE); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlrStringXY(168, 32, 299, "Sorceror", ICOLOR_WHITE); + else if (plr[myplr]._pClass == CLASS_MONK) PlrStringXY(168, 32, 299, "Monk", ICOLOR_WHITE); + else if (plr[myplr]._pClass == CLASS_BARD) PlrStringXY(168, 32, 299, "Bard", ICOLOR_WHITE); + else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlrStringXY(168, 32, 299, "Barbarian", ICOLOR_WHITE); + #endif + #endif + + sprintf(chrstr, "%i", plr[myplr]._pLevel); + PlrStringXY(66, 69, 109, chrstr, ICOLOR_WHITE); + + sprintf(chrstr, "%li", plr[myplr]._pExperience); + PlrStringXY(216, 69, 300, chrstr, ICOLOR_WHITE); + + if (plr[myplr]._pLevel == 50) { + strcpy(chrstr, "None"); + c = ICOLOR_GOLD; + } else { + sprintf(chrstr, "%li", plr[myplr]._pNextExper); + c = ICOLOR_WHITE; + } + PlrStringXY(216, 97, 300, chrstr, c); + + sprintf(chrstr, "%i", plr[myplr]._pGold); + PlrStringXY(216, 146, 300, chrstr, ICOLOR_WHITE); + + c = ICOLOR_WHITE; + if (plr[myplr]._pIBonusAC > 0) c = ICOLOR_BLUE; + if (plr[myplr]._pIBonusAC < 0) c = ICOLOR_RED; + // rjs ac = (byte)plr[myplr]._pArmorClass+plr[myplr]._pIAC+plr[myplr]._pIBonusAC; + ac = plr[myplr]._pIAC+plr[myplr]._pIBonusAC; + ac += (plr[myplr]._pDexterity / 5); + sprintf(chrstr, "%i", ac); + PlrStringXY(258, 183, 301, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pIBonusToHit > 0) c = ICOLOR_BLUE; + if (plr[myplr]._pIBonusToHit < 0) c = ICOLOR_RED; + hper = BASE_TO_HIT + (plr[myplr]._pDexterity >> 1) + plr[myplr]._pIBonusToHit; + sprintf(chrstr, "%i%%", hper); + PlrStringXY(258, 211, 301, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pIBonusDam > 0) c = ICOLOR_BLUE; + if (plr[myplr]._pIBonusDam < 0) c = ICOLOR_RED; + mind = plr[myplr]._pIMinDam; + mind += (mind * plr[myplr]._pIBonusDam) / 100; + mind += plr[myplr]._pIBonusDamMod; + if (plr[myplr].Hand1Item._itype == IT_BOW) { + if (plr[myplr]._pClass == CLASS_ROGUE) mind += plr[myplr]._pDamageMod; + else mind += (plr[myplr]._pDamageMod >> 1); + } else mind += plr[myplr]._pDamageMod; + maxd = plr[myplr]._pIMaxDam; + maxd += (maxd * plr[myplr]._pIBonusDam) / 100; + maxd += plr[myplr]._pIBonusDamMod; + if (plr[myplr].Hand1Item._itype == IT_BOW) { + if (plr[myplr]._pClass == CLASS_ROGUE) maxd += plr[myplr]._pDamageMod; + else maxd += (plr[myplr]._pDamageMod >> 1); + } else maxd += plr[myplr]._pDamageMod; + sprintf(chrstr, "%i-%i", mind, maxd); + if ((mind >= 100) || (maxd >= 100)) + PlrStringXY2(254, 239, 305, chrstr, c, -1); + else + PlrStringXY2(258, 239, 301, chrstr, c, 0); + + // Magic Resist + if (plr[myplr]._pMagResist == 0) c = ICOLOR_WHITE; + else c = ICOLOR_BLUE; + if (plr[myplr]._pMagResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pMagResist); + else { + c = ICOLOR_GOLD; + sprintf(chrstr, "MAX"); + } + PlrStringXY(257, 276, 300, chrstr, c); + + // Fire Resist + if (plr[myplr]._pFireResist == 0) c = ICOLOR_WHITE; + else c = ICOLOR_BLUE; + if (plr[myplr]._pFireResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pFireResist); + else { + c = ICOLOR_GOLD; + sprintf(chrstr, "MAX"); + } + PlrStringXY(257, 304, 300, chrstr, c); + + // Lightning Resist + if (plr[myplr]._pLghtResist == 0) c = ICOLOR_WHITE; + else c = ICOLOR_BLUE; + if (plr[myplr]._pLghtResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pLghtResist); + else { + c = ICOLOR_GOLD; + sprintf(chrstr, "MAX"); + } + PlrStringXY(257, 332, 300, chrstr, c); + + c = ICOLOR_WHITE; + sprintf(chrstr, "%i", plr[myplr]._pBaseStr); + if (MaxStats[plr[myplr]._pClass][0] == plr[myplr]._pBaseStr) c = ICOLOR_GOLD; + PlrStringXY( 95, 155, 126, chrstr, c); + + c = ICOLOR_WHITE; + sprintf(chrstr, "%i", plr[myplr]._pBaseMag); + if (MaxStats[plr[myplr]._pClass][1] == plr[myplr]._pBaseMag) c = ICOLOR_GOLD; + PlrStringXY( 95, 183, 126, chrstr, c); + + c = ICOLOR_WHITE; + sprintf(chrstr, "%i", plr[myplr]._pBaseDex); + if (MaxStats[plr[myplr]._pClass][2] == plr[myplr]._pBaseDex) c = ICOLOR_GOLD; + PlrStringXY( 95, 211, 126, chrstr, c); + + c = ICOLOR_WHITE; + sprintf(chrstr, "%i", plr[myplr]._pBaseVit); + if (MaxStats[plr[myplr]._pClass][3] == plr[myplr]._pBaseVit) c = ICOLOR_GOLD; + PlrStringXY( 95, 239, 126, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pStrength > plr[myplr]._pBaseStr) c = ICOLOR_BLUE; + if (plr[myplr]._pStrength < plr[myplr]._pBaseStr) c = ICOLOR_RED; + sprintf(chrstr, "%i", plr[myplr]._pStrength); + PlrStringXY(143, 155, 173, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pMagic > plr[myplr]._pBaseMag) c = ICOLOR_BLUE; + if (plr[myplr]._pMagic < plr[myplr]._pBaseMag) c = ICOLOR_RED; + sprintf(chrstr, "%i", plr[myplr]._pMagic); + PlrStringXY(143, 183, 173, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pDexterity > plr[myplr]._pBaseDex) c = ICOLOR_BLUE; + if (plr[myplr]._pDexterity < plr[myplr]._pBaseDex) c = ICOLOR_RED; + sprintf(chrstr, "%i", plr[myplr]._pDexterity); + PlrStringXY(143, 211, 173, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pVitality > plr[myplr]._pBaseVit) c = ICOLOR_BLUE; + if (plr[myplr]._pVitality < plr[myplr]._pBaseVit) c = ICOLOR_RED; + sprintf(chrstr, "%i", plr[myplr]._pVitality); + PlrStringXY(143, 239, 173, chrstr, c); + + // drb.patch1.start.2/05/97 + if (plr[myplr]._pStatPts > 0) { + int CalcStatDiff(int); + if (CalcStatDiff(myplr) < plr[myplr]._pStatPts) plr[myplr]._pStatPts = CalcStatDiff(myplr); + } + // drb.patch1.end.2/05/97 + // Points to distibute + if (plr[myplr]._pStatPts > 0) { + sprintf(chrstr, "%i", plr[myplr]._pStatPts); + PlrStringXY(95, 266, 126, chrstr, ICOLOR_RED);// check x y + pc = plr[myplr]._pClass; + if (plr[myplr]._pBaseStr < MaxStats[pc][0]) DrawCel(201, 319, pChrButtons, 2+chrbtn[0], 41); + if (plr[myplr]._pBaseMag < MaxStats[pc][1]) DrawCel(201, 347, pChrButtons, 4+chrbtn[1], 41); + if (plr[myplr]._pBaseDex < MaxStats[pc][2]) DrawCel(201, 376, pChrButtons, 6+chrbtn[2], 41); + if (plr[myplr]._pBaseVit < MaxStats[pc][3]) DrawCel(201, 404, pChrButtons, 8+chrbtn[3], 41); + } + + if (plr[myplr]._pMaxHP > plr[myplr]._pMaxHPBase) c = ICOLOR_BLUE; + else c = ICOLOR_WHITE; + sprintf(chrstr, "%i", (plr[myplr]._pMaxHP >> HP_SHIFT)); + PlrStringXY( 95, 304, 126, chrstr, c); + if (plr[myplr]._pHitPoints != plr[myplr]._pMaxHP) c = ICOLOR_RED; + sprintf(chrstr, "%i", (plr[myplr]._pHitPoints >> HP_SHIFT)); + PlrStringXY(143, 304, 174, chrstr, c); + + if (plr[myplr]._pMaxMana > plr[myplr]._pMaxManaBase) c = ICOLOR_BLUE; + else c = ICOLOR_WHITE; + sprintf(chrstr, "%i", (plr[myplr]._pMaxMana >> MANA_SHIFT)); + PlrStringXY( 95, 332, 126, chrstr, c); + if (plr[myplr]._pMana != plr[myplr]._pMaxMana) c = ICOLOR_RED; + sprintf(chrstr, "%i", (plr[myplr]._pMana >> MANA_SHIFT)); + PlrStringXY(143, 332, 174, chrstr, c); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void CheckLvlBtn() { + if (lvlbtndown) return; + if ((MouseX >= 40) && (MouseX <= 81) && (MouseY >= 313) && (MouseY <= 335)) + lvlbtndown = TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ReleaseLvlBtn() { + if ((MouseX >= 40) && (MouseX <= 81) && (MouseY >= 313) && (MouseY <= 335)) + chrflag = TRUE; + lvlbtndown = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawLevelUpIcon() { + int c; + + if (stextflag != STORE_NONE) return; + if (lvlbtndown) c = 3; + else c = 2; + PlrStringXY(0, 303, 120, "Level Up", ICOLOR_WHITE); + DrawCel(104, 495, pChrButtons, c, 41); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void CheckChrBtns() { + if (chrbtndown) return; + if (! plr[myplr]._pStatPts) return; + + int pc = plr[myplr]._pClass; + for (int i = 0; i < NUMCBTNS; i++) { + switch(i) { + case 0: + if (plr[myplr]._pBaseStr >= MaxStats[pc][i]) + continue; + break; + + case 1: + if (plr[myplr]._pBaseMag >= MaxStats[pc][i]) + continue; + break; + + case 2: + if (plr[myplr]._pBaseDex >= MaxStats[pc][i]) + continue; + break; + + case 3: + if (plr[myplr]._pBaseVit >= MaxStats[pc][i]) + continue; + break; + + default: + continue; + } + + int x2 = ChrBtnPos[i][0] + ChrBtnPos[i][2]; + int y2 = ChrBtnPos[i][1] + ChrBtnPos[i][3]; + if ((MouseX >= ChrBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= ChrBtnPos[i][1]) && (MouseY <= y2)) { + chrbtn[i] = TRUE; + chrbtndown = TRUE; + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ReleaseChrBtn() { + chrbtndown = FALSE; + for (int i = 0; i < NUMCBTNS; i++) { + if (! chrbtn[i]) continue; + chrbtn[i] = FALSE; + + // was mouseup inside button? + if (MouseX < ChrBtnPos[i][0]) continue; + if (MouseX > ChrBtnPos[i][0] + ChrBtnPos[i][2]) continue; + if (MouseY < ChrBtnPos[i][1]) continue; + if (MouseY > ChrBtnPos[i][1] + ChrBtnPos[i][3]) continue; + + switch(i) { + case CBTN_STR : + NetSendCmdParam1(TRUE,CMD_ADDSTR,1); + plr[myplr]._pStatPts--; + break; + case CBTN_MAG : + NetSendCmdParam1(TRUE,CMD_ADDMAG,1); + plr[myplr]._pStatPts--; + break; + case CBTN_DEX : + NetSendCmdParam1(TRUE,CMD_ADDDEX,1); + plr[myplr]._pStatPts--; + break; + case CBTN_VIT : + NetSendCmdParam1(TRUE,CMD_ADDVIT,1); + plr[myplr]._pStatPts--; + break; + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int DrawDurIcon4Item(const ItemStruct * pItem, int x, int c) { + + // don't need to draw icon if there is no item + if (pItem->_itype == -1) return x; + + // don't need to draw icon if durability is high + if (pItem->_iDurability > 5) return x; + + if (c == 0) { + if (pItem->_iClass == IC_WEAP) switch(pItem->_itype) { + case IT_SWORD: + c = 2; + break; + case IT_AXE: + c = 6; + break; + case IT_BOW: + c = 7; + break; + case IT_MACE: + c = 5; + break; + case IT_STAFF: + c = 8; + break; + } + else { + c = 1; + } + } + + // choose cel to draw based on durability + if (pItem->_iDurability > 2) c += 8; + + // draw it + DrawCel(x, 495, pDurIcons, c, 32); + + // adjust position for next durability icon + return x - 40; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawDurIcon() { + if ((chrflag || questlog) && (invflag || sbookflag)) return; + + int x = 656; + if (invflag || sbookflag) x -= 320; + const PlayerStruct * p = &plr[myplr]; + x = DrawDurIcon4Item(&p->InvBody[INVLOC_HEAD],x,4); + x = DrawDurIcon4Item(&p->InvBody[INVLOC_BODY],x,3); + x = DrawDurIcon4Item(&p->InvBody[INVLOC_HAND1],x,0); + x = DrawDurIcon4Item(&p->InvBody[INVLOC_HAND2],x,0); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void RedBack() { + long ltaboff; + + if (light4flag) ltaboff = 1536; + else ltaboff = 4608; + + app_assert(gpBuffer); + if (leveltype != 4) { + __asm { + mov edi,dword ptr [gpBuffer] + add edi,122944 + + mov ebx,dword ptr [pLightTbl] + add ebx,dword ptr [ltaboff] + + mov edx,352 +_YLp: mov ecx,640 +_XLp: mov al,byte ptr [edi] + xlatb + stosb + loop _XLp + add edi,128 + dec edx + jnz _YLp + } + } else { + __asm { + mov edi,dword ptr [gpBuffer] + add edi,122944 + + mov ebx,dword ptr [pLightTbl] + add ebx,dword ptr [ltaboff] + + mov edx,352 +_YLp2: mov ecx,640 +_XLp2: mov al,byte ptr [edi] + cmp al,32 + jb _Skip + xlatb +_Skip: stosb + loop _XLp2 + add edi,128 + dec edx + jnz _YLp2 + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void PrintSBookStr(int x, int y, BOOL cjustflag,const char * pszStr, char col) { + long boffset = nBuffWTbl[y] + x + 440; + int w = 0; + + if (cjustflag) { + int tw = 0; + const char * pszTemp = pszStr; + while (*pszTemp) { + BYTE c = char2print(*pszTemp++); + c = fonttrans[c]; + tw += fontkern[c] + 1; + } + + if (tw < 222) w = (222 - tw) >> 1; + boffset += w; + } + + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + w += fontkern[c] + 1; + if (c && w <= 222) DrawPanelFont(boffset, c, col); + boffset += fontkern[c] + 1; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +char GetSBookTrans(int ii, BOOL townok) { + char st, sl; + + // hack hack hack + if (plr[myplr]._pClass == CLASS_MONK && ii == SPL_SHOWMAGITEMS) + return STRN_GOLD; + + st = STRN_BLUE; + if (plr[myplr]._pISpells & (((__int64)1) << (ii-1))) st = STRN_ORANGE; + if (plr[myplr]._pAblSpells & (((__int64)1) << (ii-1))) st = STRN_GOLD; + if (st == STRN_BLUE) { + if (!CheckSpell(myplr, ii, SPT_MEMORIZED, TRUE)) st = STRN_GREY; + sl = plr[myplr]._pSplLvl[ii] + plr[myplr]._pISplLvlAdd; + if (sl <= 0 ) st = STRN_GREY; + } + if ((townok) && (currlevel == 0) && (st != STRN_GREY) && (spelldata[ii].sTownSpell == FALSE)) st = STRN_GREY; + return(st); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawSpellBook() +{ + int i, ii, y, mind, maxd; + __int64 tspls; + char st; + int v; + + // Drawbackground + DrawCel(384, 511, pSpellBkCel, 1, 320); + + // Draw tab + //x = (sbooktab * 51) + 391; + //DrawCel(x, 508, pSBkBtnCel, 1 + sbooktab, 51); +// x = (sbooktab * 76) + 391; +// DrawCel(x, 508, pSBkBtnCel, 1 + sbooktab, 76); + + if (sbooktab < NUMSPBKBTNS) + { + long x = (sbooktab * SPBKBTNWDTH) + 391; + DrawCel(x, 508, pSBkBtnCel, sbooktab + 1, SPBKBTNWDTH); + } + + // Draw Spell Icons + y = 215; + tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; + for (i = 1; i < 8; i++) { + ii = SpellPages[sbooktab][i-1]; + if (ii != -1) { + if (tspls & (((__int64) 1) << (ii-1))) { + st = GetSBookTrans(ii, TRUE); + SetSpellTrans(st); + DrawSpellCel(395, y, pSBkIconCels, SpellITbl[ii], 37); + if ((ii == plr[myplr]._pRSpell) && (st == plr[myplr]._pRSplType)) { + SetSpellTrans(STRN_GOLD); + DrawSpellCel(395, y, pSBkIconCels, SI_LAST, 37); + } + PrintSBookStr(10, y-23, FALSE, spelldata[ii].sNameText, ICOLOR_WHITE); + st = GetSBookTrans(ii, FALSE); + switch (st) { + case STRN_GOLD: + strcpy(tempstr, "Skill"); + break; + case STRN_ORANGE: + sprintf(tempstr, "Staff (%i charges)", plr[myplr].Hand1Item._iCharges); + break; + default: + v = GetManaAmount(myplr, ii) >> MANA_SHIFT; + GetDamageAmt(ii, &mind, &maxd); + if (mind != -1) sprintf(tempstr, "Mana: %i Dam: %i - %i", v, mind, maxd); + else sprintf(tempstr, "Mana: %i Dam: n/a", v); + if (ii == SPL_BONESPIRIT) sprintf(tempstr, "Mana: %i Dam: 1/3 tgt hp", v); + PrintSBookStr(10, y-1, FALSE, tempstr, ICOLOR_WHITE); + + v = plr[myplr]._pSplLvl[ii]+plr[myplr]._pISplLvlAdd; + if ( v < 0 ) v = 0; + if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); + else sprintf(tempstr, "Spell Level %i", v); + break; + } + PrintSBookStr(10, y-12, FALSE, tempstr, ICOLOR_WHITE); + } + } + y += 43; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckSBook() +{ + int spl; + __int64 tspls; + char st; + + // Check spell icon + if ((MouseX >= 331) && (MouseX < 368) && (MouseY >= 18) && (MouseY < 314)) { + spl = (MouseY - 18) / 43; + spl = SpellPages[sbooktab][spl]; + tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; + if (spl != -1) { + if (tspls & (((__int64)1) << (spl-1))) { + st = SPT_MEMORIZED; + if (plr[myplr]._pISpells & (((__int64)1) << (spl-1))) st = SPT_ITEM; + if (plr[myplr]._pAblSpells & (((__int64)1) << (spl-1))) st = SPT_ABILITY; + + plr[myplr]._pRSpell = spl; + plr[myplr]._pRSplType = st; + force_redraw = FULLDRAW; + } + } + } + // Check spell tabs + if ((MouseX >= 327) && (MouseX < 327 + SPBKBTNWDTH * NUMSPBKBTNS) && + (MouseY >= 320) && (MouseY < 349)) + { + sbooktab = (MouseX - 327) / SPBKBTNWDTH; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* + +BOOL CheckSBookCast() +{ + int spl; + __int64 tspls; + char st; + BOOL okflag; + + if (currlevel == 0) return(FALSE); + // Check spell icon + if ((MouseX >= 327) && (MouseX < 368) && (MouseY >= 29) && (MouseY < 346)) { + spl = (MouseY - 29) / 46; + spl = SpellPages[sbooktab][spl]; + tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; + if (spl != -1) { + if (tspls & (1 << (spl-1))) { + st = SPT_MEMORIZED; + if (plr[myplr]._pISpells & (((__int64)1) << (spl-1))) st = SPT_ITEM; + if (plr[myplr]._pAblSpells & (1 << (spl-1))) st = SPT_ABILITY; + okflag = FALSE; + switch (st) { + case SPT_ABILITY : + case SPT_MEMORIZED : + okflag = CheckSpell(myplr, spl, st, FALSE); + break; + case SPT_ITEM: + okflag = UseStaffSBook(spl); + break; + } + if (okflag) { + if (spelldata[spl].sTargeted) { + plr[myplr]._pTSpell = spl; + plr[myplr]._pTSplType = st; + NewCursor(TARGET_CURS); + } + else { + plr[myplr]._pSBkSpell = spl; + plr[myplr]._pSBkSplType = st; + NetSendCmdParam1(TRUE,CMD_SBSPELL,plr[myplr]._pSBkSpell); + } + return(TRUE); + } + } + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +const char * get_pieces_str(int nGold) { + if (nGold == 1) return "piece"; + return "pieces"; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawGoldBox(int gold) +{ + int i; + long xOffset; + + // Initialize + xOffset = 0; + + // Draw the box + DrawCel(415, 338, pGBoxBuff, 1, 261); + // Output the strings + sprintf(tempstr, "You have %u gold",initialDropGoldValue); + PlrStringXY(366, 87, 600, tempstr, ICOLOR_GOLD); + sprintf(tempstr, "%s. How many do", get_pieces_str(initialDropGoldValue)); + PlrStringXY(366, 103, 600, tempstr, ICOLOR_GOLD); + PlrStringXY(366, 121, 600, "you want to remove?", ICOLOR_GOLD); + + if (gold > 0) { + sprintf(tempstr, "%u", gold); + PrintStringXY(388, 140, tempstr, ICOLOR_WHITE); + } + + // Get x offset for pentagram + if (gold > 0) { + for (i = 0; i < tempstr[i] != 0; i++) { + BYTE c = char2print(tempstr[i]); + c = fonttrans[c]; + xOffset += fontkern[c]+1; + } + xOffset += 452; + } else xOffset = 450; + + // Draw the pentagram + DrawCel(xOffset, 300, pSTextSpinCels, pentaspin, 12); + // Increment the pentagram spinner + pentaspin = (pentaspin & 0x7) + 1; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +// macro to convert char to int +#define ATON(c) (c - 0x30) +// keyboard constants +#define DG_CR 0x0d +#define DG_ESC 0x1b +#define DG_BACK 0x08 + +void DropGoldType(char c) //, int ivalue) +{ + char dGoldStr[6]; + + // Check if player is dead. This should prevent the multi player death frame + // gold cheat. + if ((plr[myplr]._pHitPoints >> HP_SHIFT) <= 0) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + return; + } + + // Clear the string + memset(dGoldStr, 0x00, sizeof(dGoldStr)); + // Convert number to string + _itoa(dropGoldValue, dGoldStr, 10); + + // Carriage Return was pressed so the player wants to drop some gold + if (c == DG_CR) { + if (dropGoldValue > 0) DropGold(myplr, initialDropGoldIndex); + dropGoldFlag = FALSE; + return; + } + // Escape was pressed so the player wants to quit w/out dropping gold + if (c == DG_ESC) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + return; + } + // Backspace was pressed so clear the last char in the string + if (c == DG_BACK) { + dGoldStr[strlen(dGoldStr)-1] = NULL; + dropGoldValue = atoi(dGoldStr); + return; + } + // Check to see if the player typed a number and if so update the string + if ((ATON(c) >= 0) && (ATON(c) <= 9)) { + if ((dropGoldValue == 0) && (atoi(dGoldStr) > initialDropGoldValue)) + dGoldStr[0] = c; + else { + dGoldStr[strlen(dGoldStr)] = c; + if ((atoi(dGoldStr) > initialDropGoldValue) || (strlen(dGoldStr) > strlen(dGoldStr))) + return; + } + dropGoldValue = atoi(dGoldStr); + return; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DropGold(int pnum, int cii) +{ + int c; + + if (cii <= 46) { + // Item is in the InvList + c = cii - 7; + plr[pnum].InvList[c]._ivalue -= dropGoldValue; + // Modify item cursor in the InvList + if (plr[pnum].InvList[c]._ivalue > 0) SetGoldCurs(pnum, c); + else RemoveInvItem(pnum, c); + } else { + // Item is in the SpdList + c = cii - 47; + plr[pnum].SpdList[c]._ivalue -= dropGoldValue; + // Modify item cursor in the SpdList + if (plr[pnum].SpdList[c]._ivalue > 0) SetSpdbarGoldCurs(pnum, c); + else RemoveSpdBarItem(pnum, c); + } + + // Initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + // Set hold item values + plr[pnum].HoldItem._ivalue = dropGoldValue; + plr[pnum].HoldItem._iStatFlag = TRUE; + // Set cursor arrow to gold + SetDropGoldCursor(pnum); + + // Recalculate players gold + plr[pnum]._pGold = CalculateGold(pnum); + + dropGoldValue = 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetDropGoldCursor(int pnum) +{ + if (plr[pnum].HoldItem._ivalue >= GOLD_VT2) + plr[pnum].HoldItem._iCurs = ITEM_5GOLD; + else { + if (plr[pnum].HoldItem._ivalue <= GOLD_VT1) + plr[pnum].HoldItem._iCurs = ITEM_1GOLD; + else + plr[pnum].HoldItem._iCurs = ITEM_3GOLD; + } + + NewCursor(plr[pnum].HoldItem._iCurs + ICSTART); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +/* +void WhiteCtrlPan(int sx, int sy, int deltax, int deltay, int dx, int dy) +{ + long dest; + + dest = (dy * 768) + dx; + __asm { + mov edi,dword ptr [pBuffer] + add edi,dword ptr [dest] + + xor ebx,ebx + mov bx,word ptr [deltax] + xor edx,edx + mov dx,word ptr [deltay] + mov eax, 0ffffffffh +_CLp: mov ecx,ebx + shr ecx,1 + jnc _Tw + stosb + jecxz _Tx +_Tw: shr ecx,1 + jnc _TLp + stosw + jecxz _Tx +_TLp: rep stosd +_Tx: add edi,768 + sub edi,ebx + dec edx + jnz _CLp + } +} +*/ + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static char * print_talk_string( + char * pszStr, + int x, + int y, + long * plOffset, + int color +) { + // move to top left of talk box + x += 264; + //y += 546; + y += 534; + + int w = x; + *plOffset = nBuffWTbl[y] + x; + while (*pszStr) { + // can we fit the next character on this row? + BYTE c = char2print(*pszStr); + c = fonttrans[c]; + w += fontkern[c] + 1; + if (w > 250+264) return pszStr; + pszStr++; + + // draw char + if (c != 0) DrawPanelFont(*plOffset, c, color); + *plOffset += fontkern[c] + 1; + } + + return NULL; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define TALK_ROW_HGT 13 +void DrawTalkBox() { + + if (!talkflag) return; + app_assert(gpBuffer); + + // erase old box + CopyCtrlPan(175, 20+talkofs, 294, 5, 239, 516); + for (int i = 0; i < 10; i++) + CopyCtrlPan(175+(i>>1), 25+i+talkofs, 293-i, 1, 239+(i>>1), 521+i); + CopyCtrlPan(185, 35+talkofs, 274, 30, 249, 531); + CopyCtrlPan(180, 65+talkofs, 284, 5, 244, 561); + for (i = 0; i < 10; i++) + CopyCtrlPan(180, 70+i+talkofs, 284+i, 1, 244, 566+i); + CopyCtrlPan(170, 80+talkofs, 310, 55, 234, 576); + + // 200,373-450,456 (screen coords) + long lOffset; + char * pszStr = sgszTalkMsg; + for (int row = 0; row < 3; row++) { + pszStr = print_talk_string(pszStr,0,row * TALK_ROW_HGT,&lOffset,ICOLOR_WHITE); + if (! pszStr) break; + } + + // don't allow string to be too long + if (pszStr) *pszStr = 0; + + // draw spinnies on last row + DrawCelP(gpBuffer + lOffset, pSTextSpinCels, tspin, 12); + tspin = (tspin & 0x7) + 1; + + // draw player names + row = 0; + for (i = 0; i < MAX_PLRS; i++) { + if (i == myplr) continue; + + // are we "talking" to this player + int nColor, nCel; + if (sgbPlrTalkTbl[i]) { + nColor = ICOLOR_GOLD; + if (talkbtndown[row]) { + if (row == 0) nCel = 3; + else nCel = 4; + DrawCel(236, 596 + (row * 18), pTalkBtns, nCel, 61); + } + } else { + nColor = ICOLOR_RED; + if (row == 0) nCel = 1; + else nCel = 2; + if (talkbtndown[row]) nCel += 4; + DrawCel(236, 596 + (row * 18), pTalkBtns, nCel, 61); + } + + if (plr[i].plractive) + print_talk_string(plr[i]._pName,46,60 + (row * 18),&lOffset,nColor); + row++; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define TALK_NAME_TOP 421 +#define TALK_NAME_LEFT 172 +#define TALK_NAME_WDT 61 +#define TALK_NAME_HGT (18*(MAX_PLRS-1)) + +BOOL talk_click() { + if (! talkflag) return FALSE; + + if (MouseX < TALK_NAME_LEFT) return FALSE; + if (MouseY < TALK_NAME_TOP) return FALSE; + if (MouseX > TALK_NAME_LEFT + TALK_NAME_WDT) return FALSE; + if (MouseY > TALK_NAME_TOP + TALK_NAME_HGT) return FALSE; + + for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; + talkbtndown[(MouseY - TALK_NAME_TOP) / 18] = TRUE; + + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void talk_release() { + if (! talkflag) return; + + for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; + + if (MouseX < TALK_NAME_LEFT) return; + if (MouseY < TALK_NAME_TOP) return; + if (MouseX > TALK_NAME_LEFT + TALK_NAME_WDT) return; + if (MouseY > TALK_NAME_TOP + TALK_NAME_HGT) return; + + int pnum = (MouseY - TALK_NAME_TOP) / 18; + for (i = 0; (i < MAX_PLRS) && (pnum != -1); i++) + //if ((i != myplr) && plr[i].plractive) pnum--; + if (i != myplr) pnum--; + if (i <= MAX_PLRS) sgbPlrTalkTbl[i - 1] = !sgbPlrTalkTbl[i - 1]; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void TalkStart() { + if (gbMaxPlayers == 1) return; + talkflag = TRUE; + talkofs = 144; + sgszTalkMsg[0] = 0; + tspin = 1; + for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; + force_redraw = FULLDRAW; + + // reset history position + sgbTalkSavePos = sgbNextTalkSave; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void TalkEnd() { + talkflag = FALSE; + talkofs = 0; + force_redraw = FULLDRAW; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void TalkSendMsg() { + + if (sgszTalkMsg[0] != 0) { + // send message to all players who have flag set + DWORD sendmask = 0; + for (int i = 0; i < MAX_PLRS; i++) + if (sgbPlrTalkTbl[i]) sendmask |= 1 << i; + NetSendString(sendmask,sgszTalkMsg); + + // save msg in history buffer if it is unique + for (i = 0; i < MAX_TALK_SAVES; i++) { + if (! strcmp(sgszTalkSaveMsg[i],sgszTalkMsg)) + break; + } + if (i >= MAX_TALK_SAVES) { + // string is unique -- save in history buffer + strcpy(sgszTalkSaveMsg[sgbNextTalkSave],sgszTalkMsg); + sgbNextTalkSave++; + sgbNextTalkSave &= MAX_TALK_SAVES - 1; + } + else { + // string is not unique -- swap curr string with non-unique + BYTE bTemp = sgbNextTalkSave - 1; + bTemp &= MAX_TALK_SAVES - 1; + if (i != bTemp) { + strcpy(sgszTalkSaveMsg[i],sgszTalkSaveMsg[bTemp]); + strcpy(sgszTalkSaveMsg[bTemp],sgszTalkMsg); + } + } + + // reset history position + sgbTalkSavePos = sgbNextTalkSave; + + // reset talk string + sgszTalkMsg[0] = 0; + } + + TalkEnd(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL Talk_wm_char(WPARAM wKey) { + if (gbMaxPlayers == 1) return FALSE; + if (! talkflag) return FALSE; + if (wKey < 32) return FALSE; + + int i = strlen(sgszTalkMsg); + if (i < (MAX_SEND_STR_LEN-2)) { + sgszTalkMsg[i] = (char) wKey; + sgszTalkMsg[i+1] = 0; + } + + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void talk_history(int nDelta) { + for (int i = 0; i < MAX_TALK_SAVES; i++) { + sgbTalkSavePos += nDelta; + sgbTalkSavePos &= MAX_TALK_SAVES - 1; + if (! sgszTalkSaveMsg[sgbTalkSavePos][0]) continue; + + // we found a string in the history + strcpy(sgszTalkMsg,sgszTalkSaveMsg[sgbTalkSavePos]); + break; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL Talk_wm_keydown(WPARAM wKey) { + // only in multiplayer + if (gbMaxPlayers == 1) return FALSE; + if (! talkflag) return FALSE; + + if (wKey == VK_SPACE) { + // grab keystroke so + // program doesn't get it + } + else if (wKey == VK_ESCAPE) { + TalkEnd(); + } + else if (wKey == VK_RETURN) { + TalkSendMsg(); + } + else if (wKey == VK_BACK) { + int i = strlen(sgszTalkMsg); + if (i > 0) sgszTalkMsg[i-1] = 0; + } + else if (wKey == VK_DOWN) { + talk_history(+1); + } + else if (wKey == VK_UP) { + talk_history(-1); + } + else { + return FALSE; + } + + return TRUE; +} + + +//****************************************************************** +// conversion table -- converts funky ANSI/OEM chars to ASCII +// NOTE: only '\0' is allowed to translate to zero +// map all other characters into range 32..127 +//****************************************************************** +const BYTE gbFontTransTbl[256] = { + // control characters + 0, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 0x07 + 1, 1, 1, 1, 1, 1, 1, 1, // 0x08 - 0x0f + 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 0x17 + 1, 1, 1, 1, 1, 1, 1, 1, // 0x18 - 0x1f + + // punctuation/digits + ' ', '!', '"', '#', '$', '%', '&', '\'',// 0x20 - 0x27 + '(', ')', '*', '+', ',', '-', '.', '/', // 0x28 - 0x2f + '0', '1', '2', '3', '4', '5', '6', '7', // 0x30 - 0x37 + '8', '9', ':', ';', '<', '=', '>', '?', // 0x38 - 0x3f + + // uppercase + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', // 0x40 - 0x47 + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', // 0x48 - 0x4f + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', // 0x50 - 0x57 + 'X', 'Y', 'Z', '[', '\\',']', '^', '_', // 0x58 - 0x5f + + // lowercase + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', // 0x60 - 0x67 + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // 0x68 - 0x6f + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', // 0x70 - 0x77 + 'x', 'y', 'z', '{', '|', '}', '~', 1, // 0x78 - 0x7f + + 'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', // 0x80 - 0x87 + 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A', // 0x88 - 0x8f + 'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', // 0x90 - 0x97 + 'y', 'O', 'U', 'c', 'L', 'Y', 'P', 'f', // 0x98 - 0x9f + + 'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o', // 0xa0 - 0xa7 + '?', 1, 1, 1, 1, '!', '<', '>', // 0xa8 - 0xaf + 'o', '+', '2', '3', '\'','u', 'P', '.', // 0xb0 - 0xb7 + ',', '1', '0', '>', 1, 1, 1, '?', // 0xb8 - 0xbf + + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', // 0xc0 - 0xc7 + 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', // 0xc8 - 0xcf + 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'X', // 0xd0 - 0xd7 + '0', 'U', 'U', 'U', 'U', 'Y', 'b', 'B', // 0xd8 - 0xdf + + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', // 0xe0 - 0xe7 + 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', // 0xe8 - 0xef + 'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', // 0xf0 - 0xf7 + '0', 'u', 'u', 'u', 'u', 'y', 'b', 'y', // 0xf8 - 0xff +}; diff --git a/src/CONTROL.H b/src/CONTROL.H new file mode 100644 index 0000000..3532f8f --- /dev/null +++ b/src/CONTROL.H @@ -0,0 +1,149 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/CONTROL.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define SB1X1 121 +#define SB1X2 176 + +#define SB2X1 196 +#define SB2X2 251 + +#define SBY1 408 +#define SBY2 463 + +#define SBSY1 SBY1-55 +#define SBSY2 SBY2-55 + +#define TEXT_LEFT 0 +#define TEXT_CENTER 1 +#define TEXT_RIGHT 2 + +#define ICOLOR_WHITE 0 +#define ICOLOR_BLUE 1 +#define ICOLOR_RED 2 +#define ICOLOR_GOLD 3 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern BYTE *pBtmBuff; // Offscreen control panel buffer +extern BYTE *pStatusPanel; + +extern BYTE *pGBoxBuff; // Drop gold control panel buffer +extern BOOL dropGoldFlag; + +extern const BYTE fonttrans[]; +extern const BYTE fontkern[]; + +extern BOOL pinfoflag; + +extern char infostr[256]; +extern char infoclr; + +extern char tempstr[256]; + +extern BOOL drawhpflag; +extern BOOL drawmanaflag; + +extern BOOL chrflag; + +extern BOOL drawbtnflag, panbtndown; +extern BOOL panelflag; + +extern BOOL spselflag; + +extern BOOL chrbtndown; + +extern BOOL lvlbtndown; + +extern BOOL sbookflag; + +extern BOOL talkflag; + +extern int dropGoldValue; + +extern int initialDropGoldValue; + +extern int initialDropGoldIndex; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitControlPan(); +void CopyCtrlPan(int, int, int, int, int, int); +void DrawCtrlPan(); +void FreeControlPan(); + +void AddPanelString(const char *, int); +void ClearPanel(); + +void DrawHealthTop(); +void DrawHealthBar(); +void DrawManaTop(); +void DrawManaBar(); +void CalcInitBallPer(); + +BOOL InfoFit(const char *); +void DrawInfoBox(); + +void DrawSpellIcon(); +void DrawSpellList(); +void SetSpell(); +void SetupSpellSel(); +void SetSpellHK(int); +void GetSpellHK(int); + +void DrawChr(); + +void CheckLvlBtn(); +void ReleaseLvlBtn(); +void DrawLevelUpIcon(); + +void CheckPanelBtns(); +void ReleasePanelBtn(); +void DrawButtons(); +void CheckPanelInfo(); +void CheckDeadButtons(); + +void CheckChrBtns(); +void ReleaseChrBtn(); + +void DrawDurIcon(); + +void DrawPanelFont (long, long, char); + +void RedBack(); +void DrawPause(); + +void DrawSpellBook(); +void CheckSBook(); +//BOOL CheckSBookCast(); + +void TalkStart(); +void TalkEnd(); +BOOL Talk_wm_char(WPARAM wKey); +BOOL Talk_wm_keydown(WPARAM wKey); +void DrawTalkBox(); + +void PrintStringXY(int x, int y,const char * pszStr, char col); + +void DrawGoldBox(int gold); +void DropGoldType(char c); +void DropGold(int pnum, int cii); +void SetDropGoldCursor(int pnum); diff --git a/src/CURSOR.CPP b/src/CURSOR.CPP new file mode 100644 index 0000000..e9e00a5 --- /dev/null +++ b/src/CURSOR.CPP @@ -0,0 +1,746 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Cursor file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/CURSOR.CPP 4 2/12/97 10:48a Dbrevik2 $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "engine.h" +#include "gendung.h" +#include "control.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "objects.h" +#include "cursor.h" +#include "debug.h" +#include "scrollrt.h" +#include "inv.h" +#include "trigs.h" +#include "lighting.h" +#include "missiles.h" +#include "town.h" +#include "towners.h" +#include "quests.h" +#include "doom.h" + +/*-----------------------------------------------------------------------** +** externs +**-----------------------------------------------------------------------*/ +BOOL IsTracking(); +void savecrsr_reset(); + + +/*-----------------------------------------------------------------------** +** Global variables +**-----------------------------------------------------------------------*/ +int curs; +int cursW, cursH; +int icursW, icursH; +int icursW28, icursH28; +int cursmx, cursmy; +int cursmonst; +char cursobj; +char cursitem; +char cursinvitem; +char cursplr; +BYTE *pCursCels; +BYTE *pCursCels2; +static int oldcursmonst; + + +const int CursorWidth [ITEM_LAST_ID+12] = { + // Null, Glove Pointer, Identify, Repair, Recharge, Disarm, Oil, Telekenesis, Resurrect, Target, Heal Other, Watch + 0, 33, 32, 32, 32, 32, 32, 32, 32, 32, 32, 23, + // Inv 1x1 + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + // Inv 1x2 + 28, 28, 28, 28, 28, 28, + // Inv 1x3 + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, + // Inv 2x2 + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, + // Inv 2x3 + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, + + // New 1x1 + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + + // New 2x2 + 56, 56, + + // New 1x3 + 28, 28, 28, + + // New 2x3 + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, + + }; + +const int CursorHeight[ITEM_LAST_ID+12] = { + // Null, Glove Pointer, Identify, Repair, Recharge, Disarm, Oil, Telekenesis, Resurrect, Target, Heal Other, Watch + 0, 29, 32, 32, 32, 32, 32, 32, 32, 32, 32, 35, + // Inv 1x1 + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + // Inv 1x2 + 56, 56, 56, 56, 56, 56, + // Inv 1x3 + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, + // Inv 2x2 + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, + // Inv 2x3 + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, + + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + + 56, 56, + + 84, 84, 84, + + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, + + }; + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitCursor() { + app_assert(! pCursCels); + pCursCels = LoadFileInMemSig("Data\\Inv\\Objcurs.CEL",NULL,'CRSR'); + pCursCels2 = LoadFileInMemSig("Data\\Inv\\Objcurs2.CEL",NULL,'CRSR'); + savecrsr_reset(); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreeCursor() { + DiabloFreePtr(pCursCels); + DiabloFreePtr(pCursCels2); + savecrsr_reset(); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetICursor(int i) { + icursW = CursorWidth[i]; + icursH = CursorHeight[i]; + icursW28 = icursW / 28; + icursH28 = icursH / 28; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetCursor(int i) { + curs = i; + cursW = CursorWidth[curs]; + cursH = CursorHeight[curs]; + SetICursor(i); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void NewCursor(int i) { + SetCursor(i); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitLevelCursor() { + SetCursor(GLOVE_CURS); + cursmx = ViewX; + cursmy = ViewY; + oldcursmonst = -1; + cursmonst = -1; + cursobj = -1; + cursitem = -1; + cursplr = -1; + savecrsr_reset(); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CheckTown() { + for (int i = 0; i < nummissiles; i++) { + int mx = missileactive[i]; + if (missile[mx]._mitype == MIT_TOWN) { + if (((cursmx == missile[mx]._mix - 1) && (cursmy == missile[mx]._miy)) || + ((cursmx == missile[mx]._mix) && (cursmy == missile[mx]._miy - 1)) || + ((cursmx == missile[mx]._mix - 1) && (cursmy == missile[mx]._miy - 1)) || + ((cursmx == missile[mx]._mix - 2) && (cursmy == missile[mx]._miy - 1)) || + ((cursmx == missile[mx]._mix - 2) && (cursmy == missile[mx]._miy - 2)) || + ((cursmx == missile[mx]._mix - 1) && (cursmy == missile[mx]._miy - 2)) || + ((cursmx == missile[mx]._mix) && (cursmy == missile[mx]._miy))) { + trigflag = TRUE; + ClearPanel(); + strcpy(infostr, "Town Portal"); + sprintf(tempstr, "from %s", plr[missile[mx]._misource]._pName); + AddPanelString(tempstr, TEXT_CENTER); + cursmx = missile[mx]._mix; + cursmy = missile[mx]._miy; + } + } + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckRportal() { + for (int i = 0; i < nummissiles; i++) { + int mx = missileactive[i]; + if (missile[mx]._mitype == MIT_RPORTAL) { + if (((cursmx == missile[mx]._mix - 1) && (cursmy == missile[mx]._miy)) || + ((cursmx == missile[mx]._mix) && (cursmy == missile[mx]._miy - 1)) || + ((cursmx == missile[mx]._mix - 1) && (cursmy == missile[mx]._miy - 1)) || + ((cursmx == missile[mx]._mix - 2) && (cursmy == missile[mx]._miy - 1)) || + ((cursmx == missile[mx]._mix - 2) && (cursmy == missile[mx]._miy - 2)) || + ((cursmx == missile[mx]._mix - 1) && (cursmy == missile[mx]._miy - 2)) || + ((cursmx == missile[mx]._mix) && (cursmy == missile[mx]._miy))) { + trigflag = TRUE; + ClearPanel(); + strcpy(infostr, "Portal to"); + if (!(setlevel)) strcpy(tempstr, "The Unholy Altar"); + else strcpy(tempstr, "level 15"); + AddPanelString(tempstr, TEXT_CENTER); + cursmx = missile[mx]._mix; + cursmy = missile[mx]._miy; + } + } + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckCursMove() { + int mx,my; + int offsetx,offsety,gridx,gridy; + char co,ci,cp; + int cm; + BOOL minusy, plusx; + BOOL lefthalf; + int newMouseX; + int newMouseY; + + int pvar6tmp, pvar7tmp; + long xo, yo; + + newMouseX = MouseX; + newMouseY = MouseY; + + // Convert screen point to map position + if (chrflag || questlog) { + if (newMouseX >= TOTALX/4) newMouseX -= TOTALX/4; + else newMouseX = 0; + } + else if (invflag || sbookflag) { + if (newMouseX <= TOTALX/2) newMouseX += TOTALX/4; + else newMouseX = 0; + } + + // if the mouse outside the gamemap area, but + // the mouse is in tracking mode, then pretend + // that the mouse is actually in the gamemap + if (newMouseY > 351 && IsTracking()) + newMouseY = 351; + + if (!svgamode) + { + newMouseX >>= 1; + newMouseY >>= 1; + } + + // Offset mouse position by the scroll offset, to align it with tile grid + newMouseX -= ScrollInfo._sxoff; + newMouseY -= ScrollInfo._syoff; + + // THIS IS A HACK + // Here, we predict the next scroll increment, so the mouse position is + // where it would be during the next frame. + // This is a fix -- without this, the following sometimes happens: + // The user holds down the mouse button, and the walk path alternates + // between two different directions, because the cursor is sampled just before + // player reaches his next square. + xo = plr[myplr]._pVar6 >> 8; + yo = plr[myplr]._pVar7 >> 8; + pvar6tmp = plr[myplr]._pVar6 + plr[myplr]._pxvel; + pvar7tmp = plr[myplr]._pVar7 + plr[myplr]._pyvel; + xo -= (pvar6tmp >> 8); + yo -= (pvar7tmp >> 8); + if ((myplr == myplr) && (ScrollInfo._sdir != SCRL_NONE)) { + newMouseX -= xo; + newMouseY -= yo; + } + + if (newMouseX < 0) + newMouseX = 0; + if (newMouseX >= TOTALX) + newMouseX = TOTALX; + if (newMouseY < 0) + newMouseY = 0; + if (newMouseY >= TOTALY) + newMouseY = TOTALY; + + // Calculate position in square grid + gridx = newMouseX >> 6; + gridy = newMouseY >> 5; + + // Calculate offset in that square + offsetx = newMouseX & 63; + offsety = newMouseY & 31; + + // Convert from square grid to diamond grid + mx = gridx + gridy + ViewX - (svgamode ? 10:5); + my = gridy - gridx + ViewY; + + if (minusy = (offsety < (offsetx >> 1))) { + my--; + } + if (plusx = (offsety >= (32 - (offsetx >> 1)))) { + mx++; + } + + if (mx < 0) mx = 0; + if (mx >= DMAXX) mx = DMAXX - 1; + if (my < 0) my = 0; + if (my >= DMAXY) my = DMAXY - 1; + + lefthalf = (minusy && plusx) || ((minusy || plusx) && offsetx < 32); + + oldcursmonst = cursmonst; + cursmonst = -1; + cursobj = -1; + cursitem = -1; + if (cursinvitem != -1) + drawsbarflag = TRUE; + cursinvitem = -1; + cursplr = -1; + uitemflag = FALSE; + panelflag = FALSE; + trigflag = FALSE; + + if (plr[myplr]._pInvincible) return; // Dead? + + // Skip if I have an item + if ((curs >= ICSTART) || (spselflag)) { + cursmx = mx; + cursmy = my; + return; + } + + if (MouseY > 352) { + CheckPanelInfo(); + return; + } + + if (drawmapofdoom) return; + + if ((invflag) && (MouseX > 320)) { + cursinvitem = CheckInvHLight(); + return; + } + if (sbookflag && (MouseX > 320)) + return; + + if ((chrflag || questlog) && (MouseX < 320)) return; + + if (leveltype != 0) { + if (oldcursmonst != -1) { + if (!lefthalf && (dMonster[mx+2][my+1] != 0) && (dFlags[mx+2][my+1] & BFLAG_VISIBLE)) { + if (dMonster[mx+2][my+1] > 0) cm = dMonster[mx+2][my+1] - 1; + else cm = -(dMonster[mx+2][my+1] + 1); + if (cm == oldcursmonst) { + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_TOP)) { + cursmx = mx + 1; + cursmy = my + 2; + cursmonst = cm; + } + } + } + if (lefthalf && (dMonster[mx+1][my+2] != 0) && (dFlags[mx+1][my+2] & BFLAG_VISIBLE)) { + if (dMonster[mx+1][my+2] > 0) cm = dMonster[mx+1][my+2] - 1; + else cm = -(dMonster[mx+1][my+2] + 1); + if (cm == oldcursmonst) { + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_TOP)) { + cursmx = mx + 1; + cursmy = my + 2; + cursmonst = cm; + } + } + } + if ((dMonster[mx+2][my+2] != 0) && (dFlags[mx+2][my+2] & BFLAG_VISIBLE)) { + if (dMonster[mx+2][my+2] > 0) cm = dMonster[mx+2][my+2] - 1; + else cm = -(dMonster[mx+2][my+2] + 1); + if (cm == oldcursmonst) { + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_TOP)) { + cursmx = mx + 2; + cursmy = my + 2; + cursmonst = cm; + } + } + } + if (!lefthalf && (dMonster[mx+1][my] != 0) && (dFlags[mx+1][my] & BFLAG_VISIBLE)) { + if (dMonster[mx+1][my] > 0) cm = dMonster[mx+1][my] - 1; + else cm = -(dMonster[mx+1][my] + 1); + if (cm == oldcursmonst) { + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_MID)) { + cursmx = mx + 1; + cursmy = my; + cursmonst = cm; + } + } + } + if (lefthalf && (dMonster[mx][my+1] != 0) && (dFlags[mx][my+1] & BFLAG_VISIBLE)) { + if (dMonster[mx][my+1] > 0) cm = dMonster[mx][my+1] - 1; + else cm = -(dMonster[mx][my+1] + 1); + if (cm == oldcursmonst) { + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_MID)) { + cursmx = mx; + cursmy = my + 1; + cursmonst = cm; + } + } + } + if ((dMonster[mx][my] != 0) && (dFlags[mx][my] & BFLAG_VISIBLE)) { + if (dMonster[mx][my] > 0) cm = dMonster[mx][my] - 1; + else cm = -(dMonster[mx][my] + 1); + if (cm == oldcursmonst) { + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_FLR)) { + cursmx = mx; + cursmy = my; + cursmonst = cm; + } + } + } + if ((dMonster[mx+1][my+1] != 0) && (dFlags[mx+1][my+1] & BFLAG_VISIBLE)) { + if (dMonster[mx+1][my+1] > 0) cm = dMonster[mx+1][my+1] - 1; + else cm = -(dMonster[mx+1][my+1] + 1); + if (cm == oldcursmonst) { + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_MID)) { + cursmx = mx + 1; + cursmy = my + 1; + cursmonst = cm; + } + } + } + if (cursmonst != -1) { + if (monster[cursmonst]._mFlags & MFLAG_INVISIBLE) { + cursmonst = -1; + cursmx = mx; + cursmy = my; + } + } + if ((cursmonst != -1) + && ((monster[cursmonst]._mFlags & MFLAG_MKILLER) != 0) + && ((monster[cursmonst]._mFlags & MFLAG_BERSERK) == 0) + ) cursmonst = -1; + + if (cursmonst != -1) return; + } + if (!lefthalf && (dMonster[mx+2][my+1] != 0) && (dFlags[mx+2][my+1] & BFLAG_VISIBLE)) { + if (dMonster[mx+2][my+1] > 0) cm = dMonster[mx+2][my+1] - 1; + else cm = -(dMonster[mx+2][my+1] + 1); + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_TOP)) { + cursmx = mx + 2; + cursmy = my + 1; + cursmonst = cm; + } + } + if (lefthalf && (dMonster[mx+1][my+2] != 0) && (dFlags[mx+1][my+2] & BFLAG_VISIBLE)) { + if (dMonster[mx+1][my+2] > 0) cm = dMonster[mx+1][my+2] - 1; + else cm = -(dMonster[mx+1][my+2] + 1); + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_TOP)) { + cursmx = mx + 1; + cursmy = my + 2; + cursmonst = cm; + } + } + if ((dMonster[mx+2][my+2] != 0) && (dFlags[mx+2][my+2] & BFLAG_VISIBLE)) { + if (dMonster[mx+2][my+2] > 0) cm = dMonster[mx+2][my+2] - 1; + else cm = -(dMonster[mx+2][my+2] + 1); + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_TOP)) { + cursmx = mx + 2; + cursmy = my + 2; + cursmonst = cm; + } + } + if (!lefthalf && (dMonster[mx+1][my] != 0) && (dFlags[mx+1][my] & BFLAG_VISIBLE)) { + if (dMonster[mx+1][my] > 0) cm = dMonster[mx+1][my] - 1; + else cm = -(dMonster[mx+1][my] + 1); + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_MID)) { + cursmx = mx + 1; + cursmy = my; + cursmonst = cm; + } + } + if (lefthalf && (dMonster[mx][my+1] != 0) && (dFlags[mx][my+1] & BFLAG_VISIBLE)) { + if (dMonster[mx][my+1] > 0) cm = dMonster[mx][my+1] - 1; + else cm = -(dMonster[mx][my+1] + 1); + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_MID)) { + cursmx = mx; + cursmy = my + 1; + cursmonst = cm; + } + } + if ((dMonster[mx][my] != 0) && (dFlags[mx][my] & BFLAG_VISIBLE)) { + if (dMonster[mx][my] > 0) cm = dMonster[mx][my] - 1; + else cm = -(dMonster[mx][my] + 1); + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_FLR)) { + cursmx = mx; + cursmy = my; + cursmonst = cm; + } + } + if ((dMonster[mx+1][my+1] != 0) && (dFlags[mx+1][my+1] & BFLAG_VISIBLE)) { + if (dMonster[mx+1][my+1] > 0) cm = dMonster[mx+1][my+1] - 1; + else cm = -(dMonster[mx+1][my+1] + 1); + if (((monster[cm]._mhitpoints >> HP_SHIFT) > 0) && (monster[cm].MData->mSelFlag & MSEL_MID)) { + cursmx = mx + 1; + cursmy = my + 1; + cursmonst = cm; + } + } + if (cursmonst != -1) { + if (monster[cursmonst]._mFlags & MFLAG_INVISIBLE) { + cursmonst = -1; + cursmx = mx; + cursmy = my; + } + } + if ((cursmonst != -1) + && ((monster[cursmonst]._mFlags & MFLAG_MKILLER) != 0) + && ((monster[cursmonst]._mFlags & MFLAG_BERSERK) == 0) + ) cursmonst = -1; + } else { + if (!lefthalf && (dMonster[mx+1][my] > 0)) { + cursmonst = dMonster[mx+1][my] - 1; + cursmx = mx + 1; + cursmy = my; + } + if (lefthalf && (dMonster[mx][my+1] > 0)) { + cursmonst = dMonster[mx][my+1] - 1; + cursmx = mx; + cursmy = my + 1; + } + if (dMonster[mx][my] > 0) { + cursmonst = dMonster[mx][my] - 1; + cursmx = mx; + cursmy = my; + } + if (dMonster[mx+1][my+1] > 0) { + cursmonst = dMonster[mx+1][my+1] - 1; + cursmx = mx + 1; + cursmy = my + 1; + } + if (!towner[cursmonst]._tSelFlag) cursmonst = -1; + } + + if (cursmonst == -1) { + if (!lefthalf && (dPlayer[mx+1][my] != 0)) { + if (dPlayer[mx+1][my] > 0) cp = dPlayer[mx+1][my] - 1; + else cp = -(dPlayer[mx+1][my] + 1); + if ((cp != myplr) && (plr[cp]._pHitPoints != 0)) { + cursmx = mx + 1; + cursmy = my; + cursplr = cp; + } + } + if (lefthalf && (dPlayer[mx][my+1] != 0)) { + if (dPlayer[mx][my+1] > 0) cp = dPlayer[mx][my+1] - 1; + else cp = -(dPlayer[mx][my+1] + 1); + if ((cp != myplr) && (plr[cp]._pHitPoints != 0)) { + cursmx = mx; + cursmy = my + 1; + cursplr = cp; + } + } + if (dPlayer[mx][my] != 0) { + if (dPlayer[mx][my] > 0) cp = dPlayer[mx][my] - 1; + else cp = -(dPlayer[mx][my] + 1); + if (cp != myplr) { + cursmx = mx; + cursmy = my; + cursplr = cp; + } + } + if (dFlags[mx][my] & BFLAG_DEADPLR) { + for (int i = 0; i < MAX_PLRS; i++) { + if ((plr[i]._px == mx) && (plr[i]._py == my) && (i != myplr)) { + cursmx = mx; + cursmy = my; + cursplr = i; + } + } + } + + if (curs == RESURRECT_CURS) { + for (int j = -1; j < 2; j++) { + for (int k = -1; k < 2; k++) { + if (dFlags[mx+j][my+k] & BFLAG_DEADPLR) { + for (int i = 0; i < MAX_PLRS; i++) { + if ((plr[i]._px == mx+j) && (plr[i]._py == my+k) && (i != myplr)) { + cursmx = mx+j; + cursmy = my+k; + cursplr = i; + } + } + } + } + } + } + + if (dPlayer[mx+1][my+1] != 0) { + if (dPlayer[mx+1][my+1] > 0) cp = dPlayer[mx+1][my+1] - 1; + else cp = -(dPlayer[mx+1][my+1] + 1); + if ((cp != myplr) && (plr[cp]._pHitPoints != 0)) { + cursmx = mx + 1; + cursmy = my + 1; + cursplr = cp; + } + } + } + + if ((cursmonst == -1) && (cursplr == -1)) { + if (!lefthalf && (dObject[mx+1][my] != 0)) { + if (dObject[mx+1][my] > 0) co = dObject[mx+1][my] - 1; + else co = -(dObject[mx+1][my] + 1); + if (object[co]._oSelFlag >= OSEL_TOP) { + cursmx = mx + 1; + cursmy = my; + cursobj = co; + } + } + if (lefthalf && (dObject[mx][my+1] != 0)) { + if (dObject[mx][my+1] > 0) co = dObject[mx][my+1] - 1; + else co = -(dObject[mx][my+1] + 1); + if (object[co]._oSelFlag >= OSEL_TOP) { + cursmx = mx; + cursmy = my + 1; + cursobj = co; + } + } + if (dObject[mx][my] != 0) { + if (dObject[mx][my] > 0) co = dObject[mx][my] - 1; + else co = -(dObject[mx][my] + 1); + if ((object[co]._oSelFlag == OSEL_FLR) || (object[co]._oSelFlag == OSEL_ALL)) { + cursmx = mx; + cursmy = my; + cursobj = co; + } + } + if (dObject[mx+1][my+1] != 0) { + if (dObject[mx+1][my+1] > 0) co = dObject[mx+1][my+1] - 1; + else co = -(dObject[mx+1][my+1] + 1); + if (object[co]._oSelFlag >= OSEL_TOP) { + cursmx = mx + 1; + cursmy = my + 1; + cursobj = co; + } + } + } + + if ((cursplr == -1) && (cursobj == -1) && (cursmonst == -1)) { + if (!lefthalf && (dItem[mx+1][my] > 0)) { + ci = dItem[mx+1][my] - 1; + if (item[ci]._iSelFlag >= ISEL_TOP) { + cursmx = mx + 1; + cursmy = my; + cursitem = ci; + } + } + if (lefthalf && (dItem[mx][my+1] > 0)) { + ci = dItem[mx][my+1] - 1; + if (item[ci]._iSelFlag >= ISEL_TOP) { + cursmx = mx; + cursmy = my + 1; + cursitem = ci; + } + } + if (dItem[mx][my] > 0) { + ci = dItem[mx][my] - 1; + if ((item[ci]._iSelFlag == ISEL_FLR) || (item[ci]._iSelFlag == ISEL_ALL)) { + cursmx = mx; + cursmy = my; + cursitem = ci; + } + } + if (dItem[mx+1][my+1] > 0) { + ci = dItem[mx+1][my+1] - 1; + if (item[ci]._iSelFlag >= ISEL_TOP) { + cursmx = mx + 1; + cursmy = my + 1; + cursitem = ci; + } + } + if (cursitem == -1) { + cursmx = mx; + cursmy = my; + CheckTrigForce(); + CheckTown(); + CheckRportal(); + } + } + if (curs == IDENTIFY_CURS) { + cursobj = -1; + cursmonst = -1; + cursitem = -1; + cursmx = mx; + cursmy = my; + } + + if ((cursmonst != -1) + && ((monster[cursmonst]._mFlags & MFLAG_MKILLER) != 0) + && ((monster[cursmonst]._mFlags & MFLAG_BERSERK) == 0) + ) cursmonst = -1; +} diff --git a/src/CURSOR.H b/src/CURSOR.H new file mode 100644 index 0000000..aa6cff4 --- /dev/null +++ b/src/CURSOR.H @@ -0,0 +1,68 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/CURSOR.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define NO_CURSOR 0 +#define VIEW_CURSOR 1 + +#define GLOVE_CURS 1 +#define IDENTIFY_CURS 2 +#define REPAIR_CURS 3 +#define RECHARGE_CURS 4 +#define DISARM_CURS 5 +#define OIL_CURS 6 +#define TELE_CURS 7 +#define RESURRECT_CURS 8 +#define TARGET_CURS 9 +#define HEALOTHER_CURS 10 +#define WATCH_CURS 11 +#define ICSTART 12 // Cursor where items start at +#define ICLAST 179 // last of the original cursors + +#define MSEL_NONE 0 // No selection (not used) +#define MSEL_FLR 1 // Floor / single square +#define MSEL_MID 2 // Square above monster base +#define MSEL_REG 3 // Normal floor + 1 square above +#define MSEL_TOP 4 // Square 2 above monster base +#define MSEL_FLY 6 // Square 1 and 2 above base (gargolye, bat) +#define MSEL_BIG 7 // Large monsters floor, 1, and 2 squares + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern int curs; +extern int cursW, cursH; +extern int icursW, icursH; +extern int icursW28, icursH28; +extern int cursmx, cursmy; +extern int cursmonst; +extern char cursobj; +extern char cursitem; +extern char cursinvitem; +extern char cursplr; +extern BYTE *pCursCels; +extern BYTE *pCursCels2; +extern const int CursorWidth[]; +extern const int CursorHeight[]; + + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +void InitCursor(); +void InitLevelCursor(); +void CheckCursMove(); +void SetICursor(int i); +void SetCursor(int i); +void NewCursor(int i); diff --git a/src/D3DTYPES.H b/src/D3DTYPES.H new file mode 100644 index 0000000..81acb76 --- /dev/null +++ b/src/D3DTYPES.H @@ -0,0 +1,957 @@ +/*==========================================================================; + * + * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved. + * + * File: d3dtypes.h + * Content: Direct3D types include file + * + ***************************************************************************/ + +#ifndef _D3DTYPES_H_ +#define _D3DTYPES_H_ + +// pjw commented out -- win32 out to be defined! +// #ifndef WIN32 +//#include "subwtype.h" +//#else +#include +//#endif + +#include "ddraw.h" + +#pragma pack(4) + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* D3DVALUE is the fundamental Direct3D fractional data type */ + +#define D3DVALP(val, prec) ((float)(val)) +#define D3DVAL(val) ((float)(val)) +typedef float D3DVALUE, *LPD3DVALUE; +#define D3DDivide(a, b) (float)((double) (a) / (double) (b)) +#define D3DMultiply(a, b) ((a) * (b)) + +typedef LONG D3DFIXED; + +#ifndef RGB_MAKE +/* + * Format of CI colors is + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | alpha | color index | fraction | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define CI_GETALPHA(ci) ((ci) >> 24) +#define CI_GETINDEX(ci) (((ci) >> 8) & 0xffff) +#define CI_GETFRACTION(ci) ((ci) & 0xff) +#define CI_ROUNDINDEX(ci) CI_GETINDEX((ci) + 0x80) +#define CI_MASKALPHA(ci) ((ci) & 0xffffff) +#define CI_MAKE(a, i, f) (((a) << 24) | ((i) << 8) | (f)) + +/* + * Format of RGBA colors is + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | alpha | red | green | blue | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define RGBA_GETALPHA(rgb) ((rgb) >> 24) +#define RGBA_GETRED(rgb) (((rgb) >> 16) & 0xff) +#define RGBA_GETGREEN(rgb) (((rgb) >> 8) & 0xff) +#define RGBA_GETBLUE(rgb) ((rgb) & 0xff) +#define RGBA_MAKE(r, g, b, a) ((D3DCOLOR) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))) + +/* D3DRGB and D3DRGBA may be used as initialisers for D3DCOLORs + * The float values must be in the range 0..1 + */ +#define D3DRGB(r, g, b) \ + (0xff000000L | ( ((long)((r) * 255)) << 16) | (((long)((g) * 255)) << 8) | (long)((b) * 255)) +#define D3DRGBA(r, g, b, a) \ + ( (((long)((a) * 255)) << 24) | (((long)((r) * 255)) << 16) \ + | (((long)((g) * 255)) << 8) | (long)((b) * 255) \ + ) + +/* + * Format of RGB colors is + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | ignored | red | green | blue | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define RGB_GETRED(rgb) (((rgb) >> 16) & 0xff) +#define RGB_GETGREEN(rgb) (((rgb) >> 8) & 0xff) +#define RGB_GETBLUE(rgb) ((rgb) & 0xff) +#define RGBA_SETALPHA(rgba, x) (((x) << 24) | ((rgba) & 0x00ffffff)) +#define RGB_MAKE(r, g, b) ((D3DCOLOR) (((r) << 16) | ((g) << 8) | (b))) +#define RGBA_TORGB(rgba) ((D3DCOLOR) ((rgba) & 0xffffff)) +#define RGB_TORGBA(rgb) ((D3DCOLOR) ((rgb) | 0xff000000)) + +#endif + +/* + * Flags for Enumerate functions + */ + +/* + * Stop the enumeration + */ +#define D3DENUMRET_CANCEL DDENUMRET_CANCEL + +/* + * Continue the enumeration + */ +#define D3DENUMRET_OK DDENUMRET_OK + +typedef HRESULT (WINAPI* LPD3DVALIDATECALLBACK)(LPVOID lpUserArg, DWORD dwOffset); +typedef HRESULT (WINAPI* LPD3DENUMTEXTUREFORMATSCALLBACK)(LPDDSURFACEDESC lpDdsd, LPVOID lpContext); + +typedef DWORD D3DCOLOR, D3DCOLOR, *LPD3DCOLOR; + +typedef DWORD D3DMATERIALHANDLE, *LPD3DMATERIALHANDLE; +typedef DWORD D3DTEXTUREHANDLE, *LPD3DTEXTUREHANDLE; +typedef DWORD D3DMATRIXHANDLE, *LPD3DMATRIXHANDLE; + +typedef struct _D3DCOLORVALUE { + union { + D3DVALUE r; + D3DVALUE dvR; + }; + union { + D3DVALUE g; + D3DVALUE dvG; + }; + union { + D3DVALUE b; + D3DVALUE dvB; + }; + union { + D3DVALUE a; + D3DVALUE dvA; + }; +} D3DCOLORVALUE; + +typedef struct _D3DRECT { + union { + LONG x1; + LONG lX1; + }; + union { + LONG y1; + LONG lY1; + }; + union { + LONG x2; + LONG lX2; + }; + union { + LONG y2; + LONG lY2; + }; +} D3DRECT, *LPD3DRECT; + +typedef struct _D3DVECTOR { + union { + D3DVALUE x; + D3DVALUE dvX; + }; + union { + D3DVALUE y; + D3DVALUE dvY; + }; + union { + D3DVALUE z; + D3DVALUE dvZ; + }; +} D3DVECTOR, *LPD3DVECTOR; + + +/* + * Vertex data types supported in an ExecuteBuffer. + */ + +/* + * Homogeneous vertices + */ + +typedef struct _D3DHVERTEX { + DWORD dwFlags; /* Homogeneous clipping flags */ + union { + D3DVALUE hx; + D3DVALUE dvHX; + }; + union { + D3DVALUE hy; + D3DVALUE dvHY; + }; + union { + D3DVALUE hz; + D3DVALUE dvHZ; + }; +} D3DHVERTEX, *LPD3DHVERTEX; + +/* + * Transformed/lit vertices + */ +typedef struct _D3DTLVERTEX { + union { + D3DVALUE sx; /* Screen coordinates */ + D3DVALUE dvSX; + }; + union { + D3DVALUE sy; + D3DVALUE dvSY; + }; + union { + D3DVALUE sz; + D3DVALUE dvSZ; + }; + union { + D3DVALUE rhw; /* Reciprocal of homogeneous w */ + D3DVALUE dvRHW; + }; + union { + D3DCOLOR color; /* Vertex color */ + D3DCOLOR dcColor; + }; + union { + D3DCOLOR specular; /* Specular component of vertex */ + D3DCOLOR dcSpecular; + }; + union { + D3DVALUE tu; /* Texture coordinates */ + D3DVALUE dvTU; + }; + union { + D3DVALUE tv; + D3DVALUE dvTV; + }; +} D3DTLVERTEX, *LPD3DTLVERTEX; + +/* + * Untransformed/lit vertices + */ +typedef struct _D3DLVERTEX { + union { + D3DVALUE x; /* Homogeneous coordinates */ + D3DVALUE dvX; + }; + union { + D3DVALUE y; + D3DVALUE dvY; + }; + union { + D3DVALUE z; + D3DVALUE dvZ; + }; + DWORD dwReserved; + union { + D3DCOLOR color; /* Vertex color */ + D3DCOLOR dcColor; + }; + union { + D3DCOLOR specular; /* Specular component of vertex */ + D3DCOLOR dcSpecular; + }; + union { + D3DVALUE tu; /* Texture coordinates */ + D3DVALUE dvTU; + }; + union { + D3DVALUE tv; + D3DVALUE dvTV; + }; +} D3DLVERTEX, *LPD3DLVERTEX; + +/* + * Untransformed/unlit vertices + */ + +typedef struct _D3DVERTEX { + union { + D3DVALUE x; /* Homogeneous coordinates */ + D3DVALUE dvX; + }; + union { + D3DVALUE y; + D3DVALUE dvY; + }; + union { + D3DVALUE z; + D3DVALUE dvZ; + }; + union { + D3DVALUE nx; /* Normal */ + D3DVALUE dvNX; + }; + union { + D3DVALUE ny; + D3DVALUE dvNY; + }; + union { + D3DVALUE nz; + D3DVALUE dvNZ; + }; + union { + D3DVALUE tu; /* Texture coordinates */ + D3DVALUE dvTU; + }; + union { + D3DVALUE tv; + D3DVALUE dvTV; + }; +} D3DVERTEX, *LPD3DVERTEX; + +/* + * Matrix, viewport, and tranformation structures and definitions. + */ + +typedef struct _D3DMATRIX { + D3DVALUE _11, _12, _13, _14; + D3DVALUE _21, _22, _23, _24; + D3DVALUE _31, _32, _33, _34; + D3DVALUE _41, _42, _43, _44; +} D3DMATRIX, *LPD3DMATRIX; + +typedef struct _D3DVIEWPORT { + DWORD dwSize; + DWORD dwX; + DWORD dwY; /* Top left */ + DWORD dwWidth; + DWORD dwHeight; /* Dimensions */ + D3DVALUE dvScaleX; /* Scale homogeneous to screen */ + D3DVALUE dvScaleY; /* Scale homogeneous to screen */ + D3DVALUE dvMaxX; /* Min/max homogeneous x coord */ + D3DVALUE dvMaxY; /* Min/max homogeneous y coord */ + D3DVALUE dvMinZ; + D3DVALUE dvMaxZ; /* Min/max homogeneous z coord */ +} D3DVIEWPORT, *LPD3DVIEWPORT; + +/* + * Values for clip fields. + */ +#define D3DCLIP_LEFT 0x00000001L +#define D3DCLIP_RIGHT 0x00000002L +#define D3DCLIP_TOP 0x00000004L +#define D3DCLIP_BOTTOM 0x00000008L +#define D3DCLIP_FRONT 0x00000010L +#define D3DCLIP_BACK 0x00000020L +#define D3DCLIP_GEN0 0x00000040L +#define D3DCLIP_GEN1 0x00000080L +#define D3DCLIP_GEN2 0x00000100L +#define D3DCLIP_GEN3 0x00000200L +#define D3DCLIP_GEN4 0x00000400L +#define D3DCLIP_GEN5 0x00000800L + +/* + * Values for d3d status. + */ +#define D3DSTATUS_CLIPUNIONLEFT D3DCLIP_LEFT +#define D3DSTATUS_CLIPUNIONRIGHT D3DCLIP_RIGHT +#define D3DSTATUS_CLIPUNIONTOP D3DCLIP_TOP +#define D3DSTATUS_CLIPUNIONBOTTOM D3DCLIP_BOTTOM +#define D3DSTATUS_CLIPUNIONFRONT D3DCLIP_FRONT +#define D3DSTATUS_CLIPUNIONBACK D3DCLIP_BACK +#define D3DSTATUS_CLIPUNIONGEN0 D3DCLIP_GEN0 +#define D3DSTATUS_CLIPUNIONGEN1 D3DCLIP_GEN1 +#define D3DSTATUS_CLIPUNIONGEN2 D3DCLIP_GEN2 +#define D3DSTATUS_CLIPUNIONGEN3 D3DCLIP_GEN3 +#define D3DSTATUS_CLIPUNIONGEN4 D3DCLIP_GEN4 +#define D3DSTATUS_CLIPUNIONGEN5 D3DCLIP_GEN5 + +#define D3DSTATUS_CLIPINTERSECTIONLEFT 0x00001000L +#define D3DSTATUS_CLIPINTERSECTIONRIGHT 0x00002000L +#define D3DSTATUS_CLIPINTERSECTIONTOP 0x00004000L +#define D3DSTATUS_CLIPINTERSECTIONBOTTOM 0x00008000L +#define D3DSTATUS_CLIPINTERSECTIONFRONT 0x00010000L +#define D3DSTATUS_CLIPINTERSECTIONBACK 0x00020000L +#define D3DSTATUS_CLIPINTERSECTIONGEN0 0x00040000L +#define D3DSTATUS_CLIPINTERSECTIONGEN1 0x00080000L +#define D3DSTATUS_CLIPINTERSECTIONGEN2 0x00100000L +#define D3DSTATUS_CLIPINTERSECTIONGEN3 0x00200000L +#define D3DSTATUS_CLIPINTERSECTIONGEN4 0x00400000L +#define D3DSTATUS_CLIPINTERSECTIONGEN5 0x00800000L +#define D3DSTATUS_ZNOTVISIBLE 0x01000000L + +#define D3DSTATUS_CLIPUNIONALL ( \ + D3DSTATUS_CLIPUNIONLEFT | \ + D3DSTATUS_CLIPUNIONRIGHT | \ + D3DSTATUS_CLIPUNIONTOP | \ + D3DSTATUS_CLIPUNIONBOTTOM | \ + D3DSTATUS_CLIPUNIONFRONT | \ + D3DSTATUS_CLIPUNIONBACK | \ + D3DSTATUS_CLIPUNIONGEN0 | \ + D3DSTATUS_CLIPUNIONGEN1 | \ + D3DSTATUS_CLIPUNIONGEN2 | \ + D3DSTATUS_CLIPUNIONGEN3 | \ + D3DSTATUS_CLIPUNIONGEN4 | \ + D3DSTATUS_CLIPUNIONGEN5 \ + ) + +#define D3DSTATUS_CLIPINTERSECTIONALL ( \ + D3DSTATUS_CLIPINTERSECTIONLEFT | \ + D3DSTATUS_CLIPINTERSECTIONRIGHT | \ + D3DSTATUS_CLIPINTERSECTIONTOP | \ + D3DSTATUS_CLIPINTERSECTIONBOTTOM | \ + D3DSTATUS_CLIPINTERSECTIONFRONT | \ + D3DSTATUS_CLIPINTERSECTIONBACK | \ + D3DSTATUS_CLIPINTERSECTIONGEN0 | \ + D3DSTATUS_CLIPINTERSECTIONGEN1 | \ + D3DSTATUS_CLIPINTERSECTIONGEN2 | \ + D3DSTATUS_CLIPINTERSECTIONGEN3 | \ + D3DSTATUS_CLIPINTERSECTIONGEN4 | \ + D3DSTATUS_CLIPINTERSECTIONGEN5 \ + ) + +#define D3DSTATUS_DEFAULT ( \ + D3DSTATUS_CLIPINTERSECTIONALL | \ + D3DSTATUS_ZNOTVISIBLE) + + +/* + * Options for direct transform calls + */ +#define D3DTRANSFORM_CLIPPED 0x00000001l +#define D3DTRANSFORM_UNCLIPPED 0x00000002l + +typedef struct _D3DTRANSFORMDATA { + DWORD dwSize; + LPVOID lpIn; /* Input vertices */ + DWORD dwInSize; /* Stride of input vertices */ + LPVOID lpOut; /* Output vertices */ + DWORD dwOutSize; /* Stride of output vertices */ + LPD3DHVERTEX lpHOut; /* Output homogeneous vertices */ + DWORD dwClip; /* Clipping hint */ + DWORD dwClipIntersection; + DWORD dwClipUnion; /* Union of all clip flags */ + D3DRECT drExtent; /* Extent of transformed vertices */ +} D3DTRANSFORMDATA, *LPD3DTRANSFORMDATA; + +/* + * Structure defining position and direction properties for lighting. + */ +typedef struct _D3DLIGHTINGELEMENT { + D3DVECTOR dvPosition; /* Lightable point in model space */ + D3DVECTOR dvNormal; /* Normalised unit vector */ +} D3DLIGHTINGELEMENT, *LPD3DLIGHTINGELEMENT; + +/* + * Structure defining material properties for lighting. + */ +typedef struct _D3DMATERIAL { + DWORD dwSize; + union { + D3DCOLORVALUE diffuse; /* Diffuse color RGBA */ + D3DCOLORVALUE dcvDiffuse; + }; + union { + D3DCOLORVALUE ambient; /* Ambient color RGB */ + D3DCOLORVALUE dcvAmbient; + }; + union { + D3DCOLORVALUE specular; /* Specular 'shininess' */ + D3DCOLORVALUE dcvSpecular; + }; + union { + D3DCOLORVALUE emissive; /* Emissive color RGB */ + D3DCOLORVALUE dcvEmissive; + }; + union { + D3DVALUE power; /* Sharpness if specular highlight */ + D3DVALUE dvPower; + }; + D3DTEXTUREHANDLE hTexture; /* Handle to texture map */ + DWORD dwRampSize; +} D3DMATERIAL, *LPD3DMATERIAL; + +typedef enum _D3DLIGHTTYPE { + D3DLIGHT_POINT = 1, + D3DLIGHT_SPOT = 2, + D3DLIGHT_DIRECTIONAL = 3, + D3DLIGHT_PARALLELPOINT = 4, + D3DLIGHT_GLSPOT = 5, +} D3DLIGHTTYPE; + +/* + * Structure defining a light source and its properties. + */ +typedef struct _D3DLIGHT { + DWORD dwSize; + D3DLIGHTTYPE dltType; /* Type of light source */ + D3DCOLORVALUE dcvColor; /* Color of light */ + D3DVECTOR dvPosition; /* Position in world space */ + D3DVECTOR dvDirection; /* Direction in world space */ + D3DVALUE dvRange; /* Cutoff range */ + D3DVALUE dvFalloff; /* Falloff */ + D3DVALUE dvAttenuation0; /* Constant attenuation */ + D3DVALUE dvAttenuation1; /* Linear attenuation */ + D3DVALUE dvAttenuation2; /* Quadratic attenuation */ + D3DVALUE dvTheta; /* Inner angle of spotlight cone */ + D3DVALUE dvPhi; /* Outer angle of spotlight cone */ +} D3DLIGHT, *LPD3DLIGHT; + +typedef struct _D3DLIGHTDATA { + DWORD dwSize; + LPD3DLIGHTINGELEMENT lpIn; /* Input positions and normals */ + DWORD dwInSize; /* Stride of input elements */ + LPD3DTLVERTEX lpOut; /* Output colors */ + DWORD dwOutSize; /* Stride of output colors */ +} D3DLIGHTDATA, *LPD3DLIGHTDATA; + +typedef enum _D3DCOLORMODEL { + D3DCOLOR_MONO = 1, + D3DCOLOR_RGB = 2, +} D3DCOLORMODEL; + +/* + * Options for clearing + */ +#define D3DCLEAR_TARGET 0x00000001l /* Clear target surface */ +#define D3DCLEAR_ZBUFFER 0x00000002l /* Clear target z buffer */ + +/* + * Execute buffers are allocated via Direct3D. These buffers may then + * be filled by the application with instructions to execute along with + * vertex data. + */ + +/* + * Supported op codes for execute instructions. + */ +typedef enum _D3DOPCODE { + D3DOP_POINT = 1, + D3DOP_LINE = 2, + D3DOP_TRIANGLE = 3, + D3DOP_MATRIXLOAD = 4, + D3DOP_MATRIXMULTIPLY = 5, + D3DOP_STATETRANSFORM = 6, + D3DOP_STATELIGHT = 7, + D3DOP_STATERENDER = 8, + D3DOP_PROCESSVERTICES = 9, + D3DOP_TEXTURELOAD = 10, + D3DOP_EXIT = 11, + D3DOP_BRANCHFORWARD = 12, + D3DOP_SPAN = 13, + D3DOP_SETSTATUS = 14, +} D3DOPCODE; + +typedef struct _D3DINSTRUCTION { + BYTE bOpcode; /* Instruction opcode */ + BYTE bSize; /* Size of each instruction data unit */ + WORD wCount; /* Count of instruction data units to follow */ +} D3DINSTRUCTION, *LPD3DINSTRUCTION; + +/* + * Structure for texture loads + */ +typedef struct _D3DTEXTURELOAD { + D3DTEXTUREHANDLE hDestTexture; + D3DTEXTUREHANDLE hSrcTexture; +} D3DTEXTURELOAD, *LPD3DTEXTURELOAD; + +/* + * Structure for picking + */ +typedef struct _D3DPICKRECORD { + BYTE bOpcode; + BYTE bPad; + DWORD dwOffset; + D3DVALUE dvZ; +} D3DPICKRECORD, *LPD3DPICKRECORD; + +/* + * The following defines the rendering states which can be set in the + * execute buffer. + */ + +typedef enum _D3DSHADEMODE { + D3DSHADE_FLAT = 1, + D3DSHADE_GOURAUD = 2, + D3DSHADE_PHONG = 3, +} D3DSHADEMODE; + +typedef enum _D3DFILLMODE { + D3DFILL_POINT = 1, + D3DFILL_WIREFRAME = 2, + D3DFILL_SOLID = 3, +} D3DFILLMODE; + +typedef struct _D3DLINEPATTERN { + WORD wRepeatFactor; + WORD wLinePattern; +} D3DLINEPATTERN; + +typedef enum _D3DTEXTUREFILTER { + D3DFILTER_NEAREST = 1, + D3DFILTER_LINEAR = 2, + D3DFILTER_MIPNEAREST = 3, + D3DFILTER_MIPLINEAR = 4, + D3DFILTER_LINEARMIPNEAREST = 5, + D3DFILTER_LINEARMIPLINEAR = 6, +} D3DTEXTUREFILTER; + +typedef enum _D3DBLEND { + D3DBLEND_ZERO = 1, + D3DBLEND_ONE = 2, + D3DBLEND_SRCCOLOR = 3, + D3DBLEND_INVSRCCOLOR = 4, + D3DBLEND_SRCALPHA = 5, + D3DBLEND_INVSRCALPHA = 6, + D3DBLEND_DESTALPHA = 7, + D3DBLEND_INVDESTALPHA = 8, + D3DBLEND_DESTCOLOR = 9, + D3DBLEND_INVDESTCOLOR = 10, + D3DBLEND_SRCALPHASAT = 11, + D3DBLEND_BOTHSRCALPHA = 12, + D3DBLEND_BOTHINVSRCALPHA = 13, +} D3DBLEND; + +typedef enum _D3DTEXTUREBLEND { + D3DTBLEND_DECAL = 1, + D3DTBLEND_MODULATE = 2, + D3DTBLEND_DECALALPHA = 3, + D3DTBLEND_MODULATEALPHA = 4, + D3DTBLEND_DECALMASK = 5, + D3DTBLEND_MODULATEMASK = 6, + D3DTBLEND_COPY = 7, +} D3DTEXTUREBLEND; + +typedef enum _D3DTEXTUREADDRESS { + D3DTADDRESS_WRAP = 1, + D3DTADDRESS_MIRROR = 2, + D3DTADDRESS_CLAMP = 3, +} D3DTEXTUREADDRESS; + +typedef enum _D3DCULL { + D3DCULL_NONE = 1, + D3DCULL_CW = 2, + D3DCULL_CCW = 3, +} D3DCULL; + +typedef enum _D3DCMPFUNC { + D3DCMP_NEVER = 1, + D3DCMP_LESS = 2, + D3DCMP_EQUAL = 3, + D3DCMP_LESSEQUAL = 4, + D3DCMP_GREATER = 5, + D3DCMP_NOTEQUAL = 6, + D3DCMP_GREATEREQUAL = 7, + D3DCMP_ALWAYS = 8, +} D3DCMPFUNC; + +typedef enum _D3DFOGMODE { + D3DFOG_NONE = 0, + D3DFOG_EXP = 1, + D3DFOG_EXP2 = 2, + D3DFOG_LINEAR = 3 +} D3DFOGMODE; + +/* + * Amount to add to a state to generate the override for that state. + */ +#define D3DSTATE_OVERRIDE_BIAS 256 + +/* + * A state which sets the override flag for the specified state type. + */ +#define D3DSTATE_OVERRIDE(type) ((DWORD) (type) + D3DSTATE_OVERRIDE_BIAS) + +typedef enum _D3DTRANSFORMSTATETYPE { + D3DTRANSFORMSTATE_WORLD = 1, + D3DTRANSFORMSTATE_VIEW = 2, + D3DTRANSFORMSTATE_PROJECTION = 3, +} D3DTRANSFORMSTATETYPE; + +typedef enum _D3DLIGHTSTATETYPE { + D3DLIGHTSTATE_MATERIAL = 1, + D3DLIGHTSTATE_AMBIENT = 2, + D3DLIGHTSTATE_COLORMODEL = 3, + D3DLIGHTSTATE_FOGMODE = 4, + D3DLIGHTSTATE_FOGSTART = 5, + D3DLIGHTSTATE_FOGEND = 6, + D3DLIGHTSTATE_FOGDENSITY = 7, +} D3DLIGHTSTATETYPE; + +typedef enum _D3DRENDERSTATETYPE { + D3DRENDERSTATE_TEXTUREHANDLE = 1, /* Texture handle */ + D3DRENDERSTATE_ANTIALIAS = 2, /* Antialiasing prim edges */ + D3DRENDERSTATE_TEXTUREADDRESS = 3, /* D3DTEXTUREADDRESS */ + D3DRENDERSTATE_TEXTUREPERSPECTIVE = 4, /* TRUE for perspective correction */ + D3DRENDERSTATE_WRAPU = 5, /* TRUE for wrapping in u */ + D3DRENDERSTATE_WRAPV = 6, /* TRUE for wrapping in v */ + D3DRENDERSTATE_ZENABLE = 7, /* TRUE to enable z test */ + D3DRENDERSTATE_FILLMODE = 8, /* D3DFILL_MODE */ + D3DRENDERSTATE_SHADEMODE = 9, /* D3DSHADEMODE */ + D3DRENDERSTATE_LINEPATTERN = 10, /* D3DLINEPATTERN */ + D3DRENDERSTATE_MONOENABLE = 11, /* TRUE to enable mono rasterization */ + D3DRENDERSTATE_ROP2 = 12, /* ROP2 */ + D3DRENDERSTATE_PLANEMASK = 13, /* DWORD physical plane mask */ + D3DRENDERSTATE_ZWRITEENABLE = 14, /* TRUE to enable z writes */ + D3DRENDERSTATE_ALPHATESTENABLE = 15, /* TRUE to enable alpha tests */ + D3DRENDERSTATE_LASTPIXEL = 16, /* TRUE for last-pixel on lines */ + D3DRENDERSTATE_TEXTUREMAG = 17, /* D3DTEXTUREFILTER */ + D3DRENDERSTATE_TEXTUREMIN = 18, /* D3DTEXTUREFILTER */ + D3DRENDERSTATE_SRCBLEND = 19, /* D3DBLEND */ + D3DRENDERSTATE_DESTBLEND = 20, /* D3DBLEND */ + D3DRENDERSTATE_TEXTUREMAPBLEND = 21, /* D3DTEXTUREBLEND */ + D3DRENDERSTATE_CULLMODE = 22, /* D3DCULL */ + D3DRENDERSTATE_ZFUNC = 23, /* D3DCMPFUNC */ + D3DRENDERSTATE_ALPHAREF = 24, /* D3DFIXED */ + D3DRENDERSTATE_ALPHAFUNC = 25, /* D3DCMPFUNC */ + D3DRENDERSTATE_DITHERENABLE = 26, /* TRUE to enable dithering */ + D3DRENDERSTATE_BLENDENABLE = 27, /* TRUE to enable alpha blending */ + D3DRENDERSTATE_FOGENABLE = 28, /* TRUE to enable fog */ + D3DRENDERSTATE_SPECULARENABLE = 29, /* TRUE to enable specular */ + D3DRENDERSTATE_ZVISIBLE = 30, /* TRUE to enable z checking */ + D3DRENDERSTATE_SUBPIXEL = 31, /* TRUE to enable subpixel correction */ + D3DRENDERSTATE_SUBPIXELX = 32, /* TRUE to enable correction in X only */ + D3DRENDERSTATE_STIPPLEDALPHA = 33, /* TRUE to enable stippled alpha */ + D3DRENDERSTATE_FOGCOLOR = 34, /* D3DCOLOR */ + D3DRENDERSTATE_FOGTABLEMODE = 35, /* D3DFOGMODE */ + D3DRENDERSTATE_FOGTABLESTART = 36, /* Fog table start */ + D3DRENDERSTATE_FOGTABLEEND = 37, /* Fog table end */ + D3DRENDERSTATE_FOGTABLEDENSITY = 38, /* Fog table density */ + D3DRENDERSTATE_STIPPLEENABLE = 39, /* TRUE to enable stippling */ + D3DRENDERSTATE_STIPPLEPATTERN00 = 64, /* Stipple pattern 01... */ + D3DRENDERSTATE_STIPPLEPATTERN01 = 65, + D3DRENDERSTATE_STIPPLEPATTERN02 = 66, + D3DRENDERSTATE_STIPPLEPATTERN03 = 67, + D3DRENDERSTATE_STIPPLEPATTERN04 = 68, + D3DRENDERSTATE_STIPPLEPATTERN05 = 69, + D3DRENDERSTATE_STIPPLEPATTERN06 = 70, + D3DRENDERSTATE_STIPPLEPATTERN07 = 71, + D3DRENDERSTATE_STIPPLEPATTERN08 = 72, + D3DRENDERSTATE_STIPPLEPATTERN09 = 73, + D3DRENDERSTATE_STIPPLEPATTERN10 = 74, + D3DRENDERSTATE_STIPPLEPATTERN11 = 75, + D3DRENDERSTATE_STIPPLEPATTERN12 = 76, + D3DRENDERSTATE_STIPPLEPATTERN13 = 77, + D3DRENDERSTATE_STIPPLEPATTERN14 = 78, + D3DRENDERSTATE_STIPPLEPATTERN15 = 79, + D3DRENDERSTATE_STIPPLEPATTERN16 = 80, + D3DRENDERSTATE_STIPPLEPATTERN17 = 81, + D3DRENDERSTATE_STIPPLEPATTERN18 = 82, + D3DRENDERSTATE_STIPPLEPATTERN19 = 83, + D3DRENDERSTATE_STIPPLEPATTERN20 = 84, + D3DRENDERSTATE_STIPPLEPATTERN21 = 85, + D3DRENDERSTATE_STIPPLEPATTERN22 = 86, + D3DRENDERSTATE_STIPPLEPATTERN23 = 87, + D3DRENDERSTATE_STIPPLEPATTERN24 = 88, + D3DRENDERSTATE_STIPPLEPATTERN25 = 89, + D3DRENDERSTATE_STIPPLEPATTERN26 = 90, + D3DRENDERSTATE_STIPPLEPATTERN27 = 91, + D3DRENDERSTATE_STIPPLEPATTERN28 = 92, + D3DRENDERSTATE_STIPPLEPATTERN29 = 93, + D3DRENDERSTATE_STIPPLEPATTERN30 = 94, + D3DRENDERSTATE_STIPPLEPATTERN31 = 95, +} D3DRENDERSTATETYPE; + +#define D3DRENDERSTATE_STIPPLEPATTERN(y) (D3DRENDERSTATE_STIPPLEPATTERN00 + (y)) + +typedef struct _D3DSTATE { + union { + D3DTRANSFORMSTATETYPE dtstTransformStateType; + D3DLIGHTSTATETYPE dlstLightStateType; + D3DRENDERSTATETYPE drstRenderStateType; + }; + union { + DWORD dwArg[1]; + D3DVALUE dvArg[1]; + }; +} D3DSTATE, *LPD3DSTATE; + +/* + * Operation used to load matrices + * hDstMat = hSrcMat + */ +typedef struct _D3DMATRIXLOAD { + D3DMATRIXHANDLE hDestMatrix; /* Destination matrix */ + D3DMATRIXHANDLE hSrcMatrix; /* Source matrix */ +} D3DMATRIXLOAD, *LPD3DMATRIXLOAD; + +/* + * Operation used to multiply matrices + * hDstMat = hSrcMat1 * hSrcMat2 + */ +typedef struct _D3DMATRIXMULTIPLY { + D3DMATRIXHANDLE hDestMatrix; /* Destination matrix */ + D3DMATRIXHANDLE hSrcMatrix1; /* First source matrix */ + D3DMATRIXHANDLE hSrcMatrix2; /* Second source matrix */ +} D3DMATRIXMULTIPLY, *LPD3DMATRIXMULTIPLY; + +/* + * Operation used to transform and light vertices. + */ +typedef struct _D3DPROCESSVERTICES { + DWORD dwFlags; /* Do we transform or light or just copy? */ + WORD wStart; /* Index to first vertex in source */ + WORD wDest; /* Index to first vertex in local buffer */ + DWORD dwCount; /* Number of vertices to be processed */ + DWORD dwReserved; /* Must be zero */ +} D3DPROCESSVERTICES, *LPD3DPROCESSVERTICES; + +#define D3DPROCESSVERTICES_TRANSFORMLIGHT 0x00000000L +#define D3DPROCESSVERTICES_TRANSFORM 0x00000001L +#define D3DPROCESSVERTICES_COPY 0x00000002L +#define D3DPROCESSVERTICES_OPMASK 0x00000007L + +#define D3DPROCESSVERTICES_UPDATEEXTENTS 0x00000008L +#define D3DPROCESSVERTICES_NOCOLOR 0x00000010L + + +/* + * Triangle flags + */ + +/* + * Tri strip and fan flags. + * START loads all three vertices + * EVEN and ODD load just v3 with even or odd culling + * START_FLAT contains a count from 0 to 29 that allows the + * whole strip or fan to be culled in one hit. + * e.g. for a quad len = 1 + */ +#define D3DTRIFLAG_START 0x00000000L +#define D3DTRIFLAG_STARTFLAT(len) (len) /* 0 < len < 30 */ +#define D3DTRIFLAG_ODD 0x0000001eL +#define D3DTRIFLAG_EVEN 0x0000001fL + +/* + * Triangle edge flags + * enable edges for wireframe or antialiasing + */ +#define D3DTRIFLAG_EDGEENABLE1 0x00000100L /* v0-v1 edge */ +#define D3DTRIFLAG_EDGEENABLE2 0x00000200L /* v1-v2 edge */ +#define D3DTRIFLAG_EDGEENABLE3 0x00000400L /* v2-v0 edge */ +#define D3DTRIFLAG_EDGEENABLETRIANGLE \ + (D3DTRIFLAG_EDGEENABLE1 | D3DTRIFLAG_EDGEENABLE2 | D3DTRIFLAG_EDGEENABLE3) + +/* + * Primitive structures and related defines. Vertex offsets are to types + * D3DVERTEX, D3DLVERTEX, or D3DTLVERTEX. + */ + +/* + * Triangle list primitive structure + */ +typedef struct _D3DTRIANGLE { + union { + WORD v1; /* Vertex indices */ + WORD wV1; + }; + union { + WORD v2; + WORD wV2; + }; + union { + WORD v3; + WORD wV3; + }; + WORD wFlags; /* Edge (and other) flags */ +} D3DTRIANGLE, *LPD3DTRIANGLE; + +/* + * Line strip structure. + * The instruction count - 1 defines the number of line segments. + */ +typedef struct _D3DLINE { + union { + WORD v1; /* Vertex indices */ + WORD wV1; + }; + union { + WORD v2; + WORD wV2; + }; +} D3DLINE, *LPD3DLINE; + +/* + * Span structure + * Spans join a list of points with the same y value. + * If the y value changes, a new span is started. + */ +typedef struct _D3DSPAN { + WORD wCount; /* Number of spans */ + WORD wFirst; /* Index to first vertex */ +} D3DSPAN, *LPD3DSPAN; + +/* + * Point structure + */ +typedef struct _D3DPOINT { + WORD wCount; /* number of points */ + WORD wFirst; /* index to first vertex */ +} D3DPOINT, *LPD3DPOINT; + + +/* + * Forward branch structure. + * Mask is logically anded with the driver status mask + * if the result equals 'value', the branch is taken. + */ +typedef struct _D3DBRANCH { + DWORD dwMask; /* Bitmask against D3D status */ + DWORD dwValue; + BOOL bNegate; /* TRUE to negate comparison */ + DWORD dwOffset; /* How far to branch forward (0 for exit)*/ +} D3DBRANCH, *LPD3DBRANCH; + +/* + * Status used for set status instruction. + * The D3D status is initialised on device creation + * and is modified by all execute calls. + */ +typedef struct _D3DSTATUS { + DWORD dwFlags; /* Do we set extents or status */ + DWORD dwStatus; /* D3D status */ + D3DRECT drExtent; +} D3DSTATUS, *LPD3DSTATUS; + +#define D3DSETSTATUS_STATUS 0x00000001L +#define D3DSETSTATUS_EXTENTS 0x00000002L +#define D3DSETSTATUS_ALL (D3DSETSTATUS_STATUS | D3DSETSTATUS_EXTENTS) + +/* + * Statistics structure + */ +typedef struct _D3DSTATS { + DWORD dwSize; + DWORD dwTrianglesDrawn; + DWORD dwLinesDrawn; + DWORD dwPointsDrawn; + DWORD dwSpansDrawn; + DWORD dwVerticesProcessed; +} D3DSTATS, *LPD3DSTATS; + +/* + * Execute options. + * When calling using D3DEXECUTE_UNCLIPPED all the primitives + * inside the buffer must be contained within the viewport. + */ +#define D3DEXECUTE_CLIPPED 0x00000001l +#define D3DEXECUTE_UNCLIPPED 0x00000002l + +typedef struct _D3DEXECUTEDATA { + DWORD dwSize; + DWORD dwVertexOffset; + DWORD dwVertexCount; + DWORD dwInstructionOffset; + DWORD dwInstructionLength; + DWORD dwHVertexOffset; + D3DSTATUS dsStatus; /* Status after execute */ +} D3DEXECUTEDATA, *LPD3DEXECUTEDATA; + +/* + * Palette flags. + * This are or'ed with the peFlags in the PALETTEENTRYs passed to DirectDraw. + */ +#define D3DPAL_FREE 0x00 /* Renderer may use this entry freely */ +#define D3DPAL_READONLY 0x40 /* Renderer may not set this entry */ +#define D3DPAL_RESERVED 0x80 /* Renderer may not use this entry */ + +#if defined(__cplusplus) +}; +#endif + +#pragma pack() + +#endif /* _D3DTYPES_H_ */ diff --git a/src/D523BD.ZIP b/src/D523BD.ZIP new file mode 100644 index 0000000..22a144f Binary files /dev/null and b/src/D523BD.ZIP differ diff --git a/src/D523BF.ZIP b/src/D523BF.ZIP new file mode 100644 index 0000000..d44483f Binary files /dev/null and b/src/D523BF.ZIP differ diff --git a/src/DDRAW.H b/src/DDRAW.H new file mode 100644 index 0000000..abb9104 --- /dev/null +++ b/src/DDRAW.H @@ -0,0 +1,3102 @@ +/*==========================================================================; + * + * Copyright (C) 1994-1996 Microsoft Corporation. All Rights Reserved. + * + * File: ddraw.h + * Content: DirectDraw include file + * + ***************************************************************************/ + +#ifndef __DDRAW_INCLUDED__ +#define __DDRAW_INCLUDED__ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#define COM_NO_WINDOWS_H +#include +#else +#define IUnknown void +#define CO_E_NOTINITIALIZED 0x800401F0L +#endif + +#define _FACDD 0x876 +#define MAKE_DDHRESULT( code ) MAKE_HRESULT( 1, _FACDD, code ) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * GUIDS used by DirectDraw objects + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +DEFINE_GUID( CLSID_DirectDraw, 0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 ); +DEFINE_GUID( CLSID_DirectDrawClipper, 0x593817A0,0x7DB3,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xb9,0x33,0x56 ); +DEFINE_GUID( IID_IDirectDraw, 0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); +DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 ); +DEFINE_GUID( IID_IDirectDrawSurface, 0x6C14DB81,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); +DEFINE_GUID( IID_IDirectDrawSurface2, 0x57805885,0x6eec,0x11cf,0x94,0x41,0xa8,0x23,0x03,0xc1,0x0e,0x27 ); + +DEFINE_GUID( IID_IDirectDrawPalette, 0x6C14DB84,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); +DEFINE_GUID( IID_IDirectDrawClipper, 0x6C14DB85,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 ); + +#endif + +/*============================================================================ + * + * DirectDraw Structures + * + * Various structures used to invoke DirectDraw. + * + *==========================================================================*/ + +struct IDirectDraw; +struct IDirectDrawSurface; +struct IDirectDrawPalette; +struct IDirectDrawClipper; + +typedef struct IDirectDraw FAR *LPDIRECTDRAW; +typedef struct IDirectDraw2 FAR *LPDIRECTDRAW2; +typedef struct IDirectDrawSurface FAR *LPDIRECTDRAWSURFACE; +typedef struct IDirectDrawSurface2 FAR *LPDIRECTDRAWSURFACE2; + +typedef struct IDirectDrawPalette FAR *LPDIRECTDRAWPALETTE; +typedef struct IDirectDrawClipper FAR *LPDIRECTDRAWCLIPPER; + +typedef struct _DDFXROP FAR *LPDDFXROP; +typedef struct _DDSURFACEDESC FAR *LPDDSURFACEDESC; + +/* + * API's + */ +#if (defined (WIN32) || defined( _WIN32 ) ) && !defined( _NO_COM ) +//#if defined( _WIN32 ) && !defined( _NO_ENUM ) + typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKA)(GUID FAR *, LPSTR, LPSTR, LPVOID); + typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKW)(GUID FAR *, LPWSTR, LPWSTR, LPVOID); + extern HRESULT WINAPI DirectDrawEnumerateW( LPDDENUMCALLBACKW lpCallback, LPVOID lpContext ); + extern HRESULT WINAPI DirectDrawEnumerateA( LPDDENUMCALLBACKA lpCallback, LPVOID lpContext ); + #ifdef UNICODE + typedef LPDDENUMCALLBACKW LPDDENUMCALLBACK; + #define DirectDrawEnumerate DirectDrawEnumerateW + #else + typedef LPDDENUMCALLBACKA LPDDENUMCALLBACK; + #define DirectDrawEnumerate DirectDrawEnumerateA + #endif + extern HRESULT WINAPI DirectDrawCreate( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter ); + extern HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter ); + #ifdef WINNT + //This is the user-mode entry stub to the kernel mode procedure. + extern HRESULT NtDirectDrawCreate( GUID FAR *lpGUID, HANDLE *lplpDD, IUnknown FAR *pUnkOuter ); + #endif +#endif + +#define REGSTR_KEY_DDHW_DESCRIPTION "Description" +#define REGSTR_KEY_DDHW_DRIVERNAME "DriverName" +#define REGSTR_PATH_DDHW "Hardware\\DirectDrawDrivers" + +#define DDCREATE_HARDWAREONLY 0x00000001l +#define DDCREATE_EMULATIONONLY 0x00000002l + +#ifdef WINNT +typedef long HRESULT; +#endif + +//#ifndef WINNT +typedef HRESULT (FAR PASCAL * LPDDENUMMODESCALLBACK)(LPDDSURFACEDESC, LPVOID); +typedef HRESULT (FAR PASCAL * LPDDENUMSURFACESCALLBACK)(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC, LPVOID); +//#endif +/* + * DDCOLORKEY + */ +typedef struct _DDCOLORKEY +{ + DWORD dwColorSpaceLowValue; // low boundary of color space that is to + // be treated as Color Key, inclusive + DWORD dwColorSpaceHighValue; // high boundary of color space that is + // to be treated as Color Key, inclusive +} DDCOLORKEY; + +typedef DDCOLORKEY FAR* LPDDCOLORKEY; + +/* + * DDBLTFX + * Used to pass override information to the DIRECTDRAWSURFACE callback Blt. + */ +typedef struct _DDBLTFX +{ + DWORD dwSize; // size of structure + DWORD dwDDFX; // FX operations + DWORD dwROP; // Win32 raster operations + DWORD dwDDROP; // Raster operations new for DirectDraw + DWORD dwRotationAngle; // Rotation angle for blt + DWORD dwZBufferOpCode; // ZBuffer compares + DWORD dwZBufferLow; // Low limit of Z buffer + DWORD dwZBufferHigh; // High limit of Z buffer + DWORD dwZBufferBaseDest; // Destination base value + DWORD dwZDestConstBitDepth; // Bit depth used to specify Z constant for destination + union + { + DWORD dwZDestConst; // Constant to use as Z buffer for dest + LPDIRECTDRAWSURFACE lpDDSZBufferDest; // Surface to use as Z buffer for dest + }; + DWORD dwZSrcConstBitDepth; // Bit depth used to specify Z constant for source + union + { + DWORD dwZSrcConst; // Constant to use as Z buffer for src + LPDIRECTDRAWSURFACE lpDDSZBufferSrc; // Surface to use as Z buffer for src + }; + DWORD dwAlphaEdgeBlendBitDepth; // Bit depth used to specify constant for alpha edge blend + DWORD dwAlphaEdgeBlend; // Alpha for edge blending + DWORD dwReserved; + DWORD dwAlphaDestConstBitDepth; // Bit depth used to specify alpha constant for destination + union + { + DWORD dwAlphaDestConst; // Constant to use as Alpha Channel + LPDIRECTDRAWSURFACE lpDDSAlphaDest; // Surface to use as Alpha Channel + }; + DWORD dwAlphaSrcConstBitDepth; // Bit depth used to specify alpha constant for source + union + { + DWORD dwAlphaSrcConst; // Constant to use as Alpha Channel + LPDIRECTDRAWSURFACE lpDDSAlphaSrc; // Surface to use as Alpha Channel + }; + union + { + DWORD dwFillColor; // color in RGB or Palettized + DWORD dwFillDepth; // depth value for z-buffer + LPDIRECTDRAWSURFACE lpDDSPattern; // Surface to use as pattern + }; + DDCOLORKEY ddckDestColorkey; // DestColorkey override + DDCOLORKEY ddckSrcColorkey; // SrcColorkey override +} DDBLTFX; + +typedef DDBLTFX FAR* LPDDBLTFX; + + +/* + * DDSCAPS + */ +typedef struct _DDSCAPS +{ + DWORD dwCaps; // capabilities of surface wanted +} DDSCAPS; + +typedef DDSCAPS FAR* LPDDSCAPS; + +/* + * DDCAPS + */ +#define DD_ROP_SPACE (256/32) // space required to store ROP array + +typedef struct _DDCAPS +{ + DWORD dwSize; // size of the DDDRIVERCAPS structure + DWORD dwCaps; // driver specific capabilities + DWORD dwCaps2; // more driver specific capabilites + DWORD dwCKeyCaps; // color key capabilities of the surface + DWORD dwFXCaps; // driver specific stretching and effects capabilites + DWORD dwFXAlphaCaps; // alpha driver specific capabilities + DWORD dwPalCaps; // palette capabilities + DWORD dwSVCaps; // stereo vision capabilities + DWORD dwAlphaBltConstBitDepths; // DDBD_2,4,8 + DWORD dwAlphaBltPixelBitDepths; // DDBD_1,2,4,8 + DWORD dwAlphaBltSurfaceBitDepths; // DDBD_1,2,4,8 + DWORD dwAlphaOverlayConstBitDepths; // DDBD_2,4,8 + DWORD dwAlphaOverlayPixelBitDepths; // DDBD_1,2,4,8 + DWORD dwAlphaOverlaySurfaceBitDepths; // DDBD_1,2,4,8 + DWORD dwZBufferBitDepths; // DDBD_8,16,24,32 + DWORD dwVidMemTotal; // total amount of video memory + DWORD dwVidMemFree; // amount of free video memory + DWORD dwMaxVisibleOverlays; // maximum number of visible overlays + DWORD dwCurrVisibleOverlays; // current number of visible overlays + DWORD dwNumFourCCCodes; // number of four cc codes + DWORD dwAlignBoundarySrc; // source rectangle alignment + DWORD dwAlignSizeSrc; // source rectangle byte size + DWORD dwAlignBoundaryDest; // dest rectangle alignment + DWORD dwAlignSizeDest; // dest rectangle byte size + DWORD dwAlignStrideAlign; // stride alignment + DWORD dwRops[DD_ROP_SPACE]; // ROPS supported + DDSCAPS ddsCaps; // DDSCAPS structure has all the general capabilities + DWORD dwMinOverlayStretch; // minimum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMaxOverlayStretch; // maximum overlay stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMinLiveVideoStretch; // minimum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMaxLiveVideoStretch; // maximum live video stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMinHwCodecStretch; // minimum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwMaxHwCodecStretch; // maximum hardware codec stretch factor multiplied by 1000, eg 1000 == 1.0, 1300 == 1.3 + DWORD dwReserved1; // reserved + DWORD dwReserved2; // reserved + DWORD dwReserved3; // reserved + DWORD dwSVBCaps; // driver specific capabilities for System->Vmem blts + DWORD dwSVBCKeyCaps; // driver color key capabilities for System->Vmem blts + DWORD dwSVBFXCaps; // driver FX capabilities for System->Vmem blts + DWORD dwSVBRops[DD_ROP_SPACE];// ROPS supported for System->Vmem blts + DWORD dwVSBCaps; // driver specific capabilities for Vmem->System blts + DWORD dwVSBCKeyCaps; // driver color key capabilities for Vmem->System blts + DWORD dwVSBFXCaps; // driver FX capabilities for Vmem->System blts + DWORD dwVSBRops[DD_ROP_SPACE];// ROPS supported for Vmem->System blts + DWORD dwSSBCaps; // driver specific capabilities for System->System blts + DWORD dwSSBCKeyCaps; // driver color key capabilities for System->System blts + DWORD dwSSBFXCaps; // driver FX capabilities for System->System blts + DWORD dwSSBRops[DD_ROP_SPACE];// ROPS supported for System->System blts + DWORD dwReserved4; // reserved + DWORD dwReserved5; // reserved + DWORD dwReserved6; // reserved +} DDCAPS; + +typedef DDCAPS FAR* LPDDCAPS; + + + +/* + * DDPIXELFORMAT + */ +typedef struct _DDPIXELFORMAT +{ + DWORD dwSize; // size of structure + DWORD dwFlags; // pixel format flags + DWORD dwFourCC; // (FOURCC code) + union + { + DWORD dwRGBBitCount; // how many bits per pixel (BD_4,8,16,24,32) + DWORD dwYUVBitCount; // how many bits per pixel (BD_4,8,16,24,32) + DWORD dwZBufferBitDepth; // how many bits for z buffers (BD_8,16,24,32) + DWORD dwAlphaBitDepth; // how many bits for alpha channels (BD_1,2,4,8) + }; + union + { + DWORD dwRBitMask; // mask for red bit + DWORD dwYBitMask; // mask for Y bits + }; + union + { + DWORD dwGBitMask; // mask for green bits + DWORD dwUBitMask; // mask for U bits + }; + union + { + DWORD dwBBitMask; // mask for blue bits + DWORD dwVBitMask; // mask for V bits + }; + union + { + DWORD dwRGBAlphaBitMask; // mask for alpha channel + DWORD dwYUVAlphaBitMask; // mask for alpha channel + }; +} DDPIXELFORMAT; + +typedef DDPIXELFORMAT FAR* LPDDPIXELFORMAT; + +/* + * DDOVERLAYFX + */ +typedef struct _DDOVERLAYFX +{ + DWORD dwSize; // size of structure + DWORD dwAlphaEdgeBlendBitDepth; // Bit depth used to specify constant for alpha edge blend + DWORD dwAlphaEdgeBlend; // Constant to use as alpha for edge blend + DWORD dwReserved; + DWORD dwAlphaDestConstBitDepth; // Bit depth used to specify alpha constant for destination + union + { + DWORD dwAlphaDestConst; // Constant to use as alpha channel for dest + LPDIRECTDRAWSURFACE lpDDSAlphaDest; // Surface to use as alpha channel for dest + }; + DWORD dwAlphaSrcConstBitDepth; // Bit depth used to specify alpha constant for source + union + { + DWORD dwAlphaSrcConst; // Constant to use as alpha channel for src + LPDIRECTDRAWSURFACE lpDDSAlphaSrc; // Surface to use as alpha channel for src + }; + DDCOLORKEY dckDestColorkey; // DestColorkey override + DDCOLORKEY dckSrcColorkey; // DestColorkey override + DWORD dwDDFX; // Overlay FX + DWORD dwFlags; // flags +} DDOVERLAYFX; + +typedef DDOVERLAYFX FAR *LPDDOVERLAYFX; + +/* + * DDBLTBATCH: BltBatch entry structure + */ +typedef struct _DDBLTBATCH +{ + LPRECT lprDest; + LPDIRECTDRAWSURFACE lpDDSSrc; + LPRECT lprSrc; + DWORD dwFlags; + LPDDBLTFX lpDDBltFx; +} DDBLTBATCH; + +typedef DDBLTBATCH FAR * LPDDBLTBATCH; + +/* + * callbacks + */ +typedef DWORD (FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper, HWND hWnd, DWORD code, LPVOID lpContext ); +#ifdef STREAMING +typedef DWORD (FAR PASCAL *LPSURFACESTREAMINGCALLBACK)(DWORD); +#endif + + +/* + * INTERACES FOLLOW: + * IDirectDraw + * IDirectDrawClipper + * IDirectDrawPalette + * IDirectDrawSurface + */ + +/* + * IDirectDraw + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDraw +DECLARE_INTERFACE_( IDirectDraw, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDraw methods ***/ + STDMETHOD(Compact)(THIS) PURE; + STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE; + STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE; + STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE; + STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE; + STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE; + STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE; + STDMETHOD(FlipToGDISurface)(THIS) PURE; + STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE; + STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE; + STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD, LPDWORD ) PURE; + STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE; + STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE; + STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE; + STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE; + STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE; + STDMETHOD(RestoreDisplayMode)(THIS) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE; + STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD) PURE; + STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDraw_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirectDraw_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDraw_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDraw_Compact(p) (p)->lpVtbl->Compact(p) +#define IDirectDraw_CreateClipper(p, a, b, c) (p)->lpVtbl->CreateClipper(p, a, b, c) +#define IDirectDraw_CreatePalette(p, a, b, c, d) (p)->lpVtbl->CreatePalette(p, a, b, c, d) +#define IDirectDraw_CreateSurface(p, a, b, c) (p)->lpVtbl->CreateSurface(p, a, b, c) +#define IDirectDraw_DuplicateSurface(p, a, b) (p)->lpVtbl->DuplicateSurface(p, a, b) +#define IDirectDraw_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d) +#define IDirectDraw_EnumSurfaces(p, a, b, c, d) (p)->lpVtbl->EnumSurfaces(p, a, b, c, d) +#define IDirectDraw_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) +#define IDirectDraw_GetCaps(p, a, b) (p)->lpVtbl->GetCaps(p, a, b) +#define IDirectDraw_GetDisplayMode(p, a) (p)->lpVtbl->GetDisplayMode(p, a) +#define IDirectDraw_GetFourCCCodes(p, a, b) (p)->lpVtbl->GetFourCCCodes(p, a, b) +#define IDirectDraw_GetGDISurface(p, a) (p)->lpVtbl->GetGDISurface(p, a) +#define IDirectDraw_GetMonitorFrequency(p, a) (p)->lpVtbl->GetMonitorFrequency(p, a) +#define IDirectDraw_GetScanLine(p, a) (p)->lpVtbl->GetScanLine(p, a) +#define IDirectDraw_GetVerticalBlankStatus(p, a) (p)->lpVtbl->GetVerticalBlankStatus(p, a) +#define IDirectDraw_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) +#define IDirectDraw_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) +#define IDirectDraw_SetCooperativeLevel(p, a, b) (p)->lpVtbl->SetCooperativeLevel(p, a, b) +#define IDirectDraw_SetDisplayMode(p, a, b, c) (p)->lpVtbl->SetDisplayMode(p, a, b, c) +#define IDirectDraw_WaitForVerticalBlank(p, a, b) (p)->lpVtbl->WaitForVerticalBlank(p, a, b) +#endif + +#endif + +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDraw2 +DECLARE_INTERFACE_( IDirectDraw2, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDraw methods ***/ + STDMETHOD(Compact)(THIS) PURE; + STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE; + STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE; + STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, IUnknown FAR *) PURE; + STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE FAR * ) PURE; + STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE; + STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE; + STDMETHOD(FlipToGDISurface)(THIS) PURE; + STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE; + STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE; + STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD, LPDWORD ) PURE; + STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE; + STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE; + STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE; + STDMETHOD(GetVerticalBlankStatus)(THIS_ LPBOOL ) PURE; + STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE; + STDMETHOD(RestoreDisplayMode)(THIS) PURE; + STDMETHOD(SetCooperativeLevel)(THIS_ HWND, DWORD) PURE; + STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD,DWORD, DWORD, DWORD) PURE; + STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE ) PURE; + /*** Added in the v2 interface ***/ + STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE; +}; +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDraw2_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirectDraw2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDraw2_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDraw2_Compact(p) (p)->lpVtbl->Compact(p) +#define IDirectDraw2_CreateClipper(p, a, b, c) (p)->lpVtbl->CreateClipper(p, a, b, c) +#define IDirectDraw2_CreatePalette(p, a, b, c, d) (p)->lpVtbl->CreatePalette(p, a, b, c, d) +#define IDirectDraw2_CreateSurface(p, a, b, c) (p)->lpVtbl->CreateSurface(p, a, b, c) +#define IDirectDraw2_DuplicateSurface(p, a, b) (p)->lpVtbl->DuplicateSurface(p, a, b) +#define IDirectDraw2_EnumDisplayModes(p, a, b, c, d) (p)->lpVtbl->EnumDisplayModes(p, a, b, c, d) +#define IDirectDraw2_EnumSurfaces(p, a, b, c, d) (p)->lpVtbl->EnumSurfaces(p, a, b, c, d) +#define IDirectDraw2_FlipToGDISurface(p) (p)->lpVtbl->FlipToGDISurface(p) +#define IDirectDraw2_GetCaps(p, a, b) (p)->lpVtbl->GetCaps(p, a, b) +#define IDirectDraw2_GetDisplayMode(p, a) (p)->lpVtbl->GetDisplayMode(p, a) +#define IDirectDraw2_GetFourCCCodes(p, a, b) (p)->lpVtbl->GetFourCCCodes(p, a, b) +#define IDirectDraw2_GetGDISurface(p, a) (p)->lpVtbl->GetGDISurface(p, a) +#define IDirectDraw2_GetMonitorFrequency(p, a) (p)->lpVtbl->GetMonitorFrequency(p, a) +#define IDirectDraw2_GetScanLine(p, a) (p)->lpVtbl->GetScanLine(p, a) +#define IDirectDraw2_GetVerticalBlankStatus(p, a) (p)->lpVtbl->GetVerticalBlankStatus(p, a) +#define IDirectDraw2_Initialize(p, a) (p)->lpVtbl->Initialize(p, a) +#define IDirectDraw2_RestoreDisplayMode(p) (p)->lpVtbl->RestoreDisplayMode(p) +#define IDirectDraw2_SetCooperativeLevel(p, a, b) (p)->lpVtbl->SetCooperativeLevel(p, a, b) +#define IDirectDraw2_SetDisplayMode(p, a, b, c, d) (p)->lpVtbl->SetDisplayMode(p, a, b, c, d) +#define IDirectDraw2_WaitForVerticalBlank(p, a, b) (p)->lpVtbl->WaitForVerticalBlank(p, a, b) +#define IDirectDraw2_GetAvailableVidMem(p, a, b, c) (p)->lpVtbl->GetAvailableVidMem(p, a, b, c) +#endif + +#endif + +/* + * IDirectDrawPalette + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDrawPalette +DECLARE_INTERFACE_( IDirectDrawPalette, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDrawPalette methods ***/ + STDMETHOD(GetCaps)(THIS_ LPDWORD) PURE; + STDMETHOD(GetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE; + STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE; + STDMETHOD(SetEntries)(THIS_ DWORD,DWORD,DWORD,LPPALETTEENTRY) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDrawPalette_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirectDrawPalette_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDrawPalette_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDrawPalette_GetCaps(p, a) (p)->lpVtbl->GetCaps(p, a) +#define IDirectDrawPalette_GetEntries(p, a, b, c, d) (p)->lpVtbl->GetEntries(p, a, b, c, d) +#define IDirectDrawPalette_Initialize(p, a, b, c) (p)->lpVtbl->Initialize(p, a, b, c) +#define IDirectDrawPalette_SetEntries(p, a, b, c, d) (p)->lpVtbl->SetEntries(p, a, b, c, d) +#endif + +#endif + +/* + * IDirectDrawClipper + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDrawClipper +DECLARE_INTERFACE_( IDirectDrawClipper, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDrawClipper methods ***/ + STDMETHOD(GetClipList)(THIS_ LPRECT, LPRGNDATA, LPDWORD) PURE; + STDMETHOD(GetHWnd)(THIS_ HWND FAR *) PURE; + STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD) PURE; + STDMETHOD(IsClipListChanged)(THIS_ BOOL FAR *) PURE; + STDMETHOD(SetClipList)(THIS_ LPRGNDATA,DWORD) PURE; + STDMETHOD(SetHWnd)(THIS_ DWORD, HWND ) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDrawClipper_QueryInterface(p, a, b) (p)->lpVtbl->QueryInterface(p, a, b) +#define IDirectDrawClipper_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDrawClipper_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDrawClipper_GetClipList(p, a, b, c) (p)->lpVtbl->GetClipList(p, a, b, c) +#define IDirectDrawClipper_GetHWnd(p, a) (p)->lpVtbl->GetHWnd(p, a) +#define IDirectDrawClipper_Initialize(p, a, b) (p)->lpVtbl->Initialize(p, a, b) +#define IDirectDrawClipper_IsClipListChanged(p, a) (p)->lpVtbl->IsClipListChanged(p, a) +#define IDirectDrawClipper_SetClipList(p, a, b) (p)->lpVtbl->SetClipList(p, a, b) +#define IDirectDrawClipper_SetHWnd(p, a, b) (p)->lpVtbl->SetHWnd(p, a, b) +#endif + +#endif + +/* + * IDirectDrawSurface and related interfaces + */ +#if defined( _WIN32 ) && !defined( _NO_COM ) +#undef INTERFACE +#define INTERFACE IDirectDrawSurface +DECLARE_INTERFACE_( IDirectDrawSurface, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDrawSurface methods ***/ + STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE) PURE; + STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE; + STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE, LPRECT,DWORD, LPDDBLTFX) PURE; + STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE; + STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT,DWORD) PURE; + STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE) PURE; + STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE; + STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE; + STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE, DWORD) PURE; + STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE FAR *) PURE; + STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE; + STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE; + STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE; + STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; + STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE; + STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE; + STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE; + STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE; + STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE; + STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE; + STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE; + STDMETHOD(IsLost)(THIS) PURE; + STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE; + STDMETHOD(ReleaseDC)(THIS_ HDC) PURE; + STDMETHOD(Restore)(THIS) PURE; + STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE; + STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; + STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE; + STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE; + STDMETHOD(Unlock)(THIS_ LPVOID) PURE; + STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE,LPRECT,DWORD, LPDDOVERLAYFX) PURE; + STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE; + STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDrawSurface_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectDrawSurface_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDrawSurface_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDrawSurface_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) +#define IDirectDrawSurface_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) +#define IDirectDrawSurface_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) +#define IDirectDrawSurface_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) +#define IDirectDrawSurface_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) +#define IDirectDrawSurface_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) +#define IDirectDrawSurface_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) +#define IDirectDrawSurface_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) +#define IDirectDrawSurface_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) +#define IDirectDrawSurface_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) +#define IDirectDrawSurface_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) +#define IDirectDrawSurface_GetCaps(p,b) (p)->lpVtbl->GetCaps(p,b) +#define IDirectDrawSurface_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) +#define IDirectDrawSurface_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) +#define IDirectDrawSurface_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) +#define IDirectDrawSurface_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) +#define IDirectDrawSurface_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) +#define IDirectDrawSurface_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) +#define IDirectDrawSurface_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) +#define IDirectDrawSurface_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) +#define IDirectDrawSurface_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectDrawSurface_IsLost(p) (p)->lpVtbl->IsLost(p) +#define IDirectDrawSurface_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) +#define IDirectDrawSurface_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) +#define IDirectDrawSurface_Restore(p) (p)->lpVtbl->Restore(p) +#define IDirectDrawSurface_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) +#define IDirectDrawSurface_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) +#define IDirectDrawSurface_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) +#define IDirectDrawSurface_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) +#define IDirectDrawSurface_Unlock(p,b) (p)->lpVtbl->Unlock(p,b) +#define IDirectDrawSurface_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) +#define IDirectDrawSurface_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) +#define IDirectDrawSurface_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) +#endif + +/* + * IDirectDrawSurface2 and related interfaces + */ +#undef INTERFACE +#define INTERFACE IDirectDrawSurface2 +DECLARE_INTERFACE_( IDirectDrawSurface2, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectDrawSurface methods ***/ + STDMETHOD(AddAttachedSurface)(THIS_ LPDIRECTDRAWSURFACE2) PURE; + STDMETHOD(AddOverlayDirtyRect)(THIS_ LPRECT) PURE; + STDMETHOD(Blt)(THIS_ LPRECT,LPDIRECTDRAWSURFACE2, LPRECT,DWORD, LPDDBLTFX) PURE; + STDMETHOD(BltBatch)(THIS_ LPDDBLTBATCH, DWORD, DWORD ) PURE; + STDMETHOD(BltFast)(THIS_ DWORD,DWORD,LPDIRECTDRAWSURFACE2, LPRECT,DWORD) PURE; + STDMETHOD(DeleteAttachedSurface)(THIS_ DWORD,LPDIRECTDRAWSURFACE2) PURE; + STDMETHOD(EnumAttachedSurfaces)(THIS_ LPVOID,LPDDENUMSURFACESCALLBACK) PURE; + STDMETHOD(EnumOverlayZOrders)(THIS_ DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) PURE; + STDMETHOD(Flip)(THIS_ LPDIRECTDRAWSURFACE2, DWORD) PURE; + STDMETHOD(GetAttachedSurface)(THIS_ LPDDSCAPS, LPDIRECTDRAWSURFACE2 FAR *) PURE; + STDMETHOD(GetBltStatus)(THIS_ DWORD) PURE; + STDMETHOD(GetCaps)(THIS_ LPDDSCAPS) PURE; + STDMETHOD(GetClipper)(THIS_ LPDIRECTDRAWCLIPPER FAR*) PURE; + STDMETHOD(GetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; + STDMETHOD(GetDC)(THIS_ HDC FAR *) PURE; + STDMETHOD(GetFlipStatus)(THIS_ DWORD) PURE; + STDMETHOD(GetOverlayPosition)(THIS_ LPLONG, LPLONG ) PURE; + STDMETHOD(GetPalette)(THIS_ LPDIRECTDRAWPALETTE FAR*) PURE; + STDMETHOD(GetPixelFormat)(THIS_ LPDDPIXELFORMAT) PURE; + STDMETHOD(GetSurfaceDesc)(THIS_ LPDDSURFACEDESC) PURE; + STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC) PURE; + STDMETHOD(IsLost)(THIS) PURE; + STDMETHOD(Lock)(THIS_ LPRECT,LPDDSURFACEDESC,DWORD,HANDLE) PURE; + STDMETHOD(ReleaseDC)(THIS_ HDC) PURE; + STDMETHOD(Restore)(THIS) PURE; + STDMETHOD(SetClipper)(THIS_ LPDIRECTDRAWCLIPPER) PURE; + STDMETHOD(SetColorKey)(THIS_ DWORD, LPDDCOLORKEY) PURE; + STDMETHOD(SetOverlayPosition)(THIS_ LONG, LONG ) PURE; + STDMETHOD(SetPalette)(THIS_ LPDIRECTDRAWPALETTE) PURE; + STDMETHOD(Unlock)(THIS_ LPVOID) PURE; + STDMETHOD(UpdateOverlay)(THIS_ LPRECT, LPDIRECTDRAWSURFACE2,LPRECT,DWORD, LPDDOVERLAYFX) PURE; + STDMETHOD(UpdateOverlayDisplay)(THIS_ DWORD) PURE; + STDMETHOD(UpdateOverlayZOrder)(THIS_ DWORD, LPDIRECTDRAWSURFACE2) PURE; + /*** Added in the v2 interface ***/ + STDMETHOD(GetDDInterface)(THIS_ LPVOID FAR *) PURE; + STDMETHOD(PageLock)(THIS_ DWORD) PURE; + STDMETHOD(PageUnlock)(THIS_ DWORD) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectDrawSurface2_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectDrawSurface2_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectDrawSurface2_Release(p) (p)->lpVtbl->Release(p) +#define IDirectDrawSurface2_AddAttachedSurface(p,a) (p)->lpVtbl->AddAttachedSurface(p,a) +#define IDirectDrawSurface2_AddOverlayDirtyRect(p,a) (p)->lpVtbl->AddOverlayDirtyRect(p,a) +#define IDirectDrawSurface2_Blt(p,a,b,c,d,e) (p)->lpVtbl->Blt(p,a,b,c,d,e) +#define IDirectDrawSurface2_BltBatch(p,a,b,c) (p)->lpVtbl->BltBatch(p,a,b,c) +#define IDirectDrawSurface2_BltFast(p,a,b,c,d,e) (p)->lpVtbl->BltFast(p,a,b,c,d,e) +#define IDirectDrawSurface2_DeleteAttachedSurface(p,a,b) (p)->lpVtbl->DeleteAttachedSurface(p,a,b) +#define IDirectDrawSurface2_EnumAttachedSurfaces(p,a,b) (p)->lpVtbl->EnumAttachedSurfaces(p,a,b) +#define IDirectDrawSurface2_EnumOverlayZOrders(p,a,b,c) (p)->lpVtbl->EnumOverlayZOrders(p,a,b,c) +#define IDirectDrawSurface2_Flip(p,a,b) (p)->lpVtbl->Flip(p,a,b) +#define IDirectDrawSurface2_GetAttachedSurface(p,a,b) (p)->lpVtbl->GetAttachedSurface(p,a,b) +#define IDirectDrawSurface2_GetBltStatus(p,a) (p)->lpVtbl->GetBltStatus(p,a) +#define IDirectDrawSurface2_GetCaps(p,b) (p)->lpVtbl->GetCaps(p,b) +#define IDirectDrawSurface2_GetClipper(p,a) (p)->lpVtbl->GetClipper(p,a) +#define IDirectDrawSurface2_GetColorKey(p,a,b) (p)->lpVtbl->GetColorKey(p,a,b) +#define IDirectDrawSurface2_GetDC(p,a) (p)->lpVtbl->GetDC(p,a) +#define IDirectDrawSurface2_GetFlipStatus(p,a) (p)->lpVtbl->GetFlipStatus(p,a) +#define IDirectDrawSurface2_GetOverlayPosition(p,a,b) (p)->lpVtbl->GetOverlayPosition(p,a,b) +#define IDirectDrawSurface2_GetPalette(p,a) (p)->lpVtbl->GetPalette(p,a) +#define IDirectDrawSurface2_GetPixelFormat(p,a) (p)->lpVtbl->GetPixelFormat(p,a) +#define IDirectDrawSurface2_GetSurfaceDesc(p,a) (p)->lpVtbl->GetSurfaceDesc(p,a) +#define IDirectDrawSurface2_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectDrawSurface2_IsLost(p) (p)->lpVtbl->IsLost(p) +#define IDirectDrawSurface2_Lock(p,a,b,c,d) (p)->lpVtbl->Lock(p,a,b,c,d) +#define IDirectDrawSurface2_ReleaseDC(p,a) (p)->lpVtbl->ReleaseDC(p,a) +#define IDirectDrawSurface2_Restore(p) (p)->lpVtbl->Restore(p) +#define IDirectDrawSurface2_SetClipper(p,a) (p)->lpVtbl->SetClipper(p,a) +#define IDirectDrawSurface2_SetColorKey(p,a,b) (p)->lpVtbl->SetColorKey(p,a,b) +#define IDirectDrawSurface2_SetOverlayPosition(p,a,b) (p)->lpVtbl->SetOverlayPosition(p,a,b) +#define IDirectDrawSurface2_SetPalette(p,a) (p)->lpVtbl->SetPalette(p,a) +#define IDirectDrawSurface2_Unlock(p,b) (p)->lpVtbl->Unlock(p,b) +#define IDirectDrawSurface2_UpdateOverlay(p,a,b,c,d,e) (p)->lpVtbl->UpdateOverlay(p,a,b,c,d,e) +#define IDirectDrawSurface2_UpdateOverlayDisplay(p,a) (p)->lpVtbl->UpdateOverlayDisplay(p,a) +#define IDirectDrawSurface2_UpdateOverlayZOrder(p,a,b) (p)->lpVtbl->UpdateOverlayZOrder(p,a,b) +#define IDirectDrawSurface2_GetDDInterface(p,a) (p)->lpVtbl->GetDDInterface(p,a) +#define IDirectDrawSurface2_PageLock(p,a) (p)->lpVtbl->PageLock(p,a) +#define IDirectDrawSurface2_PageUnlock(p,a) (p)->lpVtbl->PageUnlock(p,a) +#endif + + +#endif + + +/* + * DDSURFACEDESC + */ +typedef struct _DDSURFACEDESC +{ + DWORD dwSize; // size of the DDSURFACEDESC structure + DWORD dwFlags; // determines what fields are valid + DWORD dwHeight; // height of surface to be created + DWORD dwWidth; // width of input surface + LONG lPitch; // distance to start of next line (return value only) + DWORD dwBackBufferCount; // number of back buffers requested + union + { + DWORD dwMipMapCount; // number of mip-map levels requested + DWORD dwZBufferBitDepth; // depth of Z buffer requested + DWORD dwRefreshRate; // refresh rate (used when display mode is described) + }; + DWORD dwAlphaBitDepth; // depth of alpha buffer requested + DWORD dwReserved; // reserved + LPVOID lpSurface; // pointer to the associated surface memory + DDCOLORKEY ddckCKDestOverlay; // color key for destination overlay use + DDCOLORKEY ddckCKDestBlt; // color key for destination blt use + DDCOLORKEY ddckCKSrcOverlay; // color key for source overlay use + DDCOLORKEY ddckCKSrcBlt; // color key for source blt use + DDPIXELFORMAT ddpfPixelFormat; // pixel format description of the surface + DDSCAPS ddsCaps; // direct draw surface capabilities +} DDSURFACEDESC; + +/* + * ddsCaps field is valid. + */ +#define DDSD_CAPS 0x00000001l // default + +/* + * dwHeight field is valid. + */ +#define DDSD_HEIGHT 0x00000002l + +/* + * dwWidth field is valid. + */ +#define DDSD_WIDTH 0x00000004l + +/* + * lPitch is valid. + */ +#define DDSD_PITCH 0x00000008l + +/* + * dwBackBufferCount is valid. + */ +#define DDSD_BACKBUFFERCOUNT 0x00000020l + +/* + * dwZBufferBitDepth is valid. + */ +#define DDSD_ZBUFFERBITDEPTH 0x00000040l + +/* + * dwAlphaBitDepth is valid. + */ +#define DDSD_ALPHABITDEPTH 0x00000080l + + + +/* + * ddpfPixelFormat is valid. + */ +#define DDSD_PIXELFORMAT 0x00001000l + +/* + * ddckCKDestOverlay is valid. + */ +#define DDSD_CKDESTOVERLAY 0x00002000l + +/* + * ddckCKDestBlt is valid. + */ +#define DDSD_CKDESTBLT 0x00004000l + +/* + * ddckCKSrcOverlay is valid. + */ +#define DDSD_CKSRCOVERLAY 0x00008000l + +/* + * ddckCKSrcBlt is valid. + */ +#define DDSD_CKSRCBLT 0x00010000l + +/* + * dwMipMapCount is valid. + */ +#define DDSD_MIPMAPCOUNT 0x00020000l + + /* + * dwRefreshRate is valid + */ +#define DDSD_REFRESHRATE 0x00040000l + + +/* + * All input fields are valid. + */ +#define DDSD_ALL 0x0007f9eel + + +/*============================================================================ + * + * Direct Draw Capability Flags + * + * These flags are used to describe the capabilities of a given Surface. + * All flags are bit flags. + * + *==========================================================================*/ + +/**************************************************************************** + * + * DIRECTDRAWSURFACE CAPABILITY FLAGS + * + ****************************************************************************/ +/* + * This bit currently has no meaning. + */ +#define DDSCAPS_3D 0x00000001l + +/* + * Indicates that this surface contains alpha information. The pixel + * format must be interrogated to determine whether this surface + * contains only alpha information or alpha information interlaced + * with pixel color data (e.g. RGBA or YUVA). + */ +#define DDSCAPS_ALPHA 0x00000002l + +/* + * Indicates that this surface is a backbuffer. It is generally + * set by CreateSurface when the DDSCAPS_FLIP capability bit is set. + * It indicates that this surface is THE back buffer of a surface + * flipping structure. DirectDraw supports N surfaces in a + * surface flipping structure. Only the surface that immediately + * precedeces the DDSCAPS_FRONTBUFFER has this capability bit set. + * The other surfaces are identified as back buffers by the presence + * of the DDSCAPS_FLIP capability, their attachment order, and the + * absence of the DDSCAPS_FRONTBUFFER and DDSCAPS_BACKBUFFER + * capabilities. The bit is sent to CreateSurface when a standalone + * back buffer is being created. This surface could be attached to + * a front buffer and/or back buffers to form a flipping surface + * structure after the CreateSurface call. See AddAttachments for + * a detailed description of the behaviors in this case. + */ +#define DDSCAPS_BACKBUFFER 0x00000004l + +/* + * Indicates a complex surface structure is being described. A + * complex surface structure results in the creation of more than + * one surface. The additional surfaces are attached to the root + * surface. The complex structure can only be destroyed by + * destroying the root. + */ +#define DDSCAPS_COMPLEX 0x00000008l + +/* + * Indicates that this surface is a part of a surface flipping structure. + * When it is passed to CreateSurface the DDSCAPS_FRONTBUFFER and + * DDSCAP_BACKBUFFER bits are not set. They are set by CreateSurface + * on the resulting creations. The dwBackBufferCount field in the + * DDSURFACEDESC structure must be set to at least 1 in order for + * the CreateSurface call to succeed. The DDSCAPS_COMPLEX capability + * must always be set with creating multiple surfaces through CreateSurface. + */ +#define DDSCAPS_FLIP 0x00000010l + +/* + * Indicates that this surface is THE front buffer of a surface flipping + * structure. It is generally set by CreateSurface when the DDSCAPS_FLIP + * capability bit is set. + * If this capability is sent to CreateSurface then a standalonw front buffer + * is created. This surface will not have the DDSCAPS_FLIP capability. + * It can be attached to other back buffers to form a flipping structure. + * See AddAttachments for a detailed description of the behaviors in this + * case. + */ +#define DDSCAPS_FRONTBUFFER 0x00000020l + +/* + * Indicates that this surface is any offscreen surface that is not an overlay, + * texture, zbuffer, front buffer, back buffer, or alpha surface. It is used + * to identify plain vanilla surfaces. + */ +#define DDSCAPS_OFFSCREENPLAIN 0x00000040l + +/* + * Indicates that this surface is an overlay. It may or may not be directly visible + * depending on whether or not it is currently being overlayed onto the primary + * surface. DDSCAPS_VISIBLE can be used to determine whether or not it is being + * overlayed at the moment. + */ +#define DDSCAPS_OVERLAY 0x00000080l + +/* + * Indicates that unique DirectDrawPalette objects can be created and + * attached to this surface. + */ +#define DDSCAPS_PALETTE 0x00000100l + +/* + * Indicates that this surface is the primary surface. The primary + * surface represents what the user is seeing at the moment. + */ +#define DDSCAPS_PRIMARYSURFACE 0x00000200l + +/* + * Indicates that this surface is the primary surface for the left eye. + * The primary surface for the left eye represents what the user is seeing + * at the moment with the users left eye. When this surface is created the + * DDSCAPS_PRIMARYSURFACE represents what the user is seeing with the users + * right eye. + */ +#define DDSCAPS_PRIMARYSURFACELEFT 0x00000400l + +/* + * Indicates that this surface memory was allocated in system memory + */ +#define DDSCAPS_SYSTEMMEMORY 0x00000800l + +/* + * Indicates that this surface can be used as a 3D texture. It does not + * indicate whether or not the surface is being used for that purpose. + */ +#define DDSCAPS_TEXTURE 0x00001000l + +/* + * Indicates that a surface may be a destination for 3D rendering. This + * bit must be set in order to query for a Direct3D Device Interface + * from this surface. + */ +#define DDSCAPS_3DDEVICE 0x00002000l + +/* + * Indicates that this surface exists in video memory. + */ +#define DDSCAPS_VIDEOMEMORY 0x00004000l + +/* + * Indicates that changes made to this surface are immediately visible. + * It is always set for the primary surface and is set for overlays while + * they are being overlayed and texture maps while they are being textured. + */ +#define DDSCAPS_VISIBLE 0x00008000l + +/* + * Indicates that only writes are permitted to the surface. Read accesses + * from the surface may or may not generate a protection fault, but the + * results of a read from this surface will not be meaningful. READ ONLY. + */ +#define DDSCAPS_WRITEONLY 0x00010000l + +/* + * Indicates that this surface is a z buffer. A z buffer does not contain + * displayable information. Instead it contains bit depth information that is + * used to determine which pixels are visible and which are obscured. + */ +#define DDSCAPS_ZBUFFER 0x00020000l + +/* + * Indicates surface will have a DC associated long term + */ +#define DDSCAPS_OWNDC 0x00040000l + +/* + * Indicates surface should be able to receive live video + */ +#define DDSCAPS_LIVEVIDEO 0x00080000l + +/* + * Indicates surface should be able to have a stream decompressed + * to it by the hardware. + */ +#define DDSCAPS_HWCODEC 0x00100000l + +/* + * Surface is a 320x200 or 320x240 ModeX surface + */ +#define DDSCAPS_MODEX 0x00200000l + +/* + * Indicates surface is one level of a mip-map. This surface will + * be attached to other DDSCAPS_MIPMAP surfaces to form the mip-map. + * This can be done explicitly, by creating a number of surfaces and + * attaching them with AddAttachedSurface or by implicitly by CreateSurface. + * If this bit is set then DDSCAPS_TEXTURE must also be set. + */ +#define DDSCAPS_MIPMAP 0x00400000l + + + +/* + * Indicates that memory for the surface is not allocated until the surface + * is loaded (via the Direct3D texture Load() function). + */ +#define DDSCAPS_ALLOCONLOAD 0x04000000l + + + + /**************************************************************************** + * + * DIRECTDRAW DRIVER CAPABILITY FLAGS + * + ****************************************************************************/ + +/* + * Display hardware has 3D acceleration. + */ +#define DDCAPS_3D 0x00000001l + +/* + * Indicates that DirectDraw will support only dest rectangles that are aligned + * on DIRECTDRAWCAPS.dwAlignBoundaryDest boundaries of the surface, respectively. + * READ ONLY. + */ +#define DDCAPS_ALIGNBOUNDARYDEST 0x00000002l + +/* + * Indicates that DirectDraw will support only source rectangles whose sizes in + * BYTEs are DIRECTDRAWCAPS.dwAlignSizeDest multiples, respectively. READ ONLY. + */ +#define DDCAPS_ALIGNSIZEDEST 0x00000004l +/* + * Indicates that DirectDraw will support only source rectangles that are aligned + * on DIRECTDRAWCAPS.dwAlignBoundarySrc boundaries of the surface, respectively. + * READ ONLY. + */ +#define DDCAPS_ALIGNBOUNDARYSRC 0x00000008l + +/* + * Indicates that DirectDraw will support only source rectangles whose sizes in + * BYTEs are DIRECTDRAWCAPS.dwAlignSizeSrc multiples, respectively. READ ONLY. + */ +#define DDCAPS_ALIGNSIZESRC 0x00000010l + +/* + * Indicates that DirectDraw will create video memory surfaces that have a stride + * alignment equal to DIRECTDRAWCAPS.dwAlignStride. READ ONLY. + */ +#define DDCAPS_ALIGNSTRIDE 0x00000020l + +/* + * Display hardware is capable of blt operations. + */ +#define DDCAPS_BLT 0x00000040l + +/* + * Display hardware is capable of asynchronous blt operations. + */ +#define DDCAPS_BLTQUEUE 0x00000080l + +/* + * Display hardware is capable of color space conversions during the blt operation. + */ +#define DDCAPS_BLTFOURCC 0x00000100l + +/* + * Display hardware is capable of stretching during blt operations. + */ +#define DDCAPS_BLTSTRETCH 0x00000200l + +/* + * Display hardware is shared with GDI. + */ +#define DDCAPS_GDI 0x00000400l + +/* + * Display hardware can overlay. + */ +#define DDCAPS_OVERLAY 0x00000800l + +/* + * Set if display hardware supports overlays but can not clip them. + */ +#define DDCAPS_OVERLAYCANTCLIP 0x00001000l + +/* + * Indicates that overlay hardware is capable of color space conversions during + * the overlay operation. + */ +#define DDCAPS_OVERLAYFOURCC 0x00002000l + +/* + * Indicates that stretching can be done by the overlay hardware. + */ +#define DDCAPS_OVERLAYSTRETCH 0x00004000l + +/* + * Indicates that unique DirectDrawPalettes can be created for DirectDrawSurfaces + * other than the primary surface. + */ +#define DDCAPS_PALETTE 0x00008000l + +/* + * Indicates that palette changes can be syncd with the veritcal refresh. + */ +#define DDCAPS_PALETTEVSYNC 0x00010000l + +/* + * Display hardware can return the current scan line. + */ +#define DDCAPS_READSCANLINE 0x00020000l + +/* + * Display hardware has stereo vision capabilities. DDSCAPS_PRIMARYSURFACELEFT + * can be created. + */ +#define DDCAPS_STEREOVIEW 0x00040000l + +/* + * Display hardware is capable of generating a vertical blank interrupt. + */ +#define DDCAPS_VBI 0x00080000l + +/* + * Supports the use of z buffers with blt operations. + */ +#define DDCAPS_ZBLTS 0x00100000l + +/* + * Supports Z Ordering of overlays. + */ +#define DDCAPS_ZOVERLAYS 0x00200000l + +/* + * Supports color key + */ +#define DDCAPS_COLORKEY 0x00400000l + +/* + * Supports alpha surfaces + */ +#define DDCAPS_ALPHA 0x00800000l + +/* + * colorkey is hardware assisted(DDCAPS_COLORKEY will also be set) + */ +#define DDCAPS_COLORKEYHWASSIST 0x01000000l + +/* + * no hardware support at all + */ +#define DDCAPS_NOHARDWARE 0x02000000l + +/* + * Display hardware is capable of color fill with bltter + */ +#define DDCAPS_BLTCOLORFILL 0x04000000l + +/* + * Display hardware is bank switched, and potentially very slow at + * random access to VRAM. + */ +#define DDCAPS_BANKSWITCHED 0x08000000l + +/* + * Display hardware is capable of depth filling Z-buffers with bltter + */ +#define DDCAPS_BLTDEPTHFILL 0x10000000l + +/* + * Display hardware is capable of clipping while bltting. + */ +#define DDCAPS_CANCLIP 0x20000000l + +/* + * Display hardware is capable of clipping while stretch bltting. + */ +#define DDCAPS_CANCLIPSTRETCHED 0x40000000l + +/* + * Display hardware is capable of bltting to or from system memory + */ +#define DDCAPS_CANBLTSYSMEM 0x80000000l + + + /**************************************************************************** + * + * MORE DIRECTDRAW DRIVER CAPABILITY FLAGS (dwCaps2) + * + ****************************************************************************/ + +/* + * Display hardware is certified + */ +#define DDCAPS2_CERTIFIED 0x00000001l + +/* + * Driver cannot interleave 2D operations (lock and blt) to surfaces with + * Direct3D rendering operations between calls to BeginScene() and EndScene() + */ +#define DDCAPS2_NO2DDURING3DSCENE 0x00000002l + +/**************************************************************************** + * + * DIRECTDRAW FX ALPHA CAPABILITY FLAGS + * + ****************************************************************************/ + +/* + * Supports alpha blending around the edge of a source color keyed surface. + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHAEDGEBLEND 0x00000001l + +/* + * Supports alpha information in the pixel format. The bit depth of alpha + * information in the pixel format can be 1,2,4, or 8. The alpha value becomes + * more opaque as the alpha value increases. (0 is transparent.) + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHAPIXELS 0x00000002l + +/* + * Supports alpha information in the pixel format. The bit depth of alpha + * information in the pixel format can be 1,2,4, or 8. The alpha value + * becomes more transparent as the alpha value increases. (0 is opaque.) + * This flag can only be set if DDCAPS_ALPHA is set. + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHAPIXELSNEG 0x00000004l + +/* + * Supports alpha only surfaces. The bit depth of an alpha only surface can be + * 1,2,4, or 8. The alpha value becomes more opaque as the alpha value increases. + * (0 is transparent.) + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHASURFACES 0x00000008l + +/* + * The depth of the alpha channel data can range can be 1,2,4, or 8. + * The NEG suffix indicates that this alpha channel becomes more transparent + * as the alpha value increases. (0 is opaque.) This flag can only be set if + * DDCAPS_ALPHA is set. + * For Blt. + */ +#define DDFXALPHACAPS_BLTALPHASURFACESNEG 0x00000010l + +/* + * Supports alpha blending around the edge of a source color keyed surface. + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHAEDGEBLEND 0x00000020l + +/* + * Supports alpha information in the pixel format. The bit depth of alpha + * information in the pixel format can be 1,2,4, or 8. The alpha value becomes + * more opaque as the alpha value increases. (0 is transparent.) + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHAPIXELS 0x00000040l + +/* + * Supports alpha information in the pixel format. The bit depth of alpha + * information in the pixel format can be 1,2,4, or 8. The alpha value + * becomes more transparent as the alpha value increases. (0 is opaque.) + * This flag can only be set if DDCAPS_ALPHA is set. + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHAPIXELSNEG 0x00000080l + +/* + * Supports alpha only surfaces. The bit depth of an alpha only surface can be + * 1,2,4, or 8. The alpha value becomes more opaque as the alpha value increases. + * (0 is transparent.) + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHASURFACES 0x00000100l + +/* + * The depth of the alpha channel data can range can be 1,2,4, or 8. + * The NEG suffix indicates that this alpha channel becomes more transparent + * as the alpha value increases. (0 is opaque.) This flag can only be set if + * DDCAPS_ALPHA is set. + * For Overlays. + */ +#define DDFXALPHACAPS_OVERLAYALPHASURFACESNEG 0x00000200l + +/**************************************************************************** + * + * DIRECTDRAW FX CAPABILITY FLAGS + * + ****************************************************************************/ + +/* + * Uses arithmetic operations to stretch and shrink surfaces during blt + * rather than pixel doubling techniques. Along the Y axis. + */ +#define DDFXCAPS_BLTARITHSTRETCHY 0x00000020l + +/* + * Uses arithmetic operations to stretch during blt + * rather than pixel doubling techniques. Along the Y axis. Only + * works for x1, x2, etc. + */ +#define DDFXCAPS_BLTARITHSTRETCHYN 0x00000010l + +/* + * Supports mirroring left to right in blt. + */ +#define DDFXCAPS_BLTMIRRORLEFTRIGHT 0x00000040l + +/* + * Supports mirroring top to bottom in blt. + */ +#define DDFXCAPS_BLTMIRRORUPDOWN 0x00000080l + +/* + * Supports arbitrary rotation for blts. + */ +#define DDFXCAPS_BLTROTATION 0x00000100l + +/* + * Supports 90 degree rotations for blts. + */ +#define DDFXCAPS_BLTROTATION90 0x00000200l + +/* + * DirectDraw supports arbitrary shrinking of a surface along the + * x axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSHRINKX 0x00000400l + +/* + * DirectDraw supports integer shrinking (1x,2x,) of a surface + * along the x axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSHRINKXN 0x00000800l + +/* + * DirectDraw supports arbitrary shrinking of a surface along the + * y axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSHRINKY 0x00001000l + +/* + * DirectDraw supports integer shrinking (1x,2x,) of a surface + * along the y axis (vertical direction) for blts. + */ +#define DDFXCAPS_BLTSHRINKYN 0x00002000l + +/* + * DirectDraw supports arbitrary stretching of a surface along the + * x axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSTRETCHX 0x00004000l + +/* + * DirectDraw supports integer stretching (1x,2x,) of a surface + * along the x axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSTRETCHXN 0x00008000l + +/* + * DirectDraw supports arbitrary stretching of a surface along the + * y axis (horizontal direction) for blts. + */ +#define DDFXCAPS_BLTSTRETCHY 0x00010000l + +/* + * DirectDraw supports integer stretching (1x,2x,) of a surface + * along the y axis (vertical direction) for blts. + */ +#define DDFXCAPS_BLTSTRETCHYN 0x00020000l + +/* + * Uses arithmetic operations to stretch and shrink surfaces during + * overlay rather than pixel doubling techniques. Along the Y axis + * for overlays. + */ +#define DDFXCAPS_OVERLAYARITHSTRETCHY 0x00040000l + +/* + * Uses arithmetic operations to stretch surfaces during + * overlay rather than pixel doubling techniques. Along the Y axis + * for overlays. Only works for x1, x2, etc. + */ +#define DDFXCAPS_OVERLAYARITHSTRETCHYN 0x00000008l + +/* + * DirectDraw supports arbitrary shrinking of a surface along the + * x axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSHRINKX 0x00080000l + +/* + * DirectDraw supports integer shrinking (1x,2x,) of a surface + * along the x axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSHRINKXN 0x00100000l + +/* + * DirectDraw supports arbitrary shrinking of a surface along the + * y axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSHRINKY 0x00200000l + +/* + * DirectDraw supports integer shrinking (1x,2x,) of a surface + * along the y axis (vertical direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSHRINKYN 0x00400000l + +/* + * DirectDraw supports arbitrary stretching of a surface along the + * x axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSTRETCHX 0x00800000l + +/* + * DirectDraw supports integer stretching (1x,2x,) of a surface + * along the x axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSTRETCHXN 0x01000000l + +/* + * DirectDraw supports arbitrary stretching of a surface along the + * y axis (horizontal direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSTRETCHY 0x02000000l + +/* + * DirectDraw supports integer stretching (1x,2x,) of a surface + * along the y axis (vertical direction) for overlays. + */ +#define DDFXCAPS_OVERLAYSTRETCHYN 0x04000000l + +/* + * DirectDraw supports mirroring of overlays across the vertical axis + */ +#define DDFXCAPS_OVERLAYMIRRORLEFTRIGHT 0x08000000l + +/* + * DirectDraw supports mirroring of overlays across the horizontal axis + */ +#define DDFXCAPS_OVERLAYMIRRORUPDOWN 0x10000000l + +/**************************************************************************** + * + * DIRECTDRAW STEREO VIEW CAPABILITIES + * + ****************************************************************************/ + +/* + * The stereo view is accomplished via enigma encoding. + */ +#define DDSVCAPS_ENIGMA 0x00000001l + +/* + * The stereo view is accomplished via high frequency flickering. + */ +#define DDSVCAPS_FLICKER 0x00000002l + +/* + * The stereo view is accomplished via red and blue filters applied + * to the left and right eyes. All images must adapt their colorspaces + * for this process. + */ +#define DDSVCAPS_REDBLUE 0x00000004l + +/* + * The stereo view is accomplished with split screen technology. + */ +#define DDSVCAPS_SPLIT 0x00000008l + +/**************************************************************************** + * + * DIRECTDRAWPALETTE CAPABILITIES + * + ****************************************************************************/ + +/* + * Index is 4 bits. There are sixteen color entries in the palette table. + */ +#define DDPCAPS_4BIT 0x00000001l + +/* + * Index is onto a 8 bit color index. This field is only valid with the + * DDPCAPS_1BIT, DDPCAPS_2BIT or DDPCAPS_4BIT capability and the target + * surface is in 8bpp. Each color entry is one byte long and is an index + * into destination surface's 8bpp palette. + */ +#define DDPCAPS_8BITENTRIES 0x00000002l + +/* + * Index is 8 bits. There are 256 color entries in the palette table. + */ +#define DDPCAPS_8BIT 0x00000004l + +/* + * Indicates that this DIRECTDRAWPALETTE should use the palette color array + * passed into the lpDDColorArray parameter to initialize the DIRECTDRAWPALETTE + * object. + */ +#define DDPCAPS_INITIALIZE 0x00000008l + +/* + * This palette is the one attached to the primary surface. Changing this + * table has immediate effect on the display unless DDPSETPAL_VSYNC is specified + * and supported. + */ +#define DDPCAPS_PRIMARYSURFACE 0x00000010l + +/* + * This palette is the one attached to the primary surface left. Changing + * this table has immediate effect on the display for the left eye unless + * DDPSETPAL_VSYNC is specified and supported. + */ +#define DDPCAPS_PRIMARYSURFACELEFT 0x00000020l + +/* + * This palette can have all 256 entries defined + */ +#define DDPCAPS_ALLOW256 0x00000040l + +/* + * This palette can have modifications to it synced with the monitors + * refresh rate. + */ +#define DDPCAPS_VSYNC 0x00000080l + +/* + * Index is 1 bit. There are two color entries in the palette table. + */ +#define DDPCAPS_1BIT 0x00000100l + +/* + * Index is 2 bit. There are four color entries in the palette table. + */ +#define DDPCAPS_2BIT 0x00000200l + + +/**************************************************************************** + * + * DIRECTDRAWPALETTE SETENTRY CONSTANTS + * + ****************************************************************************/ + + +/**************************************************************************** + * + * DIRECTDRAWPALETTE GETENTRY CONSTANTS + * + ****************************************************************************/ + +/* 0 is the only legal value */ + +/**************************************************************************** + * + * DIRECTDRAWSURFACE SETPALETTE CONSTANTS + * + ****************************************************************************/ + + +/**************************************************************************** + * + * DIRECTDRAW BITDEPTH CONSTANTS + * + * NOTE: These are only used to indicate supported bit depths. These + * are flags only, they are not to be used as an actual bit depth. The + * absolute numbers 1, 2, 4, 8, 16, 24 and 32 are used to indicate actual + * bit depths in a surface or for changing the display mode. + * + ****************************************************************************/ + +/* + * 1 bit per pixel. + */ +#define DDBD_1 0x00004000l + +/* + * 2 bits per pixel. + */ +#define DDBD_2 0x00002000l + +/* + * 4 bits per pixel. + */ +#define DDBD_4 0x00001000l + +/* + * 8 bits per pixel. + */ +#define DDBD_8 0x00000800l + +/* + * 16 bits per pixel. + */ +#define DDBD_16 0x00000400l + +/* + * 24 bits per pixel. + */ +#define DDBD_24 0X00000200l + +/* + * 32 bits per pixel. + */ +#define DDBD_32 0x00000100l + +/**************************************************************************** + * + * DIRECTDRAWSURFACE SET/GET COLOR KEY FLAGS + * + ****************************************************************************/ + +/* + * Set if the structure contains a color space. Not set if the structure + * contains a single color key. + */ +#define DDCKEY_COLORSPACE 0x00000001l + +/* + * Set if the structure specifies a color key or color space which is to be + * used as a destination color key for blt operations. + */ +#define DDCKEY_DESTBLT 0x00000002l + +/* + * Set if the structure specifies a color key or color space which is to be + * used as a destination color key for overlay operations. + */ +#define DDCKEY_DESTOVERLAY 0x00000004l + +/* + * Set if the structure specifies a color key or color space which is to be + * used as a source color key for blt operations. + */ +#define DDCKEY_SRCBLT 0x00000008l + +/* + * Set if the structure specifies a color key or color space which is to be + * used as a source color key for overlay operations. + */ +#define DDCKEY_SRCOVERLAY 0x00000010l + + +/**************************************************************************** + * + * DIRECTDRAW COLOR KEY CAPABILITY FLAGS + * + ****************************************************************************/ + +/* + * Supports transparent blting using a color key to identify the replaceable + * bits of the destination surface for RGB colors. + */ +#define DDCKEYCAPS_DESTBLT 0x00000001l + +/* + * Supports transparent blting using a color space to identify the replaceable + * bits of the destination surface for RGB colors. + */ +#define DDCKEYCAPS_DESTBLTCLRSPACE 0x00000002l + +/* + * Supports transparent blting using a color space to identify the replaceable + * bits of the destination surface for YUV colors. + */ +#define DDCKEYCAPS_DESTBLTCLRSPACEYUV 0x00000004l + +/* + * Supports transparent blting using a color key to identify the replaceable + * bits of the destination surface for YUV colors. + */ +#define DDCKEYCAPS_DESTBLTYUV 0x00000008l + +/* + * Supports overlaying using colorkeying of the replaceable bits of the surface + * being overlayed for RGB colors. + */ +#define DDCKEYCAPS_DESTOVERLAY 0x00000010l + +/* + * Supports a color space as the color key for the destination for RGB colors. + */ +#define DDCKEYCAPS_DESTOVERLAYCLRSPACE 0x00000020l + +/* + * Supports a color space as the color key for the destination for YUV colors. + */ +#define DDCKEYCAPS_DESTOVERLAYCLRSPACEYUV 0x00000040l + +/* + * Supports only one active destination color key value for visible overlay + * surfaces. + */ +#define DDCKEYCAPS_DESTOVERLAYONEACTIVE 0x00000080l + +/* + * Supports overlaying using colorkeying of the replaceable bits of the + * surface being overlayed for YUV colors. + */ +#define DDCKEYCAPS_DESTOVERLAYYUV 0x00000100l + +/* + * Supports transparent blting using the color key for the source with + * this surface for RGB colors. + */ +#define DDCKEYCAPS_SRCBLT 0x00000200l + +/* + * Supports transparent blting using a color space for the source with + * this surface for RGB colors. + */ +#define DDCKEYCAPS_SRCBLTCLRSPACE 0x00000400l + +/* + * Supports transparent blting using a color space for the source with + * this surface for YUV colors. + */ +#define DDCKEYCAPS_SRCBLTCLRSPACEYUV 0x00000800l + +/* + * Supports transparent blting using the color key for the source with + * this surface for YUV colors. + */ +#define DDCKEYCAPS_SRCBLTYUV 0x00001000l + +/* + * Supports overlays using the color key for the source with this + * overlay surface for RGB colors. + */ +#define DDCKEYCAPS_SRCOVERLAY 0x00002000l + +/* + * Supports overlays using a color space as the source color key for + * the overlay surface for RGB colors. + */ +#define DDCKEYCAPS_SRCOVERLAYCLRSPACE 0x00004000l + +/* + * Supports overlays using a color space as the source color key for + * the overlay surface for YUV colors. + */ +#define DDCKEYCAPS_SRCOVERLAYCLRSPACEYUV 0x00008000l + +/* + * Supports only one active source color key value for visible + * overlay surfaces. + */ +#define DDCKEYCAPS_SRCOVERLAYONEACTIVE 0x00010000l + +/* + * Supports overlays using the color key for the source with this + * overlay surface for YUV colors. + */ +#define DDCKEYCAPS_SRCOVERLAYYUV 0x00020000l + +/* + * there are no bandwidth trade-offs for using colorkey with an overlay + */ +#define DDCKEYCAPS_NOCOSTOVERLAY 0x00040000l + + +/**************************************************************************** + * + * DIRECTDRAW PIXELFORMAT FLAGS + * + ****************************************************************************/ + +/* + * The surface has alpha channel information in the pixel format. + */ +#define DDPF_ALPHAPIXELS 0x00000001l + +/* + * The pixel format contains alpha only information + */ +#define DDPF_ALPHA 0x00000002l + +/* + * The FourCC code is valid. + */ +#define DDPF_FOURCC 0x00000004l + +/* + * The surface is 4-bit color indexed. + */ +#define DDPF_PALETTEINDEXED4 0x00000008l + +/* + * The surface is indexed into a palette which stores indices + * into the destination surface's 8-bit palette. + */ +#define DDPF_PALETTEINDEXEDTO8 0x00000010l + +/* + * The surface is 8-bit color indexed. + */ +#define DDPF_PALETTEINDEXED8 0x00000020l + +/* + * The RGB data in the pixel format structure is valid. + */ +#define DDPF_RGB 0x00000040l + +/* + * The surface will accept pixel data in the format specified + * and compress it during the write. + */ +#define DDPF_COMPRESSED 0x00000080l + +/* + * The surface will accept RGB data and translate it during + * the write to YUV data. The format of the data to be written + * will be contained in the pixel format structure. The DDPF_RGB + * flag will be set. + */ +#define DDPF_RGBTOYUV 0x00000100l + +/* + * pixel format is YUV - YUV data in pixel format struct is valid + */ +#define DDPF_YUV 0x00000200l + +/* + * pixel format is a z buffer only surface + */ +#define DDPF_ZBUFFER 0x00000400l + +/* + * The surface is 1-bit color indexed. + */ +#define DDPF_PALETTEINDEXED1 0x00000800l + +/* + * The surface is 2-bit color indexed. + */ +#define DDPF_PALETTEINDEXED2 0x00001000l + +/*=========================================================================== + * + * + * DIRECTDRAW CALLBACK FLAGS + * + * + *==========================================================================*/ + +/**************************************************************************** + * + * DIRECTDRAW ENUMSURFACES FLAGS + * + ****************************************************************************/ + +/* + * Enumerate all of the surfaces that meet the search criterion. + */ +#define DDENUMSURFACES_ALL 0x00000001l + +/* + * A search hit is a surface that matches the surface description. + */ +#define DDENUMSURFACES_MATCH 0x00000002l + +/* + * A search hit is a surface that does not match the surface description. + */ +#define DDENUMSURFACES_NOMATCH 0x00000004l + +/* + * Enumerate the first surface that can be created which meets the search criterion. + */ +#define DDENUMSURFACES_CANBECREATED 0x00000008l + +/* + * Enumerate the surfaces that already exist that meet the search criterion. + */ +#define DDENUMSURFACES_DOESEXIST 0x00000010l + + +/**************************************************************************** + * + * DIRECTDRAW ENUMDISPLAYMODES FLAGS + * + ****************************************************************************/ + +/* + * Enumerate Modes with different refresh rates. EnumDisplayModes guarantees + * that a particular mode will be enumerated only once. This flag specifies whether + * the refresh rate is taken into account when determining if a mode is unique. + */ +#define DDEDM_REFRESHRATES 0x00000001l + + +/**************************************************************************** + * + * DIRECTDRAW SETCOOPERATIVELEVEL FLAGS + * + ****************************************************************************/ + +/* + * Exclusive mode owner will be responsible for the entire primary surface. + * GDI can be ignored. used with DD + */ +#define DDSCL_FULLSCREEN 0x00000001l + +/* + * allow CTRL_ALT_DEL to work while in fullscreen exclusive mode + */ +#define DDSCL_ALLOWREBOOT 0x00000002l + +/* + * prevents DDRAW from modifying the application window. + * prevents DDRAW from minimize/restore the application window on activation. + */ +#define DDSCL_NOWINDOWCHANGES 0x00000004l + +/* + * app wants to work as a regular Windows application + */ +#define DDSCL_NORMAL 0x00000008l + +/* + * app wants exclusive access + */ +#define DDSCL_EXCLUSIVE 0x00000010l + + +/* + * app can deal with non-windows display modes + */ +#define DDSCL_ALLOWMODEX 0x00000040l + + +/**************************************************************************** + * + * DIRECTDRAW BLT FLAGS + * + ****************************************************************************/ + +/* + * Use the alpha information in the pixel format or the alpha channel surface + * attached to the destination surface as the alpha channel for this blt. + */ +#define DDBLT_ALPHADEST 0x00000001l + +/* + * Use the dwConstAlphaDest field in the DDBLTFX structure as the alpha channel + * for the destination surface for this blt. + */ +#define DDBLT_ALPHADESTCONSTOVERRIDE 0x00000002l + +/* + * The NEG suffix indicates that the destination surface becomes more + * transparent as the alpha value increases. (0 is opaque) + */ +#define DDBLT_ALPHADESTNEG 0x00000004l + +/* + * Use the lpDDSAlphaDest field in the DDBLTFX structure as the alpha + * channel for the destination for this blt. + */ +#define DDBLT_ALPHADESTSURFACEOVERRIDE 0x00000008l + +/* + * Use the dwAlphaEdgeBlend field in the DDBLTFX structure as the alpha channel + * for the edges of the image that border the color key colors. + */ +#define DDBLT_ALPHAEDGEBLEND 0x00000010l + +/* + * Use the alpha information in the pixel format or the alpha channel surface + * attached to the source surface as the alpha channel for this blt. + */ +#define DDBLT_ALPHASRC 0x00000020l + +/* + * Use the dwConstAlphaSrc field in the DDBLTFX structure as the alpha channel + * for the source for this blt. + */ +#define DDBLT_ALPHASRCCONSTOVERRIDE 0x00000040l + +/* + * The NEG suffix indicates that the source surface becomes more transparent + * as the alpha value increases. (0 is opaque) + */ +#define DDBLT_ALPHASRCNEG 0x00000080l + +/* + * Use the lpDDSAlphaSrc field in the DDBLTFX structure as the alpha channel + * for the source for this blt. + */ +#define DDBLT_ALPHASRCSURFACEOVERRIDE 0x00000100l + +/* + * Do this blt asynchronously through the FIFO in the order received. If + * there is no room in the hardware FIFO fail the call. + */ +#define DDBLT_ASYNC 0x00000200l + +/* + * Uses the dwFillColor field in the DDBLTFX structure as the RGB color + * to fill the destination rectangle on the destination surface with. + */ +#define DDBLT_COLORFILL 0x00000400l + +/* + * Uses the dwDDFX field in the DDBLTFX structure to specify the effects + * to use for the blt. + */ +#define DDBLT_DDFX 0x00000800l + +/* + * Uses the dwDDROPS field in the DDBLTFX structure to specify the ROPS + * that are not part of the Win32 API. + */ +#define DDBLT_DDROPS 0x00001000l + +/* + * Use the color key associated with the destination surface. + */ +#define DDBLT_KEYDEST 0x00002000l + +/* + * Use the dckDestColorkey field in the DDBLTFX structure as the color key + * for the destination surface. + */ +#define DDBLT_KEYDESTOVERRIDE 0x00004000l + +/* + * Use the color key associated with the source surface. + */ +#define DDBLT_KEYSRC 0x00008000l + +/* + * Use the dckSrcColorkey field in the DDBLTFX structure as the color key + * for the source surface. + */ +#define DDBLT_KEYSRCOVERRIDE 0x00010000l + +/* + * Use the dwROP field in the DDBLTFX structure for the raster operation + * for this blt. These ROPs are the same as the ones defined in the Win32 API. + */ +#define DDBLT_ROP 0x00020000l + +/* + * Use the dwRotationAngle field in the DDBLTFX structure as the angle + * (specified in 1/100th of a degree) to rotate the surface. + */ +#define DDBLT_ROTATIONANGLE 0x00040000l + +/* + * Z-buffered blt using the z-buffers attached to the source and destination + * surfaces and the dwZBufferOpCode field in the DDBLTFX structure as the + * z-buffer opcode. + */ +#define DDBLT_ZBUFFER 0x00080000l + +/* + * Z-buffered blt using the dwConstDest Zfield and the dwZBufferOpCode field + * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively + * for the destination. + */ +#define DDBLT_ZBUFFERDESTCONSTOVERRIDE 0x00100000l + +/* + * Z-buffered blt using the lpDDSDestZBuffer field and the dwZBufferOpCode + * field in the DDBLTFX structure as the z-buffer and z-buffer opcode + * respectively for the destination. + */ +#define DDBLT_ZBUFFERDESTOVERRIDE 0x00200000l + +/* + * Z-buffered blt using the dwConstSrcZ field and the dwZBufferOpCode field + * in the DDBLTFX structure as the z-buffer and z-buffer opcode respectively + * for the source. + */ +#define DDBLT_ZBUFFERSRCCONSTOVERRIDE 0x00400000l + +/* + * Z-buffered blt using the lpDDSSrcZBuffer field and the dwZBufferOpCode + * field in the DDBLTFX structure as the z-buffer and z-buffer opcode + * respectively for the source. + */ +#define DDBLT_ZBUFFERSRCOVERRIDE 0x00800000l + +/* + * wait until the device is ready to handle the blt + * this will cause blt to not return DDERR_WASSTILLDRAWING + */ +#define DDBLT_WAIT 0x01000000l + +/* + * Uses the dwFillDepth field in the DDBLTFX structure as the depth value + * to fill the destination rectangle on the destination Z-buffer surface + * with. + */ +#define DDBLT_DEPTHFILL 0x02000000l + + +/**************************************************************************** + * + * BLTFAST FLAGS + * + ****************************************************************************/ + +#define DDBLTFAST_NOCOLORKEY 0x00000000 +#define DDBLTFAST_SRCCOLORKEY 0x00000001 +#define DDBLTFAST_DESTCOLORKEY 0x00000002 +#define DDBLTFAST_WAIT 0x00000010 + +/**************************************************************************** + * + * FLIP FLAGS + * + ****************************************************************************/ + +#define DDFLIP_WAIT 0x00000001l + + +/**************************************************************************** + * + * DIRECTDRAW SURFACE OVERLAY FLAGS + * + ****************************************************************************/ + +/* + * Use the alpha information in the pixel format or the alpha channel surface + * attached to the destination surface as the alpha channel for the + * destination overlay. + */ +#define DDOVER_ALPHADEST 0x00000001l + +/* + * Use the dwConstAlphaDest field in the DDOVERLAYFX structure as the + * destination alpha channel for this overlay. + */ +#define DDOVER_ALPHADESTCONSTOVERRIDE 0x00000002l + +/* + * The NEG suffix indicates that the destination surface becomes more + * transparent as the alpha value increases. + */ +#define DDOVER_ALPHADESTNEG 0x00000004l + +/* + * Use the lpDDSAlphaDest field in the DDOVERLAYFX structure as the alpha + * channel destination for this overlay. + */ +#define DDOVER_ALPHADESTSURFACEOVERRIDE 0x00000008l + +/* + * Use the dwAlphaEdgeBlend field in the DDOVERLAYFX structure as the alpha + * channel for the edges of the image that border the color key colors. + */ +#define DDOVER_ALPHAEDGEBLEND 0x00000010l + +/* + * Use the alpha information in the pixel format or the alpha channel surface + * attached to the source surface as the source alpha channel for this overlay. + */ +#define DDOVER_ALPHASRC 0x00000020l + +/* + * Use the dwConstAlphaSrc field in the DDOVERLAYFX structure as the source + * alpha channel for this overlay. + */ +#define DDOVER_ALPHASRCCONSTOVERRIDE 0x00000040l + +/* + * The NEG suffix indicates that the source surface becomes more transparent + * as the alpha value increases. + */ +#define DDOVER_ALPHASRCNEG 0x00000080l + +/* + * Use the lpDDSAlphaSrc field in the DDOVERLAYFX structure as the alpha channel + * source for this overlay. + */ +#define DDOVER_ALPHASRCSURFACEOVERRIDE 0x00000100l + +/* + * Turn this overlay off. + */ +#define DDOVER_HIDE 0x00000200l + +/* + * Use the color key associated with the destination surface. + */ +#define DDOVER_KEYDEST 0x00000400l + +/* + * Use the dckDestColorkey field in the DDOVERLAYFX structure as the color key + * for the destination surface + */ +#define DDOVER_KEYDESTOVERRIDE 0x00000800l + +/* + * Use the color key associated with the source surface. + */ +#define DDOVER_KEYSRC 0x00001000l + +/* + * Use the dckSrcColorkey field in the DDOVERLAYFX structure as the color key + * for the source surface. + */ +#define DDOVER_KEYSRCOVERRIDE 0x00002000l + +/* + * Turn this overlay on. + */ +#define DDOVER_SHOW 0x00004000l + +/* + * Add a dirty rect to an emulated overlayed surface. + */ +#define DDOVER_ADDDIRTYRECT 0x00008000l + +/* + * Redraw all dirty rects on an emulated overlayed surface. + */ +#define DDOVER_REFRESHDIRTYRECTS 0x00010000l + +/* + * Redraw the entire surface on an emulated overlayed surface. + */ +#define DDOVER_REFRESHALL 0x00020000l + + +/* + * Use the overlay FX flags to define special overlay FX + */ +#define DDOVER_DDFX 0x00080000l + + +/**************************************************************************** + * + * DIRECTDRAWSURFACE LOCK FLAGS + * + ****************************************************************************/ + +/* + * The default. Set to indicate that Lock should return a valid memory pointer + * to the top of the specified rectangle. If no rectangle is specified then a + * pointer to the top of the surface is returned. + */ +#define DDLOCK_SURFACEMEMORYPTR 0x00000000L // default + +/* + * Set to indicate that Lock should wait until it can obtain a valid memory + * pointer before returning. If this bit is set, Lock will never return + * DDERR_WASSTILLDRAWING. + */ +#define DDLOCK_WAIT 0x00000001L + +/* + * Set if an event handle is being passed to Lock. Lock will trigger the event + * when it can return the surface memory pointer requested. + */ +#define DDLOCK_EVENT 0x00000002L + +/* + * Indicates that the surface being locked will only be read from. + */ +#define DDLOCK_READONLY 0x00000010L + +/* + * Indicates that the surface being locked will only be written to + */ +#define DDLOCK_WRITEONLY 0x00000020L + + +/**************************************************************************** + * + * DIRECTDRAWSURFACE PAGELOCK FLAGS + * + ****************************************************************************/ + +/* + * No flags defined at present + */ + + +/**************************************************************************** + * + * DIRECTDRAWSURFACE PAGEUNLOCK FLAGS + * + ****************************************************************************/ + +/* + * No flags defined at present + */ + + +/**************************************************************************** + * + * DIRECTDRAWSURFACE BLT FX FLAGS + * + ****************************************************************************/ + +/* + * If stretching, use arithmetic stretching along the Y axis for this blt. + */ +#define DDBLTFX_ARITHSTRETCHY 0x00000001l + +/* + * Do this blt mirroring the surface left to right. Spin the + * surface around its y-axis. + */ +#define DDBLTFX_MIRRORLEFTRIGHT 0x00000002l + +/* + * Do this blt mirroring the surface up and down. Spin the surface + * around its x-axis. + */ +#define DDBLTFX_MIRRORUPDOWN 0x00000004l + +/* + * Schedule this blt to avoid tearing. + */ +#define DDBLTFX_NOTEARING 0x00000008l + +/* + * Do this blt rotating the surface one hundred and eighty degrees. + */ +#define DDBLTFX_ROTATE180 0x00000010l + +/* + * Do this blt rotating the surface two hundred and seventy degrees. + */ +#define DDBLTFX_ROTATE270 0x00000020l + +/* + * Do this blt rotating the surface ninety degrees. + */ +#define DDBLTFX_ROTATE90 0x00000040l + +/* + * Do this z blt using dwZBufferLow and dwZBufferHigh as range values + * specified to limit the bits copied from the source surface. + */ +#define DDBLTFX_ZBUFFERRANGE 0x00000080l + +/* + * Do this z blt adding the dwZBufferBaseDest to each of the sources z values + * before comparing it with the desting z values. + */ +#define DDBLTFX_ZBUFFERBASEDEST 0x00000100l + +/**************************************************************************** + * + * DIRECTDRAWSURFACE OVERLAY FX FLAGS + * + ****************************************************************************/ + +/* + * If stretching, use arithmetic stretching along the Y axis for this overlay. + */ +#define DDOVERFX_ARITHSTRETCHY 0x00000001l + +/* + * Mirror the overlay across the vertical axis + */ +#define DDOVERFX_MIRRORLEFTRIGHT 0x00000002l + +/* + * Mirror the overlay across the horizontal axis + */ +#define DDOVERFX_MIRRORUPDOWN 0x00000004l + +/**************************************************************************** + * + * DIRECTDRAW WAITFORVERTICALBLANK FLAGS + * + ****************************************************************************/ + +/* + * return when the vertical blank interval begins + */ +#define DDWAITVB_BLOCKBEGIN 0x00000001l + +/* + * set up an event to trigger when the vertical blank begins + */ +#define DDWAITVB_BLOCKBEGINEVENT 0x00000002l + +/* + * return when the vertical blank interval ends and display begins + */ +#define DDWAITVB_BLOCKEND 0x00000004l + +/**************************************************************************** + * + * DIRECTDRAW GETFLIPSTATUS FLAGS + * + ****************************************************************************/ + +/* + * is it OK to flip now? + */ +#define DDGFS_CANFLIP 0x00000001l + +/* + * is the last flip finished? + */ +#define DDGFS_ISFLIPDONE 0x00000002l + +/**************************************************************************** + * + * DIRECTDRAW GETBLTSTATUS FLAGS + * + ****************************************************************************/ + +/* + * is it OK to blt now? + */ +#define DDGBS_CANBLT 0x00000001l + +/* + * is the blt to the surface finished? + */ +#define DDGBS_ISBLTDONE 0x00000002l + + +/**************************************************************************** + * + * DIRECTDRAW ENUMOVERLAYZORDER FLAGS + * + ****************************************************************************/ + +/* + * Enumerate overlays back to front. + */ +#define DDENUMOVERLAYZ_BACKTOFRONT 0x00000000l + +/* + * Enumerate overlays front to back + */ +#define DDENUMOVERLAYZ_FRONTTOBACK 0x00000001l + +/**************************************************************************** + * + * DIRECTDRAW UPDATEOVERLAYZORDER FLAGS + * + ****************************************************************************/ + +/* + * Send overlay to front + */ +#define DDOVERZ_SENDTOFRONT 0x00000000l + +/* + * Send overlay to back + */ +#define DDOVERZ_SENDTOBACK 0x00000001l + +/* + * Move Overlay forward + */ +#define DDOVERZ_MOVEFORWARD 0x00000002l + +/* + * Move Overlay backward + */ +#define DDOVERZ_MOVEBACKWARD 0x00000003l + +/* + * Move Overlay in front of relative surface + */ +#define DDOVERZ_INSERTINFRONTOF 0x00000004l + +/* + * Move Overlay in back of relative surface + */ +#define DDOVERZ_INSERTINBACKOF 0x00000005l + +/*=========================================================================== + * + * + * DIRECTDRAW RETURN CODES + * + * The return values from DirectDraw Commands and Surface that return an HRESULT + * are codes from DirectDraw concerning the results of the action + * requested by DirectDraw. + * + *==========================================================================*/ + +/* + * Status is OK + * + * Issued by: DirectDraw Commands and all callbacks + */ +#define DD_OK 0 + +/**************************************************************************** + * + * DIRECTDRAW ENUMCALLBACK RETURN VALUES + * + * EnumCallback returns are used to control the flow of the DIRECTDRAW and + * DIRECTDRAWSURFACE object enumerations. They can only be returned by + * enumeration callback routines. + * + ****************************************************************************/ + +/* + * stop the enumeration + */ +#define DDENUMRET_CANCEL 0 + +/* + * continue the enumeration + */ +#define DDENUMRET_OK 1 + +/**************************************************************************** + * + * DIRECTDRAW ERRORS + * + * Errors are represented by negative values and cannot be combined. + * + ****************************************************************************/ + +/* + * This object is already initialized + */ +#define DDERR_ALREADYINITIALIZED MAKE_DDHRESULT( 5 ) + +/* + * This surface can not be attached to the requested surface. + */ +#define DDERR_CANNOTATTACHSURFACE MAKE_DDHRESULT( 10 ) + +/* + * This surface can not be detached from the requested surface. + */ +#define DDERR_CANNOTDETACHSURFACE MAKE_DDHRESULT( 20 ) + +/* + * Support is currently not available. + */ +#define DDERR_CURRENTLYNOTAVAIL MAKE_DDHRESULT( 40 ) + +/* + * An exception was encountered while performing the requested operation + */ +#define DDERR_EXCEPTION MAKE_DDHRESULT( 55 ) + +/* + * Generic failure. + */ +#define DDERR_GENERIC E_FAIL + +/* + * Height of rectangle provided is not a multiple of reqd alignment + */ +#define DDERR_HEIGHTALIGN MAKE_DDHRESULT( 90 ) + +/* + * Unable to match primary surface creation request with existing + * primary surface. + */ +#define DDERR_INCOMPATIBLEPRIMARY MAKE_DDHRESULT( 95 ) + +/* + * One or more of the caps bits passed to the callback are incorrect. + */ +#define DDERR_INVALIDCAPS MAKE_DDHRESULT( 100 ) + +/* + * DirectDraw does not support provided Cliplist. + */ +#define DDERR_INVALIDCLIPLIST MAKE_DDHRESULT( 110 ) + +/* + * DirectDraw does not support the requested mode + */ +#define DDERR_INVALIDMODE MAKE_DDHRESULT( 120 ) + +/* + * DirectDraw received a pointer that was an invalid DIRECTDRAW object. + */ +#define DDERR_INVALIDOBJECT MAKE_DDHRESULT( 130 ) + +/* + * One or more of the parameters passed to the callback function are + * incorrect. + */ +#define DDERR_INVALIDPARAMS E_INVALIDARG + +/* + * pixel format was invalid as specified + */ +#define DDERR_INVALIDPIXELFORMAT MAKE_DDHRESULT( 145 ) + +/* + * Rectangle provided was invalid. + */ +#define DDERR_INVALIDRECT MAKE_DDHRESULT( 150 ) + +/* + * Operation could not be carried out because one or more surfaces are locked + */ +#define DDERR_LOCKEDSURFACES MAKE_DDHRESULT( 160 ) + +/* + * There is no 3D present. + */ +#define DDERR_NO3D MAKE_DDHRESULT( 170 ) + +/* + * Operation could not be carried out because there is no alpha accleration + * hardware present or available. + */ +#define DDERR_NOALPHAHW MAKE_DDHRESULT( 180 ) + + +/* + * no clip list available + */ +#define DDERR_NOCLIPLIST MAKE_DDHRESULT( 205 ) + +/* + * Operation could not be carried out because there is no color conversion + * hardware present or available. + */ +#define DDERR_NOCOLORCONVHW MAKE_DDHRESULT( 210 ) + +/* + * Create function called without DirectDraw object method SetCooperativeLevel + * being called. + */ +#define DDERR_NOCOOPERATIVELEVELSET MAKE_DDHRESULT( 212 ) + +/* + * Surface doesn't currently have a color key + */ +#define DDERR_NOCOLORKEY MAKE_DDHRESULT( 215 ) + +/* + * Operation could not be carried out because there is no hardware support + * of the dest color key. + */ +#define DDERR_NOCOLORKEYHW MAKE_DDHRESULT( 220 ) + +/* + * No DirectDraw support possible with current display driver + */ +#define DDERR_NODIRECTDRAWSUPPORT MAKE_DDHRESULT( 222 ) + +/* + * Operation requires the application to have exclusive mode but the + * application does not have exclusive mode. + */ +#define DDERR_NOEXCLUSIVEMODE MAKE_DDHRESULT( 225 ) + +/* + * Flipping visible surfaces is not supported. + */ +#define DDERR_NOFLIPHW MAKE_DDHRESULT( 230 ) + +/* + * There is no GDI present. + */ +#define DDERR_NOGDI MAKE_DDHRESULT( 240 ) + +/* + * Operation could not be carried out because there is no hardware present + * or available. + */ +#define DDERR_NOMIRRORHW MAKE_DDHRESULT( 250 ) + +/* + * Requested item was not found + */ +#define DDERR_NOTFOUND MAKE_DDHRESULT( 255 ) + +/* + * Operation could not be carried out because there is no overlay hardware + * present or available. + */ +#define DDERR_NOOVERLAYHW MAKE_DDHRESULT( 260 ) + +/* + * Operation could not be carried out because there is no appropriate raster + * op hardware present or available. + */ +#define DDERR_NORASTEROPHW MAKE_DDHRESULT( 280 ) + +/* + * Operation could not be carried out because there is no rotation hardware + * present or available. + */ +#define DDERR_NOROTATIONHW MAKE_DDHRESULT( 290 ) + +/* + * Operation could not be carried out because there is no hardware support + * for stretching + */ +#define DDERR_NOSTRETCHHW MAKE_DDHRESULT( 310 ) + +/* + * DirectDrawSurface is not in 4 bit color palette and the requested operation + * requires 4 bit color palette. + */ +#define DDERR_NOT4BITCOLOR MAKE_DDHRESULT( 316 ) + +/* + * DirectDrawSurface is not in 4 bit color index palette and the requested + * operation requires 4 bit color index palette. + */ +#define DDERR_NOT4BITCOLORINDEX MAKE_DDHRESULT( 317 ) + +/* + * DirectDraw Surface is not in 8 bit color mode and the requested operation + * requires 8 bit color. + */ +#define DDERR_NOT8BITCOLOR MAKE_DDHRESULT( 320 ) + +/* + * Operation could not be carried out because there is no texture mapping + * hardware present or available. + */ +#define DDERR_NOTEXTUREHW MAKE_DDHRESULT( 330 ) + +/* + * Operation could not be carried out because there is no hardware support + * for vertical blank synchronized operations. + */ +#define DDERR_NOVSYNCHW MAKE_DDHRESULT( 335 ) + +/* + * Operation could not be carried out because there is no hardware support + * for zbuffer blting. + */ +#define DDERR_NOZBUFFERHW MAKE_DDHRESULT( 340 ) + +/* + * Overlay surfaces could not be z layered based on their BltOrder because + * the hardware does not support z layering of overlays. + */ +#define DDERR_NOZOVERLAYHW MAKE_DDHRESULT( 350 ) + +/* + * The hardware needed for the requested operation has already been + * allocated. + */ +#define DDERR_OUTOFCAPS MAKE_DDHRESULT( 360 ) + +/* + * DirectDraw does not have enough memory to perform the operation. + */ +#define DDERR_OUTOFMEMORY E_OUTOFMEMORY + +/* + * DirectDraw does not have enough memory to perform the operation. + */ +#define DDERR_OUTOFVIDEOMEMORY MAKE_DDHRESULT( 380 ) + +/* + * hardware does not support clipped overlays + */ +#define DDERR_OVERLAYCANTCLIP MAKE_DDHRESULT( 382 ) + +/* + * Can only have ony color key active at one time for overlays + */ +#define DDERR_OVERLAYCOLORKEYONLYONEACTIVE MAKE_DDHRESULT( 384 ) + +/* + * Access to this palette is being refused because the palette is already + * locked by another thread. + */ +#define DDERR_PALETTEBUSY MAKE_DDHRESULT( 387 ) + +/* + * No src color key specified for this operation. + */ +#define DDERR_COLORKEYNOTSET MAKE_DDHRESULT( 400 ) + +/* + * This surface is already attached to the surface it is being attached to. + */ +#define DDERR_SURFACEALREADYATTACHED MAKE_DDHRESULT( 410 ) + +/* + * This surface is already a dependency of the surface it is being made a + * dependency of. + */ +#define DDERR_SURFACEALREADYDEPENDENT MAKE_DDHRESULT( 420 ) + +/* + * Access to this surface is being refused because the surface is already + * locked by another thread. + */ +#define DDERR_SURFACEBUSY MAKE_DDHRESULT( 430 ) + +/* + * Access to this surface is being refused because no driver exists + * which can supply a pointer to the surface. + * This is most likely to happen when attempting to lock the primary + * surface when no DCI provider is present. + */ +#define DDERR_CANTLOCKSURFACE MAKE_DDHRESULT( 435 ) + +/* + * Access to Surface refused because Surface is obscured. + */ +#define DDERR_SURFACEISOBSCURED MAKE_DDHRESULT( 440 ) + +/* + * Access to this surface is being refused because the surface is gone. + * The DIRECTDRAWSURFACE object representing this surface should + * have Restore called on it. + */ +#define DDERR_SURFACELOST MAKE_DDHRESULT( 450 ) + +/* + * The requested surface is not attached. + */ +#define DDERR_SURFACENOTATTACHED MAKE_DDHRESULT( 460 ) + +/* + * Height requested by DirectDraw is too large. + */ +#define DDERR_TOOBIGHEIGHT MAKE_DDHRESULT( 470 ) + +/* + * Size requested by DirectDraw is too large -- The individual height and + * width are OK. + */ +#define DDERR_TOOBIGSIZE MAKE_DDHRESULT( 480 ) + +/* + * Width requested by DirectDraw is too large. + */ +#define DDERR_TOOBIGWIDTH MAKE_DDHRESULT( 490 ) + +/* + * Action not supported. + */ +#define DDERR_UNSUPPORTED E_NOTIMPL + +/* + * FOURCC format requested is unsupported by DirectDraw + */ +#define DDERR_UNSUPPORTEDFORMAT MAKE_DDHRESULT( 510 ) + +/* + * Bitmask in the pixel format requested is unsupported by DirectDraw + */ +#define DDERR_UNSUPPORTEDMASK MAKE_DDHRESULT( 520 ) + +/* + * vertical blank is in progress + */ +#define DDERR_VERTICALBLANKINPROGRESS MAKE_DDHRESULT( 537 ) + +/* + * Informs DirectDraw that the previous Blt which is transfering information + * to or from this Surface is incomplete. + */ +#define DDERR_WASSTILLDRAWING MAKE_DDHRESULT( 540 ) + +/* + * Rectangle provided was not horizontally aligned on reqd. boundary + */ +#define DDERR_XALIGN MAKE_DDHRESULT( 560 ) + +/* + * The GUID passed to DirectDrawCreate is not a valid DirectDraw driver + * identifier. + */ +#define DDERR_INVALIDDIRECTDRAWGUID MAKE_DDHRESULT( 561 ) + +/* + * A DirectDraw object representing this driver has already been created + * for this process. + */ +#define DDERR_DIRECTDRAWALREADYCREATED MAKE_DDHRESULT( 562 ) + +/* + * A hardware only DirectDraw object creation was attempted but the driver + * did not support any hardware. + */ +#define DDERR_NODIRECTDRAWHW MAKE_DDHRESULT( 563 ) + +/* + * this process already has created a primary surface + */ +#define DDERR_PRIMARYSURFACEALREADYEXISTS MAKE_DDHRESULT( 564 ) + +/* + * software emulation not available. + */ +#define DDERR_NOEMULATION MAKE_DDHRESULT( 565 ) + +/* + * region passed to Clipper::GetClipList is too small. + */ +#define DDERR_REGIONTOOSMALL MAKE_DDHRESULT( 566 ) + +/* + * an attempt was made to set a clip list for a clipper objec that + * is already monitoring an hwnd. + */ +#define DDERR_CLIPPERISUSINGHWND MAKE_DDHRESULT( 567 ) + +/* + * No clipper object attached to surface object + */ +#define DDERR_NOCLIPPERATTACHED MAKE_DDHRESULT( 568 ) + +/* + * Clipper notification requires an HWND or + * no HWND has previously been set as the CooperativeLevel HWND. + */ +#define DDERR_NOHWND MAKE_DDHRESULT( 569 ) + +/* + * HWND used by DirectDraw CooperativeLevel has been subclassed, + * this prevents DirectDraw from restoring state. + */ +#define DDERR_HWNDSUBCLASSED MAKE_DDHRESULT( 570 ) + +/* + * The CooperativeLevel HWND has already been set. + * It can not be reset while the process has surfaces or palettes created. + */ +#define DDERR_HWNDALREADYSET MAKE_DDHRESULT( 571 ) + +/* + * No palette object attached to this surface. + */ +#define DDERR_NOPALETTEATTACHED MAKE_DDHRESULT( 572 ) + +/* + * No hardware support for 16 or 256 color palettes. + */ +#define DDERR_NOPALETTEHW MAKE_DDHRESULT( 573 ) + +/* + * If a clipper object is attached to the source surface passed into a + * BltFast call. + */ +#define DDERR_BLTFASTCANTCLIP MAKE_DDHRESULT( 574 ) + +/* + * No blter. + */ +#define DDERR_NOBLTHW MAKE_DDHRESULT( 575 ) + +/* + * No DirectDraw ROP hardware. + */ +#define DDERR_NODDROPSHW MAKE_DDHRESULT( 576 ) + +/* + * returned when GetOverlayPosition is called on a hidden overlay + */ +#define DDERR_OVERLAYNOTVISIBLE MAKE_DDHRESULT( 577 ) + +/* + * returned when GetOverlayPosition is called on a overlay that UpdateOverlay + * has never been called on to establish a destionation. + */ +#define DDERR_NOOVERLAYDEST MAKE_DDHRESULT( 578 ) + +/* + * returned when the position of the overlay on the destionation is no longer + * legal for that destionation. + */ +#define DDERR_INVALIDPOSITION MAKE_DDHRESULT( 579 ) + +/* + * returned when an overlay member is called for a non-overlay surface + */ +#define DDERR_NOTAOVERLAYSURFACE MAKE_DDHRESULT( 580 ) + +/* + * An attempt was made to set the cooperative level when it was already + * set to exclusive. + */ +#define DDERR_EXCLUSIVEMODEALREADYSET MAKE_DDHRESULT( 581 ) + +/* + * An attempt has been made to flip a surface that is not flippable. + */ +#define DDERR_NOTFLIPPABLE MAKE_DDHRESULT( 582 ) + +/* + * Can't duplicate primary & 3D surfaces, or surfaces that are implicitly + * created. + */ +#define DDERR_CANTDUPLICATE MAKE_DDHRESULT( 583 ) + +/* + * Surface was not locked. An attempt to unlock a surface that was not + * locked at all, or by this process, has been attempted. + */ +#define DDERR_NOTLOCKED MAKE_DDHRESULT( 584 ) + +/* + * Windows can not create any more DCs + */ +#define DDERR_CANTCREATEDC MAKE_DDHRESULT( 585 ) + +/* + * No DC was ever created for this surface. + */ +#define DDERR_NODC MAKE_DDHRESULT( 586 ) + +/* + * This surface can not be restored because it was created in a different + * mode. + */ +#define DDERR_WRONGMODE MAKE_DDHRESULT( 587 ) + +/* + * This surface can not be restored because it is an implicitly created + * surface. + */ +#define DDERR_IMPLICITLYCREATED MAKE_DDHRESULT( 588 ) + +/* + * The surface being used is not a palette-based surface + */ +#define DDERR_NOTPALETTIZED MAKE_DDHRESULT( 589 ) + + +/* + * The display is currently in an unsupported mode + */ +#define DDERR_UNSUPPORTEDMODE MAKE_DDHRESULT( 590 ) + +/* + * Operation could not be carried out because there is no mip-map + * texture mapping hardware present or available. + */ +#define DDERR_NOMIPMAPHW MAKE_DDHRESULT( 591 ) + +/* + * The requested action could not be performed because the surface was of + * the wrong type. + */ +#define DDERR_INVALIDSURFACETYPE MAKE_DDHRESULT( 592 ) + + + +/* + * A DC has already been returned for this surface. Only one DC can be + * retrieved per surface. + */ +#define DDERR_DCALREADYCREATED MAKE_DDHRESULT( 620 ) + +/* + * The attempt to page lock a surface failed. + */ +#define DDERR_CANTPAGELOCK MAKE_DDHRESULT( 640 ) + +/* + * The attempt to page unlock a surface failed. + */ +#define DDERR_CANTPAGEUNLOCK MAKE_DDHRESULT( 660 ) + +/* + * An attempt was made to page unlock a surface with no outstanding page locks. + */ +#define DDERR_NOTPAGELOCKED MAKE_DDHRESULT( 680 ) + +/* + * An attempt was made to invoke an interface member of a DirectDraw object + * created by CoCreateInstance() before it was initialized. + */ +#define DDERR_NOTINITIALIZED CO_E_NOTINITIALIZED + +/* Alpha bit depth constants */ + + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/src/DDRAW.LIB b/src/DDRAW.LIB new file mode 100644 index 0000000..7dbd0aa Binary files /dev/null and b/src/DDRAW.LIB differ diff --git a/src/DEAD.CPP b/src/DEAD.CPP new file mode 100644 index 0000000..cd33208 --- /dev/null +++ b/src/DEAD.CPP @@ -0,0 +1,123 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Dead file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DEAD.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "dead.h" +#include "monster.h" +#include "monstint.h" +#include "missiles.h" +#include "misdat.h" +#include "gendung.h" +#include "lighting.h" + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +DeadStruct dead[MAXDEAD]; +int spurtndx; +int stonendx; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitDead () +{ + int nd,i,j,mi; + int mtypes[MONSTERTYPES]; + + for (i = 0; i < MONSTERTYPES; i++) mtypes[i] = 0; + + nd = 0; + for (i = 0; i < nummtypes; i++) { + if (mtypes[Monsters[i].mtype] == 0) { + for (j = 0; j < 8; j++) dead[nd]._deadData[j] = Monsters[i].Anims[MA_DEATH].Cels[j]; + dead[nd]._deadFrame = Monsters[i].Anims[MA_DEATH].Frames; + dead[nd]._deadWidth = Monsters[i].mAnimWidth; + dead[nd]._deadWidth2 = Monsters[i].mAnimWidth2; + dead[nd]._deadtrans = 0; + Monsters[i].mdeadval = nd + 1; + mtypes[Monsters[i].mtype] = nd + 1; + nd++; + } + } + + // set blood burst dead frames + for (j = 0; j < 8; j++) dead[nd]._deadData[j] = misfiledata[MF_SPURT].mAnimData[0]; + dead[nd]._deadFrame = 8; + dead[nd]._deadWidth = 128; + dead[nd]._deadWidth2 = (128 - 64) >> 1; + dead[nd]._deadtrans = 0; + spurtndx = nd + 1; + nd++; + // set stone dead frames + for (j = 0; j < 8; j++) dead[nd]._deadData[j] = misfiledata[MF_STONE].mAnimData[0]; + dead[nd]._deadFrame = 12; + dead[nd]._deadWidth = 128; + dead[nd]._deadWidth2 = (128 - 64) >> 1; + dead[nd]._deadtrans = 0; + stonendx = nd + 1; + nd++; + + // set unique monster dead frames + for (i = 0; i < nummonsters; i++) { + mi = monstactive[i]; + if (monster[mi]._uniqtype != 0) { + for (j = 0; j < 8; j++) dead[nd]._deadData[j] = monster[mi].MType->Anims[MA_DEATH].Cels[j]; + dead[nd]._deadFrame = monster[mi].MType->Anims[MA_DEATH].Frames; + dead[nd]._deadWidth = monster[mi].MType->mAnimWidth; + dead[nd]._deadWidth2 = monster[mi].MType->mAnimWidth2; + dead[nd]._deadtrans = LIGHT_U + monster[mi]._uniqtrans; + monster[mi]._udeadval = nd + 1; + nd++; + } + } + app_assert(nd <= MAXDEAD); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddDead(int dx, int dy, char dv, int ddir) +{ + char tdv; + + tdv = (dv & 0x1f) + ((ddir & 0x7) << 5); + dDead[dx][dy] = tdv; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncUniqDead() +{ + int i,mi; + int x,y; + + // See function InitDead() to understand what this is all about + + for (i = 0; i < nummonsters; i++) { + mi = monstactive[i]; + if (monster[mi]._uniqtype != 0) { + + // Search dDead array for this dead type, and place a light source there + for(x=0; x < DMAXX; x++) + for(y=0; y < DMAXY; y++) + if((dDead[x][y] & 0x1f) == monster[mi]._udeadval) + ChangeLightXY(monster[mi].mlid, x, y); + } + } +} diff --git a/src/DEAD.H b/src/DEAD.H new file mode 100644 index 0000000..c1ed909 --- /dev/null +++ b/src/DEAD.H @@ -0,0 +1,43 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/DEAD.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXDEAD 31 // Always will be 31! + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + BYTE *_deadData[8]; // Data pointer to anim tables + int _deadFrame; // current dead frame + long _deadWidth; // width of dead + long _deadWidth2; // (width - 64) / 2 of dead for drawing + char _deadtrans; // translations for unique monsters +} DeadStruct; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern DeadStruct dead[MAXDEAD]; +extern int spurtndx; +extern int stonendx; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitDead(); +void AddDead(int, int, char, int); +void SyncUniqDead(); diff --git a/src/DEBUG.CPP b/src/DEBUG.CPP new file mode 100644 index 0000000..bd01c00 --- /dev/null +++ b/src/DEBUG.CPP @@ -0,0 +1,350 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Debugging file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DEBUG.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "debug.h" +#include "engine.h" +#include "error.h" + +#include "items.h" +#include "gendung.h" +#include "player.h" + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BYTE *pSquareCel; + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitDebugGFX() { + app_assert(! pSquareCel); + if (visiondebug) + pSquareCel = LoadFileInMemSig("Data\\Square.CEL",NULL,'DBGS'); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void FreeDebugGFX() { + DiabloFreePtr(pSquareCel); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define DEBUGSEEDS 4096 + +int debugseeds[DEBUGSEEDS]; +//int seedcnt, seedidx[17]; +int seedcnt, seedidx[NUMLEVELS+1]; // JKE to add crypt +BOOL seedflag = FALSE; + +void InitDebugSeeds() +{ + for (int i = 0; i < DEBUGSEEDS; i++) debugseeds[i] = -1; + seedcnt = 0; + for (i = 0; i < 17; i++) seedidx[i] = 0; +} + +void StartDebugSeeds() +{ + if (currlevel == 0) return; + seedcnt = seedidx[currlevel]; + seedflag = TRUE; +} + +void EndDebugSeeds() +{ + if (currlevel == 0) return; + seedidx[currlevel+1] = seedcnt; + seedflag = FALSE; +} + +void SaveDebugSeed(int s) +{ + if (!seedflag) return; + if (seedcnt == DEBUGSEEDS) return; + if (currlevel == 0) return; + if (debugseeds[seedcnt] == -1) { + debugseeds[seedcnt] = s; + } else { + if (debugseeds[seedcnt] != s) app_fatal("Seeds desynced"); + } + seedcnt++; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#if 0 +char davehold1[5][MAXDUNX][MAXDUNY]; +char davehold2[5][MAXDUNX][MAXDUNY]; +BOOL daveinited[5] = { FALSE, FALSE, FALSE, FALSE, FALSE }; + +#define LEVELCHECK 1 + +void DaveCheck() +{ + int xp, yp; + + //if (currlevel != LEVELCHECK) return; + if (currlevel == 0) return; + if (currlevel >= 5) return; + for (yp = 0; yp < MAXDUNY; yp++) { + for (xp = 0; xp < MAXDUNX; xp++) { + if (dMonster[xp][yp] != 0) app_fatal("Monsters not cleared"); + if (dPlayer[xp][yp] != 0) app_fatal("Players not cleared"); + if (daveinited[currlevel]) { + if (davehold1[currlevel][xp][yp] != (dFlags[xp][yp] & BFLAG_MONSTACTIVE)) + app_fatal("MonstActive not same"); + if (davehold2[currlevel][xp][yp] != (dFlags[xp][yp] & BFLAG_SETPC)) + app_fatal("Set Piece not same"); + } else { + davehold1[currlevel][xp][yp] = dFlags[xp][yp] & BFLAG_MONSTACTIVE; + davehold2[currlevel][xp][yp] = dFlags[xp][yp] & BFLAG_SETPC; + } + } + } + daveinited[currlevel] = TRUE; +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#if 1 +#include "msg.h" +int blipplr = 0; + +void BlipDebug(BOOL next) +{ + if (next) blipplr = (blipplr + 1) & 0x3; + + int i = blipplr; + char tempstr[128]; + + sprintf(tempstr, "Plr %i : Active = %i", i, plr[i].plractive); + NetSendString((1 << myplr), tempstr); + if (plr[i].plractive) { + sprintf(tempstr, " Plr %i is %s", i, plr[i]._pName); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, " Lvl = %i : Change = %i", plr[i].plrlevel, plr[i]._pLvlChanging); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, " x = %i, y = %i : tx = %i, ty = %i : fx = %i, fy = %i", + plr[i]._px, plr[i]._py, plr[i]._ptargx, plr[i]._ptargy, plr[i]._pfutx, plr[i]._pfuty); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, " mode = %i : daction = %i : walk[0] = %i", plr[i]._pmode, plr[i].destAction, plr[i].walkpath[0]); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, " inv = %i : hp = %i", plr[i]._pInvincible, plr[i]._pHitPoints); + NetSendString((1 << myplr), tempstr); + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#if 1 +#include "quests.h" +int currqdebug = 0; + +void PrintQuestDebug() +{ + char tempstr[128]; + + sprintf(tempstr, "Quest %i : Active = %i, Var1 = %i", currqdebug, quests[currqdebug]._qactive, quests[currqdebug]._qvar1); + NetSendString((1 << myplr),tempstr); + currqdebug++; + if (currqdebug == MAXQUESTS) currqdebug = 0; +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#if 1 +#include "monstint.h" +#include "themes.h" +#include "drlg_l4.h" +extern byte dung[L4DUNX][L4DUNY]; +extern byte L4dungeon[L4DX][L4DY]; + +char mphold1[NUMLEVELS+1][MAXDUNX][MAXDUNY]; +char mphold2[NUMLEVELS+1][MAXDUNX][MAXDUNY]; + +void DaveCheck2() +{ + int xp, yp; + + for (yp = 0; yp < MAXDUNY; yp++) { + for (xp = 0; xp < MAXDUNX; xp++) { + if (dMonster[xp][yp] != 0) app_fatal("Monsters not cleared"); + if (dPlayer[xp][yp] != 0) app_fatal("Players not cleared"); + mphold1[currlevel][xp][yp] = dFlags[xp][yp] & BFLAG_MONSTACTIVE; + mphold2[currlevel][xp][yp] = dFlags[xp][yp] & BFLAG_SETPC; + } + } +} + +/*-----------------------------------------------------------------------*/ + +void PrintDaveCheck2() +{ + int i, j, xp, yp, sum1, sum2, sum3; + long fv; + char tempstr[128]; + + sum1 = 0; + sum2 = 0; + for (yp = 0; yp < MAXDUNY; yp++) { + for (xp = 0; xp < MAXDUNX; xp++) { + sum1 += mphold1[currlevel][xp][yp]; + sum2 += mphold2[currlevel][xp][yp]; + } + } + sprintf(tempstr, "Level %i : Monst Active Sum = %i : dFlag sum = %i", currlevel, sum1, sum2); + NetSendString((1 << myplr),tempstr); + + sum1 = 0; + sum2 = 0; + for (i = 1; i <= MAXTILES; i++) { + if (nSolidTable[i]) { + sum1 += i; + sum2++; + } + } + + // Calc a volume of monsters + fv = 0; + for (i = DIRTEDGED2; i < (DMAXY - (DIRTEDGED2)); i++) { + for (j = DIRTEDGED2; j < (DMAXX - (DIRTEDGED2)); j++) { + if (!SolidLoc(i,j)) fv++; + } + } + + sum3 = 0; + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) sum3 += dungeon[i][j]; + } + + sprintf(tempstr, "Solid Sum = %i:%i : Monst Vol = %i : Dungeon Sum = %i", sum1, sum2, fv, sum3); + NetSendString((1 << myplr),tempstr); + + sum1 = 0; + for (j = 0; j < MAXDUNY; j++) { + for (i = 0; i < MAXDUNX; i++) { + sum1 += dTransVal[i][j]; + } + } + + sum2 = 0; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + sum2 += dPiece[i][j]; + } + } + + sprintf(tempstr, "Num themes = %i/%i : Trans Sum = %i : dPiece Sum = %i", numthemes, themeCount, sum1, sum2); + NetSendString((1 << myplr),tempstr); + + if (leveltype == 4) { + sum1 = 0; + for (j = 0; j < L4DUNY; j++) { + for (i = 0; i < L4DUNX; i++) sum1 += dung[i][j]; + } + sum2 = 0; + for (j = 0; j < L4DY; j++) { + for (i = 0; i < L4DX; i++) sum2 += L4dungeon[i][j]; + } + sprintf(tempstr, "dung sum = %i : L4Dungeon sum = %i", sum1, sum2); + } +} + +/*-----------------------------------------------------------------------*/ + +int dungdebugy = 0; + +void DaveDungDebug() +{ + int sum, i; + char tempstr[128]; + + sum = 0; + for (i = 0; i < MDMAXX; i++) sum += dungeon[i][dungdebugy]; + + sprintf(tempstr, "dungeon Y=%i sum = %i", dungdebugy, sum); + NetSendString((1 << myplr), tempstr); + + dungdebugy++; + if (dungdebugy == MDMAXY) dungdebugy = 0; +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#if 1 +#include "sound.h" +#include "monster.h" +#include "monstdat.h" +#include "cursor.h" + +int debugmonst = 0; + +void PrintDaveMonst(int m) +{ + char tempstr[128]; + int inlist, i; + + sprintf(tempstr, "Monster %i = %s", m, monster[m].mName); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "X = %i, Y = %i", monster[m]._mx, monster[m]._my); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "Enemy = %i, HP = %i", monster[m]._menemy, monster[m]._mhitpoints); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "Mode = %i, Var1 = %i", monster[m]._mmode, monster[m]._mVar1); + NetSendString((1 << myplr), tempstr); + inlist = 0; + for (i = 0; i < nummonsters; i++) { + if (monstactive[i] == m) inlist = 1; + } + sprintf(tempstr, "Active List = %i, Squelch = %i", inlist, monster[m]._msquelch); + NetSendString((1 << myplr), tempstr); +} + +void DaveDebugMonst() +{ + int cm; + + if (cursmonst == -1) { + if (dMonster[cursmx][cursmy] == 0) cm = debugmonst; + else { + if (dMonster[cursmx][cursmy] > 0) cm = dMonster[cursmx][cursmy] - 1; + else cm = -(dMonster[cursmx][cursmy] + 1); + } + } else cm = cursmonst; + + PrintDaveMonst(cm); +} + +void DaveDebugMonst2() +{ + char tempstr[128]; + debugmonst++; + if (debugmonst == MAXMONSTERS) debugmonst = 0; + sprintf(tempstr, "Current debug monster = %i", debugmonst); + NetSendString((1 << myplr), tempstr); +} + +#endif diff --git a/src/DEBUG.H b/src/DEBUG.H new file mode 100644 index 0000000..184af69 --- /dev/null +++ b/src/DEBUG.H @@ -0,0 +1,19 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/DEBUG.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern BYTE *pSquareCel; + +void InitDebugSeeds(); +void StartDebugSeeds(); +void EndDebugSeeds(); +void SaveDebugSeed(int s); diff --git a/src/DIABLO.APS b/src/DIABLO.APS new file mode 100644 index 0000000..3b2f209 Binary files /dev/null and b/src/DIABLO.APS differ diff --git a/src/DIABLO.BAK b/src/DIABLO.BAK new file mode 100644 index 0000000..3313b7c --- /dev/null +++ b/src/DIABLO.BAK @@ -0,0 +1,5342 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +!IF "$(CFG)" == "" +CFG=Diablo - Win32 Debug +!MESSAGE No configuration specified. Defaulting to Diablo - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Diablo - Win32 Release" && "$(CFG)" != "Diablo - Win32 Debug"\ + && "$(CFG)" != "Diablo - Win32 FinalFinal" && "$(CFG)" !=\ + "Diablo - Win32 Shareware FinalFinal" && "$(CFG)" !=\ + "Diablo - Win32 Shareware Release" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "DIABLO.MAK" CFG="Diablo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Diablo - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 FinalFinal" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Shareware FinalFinal" (based on\ + "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Shareware Release" (based on\ + "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Diablo - Win32 Debug" +CPP=cl.exe +RSC=rc.exe +MTL=mktyplib.exe + +!IF "$(CFG)" == "Diablo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : "$(OUTDIR)\DIABLO.exe" + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\scroll.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\DIABLO.exe" + -@erase "$(OUTDIR)\DIABLO.map" + -@erase "$(OUTDIR)\DIABLO.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +$(OUTDIR)/DIABLO.bsc : $(OUTDIR) $(BSC32_SBRS) +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /c +# ADD CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D PROGRAM_VERSION=RETAIL /FAcs /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG"\ + /D PROGRAM_VERSION=RETAIL /FAcs /Fa"$(INTDIR)/" /Fp"$(INTDIR)/DIABLO.pch" /YX\ + /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\WinRel/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/diablo.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/DIABLO.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /map /debug /machine:I386 /nodefaultlib +# SUBTRACT LINK32 /incremental:yes +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)/DIABLO.pdb" /map:"$(INTDIR)/DIABLO.map" /debug\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)/DIABLO.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\Diabloui.lib" \ + ".\dsound.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\DIABLO.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : "$(OUTDIR)\DIABLO.exe" + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\scroll.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\DIABLO.exe" + -@erase "$(OUTDIR)\DIABLO.map" + -@erase "$(OUTDIR)\DIABLO.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +$(OUTDIR)/DIABLO.bsc : $(OUTDIR) $(BSC32_SBRS) +# ADD BASE CPP /nologo /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /c +# ADD CPP /nologo /G5 /Gr /MT /W3 /Gm /Zi /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D PROGRAM_VERSION=RETAIL /FAcs /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Gm /Zi /Od /D "WIN32" /D "_WINDOWS" /D\ + "_DEBUG" /D PROGRAM_VERSION=RETAIL /FAcs /Fa"$(INTDIR)/"\ + /Fp"$(INTDIR)/DIABLO.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\WinDebug/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/diablo.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/DIABLO.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /incremental:no /map /debug /machine:I386 /nodefaultlib +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)/DIABLO.pdb" /map:"$(INTDIR)/DIABLO.map" /debug\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)/DIABLO.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\Diabloui.lib" \ + ".\dsound.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\DIABLO.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Diablo__" +# PROP BASE Intermediate_Dir "Diablo__" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinFinal" +# PROP Intermediate_Dir "WinFinal" +# PROP Target_Dir "" +OUTDIR=.\WinFinal +INTDIR=.\WinFinal + +ALL : "$(OUTDIR)\DIABLO.exe" + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\scroll.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\DIABLO.exe" + -@erase "$(OUTDIR)\DIABLO.map" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# SUBTRACT BASE CPP /Fr +# ADD CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D PROGRAM_VERSION=RETAIL /FAcs /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG"\ + /D PROGRAM_VERSION=RETAIL /FAcs /Fa"$(INTDIR)/" /Fp"$(INTDIR)/DIABLO.pch" /YX\ + /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\WinFinal/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/diablo.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/DIABLO.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 winspool.lib libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /map /machine:I386 /nodefaultlib +# SUBTRACT LINK32 /incremental:yes +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)/DIABLO.pdb" /map:"$(INTDIR)/DIABLO.map"\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)/DIABLO.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\Diabloui.lib" \ + ".\dsound.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\DIABLO.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Diablo__" +# PROP BASE Intermediate_Dir "Diablo__" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "SFinal" +# PROP Intermediate_Dir "SFinal" +# PROP Target_Dir "" +OUTDIR=.\SFinal +INTDIR=.\SFinal + +ALL : "$(OUTDIR)\DIABLO.exe" + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\scroll.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\DIABLO.exe" + -@erase "$(OUTDIR)\DIABLO.map" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /YX /c +# SUBTRACT BASE CPP /Fr +# ADD CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D PROGRAM_VERSION=SHAREWARE /FAcs /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG"\ + /D PROGRAM_VERSION=SHAREWARE /FAcs /Fa"$(INTDIR)/" /Fp"$(INTDIR)/DIABLO.pch"\ + /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\SFinal/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/diablo.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/DIABLO.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /map /machine:I386 /nodefaultlib +# SUBTRACT LINK32 /incremental:yes +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)/DIABLO.pdb" /map:"$(INTDIR)/DIABLO.map"\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)/DIABLO.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\Diabloui.lib" \ + ".\dsound.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\DIABLO.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Diablo_0" +# PROP BASE Intermediate_Dir "Diablo_0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "SRel" +# PROP Intermediate_Dir "SRel" +# PROP Target_Dir "" +OUTDIR=.\SRel +INTDIR=.\SRel + +ALL : "$(OUTDIR)\DIABLO.exe" + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\scroll.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\DIABLO.exe" + -@erase "$(OUTDIR)\DIABLO.map" + -@erase "$(OUTDIR)\DIABLO.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /YX /c +# SUBTRACT BASE CPP /Fr +# ADD CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D PROGRAM_VERSION=SHAREWARE /FAcs /YX /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG"\ + /D PROGRAM_VERSION=SHAREWARE /FAcs /Fa"$(INTDIR)/" /Fp"$(INTDIR)/DIABLO.pch"\ + /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\SRel/ +CPP_SBRS=.\. +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/diablo.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/DIABLO.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /map /debug /machine:I386 /nodefaultlib +# SUBTRACT LINK32 /incremental:yes +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)/DIABLO.pdb" /map:"$(INTDIR)/DIABLO.map" /debug\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)/DIABLO.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\Diabloui.lib" \ + ".\dsound.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\DIABLO.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "Diablo - Win32 Release" +# Name "Diablo - Win32 Debug" +# Name "Diablo - Win32 FinalFinal" +# Name "Diablo - Win32 Shareware FinalFinal" +# Name "Diablo - Win32 Shareware Release" + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\TOWN.CPP +DEP_CPP_TOWN_=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\GENDUNG.CPP +DEP_CPP_GENDU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SCROLLRT.CPP +DEP_CPP_SCROL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sclass.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + ".\Town.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DEAD.CPP +DEP_CPP_DEAD_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Sound.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MISSILES.CPP +DEP_CPP_MISSI=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\OBJECTS.CPP +DEP_CPP_OBJEC=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MONSTER.CPP +DEP_CPP_MONST=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sclass.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\LIGHTING.CPP +DEP_CPP_LIGHT=\ + ".\automap.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DRLG_L3.CPP +DEP_CPP_DRLG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l3.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DRLG_L2.CPP +DEP_CPP_DRLG_L=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l2.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DRLG_L1.CPP +DEP_CPP_DRLG_L1=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L1) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L1) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L1) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L1) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L1) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\TRIGS.CPP +DEP_CPP_TRIGS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DEBUG.CPP +DEP_CPP_DEBUG=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\CURSOR.CPP +DEP_CPP_CURSO=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\PALETTE.CPP +DEP_CPP_PALET=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Palette.h"\ + ".\Sclass.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DIABLO.CPP +DEP_CPP_DIABL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\mainmenu.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sclass.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\PLAYER.CPP +DEP_CPP_PLAYE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\ENGINE.CPP +DEP_CPP_ENGIN=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Palette.h"\ + ".\regconst.h"\ + ".\Sclass.h"\ + ".\Scrollrt.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\CONTROL.CPP +DEP_CPP_CONTR=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SPELLS.CPP +DEP_CPP_SPELL=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SOUND.CPP +DEP_CPP_SOUND=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MONSTDAT.CPP +DEP_CPP_MONSTD=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Sound.h"\ + ".\textdat.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONSTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONSTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONSTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONSTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONSTD) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\ITEMS.CPP +DEP_CPP_ITEMS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\inv.cpp +DEP_CPP_INV_C=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Interfac.cpp +DEP_CPP_INTER=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sclass.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Storm.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\effects.cpp +DEP_CPP_EFFEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Quests.cpp +DEP_CPP_QUEST=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\GameMenu.cpp +DEP_CPP_GAMEM=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SetMaps.cpp +DEP_CPP_SETMA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\minitext.cpp +DEP_CPP_MINIT=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\textdat.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\objdat.cpp +DEP_CPP_OBJDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\itemdat.cpp +DEP_CPP_ITEMD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Spells.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\drlg_l4.cpp +DEP_CPP_DRLG_L4=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\themes.cpp +DEP_CPP_THEME=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\stores.cpp +DEP_CPP_STORE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\spelldat.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\help.cpp +DEP_CPP_HELP_=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\automap.cpp +DEP_CPP_AUTOM=\ + ".\automap.h"\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\diablo.rc +DEP_RSC_DIABLO=\ + ".\icon1.ico"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\diablo.res" : $(SOURCE) $(DEP_RSC_DIABLO) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\diablo.res" : $(SOURCE) $(DEP_RSC_DIABLO) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\diablo.res" : $(SOURCE) $(DEP_RSC_DIABLO) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\diablo.res" : $(SOURCE) $(DEP_RSC_DIABLO) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\diablo.res" : $(SOURCE) $(DEP_RSC_DIABLO) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Storm.lib + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\error.cpp +DEP_CPP_ERROR=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Items.h"\ + ".\Scrollrt.h"\ + ".\stores.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\multi.cpp +DEP_CPP_MULTI=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Spelldat.cpp +DEP_CPP_SPELLD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Missiles.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELLD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELLD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELLD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELLD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELLD) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\spelldat.h + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\misdat.h + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\misdat.cpp +DEP_CPP_MISDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\appfat.cpp +DEP_CPP_APPFA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Sclass.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\dsound.lib + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\ddraw.lib + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\sync.cpp +DEP_CPP_SYNC_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\path.cpp +DEP_CPP_PATH_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\path.h"\ + ".\Player.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\msg.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\init.cpp +DEP_CPP_INIT_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\movie.cpp +DEP_CPP_MOVIE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Sclass.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Diabloui.lib + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\mainmenu.cpp +DEP_CPP_MAINM=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\pfile.cpp +DEP_CPP_PFILE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\mpqapi.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Sclass.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\packplr.cpp +DEP_CPP_PACKP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Sclass.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\nthread.cpp +DEP_CPP_NTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\capture.cpp +DEP_CPP_CAPTU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\encrypt.cpp +DEP_CPP_ENCRY=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\implode.h"\ + ".\mpqapi.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\mpqapi.cpp +DEP_CPP_MPQAP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\mpqapi.h"\ + ".\Sclass.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\track.cpp +DEP_CPP_TRACK=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Sclass.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\implode.lib + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Scroll.asm + +!IF "$(CFG)" == "Diablo - Win32 Release" + +# Begin Custom Build - scroll.asm +IntDir=.\WinRel +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +# End Custom Build + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +# Begin Custom Build - scroll.asm +IntDir=.\WinDebug +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +# End Custom Build + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +# Begin Custom Build - scroll.asm +IntDir=.\WinFinal +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +# End Custom Build + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +# Begin Custom Build - scroll.asm +IntDir=.\SFinal +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +# End Custom Build + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +# Begin Custom Build - scroll.asm +IntDir=.\SRel +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +# End Custom Build + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SHA.CPP +DEP_CPP_SHA_C=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\CODEC.CPP +DEP_CPP_CODEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\wave.cpp +DEP_CPP_WAVE_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\towners.cpp +DEP_CPP_TOWNE=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\plrmsg.cpp +DEP_CPP_PLRMS=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\gmenu.cpp +DEP_CPP_GMENU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\loadsave.cpp +DEP_CPP_LOADS=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\Trigs.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\portal.cpp +DEP_CPP_PORTA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\portal.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\doom.cpp +DEP_CPP_DOOM_=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Textdat.cpp +DEP_CPP_TEXTD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\MiniText.h"\ + ".\textdat.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\dx.cpp +DEP_CPP_DX_CP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Sclass.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\dthread.cpp +DEP_CPP_DTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sclass.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\tmsg.cpp +DEP_CPP_TMSG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\except.cpp +DEP_CPP_EXCEP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +!IF "$(CFG)" == "Diablo - Win32 Release" + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ENDIF + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/src/DIABLO.CPP b/src/DIABLO.CPP new file mode 100644 index 0000000..0cb50e5 --- /dev/null +++ b/src/DIABLO.CPP @@ -0,0 +1,3107 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Main file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DIABLO.CPP 16 3/29/97 9:09p Pwyatt $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "mainmenu.h" +#include "interfac.h" +#include "inv.h" +#include "msg.h" +#include "multi.h" +#include "engine.h" +#include "palette.h" +#include "scrollrt.h" +#include "gendung.h" +#include "setmaps.h" +#include "debug.h" +#include "effects.h" + +#include "dead.h" +#include "lighting.h" +#include "control.h" +#include "gamemenu.h" + +#include "items.h" +#include "player.h" +#include "monster.h" +#include "objects.h" +#include "missiles.h" +#include "trigs.h" +#include "spelldat.h" +#include "spells.h" +#include "cursor.h" + +#include "town.h" +#include "towners.h" +#include "drlg_l1.h" +#include "drlg_l2.h" +#include "drlg_l3.h" +#include "drlg_l4.h" +#include "quests.h" +#include "minitext.h" +#include "themes.h" +#include "stores.h" +#include "packplr.h" +#include "portal.h" +#include "doom.h" + +#include "automap.h" +#include "help.h" +#include "error.h" +#include "diabloui.h" +#include "textdat.h" +// pjw.patch1.start +#include "mpqapi.h" +#include +// pjw.patch1.end + +/*-----------------------------------------------------------------------** +** Registration info +**-----------------------------------------------------------------------*/ +#include "regconst.h" +char sgszTblSig[TBL_LEN] = "REGISTRATION_TABLE"; + + +/*-----------------------------------------------------------------------** +** Global Variables +**-----------------------------------------------------------------------*/ +extern char gszProgKey[]; +BYTE gbDoEnding; +void DoEnding(); + +int StripPlayer(int pnum); + +DWORD glSeedTbl[NUMLEVELS]; +int gnLevelTypeTbl[NUMLEVELS]; + +// window vars +HWND ghMainWnd; +HINSTANCE ghInst; + +// video vars +BOOL fullscreen = TRUE; + + +// mouse +int MouseX, MouseY; + +// program vars +int force_redraw = NODRAW; + +BOOL svgamode; + +// Temp vars (delete all uses before final compile) +long gv1; +long gv2; +long gv3; +long gv4; +long gv5; + +#ifndef NDEBUG +// do not change this flag -- USE 'n' on the command line +static BOOL cineflag = TRUE; +#endif + +#if CHEATS +BOOL gbDumpDropLog = FALSE; +BOOL davedebug = FALSE; +BOOL cheatflag = FALSE; // Turn invincibility and all spells on/off +BOOL simplecheat = FALSE; // like cheatflag, but doesn't screw up game +BOOL gbNoDropInactive = FALSE; // don't drop players on timeout +int tstQMsgSpd; +int tstQMsgIndex = 0; +BOOL tstQMsgFlag = FALSE; +BOOL tstQMsgIndexFlag = FALSE; +BOOL itemcheat = FALSE; +BOOL uniqcheat = FALSE; +#endif + +BOOL visiondebug = FALSE; // Vision debugging +BOOL scrollflag = FALSE; // Scroll when at edge of screen with mouse +BOOL light4flag = FALSE; // 4 levels of light instead of 16 +BOOL leveldebug = FALSE; +BOOL monstdebug = FALSE; +BOOL trigdebug = FALSE; +int setseed = 0; + +int debugmonsttypes = 0; +int DebugMonsters[10]; + +BOOL PauseMode = FALSE; +BOOL FriendlyMode = TRUE; + +BOOL gbRunGame; +BOOL gbRunGameResult; +BOOL gbProcessPlayers; +BOOL gbGameLoopStartup; + +bool gbTheo = false; +bool gbCowsuit = false; +bool gbOurNest = false; +bool gbAllowBard = false; +bool gbAllowBarbarian = false; +bool gbAllowMultiPlayer = false; + +//int glEndSeed[17]; // @@@ drb temp +//int glMid1Seed[17]; +//int glMid2Seed[17]; +//int glMid3Seed[17]; + +int glEndSeed[NUMLEVELS+1]; // @@@ drb temp +int glMid1Seed[NUMLEVELS+1]; +int glMid2Seed[NUMLEVELS+1]; +int glMid3Seed[NUMLEVELS+1]; //JKE 7/30 adds new levels + +/*-----------------------------------------------------------------------** +** timeout cursor +**-----------------------------------------------------------------------*/ +#define TIMEOUT_CURSOR WATCH_CURS +static int sgnTimeoutCurs = NO_CURSOR; + +#define LMOUSE_DOWN 1 +#define RMOUSE_DOWN 2 +// drb.patch1.start.1/24/97 +// static BYTE sgbMouseDown = 0; +BYTE sgbMouseDown = 0; +// drb.patch1.end.1/24/97 + + +/*-----------------------------------------------------------------------** +** Function stubs +**-----------------------------------------------------------------------*/ +// pjw.patch1.start +// static void try_game_loop(BOOL bStartup); +static void alloc_plr(); +static void DoTimedEvents(); +static void game_loop(BOOL bStartup); +static void plr_encrypt(BOOL bEncrypt); +void InitializeHashSource(); +void Decrypt(LPDWORD data, DWORD bytes, DWORD key); +void Encrypt(LPDWORD data, DWORD bytes, DWORD key); +// pjw.patch1.end + + +void BlackPalette(); +void enable_frame_counter(); +void init_window(int nCmdShow); +void play_movie(const char * pszMovie,BOOL bAllowCancel); +void play_quotes(); +void play_quit(); +void FreeCursor(); +void InitDebugGFX(); +void FreeDebugGFX(); +void ShowProgress(UINT uMsg); +static LRESULT CALLBACK GM_Game(HWND, UINT, WPARAM, LPARAM); +void TrackInit(BOOL bMouseDown); +void TrackMouse(); +void run_delta_info(); +void toggle_frame_counter(); +WNDPROC my_SetWindowProc(WNDPROC wndProc); +void plrmsg_update(); +void screen_capture(); +void SavePaletteSettings(); +void menu_music(); +void NetStartTimeout(); +void menusnd_init(); +void InitLevels(); +void SyncInitPlrPos(int pnum); + +void OpenCloseAllDoors(); +void OpenNaKrul2(); + +//****************************************************************** +//****************************************************************** +void FlushMsgs() { + // turn tracking off + TrackInit(FALSE); + sgbMouseDown = FALSE; + ReleaseCapture(); + + // keep flushing messages until all key and mouse msgs are gone + BOOL bLoop = TRUE; + while (bLoop) { + bLoop = FALSE; + MSG msg; + while (PeekMessage(&msg,NULL,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE)) + bLoop = TRUE; + while (PeekMessage(&msg,NULL,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE)) + bLoop = TRUE; + } +} + +//****************************************************************** +//****************************************************************** +static void CommandLine(const char * s) { + int val; + (val); + + while (*s) { + + // skip over any space characters + while (isspace(*s)) + s++; + + // check for direct draw emulation mode +// pjw.patch1.start.1/13/97 + static const char sszEmulate[] = "dd_emulate"; + if (! _strnicmp(sszEmulate,s,strlen(sszEmulate))) { + extern BYTE gbUseDDEmulation; + gbUseDDEmulation = TRUE; + s += strlen(sszEmulate); + continue; + } + + // check for direct draw offscreen buffer + static const char sszBackBuf[] = "dd_backbuf"; + if (! _strnicmp(sszBackBuf,s,strlen(sszBackBuf))) { + extern BYTE gbForceBackBuf; + gbForceBackBuf = TRUE; + s += strlen(sszBackBuf); + continue; + } + + static const char sszDupSound[] = "ds_noduplicates"; + if (! _strnicmp(sszDupSound,s,strlen(sszDupSound))) { + extern BYTE gbDupSounds; + gbDupSounds = FALSE; + s += strlen(sszDupSound); + continue; + } + + char const sszTheoFlag[] = "Theoquest"; + if (! _strnicmp(sszTheoFlag, s, strlen(sszTheoFlag))) { + gbTheo = true; + s += strlen(sszTheoFlag); + continue; + } + + char const sszCowQuestFlag[] = "Cowquest"; + if (!_strnicmp(sszCowQuestFlag, s, strlen(sszCowQuestFlag))) { + gbCowsuit = true; + s += strlen(sszCowQuestFlag); + continue; + } + + char const sszOurNestFlag[] = "NestArt"; + if (!_strnicmp(sszOurNestFlag, s, strlen(sszOurNestFlag))) { + gbOurNest = true; + s += strlen(sszOurNestFlag); + continue; + } + + char const sszAllowBardFlag[] = "Bardtest"; + if (!_strnicmp(sszAllowBardFlag, s, strlen(sszAllowBardFlag))) { + gbAllowBard = true; + s += strlen(sszAllowBardFlag); + continue; + } + + char sszAllowMultiPlayerFlag[] = "Multitest"; +#if defined(_MULTITEST) + sszAllowMultiPlayerFlag[5] = 'n'; + if (!_strnicmp(sszAllowMultiPlayerFlag, s, strlen(sszAllowMultiPlayerFlag))) { +#else + if (!_strnicmp(sszAllowMultiPlayerFlag, sszAllowBardFlag, strlen(sszAllowMultiPlayerFlag))) { +#endif + gbAllowMultiPlayer = true; + s += strlen(sszAllowMultiPlayerFlag); + continue; + } + + char const sszAllowBarbarianFlag[] = "Barbariantest"; + if (!_strnicmp(sszAllowBarbarianFlag, s, strlen(sszAllowBarbarianFlag))) { + gbAllowBarbarian = true; + s += strlen(sszAllowBarbarianFlag); + continue; + } + +// pjw.patch1.end.1/13/97 + + // extract next character -- do not do ++ inside macro + // some versions of C may have nasty side effects... + char c = tolower(*s); s++; + switch (c) { + #if CHEATS + case 'b': + gbDumpDropLog = TRUE; + break; + #endif + + #if CHEATS + case 'i': + gbNoDropInactive = TRUE; + break; + #endif + + #if CHEATS + // this cheat flag is for testing without having your + // character die every two seconds -- doesn't have + // all the nasty side effects of the cheat flag + case '$': + simplecheat = TRUE; + break; + #endif + + #if CHEATS + // this cheat flag is the do-everything cheat for programmers + // it has all sorts of nasty side effects which may hide bugs + case '^': + cheatflag = TRUE; + break; + #endif + + #if CHEATS + case 'd': + davedebug = TRUE; + cineflag = FALSE; + break; + #endif + + #if CHEATS + case 'w': + davecheat = TRUE; + break; + #endif + + #if CHEATS && !IS_VERSION(SHAREWARE) + case 'l': + leveldebug = TRUE; + setlevel = FALSE; + + // get level type + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + leveltype = val; + + // get level num + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + currlevel = val; + plr[0].plrlevel = val; + break; + #endif + + #if CHEATS + case 'm': + monstdebug = TRUE; + + // get monster number + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + DebugMonsters[debugmonsttypes++] = val; + break; + #endif + + #if CHEATS + case 'q': + // get quest number + while(isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + extern int questcheat; + questcheat = val; + break; + #endif + + #if CHEATS + case 'r': + while(isspace(*s)) + s++; + val = 0; + while(isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + setseed = val; + break; + #endif + + #if CHEATS + case 's': + scrollflag = TRUE; + break; + #endif + + #if CHEATS && !IS_VERSION(SHAREWARE) + case 't': + leveldebug = TRUE; + setlevel = TRUE; + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + setlvlnum = val; + break; + #endif + + #if CHEATS + case 'j': + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + trigdebug = val; + break; + #endif + + #if CHEATS + case 'v': + visiondebug = TRUE; + break; + #endif + + #ifndef NDEBUG + case 'f': + toggle_frame_counter(); + break; + #endif + + #ifndef NDEBUG + case 'x': + fullscreen = FALSE; + break; + #endif + + #ifndef NDEBUG + case 'n': + cineflag = FALSE; + break; + #endif + + #if CHEATS + case '7': + itemcheat = TRUE; + break; + + case '8': + uniqcheat = TRUE; + break; + #endif + } + + } +} + + +//****************************************************************** +//****************************************************************** +void FreeGameMem() { + music_stop(); + + DiabloFreePtr(pDungeonCels); + DiabloFreePtr(pMegaTiles); + DiabloFreePtr(pMiniTiles); + DiabloFreePtr(pSpecialCels); + DiabloFreePtr(pSpeedCels); + FreeMissileGFX(); + + FreeMonsterGFX(); + FreeObjectGFX(); + FreeMonsterSnd(); + FreeTownerGFX(); +} + + +//****************************************************************** +// stuff done every time a game is started/ended +//****************************************************************** +static void start_game(UINT uMsg) { + gbDoEnding = FALSE; + svgamode = TRUE; + InitCursor(); + InitLightTable(); + InitDebugGFX(); + app_assert(ghMainWnd); + music_stop(); + ShowProgress(uMsg); + gmenu_init(); + InitLevelCursor(); + sgnTimeoutCurs = NO_CURSOR; + sgbMouseDown = 0; + TrackInit(FALSE); +} +static void free_game() { + FreeControlPan(); + FreeInvGFX(); + gmenu_free(); + FreeQuestText(); + FreeStoreMem(); + for (int i = 0; i < MAX_PLRS; i++) + FreePlayerGFX(i); + FreeItemGFX(); + + FreeCursor(); + FreeLightTable(); + FreeDebugGFX(); + FreeGameMem(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void run_game_loop(UINT uMsg) { + nthread_perform_keepalive(TRUE); + start_game(uMsg); + app_assert(ghMainWnd); + WNDPROC saveProc = my_SetWindowProc(GM_Game); + CalcInitBallPer(); + // pjw.patch2.start + // nthread_perform_keepalive(FALSE); + // pjw.patch2.end + run_delta_info(); + + gbRunGame = TRUE; + gbProcessPlayers = TRUE; + gbRunGameResult = TRUE; + force_redraw = FULLDRAW; + DrawAndBlit(); + PaletteFadeIn(FADE_FAST); + force_redraw = FULLDRAW; + gbGameLoopStartup = TRUE; + + // pjw.patch2.start + nthread_perform_keepalive(FALSE); + // pjw.patch2.end + + +// pjw.patch1.start + MSG msg; + //plr_encrypt(TRUE); + while (gbRunGame) { + DoTimedEvents(); // palette cycling + + // pjw.patch2.start + // if there are any messages in the queue, process them all + if (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) { + // bump thread priority to make sure that + // during peekmessage loop we are less likely + // to yield to another process + SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL); + //plr_encrypt(FALSE); + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if (msg.message == WM_QUIT) { + gbRunGame = gbRunGameResult = FALSE; + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + BOOL bRun = gbRunGame && nthread_run_gameloop(FALSE); + //if (! bRun) plr_encrypt(TRUE); + SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL); + if (! bRun) continue; + } + else if (! nthread_run_gameloop(FALSE)) { + // not enough time has elapsed since last gameloop + continue; + } + // pjw.patch2.end + + // actual game logic + //plr_encrypt(FALSE); + NetReceivePackets(); + game_loop(gbGameLoopStartup); + gbGameLoopStartup = FALSE; + DrawAndBlit(); + //plr_encrypt(TRUE); + } + //plr_encrypt(FALSE); +// pjw.patch1.end + + // save character in multiplayer mode + if (gbMaxPlayers > 1) { + void UpdatePlayerFile(); + UpdatePlayerFile(); + } + void ReleasePlayerFile(); + ReleasePlayerFile(); + + PaletteFadeOut(FADE_FAST); + SetCursor(NO_CURSOR); + ClrDraw(); + force_redraw = FULLDRAW; + FullBlit(TRUE); + + // restore old window procedure + saveProc = my_SetWindowProc(saveProc); + app_assert(saveProc == GM_Game); + + free_game(); + + if (gbDoEnding) { + gbDoEnding = FALSE; + DoEnding(); + } +} + + +/*-----------------------------------------------------------------------** +// return FALSE to quit game +// return TRUE to continue game +**-----------------------------------------------------------------------*/ +BOOL StartGame(BOOL bNewGame, BOOL bSinglePlayer) { + + extern BYTE gbSelectProvider; + gbSelectProvider = TRUE; + + while (1) { + + // initialize network + BOOL fExitProgram = FALSE; + if (! NetInit(bSinglePlayer,&fExitProgram)) { + gbRunGameResult = !fExitProgram; + break; + } + + gbSelectProvider = FALSE; + + UINT uMsg; + if (bNewGame || !gbValidSaveFile) { + + InitLevels(); + InitQuests(); + InitPortals(); + InitDungMsgs(myplr); + if (!gbValidSaveFile && gbSaveFileExists) + { + // clear the items from the character's inventory + StripPlayer(myplr); + } + uMsg = WM_DIABNEWGAME; + } + else { + uMsg = WM_DIABLOADGAME; + } + + run_game_loop(uMsg); + NetClose(); + + // in single player mode, exit this loop + if (gbMaxPlayers == 1) break; + + // in multiplayer mode, only break out of the + // loop if the player wants to exit the game, otherwise + // the loop will be exited based on results from NetInit() + if (! gbRunGameResult) break; + } + + TRACE_FCN("SNetDestroy"); + SNetDestroy(); + TRACE_FCN(NULL); + + return gbRunGameResult; +} + + +//****************************************************************** +//****************************************************************** +static void InitOnce() { + MouseX = TOTALX >> 1; + MouseY = TOTALY >> 1; + + ScrollInfo._sdx = 0; + ScrollInfo._sdy = 0; + ScrollInfo._sxoff = 0; + ScrollInfo._syoff = 0; + ScrollInfo._sdir = SCRL_NONE; + for (int i = 0; i < 1024; i++) + nBuffWTbl[i] = i * BUFFERX; + + // Init engine vars + ClrDiabloMsg(); +} + + +//****************************************************************** +//****************************************************************** +/* pjw.patch2.start +static const char sgszErrFile[] = "c:\\helfire_.err"; +static void write_exception(struct _EXCEPTION_POINTERS *pep) { + FILE * f = fopen(sgszErrFile,"wb"); + if (! f) return; + + PEXCEPTION_RECORD per = pep->ExceptionRecord; + while (per) { + fprintf( + f, + "exception: 0x%08x\r\ncode address: 0x%08x\r\n", + per->ExceptionCode, + per->ExceptionAddress + ); + + if (per->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { + if (per->ExceptionInformation[0]) + fprintf(f,"write access violation at 0x%08x\r\n",per->ExceptionInformation[1]); + else + fprintf(f,"read access violation at 0x%08x\r\n",per->ExceptionInformation[1]); + } + + per = per->ExceptionRecord; + } + + fclose(f); +} +pjw.patch2.end */ + + +//****************************************************************** +//****************************************************************** +// pjw.patch2.start +void cleanup(BOOL bNormalExit); +static LPTOP_LEVEL_EXCEPTION_FILTER sg_previousFilter; +static LONG WINAPI DiabloUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *pep) { + void free_directx(); + free_directx(); + cleanup(FALSE); + // write_exception(pep); + if (sg_previousFilter) return sg_previousFilter(pep); + return EXCEPTION_CONTINUE_SEARCH; +} +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +BOOL grab_event() { + // NOTE: this event never gets cleaned up by our code + // we rely upon windows to clean up this event so that it + // occurs as late as possible in the program exit. This is + // a really nasty hack to make sure that SMACKER doesn't + // initialize improperly + SetLastError(0); + HANDLE hExtraEvent = CreateEvent(NULL,FALSE,FALSE,"DiabloEvent"); + HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,"HellfireEvent"); + return ERROR_ALREADY_EXISTS != GetLastError(); +} + + +//****************************************************************** +//****************************************************************** +static BOOL ActivatePreviousInstance(const char * pszAppClass) { + // find main application window + HWND hWnd; + HWND hWndTop; + HWND hWndPopup; + + // get parent window + if (NULL == (hWnd = FindWindow(pszAppClass,NULL))) + return FALSE; + + // get popup window (if any) + if (NULL != (hWndPopup = GetLastActivePopup(hWnd))) + hWnd = hWndPopup; + + // get topmost control window of topmost window + hWndTop = GetTopWindow(hWnd); + if (! hWndTop) hWndTop = hWnd; + + // bring to the front + SetForegroundWindow(hWnd); + SetFocus(hWndTop); + + return TRUE; +} + + +typedef struct _SHAREDDATA { + LONG status; + DWORD processid; +} SHAREDDATA, *SHAREDDATAPTR; + + +//=========================================================================== +// pjw.patch2.start +#ifdef NDEBUG +static void inline ReloadSelf (HINSTANCE instance) { + + // GET THE MODULE FILENAME + char filename[MAX_PATH] = ""; + GetModuleFileName((HMODULE)instance,filename,MAX_PATH); + + + // OPEN NAMED SHARED MEMORY + char name[MAX_PATH+16]; + wsprintf(name,"Reload-%s",filename); + for (LPSTR curr = name; *curr; ++curr) + if (*curr == '\\') + *curr = '/'; + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + DWORD bytes = max(4096,sysinfo.dwPageSize); + + + HANDLE map = CreateFileMapping((HANDLE)0xFFFFFFFF, + NULL, + PAGE_READWRITE | SEC_COMMIT, + 0, + bytes, + name); + BOOL first = (GetLastError() != ERROR_ALREADY_EXISTS); + if (!map) + return; + + // Open secondary named shared memory to fool Diablo into not autorunning + char tmpname[MAX_PATH+16]; + strcpy(tmpname,"Reload-Diablo"); + HANDLE tmpmap = CreateFileMapping((HANDLE)0xFFFFFFFF, + NULL, + PAGE_READWRITE | SEC_COMMIT, + 0, + bytes, + tmpname); + // end of hack + + LPVOID view = MapViewOfFile(map,FILE_MAP_ALL_ACCESS,0,0,bytes); + if (!view) + return; + SHAREDDATAPTR ptr = (SHAREDDATAPTR)view; + + // IF WE ARE THE FIRST INSTANCE, THEN RELOAD OURSELVES, WAIT FOR THE + // SECOND INSTANCE TO INITIALIZE, THEN QUIT + if (first) { + ptr->status = -1; + ptr->processid = 0; + STARTUPINFO startupinfo; + ZeroMemory(&startupinfo,sizeof(STARTUPINFO)); + startupinfo.cb = sizeof(STARTUPINFO); + PROCESS_INFORMATION processinfo; + CreateProcess(filename, + NULL, + NULL, + NULL, + FALSE, + CREATE_NEW_PROCESS_GROUP, + NULL, + NULL, + &startupinfo, + &processinfo); + WaitForInputIdle(processinfo.hProcess,INFINITE); + CloseHandle(processinfo.hThread); + CloseHandle(processinfo.hProcess); + while (ptr->status < 0) + Sleep(1000); + UnmapViewOfFile(view); + CloseHandle(map); + ExitProcess(0); + } + + // OTHERWISE, ALLOW ONE INSTANCE TO RUN, AND MAKE ANY ADDITIONAL + // INSTANCES JUST REACTIVATE THE RUNNING INSTANCE + if (!InterlockedIncrement(&ptr->status)) + ptr->processid = GetCurrentProcessId(); + else { + HWND window = GetForegroundWindow(); + HWND prev; + while ((prev = GetNextWindow(window,GW_HWNDPREV)) != (HWND)0) + window = prev; + do { + DWORD processid; + GetWindowThreadProcessId(window,&processid); + if (processid == ptr->processid) { + SetForegroundWindow(window); + break; + } + } while ((window = GetNextWindow(window,GW_HWNDNEXT)) != (HWND)0); + UnmapViewOfFile(view); + CloseHandle(map); + ExitProcess(0); + } +} +#endif +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow){ +// pjw.patch2.start + #ifdef NDEBUG + ReloadSelf(hInstance); + #endif +// pjw.patch2.end + + ghInst = hInstance; + ShowCursor(FALSE); + // pjw.patch1.start + srand(GetTickCount()); + InitializeHashSource(); + alloc_plr(); + // pjw.patch1.end + + // delete any previous error file created by exception + // handler and then install exception handler + // pjw.patch2.start + // DeleteFile(sgszErrFile); + sg_previousFilter = SetUnhandledExceptionFilter(DiabloUnhandledExceptionFilter); + // pjw.patch2.end + + // if another instance of Diablo is already running, + // then activate it and exit this instance + BOOL bGotEvent = grab_event(); + if (ActivatePreviousInstance("DIABLO")) // conflict with parent is bad + return FALSE; + if (ActivatePreviousInstance(gszAppName)) + return FALSE; + if (!bGotEvent) return FALSE; + + + #ifndef NDEBUG + SFileEnableDirectAccess(1); + #endif + + InitOnce(); + char cpCmdLine[255]; + if (!lpCmdLine[0]) { + cpCmdLine[0] = 0; + FILE * const fp = fopen("command.txt","r"); + if (fp) { + fgets(cpCmdLine, sizeof(cpCmdLine)/sizeof(char), fp); + lpCmdLine = cpCmdLine; + fclose(fp); + } + } + CommandLine(lpCmdLine); + init_window(nCmdShow); + + menusnd_init(); + UiInitialize(); + + #if IS_VERSION(SHAREWARE) + UiSetSpawned(TRUE); + #endif + + + // play logo + #ifndef NDEBUG + if (cineflag) play_movie("gendata\\logo.smk",TRUE); + #else + play_movie("gendata\\logo.smk",TRUE); + #endif + + // play magazine quotes + /* + #if IS_VERSION(SHAREWARE) + #ifndef NDEBUG + if (cineflag) play_quotes(); + #else + play_quotes(); + #endif + #endif + */ + + // play main intro + #if !IS_VERSION(SHAREWARE) + const char sgszMovie[] = "Intro"; + DWORD dwPlayMovie; + if (! SRegLoadValue(gszProgKey,sgszMovie,0,&dwPlayMovie)) + dwPlayMovie = 1; + //if (dwPlayMovie) + play_movie("gendata\\Hellfire.smk",TRUE); + SRegSaveValue(gszProgKey,sgszMovie,0,0); + #endif + + + // play title screen + #ifndef NDEBUG + if (cineflag) { + #endif + UiTitleDialog(7); // DKT this needs to change to ours + BlackPalette(); + #ifndef NDEBUG + } + #endif + + // play beta warning + #if IS_VERSION(BETA) + #ifndef NDEBUG + if (cineflag) { + #endif + UiBetaDisclaimer(5); + BlackPalette(); + #ifndef NDEBUG + } + #endif + #endif + + // main game menu (finally) + DiabloMenu(); + + // play "buy me" screens + /* + #if IS_VERSION(SHAREWARE) + #ifndef NDEBUG + if (cineflag) play_quit(); + #else + play_quit(); + #endif + #endif + */ + + UiDestroy(); + SavePaletteSettings(); + + if (ghMainWnd) { + // sleep before we destroy window so + // that SFX have time to finish before exit + Sleep(300); + DestroyWindow(ghMainWnd); + } + + return FALSE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL CheckPlrLBtn(BOOL ShiftDown) { + BOOL adjacent; + + app_assert(MouseY < 352); + if (leveltype == 0) { + // + // Town Level + // + ShiftDown = FALSE; // no attacking in town + if ((cursitem != -1) && (curs == GLOVE_CURS)) + NetSendCmdLocParam1(TRUE,invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM,cursmx,cursmy,cursitem); + if (cursmonst != -1) + NetSendCmdLocParam1(TRUE,CMD_TALKXY,cursmx,cursmy,cursmonst); + if ((cursitem == -1) && (cursmonst == -1) && (cursplr == -1)) + return TRUE; + } + else { + // + // NOT Town Level + // + adjacent = abs(plr[myplr]._px - cursmx) < 2 + && abs(plr[myplr]._py - cursmy) < 2; + if ((cursitem != -1) && (curs == GLOVE_CURS) && !ShiftDown) + NetSendCmdLocParam1(TRUE,invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM,cursmx,cursmy,cursitem); + else if ((cursobj != -1) + && (!ShiftDown // allow barrel busting even with shift key down + || (adjacent && object[cursobj]._oBreak == OBJ_BREAKABLE))) + NetSendCmdLocParam1(TRUE,(curs == DISARM_CURS) ? CMD_DISARMXY : CMD_OPOBJXY,cursmx,cursmy,cursobj); + + else if (plr[myplr]._pwtype == WEAP_RANGE) { + if (ShiftDown) + NetSendCmdLoc(TRUE,CMD_RATTACKXY, cursmx, cursmy); + else if (cursmonst != -1) { + if (CanTalkToMonst(cursmonst)) + // walk over to monster to talk to him + NetSendCmdParam1(TRUE,CMD_ATTACKID,cursmonst); + else + // Attack + NetSendCmdParam1(TRUE,CMD_RATTACKID,cursmonst); + } else if (cursplr != -1 && !FriendlyMode) + NetSendCmdParam1(TRUE,CMD_RATTACKPID, cursplr); + } + + else { // pwtype == WEAP_H2H + if (ShiftDown) { + if (cursmonst != -1) { + if (CanTalkToMonst(cursmonst)) + NetSendCmdParam1(TRUE,CMD_ATTACKID,cursmonst); + else + NetSendCmdLoc(TRUE,CMD_SATTACKXY, cursmx, cursmy); + } else + NetSendCmdLoc(TRUE,CMD_SATTACKXY, cursmx, cursmy); + } + else if (cursmonst != -1) + NetSendCmdParam1(TRUE,CMD_ATTACKID,cursmonst); + else if (cursplr != -1 && !FriendlyMode) + NetSendCmdParam1(TRUE,CMD_ATTACKPID,cursplr); + } + + if ((!ShiftDown) && (cursitem == -1) && (cursobj == -1) && (cursmonst == -1) && (cursplr == -1)) + return TRUE; + } + + return FALSE; +} + +/*-----------------------------------------------------------------------** +** Game message processing +**-----------------------------------------------------------------------*/ +static BOOL TryIconCurs() { + if (curs == RESURRECT_CURS) { + NetSendCmdParam1(TRUE,CMD_RESURRECT, cursplr); + return(TRUE); + } + + if (curs == HEALOTHER_CURS) { + NetSendCmdParam1(TRUE,CMD_HEALOTHER, cursplr); + return(TRUE); + } + + if (curs == TELE_CURS) { + DoTelekinesis(); + return(TRUE); + } + if (curs == IDENTIFY_CURS) { + if (cursinvitem != -1) + CheckIdentify(myplr, cursinvitem); + else + NewCursor(GLOVE_CURS); + return(TRUE); + } + if (curs == REPAIR_CURS) { + if (cursinvitem != -1) + DoRepair(myplr, cursinvitem); + else + NewCursor(GLOVE_CURS); + return(TRUE); + } + if (curs == RECHARGE_CURS) { + if (cursinvitem != -1) + DoRecharge(myplr, cursinvitem); + else + NewCursor(GLOVE_CURS); + return(TRUE); + } + + if (curs == OIL_CURS) { + if (cursinvitem != -1) + DoOil(myplr, cursinvitem); + else + NewCursor(GLOVE_CURS); + return(TRUE); + } + + if (curs == TARGET_CURS) { + if (cursmonst != -1) + NetSendCmdParam3(TRUE,CMD_TSPELLID,cursmonst,plr[myplr]._pTSpell, GetSpellLevel(myplr, plr[myplr]._pTSpell)); + else if (cursplr != -1) + NetSendCmdParam3(TRUE,CMD_TSPELLPID,cursplr,plr[myplr]._pTSpell,GetSpellLevel(myplr, plr[myplr]._pTSpell)); + else + NetSendCmdLocParam2(TRUE,CMD_TSPELLXY,cursmx,cursmy,plr[myplr]._pTSpell,GetSpellLevel(myplr, plr[myplr]._pTSpell)); + NewCursor(GLOVE_CURS); + return(TRUE); + } + if ((curs == DISARM_CURS) && (cursobj == -1)) { + NewCursor(GLOVE_CURS); + return(TRUE); + } + return(FALSE); +} + + +//****************************************************************** +//****************************************************************** +static BOOL wm_lbuttondown(WPARAM wParam) { + if (gmenu_click(TRUE)) + return FALSE; + + BOOL talk_click(); + if (talk_click()) + return FALSE; + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) + return FALSE; + + if (deathflag) { + CheckDeadButtons(); + return FALSE; + } + + if (PauseMode == 2) + return FALSE; + + if (drawmapofdoom) { + EndMapOfDoomView(); + return FALSE; + } + + if (spselflag) { + SetSpell(); + return FALSE; + } + + if (stextflag != STORE_NONE) { + CheckStoreBtn(); + return FALSE; + } + + if (MouseY < 352) { + if (gmenu_is_on()) + return FALSE; + + if (TryIconCurs()) + return FALSE; + + if (questlog) { + if ((MouseX > 32) && (MouseX < 288) && (MouseY > 32) && (MouseY < 308)) { + CheckQLogBtn(); + return FALSE; + } + } + + if (qtextflag) { + qtextflag = FALSE; + stream_stop(); + return FALSE; + } + + if ((chrflag) && (MouseX < 320)) { + CheckChrBtns(); + return FALSE; + } + else if ((invflag) && (MouseX > 320)) { + if (!dropGoldFlag) CheckInvScrn(); + return FALSE; + } + else if ((sbookflag) && (MouseX > 320)) { + CheckSBook(); + return FALSE; + } + else if (curs >= ICSTART) { + if (TryInvPut()) { + NetSendCmdPItem(TRUE,CMD_PUTITEM,cursmx,cursmy); + NewCursor(GLOVE_CURS); + } + return FALSE; + } + else { + if ((plr[myplr]._pStatPts != 0) && (!spselflag)) + CheckLvlBtn(); + if (!lvlbtndown) + return CheckPlrLBtn(wParam == (MK_LBUTTON | MK_SHIFT)); + } + } + else { + if (!talkflag && !dropGoldFlag && !gmenu_is_on()) + CheckSpdBar(); + CheckPanelBtns(); + if ((curs > GLOVE_CURS) && (curs < ICSTART)) + NewCursor(GLOVE_CURS); + } + + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +static void wm_lbuttonup() { + gmenu_click(FALSE); + void talk_release(); + talk_release(); + if (panbtndown) ReleasePanelBtn(); + if (chrbtndown) ReleaseChrBtn(); + if (lvlbtndown) ReleaseLvlBtn(); + if (stextflag != STORE_NONE) ReleaseStoreBtn(); +} + + +//****************************************************************** +//****************************************************************** +static void wm_rbuttondown() { + + // don't allow input while the menu is active + if (gmenu_is_on()) return; + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) + return; + + if (PauseMode == 2) return; + + if (plr[myplr]._pInvincible) return; + + if (drawmapofdoom) { + EndMapOfDoomView(); + return; + } + + if (stextflag != STORE_NONE) return; + + if (spselflag) { + SetSpell(); + return; + } +// if (sbookflag && CheckSBookCast()) +// return; + if (sbookflag && MouseX > 320) return; + + if (MouseY < 352) { + if (TryIconCurs()) + return; + if (cursinvitem != -1 && UseInvItem(myplr, cursinvitem)) + return; + } + if (curs == GLOVE_CURS) { + if (cursinvitem != -1 && UseInvItem(myplr, cursinvitem)) + return; +// else if (cursitem != -1 && (wParam & WM_SHIFT)) +// UseGroundItem(cursitem); + else + CheckPlrSpell(); + } + else if ((curs > GLOVE_CURS) && (curs < ICSTART)) NewCursor(GLOVE_CURS); +} + + +//****************************************************************** +//****************************************************************** +static void wm_mousemove() { + // check for menu sliders + if (gmenu_mousemove()) return; + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) return; + + // do game mousemove here +} + + +//****************************************************************** +//****************************************************************** +static void TogglePause() { + // no pause in multiplayer + if (gbMaxPlayers > 1) return; + + if (PauseMode) { + PauseMode = 0; + } + else { + PauseMode = 2; + sound_stop(); + TrackInit(FALSE); + } + force_redraw = FULLDRAW; +} + + +//****************************************************************** +//****************************************************************** +static void SendTaunt(DWORD dwMsg) { + // don't send taunts in single player mode + if (gbMaxPlayers == 1) return; + + // get program directory + char szPath[MAX_PATH]; + if (! GetModuleFileName(ghInst,szPath,MAX_PATH)) + app_fatal("Can't get program name"); + char * pszName = strrchr(szPath,'\\'); + if (pszName) *pszName = 0; + strcat(szPath,"\\hellfire.ini"); + + static const char * spszMsgTbl[] = { + "I need help! Heal me!", + "Go through that door first.", + "Give me some gold please.", + "Look out behind you!", + }; + static const char * spszKeyTbl[] = { + "F9","F10","F11","F12" + }; + + char szBuf[MAX_SEND_STR_LEN]; + app_assert(dwMsg < sizeof(spszMsgTbl) / sizeof(spszMsgTbl[0])); + GetPrivateProfileString( + "NetMsg", // section name + spszKeyTbl[dwMsg], // key name + spszMsgTbl[dwMsg], // default string + szBuf, // dest buffer + sizeof(szBuf) / sizeof(szBuf[0]), + szPath + ); + + // send message to other players + NetSendString(SEND_ALL_MASK,szBuf); +} + + +//****************************************************************** +//****************************************************************** +static BOOL wm_syskeydown(WPARAM wKey) { + // don't allow input while the menu is active + if (gmenu_is_on()) + return FALSE; + + // note: this identical code is in the keydown case also, but + // F10 seems to come through as a system key sometimes... + if (wKey == VK_F10) { + SendTaunt(1); + return TRUE; + } + + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +static void wm_keyup(WPARAM wKey) { + // can't ever get keydown for snapshot, but we do get keyup + if (wKey == VK_SNAPSHOT) + screen_capture(); + + // if any more cases are added here, then make sure menu is not active + // if (gmenu_is_on()) return; +} + + +//****************************************************************** +//****************************************************************** +BOOL clear_windows() { + BOOL bResult = FALSE; + + if (drawmapofdoom) { + EndMapOfDoomView(); + bResult = TRUE; + } + if (helpflag) { + helpflag = FALSE; + bResult = TRUE; + } + if (qtextflag) { + qtextflag = FALSE; + stream_stop(); + #if CHEATS + if ((currlevel == 0) && (davecheat)) { + tstQMsgFlag = FALSE; + tstQMsgIndexFlag = TRUE; + } + #endif + bResult = TRUE; + } else + if (stextflag) { + STextESC(); + bResult = TRUE; + } + if (msgflag) { + msgdelay = 0; + bResult = TRUE; + } + if (talkflag) { + TalkEnd(); + bResult = TRUE; + } + if (dropGoldFlag) { + DropGoldType(VK_ESCAPE); + bResult = TRUE; + } + if (spselflag) { + spselflag = FALSE; + bResult = TRUE; + } + + return bResult; +} + + +//****************************************************************** +//****************************************************************** +static void wm_keydown(WPARAM wKey) { + // allow use of menu even when character is dead + if (gmenu_key(wKey)) + return; + + // allow user to finish current string even in timeout mode + if (Talk_wm_keydown(wKey)) + return; + + // don't allow dead player to do anything except turn on gamemenu + if (deathflag) { + // no input while in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) return; + if (wKey == VK_F9) SendTaunt(0); + if (wKey == VK_F10) SendTaunt(1); + if (wKey == VK_F11) SendTaunt(2); + if (wKey == VK_F12) SendTaunt(3); + if (wKey == VK_RETURN) TalkStart(); + if (wKey != VK_ESCAPE) return; + } + + if (wKey == VK_ESCAPE) { + if (! clear_windows()) { + TrackInit(FALSE); + gamemenu_on(); + } + #if CHEATS + if ((currlevel == 0) && (davecheat) && + ((tstQMsgFlag) || (tstQMsgIndexFlag))) { + tstQMsgFlag = FALSE; + tstQMsgIndexFlag = FALSE; + sprintf(tempstr, "STOP QUEST TEXT MODE"); + NetSendString((1 << myplr), tempstr); + return; + } + #endif + return; + } + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) + return; + + // Don't accept input when in drop gold mode + if (dropGoldFlag) + return; + + // in pause mode the only thing we can do is unpause + if (wKey == VK_PAUSE) { + TogglePause(); + return; + } + if (PauseMode == 2) return; + + if (wKey == VK_RETURN) { + if (stextflag) STextEnter(); + else if (questlog) QuestlogEnter(); + #if CHEATS + else if ((currlevel == 0) && (davecheat)) { + if (tstQMsgIndexFlag) { + tstQMsgIndexFlag = FALSE; + tstQMsgFlag = TRUE; + tstQMsgSpd = 5; + DaveQuestText(); + sprintf(tempstr, "Message Speed = %i", tstQMsgSpd); + NetSendString((1 << myplr), tempstr); + } else if (tstQMsgFlag) { + sprintf(tempstr, "[ MESSAGE = %i ]", tstQMsgIndex); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "[ MESSAGE SPEED = %i ]", tstQMsgSpd); + NetSendString((1 << myplr), tempstr); + } + } + #endif + else TalkStart(); + return; + } + + if (wKey == VK_F1) { + if (helpflag) { + helpflag = FALSE; + } + else if (stextflag != STORE_NONE) { + ClearPanel(); + AddPanelString("No help available", TEXT_CENTER); + AddPanelString("while in stores", TEXT_CENTER); + TrackInit(FALSE); + } + else { + invflag = FALSE; + chrflag = FALSE; + sbookflag = FALSE; + spselflag = FALSE; + if ((qtextflag) && (leveltype == 0)) { + qtextflag = FALSE; + stream_stop(); + } + questlog = FALSE; + automapflag = FALSE; + msgdelay = 0; + gamemenu_off(); + StartHelp(); + EndMapOfDoomView(); + } + return; + } + + #if CHEATS + if (wKey == VK_F2) { + void PrintDaveCheck2(); + PrintDaveCheck2(); + } + +/* if (wKey == VK_F3) { + extern BOOL syncdebug; + syncdebug = !syncdebug; + if (syncdebug) + strcpy(tempstr, "Item drop debug on"); + else + strcpy(tempstr, "Item drop debug off"); + NetSendString((1 << myplr), tempstr); + }*/ + if (wKey == VK_F3) { + if (cursitem != -1) { + sprintf(tempstr, "IDX = %i : Seed = %i : CF = %i", item[cursitem].IDidx, item[cursitem]._iSeed, item[cursitem]._iCreateInfo); + NetSendString((1 << myplr), tempstr); + } + sprintf(tempstr, "Numitems : %i", numitems); + NetSendString((1 << myplr), tempstr); + } + + if (wKey == VK_F4) { + void PrintQuestDebug(); + PrintQuestDebug(); + return; + } + #endif + +/* #if CHEATS + if (wKey == VK_F4) { + if (cheatflag) toggle_frame_counter(); + return; + } + #endif*/ + + if (wKey == VK_F5) { + if (spselflag) SetSpellHK(0); + else GetSpellHK(0); + return; + } + if (wKey == VK_F6) { + if (spselflag) SetSpellHK(1); + else GetSpellHK(1); + return; + } + if (wKey == VK_F7) { + if (spselflag) SetSpellHK(2); + else GetSpellHK(2); + return; + } + if (wKey == VK_F8) { + if (spselflag) SetSpellHK(3); + else GetSpellHK(3); + return; + } + + if (wKey == VK_F9) { + SendTaunt(0); + return; + } + if (wKey == VK_F10) { + SendTaunt(1); + return; + } + if (wKey == VK_F11) { + SendTaunt(2); + return; + } + if (wKey == VK_F12) { + SendTaunt(3); + return; + } + + if (wKey == VK_UP) { + if (stextflag) STextUp(); + else if (questlog) QuestlogUp(); + else if (helpflag) HelpScrollUp(); + else if (automapflag) AutomapUp(); + return; + } + + if (wKey == VK_DOWN) { + if (stextflag) STextDown(); + else if (questlog) QuestlogDown(); + else if (helpflag) HelpScrollDown(); + else if (automapflag) AutomapDown(); + return; + } + + if (wKey == VK_PRIOR) { + if (stextflag) STextPgUp(); + return; + } + + if (wKey == VK_NEXT) { + if (stextflag) STextPgDown(); + return; + } + + if (wKey == VK_LEFT) { + if (automapflag && !talkflag) AutomapLeft(); + return; + } + if (wKey == VK_RIGHT) { + if (automapflag && !talkflag) AutomapRight(); + return; + } + + if (wKey == VK_TAB) { + void DoAutoMap(); + DoAutoMap(); + return; + } + +/* if (wKey == VK_CAPITAL) { + FriendlyMode = !FriendlyMode; + drawbtnflag = TRUE; + return; + }*/ + + if (wKey == VK_SPACE) { + if ((!chrflag) && (invflag) && (MouseX < 480) && (MouseY < 352)) SetCursorPos(MouseX+160,MouseY); + if ((!invflag) && (chrflag) && (MouseX > 160) && (MouseY < 352)) SetCursorPos(MouseX-160,MouseY); + helpflag = FALSE; + invflag = FALSE; + chrflag = FALSE; + sbookflag = FALSE; + spselflag = FALSE; + if ((qtextflag) && (leveltype == 0)) { + qtextflag = FALSE; + stream_stop(); + } + questlog = FALSE; + automapflag = FALSE; + msgdelay = 0; + gamemenu_off(); + EndMapOfDoomView(); +//Never clear the cursor, else we lose a scroll or a staff charge +//for a spell we've cast. +// if ((curs != GLOVE_CURS) && (curs < ICSTART)) NewCursor(GLOVE_CURS); + return; + } +} + + +//****************************************************************** +//****************************************************************** +static void wm_char(WPARAM wKey) { + #ifdef _DEBUG + BOOL is_pat_debug_cmd(WPARAM wKey); + if (is_pat_debug_cmd(wKey)) + return; + #endif + + // don't allow input while the menu is active + if (gmenu_is_on()) + return; + + if (Talk_wm_char(wKey)) + return; + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) + return; + + // dead players can't perform input + if (deathflag) + return; + + // in pause mode the only thing we can do is unpause + if ((TCHAR) wKey == 'p' || (TCHAR) wKey == 'P') { + TogglePause(); + return; + } + if (PauseMode == 2) return; + + if (drawmapofdoom) { + EndMapOfDoomView(); + return; + } + + if (dropGoldFlag) { + DropGoldType((char) wKey); + return; + } + + switch(wKey) { + case 'g': + case 'G': + GammaDown(); + return; + + case 'f': + case 'F': + GammaUp(); + return; + + case 'i': + case 'I': + if (stextflag != STORE_NONE) return; + sbookflag = FALSE; + invflag = !invflag; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + if (invflag && !chrflag) { + if (MouseX > 160 && MouseY < 352) SetCursorPos(MouseX-160,MouseY); + } + else { + if (MouseX < 480 && MouseY < 352) SetCursorPos(MouseX+160, MouseY); + } + return; + + case 'c': + case 'C': + if (stextflag != STORE_NONE) return; + questlog = FALSE; + chrflag = !chrflag; + if (chrflag && !invflag) { + if (MouseX < 480 && MouseY < 352) SetCursorPos(MouseX+160,MouseY); + } + else { + if (MouseX > 160 && MouseY < 352) SetCursorPos(MouseX-160, MouseY); + } + return; + + #ifndef NDEBUG + case 'r': + case 'R': + sprintf(tempstr, "seed = %i", glSeedTbl[currlevel]); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "Mid1 = %i : Mid2 = %i : Mid3 = %i", + glMid1Seed[currlevel], glMid2Seed[currlevel], glMid3Seed[currlevel]); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "End = %i", glEndSeed[currlevel]); + NetSendString((1 << myplr), tempstr); + return; + #endif + + #if CHEATS + case 'A': + if (cheatflag) { + sprintf(tempstr, "Mid: %i", dMonster[cursmx][cursmy] - 1); + NetSendString((1 << myplr), tempstr); + if (dMonster[cursmx][cursmy] > 0) { + monster[(dMonster[cursmx][cursmy] - 1)]._mFlags |= MFLAG_MKILLER; + void M_Enemy(int); + M_Enemy((dMonster[cursmx][cursmy] - 1)); + } + } + return; + case 'a': + if (cheatflag) { + plr[myplr]._pSplLvl[(plr[myplr]._pSpell)]++; + spelldata[SPL_TELE].sTownSpell = TRUE; + } + return; + #endif + + #if CHEATS + case ')': + case '0': + if (cheatflag) { + if (gv1 > 2) gv1 = 0; + if (gv1 == 0) { + plr[myplr]._pIFlags &= ~IAF_FIREARROW; + plr[myplr]._pIFlags &= ~IAF_LARROW; + } + if (gv1 == 1) plr[myplr]._pIFlags |= IAF_FIREARROW; + if (gv1 == 2) plr[myplr]._pIFlags |= IAF_LARROW; + gv1++; + } + return; + #endif + + #if CHEATS + case 'l': + case 'L': + if (cheatflag) ToggleLight(); + return; + #endif + + #if CHEATS + case 't': + case 'T': + if (cheatflag) { + sprintf(tempstr, "PX = %i PY = %i", plr[myplr]._px, plr[myplr]._py); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "CX = %i CY = %i DP = %i", cursmx, cursmy, dungeon[cursmx][cursmy]); + NetSendString((1 << myplr), tempstr); + } + return; + #endif + + #ifndef NDEBUG + case 'D': + void BlipDebug(BOOL); + BlipDebug(TRUE); + return; + case 'd': + BlipDebug(FALSE); + return; + #endif + + #if CHEATS + case 'e': + if (davedebug) { + sprintf(tempstr, "EFlag = %i", plr[myplr]._peflag); + NetSendString((1 << myplr), tempstr); + } + return; + #endif + + #ifndef NDEBUG + case 'm': + void DaveDebugMonst(); + DaveDebugMonst(); + return; + case 'M': + void DaveDebugMonst2(); + DaveDebugMonst2(); + return; + #endif + + #if CHEATS + case '|': + if ((currlevel == 0) && (davecheat)) DaveGold(); + return; + #endif + + #if CHEATS + case '~': + if ((currlevel == 0) && (davecheat)) DaveNewPremium(); + return; + #endif + + #if CHEATS + case '[': + if ((currlevel == 0) && (davecheat)) DaveCleanUp(); + return; + #endif + + #if CHEATS + case ']': + if ((currlevel == 0) && (davecheat)) DaveSpells(); + return; + #endif + + #if CHEATS + case ':': + if ((currlevel == 0) && (davecheat)) DaveSpells2(); + return; + #endif + + #if CHEATS + case '.': + void DaveDungDebug(); + DaveDungDebug(); + return; + #endif + + #if CHEATS + case '?': + if ((currlevel == 0) && (davecheat)) { + tstQMsgFlag = FALSE; + tstQMsgIndexFlag = TRUE; + sprintf(tempstr, "START QUEST TEXT MODE"); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "Message = %i", tstQMsgIndex); + NetSendString((1 << myplr), tempstr); + } + return; + #endif + + case 'q': + case 'Q': + if (stextflag != STORE_NONE) return; + chrflag = FALSE; + if (!questlog) StartQuestlog(); + else questlog = FALSE; + return; + + case 'z': + case 'Z': + svgamode = !svgamode; + return; + + case 's': + case 'S': + if (stextflag != STORE_NONE) return; + invflag = FALSE; + if (!spselflag) SetupSpellSel(); + else spselflag = FALSE; + TrackInit(FALSE); + return; + + case 'b': + case 'B': + if (stextflag != STORE_NONE) return; + invflag = FALSE; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + sbookflag = !sbookflag; + return; + + case '+': + case '=': + if (automapflag) AutomapZoomIn(); + #if CHEATS + else if ((currlevel == 0) && (davecheat)) { + if (tstQMsgIndexFlag) { + tstQMsgIndex++; + if (tstQMsgIndex > (int)(gdwAllTextEntries-1)) tstQMsgIndex = 0; + sprintf(tempstr, "Message = %i", tstQMsgIndex); + NetSendString((1 << myplr), tempstr); + } else if (tstQMsgFlag) { + tstQMsgSpd++; + if (tstQMsgSpd > 9) tstQMsgSpd = 9; + qtextSpd = qtextDelaySpd[tstQMsgSpd-1]; + qtextflag = FALSE; + stream_stop(); + DaveQuestText(); + sprintf(tempstr, "Message Speed = %i", tstQMsgSpd); + NetSendString((1 << myplr), tempstr); + } + } + #endif + return; + + case '_': + case '-': + if (automapflag) AutomapZoomOut(); + #if CHEATS + else if ((currlevel == 0) && (davecheat)) { + if (tstQMsgIndexFlag) { + tstQMsgIndex--; + if (tstQMsgIndex < 0) tstQMsgIndex = (int)(gdwAllTextEntries-1); + sprintf(tempstr, "Message = %i", tstQMsgIndex); + NetSendString((1 << myplr), tempstr); + } else if (tstQMsgFlag){ + tstQMsgSpd--; + if (tstQMsgSpd < 1) tstQMsgSpd = 1; + qtextSpd = qtextDelaySpd[tstQMsgSpd-1]; + qtextflag = FALSE; + stream_stop(); + DaveQuestText(); + sprintf(tempstr, "Message Speed = %i", tstQMsgSpd); + NetSendString((1 << myplr), tempstr); + } + } + #endif + return; + + case 'v': + extern char gszPrintVersion[]; + { + char *pszaDif[] = {"Normal", "Nightmare", "Hell"}; + char tmpbuf[120]; + sprintf(tmpbuf, "%s, mode = %s", gszPrintVersion, + pszaDif[gnDifficulty]); + NetSendString((1 << myplr), tmpbuf); + } +// NetSendString((1 << myplr), gszPrintVersion); + break; + + case 'V': + extern char gszVersionNumber[]; + NetSendString((1 << myplr), gszVersionNumber); + return; + + case '!': + case '1': + if ((plr[myplr].SpdList[0]._itype != -1) && + (plr[myplr].SpdList[0]._itype != IT_GOLD)) UseInvItem(myplr, 47); + return; + + case '@': + case '2': + if ((plr[myplr].SpdList[1]._itype != -1) && + (plr[myplr].SpdList[1]._itype != IT_GOLD)) UseInvItem(myplr, 48); + return; + + case '#': + case '3': + if ((plr[myplr].SpdList[2]._itype != -1) && + (plr[myplr].SpdList[2]._itype != IT_GOLD)) UseInvItem(myplr, 49); + return; + + case '$': + case '4': + if ((plr[myplr].SpdList[3]._itype != -1) && + (plr[myplr].SpdList[3]._itype != IT_GOLD)) UseInvItem(myplr, 50); + return; + + case '%': + case '5': + if ((plr[myplr].SpdList[4]._itype != -1) && + (plr[myplr].SpdList[4]._itype != IT_GOLD)) UseInvItem(myplr, 51); + return; + + case '^': + case '6': + if ((plr[myplr].SpdList[5]._itype != -1) && + (plr[myplr].SpdList[5]._itype != IT_GOLD)) UseInvItem(myplr, 52); + return; + + case '&': + case '7': + if ((plr[myplr].SpdList[6]._itype != -1) && + (plr[myplr].SpdList[6]._itype != IT_GOLD)) UseInvItem(myplr, 53); + return; + + case '*': + case '8': + #if CHEATS + if (cheatflag || davecheat) { + NetSendCmd(TRUE,CMD_CHEAT_EXPERIENCE); + return; + } + #endif + if ((plr[myplr].SpdList[7]._itype != -1) && + (plr[myplr].SpdList[7]._itype != IT_GOLD)) UseInvItem(myplr, 54); + return; +/* + // testing diablo death + case 'k': +#define MT_DIABLO 110 + for (int i = 0; i < nummonsters; i++) { + int mi = monstactive[i]; + if (monster[mi].MType->mtype == MT_DIABLO) + M_StartKill(mi, myplr); + } + return; +*/ + } +} + + +//****************************************************************** +//****************************************************************** +LRESULT CALLBACK DisableInputWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { + switch (uMsg) { + // don't let input go to game window proc + case WM_SYSKEYDOWN: + case WM_SYSCOMMAND: + case WM_KEYUP: + case WM_KEYDOWN: + case WM_CHAR: + case WM_MOUSEMOVE: + return 0; + + case WM_LBUTTONDOWN: + if (sgbMouseDown) return 0; + sgbMouseDown = LMOUSE_DOWN; + SetCapture(hWnd); + return 0; + + case WM_LBUTTONUP: + if (sgbMouseDown != LMOUSE_DOWN) return 0; + sgbMouseDown = 0; + ReleaseCapture(); + return 0; + + case WM_RBUTTONDOWN: + if (sgbMouseDown) return 0; + sgbMouseDown = RMOUSE_DOWN; + SetCapture(hWnd); + return 0; + + case WM_RBUTTONUP: + if (sgbMouseDown != RMOUSE_DOWN) return 0; + sgbMouseDown = 0; + ReleaseCapture(); + return 0; + + case WM_CAPTURECHANGED: + if (hWnd != (HWND) lParam) + sgbMouseDown = 0; + return 0; + } + + return DiabloDefProc(hWnd,uMsg,wParam,lParam); +} + + +//****************************************************************** +//****************************************************************** +static LRESULT CALLBACK GM_Game(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { + switch (uMsg) { + case WM_SYSKEYDOWN: + if (wm_syskeydown(wParam)) return 0; + break; + + case WM_KEYUP: + wm_keyup(wParam); + return 0; + + case WM_KEYDOWN: + wm_keydown(wParam); + return 0; + + case WM_CHAR: + wm_char(wParam); + return 0; + + case WM_MOUSEMOVE: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + wm_mousemove(); + return 0; + + case WM_LBUTTONDOWN: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + + // if the mouse is already down, wait for mouse up + if (sgbMouseDown) return 0; + sgbMouseDown = LMOUSE_DOWN; + SetCapture(hWnd); + + TrackInit(wm_lbuttondown(wParam)); + return 0; + + case WM_LBUTTONUP: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + + // don't accept mouse up unless it went down in our window + if (sgbMouseDown != LMOUSE_DOWN) return 0; + sgbMouseDown = 0; + + wm_lbuttonup(); + TrackInit(FALSE); + ReleaseCapture(); + return 0; + + case WM_RBUTTONDOWN: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + + // if the mouse is already down, wait for mouse up + if (sgbMouseDown) return 0; + sgbMouseDown = RMOUSE_DOWN; + SetCapture(hWnd); + + wm_rbuttondown(); + return 0; + + case WM_RBUTTONUP: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + + // don't accept mouse up unless it went down in our window + if (sgbMouseDown != RMOUSE_DOWN) return 0; + sgbMouseDown = 0; + ReleaseCapture(); + return 0; + + case WM_CAPTURECHANGED: + if (hWnd != (HWND) lParam) { + sgbMouseDown = 0; + TrackInit(FALSE); + } + break; + + case WM_DIABNEXTLVL: + case WM_DIABPREVLVL: + case WM_DIABSETLVL: + case WM_DIABRTNLVL: + case WM_DIABWARPLVL: + case WM_DIABTOWNWARP: + case WM_DIABTWARPUP: + case WM_DIABRETOWN: + // save character in multiplayer mode + if (gbMaxPlayers > 1) { + void UpdatePlayerFile(); + UpdatePlayerFile(); + } + nthread_perform_keepalive(TRUE); + PaletteFadeOut(FADE_FAST); + sound_stop(); + music_stop(); + TrackInit(FALSE); + sgbMouseDown = FALSE; + ReleaseCapture(); + ShowProgress(uMsg); + force_redraw = FULLDRAW; + DrawAndBlit(); + if (gbRunGame) PaletteFadeIn(FADE_FAST); + nthread_perform_keepalive(FALSE); + gbGameLoopStartup = TRUE; + return 0; + + case WM_SYSCOMMAND: + if (wParam == SC_CLOSE) { + gbRunGame = FALSE; + gbRunGameResult = FALSE; + return 0; + } + break; + } + + return DiabloDefProc(hWnd, uMsg, wParam, lParam); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void LoadLvlGFX() { + app_assert(! pDungeonCels); + switch (leveltype) { + case 0: + pDungeonCels = LoadFileInMemSig("NLevels\\TownData\\Town.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("NLevels\\TownData\\Town.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("NLevels\\TownData\\Town.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\TownData\\TownS.CEL",NULL,'TILE'); + break; + + case 1: +/* pDungeonCels = LoadFileInMemSig("Levels\\L1Data\\L1.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L1Data\\L1.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L1Data\\L1.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L1Data\\L1S.CEL",NULL,'TILE'); + break;*/ + if (currlevel < CRYPTSTART) + { + pDungeonCels = LoadFileInMemSig("Levels\\L1Data\\L1.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L1Data\\L1.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L1Data\\L1.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L1Data\\L1S.CEL",NULL,'TILE'); + } + else + { + pDungeonCels = LoadFileInMemSig("NLevels\\L5Data\\L5.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("NLevels\\L5Data\\L5.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("NLevels\\L5Data\\L5.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("NLevels\\L5Data\\L5S.CEL",NULL,'TILE'); + } + break; + + #if IS_VERSION(RETAIL) || IS_VERSION(BETA) + case 2: + pDungeonCels = LoadFileInMemSig("Levels\\L2Data\\L2.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L2Data\\L2.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L2Data\\L2.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L2Data\\L2S.CEL",NULL,'TILE'); + break; + #endif + + #if IS_VERSION(RETAIL) + case 3: + if (currlevel < HIVESTART) + { + pDungeonCels = LoadFileInMemSig("Levels\\L3Data\\L3.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L3Data\\L3.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L3Data\\L3.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L1Data\\L1S.CEL",NULL,'TILE'); + } + else + { + pDungeonCels = LoadFileInMemSig("NLevels\\L6Data\\L6.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("NLevels\\L6Data\\L6.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("NLevels\\L6Data\\L6.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L1Data\\L1S.CEL",NULL,'TILE'); + } + break; + #endif + + #if IS_VERSION(RETAIL) + case 4: + pDungeonCels = LoadFileInMemSig("Levels\\L4Data\\L4.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L4Data\\L4.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L4Data\\L4.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L2Data\\L2S.CEL",NULL,'TILE'); + break; + #endif + + default: + app_fatal("LoadLvlGFX"); + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void LoadAllGFX() +{ + app_assert(! pSpeedCels); + pSpeedCels = DiabloAllocPtrSig(SPEEDSIZE,'SPED'); +// InitMonsterGFX(); + IntCheck(); +// InitMonsterSND(); + IntCheck(); + InitObjectGFX(); + IntCheck(); + InitMissileGFX(); + IntCheck(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CreateLevel(int lvldir) +{ + switch (leveltype) { + case 0: + CreateTown(lvldir); + InitTownTriggers(); + LoadRndLvlPal(0); + break; + + case 1: + CreateL5Dungeon(glSeedTbl[currlevel], lvldir); + InitL1Triggers(); + Freeupstairs(); + if (currlevel < CRYPTSTART) // JKE load correct pallet + LoadRndLvlPal(1); + else + LoadRndLvlPal(5); + break; + + #if IS_VERSION(RETAIL) || IS_VERSION(BETA) + case 2: + CreateL2Dungeon(glSeedTbl[currlevel], lvldir); + InitL2Triggers(); + Freeupstairs(); + LoadRndLvlPal(2); + break; + #endif + + #if IS_VERSION(RETAIL) + case 3: + CreateL3Dungeon(glSeedTbl[currlevel], lvldir); + InitL3Triggers(); + Freeupstairs(); + if (currlevel < HIVESTART) + LoadRndLvlPal(3); + else + LoadRndLvlPal(6); + break; + #endif + + #if IS_VERSION(RETAIL) + case 4: + CreateL4Dungeon(glSeedTbl[currlevel], lvldir); + InitL4Triggers(); + Freeupstairs(); + LoadRndLvlPal(4); + break; + #endif + + default: + app_fatal("CreateLevel"); + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void LoadGameLevel(BOOL firstflag, int lvldir) +{ + int i,j; + + if (setseed) + glSeedTbl[currlevel] = setseed; + + music_stop(); + SetCursor(GLOVE_CURS); + SetRndSeed(glSeedTbl[currlevel]); + IntCheck(); + + MakeLightTable(); + LoadLvlGFX(); + IntCheck(); + + if (firstflag) { + InitInv(); + InitItemGFX(); + InitQuestText(); + for (i = 0; i < gbMaxPlayers; i++) + InitPlrGFXMem(i); + InitStores(); + InitAutomapOnce(); + InitHelpSys(); + } + + SetRndSeed(glSeedTbl[currlevel]); + if (leveltype == 0) SetupTownStores(); + IntCheck(); + + InitAutomap(); + + if ((leveltype != 0) && (lvldir != LVL_NODIR)) { + InitLighting(); + InitVision(); + } + InitLevelMonsters(); + IntCheck(); + + if (!setlevel) { + CreateLevel(lvldir); + IntCheck(); + + // Open Tiles file + FillSolidBlockTbls(); + + SetRndSeed(glSeedTbl[currlevel]); + + if (leveltype != 0) { + GetLevelMTypes(); + InitThemes(); + LoadAllGFX(); + } else { + InitMissileGFX(); + } + IntCheck(); + + if (lvldir == LVL_RTN) GetReturnLvlPos(); + if (lvldir == LVL_WARP) GetPortalLvlPos(); + IntCheck(); + + // Init Player info + for (i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (currlevel != plr[i].plrlevel) continue; + InitPlayerGFX(i); + if (lvldir != LVL_NODIR) InitPlayer(i, firstflag); + } + + PlayDungMsgs(); + InitMultiView(); + IntCheck(); + + BOOL visited = FALSE; + for (i = 0; i < gbMaxPlayers; i++) + if (plr[i].plractive) visited = visited || plr[i]._pLvlVisited[currlevel]; + + // Resync after level changing bug + // This bug occurs when 2 players change levels one after the other. The first player + // down thinks the other player is one level above, because the change level msg has + // not been processed during loading. The second player knows that they are both + // on the same level, so more players get inited, and randoms desync. + SetRndSeed(glSeedTbl[currlevel]); + + if (leveltype != 0) { + if (!firstflag && (lvldir != LVL_NODIR) && plr[myplr]._pLvlVisited[currlevel] && (gbMaxPlayers == 1)) { + // Init monsters so uniques are loaded + InitMonsters (); + // Init missiles + InitMissiles(); + // Init dead info, not dungeon layout though + InitDead(); + IntCheck (); + // Load where things were + LoadLevel(); + IntCheck (); + } else { + // Save theme room areas + HoldThemeRooms(); + glMid1Seed[currlevel] = GetRndSeed(); // @@@ drb temp + // Init monsters into dungeon + InitMonsters (); + glMid2Seed[currlevel] = GetRndSeed(); // @@@ drb temp + // Init objects + InitObjects(); + // Init items + InitItems(); + // Fill theme rooms + if (currlevel < HIVESTART) CreateThemeRooms(); // Temp hack for failure JKE +// CreateThemeRooms(); + glMid3Seed[currlevel] = GetRndSeed(); // @@@ drb temp + // Init missiles + InitMissiles(); + // Init dead info, not dungeon layout though + InitDead(); + glEndSeed[currlevel] = GetRndSeed(); // @@@ drb temp + // if multiplayer resync level + if (gbMaxPlayers != 1) DeltaLoadLevel(); + IntCheck(); + SavePreLighting(); + } + } else { + // Make everything visible + for (i = 0; i < DMAXX; i++) + for (j = 0; j < DMAXY; j++) + dFlags[i][j] |= BFLAG_VISIBLE; + // Init town people + InitTowners(); + // Init items + InitItems(); + // Init missiles + InitMissiles(); + IntCheck(); + + // Load items + if (!firstflag && (lvldir != LVL_NODIR) && plr[myplr]._pLvlVisited[currlevel] && (gbMaxPlayers == 1)) + LoadLevel(); + if (gbMaxPlayers != 1) DeltaLoadLevel(); + IntCheck (); + } + if (gbMaxPlayers == 1) + ResyncQuests(); + else + ResyncMPQuests(); + + } +#if !IS_VERSION(SHAREWARE) + else { + // Preset levels + app_assert(! pSpeedCels); + pSpeedCels = DiabloAllocPtrSig(SPEEDSIZE,'SPED'); + + LoadSetMap(); + IntCheck(); + + GetLevelMTypes(); + + InitMonsters(); + + //SetDungeonMicros(); + + InitMissileGFX(); + + // Init dead info, not dungeon layout though + InitDead(); + + // Open Tiles file + FillSolidBlockTbls (); + IntCheck(); + + if (lvldir == LVL_WARP) GetPortalLvlPos(); + + // Init Player info + for (i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (currlevel != plr[i].plrlevel) continue; + InitPlayerGFX(i); + if (lvldir != LVL_NODIR) InitPlayer(i, firstflag); + } + + InitMultiView(); + IntCheck(); + + if ((!firstflag) && (lvldir != LVL_NODIR) && (plr[myplr]._pSLvlVisited[setlvlnum])) { + // Load where things were + LoadLevel(); + } else { + // Init items + InitItems(); + SavePreLighting(); + } + // Init missiles + InitMissiles(); + IntCheck(); + } +#endif + + SyncPortals(); + + for (i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (plr[i].plrlevel != currlevel) continue; + if (plr[i]._pLvlChanging && (i != myplr)) continue; + if (plr[i]._pHitPoints > 0) { + if (gbMaxPlayers == 1) + dPlayer[plr[i]._px][plr[i]._py] = i + 1; + else + SyncInitPlrPos(i); + } else + dFlags[plr[i]._px][plr[i]._py] |= BFLAG_DEADPLR; + } + + if (leveltype != 0) { + SetDungeonMicros(); + } + + InitLightMax(); // Set up 4 or 16 level lighting + IntCheck(); + +/* + if ((leveltype != 0) && (lvldir != LVL_NODIR)) { + SavePreLighting(); + } +*/ + IntCheck(); + + if (firstflag) { + // Get Control panel graphics and decompress panel to BtmBuff + // Has to be after init player because of bars/spells/equipment etc. + InitControlPan(); + IntCheck(); + } + + if (leveltype != 0) { + ProcessLightList(); + ProcessVisionList(); + } + if (currlevel >= CRYPTSTART) + { +// OpenCloseAllDoors(); // JKE Stupid!!! + if (currlevel == CORNERSTONE_LEVEL) + CornerstoneRestore(CornerStone.x, CornerStone.y); + if ((quests[Q_NA_KRUL]._qactive == QUEST_DONE)&&(currlevel == NA_KRUL_LEVEL)) + OpenNaKrul2(); + + } + + // start appropriate sound track + if (currlevel >= HIVESTART) // fix this later JKE + { + music_start((currlevel > HIVEEND)? 5 : 6); + } + else + music_start(leveltype); + + // finish progress bar + while (! IntCheck()) + NULL; + + #if !IS_VERSION(SHAREWARE) + if ((setlevel) && (setlvlnum == SL_SKELKING) && (quests[Q_SKELKING]._qactive == QUEST_NOTDONE)) + PlaySFX(USFX_SKING1); + #endif +} + + +//****************************************************************** +//****************************************************************** +// this parameter is the maximum number of game loops which can be run +// in a row without redrawing the screen +#define MAX_CONSECUTIVE_LOOPS 3 + + +//****************************************************************** +//****************************************************************** +static void game_logic() { + if (PauseMode == 2) return; + if (PauseMode == 1) PauseMode = 2; + + // pause when menu is active in single player mode + if (gbMaxPlayers == 1 && gmenu_is_on()) { + force_redraw |= VIEWDRAW; + return; + } + + if (! gmenu_is_on() && (sgnTimeoutCurs == NO_CURSOR)) { + CheckCursMove(); + TrackMouse(); + } + + if (gbProcessPlayers) + ProcessPlayers(); + if (leveltype) { + ProcessMonsters(); + ProcessObjects(); + ProcessMissiles(); + ProcessItems(); + ProcessLightList(); + ProcessVisionList(); + } + else { + ProcessTowners(); + ProcessItems(); + ProcessMissiles(); + } + + #if CHEATS + if ((cheatflag) && ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0)) + CheckForScroll(); + #endif + + sound_update(); + plrmsg_update(); + CheckTriggers(); + CheckQuests(); + force_redraw |= VIEWDRAW; + + void TimedUpdatePlayerFile(BOOL bForce); + TimedUpdatePlayerFile(FALSE); +} + + +//****************************************************************** +//****************************************************************** +static void timeout_cursor(BOOL bTimeout) { + if (bTimeout) { + // if we weren't in a timeout state, set timeout + if (sgnTimeoutCurs == NO_CURSOR && ! sgbMouseDown) { + sgnTimeoutCurs = curs; + + NetStartTimeout(); + + // display timeout error + ClearPanel(); + AddPanelString("-- Network timeout --", TEXT_CENTER); + AddPanelString("-- Waiting for players --", TEXT_CENTER); + + // fix up the cursor + NewCursor(TIMEOUT_CURSOR); + + // we probably made a mess of the screen + force_redraw = FULLDRAW; + } + + FullBlit(TRUE); + } + else if (sgnTimeoutCurs != NO_CURSOR) { + // ending timeout + SetCursor(sgnTimeoutCurs); + sgnTimeoutCurs = NO_CURSOR; + ClearPanel(); + force_redraw = FULLDRAW; + } +} + + +//****************************************************************** +//****************************************************************** +static void game_loop(BOOL bStartup) { + int nMaxLoops = bStartup ? GAME_FRAMES_PER_SECOND * 3 : MAX_CONSECUTIVE_LOOPS; + while (nMaxLoops--) { + // wait for synchronous network message + if (! NetEndSendCycle()) { + timeout_cursor(TRUE); + break; + } + timeout_cursor(FALSE); + + // run logic at GAME_FRAMES_PER_SECOND + game_logic(); + + // if the game mode changed, then don't continue loop + if (! gbRunGame) + break; + + // don't run multiple loops in single player mode + if (gbMaxPlayers == 1) + break; + + // have we been in the loop too long? + if (! nthread_run_gameloop(TRUE)) + break; + + #if CHEATS + static DWORD sdwSkips = 0; + sdwSkips++; + HDC hDC; + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr == DD_OK) { + char szBuf[16]; + wsprintf(szBuf,"%u",sdwSkips); + TextOut(hDC,5,370,szBuf,strlen(szBuf)); + lpDDSPrimary->ReleaseDC(hDC); + } + #endif + } +} + + +//****************************************************************** +//****************************************************************** +static void DoTimedEvents() { + static DWORD sdwCurrTime = 0; + DWORD dwCurrTime = GetTickCount(); + if (dwCurrTime - sdwCurrTime < 1000/GAME_FRAMES_PER_SECOND) + return; + sdwCurrTime = dwCurrTime; + + if (leveltype == 4) + BloodCycle(); + else if (currlevel >= CRYPTSTART) + TwinCycleCrypt(); + else if (currlevel >= HIVESTART) + TwinCycleNest(); + else if (leveltype == 3 && fullscreen) + LavaCycle(); +} + + +//****************************************************************** +//****************************************************************** +/* pjw.patch1.start +static void try_game_loop(BOOL bStartup) { + DoTimedEvents(); + NetReceivePackets(); + + if (! nthread_run_gameloop(FALSE)) + return; + + // run game loop + game_loop(bStartup); + + // redraw the screen if necessary + DrawAndBlit(); +} +pjw.patch1.end */ + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +#define RAND_MASK (32*1024-1) +#define PLR_BYTES (sizeof(PlayerStruct) * MAX_PLRS) +static PlayerStruct * alloc_plr_chunk(PlayerStruct * p1) { + + // make sure p2 ends up in different locations + LPVOID pTemp = malloc(rand() & RAND_MASK); + PlayerStruct * p2 = (PlayerStruct *) malloc(PLR_BYTES); + if (pTemp) free(pTemp); + + if (! p2) return p1; + if (p1) { + CopyMemory(p2,p1,PLR_BYTES); + free(p1); + } + return p2; +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +static void alloc_plr() { + if (NULL == (plr = alloc_plr_chunk(NULL))) + app_fatal("Unable to initialize memory"); + ZeroMemory(plr,PLR_BYTES); +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +#pragma intrinsic(_rotl) +static DWORD calc_checksum(LPVOID lpMem,DWORD dwBytes,DWORD dwSum) { + LPDWORD lpDW = (LPDWORD) lpMem; + dwBytes /= sizeof(DWORD); + while (dwBytes--) { + dwSum ^= *lpDW++; + dwSum = _rotl(dwSum,3); + } + return dwSum; +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +static void CRASH() { +#if 0 // !!! @@@ !!! fix in final + static BYTE sgbCheating = FALSE; + if (! sgbCheating) { + sgbCheating = TRUE; + app_warning("Cheating detected"); + void myDebugBreak(); + myDebugBreak(); + } +#else + LPDWORD pFrame = (LPDWORD) plr[myplr]._pAnimData; + pFrame[plr[myplr]._pAnimFrame + 1] ^= 0x3fffffff; +#endif + FullBlit(TRUE); +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +typedef void (* TCrypt)(LPDWORD,DWORD,DWORD); +static void encrypt_aux(TCrypt fnCrypt) { + for (int i = 0; i < MAX_PLRS; i++) { + // SLOW encrypt the important part of the character + fnCrypt((LPDWORD)&plr[i],offsetof(PlayerStruct,_pGFXLoad),HASH_ENCRYPTKEY); + + // FAST encrypt the inventory -- takes too long otherwise + LPDWORD lpInv = (LPDWORD) &plr[i].InvBody; + for (int j = sizeof(ItemStruct) * NUM_INVLOC / sizeof(DWORD); j--; ) + *lpInv++ ^= 0xf0638142; + + // pjw.patch2.start -- commented out -- still taking too long + #if 0 + lpInv = (LPDWORD) &plr[i].InvList; + for (j = sizeof(ItemStruct) * MAXINV / sizeof(DWORD); j--; ) + *lpInv++ ^= 0x23484862; + #endif + // pjw.patch2.end + } +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +#if 0 +// pjw.patch1.start +static void plr_encrypt(BOOL bEncrypt) { + static BOOL sbEncrypt = FALSE; + static BOOL sbCrash = FALSE; + static DWORD sdwCheckSum = 0; + static DWORD sdwCheckStart = 0; + if (sbEncrypt == bEncrypt) return; + sbEncrypt = bEncrypt; + +// pjw.patch2.start -- added for debugging only! +#if 0 + static DWORD sgdwEncryptCount = 0; + sgdwEncryptCount++; + static DWORD sgdwLastTime = 0; + if (GetTickCount() - sgdwLastTime >= 1000) { + sgdwLastTime = GetTickCount(); + do { + char szBuf[32]; + HDC hDC; + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr != DD_OK) break; + COLORREF oldTextColor = SetTextColor(hDC,RGB(0xff,0xff,0)); + COLORREF oldBkColor = SetBkColor(hDC,RGB(0,0,0)); + int oldBkMode = SetBkMode(hDC,OPAQUE); + sprintf(szBuf,"%u ",sgdwEncryptCount); + sgdwEncryptCount = 0; + TextOut(hDC,5,385,szBuf,strlen(szBuf)); + SetTextColor(hDC,oldTextColor); + SetBkColor(hDC,oldBkColor); + SetBkMode(hDC,oldBkMode); + lpDDSPrimary->ReleaseDC(hDC); + } while (0); + } +#endif +// pjw.patch2.end + + if (sbCrash) { + CRASH(); + } + else if (bEncrypt) { + sdwCheckStart = rand(); + sdwCheckSum = calc_checksum(plr,PLR_BYTES,sdwCheckStart); + encrypt_aux(Encrypt); + } + else { + encrypt_aux(Decrypt); + if (sdwCheckSum != calc_checksum(plr,PLR_BYTES,sdwCheckStart)) { + CRASH(); + sbCrash = 1; + } + } + + if ((rand() & 0x0f) == 0x0f) + plr = alloc_plr_chunk(plr); +} +#endif +// pjw.patch1.end diff --git a/src/DIABLO.DSP b/src/DIABLO.DSP new file mode 100644 index 0000000..d53c019 --- /dev/null +++ b/src/DIABLO.DSP @@ -0,0 +1,763 @@ +# Microsoft Developer Studio Project File - Name="Diablo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=Diablo - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Diablo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Diablo.mak" CFG="Diablo - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Diablo - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 FinalFinal" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Shareware FinalFinal" (based on\ + "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Shareware Release" (based on\ + "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Diablo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\WinRel" +# PROP BASE Intermediate_Dir ".\WinRel" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\WinRel" +# PROP Intermediate_Dir ".\WinRel" +# PROP Ignore_Export_Lib 0 +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /c +# ADD CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D PROGRAM_VERSION=RETAIL /FAcs /Fr /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /map /machine:I386 /nodefaultlib /out:".\WinRel/hellfire.exe" +# SUBTRACT LINK32 /incremental:yes /debug + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\WinDebug" +# PROP BASE Intermediate_Dir ".\WinDebug" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\WinDebug" +# PROP Intermediate_Dir ".\WinDebug" +# PROP Ignore_Export_Lib 0 +# ADD BASE CPP /nologo /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /c +# ADD CPP /nologo /G5 /Gr /MTd /W3 /Gm /GR /GX /Zi /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D PROGRAM_VERSION=RETAIL /D "DEBUG_MEM" /D "_MULTITEST" /FAcs /Fr /YX /FD /c +# SUBTRACT CPP /Gy +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /profile /map /debug /machine:I386 /nodefaultlib /out:".\WinDebug/Hellfire.exe" +# SUBTRACT LINK32 /force + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Diablo__" +# PROP BASE Intermediate_Dir ".\Diablo__" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\WinFinal" +# PROP Intermediate_Dir ".\WinFinal" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# SUBTRACT BASE CPP /Fr +# ADD CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D PROGRAM_VERSION=RETAIL /D "_MULTITEST" /FAcs /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 winspool.lib libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /map /machine:I386 /nodefaultlib /out:".\WinFinal/Hellfire.exe" +# SUBTRACT LINK32 /incremental:yes + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Diablo__" +# PROP BASE Intermediate_Dir ".\Diablo__" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\SFinal" +# PROP Intermediate_Dir ".\SFinal" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /YX /c +# SUBTRACT BASE CPP /Fr +# ADD CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG" /D PROGRAM_VERSION=SHAREWARE /FAcs /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /machine:I386 /nodefaultlib +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /map /machine:I386 /nodefaultlib +# SUBTRACT LINK32 /incremental:yes + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Diablo_0" +# PROP BASE Intermediate_Dir ".\Diablo_0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\SRel" +# PROP Intermediate_Dir ".\SRel" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /YX /c +# SUBTRACT BASE CPP /Fr +# ADD CPP /nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D PROGRAM_VERSION=SHAREWARE /FAcs /YX /FD /c +# SUBTRACT CPP /Fr +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib +# ADD LINK32 libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows /map /debug /machine:I386 /nodefaultlib +# SUBTRACT LINK32 /incremental:yes + +!ENDIF + +# Begin Target + +# Name "Diablo - Win32 Release" +# Name "Diablo - Win32 Debug" +# Name "Diablo - Win32 FinalFinal" +# Name "Diablo - Win32 Shareware FinalFinal" +# Name "Diablo - Win32 Shareware Release" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\appfat.cpp +# End Source File +# Begin Source File + +SOURCE=.\automap.cpp +# End Source File +# Begin Source File + +SOURCE=.\capture.cpp +# End Source File +# Begin Source File + +SOURCE=.\CODEC.CPP +# End Source File +# Begin Source File + +SOURCE=.\CONTROL.CPP +# End Source File +# Begin Source File + +SOURCE=.\CURSOR.CPP +# End Source File +# Begin Source File + +SOURCE=.\ddraw.lib +# End Source File +# Begin Source File + +SOURCE=.\DEAD.CPP +# End Source File +# Begin Source File + +SOURCE=.\DEBUG.CPP +# End Source File +# Begin Source File + +SOURCE=.\DIABLO.CPP +# End Source File +# Begin Source File + +SOURCE=.\diablo.rc + +!IF "$(CFG)" == "Diablo - Win32 Release" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\doom.cpp +# End Source File +# Begin Source File + +SOURCE=.\DRLG_L1.CPP +# End Source File +# Begin Source File + +SOURCE=.\DRLG_L2.CPP +# End Source File +# Begin Source File + +SOURCE=.\DRLG_L3.CPP +# End Source File +# Begin Source File + +SOURCE=.\drlg_l4.cpp +# End Source File +# Begin Source File + +SOURCE=.\dsound.lib +# End Source File +# Begin Source File + +SOURCE=.\dthread.cpp +# End Source File +# Begin Source File + +SOURCE=.\dx.cpp +# End Source File +# Begin Source File + +SOURCE=.\effects.cpp +# End Source File +# Begin Source File + +SOURCE=.\encrypt.cpp +# End Source File +# Begin Source File + +SOURCE=.\ENGINE.CPP +# End Source File +# Begin Source File + +SOURCE=.\error.cpp +# End Source File +# Begin Source File + +SOURCE=.\except.cpp +# End Source File +# Begin Source File + +SOURCE=.\GameMenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\GENDUNG.CPP +# End Source File +# Begin Source File + +SOURCE=.\gmenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\WinDebug\hellfrui.lib +# End Source File +# Begin Source File + +SOURCE=.\help.cpp +# End Source File +# Begin Source File + +SOURCE=.\implode.lib +# End Source File +# Begin Source File + +SOURCE=.\init.cpp +# End Source File +# Begin Source File + +SOURCE=.\Interfac.cpp +# End Source File +# Begin Source File + +SOURCE=.\inv.cpp +# End Source File +# Begin Source File + +SOURCE=.\itemdat.cpp +# End Source File +# Begin Source File + +SOURCE=.\ITEMS.CPP +# End Source File +# Begin Source File + +SOURCE=.\LIGHTING.CPP +# End Source File +# Begin Source File + +SOURCE=.\loadsave.cpp +# End Source File +# Begin Source File + +SOURCE=.\mainmenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\minitext.cpp +# End Source File +# Begin Source File + +SOURCE=.\misdat.cpp +# End Source File +# Begin Source File + +SOURCE=.\misdat.h +# End Source File +# Begin Source File + +SOURCE=.\MISSILES.CPP +# End Source File +# Begin Source File + +SOURCE=.\Mono.cpp +# End Source File +# Begin Source File + +SOURCE=.\MONSTDAT.CPP +# End Source File +# Begin Source File + +SOURCE=.\MONSTER.CPP +# End Source File +# Begin Source File + +SOURCE=.\movie.cpp +# End Source File +# Begin Source File + +SOURCE=.\mpqapi.cpp +# End Source File +# Begin Source File + +SOURCE=.\msg.cpp +# End Source File +# Begin Source File + +SOURCE=.\multi.cpp +# End Source File +# Begin Source File + +SOURCE=.\nthread.cpp +# End Source File +# Begin Source File + +SOURCE=.\objdat.cpp +# End Source File +# Begin Source File + +SOURCE=.\OBJECTS.CPP +# End Source File +# Begin Source File + +SOURCE=.\packplr.cpp +# End Source File +# Begin Source File + +SOURCE=.\PALETTE.CPP +# End Source File +# Begin Source File + +SOURCE=.\path.cpp +# End Source File +# Begin Source File + +SOURCE=.\pfile.cpp +# End Source File +# Begin Source File + +SOURCE=.\PLAYER.CPP +# End Source File +# Begin Source File + +SOURCE=.\plrmsg.cpp +# End Source File +# Begin Source File + +SOURCE=.\portal.cpp +# End Source File +# Begin Source File + +SOURCE=.\Quests.cpp +# End Source File +# Begin Source File + +SOURCE=.\SCROLLRT.CPP +# End Source File +# Begin Source File + +SOURCE=.\SetMaps.cpp +# End Source File +# Begin Source File + +SOURCE=.\SHA.CPP +# End Source File +# Begin Source File + +SOURCE=.\SOUND.CPP +# End Source File +# Begin Source File + +SOURCE=.\Spelldat.cpp +# End Source File +# Begin Source File + +SOURCE=.\SPELLS.CPP +# End Source File +# Begin Source File + +SOURCE=.\stores.cpp +# End Source File +# Begin Source File + +SOURCE=.\WinDebug\storm.lib +# End Source File +# Begin Source File + +SOURCE=.\sync.cpp +# End Source File +# Begin Source File + +SOURCE=.\Textdat.cpp +# End Source File +# Begin Source File + +SOURCE=.\themes.cpp +# End Source File +# Begin Source File + +SOURCE=.\tmsg.cpp +# End Source File +# Begin Source File + +SOURCE=.\TOWN.CPP +# End Source File +# Begin Source File + +SOURCE=.\towners.cpp +# End Source File +# Begin Source File + +SOURCE=.\track.cpp +# End Source File +# Begin Source File + +SOURCE=.\TRIGS.CPP +# End Source File +# Begin Source File + +SOURCE=.\wave.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\automap.h +# End Source File +# Begin Source File + +SOURCE=.\Control.h +# End Source File +# Begin Source File + +SOURCE=.\Cursor.h +# End Source File +# Begin Source File + +SOURCE=.\d3dtypes.h +# End Source File +# Begin Source File + +SOURCE=.\Ddraw.h +# End Source File +# Begin Source File + +SOURCE=.\Dead.h +# End Source File +# Begin Source File + +SOURCE=.\Debug.h +# End Source File +# Begin Source File + +SOURCE=.\Diablo.h +# End Source File +# Begin Source File + +SOURCE=.\Diabloui.h +# End Source File +# Begin Source File + +SOURCE=.\doom.h +# End Source File +# Begin Source File + +SOURCE=.\Drlg_l1.h +# End Source File +# Begin Source File + +SOURCE=.\Drlg_l2.h +# End Source File +# Begin Source File + +SOURCE=.\Drlg_l3.h +# End Source File +# Begin Source File + +SOURCE=.\Drlg_l4.h +# End Source File +# Begin Source File + +SOURCE=.\Dsound.h +# End Source File +# Begin Source File + +SOURCE=.\Effects.h +# End Source File +# Begin Source File + +SOURCE=.\Engine.h +# End Source File +# Begin Source File + +SOURCE=.\error.h +# End Source File +# Begin Source File + +SOURCE=.\Gamemenu.h +# End Source File +# Begin Source File + +SOURCE=.\Gendung.h +# End Source File +# Begin Source File + +SOURCE=.\help.h +# End Source File +# Begin Source File + +SOURCE=.\implode.h +# End Source File +# Begin Source File + +SOURCE=.\Interfac.h +# End Source File +# Begin Source File + +SOURCE=.\Inv.h +# End Source File +# Begin Source File + +SOURCE=.\itemdat.h +# End Source File +# Begin Source File + +SOURCE=.\Items.h +# End Source File +# Begin Source File + +SOURCE=.\Lighting.h +# End Source File +# Begin Source File + +SOURCE=.\mainmenu.h +# End Source File +# Begin Source File + +SOURCE=.\MiniText.h +# End Source File +# Begin Source File + +SOURCE=.\Missiles.h +# End Source File +# Begin Source File + +SOURCE=.\Mono.h +# End Source File +# Begin Source File + +SOURCE=.\Monstdat.h +# End Source File +# Begin Source File + +SOURCE=.\Monster.h +# End Source File +# Begin Source File + +SOURCE=.\monstint.h +# End Source File +# Begin Source File + +SOURCE=.\mpqapi.h +# End Source File +# Begin Source File + +SOURCE=.\msg.h +# End Source File +# Begin Source File + +SOURCE=.\Multi.h +# End Source File +# Begin Source File + +SOURCE=.\objdat.h +# End Source File +# Begin Source File + +SOURCE=.\Objects.h +# End Source File +# Begin Source File + +SOURCE=.\packplr.h +# End Source File +# Begin Source File + +SOURCE=.\Palette.h +# End Source File +# Begin Source File + +SOURCE=.\path.h +# End Source File +# Begin Source File + +SOURCE=.\Player.h +# End Source File +# Begin Source File + +SOURCE=.\portal.h +# End Source File +# Begin Source File + +SOURCE=.\Quests.h +# End Source File +# Begin Source File + +SOURCE=.\regconst.h +# End Source File +# Begin Source File + +SOURCE=.\Sclass.h +# End Source File +# Begin Source File + +SOURCE=.\scrlasm.h +# End Source File +# Begin Source File + +SOURCE=.\Scrollrt.h +# End Source File +# Begin Source File + +SOURCE=.\Setmaps.h +# End Source File +# Begin Source File + +SOURCE=.\Sound.h +# End Source File +# Begin Source File + +SOURCE=.\spelldat.h +# End Source File +# Begin Source File + +SOURCE=.\Spells.h +# End Source File +# Begin Source File + +SOURCE=.\stores.h +# End Source File +# Begin Source File + +SOURCE=.\Storm.h +# End Source File +# Begin Source File + +SOURCE=.\textdat.h +# End Source File +# Begin Source File + +SOURCE=.\themes.h +# End Source File +# Begin Source File + +SOURCE=.\Town.h +# End Source File +# Begin Source File + +SOURCE=.\towners.h +# End Source File +# Begin Source File + +SOURCE=.\Trigs.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\icon1.ico +# End Source File +# End Group +# Begin Source File + +SOURCE=.\WinRel\Scroll.obj +# End Source File +# End Target +# End Project diff --git a/src/DIABLO.DSW b/src/DIABLO.DSW new file mode 100644 index 0000000..2062bc1 --- /dev/null +++ b/src/DIABLO.DSW @@ -0,0 +1,41 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Diablo"=.\Diablo.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ui"=.\UISRC\UI\ui.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/DIABLO.H b/src/DIABLO.H new file mode 100644 index 0000000..f7fef8e --- /dev/null +++ b/src/DIABLO.H @@ -0,0 +1,316 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/DIABLO.H 4 2/10/97 6:22p Dbrevik2 $ +**-----------------------------------------------------------------------*/ + + +//****************************************************************** +// SOFTWARE VERSIONING +//****************************************************************** +// version constants +#define SHAREWARE 1 +#define BETA 2 +#define RETAIL 3 +#define IS_VERSION(x) (PROGRAM_VERSION == x) + +// make sure valid PROGRAM_VERSION is defined +#ifndef PROGRAM_VERSION +#error PROGRAM_VERSION should be defined in Build.Settings.C/C++.Preprocessor +#elif IS_VERSION(SHAREWARE) +//#pragma message("*building shareware") +#elif IS_VERSION(BETA) +//#pragma message("*building beta") +#elif IS_VERSION(RETAIL) +//#pragma message("*building retail") +#else +#error PROGRAM_VERSION is invalid +#endif + + + +// collin's new RLE draw code -- must have +// reprocessed .CL2 files for this to work +#define RLE_DRAW 1 // 1 in final + + +// cheats compile flag 0 == off, 1 == on +#define CHEATS 1 // 0 in final +#ifdef NDEBUG +#undef CHEATS +#define CHEATS 0 +#endif + +// misc 0 == testing, 1 == normal +#define RELEASE 1 // 1 in final +#ifdef NDEBUG +#undef RELEASE +#define RELEASE 1 +#endif + +// 1 = allow debugging, 0 = release +#define ALLOW_WINDOWED_MODE 1 // 0 in final +#ifdef NDEBUG +#undef ALLOW_WINDOWED_MODE +#define ALLOW_WINDOWED_MODE 0 +#endif + +// 1 = show network debugging info +#define TRACEOUT 1 // 0 in final +#ifdef NDEBUG +#undef TRACEOUT +#define TRACEOUT 0 +#endif + + +// 1 = show current trace function, 0 = release +#define ALLOW_TRACE_FCN 0 // 0 in final +#ifdef NDEBUG +#undef ALLOW_TRACE_FCN +#define ALLOW_TRACE_FCN 0 +#endif + +#if ALLOW_TRACE_FCN +void trace_fcn(const char * pszFcn); +#define TRACE_FCN(x) trace_fcn(x) +#else +#define TRACE_FCN(x) NULL +#endif + + +// save file "version" +// so we don't have version number conflicts: +// - EVEN number if RETAIL/SHAREWARE version +// - ODD number if BETA version +#define SAVE_GAME_KEY 0x7058 +#if IS_VERSION(RETAIL) && ((SAVE_GAME_KEY & 1) != 0) + #error -- SAVE_GAME_KEY must be EVEN for RETAIL version +#endif +#if IS_VERSION(BETA) && ((SAVE_GAME_KEY & 1) == 0) + #error -- SAVE_GAME_KEY must be ODD for BETA version +#endif + + +// EVEN version ID = retail version +// ODD version ID = beta version +#define VERSIONID 34 +#if IS_VERSION(RETAIL) && ((VERSIONID & 1) != 0) + #error -- VERSIONID must be EVEN for RETAIL version +#endif +#if IS_VERSION(BETA) && ((VERSIONID & 1) == 0) + #error -- VERSIONID must be ODD for BETA version +#endif + + +#ifndef PROGRAM_VERSION +#error PROGRAM_VERSION not defined +#elif IS_VERSION(RETAIL) +//#define PROGRAMID 'DRTL' +#define PROGRAMID 'HRTL' +#elif IS_VERSION(SHAREWARE) +#define PROGRAMID 'DSHR' +#elif IS_VERSION(BETA) +#define PROGRAMID 'DIAB' +#else +#error -- VERSION NOT DEFINED +#endif + + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ +#define MAX_PLRS 4 + +// frame rate +#define GAME_FRAMES_PER_SECOND 20 + +// Our messages +#define WM_DIABNEXTLVL WM_USER+2 +#define WM_DIABPREVLVL WM_USER+3 +#define WM_DIABRTNLVL WM_USER+4 +#define WM_DIABSETLVL WM_USER+5 +#define WM_DIABWARPLVL WM_USER+6 +#define WM_DIABTOWNWARP WM_USER+7 +#define WM_DIABTWARPUP WM_USER+8 +#define WM_DIABRETOWN WM_USER+9 +#define WM_DIABNEWGAME WM_USER+10 +#define WM_DIABLOADGAME WM_USER+11 + + +// Screen size +#define TOTALX 640 +#define TOTALY 480 + +// Size of control panel +#define CTRLPANY 128 + +// Size of game play area +#define GAMEY 352 + +// Offscreen buffer size +#define BUFFERX 768 +#define BUFFERY 656 +#define BUFFERSIZE BUFFERX*BUFFERY + +#define BTMBUFFX 640 +#define BTMBUFFY 144 +#define BTMBUFFSIZE BTMBUFFX*BTMBUFFY +#define BTMBUFFMULTISIZE BTMBUFFX*BTMBUFFY*2 + +// Used in processing players, monsters, objects etc. +#define RUN_DONE 0 +#define RUN_AGAIN 1 + +#define MAX_LEVELS 24 +#define DIABLO_LEVEL 16 +#define SLAIN_HERO_LEVEL 9 +#define STORY_BOOK1_LEVEL 4 +#define STORY_BOOK2_LEVEL 8 +#define STORY_BOOK3_LEVEL 12 + +// JKE STORY BOOKS FOR HELLFIRE +#define SKULKEN_BOOK1_LEVEL 21 +#define SKULKEN_BOOK2_LEVEL 22 +#define SKULKEN_BOOK3_LEVEL 23 + +/*-----------------------------------------------------------------------** +** Included files +**-----------------------------------------------------------------------*/ +#define STRICT +#include +#include +#include +#include +#include +#include +#include "ddraw.h" +#include "dsound.h" +#include +#include +#include + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern HWND ghMainWnd; +extern HINSTANCE ghInst; +extern const char gszAppName[]; + +// DO NOT USE gbFontTransTbl directly -- use the macro +// to prevent sign extension problems with characters!!! +extern const BYTE gbFontTransTbl[]; +#define char2print(c) gbFontTransTbl[(BYTE) (c)]; + + +// video vars +extern LPDIRECTDRAW lpDD; +extern LPDIRECTDRAWSURFACE lpDDSPrimary; +extern LPDIRECTDRAWPALETTE lpDDPal; +extern BOOL fullscreen; +extern BOOL bActive; + +// these variables are only valid if lock_buf() has been called +extern BYTE * gpBuffer; +extern "C" long glClipY; +void lock_buf(BYTE bFcn); +void unlock_buf(BYTE bFcn); + +// program vars +extern BOOL svgamode; +extern int MouseX, MouseY; +extern int force_redraw; + + +// Temp vars (delete all uses before final compile) +extern long gv1; +extern long gv2; +extern long gv3; +extern long gv4; +extern long gv5; + + +// General flags +extern BOOL PauseMode; +extern BOOL gbProcessPlayers; +extern BOOL FriendlyMode; +#if CHEATS +extern BOOL davedebug; +extern BOOL cheatflag; +extern BOOL simplecheat; +#endif +extern BOOL visiondebug; +extern BOOL light4flag; +extern BOOL leveldebug; +extern BOOL monstdebug; +extern int debugmonsttypes; +extern int DebugMonsters[10]; + + +/*----------------------------------------------------------*/ +// HELLFIRE FLAGS +/*----------------------------------------------------------*/ + +extern bool gbTheo; +extern bool gbCowsuit; +extern bool gbOurNest; +extern bool gbAllowBard; +extern bool gbAllowBarbarian; +extern bool gbAllowMultiPlayer; +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +LRESULT CALLBACK DiabloDefProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); +void LoadGameLevel(BOOL, int); +void FreeGameMem(); +void SetupSaveBasePath(); + + +#if TRACEOUT +void __cdecl TraceOut(const char * pszFmt, ...); +#endif + + +/*-----------------------------------------------------------------------** +** Assertion System +**-----------------------------------------------------------------------*/ +#define EXTENDED_ASSERT 1 // 0 in final +#ifdef NDEBUG +#undef EXTENDED_ASSERT +#define EXTENDED_ASSERT 0 +#endif + +const TCHAR * strGetLastError(); +const TCHAR * strGetError(DWORD dwErr); + +void __cdecl app_fatal(const char * pszFmt,...); +void __cdecl app_warning(const char * pszFmt,...); + +void app_assert(int); +#if EXTENDED_ASSERT && !defined(NDEBUG) +void assert_fail(int nLineNo, const char * pszFile, const char * pszFail); +#define app_assert(x) ((x) ? NULL : assert_fail(__LINE__,__FILE__,#x)) +#elif !defined(NDEBUG) +void assert_fail(int nLineNo, const char * pszFile); +#define app_assert(x) ((x) ? NULL : assert_fail(__LINE__,__FILE__)) +#else +#define app_assert(x) (x) // in case of side effects +#endif + +void ddraw_assert(int); +void ddraw_assert_fail(HRESULT ddrval, int nLineNo, const char * pszFile); +#define ddraw_assert(x) (((x) == DD_OK) ? NULL : ddraw_assert_fail((x),__LINE__,__FILE__)) + +void dsound_assert(int); +void dsound_assert_fail(HRESULT dsrval, int nLineNo, const char * pszFile); +#define dsound_assert(x) (((x) == DS_OK) ? NULL : dsound_assert_fail((x),__LINE__,__FILE__)) + +// jcm.patch1.start.1/14/97 +#ifdef NDEBUG +#define GRACEFUL_EXIT +#endif +// jcm.patch1.end.1/14/97 diff --git a/src/DIABLO.MAK b/src/DIABLO.MAK new file mode 100644 index 0000000..fbb93fd --- /dev/null +++ b/src/DIABLO.MAK @@ -0,0 +1,9974 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on Diablo.dsp +!IF "$(CFG)" == "" +CFG=Diablo - Win32 Release +!MESSAGE No configuration specified. Defaulting to Diablo - Win32 Release. +!ENDIF + +!IF "$(CFG)" != "Diablo - Win32 Release" && "$(CFG)" != "Diablo - Win32 Debug"\ + && "$(CFG)" != "Diablo - Win32 FinalFinal" && "$(CFG)" !=\ + "Diablo - Win32 Shareware FinalFinal" && "$(CFG)" !=\ + "Diablo - Win32 Shareware Release" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Diablo.mak" CFG="Diablo - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Diablo - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 FinalFinal" (based on "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Shareware FinalFinal" (based on\ + "Win32 (x86) Application") +!MESSAGE "Diablo - Win32 Shareware Release" (based on\ + "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "Diablo - Win32 Release" + +OUTDIR=.\WinRel +INTDIR=.\WinRel +# Begin Custom Macros +OutDir=.\.\WinRel +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Diablo.exe" "$(OUTDIR)\Diablo.bsc" + +!ELSE + +ALL : "$(OUTDIR)\Diablo.exe" "$(OUTDIR)\Diablo.bsc" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\appfat.sbr" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\automap.sbr" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\capture.sbr" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CODEC.SBR" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CONTROL.SBR" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\CURSOR.SBR" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEAD.SBR" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DEBUG.SBR" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\DIABLO.SBR" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\doom.sbr" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L1.SBR" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L2.SBR" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\DRLG_L3.SBR" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\drlg_l4.sbr" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dthread.sbr" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\dx.sbr" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\effects.sbr" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\encrypt.sbr" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\ENGINE.SBR" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\error.sbr" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\except.sbr" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GameMenu.sbr" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\GENDUNG.SBR" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\gmenu.sbr" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\help.sbr" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\init.sbr" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\Interfac.sbr" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\inv.sbr" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\itemdat.sbr" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\ITEMS.SBR" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\LIGHTING.SBR" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\loadsave.sbr" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\mainmenu.sbr" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\minitext.sbr" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\misdat.sbr" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MISSILES.SBR" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTDAT.SBR" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\MONSTER.SBR" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\movie.sbr" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\mpqapi.sbr" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\msg.sbr" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\multi.sbr" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\nthread.sbr" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\objdat.sbr" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\OBJECTS.SBR" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\packplr.sbr" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\PALETTE.SBR" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\path.sbr" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\pfile.sbr" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\PLAYER.SBR" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\plrmsg.sbr" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\portal.sbr" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\Quests.sbr" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SCROLLRT.SBR" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SetMaps.sbr" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SHA.SBR" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\SOUND.SBR" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\Spelldat.sbr" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\SPELLS.SBR" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\stores.sbr" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\sync.sbr" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\Textdat.sbr" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\themes.sbr" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\tmsg.sbr" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\TOWN.SBR" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\towners.sbr" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\track.sbr" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\TRIGS.SBR" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(INTDIR)\wave.sbr" + -@erase "$(OUTDIR)\Diablo.bsc" + -@erase "$(OUTDIR)\Diablo.exe" + -@erase "$(OUTDIR)\Diablo.map" + -@erase "$(OUTDIR)\Diablo.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG"\ + /D PROGRAM_VERSION=RETAIL /FAcs /Fa"$(INTDIR)\\" /Fr"$(INTDIR)\\"\ + /Fp"$(INTDIR)\Diablo.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\WinRel/ +CPP_SBRS=.\WinRel/ + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\diablo.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Diablo.bsc" +BSC32_SBRS= \ + "$(INTDIR)\appfat.sbr" \ + "$(INTDIR)\automap.sbr" \ + "$(INTDIR)\capture.sbr" \ + "$(INTDIR)\CODEC.SBR" \ + "$(INTDIR)\CONTROL.SBR" \ + "$(INTDIR)\CURSOR.SBR" \ + "$(INTDIR)\DEAD.SBR" \ + "$(INTDIR)\DEBUG.SBR" \ + "$(INTDIR)\DIABLO.SBR" \ + "$(INTDIR)\doom.sbr" \ + "$(INTDIR)\DRLG_L1.SBR" \ + "$(INTDIR)\DRLG_L2.SBR" \ + "$(INTDIR)\DRLG_L3.SBR" \ + "$(INTDIR)\drlg_l4.sbr" \ + "$(INTDIR)\dthread.sbr" \ + "$(INTDIR)\dx.sbr" \ + "$(INTDIR)\effects.sbr" \ + "$(INTDIR)\encrypt.sbr" \ + "$(INTDIR)\ENGINE.SBR" \ + "$(INTDIR)\error.sbr" \ + "$(INTDIR)\except.sbr" \ + "$(INTDIR)\GameMenu.sbr" \ + "$(INTDIR)\GENDUNG.SBR" \ + "$(INTDIR)\gmenu.sbr" \ + "$(INTDIR)\help.sbr" \ + "$(INTDIR)\init.sbr" \ + "$(INTDIR)\Interfac.sbr" \ + "$(INTDIR)\inv.sbr" \ + "$(INTDIR)\itemdat.sbr" \ + "$(INTDIR)\ITEMS.SBR" \ + "$(INTDIR)\LIGHTING.SBR" \ + "$(INTDIR)\loadsave.sbr" \ + "$(INTDIR)\mainmenu.sbr" \ + "$(INTDIR)\minitext.sbr" \ + "$(INTDIR)\misdat.sbr" \ + "$(INTDIR)\MISSILES.SBR" \ + "$(INTDIR)\MONSTDAT.SBR" \ + "$(INTDIR)\MONSTER.SBR" \ + "$(INTDIR)\movie.sbr" \ + "$(INTDIR)\mpqapi.sbr" \ + "$(INTDIR)\msg.sbr" \ + "$(INTDIR)\multi.sbr" \ + "$(INTDIR)\nthread.sbr" \ + "$(INTDIR)\objdat.sbr" \ + "$(INTDIR)\OBJECTS.SBR" \ + "$(INTDIR)\packplr.sbr" \ + "$(INTDIR)\PALETTE.SBR" \ + "$(INTDIR)\path.sbr" \ + "$(INTDIR)\pfile.sbr" \ + "$(INTDIR)\PLAYER.SBR" \ + "$(INTDIR)\plrmsg.sbr" \ + "$(INTDIR)\portal.sbr" \ + "$(INTDIR)\Quests.sbr" \ + "$(INTDIR)\SCROLLRT.SBR" \ + "$(INTDIR)\SetMaps.sbr" \ + "$(INTDIR)\SHA.SBR" \ + "$(INTDIR)\SOUND.SBR" \ + "$(INTDIR)\Spelldat.sbr" \ + "$(INTDIR)\SPELLS.SBR" \ + "$(INTDIR)\stores.sbr" \ + "$(INTDIR)\sync.sbr" \ + "$(INTDIR)\Textdat.sbr" \ + "$(INTDIR)\themes.sbr" \ + "$(INTDIR)\tmsg.sbr" \ + "$(INTDIR)\TOWN.SBR" \ + "$(INTDIR)\towners.sbr" \ + "$(INTDIR)\track.sbr" \ + "$(INTDIR)\TRIGS.SBR" \ + "$(INTDIR)\wave.sbr" + +"$(OUTDIR)\Diablo.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)\Diablo.pdb" /map:"$(INTDIR)\Diablo.map" /debug\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)\Diablo.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\dsound.lib" \ + ".\Hellfrui.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\Diablo.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +OUTDIR=.\WinDebug +INTDIR=.\WinDebug +# Begin Custom Macros +OutDir=.\.\WinDebug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Diablo.exe" + +!ELSE + +ALL : "$(OUTDIR)\Diablo.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\Diablo.exe" + -@erase "$(OUTDIR)\Diablo.map" + -@erase "$(OUTDIR)\Diablo.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Gm /Zi /Od /D "WIN32" /D "_WINDOWS" /D\ + "_DEBUG" /D PROGRAM_VERSION=RETAIL /FAcs /Fa"$(INTDIR)\\"\ + /Fp"$(INTDIR)\Diablo.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\WinDebug/ +CPP_SBRS=. + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\diablo.res" /d "_DEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Diablo.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)\Diablo.pdb" /map:"$(INTDIR)\Diablo.map" /debug\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)\Diablo.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\dsound.lib" \ + ".\Hellfrui.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\Diablo.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +OUTDIR=.\WinFinal +INTDIR=.\WinFinal +# Begin Custom Macros +OutDir=.\.\WinFinal +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Diablo.exe" + +!ELSE + +ALL : "$(OUTDIR)\Diablo.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\Diablo.exe" + -@erase "$(OUTDIR)\Diablo.map" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG"\ + /D PROGRAM_VERSION=RETAIL /FAcs /Fa"$(INTDIR)\\" /Fp"$(INTDIR)\Diablo.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\WinFinal/ +CPP_SBRS=. + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\diablo.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Diablo.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)\Diablo.pdb" /map:"$(INTDIR)\Diablo.map"\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)\Diablo.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\dsound.lib" \ + ".\Hellfrui.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\Diablo.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +OUTDIR=.\SFinal +INTDIR=.\SFinal +# Begin Custom Macros +OutDir=.\.\SFinal +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Diablo.exe" + +!ELSE + +ALL : "$(OUTDIR)\Diablo.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\Diablo.exe" + -@erase "$(OUTDIR)\Diablo.map" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "NDEBUG"\ + /D PROGRAM_VERSION=SHAREWARE /FAcs /Fa"$(INTDIR)\\" /Fp"$(INTDIR)\Diablo.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\SFinal/ +CPP_SBRS=. + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\diablo.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Diablo.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)\Diablo.pdb" /map:"$(INTDIR)\Diablo.map"\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)\Diablo.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\dsound.lib" \ + ".\Hellfrui.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\Diablo.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +OUTDIR=.\SRel +INTDIR=.\SRel +# Begin Custom Macros +OutDir=.\.\SRel +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Diablo.exe" + +!ELSE + +ALL : "$(OUTDIR)\Diablo.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\appfat.obj" + -@erase "$(INTDIR)\automap.obj" + -@erase "$(INTDIR)\capture.obj" + -@erase "$(INTDIR)\CODEC.OBJ" + -@erase "$(INTDIR)\CONTROL.OBJ" + -@erase "$(INTDIR)\CURSOR.OBJ" + -@erase "$(INTDIR)\DEAD.OBJ" + -@erase "$(INTDIR)\DEBUG.OBJ" + -@erase "$(INTDIR)\DIABLO.OBJ" + -@erase "$(INTDIR)\diablo.res" + -@erase "$(INTDIR)\doom.obj" + -@erase "$(INTDIR)\DRLG_L1.OBJ" + -@erase "$(INTDIR)\DRLG_L2.OBJ" + -@erase "$(INTDIR)\DRLG_L3.OBJ" + -@erase "$(INTDIR)\drlg_l4.obj" + -@erase "$(INTDIR)\dthread.obj" + -@erase "$(INTDIR)\dx.obj" + -@erase "$(INTDIR)\effects.obj" + -@erase "$(INTDIR)\encrypt.obj" + -@erase "$(INTDIR)\ENGINE.OBJ" + -@erase "$(INTDIR)\error.obj" + -@erase "$(INTDIR)\except.obj" + -@erase "$(INTDIR)\GameMenu.obj" + -@erase "$(INTDIR)\GENDUNG.OBJ" + -@erase "$(INTDIR)\gmenu.obj" + -@erase "$(INTDIR)\help.obj" + -@erase "$(INTDIR)\init.obj" + -@erase "$(INTDIR)\Interfac.obj" + -@erase "$(INTDIR)\inv.obj" + -@erase "$(INTDIR)\itemdat.obj" + -@erase "$(INTDIR)\ITEMS.OBJ" + -@erase "$(INTDIR)\LIGHTING.OBJ" + -@erase "$(INTDIR)\loadsave.obj" + -@erase "$(INTDIR)\mainmenu.obj" + -@erase "$(INTDIR)\minitext.obj" + -@erase "$(INTDIR)\misdat.obj" + -@erase "$(INTDIR)\MISSILES.OBJ" + -@erase "$(INTDIR)\MONSTDAT.OBJ" + -@erase "$(INTDIR)\MONSTER.OBJ" + -@erase "$(INTDIR)\movie.obj" + -@erase "$(INTDIR)\mpqapi.obj" + -@erase "$(INTDIR)\msg.obj" + -@erase "$(INTDIR)\multi.obj" + -@erase "$(INTDIR)\nthread.obj" + -@erase "$(INTDIR)\objdat.obj" + -@erase "$(INTDIR)\OBJECTS.OBJ" + -@erase "$(INTDIR)\packplr.obj" + -@erase "$(INTDIR)\PALETTE.OBJ" + -@erase "$(INTDIR)\path.obj" + -@erase "$(INTDIR)\pfile.obj" + -@erase "$(INTDIR)\PLAYER.OBJ" + -@erase "$(INTDIR)\plrmsg.obj" + -@erase "$(INTDIR)\portal.obj" + -@erase "$(INTDIR)\Quests.obj" + -@erase "$(INTDIR)\SCROLLRT.OBJ" + -@erase "$(INTDIR)\SetMaps.obj" + -@erase "$(INTDIR)\SHA.OBJ" + -@erase "$(INTDIR)\SOUND.OBJ" + -@erase "$(INTDIR)\Spelldat.obj" + -@erase "$(INTDIR)\SPELLS.OBJ" + -@erase "$(INTDIR)\stores.obj" + -@erase "$(INTDIR)\sync.obj" + -@erase "$(INTDIR)\Textdat.obj" + -@erase "$(INTDIR)\themes.obj" + -@erase "$(INTDIR)\tmsg.obj" + -@erase "$(INTDIR)\TOWN.OBJ" + -@erase "$(INTDIR)\towners.obj" + -@erase "$(INTDIR)\track.obj" + -@erase "$(INTDIR)\TRIGS.OBJ" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(INTDIR)\wave.obj" + -@erase "$(OUTDIR)\Diablo.exe" + -@erase "$(OUTDIR)\Diablo.map" + -@erase "$(OUTDIR)\Diablo.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /G5 /Gr /MT /W3 /Zi /O1 /D "WIN32" /D "_WINDOWS" /D "_DEBUG"\ + /D PROGRAM_VERSION=SHAREWARE /FAcs /Fa"$(INTDIR)\\" /Fp"$(INTDIR)\Diablo.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\SRel/ +CPP_SBRS=. + +.c{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_OBJS)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(CPP_SBRS)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +RSC_PROJ=/l 0x409 /fo"$(INTDIR)\diablo.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\Diablo.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=libcmt.lib winmm.lib kernel32.lib user32.lib gdi32.lib\ + comdlg32.lib advapi32.lib shell32.lib version.lib /nologo /subsystem:windows\ + /incremental:no /pdb:"$(OUTDIR)\Diablo.pdb" /map:"$(INTDIR)\Diablo.map" /debug\ + /machine:I386 /nodefaultlib /out:"$(OUTDIR)\Diablo.exe" +LINK32_OBJS= \ + "$(INTDIR)\appfat.obj" \ + "$(INTDIR)\automap.obj" \ + "$(INTDIR)\capture.obj" \ + "$(INTDIR)\CODEC.OBJ" \ + "$(INTDIR)\CONTROL.OBJ" \ + "$(INTDIR)\CURSOR.OBJ" \ + "$(INTDIR)\DEAD.OBJ" \ + "$(INTDIR)\DEBUG.OBJ" \ + "$(INTDIR)\DIABLO.OBJ" \ + "$(INTDIR)\diablo.res" \ + "$(INTDIR)\doom.obj" \ + "$(INTDIR)\DRLG_L1.OBJ" \ + "$(INTDIR)\DRLG_L2.OBJ" \ + "$(INTDIR)\DRLG_L3.OBJ" \ + "$(INTDIR)\drlg_l4.obj" \ + "$(INTDIR)\dthread.obj" \ + "$(INTDIR)\dx.obj" \ + "$(INTDIR)\effects.obj" \ + "$(INTDIR)\encrypt.obj" \ + "$(INTDIR)\ENGINE.OBJ" \ + "$(INTDIR)\error.obj" \ + "$(INTDIR)\except.obj" \ + "$(INTDIR)\GameMenu.obj" \ + "$(INTDIR)\GENDUNG.OBJ" \ + "$(INTDIR)\gmenu.obj" \ + "$(INTDIR)\help.obj" \ + "$(INTDIR)\init.obj" \ + "$(INTDIR)\Interfac.obj" \ + "$(INTDIR)\inv.obj" \ + "$(INTDIR)\itemdat.obj" \ + "$(INTDIR)\ITEMS.OBJ" \ + "$(INTDIR)\LIGHTING.OBJ" \ + "$(INTDIR)\loadsave.obj" \ + "$(INTDIR)\mainmenu.obj" \ + "$(INTDIR)\minitext.obj" \ + "$(INTDIR)\misdat.obj" \ + "$(INTDIR)\MISSILES.OBJ" \ + "$(INTDIR)\MONSTDAT.OBJ" \ + "$(INTDIR)\MONSTER.OBJ" \ + "$(INTDIR)\movie.obj" \ + "$(INTDIR)\mpqapi.obj" \ + "$(INTDIR)\msg.obj" \ + "$(INTDIR)\multi.obj" \ + "$(INTDIR)\nthread.obj" \ + "$(INTDIR)\objdat.obj" \ + "$(INTDIR)\OBJECTS.OBJ" \ + "$(INTDIR)\packplr.obj" \ + "$(INTDIR)\PALETTE.OBJ" \ + "$(INTDIR)\path.obj" \ + "$(INTDIR)\pfile.obj" \ + "$(INTDIR)\PLAYER.OBJ" \ + "$(INTDIR)\plrmsg.obj" \ + "$(INTDIR)\portal.obj" \ + "$(INTDIR)\Quests.obj" \ + "$(INTDIR)\scroll.obj" \ + "$(INTDIR)\SCROLLRT.OBJ" \ + "$(INTDIR)\SetMaps.obj" \ + "$(INTDIR)\SHA.OBJ" \ + "$(INTDIR)\SOUND.OBJ" \ + "$(INTDIR)\Spelldat.obj" \ + "$(INTDIR)\SPELLS.OBJ" \ + "$(INTDIR)\stores.obj" \ + "$(INTDIR)\sync.obj" \ + "$(INTDIR)\Textdat.obj" \ + "$(INTDIR)\themes.obj" \ + "$(INTDIR)\tmsg.obj" \ + "$(INTDIR)\TOWN.OBJ" \ + "$(INTDIR)\towners.obj" \ + "$(INTDIR)\track.obj" \ + "$(INTDIR)\TRIGS.OBJ" \ + "$(INTDIR)\wave.obj" \ + ".\ddraw.lib" \ + ".\dsound.lib" \ + ".\Hellfrui.lib" \ + ".\implode.lib" \ + ".\Storm.lib" + +"$(OUTDIR)\Diablo.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + + +!IF "$(CFG)" == "Diablo - Win32 Release" || "$(CFG)" == "Diablo - Win32 Debug"\ + || "$(CFG)" == "Diablo - Win32 FinalFinal" || "$(CFG)" ==\ + "Diablo - Win32 Shareware FinalFinal" || "$(CFG)" ==\ + "Diablo - Win32 Shareware Release" +SOURCE=.\appfat.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_APPFA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\appfat.obj" "$(INTDIR)\appfat.sbr" : $(SOURCE) $(DEP_CPP_APPFA)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_APPFA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_APPFA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_APPFA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_APPFA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\appfat.obj" : $(SOURCE) $(DEP_CPP_APPFA) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\automap.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_AUTOM=\ + ".\automap.h"\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + + +"$(INTDIR)\automap.obj" "$(INTDIR)\automap.sbr" : $(SOURCE) $(DEP_CPP_AUTOM)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_AUTOM=\ + ".\automap.h"\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_AUTOM=\ + ".\automap.h"\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_AUTOM=\ + ".\automap.h"\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_AUTOM=\ + ".\automap.h"\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + + +"$(INTDIR)\automap.obj" : $(SOURCE) $(DEP_CPP_AUTOM) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\capture.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_CAPTU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\capture.obj" "$(INTDIR)\capture.sbr" : $(SOURCE) $(DEP_CPP_CAPTU)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_CAPTU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_CAPTU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_CAPTU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_CAPTU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\capture.obj" : $(SOURCE) $(DEP_CPP_CAPTU) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\CODEC.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_CODEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\CODEC.OBJ" "$(INTDIR)\CODEC.SBR" : $(SOURCE) $(DEP_CPP_CODEC)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_CODEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_CODEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_CODEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_CODEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\CODEC.OBJ" : $(SOURCE) $(DEP_CPP_CODEC) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\CONTROL.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_CONTR=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CONTROL.OBJ" "$(INTDIR)\CONTROL.SBR" : $(SOURCE) $(DEP_CPP_CONTR)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_CONTR=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_CONTR=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_CONTR=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_CONTR=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CONTROL.OBJ" : $(SOURCE) $(DEP_CPP_CONTR) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\CURSOR.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_CURSO=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CURSOR.OBJ" "$(INTDIR)\CURSOR.SBR" : $(SOURCE) $(DEP_CPP_CURSO)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_CURSO=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_CURSO=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_CURSO=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_CURSO=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\CURSOR.OBJ" : $(SOURCE) $(DEP_CPP_CURSO) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\DEAD.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DEAD_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\DEAD.OBJ" "$(INTDIR)\DEAD.SBR" : $(SOURCE) $(DEP_CPP_DEAD_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DEAD_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DEAD_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DEAD_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DEAD_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\DEAD.OBJ" : $(SOURCE) $(DEP_CPP_DEAD_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\DEBUG.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DEBUG=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + + +"$(INTDIR)\DEBUG.OBJ" "$(INTDIR)\DEBUG.SBR" : $(SOURCE) $(DEP_CPP_DEBUG)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DEBUG=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DEBUG=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DEBUG=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DEBUG=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + + +"$(INTDIR)\DEBUG.OBJ" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\DIABLO.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DIABL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\mainmenu.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\mpqapi.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DIABLO.OBJ" "$(INTDIR)\DIABLO.SBR" : $(SOURCE) $(DEP_CPP_DIABL)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DIABL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\mainmenu.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\mpqapi.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DIABL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\mainmenu.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\mpqapi.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DIABL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\mainmenu.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\mpqapi.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DIABL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\mainmenu.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\mpqapi.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DIABLO.OBJ" : $(SOURCE) $(DEP_CPP_DIABL) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\diablo.rc +DEP_RSC_DIABLO=\ + ".\icon1.ico"\ + + +"$(INTDIR)\diablo.res" : $(SOURCE) $(DEP_RSC_DIABLO) "$(INTDIR)" + $(RSC) $(RSC_PROJ) $(SOURCE) + + +SOURCE=.\doom.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DOOM_=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\doom.obj" "$(INTDIR)\doom.sbr" : $(SOURCE) $(DEP_CPP_DOOM_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DOOM_=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DOOM_=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DOOM_=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DOOM_=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\DRLG_L1.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DRLG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L1.OBJ" "$(INTDIR)\DRLG_L1.SBR" : $(SOURCE) $(DEP_CPP_DRLG_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DRLG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DRLG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DRLG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DRLG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L1.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\DRLG_L2.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DRLG_L=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l2.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L2.OBJ" "$(INTDIR)\DRLG_L2.SBR" : $(SOURCE) $(DEP_CPP_DRLG_L)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DRLG_L=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l2.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DRLG_L=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l2.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DRLG_L=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l2.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DRLG_L=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l2.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L2.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\DRLG_L3.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DRLG_L3=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l3.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L3.OBJ" "$(INTDIR)\DRLG_L3.SBR" : $(SOURCE) $(DEP_CPP_DRLG_L3)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DRLG_L3=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l3.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L3) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DRLG_L3=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l3.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L3) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DRLG_L3=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l3.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L3) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DRLG_L3=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l3.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\DRLG_L3.OBJ" : $(SOURCE) $(DEP_CPP_DRLG_L3) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\drlg_l4.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DRLG_L4=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\drlg_l4.obj" "$(INTDIR)\drlg_l4.sbr" : $(SOURCE) $(DEP_CPP_DRLG_L4)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DRLG_L4=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DRLG_L4=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DRLG_L4=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DRLG_L4=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\drlg_l4.obj" : $(SOURCE) $(DEP_CPP_DRLG_L4) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\dthread.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dthread.obj" "$(INTDIR)\dthread.sbr" : $(SOURCE) $(DEP_CPP_DTHRE)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dthread.obj" : $(SOURCE) $(DEP_CPP_DTHRE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\dx.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_DX_CP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dx.obj" "$(INTDIR)\dx.sbr" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_DX_CP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_DX_CP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_DX_CP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_DX_CP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\dx.obj" : $(SOURCE) $(DEP_CPP_DX_CP) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\effects.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_EFFEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\effects.obj" "$(INTDIR)\effects.sbr" : $(SOURCE) $(DEP_CPP_EFFEC)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_EFFEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_EFFEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_EFFEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_EFFEC=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\effects.obj" : $(SOURCE) $(DEP_CPP_EFFEC) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\encrypt.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_ENCRY=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\implode.h"\ + ".\mpqapi.h"\ + + +"$(INTDIR)\encrypt.obj" "$(INTDIR)\encrypt.sbr" : $(SOURCE) $(DEP_CPP_ENCRY)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_ENCRY=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\implode.h"\ + ".\mpqapi.h"\ + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_ENCRY=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\implode.h"\ + ".\mpqapi.h"\ + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_ENCRY=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\implode.h"\ + ".\mpqapi.h"\ + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_ENCRY=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\implode.h"\ + ".\mpqapi.h"\ + + +"$(INTDIR)\encrypt.obj" : $(SOURCE) $(DEP_CPP_ENCRY) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\ENGINE.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_ENGIN=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Palette.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ENGINE.OBJ" "$(INTDIR)\ENGINE.SBR" : $(SOURCE) $(DEP_CPP_ENGIN)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_ENGIN=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Palette.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_ENGIN=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Palette.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_ENGIN=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Palette.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_ENGIN=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Palette.h"\ + ".\regconst.h"\ + ".\Scrollrt.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ENGINE.OBJ" : $(SOURCE) $(DEP_CPP_ENGIN) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\error.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_ERROR=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Items.h"\ + ".\Scrollrt.h"\ + ".\stores.h"\ + + +"$(INTDIR)\error.obj" "$(INTDIR)\error.sbr" : $(SOURCE) $(DEP_CPP_ERROR)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_ERROR=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Items.h"\ + ".\Scrollrt.h"\ + ".\stores.h"\ + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_ERROR=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Items.h"\ + ".\Scrollrt.h"\ + ".\stores.h"\ + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_ERROR=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Items.h"\ + ".\Scrollrt.h"\ + ".\stores.h"\ + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_ERROR=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Items.h"\ + ".\Scrollrt.h"\ + ".\stores.h"\ + + +"$(INTDIR)\error.obj" : $(SOURCE) $(DEP_CPP_ERROR) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\except.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_EXCEP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\except.obj" "$(INTDIR)\except.sbr" : $(SOURCE) $(DEP_CPP_EXCEP)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_EXCEP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_EXCEP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_EXCEP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_EXCEP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\except.obj" : $(SOURCE) $(DEP_CPP_EXCEP) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\GameMenu.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_GAMEM=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\GameMenu.obj" "$(INTDIR)\GameMenu.sbr" : $(SOURCE) $(DEP_CPP_GAMEM)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_GAMEM=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_GAMEM=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_GAMEM=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_GAMEM=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\GameMenu.obj" : $(SOURCE) $(DEP_CPP_GAMEM) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\GENDUNG.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_GENDU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\GENDUNG.OBJ" "$(INTDIR)\GENDUNG.SBR" : $(SOURCE) $(DEP_CPP_GENDU)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_GENDU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_GENDU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_GENDU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_GENDU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\GENDUNG.OBJ" : $(SOURCE) $(DEP_CPP_GENDU) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\gmenu.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_GMENU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\gmenu.obj" "$(INTDIR)\gmenu.sbr" : $(SOURCE) $(DEP_CPP_GMENU)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_GMENU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_GMENU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_GMENU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_GMENU=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\gmenu.obj" : $(SOURCE) $(DEP_CPP_GMENU) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\help.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_HELP_=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + + +"$(INTDIR)\help.obj" "$(INTDIR)\help.sbr" : $(SOURCE) $(DEP_CPP_HELP_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_HELP_=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_HELP_=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_HELP_=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_HELP_=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Objects.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + + +"$(INTDIR)\help.obj" : $(SOURCE) $(DEP_CPP_HELP_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\init.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_INIT_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\init.obj" "$(INTDIR)\init.sbr" : $(SOURCE) $(DEP_CPP_INIT_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_INIT_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_INIT_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_INIT_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_INIT_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Lighting.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\init.obj" : $(SOURCE) $(DEP_CPP_INIT_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\Interfac.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_INTER=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Storm.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Interfac.obj" "$(INTDIR)\Interfac.sbr" : $(SOURCE) $(DEP_CPP_INTER)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_INTER=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Storm.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_INTER=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Storm.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_INTER=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Storm.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_INTER=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Storm.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Interfac.obj" : $(SOURCE) $(DEP_CPP_INTER) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\inv.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_INV_C=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + + +"$(INTDIR)\inv.obj" "$(INTDIR)\inv.sbr" : $(SOURCE) $(DEP_CPP_INV_C)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_INV_C=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_INV_C=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_INV_C=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_INV_C=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + + +"$(INTDIR)\inv.obj" : $(SOURCE) $(DEP_CPP_INV_C) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\itemdat.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_ITEMD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\itemdat.obj" "$(INTDIR)\itemdat.sbr" : $(SOURCE) $(DEP_CPP_ITEMD)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_ITEMD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_ITEMD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_ITEMD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_ITEMD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\itemdat.obj" : $(SOURCE) $(DEP_CPP_ITEMD) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\ITEMS.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_ITEMS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ITEMS.OBJ" "$(INTDIR)\ITEMS.SBR" : $(SOURCE) $(DEP_CPP_ITEMS)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_ITEMS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_ITEMS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_ITEMS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_ITEMS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\ITEMS.OBJ" : $(SOURCE) $(DEP_CPP_ITEMS) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\LIGHTING.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_LIGHT=\ + ".\automap.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\LIGHTING.OBJ" "$(INTDIR)\LIGHTING.SBR" : $(SOURCE) $(DEP_CPP_LIGHT)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_LIGHT=\ + ".\automap.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_LIGHT=\ + ".\automap.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_LIGHT=\ + ".\automap.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_LIGHT=\ + ".\automap.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\LIGHTING.OBJ" : $(SOURCE) $(DEP_CPP_LIGHT) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\loadsave.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_LOADS=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\loadsave.obj" "$(INTDIR)\loadsave.sbr" : $(SOURCE) $(DEP_CPP_LOADS)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_LOADS=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_LOADS=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_LOADS=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_LOADS=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Interfac.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\loadsave.obj" : $(SOURCE) $(DEP_CPP_LOADS) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\mainmenu.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MAINM=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mainmenu.obj" "$(INTDIR)\mainmenu.sbr" : $(SOURCE) $(DEP_CPP_MAINM)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MAINM=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MAINM=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MAINM=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MAINM=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mainmenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\minitext.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MINIT=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\minitext.obj" "$(INTDIR)\minitext.sbr" : $(SOURCE) $(DEP_CPP_MINIT)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MINIT=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MINIT=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MINIT=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MINIT=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\minitext.obj" : $(SOURCE) $(DEP_CPP_MINIT) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\misdat.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MISDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + + +"$(INTDIR)\misdat.obj" "$(INTDIR)\misdat.sbr" : $(SOURCE) $(DEP_CPP_MISDA)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MISDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MISDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MISDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MISDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + + +"$(INTDIR)\misdat.obj" : $(SOURCE) $(DEP_CPP_MISDA) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\MISSILES.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MISSI=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\mono.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MISSILES.OBJ" "$(INTDIR)\MISSILES.SBR" : $(SOURCE) $(DEP_CPP_MISSI)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MISSI=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\mono.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MISSI=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\mono.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MISSI=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\mono.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MISSI=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\mono.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MISSILES.OBJ" : $(SOURCE) $(DEP_CPP_MISSI) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\MONSTDAT.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MONST=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Sound.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\MONSTDAT.OBJ" "$(INTDIR)\MONSTDAT.SBR" : $(SOURCE) $(DEP_CPP_MONST)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MONST=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Sound.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MONST=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Sound.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MONST=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Sound.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MONST=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\Sound.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\MONSTDAT.OBJ" : $(SOURCE) $(DEP_CPP_MONST) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\MONSTER.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MONSTE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MONSTER.OBJ" "$(INTDIR)\MONSTER.SBR" : $(SOURCE) $(DEP_CPP_MONSTE)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MONSTE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONSTE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MONSTE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONSTE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MONSTE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONSTE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MONSTE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\MONSTER.OBJ" : $(SOURCE) $(DEP_CPP_MONSTE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\movie.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MOVIE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\movie.obj" "$(INTDIR)\movie.sbr" : $(SOURCE) $(DEP_CPP_MOVIE)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MOVIE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MOVIE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MOVIE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MOVIE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Palette.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\movie.obj" : $(SOURCE) $(DEP_CPP_MOVIE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\mpqapi.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MPQAP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\mpqapi.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mpqapi.obj" "$(INTDIR)\mpqapi.sbr" : $(SOURCE) $(DEP_CPP_MPQAP)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MPQAP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\mpqapi.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MPQAP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\mpqapi.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MPQAP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\mpqapi.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MPQAP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\mpqapi.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\mpqapi.obj" : $(SOURCE) $(DEP_CPP_MPQAP) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\msg.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" "$(INTDIR)\msg.sbr" : $(SOURCE) $(DEP_CPP_MSG_C)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MSG_C=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\msg.obj" : $(SOURCE) $(DEP_CPP_MSG_C) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\multi.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_MULTI=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\multi.obj" "$(INTDIR)\multi.sbr" : $(SOURCE) $(DEP_CPP_MULTI)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_MULTI=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_MULTI=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_MULTI=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_MULTI=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\multi.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\nthread.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_NTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\nthread.obj" "$(INTDIR)\nthread.sbr" : $(SOURCE) $(DEP_CPP_NTHRE)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_NTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_NTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_NTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_NTHRE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\nthread.obj" : $(SOURCE) $(DEP_CPP_NTHRE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\objdat.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_OBJDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + + +"$(INTDIR)\objdat.obj" "$(INTDIR)\objdat.sbr" : $(SOURCE) $(DEP_CPP_OBJDA)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_OBJDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_OBJDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_OBJDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_OBJDA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + + +"$(INTDIR)\objdat.obj" : $(SOURCE) $(DEP_CPP_OBJDA) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\OBJECTS.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_OBJEC=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + + +"$(INTDIR)\OBJECTS.OBJ" "$(INTDIR)\OBJECTS.SBR" : $(SOURCE) $(DEP_CPP_OBJEC)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_OBJEC=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_OBJEC=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_OBJEC=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_OBJEC=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\towners.h"\ + + +"$(INTDIR)\OBJECTS.OBJ" : $(SOURCE) $(DEP_CPP_OBJEC) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\packplr.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_PACKP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\packplr.obj" "$(INTDIR)\packplr.sbr" : $(SOURCE) $(DEP_CPP_PACKP)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_PACKP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_PACKP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_PACKP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_PACKP=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\packplr.obj" : $(SOURCE) $(DEP_CPP_PACKP) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\PALETTE.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_PALET=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\PALETTE.OBJ" "$(INTDIR)\PALETTE.SBR" : $(SOURCE) $(DEP_CPP_PALET)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_PALET=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_PALET=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_PALET=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_PALET=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Palette.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\PALETTE.OBJ" : $(SOURCE) $(DEP_CPP_PALET) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\path.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_PATH_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\path.h"\ + ".\Player.h"\ + + +"$(INTDIR)\path.obj" "$(INTDIR)\path.sbr" : $(SOURCE) $(DEP_CPP_PATH_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_PATH_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\path.h"\ + ".\Player.h"\ + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_PATH_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\path.h"\ + ".\Player.h"\ + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_PATH_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\path.h"\ + ".\Player.h"\ + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_PATH_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\path.h"\ + ".\Player.h"\ + + +"$(INTDIR)\path.obj" : $(SOURCE) $(DEP_CPP_PATH_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\pfile.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_PFILE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\mpqapi.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\pfile.obj" "$(INTDIR)\pfile.sbr" : $(SOURCE) $(DEP_CPP_PFILE)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_PFILE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\mpqapi.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_PFILE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\mpqapi.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_PFILE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\mpqapi.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_PFILE=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Diabloui.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\mpqapi.h"\ + ".\Multi.h"\ + ".\packplr.h"\ + ".\Player.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\pfile.obj" : $(SOURCE) $(DEP_CPP_PFILE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\PLAYER.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_PLAYE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\PLAYER.OBJ" "$(INTDIR)\PLAYER.SBR" : $(SOURCE) $(DEP_CPP_PLAYE)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_PLAYE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_PLAYE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_PLAYE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_PLAYE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\path.h"\ + ".\Player.h"\ + ".\portal.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + ".\stores.h"\ + ".\Storm.h"\ + ".\textdat.h"\ + ".\themes.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\PLAYER.OBJ" : $(SOURCE) $(DEP_CPP_PLAYE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\plrmsg.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_PLRMS=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + + +"$(INTDIR)\plrmsg.obj" "$(INTDIR)\plrmsg.sbr" : $(SOURCE) $(DEP_CPP_PLRMS)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_PLRMS=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_PLRMS=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_PLRMS=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_PLRMS=\ + ".\Control.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + + +"$(INTDIR)\plrmsg.obj" : $(SOURCE) $(DEP_CPP_PLRMS) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\portal.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_PORTA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\portal.h"\ + + +"$(INTDIR)\portal.obj" "$(INTDIR)\portal.sbr" : $(SOURCE) $(DEP_CPP_PORTA)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_PORTA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\portal.h"\ + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_PORTA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\portal.h"\ + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_PORTA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\portal.h"\ + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_PORTA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\portal.h"\ + + +"$(INTDIR)\portal.obj" : $(SOURCE) $(DEP_CPP_PORTA) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\Quests.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_QUEST=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Quests.obj" "$(INTDIR)\Quests.sbr" : $(SOURCE) $(DEP_CPP_QUEST)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_QUEST=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_QUEST=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_QUEST=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_QUEST=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Drlg_l1.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Missiles.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\Setmaps.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\Quests.obj" : $(SOURCE) $(DEP_CPP_QUEST) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\Scroll.asm + +!IF "$(CFG)" == "Diablo - Win32 Release" + +IntDir=.\.\WinRel +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +IntDir=.\.\WinDebug +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +IntDir=.\.\WinFinal +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +IntDir=.\.\SFinal +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +IntDir=.\.\SRel +InputPath=.\Scroll.asm +InputName=Scroll + +"$(IntDir)\scroll.obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + tasm /t /m5 /ml /w2 /zn $(InputName) $(IntDir)\scroll.obj + +!ENDIF + +SOURCE=.\SCROLLRT.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_SCROL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + ".\Town.h"\ + + +"$(INTDIR)\SCROLLRT.OBJ" "$(INTDIR)\SCROLLRT.SBR" : $(SOURCE) $(DEP_CPP_SCROL)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_SCROL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + ".\Town.h"\ + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_SCROL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + ".\Town.h"\ + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_SCROL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + ".\Town.h"\ + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_SCROL=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Dead.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Lighting.h"\ + ".\MiniText.h"\ + ".\misdat.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\Multi.h"\ + ".\Objects.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\regconst.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\Spells.h"\ + ".\Storm.h"\ + ".\Town.h"\ + + +"$(INTDIR)\SCROLLRT.OBJ" : $(SOURCE) $(DEP_CPP_SCROL) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\SetMaps.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_SETMA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\SetMaps.obj" "$(INTDIR)\SetMaps.sbr" : $(SOURCE) $(DEP_CPP_SETMA)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_SETMA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_SETMA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_SETMA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_SETMA=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Drlg_l1.h"\ + ".\Drlg_l2.h"\ + ".\Drlg_l3.h"\ + ".\Drlg_l4.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Objects.h"\ + ".\Palette.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\SetMaps.obj" : $(SOURCE) $(DEP_CPP_SETMA) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\SHA.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_SHA_C=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\SHA.OBJ" "$(INTDIR)\SHA.SBR" : $(SOURCE) $(DEP_CPP_SHA_C)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_SHA_C=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_SHA_C=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_SHA_C=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_SHA_C=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + + +"$(INTDIR)\SHA.OBJ" : $(SOURCE) $(DEP_CPP_SHA_C) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\SOUND.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_SOUND=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\SOUND.OBJ" "$(INTDIR)\SOUND.SBR" : $(SOURCE) $(DEP_CPP_SOUND)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_SOUND=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_SOUND=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_SOUND=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_SOUND=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\SOUND.OBJ" : $(SOURCE) $(DEP_CPP_SOUND) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\Spelldat.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_SPELL=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Missiles.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\Spelldat.obj" "$(INTDIR)\Spelldat.sbr" : $(SOURCE) $(DEP_CPP_SPELL)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_SPELL=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Missiles.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_SPELL=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Missiles.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_SPELL=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Missiles.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_SPELL=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Missiles.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\Spelldat.obj" : $(SOURCE) $(DEP_CPP_SPELL) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\SPELLS.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_SPELLS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\SPELLS.OBJ" "$(INTDIR)\SPELLS.SBR" : $(SOURCE) $(DEP_CPP_SPELLS)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_SPELLS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELLS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_SPELLS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELLS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_SPELLS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELLS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_SPELLS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Missiles.h"\ + ".\Monster.h"\ + ".\Player.h"\ + ".\Sound.h"\ + ".\spelldat.h"\ + ".\Spells.h"\ + + +"$(INTDIR)\SPELLS.OBJ" : $(SOURCE) $(DEP_CPP_SPELLS) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\stores.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_STORE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\spelldat.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + + +"$(INTDIR)\stores.obj" "$(INTDIR)\stores.sbr" : $(SOURCE) $(DEP_CPP_STORE)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_STORE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\spelldat.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_STORE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\spelldat.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_STORE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\spelldat.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_STORE=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Scrollrt.h"\ + ".\spelldat.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\towners.h"\ + + +"$(INTDIR)\stores.obj" : $(SOURCE) $(DEP_CPP_STORE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\sync.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_SYNC_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\sync.obj" "$(INTDIR)\sync.sbr" : $(SOURCE) $(DEP_CPP_SYNC_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_SYNC_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_SYNC_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_SYNC_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_SYNC_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Debug.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\Monster.h"\ + ".\monstint.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Sound.h"\ + + +"$(INTDIR)\sync.obj" : $(SOURCE) $(DEP_CPP_SYNC_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\Textdat.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_TEXTD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\MiniText.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\Textdat.obj" "$(INTDIR)\Textdat.sbr" : $(SOURCE) $(DEP_CPP_TEXTD)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_TEXTD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\MiniText.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_TEXTD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\MiniText.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_TEXTD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\MiniText.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_TEXTD=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\MiniText.h"\ + ".\textdat.h"\ + + +"$(INTDIR)\Textdat.obj" : $(SOURCE) $(DEP_CPP_TEXTD) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\themes.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_THEME=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\themes.obj" "$(INTDIR)\themes.sbr" : $(SOURCE) $(DEP_CPP_THEME)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_THEME=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_THEME=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_THEME=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_THEME=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\Monstdat.h"\ + ".\Monster.h"\ + ".\objdat.h"\ + ".\Objects.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\themes.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\themes.obj" : $(SOURCE) $(DEP_CPP_THEME) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\tmsg.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_TMSG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\tmsg.obj" "$(INTDIR)\tmsg.sbr" : $(SOURCE) $(DEP_CPP_TMSG_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_TMSG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_TMSG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_TMSG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_TMSG_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + + +"$(INTDIR)\tmsg.obj" : $(SOURCE) $(DEP_CPP_TMSG_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\TOWN.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_TOWN_=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TOWN.OBJ" "$(INTDIR)\TOWN.SBR" : $(SOURCE) $(DEP_CPP_TOWN_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_TOWN_=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_TOWN_=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_TOWN_=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_TOWN_=\ + ".\automap.h"\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\doom.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\error.h"\ + ".\Gamemenu.h"\ + ".\Gendung.h"\ + ".\help.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\Multi.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\scrlasm.h"\ + ".\Scrollrt.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\Town.h"\ + ".\towners.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TOWN.OBJ" : $(SOURCE) $(DEP_CPP_TOWN_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\towners.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_TOWNE=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\towners.obj" "$(INTDIR)\towners.sbr" : $(SOURCE) $(DEP_CPP_TOWNE)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_TOWNE=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_TOWNE=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_TOWNE=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_TOWNE=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\Engine.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\itemdat.h"\ + ".\Items.h"\ + ".\MiniText.h"\ + ".\Monster.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Sound.h"\ + ".\stores.h"\ + ".\textdat.h"\ + ".\Town.h"\ + ".\towners.h"\ + + +"$(INTDIR)\towners.obj" : $(SOURCE) $(DEP_CPP_TOWNE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\track.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_TRACK=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\track.obj" "$(INTDIR)\track.sbr" : $(SOURCE) $(DEP_CPP_TRACK)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_TRACK=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_TRACK=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_TRACK=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_TRACK=\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Gendung.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Player.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\track.obj" : $(SOURCE) $(DEP_CPP_TRACK) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\TRIGS.CPP + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_TRIGS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TRIGS.OBJ" "$(INTDIR)\TRIGS.SBR" : $(SOURCE) $(DEP_CPP_TRIGS)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_TRIGS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_TRIGS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_TRIGS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_TRIGS=\ + ".\Control.h"\ + ".\Cursor.h"\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Effects.h"\ + ".\error.h"\ + ".\Gendung.h"\ + ".\Inv.h"\ + ".\Items.h"\ + ".\msg.h"\ + ".\Multi.h"\ + ".\Palette.h"\ + ".\Player.h"\ + ".\Quests.h"\ + ".\Setmaps.h"\ + ".\Trigs.h"\ + + +"$(INTDIR)\TRIGS.OBJ" : $(SOURCE) $(DEP_CPP_TRIGS) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\wave.cpp + +!IF "$(CFG)" == "Diablo - Win32 Release" + +DEP_CPP_WAVE_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\wave.obj" "$(INTDIR)\wave.sbr" : $(SOURCE) $(DEP_CPP_WAVE_)\ + "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Debug" + +DEP_CPP_WAVE_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 FinalFinal" + +DEP_CPP_WAVE_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware FinalFinal" + +DEP_CPP_WAVE_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "Diablo - Win32 Shareware Release" + +DEP_CPP_WAVE_=\ + ".\d3dtypes.h"\ + ".\Ddraw.h"\ + ".\Diablo.h"\ + ".\Dsound.h"\ + ".\Engine.h"\ + ".\Sound.h"\ + ".\Storm.h"\ + + +"$(INTDIR)\wave.obj" : $(SOURCE) $(DEP_CPP_WAVE_) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/src/DIABLO.MDP b/src/DIABLO.MDP new file mode 100644 index 0000000..3750354 Binary files /dev/null and b/src/DIABLO.MDP differ diff --git a/src/DIABLO.NCB b/src/DIABLO.NCB new file mode 100644 index 0000000..25c7d07 Binary files /dev/null and b/src/DIABLO.NCB differ diff --git a/src/DIABLO.OPT b/src/DIABLO.OPT new file mode 100644 index 0000000..fa6a7ac Binary files /dev/null and b/src/DIABLO.OPT differ diff --git a/src/DIABLO.PLG b/src/DIABLO.PLG new file mode 100644 index 0000000..e69de29 diff --git a/src/DIABLO.RC b/src/DIABLO.RC new file mode 100644 index 0000000..c1b53e0 --- /dev/null +++ b/src/DIABLO.RC @@ -0,0 +1,325 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "icon1.ico" + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,0 + PRODUCTVERSION 97,5,23,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", "Synergistic Software\0" + VALUE "FileDescription", "Hellfire\0" + VALUE "FileVersion", "1, 0, 1, 0\0" + VALUE "InternalName", "Hellfire\0" + VALUE "LegalCopyright", "Copyright © 1997\0" + VALUE "OriginalFilename", "hellfire.exe\0" + VALUE "ProductName", "Synergistic Software Hellfire\0" + VALUE "ProductVersion", "98, 1, 13, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DDRAW_ERR DIALOG DISCARDABLE 0, 0, 250, 241 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Direct Draw Error" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,193,220,50,14 + LTEXT "Hellfire was unable to properly initialize your video card using DirectX. Please try the following solutions to correct the problem:", + IDC_STATIC,7,7,236,18 + LTEXT "Use the Diablo setup program ""SETUP.EXE"" provided on the Diablo CD-ROM to install DirectX 3.0.", + IDC_STATIC,19,26,210,18 + LTEXT "Install the most recent DirectX video drivers provided by the manufacturer of your video card. A list of video card manufactuers can be found at: http://www.sierracom", + IDC_STATIC,19,48,210,27 + LTEXT "The error encountered while trying to initialize the video card was:", + IDC_STATIC,7,175,236,9 + LTEXT "unknown error",IDC_ERROR_TAG,19,186,210,27 + LTEXT "If you continue to have problems, we have also included Microsoft DirectX 2.0 drivers on the Diablo CD-ROM. This older version of DirectX may work in cases where DirectX 3.0 does not.", + IDC_STATIC,7,79,236,27 + LTEXT "USA telephone: 1-800-426-9400\nInternational telephone: 206-882-8080\nhttp://www.microsoft.com", + IDC_STATIC,19,137,210,27 + LTEXT "If you continue to have problems with DirectX, please contact Microsoft's Technical Support at:", + IDC_STATIC,7,116,236,18 +END + +IDD_MEM_ERR DIALOG DISCARDABLE 0, 0, 250, 213 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Out of Memory Error" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,193,192,50,14 + LTEXT "Hellfire has exhausted all the memory on your system. This problem can likely be corrected by changing the virtual memory settings for Windows. Ensure that your system has at least 10 megabytes of free disk space, then check your virtual memory settings:", + IDC_STATIC,7,7,236,36 + LTEXT "Select ""Settings - Control Panel"" from the ""Start"" menu\nRun the ""System"" control panel applet\nSelect the ""Performance"" tab, and press ""Virtual Memory""\nUse the ""Let Windows manage my virtual memory..."" option", + IDC_STATIC,23,54,197,36 + LTEXT "The error encountered was:",IDC_STATIC,7,146,236,11 + LTEXT "unknown location",IDC_ERROR_TAG,20,157,210,27 + LTEXT "For Windows 95:",IDC_STATIC,7,45,236,9 + LTEXT "Select ""Settings - Control Panel"" from the ""Start"" menu\nRun the ""System"" control panel applet\nSelect the ""Performance"" tab\nPress ""Change"" in ""Virtual Memory"" settings\nEnsure that the virtual memory file is at least 32 megabytes", + IDC_STATIC,17,98,197,45 + LTEXT "For Windows NT:",IDC_STATIC,7,89,236,9 +END + +IDD_FILE_ERR DIALOG DISCARDABLE 0, 0, 265, 114 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Data File Error" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,208,93,50,14 + LTEXT "Hellfire was unable to open a required file. Please ensure that the Diablo disc is in the CDROM drive. If this problem persists, try uninstalling and reinstalling Hellfire using the program ""SETUP.EXE"" on the Hellfire CD-ROM.", + -1,7,7,251,36 + LTEXT "The problem occurred while trying to load a file",-1,7, + 48,232,9 + LTEXT "unknown file",IDC_ERROR_TAG,20,59,210,27 +END + +IDD_DDRAW_DLL_ERR DIALOG DISCARDABLE 0, 0, 250, 161 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Direct Draw Error" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,193,140,50,14 + LTEXT "Hellfire was unable to find the file ""ddraw.dll"", which is a component of Microsoft DirectX. Please run the program ""SETUP.EXE"" on the Diablo CD-ROM and install Microsoft DirectX.", + -1,7,7,236,27 + LTEXT "The error encountered while trying to initialize DirectX was:", + -1,7,95,236,9 + LTEXT "unknown error",IDC_ERROR_TAG,19,106,210,29 + LTEXT "USA telephone: 1-800-426-9400\nInternational telephone: 206-882-8080\nhttp://www.microsoft.com", + -1,19,60,210,27 + LTEXT "If you continue to have problems with DirectX, please contact Microsoft's Technical Support at:", + -1,7,39,236,18 +END + +IDD_DSOUND_DLL_ERR DIALOG DISCARDABLE 0, 0, 250, 161 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Direct Sound Error" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,193,140,50,14 + LTEXT "Hellfire was unable to find the file ""dsound.dll"", which is a component of Microsoft DirectX. Please run the program ""SETUP.EXE"" on the Diablo CD-ROM and install Microsoft DirectX.", + -1,7,7,236,27 + LTEXT "The error encountered while trying to initialize DirectX was:", + -1,7,95,236,9 + LTEXT "unknown error",IDC_ERROR_TAG,19,106,210,27 + LTEXT "USA telephone: 1-800-426-9400\nInternational telephone: 206-882-8080\nhttp://www.microsoft.com", + -1,19,60,210,27 + LTEXT "If you continue to have problems with DirectX, please contact Microsoft's Technical Support at:", + -1,7,39,236,18 +END + +IDD_DISKFREE_ERR DIALOG DISCARDABLE 0, 0, 250, 100 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Out of Disk Space" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,193,79,50,14 + LTEXT "Hellfire requires at least 10 megabytes of free disk space to run properly. The disk:", + -1,7,7,236,18 + LTEXT "",-1,7,43,232,9 + LTEXT "unknown drive",IDC_ERROR_TAG,7,33,210,9 + LTEXT "has less than 10 megabytes of free space left. Please free some space on your drive and run Hellfire again.", + -1,7,52,236,18 +END + +IDD_DDRAW_PAL_ERR DIALOG DISCARDABLE 0, 0, 250, 161 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Direct Draw Error" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,193,140,50,14 + LTEXT "Hellfire was unable to switch video modes. This is a common problem for computers with more than one video card. To correct this problem, please set your video resolution to 640 x 480 and try running Hellfire again.", + IDC_STATIC,7,7,236,27 + LTEXT "The error encountered while trying to switch video modes was:", + IDC_STATIC,7,95,236,9 + LTEXT "unknown error",IDC_ERROR_TAG,19,106,210,27 + LTEXT "Select ""Settings - Control Panel"" from the ""Start"" menu\nRun the ""Display"" control panel applet\nSelect the ""Settings"" tab\nSet the ""Desktop Area"" to ""640 x 480 pixels""", + IDC_STATIC,23,50,197,36 + LTEXT "For Windows 95 and Windows NT",IDC_STATIC,7,41,236,9 +END + +IDD_CDROM_ERR DIALOG DISCARDABLE 0, 0, 250, 92 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Data File Error" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,136,71,50,14 + LTEXT "Hellfire cannot read a required data file. Your Diablo CD may not be in the CDROM drive. Please ensure that the Diablo disc is in the CDROM drive and press OK. To leave the program, press Exit.", + -1,7,7,236,27 + LTEXT "unknown file",IDC_ERROR_TAG,20,37,210,27 + PUSHBUTTON "Exit",IDCANCEL,193,71,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DDRAW_ERR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 234 + END + + IDD_MEM_ERR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 206 + END + + IDD_FILE_ERR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 258 + TOPMARGIN, 7 + BOTTOMMARGIN, 107 + END + + IDD_DDRAW_DLL_ERR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 154 + END + + IDD_DSOUND_DLL_ERR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 154 + END + + IDD_DISKFREE_ERR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 93 + END + + IDD_DDRAW_PAL_ERR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 154 + END + + IDD_CDROM_ERR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 85 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/DIABLO.SAV b/src/DIABLO.SAV new file mode 100644 index 0000000..d113ab5 --- /dev/null +++ b/src/DIABLO.SAV @@ -0,0 +1,3097 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Main file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DIABLO.CPP 16 3/29/97 9:09p Pwyatt $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "mainmenu.h" +#include "interfac.h" +#include "inv.h" +#include "msg.h" +#include "multi.h" +#include "engine.h" +#include "palette.h" +#include "scrollrt.h" +#include "gendung.h" +#include "setmaps.h" +#include "debug.h" +#include "effects.h" + +#include "dead.h" +#include "lighting.h" +#include "control.h" +#include "gamemenu.h" + +#include "items.h" +#include "player.h" +#include "monster.h" +#include "objects.h" +#include "missiles.h" +#include "trigs.h" +#include "spelldat.h" +#include "spells.h" +#include "cursor.h" + +#include "town.h" +#include "towners.h" +#include "drlg_l1.h" +#include "drlg_l2.h" +#include "drlg_l3.h" +#include "drlg_l4.h" +#include "quests.h" +#include "minitext.h" +#include "themes.h" +#include "stores.h" +#include "packplr.h" +#include "portal.h" +#include "doom.h" + +#include "automap.h" +#include "help.h" +#include "error.h" +#include "diabloui.h" +#include "textdat.h" +// pjw.patch1.start +#include "mpqapi.h" +#include +// pjw.patch1.end +#include "mono.h" + +/*-----------------------------------------------------------------------** +** Registration info +**-----------------------------------------------------------------------*/ +#include "regconst.h" +char sgszTblSig[TBL_LEN] = "REGISTRATION_TABLE"; + + +/*-----------------------------------------------------------------------** +** Global Variables +**-----------------------------------------------------------------------*/ +extern char gszProgKey[]; +BYTE gbDoEnding; +void DoEnding(); + +int StripPlayer(int pnum); + +DWORD glSeedTbl[NUMLEVELS]; +int gnLevelTypeTbl[NUMLEVELS]; + +// window vars +HWND ghMainWnd; +HINSTANCE ghInst; + +// video vars +BOOL fullscreen = TRUE; + + +// mouse +int MouseX, MouseY; + +// program vars +int force_redraw = NODRAW; + +BOOL svgamode; + +// Temp vars (delete all uses before final compile) +long gv1; +long gv2; +long gv3; +long gv4; +long gv5; + +#ifndef NDEBUG +// do not change this flag -- USE 'n' on the command line +static BOOL cineflag = TRUE; +#endif + +#if CHEATS +BOOL gbDumpDropLog = FALSE; +BOOL davedebug = FALSE; +BOOL cheatflag = FALSE; // Turn invincibility and all spells on/off +BOOL simplecheat = FALSE; // like cheatflag, but doesn't screw up game +BOOL gbNoDropInactive = FALSE; // don't drop players on timeout +int tstQMsgSpd; +int tstQMsgIndex = 0; +BOOL tstQMsgFlag = FALSE; +BOOL tstQMsgIndexFlag = FALSE; +BOOL itemcheat = FALSE; +BOOL uniqcheat = FALSE; +#endif + +BOOL visiondebug = FALSE; // Vision debugging +BOOL scrollflag = FALSE; // Scroll when at edge of screen with mouse +BOOL light4flag = FALSE; // 4 levels of light instead of 16 +BOOL leveldebug = FALSE; +BOOL monstdebug = FALSE; +BOOL trigdebug = FALSE; +int setseed = 0; + +int debugmonsttypes = 0; +int DebugMonsters[10]; + +BOOL PauseMode = FALSE; +BOOL FriendlyMode = TRUE; + +BOOL gbRunGame; +BOOL gbRunGameResult; +BOOL gbProcessPlayers; +BOOL gbGameLoopStartup; + +bool gbTheo = false; +bool gbCowsuit = false; +bool gbOurNest = false; +bool gbAllowBard = false; +bool gbAllowMultiPlayer = false; + +//int glEndSeed[17]; // @@@ drb temp +//int glMid1Seed[17]; +//int glMid2Seed[17]; +//int glMid3Seed[17]; + +int glEndSeed[NUMLEVELS+1]; // @@@ drb temp +int glMid1Seed[NUMLEVELS+1]; +int glMid2Seed[NUMLEVELS+1]; +int glMid3Seed[NUMLEVELS+1]; //JKE 7/30 adds new levels + +/*-----------------------------------------------------------------------** +** timeout cursor +**-----------------------------------------------------------------------*/ +#define TIMEOUT_CURSOR WATCH_CURS +static int sgnTimeoutCurs = NO_CURSOR; + +#define LMOUSE_DOWN 1 +#define RMOUSE_DOWN 2 +// drb.patch1.start.1/24/97 +// static BYTE sgbMouseDown = 0; +BYTE sgbMouseDown = 0; +// drb.patch1.end.1/24/97 + + +/*-----------------------------------------------------------------------** +** Function stubs +**-----------------------------------------------------------------------*/ +// pjw.patch1.start +// static void try_game_loop(BOOL bStartup); +static void alloc_plr(); +static void DoTimedEvents(); +static void game_loop(BOOL bStartup); +static void plr_encrypt(BOOL bEncrypt); +void InitializeHashSource(); +void Decrypt(LPDWORD data, DWORD bytes, DWORD key); +void Encrypt(LPDWORD data, DWORD bytes, DWORD key); +// pjw.patch1.end + + +void BlackPalette(); +void enable_frame_counter(); +void init_window(int nCmdShow); +void play_movie(const char * pszMovie,BOOL bAllowCancel); +void play_quotes(); +void play_quit(); +void FreeCursor(); +void InitDebugGFX(); +void FreeDebugGFX(); +void ShowProgress(UINT uMsg); +static LRESULT CALLBACK GM_Game(HWND, UINT, WPARAM, LPARAM); +void TrackInit(BOOL bMouseDown); +void TrackMouse(); +void run_delta_info(); +void toggle_frame_counter(); +WNDPROC my_SetWindowProc(WNDPROC wndProc); +void plrmsg_update(); +void screen_capture(); +void SavePaletteSettings(); +void menu_music(); +void NetStartTimeout(); +void menusnd_init(); +void InitLevels(); +void SyncInitPlrPos(int pnum); + +void OpenCloseAllDoors(); +void OpenNaKrul(); + +//****************************************************************** +//****************************************************************** +void FlushMsgs() { + // turn tracking off + TrackInit(FALSE); + sgbMouseDown = FALSE; + ReleaseCapture(); + + // keep flushing messages until all key and mouse msgs are gone + BOOL bLoop = TRUE; + while (bLoop) { + bLoop = FALSE; + MSG msg; + while (PeekMessage(&msg,NULL,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE)) + bLoop = TRUE; + while (PeekMessage(&msg,NULL,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE)) + bLoop = TRUE; + } +} + +//****************************************************************** +//****************************************************************** +static void CommandLine(const char * s) { + int val; + (val); + + while (*s) { + + // skip over any space characters + while (isspace(*s)) + s++; + + // check for direct draw emulation mode +// pjw.patch1.start.1/13/97 + static const char sszEmulate[] = "dd_emulate"; + if (! _strnicmp(sszEmulate,s,strlen(sszEmulate))) { + extern BYTE gbUseDDEmulation; + gbUseDDEmulation = TRUE; + s += strlen(sszEmulate); + continue; + } + + // check for direct draw offscreen buffer + static const char sszBackBuf[] = "dd_backbuf"; + if (! _strnicmp(sszBackBuf,s,strlen(sszBackBuf))) { + extern BYTE gbForceBackBuf; + gbForceBackBuf = TRUE; + s += strlen(sszBackBuf); + continue; + } + + static const char sszDupSound[] = "ds_noduplicates"; + if (! _strnicmp(sszDupSound,s,strlen(sszDupSound))) { + extern BYTE gbDupSounds; + gbDupSounds = FALSE; + s += strlen(sszDupSound); + continue; + } + + char const sszTheoFlag[] = "Theoquest"; + if (! _strnicmp(sszTheoFlag, s, strlen(sszTheoFlag))) { + gbTheo = true; + s += strlen(sszTheoFlag); + continue; + } + + char const sszCowQuestFlag[] = "Cowquest"; + if (!_strnicmp(sszCowQuestFlag, s, strlen(sszCowQuestFlag))) { + gbCowsuit = true; + s += strlen(sszCowQuestFlag); + continue; + } + + char const sszOurNestFlag[] = "NestArt"; + if (!_strnicmp(sszOurNestFlag, s, strlen(sszOurNestFlag))) { + gbOurNest = true; + s += strlen(sszOurNestFlag); + continue; + } + + char const sszAllowBardFlag[] = "Bardtest"; + if (!_strnicmp(sszAllowBardFlag, s, strlen(sszAllowBardFlag))) { + gbAllowBard = true; + s += strlen(sszAllowBardFlag); + continue; + } + + char const sszAllowMultiPlayerFlag[] = "Multitest"; + if (!_strnicmp(sszAllowMultiPlayerFlag, s, strlen(sszAllowMultiPlayerFlag))) { + gbAllowMultiPlayer = true; + s += strlen(sszAllowMultiPlayerFlag); + continue; + } + +// pjw.patch1.end.1/13/97 + + // extract next character -- do not do ++ inside macro + // some versions of C may have nasty side effects... + char c = tolower(*s); s++; + switch (c) { + #if CHEATS + case 'b': + gbDumpDropLog = TRUE; + break; + #endif + + #if CHEATS + case 'i': + gbNoDropInactive = TRUE; + break; + #endif + + #if CHEATS + // this cheat flag is for testing without having your + // character die every two seconds -- doesn't have + // all the nasty side effects of the cheat flag + case '$': + simplecheat = TRUE; + break; + #endif + + #if CHEATS + // this cheat flag is the do-everything cheat for programmers + // it has all sorts of nasty side effects which may hide bugs + case '^': + cheatflag = TRUE; + break; + #endif + + #if CHEATS + case 'd': + davedebug = TRUE; + cineflag = FALSE; + break; + #endif + + #if CHEATS + case 'w': + davecheat = TRUE; + break; + #endif + + #if CHEATS && !IS_VERSION(SHAREWARE) + case 'l': + leveldebug = TRUE; + setlevel = FALSE; + + // get level type + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + leveltype = val; + + // get level num + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + currlevel = val; + plr[0].plrlevel = val; + break; + #endif + + #if CHEATS + case 'm': + monstdebug = TRUE; + + // get monster number + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + DebugMonsters[debugmonsttypes++] = val; + break; + #endif + + #if CHEATS + case 'q': + // get quest number + while(isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + extern int questcheat; + questcheat = val; + break; + #endif + + #if CHEATS + case 'r': + while(isspace(*s)) + s++; + val = 0; + while(isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + setseed = val; + break; + #endif + + #if CHEATS + case 's': + scrollflag = TRUE; + break; + #endif + + #if CHEATS && !IS_VERSION(SHAREWARE) + case 't': + leveldebug = TRUE; + setlevel = TRUE; + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + setlvlnum = val; + break; + #endif + + #if CHEATS + case 'j': + while (isspace(*s)) + s++; + val = 0; + while (isdigit(*s)) { + val *= 10; + val += *s - '0'; + s++; + } + trigdebug = val; + break; + #endif + + #if CHEATS + case 'v': + visiondebug = TRUE; + break; + #endif + + #ifndef NDEBUG + case 'f': + toggle_frame_counter(); + break; + #endif + + #ifndef NDEBUG + case 'x': + fullscreen = FALSE; + break; + #endif + + #ifndef NDEBUG + case 'n': + cineflag = FALSE; + break; + #endif + + #if CHEATS + case '7': + itemcheat = TRUE; + break; + + case '8': + uniqcheat = TRUE; + break; + #endif + } + + } +} + + +//****************************************************************** +//****************************************************************** +void FreeGameMem() { + music_stop(); + + DiabloFreePtr(pDungeonCels); + DiabloFreePtr(pMegaTiles); + DiabloFreePtr(pMiniTiles); + DiabloFreePtr(pSpecialCels); + DiabloFreePtr(pSpeedCels); + FreeMissileGFX(); + + FreeMonsterGFX(); + FreeObjectGFX(); + FreeMonsterSnd(); + FreeTownerGFX(); +} + + +//****************************************************************** +// stuff done every time a game is started/ended +//****************************************************************** +static void start_game(UINT uMsg) { + gbDoEnding = FALSE; + svgamode = TRUE; + InitCursor(); + InitLightTable(); + InitDebugGFX(); + app_assert(ghMainWnd); + music_stop(); + ShowProgress(uMsg); + gmenu_init(); + InitLevelCursor(); + sgnTimeoutCurs = NO_CURSOR; + sgbMouseDown = 0; + TrackInit(FALSE); +} +static void free_game() { + FreeControlPan(); + FreeInvGFX(); + gmenu_free(); + FreeQuestText(); + FreeStoreMem(); + for (int i = 0; i < MAX_PLRS; i++) + FreePlayerGFX(i); + FreeItemGFX(); + + FreeCursor(); + FreeLightTable(); + FreeDebugGFX(); + FreeGameMem(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void run_game_loop(UINT uMsg) { + nthread_perform_keepalive(TRUE); + start_game(uMsg); + app_assert(ghMainWnd); + WNDPROC saveProc = my_SetWindowProc(GM_Game); + CalcInitBallPer(); + // pjw.patch2.start + // nthread_perform_keepalive(FALSE); + // pjw.patch2.end + run_delta_info(); + + gbRunGame = TRUE; + gbProcessPlayers = TRUE; + gbRunGameResult = TRUE; + force_redraw = FULLDRAW; + DrawAndBlit(); + PaletteFadeIn(FADE_FAST); + force_redraw = FULLDRAW; + gbGameLoopStartup = TRUE; + + // pjw.patch2.start + nthread_perform_keepalive(FALSE); + // pjw.patch2.end + + +// pjw.patch1.start + MSG msg; + plr_encrypt(TRUE); + while (gbRunGame) { + DoTimedEvents(); // palette cycling + + // pjw.patch2.start + // if there are any messages in the queue, process them all + if (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) { + // bump thread priority to make sure that + // during peekmessage loop we are less likely + // to yield to another process + SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL); + plr_encrypt(FALSE); + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if (msg.message == WM_QUIT) { + gbRunGame = gbRunGameResult = FALSE; + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + BOOL bRun = gbRunGame && nthread_run_gameloop(FALSE); + if (! bRun) plr_encrypt(TRUE); + SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL); + if (! bRun) continue; + } + else if (! nthread_run_gameloop(FALSE)) { + // not enough time has elapsed since last gameloop + continue; + } + // pjw.patch2.end + + // actual game logic + plr_encrypt(FALSE); + NetReceivePackets(); + game_loop(gbGameLoopStartup); + gbGameLoopStartup = FALSE; + DrawAndBlit(); + plr_encrypt(TRUE); + } + plr_encrypt(FALSE); +// pjw.patch1.end + + // save character in multiplayer mode + if (gbMaxPlayers > 1) { + void UpdatePlayerFile(); + UpdatePlayerFile(); + } + void ReleasePlayerFile(); + ReleasePlayerFile(); + + PaletteFadeOut(FADE_FAST); + SetCursor(NO_CURSOR); + ClrDraw(); + force_redraw = FULLDRAW; + FullBlit(TRUE); + + // restore old window procedure + saveProc = my_SetWindowProc(saveProc); + app_assert(saveProc == GM_Game); + + free_game(); + + if (gbDoEnding) { + gbDoEnding = FALSE; + DoEnding(); + } +} + + +/*-----------------------------------------------------------------------** +// return FALSE to quit game +// return TRUE to continue game +**-----------------------------------------------------------------------*/ +BOOL StartGame(BOOL bNewGame, BOOL bSinglePlayer) { + + extern BYTE gbSelectProvider; + gbSelectProvider = TRUE; + + while (1) { + + // initialize network + BOOL fExitProgram = FALSE; + if (! NetInit(bSinglePlayer,&fExitProgram)) { + gbRunGameResult = !fExitProgram; + break; + } + + gbSelectProvider = FALSE; + + UINT uMsg; + if (bNewGame || !gbValidSaveFile) { + + InitLevels(); + InitQuests(); + InitPortals(); + InitDungMsgs(myplr); + if (!gbValidSaveFile && gbSaveFileExists) + { + // clear the items from the character's inventory + StripPlayer(myplr); + } + uMsg = WM_DIABNEWGAME; + } + else { + uMsg = WM_DIABLOADGAME; + } + + run_game_loop(uMsg); + NetClose(); + + // in single player mode, exit this loop + if (gbMaxPlayers == 1) break; + + // in multiplayer mode, only break out of the + // loop if the player wants to exit the game, otherwise + // the loop will be exited based on results from NetInit() + if (! gbRunGameResult) break; + } + + TRACE_FCN("SNetDestroy"); + SNetDestroy(); + TRACE_FCN(NULL); + + return gbRunGameResult; +} + + +//****************************************************************** +//****************************************************************** +static void InitOnce() { + MouseX = TOTALX >> 1; + MouseY = TOTALY >> 1; + + ScrollInfo._sdx = 0; + ScrollInfo._sdy = 0; + ScrollInfo._sxoff = 0; + ScrollInfo._syoff = 0; + ScrollInfo._sdir = SCRL_NONE; + for (int i = 0; i < 1024; i++) + nBuffWTbl[i] = i * BUFFERX; + + // Init engine vars + ClrDiabloMsg(); +} + + +//****************************************************************** +//****************************************************************** +/* pjw.patch2.start +static const char sgszErrFile[] = "c:\\helfire_.err"; +static void write_exception(struct _EXCEPTION_POINTERS *pep) { + FILE * f = fopen(sgszErrFile,"wb"); + if (! f) return; + + PEXCEPTION_RECORD per = pep->ExceptionRecord; + while (per) { + fprintf( + f, + "exception: 0x%08x\r\ncode address: 0x%08x\r\n", + per->ExceptionCode, + per->ExceptionAddress + ); + + if (per->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { + if (per->ExceptionInformation[0]) + fprintf(f,"write access violation at 0x%08x\r\n",per->ExceptionInformation[1]); + else + fprintf(f,"read access violation at 0x%08x\r\n",per->ExceptionInformation[1]); + } + + per = per->ExceptionRecord; + } + + fclose(f); +} +pjw.patch2.end */ + + +//****************************************************************** +//****************************************************************** +// pjw.patch2.start +void cleanup(BOOL bNormalExit); +static LPTOP_LEVEL_EXCEPTION_FILTER sg_previousFilter; +static LONG WINAPI DiabloUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *pep) { + void free_directx(); + free_directx(); + cleanup(FALSE); + // write_exception(pep); + if (sg_previousFilter) return sg_previousFilter(pep); + return EXCEPTION_CONTINUE_SEARCH; +} +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +BOOL grab_event() { + // NOTE: this event never gets cleaned up by our code + // we rely upon windows to clean up this event so that it + // occurs as late as possible in the program exit. This is + // a really nasty hack to make sure that SMACKER doesn't + // initialize improperly + SetLastError(0); + HANDLE hExtraEvent = CreateEvent(NULL,FALSE,FALSE,"DiabloEvent"); + HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,"HellfireEvent"); + return ERROR_ALREADY_EXISTS != GetLastError(); +} + + +//****************************************************************** +//****************************************************************** +static BOOL ActivatePreviousInstance(const char * pszAppClass) { + // find main application window + HWND hWnd; + HWND hWndTop; + HWND hWndPopup; + + // get parent window + if (NULL == (hWnd = FindWindow(pszAppClass,NULL))) + return FALSE; + + // get popup window (if any) + if (NULL != (hWndPopup = GetLastActivePopup(hWnd))) + hWnd = hWndPopup; + + // get topmost control window of topmost window + hWndTop = GetTopWindow(hWnd); + if (! hWndTop) hWndTop = hWnd; + + // bring to the front + SetForegroundWindow(hWnd); + SetFocus(hWndTop); + + return TRUE; +} + + +typedef struct _SHAREDDATA { + LONG status; + DWORD processid; +} SHAREDDATA, *SHAREDDATAPTR; + + +//=========================================================================== +// pjw.patch2.start +#ifdef NDEBUG +static void inline ReloadSelf (HINSTANCE instance) { + + // GET THE MODULE FILENAME + char filename[MAX_PATH] = ""; + GetModuleFileName((HMODULE)instance,filename,MAX_PATH); + + + // OPEN NAMED SHARED MEMORY + char name[MAX_PATH+16]; + wsprintf(name,"Reload-%s",filename); + for (LPSTR curr = name; *curr; ++curr) + if (*curr == '\\') + *curr = '/'; + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + DWORD bytes = max(4096,sysinfo.dwPageSize); + + + HANDLE map = CreateFileMapping((HANDLE)0xFFFFFFFF, + NULL, + PAGE_READWRITE | SEC_COMMIT, + 0, + bytes, + name); + BOOL first = (GetLastError() != ERROR_ALREADY_EXISTS); + if (!map) + return; + + // Open secondary named shared memory to fool Diablo into not autorunning + char tmpname[MAX_PATH+16]; + strcpy(tmpname,"Reload-Diablo"); + HANDLE tmpmap = CreateFileMapping((HANDLE)0xFFFFFFFF, + NULL, + PAGE_READWRITE | SEC_COMMIT, + 0, + bytes, + tmpname); + // end of hack + + LPVOID view = MapViewOfFile(map,FILE_MAP_ALL_ACCESS,0,0,bytes); + if (!view) + return; + SHAREDDATAPTR ptr = (SHAREDDATAPTR)view; + + // IF WE ARE THE FIRST INSTANCE, THEN RELOAD OURSELVES, WAIT FOR THE + // SECOND INSTANCE TO INITIALIZE, THEN QUIT + if (first) { + ptr->status = -1; + ptr->processid = 0; + STARTUPINFO startupinfo; + ZeroMemory(&startupinfo,sizeof(STARTUPINFO)); + startupinfo.cb = sizeof(STARTUPINFO); + PROCESS_INFORMATION processinfo; + CreateProcess(filename, + NULL, + NULL, + NULL, + FALSE, + CREATE_NEW_PROCESS_GROUP, + NULL, + NULL, + &startupinfo, + &processinfo); + WaitForInputIdle(processinfo.hProcess,INFINITE); + CloseHandle(processinfo.hThread); + CloseHandle(processinfo.hProcess); + while (ptr->status < 0) + Sleep(1000); + UnmapViewOfFile(view); + CloseHandle(map); + ExitProcess(0); + } + + // OTHERWISE, ALLOW ONE INSTANCE TO RUN, AND MAKE ANY ADDITIONAL + // INSTANCES JUST REACTIVATE THE RUNNING INSTANCE + if (!InterlockedIncrement(&ptr->status)) + ptr->processid = GetCurrentProcessId(); + else { + HWND window = GetForegroundWindow(); + HWND prev; + while ((prev = GetNextWindow(window,GW_HWNDPREV)) != (HWND)0) + window = prev; + do { + DWORD processid; + GetWindowThreadProcessId(window,&processid); + if (processid == ptr->processid) { + SetForegroundWindow(window); + break; + } + } while ((window = GetNextWindow(window,GW_HWNDNEXT)) != (HWND)0); + UnmapViewOfFile(view); + CloseHandle(map); + ExitProcess(0); + } +} +#endif +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow){ +// pjw.patch2.start + #ifdef NDEBUG + ReloadSelf(hInstance); + #endif +// pjw.patch2.end + + MonoDevice::Printf("Command line: %s", lpCmdLine); + ghInst = hInstance; + ShowCursor(FALSE); + // pjw.patch1.start + srand(GetTickCount()); + InitializeHashSource(); + alloc_plr(); + // pjw.patch1.end + + // delete any previous error file created by exception + // handler and then install exception handler + // pjw.patch2.start + // DeleteFile(sgszErrFile); + sg_previousFilter = SetUnhandledExceptionFilter(DiabloUnhandledExceptionFilter); + // pjw.patch2.end + + // if another instance of Diablo is already running, + // then activate it and exit this instance + BOOL bGotEvent = grab_event(); + if (ActivatePreviousInstance("DIABLO")) // conflict with parent is bad + return FALSE; + if (ActivatePreviousInstance(gszAppName)) + return FALSE; + if (!bGotEvent) return FALSE; + + + #ifndef NDEBUG + SFileEnableDirectAccess(1); + #endif + + InitOnce(); + char cpCmdLine[255]; + if (!lpCmdLine[0]) { + cpCmdLine[0] = 0; + FILE * const fp = fopen("command.txt","r"); + if (fp) { + fgets(cpCmdLine, sizeof(cpCmdLine)/sizeof(char), fp); + lpCmdLine = cpCmdLine; + fclose(fp); + } + } + CommandLine(lpCmdLine); + init_window(nCmdShow); + + menusnd_init(); + UiInitialize(); + + #if IS_VERSION(SHAREWARE) + UiSetSpawned(TRUE); + #endif + + + // play logo + #ifndef NDEBUG + if (cineflag) play_movie("gendata\\logo.smk",TRUE); + #else + play_movie("gendata\\logo.smk",TRUE); + #endif + + // play magazine quotes + /* + #if IS_VERSION(SHAREWARE) + #ifndef NDEBUG + if (cineflag) play_quotes(); + #else + play_quotes(); + #endif + #endif + */ + + // play main intro + #if !IS_VERSION(SHAREWARE) + const char sgszMovie[] = "Intro"; + DWORD dwPlayMovie; + if (! SRegLoadValue(gszProgKey,sgszMovie,0,&dwPlayMovie)) + dwPlayMovie = 1; + //if (dwPlayMovie) + play_movie("gendata\\Hellfire.smk",TRUE); + SRegSaveValue(gszProgKey,sgszMovie,0,0); + #endif + + + // play title screen + #ifndef NDEBUG + if (cineflag) { + #endif + UiTitleDialog(7); // DKT this needs to change to ours + BlackPalette(); + #ifndef NDEBUG + } + #endif + + // play beta warning + #if IS_VERSION(BETA) + #ifndef NDEBUG + if (cineflag) { + #endif + UiBetaDisclaimer(5); + BlackPalette(); + #ifndef NDEBUG + } + #endif + #endif + + // main game menu (finally) + DiabloMenu(); + + // play "buy me" screens + /* + #if IS_VERSION(SHAREWARE) + #ifndef NDEBUG + if (cineflag) play_quit(); + #else + play_quit(); + #endif + #endif + */ + + UiDestroy(); + SavePaletteSettings(); + + if (ghMainWnd) { + // sleep before we destroy window so + // that SFX have time to finish before exit + Sleep(300); + DestroyWindow(ghMainWnd); + } + + return FALSE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL CheckPlrLBtn(BOOL ShiftDown) { + BOOL adjacent; + + app_assert(MouseY < 352); + if (leveltype == 0) { + // + // Town Level + // + ShiftDown = FALSE; // no attacking in town + if ((cursitem != -1) && (curs == GLOVE_CURS)) + NetSendCmdLocParam1(TRUE,invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM,cursmx,cursmy,cursitem); + if (cursmonst != -1) + NetSendCmdLocParam1(TRUE,CMD_TALKXY,cursmx,cursmy,cursmonst); + if ((cursitem == -1) && (cursmonst == -1) && (cursplr == -1)) + return TRUE; + } + else { + // + // NOT Town Level + // + adjacent = abs(plr[myplr]._px - cursmx) < 2 + && abs(plr[myplr]._py - cursmy) < 2; + if ((cursitem != -1) && (curs == GLOVE_CURS) && !ShiftDown) + NetSendCmdLocParam1(TRUE,invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM,cursmx,cursmy,cursitem); + else if ((cursobj != -1) + && (!ShiftDown // allow barrel busting even with shift key down + || (adjacent && object[cursobj]._oBreak == OBJ_BREAKABLE))) + NetSendCmdLocParam1(TRUE,(curs == DISARM_CURS) ? CMD_DISARMXY : CMD_OPOBJXY,cursmx,cursmy,cursobj); + + else if (plr[myplr]._pwtype == WEAP_RANGE) { + if (ShiftDown) + NetSendCmdLoc(TRUE,CMD_RATTACKXY, cursmx, cursmy); + else if (cursmonst != -1) { + if (CanTalkToMonst(cursmonst)) + // walk over to monster to talk to him + NetSendCmdParam1(TRUE,CMD_ATTACKID,cursmonst); + else + // Attack + NetSendCmdParam1(TRUE,CMD_RATTACKID,cursmonst); + } else if (cursplr != -1 && !FriendlyMode) + NetSendCmdParam1(TRUE,CMD_RATTACKPID, cursplr); + } + + else { // pwtype == WEAP_H2H + if (ShiftDown) { + if (cursmonst != -1) { + if (CanTalkToMonst(cursmonst)) + NetSendCmdParam1(TRUE,CMD_ATTACKID,cursmonst); + else + NetSendCmdLoc(TRUE,CMD_SATTACKXY, cursmx, cursmy); + } else + NetSendCmdLoc(TRUE,CMD_SATTACKXY, cursmx, cursmy); + } + else if (cursmonst != -1) + NetSendCmdParam1(TRUE,CMD_ATTACKID,cursmonst); + else if (cursplr != -1 && !FriendlyMode) + NetSendCmdParam1(TRUE,CMD_ATTACKPID,cursplr); + } + + if ((!ShiftDown) && (cursitem == -1) && (cursobj == -1) && (cursmonst == -1) && (cursplr == -1)) + return TRUE; + } + + return FALSE; +} + +/*-----------------------------------------------------------------------** +** Game message processing +**-----------------------------------------------------------------------*/ +static BOOL TryIconCurs() { + if (curs == RESURRECT_CURS) { + NetSendCmdParam1(TRUE,CMD_RESURRECT, cursplr); + return(TRUE); + } + + if (curs == HEALOTHER_CURS) { + NetSendCmdParam1(TRUE,CMD_HEALOTHER, cursplr); + return(TRUE); + } + + if (curs == TELE_CURS) { + DoTelekinesis(); + return(TRUE); + } + if (curs == IDENTIFY_CURS) { + if (cursinvitem != -1) + CheckIdentify(myplr, cursinvitem); + else + NewCursor(GLOVE_CURS); + return(TRUE); + } + if (curs == REPAIR_CURS) { + if (cursinvitem != -1) + DoRepair(myplr, cursinvitem); + else + NewCursor(GLOVE_CURS); + return(TRUE); + } + if (curs == RECHARGE_CURS) { + if (cursinvitem != -1) + DoRecharge(myplr, cursinvitem); + else + NewCursor(GLOVE_CURS); + return(TRUE); + } + + if (curs == OIL_CURS) { + if (cursinvitem != -1) + DoOil(myplr, cursinvitem); + else + NewCursor(GLOVE_CURS); + return(TRUE); + } + + if (curs == TARGET_CURS) { + if (cursmonst != -1) + NetSendCmdParam3(TRUE,CMD_TSPELLID,cursmonst,plr[myplr]._pTSpell, GetSpellLevel(myplr, plr[myplr]._pTSpell)); + else if (cursplr != -1) + NetSendCmdParam3(TRUE,CMD_TSPELLPID,cursplr,plr[myplr]._pTSpell,GetSpellLevel(myplr, plr[myplr]._pTSpell)); + else + NetSendCmdLocParam2(TRUE,CMD_TSPELLXY,cursmx,cursmy,plr[myplr]._pTSpell,GetSpellLevel(myplr, plr[myplr]._pTSpell)); + NewCursor(GLOVE_CURS); + return(TRUE); + } + if ((curs == DISARM_CURS) && (cursobj == -1)) { + NewCursor(GLOVE_CURS); + return(TRUE); + } + return(FALSE); +} + + +//****************************************************************** +//****************************************************************** +static BOOL wm_lbuttondown(WPARAM wParam) { + if (gmenu_click(TRUE)) + return FALSE; + + BOOL talk_click(); + if (talk_click()) + return FALSE; + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) + return FALSE; + + if (deathflag) { + CheckDeadButtons(); + return FALSE; + } + + if (PauseMode == 2) + return FALSE; + + if (drawmapofdoom) { + EndMapOfDoomView(); + return FALSE; + } + + if (spselflag) { + SetSpell(); + return FALSE; + } + + if (stextflag != STORE_NONE) { + CheckStoreBtn(); + return FALSE; + } + + if (MouseY < 352) { + if (gmenu_is_on()) + return FALSE; + + if (TryIconCurs()) + return FALSE; + + if (questlog) { + if ((MouseX > 32) && (MouseX < 288) && (MouseY > 32) && (MouseY < 308)) { + CheckQLogBtn(); + return FALSE; + } + } + + if (qtextflag) { + qtextflag = FALSE; + stream_stop(); + return FALSE; + } + + if ((chrflag) && (MouseX < 320)) { + CheckChrBtns(); + return FALSE; + } + else if ((invflag) && (MouseX > 320)) { + if (!dropGoldFlag) CheckInvScrn(); + return FALSE; + } + else if ((sbookflag) && (MouseX > 320)) { + CheckSBook(); + return FALSE; + } + else if (curs >= ICSTART) { + if (TryInvPut()) { + NetSendCmdPItem(TRUE,CMD_PUTITEM,cursmx,cursmy); + NewCursor(GLOVE_CURS); + } + return FALSE; + } + else { + if ((plr[myplr]._pStatPts != 0) && (!spselflag)) + CheckLvlBtn(); + if (!lvlbtndown) + return CheckPlrLBtn(wParam == (MK_LBUTTON | MK_SHIFT)); + } + } + else { + if (!talkflag && !dropGoldFlag && !gmenu_is_on()) + CheckSpdBar(); + CheckPanelBtns(); + if ((curs > GLOVE_CURS) && (curs < ICSTART)) + NewCursor(GLOVE_CURS); + } + + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +static void wm_lbuttonup() { + gmenu_click(FALSE); + void talk_release(); + talk_release(); + if (panbtndown) ReleasePanelBtn(); + if (chrbtndown) ReleaseChrBtn(); + if (lvlbtndown) ReleaseLvlBtn(); + if (stextflag != STORE_NONE) ReleaseStoreBtn(); +} + + +//****************************************************************** +//****************************************************************** +static void wm_rbuttondown() { + + // don't allow input while the menu is active + if (gmenu_is_on()) return; + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) + return; + + if (PauseMode == 2) return; + + if (plr[myplr]._pInvincible) return; + + if (drawmapofdoom) { + EndMapOfDoomView(); + return; + } + + if (stextflag != STORE_NONE) return; + + if (spselflag) { + SetSpell(); + return; + } +// if (sbookflag && CheckSBookCast()) +// return; + if (sbookflag && MouseX > 320) return; + + if (MouseY < 352) { + if (TryIconCurs()) + return; + if (cursinvitem != -1 && UseInvItem(myplr, cursinvitem)) + return; + } + if (curs == GLOVE_CURS) { + if (cursinvitem != -1 && UseInvItem(myplr, cursinvitem)) + return; +// else if (cursitem != -1 && (wParam & WM_SHIFT)) +// UseGroundItem(cursitem); + else + CheckPlrSpell(); + } + else if ((curs > GLOVE_CURS) && (curs < ICSTART)) NewCursor(GLOVE_CURS); +} + + +//****************************************************************** +//****************************************************************** +static void wm_mousemove() { + // check for menu sliders + if (gmenu_mousemove()) return; + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) return; + + // do game mousemove here +} + + +//****************************************************************** +//****************************************************************** +static void TogglePause() { + // no pause in multiplayer + if (gbMaxPlayers > 1) return; + + if (PauseMode) { + PauseMode = 0; + } + else { + PauseMode = 2; + sound_stop(); + TrackInit(FALSE); + } + force_redraw = FULLDRAW; +} + + +//****************************************************************** +//****************************************************************** +static void SendTaunt(DWORD dwMsg) { + // don't send taunts in single player mode + if (gbMaxPlayers == 1) return; + + // get program directory + char szPath[MAX_PATH]; + if (! GetModuleFileName(ghInst,szPath,MAX_PATH)) + app_fatal("Can't get program name"); + char * pszName = strrchr(szPath,'\\'); + if (pszName) *pszName = 0; + strcat(szPath,"\\hellfire.ini"); + + static const char * spszMsgTbl[] = { + "I need help! Heal me!", + "Go through that door first.", + "Give me some gold please.", + "Look out behind you!", + }; + static const char * spszKeyTbl[] = { + "F9","F10","F11","F12" + }; + + char szBuf[MAX_SEND_STR_LEN]; + app_assert(dwMsg < sizeof(spszMsgTbl) / sizeof(spszMsgTbl[0])); + GetPrivateProfileString( + "NetMsg", // section name + spszKeyTbl[dwMsg], // key name + spszMsgTbl[dwMsg], // default string + szBuf, // dest buffer + sizeof(szBuf) / sizeof(szBuf[0]), + szPath + ); + + // send message to other players + NetSendString(SEND_ALL_MASK,szBuf); +} + + +//****************************************************************** +//****************************************************************** +static BOOL wm_syskeydown(WPARAM wKey) { + // don't allow input while the menu is active + if (gmenu_is_on()) + return FALSE; + + // note: this identical code is in the keydown case also, but + // F10 seems to come through as a system key sometimes... + if (wKey == VK_F10) { + SendTaunt(1); + return TRUE; + } + + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +static void wm_keyup(WPARAM wKey) { + // can't ever get keydown for snapshot, but we do get keyup + if (wKey == VK_SNAPSHOT) + screen_capture(); + + // if any more cases are added here, then make sure menu is not active + // if (gmenu_is_on()) return; +} + + +//****************************************************************** +//****************************************************************** +BOOL clear_windows() { + BOOL bResult = FALSE; + + if (drawmapofdoom) { + EndMapOfDoomView(); + bResult = TRUE; + } + if (helpflag) { + helpflag = FALSE; + bResult = TRUE; + } + if (qtextflag) { + qtextflag = FALSE; + stream_stop(); + #if CHEATS + if ((currlevel == 0) && (davecheat)) { + tstQMsgFlag = FALSE; + tstQMsgIndexFlag = TRUE; + } + #endif + bResult = TRUE; + } else + if (stextflag) { + STextESC(); + bResult = TRUE; + } + if (msgflag) { + msgdelay = 0; + bResult = TRUE; + } + if (talkflag) { + TalkEnd(); + bResult = TRUE; + } + if (dropGoldFlag) { + DropGoldType(VK_ESCAPE); + bResult = TRUE; + } + if (spselflag) { + spselflag = FALSE; + bResult = TRUE; + } + + return bResult; +} + + +//****************************************************************** +//****************************************************************** +static void wm_keydown(WPARAM wKey) { + // allow use of menu even when character is dead + if (gmenu_key(wKey)) + return; + + // allow user to finish current string even in timeout mode + if (Talk_wm_keydown(wKey)) + return; + + // don't allow dead player to do anything except turn on gamemenu + if (deathflag) { + // no input while in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) return; + if (wKey == VK_F9) SendTaunt(0); + if (wKey == VK_F10) SendTaunt(1); + if (wKey == VK_F11) SendTaunt(2); + if (wKey == VK_F12) SendTaunt(3); + if (wKey == VK_RETURN) TalkStart(); + if (wKey != VK_ESCAPE) return; + } + + if (wKey == VK_ESCAPE) { + if (! clear_windows()) { + TrackInit(FALSE); + gamemenu_on(); + } + #if CHEATS + if ((currlevel == 0) && (davecheat) && + ((tstQMsgFlag) || (tstQMsgIndexFlag))) { + tstQMsgFlag = FALSE; + tstQMsgIndexFlag = FALSE; + sprintf(tempstr, "STOP QUEST TEXT MODE"); + NetSendString((1 << myplr), tempstr); + return; + } + #endif + return; + } + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) + return; + + // Don't accept input when in drop gold mode + if (dropGoldFlag) + return; + + // in pause mode the only thing we can do is unpause + if (wKey == VK_PAUSE) { + TogglePause(); + return; + } + if (PauseMode == 2) return; + + if (wKey == VK_RETURN) { + if (stextflag) STextEnter(); + else if (questlog) QuestlogEnter(); + #if CHEATS + else if ((currlevel == 0) && (davecheat)) { + if (tstQMsgIndexFlag) { + tstQMsgIndexFlag = FALSE; + tstQMsgFlag = TRUE; + tstQMsgSpd = 5; + DaveQuestText(); + sprintf(tempstr, "Message Speed = %i", tstQMsgSpd); + NetSendString((1 << myplr), tempstr); + } else if (tstQMsgFlag) { + sprintf(tempstr, "[ MESSAGE = %i ]", tstQMsgIndex); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "[ MESSAGE SPEED = %i ]", tstQMsgSpd); + NetSendString((1 << myplr), tempstr); + } + } + #endif + else TalkStart(); + return; + } + + if (wKey == VK_F1) { + if (helpflag) { + helpflag = FALSE; + } + else if (stextflag != STORE_NONE) { + ClearPanel(); + AddPanelString("No help available", TEXT_CENTER); + AddPanelString("while in stores", TEXT_CENTER); + TrackInit(FALSE); + } + else { + invflag = FALSE; + chrflag = FALSE; + sbookflag = FALSE; + spselflag = FALSE; + if ((qtextflag) && (leveltype == 0)) { + qtextflag = FALSE; + stream_stop(); + } + questlog = FALSE; + automapflag = FALSE; + msgdelay = 0; + gamemenu_off(); + StartHelp(); + EndMapOfDoomView(); + } + return; + } + + #if CHEATS + if (wKey == VK_F2) { + void PrintDaveCheck2(); + PrintDaveCheck2(); + } + +/* if (wKey == VK_F3) { + extern BOOL syncdebug; + syncdebug = !syncdebug; + if (syncdebug) + strcpy(tempstr, "Item drop debug on"); + else + strcpy(tempstr, "Item drop debug off"); + NetSendString((1 << myplr), tempstr); + }*/ + if (wKey == VK_F3) { + if (cursitem != -1) { + sprintf(tempstr, "IDX = %i : Seed = %i : CF = %i", item[cursitem].IDidx, item[cursitem]._iSeed, item[cursitem]._iCreateInfo); + NetSendString((1 << myplr), tempstr); + } + sprintf(tempstr, "Numitems : %i", numitems); + NetSendString((1 << myplr), tempstr); + } + + if (wKey == VK_F4) { + void PrintQuestDebug(); + PrintQuestDebug(); + return; + } + #endif + +/* #if CHEATS + if (wKey == VK_F4) { + if (cheatflag) toggle_frame_counter(); + return; + } + #endif*/ + + if (wKey == VK_F5) { + if (spselflag) SetSpellHK(0); + else GetSpellHK(0); + return; + } + if (wKey == VK_F6) { + if (spselflag) SetSpellHK(1); + else GetSpellHK(1); + return; + } + if (wKey == VK_F7) { + if (spselflag) SetSpellHK(2); + else GetSpellHK(2); + return; + } + if (wKey == VK_F8) { + if (spselflag) SetSpellHK(3); + else GetSpellHK(3); + return; + } + + if (wKey == VK_F9) { + SendTaunt(0); + return; + } + if (wKey == VK_F10) { + SendTaunt(1); + return; + } + if (wKey == VK_F11) { + SendTaunt(2); + return; + } + if (wKey == VK_F12) { + SendTaunt(3); + return; + } + + if (wKey == VK_UP) { + if (stextflag) STextUp(); + else if (questlog) QuestlogUp(); + else if (helpflag) HelpScrollUp(); + else if (automapflag) AutomapUp(); + return; + } + + if (wKey == VK_DOWN) { + if (stextflag) STextDown(); + else if (questlog) QuestlogDown(); + else if (helpflag) HelpScrollDown(); + else if (automapflag) AutomapDown(); + return; + } + + if (wKey == VK_PRIOR) { + if (stextflag) STextPgUp(); + return; + } + + if (wKey == VK_NEXT) { + if (stextflag) STextPgDown(); + return; + } + + if (wKey == VK_LEFT) { + if (automapflag && !talkflag) AutomapLeft(); + return; + } + if (wKey == VK_RIGHT) { + if (automapflag && !talkflag) AutomapRight(); + return; + } + + if (wKey == VK_TAB) { + void DoAutoMap(); + DoAutoMap(); + return; + } + +/* if (wKey == VK_CAPITAL) { + FriendlyMode = !FriendlyMode; + drawbtnflag = TRUE; + return; + }*/ + + if (wKey == VK_SPACE) { + if ((!chrflag) && (invflag) && (MouseX < 480) && (MouseY < 352)) SetCursorPos(MouseX+160,MouseY); + if ((!invflag) && (chrflag) && (MouseX > 160) && (MouseY < 352)) SetCursorPos(MouseX-160,MouseY); + helpflag = FALSE; + invflag = FALSE; + chrflag = FALSE; + sbookflag = FALSE; + spselflag = FALSE; + if ((qtextflag) && (leveltype == 0)) { + qtextflag = FALSE; + stream_stop(); + } + questlog = FALSE; + automapflag = FALSE; + msgdelay = 0; + gamemenu_off(); + EndMapOfDoomView(); +//Never clear the cursor, else we lose a scroll or a staff charge +//for a spell we've cast. +// if ((curs != GLOVE_CURS) && (curs < ICSTART)) NewCursor(GLOVE_CURS); + return; + } +} + + +//****************************************************************** +//****************************************************************** +static void wm_char(WPARAM wKey) { + #ifdef _DEBUG + BOOL is_pat_debug_cmd(WPARAM wKey); + if (is_pat_debug_cmd(wKey)) + return; + #endif + + // don't allow input while the menu is active + if (gmenu_is_on()) + return; + + if (Talk_wm_char(wKey)) + return; + + // don't accept input in timeout mode + if (sgnTimeoutCurs != NO_CURSOR) + return; + + // dead players can't perform input + if (deathflag) + return; + + // in pause mode the only thing we can do is unpause + if ((TCHAR) wKey == 'p' || (TCHAR) wKey == 'P') { + TogglePause(); + return; + } + if (PauseMode == 2) return; + + if (drawmapofdoom) { + EndMapOfDoomView(); + return; + } + + if (dropGoldFlag) { + DropGoldType((char) wKey); + return; + } + + switch(wKey) { + case 'g': + case 'G': + GammaDown(); + return; + + case 'f': + case 'F': + GammaUp(); + return; + + case 'i': + case 'I': + if (stextflag != STORE_NONE) return; + sbookflag = FALSE; + invflag = !invflag; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + if (invflag && !chrflag) { + if (MouseX > 160 && MouseY < 352) SetCursorPos(MouseX-160,MouseY); + } + else { + if (MouseX < 480 && MouseY < 352) SetCursorPos(MouseX+160, MouseY); + } + return; + + case 'c': + case 'C': + if (stextflag != STORE_NONE) return; + questlog = FALSE; + chrflag = !chrflag; + if (chrflag && !invflag) { + if (MouseX < 480 && MouseY < 352) SetCursorPos(MouseX+160,MouseY); + } + else { + if (MouseX > 160 && MouseY < 352) SetCursorPos(MouseX-160, MouseY); + } + return; + + #ifndef NDEBUG + case 'r': + case 'R': + sprintf(tempstr, "seed = %i", glSeedTbl[currlevel]); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "Mid1 = %i : Mid2 = %i : Mid3 = %i", + glMid1Seed[currlevel], glMid2Seed[currlevel], glMid3Seed[currlevel]); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "End = %i", glEndSeed[currlevel]); + NetSendString((1 << myplr), tempstr); + return; + #endif + + #if CHEATS + case 'A': + if (cheatflag) { + sprintf(tempstr, "Mid: %i", dMonster[cursmx][cursmy] - 1); + NetSendString((1 << myplr), tempstr); + if (dMonster[cursmx][cursmy] > 0) { + monster[(dMonster[cursmx][cursmy] - 1)]._mFlags |= MFLAG_MKILLER; + void M_Enemy(int); + M_Enemy((dMonster[cursmx][cursmy] - 1)); + } + } + return; + case 'a': + if (cheatflag) { + plr[myplr]._pSplLvl[(plr[myplr]._pSpell)]++; + spelldata[SPL_TELE].sTownSpell = TRUE; + } + return; + #endif + + #if CHEATS + case ')': + case '0': + if (cheatflag) { + if (gv1 > 2) gv1 = 0; + if (gv1 == 0) { + plr[myplr]._pIFlags &= ~IAF_FIREARROW; + plr[myplr]._pIFlags &= ~IAF_LARROW; + } + if (gv1 == 1) plr[myplr]._pIFlags |= IAF_FIREARROW; + if (gv1 == 2) plr[myplr]._pIFlags |= IAF_LARROW; + gv1++; + } + return; + #endif + + #if CHEATS + case 'l': + case 'L': + if (cheatflag) ToggleLight(); + return; + #endif + + #if CHEATS + case 't': + case 'T': + if (cheatflag) { + sprintf(tempstr, "PX = %i PY = %i", plr[myplr]._px, plr[myplr]._py); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "CX = %i CY = %i DP = %i", cursmx, cursmy, dungeon[cursmx][cursmy]); + NetSendString((1 << myplr), tempstr); + } + return; + #endif + + #ifndef NDEBUG + case 'D': + void BlipDebug(BOOL); + BlipDebug(TRUE); + return; + case 'd': + BlipDebug(FALSE); + return; + #endif + + #if CHEATS + case 'e': + if (davedebug) { + sprintf(tempstr, "EFlag = %i", plr[myplr]._peflag); + NetSendString((1 << myplr), tempstr); + } + return; + #endif + + #ifndef NDEBUG + case 'm': + void DaveDebugMonst(); + DaveDebugMonst(); + return; + case 'M': + void DaveDebugMonst2(); + DaveDebugMonst2(); + return; + #endif + + #if CHEATS + case '|': + if ((currlevel == 0) && (davecheat)) DaveGold(); + return; + #endif + + #if CHEATS + case '~': + if ((currlevel == 0) && (davecheat)) DaveNewPremium(); + return; + #endif + + #if CHEATS + case '[': + if ((currlevel == 0) && (davecheat)) DaveCleanUp(); + return; + #endif + + #if CHEATS + case ']': + if ((currlevel == 0) && (davecheat)) DaveSpells(); + return; + #endif + + #if CHEATS + case ':': + if ((currlevel == 0) && (davecheat)) DaveSpells2(); + return; + #endif + + #if CHEATS + case '.': + void DaveDungDebug(); + DaveDungDebug(); + return; + #endif + + #if CHEATS + case '?': + if ((currlevel == 0) && (davecheat)) { + tstQMsgFlag = FALSE; + tstQMsgIndexFlag = TRUE; + sprintf(tempstr, "START QUEST TEXT MODE"); + NetSendString((1 << myplr), tempstr); + sprintf(tempstr, "Message = %i", tstQMsgIndex); + NetSendString((1 << myplr), tempstr); + } + return; + #endif + + case 'q': + case 'Q': + if (stextflag != STORE_NONE) return; + chrflag = FALSE; + if (!questlog) StartQuestlog(); + else questlog = FALSE; + return; + + case 'z': + case 'Z': + svgamode = !svgamode; + return; + + case 's': + case 'S': + if (stextflag != STORE_NONE) return; + invflag = FALSE; + if (!spselflag) SetupSpellSel(); + else spselflag = FALSE; + TrackInit(FALSE); + return; + + case 'b': + case 'B': + if (stextflag != STORE_NONE) return; + invflag = FALSE; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + sbookflag = !sbookflag; + return; + + case '+': + case '=': + if (automapflag) AutomapZoomIn(); + #if CHEATS + else if ((currlevel == 0) && (davecheat)) { + if (tstQMsgIndexFlag) { + tstQMsgIndex++; + if (tstQMsgIndex > (int)(gdwAllTextEntries-1)) tstQMsgIndex = 0; + sprintf(tempstr, "Message = %i", tstQMsgIndex); + NetSendString((1 << myplr), tempstr); + } else if (tstQMsgFlag) { + tstQMsgSpd++; + if (tstQMsgSpd > 9) tstQMsgSpd = 9; + qtextSpd = qtextDelaySpd[tstQMsgSpd-1]; + qtextflag = FALSE; + stream_stop(); + DaveQuestText(); + sprintf(tempstr, "Message Speed = %i", tstQMsgSpd); + NetSendString((1 << myplr), tempstr); + } + } + #endif + return; + + case '_': + case '-': + if (automapflag) AutomapZoomOut(); + #if CHEATS + else if ((currlevel == 0) && (davecheat)) { + if (tstQMsgIndexFlag) { + tstQMsgIndex--; + if (tstQMsgIndex < 0) tstQMsgIndex = (int)(gdwAllTextEntries-1); + sprintf(tempstr, "Message = %i", tstQMsgIndex); + NetSendString((1 << myplr), tempstr); + } else if (tstQMsgFlag){ + tstQMsgSpd--; + if (tstQMsgSpd < 1) tstQMsgSpd = 1; + qtextSpd = qtextDelaySpd[tstQMsgSpd-1]; + qtextflag = FALSE; + stream_stop(); + DaveQuestText(); + sprintf(tempstr, "Message Speed = %i", tstQMsgSpd); + NetSendString((1 << myplr), tempstr); + } + } + #endif + return; + + case 'v': + extern char gszPrintVersion[]; + { + char *pszaDif[] = {"Normal", "Nightmare", "Hell"}; + char tmpbuf[120]; + sprintf(tmpbuf, "%s, mode = %s", gszPrintVersion, + pszaDif[gnDifficulty]); + NetSendString((1 << myplr), tmpbuf); + } +// NetSendString((1 << myplr), gszPrintVersion); + break; + + case 'V': + extern char gszVersionNumber[]; + NetSendString((1 << myplr), gszVersionNumber); + return; + + case '!': + case '1': + if ((plr[myplr].SpdList[0]._itype != -1) && + (plr[myplr].SpdList[0]._itype != IT_GOLD)) UseInvItem(myplr, 47); + return; + + case '@': + case '2': + if ((plr[myplr].SpdList[1]._itype != -1) && + (plr[myplr].SpdList[1]._itype != IT_GOLD)) UseInvItem(myplr, 48); + return; + + case '#': + case '3': + if ((plr[myplr].SpdList[2]._itype != -1) && + (plr[myplr].SpdList[2]._itype != IT_GOLD)) UseInvItem(myplr, 49); + return; + + case '$': + case '4': + if ((plr[myplr].SpdList[3]._itype != -1) && + (plr[myplr].SpdList[3]._itype != IT_GOLD)) UseInvItem(myplr, 50); + return; + + case '%': + case '5': + if ((plr[myplr].SpdList[4]._itype != -1) && + (plr[myplr].SpdList[4]._itype != IT_GOLD)) UseInvItem(myplr, 51); + return; + + case '^': + case '6': + if ((plr[myplr].SpdList[5]._itype != -1) && + (plr[myplr].SpdList[5]._itype != IT_GOLD)) UseInvItem(myplr, 52); + return; + + case '&': + case '7': + if ((plr[myplr].SpdList[6]._itype != -1) && + (plr[myplr].SpdList[6]._itype != IT_GOLD)) UseInvItem(myplr, 53); + return; + + case '*': + case '8': + #if CHEATS + if (cheatflag || davecheat) { + NetSendCmd(TRUE,CMD_CHEAT_EXPERIENCE); + return; + } + #endif + if ((plr[myplr].SpdList[7]._itype != -1) && + (plr[myplr].SpdList[7]._itype != IT_GOLD)) UseInvItem(myplr, 54); + return; +/* + // testing diablo death + case 'k': +#define MT_DIABLO 110 + for (int i = 0; i < nummonsters; i++) { + int mi = monstactive[i]; + if (monster[mi].MType->mtype == MT_DIABLO) + M_StartKill(mi, myplr); + } + return; +*/ + } +} + + +//****************************************************************** +//****************************************************************** +LRESULT CALLBACK DisableInputWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { + switch (uMsg) { + // don't let input go to game window proc + case WM_SYSKEYDOWN: + case WM_SYSCOMMAND: + case WM_KEYUP: + case WM_KEYDOWN: + case WM_CHAR: + case WM_MOUSEMOVE: + return 0; + + case WM_LBUTTONDOWN: + if (sgbMouseDown) return 0; + sgbMouseDown = LMOUSE_DOWN; + SetCapture(hWnd); + return 0; + + case WM_LBUTTONUP: + if (sgbMouseDown != LMOUSE_DOWN) return 0; + sgbMouseDown = 0; + ReleaseCapture(); + return 0; + + case WM_RBUTTONDOWN: + if (sgbMouseDown) return 0; + sgbMouseDown = RMOUSE_DOWN; + SetCapture(hWnd); + return 0; + + case WM_RBUTTONUP: + if (sgbMouseDown != RMOUSE_DOWN) return 0; + sgbMouseDown = 0; + ReleaseCapture(); + return 0; + + case WM_CAPTURECHANGED: + if (hWnd != (HWND) lParam) + sgbMouseDown = 0; + return 0; + } + + return DiabloDefProc(hWnd,uMsg,wParam,lParam); +} + + +//****************************************************************** +//****************************************************************** +static LRESULT CALLBACK GM_Game(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { + switch (uMsg) { + case WM_SYSKEYDOWN: + if (wm_syskeydown(wParam)) return 0; + break; + + case WM_KEYUP: + wm_keyup(wParam); + return 0; + + case WM_KEYDOWN: + wm_keydown(wParam); + return 0; + + case WM_CHAR: + wm_char(wParam); + return 0; + + case WM_MOUSEMOVE: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + wm_mousemove(); + return 0; + + case WM_LBUTTONDOWN: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + + // if the mouse is already down, wait for mouse up + if (sgbMouseDown) return 0; + sgbMouseDown = LMOUSE_DOWN; + SetCapture(hWnd); + + TrackInit(wm_lbuttondown(wParam)); + return 0; + + case WM_LBUTTONUP: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + + // don't accept mouse up unless it went down in our window + if (sgbMouseDown != LMOUSE_DOWN) return 0; + sgbMouseDown = 0; + + wm_lbuttonup(); + TrackInit(FALSE); + ReleaseCapture(); + return 0; + + case WM_RBUTTONDOWN: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + + // if the mouse is already down, wait for mouse up + if (sgbMouseDown) return 0; + sgbMouseDown = RMOUSE_DOWN; + SetCapture(hWnd); + + wm_rbuttondown(); + return 0; + + case WM_RBUTTONUP: + MouseX = LOWORD(lParam); + MouseY = HIWORD(lParam); + + // don't accept mouse up unless it went down in our window + if (sgbMouseDown != RMOUSE_DOWN) return 0; + sgbMouseDown = 0; + ReleaseCapture(); + return 0; + + case WM_CAPTURECHANGED: + if (hWnd != (HWND) lParam) { + sgbMouseDown = 0; + TrackInit(FALSE); + } + break; + + case WM_DIABNEXTLVL: + case WM_DIABPREVLVL: + case WM_DIABSETLVL: + case WM_DIABRTNLVL: + case WM_DIABWARPLVL: + case WM_DIABTOWNWARP: + case WM_DIABTWARPUP: + case WM_DIABRETOWN: + // save character in multiplayer mode + if (gbMaxPlayers > 1) { + void UpdatePlayerFile(); + UpdatePlayerFile(); + } + nthread_perform_keepalive(TRUE); + PaletteFadeOut(FADE_FAST); + sound_stop(); + music_stop(); + TrackInit(FALSE); + sgbMouseDown = FALSE; + ReleaseCapture(); + ShowProgress(uMsg); + force_redraw = FULLDRAW; + DrawAndBlit(); + if (gbRunGame) PaletteFadeIn(FADE_FAST); + nthread_perform_keepalive(FALSE); + gbGameLoopStartup = TRUE; + return 0; + + case WM_SYSCOMMAND: + if (wParam == SC_CLOSE) { + gbRunGame = FALSE; + gbRunGameResult = FALSE; + return 0; + } + break; + } + + return DiabloDefProc(hWnd, uMsg, wParam, lParam); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void LoadLvlGFX() { + app_assert(! pDungeonCels); + switch (leveltype) { + case 0: + pDungeonCels = LoadFileInMemSig("NLevels\\TownData\\Town.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("NLevels\\TownData\\Town.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("NLevels\\TownData\\Town.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\TownData\\TownS.CEL",NULL,'TILE'); + break; + + case 1: +/* pDungeonCels = LoadFileInMemSig("Levels\\L1Data\\L1.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L1Data\\L1.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L1Data\\L1.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L1Data\\L1S.CEL",NULL,'TILE'); + break;*/ + if (currlevel < CRYPTSTART) + { + pDungeonCels = LoadFileInMemSig("Levels\\L1Data\\L1.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L1Data\\L1.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L1Data\\L1.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L1Data\\L1S.CEL",NULL,'TILE'); + } + else + { + pDungeonCels = LoadFileInMemSig("NLevels\\L5Data\\L5.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("NLevels\\L5Data\\L5.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("NLevels\\L5Data\\L5.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("NLevels\\L5Data\\L5S.CEL",NULL,'TILE'); + } + break; + + #if IS_VERSION(RETAIL) || IS_VERSION(BETA) + case 2: + pDungeonCels = LoadFileInMemSig("Levels\\L2Data\\L2.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L2Data\\L2.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L2Data\\L2.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L2Data\\L2S.CEL",NULL,'TILE'); + break; + #endif + + #if IS_VERSION(RETAIL) + case 3: + if (currlevel < HIVESTART) + { + pDungeonCels = LoadFileInMemSig("Levels\\L3Data\\L3.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L3Data\\L3.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L3Data\\L3.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L1Data\\L1S.CEL",NULL,'TILE'); + } + else + { + pDungeonCels = LoadFileInMemSig("NLevels\\L6Data\\L6.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("NLevels\\L6Data\\L6.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("NLevels\\L6Data\\L6.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L1Data\\L1S.CEL",NULL,'TILE'); + } + break; + #endif + + #if IS_VERSION(RETAIL) + case 4: + pDungeonCels = LoadFileInMemSig("Levels\\L4Data\\L4.CEL",NULL,'TILE'); + pMegaTiles = LoadFileInMemSig("Levels\\L4Data\\L4.TIL",NULL,'TILE'); + pMiniTiles = LoadFileInMemSig("Levels\\L4Data\\L4.MIN",NULL,'TILE'); + pSpecialCels = LoadFileInMemSig("Levels\\L2Data\\L2S.CEL",NULL,'TILE'); + break; + #endif + + default: + app_fatal("LoadLvlGFX"); + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void LoadAllGFX() +{ + app_assert(! pSpeedCels); + pSpeedCels = DiabloAllocPtrSig(SPEEDSIZE,'SPED'); +// InitMonsterGFX(); + IntCheck(); +// InitMonsterSND(); + IntCheck(); + InitObjectGFX(); + IntCheck(); + InitMissileGFX(); + IntCheck(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CreateLevel(int lvldir) +{ + switch (leveltype) { + case 0: + CreateTown(lvldir); + InitTownTriggers(); + LoadRndLvlPal(0); + break; + + case 1: + CreateL5Dungeon(glSeedTbl[currlevel], lvldir); + InitL1Triggers(); + Freeupstairs(); + if (currlevel < CRYPTSTART) // JKE load correct pallet + LoadRndLvlPal(1); + else + LoadRndLvlPal(5); + break; + + #if IS_VERSION(RETAIL) || IS_VERSION(BETA) + case 2: + CreateL2Dungeon(glSeedTbl[currlevel], lvldir); + InitL2Triggers(); + Freeupstairs(); + LoadRndLvlPal(2); + break; + #endif + + #if IS_VERSION(RETAIL) + case 3: + CreateL3Dungeon(glSeedTbl[currlevel], lvldir); + InitL3Triggers(); + Freeupstairs(); + if (currlevel < HIVESTART) + LoadRndLvlPal(3); + else + LoadRndLvlPal(6); + break; + #endif + + #if IS_VERSION(RETAIL) + case 4: + CreateL4Dungeon(glSeedTbl[currlevel], lvldir); + InitL4Triggers(); + Freeupstairs(); + LoadRndLvlPal(4); + break; + #endif + + default: + app_fatal("CreateLevel"); + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void LoadGameLevel(BOOL firstflag, int lvldir) +{ + int i,j; + + if (setseed) + glSeedTbl[currlevel] = setseed; + + music_stop(); + SetCursor(GLOVE_CURS); + SetRndSeed(glSeedTbl[currlevel]); + IntCheck(); + + MakeLightTable(); + LoadLvlGFX(); + IntCheck(); + + if (firstflag) { + InitInv(); + InitItemGFX(); + InitQuestText(); + for (i = 0; i < gbMaxPlayers; i++) + InitPlrGFXMem(i); + InitStores(); + InitAutomapOnce(); + InitHelpSys(); + } + + SetRndSeed(glSeedTbl[currlevel]); + if (leveltype == 0) SetupTownStores(); + IntCheck(); + + InitAutomap(); + + if ((leveltype != 0) && (lvldir != LVL_NODIR)) { + InitLighting(); + InitVision(); + } + InitLevelMonsters(); + IntCheck(); + + if (!setlevel) { + CreateLevel(lvldir); + IntCheck(); + + // Open Tiles file + FillSolidBlockTbls(); + + SetRndSeed(glSeedTbl[currlevel]); + + if (leveltype != 0) { + GetLevelMTypes(); + InitThemes(); + LoadAllGFX(); + } else { + InitMissileGFX(); + } + IntCheck(); + + if (lvldir == LVL_RTN) GetReturnLvlPos(); + if (lvldir == LVL_WARP) GetPortalLvlPos(); + IntCheck(); + + // Init Player info + for (i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (currlevel != plr[i].plrlevel) continue; + InitPlayerGFX(i); + if (lvldir != LVL_NODIR) InitPlayer(i, firstflag); + } + + PlayDungMsgs(); + InitMultiView(); + IntCheck(); + + BOOL visited = FALSE; + for (i = 0; i < gbMaxPlayers; i++) + if (plr[i].plractive) visited = visited || plr[i]._pLvlVisited[currlevel]; + + // Resync after level changing bug + // This bug occurs when 2 players change levels one after the other. The first player + // down thinks the other player is one level above, because the change level msg has + // not been processed during loading. The second player knows that they are both + // on the same level, so more players get inited, and randoms desync. + SetRndSeed(glSeedTbl[currlevel]); + + if (leveltype != 0) { + if (!firstflag && (lvldir != LVL_NODIR) && plr[myplr]._pLvlVisited[currlevel] && (gbMaxPlayers == 1)) { + // Init monsters so uniques are loaded + InitMonsters (); + // Init missiles + InitMissiles(); + // Init dead info, not dungeon layout though + InitDead(); + IntCheck (); + // Load where things were + LoadLevel(); + IntCheck (); + } else { + // Save theme room areas + HoldThemeRooms(); + glMid1Seed[currlevel] = GetRndSeed(); // @@@ drb temp + // Init monsters into dungeon +// if (currlevel < HIVESTART) InitMonsters (); // temp hack to test failure JKE + InitMonsters (); + glMid2Seed[currlevel] = GetRndSeed(); // @@@ drb temp + // Init objects +// if (currlevel < CRYPTSTART) InitObjects(); // temp hack to test failure JKE + InitObjects(); + // Init items +// if (currlevel < HIVESTART) InitItems(); // Temp hack to test failure JKE + InitItems(); + // Fill theme rooms + if (currlevel < HIVESTART) CreateThemeRooms(); // Temp hack for failure JKE +// CreateThemeRooms(); + glMid3Seed[currlevel] = GetRndSeed(); // @@@ drb temp + // Init missiles + InitMissiles(); + // Init dead info, not dungeon layout though + InitDead(); + glEndSeed[currlevel] = GetRndSeed(); // @@@ drb temp + // if multiplayer resync level + if (gbMaxPlayers != 1) DeltaLoadLevel(); + IntCheck(); + SavePreLighting(); + } + } else { + // Make everything visible + for (i = 0; i < DMAXX; i++) + for (j = 0; j < DMAXY; j++) + dFlags[i][j] |= BFLAG_VISIBLE; + // Init town people + InitTowners(); + // Init items + InitItems(); + // Init missiles + InitMissiles(); + IntCheck(); + + // Load items + if (!firstflag && (lvldir != LVL_NODIR) && plr[myplr]._pLvlVisited[currlevel] && (gbMaxPlayers == 1)) + LoadLevel(); + if (gbMaxPlayers != 1) DeltaLoadLevel(); + IntCheck (); + } + if (gbMaxPlayers == 1) + ResyncQuests(); + else + ResyncMPQuests(); + + } +#if !IS_VERSION(SHAREWARE) + else { + // Preset levels + app_assert(! pSpeedCels); + pSpeedCels = DiabloAllocPtrSig(SPEEDSIZE,'SPED'); + + LoadSetMap(); + IntCheck(); + + GetLevelMTypes(); + + InitMonsters(); + + //SetDungeonMicros(); + + InitMissileGFX(); + + // Init dead info, not dungeon layout though + InitDead(); + + // Open Tiles file + FillSolidBlockTbls (); + IntCheck(); + + if (lvldir == LVL_WARP) GetPortalLvlPos(); + + // Init Player info + for (i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (currlevel != plr[i].plrlevel) continue; + InitPlayerGFX(i); + if (lvldir != LVL_NODIR) InitPlayer(i, firstflag); + } + + InitMultiView(); + IntCheck(); + + if ((!firstflag) && (lvldir != LVL_NODIR) && (plr[myplr]._pSLvlVisited[setlvlnum])) { + // Load where things were + LoadLevel(); + } else { + // Init items + InitItems(); + SavePreLighting(); + } + // Init missiles + InitMissiles(); + IntCheck(); + } +#endif + + SyncPortals(); + + for (i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (plr[i].plrlevel != currlevel) continue; + if (plr[i]._pLvlChanging && (i != myplr)) continue; + if (plr[i]._pHitPoints > 0) { + if (gbMaxPlayers == 1) + dPlayer[plr[i]._px][plr[i]._py] = i + 1; + else + SyncInitPlrPos(i); + } else + dFlags[plr[i]._px][plr[i]._py] |= BFLAG_DEADPLR; + } + + if (leveltype != 0) { + SetDungeonMicros(); + } + + InitLightMax(); // Set up 4 or 16 level lighting + IntCheck(); + +/* + if ((leveltype != 0) && (lvldir != LVL_NODIR)) { + SavePreLighting(); + } +*/ + IntCheck(); + + if (firstflag) { + // Get Control panel graphics and decompress panel to BtmBuff + // Has to be after init player because of bars/spells/equipment etc. + InitControlPan(); + IntCheck(); + } + + if (leveltype != 0) { + ProcessLightList(); + ProcessVisionList(); + } + if (currlevel >= CRYPTSTART) + { +// OpenCloseAllDoors(); // JKE Stupid!!! + if (currlevel == CORNERSTONE_LEVEL) + CornerstoneRestore(CornerStone.x, CornerStone.y); + if ((quests[Q_NA_KRUL]._qactive == QUEST_DONE)&&(currlevel == NA_KRUL_LEVEL)) + OpenNaKrul(); + + } + + // start appropriate sound track + if (currlevel >= HIVESTART) // fix this later JKE + { + music_start((currlevel > HIVEEND)? 5 : 6); + } + else + music_start(leveltype); + + // finish progress bar + while (! IntCheck()) + NULL; + + #if !IS_VERSION(SHAREWARE) + if ((setlevel) && (setlvlnum == SL_SKELKING) && (quests[Q_SKELKING]._qactive == QUEST_NOTDONE)) + PlaySFX(USFX_SKING1); + #endif +} + + +//****************************************************************** +//****************************************************************** +// this parameter is the maximum number of game loops which can be run +// in a row without redrawing the screen +#define MAX_CONSECUTIVE_LOOPS 3 + + +//****************************************************************** +//****************************************************************** +static void game_logic() { + if (PauseMode == 2) return; + if (PauseMode == 1) PauseMode = 2; + + // pause when menu is active in single player mode + if (gbMaxPlayers == 1 && gmenu_is_on()) { + force_redraw |= VIEWDRAW; + return; + } + + if (! gmenu_is_on() && (sgnTimeoutCurs == NO_CURSOR)) { + CheckCursMove(); + TrackMouse(); + } + + if (gbProcessPlayers) + ProcessPlayers(); + if (leveltype) { + ProcessMonsters(); + ProcessObjects(); + ProcessMissiles(); + ProcessItems(); + ProcessLightList(); + ProcessVisionList(); + } + else { + ProcessTowners(); + ProcessItems(); + ProcessMissiles(); + } + + #if CHEATS + if ((cheatflag) && ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0)) + CheckForScroll(); + #endif + + sound_update(); + plrmsg_update(); + CheckTriggers(); + CheckQuests(); + force_redraw |= VIEWDRAW; + + void TimedUpdatePlayerFile(BOOL bForce); + TimedUpdatePlayerFile(FALSE); +} + + +//****************************************************************** +//****************************************************************** +static void timeout_cursor(BOOL bTimeout) { + if (bTimeout) { + // if we weren't in a timeout state, set timeout + if (sgnTimeoutCurs == NO_CURSOR && ! sgbMouseDown) { + sgnTimeoutCurs = curs; + + NetStartTimeout(); + + // display timeout error + ClearPanel(); + AddPanelString("-- Network timeout --", TEXT_CENTER); + AddPanelString("-- Waiting for players --", TEXT_CENTER); + + // fix up the cursor + NewCursor(TIMEOUT_CURSOR); + + // we probably made a mess of the screen + force_redraw = FULLDRAW; + } + + FullBlit(TRUE); + } + else if (sgnTimeoutCurs != NO_CURSOR) { + // ending timeout + SetCursor(sgnTimeoutCurs); + sgnTimeoutCurs = NO_CURSOR; + ClearPanel(); + force_redraw = FULLDRAW; + } +} + + +//****************************************************************** +//****************************************************************** +static void game_loop(BOOL bStartup) { + int nMaxLoops = bStartup ? GAME_FRAMES_PER_SECOND * 3 : MAX_CONSECUTIVE_LOOPS; + while (nMaxLoops--) { + // wait for synchronous network message + if (! NetEndSendCycle()) { + timeout_cursor(TRUE); + break; + } + timeout_cursor(FALSE); + + // run logic at GAME_FRAMES_PER_SECOND + game_logic(); + + // if the game mode changed, then don't continue loop + if (! gbRunGame) + break; + + // don't run multiple loops in single player mode + if (gbMaxPlayers == 1) + break; + + // have we been in the loop too long? + if (! nthread_run_gameloop(TRUE)) + break; + + #if CHEATS + static DWORD sdwSkips = 0; + sdwSkips++; + HDC hDC; + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr == DD_OK) { + char szBuf[16]; + wsprintf(szBuf,"%u",sdwSkips); + TextOut(hDC,5,370,szBuf,strlen(szBuf)); + lpDDSPrimary->ReleaseDC(hDC); + } + #endif + } +} + + +//****************************************************************** +//****************************************************************** +static void DoTimedEvents() { + static DWORD sdwCurrTime = 0; + DWORD dwCurrTime = GetTickCount(); + if (dwCurrTime - sdwCurrTime < 1000/GAME_FRAMES_PER_SECOND) + return; + sdwCurrTime = dwCurrTime; + + if (leveltype == 4) + BloodCycle(); + else if (currlevel >= CRYPTSTART) + TwinCycleCrypt(); + else if (currlevel >= HIVESTART) + TwinCycleNest(); + else if (leveltype == 3 && fullscreen) + LavaCycle(); +} + + +//****************************************************************** +//****************************************************************** +/* pjw.patch1.start +static void try_game_loop(BOOL bStartup) { + DoTimedEvents(); + NetReceivePackets(); + + if (! nthread_run_gameloop(FALSE)) + return; + + // run game loop + game_loop(bStartup); + + // redraw the screen if necessary + DrawAndBlit(); +} +pjw.patch1.end */ + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +#define RAND_MASK (32*1024-1) +#define PLR_BYTES (sizeof(PlayerStruct) * MAX_PLRS) +static PlayerStruct * alloc_plr_chunk(PlayerStruct * p1) { + + // make sure p2 ends up in different locations + LPVOID pTemp = malloc(rand() & RAND_MASK); + PlayerStruct * p2 = (PlayerStruct *) malloc(PLR_BYTES); + if (pTemp) free(pTemp); + + if (! p2) return p1; + if (p1) { + CopyMemory(p2,p1,PLR_BYTES); + free(p1); + } + return p2; +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +static void alloc_plr() { + if (NULL == (plr = alloc_plr_chunk(NULL))) + app_fatal("Unable to initialize memory"); + ZeroMemory(plr,PLR_BYTES); +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +#pragma intrinsic(_rotl) +static DWORD calc_checksum(LPVOID lpMem,DWORD dwBytes,DWORD dwSum) { + LPDWORD lpDW = (LPDWORD) lpMem; + dwBytes /= sizeof(DWORD); + while (dwBytes--) { + dwSum ^= *lpDW++; + dwSum = _rotl(dwSum,3); + } + return dwSum; +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +static void CRASH() { +#if 0 // !!! @@@ !!! fix in final + static BYTE sgbCheating = FALSE; + if (! sgbCheating) { + sgbCheating = TRUE; + app_warning("Cheating detected"); + void myDebugBreak(); + myDebugBreak(); + } +#else + LPDWORD pFrame = (LPDWORD) plr[myplr]._pAnimData; + pFrame[plr[myplr]._pAnimFrame + 1] ^= 0x3fffffff; +#endif + FullBlit(TRUE); +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +typedef void (* TCrypt)(LPDWORD,DWORD,DWORD); +static void encrypt_aux(TCrypt fnCrypt) { + for (int i = 0; i < MAX_PLRS; i++) { + // SLOW encrypt the important part of the character + fnCrypt((LPDWORD)&plr[i],offsetof(PlayerStruct,_pGFXLoad),HASH_ENCRYPTKEY); + + // FAST encrypt the inventory -- takes too long otherwise + LPDWORD lpInv = (LPDWORD) &plr[i].InvBody; + for (int j = sizeof(ItemStruct) * NUM_INVLOC / sizeof(DWORD); j--; ) + *lpInv++ ^= 0xf0638142; + + // pjw.patch2.start -- commented out -- still taking too long + #if 0 + lpInv = (LPDWORD) &plr[i].InvList; + for (j = sizeof(ItemStruct) * MAXINV / sizeof(DWORD); j--; ) + *lpInv++ ^= 0x23484862; + #endif + // pjw.patch2.end + } +} +// pjw.patch1.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start +static void plr_encrypt(BOOL bEncrypt) { + static BOOL sbEncrypt = FALSE; + static BOOL sbCrash = FALSE; + static DWORD sdwCheckSum = 0; + static DWORD sdwCheckStart = 0; + if (sbEncrypt == bEncrypt) return; + sbEncrypt = bEncrypt; + +// pjw.patch2.start -- added for debugging only! +#if 0 + static DWORD sgdwEncryptCount = 0; + sgdwEncryptCount++; + static DWORD sgdwLastTime = 0; + if (GetTickCount() - sgdwLastTime >= 1000) { + sgdwLastTime = GetTickCount(); + do { + char szBuf[32]; + HDC hDC; + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr != DD_OK) break; + COLORREF oldTextColor = SetTextColor(hDC,RGB(0xff,0xff,0)); + COLORREF oldBkColor = SetBkColor(hDC,RGB(0,0,0)); + int oldBkMode = SetBkMode(hDC,OPAQUE); + sprintf(szBuf,"%u ",sgdwEncryptCount); + sgdwEncryptCount = 0; + TextOut(hDC,5,385,szBuf,strlen(szBuf)); + SetTextColor(hDC,oldTextColor); + SetBkColor(hDC,oldBkColor); + SetBkMode(hDC,oldBkMode); + lpDDSPrimary->ReleaseDC(hDC); + } while (0); + } +#endif +// pjw.patch2.end + + if (sbCrash) { + CRASH(); + } + else if (bEncrypt) { + sdwCheckStart = rand(); + sdwCheckSum = calc_checksum(plr,PLR_BYTES,sdwCheckStart); + encrypt_aux(Encrypt); + } + else { + encrypt_aux(Decrypt); + if (sdwCheckSum != calc_checksum(plr,PLR_BYTES,sdwCheckStart)) { + CRASH(); + sbCrash = 1; + } + } + + if ((rand() & 0x0f) == 0x0f) + plr = alloc_plr_chunk(plr); +} +// pjw.patch1.end diff --git a/src/DIABLOUI.H b/src/DIABLOUI.H new file mode 100644 index 0000000..eb7c2f4 --- /dev/null +++ b/src/DIABLOUI.H @@ -0,0 +1,265 @@ +//*************************************************************************** +// DiabloUI.h +// created 9.13.96 +//*************************************************************************** + + +//*************************************************************************** +extern "C" void APIENTRY UiInitialize(void); +extern "C" void APIENTRY UiSetSpawned(BOOL bSpawned); +extern "C" void APIENTRY UiDestroy(); +extern "C" void APIENTRY UiAppActivate(BOOL activating); + + +//*************************************************************************** +extern "C" BOOL CALLBACK UiCreateGameCallback (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); + +extern "C" BOOL CALLBACK UiArtCallback (DWORD providerid, + DWORD artid, + LPPALETTEENTRY pe, + LPBYTE buffer, + DWORD buffersize, + int *width, + int *height, + int *bitdepth); + +extern "C" BOOL CALLBACK UiSoundCallback(DWORD providerid, DWORD soundid, DWORD flags); + +extern "C" BOOL CALLBACK UiDrawDescCallback (DWORD providerid, + DWORD itemtype, + LPCSTR itemname, + LPCSTR itemdescription, + DWORD itemflags, + DWORD drawflags, + DWORD time, + LPDRAWITEMSTRUCT lpdis); + +extern "C" BOOL CALLBACK UiMessageBoxCallback(HWND hWnd, + LPCTSTR lpText, + LPCTSTR lpCaption, + UINT uType); + +extern "C" BOOL CALLBACK UiAuthCallback(DWORD dwItemType, LPCSTR szName, LPCSTR szDesc, DWORD dwUserFlags, LPCSTR szItem, LPSTR szErrorBuf, DWORD dwErrorBufSize); +extern "C" BOOL CALLBACK UiGetDataCallback(DWORD providerid, DWORD dataid, LPVOID buffer, DWORD buffersize, DWORD *bytesused); + +extern "C" BOOL CALLBACK UiCategoryCallback( + BOOL userinitiated, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD * categorybits, + DWORD * categorymask); + +//*************************************************************************** +enum _ui_classes { + UI_WARRIOR = 0, + UI_ROGUE, + UI_SORCERER, + UI_MONK, + UI_BARD, + UI_BARBARIAN, + UI_NUM_CLASSES +}; + +//*************************************************************************** +extern "C" BOOL APIENTRY UiTitleDialog (UINT timeoutseconds); +extern "C" BOOL APIENTRY UiBetaDisclaimer (UINT timeoutseconds); +extern "C" BOOL APIENTRY UiCreditsDialog (UINT pixelspersec); +extern "C" BOOL APIENTRY UiSupportDialog (UINT pixelspersec); + +//*************************************************************************** +enum _copyprot_results { + COPYPROT_OK = 1, + COPYPROT_CANCEL +}; +extern "C" BOOL APIENTRY UiCopyProtError (DWORD *result); + +//*************************************************************************** +#define DEFAULT_ATTRACT_TIMEOUT 30 +typedef void (CALLBACK *PLAYSND)(LPCSTR); +enum _mainmenu_selections { + MAINMENU_SINGLE_PLAYER = 1, + MAINMENU_MULTIPLAYER, + MAINMENU_REPLAY_INTRO, + MAINMENU_SUPPORT, + MAINMENU_SHOW_CREDITS, + MAINMENU_EXIT_DIABLO, + MAINMENU_ATTRACT_MODE +}; +extern "C" BOOL APIENTRY UiMainMenuDialog(LPCTSTR registration, + DWORD * selection, + bool allowMultiPlayer, + PLAYSND sndfcn = NULL, + UINT attracttimeoutseconds = DEFAULT_ATTRACT_TIMEOUT); + +//*************************************************************************** +#define MAX_GAME_LEN 32 +#define MAX_PASSWORD_LEN 32 + +enum _difficulty { + DIFF_NORMAL, + DIFF_NIGHTMARE, + DIFF_HELL, + NUM_DIFFICULTIES +}; + + +typedef struct _gamedata TGAMEDATA; +struct _gamedata { + DWORD dwSeed; + BYTE bDiff; // Use enum's from _difficulty settings +}; + + +//*************************************************************************** +//*************************************************************************** +// all the functions and structures for selecting/creating/deleting heros +//*************************************************************************** +//*************************************************************************** +#define MAX_NAME_LEN 16 // including terminting char +#define MAX_CLASS_LEN 16 // including terminting char + +typedef struct _uiheroinfo TUIHEROINFO; +typedef TUIHEROINFO *TPUIHEROINFO; + +typedef struct _uidefaultstats { + WORD strength; + WORD magic; + WORD dexterity; + WORD vitality; +} TUIDEFSTATS, *TPUIDEFSTATS; + +struct _uiheroinfo { + TPUIHEROINFO next; + char name[MAX_NAME_LEN]; // eg "Frasier" + + WORD level; + BYTE heroclass; // UI_WARRIOR, etc. + BYTE herorank; // # of times hero has killed Diablo (range = 0..NUM_DIFFICULTIES) + + WORD strength; + WORD magic; + WORD dexterity; + WORD vitality; + + DWORD gold; + BOOL hassaved; + BOOL spawned; +}; + +//*************************************************************************** + +#define UI_DESC_MAXLENGTH 128 + +// The following routines output a null terminated string to the provided preallocated +// pointers. The maximum length of the string is defined by the above constant. +extern "C" BOOL APIENTRY UiCreatePlayerDescription(TPUIHEROINFO pHeroInfo, DWORD dwProgramId, LPSTR pPlayerDesc); + +// Call this routine to generate a query string used by Battle.net to sort games in the +// JoinGame list. Returns the number of bytes written out to szQuery. +extern "C" int APIENTRY UiCreateGameCriteria(TPUIHEROINFO pHeroInfo, LPSTR pszQuery); + +//*************************************************************************** + +typedef BOOL (CALLBACK *ENUMHEROPROC)(TPUIHEROINFO); +typedef BOOL (CALLBACK *ENUMHEROS)(ENUMHEROPROC); +typedef BOOL (CALLBACK *CREATEHERO)(TPUIHEROINFO); +typedef BOOL (CALLBACK *DELETEHERO)(TPUIHEROINFO); +typedef BOOL (CALLBACK *GETDEFHERO)(int, TPUIDEFSTATS); + +enum _selhero_selections { + SELHERO_NEW_DUNGEON = 1, + SELHERO_CONTINUE, + SELHERO_CONNECT, + SELHERO_PREVIOUS +}; +extern "C" BOOL APIENTRY UiSelHeroSingDialog( + ENUMHEROS enumfcn, + CREATEHERO createfcn, + DELETEHERO deletefcn, + GETDEFHERO getstatsfcn, + DWORD *selection, + LPSTR heroname, + int *difficulty, + bool allowBard, + bool allowBarbarian + ); +extern "C" BOOL APIENTRY UiSelHeroMultDialog( + ENUMHEROS enumfcn, + CREATEHERO createfcn, + DELETEHERO deletefcn, + GETDEFHERO getstatsfcn, + DWORD *selection, + LPSTR heroname, + bool allowBard, + bool allowBarbarian + ); + +// if the default starting statistics for a character class change +// then Diablo.exe will have to provide this function +extern "C" BOOL CALLBACK UiGetDefaultStats(int heroclass, TPUIDEFSTATS defaultstats); + +//*************************************************************************** +extern "C" BOOL APIENTRY UiLogonDialog(HWND parent, + DWORD *selection, + LPSTR logonname, + UINT maxnamelen, + LPSTR logonpassword, + UINT maxpasswordlen); + +//*************************************************************************** +typedef int (CALLBACK *PROGRESSFCN)(void); +extern "C" BOOL APIENTRY UiProgressDialog(HWND parent, + LPCSTR progresstext, + BOOL abortable, + PROGRESSFCN progressfcn, + DWORD callspersec); + +//*************************************************************************** +extern "C" void APIENTRY UiOnPaint (LPPARAMS params); +extern "C" BOOL APIENTRY UiSetBackgroundBitmap (HWND window, + LPPALETTEENTRY palette, + LPBYTE bitmapbits, + int width, + int height); + +//*************************************************************************** +//*************************************************************************** +extern "C" BOOL APIENTRY UiSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY UiSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); + + +//*************************************************************************** +//*************************************************************************** + #define DEVNAME_LEN SNETSPI_MAXSTRINGLENGTH + #define DEVDESC_LEN SNETSPI_MAXSTRINGLENGTH + #define MAX_DIAL_LEN 32 + enum _dialmodes { + MODE_ANSWER = (IDCANCEL + 1), + MODE_DIALOLD, + MODE_DIALNEW + }; + typedef struct _modeminfo TMODEM; + typedef TMODEM *TPMODEM; + struct _modeminfo { + TPMODEM next; + DWORD deviceid; + TCHAR devicename[DEVNAME_LEN]; + TCHAR devicedesc[DEVDESC_LEN]; + }; diff --git a/src/DIABLOUI.LIB b/src/DIABLOUI.LIB new file mode 100644 index 0000000..8c108d7 Binary files /dev/null and b/src/DIABLOUI.LIB differ diff --git a/src/DIABLOUI.LSV b/src/DIABLOUI.LSV new file mode 100644 index 0000000..2c45a68 Binary files /dev/null and b/src/DIABLOUI.LSV differ diff --git a/src/DIABLO~1.BCE b/src/DIABLO~1.BCE new file mode 100644 index 0000000..2e47a50 Binary files /dev/null and b/src/DIABLO~1.BCE differ diff --git a/src/DOOM.CPP b/src/DOOM.CPP new file mode 100644 index 0000000..6d88bf4 --- /dev/null +++ b/src/DOOM.CPP @@ -0,0 +1,162 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Map of Doom file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DOOM.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "doom.h" +#include "engine.h" +#include "control.h" +#include "gendung.h" + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +#define DOOM_NUMFRAMES 30 +#define DOOM_ENDFRAME 31 +#define DOOM_TICK 1200 // Every 20*60 (1 min) frames is next doom map cycle +#define DOOM_TOTAL (DOOM_NUMFRAMES*DOOM_TICK)+1 +#define DOOM_ANIMSPD 5 + +bool drawmapofdoom = false; +static BYTE *pDoomCel = 0; +int doomtime = 0; +static int currdoom = 0; +static int animdoomdelay = 0; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitMapOfDoomTime() +{ + if (doomtime > 0) return; + doomtime = 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DoMapOfDoomTime() +{ + if (doomtime < DOOM_TOTAL) { + doomtime++; + if (doomtime == DOOM_TOTAL) { + #if !IS_VERSION(SHAREWARE) + PlayInGameMovie("gendata\\doom.smk"); + #endif + doomtime++; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +int CheckMapOfDoomTime() +{ + if (doomtime == DOOM_TOTAL) return(DOOM_ENDFRAME); + return(doomtime / DOOM_TICK); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void FreeDoomMem() +{ + if (pDoomCel != NULL) + { + DiabloFreePtr(pDoomCel); + pDoomCel = NULL; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static bool GetDoomMem() +{ + FreeDoomMem(); + pDoomCel = DiabloAllocPtrSig((227 + 1) * 1024,'DOOM'); + return (pDoomCel != 0); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static bool LoadDoomFrame() +{ + bool result = false; + +// if (currlevel < HIVESTART) +// { +// if (currdoom == DOOM_ENDFRAME) { +// strcpy(tempstr, "Items\\Map\\MapZDoom.CEL"); +// } +// else if (currdoom < 10) { +// sprintf (tempstr, "Items\\Map\\MapZ000%i.CEL", currdoom); +// } +// else sprintf (tempstr, "Items\\Map\\MapZ00%i.CEL", currdoom); +// LoadFileWithMem(tempstr, pDoomCel); +// } +// else + { + strcpy(tempstr, "Items\\Map\\MapZtown.CEL"); + if (LoadFileWithMem(tempstr, pDoomCel)) { + result = true; + } + } + return result; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitMapOfDoomView() +{ + if (GetDoomMem()) { + if (CheckMapOfDoomTime() == DOOM_ENDFRAME) currdoom = DOOM_ENDFRAME; + else currdoom = 0; + if (LoadDoomFrame()) + drawmapofdoom = true; + else + EndMapOfDoomView(); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void EndMapOfDoomView() +{ + //if (!drawmapofdoom) return; + drawmapofdoom = false; + FreeDoomMem(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawMapOfDoom() +{ + if (!drawmapofdoom) return; + +// if (currdoom != DOOM_ENDFRAME) { +// animdoomdelay++; +// if (animdoomdelay >= DOOM_ANIMSPD) { +// animdoomdelay = 0; +// currdoom++; +// if (currdoom > CheckMapOfDoomTime()) currdoom = 0; +// LoadDoomFrame(); +// } +// } + DrawCel(64, 511, pDoomCel, 1, 640); +} diff --git a/src/DOOM.H b/src/DOOM.H new file mode 100644 index 0000000..9643f05 --- /dev/null +++ b/src/DOOM.H @@ -0,0 +1,26 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/DOOM.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** externs +**-----------------------------------------------------------------------*/ + +extern bool drawmapofdoom; +extern int doomtime; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitMapOfDoomTime(); +void DoMapOfDoomTime(); +void InitMapOfDoomView(); +void EndMapOfDoomView(); +void DrawMapOfDoom(); diff --git a/src/DRLG_L1.CPP b/src/DRLG_L1.CPP new file mode 100644 index 0000000..1d43e05 --- /dev/null +++ b/src/DRLG_L1.CPP @@ -0,0 +1,3564 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Dungeon file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DRLG_L1.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +** CreateL1Dungeon +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "drlg_l1.h" +#include "gendung.h" +#include "engine.h" +#include "trigs.h" +#include "lighting.h" +#include "monster.h" +#include "objects.h" +#include "quests.h" +#include "multi.h" +#include "Items.h" + +// LEVEL 1 + +#define L1NGRATE 10 // cannot be higher than 100 or less than 0 + +#define L1BGRATE 5 +#define L1RFLOOR 20 + +#define L1BWALL1 30 +#define L1BWALL2 15 +#define L1BWALL3 5 + +#define L1STATUE 10 + + +// LEVEL 2 + +#define L2NGRATE 10 // cannot be higher than 100 or less than 0 + +#define L2BGRATE 10 +#define L2RFLOOR 20 + +#define L2BWALL1 30 +#define L2BWALL2 20 +#define L2BWALL3 10 + +#define L2STATUE 10 + + +// LEVEL 3 + +#define L3NGRATE 10 // cannot be higher than 100 or less than 0 + +#define L3BGRATE 15 +#define L3RFLOOR 30 + +#define L3BWALL1 30 +#define L3BWALL2 20 +#define L3BWALL3 15 + +#define L3STATUE 10 + + +// LEVEL 4 + +#define L4NGRATE 10 // cannot be higher than 100 or less than 0 + +#define L4BGRATE 20 +#define L4RFLOOR 30 + +#define L4BWALL1 30 +#define L4BWALL2 20 +#define L4BWALL3 20 + +#define L4STATUE 10 + + +Na_Krul_Struct Na_Krul; // Info for Na-Kruls room JKE + +/*-----------------------------------------------------------------------** +** Registration info +**-----------------------------------------------------------------------*/ +#include "regconst.h" +char sgszRegSig2[REG_LEN] = "REGISTRATION_BLOCK"; + + +/*-----------------------------------------------------------------------** +** File Variables +**-----------------------------------------------------------------------*/ +static byte dflags[MDMAXX][MDMAXY]; +static byte * pSetPiece; +static BOOL setloadflag; + + +/*-----------------------------------------------------------------------** +** Constant arrays +**-----------------------------------------------------------------------*/ +/* +DPatsStruct DPAT[NUMDPATS] = { { 8, 4, 1, 4, 0 }, + { 8, 1, 1, 4, 0 }, + { 4, 5, 0, 4, 0 }, + { 4, 1, 1, 4, 0 }, + { 2, 5, 1, 0, 0 }, + { 2, 4, 1, 4, 0 }, + { 1, 5, 1, 0, 0 }, + { 1, 1, 1, 4, 0 }, + { 15, 5, 1, 4, 0 } }; +*/ + +static const ShadowStruct SPATS[NUMSPATS] = { + { 7, 13, 0, 13, _S6, 0, _S4 }, + { 16, 13, 0, 13, _S6, 0, _S4 }, + { 15, 13, 0, 13, _S7, 0, _S4 }, + { 5, 13, 13, 13, _S14, _S2, _S1 }, + { 5, 13, 1, 13, _S5, _S8, _S1 }, + { 5, 13, 13, 2, _S5, _S2, _S10 }, + { 5, 0, 1, 2, 0, _S8, _S10 }, + { 5, 13, 11, 13, _S5, _S9, _S1 }, + { 5, 13, 13, 12, _S5, _S2, _S11 }, + { 5, 13, 11, 12, _S12, _S9, _S11 }, + { 5, 13, 1, 12, _S5, _S8, _S11 }, + { 5, 13, 11, 2, _S5, _S9, _S10 }, + { 9, 13, 13, 13, _S6, _S2, _S4 }, + { 9, 13, 1, 13, _S6, _S8, _S4 }, + { 9, 13, 11, 13, _S13, _S9, _S4 }, + { 8, 13, 0, 13, _S6, 0, _S1 }, + { 8, 13, 0, 12, _S5, 0, _S11 }, + { 8, 0, 0, 2, 0, 0, _S10 }, + { 11, 0, 0, 13, 0, 0, _S1 }, + { 11, 13, 0, 13, _S1, 0, _S1 }, + { 11, 2, 0, 13, _S10, 0, _S1 }, + { 11, 12, 0, 13, _S11, 0, _S1 }, + { 11, 13, 11, 12, _S1, 0, _S11 }, + { 14, 0, 0, 13, 0, 0, _S1 }, + { 14, 13, 0, 13, _S1, 0, _S1 }, + { 14, 2, 0, 13, _S10, 0, _S1 }, + { 14, 12, 0, 13, _S11, 0, _S1 }, + { 14, 13, 11, 12, _S1, 0, _S11 }, + { 10, 0, 13, 0, 0, _S2, 0 }, + { 10, 13, 13, 0, _S2, _S2, 0 }, + { 10, 0, 1, 0, 0, _S8, 0 }, + { 10, 13, 11, 0, _S2, _S9, 0 }, + { 12, 0, 13, 0, 0, _S2, 0 }, + { 12, 13, 13, 0, _S2, _S2, 0 }, + { 12, 0, 1, 0, 0, _S8, 0 }, + { 12, 13, 11, 0, _S2, _S9, 0 }, + { 3, 13, 11, 12, _S12, 0, 0 } }; + +// Types for tile substitution +/* +static const byte BTYPES[NUMBLOCKS] = { 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // L1Base + 0, 0, 0, 0, 0, 0, 0, // L1Dirt + 25, 26, 4, 28, 4, 30, 31, 6, 7, 41, 1, 2, 4, 10, 43, 40, 41, 42, 43, 14, // L1Doors + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1Big + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 80, 0, 82, 0, 0, 0, 0, 0, 0, 79, 0, 80, 0, 0, 79, 80, 0, // L1Plain + 2, 2, 2, 1, 1, 11, 25, 13, 13, 13, // L1Blood + 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 12, 0, 0, 11, 1, 11, 1, // L1Misc + 13, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1Shadow + 0, 0, 0, 0, 0, 0, 0, 0, // L1New + 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1Massac + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1DrOpen + 0, 0, 0, 0, 0, 0, 0, 0, // L1Secret + 0, 0, 0, 0, 0, 0, 0 }; // L1Dirt +*/ + +// Types for shadow pass +static const byte BSTYPES[NUMBLOCKS] = { 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // L1Base + 0, 0, 0, 0, 0, 0, 0, // L1Dirt + 1, 2, 10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 5, 14, 10, 4, 14, 4, 5, // L1Doors + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1Big + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, 3, 4, 1, 6, 7, 16, 17, 2, 1, 1, 2, 2, 1, 1, 2, 2, // L1Plain + 2, 2, 2, 1, 1, 11, 1, 13, 13, 13, // L1Blood + 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 12, 0, 0, 11, 1, 11, 1, // L1Misc + 13, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 11, 2, 12, 13, 13, 13, 12, 2, 1, 2, 2, // L1Shadow + 4, 14, 4, 10, 13, 13, 4, 4, // L1New + 1, 1, 4, 2, 2, 13, 13, 13, 13, // L1Massac + 25, 26, 28, 30, 31, 41, 43, 40, 41, 42, 43, 25, 41, 43, 28, 28, // L1DrOpen + 1, 2, 25, 26, 22, 22, 25, 26, // L1Secret + 0, 0, 0, 0, 0, 0, 0 }; // L1Dirt + +// Types for tile substitution +static const byte L5BTYPES[NUMBLOCKS] = { 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // L1Base + 0, 0, 0, 0, 0, 0, 0, // L1Dirt + 25, 26, 0, 28, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 40, 41, 42, 43, 0, // L1Doors + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1Big + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 79, 80, 0, 82, 0, 0, 0, 0, 0, 0, 79, 0, 80, 0, 0, 79, 80, 0, // L1Plain + 2, 2, 2, 1, 1, 11, 25, 13, 13, 13, // L1Blood + 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 12, 0, 0, 11, 1, 11, 1, // L1Misc + 13, 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1Shadow + 0, 0, 0, 0, 0, 0, 0, 0, // L1New + 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1Massac + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L1DrOpen + 0, 0, 0, 0, 0, 0, 0, 0, // L1Secret + 0, 0, 0, 0, 0, 0, 0 }; // L1Dirt + +/*-----------------------------------------------------------------------** +** Manditory mini set pieces +**-----------------------------------------------------------------------*/ +static const byte STAIRSUP[] = { 4, 4, // X size, Y size + + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_HWALL, D_HWALL, D_HWALL, D_HWALL, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + + 0, 66, 6, 0, // Pattern to sub + 63, 64, 65, 0, + 0, 67, 68, 0, + 0, 0, 0, 0 }; + +static const byte L5STAIRSUP[] = { 4, 5, // X size, Y size + + D_DIRT, D_DIRT, D_DIRT, D_DIRT, // Pattern to look for + D_DIRT, D_DIRT, D_DIRT, D_DIRT, + D_HWALL, D_HWALL, D_HWALL, D_HWALL, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + + 0, 54, 23, 0, + 0, 53, 18, 0, // Pattern to sub + 55, 56, 57, 0, + 58, 59, 60, 0, + 0, 0, 0, 0 }; + +static const byte STAIRSDOWN[] = { 4, 3, // X size, Y size + + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + + 62, 57, 58, 0, // Pattern to sub + 61, 59, 60, 0, + 0, 0, 0, 0 }; + +static const byte L5STAIRSDOWN[] = { 4, 5, + + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + + 0, 0, 52, 0, // Pattern to sub + 0, 48, 51, 0, + 0, 47, 50, 0, + 45, 46, 49, 0, + 0, 0, 0, 0 }; + + + +// Temp borrow to get this to work. JKE +static const byte WARPSTAIRS[] = { 4, 5, // X size, Y size + + D_DIRT, D_DIRT, D_DIRT, D_DIRT, // Pattern to look for + D_DIRT, D_DIRT, D_DIRT, D_DIRT, + D_HWALL, D_HWALL, D_HWALL, D_HWALL, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, + + 0, 62, 23, 0, + 0, 61, 18, 0, // Pattern to sub + 63, 64, 65, 0, + 66, 67, 68, 0, + 0, 0, 0, 0 }; + +static const byte LAMPS[] = { 2, 2, // X size, Y size + + D_FLOOR, 0, // Pattern to look for + D_FLOOR, D_FLOOR, + + 129, 0, // Pattern to sub + 130, 128 }; + + +static const byte PWATERIN[] = { 6, 6, // X size, Y size + + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + + 0, 0, 0, 0, 0, 0, // Pattern to sub + 0, 202, 200, 200, 84, 0, // Pattern to sub + 0, 199, 203, 203, 83, 0, // Pattern to sub + 0, 85, 206, 80, 81, 0, // Pattern to sub + 0, 0, 134, 135, 0, 0, // Pattern to sub + 0, 0, 0, 0, 0, 0}; // Pattern to sub + + +//JKE Enter new swap tiles here then call placerndset() +/* +static const byte TEMPLATE[] = { 3, 3, // X size, Y size + + D_FLOOR, D_FLOOR, D_FLOOR, // Pattern to look for + D_FLOOR, D_FLOOR, D_FLOOR, + D_FLOOR, D_FLOOR, D_FLOOR, + + 0, 0, 0, // Pattern to sub + 0, 0, 0, + 0, 0, 0}; +*/ + +// NORMAL GRATE SUBS +static const byte ARCHLEFT[] = { 1, 1, // X size, Y size + + D_AVW, // Pattern to look for + + 95}; // Pattern to sub + +static const byte ARCHRIGHT[] = { 1, 1, // X size, Y size + + D_AHW, // Pattern to look for + + 96}; // Pattern to sub + +static const byte GRATELEFT[] = { 1, 3, // X size, Y size + + D_VWALL, // Pattern to look for + D_VWALL, + D_VWALL, + + 91, // Pattern to sub + 90, + 89}; + +static const byte GRATERIGHT[] = { 3, 1, // X size, Y size + + D_HWALL,D_HWALL,D_HWALL, // Pattern to look for + + 94,93,92}; // Pattern to sub + +static const byte FLOOR1[] = { 1, 1, // X size, Y size + + D_FLOOR, // Pattern to look for + + 97}; // Pattern to sub + +static const byte FLOOR2[] = { 1, 1, // X size, Y size + + D_FLOOR, // Pattern to look for + + 98}; // Pattern to sub + +static const byte FLOOR3[] = { 1, 1, // X size, Y size + + D_FLOOR, // Pattern to look for + + 99}; // Pattern to sub + +static const byte FLOOR4[] = { 1, 1, // X size, Y size + + D_FLOOR, // Pattern to look for + + 100}; // Pattern to sub + +static const byte BIGFLOOR[] = { 3, 3, // X size, Y size + + D_FLOOR,D_FLOOR,D_FLOOR, // Pattern to look for + D_FLOOR,D_FLOOR,D_FLOOR, + D_FLOOR,D_FLOOR,D_FLOOR, + + 0, 0, 0, // Pattern to sub + 0,101, 0, + 0, 0, 0}; + + +// BROKEN GRATE SUBS +static const byte ARCHLEFT1A[] = { 1, 1, // X size, Y size + + D_AVW, // Pattern to look for + + 185}; // Pattern to sub + +static const byte ARCHLEFT1B[] = { 1, 1, // X size, Y size + + D_AVW, // Pattern to look for + + 186}; // Pattern to sub + +static const byte ARCHRIGHT1A[] = { 1, 1, // X size, Y size + + D_AHW, // Pattern to look for + + 187}; // Pattern to sub + +static const byte ARCHRIGHT1B[] = { 1, 1, // X size, Y size + + D_AHW, // Pattern to look for + + 188}; // Pattern to sub + +static const byte GRATELEFT1BA[] = { 1, 1, // X size, Y size + + 89, // Pattern to look for + + 173}; // Pattern to sub + +static const byte GRATELEFT1BB[] = { 1, 1, // X size, Y size + + 89, // Pattern to look for + + 174}; // Pattern to sub + +static const byte GRATELEFT1MA[] = { 1, 1, // X size, Y size + + 90, // Pattern to look for + + 175}; // Pattern to sub + +static const byte GRATELEFT1MB[] = { 1, 1, // X size, Y size + + 90, // Pattern to look for + + 176}; // Pattern to sub + +static const byte GRATELEFT1TA[] = { 1, 1, // X size, Y size + + 91, // Pattern to look for + + 177}; // Pattern to sub + +static const byte GRATELEFT1TB[] = { 1, 1, // X size, Y size + + 91, // Pattern to look for + + 178}; // Pattern to sub + +static const byte GRATERIGHT1RA[] = { 1, 1, // X size, Y size + + 92, // Pattern to look for + + 179}; // Pattern to sub + +static const byte GRATERIGHT1RB[] = { 1, 1, // X size, Y size + + 92, // Pattern to look for + + 180}; // Pattern to sub + +static const byte GRATERIGHT1MA[] = { 1, 1, // X size, Y size + + 92, // Pattern to look for + + 181}; // Pattern to sub + +static const byte GRATERIGHT1MB[] = { 1, 1, // X size, Y size + + 92, // Pattern to look for + + 182}; // Pattern to sub + +static const byte GRATERIGHT1LA[] = { 1, 1, // X size, Y size + + 92, // Pattern to look for + + 183}; // Pattern to sub + +static const byte GRATERIGHT1LB[] = { 1, 1, // X size, Y size + + 92, // Pattern to look for + + 184}; // Pattern to sub + +static const byte FLOOR1B1[] = { 1, 1, // X size, Y size + + 98, // Pattern to look for + + 189}; // Pattern to sub + +static const byte FLOOR2B1[] = { 1, 1, // X size, Y size + + 98, // Pattern to look for + + 190}; // Pattern to sub + +static const byte FLOOR3B1[] = { 1, 1, // X size, Y size + + 97, // Pattern to look for + + 191}; // Pattern to sub + +static const byte FLOOR4B1[] = { 1, 1, // X size, Y size + + D_COL, // Pattern to look for + + 192}; // Pattern to sub + +static const byte FLOOR5B1[] = { 1, 1, // X size, Y size + + 99, // Pattern to look for + + 193}; // Pattern to sub + +static const byte FLOOR6B1[] = { 1, 1, // X size, Y size + + 99, // Pattern to look for + + 194}; // Pattern to sub + +static const byte FLOOR7B1[] = { 1, 1, // X size, Y size + + 100, // Pattern to look for + + 195}; // Pattern to sub + +static const byte BIGFLOORB1[] = { 1, 1, // X size, Y size + + 101, // Pattern to look for + + 196}; + +static const byte BIGFLOORB2[] = { 1, 1, // X size, Y size + + 101, + + 197}; + +static const byte BIGFLOORB3[] = { 1, 1, // X size, Y size + + 101, // Pattern to look for + + 198}; + + + +// GENERAL FLOOR RUBBLE + +static const byte BIGFLOORR1[] = { 3, 3, // X size, Y size + + D_FLOOR,D_FLOOR,D_FLOOR, // Pattern to look for + D_FLOOR,D_FLOOR,D_FLOOR, + D_FLOOR,D_FLOOR,D_FLOOR, + + 0, 0, 0, // Pattern to sub + 0,167, 0, + 0, 0, 0}; + +static const byte BIGFLOORR2[] = { 3, 3, // X size, Y size + + D_FLOOR,D_FLOOR,D_FLOOR, // Pattern to look for + D_FLOOR,D_FLOOR,D_FLOOR, + D_FLOOR,D_FLOOR,D_FLOOR, + + 0, 0, 0, // Pattern to sub + 0,168, 0, + 0, 0, 0}; + +static const byte BIGFLOORR3[] = { 3, 3, // X size, Y size + + D_FLOOR,D_FLOOR,D_FLOOR, // Pattern to look for + D_FLOOR,D_FLOOR,D_FLOOR, + D_FLOOR,D_FLOOR,D_FLOOR, + + 0, 0, 0, // Pattern to sub + 0,169, 0, + 0, 0, 0}; + +static const byte BIGFLOORR4[] = { 3, 3, // X size, Y size + + D_FLOOR,D_FLOOR,D_FLOOR, // Pattern to look for + D_FLOOR,D_FLOOR,D_FLOOR, + D_FLOOR,D_FLOOR,D_FLOOR, + + 0, 0, 0, // Pattern to sub + 0,170, 0, + 0, 0, 0}; + +static const byte BIGFLOORR5[] = { 3, 3, // X size, Y size + + D_FLOOR,D_FLOOR,D_FLOOR, // Pattern to look for + D_FLOOR,D_FLOOR,D_FLOOR, + D_FLOOR,D_FLOOR,D_FLOOR, + + 0, 0, 0, // Pattern to sub + 0,171, 0, + 0, 0, 0}; + +static const byte BIGFLOORR6[] = { 3, 3, // X size, Y size + + D_FLOOR,D_FLOOR,D_FLOOR, // Pattern to look for + D_FLOOR,D_FLOOR,D_FLOOR, + D_FLOOR,D_FLOOR,D_FLOOR, + + 0, 0, 0, // Pattern to sub + 0,172, 0, + 0, 0, 0}; + +static const byte FLOORR1[] = { 1, 1, // X size, Y size + + D_FLOOR, // Pattern to look for + + 163}; // Pattern to sub + +static const byte FLOORR2[] = { 1, 1, // X size, Y size + + D_FLOOR, // Pattern to look for + + 164}; // Pattern to sub + +static const byte FLOORR3[] = { 1, 1, // X size, Y size + + D_FLOOR, // Pattern to look for + + 165}; // Pattern to sub + +static const byte FLOORR4[] = { 1, 1, // X size, Y size + + D_FLOOR, // Pattern to look for + + 166}; // Pattern to sub + + +// BROKEN WALL 1 +static const byte BROKEN_VWALL1[] = { 1, 1, + + D_VWALL, + + 112}; + +static const byte BROKEN_HWALL1[] = { 1, 1, + + D_HWALL, + + 113}; + +static const byte BROKEN_LRC1[] = { 1, 1, + + D_LRC, + + 114}; + +static const byte BROKEN_ULC1[] = { 1, 1, + + D_ULC, + + 115}; + +static const byte BROKEN_AULC1[] = { 1, 1, + + D_AULC, + + 116}; + +static const byte BROKEN_URC1[] = { 1, 1, + + D_URC, + + 117}; + +static const byte BROKEN_LLC1[] = { 1, 1, + + D_LLC, + + 118}; + +static const byte BROKEN_AURC1[] = { 1, 1, + + D_AURC, + + 119}; + +static const byte BROKEN_ALLC1[] = { 1, 1, + + D_ALLC, + + 120}; + +static const byte BROKEN_TULC11[] = { 1, 1, + + D_TULC1, + + 121}; + +static const byte BROKEN_AVW1[] = { 1, 1, + + D_AVW, + + 122}; + +static const byte BROKEN_AHW1[] = { 1, 1, + + D_AHW, + + 123}; + +static const byte BROKEN_FLOOR1[] = { 1, 1, + + D_FLOOR, + + 124}; + +static const byte BROKEN_TULC21[] = { 1, 1, + + D_TULC2, + + 125}; + +static const byte BROKEN_COL1[] = { 1, 1, + + D_COL, + + 126}; + +static const byte BROKEN_BCAP1[] = { 1, 1, + + D_BCAP, + + 127}; + +static const byte BROKEN_RCAP1[] = { 1, 1, + + D_RCAP, + + 128}; + +// BROKEN WALL 2 +static const byte BROKEN_VWALL2[] = { 1, 1, + + D_VWALL, + + 129}; + +static const byte BROKEN_HWALL2[] = { 1, 1, + + D_HWALL, + + 130}; + +static const byte BROKEN_LRC2[] = { 1, 1, + + D_LRC, + + 131}; + +static const byte BROKEN_ULC2[] = { 1, 1, + + D_ULC, + + 132}; + +static const byte BROKEN_AULC2[] = { 1, 1, + + D_AULC, + + 133}; + +static const byte BROKEN_URC2[] = { 1, 1, + + D_URC, + + 134}; + +static const byte BROKEN_LLC2[] = { 1, 1, + + D_LLC, + + 135}; + +static const byte BROKEN_AURC2[] = { 1, 1, + + D_AURC, + + 136}; + +static const byte BROKEN_ALLC2[] = { 1, 1, + + D_ALLC, + + 137}; + +static const byte BROKEN_TULC12[] = { 1, 1, + + D_TULC1, + + 138}; + +static const byte BROKEN_AVW2[] = { 1, 1, + + D_AVW, + + 139}; + +static const byte BROKEN_AHW2[] = { 1, 1, + + D_AHW, + + 140}; + +static const byte BROKEN_FLOOR2[] = { 1, 1, + + D_FLOOR, + + 141}; + +static const byte BROKEN_TULC22[] = { 1, 1, + + D_TULC2, + + 142}; + +static const byte BROKEN_COL2[] = { 1, 1, + + D_COL, + + 143}; + +static const byte BROKEN_BCAP2[] = { 1, 1, + + D_BCAP, + + 144}; + +static const byte BROKEN_RCAP2[] = { 1, 1, + + D_RCAP, + + 145}; + +// BROKEN WALL 3 +static const byte BROKEN_VWALL3[] = { 1, 1, + + D_VWALL, + + 146}; + +static const byte BROKEN_HWALL3[] = { 1, 1, + + D_HWALL, + + 147}; + +static const byte BROKEN_LRC3[] = { 1, 1, + + D_LRC, + + 148}; + +static const byte BROKEN_ULC3[] = { 1, 1, + + D_ULC, + + 149}; + +static const byte BROKEN_AULC3[] = { 1, 1, + + D_AULC, + + 150}; + +static const byte BROKEN_URC3[] = { 1, 1, + + D_URC, + + 151}; + +static const byte BROKEN_LLC3[] = { 1, 1, + + D_LLC, + + 152}; + +static const byte BROKEN_AURC3[] = { 1, 1, + + D_AURC, + + 153}; + +static const byte BROKEN_ALLC3[] = { 1, 1, + + D_ALLC, + + 154}; + +static const byte BROKEN_TULC13[] = { 1, 1, + + D_TULC1, + + 155}; + +static const byte BROKEN_AVW3[] = { 1, 1, + + D_AVW, + + 156}; + +static const byte BROKEN_AHW3[] = { 1, 1, + + D_AHW, + + 157}; + +static const byte BROKEN_FLOOR3[] = { 1, 1, + + D_FLOOR, + + 158}; + +static const byte BROKEN_TULC23[] = { 1, 1, + + D_TULC2, + + 159}; + +static const byte BROKEN_COL3[] = { 1, 1, + + D_COL, + + 160}; + +static const byte BROKEN_BCAP3[] = { 1, 1, + + D_BCAP, + + 161}; + +static const byte BROKEN_RCAP3[] = { 1, 1, + + D_RCAP, + + 162}; + +// STATUES + +static const byte STATUE_LEFTA[] = { 1, 1, + + D_VWALL, + + 199}; + +static const byte STATUE_LEFTB[] = { 1, 1, + + D_VWALL, + + 201}; + +static const byte STATUE_RIGHTA[] = { 1, 1, + + D_HWALL, + + 200}; + +static const byte STATUE_RIGHTB[] = { 1, 1, + + D_HWALL, + + 202}; + + +// QUEST ROOMS +static byte NA_KRULS_ROOM[] = { 4, 6, // Dimensions of the room + + 115,130, 6,D_FLOOR, // Define the room + 129,108, 1,D_FLOOR, + 1,107,103,D_FLOOR, + 146,106,102,D_FLOOR, + 129,168, 1,D_FLOOR, + 7, 2, 3,D_FLOOR}; + +static byte CORNERSTONE[] = { 5, 5, + + 4, 2, 2, 2, 6, // Define the room + 1,111,172, 0, 1, + 1,172, 0, 0,25, + 1, 0, 0, 0, 1, + 7, 2, 2, 2, 3}; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +/* +static void DRLG_CheckDoor(int x, int y) +{ + byte mf, c; + + mf = 0; + if ((dflags[x][y] & HDOOR) == HDOOR) { + c = dungeon[x+1][y]; + if (c == D_VWALL) mf = 1; + if (c == D_ULC) mf = 1; + if (c == D_URC) mf = 1; + if (c == D_TULC1) mf = 1; + if (c == D_DH) mf = 1; + if (c == D_DURC) mf = 1; + if (mf == 1) { + dflags[x][y] ^= HDOOR; + dflags[x-1][y] |= HDOOR; + } + } + if ((dflags[x][y] & VDOOR) == VDOOR) { + c = dungeon[x][y+1]; + if (c == D_HWALL) mf = 1; + if (c == D_ULC) mf = 1; + if (c == D_LLC) mf = 1; + if (c == D_TULC2) mf = 1; + if (c == D_DV) mf = 1; + if (c == D_DLLC) mf = 1; + if (mf == 1) { + dflags[x][y] ^= VDOOR; + dflags[x][y-1] |= VDOOR; + } + } +} +*/ + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_PlaceDoor(int x, int y) +{ + byte c, df; + + if ((dflags[x][y] & SETP_BIT) == 0) { + //dungeon[x][y] = D_COL; + //dflags[x][y] = SETP_BIT; + //return; + df = dflags[x][y] & SETP_MASK; + c = dungeon[x][y]; + if (df == HDOOR) { + if ((y != 1) && (c == D_HWALL)) dungeon[x][y] = D_DRH; + if ((y != 1) && (c == D_LLC)) dungeon[x][y] = D_DRLLC; + if ((y != 1) && (c == D_TULC2)) dungeon[x][y] = D_DRHT2; + if ((y != 1) && (c == D_ULC)) dungeon[x][y] = D_DRHULC; + if ((x != 1) && (c == D_VWALL)) dungeon[x][y] = D_DRV; + if ((x != 1) && (c == D_TULC1)) dungeon[x][y] = D_DRVT1; + if ((x != 1) && (c == D_URC)) dungeon[x][y] = D_DRURC; + } + if (df == VDOOR) { + if ((x != 1) && (c == D_VWALL)) dungeon[x][y] = D_DRV; + if ((x != 1) && (c == D_URC)) dungeon[x][y] = D_DRURC; + if ((x != 1) && (c == D_TULC1)) dungeon[x][y] = D_DRVT1; + if ((x != 1) && (c == D_ULC)) dungeon[x][y] = D_DRVULC; + if ((y != 1) && (c == D_HWALL)) dungeon[x][y] = D_DRH; + if ((y != 1) && (c == D_TULC2)) dungeon[x][y] = D_DRHT2; + if ((y != 1) && (c == D_LLC)) dungeon[x][y] = D_DRLLC; + } + if (df == DDOOR) { + if ((x != 1) && (y != 1) && (c == D_ULC)) dungeon[x][y] = D_DDULC; + if ((x != 1) && (c == D_TULC1)) dungeon[x][y] = D_DRVT1; + if ((y != 1) && (c == D_TULC2)) dungeon[x][y] = D_DRHT2; + if ((y != 1) && (c == D_HWALL)) dungeon[x][y] = D_DRH; + if ((x != 1) && (c == D_VWALL)) dungeon[x][y] = D_DRV; + if ((y != 1) && (c == D_LLC)) dungeon[x][y] = D_DRLLC; + if ((x != 1) && (c == D_URC)) dungeon[x][y] = D_DRURC; + } + } + dflags[x][y] = SETP_BIT; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +/* +static int DRLG_SubInitDoor(int v1, int v2) +{ + int rv; + + rv = random(0, 3); + if (rv == 0) rv = v1; + else if (rv == 1) rv = v2; + else if (rv == 2) rv = v1 | v2; + return(rv); +} +*/ +static void DRLG_L5Shadows() +{ + int x,y; + + for (y = 1; y < MDMAXY; y++) + { + for (x = 1; x < MDMAXX; x++) + { + switch (dungeon[x][y]) + { + case 5: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 7: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 8: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 9: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 10: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 11: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 12: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 14: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 15: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 17: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 95: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 96: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 208; + break; + + case 116: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 118: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 119: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 120: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 121: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 122: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 211; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 212; + break; + + case 123: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 125: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 126: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 128: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 133: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 135: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 136: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 137: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 213; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 214; + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 138: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 139: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 215; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 216; + break; + + case 140: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 217; + break; + + case 142: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 143: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 213; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 214; + break; + + case 145: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 213; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 214; + break; + + case 150: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 217; + break; + + case 152: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 153: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 154: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 155: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 205; + break; + + case 156: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 157: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 217; + break; + + case 159: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 160: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 206; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 207; + break; + + case 162: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 209; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 210; + break; + + case 167: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 209; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 210; + break; + + case 187: + if (dungeon[x][y-1] == D_FLOOR) + dungeon[x][y-1] = 208; + break; + + case 185: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 186: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 203; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 204; + break; + + case 192: + if (dungeon[x-1][y] == D_FLOOR) + dungeon[x-1][y] = 209; + if (dungeon[x-1][y-1] == D_FLOOR) + dungeon[x-1][y-1] = 210; + break; + + + } + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L1Shadows() +{ + int x,y,i,patflag; + byte sd[2][2]; + byte tnv3; + + for (y = 1; y < MDMAXY; y++) { + for (x = 1; x < MDMAXX; x++) { + if ((x == 60) && (y == 21)) + patflag = 1; + sd[0][0] = BSTYPES[dungeon[x][y]]; + sd[1][0] = BSTYPES[dungeon[x-1][y]]; + sd[0][1] = BSTYPES[dungeon[x][y-1]]; + sd[1][1] = BSTYPES[dungeon[x-1][y-1]]; + for (i = 0; i < NUMSPATS; i++) { + if (SPATS[i].strig == sd[0][0]) { + patflag = 1; + if ((SPATS[i].s1 != 0) && (SPATS[i].s1 != sd[1][1])) patflag = 0; + if ((SPATS[i].s2 != 0) && (SPATS[i].s2 != sd[0][1])) patflag = 0; + if ((SPATS[i].s3 != 0) && (SPATS[i].s3 != sd[1][0])) patflag = 0; + if (patflag == 1) { + if ((SPATS[i].nv1 != 0) && (dflags[x-1][y-1] == 0)) dungeon[x-1][y-1] = SPATS[i].nv1; + if ((SPATS[i].nv2 != 0) && (dflags[x][y-1] == 0)) dungeon[x][y-1] = SPATS[i].nv2; + if ((SPATS[i].nv3 != 0) && (dflags[x-1][y] == 0)) dungeon[x-1][y] = SPATS[i].nv3; + } + } + + } + } + } + + // Fix grates + for (y = 1; y < MDMAXY; y++) { + for (x = 1; x < MDMAXX; x++) { + if ((dungeon[x-1][y] == _S1) && (dflags[x-1][y] == 0)) { + tnv3 = _S1; + if (dungeon[x][y] == 29) tnv3 = _S3; + if (dungeon[x][y] == 32) tnv3 = _S3; + if (dungeon[x][y] == 35) tnv3 = _S3; + if (dungeon[x][y] == 37) tnv3 = _S3; + if (dungeon[x][y] == 38) tnv3 = _S3; + if (dungeon[x][y] == 39) tnv3 = _S3; + dungeon[x-1][y] = tnv3; + } + if ((dungeon[x-1][y] == _S11) && (dflags[x-1][y] == 0)) { + tnv3 = _S11; + if (dungeon[x][y] == 29) tnv3 = _S15; + if (dungeon[x][y] == 32) tnv3 = _S15; + if (dungeon[x][y] == 35) tnv3 = _S15; + if (dungeon[x][y] == 37) tnv3 = _S15; + if (dungeon[x][y] == 38) tnv3 = _S15; + if (dungeon[x][y] == 39) tnv3 = _S15; + dungeon[x-1][y] = tnv3; + } + if ((dungeon[x-1][y] == _S10) && (dflags[x-1][y] == 0)) { + tnv3 = _S10; + if (dungeon[x][y] == 29) tnv3 = _S16; + if (dungeon[x][y] == 32) tnv3 = _S16; + if (dungeon[x][y] == 35) tnv3 = _S16; + if (dungeon[x][y] == 37) tnv3 = _S16; + if (dungeon[x][y] == 38) tnv3 = _S16; + if (dungeon[x][y] == 39) tnv3 = _S16; + dungeon[x-1][y] = tnv3; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int DRLG_PlaceMiniSet(const byte miniset[], int tmin, int tmax, int cx, int cy, int setview, int noquad, int ldir) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int i, ii, numt; + int found; + int abort; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Number of pieces to place + if ((tmax - tmin) == 0) numt = 1; + else numt = random(0, tmax - tmin) + tmin; + + for (i = 0; i < numt; i++) { + // Random starting pos + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + + // Find a location for the mini set piece + found = 0; + abort = 0; + while (found == 0) { + found = 1; + if ((cx != -1) && (sx >= (cx - sw)) && (sx <= (cx + 12))) { + sx++; + //sx = random(0, MDMAXX-sw); + //sy = random(0, MDMAXY-sh); + found = 0; + } + if ((cy != -1) && (sy >= (cy - sh)) && (sy <= (cy + 12))) { + sy++; + //sx = random(0, MDMAXX-sw); + //sy = random(0, MDMAXY-sh); + found = 0; + } + switch (noquad) { + case 0 : + if ((sx < cx) && (sy < cy)) found = 0; + break; + case 1: + if ((sx > cx) && (sy < cy)) found = 0; + break; + case 2: + if ((sx < cx) && (sy > cy)) found = 0; + break; + case 3: + if ((sx > cx) && (sy > cy)) found = 0; + break; + } + ii = 2; + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + if (found == 0) { + sx++; + if (sx == (MDMAXX - sw)) { + sx = 0; + sy++; + if (sy == (MDMAXY - sh)) sy = 0; + } + abort++; + if (abort > 4000) return(-1); + } + } + + // Place mini set piece + ii = (sh * sw) + 2; + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[ii] != 0) dungeon[sx+xx][sy+yy] = miniset[ii]; + ii++; + } + } + } + + if (miniset == PWATERIN) { + i = TransVal; + TransVal = 0; + DRLG_MRectTrans(sx+0, sy+2, sx+5, sy+4); + TransVal = i; + quests[Q_PWATER]._qtx = (sx << 1) + 5 + DIRTEDGED2; + quests[Q_PWATER]._qty = (sy << 1) + 6 + DIRTEDGED2; + } + + if (setview == 1) { + ViewX = (sx << 1) + 3 + (DIRTEDGED2); + ViewY = (sy << 1) + 4 + (DIRTEDGED2); + } + + if (ldir == LVL_DOWN) { + LvlViewX = (sx << 1) + 3 + (DIRTEDGED2); + LvlViewY = (sy << 1) + 4 + (DIRTEDGED2); + } + + if ((sx < cx) && (sy < cy)) return(0); + if ((sx > cx) && (sy < cy)) return(1); + if ((sx < cx) && (sy > cy)) return(2); + return(3); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +/* +static void DRLG_PlaceRndSet(byte miniset[], int rndper) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int ii; + int found; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Find a location for the mini set piece + for (sy = 0; sy < (MDMAXY - sh); sy++) { + for (sx = 0; sx < (MDMAXX - sw); sx++) { + found = 1; + ii = 2; + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + if ((found == 1) && (random(0, 100) < rndper)) { + // Place mini set piece + ii = (sh * sw) + 2; + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[ii] != 0) dungeon[sx+xx][sy+yy] = miniset[ii]; + ii++; + } + } + } + } + } +} +*/ + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L1Floor() +{ + int i,j; + long rv; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dflags[i][j] == 0) && (dungeon[i][j] == D_FLOOR)) { + rv = random(0, 3); + if (rv == 1) dungeon[i][j] = 162; + if (rv == 2) dungeon[i][j] = 163; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L1Pass3() +{ + int i,j,xx,yy; + long v1,v2,v3,v4,lv; + + // Init dungeon to dirt + lv = D_DIRT - 1; + __asm { + mov esi,dword ptr [pMegaTiles] + mov eax,dword ptr [lv]; + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + for (yy = 0; yy < DMAXY; yy+=2) { + for (xx = 0; xx < DMAXX; xx+=2) { + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + } + } + + // Convert dungeon mega tiles to mini tiles + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + lv = ((long)dungeon[i][j]) - 1; + app_assert(lv >= 0); + __asm { + mov esi,dword ptr [pMegaTiles] + mov eax,dword ptr [lv]; + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + xx += 2; + } + yy += 2; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_LoadL1SP() +{ + setloadflag = FALSE; + if (QuestStatus(Q_BUTCHER)) { + pSetPiece = LoadFileInMemSig("Levels\\L1Data\\rnd6.DUN",NULL,'STPC'); + setloadflag = TRUE; + } + if (QuestStatus(Q_SKELKING) && (gbMaxPlayers == 1)) { + pSetPiece = LoadFileInMemSig("Levels\\L1Data\\SKngDO.DUN",NULL,'STPC'); + setloadflag = TRUE; + } + if (QuestStatus(Q_LTBANNER)) { + pSetPiece = LoadFileInMemSig("Levels\\L1Data\\Banner2.DUN",NULL,'STPC'); + setloadflag = TRUE; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_FreeL1SP() { + DiabloFreePtr(pSetPiece); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DRLG_Init_Globals() { + ZeroMemory(dFlags,sizeof(dFlags)); + ZeroMemory(dPlayer,sizeof(dPlayer)); + ZeroMemory(dMonster,sizeof(dMonster)); + ZeroMemory(dDead,sizeof(dDead)); + ZeroMemory(dObject,sizeof(dObject)); + ZeroMemory(dItem,sizeof(dItem)); + ZeroMemory(dMissile,sizeof(dMissile)); + ZeroMemory(dSpecial,sizeof(dSpecial)); + + // Init the light values for each piece + char cLight; + if (lightflag == 0) { + if (light4flag) cLight = 3; + else cLight = 15; + } + else { + cLight = 0; + } + FillMemory(dLight,sizeof(dLight),cLight); +} + + +static void DRLG_L5Doors() //JKE +{ + + for (int j = 0; j < DMAXY; j++) { + for (int i = 0; i < DMAXX; i++) { + // place tops of arches + int nPiece = dPiece[i][j]; + if (nPiece == 77) nPiece = 1; + else if (nPiece == 80) nPiece = 2; + else continue; + + dSpecial[i][j] = nPiece; + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_InitL1Vals() { + + for (int j = 0; j < DMAXY; j++) { + for (int i = 0; i < DMAXX; i++) { + // place tops of arches + int nPiece = dPiece[i][j]; + if (nPiece == 12) nPiece = 1; + else if (nPiece == 11) nPiece = 2; + else if (nPiece == 71) nPiece = 1; + else if (nPiece == 259) nPiece = 5; + else if (nPiece == 249) nPiece = 2; + else if (nPiece == 325) nPiece = 2; + else if (nPiece == 321) nPiece = 1; + else if (nPiece == 255) nPiece = 4; + else if (nPiece == 211) nPiece = 1; + else if (nPiece == 344) nPiece = 2; + else if (nPiece == 341) nPiece = 1; + else if (nPiece == 331) nPiece = 2; + else if (nPiece == 418) nPiece = 1; + else if (nPiece == 421) nPiece = 2; + else continue; + + dSpecial[i][j] = nPiece; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void LoadL1Dungeon(char sFileName[], int vx, int vy) +{ + int i,j,rw,rh; + byte *pLevelMap,*lm; + + dminx = DIRTEDGED2; + dminy = DIRTEDGED2; + dmaxx = DMAXX - (DIRTEDGED2); + dmaxy = DMAXY - (DIRTEDGED2); + + DRLG_InitTrans(); + + // Load map + pLevelMap = LoadFileInMemSig(sFileName,NULL,'LMPt'); + lm = pLevelMap; + + // Fill with dirt + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + dungeon[i][j] = D_DIRT; + dflags[i][j] = NODOOR; + } + } + + // Put map in dungeon + rw = *lm; + + lm+=2; + rh = *lm; + lm+=2; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*lm != 0) { + dungeon[i][j] = *lm; + dflags[i][j] |= SETP_BIT; // Don't go changin' + } else dungeon[i][j] = D_FLOOR; + lm+=2; + } + } + + // Floor subs + DRLG_L1Floor(); + + ViewX = vx; + ViewY = vy; + + // Convert to minis + DRLG_L1Pass3(); + + DRLG_Init_Globals(); + if (currlevel < HIVESTART) // JKE NO TOPS!!! + DRLG_InitL1Vals(); + + SetMapMonsters(pLevelMap, 0, 0); + SetMapObjects(pLevelMap, 0, 0); + //SetMapItems(pLevelMap); + + // Free map + DiabloFreePtr(pLevelMap); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void LoadPreL1Dungeon(char sFileName[], int vx, int vy) +{ + int i,j,rw,rh; + byte *pLevelMap,*lm; + + dminx = DIRTEDGED2; + dminy = DIRTEDGED2; + dmaxx = DMAXX - (DIRTEDGED2); + dmaxy = DMAXY - (DIRTEDGED2); + + // Load map + pLevelMap = LoadFileInMemSig(sFileName,NULL,'LMPt'); + lm = pLevelMap; + + // Fill with dirt + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + dungeon[i][j] = D_DIRT; + dflags[i][j] = NODOOR; + } + } + + // Put map in dungeon + rw = *lm; + lm+=2; + rh = *lm; + lm+=2; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*lm != 0) { + dungeon[i][j] = *lm; + dflags[i][j] |= SETP_BIT; // Don't go changin' + } else dungeon[i][j] = D_FLOOR; + lm+=2; + } + } + + // Floor subs + DRLG_L1Floor(); + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) pdungeon[i][j] = dungeon[i][j]; + } + + // Free map + DiabloFreePtr(pLevelMap); +} + +/*------------------------------------------------------------------------* +** +** DRLG (5) +** drlg1 - test +** +*-------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------* +** Defines +**------------------------------------------------------------------------*/ + +#define L5DIR_HORIZ 0 +#define L5DIR_VERT 1 + +#define L5ROOM_MIN 2 +#define L5ROOM_MAX 6 + +#define L5DUNX 40 +#define L5DUNY 40 + +#define L5MIN_AREA ((L5DUNX*L5DUNY)/3) + ((L5DUNX*L5DUNY)/7) + +#define L5DX 80 +#define L5DY 80 + +byte L5dungeon[L5DX][L5DY]; +byte L5ConvTbl[16] = { 22, 13, 1, 13, 2, 13, 13, 13, 4, 13, 1, 13, 2, 13, 16, 13 }; + +/*------------------------------------------------------------------------* +** Global variables +**------------------------------------------------------------------------*/ +static BOOL HR1, HR2, HR3; +static BOOL VR1, VR2, VR3; + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void InitL5Dungeon() +{ + int i,j; + + for (j = 0; j < L5DUNY; j++) { + for (i = 0; i < L5DUNX; i++) { + dungeon[i][j] = 0; + dflags[i][j] = NODOOR; + } + } +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void L5ClearFlags() +{ + int i,j; + + for (j = 0; j < L5DUNY; j++) { + for (i = 0; i < L5DUNX; i++) dflags[i][j] &= SETP_TMASK; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void L5drawRoom(int x, int y, int w, int h) +{ + int i,j; + + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + dungeon[i+x][j+y] = 1; + } + } +} + +/*---------------------------------------------------------------------* +** Check limits of 40 X 40 +**---------------------------------------------------------------------*/ +static BOOL L5checkRoom(int x, int y, int width, int height) +{ + int i, j; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + if ((x+i < 0) || (x+i >= L5DUNX) || (y+j < 0) || (y+j >= L5DUNY)) return(FALSE); + if (dungeon[x+i][y+j] != 0) return(FALSE); + } + } + return(TRUE); +} + +/*---------------------------------------------------------------------** +** Generate left and right, up and down rooms +**---------------------------------------------------------------------*/ +static void L5roomGen(int x, int y, int w, int h, int dir) +{ + int rx, ry, rx2, ry2; + int height, width; + int cx1, cy1, cw, ch; + int num; + int dirProb; + int ran; + BOOL c, d; + + ran = random(0, 4); + if (dir == L5DIR_VERT) { + if (ran == 0) dirProb = L5DIR_HORIZ; + else dirProb = L5DIR_VERT; + } else { + if (ran == 0) dirProb = L5DIR_VERT; + else dirProb = L5DIR_HORIZ; + } + switch(dirProb) { + case L5DIR_HORIZ : // left/right + // left room + num = 0; + do { + width = ((random(0, L5ROOM_MAX-L5ROOM_MIN+1) + L5ROOM_MIN) >> 1) << 1; + height = ((random(0, L5ROOM_MAX-L5ROOM_MIN+1) + L5ROOM_MIN) >> 1) << 1; + ry = y + (h/2) - (height/2); + rx = x - width; + cx1 = rx - 1; + cy1 = ry - 1; + cw = height + 2; + ch = width + 1; + c = L5checkRoom(cx1, cy1, cw, ch); + num++; + } while ((c == FALSE) && (num < 20)); + if (c == TRUE) L5drawRoom(rx, ry, width, height); + + // right room + rx2 = x + w; + cx1 = rx2; + cy1 = ry - 1; + ch = height + 2; + cw = width + 1; + d = L5checkRoom(cx1, cy1, cw, ch); + if (d == TRUE) L5drawRoom(rx2, ry, width, height); + if (c == TRUE) L5roomGen(rx, ry, width, height, L5DIR_VERT); + if (d == TRUE) L5roomGen(rx2, ry, width, height, L5DIR_VERT); + break; + + case L5DIR_VERT : // top/bottom + // top room + num = 0; + do { + width = ((random(0, L5ROOM_MAX-L5ROOM_MIN+1) + L5ROOM_MIN) >> 1) << 1; + height = ((random(0, L5ROOM_MAX-L5ROOM_MIN+1) + L5ROOM_MIN) >> 1) << 1; + rx = x + (w/2) - (width/2); + ry = y - height; + cx1 = rx - 1; + cy1 = ry - 1; + ch = height + 1; + cw = width + 2; + c = L5checkRoom(cx1, cy1, cw, ch); + num++; + + } while ((c == FALSE) && (num < 20)); + if (c == TRUE) L5drawRoom(rx, ry, width, height); + + // bottom room + ry2 = y + h; + cx1 = rx - 1; + cy1 = ry2; + ch = height + 1; + cw = width + 2; + d = L5checkRoom(cx1, cy1, cw, ch); + if (d == TRUE) L5drawRoom(rx, ry2, width, height); + if (c == TRUE) L5roomGen(rx, ry, width, height, L5DIR_HORIZ); + if (d == TRUE) L5roomGen(rx, ry2, width, height, L5DIR_HORIZ); + break; + } +} + +/*-----------------------------------------------------------------------* +** DRLG_GChamber(int sx, int sy, int topflag, int bottomflag, int leftflag, int rightflag) +**-----------------------------------------------------------------------*/ +static void L5firstRoom() +{ + int x, y; + int xs,xe,ys,ye; + + if (random(0, 2) == 0) { // vertical + ys = 1; + ye = L5DUNY - 1; + VR1 = random(0, 2); + VR2 = random(0, 2); + VR3 = random(0, 2); + if ((VR1 + VR3) <= 1) VR2 = 1; + if (VR1) L5drawRoom(15,1,10,10); + else ys += 17; + if (VR2) L5drawRoom(15,15,10,10); + if (VR3) L5drawRoom(15,29,10,10); + else ye -= 17; + for (y = ys; y < ye; y++) { + dungeon[17][y] = 1; + dungeon[18][y] = 1; + dungeon[19][y] = 1; + dungeon[20][y] = 1; + dungeon[21][y] = 1; + dungeon[22][y] = 1; + } + if (VR1) L5roomGen(15,1,10,10,L5DIR_HORIZ); + if (VR2) L5roomGen(15,15,10,10,L5DIR_HORIZ); + if (VR3) L5roomGen(15,29,10,10,L5DIR_HORIZ); + HR1 = HR2 = HR3 = FALSE; + } else { // horizontal + xs = 1; + xe = L5DUNX - 1; + HR1 = random(0, 2); + HR2 = random(0, 2); + HR3 = random(0, 2); + if ((HR1 + HR3) <= 1) HR2 = 1; + if (HR1) L5drawRoom(1,15,10,10); + else xs += 17; + if (HR2) L5drawRoom(15,15,10,10); + if (HR3) L5drawRoom(29,15,10,10); + else xe -= 17; + for (x = xs; x < xe; x++) { + dungeon[x][17] = 1; + dungeon[x][18] = 1; + dungeon[x][19] = 1; + dungeon[x][20] = 1; + dungeon[x][21] = 1; + dungeon[x][22] = 1; + } + if (HR1) L5roomGen(1,15,10,10,L5DIR_VERT); + if (HR2) L5roomGen(15,15,10,10,L5DIR_VERT); + if (HR3) L5roomGen(29,15,10,10,L5DIR_VERT); + VR1 = VR2 = VR3 = FALSE; + } +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static long L5GetArea() +{ + int i,j; + long rv; + + rv = 0; + for (j = 0; j < L5DUNY; j++) { + for (i = 0; i < L5DUNX; i++) { + if (dungeon[i][j] == 1) rv++; + } + } + return(rv); +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void L5makeDungeon() +{ + int i, j; + int k, l; + + for (j = 0; j < L5DUNY; j++) { + for(i = 0; i < L5DUNX; i++) { + k = i<<1; + l = j<<1; + L5dungeon[k][l] = dungeon[i][j]; + L5dungeon[k][l+1] = dungeon[i][j]; + L5dungeon[k+1][l] = dungeon[i][j]; + L5dungeon[k+1][l+1] = dungeon[i][j]; + } + } +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void L5makeDmt() +{ + int i, j; + int idx; + int val; + int dmtx, dmty; + + for (j = 0; j < L5DUNY; j++) + for (i = 0; i < L5DUNX; i++) dungeon[i][j] = D_DIRT; + + dmty = 0; + for (j = 1; j <= 77; j+=2) { + dmtx = 0; + for (i = 1; i <= 77; i+=2) { + idx = L5dungeon[i][j] + (L5dungeon[i+1][j]<<1) + + (L5dungeon[i][j+1]<<2) + (L5dungeon[i+1][j+1]<<3); + + val = L5ConvTbl[idx]; + dungeon[dmtx][dmty] = val; + dmtx++; + } + dmty++; + } + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int L5HWallOk(int i, int j) +{ + int x; + BOOL wallok; + + x = 1; + while ((dungeon[i+x][j] == 13) && + (dungeon[i+x][j-1] == 13) && + (dungeon[i+x][j+1] == 13) && + (dflags[i+x][j] == NODOOR)) x++; + wallok = FALSE; + if ((dungeon[i+x][j] >= 3) && (dungeon[i+x][j] <= 7)) wallok = TRUE; + if ((dungeon[i+x][j] >= 16) && (dungeon[i+x][j] <= 24)) wallok = TRUE; + if (dungeon[i+x][j] == 22) wallok = FALSE; + if (x == 1) wallok = FALSE; + if (wallok) return(x); + else return(-1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int L5VWallOk(int i, int j) +{ + int y; + BOOL wallok; + + y = 1; + while ((dungeon[i][j+y] == 13) && + (dungeon[i-1][j+y] == 13) && + (dungeon[i+1][j+y] == 13) && + (dflags[i][j+y] == NODOOR)) y++; + wallok = FALSE; + if ((dungeon[i][j+y] >= 3) && (dungeon[i][j+y] <= 7)) wallok = TRUE; + if ((dungeon[i][j+y] >= 16) && (dungeon[i][j+y] <= 24)) wallok = TRUE; + if (dungeon[i][j+y] == 22) wallok = FALSE; + if (y == 1) wallok = FALSE; + if (wallok) return(y); + else return(-1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void L5HorizWall(int i, int j, char p, int dx) +{ + int xx; + char wt, dt; + + switch(random(0, 4)) { + case 0: + case 1: + wt = 2; // Normal solid wall + break; + case 2: + wt = 12; // Arch wall + if (p == 2) p = 12; + if (p == 4) p = 10; + break; + case 3: + wt = 36; // Grate wall + if (p == 2) p = 36; + if (p == 4) p = 27; + break; + } + + if (random(0, 6) == 5) dt = 12; // Arch + else dt = 26; // Door + + if (wt == 12) dt = 12; // If arch wall, force arch door + + dungeon[i][j] = p; + for (xx = 1; xx < dx; xx++) dungeon[i+xx][j] = wt; + xx = random(0, dx-1) + 1; + if (dt == 12) dungeon[i+xx][j] = dt; + else { + dungeon[i+xx][j] = 2; + dflags[i+xx][j] |= HDOOR; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void L5VertWall(int i, int j, char p, int dy) +{ + int yy; + char wt, dt; + + switch(random(0, 4)) { + case 0: + case 1: + wt = 1; // Normal solid wall + break; + case 2: + wt = 11; // Arch wall + if (p == 1) p = 11; + if (p == 4) p = 14; + break; + case 3: + wt = 35; // Grate wall + if (p == 1) p = 35; + if (p == 4) p = 37; + break; + } + + if (random(0, 6) == 5) dt = 11; // Arch + else dt = 25; // Door + + if (wt == 11) dt = 11; // If arch wall, force arch door + + dungeon[i][j] = p; + for (yy = 1; yy < dy; yy++) dungeon[i][j+yy] = wt; + yy = random(0, dy-1) + 1; + if (dt == 11) dungeon[i][j+yy] = dt; + else { + dungeon[i][j+yy] = 1; + dflags[i][j+yy] |= VDOOR; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define WALLRND 100 +static void L5AddWall() +{ + int i, j; + int x, y; + + for (j = 0; j < MDMAXY ; j++) { + for (i = 0; i < MDMAXX; i++) { + if (dflags[i][j] == 0) { + if ((dungeon[i][j] == 3) && (random(0, 100) < WALLRND)) { + x = L5HWallOk(i, j); + if (x != -1) L5HorizWall(i, j, 2, x); + } + if ((dungeon[i][j] == 3) && (random(0, 100) < WALLRND)) { + y = L5VWallOk(i, j); + if (y != -1) L5VertWall(i, j, 1, y); + } + if ((dungeon[i][j] == 6) && (random(0, 100) < WALLRND)) { + x = L5HWallOk(i, j); + if (x != -1) L5HorizWall(i, j, 4, x); + } + if ((dungeon[i][j] == 7) && (random(0, 100) < WALLRND)) { + y = L5VWallOk(i, j); + if (y != -1) L5VertWall(i, j, 4, y); + } + if ((dungeon[i][j] == 2) && (random(0, 100) < WALLRND)) { + x = L5HWallOk(i, j); + if (x != -1) L5HorizWall(i, j, 2, x); + } + if ((dungeon[i][j] == 1) && (random(0, 100) < WALLRND)) { + y = L5VWallOk(i, j); + if (y != -1) L5VertWall(i, j, 1, y); + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L5GChamber(int sx, int sy, int topflag, int bottomflag, int leftflag, int rightflag) +{ + int i,j; + + if (topflag == 1) { + // Place top row tiles + dungeon[sx+2][sy] = D_AHW; + dungeon[sx+3][sy] = D_AHW; + dungeon[sx+4][sy] = D_LRC; + dungeon[sx+7][sy] = D_ALLC; + dungeon[sx+8][sy] = D_AHW; + dungeon[sx+9][sy] = D_HWALL; + } + if (bottomflag == 1) { + // Place bottom row tiles + sy += 11; + dungeon[sx+2][sy] = D_TULC1; + dungeon[sx+3][sy] = D_AHW; + dungeon[sx+4][sy] = D_AURC; + dungeon[sx+7][sy] = D_AULC; + dungeon[sx+8][sy] = D_AHW; + if (dungeon[sx+9][sy] != D_ULC) dungeon[sx+9][sy] = D_DULC; + sy -= 11; + } + + if (leftflag == 1) { + // Place left column tiles + dungeon[sx][sy+2] = D_AVW; + dungeon[sx][sy+3] = D_AVW; + dungeon[sx][sy+4] = D_LRC; + dungeon[sx][sy+7] = D_AURC; + dungeon[sx][sy+8] = D_AVW; + dungeon[sx][sy+9] = D_VWALL; + } + if (rightflag == 1) { + // Place right column tiles + sx += 11; + dungeon[sx][sy+2] = D_TULC2; + dungeon[sx][sy+3] = D_AVW; + dungeon[sx][sy+4] = D_ALLC; + dungeon[sx][sy+7] = D_AULC; + dungeon[sx][sy+8] = D_AVW; + if (dungeon[sx][sy+9] != D_ULC) dungeon[sx][sy+9] = D_DULC; + sx -= 11; + } + + for (j = 1; j < 11; j++) { + for (i = 1; i < 11; i++) { + dungeon[sx+i][sy+j] = D_FLOOR; + dflags[sx+i][sy+j] |= SETP_TEMP; + } + } + dungeon[sx+4][sy+4] = D_COL; + dungeon[sx+7][sy+4] = D_COL; + dungeon[sx+4][sy+7] = D_COL; + dungeon[sx+7][sy+7] = D_COL; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void DRLG_L5GHall(int x1, int y1, int x2, int y2) +{ + int i; + + // Horiz or vert? + if (y1 == y2) { + // Horiz + for (i = x1; i < x2; i++) { + dungeon[i][y1] = D_AHW; + dungeon[i][y1+3] = D_AHW; + } + } else { + // Vert + for (i = y1; i < y2; i++) { + dungeon[x1][i] = D_AVW; + dungeon[x1+3][i] = D_AVW; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void L5tileFix() +{ + int i, j; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 22)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 13) && (dungeon[i+1][j] == 22)) dungeon[i+1][j] = 18; + if ((dungeon[i][j] == 13) && (dungeon[i+1][j] == 2)) dungeon[i+1][j] = 7; + + if ((dungeon[i][j] == 6) && (dungeon[i+1][j] == 22)) dungeon[i+1][j] = 24; + + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 22)) dungeon[i][j+1] = 24; + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 1)) dungeon[i][j+1] = 6; + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 22)) dungeon[i][j+1] = 19; + } + } + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 13) && (dungeon[i+1][j] == 19)) dungeon[i+1][j] = 21; + if ((dungeon[i][j] == 13) && (dungeon[i+1][j] == 22)) dungeon[i+1][j] = 20; + if ((dungeon[i][j] == 7) && (dungeon[i+1][j] == 22)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 13) && (dungeon[i+1][j] == 24)) dungeon[i+1][j] = 21; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 22)) dungeon[i+1][j] = 20; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 19)) dungeon[i+1][j] = 21; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 6; + if ((dungeon[i][j] == 7) && (dungeon[i+1][j] == 19)) dungeon[i+1][j] = 21; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 6; + if ((dungeon[i][j] == 3) && (dungeon[i+1][j] == 22)) dungeon[i+1][j] = 24; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 6; + if ((dungeon[i][j] == 7) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 6; + if ((dungeon[i][j] == 7) && (dungeon[i+1][j] == 24)) dungeon[i+1][j] = 21; + if ((dungeon[i][j] == 4) && (dungeon[i+1][j] == 16)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 7) && (dungeon[i+1][j] == 13)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 24)) dungeon[i+1][j] = 21; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 13)) dungeon[i+1][j] = 17; + + if ((dungeon[i][j] == 23) && (dungeon[i-1][j] == 22)) dungeon[i-1][j] = 19; + if ((dungeon[i][j] == 19) && (dungeon[i-1][j] == 23)) dungeon[i-1][j] = 21; + if ((dungeon[i][j] == 6) && (dungeon[i-1][j] == 22)) dungeon[i-1][j] = 24; + if ((dungeon[i][j] == 6) && (dungeon[i-1][j] == 23)) dungeon[i-1][j] = 21; + + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 7; + if ((dungeon[i][j] == 6) && (dungeon[i][j+1] == 18)) dungeon[i][j+1] = 21; + if ((dungeon[i][j] == 18) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 7; + if ((dungeon[i][j] == 6) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 7; + if ((dungeon[i][j] == 21) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 7; + if ((dungeon[i][j] == 6) && (dungeon[i][j+1] == 22)) dungeon[i][j+1] = 24; + if ((dungeon[i][j] == 6) && (dungeon[i][j+1] == 13)) dungeon[i][j+1] = 16; + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 13)) dungeon[i][j+1] = 16; + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 16)) dungeon[i][j+1] = 17; + + if ((dungeon[i][j] == 6) && (dungeon[i][j-1] == 22)) dungeon[i][j-1] = 7; + if ((dungeon[i][j] == 6) && (dungeon[i][j-1] == 22)) dungeon[i][j-1] = 24; + if ((dungeon[i][j] == 7) && (dungeon[i][j-1] == 24)) dungeon[i][j-1] = 21; + if ((dungeon[i][j] == 18) && (dungeon[i][j-1] == 24)) dungeon[i][j-1] = 21; + } + } + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 4) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 7; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 19)) dungeon[i+1][j] = 21; + if ((dungeon[i][j] == 18) && (dungeon[i][j+1] == 22)) dungeon[i][j+1] = 20; + } + } +} + +static void DRLG_L5PlaceRndSet(const byte miniset[], int rndper) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int ii, kk; + int found; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Find a location for the mini set piece + for (sy = 0; sy < (MDMAXY - sh); sy++) { + for (sx = 0; sx < (MDMAXX - sw); sx++) { + found = 1; + ii = 2; + +// if (((sx >= SP3x1) && (sx <= SP3x2)) && ((sy >= SP3y1) && (sy <= SP3y2))) found = 0; + + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + + kk = (sh * sw) + 2; + if (miniset[kk] >= 84 && miniset[kk] <=100 && found == 1) { + if (dungeon[sx-1][sy] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx+1][sy] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx][sy+1] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx][sy-1] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + } + + if ((found == 1) && (random(0, 100) < rndper)) { + // Place mini set piece + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[kk] != 0) dungeon[sx+xx][sy+yy] = miniset[kk]; + kk++; + } + } + } + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L5Subs() +{ + int x,y,i,rv; + byte c; + + for (y = 0; y < MDMAXY; y++) { + for (x = 0; x < MDMAXX; x++) { + rv = random(0, 4); + if (rv == 0) { + c = dungeon[x][y]; + c = L5BTYPES[c]; + if ((c != 0) && (dflags[x][y] == 0)) { + rv = random(0, 16); + i = -1; + while (rv >= 0) { + i++; + if (i == NUMBLOCKS) i = 0; + if (c == L5BTYPES[i]) rv--; + } + if (i == 89) { + c = dungeon[x][y-1]; + if ((L5BTYPES[c] == 79) && (dflags[x][y-1] == 0)) { + dungeon[x][y-1] = 90; + } else i = 79; + } + if (i == 91) { + c = dungeon[x+1][y]; + if ((L5BTYPES[c] == 80) && (dflags[x+1][y] == 0)) { + dungeon[x+1][y] = 92; + } else i = 80; + } + dungeon[x][y] = i; + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void DRLG_L5SetRoom(int rx1, int ry1) +{ + int rw,rh; + int i,j; + byte *sp; + + sp = pSetPiece; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_x = rx1; + setpc_y = ry1; + setpc_w = rw; + setpc_h = rh; + + //DRLG_MRectTrans(rx1, ry1, rx2, ry2); + //DRLG_MRectTrans(rx1+2, ry1+2, rx2-2, ry2-2); + + sp = pSetPiece+4; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*sp != 0) { + dungeon[rx1+i][ry1+j] = *sp; + dflags[rx1+i][ry1+j] |= SETP_BIT; + } else dungeon[rx1+i][ry1+j] = D_FLOOR; + sp+=2; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void HRLG_L5SetRoom(int rx1, int ry1) +{ + int rw; + int i,j; + +// Don't know what these do. JKE + setpc_x = rx1; + setpc_y = ry1; + setpc_w = NA_KRULS_ROOM[0]; + setpc_h = NA_KRULS_ROOM[1]; + + Na_Krul.x = ((rx1 + 3) * 2); + Na_Krul.y = ((ry1 + 4) * 2); + Na_Krul.Books = FALSE; + Na_Krul.Open = FALSE; + Na_Krul.Lever_Thrown = FALSE; + + + rw = 2; + for (j = 0; j < NA_KRULS_ROOM[1]; j++) { + for (i = 0; i < NA_KRULS_ROOM[0]; i++) { + if (NA_KRULS_ROOM[rw] != 0) { + dungeon[rx1+i][ry1+j] = NA_KRULS_ROOM[rw]; + dflags[rx1+i][ry1+j] |= SETP_BIT; + } else dungeon[rx1+i][ry1+j] = D_FLOOR; + ++rw; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void CRLG_L5SetRoom(int rx1, int ry1) +{ + int rw; + int i,j; + +// Don't know what these do. JKE + setpc_x = rx1; + setpc_y = ry1; + setpc_w = CORNERSTONE[0]; + setpc_h = CORNERSTONE[1]; + + + rw = 2; + for (j = 0; j < CORNERSTONE[1]; j++) { + for (i = 0; i < CORNERSTONE[0]; i++) { + if (CORNERSTONE[rw] != 0) { + dungeon[rx1+i][ry1+j] = CORNERSTONE[rw]; + dflags[rx1+i][ry1+j] |= SETP_BIT; + } else dungeon[rx1+i][ry1+j] = D_FLOOR; + ++rw; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void L5FillChambers() +{ + int c; + + if (HR1) DRLG_L5GChamber(0, 14, 0, 0, 0, 1); + if (HR2) { + if ((HR1) && (!HR3)) DRLG_L5GChamber(14, 14, 0, 0, 1, 0); + if ((!HR1) && (HR3)) DRLG_L5GChamber(14, 14, 0, 0, 0, 1); + if ((HR1) && (HR3)) DRLG_L5GChamber(14, 14, 0, 0, 1, 1); + if ((!HR1) && (!HR3)) DRLG_L5GChamber(14, 14, 0, 0, 0, 0); + } + if (HR3) DRLG_L5GChamber(28, 14, 0, 0, 1, 0); + if ((HR1) && (HR2)) DRLG_L5GHall(12, 18, 14, 18); + if ((HR2) && (HR3)) DRLG_L5GHall(26, 18, 28, 18); + if ((HR1) && (!HR2) && (HR3)) DRLG_L5GHall(12, 18, 28, 18); + + if (VR1) DRLG_L5GChamber(14, 0, 0, 1, 0, 0); + if (VR2) { + if ((VR1) && (!VR3)) DRLG_L5GChamber(14, 14, 1, 0, 0, 0); + if ((!VR1) && (VR3)) DRLG_L5GChamber(14, 14, 0, 1, 0, 0); + if ((VR1) && (VR3)) DRLG_L5GChamber(14, 14, 1, 1, 0, 0); + if ((!VR1) && (!VR3)) DRLG_L5GChamber(14, 14, 0, 0, 0, 0); + } + if (VR3) DRLG_L5GChamber(14, 28, 1, 0, 0, 0); + if ((VR1) && (VR2)) DRLG_L5GHall(18, 12, 18, 14); + if ((VR2) && (VR3)) DRLG_L5GHall(18, 26, 18, 28); + if ((VR1) && (!VR2) && (VR3)) DRLG_L5GHall(18, 12, 18, 28); + + if (currlevel == NA_KRUL_LEVEL) + { + if ((!VR1) && (!VR2) && (!VR3)) { + // Horizontal + c = 1; // Middle room + if ((!HR1) && (HR2) && (HR3)) { + if (random(0, 2)) c = 2; + } + if ((HR1) && (HR2) && (!HR3)) { + if (random(0, 2)) c = 0; + } + if ((HR1) && (!HR2) && (HR3)) { + if (random(0, 2)) c = 0; + else c = 2; + } + if ((HR1) && (HR2) && (HR3)) c = random(0, 3); + switch (c) { + case 0: + HRLG_L5SetRoom(2,16); + break; + case 1: + HRLG_L5SetRoom(16,16); + break; + case 2: + HRLG_L5SetRoom(30,16); + break; + } + } else { + // Vertical + c = 1; // Middle room + if ((!VR1) && (VR2) && (VR3)) { + if (random(0, 2)) c = 2; + } + if ((VR1) && (VR2) && (!VR3)) { + if (random(0, 2)) c = 0; + } + if ((VR1) && (!VR2) && (VR3)) { + if (random(0, 2)) c = 0; + else c = 2; + } + if ((VR1) && (VR2) && (VR3)) c = random(0, 3); + switch (c) { + case 0: + HRLG_L5SetRoom(16,2); + break; + case 1: + HRLG_L5SetRoom(16,16); + break; + case 2: + HRLG_L5SetRoom(16,30); + break; + } + } + } + if (currlevel == CORNERSTONE_LEVEL) + { + if ((!VR1) && (!VR2) && (!VR3)) { + // Horizontal + c = 1; // Middle room + if ((!HR1) && (HR2) && (HR3)) { + if (random(0, 2)) c = 2; + } + if ((HR1) && (HR2) && (!HR3)) { + if (random(0, 2)) c = 0; + } + if ((HR1) && (!HR2) && (HR3)) { + if (random(0, 2)) c = 0; + else c = 2; + } + if ((HR1) && (HR2) && (HR3)) c = random(0, 3); + switch (c) { + case 0: + CRLG_L5SetRoom(2,16); + break; + case 1: + CRLG_L5SetRoom(16,16); + break; + case 2: + CRLG_L5SetRoom(30,16); + break; + } + } else { + // Vertical + c = 1; // Middle room + if ((!VR1) && (VR2) && (VR3)) { + if (random(0, 2)) c = 2; + } + if ((VR1) && (VR2) && (!VR3)) { + if (random(0, 2)) c = 0; + } + if ((VR1) && (!VR2) && (VR3)) { + if (random(0, 2)) c = 0; + else c = 2; + } + if ((VR1) && (VR2) && (VR3)) c = random(0, 3); + switch (c) { + case 0: + CRLG_L5SetRoom(16,2); + break; + case 1: + CRLG_L5SetRoom(16,16); + break; + case 2: + CRLG_L5SetRoom(16,30); + break; + } + } + } + if (setloadflag) { + if ((!VR1) && (!VR2) && (!VR3)) { + // Horizontal + c = 1; // Middle room + if ((!HR1) && (HR2) && (HR3)) { + if (random(0, 2)) c = 2; + } + if ((HR1) && (HR2) && (!HR3)) { + if (random(0, 2)) c = 0; + } + if ((HR1) && (!HR2) && (HR3)) { + if (random(0, 2)) c = 0; + else c = 2; + } + if ((HR1) && (HR2) && (HR3)) c = random(0, 3); + switch (c) { + case 0: + DRLG_L5SetRoom(2,16); + break; + case 1: + DRLG_L5SetRoom(16,16); + break; + case 2: + DRLG_L5SetRoom(30,16); + break; + } + } else { + // Vertical + c = 1; // Middle room + if ((!VR1) && (VR2) && (VR3)) { + if (random(0, 2)) c = 2; + } + if ((VR1) && (VR2) && (!VR3)) { + if (random(0, 2)) c = 0; + } + if ((VR1) && (!VR2) && (VR3)) { + if (random(0, 2)) c = 0; + else c = 2; + } + if ((VR1) && (VR2) && (VR3)) c = random(0, 3); + switch (c) { + case 0: + DRLG_L5SetRoom(16,2); + break; + case 1: + DRLG_L5SetRoom(16,16); + break; + case 2: + DRLG_L5SetRoom(16,30); + break; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L5FTVR(int i, int j, int x, int y, int d) +{ + if ((dTransVal[x][y] == 0) && (dungeon[i][j] == D_FLOOR)) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + DRLG_L5FTVR(i+1,j, x+2,y, 1); + DRLG_L5FTVR(i-1,j, x-2,y, 2); + DRLG_L5FTVR(i,j+1, x,y+2, 3); + DRLG_L5FTVR(i,j-1, x,y-2, 4); + + DRLG_L5FTVR(i-1,j-1, x-2,y-2, 5); + DRLG_L5FTVR(i+1,j-1, x+2,y-2, 6); + DRLG_L5FTVR(i-1,j+1, x-2,y+2, 7); + DRLG_L5FTVR(i+1,j+1, x+2,y+2, 8); + } else { + if (d == 1) { + dTransVal[x][y] = TransVal; + dTransVal[x][y+1] = TransVal; + } + if (d == 2) { + dTransVal[x+1][y] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 3) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + } + if (d == 4) { + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 5) dTransVal[x+1][y+1] = TransVal; + if (d == 6) dTransVal[x][y+1] = TransVal; + if (d == 7) dTransVal[x+1][y] = TransVal; + if (d == 8) dTransVal[x][y] = TransVal; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L5FloodTVal() +{ + int i, j; + int xx,yy; + + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == D_FLOOR) && (dTransVal[xx][yy] == 0)) { + DRLG_L5FTVR(i,j,xx,yy,0); + TransVal++; + } + xx += 2; + } + yy += 2; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L5TransFix() +{ + int i, j; + int xx,yy; + + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == D_DURC) && (dungeon[i][j-1] == D_DV)) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if ((dungeon[i][j] == D_DLLC) && (dungeon[i+1][j] == D_DH)) { + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == D_DV) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == D_DH) { + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == D_DLRC) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + xx += 2; + } + yy += 2; + } +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void DRLG_L5DirtFix() +{ + int i, j; + + if (currlevel < CRYPTSTART) + { + for (j = 0; j < MDMAXY-1 ; j++) { + for (i = 0; i < MDMAXX-1 ; i++) { + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] != 19)) dungeon[i][j] = 202; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] != 19)) dungeon[i][j] = 200; + if ((dungeon[i][j] == 24) && (dungeon[i+1][j] != 19)) dungeon[i][j] = 205; + + if ((dungeon[i][j] == 18) && (dungeon[i][j+1] != 18)) dungeon[i][j] = 199; + if ((dungeon[i][j] == 21) && (dungeon[i][j+1] != 18)) dungeon[i][j] = 202; + if ((dungeon[i][j] == 23) && (dungeon[i][j+1] != 18)) dungeon[i][j] = 204; + } + } + } + else + { + for (j = 0; j < MDMAXY - 1 ; j++) { + for (i = 0; i < MDMAXX - 1 ; i++) { +// if ((dungeon[i][j] == 21) && (dungeon[i+1][j] != 19)) +// dungeon[i][j] = 85; +// if ((dungeon[i][j] == 19) && (dungeon[i+1][j] != 19)) +// dungeon[i][j] = 83; +// if ((dungeon[i][j] == 24) && (dungeon[i+1][j] != 19)) +// dungeon[i][j] = 88; + +// if ((dungeon[i][j] == 18) && (dungeon[i][j+1] != 18)) +// dungeon[i][j] = 82; +// if ((dungeon[i][j] == 21) && (dungeon[i][j+1] != 18)) +// dungeon[i][j] = 85; +// if ((dungeon[i][j] == 23) && (dungeon[i][j+1] != 18)) + if (dungeon [i][j] == 19) + dungeon[i][j] = 83; + if (dungeon [i][j] == 21) + dungeon[i][j] = 85; + if (dungeon [i][j] == 23) + dungeon[i][j] = 87; + if (dungeon [i][j] == 24) + dungeon[i][j] = 88; + if (dungeon [i][j] == 18) + dungeon[i][j] = 82; + + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void DRLG_L5CornerFix() +{ + int i, j; + + for (j = 1; j < MDMAXY-1; j++) { + for (i = 1; i < MDMAXX-1; i++) { + if (!(dflags[i][j] & SETP_BIT)) { + if ((dungeon[i][j] == 17) && (dungeon[i-1][j] == 13) && (dungeon[i][j-1] == 1)) { + dungeon[i][j] = 16; + dflags[i][j-1] &= SETP_BIT; + } + } + if ((dungeon[i][j] == 202) && (dungeon[i+1][j] == 13) && (dungeon[i][j+1] == 1)) { + dungeon[i][j] = 8; + } + } + } +} + + +static void Statues(int chance) +{ + DRLG_L5PlaceRndSet(STATUE_LEFTA, chance); + DRLG_L5PlaceRndSet(STATUE_LEFTB, chance); + + DRLG_L5PlaceRndSet(STATUE_RIGHTA, chance); + DRLG_L5PlaceRndSet(STATUE_RIGHTB, chance); +} + +static void BrokenWall1(int chance) +{ + DRLG_L5PlaceRndSet(BROKEN_VWALL1, chance); + DRLG_L5PlaceRndSet(BROKEN_HWALL1, chance); + DRLG_L5PlaceRndSet(BROKEN_LRC1, chance); + DRLG_L5PlaceRndSet(BROKEN_ULC1, chance); + DRLG_L5PlaceRndSet(BROKEN_AULC1, chance); + DRLG_L5PlaceRndSet(BROKEN_URC1, chance); + DRLG_L5PlaceRndSet(BROKEN_LLC1, chance); + DRLG_L5PlaceRndSet(BROKEN_AURC1, chance); + DRLG_L5PlaceRndSet(BROKEN_ALLC1, chance); + DRLG_L5PlaceRndSet(BROKEN_TULC11, chance); + DRLG_L5PlaceRndSet(BROKEN_AVW1, chance); + DRLG_L5PlaceRndSet(BROKEN_AHW1, chance); + DRLG_L5PlaceRndSet(BROKEN_FLOOR1, chance); + DRLG_L5PlaceRndSet(BROKEN_TULC21, chance); + DRLG_L5PlaceRndSet(BROKEN_COL1, chance); + DRLG_L5PlaceRndSet(BROKEN_BCAP1, chance); + DRLG_L5PlaceRndSet(BROKEN_RCAP1, chance); +} + +static void BrokenWall2(int chance) +{ + DRLG_L5PlaceRndSet(BROKEN_VWALL2, chance); + DRLG_L5PlaceRndSet(BROKEN_HWALL2, chance); + DRLG_L5PlaceRndSet(BROKEN_LRC2, chance); + DRLG_L5PlaceRndSet(BROKEN_ULC2, chance); + DRLG_L5PlaceRndSet(BROKEN_AULC2, chance); + DRLG_L5PlaceRndSet(BROKEN_URC2, chance); + DRLG_L5PlaceRndSet(BROKEN_LLC2, chance); + DRLG_L5PlaceRndSet(BROKEN_AURC2, chance); + DRLG_L5PlaceRndSet(BROKEN_ALLC2, chance); + DRLG_L5PlaceRndSet(BROKEN_TULC12, chance); + DRLG_L5PlaceRndSet(BROKEN_AVW2, chance); + DRLG_L5PlaceRndSet(BROKEN_AHW2, chance); + DRLG_L5PlaceRndSet(BROKEN_FLOOR2, chance); + DRLG_L5PlaceRndSet(BROKEN_TULC22, chance); + DRLG_L5PlaceRndSet(BROKEN_COL2, chance); + DRLG_L5PlaceRndSet(BROKEN_BCAP2, chance); + DRLG_L5PlaceRndSet(BROKEN_RCAP2, chance); +} + +static void BrokenWall3(int chance) +{ + DRLG_L5PlaceRndSet(BROKEN_VWALL3, chance); + DRLG_L5PlaceRndSet(BROKEN_HWALL3, chance); + DRLG_L5PlaceRndSet(BROKEN_LRC3, chance); + DRLG_L5PlaceRndSet(BROKEN_ULC3, chance); + DRLG_L5PlaceRndSet(BROKEN_AULC3, chance); + DRLG_L5PlaceRndSet(BROKEN_URC3, chance); + DRLG_L5PlaceRndSet(BROKEN_LLC3, chance); + DRLG_L5PlaceRndSet(BROKEN_AURC3, chance); + DRLG_L5PlaceRndSet(BROKEN_ALLC3, chance); + DRLG_L5PlaceRndSet(BROKEN_TULC13, chance); + DRLG_L5PlaceRndSet(BROKEN_AVW3, chance); + DRLG_L5PlaceRndSet(BROKEN_AHW3, chance); + DRLG_L5PlaceRndSet(BROKEN_FLOOR3, chance); + DRLG_L5PlaceRndSet(BROKEN_TULC23, chance); + DRLG_L5PlaceRndSet(BROKEN_COL3, chance); + DRLG_L5PlaceRndSet(BROKEN_BCAP3, chance); + DRLG_L5PlaceRndSet(BROKEN_RCAP3, chance); +} + + + +static void FloorRubble(int chance) +{ + DRLG_L5PlaceRndSet(BIGFLOORR1, chance); + DRLG_L5PlaceRndSet(BIGFLOORR2, chance); + DRLG_L5PlaceRndSet(BIGFLOORR3, chance); + DRLG_L5PlaceRndSet(BIGFLOORR4, chance); + DRLG_L5PlaceRndSet(BIGFLOORR5, chance); + DRLG_L5PlaceRndSet(BIGFLOORR6, chance); + + DRLG_L5PlaceRndSet(FLOORR1, chance); + DRLG_L5PlaceRndSet(FLOORR2, chance); + DRLG_L5PlaceRndSet(FLOORR3, chance); + DRLG_L5PlaceRndSet(FLOORR4, chance); + +} + + + +static void BrokenGrate(int chance) +{ + DRLG_L5PlaceRndSet(ARCHLEFT1A, chance); + DRLG_L5PlaceRndSet(ARCHRIGHT1A, chance); + + DRLG_L5PlaceRndSet(ARCHLEFT1B, chance); + DRLG_L5PlaceRndSet(ARCHRIGHT1B, chance); + + + DRLG_L5PlaceRndSet(GRATELEFT1BA, chance); + DRLG_L5PlaceRndSet(GRATELEFT1BB, chance); + + DRLG_L5PlaceRndSet(GRATELEFT1MA, chance); + DRLG_L5PlaceRndSet(GRATELEFT1MB, chance); + + DRLG_L5PlaceRndSet(GRATELEFT1TA, chance); + DRLG_L5PlaceRndSet(GRATELEFT1TB, chance); + + DRLG_L5PlaceRndSet(GRATERIGHT1RA, chance); + DRLG_L5PlaceRndSet(GRATERIGHT1RB, chance); + + DRLG_L5PlaceRndSet(GRATERIGHT1MA, chance); + DRLG_L5PlaceRndSet(GRATERIGHT1MB, chance); + + DRLG_L5PlaceRndSet(GRATERIGHT1LA, chance); + DRLG_L5PlaceRndSet(GRATERIGHT1LB, chance); + + DRLG_L5PlaceRndSet(FLOOR1B1, chance); + DRLG_L5PlaceRndSet(FLOOR2B1, chance); + DRLG_L5PlaceRndSet(FLOOR3B1, chance); + DRLG_L5PlaceRndSet(FLOOR4B1, chance); + DRLG_L5PlaceRndSet(FLOOR5B1, chance); + DRLG_L5PlaceRndSet(FLOOR6B1, chance); + DRLG_L5PlaceRndSet(FLOOR7B1, chance); + + DRLG_L5PlaceRndSet(BIGFLOORB1, chance); + DRLG_L5PlaceRndSet(BIGFLOORB2, chance); + DRLG_L5PlaceRndSet(BIGFLOORB3, chance); + + +} + +static void NormalGrate(int chance) +{ + DRLG_L5PlaceRndSet(FLOOR1, chance); + DRLG_L5PlaceRndSet(FLOOR2, chance); + DRLG_L5PlaceRndSet(FLOOR3, chance); + DRLG_L5PlaceRndSet(FLOOR4, chance); +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void DRLG_L5(int entry) +{ + long area, minarea; + BOOL doneflag; + int i,j; + int xx,yy; + + doneflag = FALSE; + + switch(currlevel) { + case 1: + minarea = 533; //(L5DUNX*L5DUNY)/3; + break; + case 2: + minarea = 693; //((L5DUNX*L5DUNY)/3) + ((L5DUNX*L5DUNY)/10); + break; + case 3: + case 4: + minarea = 761; //((L5DUNX*L5DUNY)/3) + ((L5DUNX*L5DUNY)/7); + break; + default: + minarea = 761; // Crypt levels + } + while (!doneflag) { + DRLG_InitTrans(); + do{ + InitL5Dungeon(); + L5firstRoom(); + area = L5GetArea(); + } while (area < minarea); + L5makeDungeon(); +//if (currlevel < CRYPTSTART) + L5makeDmt(); + L5FillChambers(); +//if (currlevel < CRYPTSTART) + L5tileFix(); + + L5AddWall(); + L5ClearFlags(); + DRLG_L5FloodTVal(); + + doneflag = TRUE; + + + + if (QuestStatus(Q_PWATER)) { + if (entry == LVL_DOWN) { + if (DRLG_PlaceMiniSet(PWATERIN, 1, 1, 0, 0, 1, -1, LVL_DOWN) < 0) doneflag = FALSE; + } else { + if (DRLG_PlaceMiniSet(PWATERIN, 1, 1, 0, 0, 0, -1, LVL_DOWN) < 0) doneflag = FALSE; + ViewY--; + } + } + + if (QuestStatus(Q_LTBANNER)) { //JKE This might prove a problem if the quest comes up. + if (entry == LVL_DOWN) { + if (DRLG_PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, 1, -1, LVL_DOWN) < 0) doneflag = FALSE; + } else { + if (DRLG_PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, 0, -1, LVL_DOWN) < 0) doneflag = FALSE; + if (entry == LVL_UP) { + ViewX = (setpc_x << 1) + 4 + DIRTEDGED2; + ViewY = (setpc_y << 1) + 12 + DIRTEDGED2; + } else + ViewY--; + } + } else { + if (entry == LVL_DOWN) + { + if (currlevel < CRYPTSTART) + { + if (DRLG_PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, 1, -1, LVL_DOWN) < 0) doneflag = FALSE; + if (DRLG_PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, 0, -1, LVL_UP) < 0) doneflag = FALSE; + } + else + { + if (currlevel == CRYPTSTART) // JKE set town warp up + { + if (DRLG_PlaceMiniSet(WARPSTAIRS, 1, 1, 0, 0, 0, -1, LVL_TWARPDN) < 0) doneflag = FALSE; + if (DRLG_PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, 0, -1, LVL_UP) < 0) doneflag = FALSE; + } + else + { + + if (DRLG_PlaceMiniSet(L5STAIRSUP, 1, 1, 0, 0, 1, -1, LVL_DOWN) < 0) doneflag = FALSE; + if (currlevel !=CRYPTEND) // no stairs down on level 20 JKE + if (DRLG_PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, 0, -1, LVL_UP) < 0) doneflag = FALSE; + } + ++ViewY; + } + } else { + if (entry == LVL_UP){ + if (currlevel < CRYPTSTART) + { + if (DRLG_PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, 0, -1, LVL_DOWN) < 0) doneflag = FALSE; + if (DRLG_PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, 1, -1, LVL_UP) < 0) doneflag = FALSE; + ViewY--; + } + else + { + if (currlevel == CRYPTSTART) // JKE set town warp up + { + if (DRLG_PlaceMiniSet(WARPSTAIRS, 1, 1, 0, 0, 0, -1, LVL_TWARPDN) < 0) doneflag = FALSE; + if (DRLG_PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, 1, -1, LVL_UP) < 0) doneflag = FALSE; + } + else + { + if (DRLG_PlaceMiniSet(L5STAIRSUP, 1, 1, 0, 0, 1, -1, LVL_DOWN) < 0) doneflag = FALSE; + if (currlevel !=CRYPTEND) // no stairs down on level 20 JKE + if (DRLG_PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, 1, -1, LVL_UP) < 0) doneflag = FALSE; + } + ViewY +=3; + } + } else { + if (currlevel < CRYPTSTART) + { + if (DRLG_PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, 0, -1, LVL_DOWN) < 0) doneflag = FALSE; + if (DRLG_PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, 0, -1, LVL_UP) < 0) doneflag = FALSE; + } + else + { + if (currlevel == CRYPTSTART) // JKE set town warp up + { + if (DRLG_PlaceMiniSet(WARPSTAIRS, 1, 1, 0, 0, 1, -1, LVL_TWARPDN) < 0) doneflag = FALSE; + if (DRLG_PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, 0, -1, LVL_UP) < 0) doneflag = FALSE; + } + else + { + if (DRLG_PlaceMiniSet(L5STAIRSUP, 1, 1, 0, 0, 1, -1, LVL_DOWN) < 0) doneflag = FALSE; + if (currlevel !=CRYPTEND) // no stairs down on level 20 JKE + if (DRLG_PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, 0, -1, LVL_UP) < 0) doneflag = FALSE; + } + } + } + } + +// if (currlevel == NA_KRUL_LEVEL) +// if (DRLG_PlaceMiniSet(NA_KRULS_ROOM, 1, 1, 0, 0, 0, -1, LVL_DOWN) < 0) +// doneflag = FALSE; + } + } + + + + // Fix stair trans + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if (dungeon[i][j] == 64) { + xx = (i << 1) + DIRTEDGED2; + yy = (j << 1) + DIRTEDGED2; + DRLG_CopyTrans(xx, yy+1, xx, yy); + DRLG_CopyTrans(xx+1, yy+1, xx+1, yy); + } + } + } + + // Finish/fix trans +// if (currlevel < CRYPTSTART) + DRLG_L5TransFix(); + + // Fix dirt transparency floor corners +// if (currlevel < CRYPTSTART) + DRLG_L5DirtFix(); + +// if (currlevel < CRYPTSTART) + DRLG_L5CornerFix(); + + // Put in doors +// if (currlevel < CRYPTSTART) JKE Turn off crypt doors + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) + if ((dflags[i][j] & SETP_MASK) != NODOOR) DRLG_PlaceDoor(i,j); + } + + // Random subs + if (currlevel < CRYPTSTART) // These are to turn off stuff in the crypt JKE + DRLG_L5Subs(); + else + { + + Statues(L1STATUE); + + DRLG_L5PlaceRndSet(ARCHLEFT, 95); + DRLG_L5PlaceRndSet(ARCHRIGHT, 95); + DRLG_L5PlaceRndSet(GRATELEFT, 100); + DRLG_L5PlaceRndSet(GRATERIGHT, 100); + DRLG_L5PlaceRndSet(BIGFLOOR, 60); + + DRLG_L5Shadows(); + + switch (currlevel) + { + case CRYPTSTART: + BrokenWall1(L1BWALL1); + BrokenWall2(L1BWALL2); + BrokenWall3(L1BWALL3); + DRLG_L5Shadows(); + NormalGrate(L1NGRATE); + BrokenGrate(L1BGRATE); + FloorRubble(L1RFLOOR); + break; + case CRYPTSTART + 1: + NormalGrate(L2NGRATE); + BrokenGrate(L2BGRATE); + FloorRubble(L2RFLOOR); + BrokenWall1(L2BWALL1); + BrokenWall2(L2BWALL2); + BrokenWall3(L2BWALL3); + DRLG_L5Shadows(); + break; + case CRYPTSTART + 2: + NormalGrate(L3NGRATE); + BrokenGrate(L3BGRATE); + FloorRubble(L3RFLOOR); + BrokenWall1(L3BWALL1); + BrokenWall2(L3BWALL2); + BrokenWall3(L3BWALL3); + DRLG_L5Shadows(); + break; + default: + NormalGrate(L4NGRATE); + BrokenGrate(L4BGRATE); + FloorRubble(L4RFLOOR); + BrokenWall1(L4BWALL1); + BrokenWall2(L4BWALL2); + BrokenWall3(L4BWALL3); + DRLG_L5Shadows(); + break; + } + + } + + + // Create shadows + if (currlevel < CRYPTSTART) + DRLG_L1Shadows(); +// else +// DRLG_L5Shadows(); + + // Create mini set pieces + if (currlevel < CRYPTSTART) + DRLG_PlaceMiniSet(LAMPS, 5, 10, 0, 0, 0, -1, LVL_NODIR); + + // Floor subs + if (currlevel < CRYPTSTART) + DRLG_L1Floor(); + +// if (currlevel >= CRYPTSTART) // Place all our specifics here JKE +// { +// DRLG_L5Doors(); +// } + + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) pdungeon[i][j] = dungeon[i][j]; + } + + DRLG_Init_Globals(); + // Check for any mini quest pieces + DRLG_CheckQuests(setpc_x, setpc_y); + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +/* +byte L5TileType(int t) +{ + return(BTYPES[t]); +} +*/ + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +void CreateL5Dungeon(unsigned int rseed, int entry) +{ + int x,y; + + SetRndSeed(rseed); + + dminx = DIRTEDGED2; + dminy = DIRTEDGED2; + dmaxx = DMAXX - (DIRTEDGED2); + dmaxy = DMAXY - (DIRTEDGED2); + + Na_Krul.x = 0; + Na_Krul.y = 0; + Na_Krul.Books = FALSE; + Na_Krul.Open = FALSE; + Na_Krul.LeverX = 0; + Na_Krul.LeverY = 0; + Na_Krul.Lever_Thrown = FALSE; + Na_Krul.MIndex = 0; + + DRLG_InitTrans(); + DRLG_InitSetPC(); + DRLG_LoadL1SP(); + DRLG_L5(entry); + DRLG_L1Pass3(); + DRLG_FreeL1SP(); + if (currlevel < HIVESTART) // JKE NO TOPS!!!!! + DRLG_InitL1Vals(); + else + DRLG_L5Doors(); + DRLG_SetPC(); + + for (y = dminy; y < dmaxy; ++y) + { + for (x = dminx; x < dmaxx; ++x) + { + if (dPiece[x][y] == 290) + { + Na_Krul.x = x; + Na_Krul.y = y; + } + if (dPiece[x][y] == 317) + { + CornerStone.x = x; + CornerStone.y = y; + } + } + } +} diff --git a/src/DRLG_L1.H b/src/DRLG_L1.H new file mode 100644 index 0000000..5ab0fe2 --- /dev/null +++ b/src/DRLG_L1.H @@ -0,0 +1,135 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/DRLG_L1.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXCHRS 17 + +#define D_NULL 0 // Unused/empty space +#define D_VWALL 1 // Vertical wall +#define D_HWALL 2 // Horizontal wall +#define D_LRC 3 // Lower right corner +#define D_ULC 4 // Upper left corner +#define D_AULC 5 // Archway upper left corner +#define D_URC 6 // Upper right corner +#define D_LLC 7 // Lower left corner +#define D_AURC 8 // Archway upper right corner +#define D_ALLC 9 // Archway lower left corner +#define D_TULC1 10 // Transition piece #1 upper left corner +#define D_AVW 11 // Archway veritcal wall +#define D_AHW 12 // Archway horizontal wall +#define D_FLOOR 13 // Floor +#define D_TULC2 14 // Transition piece #2 upper left corner +#define D_COL 15 // Column +#define D_BCAP 16 // Bottom cap +#define D_RCAP 17 // Right cap + +#define D_DV 18 // Dirt with vertical edge +#define D_DH 19 // Dirt with horizontal edge +#define D_DLRC 20 // Dirt lower right corner +#define D_DULC 21 // Dirt upper left corner +#define D_DIRT 22 // Normal Dirt piece +#define D_DURC 23 // Dirt upper right corner +#define D_DLLC 24 // Dirt lower left corener + +#define D_DRV 25 // Door on a vertical wall +#define D_DRH 26 // Door on a horizontal wall +#define D_DDULC 28 // Double door upper left corner +#define D_DRURC 30 // Door on upper right corner +#define D_DRLLC 31 // Door on lower left corner +#define D_DRVT1 40 // Vertical door on transition 1 +#define D_DRVULC 41 // Vertical door on upper left corner +#define D_DRHT2 42 // Horizontal door on transition 2 +#define D_DRHULC 43 // Horizontal door on upper left corner + +#define AREAMIN 4 +#define AREAMAX 12 + +#define NODOOR 0x00 // No door flag +#define HDOOR 0x01 // Horizontal door +#define VDOOR 0x02 // Vertical door +#define DDOOR 0x03 // Double door (both dirs) +//#define SETP_BIT 0x80 // Non changeable set piece bit (defined in gendung.h) +#define SETP_MASK 0x7f +#define SETP_TEMP 0x40 // Temp non changeable set piece bit +#define SETP_TMASK 0xbf + +#define NUMDPATS 9 + +#define NUMSPATS 37 +#define _S1 139 +#define _S2 140 +#define _S3 141 +#define _S4 142 +#define _S5 143 +#define _S6 144 +#define _S7 145 +#define _S8 146 +#define _S9 147 +#define _S10 148 +#define _S11 149 +#define _S12 150 +#define _S13 151 +#define _S14 152 +#define _S15 153 +#define _S16 154 +#define _S17 155 +#define _S18 156 +#define _S19 157 + +#define NUMBLOCKS 206 + +#define NUMSETPIECES 4 + +#define NA_KRUL_LEVEL 24 // change to 24 for real game JKE +#define CORNERSTONE_LEVEL 21 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + int qpat; + int d1; + int d2; + int d3; + int d4; +} DPatsStruct; + +//JKE +typedef struct +{ + int x,y; //location of lower center door mini tile + BOOL Open; // is the place open? + BOOL Books; // were the books used to open? + + int LeverX, LeverY; + BOOL Lever_Thrown; + + int MIndex; + +} Na_Krul_Struct; + +extern Na_Krul_Struct Na_Krul; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +//void CreateL1Dungeon(unsigned int, int); +void LoadL1Dungeon(char [], int, int); +void LoadPreL1Dungeon(char [], int, int); +//void InitL1DirtQuads(); +//void DRLG_L1FloodTVal(); + +byte L5TileType(int t); +void CreateL5Dungeon(unsigned int, int); diff --git a/src/DRLG_L2.CPP b/src/DRLG_L2.CPP new file mode 100644 index 0000000..24dd70f --- /dev/null +++ b/src/DRLG_L2.CPP @@ -0,0 +1,3050 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Dungeon file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DRLG_L2.CPP 2 1/30/97 2:43p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +** CreateL2Dungeon +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "drlg_l2.h" +#include "gendung.h" +#include "engine.h" +#include "trigs.h" +#include "lighting.h" +#include "monster.h" +#include "objects.h" +#include "quests.h" +#include "themes.h" + +/*-----------------------------------------------------------------------** +** Registration info +**-----------------------------------------------------------------------*/ +#include "regconst.h" +char sgszRegSig3[REG_LEN] = "REGISTRATION_BLOCK"; + +/*-----------------------------------------------------------------------** +** File Variables +**-----------------------------------------------------------------------*/ + +int Area_Min = AREA_MIN; +int Room_Max = ROOM_MAX; +//int Room_Min = ROOM_MIN; +int Room_Min = 4; + +HALLNODE * pHallList; +ROOMNODE RoomList [MAX_ROOMS + 1]; +BYTE predungeon[MDMAXX][MDMAXY]; +int Dir_Xadd[5] = {0, 0, 1, 0, -1}; +int Dir_Yadd[5] = {0, -1, 0, 1, 0}; +int nRoomCnt; +int nSx1, nSy1, nSx2, nSy2; + +ShadowStruct SPATSL2[L2_NUMSPATS] = { + { 6, 3, 0, 3, 48, 0, 50 }, + { 9, 3, 0, 3, 48, 0, 50 } +}; + +// Types for tile substitution +byte BTYPESL2[L2_NUMBLOCKS] = { 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, // L2Base + 0, 0, 0, 0, 0, 0, 0, // L2Dirt + 17, 18, // L2Tops + 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 8, // L2Misc + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L2Archs + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L2Skel + 1, 1, 1, 0, 0, 2, 2, 2, 0, 0, 0, 1, // L2Blood + 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, // L2Ruins + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 3, 0, 3, // L2Flats + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L2Big + 0, 0, 0, 0, 0, 0, + 0, 0, 0, // L2New + 0, 0, 0, 0, 0, 0, 0, // L2Dirt2 + 0, 0, 0, 0, 0, 0, 0, 0, // L2NewDrs + 0, 0, 0 }; // L2Stair2 + +byte BSTYPESL2[L2_NUMBLOCKS] = { 0, + 1, 2, 3, 0, 0, 6, 0, 0, 9, // L2Base + 0, 0, 0, 0, 0, 0, 0, // L2Dirt + 0, 0, // L2Tops + 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, // L2Misc + 6, 6, 6, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L2Archs + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // L2Skel + 1, 1, 1, 0, 0, 2, 2, 2, 0, 0, 0, 1, // L2Blood + 1, 1, 1, 6, 2, 2, 2, 0, 3, 3, 3, 3, // L2Ruins + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, // L2Flats + 3, 3, 3, 3, 1, 1, 2, 2, 3, 3, 3, 3, 1, 1, 2, 2, 3, 3, 3, 3, 1, 1, // L2Big + 3, 3, 2, 2, 3, 3, + 0, 0, 0, // L2New + 0, 0, 0, 0, 0, 0, 0, // L2Dirt2 + 0, 0, 0, 0, 0, 0, 0, 0, // L2NewDrs + 0, 0, 0 }; // L2Stair2 + +byte VARCH1[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, URWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH2[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, ULWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH3[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, LRWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH4[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, LLWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH5[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DURWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH6[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DULWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH7[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DLRWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH8[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DLLWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; + +byte VARCH9[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, URWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH10[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, ULWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH11[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, LRWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH12[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, LLWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH13[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DURWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH14[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DULWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH15[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DLRWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH16[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DLLWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; + +byte VARCH17[] = { 2, 3, // X size, Y size + + HWALL_PIECE, URWALL_PIECE, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + 0, URWALL_PIECE, + + 141, 39, // Pattern to sub + 47, 44, + 0, 0}; +byte VARCH18[] = { 2, 3, // X size, Y size + + HWALL_PIECE, URWALL_PIECE, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + 0, ULWALL_PIECE, + + 141, 39, // Pattern to sub + 47, 44, + 0, 0}; +byte VARCH19[] = { 2, 3, // X size, Y size + + HWALL_PIECE, URWALL_PIECE, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + 0, LRWALL_PIECE, + + 141, 39, // Pattern to sub + 47, 44, + 0, 0}; +byte VARCH20[] = { 2, 3, // X size, Y size + + HWALL_PIECE, URWALL_PIECE, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + 0, LLWALL_PIECE, + + 141, 39, // Pattern to sub + 47, 44, + 0, 0}; + +byte VARCH21[] = { 2, 3, // X size, Y size + + HWALL_PIECE, URWALL_PIECE, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + 0, DURWALL_PIECE, + + 141, 39, // Pattern to sub + 47, 44, + 0, 0}; +byte VARCH22[] = { 2, 3, // X size, Y size + + HWALL_PIECE, URWALL_PIECE, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + 0, DULWALL_PIECE, + + 141, 39, // Pattern to sub + 47, 44, + 0, 0}; +byte VARCH23[] = { 2, 3, // X size, Y size + + HWALL_PIECE, URWALL_PIECE, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + 0, DLRWALL_PIECE, + + 141, 39, // Pattern to sub + 47, 44, + 0, 0}; +byte VARCH24[] = { 2, 3, // X size, Y size + + HWALL_PIECE, URWALL_PIECE, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + 0, DLLWALL_PIECE, + + 141, 39, // Pattern to sub + 47, 44, + 0, 0}; + +byte VARCH25[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + FLOOR_PIECE, VWALL_PIECE, + 0, URWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH26[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + FLOOR_PIECE, VWALL_PIECE, + 0, ULWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH27[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + FLOOR_PIECE, VWALL_PIECE, + 0, LRWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH28[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + FLOOR_PIECE, VWALL_PIECE, + 0, LLWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; + +byte VARCH29[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + FLOOR_PIECE, VWALL_PIECE, + 0, DURWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH30[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + FLOOR_PIECE, VWALL_PIECE, + 0, DULWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH31[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + FLOOR_PIECE, VWALL_PIECE, + 0, DLRWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; +byte VARCH32[] = { 2, 4, // X size, Y size + + FLOOR_PIECE, 0, // Pattern to look for + FLOOR_PIECE, VDOOR_PIECE, + FLOOR_PIECE, VWALL_PIECE, + 0, DLLWALL_PIECE, + + 48, 0, // Pattern to sub + 51, 39, + 47, 44, + 0, 0}; + +byte VARCH33[] = { 2, 4, // X size, Y size + + HWALL_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, URWALL_PIECE, + + 142, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH34[] = { 2, 4, // X size, Y size + + HWALL_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, ULWALL_PIECE, + + 142, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH35[] = { 2, 4, // X size, Y size + + HWALL_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, LRWALL_PIECE, + + 142, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH36[] = { 2, 4, // X size, Y size + + HWALL_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, LLWALL_PIECE, + + 142, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH37[] = { 2, 4, // X size, Y size + + HWALL_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DURWALL_PIECE, + + 142, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH38[] = { 2, 4, // X size, Y size + + HWALL_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DULWALL_PIECE, + + 142, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH39[] = { 2, 4, // X size, Y size + + HWALL_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DLRWALL_PIECE, + + 142, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; +byte VARCH40[] = { 2, 4, // X size, Y size + + HWALL_PIECE, 0, // Pattern to look for + FLOOR_PIECE, ULWALL_PIECE, + FLOOR_PIECE, VDOOR_PIECE, + 0, DLLWALL_PIECE, + + 142, 0, // Pattern to sub + 51, 42, + 47, 44, + 0, 0}; + + +byte HARCH1[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HWALL_PIECE, HDOOR_PIECE, LLWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH2[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HWALL_PIECE, HDOOR_PIECE, LRWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH3[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HWALL_PIECE, HDOOR_PIECE, ULWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH4[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HWALL_PIECE, HDOOR_PIECE, URWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH5[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HWALL_PIECE, HDOOR_PIECE, DLLWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH6[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HWALL_PIECE, HDOOR_PIECE, DLRWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH7[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HWALL_PIECE, HDOOR_PIECE, DULWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH8[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HWALL_PIECE, HDOOR_PIECE, DURWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; + +byte HARCH9[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, LLWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH10[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, LRWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH11[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, ULWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH12[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, URWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH13[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, DLLWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH14[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, DLRWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH15[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, DULWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH16[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, DURWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 43, 45, 0}; + +byte HARCH17[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, LLWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH18[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, LRWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH19[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, ULWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH20[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, URWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH21[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, DLLWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH22[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, DLRWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH23[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, DULWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 43, 45, 0}; +byte HARCH24[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + ULWALL_PIECE, HDOOR_PIECE, DURWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 43, 45, 0}; + +byte HARCH25[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HDOOR_PIECE, HWALL_PIECE, LLWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH26[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HDOOR_PIECE, HWALL_PIECE, LRWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH27[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HDOOR_PIECE, HWALL_PIECE, ULWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH28[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HDOOR_PIECE, HWALL_PIECE, URWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH29[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HDOOR_PIECE, HWALL_PIECE, DLLWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH30[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HDOOR_PIECE, HWALL_PIECE, DLRWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH31[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HDOOR_PIECE, HWALL_PIECE, DULWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH32[] = { 3, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, 0, // Pattern to look for + HDOOR_PIECE, HWALL_PIECE, DURWALL_PIECE, + + 49, 46, 0, // Pattern to sub + 40, 45, 0}; + +byte HARCH33[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + LLWALL_PIECE, HDOOR_PIECE, LLWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH34[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + LLWALL_PIECE, HDOOR_PIECE, LRWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH35[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + LLWALL_PIECE, HDOOR_PIECE, ULWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH36[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + LLWALL_PIECE, HDOOR_PIECE, URWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH37[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + LLWALL_PIECE, HDOOR_PIECE, DLLWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH38[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + LLWALL_PIECE, HDOOR_PIECE, DLRWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH39[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + LLWALL_PIECE, HDOOR_PIECE, DULWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 40, 45, 0}; +byte HARCH40[] = { 3, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, 0, // Pattern to look for + LLWALL_PIECE, HDOOR_PIECE, DURWALL_PIECE, + + 140, 46, 0, // Pattern to sub + 40, 45, 0}; + +/*byte USTAIRS[] = { 6, 6, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + + 0, 0, 0, 0, 0, 0, // Pattern to sub + 0, 0, 0, 0, 0, 0, + 0, 0, 72, 77, 0, 0, + 0, 0, 76, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; + +byte DSTAIRS[] = { 6, 6, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + + 0, 0, 0, 0, 0, 0, // Pattern to sub + 0, 0, 0, 0, 0, 0, + 0, 0, 48, 71, 0, 0, + 0, 0, 50, 78, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0}; */ + +byte USTAIRS[] = { 4, 4, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + + 0, 0, 0, 0, + 0, 72, 77, 0, + 0, 76, 0, 0, + 0, 0, 0, 0}; + +byte DSTAIRS[] = { 4, 4, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + + 0, 0, 0, 0, + 0, 48, 71, 0, + 0, 50, 78, 0, + 0, 0, 0, 0}; + +// add to prevent confusion with lvl1 JKE +static byte WARPSTAIRS[] = { 4, 4, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + + 0, 0, 0, 0, + 0, 158, 160, 0, + 0, 159, 0, 0, + 0, 0, 0, 0}; + +byte CRUSHCOL[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + HWALL_PIECE, LRWALL_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + + 0, 0, 0, // Pattern to sub + 0, 83, 0, + 0, 0, 0}; + +byte BIG1[] = { 2, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, + + 113, 0, // Pattern to sub + 112, 0}; + +byte BIG2[] = { 2, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, + + 114, 115, // Pattern to sub + 0, 0}; + +byte BIG3[] = { 1, 2, // X size, Y size + + VWALL_PIECE, // Pattern to look for + VWALL_PIECE, + + 117, // Pattern to sub + 116}; + +byte BIG4[] = { 2, 1, // X size, Y size + + HWALL_PIECE, HWALL_PIECE, // Pattern to look for + + 118, 119}; // Pattern to sub + +byte BIG5[] = { 2, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, + + 120, 122, // Pattern to sub + 121, 123}; + +byte BIG6[] = { 1, 2, // X size, Y size + + VWALL_PIECE, // Pattern to look for + VWALL_PIECE, + + 125, // Pattern to sub + 124}; + +byte BIG7[] = { 2, 1, // X size, Y size + + HWALL_PIECE, HWALL_PIECE, // Pattern to look for + + 126, 127}; // Pattern to sub + +byte BIG8[] = { 2, 2, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, + + 128, 130, // Pattern to sub + 129, 131}; + +byte BIG9[] = { 2, 2, // X size, Y size + + VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + VWALL_PIECE, FLOOR_PIECE, + + 133, 135, // Pattern to sub + 132, 134}; + +byte BIG10[] = { 2, 2, // X size, Y size + + HWALL_PIECE, HWALL_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, + + 136, 137, // Pattern to sub + 3, 3}; +// 138, 139}; + +byte RUINS1[] = { 1, 1, // X size, Y size + + VWALL_PIECE, // Pattern to look for + + 80}; // Pattern to sub +byte RUINS2[] = { 1, 1, // X size, Y size + + VWALL_PIECE, // Pattern to look for + + 81}; // Pattern to sub +byte RUINS3[] = { 1, 1, // X size, Y size + + VWALL_PIECE, // Pattern to look for + + 82}; // Pattern to sub + +byte RUINS4[] = { 1, 1, // X size, Y size + + HWALL_PIECE, // Pattern to look for + + 84}; // Pattern to sub +byte RUINS5[] = { 1, 1, // X size, Y size + + HWALL_PIECE, // Pattern to look for + + 85}; // Pattern to sub +byte RUINS6[] = { 1, 1, // X size, Y size + + HWALL_PIECE, // Pattern to look for + + 86}; // Pattern to sub +byte RUINS7[] = { 1, 1, // X size, Y size + + ULWALL_PIECE, // Pattern to look for + + 87}; // Pattern to sub + +byte PANCREAS1[] = { 5, 3, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + + 0, 0, 0, 0, 0, // Pattern to sub + 0, 0, 108, 0, 0, + 0, 0, 0, 0, 0}; + +byte PANCREAS2[] = { 5, 3, // X size, Y size + + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, // Pattern to look for + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, FLOOR_PIECE, + + 0, 0, 0, 0, 0, // Pattern to sub + 0, 0, 110, 0, 0, + 0, 0, 0, 0, 0}; + +byte CTRDOOR1[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + 0, VDOOR_PIECE, 0, + 0, LLWALL_PIECE, 0, + + 0, 4, 0, // Pattern to sub + 0, 1, 0, + 0, 0, 0}; +byte CTRDOOR2[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + 0, VDOOR_PIECE, 0, + 0, ULWALL_PIECE, 0, + + 0, 4, 0, // Pattern to sub + 0, 1, 0, + 0, 0, 0}; +byte CTRDOOR3[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + 0, VDOOR_PIECE, 0, + 0, LRWALL_PIECE, 0, + + 0, 4, 0, // Pattern to sub + 0, 1, 0, + 0, 0, 0}; +byte CTRDOOR4[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + 0, VDOOR_PIECE, 0, + 0, URWALL_PIECE, 0, + + 0, 4, 0, // Pattern to sub + 0, 1, 0, + 0, 0, 0}; +byte CTRDOOR5[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + 0, VDOOR_PIECE, 0, + 0, DLLWALL_PIECE, 0, + + 0, 4, 0, // Pattern to sub + 0, 1, 0, + 0, 0, 0}; +byte CTRDOOR6[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + 0, VDOOR_PIECE, 0, + 0, DULWALL_PIECE, 0, + + 0, 4, 0, // Pattern to sub + 0, 1, 0, + 0, 0, 0}; +byte CTRDOOR7[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + 0, VDOOR_PIECE, 0, + 0, DLRWALL_PIECE, 0, + + 0, 4, 0, // Pattern to sub + 0, 1, 0, + 0, 0, 0}; +byte CTRDOOR8[] = { 3, 3, // X size, Y size + + FLOOR_PIECE, VWALL_PIECE, FLOOR_PIECE, // Pattern to look for + 0, VDOOR_PIECE, 0, + 0, DURWALL_PIECE, 0, + + 0, 4, 0, // Pattern to sub + 0, 1, 0, + 0, 0, 0}; + +int Patterns[100][10] = { + {0,0,0,0,0,0,0,0,0,FLOOR_PIECE}, // catch all + + {0,0,0,0,CFLOOR,0,0,0,0,FLOOR_PIECE}, // fl + {0,CEoF,0,0,CWALL,0,0,CDoF,0,HWALL_PIECE}, // thw + {0,CDoF,0,0,CWALL,0,0,CEoF,0,HWALL_PIECE}, // bhw + {0,0,0,CEoF,CWALL,CDoF,0,0,0,VWALL_PIECE}, // lvw + {0,0,0,CDoF,CWALL,CEoF,0,0,0,VWALL_PIECE}, // rvw + {0,CWALL,0,0,CDOOR,0,0,CWALL,0,VDOOR_PIECE}, // vd + {0,0,0,CWALL,CDOOR,CWALL,0,0,0,HDOOR_PIECE}, // hd + + {0,CDoW,0,CDoW,CWALL,0,0,0,0,LRWALL_PIECE}, // lr + {0,CDoW,0,0,CWALL,CDoW,0,0,0,LLWALL_PIECE}, // ll + {0,0,0,CDoW,CWALL,0,0,CDoW,0,URWALL_PIECE}, // ur + {0,0,0,0,CWALL,CDoW,0,CDoW,0,ULWALL_PIECE}, // ul + + {0,CDoW,0,CDoW,CDoW,0,CDoWoF,CDoW,0,URWALL_PIECE}, // tint points l + {0,CDoW,CDoWoF,CDoW,CDoW,CDoW,0,0,0,LLWALL_PIECE}, // tint points u + {0,CDoW,0,0,CDoW,CDoW,0,CDoW,CDoWoF,ULWALL_PIECE}, // tint points r + + {CDoW,CDoW,CDoW,CDoW,CDoW,CDoW,0,CDoW,0,ULWALL_PIECE}, // tint points d + {CFLOOR,CDoW,CDoW,CDoW,CDoW,CDoW,0,CDoW,0,ULWALL_PIECE}, // tint points d + {CEoF,CEoF,CEoF,CDoW,CDoW,CDoW,0,CDoW,0,ULWALL_PIECE}, // tint points d + {CDoW,CDoW,CFLOOR,CDoW,CDoW,CDoW,0,CDoW,0,ULWALL_PIECE}, // tint points d + {CDoW,CFLOOR,CDoW,CDoW,CDoW,CDoW,0,CDoW,0,ULWALL_PIECE}, // tint points d + {CFLOOR,CDoW,CDoW,CDoW,CDoW,CDoW,0,CDoW,0,ULWALL_PIECE}, // tint points d + {CDoW,CEoF,CEoF,CDoW,CDoW,CDoW,0,CDoW,0,ULWALL_PIECE}, // tint points d + {CEMPTY,CEMPTY,CDoW,CDoW,CDoW,CDoW,CFLOOR,CDoW,CFLOOR,ULWALL_PIECE}, // tint points d + + {CFLOOR,CFLOOR,CFLOOR,CFLOOR,CDoW,CFLOOR,CFLOOR,CDoW,CFLOOR,URWALL_PIECE}, // line of walls topend + {CFLOOR,CFLOOR,CFLOOR,CFLOOR,CDoW,CFLOOR,CDoW,CDoW,CDoW,URWALL_PIECE}, // line of walls topend + {CFLOOR,CFLOOR,CDoW,CFLOOR,CDoW,CDoW,CFLOOR,CFLOOR,CDoW,LLWALL_PIECE}, // line of walls topend + {CFLOOR,CDoW,CFLOOR,CFLOOR,CDoW,CFLOOR,CFLOOR,CFLOOR,CFLOOR,LRWALL_PIECE}, // line of walls bottomend + {CFLOOR,CFLOOR,CFLOOR,CFLOOR,CDoW,CDoW,CFLOOR,CFLOOR,CFLOOR,LLWALL_PIECE}, // line of walls bottomend + {CFLOOR,CFLOOR,CFLOOR,CDoW,CDoW,CFLOOR,CFLOOR,CFLOOR,CFLOOR,LRWALL_PIECE}, // line of walls bottomend + {CFLOOR,CFLOOR,0,CFLOOR,CDoW,CDoW,CFLOOR,CFLOOR,0,LLWALL_PIECE}, // line of walls bottomend + + {0,0,0,0,CEMPTY,0,0,0,0,DFLOOR_PIECE}, // mt + + {0,CWALL,0,0,CWALL,CEMPTY,0,CWALL,0,DVWALL_PIECE}, // dvw + {0,0,0,CWALL,CWALL,CWALL,0,CEMPTY,0,DHWALL_PIECE}, // dhw + {0,0,0,CDoW,CWALL,CEMPTY,0,CWALL,0,DURWALL_PIECE}, // dur + {0,CDoW,0,CWALL,CWALL,0,0,CEMPTY,0,DLRWALL_PIECE}, // dlr + {0,CDoW,0,0,CWALL,CWALL,0,CEMPTY,0,DLLWALL_PIECE}, // dll + {0,0,0,0,CWALL,CWALL,0,CWALL,CEMPTY,DULWALL_PIECE}, // dul + + {CDoWoF,CDoWoF,CDoWoF,CDoWoF,CWALL,CWALL,0,CWALL,CWALL,DULWALL_PIECE}, // double hwall start + {CDoWoF,CDoWoF,CEMPTY,CDoWoF,CWALL,CWALL,0,CWALL,CWALL,DVWALL_PIECE}, // double hwall start + {0,0,0,CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,DHWALL_PIECE}, // double hwall cont1 + {CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CFLOOR,CFLOOR,CDoWoF,HWALL_PIECE}, // double hwall cont2 + {0,CWALL,0,CWALL,CWALL,CEMPTY,CWALL,CWALL,0,DLRWALL_PIECE}, // double hwall end1 + {0,0,0,CWALL,CWALL,CWALL,CWALL,CWALL,CEMPTY,DHWALL_PIECE}, // double hwall end2 + {CWALL,CWALL,CEMPTY,CWALL,CWALL,CWALL,0,CFLOOR,CFLOOR,HWALL_PIECE}, // double hwall end3 + {CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CDoW,CFLOOR,CDoW,HWALL_PIECE}, // double hwall end4 + {CEMPTY,CWALL,CWALL,CWALL,CWALL,CWALL,CDoW,CFLOOR,CDoW,HWALL_PIECE}, // double hwall end5 + {CFLOOR,CFLOOR,CFLOOR,CWALL,CWALL,CWALL,CEMPTY,CWALL,CWALL,DHWALL_PIECE}, // double hwall end6 + {CEMPTY,CWALL,CWALL,CWALL,CWALL,CWALL,CFLOOR,CFLOOR,CFLOOR,HWALL_PIECE}, // double hwall end7 + {CWALL,CWALL,CEMPTY,CWALL,CWALL,CWALL,CFLOOR,CFLOOR,CWALL,HWALL_PIECE}, // double hwall end8 + {CEMPTY,CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CFLOOR,CFLOOR,HWALL_PIECE}, // double hwall end9 + {CFLOOR,CFLOOR,CDoW,CWALL,CWALL,CWALL,CEMPTY,CWALL,CWALL,DHWALL_PIECE}, // double hwall end10 + {CEMPTY,CWALL,CWALL,CWALL,CWALL,CWALL,CFLOOR,CFLOOR,CDoW,HWALL_PIECE}, // double hwall end11 + {CWALL,CFLOOR,CFLOOR,CWALL,CWALL,CWALL,CEMPTY,CWALL,CWALL,DHWALL_PIECE}, // double hwall end12 + + {0,CWALL,CWALL,0,CWALL,CWALL,0,CWALL,CWALL,DVWALL_PIECE}, // double vwall cont1 + {CFLOOR,CWALL,CWALL,CDOOR,CWALL,CWALL,CFLOOR,CWALL,CWALL,DURWALL_PIECE}, // double vwall cont 1a + {CWALL,CWALL,0,CWALL,CWALL,CFLOOR,CWALL,CWALL,0,VWALL_PIECE}, // double vwall cont2 + {0,CEMPTY,0,CWALL,CWALL,CWALL,0,CWALL,CWALL,DURWALL_PIECE}, // double vwall end1 + {CEMPTY,CWALL,0,CWALL,CWALL,0,CWALL,CWALL,0,VWALL_PIECE}, // double vwall end2 + {0,CWALL,0,CEMPTY,CWALL,CWALL,0,CWALL,CWALL,DLLWALL_PIECE}, // double vwall end3 + {CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,0,CFLOOR,CFLOOR,HWALL_PIECE}, // double vwall end4 + {0,CWALL,CWALL,CFLOOR,CWALL,CWALL,CFLOOR,CWALL,CEMPTY,DVWALL_PIECE}, // double vwall end5 + {CFLOOR,CWALL,CWALL,CWALL,CWALL,CWALL,0,CEMPTY,0,DLRWALL_PIECE}, // double vwall end6 + {CWALL,CWALL,CEMPTY,CWALL,CWALL,CFLOOR,0,CWALL,CFLOOR,VWALL_PIECE}, // double vwall end7 + {CFLOOR,CWALL,CWALL,CFLOOR,CWALL,CWALL,CWALL,CWALL,CEMPTY,DVWALL_PIECE}, // double vwall end8 + {CWALL,CWALL,CFLOOR,CWALL,CWALL,CFLOOR,CEMPTY,CWALL,CDoWoF,VWALL_PIECE}, // double vwall end9 + {CFLOOR,CWALL,CEMPTY,CWALL,CWALL,CWALL,CEMPTY,CEMPTY,CWALL,DLRWALL_PIECE}, // double vwall end10 + + {CFLOOR,CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,DLRWALL_PIECE}, // 2doubles LR connect + {CWALL,CWALL,CFLOOR,CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,DLLWALL_PIECE}, // 2doubles LL connect + {CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CFLOOR,CWALL,CWALL,DURWALL_PIECE}, // 2doubles UR connect + {CEMPTY,CWALL,CWALL,CWALL,CWALL,CWALL,CFLOOR,CWALL,CWALL,DURWALL_PIECE}, // 2doubles UR connect + {CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CWALL,CFLOOR,ULWALL_PIECE}, // 2doubles UL connect + + {0,0,0,0,255,0,0,0,0,0} // end +}; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static BOOL DRLG_L2PlaceMiniSet(byte miniset[], int tmin, int tmax, int cx, int cy, int setview, int ldir) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int i, ii, numt; + int found, bailcnt; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Number of pieces to place + if ((tmax - tmin) == 0) numt = 1; + else numt = random(0, tmax - tmin) + tmin; + + for (i = 0; i < numt; i++) { + // Random starting pos + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + + // Find a location for the mini set piece + found = 0; + bailcnt = 0; + while ((found == 0) && (bailcnt < 200)) { + found = 1; + + if (((sx >= nSx1) && (sx <= nSx2)) && ((sy >= nSy1) && (sy <= nSy2))) found = 0; + + if ((cx != -1) && (sx >= (cx - sw)) && (sx <= (cx + 12))) { + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + found = 0; + } + if ((cy != -1) && (sy >= (cy - sh)) && (sy <= (cy + 12))) { + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + found = 0; + } + ii = 2; + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + if (found == 0) { + sx++; + if (sx == (MDMAXX - sw)) { + sx = 0; + sy++; + if (sy == (MDMAXY - sh)) sy = 0; + } + } + bailcnt++; + } + + if (bailcnt >= 200) return(FALSE); + + // Place mini set piece + ii = (sh * sw) + 2; + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[ii] != 0) dungeon[sx+xx][sy+yy] = miniset[ii]; + ii++; + } + } + } + + if (setview == 1) { + ViewX = (sx << 1) + 3 + (DIRTEDGED2) + 2; + ViewY = (sy << 1) + 4 + (DIRTEDGED2) + 2; + } + + if (ldir == LVL_DOWN) { + LvlViewX = (sx << 1) + 3 + (DIRTEDGED2) + 2; + LvlViewY = (sy << 1) + 4 + (DIRTEDGED2) + 2; + } + + if (ldir == LVL_TWARPDN) { + LvlViewX = (sx << 1) + 3 + (DIRTEDGED2) + 2; + LvlViewY = (sy << 1) + 4 + (DIRTEDGED2) + 2; + } + + return(TRUE); +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2PlaceRndSet(byte miniset[], int rndper) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int ii, jj, kk; + int found; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Find a location for the mini set piece + for (sy = 0; sy < (MDMAXY - sh); sy++) { + for (sx = 0; sx < (MDMAXX - sw); sx++) { + found = 1; + ii = 2; + + if (((sx >= nSx1) && (sx <= nSx2)) && ((sy >= nSy1) && (sy <= nSy2))) found = 0; + + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + + kk = (sh * sw) + 2; + + if (found == 1) { + for (ii = sy - sh; ((ii < (sy + (sh << 1))) && (found == 1)); ii ++) { + for (jj = sx - sw; jj < sx + (sw << 1); jj ++) + if (dungeon[jj][ii] == miniset[kk]) found = 0; + } + } + + if ((found == 1) && (random(0, 100) < rndper)) { + // Place mini set piece + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[kk] != 0) dungeon[sx+xx][sy+yy] = miniset[kk]; + kk++; + } + } + } + } + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2Subs() +{ + int x, y, i, j, k, rv; + byte c; + + for (y = 0; y < MDMAXY; y++) { + for (x = 0; x < MDMAXX; x++) { + if (((x < nSx1) || (x > nSx2)) && ((y < nSy1) || (y > nSy2))) { + rv = random(0, 4); + if (rv == 0) { + c = dungeon[x][y]; + c = BTYPESL2[c]; + if (c != 0) { + rv = random(0, 16); + i = -1; + while (rv >= 0) { + i++; + if (i == L2_NUMBLOCKS) i = 0; + if (c == BTYPESL2[i]) rv--; + } + + for (j = y - 2; j < y + 2; j++) { + for (k = x - 2; k < x + 2; k++) { + if (dungeon[k][j] == i) { + j = y + 3; // indicate a hit + k = x + 2; + } + } + } + if (j < y + 3) dungeon[x][y] = i; + } + } + } + } + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2Shadows() +{ + int x, y, i, patflag; + byte sd[2][2]; + + for (y = 1; y < MDMAXY; y++) { + for (x = 1; x < MDMAXX; x++) { + if ((x == 60) && (y == 21)) patflag = 1; + sd[0][0] = BSTYPESL2[dungeon[x][y]]; + sd[1][0] = BSTYPESL2[dungeon[x-1][y]]; + sd[0][1] = BSTYPESL2[dungeon[x][y-1]]; + sd[1][1] = BSTYPESL2[dungeon[x-1][y-1]]; + for (i = 0; i < L2_NUMSPATS; i++) { + if (SPATSL2[i].strig == sd[0][0]) { + patflag = 1; + if ((SPATSL2[i].s1 != 0) && (SPATSL2[i].s1 != sd[1][1])) patflag = 0; + if ((SPATSL2[i].s2 != 0) && (SPATSL2[i].s2 != sd[0][1])) patflag = 0; + if ((SPATSL2[i].s3 != 0) && (SPATSL2[i].s3 != sd[1][0])) patflag = 0; + if (patflag == 1) { + if (SPATSL2[i].nv1 != 0) dungeon[x-1][y-1] = SPATSL2[i].nv1; + if (SPATSL2[i].nv2 != 0) dungeon[x][y-1] = SPATSL2[i].nv2; + if (SPATSL2[i].nv3 != 0) dungeon[x-1][y] = SPATSL2[i].nv3; + } + } + } + } + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitDungeon() +{ + int i, j; + + for (i = 0; i < MDMAXY; i++) { + + for (j = 0; j < MDMAXX; j++) { + predungeon[j][i] = NO_CHAR; + dflags[j][i] = 0; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_LoadL2SP() +{ + setloadflag = FALSE; + if (QuestStatus(Q_BLIND)) { + pSetPiece = LoadFileInMemSig("Levels\\L2Data\\Blind2.DUN",NULL,'STPC'); + setloadflag = TRUE; + } + else if (QuestStatus(Q_BLOOD)) { + pSetPiece = LoadFileInMemSig("Levels\\L2Data\\Blood1.DUN",NULL,'STPC'); + setloadflag = TRUE; + } + else if (QuestStatus(Q_SCHAMB)) { + pSetPiece = LoadFileInMemSig("Levels\\L2Data\\Bonestr2.DUN",NULL,'STPC'); + setloadflag = TRUE; + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_FreeL2SP() { + DiabloFreePtr(pSetPiece); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2SetRoom(int rx1, int ry1) +{ + int rw,rh; + int i,j; + byte *sp; + + sp = pSetPiece; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_x = rx1; + setpc_y = ry1; + setpc_w = rw; + setpc_h = rh; + + //DRLG_MRectTrans(rx1, ry1, rx2, ry2); + //DRLG_MRectTrans(rx1+2, ry1+2, rx2-2, ry2-2); + + sp = pSetPiece+4; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*sp != 0) { + dungeon[rx1+i][ry1+j] = *sp; + dflags[rx1+i][ry1+j] |= SETP_BIT; + } else dungeon[rx1+i][ry1+j] = 3; + sp+=2; + } + } + } +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DefineRoom(int nX1, int nY1, int nX2, int nY2, int ForceHW) +{ + int i, j; + BYTE ft; + + // Four corners + predungeon[nX1][nY1] = ULWALL_CHAR; + predungeon[nX1][nY2] = LLWALL_CHAR; + predungeon[nX2][nY1] = URWALL_CHAR; + predungeon[nX2][nY2] = LRWALL_CHAR; + + nRoomCnt++; + + RoomList[nRoomCnt].nRoomx1 = nX1; + RoomList[nRoomCnt].nRoomx2 = nX2; + + RoomList[nRoomCnt].nRoomy1 = nY1; + RoomList[nRoomCnt].nRoomy2 = nY2; + if (ForceHW ==1) { + for (i = nX1; i < nX2;i++) { + for (j = nY1; i < nY2; i++) { + dflags[i][j] |= SETP_BIT; + } + } + } + // Horizontal top of room + for (i = nX1 + 1; i <= nX2 - 1; i++) { + predungeon[i][nY1] = WALL_CHAR; + predungeon[i][nY2] = WALL_CHAR; + } + + nY1++; + nY2--; + ft = FLOOR_CHAR; + + for (i = nY1; i <= nY2; i++) { + predungeon[nX1][i] = WALL_CHAR; + predungeon[nX2][i] = WALL_CHAR; + j = nX1 + 1; + + while (j < nX2) { + predungeon[j][i] = ft; + j++; + } + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void CreateDoorType(int nX, int nY) +{ + char dt; + BOOL fDoneflag; + + fDoneflag = FALSE; + + dt = predungeon[nX - 1][nY]; + if (dt == DOOR_CHAR) fDoneflag = TRUE; + + dt = predungeon[nX + 1][nY]; + if (dt == DOOR_CHAR) fDoneflag = TRUE; + + dt = predungeon[nX][nY - 1]; + if (dt == DOOR_CHAR) fDoneflag = TRUE; + + dt = predungeon[nX][nY + 1]; + if (dt == DOOR_CHAR) fDoneflag = TRUE; + + if (predungeon[nX][nY] == URWALL_CHAR || predungeon[nX][nY] == ULWALL_CHAR || + predungeon[nX][nY] == LRWALL_CHAR || predungeon[nX][nY] == LLWALL_CHAR) + fDoneflag = TRUE; + + if (!fDoneflag) predungeon[nX][nY] = DOOR_CHAR; +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void PlaceHallExt(int nX, int nY) +{ + if (predungeon[nX][nY] == NO_CHAR) + predungeon[nX][nY] = HALL_CHAR; +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void AddHall(int nX1, int nY1, int nX2, int nY2, int nHd) +{ + HALLNODE * p1; + HALLNODE * p2; + + if (pHallList == NULL) { + pHallList = (HALLNODE *) DiabloAllocPtrSig(sizeof HALLNODE,'HALL'); + pHallList->nHallx1 = nX1; + pHallList->nHally1 = nY1; + pHallList->nHallx2 = nX2; + pHallList->nHally2 = nY2; + pHallList->nHalldir = nHd; + pHallList->pNext = NULL; + } + else { + p2 = (HALLNODE *) DiabloAllocPtrSig(sizeof HALLNODE,'HALL'); + p2->nHallx1 = nX1; + p2->nHally1 = nY1; + p2->nHallx2 = nX2; + p2->nHally2 = nY2; + p2->nHalldir = nHd; + p2->pNext = NULL; + p1 = pHallList; + + while (p1->pNext != NULL) + p1 = p1->pNext; + p1->pNext = p2; + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void CreateRoom(int nX1, int nY1, int nX2, int nY2, int nRDest, int nHDir, int ForceHW, int nH, int nW) +{ + int nAw, nAh; + int nRw, nRh; + int nRx1, nRy1, nRx2, nRy2; + int nHx1, nHy1, nHx2, nHy2; + int nRid; + + if (nRoomCnt >= MAX_ROOMS) return; + + nAw = nX2 - nX1; + nAh = nY2 - nY1; + + if ((nAw >= Area_Min) && (nAh >= Area_Min)) { + if ((nAw > Room_Max)) + nRw = random(0, Room_Max - Room_Min) + Room_Min; + else { + if (nAw > Room_Min) + nRw = random(0, nAw - Room_Min) + Room_Min; + else + nRw = nAw; + } + + if (nAh > Room_Max) + nRh = random(0, Room_Max - Room_Min) + Room_Min; + else { + if (nAh > Room_Min) + nRh = random(0, nAh - Room_Min) + Room_Min; + else + nRh = nAh; + } + + if (ForceHW == 1) { + nRw = nW; + nRh = nH; + } + + nRx1 = random(0, nX2 - nX1) + nX1; + nRy1 = random(0, nY2 - nY1) + nY1; + nRx2 = nRx1 + nRw; + nRy2 = nRy1 + nRh; + + if (nRx2 > nX2) { + nRx2 = nX2; + nRx1 = nRx2 - nRw; + } + + if (nRy2 > nY2) { + nRy2 = nY2; + nRy1 = nRy2 - nRh; + } + + if (nRx1 >= MDMAXX - 2) nRx1 = MDMAXX - 2; + if (nRy1 >= MDMAXY - 2) nRy1 = MDMAXY - 2; + if (nRx1 <= 1) nRx1 = 1; + if (nRy1 <= 1) nRy1 = 1; + if (nRx2 >= MDMAXX - 2) nRx2 = MDMAXX - 2; + if (nRy2 >= MDMAXY - 2) nRy2 = MDMAXY - 2; + if (nRx2 <= 1) nRx2 = 1; + if (nRy2 <= 1) nRy2 = 1; + + DefineRoom(nRx1, nRy1, nRx2, nRy2, ForceHW); + if (ForceHW == 1) { + nSx1 = nRx1 + 2; + nSy1 = nRy1 + 2; + nSx2 = nRx2; + nSy2 = nRy2; + } + + + nRid = nRoomCnt; + RoomList[nRid].nRoomDest = nRDest; + + if (nRDest != 0) { + if (nHDir == DIR_NORTH) { + nHx1 = random(0, nRx2 - nRx1 - 2) + nRx1 + 1; + nHy1 = nRy1; + nHx2 = RoomList[nRDest].nRoomx2 - RoomList[nRDest].nRoomx1 - 2; + nHx2 = random(0, nHx2) + RoomList[nRDest].nRoomx1 + 1; + nHy2 = RoomList[nRDest].nRoomy2; + } + if (nHDir == DIR_SOUTH) { + nHx1 = random(0, nRx2 - nRx1 - 2) + nRx1 + 1; + nHy1 = nRy2; + nHx2 = RoomList[nRDest].nRoomx2 - RoomList[nRDest].nRoomx1 - 2; + nHx2 = random(0, nHx2) + RoomList[nRDest].nRoomx1 + 1; + nHy2 = RoomList[nRDest].nRoomy1; + } + if (nHDir == DIR_EAST) { + nHx1 = nRx2; + nHy1 = random(0, nRy2 - nRy1 - 2) + nRy1 + 1; + nHx2 = RoomList[nRDest].nRoomx1; + nHy2 = RoomList[nRDest].nRoomy2 - RoomList[nRDest].nRoomy1 - 2; + nHy2 = random(0, nHy2) + RoomList[nRDest].nRoomy1 + 1; + } + if (nHDir == DIR_WEST) { + nHx1 = nRx1; + nHy1 = random(0, nRy2 - nRy1 - 2) + nRy1 + 1; + nHx2 = RoomList[nRDest].nRoomx2; + nHy2 = RoomList[nRDest].nRoomy2 - RoomList[nRDest].nRoomy1 - 2; + nHy2 = random(0, nHy2) + RoomList[nRDest].nRoomy1 + 1; + } + AddHall(nHx1, nHy1, nHx2, nHy2, nHDir); + } + + if (nRh > nRw) { + CreateRoom(nX1 + SNUM2, nY1 + SNUM2, nRx1 - SNUM1, nRy2 - SNUM1, nRid, DIR_EAST, 0, 0, 0); + CreateRoom(nRx2 + SNUM1, nRy1 + SNUM1, nX2 - SNUM2, nY2 - SNUM2, nRid, DIR_WEST, 0, 0, 0); + CreateRoom(nX1 + SNUM2, nRy2 + SNUM1, nRx2 - SNUM1, nY2 - SNUM2, nRid, DIR_NORTH, 0, 0, 0); + CreateRoom(nRx1 + SNUM1, nY1 + SNUM2, nX2 - SNUM2, nRy1 - SNUM1, nRid, DIR_SOUTH, 0, 0, 0); + } + else { + CreateRoom(nX1 + SNUM2, nY1 + SNUM2, nRx2 - SNUM1, nRy1 - SNUM1, nRid, DIR_SOUTH, 0, 0, 0); + CreateRoom(nRx1 + SNUM1, nRy2 + SNUM1, nX2 - SNUM2, nY2 - SNUM2, nRid, DIR_NORTH, 0, 0, 0); + CreateRoom(nX1 + SNUM2, nRy1 + SNUM1, nRx1 - SNUM1, nY2 - SNUM2, nRid, DIR_EAST, 0, 0, 0); + CreateRoom(nRx2 + SNUM1, nY1 + SNUM2, nX2 - SNUM2, nRy2 - SNUM1, nRid, DIR_WEST, 0, 0, 0); + } + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void GetHall(int * nX1, int * nY1, int * nX2, int * nY2, int * nHd) +{ + HALLNODE * p1; + + p1 = pHallList->pNext; + *nX1 = pHallList->nHallx1; + *nY1 = pHallList->nHally1; + *nX2 = pHallList->nHallx2; + *nY2 = pHallList->nHally2; + *nHd = pHallList->nHalldir; + DiabloFreePtr (pHallList); + pHallList = p1; +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void ConnectHall(int nX1, int nY1, int nX2, int nY2, int nHd) +{ + BOOL fDoneflag, fInroom; + int nCurrd, nDx, nDy, nRp; + int nOrigX1, nOrigY1; + int fMinusFlag, fPlusFlag; + + fDoneflag = FALSE; + fMinusFlag = random(0, 100); + fPlusFlag = random(0, 100); + nOrigX1 = nX1; + nOrigY1 = nY1; + + CreateDoorType(nX1, nY1); + CreateDoorType(nX2, nY2); + + nDx = abs(nX2 - nX1); + nDy = abs(nY2 - nY1); + + nCurrd = nHd; + nX2 = nX2 - Dir_Xadd[nCurrd]; + nY2 = nY2 - Dir_Yadd[nCurrd]; + predungeon[nX2][nY2] = HALL_CHAR; + fInroom = FALSE; + + while (!fDoneflag) { + if (nX1 >= MDMAXX - 2 && nCurrd == 2) nCurrd = 4; + if (nY1 >= MDMAXY - 2 && nCurrd == 3) nCurrd = 1; + if (nX1 <= 1 && nCurrd == 4) nCurrd = 2; + if (nY1 <= 1 && nCurrd == 1) nCurrd = 3; + + if (predungeon[nX1][nY1] == ULWALL_CHAR && (nCurrd == 1 || nCurrd == 4)) + nCurrd = 2; + if (predungeon[nX1][nY1] == URWALL_CHAR && (nCurrd == 1 || nCurrd == 2)) + nCurrd = 3; + if (predungeon[nX1][nY1] == LLWALL_CHAR && (nCurrd == 4 || nCurrd == 3)) + nCurrd = 1; + if (predungeon[nX1][nY1] == LRWALL_CHAR && (nCurrd == 2 || nCurrd == 3)) + nCurrd = 4; + + nX1 = nX1 + Dir_Xadd[nCurrd]; + nY1 = nY1 + Dir_Yadd[nCurrd]; + + if (predungeon[nX1][nY1] == NO_CHAR) { + if (fInroom) + CreateDoorType(nX1 - Dir_Xadd[nCurrd], nY1 - Dir_Yadd[nCurrd]); + else { + if (fMinusFlag < 50) { + if (nCurrd == 1 || nCurrd == 3) + PlaceHallExt(nX1 - 1, nY1); + else + PlaceHallExt(nX1, nY1 - 1); + } + if (fPlusFlag < 50) { + if (nCurrd == 1 || nCurrd == 3) + PlaceHallExt(nX1 + 1, nY1); + else + PlaceHallExt(nX1, nY1 + 1); + } + } + predungeon[nX1][nY1] = HALL_CHAR; + fInroom = FALSE; + } + else { + if (!fInroom && predungeon[nX1][nY1] == WALL_CHAR) CreateDoorType(nX1,nY1); + if (predungeon[nX1][nY1] != HALL_CHAR) fInroom = TRUE; + } + + nDx = abs(nX2 - nX1); + nDy = abs(nY2 - nY1); + + if (nDx > nDy) { + nRp = nDx * 2; + if (nRp > 30) nRp = 30; + if (random(0, 100) < nRp) { + if ((nX2 > nX1) && (nX1 < MDMAXX)) + nCurrd = 2; + else + nCurrd = 4; + } + } + else { + nRp = nDy * 5; + if (nRp > 80) nRp = 80; + if (random(0, 100) < nRp) { + if ((nY2 > nY1) && (nY1 < MDMAXY)) + nCurrd = 3; + else + nCurrd = 1; + } + } + + if (nDy < 10) { + if ((nX1 == nX2) && ((nCurrd == DIR_EAST) || (nCurrd == DIR_WEST))) { + if ((nY2 > nY1) && (nY1 < MDMAXY)) + nCurrd = 3; + else + nCurrd = 1; + } + } + + if (nDx < 10) { + if ((nY1 == nY2) && ((nCurrd == DIR_NORTH) || (nCurrd == DIR_SOUTH))) { + if ((nX2 > nX1) && (nX1 < MDMAXX)) + nCurrd = 2; + else + nCurrd = 4; + } + } + + if (nDy == 1 && nDx > 1 && (nCurrd == DIR_NORTH || nCurrd == DIR_SOUTH)) { + if ((nX2 > nX1) && (nX1 < MDMAXX)) + nCurrd = 2; + else + nCurrd = 4; + } + + if (nDx == 1 && nDy > 1 && (nCurrd == DIR_EAST || nCurrd == DIR_WEST)) { + if ((nY2 > nY1) && (nX1 < MDMAXY)) + nCurrd = 3; + else + nCurrd = 1; + } + + if (nDx == 0 && predungeon[nX1][nY1] != NO_CHAR && (nCurrd == DIR_EAST || nCurrd == DIR_WEST)) { + if ((nX2 > nOrigX1) && (nX1 < MDMAXX)) + nCurrd = 3; + else + nCurrd = 1; + } + + if (nDy == 0 && predungeon[nX1][nY1] != NO_CHAR && (nCurrd == DIR_NORTH || nCurrd == DIR_SOUTH)) { + if ((nY2 > nOrigY1) && (nY1 < MDMAXY)) + nCurrd = 2; + else + nCurrd = 4; + } + + if ((nX1 == nX2) && (nY1 == nY2)) fDoneflag = TRUE; + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DoPatternCheck(int i, int j) +{ + int k, l; + int x, y; + int nOk; + + for (k = 0; Patterns[k][4] != 255; k++) { + x = i - 1; + y = j - 1; + nOk = OK; + + for (l = 0; l < 9 && nOk == OK; l ++) { + nOk = NOTOK; + if (l == 3 || l == 6) { + y ++; + x = i - 1; + } + + if (x < 0 || x >= MDMAXX || y < 0 || y >= MDMAXY) + nOk = OK; + else { + switch (Patterns[k][l]) { + case CNO: + nOk = OK; + break; + case CWALL: + if (predungeon[x][y] == WALL_CHAR) + nOk = OK; + break; + case CFLOOR: + if (predungeon[x][y] == FLOOR_CHAR) + nOk = OK; + break; + case CEMPTY: + if (predungeon[x][y] == NO_CHAR) + nOk = OK; + break; + case CDOOR: + if (predungeon[x][y] == DOOR_CHAR) + nOk = OK; + break; + case CDoF: + if (predungeon[x][y] == DOOR_CHAR || predungeon[x][y] == FLOOR_CHAR) + nOk = OK; + break; + case CDoW: + if (predungeon[x][y] == DOOR_CHAR || predungeon[x][y] == WALL_CHAR) + nOk = OK; + break; + case CEoF: + if (predungeon[x][y] == NO_CHAR || predungeon[x][y] == FLOOR_CHAR) + nOk = OK; + break; + case CDoWoF: + if (predungeon[x][y] == DOOR_CHAR || predungeon[x][y] == WALL_CHAR || + predungeon[x][y] == FLOOR_CHAR) + nOk = OK; + break; + } + } + x ++; + } + if (nOk == OK) + dungeon[i][j] = (BYTE) Patterns[k][9]; + else + nOk = NOTOK; + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void L2TileFix() +{ + int i, j; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 3)) dungeon[i][j+1] = 1; + if ((dungeon[i][j] == 3) && (dungeon[i][j+1] == 1)) dungeon[i][j+1] = 3; + + if ((dungeon[i][j] == 3) && (dungeon[i+1][j] == 7)) dungeon[i+1][j] = 3; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 3)) dungeon[i+1][j] = 2; + if ((dungeon[i][j] == 11) && (dungeon[i+1][j] == 14)) dungeon[i+1][j] = 16; + } + } +} +#endif + +#define L2_CONT 0 +#define L2_BOUNDS 1 +#define L2_WALL 2 + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static BOOL DL2_Cont(BOOL x1f, BOOL y1f, BOOL x2f, BOOL y2f) +{ + if (x1f && x2f && y1f && y2f) return(FALSE); + if (x1f && x2f && (y1f || y2f)) return(TRUE); + if (y1f && y2f && (x1f || x2f)) return(TRUE); + return(FALSE); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static int DL2_NumNoChar() +{ + int t = 0; + int ii, jj; + for (jj = 0; jj < MDMAXY; jj++) + for (ii = 0; ii < MDMAXX; ii++) + if (predungeon[ii][jj] == NO_CHAR) t++; + return(t); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DL2_DrawRoom(int x1, int y1, int x2, int y2) +{ + int ii, jj; + + for (jj = y1; jj <= y2; jj++) { + for (ii = x1; ii <= x2; ii++) predungeon[ii][jj] = FLOOR_CHAR; + } + for (jj = y1; jj <= y2; jj++) { + predungeon[x1][jj] = WALL_CHAR; + predungeon[x2][jj] = WALL_CHAR; + } + for (ii = x1; ii <= x2; ii++) { + predungeon[ii][y1] = WALL_CHAR; + predungeon[ii][y2] = WALL_CHAR; + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DL2_KnockWalls(int x1, int y1, int x2, int y2) +{ + int ii, jj; + + for (ii = x1+1; ii < x2; ii++) { + if ((predungeon[ii][y1-1] == FLOOR_CHAR) && (predungeon[ii][y1+1] == FLOOR_CHAR)) predungeon[ii][y1] = FLOOR_CHAR; + if ((predungeon[ii][y2-1] == FLOOR_CHAR) && (predungeon[ii][y2+1] == FLOOR_CHAR)) predungeon[ii][y2] = FLOOR_CHAR; + if (predungeon[ii][y1-1] == DOOR_CHAR) predungeon[ii][y1-1] = FLOOR_CHAR; + if (predungeon[ii][y2+1] == DOOR_CHAR) predungeon[ii][y2+1] = FLOOR_CHAR; + } + for (jj = y1+1; jj < y2; jj++) { + if ((predungeon[x1-1][jj] == FLOOR_CHAR) && (predungeon[x1+1][jj] == FLOOR_CHAR)) predungeon[x1][jj] = FLOOR_CHAR; + if ((predungeon[x2-1][jj] == FLOOR_CHAR) && (predungeon[x2+1][jj] == FLOOR_CHAR)) predungeon[x2][jj] = FLOOR_CHAR; + if (predungeon[x1-1][jj] == DOOR_CHAR) predungeon[x1-1][jj] = FLOOR_CHAR; + if (predungeon[x2+1][jj] == DOOR_CHAR) predungeon[x2+1][jj] = FLOOR_CHAR; + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/* +static void DL2_DoorOrEmptyX(int x, int yy, int y1, int y2) +{ + int sy1, sy2, ry; + + sy1 = sy2 = yy; + while (((predungeon[x-1][sy1-1] == FLOOR_CHAR) && (predungeon[x+1][sy1-1] == FLOOR_CHAR)) && (sy1 > y1)) sy1--; + while (((predungeon[x-1][sy2+1] == FLOOR_CHAR) && (predungeon[x+1][sy2+1] == FLOOR_CHAR)) && (sy2 < y2)) sy2++; + if (random(0, 3) && ((sy2-sy1) > 1)) { + ry = random(0, sy2 - sy1 - 1) + sy1 + 1; + predungeon[x][ry] = DOOR_CHAR; + } else { + for (ry = sy1; ry <= sy2; ry++) predungeon[x][ry] = FLOOR_CHAR; + } +} +*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/* +static void DL2_DoorOrEmptyY(int y, int xx, int x1, int x2) +{ + int sx1, sx2, rx; + + sx1 = sx2 = xx; + while (((predungeon[sx1-1][y-1] == FLOOR_CHAR) && (predungeon[sx1-1][y+1] == FLOOR_CHAR)) && (sx1 > x1)) sx1--; + while (((predungeon[sx2+1][y-1] == FLOOR_CHAR) && (predungeon[sx2+1][y+1] == FLOOR_CHAR)) && (sx2 < x2)) sx2++; + if (random(0, 3) && ((sx2-sx1) > 1)) { + rx = random(0, sx2 - sx1 - 1) + sx1 + 1; + predungeon[rx][y] = DOOR_CHAR; + } else { + for (rx = sx1; rx <= sx2; rx++) predungeon[rx][y] = FLOOR_CHAR; + } +} +*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static BOOL DL2_FillVoids() +{ + int ii, jj, xx, yy; + int x1, x2, y1, y2; + BOOL xf1, xf2, yf1, yf2; + + int to = 0; + while ((DL2_NumNoChar() > 700) && (to < 100)) { + xx = random(0, MDMAXX-2) + 1; + yy = random(0, MDMAXY-2) + 1; + if (predungeon[xx][yy] == WALL_CHAR) { + xf1 = xf2 = yf1 = yf2 = FALSE; + if ((predungeon[xx-1][yy] == NO_CHAR) && (predungeon[xx+1][yy] == FLOOR_CHAR)) { + if ((predungeon[xx+1][yy-1] == FLOOR_CHAR) && (predungeon[xx+1][yy+1] == FLOOR_CHAR) && + (predungeon[xx-1][yy-1] == NO_CHAR) && (predungeon[xx-1][yy+1] == NO_CHAR)) + xf1 = yf1 = yf2 = TRUE; + } else + if ((predungeon[xx+1][yy] == NO_CHAR) && (predungeon[xx-1][yy] == FLOOR_CHAR)) { + if ((predungeon[xx-1][yy-1] == FLOOR_CHAR) && (predungeon[xx-1][yy+1] == FLOOR_CHAR) && + (predungeon[xx+1][yy-1] == NO_CHAR) && (predungeon[xx+1][yy+1] == NO_CHAR)) + xf2 = yf1 = yf2 = TRUE; + } else + if ((predungeon[xx][yy-1] == NO_CHAR) && (predungeon[xx][yy+1] == FLOOR_CHAR)) { + if ((predungeon[xx-1][yy+1] == FLOOR_CHAR) && (predungeon[xx+1][yy+1] == FLOOR_CHAR) && + (predungeon[xx-1][yy-1] == NO_CHAR) && (predungeon[xx+1][yy-1] == NO_CHAR)) + yf1 = xf1 = xf2 = TRUE; + } else + if ((predungeon[xx][yy+1] == NO_CHAR) && (predungeon[xx][yy-1] == FLOOR_CHAR)) { + if ((predungeon[xx-1][yy-1] == FLOOR_CHAR) && (predungeon[xx+1][yy-1] == FLOOR_CHAR) && + (predungeon[xx-1][yy+1] == NO_CHAR) && (predungeon[xx+1][yy+1] == NO_CHAR)) + yf2 = xf1 = xf2 = TRUE; + } + if (DL2_Cont(xf1,yf1,xf2,yf2)) { + if (xf1) x1 = xx-1; + else x1 = xx; + if (xf2) x2 = xx+1; + else x2 = xx; + if (yf1) y1 = yy-1; + else y1 = yy; + if (yf2) y2 = yy+1; + else y2 = yy; + if (!xf1) { + while (yf1 || yf2) { + if (y1 == 0) yf1 = FALSE; + if (y2 == MDMAXY-1) yf2 = FALSE; + if ((y2 - y1) >= ROOM_MAX+4) { + yf1 = FALSE; + yf2 = FALSE; + } + if (yf1) y1--; + if (yf2) y2++; + if (predungeon[x2][y1] != NO_CHAR) yf1 = FALSE; + if (predungeon[x2][y2] != NO_CHAR) yf2 = FALSE; + } + y1 += 2; + y2 -= 2; + if ((y2 - y1) > 5) { + while (xf2) { + if (x2 == MDMAXX-1) xf2 = FALSE; + if ((x2 - x1) >= ROOM_MAX+2) xf2 = FALSE; + for (jj = y1; jj <= y2; jj++) + if (predungeon[x2][jj] != NO_CHAR) xf2 = FALSE; + if (xf2) x2++; + } + x2 -= 2; + if ((x2 - x1) > 5) { + DL2_DrawRoom(x1, y1, x2, y2); + DL2_KnockWalls(x1, y1, x2, y2); + //DL2_DoorOrEmptyX(x1, yy, y1, y2); + } + } + } else + if (!xf2) { + while (yf1 || yf2) { + if (y1 == 0) yf1 = FALSE; + if (y2 == MDMAXY-1) yf2 = FALSE; + if ((y2 - y1) >= ROOM_MAX+4) { + yf1 = FALSE; + yf2 = FALSE; + } + if (yf1) y1--; + if (yf2) y2++; + if (predungeon[x1][y1] != NO_CHAR) yf1 = FALSE; + if (predungeon[x1][y2] != NO_CHAR) yf2 = FALSE; + } + y1 += 2; + y2 -= 2; + if ((y2 - y1) > 5) { + while (xf1) { + if (x1 == 0) xf1 = FALSE; + if ((x2 - x1) >= ROOM_MAX+2) xf1 = FALSE; + for (jj = y1; jj <= y2; jj++) + if (predungeon[x1][jj] != NO_CHAR) xf1 = FALSE; + if (xf1) x1--; + } + x1 += 2; + if ((x2 - x1) > 5) { + DL2_DrawRoom(x1, y1, x2, y2); + DL2_KnockWalls(x1, y1, x2, y2); + //DL2_DoorOrEmptyX(x2, yy, y1, y2); + } + } + } else + if (!yf1) { + while (xf1 || xf2) { + if (x1 == 0) xf1 = FALSE; + if (x2 == MDMAXX-1) xf2 = FALSE; + if ((x2 - x1) >= ROOM_MAX+4) { + xf1 = FALSE; + xf2 = FALSE; + } + if (xf1) x1--; + if (xf2) x2++; + if (predungeon[x1][y2] != NO_CHAR) xf1 = FALSE; + if (predungeon[x2][y2] != NO_CHAR) xf2 = FALSE; + } + x1 += 2; + x2 -= 2; + if ((x2 - x1) > 5) { + while (yf2) { + if (y2 == MDMAXY-1) yf2 = FALSE; + if ((y2 - y1) >= ROOM_MAX+2) yf2 = FALSE; + for (ii = x1; ii <= x2; ii++) + if (predungeon[ii][y2] != NO_CHAR) yf2 = FALSE; + if (yf2) y2++; + } + y2 -= 2; + if ((y2 - y1) > 5) { + DL2_DrawRoom(x1, y1, x2, y2); + DL2_KnockWalls(x1, y1, x2, y2); + //DL2_DoorOrEmptyY(y1, xx, x1, x2); + } + } + } else + if (!yf2) { + while (xf1 || xf2) { + if (x1 == 0) xf1 = FALSE; + if (x2 == MDMAXX-1) xf2 = FALSE; + if ((x2 - x1) >= ROOM_MAX+4) { + xf1 = FALSE; + xf2 = FALSE; + } + if (xf1) x1--; + if (xf2) x2++; + if (predungeon[x1][y1] != NO_CHAR) xf1 = FALSE; + if (predungeon[x2][y1] != NO_CHAR) xf2 = FALSE; + } + x1 += 2; + x2 -= 2; + if ((x2 - x1) > 5) { + while (yf1) { + if (y1 == 0) yf1 = FALSE; + if ((y2 - y1) >= ROOM_MAX+2) yf1 = FALSE; + for (ii = x1; ii <= x2; ii++) + if (predungeon[ii][y1] != NO_CHAR) yf1 = FALSE; + if (yf1) y1--; + } + y1 += 2; + if ((y2 - y1) > 5) { + DL2_DrawRoom(x1, y1, x2, y2); + DL2_KnockWalls(x1, y1, x2, y2); + //DL2_DoorOrEmptyY(y2, xx, x1, x2); + } + } + } + } + to++; + } + } + if (DL2_NumNoChar() > 700) return(FALSE); + return(TRUE); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static BOOL CreateDungeon() +{ + int i, j; + int nHx1, nHy1, nHx2, nHy2, nHd; + int ForceH,ForceW,ForceHW; + + ForceHW = ForceH = ForceW = 0; + + switch(currlevel) { + case 5 : + if (quests[Q_BLOOD]._qactive != QUEST_NOTAVAIL) { + ForceHW = 1; + ForceH = 20; + ForceW = 14; + } + break; + case 6 : + if (quests[Q_SCHAMB]._qactive != QUEST_NOTAVAIL) { + ForceHW = 1; + ForceH = ForceW = 10; + } + break; + case 7 : + if(quests[Q_BLIND]._qactive != QUEST_NOTAVAIL) { + ForceHW = 1; + ForceH = ForceW = 15; + } + break; + case 8 : + break; + default: + break; // to use level 2 for crypt + } + + CreateRoom(2, 2, MDMAXX - 1, MDMAXY - 1, 0, DIR_NONE, ForceHW, ForceH, ForceW); + + while (pHallList != NULL) { + GetHall(&nHx1, &nHy1, &nHx2, &nHy2, &nHd); + ConnectHall(nHx1, nHy1, nHx2, nHy2, nHd); + } + + for (j = 0; j <= MDMAXY; j++) { + for (i = 0; i <= MDMAXX; i++) { + if (predungeon[i][j] == ULWALL_CHAR) predungeon[i][j] = WALL_CHAR; + if (predungeon[i][j] == URWALL_CHAR) predungeon[i][j] = WALL_CHAR; + if (predungeon[i][j] == LLWALL_CHAR) predungeon[i][j] = WALL_CHAR; + if (predungeon[i][j] == LRWALL_CHAR) predungeon[i][j] = WALL_CHAR; + if (predungeon[i][j] == HALL_CHAR) { + predungeon[i][j] = FLOOR_CHAR; + if (predungeon[i - 1][j - 1] == NO_CHAR) predungeon[i - 1][j - 1] = WALL_CHAR; + if (predungeon[i - 1][j - 0] == NO_CHAR) predungeon[i - 1][j - 0] = WALL_CHAR; + if (predungeon[i - 1][j + 1] == NO_CHAR) predungeon[i - 1][j + 1] = WALL_CHAR; + if (predungeon[i + 1][j - 1] == NO_CHAR) predungeon[i + 1][j - 1] = WALL_CHAR; + if (predungeon[i + 1][j - 0] == NO_CHAR) predungeon[i + 1][j - 0] = WALL_CHAR; + if (predungeon[i + 1][j + 1] == NO_CHAR) predungeon[i + 1][j + 1] = WALL_CHAR; + if (predungeon[i - 0][j - 1] == NO_CHAR) predungeon[i - 0][j - 1] = WALL_CHAR; + if (predungeon[i - 0][j + 1] == NO_CHAR) predungeon[i - 0][j + 1] = WALL_CHAR; + } + } + } + + // New Dave code 10/11 + if (!DL2_FillVoids()) return(FALSE); + // End new Dave code + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) + DoPatternCheck(i, j); + } + return(TRUE); +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2Pass3() +{ + int i,j,xx,yy; + long v1,v2,v3,v4,lv; + + // Init dungeon to dirt + lv = 11; // 12 - 1 + __asm { + mov esi,dword ptr [pMegaTiles] + mov eax,dword ptr [lv]; + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + for (yy = 0; yy < DMAXY; yy+=2) { + for (xx = 0; xx < DMAXX; xx+=2) { + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + } + } + + // Convert dungeon mega tiles to mini tiles + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + lv = ((long)dungeon[i][j]) - 1; + __asm { + mov esi,dword ptr [pMegaTiles] + mov eax,dword ptr [lv]; + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + xx += 2; + } + yy += 2; + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2FTVR(int i, int j, int x, int y, int d) +{ + if ((dTransVal[x][y] == 0) && (dungeon[i][j] == FLOOR_PIECE)) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + DRLG_L2FTVR(i+1,j, x+2,y, 1); + DRLG_L2FTVR(i-1,j, x-2,y, 2); + DRLG_L2FTVR(i,j+1, x,y+2, 3); + DRLG_L2FTVR(i,j-1, x,y-2, 4); + + DRLG_L2FTVR(i-1,j-1, x-2,y-2, 5); + DRLG_L2FTVR(i+1,j-1, x+2,y-2, 6); + DRLG_L2FTVR(i-1,j+1, x-2,y+2, 7); + DRLG_L2FTVR(i+1,j+1, x+2,y+2, 8); + } else { + if (d == 1) { + dTransVal[x][y] = TransVal; + dTransVal[x][y+1] = TransVal; + } + if (d == 2) { + dTransVal[x+1][y] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 3) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + } + if (d == 4) { + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 5) dTransVal[x+1][y+1] = TransVal; + if (d == 6) dTransVal[x][y+1] = TransVal; + if (d == 7) dTransVal[x+1][y] = TransVal; + if (d == 8) dTransVal[x][y] = TransVal; + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2FloodTVal() +{ + int i, j; + int xx,yy; + + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == FLOOR_PIECE) && (dTransVal[xx][yy] == 0)) { + DRLG_L2FTVR(i,j,xx,yy,0); + TransVal++; + } + xx += 2; + } + yy += 2; + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2TransFix() +{ + int i, j; + int xx,yy; + + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == DURWALL_PIECE) && (dungeon[i][j-1] == DVWALL_PIECE)) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if ((dungeon[i][j] == DLLWALL_PIECE) && (dungeon[i+1][j] == DHWALL_PIECE)) { + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == DVWALL_PIECE) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == DHWALL_PIECE) { + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == DLRWALL_PIECE) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + xx += 2; + } + yy += 2; + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void L2DirtFix() +{ + int i, j; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 13) && (dungeon[i+1][j] != 11)) dungeon[i][j] = 146; + if ((dungeon[i][j] == 11) && (dungeon[i+1][j] != 11)) dungeon[i][j] = 144; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] != 11)) dungeon[i][j] = 148; + + if ((dungeon[i][j] == 10) && (dungeon[i][j+1] != 10)) dungeon[i][j] = 143; + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] != 10)) dungeon[i][j] = 146; + if ((dungeon[i][j] == 14) && (dungeon[i][j+1] != 15)) dungeon[i][j] = 147; + } + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void L2LockoutFix() +{ + int i, j; + BOOL doorok; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 4) && (dungeon[i-1][j] != 3)) dungeon[i][j] = 1; + if ((dungeon[i][j] == 5) && (dungeon[i][j-1] != 3)) dungeon[i][j] = 2; + } + } + + for (j = 1; j < MDMAXY-1; j++) { + for (i = 1; i < MDMAXX-1; i++) { + if (!(dflags[i][j] & SETP_BIT)) { + if (((dungeon[i][j] == 2) || (dungeon[i][j] == 5)) && (dungeon[i][j-1] == 3) && (dungeon[i][j+1] == 3)) { + doorok = FALSE; + while (((dungeon[i][j] == 2) || (dungeon[i][j] == 5)) && (dungeon[i][j-1] == 3) && (dungeon[i][j+1] == 3)) { + if (dungeon[i][j] == 5) doorok = TRUE; + i++; + } + if (!doorok && !(dflags[i-1][j] & SETP_BIT)) { + dungeon[i-1][j] = 5; + } + } + } + } + } + for (i = 1; i < MDMAXX-1; i++) { + for (j = 1; j < MDMAXY-1; j++) { + if (!(dflags[i][j] & SETP_BIT)) { + if (((dungeon[i][j] == 1) || (dungeon[i][j] == 4)) && (dungeon[i-1][j] == 3) && (dungeon[i+1][j] == 3)) { + doorok = FALSE; + while (((dungeon[i][j] == 1) || (dungeon[i][j] == 4)) && (dungeon[i-1][j] == 3) && (dungeon[i+1][j] == 3)) { + if (dungeon[i][j] == 4) doorok = TRUE; + j++; + } + if (!doorok && !(dflags[i][j-1] & SETP_BIT)) { + dungeon[i][j-1] = 4; + } + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void L2DoorFix() +{ + int i, j; + + for (j = 1; j < MDMAXY; j++) { + for (i = 1; i < MDMAXX; i++) { + if ((dungeon[i][j] == 4) && (dungeon[i][j-1] == 3)) + dungeon[i][j] = 7; + if ((dungeon[i][j] == 5) && (dungeon[i-1][j] == 3)) + dungeon[i][j] = 9; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_L2(int entry) +{ + int i,j; + BOOL doneflag; + + doneflag = FALSE; + while (!doneflag) { + nRoomCnt = 0; + InitDungeon(); + DRLG_InitTrans(); + + if (CreateDungeon()) { + L2TileFix(); + + if (setloadflag) { + DRLG_L2SetRoom(nSx1,nSy1); + } + DRLG_L2FloodTVal(); + DRLG_L2TransFix(); + + if (entry == LVL_DOWN) { + doneflag = DRLG_L2PlaceMiniSet(USTAIRS, 1, 1, -1, -1, 1, LVL_DOWN); + + #if IS_VERSION(RETAIL) + if (doneflag) doneflag = DRLG_L2PlaceMiniSet(DSTAIRS, 1, 1, -1, -1, 0, LVL_UP); + #endif + + if ((doneflag) && (currlevel == 5)) doneflag = DRLG_L2PlaceMiniSet(WARPSTAIRS, 1, 1, -1, -1, 0, LVL_TWARPDN); + + ViewY -= 2; + } else { + if (entry == LVL_UP) { + doneflag = DRLG_L2PlaceMiniSet(USTAIRS, 1, 1, -1, -1, 0, LVL_DOWN); + #if IS_VERSION(RETAIL) + if (doneflag) doneflag = DRLG_L2PlaceMiniSet(DSTAIRS, 1, 1, -1, -1, 1, LVL_UP); + #endif + if ((doneflag) && (currlevel == 5)) doneflag = DRLG_L2PlaceMiniSet(WARPSTAIRS, 1, 1, -1, -1, 0, LVL_TWARPDN); + ViewX--; + } else { + doneflag = DRLG_L2PlaceMiniSet(USTAIRS, 1, 1, -1, -1, 0, LVL_DOWN); + #if IS_VERSION(RETAIL) + if (doneflag) doneflag = DRLG_L2PlaceMiniSet(DSTAIRS, 1, 1, -1, -1, 0, LVL_UP); + #endif + if ((doneflag) && (currlevel == 5)) doneflag = DRLG_L2PlaceMiniSet(WARPSTAIRS, 1, 1, -1, -1, 1, LVL_TWARPDN); + ViewY -= 2; + } + } + } + } + + L2LockoutFix(); + + L2DoorFix(); + + L2DirtFix(); + + if (doneflag) DRLG_PlaceThemeRooms(6, 10, FLOOR_PIECE, 0, FALSE); + + DRLG_L2PlaceRndSet(CTRDOOR1, 100); + DRLG_L2PlaceRndSet(CTRDOOR2, 100); + DRLG_L2PlaceRndSet(CTRDOOR3, 100); + DRLG_L2PlaceRndSet(CTRDOOR4, 100); + DRLG_L2PlaceRndSet(CTRDOOR5, 100); + DRLG_L2PlaceRndSet(CTRDOOR6, 100); + DRLG_L2PlaceRndSet(CTRDOOR7, 100); + DRLG_L2PlaceRndSet(CTRDOOR8, 100); + + DRLG_L2PlaceRndSet(VARCH33, 100); + DRLG_L2PlaceRndSet(VARCH34, 100); + DRLG_L2PlaceRndSet(VARCH35, 100); + DRLG_L2PlaceRndSet(VARCH36, 100); + DRLG_L2PlaceRndSet(VARCH37, 100); + DRLG_L2PlaceRndSet(VARCH38, 100); + DRLG_L2PlaceRndSet(VARCH39, 100); + DRLG_L2PlaceRndSet(VARCH40, 100); + + DRLG_L2PlaceRndSet(VARCH1, 100); + DRLG_L2PlaceRndSet(VARCH2, 100); + DRLG_L2PlaceRndSet(VARCH3, 100); + DRLG_L2PlaceRndSet(VARCH4, 100); + DRLG_L2PlaceRndSet(VARCH5, 100); + DRLG_L2PlaceRndSet(VARCH6, 100); + DRLG_L2PlaceRndSet(VARCH7, 100); + DRLG_L2PlaceRndSet(VARCH8, 100); + + DRLG_L2PlaceRndSet(VARCH9, 100); + DRLG_L2PlaceRndSet(VARCH10, 100); + DRLG_L2PlaceRndSet(VARCH11, 100); + DRLG_L2PlaceRndSet(VARCH12, 100); + DRLG_L2PlaceRndSet(VARCH13, 100); + DRLG_L2PlaceRndSet(VARCH14, 100); + DRLG_L2PlaceRndSet(VARCH15, 100); + DRLG_L2PlaceRndSet(VARCH16, 100); + + DRLG_L2PlaceRndSet(VARCH17, 100); + DRLG_L2PlaceRndSet(VARCH18, 100); + DRLG_L2PlaceRndSet(VARCH19, 100); + DRLG_L2PlaceRndSet(VARCH20, 100); + DRLG_L2PlaceRndSet(VARCH21, 100); + DRLG_L2PlaceRndSet(VARCH22, 100); + DRLG_L2PlaceRndSet(VARCH23, 100); + DRLG_L2PlaceRndSet(VARCH24, 100); + + DRLG_L2PlaceRndSet(VARCH25, 100); + DRLG_L2PlaceRndSet(VARCH26, 100); + DRLG_L2PlaceRndSet(VARCH27, 100); + DRLG_L2PlaceRndSet(VARCH28, 100); + DRLG_L2PlaceRndSet(VARCH29, 100); + DRLG_L2PlaceRndSet(VARCH30, 100); + DRLG_L2PlaceRndSet(VARCH31, 100); + DRLG_L2PlaceRndSet(VARCH32, 100); + + DRLG_L2PlaceRndSet(HARCH1, 100); + DRLG_L2PlaceRndSet(HARCH2, 100); + DRLG_L2PlaceRndSet(HARCH3, 100); + DRLG_L2PlaceRndSet(HARCH4, 100); + DRLG_L2PlaceRndSet(HARCH5, 100); + DRLG_L2PlaceRndSet(HARCH6, 100); + DRLG_L2PlaceRndSet(HARCH7, 100); + DRLG_L2PlaceRndSet(HARCH8, 100); + DRLG_L2PlaceRndSet(HARCH9, 100); + DRLG_L2PlaceRndSet(HARCH10, 100); + DRLG_L2PlaceRndSet(HARCH11, 100); + DRLG_L2PlaceRndSet(HARCH12, 100); + DRLG_L2PlaceRndSet(HARCH13, 100); + DRLG_L2PlaceRndSet(HARCH14, 100); + DRLG_L2PlaceRndSet(HARCH15, 100); + DRLG_L2PlaceRndSet(HARCH16, 100); + DRLG_L2PlaceRndSet(HARCH17, 100); + DRLG_L2PlaceRndSet(HARCH18, 100); + DRLG_L2PlaceRndSet(HARCH19, 100); + DRLG_L2PlaceRndSet(HARCH20, 100); + DRLG_L2PlaceRndSet(HARCH21, 100); + DRLG_L2PlaceRndSet(HARCH22, 100); + DRLG_L2PlaceRndSet(HARCH23, 100); + DRLG_L2PlaceRndSet(HARCH24, 100); + + DRLG_L2PlaceRndSet(HARCH25, 100); + DRLG_L2PlaceRndSet(HARCH26, 100); + DRLG_L2PlaceRndSet(HARCH27, 100); + DRLG_L2PlaceRndSet(HARCH28, 100); + DRLG_L2PlaceRndSet(HARCH29, 100); + DRLG_L2PlaceRndSet(HARCH30, 100); + DRLG_L2PlaceRndSet(HARCH31, 100); + DRLG_L2PlaceRndSet(HARCH32, 100); + + DRLG_L2PlaceRndSet(HARCH33, 100); + DRLG_L2PlaceRndSet(HARCH34, 100); + DRLG_L2PlaceRndSet(HARCH35, 100); + DRLG_L2PlaceRndSet(HARCH36, 100); + DRLG_L2PlaceRndSet(HARCH37, 100); + DRLG_L2PlaceRndSet(HARCH38, 100); + DRLG_L2PlaceRndSet(HARCH39, 100); + DRLG_L2PlaceRndSet(HARCH40, 100); + + DRLG_L2PlaceRndSet(CRUSHCOL, 99); + + DRLG_L2PlaceRndSet(RUINS1, 10); + DRLG_L2PlaceRndSet(RUINS2, 10); + DRLG_L2PlaceRndSet(RUINS3, 10); + DRLG_L2PlaceRndSet(RUINS4, 10); + DRLG_L2PlaceRndSet(RUINS5, 10); + DRLG_L2PlaceRndSet(RUINS6, 10); + DRLG_L2PlaceRndSet(RUINS7, 50); + + DRLG_L2PlaceRndSet(PANCREAS1, 1); + DRLG_L2PlaceRndSet(PANCREAS2, 1); + + DRLG_L2PlaceRndSet(BIG1, 3); // 1x2 water + DRLG_L2PlaceRndSet(BIG2, 3); // 2x1 water + DRLG_L2PlaceRndSet(BIG3, 3); // 1x2 ruined box + DRLG_L2PlaceRndSet(BIG4, 3); // 2x1 ruined box + DRLG_L2PlaceRndSet(BIG5, 3); // 2x2 water + DRLG_L2PlaceRndSet(BIG6, 20); // 1x2 wall water + DRLG_L2PlaceRndSet(BIG7, 20); // 2x1 wall water + DRLG_L2PlaceRndSet(BIG8, 3); // 2x2 rubble pile + DRLG_L2PlaceRndSet(BIG9, 20); // 2x2 vwall ruins + DRLG_L2PlaceRndSet(BIG10, 20); // 2x2 hwall ruins + + DRLG_L2Subs(); + DRLG_L2Shadows(); + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) pdungeon[i][j] = dungeon[i][j]; + } + + extern void DRLG_Init_Globals(); + DRLG_Init_Globals(); + // Check for any mini quest pieces + DRLG_CheckQuests(nSx1, nSy1); + +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +static void DRLG_InitL2Vals() +{ + int i,j; + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + // place tops of arches + int nPiece = dPiece[i][j]; + if (nPiece == 541) nPiece = 5; + else if (nPiece == 178) nPiece = 5; + else if (nPiece == 551) nPiece = 5; + else if (nPiece == 542) nPiece = 6; + else if (nPiece == 553) nPiece = 6; + else if (nPiece == 13) nPiece = 5; + else if (nPiece == 17) nPiece = 6; + else continue; + + dSpecial[i][j] = nPiece; + } + } + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 132) { + dSpecial[i][j+1] = 2; + dSpecial[i][j+2] = 1; + } + else if ((dPiece[i][j] == 135) || (dPiece[i][j] == 139)) { + dSpecial[i+1][j] = 3; + dSpecial[i+2][j] = 4; + } + } + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +void LoadL2Dungeon(char sFileName[], int vx, int vy) +{ + int i, j, rw, rh; + byte *pLevelMap, *lm; + + InitDungeon(); + DRLG_InitTrans(); + + pLevelMap = LoadFileInMemSig(sFileName,NULL,'LMPt'); + lm = pLevelMap; + + // Fill with dirt + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + dungeon[i][j] = DFLOOR_PIECE; + dflags[i][j] = 0; + } + } + + rw = *lm; + lm+=2; + rh = *lm; + lm+=2; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*lm != 0) { + dungeon[i][j] = *lm; + dflags[i][j] |= SETP_BIT; + } else dungeon[i][j] = FLOOR_PIECE; + lm+=2; + } + } + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if (dungeon[i][j] == 0) + dungeon[i][j] = DFLOOR_PIECE; + } + } + + DRLG_L2Pass3(); + + extern void DRLG_Init_Globals(); + DRLG_Init_Globals(); + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + int nPiece = dPiece[i][j]; + int top = 0; + if (nPiece == 541) top = 5; + if (nPiece == 178) top = 5; + if (nPiece == 551) top = 5; + if (nPiece == 542) top = 6; + if (nPiece == 553) top = 6; + if (nPiece == 13) top = 5; + if (nPiece == 17) top = 6; + dSpecial[i][j] = top; + } + } + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 132) { + dSpecial[i][j+1] = 2; + dSpecial[i][j+2] = 1; + } + else if ((dPiece[i][j] == 135) || (dPiece[i][j] == 139)) { + dSpecial[i+1][j] = 3; + dSpecial[i+2][j] = 4; + } + } + } + + ViewX = vx; + ViewY = vy; + + SetMapMonsters(pLevelMap, 0, 0); + SetMapObjects(pLevelMap, 0, 0); + //SetMapItems(pLevelMap); + + DiabloFreePtr(pLevelMap); +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +void LoadPreL2Dungeon(char sFileName[], int vx, int vy) +{ + int i, j, rw, rh; + byte *pLevelMap, *lm; + + InitDungeon(); + DRLG_InitTrans(); + + pLevelMap = LoadFileInMemSig(sFileName,NULL,'LMPt'); + lm = pLevelMap; + + // Fill with dirt + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + dungeon[i][j] = DFLOOR_PIECE; + dflags[i][j] = 0; + } + } + + rw = *lm; + lm+=2; + rh = *lm; + lm+=2; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*lm != 0) { + dungeon[i][j] = *lm; + dflags[i][j] |= SETP_BIT; + } else dungeon[i][j] = FLOOR_PIECE; + lm+=2; + } + } + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) + if (dungeon[i][j] == 0) dungeon[i][j] = DFLOOR_PIECE; + } + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) pdungeon[i][j] = dungeon[i][j]; + } + + DiabloFreePtr(pLevelMap); +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) +void CreateL2Dungeon(unsigned int rseed, int entry) +{ +// dig.patch1.start.1/30/97 + + // The variables nSx1,nSx2,nSy1,nSy2 weren't getting initialized for level 8, + // nor for level 7 when the Q_BLIND quest is not chosen. + // The result of not setting those variables is that those levels + // differ slightly when they are loaded versus when they are generated. + + // Fix: In the above mentioned cases (level 8, and level 7 without Q_BLIND) + // we need to generate values for nSx1 etc. that are identical to how they + // were set when the levels were generated. The way to do that is to figure + // out which was the last level which set those variables, and temporarily + // recreate that level. + // Level 6 always generates values for the variables. + // Level 7 generates values only if (quests[Q_BLIND]._qactive != QUEST_NOTAVAIL) + + extern DWORD glSeedTbl[NUMLEVELS]; + extern BYTE gbMaxPlayers; + if (gbMaxPlayers == 1) { + if (currlevel == 7 && quests[Q_BLIND]._qactive == QUEST_NOTAVAIL) { + currlevel = 6; + CreateL2Dungeon(glSeedTbl[6], LVL_NODIR); + currlevel = 7; + } + if (currlevel == 8) { + if (quests[Q_BLIND]._qactive == QUEST_NOTAVAIL) { + currlevel = 6; + CreateL2Dungeon(glSeedTbl[6], LVL_NODIR); + currlevel = 8; + } + else { + currlevel = 7; + CreateL2Dungeon(glSeedTbl[7], LVL_NODIR); + currlevel = 8; + } + } + } +// dig.patch1.end.1/30/97 + + SetRndSeed(rseed); + + dminx = DIRTEDGED2; + dminy = DIRTEDGED2; + dmaxx = DMAXX - (DIRTEDGED2); + dmaxy = DMAXY - (DIRTEDGED2); + + DRLG_InitTrans(); + DRLG_InitSetPC(); + DRLG_LoadL2SP(); + DRLG_L2(entry); + DRLG_L2Pass3(); + DRLG_FreeL2SP(); + DRLG_InitL2Vals(); + DRLG_SetPC(); +} +#endif diff --git a/src/DRLG_L2.H b/src/DRLG_L2.H new file mode 100644 index 0000000..f4b4810 --- /dev/null +++ b/src/DRLG_L2.H @@ -0,0 +1,109 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/DRLG_L2.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define DIR_NONE 0 +#define DIR_NORTH 1 +#define DIR_EAST 2 +#define DIR_SOUTH 3 +#define DIR_WEST 4 + +#define AREA_MIN 2 + +#define MAX_DOORS 7 +#define MAX_ROOMS 80 + +#define ROOM_MAX 10 +#define ROOM_MIN 6 + +#define VWALL_PIECE 1 +#define HWALL_PIECE 2 +#define FLOOR_PIECE 3 +#define VDOOR_PIECE 4 +#define HDOOR_PIECE 5 +#define LRWALL_PIECE 6 +#define URWALL_PIECE 7 +#define ULWALL_PIECE 8 +#define LLWALL_PIECE 9 + +#define DVWALL_PIECE 10 +#define DHWALL_PIECE 11 +#define DFLOOR_PIECE 12 +#define DULWALL_PIECE 13 +#define DURWALL_PIECE 14 +#define DLLWALL_PIECE 15 +#define DLRWALL_PIECE 16 + +#define THEME_PIECE 252 + +#define NO_CHAR ' ' +#define WALL_CHAR '#' +#define FLOOR_CHAR '.' +#define HALL_CHAR ',' +#define DOOR_CHAR 'D' +#define LRWALL_CHAR 'A' +#define URWALL_CHAR 'B' +#define ULWALL_CHAR 'C' +#define LLWALL_CHAR 'E' + +#define L2_NUMBLOCKS 161 +#define L2_NUMSPATS 2 + +#define NOTOK 255 +#define OK 254 + +#define CNO 0 +#define CWALL 1 +#define CFLOOR 2 +#define CDOOR 3 +#define CEMPTY 4 +#define CDoF 5 +#define CDoW 6 +#define CEoF 7 +#define CDoWoF 8 + +#define SNUM1 2 +#define SNUM2 2 + +#define SETP_BIT 0x80 // Non changeable set piece bit + + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct NODE { + int nHallx1; + int nHally1; + int nHallx2; + int nHally2; + int nHalldir; + struct NODE * pNext; +} HALLNODE; + +typedef struct { + int nRoomx1; + int nRoomy1; + int nRoomx2; + int nRoomy2; + int nRoomDest; +} ROOMNODE; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void CreateL2Dungeon(unsigned int, int); +void LoadL2Dungeon(char [], int, int); +void LoadPreL2Dungeon(char [], int, int); + diff --git a/src/DRLG_L3.CPP b/src/DRLG_L3.CPP new file mode 100644 index 0000000..3beafba --- /dev/null +++ b/src/DRLG_L3.CPP @@ -0,0 +1,2842 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Dungeon file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DRLG_L3.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +** CreateL1Dungeon +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "drlg_l3.h" +#include "gendung.h" +#include "scrollrt.h" +#include "engine.h" +#include "trigs.h" +#include "lighting.h" +#include "monster.h" +#include "objects.h" +#include "quests.h" + +/*-----------------------------------------------------------------------** +** Registration info +**-----------------------------------------------------------------------*/ +#include "regconst.h" +char sgszRegSig4[REG_LEN] = "REGISTRATION_BLOCK"; +//int SP3x1, SP3y1, SP3x2, SP3y2; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static const byte L3ConvTbl[16] = { 8, 11, 3, 10, 1, 9, 12, 12, 6, 13, 4, 13, 2, 14, 5, 7 }; + +static const byte L3UP[] = { 3, 3, // X size, Y size + + FILL, FILL, 0, // Pattern to look for + TOP_WALL, TOP_WALL, 0, + FLOOR, FLOOR, 0, + + 51, 50, 0, // Pattern to sub + 48, 49, 0, + 0, 0, 0}; + +//JKE level 6 stuff +static const byte L6UP[] = { 3, 3, // X size, Y size + + FILL, FILL, 0, // Pattern to look for + TOP_WALL, TOP_WALL, 0, + FLOOR, FLOOR, 0, + + 20, 19, 0, // Pattern to sub + 17, 18, 0, + 0, 0, 0}; + +static const byte L3DOWN[] = { 3, 3, // X size, Y size + + FILL, LEFT_WALL, FLOOR, // Pattern to look for + FILL, LEFT_WALL, FLOOR, + 0, 0, 0, + + 0, 47, 0, // Pattern to sub + 0, 46, 0, + 0, 0, 0}; + +// JKE level 6 stuff +static const byte L6DOWN[] = { 3, 3, // X size, Y size + + FILL, LEFT_WALL, FLOOR, // Pattern to look for + FILL, LEFT_WALL, FLOOR, + 0, 0, 0, + + 0, 16, 0, // Pattern to sub + 0, 15, 0, + 0, 0, 0}; + +static const byte L3HOLDWARP[] = { 3, 3, // X size, Y size + + FILL, FILL, 0, // Pattern to look for + TOP_WALL, TOP_WALL, 0, + FLOOR, FLOOR, 0, + + 125, 125, 0, // Pattern to sub + 125, 125, 0, + 0, 0, 0}; + +// JKE level 6 stuff +static const byte L6HOLDWARP[] = { 3, 3, // X size, Y size + + FILL, FILL, 0, // Pattern to look for + TOP_WALL, TOP_WALL, 0, + FLOOR, FLOOR, 0, + + 24, 23, 0, // Pattern to sub + 21, 22, 0, + 0, 0, 0}; + +static const byte L3TITE1[] = { 4, 4, // X size, Y size + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 0, 0, 0, 0, // Pattern to sub + 0, 57, 58, 0, + 0, 56, 55, 0, + 0, 0, 0, 0}; + +static const byte L3TITE2[] = { 4, 4, // X size, Y size + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 0, 0, 0, 0, // Pattern to sub + 0, 61, 62, 0, + 0, 60, 59, 0, + 0, 0, 0, 0}; + +static const byte L3TITE3[] = { 4, 4, // X size, Y size + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 0, 0, 0, 0, // Pattern to sub + 0, 65, 66, 0, + 0, 64, 63, 0, + 0, 0, 0, 0}; + +static const byte L3TITE4[] = { 4, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 0, 0, 0, 0, // Pattern to sub + 0, 70, 71, 0, + 0, 0, 0, 0}; + +static const byte L3TITE5[] = { 3, 4, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 0, 0, 0, // Pattern to sub + 0, 73, 0, + 0, 72, 0, + 0, 0, 0}; + +static const byte L3TITE6[] = { 5, 4, // X size, Y size + + FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, 0, FLOOR, + FLOOR, FLOOR, FLOOR, 0, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, FLOOR, + + 0, 0, 0, 0, 0, // Pattern to sub + 0, 77, 78, 0, 0, + 0, 76, 74, 75, 0, + 0, 0, 0, 0, 0}; + +static const byte L3TITE7[] = { 4, 5, // X size, Y size + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, 0, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 0, 0, 0, 0, // Pattern to sub + 0, 83, 0, 0, + 0, 82, 80, 0, + 0, 81, 79, 0, + 0, 0, 0, 0}; + +static const byte L3TITE8[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 0, 0, 0, // Pattern to sub + 0, 52, 0, + 0, 0, 0}; + +static const byte L3TITE9[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 0, 0, 0, // Pattern to sub + 0, 53, 0, + 0, 0, 0}; + +static const byte L3TITE10[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 0, 0, 0, // Pattern to sub + 0, 54, 0, + 0, 0, 0}; + +static const byte L3TITE11[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 0, 0, 0, // Pattern to sub + 0, 67, 0, + 0, 0, 0}; + +static const byte L3TITE12[] = { 2, 1, // X size, Y size + + LEFT_WALL, FLOOR, // Pattern to look for + + 68, 0}; // Pattern to sub + +static const byte L3TITE13[] = { 1, 2, // X size, Y size + + TOP_WALL, // Pattern to look for + FLOOR, + + 69, // Pattern to sub + 0}; + +static const byte L3CREV1[] = { 2, 1, // X size, Y size + + FILL, FLOOR, // Pattern to look for + + 84, 85}; // Pattern to sub + +static const byte L3CREV2[] = { 2, 1, // X size, Y size + + FILL, UL_WALL, // Pattern to look for + + 86, 87}; // Pattern to sub + +static const byte L3CREV3[] = { 1, 2, // X size, Y size + + FILL, // Pattern to look for + TOP_WALL, + + 89, // Pattern to sub + 88}; + +static const byte L3CREV4[] = { 2, 1, // X size, Y size + + FILL, FLOOR, // Pattern to look for + + 90, 91}; // Pattern to sub + +static const byte L3CREV5[] = { 1, 2, // X size, Y size + + FILL, // Pattern to look for + UL_WALL, + + 92, // Pattern to sub + 93}; + +static const byte L3CREV6[] = { 1, 2, // X size, Y size + + FILL, // Pattern to look for + TOP_WALL, + + 95, // Pattern to sub + 94}; + +static const byte L3CREV7[] = { 2, 1, // X size, Y size + + FILL, FLOOR, // Pattern to look for + + 96, 101}; // Pattern to sub + +static const byte L3CREV8[] = { 1, 2, // X size, Y size + + BOTTOM_WALL, // Pattern to look for + FILL, + + 102, // Pattern to sub + 97}; + +static const byte L3CREV9[] = { 2, 1, // X size, Y size + + UR_WALL, FILL, // Pattern to look for + + 103, 98}; // Pattern to sub + +static const byte L3CREV10[] = { 2, 1, // X size, Y size + + RIGHT_WALL, FILL, // Pattern to look for + + 104, 99}; // Pattern to sub + +static const byte L3CREV11[] = { 1, 2, // X size, Y size + + LR_WALL, // Pattern to look for + FILL, + + 105, // Pattern to sub + 100}; + +static const byte L3ISLE1[] = { 2, 3, // X size, Y size + + UL_ISLE, UR_ISLE, // Pattern to look for + RIGHT_WALL, LEFT_WALL, + LL_ISLE, LR_ISLE, + + 7, 7, // Pattern to sub + 7, 7, + 7, 7}; + +static const byte L3ISLE2[] = { 3, 2, // X size, Y size + + UL_ISLE, BOTTOM_WALL, UR_ISLE, // Pattern to look for + LL_ISLE, TOP_WALL, LR_ISLE, + + 7, 7, 7, // Pattern to sub + 7, 7, 7}; + +static const byte L3ISLE3[] = { 2, 3, // X size, Y size + + UL_ISLE, UR_ISLE, // Pattern to look for + RIGHT_WALL, LEFT_WALL, + LL_ISLE, LR_ISLE, + + 29, 30, // Pattern to sub + 25, 28, + 31, 32}; + +static const byte L3ISLE4[] = { 3, 2, // X size, Y size + + UL_ISLE, BOTTOM_WALL, UR_ISLE, // Pattern to look for + LL_ISLE, TOP_WALL, LR_ISLE, + + 29, 26, 30, // Pattern to sub + 31, 27, 32}; + +static const byte L3ISLE5[] = { 2, 2, // X size, Y size + + UL_ISLE, UR_ISLE, // Pattern to look for + LL_ISLE, LR_ISLE, + + 7, 7, // Pattern to sub + 7, 7}; + +static const byte L3XTRA1[] = { 1, 1, // X size, Y size + + FLOOR, // Pattern to look for + + 106}; // Pattern to sub + +static const byte L3XTRA2[] = { 1, 1, // X size, Y size + + FLOOR, // Pattern to look for + + 107}; // Pattern to sub + +static const byte L3XTRA3[] = { 1, 1, // X size, Y size + + FLOOR, // Pattern to look for + + 108}; // Pattern to sub + +static const byte L3XTRA4[] = { 1, 1, // X size, Y size + + LEFT_WALL, // Pattern to look for + + 109}; // Pattern to sub + +static const byte L3XTRA5[] = { 1, 1, // X size, Y size + + TOP_WALL, // Pattern to look for + + 110}; // Pattern to sub + +static const byte L3ANVIL[] = { 11, 11, + + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 29, 26, 26, 26, 26, 26, 30, 0, 0, + 0, 29, 34, 33, 33, 37, 36, 33, 35, 30, 0, + 0, 25, 33, 37, 27, 32, 31, 36, 33, 28, 0, + 0, 25, 37, 32, 7, 7, 7, 31, 27, 32, 0, + 0, 25, 28, 7, 7, 7, 7, BOTTOM_WALL, BOTTOM_WALL, BOTTOM_WALL, 0, + 0, 25, 35, 30, 7, 7, 7, 29, 26, 30, 0, + 0, 25, 33, 35, 26, 30, 29, 34, 33, 28, 0, + 0, 31, 36, 33, 33, 35, 34, 33, 37, 32, 0, + 0, 0, 31, 27, 27, 27, 27, 27, 32, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +// JKE begin L6 extras +static const byte L6FILL1[] = { 1, 1, // X size, Y size + + FILL, // Pattern to look for + + 25}; // Pattern to sub +static const byte L6FILL2[] = { 1, 1, // X size, Y size + + FILL, // Pattern to look for + + 26}; // Pattern to sub +static const byte L6FILL3[] = { 1, 1, // X size, Y size + + FILL, // Pattern to look for + + 27}; // Pattern to sub +static const byte L6FILL4[] = { 1, 1, // X size, Y size + + FILL, // Pattern to look for + + 28}; // Pattern to sub +static const byte L6FLOOR1[] = { 1, 1, // X size, Y size + + FLOOR, // Pattern to look for + + 29}; // Pattern to sub +static const byte L6FLOOR2[] = { 1, 1, // X size, Y size + + FLOOR, // Pattern to look for + + 30}; // Pattern to sub +static const byte L6FLOOR3[] = { 1, 1, // X size, Y size + + FLOOR, // Pattern to look for + + 31}; // Pattern to sub +static const byte L6FLOOR4[] = { 1, 1, // X size, Y size + + FLOOR, // Pattern to look for + + 32}; // Pattern to sub +static const byte L6FLOOR5[] = { 3, 3, // X size, Y size + + FLOOR,FLOOR,FLOOR, // Pattern to look for + FLOOR,FLOOR,FLOOR, + FLOOR,FLOOR,FLOOR, + + 0, 0 ,0, + 0,126,0, + 0, 0 ,0}; // Pattern to sub +static const byte L6FLOOR6[] = { 3, 3, // X size, Y size + + FLOOR,FLOOR,FLOOR, // Pattern to look for + FLOOR,FLOOR,FLOOR, + FLOOR,FLOOR,FLOOR, + + 0, 0 ,0, + 0,124,0, + 0, 0 ,0}; // Pattern to sub +static const byte L6WALL1[] = { 1, 1, // X size, Y size + + LEFT_WALL, // Pattern to look for + + 33}; // Pattern to sub +static const byte L6WALL2[] = { 1, 1, // X size, Y size + + LEFT_WALL, // Pattern to look for + + 34}; // Pattern to sub +static const byte L6WALL3[] = { 1, 1, // X size, Y size + + LEFT_WALL, // Pattern to look for + + 35}; // Pattern to sub +static const byte L6WALL4[] = { 1, 1, // X size, Y size + + LEFT_WALL, // Pattern to look for + + 36}; // Pattern to sub +static const byte L6WALL5[] = { 1, 1, // X size, Y size + + LEFT_WALL, // Pattern to look for + + 37}; // Pattern to sub +static const byte L6CORNER1[] = { 1, 1, // X size, Y size + + UL_WALL, // Pattern to look for + + 38}; // Pattern to sub +static const byte L6WALL6[] = { 1, 1, // X size, Y size + + TOP_WALL, // Pattern to look for + + 39}; // Pattern to sub +static const byte L6WALL7[] = { 1, 1, // X size, Y size + + TOP_WALL, // Pattern to look for + + 40}; // Pattern to sub +static const byte L6WALL8[] = { 1, 1, // X size, Y size + + TOP_WALL, // Pattern to look for + + 41}; // Pattern to sub +static const byte L6WALL9[] = { 1, 1, // X size, Y size + + TOP_WALL, // Pattern to look for + + 42}; // Pattern to sub +static const byte L6WALL10[] = { 1, 1, // X size, Y size + + TOP_WALL, // Pattern to look for + + 43}; // Pattern to sub +static const byte L6CORNER2[] = { 1, 1, // X size, Y size + + UL_WALL, // Pattern to look for + + 44}; // Pattern to sub +static const byte L6WALL11[] = { 1, 1, // X size, Y size + + LEFT_WALL, // Pattern to look for + + 45}; // Pattern to sub +static const byte L6WALL12[] = { 1, 1, // X size, Y size + + LEFT_WALL, // Pattern to look for + + 46}; // Pattern to sub +static const byte L6WALL13[] = { 1, 1, // X size, Y size + + TOP_WALL, // Pattern to look for + + 47}; // Pattern to sub +static const byte L6WALL14[] = { 1, 1, // X size, Y size + + TOP_WALL, // Pattern to look for + + 48}; // Pattern to sub +static const byte L6CORNER3[] = { 1, 1, // X size, Y size + + UL_WALL, // Pattern to look for + + 49}; // Pattern to sub +static const byte L6CORNER4[] = { 1, 1, // X size, Y size + + UL_WALL, // Pattern to look for + + 50}; // Pattern to sub +//======================================================================================= +// Stalagmites +//======================================================================================= + +static const byte L6TITE1[] = { 3, 3, // X size, Y size + + FLOOR,FLOOR, FLOOR, // Pattern to look for + FLOOR,FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 67, 0, 0, // Pattern to sub + 66,51, 0, + 0, 0, 0}; + +static const byte L6TITE2[] = { 3,3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 69, 0, 0, // Pattern to sub + 68, 52,0, + 0, 0, 0}; + +static const byte L6TITE3[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 70, 0, 0, // Pattern to sub + 71, 53, 0, + 0, 0, 0}; +static const byte L6TITE4[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 73, 0, 0, // Pattern to sub + 72, 54, 0, + 0, 0, 0}; +static const byte L6TITE5[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 75, 0, 0, // Pattern to sub + 74, 55, 0, + 0, 0, 0}; +static const byte L6TITE6[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 77, 0, 0, // Pattern to sub + 76, 56, 0, + 0, 0, 0}; +static const byte L6TITE7[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 79, 0, 0, // Pattern to sub + 78, 57, 0, + 0, 0, 0}; +static const byte L6TITE8[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 81, 0, 0, // Pattern to sub + 80, 58, 0, + 0, 0, 0}; +static const byte L6TITE9[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 83, 0, 0, // Pattern to sub + 82, 59, 0, + 0, 0, 0}; +static const byte L6TITE10[] = { 3, 3, // X size, Y size + + FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, + + 84, 0, 0, // Pattern to sub + 85, 60, 0, + 0, 0, 0}; + +static const byte ACIDISLE1[] = { 2, 3, // X size, Y size + + UL_ISLE, UR_ISLE, // Pattern to look for + RIGHT_WALL, LEFT_WALL, + LL_ISLE, LR_ISLE, + + 7, 7, // Pattern to sub + 7, 7, + 7, 7}; + +static const byte ACIDISLE2[] = { 3, 2, // X size, Y size + + UL_ISLE, BOTTOM_WALL, UR_ISLE, // Pattern to look for + LL_ISLE, TOP_WALL, LR_ISLE, + + 7, 7, 7, // Pattern to sub + 7, 7, 7}; + +static const byte ACIDISLE3[] = { 2, 3, // X size, Y size + + UL_ISLE, UR_ISLE, // Pattern to look for + RIGHT_WALL, LEFT_WALL, + LL_ISLE, LR_ISLE, + + 107, 115, // Pattern to sub + 119, 122, + 131, 123}; + +static const byte ACIDISLE4[] = { 3, 2, // X size, Y size + + UL_ISLE, BOTTOM_WALL, UR_ISLE, // Pattern to look for + LL_ISLE, TOP_WALL, LR_ISLE, + + 107, 120, 115, // Pattern to sub + 131, 121, 123}; + +static const byte ACIDISLE5[] = { 2, 2, // X size, Y size + + UL_ISLE, UR_ISLE, // Pattern to look for + LL_ISLE, LR_ISLE, + + 7, 7, // Pattern to sub + 7, 7}; + +static const byte L6ACIDTEST[] = { 1, 1, // X size, Y size + + FLOOR, // Pattern to look for + + 131}; // Pattern to sub + +static const byte L6ACID1[] = { 4, 4, + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 7, 7 , 7 ,7, + 7,107,115,7, + 7,131,123,7, + 7, 7 , 7 ,7}; + +static const byte L6ACID2[] = { 4, 4, + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 7, 7 , 7 ,7, + 7, 7 ,108,7, + 7,109,112,7, + 7, 7 , 7 ,7}; + +static const byte L6ACID3[] = { 4, 5, + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 7, 7 , 7 ,7, + 7,107,115,7, + 7,119,122,7, + 7,131,123,7, + 7, 7 , 7 ,7}; + +static const byte L6ACID4[] = { 4, 5, + + FLOOR, FLOOR, FLOOR, FLOOR, // Pattern to look for + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + FLOOR, FLOOR, FLOOR, FLOOR, + + 7, 7 , 7 ,7, + 7,126,108,7, + 7, 7 ,117,7, + 7,109,112,7, + 7, 7 , 7 ,7}; + +static int abyssx; +static BYTE lavapool; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void InitL3Dungeon() { + ZeroMemory(dungeon,sizeof(dungeon)); + int i, j; + + for (i = 0; i < MDMAXY; i++) { + + for (j = 0; j < MDMAXX; j++) { + dungeon[j][i] = D3_NULL; + dflags[j][i] = 0; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* + +void DRLG_LoadL3SP() +{ + setloadflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* +void DRLG_FreeL3SP() { + DiabloFreePtr(pSetPiece); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +void DRLG_L3SetRoom(int rx1, int ry1) +{ + int rw,rh; + int i,j; + byte *sp; + + sp = pSetPiece; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_x = rx1; + setpc_y = ry1; + setpc_w = rw; + setpc_h = rh; + + sp = pSetPiece+4; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*sp != 0) { + dungeon[rx1+i][ry1+j] = *sp; + dflags[rx1+i][ry1+j] |= SETP_BIT; + } else dungeon[rx1+i][ry1+j] = FLOOR; + sp+=2; + } + } + + } + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static int DRLG_L3FillRoom(int x1, int y1, int x2, int y2) +{ + int i,j,v,rv,rf; + + if ((x1 > 1) && (x2 < (MDMAXX-6)) && (y1 > 1) && (y2 < (MDMAXY-2))) { + v = 0; + for (j = y1; j <= y2; j++) { + for (i = x1; i <= x2; i++) v += dungeon[i][j]; + } + if (v == 0) { + for (j = (y1+1); j < y2; j++) { + for (i = (x1+1); i < x2; i++) dungeon[i][j] = 1; + } + for (j = y1; j <= y2; j++) { + rf = random(0, 2); + if (rf != 0) dungeon[x1][j] = 1; + rf = random(0, 2); + if (rf != 0) dungeon[x2][j] = 1; + } + for (i = x1; i <= x2; i++) { + rf = random(0, 2); + if (rf != 0) dungeon[i][y1] = 1; + rf = random(0, 2); + if (rf != 0) dungeon[i][y2] = 1; + } + rv = FR_TRUE; + } else rv = FR_FALSE; + } else rv = FR_FALSE; + return (rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void DRLG_L3CreateBlock(int x, int y, int obs, int dir) +{ + int blksizex, blksizey, cbd; + int x1,y1,x2,y2; + int contflag; + + blksizex = random(0, 2) + 3; // 3-5 width and height + blksizey = random(0, 2) + 3; + + if (dir == BLK_U) { + y2 = y - 1; + y1 = y2 - blksizey; + if (blksizex < obs) x1 = random(0, blksizex) + x; + if (blksizex == obs) x1 = x; + if (blksizex > obs) x1 = x - random(0, blksizex); + x2 = x1 + blksizex; + } + if (dir == BLK_L) { + x2 = x - 1; + x1 = x2 - blksizex; + if (blksizey < obs) y1 = random(0, blksizey) + y; + if (blksizey == obs) y1 = y; + if (blksizey > obs) y1 = y - random(0, blksizey); + y2 = y1 + blksizey; + } + if (dir == BLK_D) { + y1 = y + 1; + y2 = y1 + blksizey; + if (blksizex < obs) x1 = random(0, blksizex) + x; + if (blksizex == obs) x1 = x; + if (blksizex > obs) x1 = x - random(0, blksizex); + x2 = x1 + blksizex; + } + if (dir == BLK_R) { + x1 = x + 1; + x2 = x1 + blksizex; + if (blksizey < obs) y1 = random(0, blksizey) + y; + if (blksizey == obs) y1 = y; + if (blksizey > obs) y1 = y - random(0, blksizey); + y2 = y1 + blksizey; + } + contflag = DRLG_L3FillRoom(x1,y1,x2,y2); + if (contflag == FR_TRUE) { + cbd = random(0, 4); + if ((cbd != 0) && (dir != BLK_D)) DRLG_L3CreateBlock(x1,y1,blksizey,BLK_U); + if ((cbd != 0) && (dir != BLK_L)) DRLG_L3CreateBlock(x2,y1,blksizex,BLK_R); + if ((cbd != 0) && (dir != BLK_U)) DRLG_L3CreateBlock(x1,y2,blksizey,BLK_D); + if ((cbd != 0) && (dir != BLK_R)) DRLG_L3CreateBlock(x1,y1,blksizex,BLK_L); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void DRLG_L3FloorArea(int x1, int y1, int x2, int y2) +{ + int i,j; + + for (j = y1; j <= y2; j++) { + for (i = x1; i <= x2; i++) dungeon[i][j] = 1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3FillDiags() +{ + int i,j,v,rv; + + for (j = 0; j < (MDMAXY-1); j++) { + for (i = 0; i < (MDMAXX-1); i++) { + v = dungeon[i][j] << 3; // x8 + v += dungeon[i+1][j] << 2; // x4 + v += dungeon[i][j+1] << 1; // x2 + v += dungeon[i+1][j+1]; + if (v == 6) { + rv = random(0, 2); + if (rv == 0) dungeon[i][j] = 1; + else dungeon[i+1][j+1] = 1; + } + if (v == 9) { + rv = random(0, 2); + if (rv == 0) dungeon[i+1][j] = 1; + else dungeon[i][j+1] = 1; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3FillSingles() +{ + int i,j,v; + + for (j = 1; j < (MDMAXY-1); j++) { + for (i = 1; i < (MDMAXX-1); i++) { + if (dungeon[i][j] == 0) { + v = dungeon[i-1][j-1] + dungeon[i][j-1] + dungeon[i+1][j-1]; + if (v == 3) { + v = dungeon[i-1][j] + dungeon[i+1][j]; + if (v == 2) { + v = dungeon[i-1][j+1] + dungeon[i][j+1] + dungeon[i+1][j+1]; + if (v == 3) dungeon[i][j] = 1; + } + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3FillStraights() +{ + int i,j; + int xc,xs; + int yc,ys; + int k,rv; + + for (j = 0; j < (MDMAXY-1); j++) { + xc = 0; + for (i = 0; i < (MDMAXX-3); i++) { + if ((dungeon[i][j] == 0) && (dungeon[i][j+1] == 1)) { + if (xc == 0) xs = i; + xc++; + } else { + if ((xc > 3) && (random(0, 2))) { + for (k = xs; k < i; k++) { + rv = random(0, 2); + dungeon[k][j] = rv; + } + } + xc = 0; + } + } + } + for (j = 0; j < (MDMAXY-1); j++) { + xc = 0; + for (i = 0; i < (MDMAXX-3); i++) { + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 0)) { + if (xc == 0) xs = i; + xc++; + } else { + if ((xc > 3) && (random(0, 2))) { + for (k = xs; k < i; k++) { + rv = random(0, 2); + dungeon[k][j+1] = rv; + } + } + xc = 0; + } + } + } + for (i = 0; i < (MDMAXX-1); i++) { + yc = 0; + for (j = 0; j < (MDMAXY-3); j++) { + if ((dungeon[i][j] == 0) && (dungeon[i+1][j] == 1)) { + if (yc == 0) ys = j; + yc++; + } else { + if ((yc > 3) && (random(0, 2))) { + for (k = ys; k < j; k++) { + rv = random(0, 2); + dungeon[i][k] = rv; + } + } + yc = 0; + } + } + } + for (i = 0; i < (MDMAXX-1); i++) { + yc = 0; + for (j = 0; j < (MDMAXY-3); j++) { + if ((dungeon[i][j] == 1) && (dungeon[i+1][j] == 0)) { + if (yc == 0) ys = j; + yc++; + } else { + if ((yc > 3) && (random(0, 2))) { + for (k = ys; k < j; k++) { + rv = random(0, 2); + dungeon[i+1][k] = rv; + } + } + yc = 0; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3Edges() +{ + int i,j; + + for (j = 0; j < MDMAXY; j++) dungeon[MDMAXX-1][j] = 0; + for (i = 0; i < MDMAXX; i++) dungeon[i][MDMAXY-1] = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static int DRLG_L3GetFloorArea() +{ + int i,j,gfa; + + gfa = 0; + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) gfa += dungeon[i][j]; + } + return(gfa); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3MakeMegas() +{ + int i,j,k,v; + + for (j = 0; j < (MDMAXY-1); j++) { + for (i = 0; i < (MDMAXX-1); i++) { + v = dungeon[i][j] << 3; + v += dungeon[i+1][j] << 2; + v += dungeon[i][j+1] << 1; + v += dungeon[i+1][j+1]; + if (v == 6) { + k = random(0, 2); + if (k == 0) v = 12; + else v = 5; + } + if (v == 9) { + k = random(0, 2); + if (k == 0) v = 13; + else v = 14; + } + dungeon[i][j] = L3ConvTbl[v]; + } + dungeon[MDMAXX-1][j] = L3_DIRT; + } + for (i = 0; i < MDMAXX; i++) dungeon[i][MDMAXY-1] = L3_DIRT; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3River() +{ + int rx, ry, px, py; + int dir, pdir, nodir, nodir2, dircheck; + int river[3][100], rivercnt, riveramt; + int i, j; + int trys, found, bridge, lpcnt, bail; + + riveramt = 0; + found = 0; + trys = 0; + + while (trys < 200 && riveramt < 4) { + found = 0; + + while (found == 0 && trys < 200) { + rivercnt = 0; + trys++; + + rx = 0; + ry = 0; + bail = 0; + while ((dungeon[rx][ry] < 25 || dungeon[rx][ry] > 28) && (bail < 100)) { + rx = random(0, MDMAXX); + ry = random(0, MDMAXY); + bail++; + while ((dungeon[rx][ry] < 25 || dungeon[rx][ry] > 28) && (ry < MDMAXY)) { + rx ++; + if (rx >= MDMAXX) { + rx = 0; + ry++; + } + } + } + + if (bail >= 100) return; + + switch (dungeon[rx][ry]) { + case 25: + dir = WEST; + nodir = EAST; + river[2][rivercnt] = 40; + break; + case 26: + dir = NORTH; + nodir = SOUTH; + river[2][rivercnt] = 38; + break; + case 27: + dir = SOUTH; + nodir = NORTH; + river[2][rivercnt] = 41; + break; + case 28: + dir = EAST; + nodir = WEST; + river[2][rivercnt] = 39; + break; + } + river[0][rivercnt] = rx; + river[1][rivercnt] = ry; + rivercnt++; + + nodir2 = 4; + dircheck = 0; + while (dircheck < 4 && rivercnt < 100) { + + px = rx; + py = ry; + + if (dircheck == 0) dir = random(0, 4); + else dir = (dir + 1) & 3; + dircheck++; + + while (dir == nodir || dir == nodir2) { + dir = (dir + 1) & 3; + dircheck++; + } + + if (dir == NORTH && ry > 0) ry--; + if (dir == SOUTH && ry < MDMAXY) ry++; + if (dir == EAST && rx < MDMAXX) rx++; + if (dir == WEST && rx > 0) rx--; + + if (dungeon[rx][ry] == 7) { + dircheck = 0; + if (dir < EAST) river[2][rivercnt] = 17 + (BYTE)random(0, 2); + if (dir > SOUTH) river[2][rivercnt] = 15 + (BYTE)random(0, 2); + river[0][rivercnt] = rx; + river[1][rivercnt] = ry; + rivercnt++; + + if ((dir == NORTH && pdir == EAST) || (dir == WEST && pdir == SOUTH)) { + if (rivercnt > 2) river[2][rivercnt-2] = 22; + if (dir == NORTH) nodir2 = SOUTH; + else nodir2 = EAST; + } + if ((dir == NORTH && pdir == WEST) || (dir == EAST && pdir == SOUTH)) { + if (rivercnt > 2) river[2][rivercnt-2] = 21; + if (dir == NORTH) nodir2 = SOUTH; + else nodir2 = WEST; + } + if ((dir == SOUTH && pdir == EAST) || (dir == WEST && pdir == NORTH)) { + if (rivercnt > 2) river[2][rivercnt-2] = 20; + if (dir == SOUTH) nodir2 = NORTH; + else nodir2 = EAST; + } + if ((dir == SOUTH && pdir == WEST) || (dir == EAST && pdir == NORTH)) { + if (rivercnt > 2) river[2][rivercnt-2] = 19; + if (dir == SOUTH) nodir2 = NORTH; + else nodir2 = WEST; + } + + pdir = dir; + } + else { + rx = px; + ry = py; + } + } + + if (dir == NORTH && dungeon[rx][ry-1] == 10 && dungeon[rx][ry-2] == 8) { + river[0][rivercnt] = rx; + river[1][rivercnt] = ry-1; + river[2][rivercnt] = 24; + if (pdir == EAST) river[2][rivercnt-1] = 22; + if (pdir == WEST) river[2][rivercnt-1] = 21; + found = 1; + } + if (dir == SOUTH && dungeon[rx][ry+1] == 2 && dungeon[rx][ry+2] == 8) { + river[0][rivercnt] = rx; + river[1][rivercnt] = ry+1; + river[2][rivercnt] = 42; + if (pdir == EAST) river[2][rivercnt-1] = 20; + if (pdir == WEST) river[2][rivercnt-1] = 19; + found = 1; + } + if (dir == EAST && dungeon[rx+1][ry] == 4 && dungeon[rx+2][ry] == 8) { + river[0][rivercnt] = rx+1; + river[1][rivercnt] = ry; + river[2][rivercnt] = 43; + if (pdir == NORTH) river[2][rivercnt-1] = 19; + if (pdir == SOUTH) river[2][rivercnt-1] = 21; + found = 1; + } + if (dir == WEST && dungeon[rx-1][ry] == 9 && dungeon[rx-2][ry] == 8) { + river[0][rivercnt] = rx-1; + river[1][rivercnt] = ry; + river[2][rivercnt] = 23; + if (pdir == NORTH) river[2][rivercnt-1] = 20; + if (pdir == SOUTH) river[2][rivercnt-1] = 22; + found = 1; + } + } + + if (found == 1 && rivercnt < 7) found = 0; + + if (found == 1) { + + bridge = 0; + lpcnt = 0; + while (bridge == 0 && lpcnt < 30) { + lpcnt++; + i = random(0, rivercnt); + if (((river[2][i] == 15) || (river[2][i] == 16)) && + (dungeon[(river[0][i])][(river[1][i])-1] == 7) && (dungeon[(river[0][i])][(river[1][i])+1] == 7)) + bridge = 1; + if (((river[2][i] == 17) || (river[2][i] == 18)) && + (dungeon[(river[0][i])-1][(river[1][i])] == 7) && (dungeon[(river[0][i])+1][(river[1][i])] == 7)) + bridge = 2; + + for (j = 0; j < rivercnt && bridge != 0; j++) { + if ((bridge == 1) && ((river[1][i] - 1 == river[1][j]) || (river[1][i] + 1 == river[1][j])) && + (river[0][i] == river[0][j])) bridge = 0; + if ((bridge == 2) && ((river[0][i] - 1 == river[0][j]) || (river[0][i] + 1 == river[0][j])) && + (river[1][i] == river[1][j])) bridge = 0; + } + } + + if (bridge != 0) { + if (bridge == 1) river[2][i] = 44; + else river[2][i] = 45; + riveramt++; + for (i = 0; i <= rivercnt; i++) dungeon[(river[0][i])][(river[1][i])] = river[2][i]; + } + else found = 0; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int DRLG_L3SpawnEdge(int x, int y, int * totarea) +{ + BYTE i; + static const BYTE spawntable[] = {0x00,0x0a,0x43,0x05,0x2c,0x06,0x09,0x00,0x00,0x1c,0x83,0x06,0x09,0x0a,0x05}; + + if ((*totarea) > 40) return 1; + if (x < 0 || y < 0 || x >= MDMAXX || y >= MDMAXY) return 1; + + if ((dungeon[x][y] & 0x80) != 0) return 0; + if (dungeon[x][y] > 15) return 1; + + i = dungeon[x][y]; + dungeon[x][y] |= 0x80; + (*totarea)++; + + if (((spawntable[i] & 0x08) != 0) && ((DRLG_L3SpawnEdge (x, y-1, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x04) != 0) && ((DRLG_L3SpawnEdge (x, y+1, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x02) != 0) && ((DRLG_L3SpawnEdge (x+1, y, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x01) != 0) && ((DRLG_L3SpawnEdge (x-1, y, totarea)) == 1)) return 1; + + if (((spawntable[i] & 0x80) != 0) && ((DRLG_L3Spawn (x, y-1, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x40) != 0) && ((DRLG_L3Spawn (x, y+1, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x20) != 0) && ((DRLG_L3Spawn (x+1, y, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x10) != 0) && ((DRLG_L3Spawn (x-1, y, totarea)) == 1)) return 1; + + return 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int DRLG_L3Spawn(int x, int y, int * totarea) +{ + BYTE i; + static const BYTE spawntable[] = {0x00,0x0a,0x03,0x05,0x0c,0x06,0x09,0x00,0x00,0x0c,0x03,0x06,0x09,0x0a,0x05}; + + if ((*totarea) > 40) return 1; + if (x < 0 || y < 0 || x >= MDMAXX || y >= MDMAXY) return 1; + + if ((dungeon[x][y] & 0x80) != 0) return 0; + if (dungeon[x][y] > 15) return 1; + + i = dungeon[x][y]; + dungeon[x][y] |= 0x80; + (*totarea)++; + + if (i != 8) { + + if (((spawntable[i] & 0x08) != 0) && ((DRLG_L3SpawnEdge (x, y-1, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x04) != 0) && ((DRLG_L3SpawnEdge (x, y+1, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x02) != 0) && ((DRLG_L3SpawnEdge (x+1, y, totarea)) == 1)) return 1; + if (((spawntable[i] & 0x01) != 0) && ((DRLG_L3SpawnEdge (x-1, y, totarea)) == 1)) return 1; + } + else { + + if ((DRLG_L3Spawn (x+1, y, totarea)) == 1) return 1; + if ((DRLG_L3Spawn (x-1, y, totarea)) == 1) return 1; + if ((DRLG_L3Spawn (x, y+1, totarea)) == 1) return 1; + if ((DRLG_L3Spawn (x, y-1, totarea)) == 1) return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3Pool() +{ + int i, j, found; + int dunx, duny; + int totarea, poolchance; + BYTE k; + static const BYTE poolsub[] = {0,35,26,36,25,29,34,7,33,28,27,37,32,31,30}; + + for (duny = 0; duny < MDMAXY; duny++) { + for (dunx = 0; dunx < MDMAXX; dunx++) { + + if (dungeon[dunx][duny] == 8) { + + dungeon[dunx][duny] |= 0x80; + totarea = 1; + found = 0; + + if (dunx+1 < MDMAXX && found == 0) found = DRLG_L3Spawn (dunx+1, duny, &totarea); + else found = 1; + if (dunx-1 > 0 && found == 0) found = DRLG_L3Spawn (dunx-1, duny, &totarea); + else found = 1; + if (duny+1 < MDMAXY && found == 0) found = DRLG_L3Spawn (dunx, duny+1, &totarea); + else found = 1; + if (duny-1 > 0 && found == 0) found = DRLG_L3Spawn (dunx, duny-1, &totarea); + else found = 1; + + poolchance = random(0, 100); + for (i = duny-totarea; i < duny+totarea; i++) { + for (j = dunx-totarea; j < dunx+totarea; j++) { + + if ((dungeon[j][i] & 0x80) != 0 && i >= 0 && i < MDMAXY && j >= 0 && j < MDMAXX) { + + dungeon[j][i] &= 0x7f; + + if (totarea > 4 && poolchance < 25 && found == 0) { + k = poolsub[(dungeon[j][i])]; + if (k != 0 && k <= 37) + dungeon[j][i] = k; + lavapool = TRUE; + } + } + } + } + } + } + } +} +static void AcidPool() +{ + int i, j, found; + int dunx, duny; + int totarea, poolchance; + BYTE k; + static const BYTE poolsub[] = {0,133,120,125,119,107,132,7,134,122,121,118,123,131,115}; + + for (duny = 0; duny < MDMAXY; duny++) { + for (dunx = 0; dunx < MDMAXX; dunx++) { + + if (dungeon[dunx][duny] == 8) { + + dungeon[dunx][duny] |= 0x80; + totarea = 1; + found = 0; + + if (dunx+1 < MDMAXX && found == 0) found = DRLG_L3Spawn (dunx+1, duny, &totarea); + else found = 1; + if (dunx-1 > 0 && found == 0) found = DRLG_L3Spawn (dunx-1, duny, &totarea); + else found = 1; + if (duny+1 < MDMAXY && found == 0) found = DRLG_L3Spawn (dunx, duny+1, &totarea); + else found = 1; + if (duny-1 > 0 && found == 0) found = DRLG_L3Spawn (dunx, duny-1, &totarea); + else found = 1; + + poolchance = random(0, 100); + for (i = duny-totarea; i < duny+totarea; i++) { + for (j = dunx-totarea; j < dunx+totarea; j++) { + + if ((dungeon[j][i] & 0x80) != 0 && i >= 0 && i < MDMAXY && j >= 0 && j < MDMAXX) { + + dungeon[j][i] &= 0x7f; + + if (totarea > 4 && poolchance < 25 && found == 0) { + k = poolsub[(dungeon[j][i])]; + if (k != 0 && k <= 131) + dungeon[j][i] = k; + lavapool = TRUE; + } + } + } + } + } + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3PoolFix() +{ + int dunx, duny; + + for (duny = 0; duny < MDMAXY; duny++) { + for (dunx = 0; dunx < MDMAXX; dunx++) { + if ((dungeon[dunx][duny] == 8) && + ((dungeon[dunx-1][duny-1] >= 25 && dungeon[dunx-1][duny-1] <= 41) && + (dungeon[dunx-1][duny] >= 25 && dungeon[dunx-1][duny] <= 41) && + (dungeon[dunx-1][duny+1] >= 25 && dungeon[dunx-1][duny+1] <= 41) && + (dungeon[dunx][duny-1] >= 25 && dungeon[dunx][duny-1] <= 41) && + //(dungeon[dunx][duny] >= 25 && dungeon[dunx][duny+1] <= 41) && + (dungeon[dunx][duny+1] >= 25 && dungeon[dunx][duny+1] <= 41) && + (dungeon[dunx+1][duny-1] >= 25 && dungeon[dunx+1][duny-1] <= 41) && + (dungeon[dunx+1][duny] >= 25 && dungeon[dunx+1][duny] <= 41) && + (dungeon[dunx+1][duny+1] >= 25 && dungeon[dunx+1][duny+1] <= 41))) + + dungeon[dunx][duny] = 33; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void AcidPoolFix() +{ + int dunx, duny; + + for (duny = 0; duny < MDMAXY; duny++) { + for (dunx = 0; dunx < MDMAXX; dunx++) + { + if ((dungeon[dunx][duny] == 8) && + ((dungeon[dunx-1][duny-1] >= 107 && dungeon[dunx-1][duny-1] <= 135) || + (dungeon[dunx-1][duny] >= 107 && dungeon[dunx-1][duny] <= 135) || + (dungeon[dunx-1][duny+1] >= 107 && dungeon[dunx-1][duny+1] <= 135) || + (dungeon[dunx][duny-1] >= 107 && dungeon[dunx][duny-1] <= 135) || + //(dungeon[dunx][duny] >= 25 && dungeon[dunx][duny+1] <= 41) && + (dungeon[dunx][duny+1] >= 107 && dungeon[dunx][duny+1] <= 135) || + (dungeon[dunx+1][duny-1] >= 107 && dungeon[dunx+1][duny-1] <= 135) || + (dungeon[dunx+1][duny] >= 107 && dungeon[dunx+1][duny] <= 135) || + (dungeon[dunx+1][duny+1] >= 107 && dungeon[dunx+1][duny+1] <= 135))) + + dungeon[dunx][duny] = 134; + + if ((dungeon[dunx][duny] < 7) && + ((dungeon[dunx+1][duny] >= 107 && dungeon[dunx+1][duny] <= 135) || + (dungeon[dunx][duny-1] >= 107 && dungeon[dunx][duny-1] <= 135))) + + dungeon[dunx][duny] = 131; + + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int DRLG_L3PlaceMiniSet(const byte miniset[], int tmin, int tmax, int cx, int cy, int setview, int ldir) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int i, ii, numt; + int found, trys; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Number of pieces to place + if ((tmax - tmin) == 0) numt = 1; + else numt = random(0, tmax - tmin) + tmin; + + for (i = 0; i < numt; i++) { + // Random starting pos + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + + // Find a location for the mini set piece + found = 0; + trys = 0; + while ((found == 0) && (trys < 200)) { + trys++; + found = 1; + +// if (((sx >= SP3x1) && (sx <= SP3x2)) && ((sy >= SP3y1) && (sy <= SP3y2))) found = 0; + + if ((cx != -1) && (sx >= (cx - sw)) && (sx <= (cx + 12))) { + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + found = 0; + } + if ((cy != -1) && (sy >= (cy - sh)) && (sy <= (cy + 12))) { + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + found = 0; + } + ii = 2; + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + if (found == 0) { + sx++; + if (sx == (MDMAXX - sw)) { + sx = 0; + sy++; + if (sy == (MDMAXY - sh)) sy = 0; + } + } + } + + if (trys >= 200) return 1; + + // Place mini set piece + ii = (sh * sw) + 2; + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[ii] != 0) dungeon[sx+xx][sy+yy] = miniset[ii]; + ii++; + } + } + } + + if (setview == 1) { + ViewX = (sx << 1) + (DIRTEDGED2) + 1; + ViewY = (sy << 1) + (DIRTEDGED2) + 3; + } + + if (ldir == LVL_DOWN) { + LvlViewX = (sx << 1) + (DIRTEDGED2) + 1; + LvlViewY = (sy << 1) + (DIRTEDGED2) + 3; + } + + return 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3PlaceRndSet(const byte miniset[], int rndper) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int ii, kk; + int found; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Find a location for the mini set piece + for (sy = 0; sy < (MDMAXY - sh); sy++) { + for (sx = 0; sx < (MDMAXX - sw); sx++) { + found = 1; + ii = 2; + +// if (((sx >= SP3x1) && (sx <= SP3x2)) && ((sy >= SP3y1) && (sy <= SP3y2))) found = 0; + + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + + kk = (sh * sw) + 2; + if (miniset[kk] >= 84 && miniset[kk] <=100 && found == 1) { + if (dungeon[sx-1][sy] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx+1][sy] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx][sy+1] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx][sy-1] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + } + + if ((found == 1) && (random(0, 100) < rndper)) { + // Place mini set piece + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[kk] != 0) dungeon[sx+xx][sy+yy] = miniset[kk]; + kk++; + } + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static unsigned char DRLG_L3PlaceAcidPool(const byte miniset[], int rndper) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int ii, kk; + int found; + unsigned char made = 0; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Find a location for the mini set piece + for (sy = 0; sy < (MDMAXY - sh); sy++) { + for (sx = 0; sx < (MDMAXX - sw); sx++) { + found = 1; + ii = 2; + +// if (((sx >= SP3x1) && (sx <= SP3x2)) && ((sy >= SP3y1) && (sy <= SP3y2))) found = 0; + + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + + kk = (sh * sw) + 2; + if (miniset[kk] >= 84 && miniset[kk] <=100 && found == 1) { + if (dungeon[sx-1][sy] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx+1][sy] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx][sy+1] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + if (dungeon[sx][sy-1] >= 84 && dungeon[sx-1][sy] <= 100) found = 0; + } + + if ((found == 1) && (random(0, 100) < rndper)) { + // Place mini set piece + made = 1; + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[kk] != 0) dungeon[sx+xx][sy+yy] = miniset[kk]; + kk++; + } + } + } + } + } + return made; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3Abyss() +{ + int ax, sf, j; + + ax = MDMAXX - 1; + sf = 0; + while (sf == 0) { + for (j = 0; (j < MDMAXY) && (sf == 0); j++) + if (dungeon[ax][j] != 8) sf = 1; + if (sf == 0) ax--; + } + + abyssx = (ax << 1) + (DIRTEDGED2); + + for (j = 0; j < MDMAXY; j++) { + if (dungeon[ax][j] == 8) dungeon[ax][j] = 111; + if (dungeon[ax][j] == 2 || dungeon[ax][j] == 6) dungeon[ax][j] = 120; + if (dungeon[ax][j] == 3 || dungeon[ax][j] == 10) dungeon[ax][j] = 112; + if (dungeon[ax][j] < 111) dungeon[ax][j] = 7; + + if ((j & 0x0001) == 0) dungeon[ax+1][j] = 114; + else dungeon[ax+1][j] = 113; + if ((j & 0x0001) == 0) dungeon[ax+2][j] = 115; + else dungeon[ax+2][j] = 116; + if ((j & 0x0001) == 0) dungeon[ax+3][j] = 118; + else dungeon[ax+3][j] = 117; + } + + for (ax += 4; ax < MDMAXX; ax++) + for (j = 0; j < MDMAXY; j++) dungeon[ax][j] = 119; + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL WoodVertU(int i, int y) +{ + if ((dungeon[i+1][y] > 152 || dungeon[i+1][y] < 130) && + (dungeon[i-1][y] > 152 || dungeon[i-1][y] < 130)) + { + if (dungeon[i][y] == 7) return TRUE; + if (dungeon[i][y] == 10) return TRUE; + if (dungeon[i][y] == 126) return TRUE; + if (dungeon[i][y] == 129) return TRUE; + if (dungeon[i][y] == 134) return TRUE; + if (dungeon[i][y] == 136) return TRUE; + } + return FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL WoodVertD(int i, int y) +{ + if ((dungeon[i+1][y] > 152 || dungeon[i+1][y] < 130) && + (dungeon[i-1][y] > 152 || dungeon[i-1][y] < 130)) + { + if (dungeon[i][y] == 7) return TRUE; + if (dungeon[i][y] == 2) return TRUE; + if (dungeon[i][y] == 134) return TRUE; + if (dungeon[i][y] == 136) return TRUE; + } + return FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL WoodHorizL(int x, int j) +{ + if ((dungeon[x][j+1] > 152 || dungeon[x][j+1] < 130) && + (dungeon[x][j-1] > 152 || dungeon[x][j-1] < 130)) + { + if (dungeon[x][j] == 7) return TRUE; + if (dungeon[x][j] == 9) return TRUE; + if (dungeon[x][j] == 121) return TRUE; + if (dungeon[x][j] == 124) return TRUE; + if (dungeon[x][j] == 135) return TRUE; + if (dungeon[x][j] == 137) return TRUE; + } + return FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL WoodHorizR(int x, int j) +{ + if ((dungeon[x][j+1] > 152 || dungeon[x][j+1] < 130) && + (dungeon[x][j-1] > 152 || dungeon[x][j-1] < 130)) + { + if (dungeon[x][j] == 7) return TRUE; + if (dungeon[x][j] == 4) return TRUE; + if (dungeon[x][j] == 135) return TRUE; + if (dungeon[x][j] == 137) return TRUE; + } + return FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AddFenceDoors(void) +/*-----------------------------------------------------------------------** +** DESCRIPTION: Adds doors to open spaces in fence lines +** INPUT: None +** RETURN: None +/*-----------------------------------------------------------------------*/ +{ + int i, j; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + //Add horizontal doors + if (dungeon[i][j] == FLOOR && + ((dungeon[i-1][j] <= 152 && dungeon[i-1][j] >= 130) && + (dungeon[i+1][j] <= 152 && dungeon[i+1][j] >= 130))) + dungeon[i][j] = WOOD_HORIZGATE; + //Add vertical doors + else if (dungeon[i][j] == FLOOR && + ((dungeon[i][j-1] <= 152 && dungeon[i][j-1] >= 130) && + (dungeon[i][j+1] <= 152 && dungeon[i][j+1] >= 130))) + dungeon[i][j] = WOOD_VERTGATE; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void FenceDoorFix(void) +/*-----------------------------------------------------------------------** +** DESCRIPTION: Fixes any free standing doors. This removes any doors which +** are not attached to a fence line. +** INPUT: None +** RETURN: None +/*-----------------------------------------------------------------------*/ +{ + int i, j; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if (dungeon[i][j] == WOOD_HORIZGATE && + ((dungeon[i+1][j] > 152 || dungeon[i+1][j] < 130) || + (dungeon[i-1][j] > 152 || dungeon[i-1][j] < 130))) + dungeon[i][j] = FLOOR; + else if (dungeon[i][j] == WOOD_HORIZGATE && + dungeon[i+1][j] != 130 && dungeon[i-1][j] != 130 && + dungeon[i+1][j] != 132 && dungeon[i-1][j] != 132 && + dungeon[i+1][j] != 133 && dungeon[i-1][j] != 133 && + dungeon[i+1][j] != 134 && dungeon[i-1][j] != 134 && + dungeon[i+1][j] != 136 && dungeon[i-1][j] != 136 && + dungeon[i+1][j] != 138 && dungeon[i-1][j] != 138 && + dungeon[i+1][j] != 140 && dungeon[i-1][j] != 140) + dungeon[i][j] = FLOOR; + else if (dungeon[i][j] == WOOD_VERTGATE && + ((dungeon[i][j+1] > 152 || dungeon[i][j+1] < 130) || + (dungeon[i][j-1] > 152 || dungeon[i][j-1] < 130))) + dungeon[i][j] = FLOOR; + else if (dungeon[i][j] == WOOD_VERTGATE && + dungeon[i][j+1] != 131 && dungeon[i][j-1] != 131 && + dungeon[i][j+1] != 132 && dungeon[i][j-1] != 132 && + dungeon[i][j+1] != 133 && dungeon[i][j-1] != 133 && + dungeon[i][j+1] != 135 && dungeon[i][j-1] != 135 && + dungeon[i][j+1] != 137 && dungeon[i][j-1] != 137 && + dungeon[i][j+1] != 138 && dungeon[i][j-1] != 138 && + dungeon[i][j+1] != 139 && dungeon[i][j-1] != 139) + dungeon[i][j] = FLOOR; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3Wood() +{ + int i,j; + int x,y; + int xx,yy; + int rt, rp, skip; + int x1,y1,x2,y2; + + // Put wood in walls/corners + for (j = 0; j < MDMAXY-1; j++) { + for (i = 0; i < MDMAXX-1; i++) { + if ((dungeon[i][j] == 10) && (random(0, 2))) { + x = i; + while (dungeon[x][j] == 10) x++; + x--; + if ((x - i) > 0) { + dungeon[i][j] = 127; + for (xx = i+1; xx < x; xx++) { + if (random(0, 2)) dungeon[xx][j] = 126; + else dungeon[xx][j] = 129; + } + dungeon[x][j] = 128; + } + } + if ((dungeon[i][j] == 9) && (random(0, 2))) { + y = j; + while (dungeon[i][y] == 9) y++; + y--; + if ((y - j) > 0) { + dungeon[i][j] = 123; + for (yy = j+1; yy < y; yy++) { + if (random(0, 2)) dungeon[i][yy] = 121; + else dungeon[i][yy] = 124; + } + dungeon[i][y] = 122; + } + } + if ((dungeon[i][j] == 11) && (dungeon[i+1][j] == 10) && (dungeon[i][j+1] == 9) && (random(0, 2))) { + dungeon[i][j] = 125; + x = i+1; + while (dungeon[x][j] == 10) x++; + x--; + for (xx = i+1; xx < x; xx++) { + if (random(0, 2)) dungeon[xx][j] = 126; + else dungeon[xx][j] = 129; + } + dungeon[x][j] = 128; + y = j+1; + while (dungeon[i][y] == 9) y++; + y--; + for (yy = j+1; yy < y; yy++) { + if (random(0, 2)) dungeon[i][yy] = 121; + else dungeon[i][yy] = 124; + } + dungeon[i][y] = 122; + } + } + } + + // Put wood lines in + for (j = 0; j < MDMAXY; j++) + { + for (i = 0; i < MDMAXX; i++) + { + if ((dungeon[i][j] == FLOOR) && (random(0, 1) == 0) && + (SkipThemeRoom(i, j))) + { + rt = random(0, 2); + x1 = 0; + y1 = 0; + //Create vertical fence + if (rt == 0) { + y1 = j; + while (WoodVertU(i,y1)) y1--; + y1++; + y2 = j; + while (WoodVertD(i,y2)) y2++; + y2--; + rp = 1; + if (dungeon[i][y1] == FLOOR) rp = 0; + if (dungeon[i][y2] == FLOOR) rp = 0; + if (((y2 - y1) > 1) && (rp != 0)) { + skip = random(0, y2 - y1 - 1) + y1 + 1; + for (y = y1; y <= y2; y++) { + if (y != skip) { + if (dungeon[i][y] == FLOOR) { + if (random(0, 2)) dungeon[i][y] = 135; + else dungeon[i][y] = 137; + } + if (dungeon[i][y] == 10) dungeon[i][y] = 131; + if (dungeon[i][y] == 126) dungeon[i][y] = 133; + if (dungeon[i][y] == 129) dungeon[i][y] = 133; + if (dungeon[i][y] == 2) dungeon[i][y] = 139; + if (dungeon[i][y] == 134) dungeon[i][y] = 138; + if (dungeon[i][y] == 136) dungeon[i][y] = 138; + } + } + } + } + //Create horizontal fence + if (rt == 1) { + x1 = i; + while (WoodHorizL(x1,j)) x1--; + x1++; + x2 = i; + while (WoodHorizR(x2,j)) x2++; + x2--; + rp = 1; + if (dungeon[x1][j] == FLOOR) rp = 0; + if (dungeon[x2][j] == FLOOR) rp = 0; + if (((x2 - x1) > 1) && (rp != 0)) { + skip = random(0, x2 - x1 - 1) + x1 + 1; + for (x = x1; x <= x2; x++) { + if (x != skip) { + if (dungeon[x][j] == FLOOR) { + if (random(0, 2)) dungeon[x][j] = 134; + else dungeon[x][j] = 136; + } + if (dungeon[x][j] == 9) dungeon[x][j] = 130; + if (dungeon[x][j] == 121) dungeon[x][j] = 132; + if (dungeon[x][j] == 124) dungeon[x][j] = 132; + if (dungeon[x][j] == 4) dungeon[x][j] = 140; + if (dungeon[x][j] == 135) dungeon[x][j] = 138; + if (dungeon[x][j] == 137) dungeon[x][j] = 138; + } + } + } + } + } + } + } + + //Add doors to fences + AddFenceDoors(); + FenceDoorFix(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* + +void DRLG_L3FTVR(int i, int j, int x, int y, int d) +{ + if ((dTransVal[x][y] == 0) && (dungeon[i][j] == FLOOR)) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + DRLG_L3FTVR(i+1,j, x+2,y, 1); + DRLG_L3FTVR(i-1,j, x-2,y, 2); + DRLG_L3FTVR(i,j+1, x,y+2, 3); + DRLG_L3FTVR(i,j-1, x,y-2, 4); + + DRLG_L3FTVR(i-1,j-1, x-2,y-2, 5); + DRLG_L3FTVR(i+1,j-1, x+2,y-2, 6); + DRLG_L3FTVR(i-1,j+1, x-2,y+2, 7); + DRLG_L3FTVR(i+1,j+1, x+2,y+2, 8); + } else { + if (d == 1) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 2) { + dTransVal[x+1][y] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 3) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 4) { + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 5) dTransVal[x+1][y+1] = TransVal; + if (d == 6) dTransVal[x][y+1] = TransVal; + if (d == 7) dTransVal[x+1][y] = TransVal; + if (d == 8) dTransVal[x][y] = TransVal; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* + +void DRLG_L3FloodTVal() +{ + int i, j; + int xx,yy; + + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == FLOOR) && (dTransVal[xx][yy] == 0)) { + DRLG_L3FTVR(i,j,xx,yy,0); + TransVal++; + } + xx += 2; + } + yy += 2; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* + +void DRLG_L3TransFix() +{ + int i, j; + int xx,yy; + + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == UR_WALL) && (dungeon[i][j-1] == LEFT_WALL)) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if ((dungeon[i][j] == LL_WALL) && (dungeon[i+1][j] == TOP_WALL)) { + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == LEFT_WALL) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == TOP_WALL) { + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == LR_WALL) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + xx += 2; + } + yy += 2; + } + + yy = DMAXY - DIRTEDGED2 - 2; + for (j = 0; j < MDMAXY; j++) { + xx = DMAXX - DIRTEDGED2 - 2; + for (i = 0; i < MDMAXX; i++) { + if ((dTransVal[xx-1][yy] != 0) || + (dTransVal[xx][yy-1] != 0) || + (dTransVal[xx-1][yy-1] != 0)) { + dTransVal[xx][yy] = 1; + dTransVal[xx+1][yy] = 1; + dTransVal[xx][yy+1] = 1; + dTransVal[xx+1][yy+1] = 1; + } + xx -= 2; + } + yy -= 2; + } + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dTransVal[i][j] != 0) dTransVal[i][j] = 1; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +int DRLG_L3Anvil() +{ + int sx, sy; + int sw, sh; + int xx, yy; + int ii; + int found, trys; + + // Width and height of the mini set piece + sw = L3ANVIL[0]; + sh = L3ANVIL[1]; + + // Random starting pos + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + + // Find a location for the mini set piece + found = 0; + trys = 0; + while ((found == 0) && (trys < 200)) { + trys++; + found = 1; + +// if (((sx >= SP3x1) && (sx <= SP3x2)) && ((sy >= SP3y1) && (sy <= SP3y2))) found = 0; + + ii = 2; + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((L3ANVIL[ii] != 0) && (dungeon[sx+xx][sy+yy] != L3ANVIL[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + if (found == 0) { + sx++; + if (sx == (MDMAXX - sw)) { + sx = 0; + sy++; + if (sy == (MDMAXY - sh)) sy = 0; + } + } + } + + if (trys >= 200) return 1; + + // Place mini set piece + ii = (sh * sw) + 2; + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (L3ANVIL[ii] != 0) dungeon[sx+xx][sy+yy] = L3ANVIL[ii]; + dflags[sx+xx][sy+yy] |= SETP_BIT; + ii++; + } + } + + setpc_x = sx; + setpc_y = sy; + setpc_w = sw; + setpc_h = sh; + + return 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void FixL3Warp() +{ + int i, j; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 125) && + (dungeon[i+1][j] == 125) && + (dungeon[i][j+1] == 125) && + (dungeon[i+1][j+1] == 125)) { + dungeon[i][j] = 156; + dungeon[i+1][j] = 155; + dungeon[i][j+1] = 153; + dungeon[i+1][j+1] = 154; + return; + } + if ((dungeon[i][j] == 5) && (dungeon[i+1][j+1] == 7)) + dungeon[i][j] = 7; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void FixL3HallofHeroes() +{ + int i, j; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 5) && (dungeon[i+1][j+1] == 7)) + dungeon[i][j] = 7; + } + } + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 5) && (dungeon[i+1][j+1] == 12) && (dungeon[i+1][j] == 7)) { + dungeon[i][j] = 7; + dungeon[i][j+1] = 7; + dungeon[i+1][j+1] = 7; + } + if ((dungeon[i][j] == 5) && (dungeon[i+1][j+1] == 12) && (dungeon[i][j+1] == 7)) { + dungeon[i][j] = 7; + dungeon[i+1][j] = 7; + dungeon[i+1][j+1] = 7; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +byte lockout[MDMAXX][MDMAXY]; +int lockoutcnt; + +void DRLG_L3LockRec(int x, int y) +{ + if (lockout[x][y] != 0) { + lockout[x][y] = 0; + lockoutcnt++; + DRLG_L3LockRec(x, y-1); + DRLG_L3LockRec(x, y+1); + DRLG_L3LockRec(x-1, y); + DRLG_L3LockRec(x+1, y); + } +} + +BOOL DRLG_L3Lockout() +{ + int i,j,t; + int fx,fy; + + t = 0; + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if (dungeon[i][j] != 0) { + lockout[i][j] = 1; + fx = i; + fy = j; + t++; + } else lockout[i][j] = 0; + } + } + lockoutcnt = 0; + DRLG_L3LockRec(fx, fy); + if (t == lockoutcnt) return(TRUE); + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DRLG_L3(int entry) +{ + int x1, y1, x2, y2, sx1, sy1; + int i, j; + int found; + BOOL genok; + + lavapool = FALSE; + do { + do { + do { // do this till MIN AREA is met. + InitL3Dungeon(); // fill dungeon with fill + + x1 = random(0, MDMAXX >> 1) + (MDMAXX >> 2); // random number 0-30 + y1 = random(0, MDMAXY >> 1) + (MDMAXY >> 2); + x2 = x1 + 2; + y2 = y1 + 2; + DRLG_L3FillRoom(x1,y1,x2,y2); // if empty, randomly fill dungeon with 1s + DRLG_L3CreateBlock(x1,y1,2,BLK_U); // recursively add blocks at random directions + DRLG_L3CreateBlock(x2,y1,2,BLK_R); // starting with the direction listed at the + DRLG_L3CreateBlock(x1,y2,2,BLK_D); // end of the function + DRLG_L3CreateBlock(x1,y1,2,BLK_L); + + if (QuestStatus(Q_ANVIL)) { // force this whole area to be a floor + sx1 = random(0, MDMAXX >> 2) + (MDMAXX >> 2); + sy1 = random(0, MDMAXY >> 2) + (MDMAXY >> 2); + DRLG_L3FloorArea(sx1, sy1, sx1+12, sy1+12); + } + + DRLG_L3FillDiags(); + DRLG_L3FillSingles(); + DRLG_L3FillStraights(); + DRLG_L3FillDiags(); + DRLG_L3Edges(); + if (DRLG_L3GetFloorArea() >= MINFAREA) { + genok = DRLG_L3Lockout(); + } else genok = FALSE; + } while (! genok); + DRLG_L3MakeMegas(); + +//************************************************************* +// Place stairs +//************************************************************* + + if (entry == LVL_DOWN) { + if (currlevel < HIVESTART) + found = DRLG_L3PlaceMiniSet(L3UP, 1, 1, -1, -1, 1, LVL_DOWN); + else // place stairs down. On first level have town warp stairs + { + if (currlevel != HIVESTART) + found = DRLG_L3PlaceMiniSet(L6UP, 1, 1, -1, -1, 1, LVL_DOWN); + else + found = DRLG_L3PlaceMiniSet(L6HOLDWARP, 1, 1, -1, -1, 1, LVL_TWARPDN); // JKE add hive + } + + if (found == 0) // Place stairs down + { + if (currlevel < HIVESTART) + found = DRLG_L3PlaceMiniSet(L3DOWN, 1, 1, -1, -1, 0, LVL_UP); + else + if (currlevel != HIVEEND) // no stairs down on last level + found = DRLG_L3PlaceMiniSet(L6DOWN, 1, 1, -1, -1, 0, LVL_UP); + } + + if ((found == 0) && (currlevel == 9)) + { + if (currlevel < HIVESTART) + found = DRLG_L3PlaceMiniSet(L3HOLDWARP, 1, 1, -1, -1, 0, LVL_TWARPDN); // add hive level JKE + } + } else { + if (entry == LVL_UP) { + if (currlevel < HIVESTART) + found = DRLG_L3PlaceMiniSet(L3UP, 1, 1, -1, -1, 0, LVL_DOWN); + else + { + if (currlevel != HIVESTART) + found = DRLG_L3PlaceMiniSet(L6UP, 1, 1, -1, -1, 0, LVL_DOWN); + else + found = DRLG_L3PlaceMiniSet(L6HOLDWARP, 1, 1, -1, -1, 0, LVL_TWARPDN); // JKE add hive + } + if (found == 0) { + if (currlevel < HIVESTART) + { + found = DRLG_L3PlaceMiniSet(L3DOWN, 1, 1, -1, -1, 1, LVL_UP); + ViewX += 2; + ViewY -= 2; + } + else + { + if (currlevel != HIVEEND) + { + found = DRLG_L3PlaceMiniSet(L6DOWN, 1, 1, -1, -1, 1, LVL_UP); + ViewX += 2; + ViewY -= 2; + } + } + + if ((found == 0) && (currlevel == 9)) + if (currlevel < HIVESTART) + found = DRLG_L3PlaceMiniSet(L3HOLDWARP, 1, 1, -1, -1, 0, LVL_TWARPDN); // JKE add hive + } + } else { + if (currlevel < HIVESTART) + found = DRLG_L3PlaceMiniSet(L3UP, 1, 1, -1, -1, 0, LVL_DOWN); + else + { + if (currlevel != HIVESTART) + found = DRLG_L3PlaceMiniSet(L6UP, 1, 1, -1, -1, 0, LVL_DOWN); + else + found = DRLG_L3PlaceMiniSet(L6HOLDWARP, 1, 1, -1, -1, 1, LVL_TWARPDN); // JKE add hive + } + if (found == 0) + if (currlevel < HIVESTART) + found = DRLG_L3PlaceMiniSet(L3DOWN, 1, 1, -1, -1, 0, LVL_UP); + else + if (currlevel != HIVEEND) + found = DRLG_L3PlaceMiniSet(L6DOWN, 1, 1, -1, -1, 0, LVL_UP); + + if ((found == 0) && (currlevel == 9)) + found = DRLG_L3PlaceMiniSet(L3HOLDWARP, 1, 1, -1, -1, 1, LVL_TWARPDN); // JKE add hive + } + } + + if ((found == 0) && QuestStatus(Q_ANVIL)) + found = DRLG_L3Anvil(); + + } while (found == 1); + +// if (currlevel < HIVESTART) +// DRLG_L3Abyss(); +// JKE temp hack remove lava + if (currlevel < HIVESTART) + DRLG_L3Pool(); + else + { +// lavapool = TRUE; + lavapool += DRLG_L3PlaceAcidPool(L6ACID3, 30); + lavapool += DRLG_L3PlaceAcidPool(L6ACID4, 40); + lavapool += DRLG_L3PlaceAcidPool(L6ACID1, 50); + lavapool += DRLG_L3PlaceAcidPool(L6ACID2, 60); + + if (lavapool < 3) + lavapool = FALSE; + } +// AcidPool(); + + } while (!lavapool); + +// JKE temp hack remove lava + if (currlevel < HIVESTART) + DRLG_L3PoolFix(); +// else +// AcidPoolFix(); + + if (currlevel < HIVESTART) + FixL3Warp(); +// JKE temp hack remove lava + if (currlevel < HIVESTART) + { + DRLG_L3PlaceRndSet(L3ISLE1, 70); + DRLG_L3PlaceRndSet(L3ISLE2, 70); + DRLG_L3PlaceRndSet(L3ISLE3, 30); + DRLG_L3PlaceRndSet(L3ISLE4, 30); + DRLG_L3PlaceRndSet(L3ISLE1, 100); + DRLG_L3PlaceRndSet(L3ISLE2, 100); + DRLG_L3PlaceRndSet(L3ISLE5, 90); + } + else + { + DRLG_L3PlaceRndSet(ACIDISLE1, 70); + DRLG_L3PlaceRndSet(ACIDISLE2, 70); + DRLG_L3PlaceRndSet(ACIDISLE3, 30); + DRLG_L3PlaceRndSet(ACIDISLE4, 30); + DRLG_L3PlaceRndSet(ACIDISLE1, 100); + DRLG_L3PlaceRndSet(ACIDISLE2, 100); + DRLG_L3PlaceRndSet(ACIDISLE5, 90); + } + + if (currlevel < HIVESTART) + FixL3HallofHeroes(); + +// temp hack JKE remove lava + if (currlevel < HIVESTART) + DRLG_L3River(); + + // this may make other lockouts - (only on lvl10 with anvil quest). . . . + // this is a kludgy fix for anvil quest - the bridge to the anvil was sometimes getting + // blocked by river, this makes the "fake" walls back into the bridge - rjs + if (QuestStatus(Q_ANVIL)) { + dungeon[setpc_x + 7][setpc_y + 5] = 7; + dungeon[setpc_x + 8][setpc_y + 5] = 7; + dungeon[setpc_x + 9][setpc_y + 5] = 7; + if ((dungeon[setpc_x + 10][setpc_y + 5] == 17) || + (dungeon[setpc_x + 10][setpc_y + 5] == 18)) dungeon[setpc_x + 10][setpc_y + 5] = 45; + } + + if (currlevel < HIVESTART) + DRLG_PlaceThemeRooms(5, 10, FLOOR, 0, FALSE); +// temp hack JKE remove most + if (currlevel < HIVESTART) + { + DRLG_L3Wood(); + + DRLG_L3PlaceRndSet(L3TITE1, 10); + DRLG_L3PlaceRndSet(L3TITE2, 10); + DRLG_L3PlaceRndSet(L3TITE3, 10); + DRLG_L3PlaceRndSet(L3TITE6, 20); + DRLG_L3PlaceRndSet(L3TITE7, 20); + //DRLG_L3PlaceRndSet(L3TITE4, 10); + //DRLG_L3PlaceRndSet(L3TITE5, 10); + DRLG_L3PlaceRndSet(L3TITE8, 20); + DRLG_L3PlaceRndSet(L3TITE9, 20); + DRLG_L3PlaceRndSet(L3TITE10,20); + DRLG_L3PlaceRndSet(L3TITE11,30); + DRLG_L3PlaceRndSet(L3TITE12,20); + DRLG_L3PlaceRndSet(L3TITE13,20); + + DRLG_L3PlaceRndSet(L3CREV1, 30); + DRLG_L3PlaceRndSet(L3CREV2, 30); + DRLG_L3PlaceRndSet(L3CREV3, 30); + DRLG_L3PlaceRndSet(L3CREV4, 30); + DRLG_L3PlaceRndSet(L3CREV5, 30); + DRLG_L3PlaceRndSet(L3CREV6, 30); + DRLG_L3PlaceRndSet(L3CREV7, 30); + DRLG_L3PlaceRndSet(L3CREV8, 30); + DRLG_L3PlaceRndSet(L3CREV9, 30); + DRLG_L3PlaceRndSet(L3CREV10,30); + DRLG_L3PlaceRndSet(L3CREV11,30); + + DRLG_L3PlaceRndSet(L3XTRA1,25); + DRLG_L3PlaceRndSet(L3XTRA2,25); + DRLG_L3PlaceRndSet(L3XTRA3,25); + DRLG_L3PlaceRndSet(L3XTRA4,25); + DRLG_L3PlaceRndSet(L3XTRA5,25); + } + else // JKE Place our tiles here. + { +// DRLG_L3PlaceRndSet(L6ACIDTEST,25); + DRLG_L3PlaceRndSet(L6FILL1,20); // JKE Tile to sub, and % to exchange. + DRLG_L3PlaceRndSet(L6FILL2,20); + DRLG_L3PlaceRndSet(L6FILL3,20); + DRLG_L3PlaceRndSet(L6FILL4,20); + + DRLG_L3PlaceRndSet(L6TITE1,10); + DRLG_L3PlaceRndSet(L6TITE2,15); + DRLG_L3PlaceRndSet(L6TITE3,20); + DRLG_L3PlaceRndSet(L6TITE4,25); + DRLG_L3PlaceRndSet(L6TITE5,30); + DRLG_L3PlaceRndSet(L6TITE6,35); + DRLG_L3PlaceRndSet(L6TITE7,40); + DRLG_L3PlaceRndSet(L6TITE8,45); + DRLG_L3PlaceRndSet(L6TITE9,50); + DRLG_L3PlaceRndSet(L6TITE10,55); + + DRLG_L3PlaceRndSet(L6TITE10,10); + DRLG_L3PlaceRndSet(L6TITE9,15); + DRLG_L3PlaceRndSet(L6TITE8,20); + DRLG_L3PlaceRndSet(L6TITE7,25); + DRLG_L3PlaceRndSet(L6TITE6,30); + DRLG_L3PlaceRndSet(L6TITE5,35); + DRLG_L3PlaceRndSet(L6TITE4,40); + DRLG_L3PlaceRndSet(L6TITE3,45); + DRLG_L3PlaceRndSet(L6TITE2,50); + DRLG_L3PlaceRndSet(L6TITE1,55); + + DRLG_L3PlaceRndSet(L6FLOOR5,40); + DRLG_L3PlaceRndSet(L6FLOOR6,45); + + DRLG_L3PlaceRndSet(L6FLOOR1,25); + DRLG_L3PlaceRndSet(L6FLOOR2,25); + DRLG_L3PlaceRndSet(L6FLOOR3,25); + DRLG_L3PlaceRndSet(L6FLOOR4,25); + DRLG_L3PlaceRndSet(L6WALL1,25); + DRLG_L3PlaceRndSet(L6WALL2,25); + DRLG_L3PlaceRndSet(L6WALL3,25); + DRLG_L3PlaceRndSet(L6WALL4,25); + DRLG_L3PlaceRndSet(L6WALL5,25); + DRLG_L3PlaceRndSet(L6WALL6,25); + DRLG_L3PlaceRndSet(L6WALL7,25); + DRLG_L3PlaceRndSet(L6WALL8,25); + DRLG_L3PlaceRndSet(L6WALL9,25); + DRLG_L3PlaceRndSet(L6WALL10,25); + DRLG_L3PlaceRndSet(L6WALL11,25); + DRLG_L3PlaceRndSet(L6WALL12,25); + DRLG_L3PlaceRndSet(L6WALL13,25); + DRLG_L3PlaceRndSet(L6WALL14,25); + DRLG_L3PlaceRndSet(L6CORNER1,25); + DRLG_L3PlaceRndSet(L6CORNER2,25); + DRLG_L3PlaceRndSet(L6CORNER3,25); + DRLG_L3PlaceRndSet(L6CORNER4,25); + + } + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) pdungeon[i][j] = dungeon[i][j]; + } + + extern void DRLG_Init_Globals(); + DRLG_Init_Globals(); + +// DRLG_CheckQuests(SP3x1,SP3y1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L3Pass3() +{ + int i,j,xx,yy; + long v1,v2,v3,v4,lv; + + // Init dungeon to dirt + lv = L3_DIRT - 1; + __asm { + mov esi,dword ptr [pMegaTiles] + mov eax,dword ptr [lv]; + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + + for (yy = 0; yy < DMAXY; yy+=2) { + for (xx = 0; xx < DMAXX; xx+=2) { //DMAXX = abyssx for abyss + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + } + } + + // Convert dungeon mega tiles to mini tiles + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + lv = ((long)dungeon[i][j]) - 1; + if (lv >= 0) { + __asm { + mov esi,dword ptr [pMegaTiles] + mov eax,dword ptr [lv]; + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + } else { + v1 = 0; + v2 = 0; + v3 = 0; + v4 = 0; + } + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + xx += 2; + } + yy += 2; + } + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#if IS_VERSION(RETAIL) +void CreateL3Dungeon(unsigned int rseed, int entry) +{ + int i,j; + + SetRndSeed(rseed); + + dminx = DIRTEDGED2; + dminy = DIRTEDGED2; + dmaxx = DMAXX - (DIRTEDGED2); + dmaxy = DMAXY - (DIRTEDGED2); + + //DRLG_LoadL3SP(); + DRLG_InitTrans(); // initialize transparent values + DRLG_InitSetPC(); // ? sets 4 pc values to 0 + DRLG_L3(entry); + DRLG_L3Pass3(); + //DRLG_FreeL3SP(); + + // Special lava lighting!!! JKE + if (currlevel < HIVESTART) + { + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if ((dPiece[i][j] >= 56) && (dPiece[i][j] <= 147)) DoLighting (i, j, 7, -1); + else if ((dPiece[i][j] >= 154) && (dPiece[i][j] <= 161)) DoLighting (i, j, 7, -1); + else if (dPiece[i][j] == 150) DoLighting (i, j, 7, -1); + else if (dPiece[i][j] == 152) DoLighting (i, j, 7, -1); + } + } + } + else + { + for (j = 0; j < DMAXY; j++) + for (i = 0; i < DMAXX; i++) + if ((dPiece[i][j] >= 382) && (dPiece[i][j] <= 457)) + DoLighting (i, j, 9, -1); + //dLight[i][j] = 1; + } + + DRLG_SetPC(); +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void LoadL3Dungeon(char sFileName[], int vx, int vy) +{ + int i, j, rw, rh; + byte *pLevelMap, *lm; + + InitL3Dungeon(); + + dminx = DIRTEDGED2; + dminy = DIRTEDGED2; + dmaxx = DMAXX - (DIRTEDGED2); + dmaxy = DMAXY - (DIRTEDGED2); + + DRLG_InitTrans(); + + pLevelMap = LoadFileInMemSig(sFileName,NULL,'LMPt'); + lm = pLevelMap; + + rw = *lm; + lm+=2; + rh = *lm; + lm+=2; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*lm != 0) { + dungeon[i][j] = *lm; + } else dungeon[i][j] = FLOOR; + lm+=2; + } + } + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) + if (dungeon[i][j] == 0) dungeon[i][j] = L3_DIRT; + } + + abyssx = DMAXX; + DRLG_L3Pass3(); + + extern void DRLG_Init_Globals(); + DRLG_Init_Globals(); + + ViewX = 31; + ViewY = 83; + + SetMapMonsters(pLevelMap, 0, 0); + SetMapObjects(pLevelMap, 0, 0); + + // Special lava lighting!!! + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if ((dPiece[i][j] >= 56) && (dPiece[i][j] <= 147)) DoLighting (i, j, 7, -1); + else if ((dPiece[i][j] >= 154) && (dPiece[i][j] <= 161)) DoLighting (i, j, 7, -1); + else if (dPiece[i][j] == 150) DoLighting (i, j, 7, -1); + else if (dPiece[i][j] == 152) DoLighting (i, j, 7, -1); + } + } + + DiabloFreePtr(pLevelMap); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void LoadPreL3Dungeon(char sFileName[], int vx, int vy) +{ + int i, j, rw, rh; + byte *pLevelMap, *lm; + + InitL3Dungeon(); + + DRLG_InitTrans(); + + pLevelMap = LoadFileInMemSig(sFileName,NULL,'LMPt'); + lm = pLevelMap; + + rw = *lm; + lm+=2; + rh = *lm; + lm+=2; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*lm != 0) { + dungeon[i][j] = *lm; + } else dungeon[i][j] = FLOOR; + lm+=2; + } + } + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) + if (dungeon[i][j] == 0) dungeon[i][j] = L3_DIRT; + } + + CopyMemory(pdungeon,dungeon,sizeof(pdungeon)); + + DiabloFreePtr(pLevelMap); +} diff --git a/src/DRLG_L3.H b/src/DRLG_L3.H new file mode 100644 index 0000000..b58d496 --- /dev/null +++ b/src/DRLG_L3.H @@ -0,0 +1,68 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/DRLG_L3.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define BLK_U 0 +#define BLK_R 1 +#define BLK_D 2 +#define BLK_L 3 + +#define L3_DIRT 8 + +//#define MINFAREA 1536 +#define MINFAREA 600 + +#define FR_FALSE 0 +#define FR_TRUE 1 + +#define UR_ISLE 14 +#define LL_ISLE 13 +#define LR_ISLE 12 +#define UL_WALL 11 +#define TOP_WALL 10 +#define LEFT_WALL 9 +#define FILL 8 +#define FLOOR 7 +#define LR_WALL 6 +#define UL_ISLE 5 +#define RIGHT_WALL 4 +#define UR_WALL 3 +#define BOTTOM_WALL 2 +#define LL_WALL 1 +#define D3_NULL 0 + +#define L3_NUMBLOCKS 124 + +#define NORTH 0 +#define SOUTH 1 +#define EAST 2 +#define WEST 3 + +#define WOOD_HORIZWALL 134 +#define WOOD_VERTWALL 137 +#define WOOD_LRCORNER 138 +#define WOOD_HORIZGATE 146 +#define WOOD_VERTGATE 147 +#define WOOD_ULCORNER 150 +#define WOOD_URCORNER 151 +#define WOOD_LLCORNER 152 + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void CreateL3Dungeon(unsigned int, int); +void LoadPreL3Dungeon(char [], int, int); +void LoadL3Dungeon(char [], int, int); +int DRLG_L3Spawn(int, int, int *); +BOOL SkipThemeRoom( int x, int y ); diff --git a/src/DRLG_L4.CPP b/src/DRLG_L4.CPP new file mode 100644 index 0000000..9083e2f --- /dev/null +++ b/src/DRLG_L4.CPP @@ -0,0 +1,1668 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Dungeon file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DRLG_L4.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +** CreateL1Dungeon +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "drlg_l4.h" +#include "gendung.h" +#include "scrollrt.h" +#include "engine.h" +#include "trigs.h" +#include "lighting.h" +#include "quests.h" +#include "multi.h" + +/*-----------------------------------------------------------------------* +** Diablo quads +**-----------------------------------------------------------------------*/ + +#define DIABSIZE 14 + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +byte dung[L4DUNX][L4DUNY]; +BOOL hallok[L4DUNY]; +byte L4dungeon[L4DX][L4DY]; +static const byte L4ConvTbl[16] = { 30, 6, 1, 6, 2, 6, 6, 6, 9, 6, 1, 6, 2, 6, 3, 6 }; +int SP4x1, SP4y1, SP4x2, SP4y2; +int l4holdx,l4holdy; + +int diabquad1x, diabquad2x, diabquad3x, diabquad4x; +int diabquad1y, diabquad2y, diabquad3y, diabquad4y; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static const byte L4USTAIRS[] = { 4, 5, // X size, Y size + + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + + 0, 0, 0, 0, + 36, 38, 35, 0, + 37, 34, 33, 32, + 0, 0, 31, 0, + 0, 0, 0, 0}; + +static const byte L4TWARP[] = { 4, 5, // X size, Y size + + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + + 0, 0, 0, 0, + 134, 136, 133, 0, + 135, 132, 131, 130, + 0, 0, 129, 0, + 0, 0, 0, 0}; + +static const byte L4DSTAIRS[] = { 5, 5, // X size, Y size + + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + + 0, 0, 0, 0, 0, + 0, 0, 45, 41, 0, + 0, 44, 43, 40, 0, + 0, 46, 42, 39, 0, + 0, 0, 0, 0, 0}; + +static const byte L4PENTA[] = { 5, 5, // X size, Y size + + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + + 0, 0, 0, 0, 0, + 0, 98, 100, 103, 0, + 0, 99, 102, 105, 0, + 0, 101, 104, 106, 0, + 0, 0, 0, 0, 0}; + +static const byte L4PENTA2[] = { 5, 5, // X size, Y size + + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, FLOOR_PIC, + + 0, 0, 0, 0, 0, + 0, 107, 109, 112, 0, + 0, 108, 111, 114, 0, + 0, 110, 113, 115, 0, + 0, 0, 0, 0, 0}; + +// Types for tile substitution +static const byte L4BTYPES[NUMBBLOCKS] = { 0, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, // L4Base + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30 // L4Dirt + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,//46 // L4Stairs + 0, 0, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0,//60 // L4Shadow + 1, 2, 1, 2, 1, 2, 1, 1, 2, 2,//70 // L4Misc + 0, 0, 0, 0, 0, 0, 15, 16, 9, 12, 4, 5, 7, //83 // L4Misc2 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,//97 // L4Floor + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,//115 // L4Penta + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,//128 // L4Dirt2 + 0, 0, 0, 0, 0, 0, 0, 0}; // L4Stair2 + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L4Shadows() +{ + int x,y; + BOOL okflag; + + for (y = 1; y < MDMAXY; y++) { + for (x = 1; x < MDMAXX; x++) { + okflag = FALSE; + if (dungeon[x][y] == 3) okflag = TRUE; + if (dungeon[x][y] == 4) okflag = TRUE; + if (dungeon[x][y] == 8) okflag = TRUE; + if (dungeon[x][y] == 15) okflag = TRUE; + if (okflag) { + if (dungeon[x-1][y] == 6) dungeon[x-1][y] = 47; + if (dungeon[x-1][y-1] == 6) dungeon[x-1][y-1] = 48; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void InitL4Dungeon() +{ + ZeroMemory(dung,sizeof(dung)); + ZeroMemory(L4dungeon,sizeof(L4dungeon)); + + for (int j = 0; j < MDMAXY; j++) { + for (int i = 0; i < MDMAXX; i++) { + dungeon[i][j] = 30; //L4_DIRT;DIRT_PIC + dflags[i][j] = 0; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DRLG_LoadL4SP() +{ + setloadflag = FALSE; + if (QuestStatus(Q_WARLORD)) { + app_assert(gbMaxPlayers == 1); + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\Warlord.DUN",NULL,'STPC'); + setloadflag = TRUE; + } + if ((currlevel == 15) && (gbMaxPlayers != 1)) { + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\Vile1.DUN", NULL, 'STPC'); + setloadflag = TRUE; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DRLG_FreeL4SP() { + DiabloFreePtr(pSetPiece); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DRLG_L4SetSPRoom(int rx1, int ry1) +{ + int rw,rh; + int i,j; + byte *sp; + + sp = pSetPiece; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_x = rx1; + setpc_y = ry1; + setpc_w = rw; + setpc_h = rh; + + sp = pSetPiece+4; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*sp != 0) { + dungeon[rx1+i][ry1+j] = *sp; + dflags[rx1+i][ry1+j] |= SETP_BIT; + } else dungeon[rx1+i][ry1+j] = FLOOR_PIC; + sp+=2; + } + } + + } + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void L4makeDmt() +{ + int i, j; + int idx; + int val; + int dmtx, dmty; + + dmty = 0; + for (j = 1; j <= 77; j+=2) { + dmtx = 0; + for (i = 1; i <= 77; i+=2) { + idx = L4dungeon[i][j] + (L4dungeon[i+1][j]<<1) + + (L4dungeon[i][j+1]<<2) + (L4dungeon[i+1][j+1]<<3); + val = L4ConvTbl[idx]; + dungeon[dmtx][dmty] = val; + dmtx++; + } + dmty++; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int L4HWallOk(int i, int j) +{ + int x; + BOOL wallok; + + x = 1; + while ((dungeon[i+x][j] == 6) && + (dflags[i+x][j] == 0) && + (dungeon[i+x][j-1] == 6) && + (dungeon[i+x][j+1] == 6)) x++; + wallok = FALSE; + if (dungeon[i+x][j] == 10) wallok = TRUE; + if (dungeon[i+x][j] == 12) wallok = TRUE; + if (dungeon[i+x][j] == 13) wallok = TRUE; + if (dungeon[i+x][j] == 15) wallok = TRUE; + if (dungeon[i+x][j] == 16) wallok = TRUE; + if (dungeon[i+x][j] == 21) wallok = TRUE; + if (dungeon[i+x][j] == 22) wallok = TRUE; + if (x <= 3) wallok = FALSE; + if (wallok) return(x); + else return(-1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int L4VWallOk(int i, int j) +{ + int y; + BOOL wallok; + + y = 1; + while ((dungeon[i][j+y] == 6) && + (dflags[i][j+y] == 0) && + (dungeon[i-1][j+y] == 6) && + (dungeon[i+1][j+y] == 6)) y++; + wallok = FALSE; + if (dungeon[i][j+y] == 8) wallok = TRUE; + if (dungeon[i][j+y] == 9) wallok = TRUE; + if (dungeon[i][j+y] == 11) wallok = TRUE; + if (dungeon[i][j+y] == 14) wallok = TRUE; + if (dungeon[i][j+y] == 15) wallok = TRUE; + if (dungeon[i][j+y] == 16) wallok = TRUE; + if (dungeon[i][j+y] == 21) wallok = TRUE; + if (dungeon[i][j+y] == 23) wallok = TRUE; + if (y <= 3) wallok = FALSE; + if (wallok) return(y); + else return(-1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void L4HorizWall(int i, int j, int dx) +{ + int xx; + + // Left side connector + if (dungeon[i][j] == 13) dungeon[i][j] = 17; + if (dungeon[i][j] == 16) dungeon[i][j] = 11; + if (dungeon[i][j] == 12) dungeon[i][j] = 14; + // Middle fill + for (xx = 1; xx < dx; xx++) dungeon[i+xx][j] = 2; + // Right side connector + if (dungeon[i+dx][j] == 15) dungeon[i+dx][j] = 14; + if (dungeon[i+dx][j] == 10) dungeon[i+dx][j] = 17; + if (dungeon[i+dx][j] == 21) dungeon[i+dx][j] = 23; + if (dungeon[i+dx][j] == 22) dungeon[i+dx][j] = 29; + // Put in arch + xx = random(0, dx-3) + 1; + dungeon[i+xx][j] = 57; + dungeon[i+xx+2][j] = 56; + // Arch shadows + dungeon[i+xx+1][j] = 60; + if (dungeon[i+xx][j-1] == 6) dungeon[i+xx][j-1] = 58; + if (dungeon[i+xx+1][j-1] == 6) dungeon[i+xx+1][j-1] = 59; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void L4VertWall(int i, int j, int dy) +{ + int yy; + + //Up side connector; + if (dungeon[i][j] == 14) dungeon[i][j] = 17; + if (dungeon[i][j] == 8) dungeon[i][j] = 9; + if (dungeon[i][j] == 15) dungeon[i][j] = 10; + //Middle fill + for (yy = 1; yy < dy; yy++) dungeon[i][j+yy] = 1; + //Down side connector + if (dungeon[i][j+dy] == 11) dungeon[i][j+dy] = 17; + if (dungeon[i][j+dy] == 9) dungeon[i][j+dy] = 10; + if (dungeon[i][j+dy] == 16) dungeon[i][j+dy] = 13; + if (dungeon[i][j+dy] == 21) dungeon[i][j+dy] = 22; + if (dungeon[i][j+dy] == 23) dungeon[i][j+dy] = 29; + // Put in arch + yy = random(0, dy-3) + 1; + dungeon[i][j+yy] = 53; + dungeon[i][j+yy+2] = 52; + // Arch shadows + dungeon[i][j+yy+1] = 6; + if (dungeon[i-1][j+yy] == 6) dungeon[i-1][j+yy] = 54; + if (dungeon[i-1][j+yy-1] == 6) dungeon[i-1][j+yy-1] = 55; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define WALLRND 100 +static void L4AddWall() +{ + int i, j; + int x, y; + + for (j = 0; j < MDMAXY ; j++) { + for (i = 0; i < MDMAXX; i++) { + if (dflags[i][j] == 0) { + // Horizontal + if ((dungeon[i][j] == 10) && (random(0, 100) < WALLRND)) { + x = L4HWallOk(i, j); + if (x != -1) L4HorizWall(i, j, x); + } + if ((dungeon[i][j] == 12) && (random(0, 100) < WALLRND)) { + x = L4HWallOk(i, j); + if (x != -1) L4HorizWall(i, j, x); + } + if ((dungeon[i][j] == 13) && (random(0, 100) < WALLRND)) { + x = L4HWallOk(i, j); + if (x != -1) L4HorizWall(i, j, x); + } + if ((dungeon[i][j] == 15) && (random(0, 100) < WALLRND)) { + x = L4HWallOk(i, j); + if (x != -1) L4HorizWall(i, j, x); + } + if ((dungeon[i][j] == 16) && (random(0, 100) < WALLRND)) { + x = L4HWallOk(i, j); + if (x != -1) L4HorizWall(i, j, x); + } + if ((dungeon[i][j] == 21) && (random(0, 100) < WALLRND)) { + x = L4HWallOk(i, j); + if (x != -1) L4HorizWall(i, j, x); + } + if ((dungeon[i][j] == 22) && (random(0, 100) < WALLRND)) { + x = L4HWallOk(i, j); + if (x != -1) L4HorizWall(i, j, x); + } + // Vertical + if ((dungeon[i][j] == 8) && (random(0, 100) < WALLRND)) { + y = L4VWallOk(i, j); + if (y != -1) L4VertWall(i, j, y); + } + if ((dungeon[i][j] == 9) && (random(0, 100) < WALLRND)) { + y = L4VWallOk(i, j); + if (y != -1) L4VertWall(i, j, y); + } + if ((dungeon[i][j] == 11) && (random(0, 100) < WALLRND)) { + y = L4VWallOk(i, j); + if (y != -1) L4VertWall(i, j, y); + } + if ((dungeon[i][j] == 14) && (random(0, 100) < WALLRND)) { + y = L4VWallOk(i, j); + if (y != -1) L4VertWall(i, j, y); + } + if ((dungeon[i][j] == 15) && (random(0, 100) < WALLRND)) { + y = L4VWallOk(i, j); + if (y != -1) L4VertWall(i, j, y); + } + if ((dungeon[i][j] == 16) && (random(0, 100) < WALLRND)) { + y = L4VWallOk(i, j); + if (y != -1) L4VertWall(i, j, y); + } + if ((dungeon[i][j] == 21) && (random(0, 100) < WALLRND)) { + y = L4VWallOk(i, j); + if (y != -1) L4VertWall(i, j, y); + } + if ((dungeon[i][j] == 23) && (random(0, 100) < WALLRND)) { + y = L4VWallOk(i, j); + if (y != -1) L4VertWall(i, j, y); + } + } + } + } +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void L4tileFix() +{ + int i, j; + // tiles in middle of dungeon + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 6)) dungeon[i+1][j] = 5; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 13; + + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 14; + } + } + + // tiles in middle of dungeon + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 6)) dungeon[i+1][j] = 2; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 9)) dungeon[i+1][j] = 11; + if ((dungeon[i][j] == 9) && (dungeon[i+1][j] == 6)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 13; + if ((dungeon[i][j] == 6) && (dungeon[i+1][j] == 14)) dungeon[i+1][j] = 15; + + if ((dungeon[i][j] == 6) && (dungeon[i][j+1] == 13)) dungeon[i][j+1] = 16; + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 10; + + if ((dungeon[i][j] == 6) && (dungeon[i][j-1] == 1)) dungeon[i][j-1] = 1; + } + } + + // around edges + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 27; + + if ((dungeon[i][j] == 27) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 19; + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 27; + if ((dungeon[i][j] == 27) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 16; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 27)) dungeon[i+1][j] = 26; + if ((dungeon[i][j] == 27) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 19; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 15)) dungeon[i+1][j] = 14; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 15)) dungeon[i+1][j] = 14; + if ((dungeon[i][j] == 22) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 16; + if ((dungeon[i][j] == 27) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 16; + if ((dungeon[i][j] == 6) && (dungeon[i+1][j] == 27) && (dungeon[i+1][j+1])) dungeon[i+1][j] = 22; + if ((dungeon[i][j] == 22) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 19; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 1) && (dungeon[i+1][j-1] == 1)) dungeon[i+1][j] = 13; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 30) && (dungeon[i][j+1] == 6)) dungeon[i+1][j] = 28; + + if ((dungeon[i][j] == 16) && (dungeon[i+1][j] == 6) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 27; + if ((dungeon[i][j] == 16) && (dungeon[i][j+1] == 30) && (dungeon[i+1][j+1] == 30)) dungeon[i][j+1] = 27; + if ((dungeon[i][j] == 6) && (dungeon[i+1][j] == 30) && (dungeon[i+1][j-1] == 6)) dungeon[i+1][j] = 21; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 27) && (dungeon[i+1][j+1] == 9)) dungeon[i+1][j] = 29; + if ((dungeon[i][j] == 9) && (dungeon[i+1][j] == 15)) dungeon[i+1][j] = 14; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 27) && (dungeon[i+1][j+1] == 2)) dungeon[i+1][j] = 29; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 18)) dungeon[i+1][j] = 24; + if ((dungeon[i][j] == 9) && (dungeon[i+1][j] == 15)) dungeon[i+1][j] = 14; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 19) && (dungeon[i+1][j-1] == 30)) dungeon[i+1][j] = 24; + if ((dungeon[i][j] == 24) && (dungeon[i][j-1] == 30) && (dungeon[i][j-2] == 6)) dungeon[i][j-1] = 21; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 28; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 28; + if ((dungeon[i][j] == 28) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 18; + if ((dungeon[i][j] == 28) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + + if ((dungeon[i][j] == 19) && (dungeon[i+2][j] == 2) && (dungeon[i+1][j-1] == 18) && (dungeon[i+1][j+1] == 1)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 19) && (dungeon[i+2][j] == 2) && (dungeon[i+1][j-1] == 22) && (dungeon[i+1][j+1] == 1)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 19) && (dungeon[i+2][j] == 2) && (dungeon[i+1][j-1] == 18) && (dungeon[i+1][j+1] == 13)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 21) && (dungeon[i+2][j] == 2) && (dungeon[i+1][j-1] == 18) && (dungeon[i+1][j+1] == 1)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j+1] == 1) && (dungeon[i+1][j-1] == 22) && (dungeon[i+2][j] == 3)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 28) && (dungeon[i+2][j] == 30) && (dungeon[i+1][j-1] == 6)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 28) && (dungeon[i+2][j] == 1)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 27) && (dungeon[i+1][j+1] == 30)) dungeon[i+1][j] = 29; + if ((dungeon[i][j] == 28) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j-1] == 21)) dungeon[i+1][j] = 24; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 27) && (dungeon[i+1][j+1] == 30)) dungeon[i+1][j] = 29; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 18)) dungeon[i+1][j] = 25; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 9) && (dungeon[i+2][j] == 2)) dungeon[i+1][j] = 11; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 10)) dungeon[i+1][j] = 17; + + if ((dungeon[i][j] == 15) && (dungeon[i][j+1] == 3)) dungeon[i][j+1] = 4; + + if ((dungeon[i][j] == 22) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 18) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 18; + if ((dungeon[i][j] == 24) && (dungeon[i-1][j] == 30)) dungeon[i-1][j] = 19; + if ((dungeon[i][j] == 21) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 21) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 10; + if ((dungeon[i][j] == 22) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 18; + if ((dungeon[i][j] == 21) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 18; + if ((dungeon[i][j] == 16) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 22) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 18) && (dungeon[i+2][j] == 30)) dungeon[i+1][j] = 24; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 9) && (dungeon[i+1][j+1] == 1)) dungeon[i+1][j] = 16; + + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 27) && (dungeon[i+1][j+1] == 2)) dungeon[i+1][j] = 29; + if ((dungeon[i][j] == 23) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 23) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 25) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 22) && (dungeon[i+1][j] == 9)) dungeon[i+1][j] = 11; + if ((dungeon[i][j] == 23) && (dungeon[i+1][j] == 9)) dungeon[i+1][j] = 11; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 16; + if ((dungeon[i][j] == 11) && (dungeon[i+1][j] == 15)) dungeon[i+1][j] = 14; + if ((dungeon[i][j] == 23) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 16; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 27)) dungeon[i+1][j] = 26; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 18)) dungeon[i+1][j] = 24; + if ((dungeon[i][j] == 26) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 16; + if ((dungeon[i][j] == 29) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 16; + if ((dungeon[i][j] == 29) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 1) && (dungeon[i][j-1] == 15)) dungeon[i][j-1] = 10; + if ((dungeon[i][j] == 18) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 23) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 18; + if ((dungeon[i][j] == 18) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 10; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 30) && (dungeon[i+1][j+1] == 30)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 28) && (dungeon[i+1][j-1] == 6)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 23) && (dungeon[i+1][j] == 18) && (dungeon[i][j-1] == 6)) dungeon[i+1][j] = 24; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 23) && (dungeon[i+2][j] == 30)) dungeon[i+1][j] = 28; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 28) && (dungeon[i+2][j] == 30) && (dungeon[i+1][j-1] == 6)) dungeon[i+1][j] = 23; + + // fill in blood around edges + if ((dungeon[i][j] == 23) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 19; + if ((dungeon[i][j] == 29) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 19; + if ((dungeon[i][j] == 29) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 18; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 19; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 19; + if ((dungeon[i][j] == 26) && (dungeon[i+1][j] == 30)) dungeon[i+1][j] = 19; + if ((dungeon[i][j] == 16) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 18; + + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 10; + if ((dungeon[i][j] == 25) && (dungeon[i][j+1] == 30)) dungeon[i][j+1] = 18; + if ((dungeon[i][j] == 18) && (dungeon[i][j+1] == 2)) dungeon[i][j+1] = 15; + if ((dungeon[i][j] == 11) && (dungeon[i+1][j] == 3)) dungeon[i+1][j] = 5; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 9)) dungeon[i+1][j] = 11; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 13; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 13) && (dungeon[i+1][j-1] == 6)) dungeon[i+1][j] = 16; + } + } + + // tiles in middle of dungeon + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 21) && (dungeon[i][j+1] == 24) && (dungeon[i][j+2] == 1)) dungeon[i][j+1] = 17; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j+1] == 9) && (dungeon[i+1][j-1] == 1) && (dungeon[i+2][j] == 16)) dungeon[i+1][j] = 29; + if ((dungeon[i][j] == 2) && (dungeon[i-1][j] == 6)) dungeon[i-1][j] = 8; + if ((dungeon[i][j] == 1) && (dungeon[i][j-1] == 6)) dungeon[i][j-1] = 7; + + if ((dungeon[i][j] == 6) && (dungeon[i+1][j] == 15) && (dungeon[i+1][j+1] == 4)) dungeon[i+1][j] = 10; + + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 3)) dungeon[i][j+1] = 4; + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 6)) dungeon[i][j+1] = 4; + if ((dungeon[i][j] == 9) && (dungeon[i][j+1] == 3)) dungeon[i][j+1] = 4; + if ((dungeon[i][j] == 10) && (dungeon[i][j+1] == 3)) dungeon[i][j+1] = 4; + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 3)) dungeon[i][j+1] = 4; + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 5)) dungeon[i][j+1] = 12; + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 16)) dungeon[i][j+1] = 13; + if ((dungeon[i][j] == 6) && (dungeon[i][j+1] == 13)) dungeon[i][j+1] = 16; + if ((dungeon[i][j] == 25) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 10; + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 5)) dungeon[i][j+1] = 12; + + if ((dungeon[i][j] == 28) && (dungeon[i][j-1] == 6) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 10)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 9)) dungeon[i+1][j] = 11; + if ((dungeon[i][j] == 11) && (dungeon[i+1][j] == 3)) dungeon[i+1][j] = 5; + if ((dungeon[i][j] == 10) && (dungeon[i+1][j] == 4)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 4)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 27) && (dungeon[i+1][j] == 9)) dungeon[i+1][j] = 11; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 4)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 1)) dungeon[i+1][j] = 16; + if ((dungeon[i][j] == 11) && (dungeon[i+1][j] == 4)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 3)) dungeon[i+1][j] = 5; + if ((dungeon[i][j] == 9) && (dungeon[i+1][j] == 3)) dungeon[i+1][j] = 5; + if ((dungeon[i][j] == 14) && (dungeon[i+1][j] == 3)) dungeon[i+1][j] = 5; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 3)) dungeon[i+1][j] = 5; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 5) && (dungeon[i+1][j-1] == 16)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 2) && (dungeon[i+1][j] == 4)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 9) && (dungeon[i+1][j] == 4)) dungeon[i+1][j] = 12; + + if ((dungeon[i][j] == 1) && (dungeon[i][j-1] == 8)) dungeon[i][j-1] = 9; + if ((dungeon[i][j] == 28) && (dungeon[i+1][j] == 23) && (dungeon[i+1][j+1] == 3)) dungeon[i+1][j] = 16; + } + } + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 10)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 17) && (dungeon[i+1][j] == 4)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 10) && (dungeon[i+1][j] == 4)) dungeon[i+1][j] = 12; + + if ((dungeon[i][j] == 17) && (dungeon[i][j+1] == 5)) dungeon[i][j+1] = 12; + if ((dungeon[i][j] == 29) && (dungeon[i][j+1] == 9)) dungeon[i][j+1] = 10; + if ((dungeon[i][j] == 13) && (dungeon[i][j+1] == 5)) dungeon[i][j+1] = 12; + if ((dungeon[i][j] == 9) && (dungeon[i][j+1] == 16)) dungeon[i][j+1] = 13; + if ((dungeon[i][j] == 10) && (dungeon[i][j+1] == 16)) dungeon[i][j+1] = 13; + if ((dungeon[i][j] == 16) && (dungeon[i][j+1] == 3)) dungeon[i][j+1] = 4; + if ((dungeon[i][j] == 11) && (dungeon[i][j+1] == 5)) dungeon[i][j+1] = 12; + if ((dungeon[i][j] == 10) && (dungeon[i+1][j] == 3) && (dungeon[i+1][j-1] == 16)) dungeon[i+1][j] = 12; + if ((dungeon[i][j] == 16) && (dungeon[i][j+1] == 5)) dungeon[i][j+1] = 12; + if ((dungeon[i][j] == 1) && (dungeon[i][j+1] == 6)) dungeon[i][j+1] = 4; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j] == 13) && (dungeon[i][j+1] == 10)) dungeon[i+1][j+1] = 12; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 10)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 22) && (dungeon[i][j+1] == 11)) dungeon[i][j+1] = 17; + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 28) && (dungeon[i+2][j] == 16)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 28) && (dungeon[i+1][j] == 23) && (dungeon[i+1][j+1] == 1) && (dungeon[i+2][j] == 6)) dungeon[i+1][j] = 16; + } + } + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == 15) && (dungeon[i+1][j] == 28) && (dungeon[i+2][j] == 16)) dungeon[i+1][j] = 23; + if ((dungeon[i][j] == 21) && (dungeon[i+1][j-1] == 21) && (dungeon[i+1][j+1] == 13) && (dungeon[i+2][j] == 2)) dungeon[i+1][j] = 17; + if ((dungeon[i][j] == 19) && (dungeon[i+1][j] == 15) && (dungeon[i+1][j+1] == 12)) dungeon[i+1][j] = 17; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L4Subs() +{ + int x,y,i,rv; + byte c; + + for (y = 0; y < MDMAXY; y++) { + for (x = 0; x < MDMAXX; x++) { + rv = random(0, 3); + if (rv == 0) { + c = dungeon[x][y]; + c = L4BTYPES[c]; + if ((c != 0) && (dflags[x][y] == 0)) { + rv = random(0, 16); + i = -1; + while (rv >= 0) { + i++; + if (i == NUMBBLOCKS) i = 0; + if (c == L4BTYPES[i]) rv--; + } + dungeon[x][y] = i; + } + } + } + } + for (y = 0; y < MDMAXY; y++) { + for (x = 0; x < MDMAXX; x++) { + rv = random(0, 10); + if (rv == 0) { + c = dungeon[x][y]; + c = L4BTYPES[c]; + if ((c == 6) && (dflags[x][y] == 0)) + dungeon[x][y] = random(0, 3) + 95; + } + } + } +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void L4makeDungeon() +{ + int i, j; + int k, l; + + // top left + for (j = 0; j < L4DUNY; j++) { + for(i = 0; i < L4DUNX; i++) { + k = i<<1; + l = j<<1; + L4dungeon[k][l] = dung[i][j]; + L4dungeon[k][l+1] = dung[i][j]; + L4dungeon[k+1][l] = dung[i][j]; + L4dungeon[k+1][l+1] = dung[i][j]; + } + } + // bottom left + for (j = 0; j < L4DUNY; j++) { + for(i = 0; i < L4DUNX; i++) { + k = i<<1; + l = j<<1; + L4dungeon[k][L4DUNY*2+l] = dung[i][L4DUNY - 1 - j]; + L4dungeon[k][L4DUNY*2+l+1] = dung[i][L4DUNY - 1 - j]; + L4dungeon[k+1][L4DUNY*2+l] = dung[i][L4DUNY - 1 - j]; + L4dungeon[k+1][L4DUNY*2+l+1] = dung[i][L4DUNY - 1 - j]; + } + } + // top right + for (j = 0; j < L4DUNY; j++) { + for(i = 0; i < L4DUNX; i++) { + k = i<<1; + l = j<<1; + L4dungeon[k+L4DUNX*2][l] = dung[L4DUNX - 1 - i][j]; + L4dungeon[k+L4DUNX*2][l+1] = dung[L4DUNX - 1 - i][j]; + L4dungeon[k+L4DUNX*2+1][l] = dung[L4DUNX - 1 - i][j]; + L4dungeon[k+L4DUNX*2+1][l+1] = dung[L4DUNX - 1 - i][j]; + } + } + // bottom right + for (j = 0; j < L4DUNY; j++) { + for(i = 0; i < L4DUNX; i++) { + k = i<<1; + l = j<<1; + L4dungeon[L4DUNX*2+k][L4DUNY*2+l] = dung[L4DUNX - 1 - i][L4DUNY - 1 - j]; + L4dungeon[L4DUNX*2+k][L4DUNY*2+l+1] = dung[L4DUNX - 1 - i][L4DUNY - 1 - j]; + L4dungeon[L4DUNX*2+k+1][L4DUNY*2+l] = dung[L4DUNX - 1 - i][L4DUNY - 1 - j]; + L4dungeon[L4DUNX*2+k+1][L4DUNY*2+l+1] = dung[L4DUNX - 1 - i][L4DUNY - 1 - j]; + } + } +} + +/*------------------------------------------------------------------------* +** Connecting the boxes to make U +**------------------------------------------------------------------------*/ +static void uShape() +{ + int j, i; + int rv; + + for (j = 19; j >= 0; j--) { + for (i = 19; i >= 0; i--) { + if (dung[i][j] != 1) hallok[j] = FALSE; + if (dung[i][j] == 1) { + if ((dung[i][j+1] == 1) && (dung[i+1][j+1] == 0)) { + hallok[j] = TRUE; + } + else hallok[j] = FALSE; + i = 0; // abort out of loop + } + } + } + rv = random(0, 19) + 1; + do{ + if (hallok[rv]) { + for (i = 19; i >= 0; i--) { + if (dung[i][rv] == 1) { + i = -1; + rv = 0; + } else { + dung[i][rv] = 1; + dung[i][rv+1] = 1; + } + + } + } else { + rv++; + if (rv == 20) rv = 1; + } + } while (rv != 0); + + for (i = 19; i >= 0; i--) { + for (j = 19; j >= 0; j--) { + if (dung[i][j] != 1) hallok[i] = FALSE; + if (dung[i][j] == 1) { + if ((dung[i+1][j] == 1) && (dung[i+1][j+1] == 0)) { + hallok[i] = TRUE; + } + else hallok[i] = FALSE; + j = 0; // abort out of loop + } + } + } + rv = random(0, 19) + 1; + do{ + if (hallok[rv]) { + for (j = 19; j >= 0; j--) { + if (dung[rv][j] == 1) { + j = -1; + rv = 0; + } else { + dung[rv][j] = 1; + dung[rv+1][j] = 1; + } + + } + } else { + rv++; + if (rv == 20) rv = 1; + } + } while (rv != 0); +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static long GetArea() +{ + int i,j; + long rv; + + rv = 0; + for (j = 0; j < L4DUNY; j++) { + for (i = 0; i < L4DUNX; i++) { + if (dung[i][j] == 1) rv++; + } + } + return(rv); +} + +/*----------------------------------------------------------------------* +**----------------------------------------------------------------------*/ +static void L4drawRoom(int x, int y, int width, int height) +{ + int i, j; + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + dung[x+i][y+j] = 1; + } + } +} + +/*---------------------------------------------------------------------* +** Check limits of 20 X 20 +**---------------------------------------------------------------------*/ +static BOOL L4checkRoom(int x, int y, int width, int height) +{ + int i, j; + + if (( x <= 0 ) || (y <= 0)) return(FALSE); + + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + if ((x+i < 0) || (x+i >= L4DUNX) || (y+j < 0) || (y+j >= L4DUNY)) return(FALSE); + if (dung[x+i][y+j] != 0) return(FALSE); + } + } + return(TRUE); +} + +/*---------------------------------------------------------------------** +** Generate left and right, up and down rooms +**---------------------------------------------------------------------*/ +static void L4roomGen(int x, int y, int w, int h, int dir) +{ + int rx, ry, rx2, ry2; + int height, width; + int cx1, cy1, cw, ch; + int num; + int dirProb; + int ran; + BOOL c, d; + + ran = random(0, 4); + if (dir == L4DIR_VERT) { + if (ran == 0) dirProb = L4DIR_HORIZ; + else dirProb = L4DIR_VERT; + } else { + if (ran == 0) dirProb = L4DIR_VERT; + else dirProb = L4DIR_HORIZ; + } + switch(dirProb) { + case L4DIR_HORIZ : // left/right + // left room + num = 0; + do { + width = ((random(0, L4ROOM_MAX-L4ROOM_MIN+1) + L4ROOM_MIN) >> 1) << 1; + height = ((random(0, L4ROOM_MAX-L4ROOM_MIN+1) + L4ROOM_MIN) >> 1) << 1; + ry = y + (h/2) - (height/2); + rx = x - width; + cx1 = rx - 1; + cy1 = ry - 1; + cw = height + 2; + ch = width + 1; + c = L4checkRoom(cx1, cy1, cw, ch); + num++; + } while ((c == FALSE) && (num < 20)); + if (c == TRUE) L4drawRoom(rx, ry, width, height); + + // right room + rx2 = x + w; + cx1 = rx2; + cy1 = ry - 1; + ch = height + 2; + cw = width + 1; + d = L4checkRoom(cx1, cy1, cw, ch); + if (d == TRUE) L4drawRoom(rx2, ry, width, height); + if (c == TRUE) L4roomGen(rx, ry, width, height, L4DIR_VERT); + if (d == TRUE) L4roomGen(rx2, ry, width, height, L4DIR_VERT); + break; + + case L4DIR_VERT : // top/bottom + // top room + num = 0; + do { + width = ((random(0, L4ROOM_MAX-L4ROOM_MIN+1) + L4ROOM_MIN) >> 1) << 1; + height = ((random(0, L4ROOM_MAX-L4ROOM_MIN+1) + L4ROOM_MIN) >> 1) << 1; + rx = x + (w/2) - (width/2); + ry = y - height; + cx1 = rx - 1; + cy1 = ry - 1; + ch = height + 1; + cw = width + 2; + c = L4checkRoom(cx1, cy1, cw, ch); + num++; + + } while ((c == FALSE) && (num < 20)); + if (c == TRUE) L4drawRoom(rx, ry, width, height); + + // bottom room + ry2 = y + h; + cx1 = rx - 1; + cy1 = ry2; + ch = height + 1; + cw = width + 2; + d = L4checkRoom(cx1, cy1, cw, ch); + if (d == TRUE) L4drawRoom(rx, ry2, width, height); + if (c == TRUE) L4roomGen(rx, ry, width, height, L4DIR_HORIZ); + if (d == TRUE) L4roomGen(rx, ry2, width, height, L4DIR_HORIZ); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void L4firstRoom() +{ + int x,y,w,h; + int xstor, ystor; + int rndx, rndy; + int xmin, xmax, ymin, ymax; + + if (currlevel != 16) { + if ((currlevel == quests[Q_WARLORD]._qlevel) && (quests[Q_WARLORD]._qactive != QUEST_NOTAVAIL)) { + app_assert(gbMaxPlayers == 1); + w = 11; + h = 11; + } + else if ((currlevel == quests[Q_BETRAYER]._qlevel) && (gbMaxPlayers != 1)) { + w = 11; + h = 11; + } + else { + w = ((random(0, L4ROOM_MAX-L4ROOM_MIN+1) + L4ROOM_MIN)); + h = ((random(0, L4ROOM_MAX-L4ROOM_MIN+1) + L4ROOM_MIN)); + } + } else { + w = DIABSIZE; + h = DIABSIZE; + } + + + xmin = ((20 - w) >>1); + xmax = (19 - w); + rndx = random(0, xmax - xmin + 1) + xmin; + if ((w + rndx) > 19) { + xstor = (w + rndx) - 19; + x = (rndx - xstor) + 1; + } + else x = rndx; + + ymin = ((20 - h) >>1); + ymax = (19 - h); + rndy = random(0, ymax - ymin + 1) + ymin; + if ((h + rndy) > 19) { + ystor = (h + rndy) - 19; + y = (rndy - ystor) + 1; + } + else y = rndy; + + if (currlevel == 16) { + l4holdx = x; + l4holdy = y; + } + if (QuestStatus(Q_WARLORD) + || ((currlevel == quests[Q_BETRAYER]._qlevel) && (gbMaxPlayers != 1))) { + SP4x1 = x + 1; + SP4y1 = y + 1; + SP4x2 = SP4x1 + w; + SP4y2 = SP4y1 + h; + } else { + SP4x1 = 0; + SP4y1 = 0; + SP4x2 = 0; + SP4y2 = 0; + } + + L4drawRoom(x, y, w, h); + L4roomGen(x, y, w, h, random(0, 2)); +} + +/*-----------------------------------------------------------------------** +** Save 4 quads for diablo level +**-----------------------------------------------------------------------*/ + +void L4SaveQuads() +{ + int i,j,x,y; + + x = l4holdx; + y = l4holdy; + for (j = 0; j < DIABSIZE; j++) { + for (i = 0; i < DIABSIZE; i++) { + dflags[x+i][y+j] = 1; + dflags[39-x-i][y+j] = 1; + dflags[x+i][39-y-j] = 1; + dflags[39-x-i][39-y-j] = 1; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DRLG_L4SetRoom(BYTE *pSetPiece, int rx1, int ry1) +{ + int rw,rh; + int i,j; + byte *sp; + + sp = pSetPiece; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + sp = pSetPiece+4; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*sp != 0) { + dungeon[rx1+i][ry1+j] = *sp; + dflags[rx1+i][ry1+j] |= SETP_BIT; + } else dungeon[rx1+i][ry1+j] = 6; + sp+=2; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DRLG_LoadDiabQuads(BOOL preflag) +{ + BYTE *pSetPiece; + + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab1.DUN",NULL,'STPC'); + diabquad1x = l4holdx + ((DIABSIZE - 6) >> 1); + diabquad1y = l4holdy + ((DIABSIZE - 6) >> 1); + DRLG_L4SetRoom(pSetPiece, diabquad1x, diabquad1y); + DiabloFreePtr(pSetPiece); + + if (preflag) pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab2b.DUN",NULL,'STPC'); + else pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab2a.DUN",NULL,'STPC'); + diabquad2x = 39 - 11 - l4holdx - ((DIABSIZE - 11) >> 1); + diabquad2y = l4holdy + ((DIABSIZE - 12) >> 1); + DRLG_L4SetRoom(pSetPiece, diabquad2x, diabquad2y); + DiabloFreePtr(pSetPiece); + + if (preflag) pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab3b.DUN",NULL,'STPC'); + else pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab3a.DUN",NULL,'STPC'); + diabquad3x = l4holdx + ((DIABSIZE - 11) >> 1); + diabquad3y = 39 - 11 - l4holdy - ((DIABSIZE - 11) >> 1); + DRLG_L4SetRoom(pSetPiece, diabquad3x, diabquad3y); + DiabloFreePtr(pSetPiece); + + if (preflag) pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab4b.DUN",NULL,'STPC'); + else pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab4a.DUN",NULL,'STPC'); + diabquad4x = 39 - 9 - l4holdx - ((DIABSIZE - 9) >> 1); + diabquad4y = 39 - 9 - l4holdy - ((DIABSIZE - 9) >> 1); + DRLG_L4SetRoom(pSetPiece, diabquad4x, diabquad4y); + DiabloFreePtr(pSetPiece); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL DRLG_L4PlaceMiniSet(const byte miniset[], int tmin, int tmax, int cx, int cy, int setview, int ldir) +{ + int sx, sy; + int sw, sh; + int xx, yy; + int i, ii, numt; + int found, bailcnt; + + // Width and height of the mini set piece + sw = miniset[0]; + sh = miniset[1]; + + // Number of pieces to place + if ((tmax - tmin) == 0) numt = 1; + else numt = random(0, tmax - tmin) + tmin; + + for (i = 0; i < numt; i++) { + // Random starting pos + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + + // Find a location for the mini set piece + found = 0; + bailcnt = 0; + while ((found == 0) && (bailcnt < 200)) { + found = 1; + + if (((sx >= SP4x1) && (sx <= SP4x2)) && ((sy >= SP4y1) && (sy <= SP4y2))) found = 0; + + if ((cx != -1) && (sx >= (cx - sw)) && (sx <= (cx + 12))) { + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + found = 0; + } + if ((cy != -1) && (sy >= (cy - sh)) && (sy <= (cy + 12))) { + sx = random(0, MDMAXX-sw); + sy = random(0, MDMAXY-sh); + found = 0; + } + ii = 2; + for (yy = 0; ((yy < sh) && (found == 1)); yy++) { + for (xx = 0; ((xx < sw) && (found == 1)); xx++) { + if ((miniset[ii] != 0) && (dungeon[sx+xx][sy+yy] != miniset[ii])) found = 0; + if (dflags[sx+xx][sy+yy] != 0) found = 0; + ii++; + } + } + if (found == 0) { + sx++; + if (sx == (MDMAXX - sw)) { + sx = 0; + sy++; + if (sy == (MDMAXY - sh)) sy = 0; + } + + } + bailcnt++; + } + + if (bailcnt >= 200) return(FALSE); + + // Place mini set piece + ii = (sh * sw) + 2; + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[ii] != 0) { + dungeon[sx+xx][sy+yy] = miniset[ii]; + dflags[sx+xx][sy+yy] |= BFLAG_SETPC; + } + ii++; + } + } + } + if (currlevel == 15) // Don't take this out + { + quests[Q_BETRAYER]._qtx = sx+1 ; + quests[Q_BETRAYER]._qty = sy+1; + } + + if (setview == 1) { + ViewX = (sx << 1) + 3 + (DIRTEDGED2) + 2; + ViewY = (sy << 1) + 4 + (DIRTEDGED2) + 2; + } + + if (ldir == LVL_DOWN) { + LvlViewX = (sx << 1) + 3 + (DIRTEDGED2) + 2; + LvlViewY = (sy << 1) + 4 + (DIRTEDGED2) + 2; + } + + return(TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L4FTVR(int i, int j, int x, int y, int d) +{ + if ((dTransVal[x][y] == 0) && (dungeon[i][j] == FLOOR_PIC)) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + DRLG_L4FTVR(i+1,j, x+2,y, 1); + DRLG_L4FTVR(i-1,j, x-2,y, 2); + DRLG_L4FTVR(i,j+1, x,y+2, 3); + DRLG_L4FTVR(i,j-1, x,y-2, 4); + + DRLG_L4FTVR(i-1,j-1, x-2,y-2, 5); + DRLG_L4FTVR(i+1,j-1, x+2,y-2, 6); + DRLG_L4FTVR(i-1,j+1, x-2,y+2, 7); + DRLG_L4FTVR(i+1,j+1, x+2,y+2, 8); + } else { + if (d == 1) { + dTransVal[x][y] = TransVal; + dTransVal[x][y+1] = TransVal; + } + if (d == 2) { + dTransVal[x+1][y] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 3) { + dTransVal[x][y] = TransVal; + dTransVal[x+1][y] = TransVal; + } + if (d == 4) { + dTransVal[x][y+1] = TransVal; + dTransVal[x+1][y+1] = TransVal; + } + if (d == 5) dTransVal[x+1][y+1] = TransVal; + if (d == 6) dTransVal[x][y+1] = TransVal; + if (d == 7) dTransVal[x+1][y] = TransVal; + if (d == 8) dTransVal[x][y] = TransVal; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L4FloodTVal() +{ + int i, j; + int xx,yy; + + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + if ((dungeon[i][j] == FLOOR_PIC) && (dTransVal[xx][yy] == 0)) { + DRLG_L4FTVR(i,j,xx,yy,0); + TransVal++; + } + xx += 2; + } + yy += 2; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL IsDURWall(char d) +{ + if (d == DURWALL_PIC) return(TRUE); + if (d == DURWALL2_PIC) return(TRUE); + if (d == DURWALL3_PIC) return(TRUE); + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL IsDLLWall(char dd) +{ + if (dd == DLLWALL_PIC) return(TRUE); + if (dd == DLLWALL2_PIC) return(TRUE); + if (dd == DLLWALL3_PIC) return(TRUE); + return(FALSE); +} +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L4TransFix() +{ + int i, j; + int xx,yy; + + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + if (((IsDURWall(dungeon[i][j])) && (dungeon[i][j-1] == DVWALL_PIC))) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (((IsDLLWall(dungeon[i][j])) && (dungeon[i+1][j] == DHWALL_PIC))) { + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == DVWALL_PIC) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == DHWALL_PIC) { + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == DLRWALL_PIC) { + dTransVal[xx+1][yy] = dTransVal[xx][yy]; + dTransVal[xx][yy+1] = dTransVal[xx][yy]; + dTransVal[xx+1][yy+1] = dTransVal[xx][yy]; + } + if (dungeon[i][j] == XARCHWALL_PIC) { + dTransVal[xx-1][yy] = dTransVal[xx][yy+1]; + dTransVal[xx][yy] = dTransVal[xx][yy+1]; + } + if (dungeon[i][j] == YARCHWALL_PIC) { + dTransVal[xx][yy-1] = dTransVal[xx+1][yy]; + dTransVal[xx][yy] = dTransVal[xx+1][yy]; + } + + xx += 2; + } + yy += 2; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L4Corners() +{ + int i,j; + + for (j = 1; j < MDMAXY-1; j++) { + for (i = 1; i < MDMAXX-1; i++) { + if ((dungeon[i][j] >= 18) && (dungeon[i][j] <= 30)) { + if (dungeon[i+1][j] < 18) { + dungeon[i][j] += 98; + } else + if (dungeon[i][j+1] < 18) dungeon[i][j] += 98; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void L4FixRim() +{ + for (int i = 0; i < 20; i++) dung[i][0] = 0; + for (int j = 0; j < 20; j++) dung[0][j] = 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DRLG_L4GeneralFix() +{ + int i,j; + + for (j = 0; j < MDMAXY-1; j++) { + for (i = 0; i < MDMAXX-1; i++) { + if ((dungeon[i][j] == 24) || (dungeon[i][j] == 122)) { + if ((dungeon[i+1][j] == 2) && (dungeon[i][j+1] == 5)) dungeon[i][j] = 17; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L4(int entry) +{ + long area; + int t; + BOOL doneflag; + int i, j; + int spi, spj; + + doneflag = FALSE; + while (!doneflag) { + + DRLG_InitTrans(); + t = 0; + + do { + InitL4Dungeon(); + L4firstRoom(); + L4FixRim(); + area = GetArea(); + if (area >= L4MIN_AREA) uShape(); + t++; + }while (area < L4MIN_AREA); + L4makeDungeon(); + L4makeDmt(); + L4tileFix(); + + if (currlevel == 16) L4SaveQuads(); + if (QuestStatus(Q_WARLORD) || ((currlevel == quests[Q_BETRAYER]._qlevel) && (gbMaxPlayers != 1))) { + for (spi = SP4x1; spi < SP4x2;spi++) { + for (spj = SP4y1; spj < SP4y2; spj++) + dflags[spi][spj] = 1; + } + } + + L4AddWall(); + DRLG_L4FloodTVal(); + DRLG_L4TransFix(); + + if (setloadflag) { + DRLG_L4SetSPRoom(SP4x1,SP4y1); + } + + if (currlevel == 16) { + DRLG_LoadDiabQuads(TRUE); + } + + if (QuestStatus(Q_WARLORD)) { + if (entry == LVL_DOWN) { + doneflag = DRLG_L4PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, 1, LVL_DOWN); + if ((doneflag) && (currlevel == 13)) doneflag = DRLG_L4PlaceMiniSet(L4TWARP, 1, 1, -1, -1, 0, LVL_TWARPDN); + ViewX++; + } else { + if (entry == LVL_UP) { + doneflag = DRLG_L4PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, 0, LVL_DOWN); + if ((doneflag) && (currlevel == 13)) doneflag = DRLG_L4PlaceMiniSet(L4TWARP, 1, 1, -1, -1, 0, LVL_TWARPDN); + ViewX = (setpc_x << 1) + 6 + DIRTEDGED2; + ViewY = (setpc_y << 1) + 6 + DIRTEDGED2; + } else { + doneflag = DRLG_L4PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, 0, LVL_DOWN); + if ((doneflag) && (currlevel == 13)) doneflag = DRLG_L4PlaceMiniSet(L4TWARP, 1, 1, -1, -1, 1, LVL_TWARPDN); + ViewX++; + } + } + } else if (currlevel != 15) { + if (entry == LVL_DOWN) { + doneflag = DRLG_L4PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, 1, LVL_DOWN); + if ((doneflag) && (currlevel != 16)) doneflag = DRLG_L4PlaceMiniSet(L4DSTAIRS, 1, 1, -1, -1, 0, LVL_UP); + if ((doneflag) && (currlevel == 13)) doneflag = DRLG_L4PlaceMiniSet(L4TWARP, 1, 1, -1, -1, 0, LVL_TWARPDN); + ViewX++; + } else { + if (entry == LVL_UP) { + doneflag = DRLG_L4PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, 0, LVL_DOWN); + if ((doneflag) && (currlevel != 16)) doneflag = DRLG_L4PlaceMiniSet(L4DSTAIRS, 1, 1, -1, -1, 1, LVL_UP); + if ((doneflag) && (currlevel == 13)) doneflag = DRLG_L4PlaceMiniSet(L4TWARP, 1, 1, -1, -1, 0, LVL_TWARPDN); + ViewY++; + } else { + doneflag = DRLG_L4PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, 0, LVL_DOWN); + if ((doneflag) && (currlevel != 16)) doneflag = DRLG_L4PlaceMiniSet(L4DSTAIRS, 1, 1, -1, -1, 0, LVL_UP); + if ((doneflag) && (currlevel == 13)) doneflag = DRLG_L4PlaceMiniSet(L4TWARP, 1, 1, -1, -1, 1, LVL_TWARPDN); + ViewX++; + } + } + } else { + if (entry == LVL_DOWN) { + doneflag = DRLG_L4PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, 1, LVL_DOWN); + if (doneflag) { + if ((gbMaxPlayers != 1) || (quests[Q_DIABLO]._qactive == QUEST_NOTDONE)) + doneflag = DRLG_L4PlaceMiniSet(L4PENTA2, 1, 1, -1, -1, 0, LVL_UP); + else + doneflag = DRLG_L4PlaceMiniSet(L4PENTA, 1, 1, -1, -1, 0, LVL_UP); + } + ViewX++; + } else { + doneflag = DRLG_L4PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, 0, LVL_DOWN); + if (doneflag) { + if ((gbMaxPlayers != 1) || (quests[Q_DIABLO]._qactive == QUEST_NOTDONE)) + doneflag = DRLG_L4PlaceMiniSet(L4PENTA2, 1, 1, -1, -1, 1, LVL_UP); + else + doneflag = DRLG_L4PlaceMiniSet(L4PENTA, 1, 1, -1, -1, 1, LVL_UP); + } + ViewY++; + } + } + } + + DRLG_L4GeneralFix(); + + if (currlevel != 16) DRLG_PlaceThemeRooms(7, 10, FLOOR_PIC, 8, TRUE); + + // Create shadows + DRLG_L4Shadows(); + + DRLG_L4Corners(); + + DRLG_L4Subs(); + + extern void DRLG_Init_Globals(); + DRLG_Init_Globals(); + + // for warlord quest + if (QuestStatus(Q_WARLORD)) { + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) pdungeon[i][j] = dungeon[i][j]; + } + } + DRLG_CheckQuests(SP4x1,SP4y1); + + // make sure nothing is placed on the pentagrams + if (currlevel == 15) { + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + if (dungeon[i][j] == 98) Make_SetPC(i-1, j-1, 5, 5); + if (dungeon[i][j] == 107) Make_SetPC(i-1, j-1, 5, 5); + } + } + } + + // for diablo level, we need to save the current state so we can use the switches + if (currlevel == 16) { + // Save the layout for the switches + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) pdungeon[i][j] = dungeon[i][j]; + } + + // set the current layout + DRLG_LoadDiabQuads(FALSE); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DRLG_L4Pass3() +{ + int i,j,xx,yy; + long v1,v2,v3,v4,lv; + + // Init dungeon to dirt + lv = 30 - 1; + __asm { + mov esi,dword ptr [pMegaTiles] + mov eax,dword ptr [lv]; + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + for (yy = 0; yy < DMAXY; yy+=2) { + for (xx = 0; xx < DMAXX; xx+=2) { + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + } + } + + // Convert dungeon mega tiles to mini tiles + yy = DIRTEDGED2; + for (j = 0; j < MDMAXY; j++) { + xx = DIRTEDGED2; + for (i = 0; i < MDMAXX; i++) { + lv = ((long)dungeon[i][j]) - 1; + if (lv >= 0) { + __asm { + mov esi,dword ptr [pMegaTiles] + mov eax,dword ptr [lv]; + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + } else { + v1 = 0; + v2 = 0; + v3 = 0; + v4 = 0; + } + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + xx += 2; + } + yy += 2; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if IS_VERSION(RETAIL) +void CreateL4Dungeon(unsigned int rseed, int entry) +{ + SetRndSeed(rseed); + + dminx = DIRTEDGED2; + dminy = DIRTEDGED2; + dmaxx = DMAXX - (DIRTEDGED2); + dmaxy = DMAXY - (DIRTEDGED2); + + ViewX = 40; + ViewY = 40; + + DRLG_InitSetPC(); + DRLG_LoadL4SP(); + DRLG_L4(entry); + DRLG_L4Pass3(); + DRLG_FreeL4SP(); + + // Init the light values for each piece +/* + for (int j = 0; j < DMAXY; j++) { + for (int i = 0; i < DMAXX; i++) { + // Tops of doors + //if (dPiece[i][j] == 13) dSpecial[i][j] = 5; + //if (dPiece[i][j] == 17) dSpecial[i][j] = 6; + } + } +*/ + DRLG_SetPC(); +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void L4DrawDung() +{ + byte *p, *p2; + + p = &dungeon[0][0]; + p2 = &dflags[0][0]; + app_assert(gpBuffer); + __asm { + // draw dung + mov esi,dword ptr [p] + mov edi,dword ptr [gpBuffer] + add edi,135248 + mov edx,40 +_YLp: push edi + mov ecx,40 +_XLp: lodsb + cmp al,0 + jz _Save + mov al,229 +_Save: mov byte ptr [edi],al + add edi,768 + loop _XLp + pop edi + inc edi + dec edx + jnz _YLp + + // Draw dflags + mov esi,dword ptr [p2] + mov edi,dword ptr [gpBuffer] + add edi,135248 + mov edx,40 +_YLp2: push edi + mov ecx,40 +_XLp2: lodsb + cmp al,0 + jz _Skip + mov al,146 + mov byte ptr [edi],al +_Skip: add edi,768 + loop _XLp2 + pop edi + inc edi + dec edx + jnz _YLp2 + } +} diff --git a/src/DRLG_L4.H b/src/DRLG_L4.H new file mode 100644 index 0000000..63f1fc9 --- /dev/null +++ b/src/DRLG_L4.H @@ -0,0 +1,86 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/DRLG_L4.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define L4DIR_HORIZ 0 +#define L4DIR_VERT 1 + +#define L4ROOM_MIN 2 +#define L4ROOM_MAX 6 + +#define L4DUNX 20 +#define L4DUNY 20 + +#define L4MIN_AREA ((L4DUNX*L4DUNY)/3) + ((L4DUNX*L4DUNY)/10) + +#define L4DX 80 +#define L4DY 80 +#define L4_DIRT 12 + +#define NUMBBLOCKS 140 + +// PIC == PIECE +#define VWALL_PIC 1 +#define HWALL_PIC 2 +#define LRWALL_PIC 12 +#define FLOOR_PIC 6 +#define URWALL_PIC 16 +#define ULWALL_PIC 9 +#define LLWALL_PIC 15 + +#define DVWALL_PIC 18 +#define DHWALL_PIC 19 +#define DFLOOR_PIC 20 +#define DULWALL_PIC 21 + +#define DURWALL_PIC 25 +#define DURWALL2_PIC 28 +#define DURWALL3_PIC 23 + +#define DLLWALL_PIC 27 +#define DLLWALL2_PIC 26 +#define DLLWALL3_PIC 22 + +#define DLRWALL_PIC 24 +#define DIRT_PIC 30 +//Arches +#define YARCHWALL_PIC 53 +#define XARCHWALL_PIC 57 + +#define NUMSPATS 37 +#define _1S 47 +#define _2S 48 +#define _3S 49 +#define _4S 50 +#define _5S 51 +#define _6S 54 +#define _7S 55 +#define _8S 58 +#define _9S 59 +#define _10S 60 + + +/*-----------------------------------------------------------------------** +** externs +**-----------------------------------------------------------------------*/ + +extern int diabquad1x, diabquad2x, diabquad3x, diabquad4x; +extern int diabquad1y, diabquad2y, diabquad3y, diabquad4y; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void CreateL4Dungeon(unsigned int, int); +//int DRLG_L4Spawn(int, int, int *); diff --git a/src/DSOUND.H b/src/DSOUND.H new file mode 100644 index 0000000..28a5766 --- /dev/null +++ b/src/DSOUND.H @@ -0,0 +1,605 @@ +/*==========================================================================; + * + * Copyright (C) 1995,1996 Microsoft Corporation. All Rights Reserved. + * + * File: dsound.h + * Content: DirectSound include file + * + ***************************************************************************/ + +#ifndef __DSOUND_INCLUDED__ +#define __DSOUND_INCLUDED__ + +#include "d3dtypes.h" + +#ifdef _WIN32 +#define COM_NO_WINDOWS_H +#include +#endif + +#define _FACDS 0x878 +#define MAKE_DSHRESULT( code ) MAKE_HRESULT( 1, _FACDS, code ) + +#ifdef __cplusplus +extern "C" { +#endif + +// Direct Sound Component GUID {47D4D946-62E8-11cf-93BC-444553540000} +DEFINE_GUID(CLSID_DirectSound, +0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0); + +// DirectSound 279afa83-4981-11ce-a521-0020af0be560 +DEFINE_GUID(IID_IDirectSound,0x279AFA83,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); +// DirectSoundBuffer 279afa85-4981-11ce-a521-0020af0be560 +DEFINE_GUID(IID_IDirectSoundBuffer,0x279AFA85,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); + +//DirectSound3DListener 279afa84-4981-11ce-a521-0020af0be560 +DEFINE_GUID(IID_IDirectSound3DListener,0x279AFA84,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); +//DirectSound3DBuffer 279afa86-4981-11ce-a521-0020af0be560 +DEFINE_GUID(IID_IDirectSound3DBuffer,0x279AFA86,0x4981,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60); + + +//==========================================================================; +// +// Structures... +// +//==========================================================================; +#ifdef __cplusplus +/* 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined */ +struct IDirectSound; +struct IDirectSoundBuffer; +struct IDirectSound3DListener; +struct IDirectSound3DBuffer; +#endif + +typedef struct IDirectSound *LPDIRECTSOUND; +typedef struct IDirectSoundBuffer *LPDIRECTSOUNDBUFFER; +typedef struct IDirectSoundBuffer **LPLPDIRECTSOUNDBUFFER; +typedef struct IDirectSound3DListener *LPDIRECTSOUND3DLISTENER; +typedef struct IDirectSound3DBuffer *LPDIRECTSOUND3DBUFFER; + + +typedef struct _DSCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwMinSecondarySampleRate; + DWORD dwMaxSecondarySampleRate; + DWORD dwPrimaryBuffers; + DWORD dwMaxHwMixingAllBuffers; + DWORD dwMaxHwMixingStaticBuffers; + DWORD dwMaxHwMixingStreamingBuffers; + DWORD dwFreeHwMixingAllBuffers; + DWORD dwFreeHwMixingStaticBuffers; + DWORD dwFreeHwMixingStreamingBuffers; + DWORD dwMaxHw3DAllBuffers; + DWORD dwMaxHw3DStaticBuffers; + DWORD dwMaxHw3DStreamingBuffers; + DWORD dwFreeHw3DAllBuffers; + DWORD dwFreeHw3DStaticBuffers; + DWORD dwFreeHw3DStreamingBuffers; + DWORD dwTotalHwMemBytes; + DWORD dwFreeHwMemBytes; + DWORD dwMaxContigFreeHwMemBytes; + DWORD dwUnlockTransferRateHwBuffers; + DWORD dwPlayCpuOverheadSwBuffers; + DWORD dwReserved1; + DWORD dwReserved2; +} DSCAPS, *LPDSCAPS; + +typedef struct _DSBCAPS +{ + + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwUnlockTransferRate; + DWORD dwPlayCpuOverhead; +} DSBCAPS, *LPDSBCAPS; + +typedef struct _DSBUFFERDESC +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +} DSBUFFERDESC, *LPDSBUFFERDESC; + +typedef struct _DS3DBUFFER +{ + DWORD dwSize; + D3DVECTOR vPosition; + D3DVECTOR vVelocity; + DWORD dwInsideConeAngle; + DWORD dwOutsideConeAngle; + D3DVECTOR vConeOrientation; + LONG lConeOutsideVolume; + D3DVALUE flMinDistance; + D3DVALUE flMaxDistance; + DWORD dwMode; +} DS3DBUFFER, *LPDS3DBUFFER; + +typedef struct _DS3DLISTENER +{ + DWORD dwSize; + D3DVECTOR vPosition; + D3DVECTOR vVelocity; + D3DVECTOR vOrientFront; + D3DVECTOR vOrientTop; + D3DVALUE flDistanceFactor; + D3DVALUE flRolloffFactor; + D3DVALUE flDopplerFactor; +} DS3DLISTENER, *LPDS3DLISTENER; + + + +typedef LPVOID* LPLPVOID; + + +typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKW)(const GUID FAR *, LPWSTR, LPWSTR, LPVOID); +typedef BOOL (FAR PASCAL * LPDSENUMCALLBACKA)(const GUID FAR *, LPSTR, LPSTR, LPVOID); + +extern HRESULT WINAPI DirectSoundCreate(const GUID * lpGUID, LPDIRECTSOUND * ppDS, IUnknown FAR *pUnkOuter ); +extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW lpCallback, LPVOID lpContext ); +extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA lpCallback, LPVOID lpContext ); + +#ifdef UNICODE +#define LPDSENUMCALLBACK LPDSENUMCALLBACKW +#define DirectSoundEnumerate DirectSoundEnumerateW +#else +#define LPDSENUMCALLBACK LPDSENUMCALLBACKA +#define DirectSoundEnumerate DirectSoundEnumerateA +#endif + +// +// IDirectSound +// +#undef INTERFACE +#define INTERFACE IDirectSound +#ifdef _WIN32 +DECLARE_INTERFACE_( IDirectSound, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectSound methods ***/ + + STDMETHOD( CreateSoundBuffer)(THIS_ LPDSBUFFERDESC, LPLPDIRECTSOUNDBUFFER, IUnknown FAR *) PURE; + STDMETHOD( GetCaps)(THIS_ LPDSCAPS ) PURE; + STDMETHOD( DuplicateSoundBuffer)(THIS_ LPDIRECTSOUNDBUFFER, LPLPDIRECTSOUNDBUFFER ) PURE; + STDMETHOD( SetCooperativeLevel)(THIS_ HWND, DWORD ) PURE; + STDMETHOD( Compact)(THIS ) PURE; + STDMETHOD( GetSpeakerConfig)(THIS_ LPDWORD ) PURE; + STDMETHOD( SetSpeakerConfig)(THIS_ DWORD ) PURE; + STDMETHOD( Initialize)(THIS_ const GUID * ) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectSound_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectSound_Release(p) (p)->lpVtbl->Release(p) +#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c) +#define IDirectSound_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b) +#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectSound_Compact(p) (p)->lpVtbl->Compact(p) +#define IDirectSound_GetSpeakerConfig(p,a) (p)->lpVtbl->GetSpeakerConfig(p,a) +#define IDirectSound_SetSpeakerConfig(p,b) (p)->lpVtbl->SetSpeakerConfig(p,b) +#define IDirectSound_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) +#else +#define IDirectSound_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectSound_AddRef(p) (p)->AddRef() +#define IDirectSound_Release(p) (p)->Release() +#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->CreateSoundBuffer(a,b,c) +#define IDirectSound_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->DuplicateSoundBuffer(a,b) +#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectSound_Compact(p) (p)->Compact() +#define IDirectSound_GetSpeakerConfig(p,a) (p)->GetSpeakerConfig(a) +#define IDirectSound_SetSpeakerConfig(p,b) (p)->SetSpeakerConfig(b) +#define IDirectSound_Initialize(p,a) (p)->Initialize(a) +#endif + +#endif + +// +// IDirectSoundBuffer +// +#undef INTERFACE +#define INTERFACE IDirectSoundBuffer +#ifdef _WIN32 +DECLARE_INTERFACE_( IDirectSoundBuffer, IUnknown ) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + /*** IDirectSoundBuffer methods ***/ + + STDMETHOD( GetCaps)(THIS_ LPDSBCAPS ) PURE; + STDMETHOD(GetCurrentPosition)(THIS_ LPDWORD,LPDWORD ) PURE; + STDMETHOD( GetFormat)(THIS_ LPWAVEFORMATEX, DWORD, LPDWORD ) PURE; + STDMETHOD( GetVolume)(THIS_ LPLONG ) PURE; + STDMETHOD( GetPan)(THIS_ LPLONG ) PURE; + STDMETHOD( GetFrequency)(THIS_ LPDWORD ) PURE; + STDMETHOD( GetStatus)(THIS_ LPDWORD ) PURE; + STDMETHOD( Initialize)(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC ) PURE; + STDMETHOD( Lock)(THIS_ DWORD,DWORD,LPVOID,LPDWORD,LPVOID,LPDWORD,DWORD ) PURE; + STDMETHOD( Play)(THIS_ DWORD,DWORD,DWORD ) PURE; + STDMETHOD(SetCurrentPosition)(THIS_ DWORD ) PURE; + STDMETHOD( SetFormat)(THIS_ LPWAVEFORMATEX ) PURE; + STDMETHOD( SetVolume)(THIS_ LONG ) PURE; + STDMETHOD( SetPan)(THIS_ LONG ) PURE; + STDMETHOD( SetFrequency)(THIS_ DWORD ) PURE; + STDMETHOD( Stop)(THIS ) PURE; + STDMETHOD( Unlock)(THIS_ LPVOID,DWORD,LPVOID,DWORD ) PURE; + STDMETHOD( Restore)(THIS ) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectSoundBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectSoundBuffer_Release(p) (p)->lpVtbl->Release(p) +#define IDirectSoundBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) +#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) +#define IDirectSoundBuffer_GetVolume(p,a) (p)->lpVtbl->GetVolume(p,a) +#define IDirectSoundBuffer_GetPan(p,a) (p)->lpVtbl->GetPan(p,a) +#define IDirectSoundBuffer_GetFrequency(p,a) (p)->lpVtbl->GetFrequency(p,a) +#define IDirectSoundBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) +#define IDirectSoundBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundBuffer_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c) +#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->lpVtbl->SetCurrentPosition(p,a) +#define IDirectSoundBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) +#define IDirectSoundBuffer_SetVolume(p,a) (p)->lpVtbl->SetVolume(p,a) +#define IDirectSoundBuffer_SetPan(p,a) (p)->lpVtbl->SetPan(p,a) +#define IDirectSoundBuffer_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a) +#define IDirectSoundBuffer_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) +#define IDirectSoundBuffer_Restore(p) (p)->lpVtbl->Restore(p) +#else +#define IDirectSoundBuffer_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectSoundBuffer_AddRef(p) (p)->AddRef() +#define IDirectSoundBuffer_Release(p) (p)->Release() +#define IDirectSoundBuffer_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) +#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) +#define IDirectSoundBuffer_GetVolume(p,a) (p)->GetVolume(a) +#define IDirectSoundBuffer_GetPan(p,a) (p)->GetPan(a) +#define IDirectSoundBuffer_GetFrequency(p,a) (p)->GetFrequency(a) +#define IDirectSoundBuffer_GetStatus(p,a) (p)->GetStatus(a) +#define IDirectSoundBuffer_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) +#define IDirectSoundBuffer_Play(p,a,b,c) (p)->Play(a,b,c) +#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->SetCurrentPosition(a) +#define IDirectSoundBuffer_SetFormat(p,a) (p)->SetFormat(a) +#define IDirectSoundBuffer_SetVolume(p,a) (p)->SetVolume(a) +#define IDirectSoundBuffer_SetPan(p,a) (p)->SetPan(a) +#define IDirectSoundBuffer_SetFrequency(p,a) (p)->SetFrequency(a) +#define IDirectSoundBuffer_Stop(p) (p)->Stop() +#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) +#define IDirectSoundBuffer_Restore(p) (p)->Restore() +#endif + +#endif + +// +// IDirectSound3DListener +// +#undef INTERFACE +#define INTERFACE IDirectSound3DListener +#ifdef _WIN32 +DECLARE_INTERFACE_(IDirectSound3DListener, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + /*** IDirectSound3D methods ***/ + STDMETHOD(GetAllParameters)(THIS_ LPDS3DLISTENER) PURE; + STDMETHOD(GetDistanceFactor)(THIS_ LPD3DVALUE) PURE; + STDMETHOD(GetDopplerFactor)(THIS_ LPD3DVALUE) PURE; + STDMETHOD(GetOrientation)(THIS_ LPD3DVECTOR, LPD3DVECTOR) PURE; + STDMETHOD(GetPosition)(THIS_ LPD3DVECTOR) PURE; + STDMETHOD(GetRolloffFactor)(THIS_ LPD3DVALUE ) PURE; + STDMETHOD(GetVelocity)(THIS_ LPD3DVECTOR) PURE; + STDMETHOD(SetAllParameters)(THIS_ LPDS3DLISTENER, DWORD) PURE; + STDMETHOD(SetDistanceFactor)(THIS_ D3DVALUE, DWORD) PURE; + STDMETHOD(SetDopplerFactor)(THIS_ D3DVALUE, DWORD) PURE; + STDMETHOD(SetOrientation)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE, D3DVALUE, D3DVALUE, D3DVALUE, DWORD) PURE; + STDMETHOD(SetPosition)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE, DWORD) PURE; + STDMETHOD(SetRolloffFactor)(THIS_ D3DVALUE, DWORD) PURE; + STDMETHOD(SetVelocity)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE, DWORD) PURE; + STDMETHOD(CommitDeferredSettings)(THIS) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DListener_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectSound3DListener_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectSound3DListener_Release(p) (p)->lpVtbl->Release(p) +#define IDirectSound3DListener_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->lpVtbl->GetDistanceFactor(p,a) +#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->lpVtbl->GetDopplerFactor(p,a) +#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->lpVtbl->GetOrientation(p,a,b) +#define IDirectSound3DListener_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) +#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->lpVtbl->GetRolloffFactor(p,a) +#define IDirectSound3DListener_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) +#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) +#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->lpVtbl->SetDistanceFactor(p,a,b) +#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->lpVtbl->SetDopplerFactor(p,a,b) +#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->lpVtbl->SetOrientation(p,a,b,c,d,e,f,g) +#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) +#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->lpVtbl->SetRolloffFactor(p,a,b) +#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) +#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->lpVtbl->CommitDeferredSettings(p) +#else +#define IDirectSound3DListener_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectSound3DListener_AddRef(p) (p)->AddRef() +#define IDirectSound3DListener_Release(p) (p)->Release() +#define IDirectSound3DListener_GetAllParameters(p,a) (p)->GetAllParameters(a) +#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->GetDistanceFactor(a) +#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->GetDopplerFactor(a) +#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->GetOrientation(a,b) +#define IDirectSound3DListener_GetPosition(p,a) (p)->GetPosition(a) +#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->GetRolloffFactor(a) +#define IDirectSound3DListener_GetVelocity(p,a) (p)->GetVelocity(a) +#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) +#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->SetDistanceFactor(a,b) +#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->SetDopplerFactor(a,b) +#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->SetOrientation(a,b,c,d,e,f,g) +#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) +#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->SetRolloffFactor(a,b) +#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) +#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->CommitDeferredSettings() +#endif + +#endif + +// +// IDirectSound3DBuffer +// +#undef INTERFACE +#define INTERFACE IDirectSound3DBuffer +#ifdef _WIN32 +DECLARE_INTERFACE_(IDirectSound3DBuffer, IUnknown) +{ + /*** IUnknown methods ***/ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + /*** IDirectSoundBuffer3D methods ***/ + STDMETHOD(GetAllParameters)(THIS_ LPDS3DBUFFER) PURE; + STDMETHOD(GetConeAngles)(THIS_ LPDWORD, LPDWORD) PURE; + STDMETHOD(GetConeOrientation)(THIS_ LPD3DVECTOR) PURE; + STDMETHOD(GetConeOutsideVolume)(THIS_ LPLONG) PURE; + STDMETHOD(GetMaxDistance)(THIS_ LPD3DVALUE) PURE; + STDMETHOD(GetMinDistance)(THIS_ LPD3DVALUE) PURE; + STDMETHOD(GetMode)(THIS_ LPDWORD) PURE; + STDMETHOD(GetPosition)(THIS_ LPD3DVECTOR) PURE; + STDMETHOD(GetVelocity)(THIS_ LPD3DVECTOR) PURE; + STDMETHOD(SetAllParameters)(THIS_ LPDS3DBUFFER, DWORD) PURE; + STDMETHOD(SetConeAngles)(THIS_ DWORD, DWORD, DWORD) PURE; + STDMETHOD(SetConeOrientation)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE, DWORD) PURE; + STDMETHOD(SetConeOutsideVolume)(THIS_ LONG, DWORD) PURE; + STDMETHOD(SetMaxDistance)(THIS_ D3DVALUE, DWORD) PURE; + STDMETHOD(SetMinDistance)(THIS_ D3DVALUE, DWORD) PURE; + STDMETHOD(SetMode)(THIS_ DWORD, DWORD) PURE; + STDMETHOD(SetPosition)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE, DWORD) PURE; + STDMETHOD(SetVelocity)(THIS_ D3DVALUE, D3DVALUE, D3DVALUE, DWORD) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DBuffer_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirectSound3DBuffer_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirectSound3DBuffer_Release(p) (p)->lpVtbl->Release(p) +#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->lpVtbl->GetConeAngles(p,a,b) +#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->lpVtbl->GetConeOrientation(p,a) +#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->lpVtbl->GetConeOutsideVolume(p,a) +#define IDirectSound3DBuffer_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) +#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->lpVtbl->GetMinDistance(p,a) +#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->lpVtbl->GetMaxDistance(p,a) +#define IDirectSound3DBuffer_GetMode(p,a) (p)->lpVtbl->GetMode(p,a) +#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) +#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) +#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->lpVtbl->SetConeAngles(p,a,b,c) +#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->lpVtbl->SetConeOrientation(p,a,b,c,d) +#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b)(p)->lpVtbl->SetConeOutsideVolume(p,a,b) +#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) +#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->lpVtbl->SetMinDistance(p,a,b) +#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->lpVtbl->SetMaxDistance(p,a,b) +#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->lpVtbl->SetMode(p,a,b) +#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) +#else +#define IDirectSound3DBuffer_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirectSound3DBuffer_AddRef(p) (p)->AddRef() +#define IDirectSound3DBuffer_Release(p) (p)->Release() +#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->GetAllParameters(a) +#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->GetConeAngles(a,b) +#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->GetConeOrientation(a) +#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->GetConeOutsideVolume(a) +#define IDirectSound3DBuffer_GetPosition(p,a) (p)->GetPosition(a) +#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->GetMinDistance(a) +#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->GetMaxDistance(a) +#define IDirectSound3DBuffer_GetMode(p,a) (p)->GetMode(a) +#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->GetVelocity(a) +#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) +#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->SetConeAngles(a,b,c) +#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->SetConeOrientation(a,b,c,d) +#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b)(p)->SetConeOutsideVolume(a,b) +#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) +#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->SetMinDistance(a,b) +#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->SetMaxDistance(a,b) +#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->SetMode(a,b) +#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) +#endif + +#endif + + +/* + * Return Codes + */ + +#define DS_OK 0 + +/* + * The call failed because resources (such as a priority level) + * were already being used by another caller. + */ +#define DSERR_ALLOCATED MAKE_DSHRESULT( 10 ) +/* + * The control (vol,pan,etc.) requested by the caller is not available. + */ +#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT( 30 ) +/* + * An invalid parameter was passed to the returning function + */ +#define DSERR_INVALIDPARAM E_INVALIDARG +/* + * This call is not valid for the current state of this object + */ +#define DSERR_INVALIDCALL MAKE_DSHRESULT( 50 ) +/* + * An undetermined error occured inside the DSound subsystem + */ +#define DSERR_GENERIC E_FAIL +/* + * The caller does not have the priority level required for the function to + * succeed. + */ +#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT( 70 ) +/* + * The DSound subsystem couldn't allocate sufficient memory to complete the + * caller's request. + */ +#define DSERR_OUTOFMEMORY E_OUTOFMEMORY +/* + * The specified WAVE format is not supported + */ +#define DSERR_BADFORMAT MAKE_DSHRESULT( 100 ) +/* + * The function called is not supported at this time + */ +#define DSERR_UNSUPPORTED E_NOTIMPL +/* + * No sound driver is available for use + */ +#define DSERR_NODRIVER MAKE_DSHRESULT( 120 ) +/* + * This object is already initialized + */ +#define DSERR_ALREADYINITIALIZED MAKE_DSHRESULT( 130 ) +/* + * This object does not support aggregation + */ +#define DSERR_NOAGGREGATION CLASS_E_NOAGGREGATION +/* + * The buffer memory has been lost, and must be Restored. + */ +#define DSERR_BUFFERLOST MAKE_DSHRESULT( 150 ) +/* + * Another app has a higher priority level, preventing this call from + * succeeding. + */ +#define DSERR_OTHERAPPHASPRIO MAKE_DSHRESULT( 160 ) +/* + * The Initialize() member on the Direct Sound Object has not been + * called or called successfully before calls to other members. + */ +#define DSERR_UNINITIALIZED MAKE_DSHRESULT( 170 ) + + + + +//==========================================================================; +// +// Flags... +// +//==========================================================================; + +#define DSCAPS_PRIMARYMONO 0x00000001 +#define DSCAPS_PRIMARYSTEREO 0x00000002 +#define DSCAPS_PRIMARY8BIT 0x00000004 +#define DSCAPS_PRIMARY16BIT 0x00000008 +#define DSCAPS_CONTINUOUSRATE 0x00000010 +#define DSCAPS_EMULDRIVER 0x00000020 +#define DSCAPS_CERTIFIED 0x00000040 +#define DSCAPS_SECONDARYMONO 0x00000100 +#define DSCAPS_SECONDARYSTEREO 0x00000200 +#define DSCAPS_SECONDARY8BIT 0x00000400 +#define DSCAPS_SECONDARY16BIT 0x00000800 + + + +#define DSBPLAY_LOOPING 0x00000001 + + +#define DSBSTATUS_PLAYING 0x00000001 +#define DSBSTATUS_BUFFERLOST 0x00000002 +#define DSBSTATUS_LOOPING 0x00000004 + + +#define DSBLOCK_FROMWRITECURSOR 0x00000001 + + + +#define DSSCL_NORMAL 1 +#define DSSCL_PRIORITY 2 +#define DSSCL_EXCLUSIVE 3 +#define DSSCL_WRITEPRIMARY 4 + + + +// flags for IDirectSound3DBuffer::SetMode +#define DS3DMODE_NORMAL 0 // default must be 0 +#define DS3DMODE_HEADRELATIVE 1 +#define DS3DMODE_DISABLE 2 + +// flags for dwApply parameter of some 3D functions +#define DS3D_IMMEDIATE 0 +#define DS3D_DEFERRED 1 + +// default values for 3d factors +#define DS3D_DEFAULTDISTANCEFACTOR 1.0f +#define DS3D_DEFAULTROLLOFFFACTOR 1.0f +#define DS3D_DEFAULTDOPPLERFACTOR 1.0f + +#define DSBCAPS_PRIMARYBUFFER 0x00000001 +#define DSBCAPS_STATIC 0x00000002 +#define DSBCAPS_LOCHARDWARE 0x00000004 +#define DSBCAPS_LOCSOFTWARE 0x00000008 +#define DSBCAPS_CTRL3D 0x00000010 +#define DSBCAPS_CTRLFREQUENCY 0x00000020 +#define DSBCAPS_CTRLPAN 0x00000040 +#define DSBCAPS_CTRLVOLUME 0x00000080 +#define DSBCAPS_CTRLDEFAULT 0x000000E0 // Pan + volume + frequency. +#define DSBCAPS_CTRLALL 0x000000F0 // All control capabilities +#define DSBCAPS_STICKYFOCUS 0x00004000 +#define DSBCAPS_GLOBALFOCUS 0x00008000 +#define DSBCAPS_GETCURRENTPOSITION2 0x00010000 // More accurate play cursor under emulation + + + + +#define DSSPEAKER_HEADPHONE 1 +#define DSSPEAKER_MONO 2 +#define DSSPEAKER_QUAD 3 +#define DSSPEAKER_STEREO 4 +#define DSSPEAKER_SURROUND 5 + + + + + + +#ifdef __cplusplus +}; +#endif + +#endif /* __DSOUND_INCLUDED__ */ diff --git a/src/DSOUND.LIB b/src/DSOUND.LIB new file mode 100644 index 0000000..dae02aa Binary files /dev/null and b/src/DSOUND.LIB differ diff --git a/src/DTHREAD.CPP b/src/DTHREAD.CPP new file mode 100644 index 0000000..18981c3 --- /dev/null +++ b/src/DTHREAD.CPP @@ -0,0 +1,214 @@ +//****************************************************************** +// dthread.cpp +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include +#include "msg.h" +#include "multi.h" +#include "gendung.h" +#include "sound.h" +#include "storm.h" +#include "items.h" +#include "player.h" +#include "engine.h" + + +//****************************************************************** +// extern +//****************************************************************** +extern DWORD gdwDeltaBytesSec; +void SendPlayerInfoChunk(int pnum,BYTE bCmd,const BYTE * pbSrc,DWORD dwLen); + + +//****************************************************************** +// private +//****************************************************************** +typedef struct TInfo { + struct TInfo * pNext; + int pnum; + BYTE bCmd; + DWORD dwLen; + BYTE bData[1]; +} TInfo; + +// linked list and critical section to protect it +static TInfo * sgpInfoHead; +static CCritSect sgInfoCrit; + +// thread and synchronization objects +static BYTE sgbRunThread = FALSE; +static HANDLE sghThread = INVALID_HANDLE_VALUE; +static HANDLE sghWorkToDoEvent = NULL; +static unsigned sgThreadID; + + +//****************************************************************** +//****************************************************************** +static unsigned __stdcall dthread_proc(void *) { + TInfo * pInfo; + + while (sgbRunThread) { + // sleep until there is work to do + if (! sgpInfoHead && WAIT_FAILED == WaitForSingleObject(sghWorkToDoEvent,INFINITE)) + app_fatal(TEXT("dthread4:\n%s"),strGetLastError()); + + // pull one item off the list + sgInfoCrit.Enter(); + pInfo = sgpInfoHead; + if (sgpInfoHead) sgpInfoHead = sgpInfoHead->pNext; + else ResetEvent(sghWorkToDoEvent); + sgInfoCrit.Leave(); + if (! pInfo) continue; + + // send the item if it still has a valid destination + if (pInfo->pnum != MAX_PLRS) { + SendPlayerInfoChunk( + pInfo->pnum, + pInfo->bCmd, + &pInfo->bData[0], + pInfo->dwLen + ); + } + + // (bytes * 1000 ms/sec) / (bytes/sec) = ms sleep time + app_assert(gdwDeltaBytesSec); + DWORD dwSleepTime = pInfo->dwLen * 1000 / gdwDeltaBytesSec; + dwSleepTime = min(dwSleepTime,1); + + // free item + DiabloFreePtr(pInfo); + + // wait for output queue to empty before sending again + if (dwSleepTime) Sleep(dwSleepTime); + + // pjw.patch2.start + #if CHEATS + static DWORD sdwSkips = 0; + sdwSkips++; + HDC hDC; + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr == DD_OK) { + char szBuf[16]; + wsprintf(szBuf,"d:%u",sdwSkips); + TextOut(hDC,5,460,szBuf,strlen(szBuf)); + lpDDSPrimary->ReleaseDC(hDC); + } + #endif + // pjw.patch2.end + + } + + return 0; +} + + +//****************************************************************** +//****************************************************************** +void dthread_remove_player(int pnum) { + sgInfoCrit.Enter(); + for (TInfo * pInfo = sgpInfoHead; pInfo; pInfo = pInfo->pNext) + if (pInfo->pnum == pnum) pInfo->pnum = MAX_PLRS; + sgInfoCrit.Leave(); +} + + +//****************************************************************** +//****************************************************************** +void dthread_SendPlayerInfoChunk(int pnum,BYTE bCmd,const BYTE * pbSrc,DWORD dwLen) { +// pjw.patch2.start +// app_assert((DWORD) pnum < MAX_PLRS); + if (gbMaxPlayers == 1) return; +// pjw.patch2.end + app_assert(pnum != myplr); + app_assert(pbSrc); + app_assert(dwLen); + + // create a block of memory for the player info + TInfo * pInfo = (TInfo *) DiabloAllocPtrSig(sizeof(TInfo) + dwLen,'DLTA'); + pInfo->pNext = NULL; + pInfo->pnum = pnum; + pInfo->bCmd = bCmd; + pInfo->dwLen = dwLen; + CopyMemory(pInfo->bData,pbSrc,dwLen); + + // link to tail of list + sgInfoCrit.Enter(); + TInfo ** ppInfo = &sgpInfoHead; + while (*ppInfo) ppInfo = &(*ppInfo)->pNext; + *ppInfo = pInfo; + + // wake up thread if necessary -- inside crit section + SetEvent(sghWorkToDoEvent); + + sgInfoCrit.Leave(); +} + + +//****************************************************************** +//****************************************************************** +void dthread_init() { + // we don't have to send delta info in single + // player mode, so don't bother initializing thread + app_assert(sghThread == INVALID_HANDLE_VALUE); + if (gbMaxPlayers == 1) return; + + // make sure linked list is properly initialized + app_assert(! sgpInfoHead); + + // create synchronization object for thread + app_assert(! sghWorkToDoEvent); + if (NULL == (sghWorkToDoEvent = CreateEvent( + NULL, // security info + TRUE, // manual reset + FALSE, // initial state + NULL // name + ))) app_fatal("dthread:1\n%s",strGetLastError()); + + // create worker thread + sgbRunThread = TRUE; + app_assert(sghThread == INVALID_HANDLE_VALUE); + if (INVALID_HANDLE_VALUE == (sghThread = (HANDLE) _beginthreadex( + NULL, // no security info + 0, // stack size + dthread_proc, // start address + NULL, // argument list + 0, // initial state + &sgThreadID // sgThreadID + ))) app_fatal(TEXT("dthread2:\n%s"),strGetLastError()); +} + + +//****************************************************************** +//****************************************************************** +void dthread_free() { + // if the event was never initialized, the thread cannot be running + if (! sghWorkToDoEvent) return; + + // kill off the loader thread + sgbRunThread = FALSE; + SetEvent(sghWorkToDoEvent); + + // wait til the thread is done + if (sghThread != INVALID_HANDLE_VALUE) { + if (sgThreadID != GetCurrentThreadId()) { + if (WAIT_FAILED == WaitForSingleObject(sghThread,INFINITE)) + app_fatal("dthread3:\n(%s)",strGetLastError()); + CloseHandle(sghThread); + sghThread = INVALID_HANDLE_VALUE; + } + } + + // clean up event + CloseHandle(sghWorkToDoEvent); + sghWorkToDoEvent = NULL; + + // clean up linked list + while (sgpInfoHead) { + TInfo * pNext = sgpInfoHead->pNext; + DiabloFreePtr(sgpInfoHead); + sgpInfoHead = pNext; + } +} diff --git a/src/DX.CPP b/src/DX.CPP new file mode 100644 index 0000000..35e5a43 --- /dev/null +++ b/src/DX.CPP @@ -0,0 +1,371 @@ +//****************************************************************** +// dx.cpp +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "palette.h" +#include "engine.h" +#include "resource.h" +#include "gendung.h" + + +//****************************************************************** +// extern +//****************************************************************** +void myDebugBreak(); +void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine); + + +//****************************************************************** +// public +//****************************************************************** +BYTE * gpBuffer; +LPDIRECTDRAW lpDD; // DirectDraw object +LPDIRECTDRAWSURFACE lpDDSPrimary; // DirectDraw primary surface +LPDIRECTDRAWSURFACE lpDDSBackBuf; // optional back buffer +LPDIRECTDRAWPALETTE lpDDPal; // DirectDraw palette +BYTE gbForceBackBuf = FALSE; +BYTE gbUseDDEmulation = FALSE; + + +//****************************************************************** +// private +//****************************************************************** +static DWORD sgdwLockCount; +static CCritSect sgDrawCrit; +static BYTE * sgpBackBuf; +static HINSTANCE sghDDlib = NULL; + +#ifndef NDEBUG +static DWORD sgdwLockTbl[256]; +#endif + + +//****************************************************************** +//****************************************************************** +static void init_backbuf() { + app_assert(! gpBuffer); + app_assert(! sgdwLockCount); + app_assert(! sgpBackBuf); + + // can we lock the primary surface? + DDSCAPS caps; + DDSURFACEDESC ddsd; + app_assert(lpDDSPrimary); + HRESULT ddrval = lpDDSPrimary->GetCaps(&caps); + ddraw_assert(ddrval); + app_assert(caps.dwCaps & DDSCAPS_PRIMARYSURFACE); + + // is this a lockable surface? + extern BYTE gbForceBackBuf; + if (! gbForceBackBuf) { + ddsd.dwSize = sizeof(ddsd); + ddrval = lpDDSPrimary->Lock(NULL,&ddsd,DDLOCK_WAIT|DDLOCK_WRITEONLY,NULL); + if (ddrval == DD_OK) { + ddrval = lpDDSPrimary->Unlock(NULL); + // pjw.patch1.start.1/13/97 + // commented out -- in NT it is possible to + // lose a video surface while it is locked + // ddraw_assert(ddrval); + // pjw.patch1.end.1/13/97 + + // surface is lockable, just create an offscreen memory buffer + sgpBackBuf = DiabloAllocPtrSig(BUFFERSIZE,'OFFS'); + return; + } + // non-lockable surface? + if (ddrval != DDERR_CANTLOCKSURFACE) + ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__); + } + + // create a secondary surface and lock it permanently + ZeroMemory(&ddsd,sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_PIXELFORMAT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + ddsd.dwHeight = BUFFERY; + ddsd.dwWidth = BUFFERX; + ddsd.lPitch = BUFFERX; + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddrval = lpDDSPrimary->GetPixelFormat(&ddsd.ddpfPixelFormat); + if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__); + ddrval = lpDD->CreateSurface(&ddsd,&lpDDSBackBuf,NULL); + if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__); +} + + +//****************************************************************** +//****************************************************************** +static void init_primary() { + DDSURFACEDESC ddsd; + ZeroMemory(&ddsd, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + HRESULT ddrval = lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL); + if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__); +} + + +//****************************************************************** +//****************************************************************** +static HRESULT InDirectDrawCreate( + GUID * lpGUID, + LPDIRECTDRAW * lplpDD, + IUnknown * pUnkOuter +) { + // load direct draw library + if (! sghDDlib) sghDDlib = LoadLibrary(TEXT("ddraw.dll")); + if (! sghDDlib) ErrorDlg(IDD_DDRAW_DLL_ERR,GetLastError(),__FILE__,__LINE__); + + // bind to DirectDrawCreate + typedef HRESULT (WINAPI * DDCREATETYPE)(GUID *,LPDIRECTDRAW *,IUnknown *); + DDCREATETYPE ddcreatefunc = (DDCREATETYPE) GetProcAddress(sghDDlib,TEXT("DirectDrawCreate")); + if (! ddcreatefunc) ErrorDlg(IDD_DDRAW_DLL_ERR,GetLastError(),__FILE__,__LINE__); + + // call DirectDrawCreate + return ddcreatefunc(lpGUID,lplpDD,pUnkOuter); +} + + +//****************************************************************** +//****************************************************************** +void init_directx(HWND hWnd) { + HRESULT ddrval; + app_assert(! gpBuffer); + app_assert(! sgdwLockCount); + app_assert(! sgpBackBuf); + + SetFocus(hWnd); + ShowWindow(hWnd,SW_SHOWNORMAL); + + extern BYTE gbUseDDEmulation; + GUID * lpGUID = NULL; + if (gbUseDDEmulation) lpGUID = (GUID *) DDCREATE_EMULATIONONLY; + ddrval = InDirectDrawCreate(lpGUID,&lpDD,NULL); + if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__); + + #if !ALLOW_WINDOWED_MODE + fullscreen = TRUE; + #endif + + #if ALLOW_WINDOWED_MODE + if (!fullscreen) { + ddrval = lpDD->SetCooperativeLevel(hWnd,DDSCL_NORMAL | DDSCL_ALLOWREBOOT); + if (ddrval == DDERR_EXCLUSIVEMODEALREADYSET) myDebugBreak(); + else if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__); + + // turn off "topmost" flag so that we don't stick above debugger + SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + } + else { + #endif + // Get exclusive mode + ddrval = lpDD->SetCooperativeLevel(hWnd,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT); + if (ddrval == DDERR_EXCLUSIVEMODEALREADYSET) myDebugBreak(); + else if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__); + + // Set the video mode to 640x480x8 + ddrval = lpDD->SetDisplayMode( 640, 480, 8); + // pjw.patch1.start.1/13/97 + // some notebook computers can't switch resolutions -- but + // we should be able to switch the color depth to 256 ??? + if (ddrval != DD_OK) { + int nWdt = GetSystemMetrics(SM_CXSCREEN); + int nHgt = GetSystemMetrics(SM_CYSCREEN); + ddrval = lpDD->SetDisplayMode(nWdt, nHgt, 8); + } + // pjw.patch1.end.1/13/97 + if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_ERR,ddrval,__FILE__,__LINE__); + + #if ALLOW_WINDOWED_MODE + } + #endif + + init_primary(); + + CreatePalette(); + + // Do not allow gdi batching + GdiSetBatchLimit(1); + + // Get the full offscreen buffer including edges + init_backbuf(); + + // inform STORM library of our DirectDraw objects + BOOL bSuccess = SDrawManualInitialize( + hWnd, // window + lpDD, // direct draw + lpDDSPrimary, // primary + NULL, // secondary + NULL, // system + lpDDSBackBuf, // temporary + lpDDPal, // palette + NULL // gdi palette + ); + app_assert(bSuccess); +} + + +//****************************************************************** +//****************************************************************** +static void lock_buf_priv() { + // don't allow any other threads access to the draw + // buffer while we have it locked + sgDrawCrit.Enter(); + + if (sgpBackBuf) { + gpBuffer = sgpBackBuf; + } + else if (! lpDDSBackBuf) { + // if the back buffer was destroyed by another thread + // it is because it is fataling...give it a chance to + // shut down the system before performing our own fatal + Sleep(20000); + app_fatal("lock_buf_priv"); + } + else if (! sgdwLockCount) { + DDSURFACEDESC ddsd; + ddsd.dwSize = sizeof(ddsd); + HRESULT ddrval = lpDDSBackBuf->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL); + ddraw_assert(ddrval); + gpBuffer = (BYTE *) ddsd.lpSurface; + app_assert(gpBuffer); + glClipY += (long) gpBuffer; + } + + // increment lock count + sgdwLockCount++; +} + + +//****************************************************************** +//****************************************************************** +void lock_buf(BYTE bFcn) { + // for debugging -- make sure no lock count over/underflow + #ifndef NDEBUG + sgdwLockTbl[bFcn]++; + #endif + + lock_buf_priv(); +} + + +//****************************************************************** +//****************************************************************** +static void unlock_buf_priv() { + if (! sgdwLockCount) app_fatal("draw main unlock error"); + if (! gpBuffer) app_fatal("draw consistency error"); + if (! sgpBackBuf) app_assert(lpDDSBackBuf); + + // decrement lock count + sgdwLockCount--; + + if (! sgdwLockCount) { + glClipY -= (long) gpBuffer; + gpBuffer = NULL; + if (! sgpBackBuf) { + HRESULT ddrval = lpDDSBackBuf->Unlock(NULL); + ddraw_assert(ddrval); + } + } + + sgDrawCrit.Leave(); +} + + +//****************************************************************** +//****************************************************************** +void unlock_buf(BYTE bFcn) { + // for debugging -- make sure no lock count over/underflow + #ifndef NDEBUG + if (! sgdwLockTbl[bFcn]) app_fatal("Draw lock underflow: 0x%x",bFcn); + sgdwLockTbl[bFcn]--; + #endif + + unlock_buf_priv(); +} + + +//****************************************************************** +// THIS FUNCTION MAY BE CALLED FROM ANY THREAD IN THE PROGRAM +// ALL OTHER PUBLIC FUNCTIONS IN THIS MODULE MAY ONLY BE CALLED +// FROM THE MAIN APPLICATION THREAD! +//****************************************************************** +void free_directx() { + if (ghMainWnd) ShowWindow(ghMainWnd,SW_HIDE); + + // tell SDraw that we're about to kill off direct draw + // so it doesn't try to re-use freed objects + SDrawDestroy(); + + sgDrawCrit.Enter(); + if (sgpBackBuf) { + app_assert(! lpDDSBackBuf); + DiabloFreePtr(sgpBackBuf); + } + else if (lpDDSBackBuf) { + lpDDSBackBuf->Release(); + lpDDSBackBuf = NULL; + } + sgdwLockCount = 0; + gpBuffer = NULL; + sgDrawCrit.Leave(); + + if (lpDDSPrimary) { + lpDDSPrimary->Release(); + lpDDSPrimary = NULL; + } + if (lpDDPal) { + lpDDPal->Release(); + lpDDPal = NULL; + } + if (lpDD) { + lpDD->Release(); + lpDD = NULL; + } + +// cannot free library now, still may be in use +// by directX window procedure... +/* + if (sghDDlib) { + FreeLibrary(sghDDlib); + sghDDlib = NULL; + } +*/ +} + + +//****************************************************************** +//****************************************************************** +void ddraw_switch_modes() { + sgDrawCrit.Enter(); + app_assert(ghMainWnd); + + void savecrsr_reset(); + savecrsr_reset(); + + // remove any locks this thread has on buffer + DWORD dwSaveCount = sgdwLockCount; + while (sgdwLockCount) unlock_buf_priv(); + + free_directx(); + force_redraw = FULLDRAW; + init_directx(ghMainWnd); + + // restore locks + while (dwSaveCount--) lock_buf_priv(); + + sgDrawCrit.Leave(); +} + + +//****************************************************************** +//****************************************************************** +void ddraw_reinit() { + ddraw_switch_modes(); +} diff --git a/src/EFFECTS.CPP b/src/EFFECTS.CPP new file mode 100644 index 0000000..848a2ee --- /dev/null +++ b/src/EFFECTS.CPP @@ -0,0 +1,595 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Sound sgpSFX +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/EFFECTS.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------**/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "monster.h" +#include "monstdat.h" +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "engine.h" +#include "effects.h" +#include "multi.h" + + +//****************************************************************** +// debugging +//****************************************************************** +#define DEBUG_STREAM 1 // 0 in final +#ifdef NDEBUG +#undef DEBUG_STREAM +#define DEBUG_STREAM 0 +#endif + + +//****************************************************************** +// extern +//****************************************************************** +void snd_update(BOOL bStopAll); + + +//****************************************************************** +// public +//****************************************************************** +int sfxdelay, sfxdnum; + + +//****************************************************************** +// private +//****************************************************************** +// sound constants +#define sfx_STREAM 0x01 // streaming sound effect +#define sfx_ALLOWMULTIPLE 0x02 // only valid for non-streamed sounds +#define sfx_MENU 0x04 // menu sound +#define sfx_MONK 0x08 // only needed for the monk +#define sfx_ROGUE 0x10 // only needed for the rogue +#define sfx_WARRIOR 0x20 // only needed for the warrior +#define sfx_SORCEROR 0x40 // only needed for the sorceror +#define sfx_BARD 0x10 // reuse the rogue +#define sfx_BARBARIAN 0x20 // reuse the warrior +#define sfx_DEBUG_STREAM 0x80 // for debugging when streaming is off + +#define sfx_CHAR_MASK (sfx_MONK|sfx_ROGUE|sfx_WARRIOR|sfx_SORCEROR) + +// sound structure +#pragma pack(push,1) +typedef struct TSFX { + BYTE bFlags; + char * pszName; + TSnd * pSnd; +} TSFX; +#pragma pack(pop) + + +// build sound data table +#define EFFECTS_DATA +#include "effects.h" +#undef EFFECTS_DATA +#define NUM_SFX (sizeof(sgSFX) / sizeof(sgSFX[0])) + + +static HSFILE sghStream = NULL; +static TSFX * sgpStreamSFX = NULL; + + +//****************************************************************** +//****************************************************************** +BOOL effect_is_playing(int nSFX) { + app_assert(nSFX < NUM_SFX); + TSFX * pSFX = &sgSFX[nSFX]; + + // if a sound buffer is allocated, then just return play status + if (pSFX->pSnd) return snd_playing(pSFX->pSnd); + + // if this is a streamed sound, is it the current stream? + if (pSFX->bFlags & sfx_STREAM) + return (pSFX == sgpStreamSFX); + + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +#if DEBUG_STREAM +static void debug_stream_update(BOOL bStop) { + // if sound isn't initialized, we don't have to do any work + if (! gbSndInited) return; + + TSFX * pSFX = sgSFX; + for (DWORD d = NUM_SFX; d--; pSFX++) { + if (! (pSFX->bFlags & sfx_DEBUG_STREAM)) continue; + if (! pSFX->pSnd) continue; + if (!bStop && snd_playing(pSFX->pSnd)) continue; + pSFX->bFlags &= ~sfx_DEBUG_STREAM; + snd_free_snd(pSFX->pSnd); + pSFX->pSnd = NULL; + } +} +#endif + + +//****************************************************************** +//****************************************************************** +void stream_stop() { + if (sghStream) { + SFileDdaEnd(sghStream); + SFileCloseFile(sghStream); + sghStream = NULL; + sgpStreamSFX = NULL; + } + + #if DEBUG_STREAM + debug_stream_update(TRUE); + #endif +} + + +//****************************************************************** +//****************************************************************** +#if DEBUG_STREAM +static void debug_stream(TSFX * pSFX,LONG lVolume,LONG lPan) { + // OK, the streaming stuff failed, just load + // it into memory and play it, then free it + if (pSFX->pSnd) return; + if (NULL == (pSFX->pSnd = snd_load_snd(pSFX->pszName))) + return; + pSFX->bFlags |= sfx_DEBUG_STREAM; + snd_play_snd(pSFX->pSnd,lVolume,lPan); +} +#endif + + +//****************************************************************** +//****************************************************************** +static void stream_play(TSFX * pSFX,LONG lVolume,LONG lPan) { + app_assert(pSFX); + app_assert(pSFX->bFlags & sfx_STREAM); + stream_stop(); + + // adjust volume by global volume amount + lVolume += sound_volume(VOLUME_READ); + if (lVolume < VOLUME_MIN) return; + else if (lVolume > VOLUME_MAX) lVolume = VOLUME_MAX; + + // open stream file + #ifndef NDEBUG + SFileEnableDirectAccess(0); + #endif + BOOL bResult = SFileOpenFile(pSFX->pszName,&sghStream); + #ifndef NDEBUG + SFileEnableDirectAccess(1); + #endif + if (! bResult) { + sghStream = NULL; + #if DEBUG_STREAM + debug_stream(pSFX,lVolume,lPan); + #endif + return; + } + + // play it + if (! SFileDdaBeginEx(sghStream,DDA_BUF_SIZE,0,0,lVolume,lPan,0)) { + stream_stop(); + #if DEBUG_STREAM + debug_stream(pSFX,lVolume,lPan); + #endif + return; + } + + sgpStreamSFX = pSFX; +} + + +//****************************************************************** +//****************************************************************** +static void stream_update() { + // is there a stream playing? + if (! sghStream) return; + + // get current stream position + DWORD nPosition,nMaxPosition; + if (! SFileDdaGetPos(sghStream,&nPosition,&nMaxPosition)) + return; + + // if it hasn't finished playing, let it run + if (nPosition < nMaxPosition) + return; + + stream_stop(); +} + + +//****************************************************************** +//****************************************************************** +static void sfx_stop() { + TSFX * pSFX = sgSFX; + for (DWORD d = NUM_SFX; d--; pSFX++) { + if (! pSFX->pSnd) continue; + snd_stop_snd(pSFX->pSnd); + } +} + + +//****************************************************************** +//****************************************************************** +void InitMonsterSND(int monst) { + + // if sound isn't initialized, we don't have to do any work + if (! gbSndInited) return; + + static const char sndletter[MAX_MS + 1] = "ahds"; + int mtype = Monsters[monst].mtype; + for (int snd = 0; snd < MAX_MS; snd++) { + // if this is the "special" sound, and monster doesn't have + // a special sound then we don't need to load the sound + if (sndletter[snd] == 's' && !monsterdata[mtype].snd_special) + continue; + + for (int i = 0; i < 2; i++) { + // derive path for sound effect + char szTemp[MAX_PATH]; + sprintf(szTemp,monsterdata[mtype].sndfile,sndletter[snd],i+1); + char * pszBuf = (char *) DiabloAllocPtrSig(strlen(szTemp) + 1,'SNDN'); + strcpy(pszBuf,szTemp); + + // load sound effect + // leave ptr active + TSnd * pSnd = snd_load_snd(pszBuf); + Monsters[monst].Snds[snd].effect[i] = pSnd; + + // if the sound was never allocated, free the file name buffer + if (! pSnd) DiabloFreePtr(pszBuf); + } + } +} + + +//****************************************************************** +//****************************************************************** +void FreeMonsterSnd() { + for (int monst = 0;monst < nummtypes; monst++) { + int mtype = Monsters[monst].mtype; + for (int snd = 0; snd < MAX_MS; snd++) { + for (int i = 0; i < 2; i++) { + TSnd * pSnd = Monsters[monst].Snds[snd].effect[i]; + if (! pSnd) continue; + Monsters[monst].Snds[snd].effect[i] = NULL; + + // save ptr to sound effect name + char * pszBuf = (char *) pSnd->pszName; + pSnd->pszName = NULL; + + // free sound + snd_free_snd(pSnd); + + // free sound name + DiabloFreePtr(pszBuf); + } + } + } +} + + +//****************************************************************** +//****************************************************************** +static BOOL calc_snd_position(int x,int y,LONG * plVolume,LONG * plPan) { + // calc position relative to player + x -= plr[myplr]._px; + y -= plr[myplr]._py; + + // calc pan + *plPan = (x - y) * 256; + if (abs(*plPan) > 6400) return FALSE; + + // calc volume + *plVolume = max(abs(x),abs(y)) * 64; + if (*plVolume >= 6400) return FALSE; + *plVolume = - *plVolume; + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static void PlaySFX_priv(TSFX * pSFX,BOOL loc,int x, int y) { + + // Don't play sfx if in just onto level + if ((plr[myplr].pLvlLoad) && (gbMaxPlayers != 1)) return; + + // if sound isn't initialized, we don't have to do any work + if (! gbSndInited) return; + if (! gbSoundOn) return; + + // this is the lowest level location to intercept game sound + // effects. If we are in some buffering mode (either because + // we're receiving or parsing information prior to starting a + // level) then we don't want to play any sound effects because + // the player is not in a position to interact with anything yet. + if (gbBufferMsgs != BUFFER_OFF) return; + + // check for sound buffer duplication + if (pSFX->bFlags & sfx_STREAM) { + // streams sounds are always allowed to play + // as they will shut off any previous stream + } + else if (pSFX->bFlags & sfx_ALLOWMULTIPLE) { + // we allow this sound to use multiple buffers + } + else if (pSFX->pSnd && snd_playing(pSFX->pSnd)) { + // this sound is already playing -- skip + return; + } + + // calculate volume and panning, and clip sound if necessary + LONG lPan = 0; + LONG lVolume = 0; + if (loc && !calc_snd_position(x,y,&lVolume,&lPan)) + return; + + if (pSFX->bFlags & sfx_STREAM) { + stream_play(pSFX,lVolume,lPan); + } + else { + if (! pSFX->pSnd) pSFX->pSnd = snd_load_snd(pSFX->pszName); + if (pSFX->pSnd) snd_play_snd(pSFX->pSnd,lVolume,lPan); + } +} + + +//****************************************************************** +// Plays a monster sound effect +// i = monster# to player for +// mode = which sfx to play (attack, hit, death, etc) +//****************************************************************** +void PlayEffect(int i, int mode) { + + // Don't play sfx if in just onto level + if (plr[myplr].pLvlLoad) return; + + // choose which of the two rnd sfx to play + // always perform random() function even if + // sound is off so that random generators stay synced + int nr = random(164, 2); + + // return *after* the random call so that all systems are synced + if (! gbSndInited) return; + if (! gbSoundOn) return; + + // this is the lowest level location to intercept game sound + // effects. If we are in some buffering mode (either because + // we're receiving or parsing information prior to starting a + // level) then we don't want to play any sound effects because + // the player is not in a position to interact with anything yet. + if (gbBufferMsgs != BUFFER_OFF) return; + + // monster type index (0 - nummtypes) + int mi = monster[i]._mMTidx; + + // validate sound effect + TSnd * pSnd = Monsters[mi].Snds[mode].effect[nr]; + if (! pSnd) { + #ifndef NDEBUG // don't fatal out in release version + app_fatal("Monster sound problem\n:%s playing %i", Monsters[mi].MData->mName, mode); + #endif + return; + } + + // don't allow duplication multiple monster effects + if (snd_playing(pSnd)) return; + + // calculate volume and panning, and clip sound if necessary + LONG lPan; + LONG lVolume; + if (!calc_snd_position(monster[i]._mx,monster[i]._my,&lVolume,&lPan)) + return; + + snd_play_snd(pSnd,lVolume,lPan); +} + + +//****************************************************************** +// Determine random sfx to play +//****************************************************************** +static int RndSFX(int psfx) { + int nRand; + if (psfx == PS_WARR69) nRand = 2; + else if (psfx == PS_WARR14) nRand = 3; + else if (psfx == PS_WARR15) nRand = 3; + else if (psfx == PS_WARR16) nRand = 3; +#if !IS_VERSION(SHAREWARE) + else if (psfx == PS_MAGE69) nRand = 2; + else if (psfx == PS_ROGUE69) nRand = 2; + else if (psfx == PS_MONK69) nRand = 2; + else if (psfx == PS_BARD69) nRand = 2; +#endif + else if (psfx == PS_SWING) nRand = 2; + else if (psfx == LS_ACID) nRand = 2; + else if (psfx == IS_FMAG) nRand = 2; + else if (psfx == IS_MAGIC) nRand = 2; + else if (psfx == IS_BHIT) nRand = 2; +// else if (psfx == PS_WALK1) nRand = 4; +#if !IS_VERSION(SHAREWARE) + else if (psfx == PS_WARR2) nRand = 3; +#endif + else return psfx; + + return psfx + random(165,nRand); +} + + +//****************************************************************** +// If player has hit something, play the hit sfx from the player +// (sword hitting metal, bone, etc) +//****************************************************************** +void PlaySFX(int psfx) { + psfx = RndSFX(psfx); + app_assert(psfx < NUM_SFX); + PlaySFX_priv(&sgSFX[psfx],FALSE,0,0); +} + + +//****************************************************************** +// Like PlaySFX, but with a dungeon location +//****************************************************************** +void PlaySfxLoc(int psfx, int x, int y) { + psfx = RndSFX(psfx); + app_assert(psfx < NUM_SFX); + + // don't let walk sounds get clipped! + if (psfx >= PS_WALK1 && psfx <= PS_WALK4) { + TSnd * pSnd = sgSFX[psfx].pSnd; + if (pSnd) pSnd->dwLastPlayTime = 0; + } + + PlaySFX_priv(&sgSFX[psfx],TRUE,x,y); +} + + +//****************************************************************** +//****************************************************************** +void sound_stop() { + snd_update(TRUE); + stream_stop(); + sfx_stop(); + + // stop all monster sounds + int mi, mode, nr; + for (mi = 0; mi < nummtypes; mi++) { + for (mode = 0; mode < MAX_MS; mode++) { + for (nr = 0; nr < 2; nr++) { + TSnd * pSnd = Monsters[mi].Snds[mode].effect[nr]; + snd_stop_snd(pSnd); + } + } + } +} + + +//****************************************************************** +//****************************************************************** +void sound_update() { + // if sound isn't initialized, we don't have to do any work + if (! gbSndInited) return; + + snd_update(FALSE); + stream_update(); + + #if DEBUG_STREAM + debug_stream_update(FALSE); + #endif +} + + +//****************************************************************** +//****************************************************************** +void sound_exit() { + sound_stop(); + for (DWORD d = 0; d < NUM_SFX; d++) { + if (! sgSFX[d].pSnd) continue; + + #if DEBUG_STREAM + sgSFX[d].bFlags &= ~sfx_DEBUG_STREAM; + #endif + + snd_free_snd(sgSFX[d].pSnd); + sgSFX[d].pSnd = NULL; + } +} + + +//****************************************************************** +//****************************************************************** +static void priv_sound_init(BYTE bLoadMask) { + // if sound manager isn't initialized, we don't have to do any work + if (! gbSndInited) return; + + // save character load flags + BYTE bCharMask = bLoadMask & sfx_CHAR_MASK; + + // load mask excludes character mask + bLoadMask ^= bCharMask; + + // load sounds + for (DWORD d = 0; d < NUM_SFX; d++) { + // is it already loaded? + if (sgSFX[d].pSnd) continue; + + // don't load streamed sounds + if (sgSFX[d].bFlags & sfx_STREAM) continue; + + // if load mask is non-zero, only load sound effect if + // it has a flag which is set in the load mask + if (bLoadMask && !(sgSFX[d].bFlags & bLoadMask)) continue; + + // is this a character sound that we don't need? + if (sgSFX[d].bFlags & sfx_CHAR_MASK) { + if (! (sgSFX[d].bFlags & bCharMask)) + continue; + } + + // load it + sgSFX[d].pSnd = snd_load_snd(sgSFX[d].pszName); + } +} + + +//****************************************************************** +//****************************************************************** +void sound_init() { + BYTE bLoadMask = 0; + if (gbMaxPlayers > 1) + bLoadMask = sfx_CHAR_MASK; + else if (plr[myplr]._pClass == CLASS_WARRIOR) + bLoadMask = sfx_WARRIOR; + else if (plr[myplr]._pClass == CLASS_ROGUE) + bLoadMask = sfx_ROGUE; + else if (plr[myplr]._pClass == CLASS_SORCEROR) + bLoadMask = sfx_SORCEROR; + else if (plr[myplr]._pClass == CLASS_MONK) + bLoadMask = sfx_MONK; + else if (plr[myplr]._pClass == CLASS_BARD) + bLoadMask = sfx_BARD; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) + bLoadMask = sfx_BARBARIAN; + else + app_fatal("effects:1"); + priv_sound_init(bLoadMask); +} + + +//****************************************************************** +//****************************************************************** +void menusnd_init() { + priv_sound_init(sfx_MENU); +} + + +//****************************************************************** +//****************************************************************** +void CALLBACK menusnd_play(LPCSTR pszName) { + // sound initialized? + if (! gbSndInited) return; + if (! gbSoundOn) return; + + for (DWORD d = 0; d < NUM_SFX; d++) { + if (_stricmp(sgSFX[d].pszName,pszName)) continue; + if (! sgSFX[d].pSnd) continue; + if (snd_playing(sgSFX[d].pSnd)) break; + snd_play_snd(sgSFX[d].pSnd,0,0); + break; + } +} + diff --git a/src/EFFECTS.H b/src/EFFECTS.H new file mode 100644 index 0000000..641d0d1 --- /dev/null +++ b/src/EFFECTS.H @@ -0,0 +1,1440 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/EFFECTS.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +//****************************************************************** +// Defines +//****************************************************************** +// monster sfx +#define MS_ATTACK 0 +#define MS_GOTHIT 1 +#define MS_DEATH 2 +#define MS_SATTACK 3 +#define MAX_MS 4 + + +//****************************************************************** +// externs +//****************************************************************** +extern sfxdelay, sfxdnum; + + +//****************************************************************** +// public functions +//****************************************************************** +void sound_init(); +void sound_exit(); +void sound_update(); +void sound_stop(); +void stream_stop(); + +void PlrTryHitSnd(); +void PlaySFX(int); +void PlaySfxLoc(int psfx, int x, int y); + +void InitMonsterSND(); +void PlayEffect(int, int); +void FreeMonsterSnd(); + + +//****************************************************************** +// sound effects data +//****************************************************************** +#ifdef EFFECTS_DATA + #define SFX(a,b,c) { a, b, NULL } + #define rSFX(a,b,c) { a | sfx_ROGUE, b, NULL } + #define wSFX(a,b,c) { a | sfx_WARRIOR, b, NULL } + #define sSFX(a,b,c) { a | sfx_SORCEROR, b, NULL } + #define mSFX(a,b,c) { a | sfx_MONK, b, NULL } +#else + #define SFX(a,b,c) c + #define rSFX(a,b,c) c + #define wSFX(a,b,c) c + #define sSFX(a,b,c) c + #define mSFX(a,b,c) c +#endif + + +// build data table or header enum +#ifdef EFFECTS_DATA +static TSFX sgSFX[] = { +#else +enum { +#endif +// NOTE NOTE NOTE NOTE NOTE +// do not put any sound effects before these effects +// DirectSound loads sound effects into hardware on +// a first-come, first-served basis, so we want the +// most common sounds to come first so they end up +// in hardware. + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Walk1.wav", PS_WALK1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Walk2.wav", PS_WALK2), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Walk3.wav", PS_WALK3), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Walk4.wav", PS_WALK4), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\BFire.wav", PS_BFIRE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Fmag.wav", PS_FMAG), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Tmag.wav", PS_TMAG), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Lghit.wav", PS_LGHIT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Lghit1.wav", PS_LGHIT1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Swing.wav", PS_SWING), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Swing2.wav", PS_SWING2), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Dead.wav", PS_DEAD), + +// SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\NewBFire.wav", PS_NEW_BFIRE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Sting1.wav", PS_NEW_BFIRE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\FBallBow.wav", PS_FB_BFIRE), + // Quests SoundEffects + SFX(sfx_STREAM, "Sfx\\Misc\\Questdon.wav", IS_QUESTDN), + + // Item SoundEffects + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Armrfkd.wav", IS_ARMRFKD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Barlfire.wav", IS_BARLFIRE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Barrel.wav", IS_BARREL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\PodPop8.wav", IS_PODFIRE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\PodPop5.wav", IS_POD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\UrnPop3.wav", IS_URNFIRE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\UrnPop2.wav", IS_URN), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Bhit.wav", IS_BHIT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Bhit1.wav", IS_BHIT1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Chest.wav", IS_CHEST), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Doorclos.wav", IS_DOORCLOS), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Dooropen.wav", IS_DOOROPEN), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipanvl.wav", IS_FANVL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipaxe.wav", IS_FAXE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipblst.wav", IS_FBLST), // ear + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipbody.wav", IS_FBODY), // ear + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipbook.wav", IS_FBOOK), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipbow.wav", IS_FBOW), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipcap.wav", IS_FCAP), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipharm.wav", IS_FHARM), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Fliplarm.wav", IS_FLARM), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipmag.wav", IS_FMAG), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipmag1.wav", IS_FMAG1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipmush.wav", IS_FMUSH), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flippot.wav", IS_FPOT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipring.wav", IS_FRING), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Fliprock.wav", IS_FROCK), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipscrl.wav", IS_FSCRL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipshld.wav", IS_FSHLD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipsign.wav", IS_FSIGN), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipstaf.wav", IS_FSTAF), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Flipswor.wav", IS_FSWOR), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Gold.wav", IS_GOLD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Hlmtfkd.wav", IS_HLMTFKD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invanvl.wav", IS_IANVL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invaxe.wav", IS_IAXE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invblst.wav", IS_IBLST), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invbody.wav", IS_IBODY), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invbook.wav", IS_IBOOK), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invbow.wav", IS_IBOW), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invcap.wav", IS_ICAP), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invgrab.wav", IS_IGRAB), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invharm.wav", IS_IHARM), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invlarm.wav", IS_ILARM), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invmush.wav", IS_IMUSH), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invpot.wav", IS_IPOT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invring.wav", IS_IRING), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invrock.wav", IS_IROCK), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invscrol.wav", IS_ISCROL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invshiel.wav", IS_ISHIEL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invsign.wav", IS_ISIGN), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invstaf.wav", IS_ISTAF), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Invsword.wav", IS_ISWORD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Lever.wav", IS_LEVER), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Magic.wav", IS_MAGIC), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Magic1.wav", IS_MAGIC1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Readbook.wav", IS_RBOOK), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Sarc.wav", IS_SARC), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Shielfkd.wav", IS_SHLDFKD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Swrdfkd.wav", IS_SWRDFKD), + SFX(sfx_MENU, "Sfx\\Items\\Titlemov.wav", IS_TITLEMOV), + SFX(sfx_MENU, "Sfx\\Items\\Titlslct.wav", IS_TITLSLCT), + SFX(sfx_MENU, "Sfx\\Misc\\blank.wav", SFX_SILENCE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Trap.wav", IS_TRAP), + + // Cast + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast1.wav", IS_CAST1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast10.wav", IS_CAST10), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast12.wav", IS_CAST12), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast2.wav", IS_CAST2), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast3.wav", IS_CAST3), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast4.wav", IS_CAST4), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast5.wav", IS_CAST5), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast6.wav", IS_CAST6), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast7.wav", IS_CAST7), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast8.wav", IS_CAST8), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cast9.wav", IS_CAST9), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Healing.wav", LS_HEALING), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Repair.wav", IS_REPAIR), + + // Launch and impact sounds + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Acids1.wav", LS_ACID), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Acids2.wav", LS_ACIDS), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Apoc.wav", LS_APOC), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Arrowall.wav", LS_ARROWALL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Bldboil.wav", LS_BLODBOIL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Blodstar.wav", LS_BLODSTAR), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Blsimpt.wav", LS_BLSIMPT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Bonesp.wav", LS_BONESP), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Bsimpct.wav", LS_BSIMPCT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Caldron.wav", LS_CALDRON), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Cbolt.wav", LS_CBOLT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Chltning.wav", LS_CHLTNING), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\DSerp.wav", LS_DSERP), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Elecimp1.wav", LS_ELECIMP1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Elementl.wav", LS_ELEMENTL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Ethereal.wav", LS_ETHEREAL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Fball.wav", LS_FBALL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Fbolt1.wav", LS_FBOLT1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Fbolt2.wav", LS_FBOLT2), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Firimp1.wav", LS_FIRIMP1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Firimp2.wav", LS_FIRIMP2), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Flamwave.wav", LS_FLAMWAVE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Flash.wav", LS_FLASH), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Fountain.wav", LS_FOUNTAIN), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Golum.wav", LS_GOLUM), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Golumded.wav", LS_GOLUMDED), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Gshrine.wav", LS_GSHRINE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Guard.wav", LS_GUARD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Grdlanch.wav", LS_GUARDLAN), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Holybolt.wav", LS_HOLYBOLT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Hyper.wav", LS_HYPER), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Infravis.wav", LS_INFRAVIS), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Invisibl.wav", LS_INVISIBL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Invpot.wav", LS_INVPOT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Lning1.wav", LS_LNING1), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Ltning.wav", LS_LTNING), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Mshield.wav", LS_MSHIELD), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\NestXpld.wav", LS_BIGEXP), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Nova.wav", LS_NOVA), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Portal.wav", LS_PORTAL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Puddle.wav", LS_PUDDLE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Resur.wav", LS_RESUR), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Scurse.wav", LS_SCURSE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Scurimp.wav", LS_SCURIMP), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Sentinel.wav", LS_SENTINEL), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Shatter.wav", LS_SHATTER), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Soulfire.wav", LS_SOULFIRE), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Spoutlop.wav", LS_SPOUTLOP), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Spoutstr.wav", LS_SPOUTSTR), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Storm.wav", LS_STORM), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Trapdis.wav", LS_TRAPDIS), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Teleport.wav", LS_TELEPORT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Vtheft.wav", LS_VTHEFT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Wallloop.wav", LS_WALLLOOP), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\Wallstrt.wav", LS_WALLSTRT), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Misc\\LMag.wav", LS_LMAG), + + // town sounds +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid01.wav", TSFX_BMAID1), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid02.wav", TSFX_BMAID2), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid03.wav", TSFX_BMAID3), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid04.wav", TSFX_BMAID4), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid05.wav", TSFX_BMAID5), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid06.wav", TSFX_BMAID6), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid07.wav", TSFX_BMAID7), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid08.wav", TSFX_BMAID8), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid09.wav", TSFX_BMAID9), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid10.wav", TSFX_BMAID10), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid11.wav", TSFX_BMAID11), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid12.wav", TSFX_BMAID12), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid13.wav", TSFX_BMAID13), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid14.wav", TSFX_BMAID14), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid15.wav", TSFX_BMAID15), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid16.wav", TSFX_BMAID16), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid17.wav", TSFX_BMAID17), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid18.wav", TSFX_BMAID18), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid19.wav", TSFX_BMAID19), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid20.wav", TSFX_BMAID20), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid21.wav", TSFX_BMAID21), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid22.wav", TSFX_BMAID22), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid23.wav", TSFX_BMAID23), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid24.wav", TSFX_BMAID24), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid25.wav", TSFX_BMAID25), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid26.wav", TSFX_BMAID26), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid27.wav", TSFX_BMAID27), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid28.wav", TSFX_BMAID28), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid29.wav", TSFX_BMAID29), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid30.wav", TSFX_BMAID30), +#endif + // greeting -- good day... + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid31.wav", TSFX_BMAID31), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid32.wav", TSFX_BMAID32), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid33.wav", TSFX_BMAID33), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid34.wav", TSFX_BMAID34), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid35.wav", TSFX_BMAID35), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid36.wav", TSFX_BMAID36), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid37.wav", TSFX_BMAID37), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid38.wav", TSFX_BMAID38), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid39.wav", TSFX_BMAID39), + SFX(sfx_STREAM, "Sfx\\Towners\\Bmaid40.wav", TSFX_BMAID40), +#endif + + // BlackSmith +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith01.wav", TSFX_SMITH1), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith02.wav", TSFX_SMITH2), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith03.wav", TSFX_SMITH3), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith04.wav", TSFX_SMITH4), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith05.wav", TSFX_SMITH5), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith06.wav", TSFX_SMITH6), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith07.wav", TSFX_SMITH7), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith08.wav", TSFX_SMITH8), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith09.wav", TSFX_SMITH9), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith10.wav", TSFX_SMITH10), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith11.wav", TSFX_SMITH11), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith12.wav", TSFX_SMITH12), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith13.wav", TSFX_SMITH13), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith14.wav", TSFX_SMITH14), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith15.wav", TSFX_SMITH15), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith16.wav", TSFX_SMITH16), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith17.wav", TSFX_SMITH17), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith18.wav", TSFX_SMITH18), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith19.wav", TSFX_SMITH19), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith20.wav", TSFX_SMITH20), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith21.wav", TSFX_SMITH21), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith22.wav", TSFX_SMITH22), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith23.wav", TSFX_SMITH23), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith24.wav", TSFX_SMITH24), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith25.wav", TSFX_SMITH25), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith26.wav", TSFX_SMITH26), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith27.wav", TSFX_SMITH27), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith28.wav", TSFX_SMITH28), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith29.wav", TSFX_SMITH29), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith30.wav", TSFX_SMITH30), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith31.wav", TSFX_SMITH31), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith32.wav", TSFX_SMITH32), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith33.wav", TSFX_SMITH33), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith34.wav", TSFX_SMITH34), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith35.wav", TSFX_SMITH35), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith36.wav", TSFX_SMITH36), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith37.wav", TSFX_SMITH37), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith38.wav", TSFX_SMITH38), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith39.wav", TSFX_SMITH39), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith40.wav", TSFX_SMITH40), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith41.wav", TSFX_SMITH41), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith42.wav", TSFX_SMITH42), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith43.wav", TSFX_SMITH43), +#endif + // greeting -- well, what can I do for you? + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith44.wav", TSFX_SMITH44), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith45.wav", TSFX_SMITH45), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith46.wav", TSFX_SMITH46), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith47.wav", TSFX_SMITH47), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith48.wav", TSFX_SMITH48), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith49.wav", TSFX_SMITH49), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith50.wav", TSFX_SMITH50), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith51.wav", TSFX_SMITH51), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith52.wav", TSFX_SMITH52), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith53.wav", TSFX_SMITH53), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith54.wav", TSFX_SMITH54), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith55.wav", TSFX_SMITH55), + SFX(sfx_STREAM, "Sfx\\Towners\\Bsmith56.wav", TSFX_SMITH56), +#endif + + SFX(0, "Sfx\\Towners\\Cow1.wav", TSFX_COW1), + SFX(0, "Sfx\\Towners\\Cow2.wav", TSFX_COW2), + +#if 0 + SFX(sfx_STREAM, "Sfx\\Towners\\Cow3.wav", TSFX_COW3), + SFX(sfx_STREAM, "Sfx\\Towners\\Cow4.wav", TSFX_COW4), + SFX(sfx_STREAM, "Sfx\\Towners\\Cow5.wav", TSFX_COW5), + SFX(sfx_STREAM, "Sfx\\Towners\\Cow6.wav", TSFX_COW6), +#endif + SFX(sfx_STREAM, "Sfx\\Towners\\Cow7.wav", TSFX_COW7), + SFX(sfx_STREAM, "Sfx\\Towners\\Cow8.wav", TSFX_COW8), + +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Deadguy2.wav", TSFX_DEADGUY), +#endif + +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk01.wav", TSFX_DRUNK1), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk02.wav", TSFX_DRUNK2), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk03.wav", TSFX_DRUNK3), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk04.wav", TSFX_DRUNK4), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk05.wav", TSFX_DRUNK5), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk06.wav", TSFX_DRUNK6), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk07.wav", TSFX_DRUNK7), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk08.wav", TSFX_DRUNK8), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk09.wav", TSFX_DRUNK9), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk10.wav", TSFX_DRUNK10), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk11.wav", TSFX_DRUNK11), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk12.wav", TSFX_DRUNK12), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk13.wav", TSFX_DRUNK13), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk14.wav", TSFX_DRUNK14), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk15.wav", TSFX_DRUNK15), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk16.wav", TSFX_DRUNK16), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk17.wav", TSFX_DRUNK17), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk18.wav", TSFX_DRUNK18), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk19.wav", TSFX_DRUNK19), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk20.wav", TSFX_DRUNK20), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk21.wav", TSFX_DRUNK21), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk22.wav", TSFX_DRUNK22), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk23.wav", TSFX_DRUNK23), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk24.wav", TSFX_DRUNK24), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk25.wav", TSFX_DRUNK25), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk26.wav", TSFX_DRUNK26), +#endif + // greeting -- can't a fellow drink in peace? + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk27.wav", TSFX_DRUNK27), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk28.wav", TSFX_DRUNK28), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk29.wav", TSFX_DRUNK29), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk30.wav", TSFX_DRUNK30), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk31.wav", TSFX_DRUNK31), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk32.wav", TSFX_DRUNK32), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk33.wav", TSFX_DRUNK33), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk34.wav", TSFX_DRUNK34), + SFX(sfx_STREAM, "Sfx\\Towners\\Drunk35.wav", TSFX_DRUNK35), +#endif + +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Healer01.wav", TSFX_HEALER1), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer02.wav", TSFX_HEALER2), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer03.wav", TSFX_HEALER3), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer04.wav", TSFX_HEALER4), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer05.wav", TSFX_HEALER5), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer06.wav", TSFX_HEALER6), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer07.wav", TSFX_HEALER7), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer08.wav", TSFX_HEALER8), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer09.wav", TSFX_HEALER9), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer10.wav", TSFX_HEALER10), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer11.wav", TSFX_HEALER11), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer12.wav", TSFX_HEALER12), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer13.wav", TSFX_HEALER13), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer14.wav", TSFX_HEALER14), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer15.wav", TSFX_HEALER15), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer16.wav", TSFX_HEALER16), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer17.wav", TSFX_HEALER17), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer18.wav", TSFX_HEALER18), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer19.wav", TSFX_HEALER19), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer20.wav", TSFX_HEALER20), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer21.wav", TSFX_HEALER21), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer22.wav", TSFX_HEALER22), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer23.wav", TSFX_HEALER23), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer24.wav", TSFX_HEALER24), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer25.wav", TSFX_HEALER25), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer26.wav", TSFX_HEALER26), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer27.wav", TSFX_HEALER27), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer28.wav", TSFX_HEALER28), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer29.wav", TSFX_HEALER29), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer30.wav", TSFX_HEALER30), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer31.wav", TSFX_HEALER31), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer32.wav", TSFX_HEALER32), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer33.wav", TSFX_HEALER33), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer34.wav", TSFX_HEALER34), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer35.wav", TSFX_HEALER35), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer36.wav", TSFX_HEALER36), +#endif + // greeting -- what ails you my friend? + SFX(sfx_STREAM, "Sfx\\Towners\\Healer37.wav", TSFX_HEALER37), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Healer38.wav", TSFX_HEALER38), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer39.wav", TSFX_HEALER39), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer40.wav", TSFX_HEALER40), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer41.wav", TSFX_HEALER41), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer42.wav", TSFX_HEALER42), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer43.wav", TSFX_HEALER43), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer44.wav", TSFX_HEALER44), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer45.wav", TSFX_HEALER45), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer46.wav", TSFX_HEALER46), + SFX(sfx_STREAM, "Sfx\\Towners\\Healer47.wav", TSFX_HEALER47), +#endif + +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy01.wav", TSFX_PEGBOY1), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy02.wav", TSFX_PEGBOY2), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy03.wav", TSFX_PEGBOY3), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy04.wav", TSFX_PEGBOY4), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy05.wav", TSFX_PEGBOY5), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy06.wav", TSFX_PEGBOY6), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy07.wav", TSFX_PEGBOY7), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy08.wav", TSFX_PEGBOY8), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy09.wav", TSFX_PEGBOY9), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy10.wav", TSFX_PEGBOY10), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy11.wav", TSFX_PEGBOY11), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy12.wav", TSFX_PEGBOY12), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy13.wav", TSFX_PEGBOY13), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy14.wav", TSFX_PEGBOY14), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy15.wav", TSFX_PEGBOY15), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy16.wav", TSFX_PEGBOY16), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy17.wav", TSFX_PEGBOY17), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy18.wav", TSFX_PEGBOY18), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy19.wav", TSFX_PEGBOY19), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy20.wav", TSFX_PEGBOY20), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy21.wav", TSFX_PEGBOY21), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy22.wav", TSFX_PEGBOY22), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy23.wav", TSFX_PEGBOY23), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy24.wav", TSFX_PEGBOY24), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy25.wav", TSFX_PEGBOY25), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy26.wav", TSFX_PEGBOY26), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy27.wav", TSFX_PEGBOY27), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy28.wav", TSFX_PEGBOY28), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy29.wav", TSFX_PEGBOY29), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy30.wav", TSFX_PEGBOY30), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy31.wav", TSFX_PEGBOY31), +#endif + // greeting -- psst, over here... + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy32.wav", TSFX_PEGBOY32), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy33.wav", TSFX_PEGBOY33), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy34.wav", TSFX_PEGBOY34), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy35.wav", TSFX_PEGBOY35), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy36.wav", TSFX_PEGBOY36), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy37.wav", TSFX_PEGBOY37), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy38.wav", TSFX_PEGBOY38), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy39.wav", TSFX_PEGBOY39), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy40.wav", TSFX_PEGBOY40), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy41.wav", TSFX_PEGBOY41), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy42.wav", TSFX_PEGBOY42), + SFX(sfx_STREAM, "Sfx\\Towners\\Pegboy43.wav", TSFX_PEGBOY43), +#endif + +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Priest00.wav", TSFX_PRIEST0), + SFX(sfx_STREAM, "Sfx\\Towners\\Priest01.wav", TSFX_PRIEST1), + SFX(sfx_STREAM, "Sfx\\Towners\\Priest02.wav", TSFX_PRIEST2), + SFX(sfx_STREAM, "Sfx\\Towners\\Priest03.wav", TSFX_PRIEST3), + SFX(sfx_STREAM, "Sfx\\Towners\\Priest04.wav", TSFX_PRIEST4), + SFX(sfx_STREAM, "Sfx\\Towners\\Priest05.wav", TSFX_PRIEST5), + SFX(sfx_STREAM, "Sfx\\Towners\\Priest06.wav", TSFX_PRIEST6), + SFX(sfx_STREAM, "Sfx\\Towners\\Priest07.wav", TSFX_PRIEST7), +#endif + +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt00.wav", TSFX_STORY0), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt01.wav", TSFX_STORY1), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt02.wav", TSFX_STORY2), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt03.wav", TSFX_STORY3), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt04.wav", TSFX_STORY4), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt05.wav", TSFX_STORY5), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt06.wav", TSFX_STORY6), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt07.wav", TSFX_STORY7), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt08.wav", TSFX_STORY8), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt09.wav", TSFX_STORY9), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt10.wav", TSFX_STORY10), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt11.wav", TSFX_STORY11), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt12.wav", TSFX_STORY12), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt13.wav", TSFX_STORY13), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt14.wav", TSFX_STORY14), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt15.wav", TSFX_STORY15), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt16.wav", TSFX_STORY16), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt17.wav", TSFX_STORY17), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt18.wav", TSFX_STORY18), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt19.wav", TSFX_STORY19), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt20.wav", TSFX_STORY20), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt21.wav", TSFX_STORY21), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt22.wav", TSFX_STORY22), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt23.wav", TSFX_STORY23), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt24.wav", TSFX_STORY24), +#endif + // greeting -- hello my friend... + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt25.wav", TSFX_STORY25), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt26.wav", TSFX_STORY26), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt27.wav", TSFX_STORY27), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt28.wav", TSFX_STORY28), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt29.wav", TSFX_STORY29), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt30.wav", TSFX_STORY30), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt31.wav", TSFX_STORY31), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt32.wav", TSFX_STORY32), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt33.wav", TSFX_STORY33), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt34.wav", TSFX_STORY34), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt35.wav", TSFX_STORY35), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt36.wav", TSFX_STORY36), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt37.wav", TSFX_STORY37), + SFX(sfx_STREAM, "Sfx\\Towners\\Storyt38.wav", TSFX_STORY38), +#endif + + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown00.wav", TSFX_TAVERN0), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown01.wav", TSFX_TAVERN1), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown02.wav", TSFX_TAVERN2), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown03.wav", TSFX_TAVERN3), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown04.wav", TSFX_TAVERN4), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown05.wav", TSFX_TAVERN5), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown06.wav", TSFX_TAVERN6), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown07.wav", TSFX_TAVERN7), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown08.wav", TSFX_TAVERN8), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown09.wav", TSFX_TAVERN9), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown10.wav", TSFX_TAVERN10), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown11.wav", TSFX_TAVERN11), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown12.wav", TSFX_TAVERN12), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown13.wav", TSFX_TAVERN13), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown14.wav", TSFX_TAVERN14), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown15.wav", TSFX_TAVERN15), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown16.wav", TSFX_TAVERN16), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown17.wav", TSFX_TAVERN17), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown18.wav", TSFX_TAVERN18), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown19.wav", TSFX_TAVERN19), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown20.wav", TSFX_TAVERN20), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown21.wav", TSFX_TAVERN21), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown22.wav", TSFX_TAVERN22), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown23.wav", TSFX_TAVERN23), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown24.wav", TSFX_TAVERN24), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown25.wav", TSFX_TAVERN25), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown26.wav", TSFX_TAVERN26), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown27.wav", TSFX_TAVERN27), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown28.wav", TSFX_TAVERN28), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown29.wav", TSFX_TAVERN29), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown30.wav", TSFX_TAVERN30), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown31.wav", TSFX_TAVERN31), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown32.wav", TSFX_TAVERN32), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown33.wav", TSFX_TAVERN33), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown34.wav", TSFX_TAVERN34), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown35.wav", TSFX_TAVERN35), +#endif + // greeting -- greetings good master... + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown36.wav", TSFX_TAVERN36), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown37.wav", TSFX_TAVERN37), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown38.wav", TSFX_TAVERN38), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown39.wav", TSFX_TAVERN39), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown40.wav", TSFX_TAVERN40), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown41.wav", TSFX_TAVERN41), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown42.wav", TSFX_TAVERN42), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown43.wav", TSFX_TAVERN43), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown44.wav", TSFX_TAVERN44), + SFX(sfx_STREAM, "Sfx\\Towners\\Tavown45.wav", TSFX_TAVERN45), +#endif + +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Witch01.wav", TSFX_WITCH1), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch02.wav", TSFX_WITCH2), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch03.wav", TSFX_WITCH3), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch04.wav", TSFX_WITCH4), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch05.wav", TSFX_WITCH5), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch06.wav", TSFX_WITCH6), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch07.wav", TSFX_WITCH7), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch08.wav", TSFX_WITCH8), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch09.wav", TSFX_WITCH9), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch10.wav", TSFX_WITCH10), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch11.wav", TSFX_WITCH11), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch12.wav", TSFX_WITCH12), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch13.wav", TSFX_WITCH13), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch14.wav", TSFX_WITCH14), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch15.wav", TSFX_WITCH15), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch16.wav", TSFX_WITCH16), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch17.wav", TSFX_WITCH17), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch18.wav", TSFX_WITCH18), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch19.wav", TSFX_WITCH19), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch20.wav", TSFX_WITCH20), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch21.wav", TSFX_WITCH21), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch22.wav", TSFX_WITCH22), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch23.wav", TSFX_WITCH23), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch24.wav", TSFX_WITCH24), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch25.wav", TSFX_WITCH25), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch26.wav", TSFX_WITCH26), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch27.wav", TSFX_WITCH27), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch28.wav", TSFX_WITCH28), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch29.wav", TSFX_WITCH29), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch30.wav", TSFX_WITCH30), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch31.wav", TSFX_WITCH31), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch32.wav", TSFX_WITCH32), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch33.wav", TSFX_WITCH33), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch34.wav", TSFX_WITCH34), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch35.wav", TSFX_WITCH35), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch36.wav", TSFX_WITCH36), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch37.wav", TSFX_WITCH37), +#endif + // greeting -- I sense a soul in search of answers + SFX(sfx_STREAM, "Sfx\\Towners\\Witch38.wav", TSFX_WITCH38), +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Witch39.wav", TSFX_WITCH39), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch40.wav", TSFX_WITCH40), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch41.wav", TSFX_WITCH41), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch42.wav", TSFX_WITCH42), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch43.wav", TSFX_WITCH43), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch44.wav", TSFX_WITCH44), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch45.wav", TSFX_WITCH45), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch46.wav", TSFX_WITCH46), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch47.wav", TSFX_WITCH47), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch48.wav", TSFX_WITCH48), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch49.wav", TSFX_WITCH49), + SFX(sfx_STREAM, "Sfx\\Towners\\Witch50.wav", TSFX_WITCH50), +#endif + +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Towners\\Wound01.wav", TSFX_WOUND), +#endif + + // Mage +#if !IS_VERSION(SHAREWARE) + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage01.wav", PS_MAGE1), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage02.wav", PS_MAGE2), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage03.wav", PS_MAGE3), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage04.wav", PS_MAGE4), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage05.wav", PS_MAGE5), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage06.wav", PS_MAGE6), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage07.wav", PS_MAGE7), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage08.wav", PS_MAGE8), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage09.wav", PS_MAGE9), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage10.wav", PS_MAGE10), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage11.wav", PS_MAGE11), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage12.wav", PS_MAGE12), + sSFX(0, "Sfx\\Sorceror\\Mage13.wav", PS_MAGE13), + sSFX(0, "Sfx\\Sorceror\\Mage14.wav", PS_MAGE14), + sSFX(0, "Sfx\\Sorceror\\Mage15.wav", PS_MAGE15), + sSFX(0, "Sfx\\Sorceror\\Mage16.wav", PS_MAGE16), + sSFX(0, "Sfx\\Sorceror\\Mage17.wav", PS_MAGE17), + sSFX(0, "Sfx\\Sorceror\\Mage18.wav", PS_MAGE18), + sSFX(0, "Sfx\\Sorceror\\Mage19.wav", PS_MAGE19), + sSFX(0, "Sfx\\Sorceror\\Mage20.wav", PS_MAGE20), + sSFX(0, "Sfx\\Sorceror\\Mage21.wav", PS_MAGE21), + sSFX(0, "Sfx\\Sorceror\\Mage22.wav", PS_MAGE22), + sSFX(0, "Sfx\\Sorceror\\Mage23.wav", PS_MAGE23), + sSFX(0, "Sfx\\Sorceror\\Mage24.wav", PS_MAGE24), + sSFX(0, "Sfx\\Sorceror\\Mage25.wav", PS_MAGE25), + sSFX(0, "Sfx\\Sorceror\\Mage26.wav", PS_MAGE26), + sSFX(0, "Sfx\\Sorceror\\Mage27.wav", PS_MAGE27), + sSFX(0, "Sfx\\Sorceror\\Mage28.wav", PS_MAGE28), + sSFX(0, "Sfx\\Sorceror\\Mage29.wav", PS_MAGE29), + sSFX(0, "Sfx\\Sorceror\\Mage30.wav", PS_MAGE30), + sSFX(0, "Sfx\\Sorceror\\Mage31.wav", PS_MAGE31), + sSFX(0, "Sfx\\Sorceror\\Mage32.wav", PS_MAGE32), + sSFX(0, "Sfx\\Sorceror\\Mage33.wav", PS_MAGE33), + sSFX(0, "Sfx\\Sorceror\\Mage34.wav", PS_MAGE34), + sSFX(0, "Sfx\\Sorceror\\Mage35.wav", PS_MAGE35), + sSFX(0, "Sfx\\Sorceror\\Mage36.wav", PS_MAGE36), + sSFX(0, "Sfx\\Sorceror\\Mage37.wav", PS_MAGE37), + sSFX(0, "Sfx\\Sorceror\\Mage38.wav", PS_MAGE38), + sSFX(0, "Sfx\\Sorceror\\Mage39.wav", PS_MAGE39), + sSFX(0, "Sfx\\Sorceror\\Mage40.wav", PS_MAGE40), + sSFX(0, "Sfx\\Sorceror\\Mage41.wav", PS_MAGE41), + sSFX(0, "Sfx\\Sorceror\\Mage42.wav", PS_MAGE42), + sSFX(0, "Sfx\\Sorceror\\Mage43.wav", PS_MAGE43), + sSFX(0, "Sfx\\Sorceror\\Mage44.wav", PS_MAGE44), + sSFX(0, "Sfx\\Sorceror\\Mage45.wav", PS_MAGE45), + sSFX(0, "Sfx\\Sorceror\\Mage46.wav", PS_MAGE46), + sSFX(0, "Sfx\\Sorceror\\Mage47.wav", PS_MAGE47), + sSFX(0, "Sfx\\Sorceror\\Mage48.wav", PS_MAGE48), + sSFX(0, "Sfx\\Sorceror\\Mage49.wav", PS_MAGE49), + sSFX(0, "Sfx\\Sorceror\\Mage50.wav", PS_MAGE50), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage51.wav", PS_MAGE51), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage52.wav", PS_MAGE52), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage53.wav", PS_MAGE53), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage54.wav", PS_MAGE54), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage55.wav", PS_MAGE55), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage56.wav", PS_MAGE56), + sSFX(0, "Sfx\\Sorceror\\Mage57.wav", PS_MAGE57), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage58.wav", PS_MAGE58), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage59.wav", PS_MAGE59), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage60.wav", PS_MAGE60), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage61.wav", PS_MAGE61), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage62.wav", PS_MAGE62), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage63.wav", PS_MAGE63), + sSFX(0, "Sfx\\Sorceror\\Mage64.wav", PS_MAGE64), + sSFX(0, "Sfx\\Sorceror\\Mage65.wav", PS_MAGE65), + sSFX(0, "Sfx\\Sorceror\\Mage66.wav", PS_MAGE66), + sSFX(0, "Sfx\\Sorceror\\Mage67.wav", PS_MAGE67), + sSFX(0, "Sfx\\Sorceror\\Mage68.wav", PS_MAGE68), + sSFX(0, "Sfx\\Sorceror\\Mage69.wav", PS_MAGE69), + sSFX(0, "Sfx\\Sorceror\\Mage69b.wav", PS_MAGE69B), + sSFX(0, "Sfx\\Sorceror\\Mage70.wav", PS_MAGE70), + sSFX(0, "Sfx\\Sorceror\\Mage71.wav", PS_MAGE71), + sSFX(0, "Sfx\\Sorceror\\Mage72.wav", PS_MAGE72), + sSFX(0, "Sfx\\Sorceror\\Mage73.wav", PS_MAGE73), + sSFX(0, "Sfx\\Sorceror\\Mage74.wav", PS_MAGE74), + sSFX(0, "Sfx\\Sorceror\\Mage75.wav", PS_MAGE75), + sSFX(0, "Sfx\\Sorceror\\Mage76.wav", PS_MAGE76), + sSFX(0, "Sfx\\Sorceror\\Mage77.wav", PS_MAGE77), + sSFX(0, "Sfx\\Sorceror\\Mage78.wav", PS_MAGE78), + sSFX(0, "Sfx\\Sorceror\\Mage79.wav", PS_MAGE79), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage80.wav", PS_MAGE80), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage81.wav", PS_MAGE81), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage82.wav", PS_MAGE82), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage83.wav", PS_MAGE83), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage84.wav", PS_MAGE84), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage85.wav", PS_MAGE85), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage86.wav", PS_MAGE86), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage87.wav", PS_MAGE87), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage88.wav", PS_MAGE88), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage89.wav", PS_MAGE89), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage90.wav", PS_MAGE90), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage91.wav", PS_MAGE91), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage92.wav", PS_MAGE92), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage93.wav", PS_MAGE93), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage94.wav", PS_MAGE94), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage95.wav", PS_MAGE95), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage96.wav", PS_MAGE96), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage97.wav", PS_MAGE97), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage98.wav", PS_MAGE98), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage99.wav", PS_MAGE99), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage100.wav", PS_MAGE100), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage101.wav", PS_MAGE101), + sSFX(sfx_STREAM, "Sfx\\Sorceror\\Mage102.wav", PS_MAGE102), +#endif + + // Rogue +#if !IS_VERSION(SHAREWARE) + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue01.wav", PS_ROGUE1), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue02.wav", PS_ROGUE2), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue03.wav", PS_ROGUE3), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue04.wav", PS_ROGUE4), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue05.wav", PS_ROGUE5), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue06.wav", PS_ROGUE6), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue07.wav", PS_ROGUE7), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue08.wav", PS_ROGUE8), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue09.wav", PS_ROGUE9), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue10.wav", PS_ROGUE10), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue11.wav", PS_ROGUE11), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue12.wav", PS_ROGUE12), + rSFX(0, "Sfx\\Rogue\\Rogue13.wav", PS_ROGUE13), + rSFX(0, "Sfx\\Rogue\\Rogue14.wav", PS_ROGUE14), + rSFX(0, "Sfx\\Rogue\\Rogue15.wav", PS_ROGUE15), + rSFX(0, "Sfx\\Rogue\\Rogue16.wav", PS_ROGUE16), + rSFX(0, "Sfx\\Rogue\\Rogue17.wav", PS_ROGUE17), + rSFX(0, "Sfx\\Rogue\\Rogue18.wav", PS_ROGUE18), + rSFX(0, "Sfx\\Rogue\\Rogue19.wav", PS_ROGUE19), + rSFX(0, "Sfx\\Rogue\\Rogue20.wav", PS_ROGUE20), + rSFX(0, "Sfx\\Rogue\\Rogue21.wav", PS_ROGUE21), + rSFX(0, "Sfx\\Rogue\\Rogue22.wav", PS_ROGUE22), + rSFX(0, "Sfx\\Rogue\\Rogue23.wav", PS_ROGUE23), + rSFX(0, "Sfx\\Rogue\\Rogue24.wav", PS_ROGUE24), + rSFX(0, "Sfx\\Rogue\\Rogue25.wav", PS_ROGUE25), + rSFX(0, "Sfx\\Rogue\\Rogue26.wav", PS_ROGUE26), + rSFX(0, "Sfx\\Rogue\\Rogue27.wav", PS_ROGUE27), + rSFX(0, "Sfx\\Rogue\\Rogue28.wav", PS_ROGUE28), + rSFX(0, "Sfx\\Rogue\\Rogue29.wav", PS_ROGUE29), + rSFX(0, "Sfx\\Rogue\\Rogue30.wav", PS_ROGUE30), + rSFX(0, "Sfx\\Rogue\\Rogue31.wav", PS_ROGUE31), + rSFX(0, "Sfx\\Rogue\\Rogue32.wav", PS_ROGUE32), + rSFX(0, "Sfx\\Rogue\\Rogue33.wav", PS_ROGUE33), + rSFX(0, "Sfx\\Rogue\\Rogue34.wav", PS_ROGUE34), + rSFX(0, "Sfx\\Rogue\\Rogue35.wav", PS_ROGUE35), + rSFX(0, "Sfx\\Rogue\\Rogue36.wav", PS_ROGUE36), + rSFX(0, "Sfx\\Rogue\\Rogue37.wav", PS_ROGUE37), + rSFX(0, "Sfx\\Rogue\\Rogue38.wav", PS_ROGUE38), + rSFX(0, "Sfx\\Rogue\\Rogue39.wav", PS_ROGUE39), + rSFX(0, "Sfx\\Rogue\\Rogue40.wav", PS_ROGUE40), + rSFX(0, "Sfx\\Rogue\\Rogue41.wav", PS_ROGUE41), + rSFX(0, "Sfx\\Rogue\\Rogue42.wav", PS_ROGUE42), + rSFX(0, "Sfx\\Rogue\\Rogue43.wav", PS_ROGUE43), + rSFX(0, "Sfx\\Rogue\\Rogue44.wav", PS_ROGUE44), + rSFX(0, "Sfx\\Rogue\\Rogue45.wav", PS_ROGUE45), + rSFX(0, "Sfx\\Rogue\\Rogue46.wav", PS_ROGUE46), + rSFX(0, "Sfx\\Rogue\\Rogue47.wav", PS_ROGUE47), + rSFX(0, "Sfx\\Rogue\\Rogue48.wav", PS_ROGUE48), + rSFX(0, "Sfx\\Rogue\\Rogue49.wav", PS_ROGUE49), + rSFX(0, "Sfx\\Rogue\\Rogue50.wav", PS_ROGUE50), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue51.wav", PS_ROGUE51), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue52.wav", PS_ROGUE52), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue53.wav", PS_ROGUE53), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue54.wav", PS_ROGUE54), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue55.wav", PS_ROGUE55), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue56.wav", PS_ROGUE56), + rSFX(0, "Sfx\\Rogue\\Rogue57.wav", PS_ROGUE57), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue58.wav", PS_ROGUE58), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue59.wav", PS_ROGUE59), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue60.wav", PS_ROGUE60), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue61.wav", PS_ROGUE61), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue62.wav", PS_ROGUE62), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue63.wav", PS_ROGUE63), + rSFX(0, "Sfx\\Rogue\\Rogue64.wav", PS_ROGUE64), + rSFX(0, "Sfx\\Rogue\\Rogue65.wav", PS_ROGUE65), + rSFX(0, "Sfx\\Rogue\\Rogue66.wav", PS_ROGUE66), + rSFX(0, "Sfx\\Rogue\\Rogue67.wav", PS_ROGUE67), + rSFX(0, "Sfx\\Rogue\\Rogue68.wav", PS_ROGUE68), + rSFX(0, "Sfx\\Rogue\\Rogue69.wav", PS_ROGUE69), + rSFX(0, "Sfx\\Rogue\\Rogue69b.wav", PS_ROGUE69B), + rSFX(0, "Sfx\\Rogue\\Rogue70.wav", PS_ROGUE70), + rSFX(0, "Sfx\\Rogue\\Rogue71.wav", PS_ROGUE71), + rSFX(0, "Sfx\\Rogue\\Rogue72.wav", PS_ROGUE72), + rSFX(0, "Sfx\\Rogue\\Rogue73.wav", PS_ROGUE73), + rSFX(0, "Sfx\\Rogue\\Rogue74.wav", PS_ROGUE74), + rSFX(0, "Sfx\\Rogue\\Rogue75.wav", PS_ROGUE75), + rSFX(0, "Sfx\\Rogue\\Rogue76.wav", PS_ROGUE76), + rSFX(0, "Sfx\\Rogue\\Rogue77.wav", PS_ROGUE77), + rSFX(0, "Sfx\\Rogue\\Rogue78.wav", PS_ROGUE78), + rSFX(0, "Sfx\\Rogue\\Rogue79.wav", PS_ROGUE79), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue80.wav", PS_ROGUE80), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue81.wav", PS_ROGUE81), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue82.wav", PS_ROGUE82), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue83.wav", PS_ROGUE83), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue84.wav", PS_ROGUE84), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue85.wav", PS_ROGUE85), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue86.wav", PS_ROGUE86), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue87.wav", PS_ROGUE87), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue88.wav", PS_ROGUE88), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue89.wav", PS_ROGUE89), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue90.wav", PS_ROGUE90), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue91.wav", PS_ROGUE91), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue92.wav", PS_ROGUE92), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue93.wav", PS_ROGUE93), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue94.wav", PS_ROGUE94), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue95.wav", PS_ROGUE95), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue96.wav", PS_ROGUE96), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue97.wav", PS_ROGUE97), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue98.wav", PS_ROGUE98), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue99.wav", PS_ROGUE99), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue100.wav", PS_ROGUE100), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue101.wav", PS_ROGUE101), + rSFX(sfx_STREAM, "Sfx\\Rogue\\Rogue102.wav", PS_ROGUE102), +#endif + + // Warrior +#if !IS_VERSION(SHAREWARE) + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior01.wav", PS_WARR1), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior02.wav", PS_WARR2), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior03.wav", PS_WARR3), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior04.wav", PS_WARR4), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior05.wav", PS_WARR5), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior06.wav", PS_WARR6), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior07.wav", PS_WARR7), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior08.wav", PS_WARR8), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior09.wav", PS_WARR9), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior10.wav", PS_WARR10), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior11.wav", PS_WARR11), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior12.wav", PS_WARR12), +#endif + wSFX(0, "Sfx\\Warrior\\Warior13.wav", PS_WARR13), + wSFX(0, "Sfx\\Warrior\\Warior14.wav", PS_WARR14), + wSFX(0, "Sfx\\Warrior\\Wario14b.wav", PS_WARR14B), + wSFX(0, "Sfx\\Warrior\\Wario14c.wav", PS_WARR14C), + wSFX(0, "Sfx\\Warrior\\Warior15.wav", PS_WARR15), + wSFX(0, "Sfx\\Warrior\\Wario15b.wav", PS_WARR15B), + wSFX(0, "Sfx\\Warrior\\Wario15c.wav", PS_WARR15C), + wSFX(0, "Sfx\\Warrior\\Warior16.wav", PS_WARR16), + wSFX(0, "Sfx\\Warrior\\Wario16b.wav", PS_WARR16B), + wSFX(0, "Sfx\\Warrior\\Wario16c.wav", PS_WARR16C), + wSFX(0, "Sfx\\Warrior\\Warior17.wav", PS_WARR17), + wSFX(0, "Sfx\\Warrior\\Warior18.wav", PS_WARR18), + wSFX(0, "Sfx\\Warrior\\Warior19.wav", PS_WARR19), + wSFX(0, "Sfx\\Warrior\\Warior20.wav", PS_WARR20), + wSFX(0, "Sfx\\Warrior\\Warior21.wav", PS_WARR21), + wSFX(0, "Sfx\\Warrior\\Warior22.wav", PS_WARR22), + wSFX(0, "Sfx\\Warrior\\Warior23.wav", PS_WARR23), + wSFX(0, "Sfx\\Warrior\\Warior24.wav", PS_WARR24), + wSFX(0, "Sfx\\Warrior\\Warior25.wav", PS_WARR25), + wSFX(0, "Sfx\\Warrior\\Warior26.wav", PS_WARR26), + wSFX(0, "Sfx\\Warrior\\Warior27.wav", PS_WARR27), + wSFX(0, "Sfx\\Warrior\\Warior28.wav", PS_WARR28), + wSFX(0, "Sfx\\Warrior\\Warior29.wav", PS_WARR29), + wSFX(0, "Sfx\\Warrior\\Warior30.wav", PS_WARR30), + wSFX(0, "Sfx\\Warrior\\Warior31.wav", PS_WARR31), + wSFX(0, "Sfx\\Warrior\\Warior32.wav", PS_WARR32), + wSFX(0, "Sfx\\Warrior\\Warior33.wav", PS_WARR33), + wSFX(0, "Sfx\\Warrior\\Warior34.wav", PS_WARR34), + wSFX(0, "Sfx\\Warrior\\Warior35.wav", PS_WARR35), + wSFX(0, "Sfx\\Warrior\\Warior36.wav", PS_WARR36), + wSFX(0, "Sfx\\Warrior\\Warior37.wav", PS_WARR37), + wSFX(0, "Sfx\\Warrior\\Warior38.wav", PS_WARR38), + wSFX(0, "Sfx\\Warrior\\Warior39.wav", PS_WARR39), + wSFX(0, "Sfx\\Warrior\\Warior40.wav", PS_WARR40), + wSFX(0, "Sfx\\Warrior\\Warior41.wav", PS_WARR41), + wSFX(0, "Sfx\\Warrior\\Warior42.wav", PS_WARR42), + wSFX(0, "Sfx\\Warrior\\Warior43.wav", PS_WARR43), + wSFX(0, "Sfx\\Warrior\\Warior44.wav", PS_WARR44), + wSFX(0, "Sfx\\Warrior\\Warior45.wav", PS_WARR45), + wSFX(0, "Sfx\\Warrior\\Warior46.wav", PS_WARR46), + wSFX(0, "Sfx\\Warrior\\Warior47.wav", PS_WARR47), + wSFX(0, "Sfx\\Warrior\\Warior48.wav", PS_WARR48), + wSFX(0, "Sfx\\Warrior\\Warior49.wav", PS_WARR49), + wSFX(0, "Sfx\\Warrior\\Warior50.wav", PS_WARR50), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior51.wav", PS_WARR51), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior52.wav", PS_WARR52), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior53.wav", PS_WARR53), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior54.wav", PS_WARR54), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior55.wav", PS_WARR55), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior56.wav", PS_WARR56), + wSFX(0, "Sfx\\Warrior\\Warior57.wav", PS_WARR57), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior58.wav", PS_WARR58), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior59.wav", PS_WARR59), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior60.wav", PS_WARR60), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior61.wav", PS_WARR61), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior62.wav", PS_WARR62), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior63.wav", PS_WARR63), + wSFX(0, "Sfx\\Warrior\\Warior64.wav", PS_WARR64), + wSFX(0, "Sfx\\Warrior\\Warior65.wav", PS_WARR65), + wSFX(0, "Sfx\\Warrior\\Warior66.wav", PS_WARR66), + wSFX(0, "Sfx\\Warrior\\Warior67.wav", PS_WARR67), + wSFX(0, "Sfx\\Warrior\\Warior68.wav", PS_WARR68), + wSFX(0, "Sfx\\Warrior\\Warior69.wav", PS_WARR69), + wSFX(0, "Sfx\\Warrior\\Wario69b.wav", PS_WARR69B), + wSFX(0, "Sfx\\Warrior\\Warior70.wav", PS_WARR70), + wSFX(0, "Sfx\\Warrior\\Warior71.wav", PS_WARR71), + wSFX(0, "Sfx\\Warrior\\Warior72.wav", PS_WARR72), + wSFX(0, "Sfx\\Warrior\\Warior73.wav", PS_WARR73), + wSFX(0, "Sfx\\Warrior\\Warior74.wav", PS_WARR74), + wSFX(0, "Sfx\\Warrior\\Warior75.wav", PS_WARR75), + wSFX(0, "Sfx\\Warrior\\Warior76.wav", PS_WARR76), + wSFX(0, "Sfx\\Warrior\\Warior77.wav", PS_WARR77), + wSFX(0, "Sfx\\Warrior\\Warior78.wav", PS_WARR78), + wSFX(0, "Sfx\\Warrior\\Warior79.wav", PS_WARR79), +#if !IS_VERSION(SHAREWARE) + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior80.wav", PS_WARR80), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior81.wav", PS_WARR81), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior82.wav", PS_WARR82), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior83.wav", PS_WARR83), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior84.wav", PS_WARR84), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior85.wav", PS_WARR85), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior86.wav", PS_WARR86), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior87.wav", PS_WARR87), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior88.wav", PS_WARR88), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior89.wav", PS_WARR89), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior90.wav", PS_WARR90), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior91.wav", PS_WARR91), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior92.wav", PS_WARR92), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior93.wav", PS_WARR93), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior94.wav", PS_WARR94), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior95.wav", PS_WARR95), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario95b.wav", PS_WARR95B), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario95c.wav", PS_WARR95C), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario95d.wav", PS_WARR95D), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario95e.wav", PS_WARR95E), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario95f.wav", PS_WARR95F), + // unused wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior96.wav", PS_WARR96), +#endif + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario96b.wav", PS_WARR96B), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario97.wav", PS_WARR97), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario98.wav", PS_WARR98), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Warior99.wav", PS_WARR99), +#if !IS_VERSION(SHAREWARE) + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario100.wav", PS_WARR100), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario101.wav", PS_WARR101), + wSFX(sfx_STREAM, "Sfx\\Warrior\\Wario102.wav", PS_WARR102), +#endif + +// Silence "Sfx\\Misc\\blank.wav" + // GWP Fix this: New sounds! + // Monk +#if !IS_VERSION(SHAREWARE) + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk01.wav", PS_MONK1), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK2), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK3), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK4), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK5), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK6), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK7), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk08.wav", PS_MONK8), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk09.wav", PS_MONK9), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk10.wav", PS_MONK10), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk11.wav", PS_MONK11), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk12.wav", PS_MONK12), + mSFX(0, "Sfx\\Monk\\Monk13.wav", PS_MONK13), + mSFX(0, "Sfx\\Monk\\Monk14.wav", PS_MONK14), + mSFX(0, "Sfx\\Monk\\Monk15.wav", PS_MONK15), + mSFX(0, "Sfx\\Monk\\Monk16.wav", PS_MONK16), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK17), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK18), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK19), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK20), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK21), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK22), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK23), + mSFX(0, "Sfx\\Monk\\Monk24.wav", PS_MONK24), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK25), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK26), + mSFX(0, "Sfx\\Monk\\Monk27.wav", PS_MONK27), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK28), + mSFX(0, "Sfx\\Monk\\Monk29.wav", PS_MONK29), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK30), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK31), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK32), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK33), + mSFX(0, "Sfx\\Monk\\Monk34.wav", PS_MONK34), + mSFX(0, "Sfx\\Monk\\Monk35.wav", PS_MONK35), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK36), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK37), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK38), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK39), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK40), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK41), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK42), + mSFX(0, "Sfx\\Monk\\Monk43.wav", PS_MONK43), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK44), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK45), + mSFX(0, "Sfx\\Monk\\Monk46.wav", PS_MONK46), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK47), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK48), + mSFX(0, "Sfx\\Monk\\Monk49.wav", PS_MONK49), + mSFX(0, "Sfx\\Monk\\Monk50.wav", PS_MONK50), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK51), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk52.wav", PS_MONK52), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK53), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk54.wav", PS_MONK54), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk55.wav", PS_MONK55), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk56.wav", PS_MONK56), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK57), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK58), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK59), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK60), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk61.wav", PS_MONK61), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk62.wav", PS_MONK62), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK63), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK64), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK65), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK66), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK67), + mSFX(0, "Sfx\\Monk\\Monk68.wav", PS_MONK68), + mSFX(0, "Sfx\\Monk\\Monk69.wav", PS_MONK69), + mSFX(0, "Sfx\\Monk\\Monk69b.wav", PS_MONK69B), + mSFX(0, "Sfx\\Monk\\Monk70.wav", PS_MONK70), + mSFX(0, "Sfx\\Monk\\Monk71.wav", PS_MONK71), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK72), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK73), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK74), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK75), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK76), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK77), + mSFX(0, "Sfx\\Misc\\blank.wav", PS_MONK78), + mSFX(0, "Sfx\\Monk\\Monk79.wav", PS_MONK79), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk80.wav", PS_MONK80), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK81), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk82.wav", PS_MONK82), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk83.wav", PS_MONK83), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK84), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK85), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK86), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk87.wav", PS_MONK87), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk88.wav", PS_MONK88), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk89.wav", PS_MONK89), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK90), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk91.wav", PS_MONK91), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk92.wav", PS_MONK92), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK93), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk94.wav", PS_MONK94), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk95.wav", PS_MONK95), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk96.wav", PS_MONK96), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk97.wav", PS_MONK97), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk98.wav", PS_MONK98), + mSFX(sfx_STREAM, "Sfx\\Monk\\Monk99.wav", PS_MONK99), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK100), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK101), + mSFX(sfx_STREAM, "Sfx\\Misc\\blank.wav", PS_MONK102), +#endif + + // Narrator +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar01.wav", PS_NAR1), + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar02.wav", PS_NAR2), + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar03.wav", PS_NAR3), + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar04.wav", PS_NAR4), + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar05.wav", PS_NAR5), + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar06.wav", PS_NAR6), + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar07.wav", PS_NAR7), + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar08.wav", PS_NAR8), + SFX(sfx_STREAM, "Sfx\\Narrator\\Nar09.wav", PS_NAR9), + + // Level 16 intro + SFX(sfx_STREAM, "Sfx\\Misc\\Lvl16int.wav", PS_DIABLVLINT), + +#endif + + // unique monster sounds +#if !IS_VERSION(SHAREWARE) + SFX(sfx_STREAM, "Sfx\\Monsters\\Butcher.wav", USFX_CLEAVER), + SFX(sfx_STREAM, "Sfx\\Monsters\\Garbud01.wav", USFX_GARBUD1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Garbud02.wav", USFX_GARBUD2), + SFX(sfx_STREAM, "Sfx\\Monsters\\Garbud03.wav", USFX_GARBUD3), + SFX(sfx_STREAM, "Sfx\\Monsters\\Garbud04.wav", USFX_GARBUD4), + SFX(sfx_STREAM, "Sfx\\Monsters\\Izual01.wav", USFX_IZUAL1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Lach01.wav", USFX_LACH1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Lach02.wav", USFX_LACH2), + SFX(sfx_STREAM, "Sfx\\Monsters\\Lach03.wav", USFX_LACH3), + SFX(sfx_STREAM, "Sfx\\Monsters\\Laz01.wav", USFX_LAZ1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Laz02.wav", USFX_LAZ2), + SFX(sfx_STREAM, "Sfx\\Monsters\\Sking01.wav", USFX_SKING1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Snot01.wav", USFX_SNOT1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Snot02.wav", USFX_SNOT2), + SFX(sfx_STREAM, "Sfx\\Monsters\\Snot03.wav", USFX_SNOT3), + SFX(sfx_STREAM, "Sfx\\Monsters\\Warlrd01.wav", USFX_WARLRD1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Wlock01.wav", USFX_WLOCK1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Zhar01.wav", USFX_ZHAR1), + SFX(sfx_STREAM, "Sfx\\Monsters\\Zhar02.wav", USFX_ZHAR2), + SFX(sfx_STREAM, "Sfx\\Monsters\\DiabloD.wav", USFX_DIABLOD), + +// JKEQUEST Enter new sound cues here + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer1.wav", HSFX_FARMER1), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer2.wav", HSFX_FARMER2), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer2A.wav", HSFX_FARMER2A), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer3.wav", HSFX_FARMER3), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer4.wav", HSFX_FARMER4), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer5.wav", HSFX_FARMER5), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer6.wav", HSFX_FARMER6), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer7.wav", HSFX_FARMER7), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer8.wav", HSFX_FARMER8), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Farmer9.wav", HSFX_FARMER9), + + SFX(sfx_STREAM, "Sfx\\Hellfire\\TEDDYBR1.wav", HSFX_THEO1), + SFX(sfx_STREAM, "Sfx\\Hellfire\\TEDDYBR2.wav", HSFX_THEO2), + SFX(sfx_STREAM, "Sfx\\Hellfire\\TEDDYBR3.wav", HSFX_THEO3), + SFX(sfx_STREAM, "Sfx\\Hellfire\\TEDDYBR4.wav", HSFX_THEO4), + + SFX(sfx_STREAM, "Sfx\\Hellfire\\DEFILER1.wav", HSFX_DEFILER1), + SFX(sfx_STREAM, "Sfx\\Hellfire\\DEFILER2.wav", HSFX_DEFILER2), + SFX(sfx_STREAM, "Sfx\\Hellfire\\DEFILER3.wav", HSFX_DEFILER3), + SFX(sfx_STREAM, "Sfx\\Hellfire\\DEFILER4.wav", HSFX_DEFILER4), + SFX(sfx_STREAM, "Sfx\\Hellfire\\DEFILER8.wav", HSFX_DEFILER5), + SFX(sfx_STREAM, "Sfx\\Hellfire\\DEFILER6.wav", HSFX_DEFILER6), + SFX(sfx_STREAM, "Sfx\\Hellfire\\DEFILER7.wav", HSFX_DEFILER7), + + SFX(sfx_STREAM, "Sfx\\Hellfire\\NAKRUL1.wav", HSFX_NA_KRUL1), + SFX(sfx_STREAM, "Sfx\\Hellfire\\NAKRUL2.wav", HSFX_NA_KRUL2), + SFX(sfx_STREAM, "Sfx\\Hellfire\\NAKRUL3.wav", HSFX_NA_KRUL3), + SFX(sfx_STREAM, "Sfx\\Hellfire\\NAKRUL4.wav", HSFX_NA_KRUL4), + SFX(sfx_STREAM, "Sfx\\Hellfire\\NAKRUL5.wav", HSFX_NA_KRUL5), + SFX(sfx_STREAM, "Sfx\\Hellfire\\NAKRUL6.wav", HSFX_NA_KRUL6), + + SFX(sfx_STREAM, "Sfx\\Hellfire\\NARATR3.wav", HSFX_CORNERSTONE1), + + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT1.wav", HSFX_COWSUIT1), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT2.wav", HSFX_COWSUIT2), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT3.wav", HSFX_COWSUIT3), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT4.wav", HSFX_COWSUIT4), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT4A.wav", HSFX_COWSUIT4A), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT5.wav", HSFX_COWSUIT5), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT6.wav", HSFX_COWSUIT6), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT7.wav", HSFX_COWSUIT7), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT8.wav", HSFX_COWSUIT8), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT9.wav", HSFX_COWSUIT9), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT10.wav", HSFX_COWSUIT10), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT11.wav", HSFX_COWSUIT11), + SFX(sfx_STREAM, "Sfx\\Hellfire\\COWSUT12.wav", HSFX_COWSUIT12), + + SFX(sfx_STREAM, "Sfx\\Hellfire\\Skljrn1.wav", HSFX_SKULLJRNL1), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Naratr6.wav", HSFX_SKULLJRNL2), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Naratr7.wav", HSFX_SKULLJRNL3), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Naratr8.wav", HSFX_SKULLJRNL4), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Naratr5.wav", HSFX_SKULLJRNL5), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Naratr9.wav", HSFX_SKULLJRNL6), + SFX(sfx_STREAM, "Sfx\\Hellfire\\Naratr4.wav", HSFX_SKULLJRNL7), + + SFX(sfx_STREAM, "Sfx\\Hellfire\\TRADER1.wav", HSFX_TRADER1), + + + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Cropen.wav", CR_DOOROPEN), + SFX(sfx_ALLOWMULTIPLE, "Sfx\\Items\\Crclos.wav", CR_DOORCLOS), + + + +#endif +}; + +// Until there are actual sounds, don't hog the memory by loading duplicates. +#if !IS_VERSION(SHAREWARE) +#define PS_BARD1 PS_ROGUE1 +#define PS_BARD2 PS_ROGUE2 +#define PS_BARD3 PS_ROGUE3 +#define PS_BARD4 PS_ROGUE4 +#define PS_BARD5 PS_ROGUE5 +#define PS_BARD6 PS_ROGUE6 +#define PS_BARD7 PS_ROGUE7 +#define PS_BARD8 PS_ROGUE8 +#define PS_BARD9 PS_ROGUE9 +#define PS_BARD10 PS_ROGUE10 +#define PS_BARD11 PS_ROGUE11 +#define PS_BARD12 PS_ROGUE12 +#define PS_BARD13 PS_ROGUE13 +#define PS_BARD14 PS_ROGUE14 +#define PS_BARD15 PS_ROGUE15 +#define PS_BARD16 PS_ROGUE16 +#define PS_BARD17 PS_ROGUE17 +#define PS_BARD18 PS_ROGUE18 +#define PS_BARD19 PS_ROGUE19 +#define PS_BARD20 PS_ROGUE20 +#define PS_BARD21 PS_ROGUE21 +#define PS_BARD22 PS_ROGUE22 +#define PS_BARD23 PS_ROGUE23 +#define PS_BARD24 PS_ROGUE24 +#define PS_BARD25 PS_ROGUE25 +#define PS_BARD26 PS_ROGUE26 +#define PS_BARD27 PS_ROGUE27 +#define PS_BARD28 PS_ROGUE28 +#define PS_BARD29 PS_ROGUE29 +#define PS_BARD30 PS_ROGUE30 +#define PS_BARD31 PS_ROGUE31 +#define PS_BARD32 PS_ROGUE32 +#define PS_BARD33 PS_ROGUE33 +#define PS_BARD34 PS_ROGUE34 +#define PS_BARD35 PS_ROGUE35 +#define PS_BARD36 PS_ROGUE36 +#define PS_BARD37 PS_ROGUE37 +#define PS_BARD38 PS_ROGUE38 +#define PS_BARD39 PS_ROGUE39 +#define PS_BARD40 PS_ROGUE40 +#define PS_BARD41 PS_ROGUE41 +#define PS_BARD42 PS_ROGUE42 +#define PS_BARD43 PS_ROGUE43 +#define PS_BARD44 PS_ROGUE44 +#define PS_BARD45 PS_ROGUE45 +#define PS_BARD46 PS_ROGUE46 +#define PS_BARD47 PS_ROGUE47 +#define PS_BARD48 PS_ROGUE48 +#define PS_BARD49 PS_ROGUE49 +#define PS_BARD50 PS_ROGUE50 +#define PS_BARD51 PS_ROGUE51 +#define PS_BARD52 PS_ROGUE52 +#define PS_BARD53 PS_ROGUE53 +#define PS_BARD54 PS_ROGUE54 +#define PS_BARD55 PS_ROGUE55 +#define PS_BARD56 PS_ROGUE56 +#define PS_BARD57 PS_ROGUE57 +#define PS_BARD58 PS_ROGUE58 +#define PS_BARD59 PS_ROGUE59 +#define PS_BARD60 PS_ROGUE60 +#define PS_BARD61 PS_ROGUE61 +#define PS_BARD62 PS_ROGUE62 +#define PS_BARD63 PS_ROGUE63 +#define PS_BARD64 PS_ROGUE64 +#define PS_BARD65 PS_ROGUE65 +#define PS_BARD66 PS_ROGUE66 +#define PS_BARD67 PS_ROGUE67 +#define PS_BARD68 PS_ROGUE68 +#define PS_BARD69 PS_ROGUE69 +#define PS_BARD69B PS_ROGUE69B +#define PS_BARD70 PS_ROGUE70 +#define PS_BARD71 PS_ROGUE71 +#define PS_BARD72 PS_ROGUE72 +#define PS_BARD73 PS_ROGUE73 +#define PS_BARD74 PS_ROGUE74 +#define PS_BARD75 PS_ROGUE75 +#define PS_BARD76 PS_ROGUE76 +#define PS_BARD77 PS_ROGUE77 +#define PS_BARD78 PS_ROGUE78 +#define PS_BARD79 PS_ROGUE79 +#define PS_BARD80 PS_ROGUE80 +#define PS_BARD81 PS_ROGUE81 +#define PS_BARD82 PS_ROGUE82 +#define PS_BARD83 PS_ROGUE83 +#define PS_BARD84 PS_ROGUE84 +#define PS_BARD85 PS_ROGUE85 +#define PS_BARD86 PS_ROGUE86 +#define PS_BARD87 PS_ROGUE87 +#define PS_BARD88 PS_ROGUE88 +#define PS_BARD89 PS_ROGUE89 +#define PS_BARD90 PS_ROGUE90 +#define PS_BARD91 PS_ROGUE91 +#define PS_BARD92 PS_ROGUE92 +#define PS_BARD93 PS_ROGUE93 +#define PS_BARD94 PS_ROGUE94 +#define PS_BARD95 PS_ROGUE95 +#define PS_BARD96 PS_ROGUE96 +#define PS_BARD97 PS_ROGUE97 +#define PS_BARD98 PS_ROGUE98 +#define PS_BARD99 PS_ROGUE99 +#define PS_BARD100 PS_ROGUE100 +#define PS_BARD101 PS_ROGUE101 +#define PS_BARD102 PS_ROGUE102 + +#define PS_BARBARIAN1 PS_WARR1 +#define PS_BARBARIAN2 PS_WARR2 +#define PS_BARBARIAN3 PS_WARR3 +#define PS_BARBARIAN4 PS_WARR4 +#define PS_BARBARIAN5 PS_WARR5 +#define PS_BARBARIAN6 PS_WARR6 +#define PS_BARBARIAN7 PS_WARR7 +#define PS_BARBARIAN8 PS_WARR8 +#define PS_BARBARIAN9 PS_WARR9 +#define PS_BARBARIAN10 PS_WARR10 +#define PS_BARBARIAN11 PS_WARR11 +#define PS_BARBARIAN12 PS_WARR12 +#define PS_BARBARIAN13 PS_WARR13 +#define PS_BARBARIAN14 PS_WARR14 +#define PS_BARBARIAN15 PS_WARR15 +#define PS_BARBARIAN16 PS_WARR16 +#define PS_BARBARIAN17 PS_WARR17 +#define PS_BARBARIAN18 PS_WARR18 +#define PS_BARBARIAN19 PS_WARR19 +#define PS_BARBARIAN20 PS_WARR20 +#define PS_BARBARIAN21 PS_WARR21 +#define PS_BARBARIAN22 PS_WARR22 +#define PS_BARBARIAN23 PS_WARR23 +#define PS_BARBARIAN24 PS_WARR24 +#define PS_BARBARIAN25 PS_WARR25 +#define PS_BARBARIAN26 PS_WARR26 +#define PS_BARBARIAN27 PS_WARR27 +#define PS_BARBARIAN28 PS_WARR28 +#define PS_BARBARIAN29 PS_WARR29 +#define PS_BARBARIAN30 PS_WARR30 +#define PS_BARBARIAN31 PS_WARR31 +#define PS_BARBARIAN32 PS_WARR32 +#define PS_BARBARIAN33 PS_WARR33 +#define PS_BARBARIAN34 PS_WARR34 +#define PS_BARBARIAN35 PS_WARR35 +#define PS_BARBARIAN36 PS_WARR36 +#define PS_BARBARIAN37 PS_WARR37 +#define PS_BARBARIAN38 PS_WARR38 +#define PS_BARBARIAN39 PS_WARR39 +#define PS_BARBARIAN40 PS_WARR40 +#define PS_BARBARIAN41 PS_WARR41 +#define PS_BARBARIAN42 PS_WARR42 +#define PS_BARBARIAN43 PS_WARR43 +#define PS_BARBARIAN44 PS_WARR44 +#define PS_BARBARIAN45 PS_WARR45 +#define PS_BARBARIAN46 PS_WARR46 +#define PS_BARBARIAN47 PS_WARR47 +#define PS_BARBARIAN48 PS_WARR48 +#define PS_BARBARIAN49 PS_WARR49 +#define PS_BARBARIAN50 PS_WARR50 +#define PS_BARBARIAN51 PS_WARR51 +#define PS_BARBARIAN52 PS_WARR52 +#define PS_BARBARIAN53 PS_WARR53 +#define PS_BARBARIAN54 PS_WARR54 +#define PS_BARBARIAN55 PS_WARR55 +#define PS_BARBARIAN56 PS_WARR56 +#define PS_BARBARIAN57 PS_WARR57 +#define PS_BARBARIAN58 PS_WARR58 +#define PS_BARBARIAN59 PS_WARR59 +#define PS_BARBARIAN60 PS_WARR60 +#define PS_BARBARIAN61 PS_WARR61 +#define PS_BARBARIAN62 PS_WARR62 +#define PS_BARBARIAN63 PS_WARR63 +#define PS_BARBARIAN64 PS_WARR64 +#define PS_BARBARIAN65 PS_WARR65 +#define PS_BARBARIAN66 PS_WARR66 +#define PS_BARBARIAN67 PS_WARR67 +#define PS_BARBARIAN68 PS_WARR68 +#define PS_BARBARIAN69 PS_WARR69 +#define PS_BARBARIAN69B PS_WARR69B +#define PS_BARBARIAN70 PS_WARR70 +#define PS_BARBARIAN71 PS_WARR71 +#define PS_BARBARIAN72 PS_WARR72 +#define PS_BARBARIAN73 PS_WARR73 +#define PS_BARBARIAN74 PS_WARR74 +#define PS_BARBARIAN75 PS_WARR75 +#define PS_BARBARIAN76 PS_WARR76 +#define PS_BARBARIAN77 PS_WARR77 +#define PS_BARBARIAN78 PS_WARR78 +#define PS_BARBARIAN79 PS_WARR79 +#define PS_BARBARIAN80 PS_WARR80 +#define PS_BARBARIAN81 PS_WARR81 +#define PS_BARBARIAN82 PS_WARR82 +#define PS_BARBARIAN83 PS_WARR83 +#define PS_BARBARIAN84 PS_WARR84 +#define PS_BARBARIAN85 PS_WARR85 +#define PS_BARBARIAN86 PS_WARR86 +#define PS_BARBARIAN87 PS_WARR87 +#define PS_BARBARIAN88 PS_WARR88 +#define PS_BARBARIAN89 PS_WARR89 +#define PS_BARBARIAN90 PS_WARR90 +#define PS_BARBARIAN91 PS_WARR91 +#define PS_BARBARIAN92 PS_WARR92 +#define PS_BARBARIAN93 PS_WARR93 +#define PS_BARBARIAN94 PS_WARR94 +#define PS_BARBARIAN95 PS_WARR95 +#define PS_BARBARIAN96 PS_WARR96B +#define PS_BARBARIAN97 PS_WARR97 +#define PS_BARBARIAN98 PS_WARR98 +#define PS_BARBARIAN99 PS_WARR99 +#define PS_BARBARIAN100 PS_WARR100 +#define PS_BARBARIAN101 PS_WARR101 +#define PS_BARBARIAN102 PS_WARR102 + +#endif // SHAREWARE + +#undef SFX +#undef rSFX +#undef wSFX +#undef sSFX +#undef mSFX diff --git a/src/ENCRYPT.CPP b/src/ENCRYPT.CPP new file mode 100644 index 0000000..b1bc388 --- /dev/null +++ b/src/ENCRYPT.CPP @@ -0,0 +1,165 @@ +//****************************************************************** +// ENCRYPT.CPP +// File pack utility +// By Michael O'Brien (6/1/96) && Patrick Wyatt (6/24/96) +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "engine.h" +#include "mpqapi.h" +#include "implode.h" + + +//****************************************************************** +// private +//****************************************************************** + typedef struct _COMPRESSIONINFO { + LPVOID sourcebuffer; + DWORD sourceoffset; + LPVOID destbuffer; + DWORD destoffset; + DWORD bytes; + } COMPRESSIONINFO, *COMPRESSIONPTR; + + static DWORD hashsource[5][256]; + + +//****************************************************************** +//****************************************************************** +void Decrypt(LPDWORD data, DWORD bytes, DWORD key) { + DWORD adjust = 0xEEEEEEEE; + DWORD iter = bytes >> 2; + while (iter--) { + adjust += hashsource[HASH_ENCRYPTDATA][key & 0xFF]; + adjust += (*data++ ^= adjust+key)+(adjust << 5)+3; + key = (key >> 11) | ((key << 21) ^ 0xFFE00000)+0x11111111; + } +} + + +//****************************************************************** +//****************************************************************** +void Encrypt(LPDWORD data, DWORD bytes, DWORD key) { + DWORD adjust = 0xEEEEEEEE; + DWORD iter = bytes >> 2; + while (iter--) { + DWORD origdata = *data; + adjust += hashsource[HASH_ENCRYPTDATA][key & 0xFF]; + *data++ = origdata ^ (adjust+key); + adjust += origdata + (adjust << 5)+3; + key = (key >> 11) | ((key << 21) ^ 0xFFE00000)+0x11111111; + } +} + + +//****************************************************************** +//****************************************************************** +DWORD Hash(const char *filename, int hashtype) { + DWORD result = 0x7FED7FED; + DWORD adjust = 0xEEEEEEEE; + while (filename && *filename) { + char origchar = toupper(*filename++); + result = (result+adjust) ^ hashsource[hashtype][origchar]; + adjust += origchar+result+(adjust << 5)+3; + } + + return result; +} + + +//****************************************************************** +//****************************************************************** +void InitializeHashSource() { + DWORD seed = 0x100001; + for (int loop1 = 0; loop1 < 256; ++loop1) { + for (int loop2 = 0; loop2 < 5; ++loop2) { + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand1 = seed & 0xFFFF; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand2 = seed & 0xFFFF; + hashsource[loop2][loop1] = (rand1 << 16) | rand2; + } + } +} + + +//****************************************************************** +//****************************************************************** +static UINT __cdecl CompBufferRead(LPSTR buffer, UINT *size, LPVOID param) { + COMPRESSIONPTR infoptr = (COMPRESSIONPTR) param; + UINT bytes = min(*size,infoptr->bytes-infoptr->sourceoffset); + CopyMemory(buffer,(LPSTR)infoptr->sourcebuffer+infoptr->sourceoffset,bytes); + infoptr->sourceoffset += bytes; + return bytes; +} + + +//****************************************************************** +//****************************************************************** +static void __cdecl CompBufferWrite(LPSTR buffer, UINT *size, LPVOID param) { + COMPRESSIONPTR infoptr = (COMPRESSIONPTR)param; + CopyMemory((LPSTR)infoptr->destbuffer+infoptr->destoffset,buffer,*size); + infoptr->destoffset += *size; +} + + +//****************************************************************** +//****************************************************************** +DWORD Compress(LPBYTE data, DWORD bytes) { + // ALLOCATE COMPRESSION BUFFERS + LPVOID implodebuffer = DiabloAllocPtrSig(CMP_BUFFER_SIZE,'CMPt'); + LPVOID destbuffer = DiabloAllocPtrSig(max(SECTORSIZE*2,bytes*2),'CMPt'); + + // CREATE AN INFORMATION RECORD + COMPRESSIONINFO info; + info.sourcebuffer = data; + info.sourceoffset = 0; + info.destbuffer = destbuffer; + info.destoffset = 0; + info.bytes = bytes; + + // PERFORM THE COMPRESSION + UINT comptype = CMP_BINARY; + UINT dictsize = max(512,min(4096,SECTORSIZE)); + implode(CompBufferRead,CompBufferWrite,(LPSTR)implodebuffer,&info,&comptype,&dictsize); + + // IF THE DATA WAS NOT COMPRESSABLE, RETURN THE SOURCE DATA + // OTHERWISE, RETURN THE COMPRESSED DATA + if (info.destoffset < bytes) { + CopyMemory(data,destbuffer,info.destoffset); + bytes = info.destoffset; + } + + DiabloFreePtr(implodebuffer); + DiabloFreePtr(destbuffer); + return bytes; +} + + +//****************************************************************** +//****************************************************************** +void Expand(LPBYTE data, DWORD bytes, DWORD dwMaxBytes) { + // ALLOCATE COMPRESSION BUFFERS + LPVOID implodebuffer = DiabloAllocPtrSig(CMP_BUFFER_SIZE,'CMPt'); + LPVOID destbuffer = DiabloAllocPtrSig(dwMaxBytes,'CMPt'); + + // CREATE AN INFORMATION RECORD + COMPRESSIONINFO info; + info.sourcebuffer = data; + info.sourceoffset = 0; + info.destbuffer = destbuffer; + info.destoffset = 0; + info.bytes = bytes; + + // PERFORM THE DECOMPRESSION + explode(CompBufferRead,CompBufferWrite,(LPSTR)implodebuffer,&info); + app_assert(info.destoffset <= dwMaxBytes); + + // copy back into the original buffer + CopyMemory(data,destbuffer,info.destoffset); + + DiabloFreePtr(implodebuffer); + DiabloFreePtr(destbuffer); +} diff --git a/src/ENGINE.CPP b/src/ENGINE.CPP new file mode 100644 index 0000000..cdb76f4 --- /dev/null +++ b/src/ENGINE.CPP @@ -0,0 +1,3500 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Engine file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/ENGINE.CPP 2 1/22/97 2:32p Dgartner $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "resource.h" +#include "storm.h" +#include "engine.h" +#include "lighting.h" +#include "scrollrt.h" +#include "debug.h" +#include "gendung.h" +#include "palette.h" + +//****************************************************************** +// extern +//****************************************************************** +void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine); + + +//****************************************************************** +// Registration info +//****************************************************************** +#include "regconst.h" +char sgszRegSig1[REG_LEN] = "REGISTRATION_BLOCK"; + + +//****************************************************************** +// random numbers +//****************************************************************** + static long sglGameSeed; + + +/*-----------------------------------------------------------------------** +** Decode RLE data without lighting +**-----------------------------------------------------------------------*/ +void DecodeFullCel (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth) +{ + long nBufferW; + app_assert(pDecodeTo != NULL); + app_assert(pRLEBytes != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDecodeTo == NULL || pRLEBytes == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + + __asm { + mov esi,dword ptr [pRLEBytes] // Source + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nWidth] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [lRLECount] + add ebx,esi + +_T1Lp1: mov edx,dword ptr [nWidth] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + mov ecx,eax + shr ecx,1 + jnc _T1w + movsb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + movsw + jecxz _T1x +_T1Lp3: rep movsd +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 + } // end of asm block +} + + +/*-----------------------------------------------------------------------** +** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel +** +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +**-----------------------------------------------------------------------*/ +void DrawCel (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen; + + app_assert(gpBuffer); + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DecodeFullCel (pTo, pFrom, RLELen, nCelW); +} + + +/*-----------------------------------------------------------------------** +** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel +** +** *pBuff = pointer to destination x,y in offscreen buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +**-----------------------------------------------------------------------*/ +void DrawCelP (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW) +{ + BYTE *pFrom; + long RLELen; + + app_assert(pCelBuff != NULL); + app_assert(pBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pCelBuff == NULL || pBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + DecodeFullCel (pBuff, pFrom, RLELen, nCelW); +} + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +**-----------------------------------------------------------------------*/ +void DrawSlabCel (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(gpBuffer); + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + DecodeFullCel(pTo, pFrom, RLELen, nCelW); +} + + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** *pBuff = pointer to destination x,y in offscreen buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +**-----------------------------------------------------------------------*/ +void DrawSlabCelP (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(pCelBuff != NULL); + app_assert(pBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pCelBuff == NULL || pBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + DecodeFullCel(pBuff, pFrom, RLELen, nCelW); +} + + +/*-----------------------------------------------------------------------** +** Decode RLE data with light translation +**-----------------------------------------------------------------------*/ +void DecodeFullCelL (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth) +{ + long nBufferW, nL; + app_assert(pDecodeTo != NULL); + app_assert(pRLEBytes != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDecodeTo == NULL || pRLEBytes == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + + __asm { + mov eax,dword ptr [nLVal]; + shl eax,8 + add eax,dword ptr [pLightTbl]; + mov dword ptr [nL],eax + + mov esi,dword ptr [pRLEBytes] // Source + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nWidth] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [lRLECount] + add ebx,esi + +_T1Lp1: mov edx,dword ptr [nWidth] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + push ebx + mov ebx,dword ptr [nL] + sub edx,eax + mov ecx,eax + + push edx + call xbytes + pop edx + + pop ebx + or edx,edx + jnz _T1Lp2 + jmp _T1Nxt + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 + + jmp _done +xbytes: + + shr cl,1 + jnc xwords + + mov dl, [esi] + mov dl, [ebx+edx] + mov [edi],dl + + add esi,1 + add edi,1 + +xwords: + shr cl,1 + jnc xquads + + mov dl, [esi] + mov ch, [ebx+edx] + + mov [edi],ch + mov dl, [esi+1] + + mov ch, [ebx+edx] + mov [edi+1],ch + + add esi,2 + add edi,2 + +xquads: + test cl,cl + jz xend + +xnext: + mov eax, [esi] + add esi,4 + + mov dl,al + mov ch,[ebx+edx] + + mov dl,ah + ror eax,16 + mov [edi],ch + + mov ch,[ebx+edx] + + mov dl,al + mov [edi+1],ch + + mov ch,[ebx+edx] + + mov dl,ah + mov [edi+2],ch + + mov ch,[ebx+edx] + mov [edi+3],ch + + add edi,4 + + dec cl + jnz xnext + +xend: + ret + +_done: + } // end of asm block +} + +/*-----------------------------------------------------------------------** +** Decode RLE data with light translation and transparency +**-----------------------------------------------------------------------*/ +void TDecodeFullCelL (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth) +{ + long nBufferW, nL, LineVal; + app_assert(pDecodeTo != NULL); + app_assert(pRLEBytes != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDecodeTo == NULL || pRLEBytes == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + + __asm { + mov eax,dword ptr [nLVal]; + shl eax,8 + add eax,dword ptr [pLightTbl]; + mov dword ptr [nL],eax + + mov esi,dword ptr [pRLEBytes] // Source + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nWidth] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [lRLECount] + add ebx,esi + + mov eax,edi + and eax,1 + mov dword ptr [LineVal],eax + +_T1Lp1: mov edx,dword ptr [nWidth] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + push ebx + mov ebx,dword ptr [nL] + sub edx,eax + mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [LineVal] + jnz _T1Od + shr ecx,1 + jnc _T1w + inc esi + inc edi + jecxz _T1x + jmp _T1w2 +_T1w: shr ecx,1 + jnc _T1Lp3 + inc esi + inc edi + lodsb + xlatb + stosb + jecxz _T1x +_T1Lp3: lodsd + inc edi + ror eax,8 + xlatb + stosb + ror eax,16 + inc edi + xlatb + stosb + loop _T1Lp3 + jmp _T1x + +_T1Od: shr ecx,1 + jnc _T1w2 + lodsb + xlatb + stosb + jecxz _T1x + jmp _T1w +_T1w2: shr ecx,1 + jnc _T1Lp4 + lodsb + xlatb + stosb + inc esi + inc edi + jecxz _T1x +_T1Lp4: lodsd + xlatb + stosb + inc edi + ror eax,16 + xlatb + stosb + inc edi + loop _T1Lp4 + +_T1x: pop ebx + or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + mov eax,dword ptr [LineVal] + inc eax + and eax,1 + mov dword ptr [LineVal],eax + cmp ebx,esi + jnz _T1Lp1 + } // end of asm block +} + +/*-----------------------------------------------------------------------** +** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel +** +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void DrawCelL (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen; + + app_assert(gpBuffer); + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + pTo = gpBuffer + nBuffWTbl[yp] + xp; + if (nLVal) + DecodeFullCelL (pTo, pFrom, RLELen, nCelW); + else + DecodeFullCel (pTo, pFrom, RLELen, nCelW); +} + + +/*-----------------------------------------------------------------------** +** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel +** +** *pBuff = pointer to destination x,y in offscreen buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +/* +void DrawCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW) +{ + BYTE *pFrom; + long RLELen; + + app_assert(pCelBuff != NULL); + app_assert(pBuff != NULL); + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + if (nLVal) + DecodeFullCelL (pBuff, pFrom, RLELen, nCelW); + else + DecodeFullCel (pBuff, pFrom, RLELen, nCelW); +} +*/ + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void DrawSlabCelL (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(gpBuffer); + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + if (nLVal) + DecodeFullCelL (pTo, pFrom, RLELen, nCelW); + else + DecodeFullCel (pTo, pFrom, RLELen, nCelW); +} + + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** *pBuff = pointer to destination x,y in offscreen buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +/* +void DrawSlabCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(pCelBuff != NULL); + app_assert(pBuff != NULL); + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + if (nLVal) + DecodeFullCelL (pBuff, pFrom, RLELen, nCelW); + else + DecodeFullCel (pBuff, pFrom, RLELen, nCelW); +} +*/ + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. with transparency +** +** *pBuff = pointer to destination x,y in offscreen buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void TDrawSlabCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(pCelBuff != NULL); + app_assert(pBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pCelBuff == NULL || pBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + if (nTrans) + TDecodeFullCelL (pBuff, pFrom, RLELen, nCelW); + else if (nLVal) + DecodeFullCelL (pBuff, pFrom, RLELen, nCelW); + else + DecodeFullCel (pBuff, pFrom, RLELen, nCelW); +} + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. With infared vision +** +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void DrawSlabCelI (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen, offval, offval2; + long nBufferW, nL, ltaboff; + + app_assert(gpBuffer); + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + ltaboff = light4flag ? 1024 : 4096; + if (loff == LIGHT_STONE) + ltaboff += 256; + if (loff >= LIGHT_U) + ltaboff += ((loff - LIGHT_U) << 8) + 768; + __asm { + mov eax,dword ptr [pLightTbl] + add eax,dword ptr [ltaboff] + mov dword ptr [nL],eax + + mov esi,dword ptr [pFrom] // Source + mov edi,dword ptr [pTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nCelW] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [RLELen] + add ebx,esi +_T1Lp1: + mov edx,dword ptr [nCelW] +_T1Lp2: + xor eax,eax // Load control byte + mov al,[esi] + inc esi + test al,al + js _T1J + + push ebx + mov ebx,dword ptr [nL] + sub edx,eax + mov ecx,eax +Bytes: + mov al,[esi] + inc esi + mov al,[ebx+eax] + mov [edi],al + dec ecx + lea edi,[edi+1] + jnz Bytes + + pop ebx + test edx,edx + jz _T1Nxt + jmp _T1Lp2 +_T1J: + neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: + sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 + } // end of asm block +} + + +/*-----------------------------------------------------------------------** +** Decode RLE data without lighting, with clipping +**-----------------------------------------------------------------------*/ +void CDecodeFullCel (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth) +{ + long nBufferW; + app_assert(pDecodeTo != NULL); + app_assert(pRLEBytes != NULL); + app_assert(gpBuffer); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDecodeTo == NULL || pRLEBytes == NULL || gpBuffer == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + + __asm { + mov esi,dword ptr [pRLEBytes] // Source + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nWidth] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [lRLECount] + add ebx,esi + +_T1Lp1: mov edx,dword ptr [nWidth] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [glClipY] + jb _T1C1 + add esi,eax + add edi,eax + jmp _T1x +_T1C1: mov ecx,eax + shr ecx,1 + jnc _T1w + movsb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + movsw + jecxz _T1x +_T1Lp3: rep movsd +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 + } // end of asm block +} + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +**-----------------------------------------------------------------------*/ +void CDrawSlabCel (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(gpBuffer); + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + CDecodeFullCel(pTo, pFrom, RLELen, nCelW); +} + + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** *pBuff = pointer to destination x,y in offscreen buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +**-----------------------------------------------------------------------*/ +void CDrawSlabCelP (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(pCelBuff != NULL); + app_assert(pBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pCelBuff == NULL || pBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = *(WORD*)(pFrom + oend); + if (oend == 8) + offval2 = 0; + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + CDecodeFullCel (pBuff, pFrom, RLELen, nCelW); +} + +/*-----------------------------------------------------------------------** +** Decode RLE data with light translation and with clipping +**-----------------------------------------------------------------------*/ +void CDecodeFullCelL (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth) +{ + long nBufferW, nL; + app_assert(pDecodeTo != NULL); + app_assert(pRLEBytes != NULL); + + app_assert(gpBuffer); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDecodeTo == NULL || pRLEBytes == NULL || gpBuffer == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + __asm { + mov eax,dword ptr [nLVal]; + shl eax,8 + add eax,dword ptr [pLightTbl]; + mov dword ptr [nL],eax + + mov esi,dword ptr [pRLEBytes] // Source + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nWidth] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [lRLECount] + add ebx,esi + +_T1Lp1: mov edx,dword ptr [nWidth] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + push ebx + mov ebx,dword ptr [nL] + sub edx,eax + cmp edi,dword ptr [glClipY] + jb _T1C1 + add esi,eax + add edi,eax + jmp _T1x +_T1C1: mov ecx,eax + + push edx + call xbytes + pop edx + +_T1x: pop ebx + or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 + + jmp _done + +xbytes: + + shr cl,1 + jnc xwords + + mov dl, [esi] + mov dl, [ebx+edx] + mov [edi],dl + + add esi,1 + add edi,1 + +xwords: + shr cl,1 + jnc xquads + + mov dl, [esi] + mov ch, [ebx+edx] + + mov [edi],ch + mov dl, [esi+1] + + mov ch, [ebx+edx] + mov [edi+1],ch + + add esi,2 + add edi,2 + +xquads: + test cl,cl + jz xend + +xnext: + mov eax, [esi] + add esi,4 + + mov dl,al + mov ch,[ebx+edx] + + mov dl,ah + ror eax,16 + mov [edi],ch + + mov ch,[ebx+edx] + + mov dl,al + mov [edi+1],ch + + mov ch,[ebx+edx] + + mov dl,ah + mov [edi+2],ch + + mov ch,[ebx+edx] + mov [edi+3],ch + + add edi,4 + + dec cl + jnz xnext + +xend: + ret +_done: + } // end of asm block +} + + +/*-----------------------------------------------------------------------** +** Decode RLE data with light translation and with clipping and transparency +**-----------------------------------------------------------------------*/ +void TCDecodeFullCelL (BYTE *pDecodeTo, BYTE *pRLEBytes, long lRLECount, long nWidth) +{ + long nBufferW, nL, LineVal; + app_assert(pDecodeTo != NULL); + app_assert(pRLEBytes != NULL); + + app_assert(gpBuffer); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDecodeTo == NULL || pRLEBytes == NULL || gpBuffer == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + __asm { + mov eax,dword ptr [nLVal]; + shl eax,8 + add eax,dword ptr [pLightTbl]; + mov dword ptr [nL],eax + + mov esi,dword ptr [pRLEBytes] // Source + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nWidth] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [lRLECount] + add ebx,esi + + mov eax,edi + and eax,1 + mov dword ptr [LineVal],eax + +_T1Lp1: mov edx,dword ptr [nWidth] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + push ebx + mov ebx,dword ptr [nL] + sub edx,eax + cmp edi,dword ptr [glClipY] + jb _T1C1 + add esi,eax + add edi,eax + jmp _T1x +_T1C1: mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [LineVal] + jnz _T1Od + shr ecx,1 + jnc _T1w + inc esi + inc edi + jecxz _T1x + jmp _T1w2 +_T1w: shr ecx,1 + jnc _T1Lp3 + inc esi + inc edi + lodsb + xlatb + stosb + jecxz _T1x +_T1Lp3: lodsd + inc edi + ror eax,8 + xlatb + stosb + ror eax,16 + inc edi + xlatb + stosb + loop _T1Lp3 + jmp _T1x + +_T1Od: shr ecx,1 + jnc _T1w2 + lodsb + xlatb + stosb + jecxz _T1x + jmp _T1w +_T1w2: shr ecx,1 + jnc _T1Lp4 + lodsb + xlatb + stosb + inc esi + inc edi + jecxz _T1x +_T1Lp4: lodsd + xlatb + stosb + inc edi + ror eax,16 + xlatb + stosb + inc edi + loop _T1Lp4 + +_T1x: pop ebx + or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + mov eax,dword ptr [LineVal] + inc eax + and eax,1 + mov dword ptr [LineVal],eax + cmp ebx,esi + jnz _T1Lp1 + } // end of asm block +} + + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void CDrawSlabCelL (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(gpBuffer); + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = *(WORD*)(pFrom + oend); + if (oend == 8) + offval2 = 0; + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + if (nLVal) + CDecodeFullCelL(pTo, pFrom, RLELen, nCelW); + else + CDecodeFullCel(pTo, pFrom, RLELen, nCelW); +} + + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** *pBuff = pointer to destination x,y in offscreen buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +/* +void CDrawSlabCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(pCelBuff != NULL); + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = *(WORD*)(pFrom + oend); + if (oend == 8) + offval2 = 0; + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + if (nLVal) + CDecodeFullCelL (pBuff, pFrom, RLELen, nCelW); + else + CDecodeFullCel (pBuff, pFrom, RLELen, nCelW); +} +*/ + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. +** +** *pBuff = pointer to destination x,y in offscreen buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void TCDrawSlabCelPL (BYTE *pBuff, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pFrom; + long RLELen, offval, offval2; + + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = *(WORD*)(pFrom + oend); + if (oend == 8) + offval2 = 0; + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + if (nTrans) + TCDecodeFullCelL (pBuff, pFrom, RLELen, nCelW); + else if (nLVal) + CDecodeFullCelL (pBuff, pFrom, RLELen, nCelW); + else + CDecodeFullCel (pBuff, pFrom, RLELen, nCelW); +} + + +/*-----------------------------------------------------------------------** +** Draws a 5 offset slab cel in a cel file RAM buffer. With infared vision and clipping +** +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void CDrawSlabCelI (long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen, offval, offval2; + long nBufferW, nL, ltaboff; + + app_assert(gpBuffer); + app_assert(pCelBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + pFrom = pCelBuff + *((DWORD*)pCelBuff + nCel); + offval = *(WORD*)(pFrom + ostart); + if (!offval) + return; + RLELen = *((DWORD*)pCelBuff + nCel+1) - *((DWORD*)pCelBuff + nCel); + offval2 = (oend == 8) ? 0 : *(WORD*)(pFrom + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pFrom += offval; + pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + ltaboff = light4flag ? 1024 : 4096; + if (loff == LIGHT_STONE) + ltaboff += 256; + if (loff >= LIGHT_U) + ltaboff += ((loff - LIGHT_U) << 8) + 768; + nL = (long)(pLightTbl + ltaboff); + nBufferW = 768 + nCelW; // Increase width + __asm { + mov esi,[pFrom] // Source + mov edi,[pTo] // Dest + + mov ecx,[RLELen] + add ecx,esi +_T1Lp1: + push ecx + mov edx,[nCelW] + xor ecx,ecx +_T1Lp2: + xor eax,eax // Load control byte + mov al,[esi] + inc esi + test al,al + js _T1J + + mov ebx,[nL] + sub edx,eax + cmp edi,[glClipY] + jb _T1C1 + add esi,eax + add edi,eax + jmp _T1x +_T1C1: + mov cl,[esi] + inc esi + mov cl,[ebx+ecx] + mov [edi],cl + dec eax + lea edi,[edi+1] + jnz _T1C1 +_T1x: + test edx,edx + jz _T1Nxt + jmp _T1Lp2 +_T1J: + neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: + pop ecx + sub edi,dword ptr [nBufferW] + cmp ecx,esi + jnz _T1Lp1 + } // end of asm block +} + + +/*-----------------------------------------------------------------------** +** Draws a NORMAL cel in a cel file RAM buffer. NOTE: non-dungeon 5 offset cel +** +** pBuff = Buffer to draw in +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** nBuffW = Width of the buffer +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +**-----------------------------------------------------------------------*/ +void DrawBuffCel(BYTE *pBuff, long xp, long yp, long nBuffW, BYTE *pCelBuff, long nCel, long nCelW) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen; + app_assert(pCelBuff != NULL); + app_assert(pBuff != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pCelBuff == NULL || pBuff == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + + __asm { + mov ebx,dword ptr [pCelBuff] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] + sub eax,dword ptr [ebx] + mov dword ptr [RLELen],eax + mov eax,dword ptr [pCelBuff] + add eax,dword ptr [ebx] + mov dword ptr [pFrom],eax + } + pTo = pBuff + (nBuffW * yp) + xp; + __asm { + mov esi,dword ptr [pFrom] // Source + mov edi,dword ptr [pTo] // Dest + + mov eax,dword ptr [nBuffW] // Increase width + add eax,dword ptr [nCelW] + mov dword ptr [nBuffW],eax + + mov ebx,dword ptr [RLELen] + add ebx,esi + +_T1Lp1: mov edx,dword ptr [nCelW] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + mov ecx,eax + shr ecx,1 + jnc _T1w + movsb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + movsw + jecxz _T1x +_T1Lp3: rep movsd +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBuffW] + cmp ebx,esi + jnz _T1Lp1 + } // end of asm block +} + + +/*-----------------------------------------------------------------------** +** Makes a mask outline of a 5 offset slab cel in a cel file RAM buffer +** +** ocolor = Color to outline object with +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void OutlineSlabCel(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen, offval, offval2; + long nBufferW; + app_assert(pCelBuff != NULL); + app_assert(gpBuffer); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pCelBuff == NULL || gpBuffer == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + + __asm { + mov ebx,dword ptr [pCelBuff] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] + sub eax,dword ptr [ebx] + mov dword ptr [RLELen],eax + mov edx,dword ptr [pCelBuff] + add edx,dword ptr [ebx] + mov dword ptr [pFrom],edx + add edx,dword ptr [ostart] + xor eax,eax + mov ax,word ptr [edx] + mov dword ptr [offval],eax + mov edx,dword ptr [pFrom] + add edx,dword ptr [oend] + mov ax,word ptr [edx] + mov dword ptr [offval2],eax + } + if (offval != 0) { + if (oend == 8) offval2 = 0; + if (offval2 != 0) RLELen = offval2 - offval; + else RLELen -= offval; + pFrom += offval; + pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + __asm { + mov esi,dword ptr [pFrom] // Source + mov edi,dword ptr [pTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nCelW] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [RLELen] + add ebx,esi + +_T1Lp1: mov edx,dword ptr [nCelW] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + mov ecx,eax + mov ah,byte ptr [ocolor] +_T1Lp3: lodsb + or al,al + jz _T1Skip + mov byte ptr [edi-768],ah + mov byte ptr [edi-1],ah + mov byte ptr [edi+1],ah + mov byte ptr [edi+768],ah +_T1Skip: inc edi + loop _T1Lp3 + or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 + } // end of asm block + } +} + +/*-----------------------------------------------------------------------** +** Makes a mask outline of a 5 offset slab cel in a cel file RAM buffer. With clipping +** +** ocolor = Color to outline object with +** xp = Left X pixel position in offscreen buffer to draw to +** yp = Bottom Y pixel position in offscreen buffer to draw to +** *pCelBuff = pointer to cel file RAM buffer +** nCel = Cel number to draw in cel file (start with 1!!!!) +** nCelW = width of cel to draw +** nLVal = light value +**-----------------------------------------------------------------------*/ +void COutlineSlabCel(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE *pTo; + BYTE *pFrom; + long RLELen, offval, offval2; + long nBufferW; + app_assert(pCelBuff != NULL); + app_assert(gpBuffer); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pCelBuff == NULL || gpBuffer == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + + __asm { + mov ebx,dword ptr [pCelBuff] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] + sub eax,dword ptr [ebx] + mov dword ptr [RLELen],eax + mov edx,dword ptr [pCelBuff] + add edx,dword ptr [ebx] + mov dword ptr [pFrom],edx + add edx,dword ptr [ostart] + xor eax,eax + mov ax,word ptr [edx] + mov dword ptr [offval],eax + mov edx,dword ptr [pFrom] + add edx,dword ptr [oend] + mov ax,word ptr [edx] + mov dword ptr [offval2],eax + } + if (offval != 0) { + if (oend == 8) offval2 = 0; + if (offval2 != 0) RLELen = offval2 - offval; + else RLELen -= offval; + pFrom += offval; + pTo = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + __asm { + mov esi,dword ptr [pFrom] // Source + mov edi,dword ptr [pTo] // Dest + + mov eax,768 // Increase width + add eax,dword ptr [nCelW] + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [RLELen] + add ebx,esi + +_T1Lp1: mov edx,dword ptr [nCelW] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + mov ecx,dword ptr [glClipY] + cmp edi,ecx + jb _T1C1 + add esi,eax + add edi,eax + jmp _T1x +_T1C1: sub ecx,768 + cmp edi,ecx + jae _T1C2 + mov ecx,eax + mov ah,byte ptr [ocolor] +_T1Lp3: lodsb + or al,al + jz _T1Skip + mov byte ptr [edi-768],ah + mov byte ptr [edi-1],ah + mov byte ptr [edi+1],ah + mov byte ptr [edi+768],ah +_T1Skip: inc edi + loop _T1Lp3 + jmp _T1x + +_T1C2: mov ecx,eax + mov ah,byte ptr [ocolor] +_T1Lp4: lodsb + or al,al + jz _T1Skip2 + mov byte ptr [edi-768],ah + mov byte ptr [edi-1],ah + mov byte ptr [edi+1],ah +_T1Skip2: inc edi + loop _T1Lp4 + +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 + } // end of asm block + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +void TranslateCels(byte *p, byte *ttbl, int nf) + +{ + int j; + app_assert(p != NULL); + app_assert(ttbl != NULL); + + for (j = 1; j <= nf; j++) { + __asm { + mov ebx,dword ptr [p] + mov eax,dword ptr [j] + shl eax,2 + add ebx,eax + mov esi,dword ptr [p] + add esi,dword ptr [ebx] + add esi,10 // Source + + mov edx,dword ptr [ebx+4] // Size + sub edx,dword ptr [ebx] + sub edx,10 + + mov edi,esi // Dest + + mov ebx,dword ptr [ttbl] // Color conversion table + +_TLp1: xor eax,eax // Load control byte + lodsb + stosb + dec edx + jz _TNxt + or al,al + js _TLp1 + + sub edx,eax + mov ecx,eax +_TLp2: lodsb + xlatb + stosb + loop _TLp2 + or edx,edx + jnz _TLp1 + +_TNxt: nop + } + } +} +#endif + + +/*-----------------------------------------------------------------------** +** Plot a point +**-----------------------------------------------------------------------*/ +void DrawPoint(int x, int y, byte c) +{ + BYTE *pTo; + + app_assert(gpBuffer); + if ((y < 0) || (y >= 640)) return; + if ((x < 64) || (x >= 704)) return; + pTo = gpBuffer + nBuffWTbl[y] + x; + __asm { + mov edi, dword ptr [pTo]; + cmp edi, dword ptr [glClipY] + jae _NoD + mov al, byte ptr [c] + mov byte ptr [edi], al +_NoD: + } +} + +/*-----------------------------------------------------------------------** +** For line drawing +**-----------------------------------------------------------------------*/ +#define dlswap(a,b) { a^=b; b^=a; a^=b; } +#define absolute(i,j,k) ( (i-j)*(k = ( (i-j)<0 ? -1 : 1))) + +int dlreverse; +byte dlcolor; +BOOL dlclipflag; + + +/*-----------------------------------------------------------------------** +** plot for line drawing (temp probably, will write in asm) +**-----------------------------------------------------------------------*/ +void plot(int x, int y) +{ + BYTE *pTo; + + app_assert(gpBuffer); + if (dlreverse) { + if (dlclipflag) { + if ((x < 0) || (x >= 640)) return; + if ((y < 64) || (y >= 704)) return; + } + pTo = gpBuffer + nBuffWTbl[x] + y; + } else { + if (dlclipflag) { + if ((y < 0) || (y >= 640)) return; + if ((x < 64) || (x >= 704)) return; + } + pTo = gpBuffer + nBuffWTbl[y] + x; + } + __asm { + mov edi, dword ptr [pTo]; + cmp edi,dword ptr [glClipY] + jae _NoD + mov al,byte ptr [dlcolor] + mov byte ptr [edi],al +_NoD: + } +} + + +/*-----------------------------------------------------------------------** +** line drawing ctrl (temp probably, will write in asm) +**-----------------------------------------------------------------------*/ +void DrawLine(int a1, int b1, int a2, int b2, byte clr) +{ + int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left; + int x1, y1; + int sign_x, sign_y, step, i; + + dlcolor = clr; + + // Test clipping bounds to see if we even need to test on the pixel level + dlclipflag = FALSE; + if ((a1 < 64) || (a1 >= 704)) dlclipflag = TRUE; + if ((a2 < 64) || (a2 >= 704)) dlclipflag = TRUE; + if ((b1 < 160) || (b1 >= 512)) dlclipflag = TRUE; + if ((b2 < 160) || (b2 >= 512)) dlclipflag = TRUE; + + dx = absolute(a2, a1, sign_x); + dy = absolute(b2, b1, sign_y); + + if (sign_x == sign_y) + step = 1; + else + step = -1; + + if (dy > dx) { + dlswap(a1, b1); + dlswap(a2, b2); + dlswap(dx, dy); + dlreverse = 1; + } else + dlreverse = 0; + + if (a1 > a2) { + x = a2; + y = b2; + x1 = a1; + y1 = b1; + } else { + x = a1; + y = b1; + x1 = a2; + y1 = b2; + } + + xend = (dx - 1) / 4; + pixels_left = (dx - 1) % 4; + + plot(x, y); + plot(x1, y1); + incr2 = 4 * dy - 2 * dx; + if (incr2 < 0) { + c = 2 * dy; + incr1 = 2 * c; + D = incr1 - dx; + + for (i = 0; i < xend; i++) { + ++x; + --x1; + if (D < 0) { + plot(x, y); + plot(++x, y); + plot(x1, y1); + plot(--x1, y1); + D += incr1; + } else { + if (D < c) { + plot(x, y); + plot(++x, y += step); + plot(x1, y1); + plot(--x1, y1 -= step); + } else { + plot(x, y += step); + plot(++x, y); + plot(x1, y1 -= step); + plot(--x1, y1); + } + D += incr2; + } + } + + if (pixels_left) { + if (D < 0) { + plot(++x, y); + if (pixels_left > 1) + plot(++x, y); + if (pixels_left > 2) + plot(--x1, y1); + } else { + if (D < c) { + plot(++x, y); + if (pixels_left > 1) + plot(++x, y += step); + if (pixels_left > 2) + plot(--x1, y1); + } else { + plot(++x, y += step); + if (pixels_left > 1) + plot(++x, y); + if (pixels_left > 2) + plot(--x1, y1 -= step); + } + } + } + } else { + c = 2 * (dy - dx); + incr1 = 2 * c; + D = incr1 + dx; + for (i = 0; i < xend; i++) { + ++x; + --x1; + if (D > 0) { + plot(x, y += step); + plot(++x, y += step); + plot(x1, y1 -= step); + plot(--x1, y1 -= step); + D += incr1; + } else { + if (D < c) { + plot(x, y); + plot(++x, y += step); + plot(x1, y1); + plot(--x1, y1 -= step); + } else { + plot(x, y += step); + plot(++x, y); + plot(x1, y1 -= step); + plot(--x1, y1); + } + D += incr2; + } + } + + if (pixels_left) { + if (D > 0) { + plot(++x, y += step); + if (pixels_left > 1) + plot(++x, y += step); + if (pixels_left > 2) + plot(--x1, y1 -= step); + } else { + if (D < c) { + plot(++x, y); + if (pixels_left > 1) + plot(++x, y += step); + if (pixels_left > 2) + plot(--x1, y1); + } else { + plot(++x, y += step); + if (pixels_left > 1) + plot(++x, y); + if (pixels_left > 2) { + if (D > c) + plot(--x1, y1 -= step); + else + plot(--x1, y1); + } + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +int GetDirection(int x1, int y1, int x2, int y2) +{ + int mx, my, md; + + mx = x2-x1; + my = y2-y1; + if (mx >= 0) { + if (my >= 0) { + md = 0; + if ((mx << 1) < my) md = 1; + if ((my << 1) < mx) md = 7; + } else { + md = 6; + my = -my; + if ((mx << 1) < my) md = 5; + if ((my << 1) < mx) md = 7; + } + } else { + if (my >= 0) { + md = 2; + mx = -mx; + if ((mx << 1) < my) md = 1; + if ((my << 1) < mx) md = 3; + } else { + md = 4; + mx = -mx; + my = -my; + if ((mx << 1) < my) md = 5; + if ((my << 1) < mx) md = 3; + } + } + return (md); +} + +int SeedCount; +long orgseed; + +//*************************************************************************** +//*************************************************************************** +void SetRndSeed(long s) { + sglGameSeed = s; + orgseed = s; //debug + SeedCount = 0; +} + +//*************************************************************************** +//*************************************************************************** +long GetRndSeed() { + SeedCount++; + static const DWORD INCREMENT = 1; + static const DWORD MULTIPLIER = 0x015a4e35L; + sglGameSeed = MULTIPLIER * sglGameSeed + INCREMENT; + return abs(sglGameSeed); +} + + +//*************************************************************************** +//*************************************************************************** +long random(byte idx,long v) { + if (v <= 0) return 0; + + // high order bits are more "random" than low order bits + if (v < 0x0ffff) return (GetRndSeed() >> 16) % v; + + return GetRndSeed() % v; +} + + +//****************************************************************** +// memory manager vars +//****************************************************************** +#define TRACK_MEM_BLOCKS 1 // 0 in final +#if DEBUG_MEM +#define DUMP_MEM_BLOCKS 1 // 0 in final +#else +#define DUMP_MEM_BLOCKS 0 // 0 in final +#endif +#ifdef NDEBUG +#undef TRACK_MEM_BLOCKS +#undef DUMP_MEM_BLOCKS +#define TRACK_MEM_BLOCKS 0 +#define DUMP_MEM_BLOCKS 0 +#endif + +#if DEBUG_MEM && TRACK_MEM_BLOCKS +typedef struct TMemType { + struct TMemType * pNext; + DWORD dwSig; + + // current amount of memory allocated with this signature + DWORD dwCurrAmount; + + // maximum amount ever allocated for this signature + DWORD dwMostEver; + + // amount of memory allocated to this signature when the + // program had its maximum memory allocated + DWORD dwAmountAtMax; +} TMemType; + +typedef union TPrintSig { + DWORD dwSig; + char szSig[sizeof(DWORD) + 1]; +} TPrintSig; + +static DWORD sgdwCurrAllocated = 0; +static DWORD sgdwHighestAllocated = 0; +static TMemType * sgpMemTypeHead = NULL; + +typedef struct TMemBlockHdr { + DWORD dwBytes; + DWORD dwSig; + DWORD dwCheck1; + DWORD dwCheck2; +} TMemBlockHdr; +typedef struct TMemBlockFtr { + DWORD dwCheck3; + DWORD dwCheck4; +} TMemBlockFtr; + +#define MEM_CHECK1 0x497208ab +#define MEM_CHECK2 0x127834dc +#define MEM_CHECK3 0x023481a9 +#define MEM_CHECK4 0xfcb87147 + +#endif + +// serialize access to memory manager -- according to Mike O'Brien, +// malloc does not serialize access in all cases in NT 4.0 even +// when using LIBCMT.LIB. Therefore, don't trust *any* memory munger +static CCritSect sgMemCrit; + + +//****************************************************************** +//****************************************************************** +#if DEBUG_MEM && TRACK_MEM_BLOCKS +static const char * sig_to_string(DWORD dwSig,TPrintSig * pSig) { + __asm mov eax, dwSig + __asm bswap eax + __asm mov dwSig, eax + pSig->dwSig = dwSig; + pSig->szSig[sizeof(DWORD)] = 0; + return pSig->szSig; + +} +#endif + + +//****************************************************************** +//****************************************************************** +void mem_cleanup(BOOL bNormalExit) { +#if DEBUG_MEM && TRACK_MEM_BLOCKS + // serialize access to memory manager -- according to Mike O'Brien, + // malloc does not serialize access in all cases in NT 4.0 even + // when using LIBCMT.LIB. Therefore, don't trust *any* memory munger + sgMemCrit.Enter(); + + FILE * f = NULL; + + #if DUMP_MEM_BLOCKS + if (bNormalExit) f = fopen("c:\\memdump.txt","wb"); + #endif + + if (f) { + fprintf( + f, + "sig most ever amount at max at end of game\r\n" + "------------------------------------------------------\r\n" + ); + } + + TMemType * pNext = NULL; + for (TMemType * pType = sgpMemTypeHead; pType; pType = pNext) { + if (f) { + TPrintSig sig; + fprintf( + f, + "%4s 0x%08x 0x%08x %8dk %8d\r\n", + sig_to_string(pType->dwSig,&sig), + pType->dwMostEver, + pType->dwAmountAtMax, + pType->dwAmountAtMax / 1024, + pType->dwCurrAmount + ); + } + + pNext = pType->pNext; + SMemFree(pType,__FILE__,__LINE__); + } + + if (f) { + fprintf( + f, + "------------------------------------------------\r\n" + "max allocated 0x%08x %8dk\r\n", + sgdwHighestAllocated, + sgdwHighestAllocated / 1024 + ); + fclose(f); + } + + sgMemCrit.Leave(); +#endif +} + + +//****************************************************************** +//****************************************************************** +#if DEBUG_MEM && TRACK_MEM_BLOCKS +static TMemType * find_mem_type_by_sig(DWORD dwSig) { + // find existing block with signature + for (TMemType * pType = sgpMemTypeHead; pType; pType = pType->pNext) + if (pType->dwSig == dwSig) return pType; + + // create a new signature block + pType = (TMemType *) SMemAlloc(sizeof(TMemType),__FILE__,__LINE__); + ZeroMemory(pType,sizeof TMemType); + pType->dwSig = dwSig; + + // link to list + pType->pNext = sgpMemTypeHead; + sgpMemTypeHead = pType; + + // return new signature block + return pType; +} +#endif + + +//****************************************************************** +//****************************************************************** +#if DEBUG_MEM && TRACK_MEM_BLOCKS +static void mem_addto_type(TMemType * pType,DWORD dwBytes) { + // fixup memory for this type + pType->dwCurrAmount += dwBytes; + if (pType->dwMostEver < pType->dwCurrAmount) + pType->dwMostEver = pType->dwCurrAmount; + + // fixup memory for all types + sgdwCurrAllocated += dwBytes; + if (sgdwHighestAllocated < sgdwCurrAllocated) { + sgdwHighestAllocated = sgdwCurrAllocated; + for (TMemType * pHigh = sgpMemTypeHead; pHigh; pHigh = pHigh->pNext) + pHigh->dwAmountAtMax = pHigh->dwCurrAmount; + } +} +#endif + + +//****************************************************************** +//****************************************************************** +#if DEBUG_MEM && TRACK_MEM_BLOCKS +static const char * mem_freefrom_type(TMemType * pType,DWORD dwBytes) { + // fixup memory for this type + DWORD dwTemp = pType->dwCurrAmount; + pType->dwCurrAmount -= dwBytes; + if (pType->dwCurrAmount > dwTemp) + return "memory block signature underflow: %s"; + + // fixup global memory indicator + dwTemp = sgdwCurrAllocated; + sgdwCurrAllocated -= dwBytes; + if (sgdwCurrAllocated > dwTemp) + return "memory free underflow"; + + return NULL; +} +#endif + + +//****************************************************************** +//****************************************************************** +#if DEBUG_MEM +void mem_use_sig(DWORD dwSig,DWORD dwBytes) { +#if TRACK_MEM_BLOCKS + TMemType * pType = find_mem_type_by_sig(dwSig); + if (! pType) ErrorDlg(IDD_MEM_ERR,GetLastError(),__FILE__,__LINE__); + + mem_addto_type(pType,dwBytes); +#endif +} + + +//****************************************************************** +//****************************************************************** +void mem_unuse_sig(DWORD dwSig,DWORD dwBytes) { +#if TRACK_MEM_BLOCKS + const char * pszErr_s; + TMemType * pType = find_mem_type_by_sig(dwSig); + if (pType) + pszErr_s = mem_freefrom_type(pType,dwBytes); + else + pszErr_s = "Bad signature unused: %s"; + + TPrintSig sig; + if (pszErr_s) app_fatal(pszErr_s,sig_to_string(dwSig,&sig)); +#endif +} +#endif + + +//****************************************************************** +//****************************************************************** +#if DEBUG_MEM +BYTE * mem_malloc_dbg(DWORD dwBytes,DWORD dwSig,DWORD dwLine,const TCHAR * pszFile) +#else +BYTE * DiabloAllocPtr(DWORD dwBytes) +#endif +{ + // serialize access to memory manager -- according to Mike O'Brien, + // malloc does not serialize access in all cases in NT 4.0 even + // when using LIBCMT.LIB. Therefore, don't trust *any* memory munger + sgMemCrit.Enter(); + + // allocate memory block + #if DEBUG_MEM && TRACK_MEM_BLOCKS + DWORD dwAlloc = dwBytes + sizeof(TMemBlockHdr) + sizeof(TMemBlockFtr); + + BYTE * rv = (BYTE *) SMemAlloc(dwAlloc,pszFile,dwLine); + #elif DEBUG_MEM + BYTE * rv = (BYTE *) SMemAlloc(dwBytes,pszFile,dwLine); + #else + BYTE * rv = (BYTE *) SMemAlloc(dwBytes,__FILE__,__LINE__); + #endif + + #if DEBUG_MEM && TRACK_MEM_BLOCKS + if (rv) { + TMemType * pType = find_mem_type_by_sig(dwSig); + if (pType) { + mem_addto_type(pType,dwBytes); + + TMemBlockHdr * pHdr = (TMemBlockHdr *) rv; + rv += sizeof(TMemBlockHdr); + TMemBlockFtr * pFtr = (TMemBlockFtr *) (rv + dwBytes); + + pHdr->dwSig = dwSig; + pHdr->dwBytes = dwBytes; + pHdr->dwCheck1 = MEM_CHECK1; + pHdr->dwCheck2 = MEM_CHECK2; + + pFtr->dwCheck3 = MEM_CHECK3; + pFtr->dwCheck4 = MEM_CHECK4; + } + else { + SMemFree(rv,__FILE__,__LINE__); + rv = NULL; + } + } + #endif + + sgMemCrit.Leave(); + + #if DEBUG_MEM + if (! rv) ErrorDlg(IDD_MEM_ERR,GetLastError(),pszFile,dwLine); + #else + if (! rv) ErrorDlg(IDD_MEM_ERR,GetLastError(),__FILE__,__LINE__); + #endif + + return rv; +} + + +//****************************************************************** +//****************************************************************** +#if DEBUG_MEM +void mem_free_dbg(void * p,DWORD dwLine,const TCHAR * pszFile) +#else +void mem_free_dbg(void * p) +#endif +{ + if (! p) return; + + // serialize access to memory manager -- according to Mike O'Brien, + // malloc does not serialize access in all cases in NT 4.0 even + // when using LIBCMT.LIB. Therefore, don't trust *any* memory munger + sgMemCrit.Enter(); + + // free memory block +#if DEBUG_MEM && TRACK_MEM_BLOCKS + const char * pszErr_s = NULL; + TMemBlockHdr * pHdr = (TMemBlockHdr *) ((BYTE *) p - sizeof(TMemBlockHdr)); + DWORD dwSig = pHdr->dwSig; // assume signature is valid + if (pHdr->dwCheck1 != MEM_CHECK1 || pHdr->dwCheck2 != MEM_CHECK2) + pszErr_s = "Memory block header corruption: %s"; + else { + // Now change it so if there is duplicate free we'll catch it. + pHdr->dwCheck1 = 0xDEADC0DE; + pHdr->dwCheck2 = 0xDEADC0DE; + } + + if (! pszErr_s) { + TMemBlockFtr * pFtr = (TMemBlockFtr *) ((BYTE *) p + pHdr->dwBytes); + if (pFtr->dwCheck3 != MEM_CHECK3 || pFtr->dwCheck4 != MEM_CHECK4) + pszErr_s = "Memory block footer corruption: %s"; + else { + // Now change it so if there is duplicate free we'll catch it. + pFtr->dwCheck3 = 0xDEADC0DE; + pFtr->dwCheck4 = 0xDEADC0DE; + } + } + if (! pszErr_s) { + TMemType * pType = find_mem_type_by_sig(dwSig); + if (pType) + pszErr_s = mem_freefrom_type(pType,pHdr->dwBytes); + else + pszErr_s = "Attempt to free memory with unknown signature %s"; + } + + p = (void *) pHdr; + SMemFree(p,pszFile,dwLine); +#elif DEBUG_MEM + SMemFree(p,pszFile,dwLine); +#else + SMemFree(p,__FILE__,__LINE__); +#endif + + sgMemCrit.Leave(); + + // display any error which occurred -- outside critical section + #if DEBUG_MEM && TRACK_MEM_BLOCKS + if (pszErr_s) { + TPrintSig sig; + app_fatal(pszErr_s,sig_to_string(dwSig,&sig)); + } + #endif +} + + +//****************************************************************** +//****************************************************************** +#if DEBUG_MEM +BYTE * load_file_dbg(const char * pszName,DWORD * pdwFileLen,DWORD dwSig,DWORD dwLine,const TCHAR * pszFile) +#else +BYTE * LoadFileInMem(const char * pszName,DWORD * pdwFileLen) +#endif +{ + HSFILE hFile; + + #if DEBUG_MEM + if (! pszName) app_fatal("LoadFileInMem: %s:%d",pszFile,dwLine); + #else + app_assert(pszName); + #endif + + patSFileOpenFile(pszName,&hFile); + DWORD dwFileLen = patSFileGetFileSize(hFile,NULL); + if (pdwFileLen) *pdwFileLen = dwFileLen; + if (! dwFileLen) app_fatal("Zero length SFILE:\n%s",pszName); + + #if DEBUG_MEM + BYTE * pbMem = mem_malloc_dbg(dwFileLen,dwSig,dwLine,pszFile); + #else + BYTE * pbMem = DiabloAllocPtr(dwFileLen); + #endif + + patSFileReadFile(hFile,pbMem,dwFileLen); + patSFileCloseFile(hFile); + return pbMem; +} + + +//****************************************************************** +//****************************************************************** +DWORD LoadFileWithMem(const char * pszName,BYTE * pbMem) { + HSFILE hFile; + + app_assert(pszName); + if (! pbMem) app_fatal("LoadFileWithMem(NULL):\n%s",pszName); + + patSFileOpenFile(pszName,&hFile); + DWORD dwFileLen = patSFileGetFileSize(hFile,NULL); + if (! dwFileLen) app_fatal("Zero length SFILE:\n%s",pszName); + patSFileReadFile(hFile,pbMem,dwFileLen); + patSFileCloseFile(hFile); + return dwFileLen; +} + + +//************************************************************* +// RLE Unitdraw Code +//************************************************************* +#if RLE_DRAW + #define MAX_RLE_COPY 65 + static int sgnWidth; //used in both RLEDrawLitUnit f'cns +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void TranslateCels(BYTE *p, BYTE *ttbl, int nFrames) +{ + app_assert(p != NULL); + app_assert(ttbl != NULL); + + int nDataSize; + BYTE * pImage; + char bBlock; + for (int j = 1; j <= nFrames; j++) { + pImage = p + ((DWORD*)p)[j] + sizeof(WORD)*5; + nDataSize = ((DWORD*)p)[j+1] - ((DWORD*)p)[j] - sizeof(WORD)*5; + while (nDataSize) { + bBlock = *pImage++; + nDataSize--; + app_assert(nDataSize >= 0); + //check for skip + if (bBlock >= 0) + continue; + bBlock = -bBlock; + //check for run + if (bBlock > MAX_RLE_COPY) { + bBlock -= MAX_RLE_COPY; + nDataSize--; + app_assert(nDataSize >= 0); + *pImage = ttbl[*pImage++]; + continue; + } + //do copy + nDataSize -= bBlock; + app_assert(nDataSize >= 0); + while (bBlock--) + *pImage = ttbl[*pImage++]; + } + } +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +static void RLEDrawUnit(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth) { + _asm { + //**** Assumes _fastcall convention!! **** + push ebx + push esi + push edi + + //eax - copy/run/skip block size + //ebx - pixels left to draw this line + //ecx - bytes of RLE data left + //edx - scratch + //esi - source RLE data + //edi - destination buffer + + mov esi, edx + mov edi, ecx + + xor eax, eax + mov ebx, [nWidth] + mov ecx, [nDataSize] + +Loop1: + mov al,[esi] + inc esi + dec ecx + + //negative packets are copy/runs, nonnegative are skips + test al,al + jns SkipLoop + + neg al + //packets larger than MAX_RLE_COPY are runs, rest are copies + cmp al,MAX_RLE_COPY + jle Copy + + //get size of run + sub al,MAX_RLE_COPY + dec ecx + + //write out run packet + mov dl,[esi] + inc esi + sub ebx,eax +RunMemset: + mov [edi],dl + dec eax + lea edi,[edi+1] + jnz RunMemset + jmp EOLTest + +Copy: + //write out copy packet + sub ecx,eax + sub ebx,eax +CopyMemcpy: + mov dl,[esi] + inc esi + mov [edi],dl + dec eax + lea edi,[edi+1] + jnz CopyMemcpy + +EOLTest: + //if at end of line, move dst and reset linecounter + test ebx,ebx + jnz NextBlock + mov ebx,[nWidth] + sub edi,BUFFERX + sub edi,ebx + jmp NextBlock + +SkipLoop: + //does skip extend past end of this line? + cmp eax,ebx + jle SingleLineSkip + mov edx,ebx + add edi,ebx + sub eax,ebx + jmp SkipMem +SingleLineSkip: + mov edx,eax + add edi,eax + xor eax,eax +SkipMem: + //if at end of line, move dst and reset linecounter + sub ebx,edx + jnz SkipNotEOL + mov ebx,[nWidth] + sub edi,BUFFERX + sub edi,ebx +SkipNotEOL: + //have we finished off this block? (skips may span multiple lines) + test eax,eax + jnz SkipLoop + +NextBlock: + test ecx,ecx + jnz Loop1 + + pop edi + pop esi + pop ebx + } +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +static void RLEDrawOutline(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth, BYTE bOutLineColor) { + _asm { + //**** Assumes _fastcall convention!! **** + push ebx + push esi + push edi + + //eax - copy/run/skip block size + //ebx - pixels left to draw this line + //ecx - bytes of RLE data left + //dl - outline color + //dh - scratch + //esi - source RLE data + //edi - destination buffer + + mov esi,edx + mov edi,ecx + + xor eax,eax + mov ebx,[nWidth] + xor edx,edx + mov ecx,[nDataSize] + mov dl, [bOutLineColor] + +Loop1: + mov al,[esi] + inc esi + dec ecx + + //negative packets are copy/runs, nonnegative are skips + test al,al + jns SkipLoop + + neg al + //packets larger than MAX_RLE_COPY are runs, rest are copies + cmp al,MAX_RLE_COPY + jle Copy + + //get size of run + sub al,MAX_RLE_COPY + dec ecx + + //no outline for color zero (shadows) + mov dh,[esi] + inc esi + test dh,dh + jz SkipLoop + + //write outline for run packet + mov [edi-1],dl //outline pixel left + sub ebx,eax + mov [edi+eax],dl //and right of run +RunMemset: + mov [edi-BUFFERX],dl //outline above + mov [edi+BUFFERX],dl //and below run + dec eax + lea edi,[edi+1] + jnz RunMemset + jmp EOLCheck + +Copy: + sub ecx,eax + sub ebx,eax +CopyMemcpy: + mov dh,[esi] + inc esi + //don't draw outline for shadow pixels + test dh,dh + jz SkipPixel + + mov [edi-1],dl //outline pixel left + mov [edi+1],dl //and right of copy + mov [edi-BUFFERX],dl //outline above + mov [edi+BUFFERX],dl //and below copy +SkipPixel: + dec eax + lea edi,[edi+1] + jnz CopyMemcpy + +EOLCheck: + //if at end of line, move dst and reset linecounter + test ebx,ebx + jnz NextBlock + mov ebx,[nWidth] + sub edi,BUFFERX + sub edi,ebx + jmp NextBlock + +SkipLoop: + cmp eax,ebx + jle SingleLineSkip + mov edx,ebx + add edi,ebx + sub eax,ebx + jmp SkipMem +SingleLineSkip: + mov edx,eax + add edi,eax + xor eax,eax +SkipMem: + //if at end of line, move dst and reset linecounter + sub ebx,edx + jnz SkipNotEOL + mov ebx,[nWidth] + sub edi,BUFFERX + sub edi,ebx +SkipNotEOL: + //have we finished off this block? + test eax,eax + jnz SkipLoop + mov dl, [bOutLineColor] + +NextBlock: + test ecx,ecx + jnz Loop1 + + pop edi + pop esi + pop ebx + } +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +static void RLEDrawLitUnit(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth, BYTE * pLightTable) { + _asm { + //**** Assumes _fastcall convention!! **** + push ebx + push esi + push edi + + //eax - copy/run/skip block size + //ebx - pixels left to draw this line + //ecx - bytes of RLE data left + //edx - scratch + //ebp - light table pointer + //esi - source RLE data + //edi - destination buffer + + mov esi, edx + mov edi, ecx + + mov ebx, [nWidth] + mov ecx, [nDataSize] + mov edx, [pLightTable] + push ebp + mov [sgnWidth],ebx //cheesy way to avoid using ebp + mov ebp,edx + xor eax,eax + xor edx,edx + +Loop1: + mov al,[esi] + inc esi + dec ecx + + //negative packets are copy/runs, nonnegative are skips + test al,al + jns SkipLoop + + neg al + //packets larger than MAX_RLE_COPY are runs, rest are copies + cmp al,MAX_RLE_COPY + jle Copy + + //get size of run + sub al,MAX_RLE_COPY + dec ecx + + //write run packet + sub ebx,eax + mov dl,[esi] + inc esi + mov dl,[ebp+edx] +RunMemset: + mov [edi],dl + dec eax + lea edi,[edi+1] + jnz RunMemset + jmp EOLCheck + +Copy: + //write copy packet + sub ecx,eax + sub ebx,eax +CopyMemcpy: + mov dl,[esi] + inc esi + mov dl,[ebp+edx] + mov [edi],dl + dec eax + lea edi,[edi+1] + jnz CopyMemcpy + +EOLCheck: + //if at end of line, move dst and reset linecounter + test ebx,ebx + jnz NextBlock + mov ebx,[sgnWidth] + sub edi,BUFFERX + sub edi,ebx + jmp NextBlock + +SkipLoop: + cmp eax,ebx + jle SingleLineSkip + mov edx,ebx + add edi,ebx + sub eax,ebx + jmp SkipMem +SingleLineSkip: + mov edx,eax + add edi,eax + xor eax,eax +SkipMem: + //if at end of line, move dst and reset linecounter + sub ebx,edx + jnz SkipNotEOL + mov ebx,[sgnWidth] + sub edi,BUFFERX + sub edi,ebx +SkipNotEOL: + //have we finished off this block? + test eax,eax + jnz SkipLoop + +NextBlock: + test ecx,ecx + jnz Loop1 + + pop ebp + + pop edi + pop esi + pop ebx + } +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +static void RLEDrawUnitClipped(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth) { + _asm { + //**** Assumes _fastcall convention!! **** + push ebx + push esi + push edi + + //eax - copy/run/skip block size + //ebx - pixels left to draw this line + //ecx - bytes of RLE data left + //edx - scratch + //esi - source RLE data + //edi - destination buffer + + mov esi, edx + mov edi, ecx + + xor eax, eax + mov ebx, [nWidth] + mov ecx, [nDataSize] + +Loop1: + mov al,[esi] + inc esi + dec ecx + + //negative packets are copy/runs, nonnegative are skips + test al,al + jns SkipLoop + + neg al + //packets larger than MAX_RLE_COPY are runs, rest are copies + cmp al,MAX_RLE_COPY + jle Copy + + //get size of run + sub al,MAX_RLE_COPY + dec ecx + + //prepare to write out run packet + mov dl,[esi] + inc esi + + //off end of buffer? + cmp edi,[glClipY] + jge SkipLoop + + sub ebx,eax +RunMemset: + mov [edi],dl + dec eax + lea edi,[edi+1] + jnz RunMemset + jmp EOLTest + +Copy: + //prepare to write out copy packet + sub ecx,eax + + //off end of buffer? + cmp edi,[glClipY] + jl PreCopyMemcpy + add esi,eax + jmp SkipLoop + +PreCopyMemcpy: + sub ebx,eax +CopyMemcpy: + mov dl,[esi] + inc esi + mov [edi],dl + dec eax + lea edi,[edi+1] + jnz CopyMemcpy + +EOLTest: + //if at end of line, move dst and reset linecounter + test ebx,ebx + jnz NextBlock + mov ebx,[nWidth] + sub edi,BUFFERX + sub edi,ebx + jmp NextBlock + +SkipLoop: + //does skip extend past end of this line? + cmp eax,ebx + jle SingleLineSkip + mov edx,ebx + add edi,ebx + sub eax,ebx + jmp SkipMem +SingleLineSkip: + mov edx,eax + add edi,eax + xor eax,eax +SkipMem: + //if at end of line, move dst and reset linecounter + sub ebx,edx + jnz SkipNotEOL + mov ebx,[nWidth] + sub edi,BUFFERX + sub edi,ebx +SkipNotEOL: + //have we finished off this block? (skips may span multiple lines) + test eax,eax + jnz SkipLoop + +NextBlock: + test ecx,ecx + jnz Loop1 + + pop edi + pop esi + pop ebx + } +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +static void RLEDrawOutlineClipped(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth, BYTE bOutLineColor) { + _asm { + //**** Assumes _fastcall convention!! **** + push ebx + push esi + push edi + + //eax - copy/run/skip block size + //ebx - pixels left to draw this line + //ecx - bytes of RLE data left + //dl - outline color + //dh - scratch + //esi - source RLE data + //edi - destination buffer + + mov esi,edx + mov edi,ecx + + xor eax,eax + mov ebx,[nWidth] + xor edx,edx + mov ecx,[nDataSize] + mov dl, [bOutLineColor] + +Loop1: + mov al,[esi] + inc esi + dec ecx + + //negative packets are copy/runs, nonnegative are skips + test al,al + jns SkipLoop + + neg al + //packets larger than MAX_RLE_COPY are runs, rest are copies + cmp al,MAX_RLE_COPY + jle Copy + + //get size of run + sub al,MAX_RLE_COPY + dec ecx + + //no outline for color zero (shadows) + mov dh,[esi] + inc esi + test dh,dh + jz SkipLoop + + //off end of buffer? + cmp edi,[glClipY] + jge SkipLoop + + //write outline for run packet + mov [edi-1],dl //outline pixel left + sub ebx,eax + mov [edi+eax],dl //and right of run +RunMemset: + mov [edi-BUFFERX],dl //outline above + mov [edi+BUFFERX],dl //and below run + dec eax + lea edi,[edi+1] + jnz RunMemset + jmp EOLCheck + +Copy: + sub ecx,eax + + //off end of buffer? + cmp edi,[glClipY] + jl PreCopyMemcpy + add esi,eax + jmp SkipLoop + +PreCopyMemcpy: + sub ebx,eax +CopyMemcpy: + mov dh,[esi] + inc esi + //don't draw outline for shadow pixels + test dh,dh + jz SkipPixel + + mov [edi-1],dl //outline pixel left + mov [edi+1],dl //and right of copy + mov [edi-BUFFERX],dl //outline above + mov [edi+BUFFERX],dl //and below copy +SkipPixel: + dec eax + lea edi,[edi+1] + jnz CopyMemcpy + +EOLCheck: + //if at end of line, move dst and reset linecounter + test ebx,ebx + jnz NextBlock + mov ebx,[nWidth] + sub edi,BUFFERX + sub edi,ebx + jmp NextBlock + +SkipLoop: + cmp eax,ebx + jle SingleLineSkip + mov edx,ebx + add edi,ebx + sub eax,ebx + jmp SkipMem +SingleLineSkip: + mov edx,eax + add edi,eax + xor eax,eax +SkipMem: + //if at end of line, move dst and reset linecounter + sub ebx,edx + jnz SkipNotEOL + mov ebx,[nWidth] + sub edi,BUFFERX + sub edi,ebx +SkipNotEOL: + //have we finished off this block? + test eax,eax + jnz SkipLoop + mov dl, [bOutLineColor] + +NextBlock: + test ecx,ecx + jnz Loop1 + + pop edi + pop esi + pop ebx + } +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +static void RLEDrawLitUnitClipped(BYTE * pDst, BYTE * pRLEData, int nDataSize, int nWidth, BYTE * pLightTable) { + _asm { + //**** Assumes _fastcall convention!! **** + push ebx + push esi + push edi + + //eax - copy/run/skip block size + //ebx - pixels left to draw this line + //ecx - bytes of RLE data left + //edx - scratch + //ebp - light table pointer + //esi - source RLE data + //edi - destination buffer + + mov esi, edx + mov edi, ecx + + mov ebx, [nWidth] + mov ecx, [nDataSize] + mov edx, [pLightTable] + push ebp + mov [sgnWidth],ebx //cheesy way to avoid using ebp + mov ebp,edx + xor eax,eax + xor edx,edx + +Loop1: + mov al,[esi] + inc esi + dec ecx + + //negative packets are copy/runs, nonnegative are skips + test al,al + jns SkipLoop + + neg al + //packets larger than MAX_RLE_COPY are runs, rest are copies + cmp al,MAX_RLE_COPY + jle Copy + + //get size of run + sub al,MAX_RLE_COPY + dec ecx + + //prepare to write run packet + mov dl,[esi] + inc esi + mov dl,[ebp+edx] + + //off end of buffer? + cmp edi,[glClipY] + jge SkipLoop + + sub ebx,eax +RunMemset: + mov [edi],dl + dec eax + lea edi,[edi+1] + jnz RunMemset + jmp EOLCheck + +Copy: + //write copy packet + sub ecx,eax + + //off end of buffer? + cmp edi,[glClipY] + jl PreCopyMemcpy + add esi,eax + jmp SkipLoop + +PreCopyMemcpy: + sub ebx,eax +CopyMemcpy: + mov dl,[esi] + inc esi + mov dl,[ebp+edx] + mov [edi],dl + dec eax + lea edi,[edi+1] + jnz CopyMemcpy + +EOLCheck: + //if at end of line, move dst and reset linecounter + test ebx,ebx + jnz NextBlock + mov ebx,[sgnWidth] + sub edi,BUFFERX + sub edi,ebx + jmp NextBlock + +SkipLoop: + cmp eax,ebx + jle SingleLineSkip + mov edx,ebx + add edi,ebx + sub eax,ebx + jmp SkipMem +SingleLineSkip: + mov edx,eax + add edi,eax + xor eax,eax +SkipMem: + //if at end of line, move dst and reset linecounter + sub ebx,edx + jnz SkipNotEOL + mov ebx,[sgnWidth] + sub edi,BUFFERX + sub edi,ebx +SkipNotEOL: + //have we finished off this block? + test eax,eax + jnz SkipLoop + +NextBlock: + test ecx,ecx + jnz Loop1 + + pop ebp + + pop edi + pop esi + pop ebx + } +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawUnit (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend) +{ + BYTE *pDst, *pSrc; + DWORD * pFrameTable; + long RLELen, nFrameStart, nFrameEnd; + + app_assert(gpBuffer != NULL); + app_assert(pCelBuff != NULL); + app_assert(nCel > 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + // jcm.patch1.end.1/14/97 + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int) pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + nFrameStart = *(WORD*)(pSrc + ostart); + if (!nFrameStart) + return; + nFrameEnd = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (nFrameEnd ? nFrameEnd : pFrameTable[nCel+1] - pFrameTable[nCel]) - nFrameStart; + pSrc += nFrameStart; + pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp; + RLEDrawUnit(pDst, pSrc, RLELen, nCelW); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawUnitOutline(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE * pDst, * pSrc; + DWORD * pFrameTable; + long RLELen, offval, offval2; + + app_assert(pCelBuff != NULL); + app_assert(gpBuffer != NULL); + app_assert(nCel > 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + // jcm.patch1.end.1/14/97 + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int) pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp; + RLEDrawOutline(pDst,pSrc,RLELen,nCelW,ocolor); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawInfraUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff) +{ + BYTE * pDst, * pSrc; + DWORD * pFrameTable; + long RLELen, offval, offval2, ltaboff; + + app_assert(gpBuffer != NULL); + app_assert(pCelBuff != NULL); + app_assert(nCel > 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + // jcm.patch1.end.1/14/97 + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int) pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp; + ltaboff = light4flag ? 1024 : 4096; + if (loff == LIGHT_STONE) + ltaboff += 256; + if (loff >= LIGHT_U) + ltaboff += ((loff - LIGHT_U) << 8) + 768; + RLEDrawLitUnit(pDst,pSrc,RLELen,nCelW,pLightTbl+ltaboff); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawLitUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE * pDst, * pSrc; + DWORD * pFrameTable; + long RLELen, offval, offval2; + + app_assert(gpBuffer != NULL); + app_assert(pCelBuff != NULL); + app_assert(nCel > 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + // jcm.patch1.end.1/14/97 + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int) pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp; + if (nLVal) + RLEDrawLitUnit(pDst,pSrc,RLELen,nCelW,pLightTbl + (nLVal << 8)); + else + RLEDrawUnit(pDst,pSrc,RLELen,nCelW); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawUnitClipped (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend) +{ + BYTE * pDst, * pSrc; + DWORD * pFrameTable; + long RLELen, offval, offval2; + + app_assert(gpBuffer != NULL); + app_assert(pCelBuff != NULL); + app_assert(nCel > 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + // jcm.patch1.end.1/14/97 + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int) pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp; + RLEDrawUnitClipped(pDst, pSrc, RLELen, nCelW); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawUnitOutlineClipped(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE * pDst, * pSrc; + DWORD * pFrameTable; + long RLELen, offval, offval2; + + app_assert(pCelBuff != NULL); + app_assert(gpBuffer != NULL); + app_assert(nCel > 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + // jcm.patch1.end.1/14/97 + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int) pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp; + glClipY -= BUFFERX; + RLEDrawOutlineClipped(pDst,pSrc,RLELen,nCelW,ocolor); + glClipY += BUFFERX; +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawInfraUnitClipped( + long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff) +{ + BYTE * pDst, * pSrc; + DWORD * pFrameTable; + long RLELen, offval, offval2, ltaboff; + + app_assert(gpBuffer != NULL); + app_assert(pCelBuff != NULL); + app_assert(nCel > 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + // jcm.patch1.end.1/14/97 + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int) pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - ostart*16] + xp; + ltaboff = light4flag ? 1024 : 4096; + if (loff == LIGHT_STONE) + ltaboff += 256; + if (loff >= LIGHT_U) + ltaboff += ((loff - LIGHT_U) << 8) + 768; + RLEDrawLitUnitClipped(pDst,pSrc,RLELen,nCelW,pLightTbl + ltaboff); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawLitUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + BYTE * pDst, * pSrc; + DWORD * pFrameTable; + long RLELen, offval, offval2; + + app_assert(gpBuffer != NULL); + app_assert(pCelBuff != NULL); + app_assert(nCel > 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + // jcm.patch1.end.1/14/97 + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int) pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel+1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - (ostart << 4)] + xp; + if (nLVal) + RLEDrawLitUnitClipped(pDst,pSrc,RLELen,nCelW,pLightTbl + (nLVal << 8)); + else + RLEDrawUnitClipped(pDst,pSrc,RLELen,nCelW); +} +#endif + + +//************************************************************************* +//************************************************************************* +void play_movie(const char * pszMovie,BOOL bAllowCancel); +void PlayInGameMovie(const char * pszMovie) { + PaletteFadeOut(FADE_FAST); + play_movie(pszMovie,FALSE); + ClrDraw(); + force_redraw = FULLDRAW; + FullBlit(TRUE); + PaletteFadeIn(FADE_FAST); + force_redraw = FULLDRAW; +} diff --git a/src/ENGINE.H b/src/ENGINE.H new file mode 100644 index 0000000..aa08fda --- /dev/null +++ b/src/ENGINE.H @@ -0,0 +1,142 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/ENGINE.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +void DrawCel (long, long, BYTE *, long, long); +void DrawCelP (BYTE *, BYTE *, long, long); +void DrawSlabCel (long, long, BYTE *, long, long, long, long); +void DrawSlabCelP (BYTE *, BYTE *, long, long, long, long); + +void DrawCelL (long, long, BYTE *, long, long); +void DrawCelPL (BYTE *, BYTE *, long, long); +void DrawSlabCelL (long, long, BYTE *, long, long, long, long); +void DrawSlabCelPL (BYTE *, BYTE *, long, long, long, long); +void TDrawSlabCelPL (BYTE *, BYTE *, long, long, long, long); + +void CDrawSlabCel (long, long, BYTE *, long, long, long, long); +void CDrawSlabCelP (BYTE *, BYTE *, long, long, long, long); +void CDrawSlabCelL (long, long, BYTE *, long, long, long, long); +void CDrawSlabCelPL (BYTE *, BYTE *, long, long, long, long); +void TCDrawSlabCelPL (BYTE *, BYTE *, long, long, long, long); + +void DrawSlabCelI(long, long, BYTE *, long, long, long, long, char); +void CDrawSlabCelI(long, long, BYTE *, long, long, long, long, char); + +void OutlineSlabCel(byte, long, long, BYTE *, long, long, long, long); +void COutlineSlabCel(byte, long, long, BYTE *, long, long, long, long); + +void DrawBuffCel(BYTE *, long, long, long, BYTE *, long, long); + +void DecodeFullCel (BYTE *, BYTE *, long, long); +void DecodeFullCelL (BYTE *, BYTE *, long, long); + +void CDecodeFullCel (BYTE *, BYTE *, long, long); +void CDecodeFullCelL (BYTE *, BYTE *, long, long); + +void TranslateCels(byte *, byte *, int); + +int GetDirection(int, int, int, int); + +long GetRndSeed(); +void SetRndSeed(long); +long random(byte, long); + +void DrawLine(int, int, int, int, byte); +void DrawPoint(int, int, byte); + +void PlayInGameMovie(const char * pszMovie); + +//****************************************************************** +// memory management +//****************************************************************** +#define DEBUG_MEM 1 // 0 in final +#ifdef NDEBUG +#undef DEBUG_MEM +#define DEBUG_MEM 0 +#endif + +// public memory management functions +BYTE * DiabloAllocPtr(DWORD dwBytes); +BYTE * DiabloAllocPtrSig(DWORD dwBytes,DWORD dwSig); + +// NOTE: DiabloFreePtr behavior +// +// p MUST be an l-value +// +// if p is NULL: +// no memory is freed +// if p is NOT NULL: +// p is set to NULL before call to free, and then memory is freed +// GUARANTEES p == NULL immediately after DiabloFreePtr is called! +void DiabloFreePtr(void * p); + + +BYTE * LoadFileInMem(const char * pszName, DWORD * pdwFileLen); +BYTE * LoadFileInMemSig(const char * pszName, DWORD * pdwFileLen,DWORD dwSig); +DWORD LoadFileWithMem(const char * pszName, BYTE * pbMem); +void mem_cleanup(BOOL bNormalExit); + + +#if DEBUG_MEM + +// internal functions +void mem_use_sig(DWORD dwSig,DWORD dwBytes); +void mem_unuse_sig(DWORD dwSig,DWORD dwBytes); +BYTE * mem_malloc_dbg(DWORD dwBytes,DWORD dwSig,DWORD dwLine,const TCHAR * pszFile); +void mem_free_dbg(void * p,DWORD dwLine,const TCHAR * pszFile); +BYTE * load_file_dbg(const char * pszName,DWORD * pdwFileLen,DWORD dwSig,DWORD dwLine,const TCHAR * pszFile); + +// definitions of public functions +#define DiabloAllocPtr(dwBytes) mem_malloc_dbg(dwBytes,'NONE',__LINE__,__FILE__) +#define DiabloAllocPtrSig(dwBytes,dwSig) mem_malloc_dbg(dwBytes,dwSig,__LINE__,__FILE__) +#define LoadFileInMem(pszName,pdwFileLen) load_file_dbg(pszName,pdwFileLen,'NONE',__LINE__,__FILE__) +#define LoadFileInMemSig(pszName,pdwFileLen,dwSig) load_file_dbg(pszName,pdwFileLen,dwSig,__LINE__,__FILE__) + +// free function -- set pointer to NULL before real call to free +#define DiabloFreePtr(p) { \ + void * p__p = (void *) (p); \ + (p) = NULL; \ + mem_free_dbg(p__p,__LINE__,__FILE__); \ +} + + +#else + +// internal functions +void mem_free_dbg(void * p); + +// definitions of public functions +#define DiabloAllocPtrSig(dwBytes,dwSig) DiabloAllocPtr(dwBytes) +#define LoadFileInMemSig(pszName,pdwFileLen,dwSig) LoadFileInMem(pszName,pdwFileLen) + +// free function -- set pointer to NULL before real call to free +#define DiabloFreePtr(p) { \ + void * p__p = (void *) (p); \ + (p) = NULL; \ + mem_free_dbg(p__p); \ +} + + +#endif + + +//****************************************************************** +// file manager +//****************************************************************** +#ifdef _STORM_H_ +void patSFileCloseFile(HSFILE handle); +DWORD patSFileGetFileSize(HSFILE handle,LPDWORD filesizehigh = NULL); +BOOL patSFileOpenFile(LPCTSTR filename,HSFILE *handle,BOOL bCanFail = FALSE); +void patSFileReadFile(HSFILE handle,LPVOID buffer,DWORD bytestoread); +DWORD patSFileSetFilePointer(HSFILE handle,LONG distancetomove,PLONG distancetomovehigh,DWORD movemethod); +#endif diff --git a/src/ERROR.CPP b/src/ERROR.CPP new file mode 100644 index 0000000..7e4f22f --- /dev/null +++ b/src/ERROR.CPP @@ -0,0 +1,206 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Control panel file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/ERROR.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "error.h" +#include "engine.h" +#include "control.h" +#include "items.h" +#include "stores.h" +#include "scrollrt.h" + +/*-----------------------------------------------------------------------** +** Message strings +**-----------------------------------------------------------------------*/ + +char *MsgStrings[] = { +"", +"No automap available in town", +"No multiplayer functions in demo", +"Direct Sound Creation Failed", +"Not available in shareware version", +"Not enough space to save", +"No Pause in town", +"Copying to a hard disk is recommended", + +"Multiplayer sync problem", +"No pause in multiplayer", +"Loading...", +"Saving...", + +//Shrine messages +"Some are weakened as one grows strong", //12 Mysterious +"New strength is forged through destruction", //13 Hidden +"Those who defend seldom attack", //14 Gloomy +"The sword of justice is swift and sharp", //15 Weird +"While the spirit is vigilant the body thrives", //16 Magical +"The powers of mana refocused renews", //17 Stone +"Time cannot diminish the power of steel", //18 Religious +"Magic is not always what it seems to be", //19 Enchanted +"What once was opened now is closed", //20 Thaumaturgic +"Intensity comes at the cost of wisdom", //21 Fascinating +"Arcane power brings destruction", //22 Cryptic +"That which cannot be held cannot be harmed", //23 Supernatural +"Crimson and Azure become as the sun", //24 Eldritch +"Knowledge and wisdom at the cost of self", //25 Eerie +"Drink and be refreshed", //26 Divine +"Wherever you go, there you are", //27 Holy +"Energy comes at the cost of wisdom", //28 Sacred +"Riches abound when least expected", //29 Spiritual +"Where avarice fails, patience gains reward", //30 Spooky +"Blessed by a benevolent companion!", //31 Spooky Multi +"The hands of men may be guided by fate", //32 Abandoned +"Strength is bolstered by heavenly faith", //33 Creepy +"The essence of life flows from within", //34 Quiet +"The way is made clear when viewed from above", //35 Secluded +"Salvation comes at the cost of wisdom", //36 Ornate +"Mysteries are revealed in the light of reason", //37 Glimmering +"Those who are last may yet be first", //38 Tainted +"Generosity brings its own rewards", //39 Tainted Multi + +//Shortcut messages +"You must be at least level 8 to use this.", //40 +"You must be at least level 13 to use this.", //41 +"You must be at least level 17 to use this.", //42 +"Arcane knowledge gained!", //43 + +// New Shrines +"That which does not kill you...", //44 Oily +"Knowledge is power.", //45 Glowing +"Give and you shall receive.", //46 Mendicants. +"Some experience is gained by touch.", //47 Edisons +"There's no place like home.", //48 Town +"Spirtual energy is restored.", //49 Energy +"You feel more agile.", //50 Time Morning +"You feel stronger.", //51 Time Afternoon. +"You feel wiser.", //52 Time Evening. +"You feel refreshed.", //53 Time Night. +"That which can break will.", //54 Murphy's +}; + +/*-----------------------------------------------------------------------** +** Local defines +**-----------------------------------------------------------------------*/ + +#define MSGCNT 70 + +char msgflag; +char msgdelay; +char msgtable[80]; +char msgcnt = 0; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitDiabloMsg(char e) +{ + int i; + + for (i = 0; i < msgcnt; i++) { + if (msgtable[i] == e) return; + } + + msgtable[msgcnt] = e; + if (msgcnt < 80) msgcnt++; + msgflag = msgtable[0]; + msgdelay = MSGCNT; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ClrDiabloMsg() +{ + for (int i = 0; i < 80; i++) msgtable[i] = MSG_NONE; + msgflag = MSG_NONE; + msgcnt = 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawDiabloMsg() +{ + int i, x, y; + long boffset; + int sl,tw; + + // Draw error box + DrawCel(165, 318, pSTextSlidCels, 1, 12); + DrawCel(591, 318, pSTextSlidCels, 4, 12); + DrawCel(165, 366, pSTextSlidCels, 2, 12); + DrawCel(591, 366, pSTextSlidCels, 3, 12); + + x = 173; + for (i = 0; i < 35; i++) { + DrawCel(x, 318, pSTextSlidCels, 5, 12); + DrawCel(x, 366, pSTextSlidCels, 7, 12); + x += 12; + } + y = 330; + for (i = 0; i < 3; i++) { + DrawCel(165, y, pSTextSlidCels, 6, 12); + DrawCel(591, y, pSTextSlidCels, 8, 12); + y += 12; + } + + app_assert(gpBuffer); + __asm { + mov edi,dword ptr [gpBuffer] + add edi,278952 + + xor eax,eax + mov edx,27 +_YLp: mov ecx,216 // (width+6)/2 +_XLp1: stosb + inc edi + loop _XLp1 + sub edi,1200 // ((width+6)/2) + 768 + mov ecx,216 // (width+6)/2 +_XLp2: inc edi + stosb + loop _XLp2 + sub edi,1200 // ((width+6)/2) + 768 + dec edx + jnz _YLp + } + + strcpy(tempstr, MsgStrings[msgflag]); + + boffset = nBuffWTbl[342] + 165; + sl = strlen(tempstr); + tw = 0; + for (i = 0; i < sl; i++) { + BYTE c = char2print(tempstr[i]); + c = fonttrans[c]; + tw += fontkern[c]+1; + } + if (tw < 442) boffset += (442 - tw) >> 1; + for (i = 0; i < sl; i++) { + BYTE c = char2print(tempstr[i]); + c = fonttrans[c]; + if (c) DrawPanelFont(boffset, c, ICOLOR_GOLD); + boffset += fontkern[c]+1; + } + + if (msgdelay > 0) msgdelay--; + + if (msgdelay == 0) { + msgcnt--; + msgdelay = MSGCNT; + if (msgcnt == 0) msgflag = MSG_NONE; + else msgflag = msgtable[msgcnt]; + } +} diff --git a/src/ERROR.H b/src/ERROR.H new file mode 100644 index 0000000..3df66d3 --- /dev/null +++ b/src/ERROR.H @@ -0,0 +1,93 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/ERROR.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MSG_NONE 0 +#define MSG_AMAPTWN 1 +#define MSG_MULTIBTN 2 +#define MSG_SOUND 3 +#define MSG_SHAREWARE 4 +#define MSG_SAVESIZE 5 +#define MSG_NOPAUSE 6 +#define MSG_HDRIVE 7 + +#define MSG_SYNC 8 // Multi sync +#define MSG_MULTIPAUSE 9 // No multiplayer pause +#define MSG_LOADGAME 10 +#define MSG_SAVEGAME 11 + +#define SHRINE_1 12 // Mysterious +#define SHRINE_2 13 // Hidden +#define SHRINE_3 14 // Gloomy +#define SHRINE_4 15 // Weird +#define SHRINE_5 16 // Magical +#define SHRINE_6 17 // Stone +#define SHRINE_7 18 // Religious +#define SHRINE_8 19 // Enchanted +#define SHRINE_9 20 // Thaumaturgic +#define SHRINE_10 21 // Fascinating +#define SHRINE_11 22 // Cryptic +#define SHRINE_12 23 // Supernatural +#define SHRINE_13 24 // Eldritch +#define SHRINE_14 25 // Eerie +#define SHRINE_15 26 // Divine +#define SHRINE_16 27 // Holy +#define SHRINE_17 28 // Sacred +#define SHRINE_18 29 // Spiritual +#define SHRINE_19 30 // Spooky +#define SHRINE_19B 31 // Spooky for multiplayer +#define SHRINE_20 32 // Abandoned +#define SHRINE_21 33 // Creepy +#define SHRINE_22 34 // Quiet +#define SHRINE_23 35 // Secluded +#define SHRINE_24 36 // Ornate +#define SHRINE_25 37 // Glimmering +#define SHRINE_26 38 // Tainted +#define SHRINE_26B 39 // Tainted for mulitplayer +#define SHRINE_27 44 // Oily +#define SHRINE_28 45 // Glowing +#define SHRINE_29 46 // Mendicants +#define SHRINE_30 47 // Edisons +#define SHRINE_31 48 // Town +#define SHRINE_32 49 // Energy +#define SHRINE_33A 50 // Time Morning +#define SHRINE_33B 51 // Time Afternoon +#define SHRINE_33C 52 // Time Evening +#define SHRINE_33D 53 // Time Night +#define SHRINE_34 54 // Murphy's + +#define MSG_TRIG1 40 // Shortcut to catacombs +#define MSG_TRIG2 41 // Shortcut to caves +#define MSG_TRIG3 42 // Shortcut to hell + +#define MSG_INBONE 43 // Book with spell in Bone Chamber + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern char msgflag; +extern char msgdelay; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitDiabloMsg(char); +void ClrDiabloMsg(); +void DrawDiabloMsg(); + diff --git a/src/EXCEPT.CPP b/src/EXCEPT.CPP new file mode 100644 index 0000000..f0bf77d --- /dev/null +++ b/src/EXCEPT.CPP @@ -0,0 +1,286 @@ +//****************************************************************** +// except.cpp +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include + + +//****************************************************************** +// private +//****************************************************************** +class CExcept { +public: + CExcept(); + ~CExcept(); + +private: + // entry point where control comes on an unhandled exception + static LONG WINAPI ExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo); + + // variables used by the class + static TCHAR m_szLogFileName[MAX_PATH]; + static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; +}; + +TCHAR CExcept::m_szLogFileName[MAX_PATH]; +LPTOP_LEVEL_EXCEPTION_FILTER CExcept::m_previousFilter; +static CExcept g_CExcept; + + +//****************************************************************** +//****************************************************************** +static void __cdecl tprintf(HANDLE hFile,LPCTSTR pszFmt,...) { + va_list argptr; + DWORD cbWritten; + TCHAR szBuf[1024]; + va_start(argptr,pszFmt); + int nChars = wvsprintf(szBuf,pszFmt,argptr); + WriteFile(hFile,szBuf,nChars * sizeof(TCHAR),&cbWritten,0); + va_end(argptr); +} + + +//****************************************************************** +// Given a linear address,locates the module,section,and offset containing +// that address. +// +// Note: the szModule paramater buffer is an output buffer of length specified +// by the len parameter (in characters!) +//****************************************************************** +static BOOL GetLogicalAddress( + PVOID addr, + PTSTR szModule, + DWORD len, + DWORD *pdwSection, + DWORD *pdwOffset +) { + MEMORY_BASIC_INFORMATION mbi; + if (!VirtualQuery(addr,&mbi,sizeof(mbi))) + return FALSE; + + DWORD hMod = (DWORD)mbi.AllocationBase; + if (!GetModuleFileName((HMODULE)hMod,szModule,len)) + return FALSE; + + // Point to the DOS header in memory + PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; + + // From the DOS header,find the NT (PE) header + PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew); + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr); + DWORD rva = (DWORD)addr - hMod; // RVA is offset from module load address + + // Iterate through the section table,looking for the one that encompasses + // the linear address. + for ( + unsigned i = 0; + i < pNtHdr->FileHeader.NumberOfSections; + i++,pSection++ + ) { + DWORD sectionStart = pSection->VirtualAddress; + DWORD sectionEnd = sectionStart + + max(pSection->SizeOfRawData,pSection->Misc.VirtualSize); + + // Is the address in this section??? + if ((rva >= sectionStart) && (rva <= sectionEnd)) { + // Yes,address is in the section. Calculate section and offset + *pdwSection = i+1; + *pdwOffset = rva - sectionStart; + return TRUE; + } + } + + return FALSE; // Should never get here! +} + + +//****************************************************************** +//****************************************************************** +static void IntelStackWalk(HANDLE hFile,PCONTEXT pContext) { + tprintf(hFile,_T("\r\nCall stack:\r\n")); + tprintf(hFile,_T("Address Frame Logical addr Module\r\n")); + + DWORD pc = pContext->Eip; + PDWORD pFrame,pPrevFrame; + pFrame = (PDWORD)pContext->Ebp; + while (1) { + TCHAR szModule[MAX_PATH] = _T(""); + DWORD section = 0,offset = 0; + + GetLogicalAddress((PVOID)pc,szModule,sizeof(szModule),§ion,&offset); + tprintf(hFile,_T("%08X %08X %04X:%08X %s\r\n"), + pc,pFrame,section,offset,szModule); + + // precede to next higher frame on stack + pc = pFrame[1]; + pPrevFrame = pFrame; + pFrame = (PDWORD)pFrame[0]; + // Frame pointer must be aligned on a DWORD boundary + if ((DWORD)pFrame & 3) break; + if (pFrame <= pPrevFrame) break; + + // Can two DWORDs be read from the supposed frame address? + if (IsBadWritePtr(pFrame,sizeof(PVOID)*2)) break; + } +} + + +//****************************************************************** +//****************************************************************** +static LPTSTR GetExceptionString(DWORD dwCode) { + #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x); + switch (dwCode) { + EXCEPTION(ACCESS_VIOLATION) + EXCEPTION(DATATYPE_MISALIGNMENT) + EXCEPTION(BREAKPOINT) + EXCEPTION(SINGLE_STEP) + EXCEPTION(ARRAY_BOUNDS_EXCEEDED) + EXCEPTION(FLT_DENORMAL_OPERAND) + EXCEPTION(FLT_DIVIDE_BY_ZERO) + EXCEPTION(FLT_INEXACT_RESULT) + EXCEPTION(FLT_INVALID_OPERATION) + EXCEPTION(FLT_OVERFLOW) + EXCEPTION(FLT_STACK_CHECK) + EXCEPTION(FLT_UNDERFLOW) + EXCEPTION(INT_DIVIDE_BY_ZERO) + EXCEPTION(INT_OVERFLOW) + EXCEPTION(PRIV_INSTRUCTION) + EXCEPTION(IN_PAGE_ERROR) + EXCEPTION(ILLEGAL_INSTRUCTION) + EXCEPTION(NONCONTINUABLE_EXCEPTION) + EXCEPTION(STACK_OVERFLOW) + EXCEPTION(INVALID_DISPOSITION) + EXCEPTION(GUARD_PAGE) + EXCEPTION(INVALID_HANDLE) + } + #undef EXCEPTION + + // If not one of the "known" exceptions, try to + // get the string from NTDLL.DLL's message table. + static TCHAR szBuf[512] = { 0 }; + FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, + GetModuleHandle(_T("NTDLL.DLL")), + dwCode,0,szBuf,sizeof(szBuf),0); + return szBuf; +} + + +//****************************************************************** +//****************************************************************** +static void GenerateExceptionReport(HANDLE hFile,PEXCEPTION_POINTERS pExceptionInfo) { + PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; + + // First print information about the type of fault + tprintf(hFile,_T("Exception code: %08X %s\r\n"), + pExceptionRecord->ExceptionCode, + GetExceptionString(pExceptionRecord->ExceptionCode)); + + // Now print information about where the fault occured + TCHAR szFaultingModule[MAX_PATH]; + DWORD section,offset; + GetLogicalAddress(pExceptionRecord->ExceptionAddress, + szFaultingModule, + sizeof(szFaultingModule), + §ion,&offset); + + tprintf(hFile,_T("Fault address: %08X %02X:%08X %s\r\n"), + pExceptionRecord->ExceptionAddress, + section,offset,szFaultingModule); + + PCONTEXT pCtx = pExceptionInfo->ContextRecord; + + // Show the registers + #ifdef _M_IX86 // Intel Only! + tprintf(hFile,_T("\r\nRegisters:\r\n")); + + tprintf(hFile,_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n"), + pCtx->Eax,pCtx->Ebx,pCtx->Ecx,pCtx->Edx,pCtx->Esi,pCtx->Edi); + + tprintf(hFile,_T("CS:EIP:%04X:%08X\r\n"),pCtx->SegCs,pCtx->Eip); + tprintf(hFile,_T("SS:ESP:%04X:%08X EBP:%08X\r\n"), + pCtx->SegSs,pCtx->Esp,pCtx->Ebp); + tprintf(hFile,_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), + pCtx->SegDs,pCtx->SegEs,pCtx->SegFs,pCtx->SegGs); + tprintf(hFile,_T("Flags:%08X\r\n"),pCtx->EFlags); + + // Walk the stack using x86 specific code + IntelStackWalk(hFile,pCtx); + + #endif + + tprintf(hFile,_T("\r\n")); +} + + +//****************************************************************** +//****************************************************************** +LONG WINAPI CExcept::ExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo) { + + // try opening the error report file in the program directory + // if we can't open the file, it may be because the app + // is running from a CDROM drive -- try opening a file + // with the same name in c: + HANDLE hFile; + for (int i = 0; i < 2; i++) { + hFile = CreateFile( + m_szLogFileName, + GENERIC_WRITE, + 0, + 0, + OPEN_ALWAYS, + FILE_FLAG_WRITE_THROUGH, + 0 + ); + if (hFile != INVALID_HANDLE_VALUE) break; + + // extract the file name + LPTSTR lpFName = _tcsrchr(m_szLogFileName,_T('\\')); + if (! lpFName) break; + + // create full path to file in C: + TCHAR szTemp[MAX_PATH] = _T("c:\\"); + _tcscat(szTemp,lpFName); + _tcscpy(m_szLogFileName,szTemp); + } + + if (hFile != INVALID_HANDLE_VALUE) { + SetFilePointer(hFile,0,0,FILE_END); + GenerateExceptionReport(hFile,pExceptionInfo); + CloseHandle(hFile); + } + + if (m_previousFilter) return m_previousFilter(pExceptionInfo); + return EXCEPTION_CONTINUE_SEARCH; +} + + +//****************************************************************** +//****************************************************************** +CExcept::CExcept() { + // Install the unhandled exception filter function + m_previousFilter = SetUnhandledExceptionFilter(ExceptionFilter); + + // Figure out what the report file will be named,and store it away + GetModuleFileName(0,m_szLogFileName,MAX_PATH); + + // replace .EXE with .ERR + PTSTR pszDot = _tcsrchr(m_szLogFileName,_T('.')); + if (pszDot) { + pszDot++; + if (_tcslen(pszDot) >= 3) + _tcscpy(pszDot,_T("ERR")); + } + + // delete any old exception reports + DeleteFile(m_szLogFileName); +} + + +//****************************************************************** +//****************************************************************** +CExcept::~CExcept() { + SetUnhandledExceptionFilter(m_previousFilter); +} diff --git a/src/FIXES.TXT b/src/FIXES.TXT new file mode 100644 index 0000000..fb492d8 --- /dev/null +++ b/src/FIXES.TXT @@ -0,0 +1,25 @@ + +*) Fixed the bug where picking up gold when your inventory is full +duplicates the gold in your hand and fills your gold slot. + +*) Fixed the Berserk spell to prevent crashes. + +*) Fixed entering the new levels. + +*) Fixed to dropping and picking back up oiled items. + +*) Fixed generating spell books by Adria. + +*) Fixed placing of weapons for all player classes. + +*) Fixed generating rings of fire behind a wall. + + +Donald: + +*) Fixed Gosip. + +*) Fix to item changing between games. + +12/29/97 +*)Fix to gold cursor when full of gold in inventory. diff --git a/src/FUTURES.TXT b/src/FUTURES.TXT new file mode 100644 index 0000000..57f7e10 --- /dev/null +++ b/src/FUTURES.TXT @@ -0,0 +1,13 @@ +Bad Priest: + Low max strength: + Medium armor cuts spell level in half. + Full armor sets spell level to 1. + + Daggers and small swords are best. + + + Large weapons don't do full damage. (Priest is too weak) + + Benefit: mana cost is really low. Heal other in Multiplayer mode + + diff --git a/src/GAMEMENU.CPP b/src/GAMEMENU.CPP new file mode 100644 index 0000000..615e959 --- /dev/null +++ b/src/GAMEMENU.CPP @@ -0,0 +1,485 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Game Menu file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/GAMEMENU.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "gendung.h" +#include "sound.h" +#include "gamemenu.h" +#include "scrollrt.h" +#include "multi.h" +#include "cursor.h" +#include "items.h" +#include "player.h" +#include "error.h" +#include "palette.h" +#include "effects.h" +#include "msg.h" +#include "storm.h" + + +//****************************************************************** +// extern +//****************************************************************** +extern BOOL gbRunGame; +extern BOOL gbRunGameResult; +extern BOOL deathflag; +void sound_stop(); +void GM_SaveGame(); +void GM_LoadGame(BOOL firstflag); +LRESULT CALLBACK DisableInputWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); +void interface_msg_pump(); +WNDPROC my_SetWindowProc(WNDPROC wndProc); +/*extern*/ DWORD gbWalkOn = TRUE; +extern char gszProgKey[]; + +void CornerstoneSave(); + +//****************************************************************** +// private +//****************************************************************** +// menu functions +static void fnNew(BOOL bActivate); +static void fnLoad(BOOL bActivate); +static void fnOptions(BOOL bActivate); +static void fnSave(BOOL bActivate); +static void fnQuit(BOOL bActivate); +static void fnRestart(BOOL bActivate); +static void fnMusic(BOOL bActivate); +static void fnSound(BOOL bActivate); +static void fnWalk(BOOL bActivate); +static void fnGamma(BOOL bActivate); +static void fnOptionPrevious(BOOL bActivate); +static void fnReturnToGame(BOOL bActivate); +static void fnSaveAndQuit(BOOL bActivate); + +// menus +#define OPTION_SINGLE_SAVE 0 +#define OPTION_SINGLE_LOAD 3 +static TMenuItem sgSingleMenu[] = { + { mf_ENABLED, "Save Game", fnSave }, + { mf_ENABLED, "Options", fnOptions }, + { mf_ENABLED, "New Game", fnNew }, + { mf_ENABLED, "Load Game", fnLoad }, + { mf_ENABLED, "Quit Hellfire", fnQuit }, + { mf_ENABLED, NULL, NULL } +}; + +#define OPTION_MULTI_RESTART 2 +static TMenuItem sgMultiMenu[] = { + { mf_ENABLED, "Options", fnOptions }, + { mf_ENABLED, "New Game", fnNew }, + { mf_ENABLED, "Restart In Town", fnRestart }, + { mf_ENABLED, "Quit Hellfire", fnQuit }, + { mf_ENABLED, NULL, NULL } +}; + +#define OPTION_MUSIC 0 +#define OPTION_SOUND 1 +#define OPTION_GAMMA 2 +#define OPTION_WALK 3 +static TMenuItem sgOptionsMenu[] = { + { mf_ENABLED | mf_SLIDER, NULL, fnMusic }, + { mf_ENABLED | mf_SLIDER, NULL, fnSound }, + { mf_ENABLED | mf_SLIDER, "Gamma", fnGamma }, + { mf_ENABLED | mf_SLIDER, NULL, fnWalk }, + { mf_ENABLED, "Previous Menu", fnOptionPrevious }, + { mf_ENABLED, NULL, NULL } +}; + +// strings for options menu +#define SM_ON 0 +#define SM_DISABLED 1 +static const char * sgszMusic[] = { + "Music", + "Music Disabled", +}; +static const char * sgszSound[] = { + "Sound", + "Sound Disabled", +}; +static const char * sgszWalk[] = { + "Jog", + "Walk", +}; +const char * sgszWalkId = "Fast Walk"; + + +//****************************************************************** +//****************************************************************** +static void gm_single_update(TMenuItem * pMenuItems) { + app_assert(pMenuItems == sgSingleMenu); + gmenu_set_enable(&sgSingleMenu[OPTION_SINGLE_LOAD],gbValidSaveFile); + gmenu_set_enable( + &sgSingleMenu[OPTION_SINGLE_SAVE], + plr[myplr]._pmode != PM_DEATH && !deathflag + ); +} + + +//****************************************************************** +//****************************************************************** +static void gm_multi_update(TMenuItem * pMenuItems) { + app_assert(pMenuItems == sgMultiMenu); + gmenu_set_enable(&sgMultiMenu[OPTION_MULTI_RESTART],deathflag); +} + + +//****************************************************************** +//****************************************************************** +void gamemenu_on() { + if (gbMaxPlayers == 1) + gmenu_set_menu(sgSingleMenu,gm_single_update); + else + gmenu_set_menu(sgMultiMenu,gm_multi_update); + + // remove all junky windows under the menu + extern BOOL clear_windows(); + clear_windows(); +} + + +//****************************************************************** +//****************************************************************** +void gamemenu_off() { + gmenu_set_menu(NULL,NULL); +} + + +//****************************************************************** +//****************************************************************** +void gamemenu_toggle() { + if (gmenu_is_on()) + gamemenu_off(); + else + gamemenu_on(); +} + + +//****************************************************************** +//****************************************************************** +static void fnOptionPrevious(BOOL bActivate) { + app_assert(bActivate); + gamemenu_on(); +} + + +//****************************************************************** +//****************************************************************** +static void fnNew(BOOL bActivate) { + app_assert(bActivate); + for (int i = 0; i < MAX_PLRS; i++) { + plr[i]._pmode = PM_QUIT; + plr[i]._pInvincible = TRUE; + } + + deathflag = FALSE; + force_redraw = FULLDRAW; + FullBlit(TRUE); + + CornerStone.Initted = FALSE; + // stop running game loop + gbRunGame = FALSE; + gamemenu_off(); +} + + +//****************************************************************** +//****************************************************************** +static void fnQuit(BOOL bActivate) { + app_assert(bActivate); + fnNew(bActivate); + gbRunGameResult = FALSE; +} + + +//****************************************************************** +//****************************************************************** +static void fnLoad(BOOL bActivate) { + app_assert(bActivate); + app_assert(gbMaxPlayers == 1); + app_assert(gbValidSaveFile); + + // set window proc to function which will ignore input + app_assert(ghMainWnd); + WNDPROC saveProc = my_SetWindowProc(DisableInputWndProc); + + gamemenu_off(); + SetCursor(NO_CURSOR); + InitDiabloMsg(MSG_LOADGAME); + force_redraw = FULLDRAW; + DrawAndBlit(); + GM_LoadGame(FALSE); + ClrDiabloMsg(); + + CornerStone.Initted = FALSE; + + PaletteFadeOut(FADE_FAST); + deathflag = FALSE; + force_redraw = FULLDRAW; + DrawAndBlit(); + PaletteFadeIn(FADE_FAST); + SetCursor(GLOVE_CURS); + + // flush out all the messages and restore old wndproc + interface_msg_pump(); + saveProc = my_SetWindowProc(saveProc); + app_assert(saveProc == DisableInputWndProc); +} + + +//****************************************************************** +//****************************************************************** +static void fnSave(BOOL bActivate) { + app_assert(bActivate); + app_assert(gbMaxPlayers == 1); + if (curs != GLOVE_CURS) { + // @@@ how bout an error msg + return; + } + + if (plr[myplr]._pmode == PM_DEATH || deathflag) { + gamemenu_off(); + return; + } + + // set window proc to function which will ignore input + app_assert(ghMainWnd); + WNDPROC saveProc = my_SetWindowProc(DisableInputWndProc); + + SetCursor(NO_CURSOR); + gamemenu_off(); + InitDiabloMsg(MSG_SAVEGAME); + force_redraw = FULLDRAW; + DrawAndBlit(); + GM_SaveGame(); + ClrDiabloMsg(); + force_redraw = FULLDRAW; + SetCursor(GLOVE_CURS); + + // update the Cornerstone of the World + if (CornerStone.Initted) + CornerstoneSave(); + + // flush out all the messages and restore old wndproc + interface_msg_pump(); + saveProc = my_SetWindowProc(saveProc); + app_assert(saveProc == DisableInputWndProc); +} + + +//****************************************************************** +//****************************************************************** +static void fnRestart(BOOL bActivate) { + app_assert(bActivate); + NetSendCmd(TRUE, CMD_RETOWN); +} + + +//****************************************************************** +//****************************************************************** +static void set_volume_item(const char ** ppStrs,TMenuItem * pItem,LONG lVolume) { + if (gbSndInited) { + pItem->dwFlags |= mf_ENABLED | mf_SLIDER; + pItem->pszStr = ppStrs[SM_ON]; + gmenu_set_slider_ticks(pItem,VOLUME_TICKS); + gmenu_set_slider(pItem,VOLUME_MIN,VOLUME_MAX,lVolume); + } + else { + pItem->dwFlags &= ~(mf_ENABLED | mf_SLIDER); + pItem->pszStr = ppStrs[SM_DISABLED]; + } +} + + +//****************************************************************** +//****************************************************************** +static LONG get_volume_item(const TMenuItem * pItem) { + return gmenu_get_slider(pItem,VOLUME_MIN,VOLUME_MAX); +} + + +//****************************************************************** +//****************************************************************** +static void set_music_item() { + set_volume_item(sgszMusic,&sgOptionsMenu[OPTION_MUSIC],music_volume(VOLUME_READ)); +} + + +//****************************************************************** +//****************************************************************** +static void set_sound_item() { + set_volume_item(sgszSound,&sgOptionsMenu[OPTION_SOUND],sound_volume(VOLUME_READ)); +} + +//****************************************************************** +//****************************************************************** +static void set_walk_item() { + gmenu_set_slider_ticks(&sgOptionsMenu[OPTION_WALK],2); + gmenu_set_slider( + &sgOptionsMenu[OPTION_WALK], 0, 1, gbWalkOn); + sgOptionsMenu[OPTION_WALK].pszStr = + sgszWalk[(gbWalkOn)?SM_ON:SM_DISABLED]; +} + +//****************************************************************** +//****************************************************************** +static void set_gamma_item() { + gmenu_set_slider_ticks(&sgOptionsMenu[OPTION_GAMMA],lGAMMA_TICKS); + gmenu_set_slider( + &sgOptionsMenu[OPTION_GAMMA], + lGAMMA_MIN, + lGAMMA_MAX, + GammaLevel(lGAMMA_READ) + ); +} + + +//****************************************************************** +//****************************************************************** +static LONG get_gamma_item() { + return gmenu_get_slider( + &sgOptionsMenu[OPTION_GAMMA], + lGAMMA_MIN, + lGAMMA_MAX + ); +} + + +//****************************************************************** +//****************************************************************** +static void fnOptions(BOOL bActivate) { + app_assert(bActivate); + set_music_item(); + set_sound_item(); + set_walk_item(); + set_gamma_item(); + gmenu_set_menu(sgOptionsMenu,NULL); +} + + +//****************************************************************** +//****************************************************************** +static void fnMusic(BOOL bActivate) { + if (bActivate) { + if (gbMusicOn) { + gbMusicOn = FALSE; + music_stop(); + music_volume(VOLUME_MIN); + } + else { + gbMusicOn = TRUE; + music_volume(VOLUME_MAX); + + if (currlevel >= HIVESTART) // fix this later JKE + { + music_start((currlevel > HIVEEND)? 5 : 6); + } + else + music_start(leveltype); + } + } + else { + LONG lVolume = get_volume_item(&sgOptionsMenu[OPTION_MUSIC]); + music_volume(lVolume); + + if (lVolume == VOLUME_MIN) { + if (gbMusicOn) { + gbMusicOn = FALSE; + music_stop(); + } + } + else { + if (! gbMusicOn) { + gbMusicOn = TRUE; + if (currlevel >= HIVESTART) // fix this later JKE + { + music_start((currlevel > HIVEEND)? 5 : 6); + } + else + music_start(leveltype); + } + } + } + + set_music_item(); +} + + +//****************************************************************** +//****************************************************************** +static void fnSound(BOOL bActivate) { + if (bActivate) { + if (gbSoundOn) { + gbSoundOn = FALSE; + sound_stop(); + sound_volume(VOLUME_MIN); + } + else { + gbSoundOn = TRUE; + sound_volume(VOLUME_MAX); + } + } + else { + LONG lVolume = get_volume_item(&sgOptionsMenu[OPTION_SOUND]); + sound_volume(lVolume); + + if (lVolume == VOLUME_MIN) { + if (gbSoundOn) { + gbSoundOn = FALSE; + sound_stop(); + } + } + else { + if (! gbSoundOn) { + gbSoundOn = TRUE; + } + } + } + + PlaySFX(IS_TITLEMOV); + set_sound_item(); +} + +static void fnWalk(BOOL bActivate) { + if (gbMaxPlayers != 1) // single-player only + return; + + if (gbWalkOn) { + gbWalkOn = FALSE; + } + else { + gbWalkOn = TRUE; + } + SRegSaveValue(gszProgKey,sgszWalkId,0,gbWalkOn); + + PlaySFX(IS_TITLEMOV); + set_walk_item(); +} + +//****************************************************************** +//****************************************************************** +static void fnGamma(BOOL bActivate) { + LONG lGamma; + if (bActivate) { + lGamma = GammaLevel(lGAMMA_READ); + if (lGamma == lGAMMA_MIN) + lGamma = lGAMMA_MAX; + else + lGamma = lGAMMA_MIN; + } + else { + lGamma = get_gamma_item(); + } + + GammaLevel(lGamma); + set_gamma_item(); +} diff --git a/src/GAMEMENU.H b/src/GAMEMENU.H new file mode 100644 index 0000000..f78e846 --- /dev/null +++ b/src/GAMEMENU.H @@ -0,0 +1,56 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/GAMEMENU.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + + +//****************************************************************** +//****************************************************************** +#define mf_ENABLED 0x80000000 +#define mf_SLIDER 0x40000000 +typedef void (* TMenuFcn)(BOOL bActivate); +typedef struct TMenuItem { + DWORD dwFlags; + const char * pszStr; + TMenuFcn fnMenu; +} TMenuItem; + +typedef void (* TMenuUpdateFcn)(TMenuItem * pMenuItems); + +//****************************************************************** +// menu functions +//****************************************************************** +void gmenu_init(); +void gmenu_free(); +void gmenu_draw(); +BOOL gmenu_is_on(); +BOOL gmenu_click(BOOL bMouseDown); +BOOL gmenu_mousemove(); +BOOL gmenu_key(WPARAM wKey); +void gmenu_set_menu(TMenuItem * pMenuItems,TMenuUpdateFcn fnUpdate); +void gmenu_set_enable(TMenuItem * pMenuItem,BOOL bEnable); + +void gmenu_set_slider(TMenuItem * pItem,LONG lMin,LONG lMax,LONG lVal); +LONG gmenu_get_slider(const TMenuItem * pItem,LONG lMin,LONG lMax); +void gmenu_set_slider_ticks(TMenuItem * pMenuItem,DWORD dwTicks); + + +//****************************************************************** +// gamemenu functions +//****************************************************************** +void gamemenu_toggle(); +void gamemenu_on(); +void gamemenu_off(); + + +//****************************************************************** +// other prototypes +//****************************************************************** +void GM_LoadGame(BOOL); +void SaveLevel(); +void LoadLevel(); diff --git a/src/GENDUNG.CPP b/src/GENDUNG.CPP new file mode 100644 index 0000000..c50bf6b --- /dev/null +++ b/src/GENDUNG.CPP @@ -0,0 +1,1209 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** General Dungeon file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/GENDUNG.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +** FillDungeonInfo +** DRLG +** MakeDungeonLayout +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "gendung.h" +#include "engine.h" +#include "lighting.h" +#include "palette.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "objects.h" +#include "missiles.h" +#include "spells.h" + +/*-----------------------------------------------------------------------** +** Global variables +**-----------------------------------------------------------------------*/ + +byte dungeon[MDMAXX][MDMAXY]; +byte pdungeon[MDMAXX][MDMAXY]; +byte dflags[MDMAXX][MDMAXY]; +int setpc_x, setpc_y, setpc_w, setpc_h; // Where the important set piece of a level is +byte *pSetPiece; +BOOL setloadflag; + +BYTE *pSpecialCels; +BYTE *pMegaTiles; +BYTE *pMiniTiles; +extern "C" { + BYTE *pDungeonCels; + BYTE *pSpeedCels; + long microoffset[MAXMREND][16]; + byte nWTypeTable[MAXTILES+1]; +} + +int mcount[MAXMICRO]; +int mlist[MAXMICRO]; +//WORD mtype[MAXMICRO]; +static WORD mtype[MAXMICRO]; // resolve ambiguity with monsters JKE 7/30 +int msize[MAXMICRO]; +int nummicros; + +BYTE nBlockTable[MAXTILES+1]; +BYTE nSolidTable[MAXTILES+1]; +BYTE nTransTable[MAXTILES+1]; +BYTE nMissileTable[MAXTILES+1]; +BYTE nTrapTable[MAXTILES+1]; + +int dminx, dminy, dmaxx, dmaxy; + +int gnDifficulty; + +BYTE leveltype; +BYTE currlevel; +BYTE setlevel; +BYTE setlvlnum; +BYTE setlvltype; + +int ViewX, ViewY; +int ViewDX, ViewDY; +int ViewBX, ViewBY; +ScrollStruct ScrollInfo; + +int LvlViewX, LvlViewY; + +int btmbx, btmby; +int btmdx, btmdy; + +int MicroTileLen; + +char TransVal; +BYTE TransList[256]; + +int dPiece[MAXDUNX][MAXDUNY]; // Tile # + +MICROS dMT[MAXDUNX][MAXDUNY]; // Micro Tiles +MICROS dMT2[(MAXDUNX)*(MAXDUNY)]; + +char dTransVal[MAXDUNX][MAXDUNY]; // Transparent active value +char dLight[MAXDUNX][MAXDUNY]; // Current light value +char dSaveLight[MAXDUNX][MAXDUNY]; // Static light value +char dFlags[MAXDUNX][MAXDUNY]; // Flags for Solid collision, etc. +char dPlayer[MAXDUNX][MAXDUNY]; // Player +int dMonster[MAXDUNX][MAXDUNY]; // Monster +char dDead[MAXDUNX][MAXDUNY]; // Dead plr/monster +char dObject[MAXDUNX][MAXDUNY]; // Objects +char dItem[MAXDUNX][MAXDUNY]; // Items +char dMissile[MAXDUNX][MAXDUNY]; // Missiles +char dSpecial[MAXDUNX][MAXDUNY]; // Second layer of tiling +int themeCount; // Theme room count +THEME_LOC themeLoc[50]; // Theme room array + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void FillSolidBlockTbls() { + DWORD dwTiles; + BYTE *pSBFile; + + ZeroMemory(nBlockTable,sizeof(nBlockTable)); + ZeroMemory(nSolidTable,sizeof(nSolidTable)); + ZeroMemory(nTransTable,sizeof(nTransTable)); + ZeroMemory(nMissileTable,sizeof(nMissileTable)); + ZeroMemory(nTrapTable,sizeof(nTrapTable)); + + switch (leveltype) { + case 0: + pSBFile = LoadFileInMemSig("NLevels\\TownData\\Town.SOL",&dwTiles,'SOL '); + break; + case 1: + if (currlevel < 17) + pSBFile = LoadFileInMemSig("Levels\\L1Data\\L1.SOL",&dwTiles,'SOL '); + else + pSBFile = LoadFileInMemSig("NLevels\\L5Data\\L5.SOL",&dwTiles,'SOL '); //JKE Attributes loaded + + break; + case 2: + pSBFile = LoadFileInMemSig("Levels\\L2Data\\L2.SOL",&dwTiles,'SOL '); + break; + case 3: + if (currlevel < 17) + pSBFile = LoadFileInMemSig("Levels\\L3Data\\L3.SOL",&dwTiles,'SOL '); + else + pSBFile = LoadFileInMemSig("NLevels\\L6Data\\L6.SOL",&dwTiles,'SOL '); //JKE Attributes loaded + break; + case 4: + pSBFile = LoadFileInMemSig("Levels\\L4Data\\L4.SOL",&dwTiles,'SOL '); + break; + default: + app_fatal("FillSolidBlockTbls"); + break; + } + + BYTE * pTmp = pSBFile; + for (DWORD d = 1; d <= dwTiles; d++) { + BYTE bv = *pTmp++; + if ((bv & 0x01) != 0) nSolidTable[d] = TRUE; + if ((bv & 0x02) != 0) nBlockTable[d] = TRUE; + if ((bv & 0x04) != 0) nMissileTable[d] = TRUE; + if ((bv & 0x08) != 0) nTransTable[d] = TRUE; + if ((bv & 0x80) != 0) nTrapTable[d] = TRUE; + nWTypeTable[d] = (bv & 0x70) >> 4; + } + + DiabloFreePtr(pSBFile); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void bs_swap(int a, int b) { + int v; + + v = mcount[a]; + mcount[a] = mcount[b]; + mcount[b] = v; + v = mlist[a]; + mlist[a] = mlist[b]; + mlist[b] = v; + v = mtype[a]; + mtype[a] = mtype[b]; + mtype[b] = v; + v = msize[a]; + msize[a] = msize[b]; + msize[b] = v; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void bubblesort(int n) { + int j,k,sorted; + + k = n; + sorted = 0; + + while ((k > 0) && (sorted == 0)) { + sorted = 1; + for (j = 0; j < k; j++) { + if (mcount[j] < mcount[j+1]) { + bs_swap(j, j+1); + sorted = 0; + } + } + k--; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void PreRendMicros() +{ + long i,j,llvls; + WORD k; + long nPNum; + long tl, tms, total; + int numrend; + WORD *mt; + int t, tlen; + int ok2rend; + + for (i = 0; i < MAXMICRO; i++) { + mlist[i] = i; + mcount[i] = 0; + mtype[i] = 0; + } + + if (leveltype != 4) tlen = 10; + else tlen = 12; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + mt = &(dMT[i][j].mt[0]); + for(t = 0; t < tlen; t++) + { + nPNum = mt[t]; + if (nPNum) { + mcount[nPNum & 0xfff]++; + mtype[nPNum & 0xfff] = nPNum & 0x7000; + } + } + } + } + + __asm { + mov ebx,dword ptr [pDungeonCels] + mov eax,dword ptr [ebx] + mov dword ptr [tms],eax + } + nummicros = tms & 0xffff; + + for (i = 0; i < nummicros; i++) { + nPNum = i; + __asm { + mov ebx,dword ptr [pDungeonCels] + mov eax,dword ptr [nPNum] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] // Size + sub eax,dword ptr [ebx] + mov dword ptr [tms],eax + } + msize[i] = tms & 0xffff; + } + msize[0] = 0; // Zero doesn't exist + + + // On level type 4 we cycle the lava using the translation tables so it can't + // be prerendered + if (leveltype == 4) { + for (i = 0; i < nummicros; i++) { + nPNum = i; + ok2rend = 1; + if (mcount[i] == 0) continue; + if (mtype[i] != 0x1000) { + tl = msize[i]; + __asm { + mov ebx,dword ptr [pDungeonCels] + mov eax,dword ptr [nPNum] + shl eax,2 + add ebx,eax + mov esi,dword ptr [pDungeonCels] + add esi,dword ptr [ebx] // Source + + xor ebx,ebx + + mov ecx,dword ptr [tl] // Number of bytes to translate + jecxz _XSkip +_XLp1: lodsb + cmp al,0 + je _XOk1 + cmp al,32 + jae _XOk1 + mov dword ptr [ok2rend],ebx +_XOk1: loop _XLp1 +_XSkip: nop + } + } else { + __asm { + mov ebx,dword ptr [pDungeonCels] + mov eax,dword ptr [nPNum] + shl eax,2 + add ebx,eax + mov esi,dword ptr [pDungeonCels] + add esi,dword ptr [ebx] // Source + + xor ebx,ebx + + mov ecx,32 +_X1Lp1: push ecx + mov edx,32 +_X1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _X1J + + sub edx,eax + + mov ecx,eax +_X1Lp3: lodsb + cmp al,0 + je _XOk2 + cmp al,32 + jae _XOk2 + mov dword ptr [ok2rend],ebx +_XOk2: loop _X1Lp3 + or edx,edx + jz _X1Nxt + jmp _X1Lp2 + +_X1J: neg al // Do jump + sub edx,eax + jnz _X1Lp2 +_X1Nxt: pop ecx + loop _X1Lp1 + } + } + if (ok2rend == 0) mcount[i] = 0; + } + } + + bubblesort(MAXMICRO-1); + + total = 0; + numrend = 0; + if (light4flag) { + while (total < 1048576) { + total = total + ((long)msize[numrend] << 1); + numrend++; + } + } else { + while (total < 1048576) { + total = total + ((long)msize[numrend] << 4) - ((long)msize[numrend] << 1); + numrend++; + } + } + numrend--; + + if (numrend > MAXMREND) numrend = MAXMREND; + + // Pre render the most used + total = 0; + if (light4flag) llvls = 3; + else llvls = 15; + for (j = 0; j < numrend; j++) { + nPNum = mlist[j]; + microoffset[j][0] = nPNum; + if (mtype[j] != 0x1000) { + tl = msize[j]; + // Pre render for each light level + for (i = 1; i < llvls; i++) { + microoffset[j][i] = total; + __asm { + mov ebx,dword ptr [pDungeonCels] + mov eax,dword ptr [nPNum] + shl eax,2 + add ebx,eax + mov esi,dword ptr [pDungeonCels] + add esi,dword ptr [ebx] // Source + + mov edi,dword ptr [pSpeedCels] + add edi,dword ptr [total] + + mov ebx,dword ptr [i] // Light conversion table + shl ebx,8 + add ebx,dword ptr [pLightTbl] + + mov ecx,dword ptr [tl] // Number of bytes to translate + jecxz _Skip + +_Lp1: lodsb + xlatb + stosb + loop _Lp1 +_Skip: nop + } + total += tl; + } + } else { + // Pre render for each light level + for (i = 1; i < llvls; i++) { + microoffset[j][i] = total; + __asm { + mov ebx,dword ptr [pDungeonCels] + mov eax,dword ptr [nPNum] + shl eax,2 + add ebx,eax + mov esi,dword ptr [pDungeonCels] + add esi,dword ptr [ebx] // Source + + mov edi,dword ptr [pSpeedCels] + add edi,dword ptr [total] + + mov ebx,dword ptr [i] // Light conversion table + shl ebx,8 + add ebx,dword ptr [pLightTbl] + + mov ecx,32 +_T1Lp1: push ecx + mov edx,32 +_T1Lp2: xor eax,eax // Load control byte + lodsb + stosb + or al,al + js _T1J + + sub edx,eax + + mov ecx,eax +_T1Lp3: lodsb + xlatb + stosb + loop _T1Lp3 + or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + sub edx,eax + jnz _T1Lp2 +_T1Nxt: pop ecx + loop _T1Lp1 + } + total += msize[j]; + } + } + } + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] != 0) { + mt = &(dMT[i][j].mt[0]); + for(t = 0; t < tlen; t++) + { + if (mt[t]) { + for (k = 0; k < numrend; k++) { + if ((mt[t] & 0xfff) == mlist[k]) { + mt[t] = mtype[k] + 0x8000 + k; + k = numrend; + } + } + } + } + } + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +int CalcRot(int x, int y) +{ + int rot; + + if(x < DMAXX - y) + rot = ((y*y+y) + ((2*y + x + 3)*x))/2; + else + { + x = DMAXX - x - 1; + y = DMAXY - y - 1; + rot = (DMAXX)*(DMAXY)-(1 + ((y*y+y) + ((2*y + x + 3)*x))/2); + } + return rot; +} + +/*-----------------------------------------------------------------------** + * RotateMicros + * + * Rotates the dMT array by 45 degrees, so that when drawn to the screen, + * the elements are read sequentially. Previously, DrawHTileLine had to + * scan through dMT diagonally, which causes a lot of caching. +**-----------------------------------------------------------------------*/ + +void RotateMicros() +{ + int x,y; + + for(x = 0; x < DMAXX; x++) + { + for(y = 0; y < DMAXX; y++) + { + dMT2[CalcRot(x,y)] = dMT[x][y]; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetDungeonMicros() +{ + int wv; + int i,j; + WORD *mtsource; + int t; + WORD *mt; + int tlen; + + if (leveltype != 4) { + MicroTileLen = 10; + tlen = 10; + } else { + MicroTileLen = 12; + tlen = 16; + } + // Init the light values for each piece + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + wv = dPiece[i][j]; + mt = &(dMT[i][j].mt[0]); + if (wv != 0) { + wv--; + if (leveltype != 4) mtsource = (WORD *)(pMiniTiles + 20*wv); + else mtsource = (WORD *)(pMiniTiles + 32*wv); + for(t = 0; t < tlen; t++) + // MiniTiles array uses opposite y direction + // hence wierd index on next line + mt[t] = mtsource[(tlen-2)-(t&0xe)+(t&1)]; + } + else + { + for(t = 0; t < tlen; t++) + mt[t] = 0; + } + } + } + + PreRendMicros(); + + RotateMicros(); + + if (svgamode) { + ViewDX = 640; + ViewDY = 352; + ViewBX = 10; + ViewBY = 11; + } else { + ViewDX = 384; + ViewDY = 224; + ViewBX = 6; + ViewBY = 7; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DRLG_InitTrans() +{ + // Init the transparent values for each piece + ZeroMemory(dTransVal,sizeof(dTransVal)); + ZeroMemory(TransList,sizeof(TransList)); + // JKE TransVal = 1; + TransVal = 1; +} + +/*-----------------------------------------------------------------------** +** Do Transparent values on megatiles +**-----------------------------------------------------------------------*/ + +void DRLG_MRectTrans(int x1, int y1, int x2, int y2) +{ + int i,j; + + x1 = (x1 << 1) + DIRTEDGED2 + 1; + y1 = (y1 << 1) + DIRTEDGED2 + 1; + x2 = (x2 << 1) + DIRTEDGED2; + y2 = (y2 << 1) + DIRTEDGED2; + for (j = y1; j <= y2; j++) { + for (i = x1; i <= x2; i++) dTransVal[i][j] = TransVal; + } + TransVal++; +} + +/*-----------------------------------------------------------------------** +** Copy Transparent values on megatiles level with 4 flags for mini +**-----------------------------------------------------------------------*/ + +void DRLG_MCopyTrans(int sx, int sy, int dx, int dy, BOOL ul, BOOL ur, BOOL ll, BOOL lr) +{ + char v; + + sx = (sx << 1) + DIRTEDGED2; + sy = (sy << 1) + DIRTEDGED2; + v = dTransVal[sx][sy]; + dx = (dx << 1) + DIRTEDGED2; + dy = (dy << 1) + DIRTEDGED2; + if (ul) dTransVal[dx][dy] = v; + if (ur) dTransVal[dx+1][dy] = v; + if (ll) dTransVal[dx][dy+1] = v; + if (lr) dTransVal[dx+1][dy+1] = v; +} + +/*-----------------------------------------------------------------------** +** Do Transparent values on minitiles +**-----------------------------------------------------------------------*/ + +void DRLG_RectTrans(int x1, int y1, int x2, int y2) +{ + int i,j; + + for (j = y1; j <= y2; j++) { + for (i = x1; i <= x2; i++) dTransVal[i][j] = TransVal; + } + TransVal++; +} + +/*-----------------------------------------------------------------------** +** Copy Transparent values on minitile level +**-----------------------------------------------------------------------*/ + +void DRLG_CopyTrans(int sx, int sy, int dx, int dy) +{ + dTransVal[dx][dy] = dTransVal[sx][sy]; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DRLG_ListTrans(int num, byte *List) +{ + int i; + byte x1,y1,x2,y2; + + for (i = 0; i < num; i++) { + x1 = *List++; + y1 = *List++; + x2 = *List++; + y2 = *List++; + DRLG_RectTrans(x1, y1, x2, y2); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DRLG_AreaTrans(int num, byte *List) +{ + int i; + byte x1,y1,x2,y2; + + for (i = 0; i < num; i++) { + x1 = *List++; + y1 = *List++; + x2 = *List++; + y2 = *List++; + DRLG_RectTrans(x1, y1, x2, y2); + TransVal--; + } + TransVal++; +} + +/*-----------------------------------------------------------------------** +** Fuckin all problems solved with this routine +**-----------------------------------------------------------------------*/ + +void DRLG_InitSetPC() +{ + setpc_x = 0; + setpc_y = 0; + setpc_w = 0; + setpc_h = 0; +} + +/*-----------------------------------------------------------------------** +** Don't put rnd monsters, objects in set piece areas +**-----------------------------------------------------------------------*/ + +void DRLG_SetPC() +{ + int i,j; + int x,y,w,h; + + w = setpc_w << 1; + h = setpc_h << 1; + x = (setpc_x << 1) + DIRTEDGED2; + y = (setpc_y << 1) + DIRTEDGED2; + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) dFlags[x+i][y+j] |= BFLAG_SETPC; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Make_SetPC(int x, int y, int w, int h) +{ + int i,j; + int dx, dy, dh, dw; + + dw = w << 1; + dh = h << 1; + dx = (x << 1) + DIRTEDGED2; + dy = (y << 1) + DIRTEDGED2; + for (j = 0; j < dh; j++) { + for (i = 0; i < dw; i++) dFlags[dx+i][dy+j] |= BFLAG_SETPC; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawDungMiniMap(unsigned char floor) +/*-----------------------------------------------------------------------** +** DESCRIPTION: Draws a mini map of the dungeon and player locations. +** INPUT: floor = The floor type to look for +** RETURN: None +/*-----------------------------------------------------------------------*/ +{ + int *p; + byte *d; + unsigned int pSize; + int pIndex, pXMega, pYMega, pX, pY; + + p = &plr[0]._px; + d = &dungeon[0][0]; + pSize = sizeof(PlayerStruct); + + //*NOTE* The x and y coords had to be swapped in the compares to ecx and edx + // to get the proper output coordinates for the players. + + app_assert(gpBuffer); + __asm { + mov esi,dword ptr [d] + mov edi,dword ptr [gpBuffer] + add edi,135248 + mov edx,MDMAXY +_YLp: + push edi + mov ecx,MDMAXX +_XLp: + lodsb //Read byte from dungeon array + +//Start Search for Player coords + push eax + push esi + push edi + mov esi,dword ptr [p] //PlayerStruct._px + mov edi,0 //Initialize plr array index +LoopThruPlayers: + lodsd //Get _px + mov pX,eax //Fill in pX + lodsd //Get _py + mov pY,eax //Fill in pY + add esi,pSize //Add sizeof(PlayerStruct) + sub esi,8 //Subtract 2 dwords read + cmp pX,0 //Ignore 0,0 coords + jnz PNotOrigin + cmp pY,0 //Ignore 0,0 coords + jz PNoX +PNotOrigin: + mov pIndex,edi //Save plr index + jmp PMiniToMega //Convert mini tiles to mega tiles +PMegaFound: + cmp edx,pXMega //Did we match a players x coord? + jnz PNoX + cmp ecx,pYMega //Did we match a players y coord? + jz Player +PNoX: + inc edi //Increment index + cmp edi,MAX_PLRS //Are we done with our for loop? + jl LoopThruPlayers + pop edi + pop esi + pop eax +//End Search for Player coords + + cmp al,floor //Did we find a floor piece? + jz NoSave //Let background show thru + jmp Other //We found a wall or something +Player: + pop edi + pop esi + pop eax + cmp pIndex,0 //Are we dealing with player 0? + jnz Player1 + mov al,240 //Set color to white + jmp Save +Player1: + cmp pIndex,1 //Are we dealing with player 1? + jnz Player2 + mov al,139 //Set color to red + jmp Save +Player2: + cmp pIndex,2 //Are we dealing with player 2? + jnz Player3 + mov al,154 //Set color to orange + jmp Save +Player3: //We are dealing with player 3 + mov al,147 //Set color to yellow + jmp Save +Other: + mov al,131 //Set color to blue +Save: + mov byte ptr [edi],al + mov byte ptr [edi+1],al + mov byte ptr [edi+768],al + mov byte ptr [edi+769],al +NoSave: + add edi,1536 + dec ecx + jnz _XLp + pop edi + add edi,2 + dec edx + jnz _YLp + jmp EndL2DrawDung + +//Start Convert player mini tiles to mega tiles +PMiniToMega: + push eax + push edx + mov eax,pX + sub eax,DIRTEDGED2 + shr eax,1 + mov edx,MDMAXX + sub edx,eax + mov pXMega,edx + mov eax,pY + sub eax,DIRTEDGED2 + shr eax,1 + mov edx,MDMAXY + sub edx,eax + mov pYMega,edx + pop edx + pop eax + jmp PMegaFound +//End Convert player mini tiles to mega tiles + +EndL2DrawDung: + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL DRLG_WillThemeRoomFit(int floor, + int x, + int y, + int minSize, + int maxSize, + int *width, + int *height) +/*-----------------------------------------------------------------------** +** DESCRIPTION: Checks if a theme room between minSize and maxSize will fit at +** (x, y). +** INPUT: floor = Floor value to look for +** x, y = Top left corner to start search from +** minSize = Min sized room to create. This will actually create a room of +** size (minSize - 2) to account for a hall, 1 megatile wide, +** around the room. +** maxSize = Max sized room to create. This will actually create a room of +** size (maxSize - 2) to account for a hall, 1 megatile wide, +** around the room. +** *width = Actual room width return value +** *height = Actual room height return value +** +** RETURN: FALSE = Could not fit a room with specified parameters +** TRUE = Room dimensions were found +/*-----------------------------------------------------------------------*/ +{ + int ii, xx, yy; + int xSmallest, ySmallest; + int xArray[20]; + int yArray[20]; + int xCount = 0; + int yCount = 0; + BOOL yFlag = TRUE; + BOOL xFlag = TRUE; + + //Check to see if we are within the bounds of the dungeon[40][40] array + if ((x > (MDMAXX - maxSize)) && (y > (MDMAXY - maxSize))) + return FALSE; + + //Skip any existing theme rooms + if (!SkipThemeRoom(x, y)) + return FALSE; + + //Intialize arrays + memset(xArray, 0x00, sizeof(xArray)); + memset(yArray, 0x00, sizeof(yArray)); + + //Find the lengths of each row and column + for (ii = 0; ii < maxSize; ii++) { + //Find the row lengths + if (xFlag) { + for (xx = x; xx < (x + maxSize); xx++) { + //We ran into a wall or something + if (dungeon[xx][y+ii] != floor) { + if (xx < minSize) xFlag = FALSE; + else break; + } else xCount++; + } + if (xFlag) { + xArray[ii] = xCount; + xCount = 0; + } + } + //Find the column lengths + if (yFlag) { + for (yy = y; yy < (y + maxSize); yy++) { + //We ran into a wall or something + if (dungeon[x+ii][yy] != floor) { + if (yy < minSize) yFlag = FALSE; + else break; + } else yCount++; + } + if (yFlag) { + yArray[ii] = yCount; + yCount = 0; + } + } + } + //Make sure we meet the minimum requirements + for (ii = 0; ii < minSize; ii++) { + if (xArray[ii] < minSize || yArray[ii] < minSize) return FALSE; + } + //Initialize + xSmallest = xArray[0]; + ySmallest = yArray[0]; + //Find the best x and y values + for (ii = 0; ii < maxSize; ii++) { + if (xArray[ii] >= minSize && yArray[ii] >= minSize) { + if (xArray[ii] < xSmallest) xSmallest = xArray[ii]; + if (yArray[ii] < ySmallest) ySmallest = yArray[ii]; + } else break; + } + //Set the room dimenions + *width = xSmallest - 2; //Subtract 2 to acount for hall around room + *height = ySmallest - 2; //Subtract 2 to acount for hall around room + + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DRLG_CreateThemeRoom(int themeIndex) +/*-----------------------------------------------------------------------** +** DESCRIPTION: Creates themeIndex theme room in the themeLoc array. +** INPUT: themeIndex = Index into themeLoc array +** RETURN: None +/*-----------------------------------------------------------------------*/ +{ + int xx; + int yy; + + //Add the walls + for (yy = themeLoc[themeIndex].y; yy < (themeLoc[themeIndex].y + themeLoc[themeIndex].height); yy++) { + for (xx = themeLoc[themeIndex].x; xx < (themeLoc[themeIndex].x + themeLoc[themeIndex].width); xx++) { + if (leveltype == 2) { + //TOP/BOTTOM WALLS + if ((yy == themeLoc[themeIndex].y && (xx >= themeLoc[themeIndex].x && (xx <= themeLoc[themeIndex].x + themeLoc[themeIndex].width))) || + ((yy == themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)) && (xx >= themeLoc[themeIndex].x && (xx <= themeLoc[themeIndex].x + themeLoc[themeIndex].width)))) + dungeon[xx][yy] = 2; //HWALL_PIECE + //RIGHT/LEFT WALLS + else if ((xx == themeLoc[themeIndex].x && (yy >= themeLoc[themeIndex].y && (yy <= themeLoc[themeIndex].y + themeLoc[themeIndex].height))) || + ((xx == themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)) && (yy >= themeLoc[themeIndex].y && (yy <= themeLoc[themeIndex].y + themeLoc[themeIndex].height)))) + dungeon[xx][yy] = 1; //VWALL_PIECE + //FLOOR PIECE + else dungeon[xx][yy] = 3; //FLOOR_PIECE + } + if (leveltype == 3) { + //UPPER/LOWER WALL + if ((yy == themeLoc[themeIndex].y && (xx >= themeLoc[themeIndex].x && (xx <= themeLoc[themeIndex].x + themeLoc[themeIndex].width))) || + ((yy == themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)) && (xx >= themeLoc[themeIndex].x && (xx <= themeLoc[themeIndex].x + themeLoc[themeIndex].width)))) + dungeon[xx][yy] = 134; //WOOD_HORIZWALL + //RIGHT/LEFT WALL + else if ((xx == themeLoc[themeIndex].x && (yy >= themeLoc[themeIndex].y && (yy <= themeLoc[themeIndex].y + themeLoc[themeIndex].height))) || + ((xx == themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)) && (yy >= themeLoc[themeIndex].y && (yy <= themeLoc[themeIndex].y + themeLoc[themeIndex].height)))) + dungeon[xx][yy] = 137; //WOOD_VERTWALL + //FLOOR PIECE + else dungeon[xx][yy] = 7; //FLOOR + } + if (leveltype == 4) { + //UPPER/LOWER WALL + if ((yy == themeLoc[themeIndex].y && (xx >= themeLoc[themeIndex].x && (xx <= themeLoc[themeIndex].x + themeLoc[themeIndex].width))) || + ((yy == themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)) && (xx >= themeLoc[themeIndex].x && (xx <= themeLoc[themeIndex].x + themeLoc[themeIndex].width)))) + dungeon[xx][yy] = 2; //HWALL_PIC + //RIGHT/LEFT WALL + else if ((xx == themeLoc[themeIndex].x && (yy >= themeLoc[themeIndex].y && (yy <= themeLoc[themeIndex].y + themeLoc[themeIndex].height))) || + ((xx == themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)) && (yy >= themeLoc[themeIndex].y && (yy <= themeLoc[themeIndex].y + themeLoc[themeIndex].height)))) + dungeon[xx][yy] = 1; //VWALL_PIC + //FLOOR PIECE + else dungeon[xx][yy] = 6; //FLOOR_PIC + } + } + } + + //Add the corners + if (leveltype == 2) { + dungeon[themeLoc[themeIndex].x][themeLoc[themeIndex].y] = 8; //ULWALL_PIECE + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y] = 7; //URWALL_PIECE + dungeon[themeLoc[themeIndex].x][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 9; //LLWALL_PIECE + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 6; //LRWALL_PIECE + } + if (leveltype == 3) { + dungeon[themeLoc[themeIndex].x][themeLoc[themeIndex].y] = 150; //WOOD_ULCORNER + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y] = 151; //WOOD_URCORNER + dungeon[themeLoc[themeIndex].x][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 152; //WOOD_LLCORNER + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 138; //WOOD_LRCORNER + } + if (leveltype == 4) { + dungeon[themeLoc[themeIndex].x][themeLoc[themeIndex].y] = 9; //ULWALL_PIC + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y] = 16; //URWALL_PIC + dungeon[themeLoc[themeIndex].x][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 15; //LLWALL_PIC + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 12; //LRWALL_PIC + } + + //Add the door to the east or south wall + if (leveltype == 2) { + switch(random(0, 2)) { + //East wall + case 0 : dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height / 2)] = 4; //VDOOR_PIECE + break; + //South wall + case 1 : dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width / 2)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 5; //HDOOR_PIECE + break; + } + } + if (leveltype == 3) { + switch(random(0, 2)) { + //East wall + case 0 : dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height / 2)] = 147; //WOOD_VERTGATE + break; + //South wall + case 1 : dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width / 2)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 146; //WOOD_HORIZGATE + break; + } + } + if (leveltype == 4) { + switch(random(0, 2)) { + //East wall + case 0 : dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][(themeLoc[themeIndex].y + (themeLoc[themeIndex].height / 2))-1] = 53; //VERT RIGHT + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height / 2)] = 6; //FLOOR_PIC + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-1)][(themeLoc[themeIndex].y + (themeLoc[themeIndex].height / 2))+1] = 52; //VERT LEFT + //Add Shadows + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width-2)][(themeLoc[themeIndex].y + (themeLoc[themeIndex].height / 2))-1] = 54; + break; + //South wall + case 1 : dungeon[(themeLoc[themeIndex].x + (themeLoc[themeIndex].width / 2))-1][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 57; //HORIZ LEFT + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width / 2)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 6; //FLOOR_PIC + dungeon[(themeLoc[themeIndex].x + (themeLoc[themeIndex].width / 2))+1][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-1)] = 56; //HORIZ RIGHT + //Add Shadows + dungeon[themeLoc[themeIndex].x + (themeLoc[themeIndex].width / 2)][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-2)] = 59; + dungeon[(themeLoc[themeIndex].x + (themeLoc[themeIndex].width / 2))-1][themeLoc[themeIndex].y + (themeLoc[themeIndex].height-2)] = 58; + break; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DRLG_PlaceThemeRooms(int minSize, + int maxSize, + int floor, + int freq, + BOOL rndSize) +/*-----------------------------------------------------------------------** +** DESCRIPTION: Places theme rooms in dungeon types 2,3 & 4. +** INPUT: minSize = The minimum sized room to create +** maxSize = The maximum sized room to create +** floor = The floor value to look for +** freq = The frequency to check for theme rooms. Set to 0 if you +** want to check everything. +** rndSize = If TRUE, then create rooms between max and min. If FALSE, +** then the largest theme rooms in an area will be created. +** RETURN: None +/*-----------------------------------------------------------------------*/ +{ + int i; + int j; + int themeW; + int themeH; + + //Initialize + themeCount = 0; + memset(themeLoc, 0x00, sizeof(THEME_LOC)); + + //Loop thru dungeon array + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) { + //Did we find a floor piece? + if ((dungeon[i][j] == floor) && (!random(0, freq))) { + //Check to see if theme room can fit + if (DRLG_WillThemeRoomFit(floor, i, j, minSize, maxSize, &themeW, &themeH)) { + //Do we want a random room size between max and min? + if (rndSize) { + int rv1, rv2, min, max; + min = minSize - 2; + max = maxSize - 2; + //Get a random width + rv1 = random(0, ((themeW-min)+1)); + rv2 = min + random(0, rv1); + if (rv2 < min || rv2 > max) themeW = min; + else themeW = rv2; + //Get a random height + rv1 = random(0, ((themeH-min)+1)); + rv2 = min + random(0, rv1); + if (rv2 < min || rv2 > max) themeH = min; + else themeH = rv2; + } + //Update the theme array + themeLoc[themeCount].x = i+1; + themeLoc[themeCount].y = j+1; + themeLoc[themeCount].width = themeW; + themeLoc[themeCount].height = themeH; + //Get transparency value + //Had to add special case in for L3 + if (leveltype == 3) { + DRLG_RectTrans( + ((i+2) << 1) + DIRTEDGED2, + ((j+2) << 1) + DIRTEDGED2, + (((i+themeW)-1) << 1) + DIRTEDGED2+1, + (((j+themeH)-1) << 1) + DIRTEDGED2+1); + } else DRLG_MRectTrans(i+1, j+1, (i+themeW), (j+themeH)); + themeLoc[themeCount].ttval = TransVal-1; + //Add the new theme room to the dungeon + DRLG_CreateThemeRoom(themeCount); + //Increment theme count + themeCount++; + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DRLG_HoldThemeRooms() +/*-----------------------------------------------------------------------** +** DESCRIPTION: Holds theme rooms created in dungeon types 2,3 & 4. +** INPUT: None +** RETURN: None +/*-----------------------------------------------------------------------*/ +{ + int i, x, y, xx, yy; + + if (themeCount > 0) { + for (i = 0; i < themeCount; i++) { + for (y = themeLoc[i].y; y < (themeLoc[i].y + themeLoc[i].height)-1; y++) { + for (x = themeLoc[i].x; x < (themeLoc[i].x + themeLoc[i].width)-1; x++) { + //Mega tiles to mini tiles + xx = (x << 1) + DIRTEDGED2; + yy = (y << 1) + DIRTEDGED2; + dFlags[xx][yy] |= BFLAG_SETPC; + dFlags[xx+1][yy] |= BFLAG_SETPC; + dFlags[xx][yy+1] |= BFLAG_SETPC; + dFlags[xx+1][yy+1] |= BFLAG_SETPC; + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL SkipThemeRoom( int x, int y ) +/*-----------------------------------------------------------------------** +** DESCRIPTION: Skips any existing theme rooms +** INPUT: None +** RETURN: TRUE = If not in a theme room +** FALSE = If in a theme room +/*-----------------------------------------------------------------------*/ +{ + int i; + + //Skip all L2, L3, & L4 themes rooms + for (i = 0; i < themeCount; i++) { + if ((x >= themeLoc[i].x-2 && x <= (themeLoc[i].x + themeLoc[i].width)+2) && + (y >= themeLoc[i].y-2 && y <= (themeLoc[i].y + themeLoc[i].height)+2)) + //We are inside a theme room + return FALSE; + } + + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitLevels() +{ + if (! leveldebug) { + currlevel = 0; + leveltype = 0; + setlevel = FALSE; + } +} + diff --git a/src/GENDUNG.H b/src/GENDUNG.H new file mode 100644 index 0000000..c866db4 --- /dev/null +++ b/src/GENDUNG.H @@ -0,0 +1,234 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/GENDUNG.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define LVLLENGTH 4 + +#define TLVL_START 0 +#define LVL1_START 1 +#define LVL2_START LVL1_START+LVLLENGTH +#define LVL3_START LVL2_START+LVLLENGTH +#define LVL4_START LVL3_START+LVLLENGTH +//HellFire JKE 7/29 +#define LVL5_START LVL4_START+LVLLENGTH +#define CRYPTSTART 21 +#define CRYPTEND 24 +#define HIVESTART 17 +#define HIVEEND 20 + +//#define NUMLEVELS ((4*LVLLENGTH)+1) +#define NUMLEVELS ((6*LVLLENGTH)+1) //HellFire JKE 7/29 +#define NUMSLEVELS 10 + +#define DIRTEDGE 32 +#define DIRTEDGED2 (DIRTEDGE/2) +#define DMAXX (80+DIRTEDGE) +#define DMAXY (80+DIRTEDGE) +#define MAXDUNX DMAXX +#define MAXDUNY DMAXY + +#define MDMAXX ((DMAXX-DIRTEDGE)/2) // Mega tile dungeon max (max div 2) +#define MDMAXY ((DMAXY-DIRTEDGE)/2) + +#define MAXTILES 2048 + +#define MAXMREND 128 + +#define NUMSPEEDCELS 64 +#define SPEEDSIZE NUMSPEEDCELS*16384 + +#define MAXMICRO 2048 + +#define MAXDIRT 32 + +#define NODRAW 0 +#define VIEWDRAW 1 +#define FULLDRAW 0xff + +#define SCRL_NONE 0 +#define SCRL_U 1 +#define SCRL_UR 2 +#define SCRL_R 3 +#define SCRL_DR 4 +#define SCRL_D 5 +#define SCRL_DL 6 +#define SCRL_L 7 +#define SCRL_UL 8 + +// bFlags bits +#define BFLAG_AUTOMAP 0x80 +#define BFLAG_VISIBLE 0x40 +#define BFLAG_PLRLR 0x20 +#define BFLAG_MONSTLR 0x10 +#define BFLAG_SETPC 0x08 +#define BFLAG_DEADPLR 0x04 + +// Set Piece bit used in all drlg's +#define SETP_BIT 0x80 // Non changeable set piece bit + +#define BFLAG_MONSTACTIVE 0x02 +#define BFLAG_MISSILE 0x01 + +#define BFMASK_AUTOMAP 0x7f +#define BFMASK_VISIBLE 0xbf +#define BFMASK_PLRLR 0xdf +#define BFMASK_MONSTLR 0xef +#define BFMASK_SETPC 0xf7 +//#define BFMASK_UNUSED 0xfb +//#define BFMASK_UNUSED 0xfd +#define BFMASK_MISSILE 0xfe + +#define WTYPE_NONE 0 +#define WTYPE_LEFT 1 +#define WTYPE_RIGHT 2 +#define WTYPE_ULC 3 +#define WTYPE_LRC 4 + +#define D_NORMAL 0 +#define D_NIGHTMARE 1 +#define D_HELL 2 + +/*-----------------------------------------------------------------------** +** Macros +**-----------------------------------------------------------------------*/ +#define MegaToMini(M) ((M << 1) + DIRTEDGED2) +#define MiniToMega(m) ((m - DIRTEDGED2) >> 1) + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + byte strig; + byte s1; + byte s2; + byte s3; + byte nv1; + byte nv2; + byte nv3; +} ShadowStruct; + +typedef struct { + int _sxoff; // Smooth scroll x,y offsets + int _syoff; + int _sdx; // Delta between plr and view x,y + int _sdy; + int _sdir; // Direction +} ScrollStruct; + +typedef struct THEME_LOC { + int x; //Upper left coord + int y; //Upper left coord + int ttval; //Transparency value + int width; //Room width + int height; //Room height +} THEME_LOC; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern byte dungeon[MDMAXX][MDMAXY]; +extern byte pdungeon[MDMAXX][MDMAXY]; +extern byte dflags[MDMAXX][MDMAXY]; + +extern int setpc_x, setpc_y, setpc_w, setpc_h; +extern byte *pSetPiece; +extern BOOL setloadflag; + +extern "C" { + extern BYTE *pDungeonCels; + extern BYTE *pSpeedCels; + extern long microoffset[MAXMREND][16]; + extern byte nWTypeTable[MAXTILES+1]; +} + +extern BYTE *pSpecialCels; +extern BYTE *pMegaTiles; +extern BYTE *pMiniTiles; + +extern BYTE nBlockTable[MAXTILES+1]; +extern BYTE nSolidTable[MAXTILES+1]; +extern BYTE nTransTable[MAXTILES+1]; +extern BYTE nMissileTable[MAXTILES+1]; +extern BYTE nTrapTable[MAXTILES+1]; + +extern int dminx, dminy, dmaxx, dmaxy; + +extern int gnDifficulty; + +extern BYTE currlevel; +extern BYTE leveltype; +extern BYTE setlevel; +extern BYTE setlvlnum; +extern BYTE setlvltype; + +extern int ViewX, ViewY; +extern int ViewDX, ViewDY; +extern int ViewBX, ViewBY; +extern ScrollStruct ScrollInfo; + +extern int LvlViewX, LvlViewY; + +extern int btmbx, btmby; +extern int btmdx, btmdy; + +extern int MicroTileLen; + +extern char TransVal; +extern BYTE TransList[256]; + +extern int dPiece[MAXDUNX][MAXDUNY]; // Tile # + +typedef struct { WORD mt[16]; } MICROS; +extern MICROS dMT[MAXDUNX][MAXDUNY]; // Micro Tiles +extern MICROS dMT2[MAXDUNX*MAXDUNY]; + +extern char dTransVal[MAXDUNX][MAXDUNY]; // Transparent active value +extern char dLight[MAXDUNX][MAXDUNY]; // Current light value +extern char dSaveLight[MAXDUNX][MAXDUNY]; // Static light value +extern char dFlags[MAXDUNX][MAXDUNY]; // Flags for Solid collision, etc. +extern char dPlayer[MAXDUNX][MAXDUNY]; // Player +extern int dMonster[MAXDUNX][MAXDUNY]; // Monster +extern char dDead[MAXDUNX][MAXDUNY]; // Dead plr/monster +extern char dObject[MAXDUNX][MAXDUNY]; // Objects +extern char dItem[MAXDUNX][MAXDUNY]; // Items +extern char dMissile[MAXDUNX][MAXDUNY]; // Missiles (0 = none, # = missile, -1 = two or more) +extern char dSpecial[MAXDUNX][MAXDUNY]; // Second layer of tiling +extern int themeCount; +extern THEME_LOC themeLoc[50]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +int CalcRot(int x, int y); +void SetDungeonMicros(); +void FillSolidBlockTbls (); + +void DRLG_InitTrans(); +void DRLG_MRectTrans(int, int, int, int); +void DRLG_MCopyTrans(int, int, int, int, BOOL, BOOL, BOOL, BOOL); +void DRLG_RectTrans(int, int, int, int); +void DRLG_CopyTrans(int, int, int, int); +void DRLG_ListTrans(int, byte *); +void DRLG_AreaTrans(int, byte *); +void DRLG_InitSetPC(); +void DRLG_SetPC(); +void Make_SetPC(int x, int y, int w, int h); +void DrawDungMiniMap(unsigned char floor); +BOOL DRLG_WillThemeRoomFit(int, int, int, int, int, int *, int *); +void DRLG_CreateThemeRoom(int); +void DRLG_PlaceThemeRooms(int, int, int, int, BOOL); +void DRLG_HoldThemeRooms(); +BOOL SkipThemeRoom(int, int); diff --git a/src/GMENU.CPP b/src/GMENU.CPP new file mode 100644 index 0000000..510df0e --- /dev/null +++ b/src/GMENU.CPP @@ -0,0 +1,527 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Game Menu file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/GMENU.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "gendung.h" +#include "gamemenu.h" +#include "scrollrt.h" +#include "engine.h" +#include "effects.h" + + +//****************************************************************** +// extern +//****************************************************************** +void RedBack(); + + +//****************************************************************** +// kerning +//****************************************************************** +#define KERNSPACE 2 +static const BYTE mfonttrans[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 0, 37, 49, 38, 0, 39, 40, 47, 42, 43, 41, 45, 52, 44, 53, 55, // 32-47 + 36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 51, 50, 0, 46, 0, 54, // 48-63 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 64-79 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 0, 43, 0, 0, // 80-95 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 96-111 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 20, 0, 21, 0, 0 // 112-127 +}; +static const BYTE mfontkern[56] = { 18, // Space/Invalid + 33, 21, 26, 28, 19, 19, 26, 25, 11, 12, 25, 19, 34, 28, 32, 20, // a-p + 32, 28, 20, 28, 36, 35, 46, 33, 33, 24, // q-z + 11, 23, 22, 22, 21, 22, 21, 21, 21, 32, // 1-0 + 10, 20, 36, 31, 17, 13, 12, 13, 18, 16, 11, 20, 21, 11, 10, 12, 11, 21, 23 // misc +}; + + +//****************************************************************** +// private data +//****************************************************************** +static BYTE sgbGameSpin; +static BYTE sgbTitleAnimate; +static BYTE * sgpLogo; +static BYTE * sgpSpinCels; +static BYTE * sgpMenuCels; +static BYTE * sgpSliderCels; +static BYTE * sgpBarCels; +static TMenuItem * sgpMenu; +static TMenuUpdateFcn sgfnMenuUpdateFcn; +static TMenuItem * sgpCurrItem; +static DWORD sgdwMenuItems; +static long sglSpinnerTime; +static long sglTitleTime; +static BYTE sgbTracking; + +#define MENU_STARTY 320 +#define MENU_CLICKY (MENU_STARTY - 203) +#define MENU_LINEHGT 45 +#define SLIDER_WDT 256 +#define SLIDER_ITEM_WDT 27 +#define SLIDER_TOTAL_WDT 490 + +#define ENABLE_LVAL 0 +#define DISABLE_LVAL 15 + +#define MIN_SLIDER_TICKS 2 +#define SLIDER_TICK_SHIFT 12 +#define MAX_SLIDER_TICKS 0xfff +#define mf_SLIDER_VAL_MASK 0x00000fff +#define mf_SLIDER_TICK_MASK 0x00fff000 + +#define SPINNER_TIME 25 // milliseconds +#define TITLE_TIME 25 // milliseconds + + +//****************************************************************** +//****************************************************************** +static void DrawBigFontXY(int x, int y,const char * pszStr) { + app_assert(pszStr); + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = mfonttrans[c]; + if (c != 0) DrawCelL(x, y, sgpMenuCels, c, 46); + x += mfontkern[c] + KERNSPACE; + } +} + + +//****************************************************************** +//****************************************************************** +void DrawPause() { + if (currlevel != 0) RedBack(); + if (! sgpMenu) { + nLVal = 0; // set light level + DrawBigFontXY(316, 336, "Pause"); + } +} + + +//****************************************************************** +//****************************************************************** +void gmenu_free() { + DiabloFreePtr(sgpLogo); + DiabloFreePtr(sgpMenuCels); + DiabloFreePtr(sgpSpinCels); + DiabloFreePtr(sgpSliderCels); + DiabloFreePtr(sgpBarCels); +} + + +//****************************************************************** +//****************************************************************** +void gmenu_init() { + sgbGameSpin = 1; + sgbTitleAnimate = 1; + sgpMenu = NULL; + sgpCurrItem = NULL; + sgfnMenuUpdateFcn = NULL; + sgdwMenuItems = 0; + sgbTracking = FALSE; + + app_assert(! sgpLogo); + //sgpLogo = LoadFileInMemSig("Data\\Diabsmal.CEL",NULL,'MENU'); + sgpLogo = LoadFileInMemSig("Data\\hf_logo3.CEL",NULL,'MENU'); + sgpMenuCels = LoadFileInMemSig("Data\\BigTGold.CEL",NULL,'MENU'); + sgpSpinCels = LoadFileInMemSig("Data\\PentSpin.CEL",NULL,'MENU'); + sgpSliderCels = LoadFileInMemSig("Data\\option.CEL",NULL,'MENU'); + sgpBarCels = LoadFileInMemSig("Data\\optbar.CEL",NULL,'MENU'); +} + + +//****************************************************************** +//****************************************************************** +BOOL gmenu_is_on() { + return sgpMenu != NULL; +} + + +//****************************************************************** +//****************************************************************** +static void gmenu_change(BOOL bNext) { + if (! sgpCurrItem) return; + sgbTracking = FALSE; + for (DWORD d = sgdwMenuItems; d--; ) { + if (bNext) { + // next item + sgpCurrItem++; + + // wrap at end of list + if (! sgpCurrItem->fnMenu) + sgpCurrItem = sgpMenu; + } + else { + // wrap at beginning of list + if (sgpCurrItem == sgpMenu) + sgpCurrItem = sgpMenu + sgdwMenuItems; + + // prev item + sgpCurrItem--; + } + + if (sgpCurrItem->dwFlags & mf_ENABLED) { + if (d) PlaySFX(IS_TITLEMOV); + break; + } + } +} + + +//****************************************************************** +//****************************************************************** +void gmenu_set_menu(TMenuItem * pMenuItems,TMenuUpdateFcn fnUpdate) { + PauseMode = 0; + + sgpMenu = pMenuItems; + sgbTracking = FALSE; + sgfnMenuUpdateFcn = fnUpdate; + if (sgfnMenuUpdateFcn) sgfnMenuUpdateFcn(sgpMenu); + + // calculate number of items in menu + sgdwMenuItems = 0; + if (sgpMenu) { + for (TMenuItem * pItem = sgpMenu; pItem->fnMenu; pItem++) + sgdwMenuItems++; + } + + // move to the first active item in the menu + sgpCurrItem = sgpMenu + sgdwMenuItems - 1; + gmenu_change(TRUE); +} + + +//****************************************************************** +//****************************************************************** +static void DrawBar(DWORD x,DWORD y,DWORD wdt,DWORD hgt) { + app_assert(gpBuffer); + BYTE * pbDst = gpBuffer + nBuffWTbl[y] + x; + while (hgt--) { + FillMemory(pbDst,wdt,0xcd); + pbDst -= 768; + } +} + + +//****************************************************************** +//****************************************************************** +static DWORD gmenu_calc_item_width(const TMenuItem * pItem) { + // hardcode the size of sliders so they all justify uniformly + // so that the slider bars line up vertically + if (pItem->dwFlags & mf_SLIDER) + return SLIDER_TOTAL_WDT; + + DWORD wdt = 0; + const char * pszStr = pItem->pszStr; + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = mfonttrans[c]; + wdt += mfontkern[c] + KERNSPACE; + } + wdt -= KERNSPACE; + return wdt; +} + + +//****************************************************************** +//****************************************************************** +static void gmenu_draw_item(const TMenuItem * pItem,int yPos) { + DWORD wdt = gmenu_calc_item_width(pItem); + + if (pItem->dwFlags & mf_SLIDER) { + int xPos = 640/2 + wdt/2 + 43 - SLIDER_WDT - SLIDER_ITEM_WDT; + DrawCel(xPos + 0,yPos - 10,sgpBarCels, 1, 287); + DWORD dwLen = pItem->dwFlags & mf_SLIDER_VAL_MASK; + + // scale 0..ticks to 0..SLIDER_WDT + DWORD dwTicks = pItem->dwFlags & mf_SLIDER_TICK_MASK; + dwTicks >>= SLIDER_TICK_SHIFT; + if (dwTicks < MIN_SLIDER_TICKS) dwTicks = MIN_SLIDER_TICKS; + dwLen *= SLIDER_WDT; + dwLen /= dwTicks; + + DrawBar(xPos + 2,yPos - 12,dwLen + SLIDER_ITEM_WDT/2,28); + xPos += dwLen; + DrawCel(xPos + 2,yPos - 12,sgpSliderCels, 1, 27); + } + + // draw string with lighting + int xPos = 640/2 - wdt/2 + 64; + nLVal = (pItem->dwFlags & mf_ENABLED) ? ENABLE_LVAL : DISABLE_LVAL; + DrawBigFontXY(xPos, yPos, pItem->pszStr); + + if (pItem == sgpCurrItem) { + DrawCel(xPos - 54, yPos + 1, sgpSpinCels, sgbGameSpin, 48); + DrawCel(xPos + wdt + 4, yPos + 1, sgpSpinCels, sgbGameSpin, 48); + } +} + + +//****************************************************************** +//****************************************************************** +void gmenu_draw() { + if (! sgpMenu) return; + if (sgfnMenuUpdateFcn) sgfnMenuUpdateFcn(sgpMenu); + + const TMenuItem * pItem; + long lCurrTime = (long) GetTickCount(); + //DrawCel(236, 262, sgpLogo, 1, 296); + if (lCurrTime - sglTitleTime > TITLE_TIME){ + ++sgbTitleAnimate; + if (sgbTitleAnimate > 16) sgbTitleAnimate = 1; + sglTitleTime = lCurrTime; + } + DrawCel(169, 262, sgpLogo, sgbTitleAnimate, 430); + + // draw items + DWORD yPos = MENU_STARTY; + for (pItem = sgpMenu; pItem->fnMenu; pItem++) { + gmenu_draw_item(pItem,yPos); + yPos += MENU_LINEHGT; + } + + // adjust spinner + if (lCurrTime - sglSpinnerTime > SPINNER_TIME) { + sgbGameSpin++; + if (sgbGameSpin == 9) sgbGameSpin = 1; + sglSpinnerTime = lCurrTime; + } +} + + +//****************************************************************** +//****************************************************************** +static void gmenu_slider(BOOL bNext) { + if (! (sgpCurrItem->dwFlags & mf_SLIDER)) return; + + LONG lVal = sgpCurrItem->dwFlags & mf_SLIDER_VAL_MASK; + LONG lTicks = sgpCurrItem->dwFlags & mf_SLIDER_TICK_MASK; + lTicks >>= SLIDER_TICK_SHIFT; + if (bNext) { + if (lVal == lTicks) return; + lVal++; + } + else { + if (! lVal) return; + lVal--; + } + + sgpCurrItem->dwFlags &= ~mf_SLIDER_VAL_MASK; + sgpCurrItem->dwFlags |= lVal; + sgpCurrItem->fnMenu(FALSE); +} + + +//****************************************************************** +//****************************************************************** +BOOL gmenu_key(WPARAM wKey) { + + if (! sgpMenu) return FALSE; + app_assert(sgpCurrItem); + + switch (wKey) { + case VK_SPACE: + // allow spacebar + return FALSE; + + case VK_LEFT: + gmenu_slider(FALSE); + break; + + case VK_RIGHT: + gmenu_slider(TRUE); + break; + + case VK_UP: + gmenu_change(FALSE); + break; + + case VK_DOWN: + gmenu_change(TRUE); + break; + + case VK_RETURN: + app_assert(sgpCurrItem); + if (sgpCurrItem->dwFlags & mf_ENABLED) { + PlaySFX(IS_TITLEMOV); + sgpCurrItem->fnMenu(TRUE); + } + break; + + case VK_ESCAPE: + PlaySFX(IS_TITLEMOV); + gmenu_set_menu(NULL,NULL); + break; + } + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static BYTE gmenu_mouse_in_slider(LONG * plOffset) { + app_assert(plOffset); + *plOffset = 640/2 + SLIDER_TOTAL_WDT/2 - SLIDER_WDT - SLIDER_ITEM_WDT; + if (MouseX < *plOffset) { + *plOffset = 0; + return FALSE; + } + else if (MouseX > *plOffset + SLIDER_WDT) { + *plOffset = SLIDER_WDT; + return FALSE; + } + + *plOffset = MouseX - *plOffset; + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +BOOL gmenu_mousemove() { + if (! sgbTracking) return FALSE; + app_assert(sgpCurrItem); + + // get position = 0..SLIDER_WDT + LONG lOffset; + gmenu_mouse_in_slider(&lOffset); + + // scale to 0..ticks + LONG lTicks = sgpCurrItem->dwFlags & mf_SLIDER_TICK_MASK; + lTicks >>= SLIDER_TICK_SHIFT; + lOffset *= lTicks; + lOffset /= SLIDER_WDT; + + // set item value + sgpCurrItem->dwFlags &= ~mf_SLIDER_VAL_MASK; + sgpCurrItem->dwFlags |= lOffset; + sgpCurrItem->fnMenu(FALSE); + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +BOOL gmenu_click(BOOL bMouseDown) { + // handle mouseup + if (! bMouseDown) { + if (! sgbTracking) return FALSE; + sgbTracking = FALSE; + return TRUE; + } + + if (! sgpMenu) return FALSE; + if (MouseY >= 352) return FALSE; + + int nItem = MouseY - MENU_CLICKY; + if (nItem < 0) return TRUE; + nItem /= MENU_LINEHGT; + if ((DWORD) nItem >= sgdwMenuItems) return TRUE; + + // only click menu item if it is enabled + TMenuItem * pItem = sgpMenu + nItem; + if (! (pItem->dwFlags & mf_ENABLED)) return TRUE; + + DWORD wdt = gmenu_calc_item_width(pItem); + if ((DWORD) MouseX < 640/2-wdt/2) return TRUE; + if ((DWORD) MouseX > 640/2+wdt/2) return TRUE; + + // set current item + sgpCurrItem = pItem; + PlaySFX(IS_TITLEMOV); + + if (pItem->dwFlags & mf_SLIDER) { + LONG lTemp; + sgbTracking = gmenu_mouse_in_slider(&lTemp); + gmenu_mousemove(); + } + else { + sgpCurrItem->fnMenu(TRUE); + } + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +void gmenu_set_enable(TMenuItem * pMenuItem,BOOL bEnable) { + app_assert(pMenuItem); + if (bEnable) + pMenuItem->dwFlags |= mf_ENABLED; + else + pMenuItem->dwFlags &= ~mf_ENABLED; +} + + +//****************************************************************** +//****************************************************************** +void gmenu_set_slider(TMenuItem * pItem,LONG lMin,LONG lMax,LONG lVal) { + app_assert(pItem); + + LONG lTicks = pItem->dwFlags & mf_SLIDER_TICK_MASK; + lTicks >>= SLIDER_TICK_SHIFT; + if (lTicks < MIN_SLIDER_TICKS) lTicks = MIN_SLIDER_TICKS; + + // make lVal zero-based + lVal -= lMin; + + // scale to slider + lVal *= lTicks; + lVal += (lMax - lMin - 1) / 2; + lVal /= lMax - lMin; + + // store into menu item + pItem->dwFlags &= ~mf_SLIDER_VAL_MASK; + pItem->dwFlags |= lVal; +} + + +//****************************************************************** +//****************************************************************** +LONG gmenu_get_slider(const TMenuItem * pItem,LONG lMin,LONG lMax) { + app_assert(pItem); + + // get value from menu item + LONG lVal = pItem->dwFlags & mf_SLIDER_VAL_MASK; + + LONG lTicks = pItem->dwFlags & mf_SLIDER_TICK_MASK; + lTicks >>= SLIDER_TICK_SHIFT; + if (lTicks < MIN_SLIDER_TICKS) lTicks = MIN_SLIDER_TICKS; + + // restore scale + lVal *= lMax - lMin; + lVal += (lTicks - 1) / 2; + lVal /= lTicks; + + // re-base + lVal += lMin; + + return lVal; +} + + +//****************************************************************** +//****************************************************************** +void gmenu_set_slider_ticks(TMenuItem * pItem,DWORD dwTicks) { + app_assert(pItem); + app_assert(dwTicks >= MIN_SLIDER_TICKS && dwTicks <= MAX_SLIDER_TICKS); + + pItem->dwFlags &= ~mf_SLIDER_TICK_MASK; + pItem->dwFlags |= mf_SLIDER_TICK_MASK & (dwTicks << SLIDER_TICK_SHIFT); +} diff --git a/src/HELLFRUI.LIB b/src/HELLFRUI.LIB new file mode 100644 index 0000000..984ab8a Binary files /dev/null and b/src/HELLFRUI.LIB differ diff --git a/src/HELP.CPP b/src/HELP.CPP new file mode 100644 index 0000000..29cc8d4 --- /dev/null +++ b/src/HELP.CPP @@ -0,0 +1,1106 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Help file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/HELP.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "help.h" +#include "engine.h" +#include "control.h" +#include "gendung.h" +#include "items.h" +#include "stores.h" +#include "minitext.h" +#include "cursor.h" +#include "control.h" +#include "scrollrt.h" + +#include "monster.h" +#include "objects.h" + +BOOL helpflag; // F1 help + +HelpStrStruct helpstr[MAXHELPSTRS]; +HelpLineStruct helpline[MAXHELPLINES]; + +int numhelpstrs; +int numhelplines; + +int helpx, helpy; + +int help_cy, help_end; + +/*-----------------------------------------------------------------------* +** Microsoft demo text +/*-----------------------------------------------------------------------* + +static const char helpdata[] = { +"Welcome mortals! Hellfire is real-time action in a dark, gothic role-playing game. " +"Prepare to be taken into the very depths of hell on your quest to destroy the Lord " +"of all Evil - Diablo.|" +"|" +"This Help section is designed to make your playing experience as easy as possible. " +"Let's get started...|" +"|" +"$Keyboard Shortcuts:|" +"Hellfire can be played exclusively by using the mouse controls. There are times, however, " +"when you may want to use shortcuts to some commands by using the keyboard. These " +"shortcuts are listed below:|" +"|" +"F1: Open the Help Screen|" +"Esc: Displays the main menu|" +"Tab: Displays the Auto-map|" +"Space: Removes all screens and map from the play area|" +"S: Opens Spell selection pop-up menu|" +"I: Opens the Inventory screen|" +"C: Opens the Character screen|" +"Z: Zooms the game screen in and out|" +"F: Reduces the brightness of the screen|" +"G: Increases the brightness of the screen|" +"Shift + Left Click: Fire any Bow without moving|" +"1,2,3: While the Spell selection pop-up menu is active, these keys will " +"set that number as a hot-key selection (pressing the number will " +"automatically ready that spell).|" +"|" +"$Movement:|" +"Movement is controlled by the mouse. The gauntlet on the screen is your cursor. " +"Use this to indicate the destination of your character and then left-click to move " +"to that area.|" +"|" +"$Selecting Items:|" +"What you can interact with within the game is easily identifiable. Simply move the " +"cursor over any object or creature. If the object can be picked up, attacked, activated " +"or used in any way, it will be immediately outlined and highlighted with a description of " +"the object appearing in the text area on the control panel.|" +"|" +"Example: If you select a door and then left-click the character will walk to the door and " +"open it. A second click closes the door. If you left-click on a selected weapon, the " +"character will walk over to it and put it in his inventory. If you left-click on a selected " +"creature....|" +"|" +"$Combat:|" +"Combat is initiated by left-clicking on a creature that has been selected. Left-clicking " +"on a creature that you are next to will cause your character to attack it immediately. " +"Left-clicking on a distant creature will cause the character to walk to the creature and " +"then attack. This will work if your character has a melee weapon (sword, mace, club, etc.), " +"just a shield or is unarmed.|" +"|" +"If your character is equipped with a bow, left-clicking will fire an arrow at a selected " +"creature. Holding down the shift key and then left-clicking allows the character to fire " +"the bow without accidentally moving.|" +"|" +"$Picking up Objects:|" +"If you left-click an item - such as a weapon, armor, scroll or book - your character will " +"move to that item and add it to his inventory automatically. If you do not have enough " +"room in your inventory for the item, it will fall from your grasp and you will receive a " +"message that more room is needed. Open your inventory screen and try re-arranging or " +"removing items to carry what you really want or need.|" +"|" +"$Inventory:|" +"You can toggle the Inventory screen on and off by clicking the INV> button on the control " +"panel. Items may be moved around in your inventory by selecting them and then left-clicking " +"to pick them up. When you pick up an item while in the inventory screen, your cursor " +"changes into the item. You can then place this item into empty spaces in your inventory, " +"swap them with other items in your inventory or equip them.|" +"|" +"If you have an item that you no longer wish to carry, simply grab the item from your " +"inventory and then left-click in the play area to drop it.|" +"|" +"$Equipping Items:|" +"Equipping items is done by picking up an item from your inventory and placing it in the " +"appropriate boxes on the figure in the Inventory screen. Weapons and shields go into the " +"large spaces to the right or left of the figure. Two-handed weapons such as bows and " +"axes preclude the use of a shield and will take up both of these large spaces.|" +"|" +"Cloaks, robes, capes and all other armor must go in the central torso slot of the figure.|" +"|" +"Helmets and caps go in the head box and rings go into the small boxes at the hands of " +"the figure.|" +"|" +"To change items that your character has equipped, pick up a new item and place it on top " +"of the item you wish to remove. Your character will automatically swap the items and the " +"cursor will now change into the item that was in that box.|" +"|" +"$Usable Items:|" +"Potions, elixirs, oils and books are classified as usable items. These items can be used " +"by right-clicking on them in the inventory screen. Any one item can also be 'readied' in " +"the same way as spells. To ready an item, left-click the 'select current item' button to " +"the left of the red health ball on the control panel. " +"A pop-up menu will activate that you can scroll through to choose an item to be readied. " +"Left-click when the desired item is selected and you will see that item displayed on the " +"button. To use a readied item, simply right-click on the 'select current item' button or " +"press the Enter key on your keyboard.|" +"|" +"$Item Information:|" +"All items in Hellfire share certain common attributes. These are damage, durability, charges " +"and minimum requirements.|" +"|" +"Damage: This is represented by a range that shows the minimum and maximum damage that item " +"can inflict. An sword that has a (2-6) after its name does a minimum of two damage and a " +"maximum of six when it hits. Damage can be modified by the quality of the weapon, the " +"characters strength and magic.|" +"|" +"Durability: This is how long an item can last before it is rendered useless. This is " +"represented by a ratio of current durability to maximum durability. A shield that has a " +"durability of 15/20 would have 15 points of damage it could take from use before it was " +"rendered useless. Maximum durability can be affected by the quality of the item, magic or " +"repairs upon the item. Minimum durability can be raised by repairing an item.|" +"When the durability of an item you are wearing or wielding drops to 5 points or below, " +"an icon of the image appears in the lower left corner above the control panel. These icons " +"warn the player that the item is about to break and needs to be repaired soon.|" +"|" +"Charges: Some items have charges associated with. These represent how many times that item " +"can be used to cast the spell or affect indicated in its description. Charges are " +"represented by a ratio of charges left to maximum charges. A staff that has charges of " +"2/5 could be used to cast 2 more spells before it was rendered powerless (it could still " +"be used to attack with physically). Maximum charges can be affected by the magic or " +"recharges cast upon the item. Minimum charges can be raised by recharging the item.|" +"|" +"Minimum Requirements: These are the minimum requirements that a character must meet to " +"wield the item. The more powerful an item is, the higher the minimum requirements will be. " +"If a character does not meet these requirements, he will be unable to equip the item and " +"its name and information will be displayed in red. The item artwork will also have a red " +"tint to it in the Inventory screen.|" +"|" +"There are also three classes of items in Hellfire. These are mundane, magic and Unique:|" +"|" +"Mundane items have no special attributes and their information is displayed in white text.|" +"|" +"Magic Items are represented by blue text descriptions. Use the Identify spell to determine " +"their exact properties and attributes.|" +"|" +"Unique items are fully identified when you obtain them. Information on these items is " +"displayed in gold.|" +"|" +"$Skills:|" +"Important Note - Skills do not work in the town in this pre-release demo. Left-clicking " +"on the 'select current spell' button will open a pop-up menu that will allow you to ready " +"a skill or spell for use. To use a readied skill or spell, simply right-click in the main " +"play area.|" +"|" +"Skills are the innate abilities of your character. These skills are different depending on " +"what class you choose and they require no mana to use.|" +"|" +"The Warrior starts the game with the Repair skill. The Repair Skill icon appears as the " +"'select current spell' button found next to the blue Mana sphere on the control panel. " +"When the skill is useable, the button will be gold in color. The game starts with the " +"button grayed out as you cannot repair or cast spells in the town.|" +"|" +"The Repair skill allows the Warrior to fix an item that has been worn by use or is damaged " +"in combat. To repair an item, have the Repair Skill selected (your character starts the " +"game this way) and right-click the mouse as if you were casting a spell. Your cursor will " +"change into a hammer shaped cursor that you will use to select the item to be repaired. " +"Repairing an item will decrease the maximum durability of that item, but can be done while " +"in the labyrinth.|" +"|" +"The Blacksmith can repair items, but it will cost you gold. When the Blacksmith repairs " +"an item, it does not decrease the maximum durability of the item.|" +"|" +"$Spells:|" +"Important Note - Spells do not work in the town in this pre-release demo.|" +"|" +"Spells are magical effects that can be cast from a scroll, a staff or memorized from a " +"book. Spells may or may not require mana to use and are available to all classes.|" +"|" +"Spells cast from an item (a scroll or staff) cost no mana to use, but are limited by " +"the number of charges available on the item. Scrolls always have one charge while staves " +"may have multiple charges. To use spells from a staff, you must equip the staff to cast " +"the spell. Spells that are cast from staves are represented by an orange icon button in " +"the 'select current spell' button area. Scrolls are represented by a red button.|" +"|" +"Memorized spells cost mana to cast, but they can be used as long as the character has " +"mana to power them. The Warrior starts the game with no memorized spells. If the " +"character finds a book in the labyrinth, he can memorize the spell written in that " +"book by opening the Inventory screen and right-clicking on the book. This will make " +"the spell always available to the character for casting. Memorized spells are denoted " +"by a blue button.|" +"|" +"While some spells affect the caster, some spells require a target. These targeted spells " +"are cast in the direction that you indicate with your cursor on the play area. If you " +"highlight a creature, you will cast that spell at that creature. Not all items within " +"the labyrinth can be targeted.|" +"|" +"Example: A fireball spell will travel at the creature or to the location you right-click " +"on. A Healing spell will simply add health to your character while diminishing his " +"available mana and requires no targeting.|" +"|" +"You can also set a spell or scroll as a Hot Key position for instant selection. Start " +"by opening the pop-up menu as described in the skill section above. Assign Hot Keys by " +"hitting the 1, 2 or 3 keys on your keyboard after scrolling through the available spells " +"and skills and stopping on the one you wish to assign.|" +"|" +"$Health and Mana:|" +"The two spheres in the control panel display your health and mana. Your health is a " +"measure of how much life force your character has. The red sphere of fluid on the left " +"side of the control panel represents the health of your character. When the fluid is " +"gone - your character is dead.|" +"|" +"The blue fluid on the right side of the control panel represents your character's " +"available mana. Mana is the magical force used by your character to cast spells. When " +"the liquid in the sphere is low or depleted, you may be unable to cast some (or all) of " +"your spells.|" +"|" +"$Control Panel:|" +"The control panel is how you receive detailed information in Hellfire and interact with " +"much of your surroundings. Here is a quick run-down of the control panel areas and their " +"use:|" +"|" +"INV: This button is used to access your Inventory screen|" +"CHAR: This button is used to access your Character Statistics screen|" +"Current Item: This is the item that has been readied for immediate use|" +"Current Spell: This is the spell that has been readied for immediate casting|" +"Health Sphere: This is the amount of health your character currently has|" +"Mana Sphere: This is the amount of mana your character currently has|" +"Automap: This button activates the mapping overlay|" +"Main Menu: This activates the main menu screen|" +"Multiplayer Message: Unavailable in the pre-release demo|" +"Message Filter: Unavailable in the pre-release demo|" +"Description Area: This is where any important information about creatures or items " +"you can interact with is displayed.|" +"|" +"Character Info:|" +"Toggle the Character Statistics Screen on and off by clicking the button on the control " +"panel. Items may be moved around in your inventory by selecting them and then left-clicking " +"to pick them up. When you pick up an item while in the inventory screen, your cursor " +"changes into the item. You can then place this item into empty spaces in your inventory, " +"swap them with other items in your inventory or equip them.|" +"|" +"If you have an item that you no longer wish to carry, simply grab the item from your " +"inventory and then left-click in the play area to drop it.|" +"|" +"$Equipping Items:|" +"To equip an item, open the inventory screen and pick up the desired item, either from " +"play or from your inventory, placing it in the appropriate box on the figure in the " +"inventory screen. Weapons and shields go into the large spaces to the right or left of " +"the figure. Two-handed weapons such as bows and axes preclude the use of a shield and " +"will take up both of these large spaces.|" +"|" +"Cloaks, robes, capes and all other armor must go in the central torso slot of the figure. |" +"|" +"Helmets and caps go in the box over the head of the character.|" +"|" +"Rings go into the small boxes at the hands of the figure.|" +"|" +"Amulets go into the small box at the next to the neck of the figure.|" +"|" +"To change items that your character has equipped, pick up a new item and place it on top " +"of the item you wish to remove. Your character will automatically swap the items and the " +"cursor will now change into the item that was in that box.|" +"|" +"$Usable Items:|" +"Potions, elixirs and books are classified as usable items. These items can be used by " +"right-clicking on them in the inventory screen. Books are too large to be placed in the " +"belt, but any potions or scrolls that are put there can also be used by pressing the " +"corresponding number on the keyboard.|" +"|" +"$Gold:|" +"You can select a specific amount of gold to drop by right clicking on a pile of gold in " +"your inventory. A dialog will appear that allows you to select a specific amount of gold " +"to take. When you have entered that number, your cursor will change into that amount of gold.|" +"|" +"$Item Information:|" +"Many items in Hellfire share certain common attributes. These are damage, durability, " +"charges and minimum requirements..|" +"|" +"Damage: This is represented by a range that indicates the minimum and maximum damage " +"that item can inflict. A short sword has a (2-6) after its name, meaning it inflicts a " +"minimum of two damage and a maximum of six when it hits. Damage can be modified by the " +"quality of the weapon, the character's strength and magical effects.|" +"|" +"Durability: This is the amount of damage that an item can take before it is rendered " +"useless. Durability is represented by a ratio of current durability to maximum " +"durability. A shield that has a durability of 15/20 would still have 15 points of " +"damage it could take from use before it was rendered useless. Maximum durability can " +"be affected by the quality of the item, enchantments or repairs made upon the item. " +"The minimum durability can be raised by repairing an item.|" +"|" +"Charges: Some items have charges associated with them. Charges indicate how many times " +"that item can be used to cast the spell or affect indicated in its description. Charges " +"are represented by a ratio of charges left to maximum charges. A staff that has charges " +"listed as 2/5 could be used to cast 2 more spells before it was rendered powerless. It " +"could still be used to attack with as a physical weapon, however. Maximum charges can " +"be affected by the magic or recharges cast upon the item. Minimum charges can be raised " +"by recharging the item.|" +"|" +"Minimum Requirements: These are the minimum requirements that a character must meet to " +"wield the item. The more powerful an item is, the higher the minimum requirements will " +"be. If a character does not meet these requirements, he will be unable to equip the " +"item and its name and information will be displayed in red. The item artwork will also " +"have a red tint in the Inventory screen.|" +"|" +"$Items Classes:|" +"There are three classes of items in Hellfire - Mundane, Magic and Unique:|" +"|" +"Mundane items have no special attributes. Their information is displayed in white text.|" +"|" +"Magic Items are represented by blue names and text descriptions. Use the Identify spell " +"or speak to Cain in town to determine their exact properties and attributes.|" +"|" +"Unique items are represented by gold names and text descriptions. Use the Identify spell " +"or speak to Cain in town to determine their exact properties and attributes.|" +"|" +"$Skills & Spells:|" +"You can access your list of skills and spells by left-clicking on the SPELLS button in " +"the interface bar. This 'Spellbook' contains all of the skills and spells that your " +"character knows. Spells available through staffs are also listed here. Left-clicking " +"on the Icon of the spell you wish to ready will place it in the 'select current spell' " +"icon/area and set it as the current readied spell. A readied spell may be cast by simply " +"right-clicking in the play area.|" +"|" +"Left-clicking on the 'select current spell' button will also open a 'Speedbook' menu " +"that also allows you to ready a skill or spell for use. To use a readied skill or " +"spell, simply right-click in the main play area.|" +"|" +"Skills are the innate abilities of your character. These skills are different depending " +"on what class you choose and require no mana to use.|" +"|" +"Warrior:|" +"The Warrior has the skill of Repair Items. This allows him to fix an item that has been " +"worn by use or is damaged in combat. To accomplish this, select the Repair Skill through " +"the Spellbook or Speedbook and right-click the mouse as if you were casting a spell. " +"Your cursor will change into a Hammer Icon that you will use to select the item to be " +"repaired. Although Repairing an item in this way will decrease the maximum durability " +"of that item, it can be done without leaving the labyrinth.|" +"|" +"The Blacksmith can also repair items for a price. When the Blacksmith performs this " +"service, it does decrease the maximum durability of the item.|" +"|" +"Rogue:|" +"The Rogue has the skill of Disarm Traps. This allows her to not only remove traps, but " +"also acts as a 'sixth sense' that warns her of where these trapped items are located. " +"To accomplish this, select the Disarm Trap skill through the Spellbook or Speedbook and " +"right-click the mouse as if you were casting a spell. Your cursor will change into a " +"Targeting Cursor that you will use to select the item to be disarmed. The success of " +"this attempt is based on the level of the Rogue and the expertise of whomever set the trap.|" +"|" +"Sorcerer:|" +"The Sorcerer has the skill of Recharge Staffs. This allows him to focus his mana into " +"an staff that has been drained of its magical energies. To accomplish this, select " +"the Recharge Staffs skill through the Spellbook or Speedbook and right-click the mouse " +"as if you were casting a spell. Your cursor will change into a Staff Icon that you will " +"use to select the item to be recharged. Although Recharging a staff in this way will " +"decrease its maximum charges, it can be done without leaving the labyrinth.|" +"|" +"The Witch can also recharge staffs for a price. When the Witch performs this service, it " +"does decrease the maximum charges of the item.|" +"|" +"Spells are magical effects that can be cast from a scroll, a staff or memorized from a " +"book. Spells may or may not require mana to use and are available to all classes.|" +"|" +"Spells cast from a scroll cost no mana to use, but are limited to only one charge. " +"Casting a spell from a scroll is accomplished by either right clicking on the scroll " +"or, if it is located in our belt, pressing the corresponding number on the keyboard. " +"Scrolls can also be readied in the Speedbook and are represented by a red icon/button " +"in the 'select current spell' area.|" +"|" +"Spells cast from staffs cost no mana to use, but are limited by the number of charges " +"available. To cast spells from a staff, it must first be equipped. The 'select current " +"spell' icon/button will change to indicate that the spell on the staff is currently ready " +"to cast. Scrolls can also be readied in the Spellbook or Speedbook and are represented " +"by an orange icon/button in the 'select current spell' area.|" +"|" +"Spells that are memorized cost mana to cast, but they can be used as long as the " +"character has mana to power them. The Warrior and Rogue start the game with no memorized " +"spells while the sorcerer begins with Firebolt. If the character finds a book in the " +"labyrinth, he can memorize the spell written in that book by opening the Inventory " +"screen and right-clicking on the book. This will make that spell always available to " +"the character for casting. Memorized spells can be readied through either the Spellbook " +"or Speedbook and are represented by a blue icon/button in the 'select current spell' area.|" +"|" +"$Important note on books:|" +"Reading more than one book increases your knowledge of that spell and gives you the " +"spell at a higher level. The higher the level of a spell the more effective it is.|" +"|" +"While some spells affect the caster, other spells require a target. These targeted spells " +"are cast in the direction that you indicate with your cursor on the play area. If you " +"highlight a creature, you will cast that spell at that creature. Not all items within " +"the labyrinth can be targeted.|" +"|" +"Example: A fireball spell will travel at the creature or to the location you right-click " +"on. A Healing spell will simply add health to your character while diminishing his " +"available mana and requires no targeting.|" +"|" +"You can also set a spell or scroll as a Hot Key position for instant selection. Start " +"by opening the pop-up menu as described in the skill section above. Assign Hot Keys by " +"hitting the F5, F6, F7 or F8 keys on your keyboard after scrolling through the available " +"spells and highlighting the one you wish to assign. |" +"|" +"$Health and Mana:|" +"The two orbs in the Information Bar display your life and mana. The red sphere of fluid " +"on the left side of the control panel represents the overall health of your character. " +"When the fluid is gone - your character is dead.|" +"|" +"The blue fluid on the right side of the control panel represents your character's " +"available mana. Mana is the magical force used by your character to cast spells. " +"When the liquid in the sphere is low or depleted, you may be unable to cast some " +"(or all) of your spells.|" +"|" +"$Information Bar:|" +"The Information Bar is where you receive detailed information in Hellfire and interact " +"with much of your surroundings. Here is a quick run-down of the control panel areas " +"and their use:|" +"|" +"CHAR: This button is used to access your Character Statistics screen|" +"INV: This button is used to access your Inventory screen|" +"Quest: This button displays your Quest Log (inactive in Shareware version)|" +"Automap: This button activates the mapping overlay|" +"Menu: This button activates the game menu screen|" +"Spells: This button is used to access your Spellbook|" +"Current Spell: This is the spell that has been readied for immediate casting|" +"Life Orb: This is the amount of health your character currently has|" +"Mana Orb: This is the amount of mana your character currently has|" +"Multiplayer Message: This activates the Message Area|" +"Description Area: This is where any important information about creatures or items you " +"can interact with is displayed. This is also where you will enter the text you wish to " +"send when sending multiplayer messages.|" +"|" +"$Character Info:|" +"Toggle the Character Statistics Screen on and off by clicking the button on the control " +"panel. Items may be moved around in your inventory by selecting them and then left-clicking " +"to pick them up. When you pick up an item while in the inventory screen, your cursor " +"changes into the item. You can then place this item into empty spaces in your inventory, " +"swap them with other items in your inventory or equip them.|" +"|" +"If you have an item that you no longer wish to carry, simply grab the item from your " +"inventory and then left-click in the play area to drop it.|" +"|" +"$Equipping Items:|" +"To equip an item, open the inventory screen and pick up the desired item, either from " +"play or from your inventory, placing it in the appropriate box on the figure in the " +"inventory screen. Weapons and shields go into the large spaces to the right or left of " +"the figure. Two-handed weapons such as bows and axes preclude the use of a shield and " +"will take up both of these large spaces.|" +"|" +"Cloaks, robes, capes and all other armor must go in the central torso slot of the figure. |" +"|" +"Helmets and caps go in the box over the head of the character.|" +"|" +"Rings go into the small boxes at the hands of the figure.|" +"|" +"Amulets go into the small box at the next to the neck of the figure.|" +"|" +"To change items that your character has equipped, pick up a new item and place it on top " +"of the item you wish to remove. Your character will automatically swap the items and the " +"cursor will now change into the item that was in that box.|" +"|" +"$Usable Items:|" +"Potions, elixirs and books are classified as usable items. These items can be used by " +"right-clicking on them in the inventory screen. Books are too large to be placed in the " +"belt, but any potions or scrolls that are put there can also be used by pressing the " +"corresponding number on the keyboard.|" +"|" +"$Gold:|" +"You can select a specific amount of gold to drop by right clicking on a pile of gold in " +"your inventory. A dialog will appear that allows you to select a specific amount of gold " +"to take. When you have entered that number, your cursor will change into that amount of gold.|" +"|" +"$Item Information:|" +"Many items in Hellfire share certain common attributes. These are damage, durability, " +"charges and minimum requirements..|" +"|" +"Damage: This is represented by a range that indicates the minimum and maximum damage " +"that item can inflict. A short sword has a (2-6) after its name, meaning it inflicts a " +"minimum of two damage and a maximum of six when it hits. Damage can be modified by the " +"quality of the weapon, the character's strength and magical effects.|" +"|" +"Durability: This is the amount of damage that an item can take before it is rendered " +"useless. Durability is represented by a ratio of current durability to maximum " +"durability. A shield that has a durability of 15/20 would still have 15 points of " +"damage it could take from use before it was rendered useless. Maximum durability can " +"be affected by the quality of the item, enchantments or repairs made upon the item. " +"The minimum durability can be raised by repairing an item.|" +"|" +"Charges: Some items have charges associated with them. Charges indicate how many times " +"that item can be used to cast the spell or affect indicated in its description. Charges " +"are represented by a ratio of charges left to maximum charges. A staff that has charges " +"listed as 2/5 could be used to cast 2 more spells before it was rendered powerless. It " +"could still be used to attack with as a physical weapon, however. Maximum charges can " +"be affected by the magic or recharges cast upon the item. Minimum charges can be raised " +"by recharging the item.|" +"|" +"Minimum Requirements: These are the minimum requirements that a character must meet to " +"wield the item. The more powerful an item is, the higher the minimum requirements will " +"be. If a character does not meet these requirements, he will be unable to equip the " +"item and its name and information will be displayed in red. The item artwork will also " +"have a red tint in the Inventory screen.|" +"|" +"$Items Classes:|" +"There are three classes of items in Hellfire - Mundane, Magic and Unique:|" +"|" +"Mundane items have no special attributes. Their information is displayed in white text.|" +"|" +"Magic Items are represented by blue names and text descriptions. Use the Identify spell " +"or speak to Cain in town to determine their exact properties and attributes.|" +"|" +"Unique items are represented by gold names and text descriptions. Use the Identify spell " +"or speak to Cain in town to determine their exact properties and attributes.|" +"|" +"$Skills & Spells:|" +"You can access your list of skills and spells by left-clicking on the SPELLS button in " +"the interface bar. This 'Spellbook' contains all of the skills and spells that your " +"character knows. Spells available through staffs are also listed here. Left-clicking " +"on the Icon of the spell you wish to ready will place it in the 'select current spell' " +"icon/area and set it as the current readied spell. A readied spell may be cast by simply " +"right-clicking in the play area.|" +"|" +"Left-clicking on the 'select current spell' button will also open a 'Speedbook' menu " +"that also allows you to ready a skill or spell for use. To use a readied skill or " +"spell, simply right-click in the main play area.|" +"|" +"$Skills:|" +"Important Note - Skills are non-functional in the town for this Battle.net Beta. |" +"|" +"Skills are the innate abilities of your character. These skills are different depending " +"on what class you choose and require no mana to use.|" +"|" +"Warrior:|" +"The Warrior has the skill of Repair Items. This allows him to fix an item that has been " +"worn by use or is damaged in combat. To accomplish this, select the Repair Skill through " +"the Spellbook or Speedbook and right-click the mouse as if you were casting a spell. " +"Your cursor will change into a Hammer Icon that you will use to select the item to be " +"repaired. Although Repairing an item in this way will decrease the maximum durability " +"of that item, it can be done without leaving the labyrinth.|" +"|" +"The Blacksmith can also repair items for a price. When the Blacksmith performs this " +"service, it does decrease the maximum durability of the item.|" +"|" +"Rogue:|" +"The Rogue has the skill of Disarm Traps. This allows her to not only remove traps, but " +"also acts as a 'sixth sense' that warns her of where these trapped items are located. " +"To accomplish this, select the Disarm Trap skill through the Spellbook or Speedbook and " +"right-click the mouse as if you were casting a spell. Your cursor will change into a " +"Targeting Cursor that you will use to select the item to be disarmed. The success of " +"this attempt is based on the level of the Rogue and the expertise of whomever set the trap.|" +"|" +"Sorcerer:|" +"The Sorcerer has the skill of Recharge Staffs. This allows him to focus his mana into " +"an staff that has been drained of its magical energies. To accomplish this, select " +"the Recharge Staffs skill through the Spellbook or Speedbook and right-click the mouse " +"as if you were casting a spell. Your cursor will change into a Staff Icon that you will " +"use to select the item to be recharged. Although Recharging a staff in this way will " +"decrease its maximum charges, it can be done without leaving the labyrinth.|" +"|" +"The Witch can also recharge staffs for a price. When the Witch performs this service, it " +"does decrease the maximum charges of the item.|" +"|" +"$Spells:|" +"Important note - Spells are non-functional in the town for this Battle.net Beta.|" +"|" +"Spells are magical effects that can be cast from a scroll, a staff or memorized from a " +"book. Spells may or may not require mana to use and are available to all classes.|" +"|" +"Spells cast from a scroll cost no mana to use, but are limited to only one charge. " +"Casting a spell from a scroll is accomplished by either right clicking on the scroll " +"or, if it is located in our belt, pressing the corresponding number on the keyboard. " +"Scrolls can also be readied in the Speedbook and are represented by a red icon/button " +"in the 'select current spell' area.|" +"|" +"Spells cast from staffs cost no mana to use, but are limited by the number of charges " +"available. To cast spells from a staff, it must first be equipped. The 'select current " +"spell' icon/button will change to indicate that the spell on the staff is currently ready " +"to cast. Scrolls can also be readied in the Spellbook or Speedbook and are represented " +"by an orange icon/button in the 'select current spell' area.|" +"|" +"Spells that are memorized cost mana to cast, but they can be used as long as the " +"character has mana to power them. The Warrior and Rogue start the game with no memorized " +"spells while the sorcerer begins with Firebolt. If the character finds a book in the " +"labyrinth, he can memorize the spell written in that book by opening the Inventory " +"screen and right-clicking on the book. This will make that spell always available to " +"the character for casting. Memorized spells can be readied through either the Spellbook " +"or Speedbook and are represented by a blue icon/button in the 'select current spell' area.|" +"|" +"$Important note on books:|" +"$Reading more than one book increases your knowledge of that spell and gives you the " +"spell at a higher level. The higher the level of a spell the more effective it is.|" +"|" +"While some spells affect the caster, other spells require a target. These targeted spells " +"are cast in the direction that you indicate with your cursor on the play area. If you " +"highlight a creature, you will cast that spell at that creature. Not all items within " +"the labyrinth can be targeted.|" +"|" +"Example: A fireball spell will travel at the creature or to the location you right-click " +"on. A Healing spell will simply add health to your character while diminishing his " +"available mana and requires no targeting.|" +"|" +"You can also set a spell or scroll as a Hot Key position for instant selection. Start " +"by opening the pop-up menu as described in the skill section above. Assign Hot Keys by " +"hitting the F5, F6, F7 or F8 keys on your keyboard after scrolling through the available " +"spells and highlighting the one you wish to assign. |" +"|" +"$Health and Mana:|" +"The two orbs in the Information Bar display your life and mana. The red sphere of fluid " +"on the left side of the control panel represents the overall health of your character. " +"When the fluid is gone - your character is dead.|" +"|" +"The blue fluid on the right side of the control panel represents your character's " +"available mana. Mana is the magical force used by your character to cast spells. " +"When the liquid in the sphere is low or depleted, you may be unable to cast some " +"(or all) of your spells.|" +"|" +"$Information Bar:|" +"The Information Bar is where you receive detailed information in Hellfire and interact " +"with much of your surroundings. Here is a quick run-down of the control panel areas " +"and their use:|" +"|" +"CHAR: This button is used to access your Character Statistics screen|" +"INV: This button is used to access your Inventory screen|" +"Quest: This button displays your Quest Log (inactive in this Beta)|" +"Automap: This button activates the mapping overlay|" +"Menu: This button activates the game menu screen|" +"Spells: This button is used to access your Spellbook|" +"Current Spell: This is the spell that has been readied for immediate casting|" +"Life Orb: This is the amount of health your character currently has|" +"Mana Orb: This is the amount of mana your character currently has|" +"Multiplayer Message: This activates the Message Area|" +"Description Area: This is where any important information about creatures or items you " +"can interact with is displayed. This is also where you will enter the text you wish to " +"send when sending multiplayer messages.|" +"|" +"$Character Info:|" +"Toggle the Character Statistics Screen on and off by clicking the = 577) { + while (tempstr[--t] != ' ') p--; + } + if (*p == '|') p++; + } + } + y = 7; + while (y < 22) { + t = 0; + w = 0; + while (*p == 0) p++; + if (*p == '$') { + p++; + lc = ICOLOR_RED; + } else lc = ICOLOR_WHITE; + if (*p == '&') help_end = help_cy; + else { + while ((*p != '|') && (w < 577)) { + while (*p == 0) p++; + tempstr[t] = *p; + BYTE c = char2print(tempstr[t]); + c = fonttrans[c]; + w += fontkern[c]+1; + t++; + p++; + } + if (w >= 577) { + while (tempstr[--t] != ' ') p--; + } + if (t != 0) { + tempstr[t] = 0; + PrintHelpStr(0, y, tempstr, lc); + } + if (*p == '|') p++; + } + y++; + } + PrintSString(0, 23, TRUE, "Press ESC to end or the arrow keys to scroll.", ICOLOR_GOLD, 0); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void StartHelp() +{ + helpflag = TRUE; + help_cy = 0; + help_end = 5000; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void HelpScrollUp() +{ + if (help_cy > 0) help_cy--; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void HelpScrollDown() +{ + if (help_cy < help_end) help_cy++; +} + diff --git a/src/HELP.H b/src/HELP.H new file mode 100644 index 0000000..23060fe --- /dev/null +++ b/src/HELP.H @@ -0,0 +1,54 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/HELP.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXHELPSTRS 8 +#define MAXHELPLINES 4 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + int hsx; + int hsy; + char hstr[128]; + byte hclr; +} HelpStrStruct; + +typedef struct { + int hlx1; + int hly1; + int hlx2; + int hly2; + byte hlclr; +} HelpLineStruct; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern BOOL helpflag; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + + +void InitHelpSys(); + +void DrawHelp(); + +void StartHelp(); +void HelpScrollUp(); +void HelpScrollDown(); diff --git a/src/ICON1.ICO b/src/ICON1.ICO new file mode 100644 index 0000000..b66a61e Binary files /dev/null and b/src/ICON1.ICO differ diff --git a/src/IMPLODE.H b/src/IMPLODE.H new file mode 100644 index 0000000..c65ccc1 --- /dev/null +++ b/src/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int __cdecl implode( + unsigned int (__cdecl *read_buf)(char *buf, unsigned int *size, void *param), + void (__cdecl *write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int __cdecl explode( + unsigned int (__cdecl *read_buf)(char *buf, unsigned int *size, void *param), + void (__cdecl *write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long __cdecl crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/IMPLODE.LIB b/src/IMPLODE.LIB new file mode 100644 index 0000000..4cc55e1 Binary files /dev/null and b/src/IMPLODE.LIB differ diff --git a/src/INIT.CPP b/src/INIT.CPP new file mode 100644 index 0000000..8a62f13 --- /dev/null +++ b/src/INIT.CPP @@ -0,0 +1,804 @@ +//****************************************************************** +// init.cpp +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include +#include "storm.h" +#include "palette.h" +#include "engine.h" +#include "gendung.h" +#include "lighting.h" +#include "multi.h" +#include "sound.h" +#include "effects.h" +#include "diabloui.h" +#include "resource.h" + + +//****************************************************************** +// debugging +//****************************************************************** +// minor version number -- as in 1.xx +// jmm.patch3 +#define MINOR_VERSION "04" +// jmm.endpatch3 + +// change to "01" when done with patch +#define HF_MINOR_VERSION "01" + + +#define DIRECT_FILE_ACCESS 1 // 0 in final +#ifdef NDEBUG +#undef DIRECT_FILE_ACCESS +#define DIRECT_FILE_ACCESS 0 +#endif + + +//****************************************************************** +// extern +//****************************************************************** +void init_directx(HWND hWnd); +void free_directx(); +void ddraw_switch_modes(); +void BlackPalette(); +void ReleasePlayerFile(); +void FileErrorDlg(const char * pszName); + + +//****************************************************************** +// public +//****************************************************************** +BOOL bActive; // is application active? +const char gszAppName[] = "HELLFIRE"; +const char gszDiabloName[] = "DIABLO"; +HSARCHIVE ghsMainArchive; +HSARCHIVE ghsHFBardArchive = NULL; +HSARCHIVE ghsHFBarbarianArchive = NULL; + + +// Version string --- NOTE: DO NOT CHANGE THIS VERSION +// NUMBER IN THE PROGRAM, CHANGE IT IN THE RESOURCE FILE! +char gszVersionNumber[MAX_PATH] = "internal version unknown"; +char gszPrintVersion[MAX_PATH] = "Hellfire v1." HF_MINOR_VERSION ; // " (from Diablo v1." MINOR_VERSION ")"; +SNETVERSIONDATA gVersion; +static char sgszProgramName[MAX_PATH]; +static char sgszMainArchiveName[MAX_PATH]; +static char sgszPatchArchiveName[MAX_PATH]; +static char sgszHFArchiveName[MAX_PATH]; +static char sgszHFMonkArchiveName[MAX_PATH]; +static char sgszHFBardArchiveName[MAX_PATH]; +static char sgszHFBarbarianArchiveName[MAX_PATH]; +static char sgszHFMusicArchiveName[MAX_PATH]; +static char sgszHFVoiceArchiveName[MAX_PATH]; +static char sgszHFOpt1ArchiveName[MAX_PATH]; +static char sgszHFOpt2ArchiveName[MAX_PATH]; + + +//****************************************************************** +// private +//****************************************************************** +static WNDPROC sgWndProc; +static LRESULT CALLBACK WndProc(HWND ,UINT ,WPARAM ,LPARAM ); +static HSARCHIVE sghsPatchArchive; +static HSARCHIVE sghsHFArchive; +static HSARCHIVE sghsHFMonkArchive; +static HSARCHIVE sghsHFMusicArchive; +static HSARCHIVE sghsHFVoiceArchive; +static HSARCHIVE sghsHFOpt1Archive; +static HSARCHIVE sghsHFOpt2Archive; + +static BOOL killedmom = 0; +#define MOMLINKNAME "Microsoft Office Shortcut Bar.lnk" + + +//****************************************************************** +//****************************************************************** +static void SearchDirectory(LPCSTR directory) { + char searchspec[MAX_PATH]; + strcpy(searchspec,directory); + if ((!searchspec[0]) ||(searchspec[strlen(searchspec)-1] != '\\')) + strcat(searchspec,"\\*"); + else + strcat(searchspec,"*"); + WIN32_FIND_DATA finddata; + HANDLE findhandle = FindFirstFile(searchspec,&finddata); + if (findhandle != INVALID_HANDLE_VALUE) { + do + if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (strcmp(finddata.cFileName,".") && strcmp(finddata.cFileName,"..")) { + char buffer[MAX_PATH] = ""; + if ((!directory[0]) ||(directory[strlen(directory)-1] != '\\')) + sprintf(buffer,"%s\\%s\\",directory,finddata.cFileName); + else + sprintf(buffer,"%s%s\\",directory,finddata.cFileName); + SearchDirectory(buffer); + } + } + else { + if (!_stricmp(finddata.cFileName,MOMLINKNAME)) + ShellExecute(GetDesktopWindow(),"open",finddata.cFileName,"",directory,SW_SHOWNORMAL); + } + while (FindNextFile(findhandle,&finddata)); + FindClose(findhandle); + } +} + + +//****************************************************************** +//****************************************************************** +static HWND find_mom_window() { + HWND hWnd = GetForegroundWindow(); + while (hWnd) { + char classname[256]; + GetClassName(hWnd,classname,255); + if (! _stricmp(classname,"MOM Parent")) break; + hWnd = GetNextWindow(hWnd,GW_HWNDNEXT); + } + + return hWnd; +} + +//****************************************************************** +//****************************************************************** +static void KillMom() { + HWND hWnd; + if (NULL != (hWnd = find_mom_window())) { + PostMessage(hWnd,WM_CLOSE,0,0); + killedmom = 1; + } +} + + +//****************************************************************** +//****************************************************************** +static void WaitMomDead() { + HWND hWnd; + DWORD dwCurrTime = GetTickCount(); + while (NULL != (hWnd = find_mom_window())) { + Sleep(250); + if (GetTickCount() - dwCurrTime > 4000) + break; + } +} + + +//****************************************************************** +//****************************************************************** +static void ResurrectMom() { + if (!killedmom) + return; + killedmom = 0; + char buffer[256] = ""; + LPITEMIDLIST idlist = NULL; + if (SHGetSpecialFolderLocation(GetDesktopWindow(),CSIDL_STARTMENU,&idlist) == NOERROR) { + SHGetPathFromIDList(idlist,buffer); + SearchDirectory(buffer); + } +} + + +//****************************************************************** +//****************************************************************** +static void disable_screen_saver(BYTE bDisable) { +// direct draw doesn't like the screen saver to be enabled, it +// will quit with a fatal error if the screen saver kicks in. +// Disable the screen saver while the program is running + HKEY hKey; + BYTE bNewState; + DWORD dwSuccess; + TCHAR szBuf[16]; + static BYTE sbState = FALSE; + static const TCHAR scszKey[] = TEXT("ScreenSaveActive"); + + // open master key + dwSuccess = RegOpenKeyEx(HKEY_CURRENT_USER,TEXT("Control Panel\\Desktop"),0,KEY_READ | KEY_WRITE,&hKey); + if (dwSuccess != ERROR_SUCCESS) return; + + if (bDisable) { + // get current screen saver state + DWORD dwType; + DWORD dwSize = sizeof(szBuf); + dwSuccess = RegQueryValueEx(hKey,scszKey,NULL,&dwType,(LPBYTE) szBuf,&dwSize); + if (dwSuccess == ERROR_SUCCESS) sbState = szBuf[0] != TEXT('0'); + bNewState = 0; + } + else { + // restore old screen saver state + bNewState = sbState; + } + + // set the new state + szBuf[0] = bNewState ? TEXT('1') : TEXT('0'); + szBuf[1] = 0; + RegSetValueEx(hKey,scszKey,NULL,REG_SZ,(LPBYTE) szBuf,2 * sizeof(szBuf[0])); + + RegCloseKey(hKey); +} + + +//****************************************************************** +//****************************************************************** +/* +static void key_press(int key) +{ + // Simulate a key press + keybd_event( key, + 0x45, + KEYEVENTF_EXTENDEDKEY | 0, + 0 ); + + // Simulate a key release + keybd_event( VK_CAPITAL, + 0x45, + KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, + 0); +} +*/ + +//****************************************************************** +//****************************************************************** +/* +static void init_caps_lock(BOOL init) +{ + BYTE keyState[256]; + static BOOL capslocked; + + GetKeyboardState((LPBYTE)&keyState); + if(init) + { + capslocked = keyState[VK_CAPITAL] & 1; + // Set caps lock off initially + // NOTE: FriendlyMode is opposite polarity to caps_lock, i.e., it is originally ON + if(capslocked) + key_press(VK_CAPITAL); + } + else { // restore caps lock to originial state + if( (capslocked && !(keyState[VK_CAPITAL] & 1)) || + (!capslocked && (keyState[VK_CAPITAL] & 1)) ) + key_press(VK_CAPITAL); + } +} +*/ + + +//****************************************************************** +//****************************************************************** +void cleanup(BOOL bNormalExit) { + + ReleasePlayerFile(); + disable_screen_saver(FALSE); + // init_caps_lock(FALSE); + ResurrectMom(); + + if (ghsMainArchive) { + SFileCloseArchive(ghsMainArchive); + ghsMainArchive = NULL; + } + if (sghsPatchArchive) { + SFileCloseArchive(sghsPatchArchive); + sghsPatchArchive = NULL; + } + if (sghsHFArchive) { + SFileCloseArchive(sghsHFArchive); + sghsHFArchive = NULL; + } + if (sghsHFMonkArchive) { + SFileCloseArchive(sghsHFMonkArchive); + sghsHFMonkArchive = NULL; + } + if (ghsHFBardArchive) { + SFileCloseArchive(ghsHFBardArchive); + ghsHFBardArchive = NULL; + } + if (ghsHFBarbarianArchive) { + SFileCloseArchive(ghsHFBarbarianArchive); + ghsHFBarbarianArchive = NULL; + } + if (sghsHFMusicArchive) { + SFileCloseArchive(sghsHFMusicArchive); + sghsHFMusicArchive = NULL; + } + if (sghsHFVoiceArchive) { + SFileCloseArchive(sghsHFVoiceArchive); + sghsHFVoiceArchive = NULL; + } + if (sghsHFOpt1Archive) { + SFileCloseArchive(sghsHFOpt1Archive); + sghsHFOpt1Archive = NULL; + } + if (sghsHFOpt2Archive) { + SFileCloseArchive(sghsHFOpt2Archive); + sghsHFOpt2Archive = NULL; + } + + UiDestroy(); + sound_exit(); + snd_exit(); + NetClose(); + free_directx(); + mem_cleanup(bNormalExit); + StormDestroy(); + if (bNormalExit) ShowCursor(TRUE); +} + + +//****************************************************************** +//****************************************************************** +static void remove_trailing_bslash(char * pszPath) { + char * pszTemp = strrchr(pszPath,'\\'); + if (pszTemp && !pszTemp[1]) + *pszTemp = 0; +} + + +//****************************************************************** +//****************************************************************** +static BOOL FindCDArchive( + char szName[MAX_PATH], // saved full path + const char * pszArchName, // default archive name + DWORD dwPriority, // priority + HSARCHIVE * phsArchive // archive name +) { + // get a list of drives, and figure out which ones are CDROM + char szDriveList[MAX_PATH]; + DWORD dwLen = GetLogicalDriveStrings(MAX_PATH,szDriveList); + if (! dwLen) return FALSE; + if (dwLen > MAX_PATH) return FALSE; + + // skip over leading bslash in archive name + while (*pszArchName == '\\') pszArchName++; + + const char * pszDriveList = szDriveList; + while (*pszDriveList) { + // save current drive + const char * pszCurrDrive = pszDriveList; + + // skip over drive string and trailing NULL + while (*pszDriveList++) NULL; + + // is this a CDROM drive? + if (DRIVE_CDROM != GetDriveType(pszCurrDrive)) + continue; + + strcpy(szName,pszCurrDrive); + strcat(szName,pszArchName); + if (SFileOpenArchive(szName,dwPriority,TRUE,phsArchive)) + return TRUE; + } + + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +static HSARCHIVE open_1_archive( + char szName[MAX_PATH], // saved full path + const char * pszArchName, // default archive name + const char * pszArchPathRegKey, // registry key for directory + DWORD dwPriority, // priority + BOOL bCDOnly // TRUE => CD ROM only +) { + HSARCHIVE hArchive; + + // get current directory + char szCurrDir[MAX_PATH]; + if (! GetCurrentDirectory(MAX_PATH,szCurrDir)) + app_fatal("Can't get program path"); + remove_trailing_bslash(szCurrDir); + if (! SFileSetBasePath(szCurrDir)) + app_fatal("SFileSetBasePath"); + + // get program directory + char szProgDir[MAX_PATH]; + if (! GetModuleFileName(ghInst,szProgDir,MAX_PATH)) + app_fatal("Can't get program name"); + char * pszExeName = strrchr(szProgDir,'\\'); + if (pszExeName) *pszExeName = 0; + remove_trailing_bslash(szProgDir); + + // try the current directory + strcpy(szName,szCurrDir); + strcat(szName,pszArchName); + if (SFileOpenArchive( + szName, + dwPriority, + #if DIRECT_FILE_ACCESS + FALSE, + #else + bCDOnly, + #endif + &hArchive + )) return hArchive; + + // try the program directory + if (strcmp(szProgDir,szCurrDir)) { + strcpy(szName,szProgDir); + strcat(szName,pszArchName); + if (SFileOpenArchive( + szName, + dwPriority, + #if DIRECT_FILE_ACCESS + FALSE, + #else + bCDOnly, + #endif + &hArchive + )) return hArchive; + } + + // get CD directory + char szDataDir[MAX_PATH]; + szDataDir[0] = 0; + if (pszArchPathRegKey && SRegLoadString(TEXT("Archives"),pszArchPathRegKey,0,szDataDir,MAX_PATH)) { + // try the data directory + remove_trailing_bslash(szDataDir); + strcpy(szName,szDataDir); + strcat(szName,pszArchName); + if (SFileOpenArchive( + szName, + dwPriority, + #if DIRECT_FILE_ACCESS + FALSE, + #else + bCDOnly, + #endif + &hArchive + )) return hArchive; + } + + // if this file is to be found on a CDROM, search *all* CDROMs + // don't pass szName, because in case of failure by FindCDArchive, + // it already contains the name of the desired archive, which + // STORM wants + if (bCDOnly && FindCDArchive(szDataDir,pszArchName,dwPriority,&hArchive)) { + strcpy(szName,szDataDir); + return hArchive; + } + + // we couldn't open the file, but leave the szName variable + // filled in with the program directory + archive name + return NULL; +} + + +//****************************************************************** +//****************************************************************** +static void get_program_version_info() { + // get name of .EXE file + if (! GetModuleFileName(ghInst,sgszProgramName,MAX_PATH)) + return; + + // get sizeof version structure to allocate + DWORD dwUnused; + DWORD dwVerLen = GetFileVersionInfoSize(sgszProgramName,&dwUnused); + if (! dwVerLen) return; + + // get version info + LPVOID lpData = DiabloAllocPtrSig(dwVerLen,'VERS'); + if (! GetFileVersionInfo(sgszProgramName,0,dwVerLen,lpData)) + goto cleanup; + + UINT uBytes; + VS_FIXEDFILEINFO * pInfo; + if (! VerQueryValue(lpData,TEXT("\\"),(LPVOID *) &pInfo,&uBytes)) + goto cleanup; + app_assert(uBytes >= sizeof(VS_FIXEDFILEINFO)); + + sprintf( + gszVersionNumber, + "version %d.%d.%d.%d", + pInfo->dwProductVersionMS >> 16, + pInfo->dwProductVersionMS & 0x0ffff, + pInfo->dwProductVersionLS >> 16, + pInfo->dwProductVersionLS & 0x0ffff + ); + +cleanup: + DiabloFreePtr(lpData); +} + + +//****************************************************************** +//****************************************************************** +static void open_archives() { + // setup version info + ZeroMemory(&gVersion,sizeof(gVersion)); + gVersion.size = sizeof(gVersion); + gVersion.versionstring = gszVersionNumber; + gVersion.executablefile = sgszProgramName; + gVersion.originalarchivefile = sgszMainArchiveName; + gVersion.patcharchivefile = sgszPatchArchiveName; + + // fill in program name and version string + get_program_version_info(); + + while (1) { + // open main archive + ghsMainArchive = open_1_archive( + sgszMainArchiveName, // saved full path + #if IS_VERSION(SHAREWARE) + TEXT("\\spawn.mpq"), // default archive name + TEXT("DiabloSpawn"), // key for spawned directory + #else + TEXT("\\diabdat.mpq"), // default archive name + TEXT("DiabloCD"), // key for CDROM directory + #endif + 1000, // priority + #if IS_VERSION(SHAREWARE) + FALSE // TRUE == CD ROM only + #else + TRUE // TRUE == CD ROM only + #endif + ); + if (ghsMainArchive) break; + + #if DIRECT_FILE_ACCESS + // we're in debugging mode, so we can just exit + break; + #endif + + #if IS_VERSION(SHAREWARE) + // couldn't find spawn.mpq file + break; + #else + // tell the user to insert the CD + DWORD dwResult; + UiCopyProtError(&dwResult); + if (dwResult == COPYPROT_CANCEL) + FileErrorDlg("diabdat.mpq"); + #endif + } + + // make sure we have access to our data + HSFILE hsFile; + if (! patSFileOpenFile("ui_art\\title.pcx",&hsFile,TRUE)) { + #if IS_VERSION(SHAREWARE) + FileErrorDlg("Main program archive: spawn.mpq"); + #else + FileErrorDlg("Main program archive: diabdat.mpq"); + #endif + } + patSFileCloseFile(hsFile); + + // open patch file + sghsPatchArchive = open_1_archive( + sgszPatchArchiveName, // saved full path + #if IS_VERSION(SHAREWARE) + TEXT("\\patch_sh.mpq"), // default archive name + TEXT("DiabloSpawn"), // key for spawned directory + #else + TEXT("\\patch_rt.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + #endif + 2000, // priority + FALSE // TRUE == CD ROM only + ); + // open Hellfire file + sghsHFArchive = open_1_archive( + sgszHFArchiveName, // saved full path + TEXT("\\hellfire.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + 8000, // priority + FALSE // TRUE == CD ROM only + ); + // open Hellfire Character file + sghsHFMonkArchive = open_1_archive( + sgszHFMonkArchiveName, // saved full path + TEXT("\\hfmonk.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + 8100, // priority + FALSE // TRUE == CD ROM only + ); + // open Hellfire Character file + ghsHFBardArchive = open_1_archive( + sgszHFBardArchiveName, // saved full path + TEXT("\\hfbard.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + 8110, // priority + FALSE // TRUE == CD ROM only + ); + // open Hellfire Character file + ghsHFBarbarianArchive = open_1_archive( + sgszHFBarbarianArchiveName, // saved full path + TEXT("\\hfbarb.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + 8120, // priority + FALSE // TRUE == CD ROM only + ); + // open Hellfire Music file + sghsHFMusicArchive = open_1_archive( + sgszHFMusicArchiveName, // saved full path + TEXT("\\hfmusic.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + 8200, // priority + FALSE // TRUE == CD ROM only + ); + // open Hellfire Voice file + sghsHFVoiceArchive = open_1_archive( + sgszHFVoiceArchiveName, // saved full path + TEXT("\\hfvoice.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + 8500, // priority + FALSE // TRUE == CD ROM only + ); + // open Hellfire Option file #1 + sghsHFOpt1Archive = open_1_archive( + sgszHFOpt1ArchiveName, // saved full path + TEXT("\\hfopt1.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + 8600, // priority + FALSE // TRUE == CD ROM only + ); + // open Hellfire Option file #2 + sghsHFOpt2Archive = open_1_archive( + sgszHFOpt2ArchiveName, // saved full path + TEXT("\\hfopt2.mpq"), // default archive name + TEXT("DiabloInstall"), // key for installed directory + 8610, // priority + FALSE // TRUE == CD ROM only + ); +} + + +//****************************************************************** +//****************************************************************** +void init_window(int nCmdShow) { + KillMom(); + + void check_disk_space(); + check_disk_space(); + + // set up and register window class + WNDCLASSEX wc; + ZeroMemory(&wc,sizeof(wc)); + wc.cbSize = sizeof(wc); + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = WndProc; + wc.hInstance = ghInst; + wc.hIcon = LoadIcon(ghInst,MAKEINTRESOURCE(IDI_ICON1)); + wc.hCursor = LoadCursor(NULL,IDC_ARROW); + wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); + wc.lpszMenuName = gszAppName; + // So the Diablo auto run won't. + wc.lpszClassName = gszDiabloName; //gszAppName; + wc.hIconSm = (HICON) LoadImage(ghInst,MAKEINTRESOURCE(IDI_ICON1),IMAGE_ICON,16,16,0); + if (! RegisterClassEx(&wc)) + app_fatal("Unable to register window class"); + +#if ALLOW_WINDOWED_MODE + int nWdt = 640; + int nHgt = 480; +#else + int nWdt = max(640,GetSystemMetrics(SM_CXSCREEN)); + int nHgt = max(480,GetSystemMetrics(SM_CYSCREEN)); +#endif + + // create main window + HWND hWnd = CreateWindow( + gszDiabloName, + gszAppName, + WS_POPUP, + 0, + 0, + nWdt, + nHgt, + NULL, + NULL, + ghInst, + NULL + ); + if (! hWnd) app_fatal("Unable to create main window"); + ShowWindow(hWnd,SW_SHOWNORMAL); + UpdateWindow(hWnd); + + WaitMomDead(); + init_directx(hWnd); + BlackPalette(); + snd_init(hWnd); + open_archives(); + disable_screen_saver(TRUE); + // init_caps_lock(TRUE); +} + + +//****************************************************************** +//****************************************************************** +static void app_activate(HWND hWnd,WPARAM wParam) { + bActive = wParam; + UiAppActivate(wParam); + + // make our 16x16 icon show up on the taskbar + // -- have to have WM_SYSMENU set for the icon to show up + // -- don't want WM_SYSMENU during fullscreen mode, otherwise + // menu will pop up during gameplay! + DWORD dwStyle = GetWindowLong(hWnd,GWL_STYLE); + if (bActive && fullscreen) + dwStyle &= ~WS_SYSMENU; + else + dwStyle |= WS_SYSMENU; + SetWindowLong(hWnd,GWL_STYLE,dwStyle); + + if (! bActive) return; + force_redraw = FULLDRAW; + ResetPal(); +} + + +//****************************************************************** +//****************************************************************** +LRESULT CALLBACK DiabloDefProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { + switch(uMsg) { + #if ALLOW_WINDOWED_MODE + case WM_SYSKEYUP: + if (wParam == VK_RETURN) { + fullscreen = !fullscreen; + ddraw_switch_modes(); + return 0; + } + break; + #endif + + case WM_CLOSE: + return 0; + + case WM_ERASEBKGND: + // ignore erase messages + return 0; + + case WM_PAINT: + force_redraw = FULLDRAW; + break; + + case WM_ACTIVATEAPP: + app_activate(hWnd,wParam); + break; + + case WM_QUERYNEWPALETTE: + SDrawRealizePalette(); + return TRUE; + + case WM_PALETTECHANGED: + // pjw.patch1.start + // if (bActive && (HWND)wParam != hWnd) + if ((HWND)wParam != hWnd) + // pjw.patch1.end + SDrawRealizePalette(); + break; + + case WM_CREATE: + ghMainWnd = hWnd; + break; + + case WM_DESTROY: + cleanup(TRUE); + ghMainWnd = NULL; + PostQuitMessage(0); + break; + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + + +//****************************************************************** +//****************************************************************** +static LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { + if (sgWndProc) return sgWndProc(hWnd,uMsg,wParam,lParam); + return DiabloDefProc(hWnd,uMsg,wParam,lParam); +} + + +//****************************************************************** +//****************************************************************** +WNDPROC my_SetWindowProc(WNDPROC wndProc) { +// we can't use SetWindowLong, because DirectDraw won't properly support +// stuff like alt-tabbing if we override the funky stuff it does to the +// window procedure. + WNDPROC tempProc = sgWndProc; + sgWndProc = wndProc; + return tempProc; +} diff --git a/src/INTERFAC.CPP b/src/INTERFAC.CPP new file mode 100644 index 0000000..1d670ff --- /dev/null +++ b/src/INTERFAC.CPP @@ -0,0 +1,544 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Menu interface processing +** +** (C)1996 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/INTERFAC.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "palette.h" +#include "engine.h" +#include "scrollrt.h" +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "gamemenu.h" +#include "control.h" +#include "cursor.h" +#include "trigs.h" +#include "multi.h" +#include "msg.h" +#include "effects.h" +#include "portal.h" +#include "quests.h" +#include "setmaps.h" + + +//****************************************************************** +// extern +//****************************************************************** +extern BYTE gbSomebodyWonGameKludge; +WNDPROC my_SetWindowProc(WNDPROC wndProc); +void plrmsg_hold(BOOL bStart); +void BlackPalette(); +void DestroyTempSaves(); +LRESULT CALLBACK DisableInputWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); + + +//****************************************************************** +// private +//****************************************************************** +#define MAX_PROGRESS 534 +static BYTE *sgpBackCel; +static DWORD sgdwProgress, sgdwXY; + + +//****************************************************************** +//****************************************************************** +static void ProgressFree() { + DiabloFreePtr(sgpBackCel); +} + + +//****************************************************************** +//****************************************************************** +static void ProgressLoad(UINT uMsg) { + app_assert(! sgpBackCel); + switch (uMsg) { + case WM_DIABNEXTLVL : + switch (gnLevelTypeTbl[currlevel]) { + case 0: + sgpBackCel = LoadFileInMemSig("Gendata\\Cuttt.CEL",NULL,'PROG'); + LoadPalette("Gendata\\Cuttt.pal"); + sgdwXY = 1; + break; + case 1: + if (currlevel < HIVESTART) + { + sgpBackCel = LoadFileInMemSig("Gendata\\Cutl1d.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutl1d.pal"); + sgdwXY = 0; + break; + } + else + { + sgpBackCel = LoadFileInMemSig("Nlevels\\cutl5.CEL",NULL,'PROG'); + LoadPalette ("Nlevels\\cutl5.pal"); + sgdwXY = 1; + break; + } + + case 2: + sgpBackCel = LoadFileInMemSig("Gendata\\Cut2.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut2.pal"); + sgdwXY = 2; + break; + case 3: + if (currlevel < HIVESTART) + { + sgpBackCel = LoadFileInMemSig("Gendata\\Cut3.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut3.pal"); + sgdwXY = 1; + break; + } + else + { + sgpBackCel = LoadFileInMemSig("Nlevels\\cutl6.CEL",NULL,'PROG'); + LoadPalette ("Nlevels\\cutl6.pal"); + sgdwXY = 1; + break; + } + + case 4: + if (currlevel < 15) { + sgpBackCel = LoadFileInMemSig("Gendata\\Cut4.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut4.pal"); + sgdwXY = 1; + } else { + sgpBackCel = LoadFileInMemSig("Gendata\\Cutgate.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutgate.pal"); + sgdwXY = 1; + } + break; + default: + sgpBackCel = LoadFileInMemSig("Gendata\\Cutl1d.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutl1d.pal"); + sgdwXY = 0; + break; + } + break; + + case WM_DIABPREVLVL : + if (gnLevelTypeTbl[currlevel-1] == 0) { + sgpBackCel = LoadFileInMemSig("Gendata\\Cuttt.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cuttt.pal"); + sgdwXY = 1; + } else { + switch (gnLevelTypeTbl[currlevel]) { + case 0: + sgpBackCel = LoadFileInMemSig("Gendata\\Cuttt.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cuttt.pal"); + sgdwXY = 1; + break; + case 1: + if (currlevel < HIVESTART) + { + sgpBackCel = LoadFileInMemSig("Gendata\\Cutl1d.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutl1d.pal"); + sgdwXY = 0; + break; + } + else + { + sgpBackCel = LoadFileInMemSig("Nlevels\\cutl5.CEL",NULL,'PROG'); + LoadPalette ("Nlevels\\cutl5.pal"); + sgdwXY = 1; + break; + } + + case 2: + sgpBackCel = LoadFileInMemSig("Gendata\\Cut2.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut2.pal"); + sgdwXY = 2; + break; + case 3: + if (currlevel < HIVESTART) + { + sgpBackCel = LoadFileInMemSig("Gendata\\Cut3.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut3.pal"); + sgdwXY = 1; + break; + } + else + { + sgpBackCel = LoadFileInMemSig("Nlevels\\cutl6.CEL",NULL,'PROG'); + LoadPalette ("Nlevels\\cutl6.pal"); + sgdwXY = 1; + break; + } + case 4: + sgpBackCel = LoadFileInMemSig("Gendata\\Cut4.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut4.pal"); + sgdwXY = 1; + break; + default: + sgpBackCel = LoadFileInMemSig("Gendata\\Cutl1d.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutl1d.pal"); + sgdwXY = 0; + break; + } + } + break; + + case WM_DIABSETLVL : + if (setlvlnum == SL_BONECHAMB) { + sgpBackCel = LoadFileInMemSig("Gendata\\Cut2.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut2.pal"); + sgdwXY = 2; + } else if (setlvlnum == SL_VILEBETRAYER) { + sgpBackCel = LoadFileInMemSig("Gendata\\Cutportr.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutportr.pal"); + sgdwXY = 1; + } else { + sgpBackCel = LoadFileInMemSig("Gendata\\Cutl1d.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutl1d.pal"); + sgdwXY = 0; + } + break; + + case WM_DIABRTNLVL : + if (setlvlnum == SL_BONECHAMB) { // bone chamber + sgpBackCel = LoadFileInMemSig("Gendata\\Cut2.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut2.pal"); + sgdwXY = 2; + } else if (setlvlnum == SL_VILEBETRAYER) { // vile betrayer + sgpBackCel = LoadFileInMemSig("Gendata\\Cutportr.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutportr.pal"); + sgdwXY = 1; + } else { + sgpBackCel = LoadFileInMemSig("Gendata\\Cutl1d.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutl1d.pal"); + sgdwXY = 0; + } + break; + + case WM_DIABWARPLVL : + sgpBackCel = LoadFileInMemSig("Gendata\\Cutportl.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutportl.pal"); + sgdwXY = 1; + break; + + case WM_DIABLOADGAME : + sgpBackCel = LoadFileInMemSig("Gendata\\Cutstart.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutstart.pal"); + sgdwXY = 1; + break; + + case WM_DIABNEWGAME: + sgpBackCel = LoadFileInMemSig("Gendata\\Cutstart.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutstart.pal"); + sgdwXY = 1; + break; + + case WM_DIABTOWNWARP: + case WM_DIABTWARPUP: + switch (gnLevelTypeTbl[plr[myplr].plrlevel]) { + case 0: + sgpBackCel = LoadFileInMemSig("Gendata\\Cuttt.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cuttt.pal"); + sgdwXY = 1; + break; + case 1: // added to allow the crypt JKE + if (plr[myplr].plrlevel < HIVESTART) + { + sgpBackCel = LoadFileInMemSig("Gendata\\Cutl1d.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cutl1d.pal"); + sgdwXY = 0; + break; + } + else + { + sgpBackCel = LoadFileInMemSig("Nlevels\\Cutl5.CEL",NULL,'PROG'); + LoadPalette ("Nlevels\\Cutl5.pal"); + sgdwXY = 1; + break; + } + case 2: + sgpBackCel = LoadFileInMemSig("Gendata\\Cut2.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut2.pal"); + sgdwXY = 2; + break; + case 3: + if (plr[myplr].plrlevel < HIVESTART) + { + sgpBackCel = LoadFileInMemSig("Gendata\\Cut3.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut3.pal"); + sgdwXY = 1; + break; + } + else + { + sgpBackCel = LoadFileInMemSig("Nlevels\\Cutl6.CEL",NULL,'PROG'); + LoadPalette ("Nlevels\\Cutl6.pal"); + sgdwXY = 1; + break; + } + + case 4: + sgpBackCel = LoadFileInMemSig("Gendata\\Cut4.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cut4.pal"); + sgdwXY = 1; + break; + } + break; + + case WM_DIABRETOWN: + sgpBackCel = LoadFileInMemSig("Gendata\\Cuttt.CEL",NULL,'PROG'); + LoadPalette ("Gendata\\Cuttt.pal"); + sgdwXY = 1; + break; + + default: + app_fatal("Unknown progress mode"); + break; + } + + // Indicates time for the progress bar + sgdwProgress = 0; +} + + +//****************************************************************** +//****************************************************************** +static void DrawBarXY(int x, int y, int v2) { + app_assert(gpBuffer); + static const BYTE pixel[3] = { 0x8a, 0x2b, 0xfe }; + BYTE * pto = gpBuffer + nBuffWTbl[y] + x; + for (int i = 0; i < 22; i++) { + *pto = pixel[v2]; + pto = pto + 768; + } +} + + +//****************************************************************** +//****************************************************************** +static void ProgressIntDraw() { + static const int xytable[3][2] = { {53, 37}, {53, 421}, {53, 37} }; + + // draw background + lock_buf(1); + app_assert(sgpBackCel); + DrawCel(64, 639, sgpBackCel, 1, 640); + + // draw load/progress bar + for (DWORD i = 0; i < sgdwProgress; i++) + DrawBarXY (64 + xytable[sgdwXY][0] + i, xytable[sgdwXY][1] + 160, sgdwXY); + unlock_buf(1); + + // force a full blit + force_redraw = FULLDRAW; + FullBlit(FALSE); +} + + +//****************************************************************** +//****************************************************************** +void interface_msg_pump() { + MSG msg; + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if (msg.message != WM_QUIT) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + + +//****************************************************************** +//****************************************************************** +BOOL IntCheck() { + interface_msg_pump(); + + // make bar increase + sgdwProgress += 15; + if (sgdwProgress > MAX_PROGRESS) + sgdwProgress = MAX_PROGRESS; + + // redraw the screen + if (sgpBackCel) ProgressIntDraw(); + + // are we done? + return (sgdwProgress >= MAX_PROGRESS); +} + + +//****************************************************************** +//****************************************************************** +void ShowProgress(UINT uMsg) { + gbSomebodyWonGameKludge = FALSE; + plrmsg_hold(TRUE); + + app_assert(ghMainWnd); + WNDPROC saveProc = my_SetWindowProc(DisableInputWndProc); + interface_msg_pump(); + + // load progress background and fade in + ClrDraw(); + FullBlit(TRUE); + ProgressLoad(uMsg); + BlackPalette(); + ProgressIntDraw(); + PaletteFadeIn(FADE_FAST); + + IntCheck(); + sound_init(); + IntCheck(); + + switch (uMsg) { + case WM_DIABLOADGAME : + IntCheck(); + GM_LoadGame(TRUE); + IntCheck(); + break; + + case WM_DIABNEWGAME : + IntCheck(); + FreeGameMem(); + IntCheck(); + DestroyTempSaves(); + LoadGameLevel(TRUE, LVL_DOWN); + IntCheck(); + break; + + case WM_DIABNEXTLVL : + IntCheck(); + if (gbMaxPlayers == 1) SaveLevel(); + else DeltaSaveLevel(); + + FreeGameMem(); + currlevel++; + leveltype = gnLevelTypeTbl[currlevel]; + app_assert(plr[myplr].plrlevel == currlevel); + IntCheck(); + LoadGameLevel(FALSE, LVL_DOWN); + IntCheck(); + break; + + case WM_DIABPREVLVL : + IntCheck(); + if (gbMaxPlayers == 1) SaveLevel(); + else DeltaSaveLevel(); + + IntCheck(); + FreeGameMem(); + currlevel--; + leveltype = gnLevelTypeTbl[currlevel]; + app_assert(plr[myplr].plrlevel == currlevel); + IntCheck(); + LoadGameLevel(FALSE, LVL_UP); + IntCheck(); + break; + + case WM_DIABSETLVL : + SetReturnLvlPos(); + if (gbMaxPlayers == 1) SaveLevel(); + else DeltaSaveLevel(); + setlevel = TRUE; + leveltype = setlvltype; + FreeGameMem(); + IntCheck(); + LoadGameLevel(FALSE, LVL_SET); + IntCheck(); + break; + + case WM_DIABRTNLVL : + if (gbMaxPlayers == 1) SaveLevel(); + else DeltaSaveLevel(); + setlevel = FALSE; + FreeGameMem(); + IntCheck(); + GetReturnLvlPos(); + LoadGameLevel(FALSE, LVL_RTN); + IntCheck(); + break; + + case WM_DIABWARPLVL : + IntCheck(); + if (gbMaxPlayers == 1) SaveLevel(); + else DeltaSaveLevel(); + FreeGameMem(); + GetPortalLevel(); + IntCheck(); + + LoadGameLevel(FALSE, LVL_WARP); + IntCheck(); + break; + + case WM_DIABTOWNWARP: + IntCheck(); + if (gbMaxPlayers == 1) SaveLevel(); + else DeltaSaveLevel(); + + FreeGameMem(); + currlevel = plr[myplr].plrlevel; + leveltype = gnLevelTypeTbl[currlevel]; + app_assert(plr[myplr].plrlevel == currlevel); + IntCheck(); + LoadGameLevel(FALSE, LVL_TWARPDN); + IntCheck(); + break; + + case WM_DIABTWARPUP: + IntCheck(); + if (gbMaxPlayers == 1) SaveLevel(); + else DeltaSaveLevel(); + + FreeGameMem(); + currlevel = plr[myplr].plrlevel; + leveltype = gnLevelTypeTbl[currlevel]; + app_assert(plr[myplr].plrlevel == currlevel); + IntCheck(); + LoadGameLevel(FALSE, LVL_TWARPUP); + IntCheck(); + break; + + case WM_DIABRETOWN: + IntCheck(); + if (gbMaxPlayers == 1) SaveLevel(); + else DeltaSaveLevel(); + + FreeGameMem(); + currlevel = plr[myplr].plrlevel; + leveltype = gnLevelTypeTbl[currlevel]; + app_assert(plr[myplr].plrlevel == currlevel); + IntCheck(); + LoadGameLevel(FALSE, LVL_DOWN); + IntCheck(); + break; + + } + + // cleanup + app_assert(ghMainWnd); + PaletteFadeOut(FADE_FAST); + ProgressFree(); + + // restore window procedure + saveProc = my_SetWindowProc(saveProc); + app_assert(saveProc == DisableInputWndProc); + + NetSendCmdLocParam1( + TRUE, + CMD_PLAYER_JOINLEVEL, + plr[myplr]._px, + plr[myplr]._py, + plr[myplr].plrlevel + ); + + plrmsg_hold(FALSE); + ResetPal(); + + if (gbSomebodyWonGameKludge && plr[myplr].plrlevel == 16) { + // somebody killed diablo while we were on the stairs + void PrepDoEnding(); + PrepDoEnding(); + } + gbSomebodyWonGameKludge = FALSE; +} \ No newline at end of file diff --git a/src/INTERFAC.H b/src/INTERFAC.H new file mode 100644 index 0000000..82864fe --- /dev/null +++ b/src/INTERFAC.H @@ -0,0 +1,19 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1996 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/INTERFAC.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +BOOL IntCheck(); diff --git a/src/INV.CPP b/src/INV.CPP new file mode 100644 index 0000000..002c728 --- /dev/null +++ b/src/INV.CPP @@ -0,0 +1,3086 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Invetory file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/INV.CPP 11 2/24/97 7:53p Jmcreynolds $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "gendung.h" //required for player.h +#include "items.h" +#include "itemdat.h" +#include "player.h" +#include "inv.h" +#include "engine.h" +#include "lighting.h" +#include "cursor.h" +#include "scrollrt.h" +#include "control.h" +#include "monster.h" +#include "effects.h" +#include "spelldat.h" +#include "spells.h" +#include "objects.h" +#include "quests.h" +#include "doom.h" +#include "msg.h" +#include "stores.h" +#include "missiles.h" +#include "minitext.h" +#include "textdat.h" +#include "multi.h" + +ItemStruct *PlrHasItem(int pnum, int item, int &i); +void SetupItem(int); + +void CheckItemStats(int pnum); +void DeleteItem(int ii, int i); +void OpenNest(); +void OpenCrypt(); +void InitTownTriggers(); + +// JMM.PATCH1.2.22.97 +void sysmsg_add_string(const char * pszMsg); +// END.JMM.PATCH1.2.22.97 + + +/*-----------------------------------------------------------------------** +** Global variables +**-----------------------------------------------------------------------*/ +BOOL invflag; +BOOL drawsbarflag; + +/*-----------------------------------------------------------------------** +** private +**-----------------------------------------------------------------------*/ +// Offscreen control panel buffer +static BYTE *pInvCels; + +int AP2x2Tbl[10] = { 8, 28, 6, 26, 4, 24, 2, 22, 0, 20 }; + +// InvRect defines lower-left corners of inventory screen rectangles +static const POINT InvRect[] = { + { 452, 31 },{ 480, 31 }, // Head (0-3) + { 452, 59 },{ 480, 59 }, + + { 365,205 }, // Ring 1 (4) + + { 567,205 }, // Ring 2 (5) + + { 524, 59 }, // Neck (6) + + { 337,104 },{ 366,104 }, // Left Hand (7-12) + { 337,132 },{ 366,132 }, + { 337,160 },{ 366,160 }, + + { 567,104 },{ 596,104 }, // Right Hand (13-18) + { 567,132 },{ 596,132 }, + { 567,160 },{ 596,160 }, + + { 452,104 },{ 480,104 }, // Body (19-24) + { 452,132 },{ 480,132 }, + { 452,160 },{ 480,160 }, + + // Inv (25-64) + { 337,250 },{ 366,250 },{ 394,250 },{ 423,250 },{ 451,250 },{ 480,250 },{ 509,250 },{ 538,250 },{ 567,250 },{ 596,250 }, + { 337,279 },{ 366,279 },{ 394,279 },{ 423,279 },{ 451,279 },{ 480,279 },{ 509,279 },{ 538,279 },{ 567,279 },{ 596,279 }, + { 337,308 },{ 366,308 },{ 394,308 },{ 423,308 },{ 451,308 },{ 480,308 },{ 509,308 },{ 538,308 },{ 567,308 },{ 596,308 }, + { 337,336 },{ 366,336 },{ 394,336 },{ 423,336 },{ 451,336 },{ 480,336 },{ 509,336 },{ 538,336 },{ 567,336 },{ 596,336 }, + + // Speed Bar(65-72) + { 205,385 },{ 234,385 },{ 263,385 },{ 292,385 },{ 321,385 },{ 350,385 },{ 379,385 },{ 408,385 } +}; +#define INVRECTS (sizeof(InvRect) / sizeof(InvRect[0])) + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void FreeInvGFX() { + DiabloFreePtr (pInvCels); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitInv() { + app_assert(! pInvCels); + if (plr[myplr]._pClass == CLASS_WARRIOR) pInvCels = LoadFileInMemSig("Data\\Inv\\Inv.CEL",NULL,'INVC'); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) pInvCels = LoadFileInMemSig("Data\\Inv\\Inv_rog.CEL",NULL,'INVC'); + else if (plr[myplr]._pClass == CLASS_SORCEROR) pInvCels = LoadFileInMemSig("Data\\Inv\\Inv_Sor.CEL",NULL,'INVC'); + else if (plr[myplr]._pClass == CLASS_MONK) pInvCels = LoadFileInMemSig("Data\\Inv\\Inv_Sor.CEL",NULL,'INVC'); // GWP Fix this + else if (plr[myplr]._pClass == CLASS_BARD) pInvCels = LoadFileInMemSig("Data\\Inv\\Inv_rog.CEL",NULL,'INVC'); // GWP Fix this + else if (plr[myplr]._pClass == CLASS_BARBARIAN) pInvCels = LoadFileInMemSig("Data\\Inv\\Inv.CEL",NULL,'INVC'); // GWP Fix this + #endif + invflag = FALSE; + drawsbarflag = FALSE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ChangeBackground(int x, int y, int w, int h) +{ + BYTE *p; + + app_assert(gpBuffer); + p = gpBuffer + nBuffWTbl[y] + x; + __asm { + mov edi,dword ptr [p] + xor edx,edx + xor ebx,ebx + mov dx,word ptr [h] + mov bx,word ptr [w] + +_YLp: mov ecx,ebx +_XLp: mov al,byte ptr [edi] + cmp al,176 + jb _Skip2 + cmp al,191 + ja _Try2 + sub al,16 + jmp _Save +_Try2: cmp al,240 + jb _Skip2 + sub al,80 +_Save: mov byte ptr [edi],al +_Skip2: inc edi + loop _XLp + sub edi,768 + sub edi,ebx + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#define INVOCLR 197 +#define INVOMCLR 181 +#define INVOICLR 229 + +void DrawInv() +{ + int i, f, w, ii, xx, yy, oc; + BYTE *pB; + BOOL invtest[MAXINV]; // @@@@ Dave test + + app_assert(gpBuffer); + DrawCel(384, 511, pInvCels, 1, 320); + + if (plr[myplr].HeadItem._itype != -1) { + ChangeBackground(517, 219, 56, 56); + f = plr[myplr].HeadItem._iCurs + ICSTART; + w = CursorWidth[f]; + if (cursinvitem == INVLOC_HEAD) { + oc = INVOCLR; + if (plr[myplr].HeadItem._iMagical) oc = INVOMCLR; + if (!plr[myplr].HeadItem._iStatFlag) oc = INVOICLR; + + if (f <= ICLAST ) + OutlineSlabCel(oc, 517, 219, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, 517, 219, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].HeadItem._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(517, 219, pCursCels, f, w, 0, 8); + else + DrawSlabCel(517, 219, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(517, 219, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(517, 219, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + } + if (plr[myplr].Ring1Item._itype != -1) { + ChangeBackground(432, 365, 28, 28); + f = plr[myplr].Ring1Item._iCurs + ICSTART; + w = CursorWidth[f]; + if (cursinvitem == INVLOC_RING1) { + oc = INVOCLR; + if (plr[myplr].Ring1Item._iMagical) oc = INVOMCLR; + if (!plr[myplr].Ring1Item._iStatFlag) oc = INVOICLR; + + if (f <= ICLAST) + OutlineSlabCel(oc, 432, 365, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, 432, 365, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].Ring1Item._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(432, 365, pCursCels, f, w, 0, 8); + else + DrawSlabCel(432, 365, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(432, 365, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(432, 365, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + } + if (plr[myplr].Ring2Item._itype != -1) { + ChangeBackground(633, 365, 28, 28); + f = plr[myplr].Ring2Item._iCurs + ICSTART; + w = CursorWidth[f]; + if (cursinvitem == INVLOC_RING2) { + oc = INVOCLR; + if (plr[myplr].Ring2Item._iMagical) oc = INVOMCLR; + if (!plr[myplr].Ring2Item._iStatFlag) oc = INVOICLR; + if (f <= ICLAST) + OutlineSlabCel(oc, 633, 365, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, 633, 365, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].Ring2Item._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(633, 365, pCursCels, f, w, 0, 8); + else + DrawSlabCel(633, 365, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(633, 365, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(633, 365, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + } + if (plr[myplr].NeckItem._itype != -1) { + ChangeBackground(589, 220, 28, 28); + f = plr[myplr].NeckItem._iCurs + ICSTART; + w = CursorWidth[f]; + if (cursinvitem == INVLOC_NECK) { + oc = INVOCLR; + if (plr[myplr].NeckItem._iMagical) oc = INVOMCLR; + if (!plr[myplr].NeckItem._iStatFlag) oc = INVOICLR; + if (f <= ICLAST) + OutlineSlabCel(oc, 589, 220, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, 589, 220, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].NeckItem._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(589, 220, pCursCels, f, w, 0, 8); + else + DrawSlabCel(589, 220, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(589, 220, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(589, 220, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + } + if (plr[myplr].Hand1Item._itype != -1) { + ChangeBackground(401, 320, 56, 84); + f = plr[myplr].Hand1Item._iCurs + ICSTART; + w = CursorWidth[f]; + if (w == 28) xx = 415; + else xx = 401; + if (CursorHeight[f] == 84) yy = 320; + else yy = 306; + if (cursinvitem == INVLOC_HAND1) { + oc = INVOCLR; + if (plr[myplr].Hand1Item._iMagical) oc = INVOMCLR; + if (!plr[myplr].Hand1Item._iStatFlag) oc = INVOICLR; + if (f <= ICLAST) + OutlineSlabCel(oc, xx, yy, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, xx, yy, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].Hand1Item._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(xx, yy, pCursCels, f, w, 0, 8); + else + DrawSlabCel(xx, yy, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(xx, yy, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(xx, yy, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + if (plr[myplr].Hand1Item._iLoc == IL_2HAND + && !(plr[myplr]._pClass == CLASS_BARBARIAN + && (plr[myplr].Hand1Item._itype == IT_SWORD || + plr[myplr].Hand1Item._itype == IT_MACE) + ) + ) { + ChangeBackground(631, 320, 56, 84); + nLVal = 0; + nTrans = TRUE; + if (w == 28) pB = gpBuffer + 246405; + else pB = gpBuffer + 246391; + if (f <= ICLAST) + TDrawSlabCelPL (pB, pCursCels, f, w, 0, 8); + else + TDrawSlabCelPL (pB, pCursCels2, f - ICLAST, w, 0, 8); + nTrans = FALSE; + } + } + if (plr[myplr].Hand2Item._itype != -1) { + ChangeBackground(631, 320, 56, 84); + f = plr[myplr].Hand2Item._iCurs + ICSTART; + w = CursorWidth[f]; + if (w == 28) xx = 645; + else xx = 633; + if (CursorHeight[f] == 84) yy = 320; + else yy = 306; + if (cursinvitem == INVLOC_HAND2) { + oc = INVOCLR; + if (plr[myplr].Hand2Item._iMagical) oc = INVOMCLR; + if (!plr[myplr].Hand2Item._iStatFlag) oc = INVOICLR; + if (f <= ICLAST) + OutlineSlabCel(oc, xx, yy, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, xx, yy, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].Hand2Item._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(xx, yy, pCursCels, f, w, 0, 8); + else + DrawSlabCel(xx, yy, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(xx, yy, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(xx, yy, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + } + if (plr[myplr].BodyItem._itype != -1) { + ChangeBackground(517, 320, 56, 84); + f = plr[myplr].BodyItem._iCurs + ICSTART; + w = CursorWidth[f]; + if (cursinvitem == INVLOC_BODY) { + oc = INVOCLR; + if (plr[myplr].BodyItem._iMagical) oc = INVOMCLR; + if (!plr[myplr].BodyItem._iStatFlag) oc = INVOICLR; + if (f <= ICLAST) + OutlineSlabCel(oc, 517, 320, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, 517, 320, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].BodyItem._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(517, 320, pCursCels, f, w, 0, 8); + else + DrawSlabCel(517, 320, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(517, 320, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(517, 320, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + } + + for (i = 0; i < MAXINV; i++) { + invtest[i] = FALSE; + if (plr[myplr].InvGrid[i] != 0) + ChangeBackground(InvRect[i+25].x + 64, InvRect[i+25].y + 159, 28, 28); + } + + for (i = 0; i < MAXINV; i++) { + if (plr[myplr].InvGrid[i] > 0) { + app_assert(!invtest[i]); + invtest[i] = TRUE; + app_assert(plr[myplr].InvGrid[i] <= plr[myplr]._pNumInv); + ii = plr[myplr].InvGrid[i] - 1; + f = plr[myplr].InvList[ii]._iCurs + ICSTART; + w = CursorWidth[f]; + if (cursinvitem == (ii + NUM_INVLOC)) { + oc = INVOCLR; + if (plr[myplr].InvList[ii]._iMagical) oc = INVOMCLR; + if (!plr[myplr].InvList[ii]._iStatFlag) oc = INVOICLR; + if (f <= ICLAST) + OutlineSlabCel(oc, InvRect[i+25].x + 64, InvRect[i+25].y + 159, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, InvRect[i+25].x + 64, InvRect[i+25].y + 159, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].InvList[ii]._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(InvRect[i+25].x + 64, InvRect[i+25].y + 159, pCursCels, f, w, 0, 8); + else + DrawSlabCel(InvRect[i+25].x + 64, InvRect[i+25].y + 159, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(InvRect[i+25].x + 64, InvRect[i+25].y + 159, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(InvRect[i+25].x + 64, InvRect[i+25].y + 159, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawSpdBar() +{ + int i, f, w, oc, idata; + long poffset; + + if (talkflag) return; + CopyCtrlPan(205, 21, 232, 28, 269, 517); + for (i = 0; i < MAXSPD; i++) { + if (plr[myplr].SpdList[i]._itype != -1) { + ChangeBackground(InvRect[i+65].x + 64, InvRect[i+65].y + 159, 28, 28); + f = plr[myplr].SpdList[i]._iCurs + ICSTART; + w = CursorWidth[f]; + if (cursinvitem == (i + 47)) { + oc = INVOCLR; + if (plr[myplr].SpdList[i]._iMagical) oc = INVOMCLR; + if (!plr[myplr].SpdList[i]._iStatFlag) oc = INVOICLR; + if (f <= ICLAST) + OutlineSlabCel(oc, InvRect[i+65].x + 64, InvRect[i+65].y + 159, pCursCels, f, w, 0, 8); + else + OutlineSlabCel(oc, InvRect[i+65].x + 64, InvRect[i+65].y + 159, pCursCels2, f - ICLAST, w, 0, 8); + } + if (plr[myplr].SpdList[i]._iStatFlag) { + app_assert(pCursCels); + if (f <= ICLAST) + DrawSlabCel(InvRect[i+65].x + 64, InvRect[i+65].y + 159, pCursCels, f, w, 0, 8); + else + DrawSlabCel(InvRect[i+65].x + 64, InvRect[i+65].y + 159, pCursCels2, f - ICLAST, w, 0, 8); + } + else { + if (f <= ICLAST) + DrawSlabCelI(InvRect[i+65].x + 64, InvRect[i+65].y + 159, pCursCels, f, w, 0, 8, LIGHT_INFRA); + else + DrawSlabCelI(InvRect[i+65].x + 64, InvRect[i+65].y + 159, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); + } + idata = plr[myplr].SpdList[i].IDidx; + if (AllItemsList[idata].iUsable && plr[myplr].SpdList[i]._iStatFlag && + (plr[myplr].SpdList[i]._itype != IT_GOLD)) + { + BYTE c = char2print(i + '1'); + c = fonttrans[c]; + poffset = nBuffWTbl[InvRect[i+65].y + 159] + InvRect[i+65].x + 92 - fontkern[c]; + DrawPanelFont(poffset, c, ICOLOR_WHITE); + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL AutoPlace(int pnum, int ii, int sx, int sy, BOOL saveflag) +{ + int i, j, xx, yy; + BOOL done; + + done = TRUE; + yy = (ii / 10) * 10; + if (yy < 0) yy = 0; + for (j = 0; (j < sy) && done; j++) { + if (yy >= 40) done = FALSE; + xx = (ii % 10); + if (xx < 0) xx = 0; + for (i = 0; (i < sx) && done; i++) { + if (xx >= 10) done = FALSE; + else done = (plr[pnum].InvGrid[xx+yy] == 0); + xx++; + } + yy+=10; + } + + if ((done) && (saveflag)) { + i = plr[pnum]._pNumInv; + plr[pnum].InvList[i] = plr[pnum].HoldItem; + plr[pnum]._pNumInv++; + yy = (ii / 10) * 10; + if (yy < 0) yy = 0; + for (j = 0; j < sy; j++) { + xx = (ii % 10); + if (xx < 0) xx = 0; + for (i = 0; i < sx; i++) { + if ((i == 0) && (j == sy-1)) plr[pnum].InvGrid[xx+yy] = plr[pnum]._pNumInv; + else plr[pnum].InvGrid[xx+yy] = -plr[pnum]._pNumInv; + xx++; + } + yy+=10; + } + CalcPlrScrolls(pnum); + } + return(done); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL SpecialAutoPlace(int pnum, int ii, int sx, int sy, BOOL saveflag) +{ + int i, j, xx, yy; + BOOL done; + + //Check InvList + done = TRUE; + yy = (ii / 10) * 10; + if (yy < 0) yy = 0; + for (j = 0; (j < sy) && done; j++) { + if (yy >= 40) done = FALSE; + xx = (ii % 10); + if (xx < 0) xx = 0; + for (i = 0; (i < sx) && done; i++) { + if (xx >= 10) done = FALSE; + else done = (plr[pnum].InvGrid[xx+yy] == 0); + xx++; + } + yy+=10; + } + //Inventory is full so check SpdList + if (!done) { + if (sx > 1 || sy > 1) done = FALSE; + else { + for (i = 0; i < MAXSPD; i++) { + if (plr[pnum].SpdList[i]._itype == -1) { + done = TRUE; + break; + } + } + } + } + + if ((done) && (saveflag)) { + i = plr[pnum]._pNumInv; + plr[pnum].InvList[i] = plr[pnum].HoldItem; + plr[pnum]._pNumInv++; + yy = (ii / 10) * 10; + if (yy < 0) yy = 0; + for (j = 0; j < sy; j++) { + xx = (ii % 10); + if (xx < 0) xx = 0; + for (i = 0; i < sx; i++) { + if ((i == 0) && (j == sy-1)) plr[pnum].InvGrid[xx+yy] = plr[pnum]._pNumInv; + else plr[pnum].InvGrid[xx+yy] = -plr[pnum]._pNumInv; + xx++; + } + yy+=10; + } + CalcPlrScrolls(pnum); + } + return(done); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL GoldAutoPlace(int pnum) +{ + int i, ii, xx, yy; + long gt; + BOOL done; + + // Check if it can be added on to a gold location + done = FALSE; + for (i = 0; (i < plr[pnum]._pNumInv) && (!done); i++) { + if (plr[pnum].InvList[i]._itype == IT_GOLD) { + gt = plr[pnum].HoldItem._ivalue + plr[pnum].InvList[i]._ivalue; + if (gt <= GOLD_VMAX) { + plr[pnum].InvList[i]._ivalue += plr[pnum].HoldItem._ivalue; + if (gt >= GOLD_VT2) { + plr[pnum].InvList[i]._iCurs = ITEM_5GOLD; + } else { + if (gt <= GOLD_VT1) plr[pnum].InvList[i]._iCurs = ITEM_1GOLD; + else plr[pnum].InvList[i]._iCurs = ITEM_3GOLD; + } + plr[pnum]._pGold = CalculateGold(pnum); + plr[pnum].HoldItem._ivalue = 0; + done = TRUE; + } + else if (plr[pnum].InvList[i]._ivalue < GOLD_VMAX) { + // There's room, add to existing gold. + int const depositGold = GOLD_VMAX - plr[pnum].InvList[i]._ivalue; + plr[pnum].InvList[i]._ivalue = GOLD_VMAX; + plr[pnum].InvList[i]._iCurs = ITEM_5GOLD; + + plr[pnum].HoldItem._ivalue -= depositGold; + // Just in case. + if (plr[pnum].HoldItem._ivalue < 0) + { + plr[pnum].HoldItem._ivalue = 0; + done = TRUE; + } + GetPlrHandSeed(&plr[pnum].HoldItem); + + SetDropGoldCursor(pnum); + plr[pnum]._pGold = CalculateGold(pnum); + } + } + } + + +#if 0 + // If there's still gold in my hand, try to place it in more empty slots + if (!done) { + for (i = 0; (i < plr[pnum]._pNumInv) && (!done); i++) { + if (plr[pnum].InvList[i]._itype == IT_GOLD) { + if (plr[pnum].InvList[i]._ivalue < GOLD_VMAX) { + gt = plr[pnum].InvList[i]._ivalue + plr[pnum].HoldItem._ivalue; + if (gt <= GOLD_VMAX) { + plr[pnum].InvList[i]._ivalue += plr[pnum].HoldItem._ivalue; + if (gt >= GOLD_VT2) { + plr[pnum].InvList[i]._iCurs = ITEM_5GOLD; + } else { + if (gt <= GOLD_VT1) plr[pnum].InvList[i]._iCurs = ITEM_1GOLD; + else plr[pnum].InvList[i]._iCurs = ITEM_3GOLD; + } + plr[pnum]._pGold = CalculateGold(pnum); + done = TRUE; + } + } + } + } + } +#endif + + // Lastly check for any empty space to drop put gold into + if (!done) { + for (ii = MAXINV-1; (ii >= 0) && (!done); --ii) { + yy = (ii / 10) * 10; + xx = ii % 10; + if (plr[pnum].InvGrid[xx+yy] == 0) { + i = plr[pnum]._pNumInv; + plr[pnum].InvList[i] = plr[pnum].HoldItem; // struct copy. + plr[pnum]._pNumInv++; + plr[pnum].InvGrid[xx+yy] = plr[pnum]._pNumInv; + if (plr[pnum].HoldItem._ivalue >= GOLD_VT2) { + plr[pnum].InvList[i]._iCurs = ITEM_5GOLD; + } else { + if (plr[pnum].HoldItem._ivalue <= GOLD_VT1) plr[pnum].InvList[i]._iCurs = ITEM_1GOLD; + else plr[pnum].InvList[i]._iCurs = ITEM_3GOLD; + } + if (plr[pnum].HoldItem._ivalue > GOLD_VMAX) { + plr[pnum].HoldItem._ivalue -= GOLD_VMAX; + GetPlrHandSeed(&plr[pnum].HoldItem); + // We have to set the inventory value because we did a struct copy above. + plr[pnum].InvList[i]._ivalue = GOLD_VMAX; + } else { + done = TRUE; + plr[pnum].HoldItem._ivalue = 0; + plr[pnum]._pGold = CalculateGold(pnum); + SetCursor(GLOVE_CURS); + } + } + } + } + return(done); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL WeaponAutoPlace(int pnum) +{ + if (plr[pnum]._pClass == CLASS_MONK) // Monks don't autoequip weapons + return FALSE; // (open-hand is often better) + + if (plr[pnum].HoldItem._iLoc == IL_2HAND + && !(plr[pnum]._pClass == CLASS_BARBARIAN + && (plr[pnum].HoldItem._itype == IT_SWORD || + plr[pnum].HoldItem._itype == IT_MACE) + ) + ) + { + if ((plr[pnum].Hand1Item._itype != -1) || (plr[pnum].Hand2Item._itype != -1)) return(FALSE); + NetSendCmdChItem(TRUE, INVLOC_HAND1); + plr[pnum].Hand1Item = plr[pnum].HoldItem; + return(TRUE); + } + else + { + if (plr[pnum]._pClass != CLASS_BARD) + { + if ((plr[pnum].Hand1Item._itype != -1) && (plr[pnum].Hand1Item._iClass == IC_WEAP)) return(FALSE); + if ((plr[pnum].Hand2Item._itype != -1) && (plr[pnum].Hand2Item._iClass == IC_WEAP)) return(FALSE); + } + if (plr[pnum].Hand1Item._itype == -1) { + NetSendCmdChItem(TRUE, INVLOC_HAND1); + plr[pnum].Hand1Item = plr[pnum].HoldItem; + } else { + if ((plr[pnum].Hand2Item._itype == -1) && (plr[pnum].Hand1Item._iLoc != IL_2HAND)) { + NetSendCmdChItem(TRUE, INVLOC_HAND2); + plr[pnum].Hand2Item = plr[pnum].HoldItem; + } else return(FALSE); + } + return(TRUE); + } + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int SwapItem(ItemStruct *a, ItemStruct *b) +{ + ItemStruct h; + + h = *a; + *a = *b; + *b = h; + return(h._iCurs + ICSTART); +} + +/*-----------------------------------------------------------------------* +** Place cursor item into inventory window +**-----------------------------------------------------------------------*/ + +void CheckInvPaste(int pnum, int mx, int my) +{ + int r; + int i, j, xx, yy, ii; + int il, cn, it, iv, ig; + long gt; + ItemStruct tempitem; + + SetICursor(plr[pnum].HoldItem._iCurs + ICSTART); + + int cx = mx + (icursW>>1); // center of cursor graphic + int cy = my + (icursH>>1); + int const sx = icursW28; // size of cursor, in 28x28 blocks + int const sy = icursH28; + + BOOL done = FALSE; + for (r = 0; (r < INVRECTS) && (!done); r++) { + if ((cx >= InvRect[r].x) && (cx < InvRect[r].x + 28) && (cy >= InvRect[r].y - 29) && (cy < InvRect[r].y)) { + done = TRUE; + r--; + } + // shift for inv grid + if (r == 24) { + if (!(sx & 1)) cx -= 14; + if (!(sy & 1)) cy -= 14; + } + // shift back y for spd bar + if (r == 64) { + if (!(sy & 1)) cy += 14; + } + } + + if (done) { + // Check if correct item location type + il = IL_INV; + if ((r >= 0) && (r <= 3)) il = IL_HEAD; + if ((r >= 4) && (r <= 5)) il = IL_RING; + if (r == 6) il = IL_NECK; + if ((r >= 7) && (r <= 18)) il = IL_HAND; + if ((r >= 19) && (r <= 24)) il = IL_BODY; + if ((r >= 65) && (r <= 72)) il = IL_SPD; + + done = FALSE; + if (plr[pnum].HoldItem._iLoc == il) done = TRUE; + if ((il == IL_HAND) && (plr[pnum].HoldItem._iLoc == IL_2HAND)) { + + // Hack so placement will work for a two handed weapon. + if (plr[pnum]._pClass == CLASS_BARBARIAN + && (plr[pnum].HoldItem._itype == IT_SWORD || + plr[pnum].HoldItem._itype == IT_MACE) + ) + { + il = IL_HAND; + } + else + { + il = IL_2HAND; + } + done = TRUE; + } + if ((plr[pnum].HoldItem._iLoc == IL_INV) && (il == IL_SPD) && (sx == 1) && (sy == 1)) { + done = TRUE; + if (!AllItemsList[plr[pnum].HoldItem.IDidx].iUsable) done = FALSE; + if (!plr[pnum].HoldItem._iStatFlag) done = FALSE; + if (plr[pnum].HoldItem._itype == IT_GOLD) done = FALSE; + } + + if (il == IL_INV) { + ii = r - 25; + iv = 0; + done = TRUE; + if (plr[pnum].HoldItem._itype == IT_GOLD) { + yy = (ii / 10) * 10; + xx = ii % 10; + if (plr[pnum].InvGrid[xx+yy] != 0) { + ig = plr[pnum].InvGrid[xx+yy]; + if (ig > 0) { + if (plr[pnum].InvList[ig-1]._itype != IT_GOLD) iv = ig; + } else iv = -ig; + } + } else { + yy = ((ii / 10) - ((sy - 1) >> 1)) * 10; + if (yy < 0) yy = 0; + for (j = 0; (j < sy) && done; j++) { + if (yy >= 40) done = FALSE; + xx = (ii % 10) - ((sx - 1) >> 1); + if (xx < 0) xx = 0; + for (i = 0; (i < sx) && done; i++) { + if (xx >= 10) done = FALSE; + else { + if (plr[pnum].InvGrid[xx+yy] != 0) { + ig = plr[pnum].InvGrid[xx+yy]; + if (ig < 0) ig = -ig; + if (iv != 0) { + if (iv != ig) done = FALSE; + } else iv = ig; + } + } + xx++; + } + yy+=10; + } + } + } + + // Do I have the min stats to place this item? + if ((done) && (il != IL_INV) && (il != IL_SPD) && (!plr[pnum].HoldItem._iStatFlag)) { + done = FALSE; + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR13); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE13); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE13); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySFX(PS_MONK13); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySFX(PS_BARD13); + else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN13); + #endif + } + + if (done) { + it = ItemCAnimTbl[plr[pnum].HoldItem._iCurs]; + if(pnum == myplr) + PlaySFX(ItemInvSnds[it]); + cn = GLOVE_CURS; // Go back to gaunts unless something else there + switch (il) { + case IL_HEAD : + NetSendCmdChItem(FALSE, INVLOC_HEAD); + if (plr[pnum].HeadItem._itype == -1) plr[pnum].HeadItem = plr[pnum].HoldItem; + else cn = SwapItem(&plr[pnum].HeadItem, &plr[pnum].HoldItem); + break; + case IL_RING : + if (r == 4) { + NetSendCmdChItem(FALSE, INVLOC_RING1); + if (plr[pnum].Ring1Item._itype == -1) plr[pnum].Ring1Item = plr[pnum].HoldItem; + else cn = SwapItem(&plr[pnum].Ring1Item, &plr[pnum].HoldItem); + } else { + NetSendCmdChItem(FALSE, INVLOC_RING2); + if (plr[pnum].Ring2Item._itype == -1) plr[pnum].Ring2Item = plr[pnum].HoldItem; + else cn = SwapItem(&plr[pnum].Ring2Item, &plr[pnum].HoldItem); + } + break; + case IL_NECK: + NetSendCmdChItem(FALSE, INVLOC_NECK); + if (plr[pnum].NeckItem._itype == -1) plr[pnum].NeckItem = plr[pnum].HoldItem; + else cn = SwapItem(&plr[pnum].NeckItem, &plr[pnum].HoldItem); + break; + case IL_HAND : + if (r <= 12) { + if (plr[pnum].Hand1Item._itype == -1) { + if ((plr[pnum].Hand2Item._itype != -1) + && (plr[pnum].Hand2Item._iClass == plr[pnum].HoldItem._iClass) + && !(plr[pnum]._pClass == CLASS_BARD + && plr[pnum].Hand2Item._iClass == IC_WEAP + && plr[pnum].HoldItem._iClass == IC_WEAP) + ) { + NetSendCmdChItem(FALSE, INVLOC_HAND2); + cn = SwapItem(&plr[pnum].Hand2Item, &plr[pnum].HoldItem); + } else { + NetSendCmdChItem(FALSE, INVLOC_HAND1); + plr[pnum].Hand1Item = plr[pnum].HoldItem; + } + } else { + if ((plr[pnum].Hand2Item._itype != -1) + && (plr[pnum].Hand2Item._iClass == plr[pnum].HoldItem._iClass) + && !(plr[pnum]._pClass == CLASS_BARD + && plr[pnum].Hand2Item._iClass == IC_WEAP + && plr[pnum].HoldItem._iClass == IC_WEAP) + ) { + NetSendCmdChItem(FALSE, INVLOC_HAND2); + cn = SwapItem(&plr[pnum].Hand2Item, &plr[pnum].HoldItem); + } else { + NetSendCmdChItem(FALSE, INVLOC_HAND1); + cn = SwapItem(&plr[pnum].Hand1Item, &plr[pnum].HoldItem); + } + } + } else { + if (plr[pnum].Hand2Item._itype == -1) { + if ((plr[pnum].Hand1Item._itype != -1) + && (plr[pnum].Hand1Item._iLoc == IL_2HAND + && !(plr[pnum]._pClass == CLASS_BARBARIAN + && (plr[pnum].Hand1Item._itype == IT_SWORD || + plr[pnum].Hand1Item._itype == IT_MACE ) + ) + ) + ) { + NetSendCmdChItem(FALSE, INVLOC_HAND1); + SwapItem(&plr[pnum].Hand2Item, &plr[pnum].Hand1Item); + cn = SwapItem(&plr[pnum].Hand2Item, &plr[pnum].HoldItem); + } else { + if ((plr[pnum].Hand1Item._itype != -1) + && (plr[pnum].Hand1Item._iClass == plr[pnum].HoldItem._iClass) + && !(plr[pnum]._pClass == CLASS_BARD + && plr[pnum].Hand1Item._iClass == IC_WEAP + && plr[pnum].HoldItem._iClass == IC_WEAP) + ) { + NetSendCmdChItem(FALSE, INVLOC_HAND1); + cn = SwapItem(&plr[pnum].Hand1Item, &plr[pnum].HoldItem); + } else { + NetSendCmdChItem(FALSE, INVLOC_HAND2); + plr[pnum].Hand2Item = plr[pnum].HoldItem; + } + } + } else { + if ((plr[pnum].Hand1Item._itype != -1) + && (plr[pnum].Hand1Item._iClass == plr[pnum].HoldItem._iClass + && !(plr[pnum]._pClass == CLASS_BARD + && plr[pnum].Hand1Item._iClass == IC_WEAP + && plr[pnum].HoldItem._iClass == IC_WEAP) + ) + ) { + NetSendCmdChItem(FALSE, INVLOC_HAND1); + cn = SwapItem(&plr[pnum].Hand1Item, &plr[pnum].HoldItem); + } else { + NetSendCmdChItem(FALSE, INVLOC_HAND2); + cn = SwapItem(&plr[pnum].Hand2Item, &plr[pnum].HoldItem); + } + } + } + break; + case IL_2HAND : + NetSendCmdDelItem(FALSE, INVLOC_HAND2); + if ((plr[pnum].Hand1Item._itype != -1) + && (plr[pnum].Hand2Item._itype != -1)) + { + tempitem = plr[pnum].HoldItem; + if (plr[pnum].Hand2Item._itype == IT_SHIELD) { + plr[pnum].HoldItem = plr[pnum].Hand2Item; + } else { + plr[pnum].HoldItem = plr[pnum].Hand1Item; + } + if (pnum == myplr) { + SetCursor(plr[pnum].HoldItem._iCurs + ICSTART); + } + else { + SetICursor(plr[pnum].HoldItem._iCurs + ICSTART); + } + + BOOL done2h(FALSE); + + for (i = 0; (i < MAXINV) && (!done2h); ++i) { + done2h = AutoPlace(pnum, i, icursW28, icursH28, TRUE); + } + + plr[pnum].HoldItem = tempitem; + if (pnum == myplr) + SetCursor(plr[pnum].HoldItem._iCurs + ICSTART); + else + SetICursor(plr[pnum].HoldItem._iCurs + ICSTART); + if (done2h) { + if (plr[pnum].Hand2Item._itype == IT_SHIELD) { + plr[pnum].Hand2Item._itype = -1; + } else { + plr[pnum].Hand1Item._itype = -1; + } + } else + return; + } + if ((plr[pnum].Hand1Item._itype == -1) + && (plr[pnum].Hand2Item._itype == -1)) { + NetSendCmdChItem(FALSE, INVLOC_HAND1); + plr[pnum].Hand1Item = plr[pnum].HoldItem; + } else { + NetSendCmdChItem(FALSE, INVLOC_HAND1); + if (plr[pnum].Hand1Item._itype == -1) SwapItem(&plr[pnum].Hand1Item, &plr[pnum].Hand2Item); + cn = SwapItem(&plr[pnum].Hand1Item, &plr[pnum].HoldItem); + } + if (plr[pnum].Hand1Item._itype == IT_STAFF) { + if ((plr[pnum].Hand1Item._iSpell) && (plr[pnum].Hand1Item._iCharges > 0)) { + plr[pnum]._pRSpell = plr[pnum].Hand1Item._iSpell; + plr[pnum]._pRSplType = SPT_ITEM; + force_redraw = FULLDRAW; + } + } + break; + case IL_BODY : + NetSendCmdChItem(FALSE, INVLOC_BODY); + if (plr[pnum].BodyItem._itype == -1) plr[pnum].BodyItem = plr[pnum].HoldItem; + else cn = SwapItem(&plr[pnum].BodyItem, &plr[pnum].HoldItem); + break; + case IL_INV : + // Gold is stackable + if ((plr[pnum].HoldItem._itype == IT_GOLD) && (iv == 0)) { + ii = r - 25; + yy = (ii / 10) * 10; + xx = ii % 10; + // Empty (== 0) or gold (> 0) + if (plr[pnum].InvGrid[xx+yy] > 0) { + i = plr[pnum].InvGrid[xx+yy] - 1; + gt = plr[pnum].InvList[i]._ivalue + plr[pnum].HoldItem._ivalue; + // Gold total <= GOLD_VMAX then all done + if (gt <= GOLD_VMAX) { + plr[pnum].InvList[i]._ivalue += plr[pnum].HoldItem._ivalue; + plr[pnum]._pGold += plr[pnum].HoldItem._ivalue; + if (gt >= GOLD_VT2) { + plr[pnum].InvList[i]._iCurs = ITEM_5GOLD; + } else { + if (gt <= GOLD_VT1) plr[pnum].InvList[i]._iCurs = ITEM_1GOLD; + else plr[pnum].InvList[i]._iCurs = ITEM_3GOLD; + } + } else { + // Fill as much as possible and keep holding extra + gt = GOLD_VMAX - plr[pnum].InvList[i]._ivalue; + plr[pnum]._pGold += gt; + plr[pnum].HoldItem._ivalue -= gt; + plr[pnum].InvList[i]._ivalue = GOLD_VMAX; + plr[pnum].InvList[i]._iCurs = ITEM_5GOLD; + if (plr[pnum].HoldItem._ivalue >= GOLD_VT2) cn = ITEM_5GOLD + ICSTART; + else { + if (plr[pnum].HoldItem._ivalue <= GOLD_VT1) cn = ITEM_1GOLD + ICSTART; + else cn = ITEM_3GOLD + ICSTART; + } + } + } else { + // Place gold in empty spot + ii = plr[pnum]._pNumInv; + plr[pnum].InvList[ii] = plr[pnum].HoldItem; + plr[pnum]._pNumInv++; + plr[pnum].InvGrid[xx+yy] = plr[pnum]._pNumInv; + plr[pnum]._pGold += plr[pnum].HoldItem._ivalue; + //Choose correct gold cursor + gt = plr[pnum].HoldItem._ivalue; + if (gt <= GOLD_VMAX) { + if (gt >= GOLD_VT2) { + plr[pnum].InvList[ii]._iCurs = ITEM_5GOLD; + } else { + if (gt <= GOLD_VT1) plr[pnum].InvList[ii]._iCurs = ITEM_1GOLD; + else plr[pnum].InvList[ii]._iCurs = ITEM_3GOLD; + } + } else { + plr[pnum].InvList[ii]._iCurs = ITEM_5GOLD; + } + } + } else { + // Item not gold + if (iv == 0) { + // No swaping item + ii = plr[pnum]._pNumInv; + plr[pnum].InvList[ii] = plr[pnum].HoldItem; + plr[pnum]._pNumInv++; + iv = plr[pnum]._pNumInv; + } else { + ii = iv-1; + if (plr[pnum].HoldItem._itype == IT_GOLD) plr[pnum]._pGold += plr[pnum].HoldItem._ivalue; + cn = SwapItem(&plr[pnum].InvList[ii], &plr[pnum].HoldItem); + if (plr[pnum].HoldItem._itype == IT_GOLD) plr[pnum]._pGold = CalculateGold(pnum); + for (i = 0; i < MAXINV; i++) { + if (plr[pnum].InvGrid[i] == iv) plr[pnum].InvGrid[i] = 0; + if (plr[pnum].InvGrid[i] == -iv) plr[pnum].InvGrid[i] = 0; + } + } + ii = r - 25; + yy = ((ii / 10) - ((sy - 1) >> 1)) * 10; + if (yy < 0) yy = 0; + for (j = 0; j < sy; j++) { + xx = (ii % 10) - ((sx - 1) >> 1); + if (xx < 0) xx = 0; + for (i = 0; i < sx; i++) { + if ((i == 0) && (j == sy-1)) plr[pnum].InvGrid[xx+yy] = iv; + else plr[pnum].InvGrid[xx+yy] = -iv; + xx++; + } + yy+=10; + } + } + break; + case IL_SPD: + ii = r - 65; + // Gold is stackable + if (plr[pnum].HoldItem._itype == IT_GOLD) { + // Check if something is already there + if (plr[pnum].SpdList[ii]._itype != -1) { + if (plr[pnum].SpdList[ii]._itype == IT_GOLD) { + gt = plr[pnum].SpdList[ii]._ivalue + plr[pnum].HoldItem._ivalue; + // Gold total <= GOLD_VMAX then all done + if (gt <= GOLD_VMAX) { + plr[pnum].SpdList[ii]._ivalue += plr[pnum].HoldItem._ivalue; + plr[pnum]._pGold += plr[pnum].HoldItem._ivalue; + if (gt >= GOLD_VT2) { + plr[pnum].SpdList[ii]._iCurs = ITEM_5GOLD; + } else { + if (gt <= GOLD_VT1) plr[pnum].SpdList[ii]._iCurs = ITEM_1GOLD; + else plr[pnum].SpdList[ii]._iCurs = ITEM_3GOLD; + } + } else { + // Fill as much as possible and keep holding extra + gt = GOLD_VMAX - plr[pnum].SpdList[ii]._ivalue; + plr[pnum]._pGold += gt; + plr[pnum].HoldItem._ivalue -= gt; + plr[pnum].SpdList[ii]._ivalue = GOLD_VMAX; + plr[pnum].SpdList[ii]._iCurs = ITEM_5GOLD; + if (plr[pnum].HoldItem._ivalue >= GOLD_VT2) cn = ITEM_5GOLD + ICSTART; + else { + if (plr[pnum].HoldItem._ivalue <= GOLD_VT1) cn = ITEM_1GOLD + ICSTART; + else cn = ITEM_3GOLD + ICSTART; + } + } + } else { + // Swap with non gold + plr[pnum]._pGold += plr[pnum].HoldItem._ivalue; + cn = SwapItem(&plr[pnum].SpdList[ii], &plr[pnum].HoldItem); + } + } else { + // Place gold in empty spot + plr[pnum].SpdList[ii] = plr[pnum].HoldItem; + plr[pnum]._pGold += plr[pnum].HoldItem._ivalue; + } + } else { + // Not gold. Place or swap + if (plr[pnum].SpdList[ii]._itype == -1) plr[pnum].SpdList[ii] = plr[pnum].HoldItem; + else { + cn = SwapItem(&plr[pnum].SpdList[ii], &plr[pnum].HoldItem); + if (plr[pnum].HoldItem._itype == IT_GOLD) plr[pnum]._pGold = CalculateGold(pnum); + } + } + drawsbarflag = TRUE; + break; + } + + CalcPlrInv(pnum,TRUE); + if (pnum == myplr) { + if (cn == GLOVE_CURS) SetCursorPos(MouseX + (cursW>>1),MouseY + (cursH>>1)); + SetCursor(cn); + } + } + } +} + +/*-----------------------------------------------------------------------** +** Change items for another player +**-----------------------------------------------------------------------*/ +// drb.patch1.start.02/10/97 +//void SyncInvPaste(int pnum, BYTE bLoc, int idx, WORD icreateinfo, int iseed) +void SyncInvPaste(int pnum, BYTE bLoc, int idx, WORD icreateinfo, int iseed, BOOL Id) +// drb.patch1.end.02/10/97 +{ + // temp use the first slot to grab an item + RecreateItem(TEMPAVAIL, idx, icreateinfo, iseed, 0); + PlayerStruct * p = &plr[pnum]; + p->HoldItem = item[TEMPAVAIL]; + // drb.patch1.start.02/10/97 + if (Id) p->HoldItem._iIdentified = TRUE; + // drb.patch1.end.02/10/97 + + if (bLoc < NUM_INVLOC) { + p->InvBody[bLoc] = p->HoldItem; + if (bLoc == INVLOC_HAND1) { + if (p->HoldItem._iLoc == IL_2HAND) + p->Hand2Item._itype = -1; + } + else if (bLoc == INVLOC_HAND2) { + if (p->HoldItem._iLoc == IL_2HAND) + p->Hand1Item._itype = -1; + } + } + + CalcPlrInv(pnum,TRUE); +} + +/*-----------------------------------------------------------------------** +** Pick up items from inventory window and set cursor appropriately +**-----------------------------------------------------------------------*/ + +void CheckInvCut(int pnum, int mx, int my) +{ + int r; + BOOL done; + int ii,iv,i; + + if (plr[pnum]._pmode > PM_WALK3) return; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + + done = FALSE; + for (r = 0; (r < INVRECTS) && (!done); r++) { + if ((mx >= InvRect[r].x) && (mx < InvRect[r].x + 29) && (my >= InvRect[r].y - 29) && (my < InvRect[r].y)) { + done = TRUE; + r--; + } + } + if (done) { + plr[pnum].HoldItem._itype = -1; + if ((r >= 0) && (r <= 3) && (plr[pnum].HeadItem._itype != -1)) { + NetSendCmdDelItem(FALSE, INVLOC_HEAD); + plr[pnum].HoldItem = plr[pnum].HeadItem; + plr[pnum].HeadItem._itype = -1; + } + if ((r == 4) && (plr[pnum].Ring1Item._itype != -1)) { + NetSendCmdDelItem(FALSE, INVLOC_RING1); + plr[pnum].HoldItem = plr[pnum].Ring1Item; + plr[pnum].Ring1Item._itype = -1; + } + if ((r == 5) && (plr[pnum].Ring2Item._itype != -1)) { + NetSendCmdDelItem(FALSE, INVLOC_RING2); + plr[pnum].HoldItem = plr[pnum].Ring2Item; + plr[pnum].Ring2Item._itype = -1; + } + if ((r == 6) && (plr[pnum].NeckItem._itype != -1)) { + NetSendCmdDelItem(FALSE, INVLOC_NECK); + plr[pnum].HoldItem = plr[pnum].NeckItem; + plr[pnum].NeckItem._itype = -1; + } + if ((r >= 7) && (r <= 12) && (plr[pnum].Hand1Item._itype != -1)) { + NetSendCmdDelItem(FALSE, INVLOC_HAND1); + plr[pnum].HoldItem = plr[pnum].Hand1Item; + plr[pnum].Hand1Item._itype = -1; + } + if ((r >= 13) && (r <= 18) && (plr[pnum].Hand2Item._itype != -1)) { + NetSendCmdDelItem(FALSE, INVLOC_HAND2); + plr[pnum].HoldItem = plr[pnum].Hand2Item; + plr[pnum].Hand2Item._itype = -1; + } + if ((r >= 19) && (r <= 24) && (plr[pnum].BodyItem._itype != -1)) { + NetSendCmdDelItem(FALSE, INVLOC_BODY); + plr[pnum].HoldItem = plr[pnum].BodyItem; + plr[pnum].BodyItem._itype = -1; + } + + if ((r >= 25) && (r <= 64)) { + ii = r - 25; + if (plr[pnum].InvGrid[ii] != 0) { + if (plr[pnum].InvGrid[ii] > 0) iv = plr[pnum].InvGrid[ii]; + else iv = -plr[pnum].InvGrid[ii]; + for (i = 0; i < MAXINV; i++) { + if ((plr[pnum].InvGrid[i] == iv) || (plr[pnum].InvGrid[i] == -iv)) + plr[pnum].InvGrid[i] = 0; + } + iv--; + plr[pnum].HoldItem = plr[pnum].InvList[iv]; + plr[pnum]._pNumInv--; + if ((plr[pnum]._pNumInv > 0) && (plr[pnum]._pNumInv != iv)) { + plr[pnum].InvList[iv] = plr[pnum].InvList[plr[pnum]._pNumInv]; + for (i = 0; i < MAXINV; i++) { + if (plr[pnum].InvGrid[i] == plr[pnum]._pNumInv+1) plr[pnum].InvGrid[i] = iv+1; + if (plr[pnum].InvGrid[i] == -(plr[pnum]._pNumInv+1)) plr[pnum].InvGrid[i] = -(iv+1); + } + } + } + } + if (r >= 65) { + ii = r - 65; + if (plr[pnum].SpdList[ii]._itype != -1) { + plr[pnum].HoldItem = plr[pnum].SpdList[ii]; + plr[pnum].SpdList[ii]._itype = -1; + drawsbarflag = TRUE; + } + } + + if (plr[pnum].HoldItem._itype != -1) { + if (plr[pnum].HoldItem._itype == IT_GOLD) plr[pnum]._pGold = CalculateGold(pnum); + CalcPlrInv(pnum,TRUE); + CheckItemStats(pnum); + if (pnum == myplr) { + PlaySFX(IS_IGRAB); + SetCursor(plr[pnum].HoldItem._iCurs + ICSTART); + SetCursorPos(mx - (cursW>>1),MouseY - (cursH>>1)); + } + } + } +} + +/*-----------------------------------------------------------------------* +** Remove an item from another player +**-----------------------------------------------------------------------*/ +void SyncInvCut(int pnum, BYTE bLoc) { + if (bLoc < NUM_INVLOC) + plr[pnum].InvBody[bLoc]._itype = -1; + if (plr[pnum]._pmode != PM_DEATH) CalcPlrInv(pnum,TRUE); + else CalcPlrInv(pnum,FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RemoveInvItem(int pnum, int iv) +{ + int i; + + iv++; + for (i = 0; i < MAXINV; i++) { + if ((plr[pnum].InvGrid[i] == iv) || (plr[pnum].InvGrid[i] == -iv)) + plr[pnum].InvGrid[i] = 0; + } + iv--; + plr[pnum]._pNumInv--; + if ((plr[pnum]._pNumInv > 0) && (plr[pnum]._pNumInv != iv)) { + plr[pnum].InvList[iv] = plr[pnum].InvList[plr[pnum]._pNumInv]; + for (i = 0; i < MAXINV; i++) { + if (plr[pnum].InvGrid[i] == plr[pnum]._pNumInv+1) plr[pnum].InvGrid[i] = iv+1; + if (plr[pnum].InvGrid[i] == -(plr[pnum]._pNumInv+1)) plr[pnum].InvGrid[i] = -(iv+1); + } + } + + CalcPlrScrolls(pnum); + if ((plr[pnum]._pRSplType == SPT_SCROLL) && (plr[pnum]._pRSpell != -1)) { + if (!(plr[pnum]._pScrlSpells & (1 << plr[pnum]._pRSpell-1))) plr[pnum]._pRSpell = -1; + force_redraw = FULLDRAW; + } +} + +StripPlayer(int pnum) +{ + int i; + + // Give the plr no items in hands gfx + if (plr[pnum]._pgfxnum != PGFX_NGUY) { + plr[pnum]._pgfxnum = PGFX_NGUY; + plr[pnum]._pGFXLoad = 0; + SetPlrAnims(pnum); + } + + ItemStruct *pi = &plr[pnum].InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) + pi->_itype = -1; + + + int oldnum = plr[pnum]._pNumInv; + + ZeroMemory(plr[pnum].InvGrid,sizeof(plr[pnum].InvGrid)); + plr[pnum]._pNumInv = 0; + for (i = 0; i < oldnum; ++i) + { + pi = &plr[pnum].InvList[i]; + if (pi->_itype == IT_GOLD) + { + int num = plr[pnum]._pNumInv; + ItemStruct tmp = *pi; + + pi->_itype = -1; + plr[pnum].InvList[num] = tmp; + plr[pnum]._pNumInv++; + plr[pnum].InvGrid[i] = plr[pnum]._pNumInv; + } + else + pi->_itype = -1; + } + + // zero speedbar + pi = &plr[pnum].SpdList[0]; + for (i = MAXSPD; i--; pi++) + pi->_itype = -1; + + CalcPlrItemVals(pnum,FALSE); + return FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RemoveSpdBarItem(int pnum, int iv) +{ + plr[pnum].SpdList[iv]._itype = -1; + CalcPlrScrolls(pnum); + if ((plr[pnum]._pRSplType == SPT_SCROLL) && (plr[pnum]._pRSpell != -1)) { + if (!(plr[pnum]._pScrlSpells & (1 << plr[pnum]._pRSpell-1))) plr[pnum]._pRSpell = -1; + } + force_redraw = FULLDRAW; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckInvScrn() { + if (curs >= ICSTART) CheckInvPaste(myplr, MouseX, MouseY); + else CheckInvCut(myplr, MouseX, MouseY); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckSpdBar() { + if ((MouseX > 190) && (MouseX < 437) && (MouseY > 352) && (MouseY < 385)) + CheckInvScrn(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckItemStats(int pnum) { + PlayerStruct * p = &plr[pnum]; + ItemStruct * pi = &p->HoldItem; + + pi->_iStatFlag = FALSE; + if (p->_pStrength < pi->_iMinStr) return; + if (p->_pMagic < (byte)pi->_iMinMag) return; + if (p->_pDexterity < pi->_iMinDex) return; + pi->_iStatFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CheckBookLevel(int pnum) +{ + if (plr[pnum].HoldItem._iMiscId != IMID_BOOK) return; + plr[pnum].HoldItem._iMinMag = spelldata[plr[pnum].HoldItem._iSpell].sMinInt; + int slvl = plr[pnum]._pSplLvl[plr[pnum].HoldItem._iSpell]; + while (slvl != 0) { + plr[pnum].HoldItem._iMinMag += ((plr[pnum].HoldItem._iMinMag * 20) / 100); + slvl--; + if ((plr[pnum].HoldItem._iMinMag + ((plr[pnum].HoldItem._iMinMag * 20) / 100)) > 255) { + plr[pnum].HoldItem._iMinMag = 255; + slvl = 0; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CheckQuestItem(int pnum) +{ + if (plr[pnum].HoldItem.IDidx == IDI_OPTAMULET) quests[Q_BLIND]._qactive = QUEST_DONE; + if (plr[pnum].HoldItem.IDidx == IDI_MUSHROOM + && quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE + && quests[Q_BKMUSHRM]._qvar1 == QS_MUSHSPAWNED) { + // say "That is a big mushroom" + #if !IS_VERSION(SHAREWARE) + sfxdelay = 10; + if (plr[pnum]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR95; + else if (plr[pnum]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE95; + else if (plr[pnum]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE95; + else if (plr[pnum]._pClass == CLASS_MONK) sfxdnum = PS_MONK95; + else if (plr[pnum]._pClass == CLASS_BARD) sfxdnum = PS_BARD95; + else if (plr[pnum]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN95; + #endif + quests[Q_BKMUSHRM]._qvar1 = QS_MUSHPICKED; + } + if (plr[pnum].HoldItem.IDidx == IDI_ANVIL) { + if (quests[Q_ANVIL]._qactive == QUEST_NOTACTIVE) { + quests[Q_ANVIL]._qactive = QUEST_NOTDONE; + quests[Q_ANVIL]._qvar1 = 1; + } + if (quests[Q_ANVIL]._qlog == TRUE) { + #if !IS_VERSION(SHAREWARE) + sfxdelay = 10; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR89; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE89; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE89; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK89; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD89; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN89; + #endif + } + } + + if (plr[pnum].HoldItem.IDidx == IDI_GLDNELIX) { + #if !IS_VERSION(SHAREWARE) + sfxdelay = 30; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR88; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE88; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE88; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK88; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD88; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN88; + #endif + } + if (plr[pnum].HoldItem.IDidx == IDI_ROCK) { + if (quests[Q_ROCK]._qactive == QUEST_NOTACTIVE) { + quests[Q_ROCK]._qactive = QUEST_NOTDONE; + quests[Q_ROCK]._qvar1 = 1; + } + if (quests[Q_ROCK]._qlog == TRUE) { + #if !IS_VERSION(SHAREWARE) + sfxdelay = 10; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR87; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE87; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE87; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK87; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD87; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN87; + #endif + } + } + + if (plr[pnum].HoldItem.IDidx == IDI_ARMOFVAL) { + quests[Q_BLOOD]._qactive = QUEST_DONE; + #if !IS_VERSION(SHAREWARE) + sfxdelay = 20; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR91; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE91; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE91; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK91; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD91; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN91; + #endif + } + + // Add pick up item triggers here. JKE + if (plr[pnum].HoldItem.IDidx == IDI_MAPOFDOOM) { + quests[Q_CRYPTMAP]._qactive = QUEST_NOTDONE; + quests[Q_CRYPTMAP]._qvar1 = 1; + quests[Q_CRYPTMAP]._qlog = FALSE; + + #if !IS_VERSION(SHAREWARE) + sfxdelay = 10; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR79; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE79; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE79; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK79; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD79; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN79; + #endif + + } + + if ((plr[pnum].HoldItem.IDidx == IDI_NOTE1) || + (plr[pnum].HoldItem.IDidx == IDI_NOTE2) || + (plr[pnum].HoldItem.IDidx == IDI_NOTE3)) + { + #if !IS_VERSION(SHAREWARE) + + int noteflag = 0; + int idi = plr[pnum].HoldItem.IDidx; + int x1, x2, x3; + + if (PlrHasItem(pnum, IDI_NOTE1, x1) || idi == IDI_NOTE1) + noteflag |= 0x01; + + if (PlrHasItem(pnum, IDI_NOTE2, x2) || idi == IDI_NOTE2) + noteflag |= 0x02; + + if (PlrHasItem(pnum, IDI_NOTE3, x3) || idi == IDI_NOTE3) + noteflag |= 0x04; + + if (noteflag == 0x07) + { + // "Just what I was looking for" + sfxdelay = 10; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR46; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE46; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE46; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK46; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD46; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN46; + + // Put the items together + switch(idi) + { + case IDI_NOTE1: + PlrHasItem(pnum, IDI_NOTE2, x2); + RemoveInvItem(pnum, x2); + PlrHasItem(pnum, IDI_NOTE3, x3); + RemoveInvItem(pnum, x3); + break; + case IDI_NOTE2: + PlrHasItem(pnum, IDI_NOTE1, x1); + RemoveInvItem(pnum, x1); + PlrHasItem(pnum, IDI_NOTE3, x3); + RemoveInvItem(pnum, x3); + break; + case IDI_NOTE3: + PlrHasItem(pnum, IDI_NOTE1, x1); + RemoveInvItem(pnum, x1); + PlrHasItem(pnum, IDI_NOTE2, x2); + RemoveInvItem(pnum, x2); + break; + } + + int ii = itemavail[0]; // use this item slot temporarily + ItemStruct tmp = item[ii]; + + GetItemAttrs(ii, IDI_FULLNOTE, 16); + SetupItem(ii); + plr[pnum].HoldItem = item[ii]; + + item[ii] = tmp; + } + #endif + } + +} + +/*-----------------------------------------------------------------------* +** Processes CMD_GETITEM player command +**-----------------------------------------------------------------------*/ + +void InvGetItem(int pnum, int ii) +{ + + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + if (dItem[item[ii]._ix][item[ii]._iy] == 0) return; // Already picked up? + // Next line can happen in mulitplayer due to latecency + if ((myplr == pnum) && (curs >= ICSTART)) { + NetSendCmdPItem(TRUE,CMD_SYNCPUTITEM,plr[myplr]._px,plr[myplr]._py); + //InvPutItem(myplr,plr[myplr]._px,plr[myplr]._py); + } + + // once an item is picked up it is no longer a pregen item + if (item[ii]._iUid != 0) + item[ii]._iCreateInfo &= ICI_PREGENMASK; + plr[pnum].HoldItem = item[ii]; + CheckQuestItem(pnum); + CheckBookLevel(pnum); + CheckItemStats(pnum); + + // added 970911 by DKT + BOOL done = FALSE; + if (plr[pnum].HoldItem._itype == IT_GOLD) { + if (GoldAutoPlace(pnum)) + done = TRUE; + } + + // PATCH1.JMM + DROPLOG(" InvGetItem: deleting item %d.\n",ii); +// item[ii]._iDelFlag = TRUE; + // ENDPATCH1.JMM + + dItem[item[ii]._ix][item[ii]._iy] = 0; + if (currlevel == CRYPTSTART) + { + if (item[ii]._ix == CornerStone.x && + item[ii]._iy == CornerStone.y) + { + CornerStone.item.IDidx = -1; + CornerStone.item._itype = 0; + CornerStone.item._ix = 0; + CornerStone.item._iy = 0; + CornerStone.item._iAnimFlag = FALSE; + CornerStone.item._iSelFlag = ISEL_NONE; + CornerStone.item._iIdentified = FALSE; + CornerStone.item._iPostDraw = FALSE; + + } + } + + // PATCH1.JMM + int j; + int jj; + + #if _DEBUG + for(j = 0; j < numitems; j++) { + DROPLOG(" InvGetItem: itemactive[%2.2d]: %2.2d\n",j,itemactive[j]); + } + #endif + + j = 0; + while (j < numitems) { + jj = itemactive[j]; + + if (jj == ii) { + DROPLOG(" InvGetItem: Removing item index %d (struct %d,numitems %d) from item list!\n",j,jj,numitems); + DeleteItem(jj, j); + j = 0; + } + else { + j++; + } + + } + // ENDPATCH1.JMM + + cursitem = -1; + if (!done) + NewCursor(plr[pnum].HoldItem._iCurs + ICSTART); +} + +/*-----------------------------------------------------------------------* +** Processes CMD_AGETITEM player command +**-----------------------------------------------------------------------*/ + +void AutoGetItem(int pnum, int ii) +{ + int i, g, w, h, idx; + BOOL done; + + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + + // drb.patch1.start.02/15/97 + if (ii != TEMPAVAIL) { + // drb.patch1.end.02/15/97 + if (dItem[item[ii]._ix][item[ii]._iy] == 0) return; // Already picked up? + } + + done = FALSE; + // once an item is picked up it is no longer a pregen item + if (item[ii]._iUid != 0) + item[ii]._iCreateInfo &= ICI_PREGENMASK; + // Pick it up to get params for placing UID_OPTAMULET + plr[pnum].HoldItem = item[ii]; + CheckQuestItem(pnum); + CheckBookLevel(pnum); + CheckItemStats(pnum); + SetICursor(plr[pnum].HoldItem._iCurs + ICSTART); + + // Try and fit it in + if (plr[pnum].HoldItem._itype == IT_GOLD) { + done = GoldAutoPlace(pnum); + + if (!done) + { + // If we only particially filled our inventory with gold. + // reduce the temp value by to the new amount we are holding. + item[ii]._ivalue = plr[pnum].HoldItem._ivalue; + } + } else { + done = FALSE; + g = plr[pnum]._pgfxnum & PGFX_MASK; + if (((g == PGFX_NGUY) || (g == PGFX_SGUY) || + (plr[pnum]._pClass == CLASS_BARD && (g == PGFX_ZGUY || g == PGFX_XGUY))) && + (plr[pnum]._pmode <= PM_WALK3) && + ((plr[pnum].HoldItem._iStatFlag) && (plr[pnum].HoldItem._iClass == IC_WEAP))) { + done = WeaponAutoPlace(pnum); + if (done) CalcPlrInv(pnum,TRUE); + } + if (!done) { + // all items are either 1x1, 1x2, 1x3, 2x2, or 2x3 + // the inv is 10x4 + w = icursW28; + h = icursH28; + if ((w == 1) && (h == 1)) { + // Check to see if speed bar available first + idx = plr[pnum].HoldItem.IDidx; + if ((plr[pnum].HoldItem._iStatFlag) && (AllItemsList[idx].iUsable)) { + for (i = 0; (i < MAXSPD) && (!done); i++) { + if (plr[pnum].SpdList[i]._itype == -1) { + plr[pnum].SpdList[i] = plr[pnum].HoldItem; + CalcPlrScrolls(pnum); + drawsbarflag = TRUE; + done = TRUE; + } + } + } + // Start in lower left and continue trying right then up a line + for (i = 30; (i <= 39) && (!done); i++) done = AutoPlace(pnum, i, w, h, TRUE); + for (i = 20; (i <= 29) && (!done); i++) done = AutoPlace(pnum, i, w, h, TRUE); + for (i = 10; (i <= 19) && (!done); i++) done = AutoPlace(pnum, i, w, h, TRUE); + for (i = 0; (i <= 9) && (!done); i++) done = AutoPlace(pnum, i, w, h, TRUE); + } + if ((w == 1) && (h == 2)) { + // Try 3rd row, 1st row, and then 2nd row + for (i = 29; (i >= 20) && (!done); i--) done = AutoPlace(pnum, i, w, h, TRUE); + for (i = 9; (i >= 0) && (!done); i--) done = AutoPlace(pnum, i, w, h, TRUE); + for (i = 19; (i >= 10) && (!done); i--) done = AutoPlace(pnum, i, w, h, TRUE); + } + if ((w == 1) && (h == 3)) { + // Try 1st row then 2nd row + for (i = 0; (i < 20) && (!done); i++) done = AutoPlace(pnum, i, w, h, TRUE); + } + if ((w == 2) && (h == 2)) { + // Try 1st and 3rd row starting right and moving left + for (i = 0; (i < 10) && (!done); i++) done = AutoPlace(pnum, AP2x2Tbl[i], w, h, TRUE); + // Try 3rd row, 1st row, and then 2nd row + for (i = 21; (i < 29) && (!done); i+=2) done = AutoPlace(pnum, i, w, h, TRUE); + for (i = 1; (i < 9) && (!done); i+=2) done = AutoPlace(pnum, i, w, h, TRUE); + for (i = 10; (i < 19) && (!done); i++) done = AutoPlace(pnum, i, w, h, TRUE); + } + if ((w == 2) && (h == 3)) { + // Try 1st row then 2nd row + for (i = 0; (i < 9) && (!done); i++) done = AutoPlace(pnum, i, w, h, TRUE); + for (i = 10; (i < 19) && (!done); i++) done = AutoPlace(pnum, i, w, h, TRUE); + } + } + } + + if (done) { + // PATCH1.JMM + DROPLOG(" AutoGetItem: set item[%d].iDelFlag = TRUE",ii); + //item[ii]._iDelFlag = TRUE; + dItem[item[ii]._ix][item[ii]._iy] = 0; + if (currlevel == CRYPTSTART) + { + if (item[ii]._ix == CornerStone.x && + item[ii]._iy == CornerStone.y) + { + CornerStone.item.IDidx = -1; + CornerStone.item._itype = 0; + CornerStone.item._ix = 0; + CornerStone.item._iy = 0; + CornerStone.item._iAnimFlag = FALSE; + CornerStone.item._iSelFlag = ISEL_NONE; + CornerStone.item._iIdentified = FALSE; + CornerStone.item._iPostDraw = FALSE; + } + } + + int j; + int jj; + + j = 0; + while (j < numitems) { + jj = itemactive[j]; + + if (jj == ii) { + DROPLOG(" AutogetItem: Removing item index %d (struct %d,numitems %d) from item list!\n",j,jj,numitems); + DeleteItem(jj, j); + j = 0; + } + else { + j++; + } + + } + // ENDPATCH1.JMM + + } else { + if (pnum == myplr) { + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR14+random(0,3)); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE14+random(0,3)); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE14+random(0,3)); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySFX(PS_MONK14+random(0,3)); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySFX(PS_BARD14+random(0,3)); + else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN14+random(0,3)); + #endif + } + plr[pnum].HoldItem = item[ii]; + DROPLOG("AutogetItem\n"); + RespawnItem(ii, TRUE); + NetSendCmdPItem(TRUE,CMD_RESPAWNITEM,item[ii]._ix,item[ii]._iy); + plr[pnum].HoldItem._itype = -1; + // we're going to drop the item so change the cursor back to a glove. + NewCursor(GLOVE_CURS); + } +} + +// PATCH1.JMM +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if _DEBUG +void VerifyItemActiveList( void ) +{ + int i, j; + UINT nItemIndex; + + int nCurrIndex; + WORD wCurrCI; + int dwCurrSeed; + BYTE x, y; + + for( i = 0; i < numitems; i++ ) { + nItemIndex = itemactive[i]; + + nCurrIndex = item[nItemIndex].IDidx; + wCurrCI = item[nItemIndex]._iCreateInfo; + dwCurrSeed = item[nItemIndex]._iSeed; + x = item[nItemIndex]._ix; + y = item[nItemIndex]._iy; + + for( j = i+1; j < numitems; j++ ) { + nItemIndex = itemactive[j]; + if((item[nItemIndex].IDidx == nCurrIndex) && (item[nItemIndex]._iSeed == dwCurrSeed) && (item[nItemIndex]._iCreateInfo == wCurrCI)) + DROPLOG(" VerifyItemActiveList: Duplicate item detected: itemactive[%d] = %d (%d %8.8x %4.4x)\n",j, nItemIndex, nCurrIndex, dwCurrSeed, wCurrCI); + +// app_assert(!((item[nItemIndex].IDidx == nCurrIndex) && (item[nItemIndex]._iSeed == dwCurrSeed) && (item[nItemIndex]._iCreateInfo == wCurrCI))); +// app_assert(!((item[nItemIndex]._ix == x) && (item[nItemIndex]._iy == y))); + } + } +} +#else + #define VerifyItemActiveList() +#endif +// ENDPATCH1.JMM + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int FindGetItem(int idx, WORD ci, int iseed) +{ + int i, ii; + + // PATCH1.JMM + VerifyItemActiveList(); + + for (i = 0; i < numitems; i++) { + ii = itemactive[i]; + if ((item[ii].IDidx == idx) && (item[ii]._iSeed == iseed) && (item[ii]._iCreateInfo == ci)) { + return (ii); + } + } + // ENDPATCH1.JMM + + return (-1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SyncGetItem(int x, int y, int idx, WORD ci, int iseed) +{ + int ii; + + // PATCH1.JMM + VerifyItemActiveList(); + + DROPLOG(" Doing SyncGetItem...\n"); + // try optimal location first + if (dItem[x][y] != 0) { + DROPLOG(" Attempting to find item by (x,y)\n"); + ii = dItem[x][y] - 1; + if ((item[ii].IDidx != idx) || (item[ii]._iSeed != iseed) || (item[ii]._iCreateInfo != ci)) { + ii = FindGetItem(idx, ci, iseed); + DROPLOG(" Bad (x,y). Did FindGetItem->%d.\n"); + } + else { + DROPLOG(" (x,y) said ii == %d, FindGetItem says ii == %d\n",ii,FindGetItem(idx,ci,iseed)); + } + } + else { + DROPLOG(" Nongood (x,y)\n"); + ii = FindGetItem(idx, ci, iseed); + } + + DROPLOG(" FindGetItem returned %d\n",ii); + + if (ii != -1) { + DROPLOG(" Removing item from map!\n"); + // remove from map + dItem[item[ii]._ix][item[ii]._iy] = 0; + + if (currlevel == CRYPTSTART) + { + if (item[ii]._ix == CornerStone.x && + item[ii]._iy == CornerStone.y) + { + CornerStone.item.IDidx = -1; + CornerStone.item._itype = 0; + CornerStone.item._ix = 0; + CornerStone.item._iy = 0; + CornerStone.item._iAnimFlag = FALSE; + CornerStone.item._iSelFlag = ISEL_NONE; + CornerStone.item._iIdentified = FALSE; + CornerStone.item._iPostDraw = FALSE; + } + } + // remove from list + int j = 0; + while (j < numitems) { + int jj = itemactive[j]; + + if (jj == ii) { + DROPLOG(" Removing item index %d (struct %d,numitems %d) from item list!\n",j,jj,numitems); + + DeleteItem(jj, j); + + jj = FindGetItem(idx,ci,iseed); + DROPLOG(" Item removed. FindGetItem->%d, numitems->%d\n", jj, numitems); + + j = 0; + } + else { + j++; + } + + } + + app_assert(FindGetItem(idx, ci, iseed) == -1); + DROPLOG(" Item is definitely removed!\n"); + } + // ENDPATCH1.JMM +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL CanPut(int i, int j) { + int oi; + + if (dItem[i][j]) return FALSE; + if (nSolidTable[dPiece[i][j]]) return FALSE; + + if (dObject[i][j] != 0) { + if (dObject[i][j] > 0) oi = dObject[i][j]-1; + else oi = -(dObject[i][j]+1); + if (object[oi]._oSolidFlag) return FALSE; + } + if (dObject[i+1][j+1] > 0) { + oi = dObject[i+1][j+1]-1; + if (object[oi]._oSelFlag != OSEL_NONE) return FALSE; + } + if (dObject[i+1][j+1] < 0) { + oi = -(dObject[i+1][j+1]+1); + if (object[oi]._oSelFlag != OSEL_NONE) return FALSE; + } + if ((dObject[i+1][j] > 0) && (dObject[i][j+1] > 0)) { + oi = dObject[i+1][j]-1; + if (object[oi]._oSelFlag != OSEL_NONE) { + oi = dObject[i][j+1]-1; + if (object[oi]._oSelFlag != OSEL_NONE) return FALSE; + } + } + + if (((currlevel == 0) && (dMonster[i][j] != 0)) || + ((currlevel == 0) && (dMonster[i+1][j+1] != 0))) + return FALSE; + + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL TryInvPut() { + // can't drop if too many items on floor already + if (numitems >= MAXITEMS) return FALSE; + + int d = GetDirection(plr[myplr]._px, plr[myplr]._py, cursmx, cursmy); + int x = plr[myplr]._px + offset_x[d]; + int y = plr[myplr]._py + offset_y[d]; + if (CanPut(x,y)) return TRUE; + + d = (d - 1) & 0x7; + x = plr[myplr]._px + offset_x[d]; + y = plr[myplr]._py + offset_y[d]; + if (CanPut(x,y)) return TRUE; + + d = (d + 2) & 0x7; + x = plr[myplr]._px + offset_x[d]; + y = plr[myplr]._py + offset_y[d]; + if (CanPut(x,y)) return TRUE; + return(CanPut(plr[myplr]._px, plr[myplr]._py)); +} + + +// PATCH1.JMM.2/24/97 +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#define DUP_DISP_INTERVAL 5 +static DWORD sgdwLastTime = 0; + +void ShowDupString( LPCSTR lpszMessage ) { + DWORD dwCurrTime; + + dwCurrTime = GetTickCount( ); + + if((dwCurrTime - sgdwLastTime) < (DUP_DISP_INTERVAL*1000)) + return; + + sgdwLastTime = dwCurrTime; + + sysmsg_add_string( lpszMessage ); +} + + +// ENDPATCH1.JMM.2/24/97 + + +/*-----------------------------------------------------------------------* +** Processes CMD_PUTITEM player command from myself +**-----------------------------------------------------------------------*/ +int InvPutItem(int pnum, int x, int y) { + // can't drop if too many items on floor already + if (numitems >= MAXITEMS) { + DROPLOG("numitems >= MAXITEMS\n"); + return -1; + } + + // drb.patch1.start.02/18/97 + // already in list? + int ii = FindGetItem(plr[pnum].HoldItem.IDidx, + plr[pnum].HoldItem._iCreateInfo, plr[pnum].HoldItem._iSeed); + if (ii != -1) { + DROPLOG(" Duplicate item detected!\n"); + // JMM.PATCH1.2.22.97 + // NetSendString(1 << myplr, "A duplicate item has been detected. Unable to drop."); + ShowDupString("A duplicate item has been detected. Destroying duplicate..."); + SyncGetItem(x,y,plr[pnum].HoldItem.IDidx,plr[pnum].HoldItem._iCreateInfo,plr[pnum].HoldItem._iSeed); + // END.JMM.PATCH1.2.22.97 + } + // drb.patch1.end.02/18/97 + + VerifyItemActiveList(); + + // if square is too far away, then drop on adjacent square + int d = GetDirection(plr[pnum]._px, plr[pnum]._py, x, y); + int dx = x - plr[pnum]._px; + int dy = y - plr[pnum]._py; + if (abs(dx) > 1 || abs(dy) > 1) { + x = plr[pnum]._px + offset_x[d]; + y = plr[pnum]._py + offset_y[d]; + } + + if (!CanPut(x,y)) { + d = (d - 1) & 0x7; + x = plr[pnum]._px + offset_x[d]; + y = plr[pnum]._py + offset_y[d]; + if (!CanPut(x,y)) { + d = (d + 2) & 0x7; + x = plr[pnum]._px + offset_x[d]; + y = plr[pnum]._py + offset_y[d]; + if (!CanPut(x,y)) { + // radial search outward until a space is found + BOOL done = FALSE; + for (int l = 1; (l < 50) && !done; l++) { + for (int j = -l; (j <= l) && !done; j++) { + int yy = plr[pnum]._py + j; + for (int i = -l; (i <= l) && !done; i++) { + int xx = plr[pnum]._px + i; + if (!CanPut(xx,yy)) continue; + done = TRUE; + x = xx; + y = yy; + } + } + } + if (! done) return -1; + } + } + } +// JKEQUESTS Dropping stuff + if (currlevel == 0) + { + if (plr[pnum].HoldItem._iCurs == ITEM_RUNEBOMB) + { + if(((cursmx >= 79) && (cursmx <= 82)) && ((cursmy >= 61) && (cursmy <= 64))) + { + NetSendCmdLocParam2(FALSE, + CMD_OPEN_NEST, + plr[pnum]._px, + plr[pnum]._py, + dx, + dy ); + quests[Q_FARMER]._qactive = QUEST_DONE; + if (gbMaxPlayers != 1) + NetSendCmdQuest(TRUE, Q_FARMER); + return -1; + } + } + if (plr[pnum].HoldItem.IDidx == IDI_MAPOFDOOM) + { + if(((cursmx >= 35) && (cursmx <= 38)) && ((cursmy >= 20) && (cursmy <= 24))) + { + NetSendCmd(FALSE, CMD_OPEN_CRYPT); + quests[Q_CRYPTMAP]._qactive = QUEST_DONE; + if (gbMaxPlayers != 1) + NetSendCmdQuest(TRUE, Q_CRYPTMAP); + return -1; + } + } + } + + + app_assert(CanPut(x,y)); + ii = itemavail[0]; + dItem[x][y] = ii+1; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + + item[ii] = plr[pnum].HoldItem; + item[ii]._ix = x; + item[ii]._iy = y; + + + DROPLOG(" InvPutItem\n"); + RespawnItem(ii, TRUE); + numitems++; + + if (currlevel == CRYPTSTART) + { + if (x == CornerStone.x && y == CornerStone.y) + { +// memcpy(&(CornerStone.item), &(item[ii]), SAVE_ITEM_SIZE); + CornerStone.item = item[ii]; + + // Jims stuff + InitQTextMsg(TXT_CORNERSTONE1); + + quests[Q_CORNERSTONE]._qlog = FALSE; + quests[Q_CORNERSTONE]._qactive = QUEST_DONE; + + + } + } + + NewCursor(GLOVE_CURS); + return ii; +} + + +/*-----------------------------------------------------------------------* +** Processes CMD_PUTITEM player command from another person +**-----------------------------------------------------------------------*/ +#if CHEATS +BOOL syncdebug = FALSE; +#endif + + +int SyncPutItem( + int pnum, + int x, + int y, + int idx, + WORD icreateinfo, + int iseed, + BOOL Id, + int dur, + int mdur, + int ch, + int mch, + int ivalue, + DWORD ibuff, + int PLToHit, + int MaxDam, + int MinStr, + int MinMag, + int MinDex, + int AC) { + + #if CHEATS + if (syncdebug) { + sprintf(tempstr, "Player %i dropping item.", pnum); + NetSendString((1 << myplr), tempstr); + } + #endif + + // can't drop if too many items on floor already + if (numitems >= MAXITEMS) { + DROPLOG("numitems >= MAXITEMS\n"); + return -1; + } + + // drb.patch1.start.02/18/97 + // already in list? + int ii = FindGetItem(idx, icreateinfo, iseed); + if (ii != -1) { + DROPLOG(" Duplicate item detected!\n"); + // JMM.PATCH1.2.22.97 + //NetSendString(1 << myplr, "A duplicate item has been detected from another player."); + ShowDupString("A duplicate item has been detected from another player."); + SyncGetItem(x,y,idx,icreateinfo,iseed); + // END.JMM.PATCH1.2.22.97 + // return(-1); + } + // drb.patch1.end.02/18/97 + + // if square is too far away, then drop on adjacent square + int d = GetDirection(plr[pnum]._px, plr[pnum]._py, x, y); + int dx = x - plr[pnum]._px; + int dy = y - plr[pnum]._py; + if (abs(dx) > 1 || abs(dy) > 1) { + x = plr[pnum]._px + offset_x[d]; + y = plr[pnum]._py + offset_y[d]; + } + + if (!CanPut(x,y)) { + d = (d - 1) & 0x7; + x = plr[pnum]._px + offset_x[d]; + y = plr[pnum]._py + offset_y[d]; + if (!CanPut(x,y)) { + d = (d + 2) & 0x7; + x = plr[pnum]._px + offset_x[d]; + y = plr[pnum]._py + offset_y[d]; + if (!CanPut(x,y)) { + BOOL done = FALSE; + // radial search outward until a space is found + for (int l = 1; (l < 50) && !done; l++) { + for (int j = -l; (j <= l) && !done; j++) { + int yy = plr[pnum]._py + j; + for (int i = -l; (i <= l) && !done; i++) { + int xx = plr[pnum]._px + i; + if (!CanPut(xx,yy)) continue; + done = TRUE; + x = xx; + y = yy; + } + } + } + if (! done) { + DROPLOG("Failed to find a good square to drop in!\n"); + return -1; + } + } + } + } + + + app_assert(CanPut(x,y)); + ii = itemavail[0]; + dItem[x][y] = ii+1; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + + app_assert(ii >= 0); + + if (idx == IDI_EAR) { + RecreateEar(ii, icreateinfo, iseed, Id, dur, mdur, ch, mch, ivalue, ibuff); + } else { + RecreateItem(ii, idx, icreateinfo, iseed, ivalue); + if (Id) item[ii]._iIdentified = TRUE; + item[ii]._iDurability = dur; + item[ii]._iMaxDur = mdur; + item[ii]._iCharges = ch; + item[ii]._iMaxCharges = mch; + item[ii]._iPLToHit = PLToHit; + item[ii]._iMaxDam = MaxDam; + item[ii]._iMinStr = MinStr; + item[ii]._iMinMag = MinMag; + item[ii]._iMinDex = MinDex; + item[ii]._iAC = AC; + } + item[ii]._ix = x; + item[ii]._iy = y; + + DROPLOG("SyncPutItem: respawning object %d!\n",ii); + RespawnItem(ii, TRUE); + numitems++; + + if (currlevel == CRYPTSTART) + { + if (x == CornerStone.x && y == CornerStone.y) + { +// memcpy(&(CornerStone.item), &(item[ii]), SAVE_ITEM_SIZE); + CornerStone.item = item[ii]; + + // Jims stuff + InitQTextMsg(TXT_CORNERSTONE1); + + quests[Q_CORNERSTONE]._qlog = FALSE; + quests[Q_CORNERSTONE]._qactive = QUEST_DONE; + + } + } + + return(ii); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +char CheckInvHLight() { + + // find box + for (int r = 0; r < INVRECTS; r++) { + if ((MouseX >= InvRect[r].x) && + (MouseX < InvRect[r].x + 29) && + (MouseY >= InvRect[r].y - 29) && + (MouseY < InvRect[r].y)) + break; + } + if (r >= INVRECTS) return -1; + + char rv = -1; + infoclr = ICOLOR_WHITE; + ItemStruct * pi = NULL; + PlayerStruct * p = &plr[myplr]; + ClearPanel(); + + if (r >= 0 && r <= 3) { + rv = INVLOC_HEAD; + pi = &p->HeadItem; + } + else if (r == 4) { + rv = INVLOC_RING1; + pi = &p->Ring1Item; + } + else if (r == 5) { + rv = INVLOC_RING2; + pi = &p->Ring2Item; + } + else if (r == 6) { + rv = INVLOC_NECK; + pi = &p->NeckItem; + } + else if (r >= 7 && r <= 12) { + rv = INVLOC_HAND1; + pi = &p->Hand1Item; + } + else if (r >= 13 && r <= 18) { + // check for two handed item + pi = &p->Hand1Item; + if (pi->_itype != -1 && pi->_iLoc == IL_2HAND + && !(p->_pClass == CLASS_BARBARIAN + && ( p->Hand1Item._itype == IT_SWORD || + p->Hand1Item._itype == IT_MACE ) + ) + ) { + rv = INVLOC_HAND1; + } + else { + rv = INVLOC_HAND2; + pi = &p->Hand2Item; + } + } + else if (r >= 19 && r <= 24) { + rv = INVLOC_BODY; + pi = &p->BodyItem; + } + else if (r >= 25 && r <= 64) { + // is there an inventory item in this slot? + if (0 == (r = abs(p->InvGrid[r - 25]))) return -1; + + // make zero based + r--; + + // convert to global inventory slot number + rv = r + NUM_INVLOC; + + // get item + pi = &p->InvList[r]; + } + else if (r >= 65) { + drawsbarflag = TRUE; + r -= 65; + pi = &p->SpdList[r]; + if (pi->_itype == -1) return -1; + + // convert to global inventory slot number + rv = r + MAXINV + NUM_INVLOC; + } + + // Do I have an item (I should) + app_assert(pi); + + // Is it still there? + if (pi->_itype == -1) return -1; + + if (pi->_itype == IT_GOLD) { + int nGold = pi->_ivalue; + const char * get_pieces_str(int nGold); + sprintf(infostr,"%i gold %s",nGold,get_pieces_str(nGold)); + } + else { + if (pi->_iMagical == IMAGIC_MAGIC) infoclr = ICOLOR_BLUE; + else if (pi->_iMagical == IMAGIC_UNIQUE) infoclr = ICOLOR_GOLD; + strcpy(infostr, pi->_iName); + if (pi->_iIdentified) { + strcpy(infostr, pi->_iIName); + PrintItemDetails(pi); + } else { + PrintItemDur(pi); + } + } + + return rv; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RemoveScroll(int pnum) +{ + int i; + + for (i = 0; i < plr[pnum]._pNumInv; i++) { + if ((plr[pnum].InvList[i]._itype != -1) && + ((plr[pnum].InvList[i]._iMiscId == IMID_SCROLL) || + (plr[pnum].InvList[i]._iMiscId == IMID_TSCROLL)) && + (plr[pnum].InvList[i]._iSpell == plr[pnum]._pSpell)) { + RemoveInvItem(pnum, i); + CalcPlrScrolls(pnum); + return; + } + } + for (i = 0; i < MAXSPD; i++) { + if ((plr[pnum].SpdList[i]._itype != -1) && + ((plr[pnum].SpdList[i]._iMiscId == IMID_SCROLL) || + (plr[pnum].SpdList[i]._iMiscId == IMID_TSCROLL)) && + (plr[pnum].SpdList[i]._iSpell == plr[pnum]._pSpell)) { + RemoveSpdBarItem(pnum, i); + CalcPlrScrolls(pnum); + return; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL UseScroll() +{ + int i; + + if (curs != GLOVE_CURS) return(FALSE); + // rjs if (leveltype == 0) return(FALSE); + if (leveltype == 0 && spelldata[plr[myplr]._pRSpell].sTownSpell == FALSE) return(FALSE); + for (i = 0; i < plr[myplr]._pNumInv; i++) { + if ((plr[myplr].InvList[i]._itype != -1) && + ((plr[myplr].InvList[i]._iMiscId == IMID_SCROLL) || + (plr[myplr].InvList[i]._iMiscId == IMID_TSCROLL)) && + (plr[myplr].InvList[i]._iSpell == plr[myplr]._pRSpell)) { + return(TRUE); + } + } + for (i = 0; i < MAXSPD; i++) { + if ((plr[myplr].SpdList[i]._itype != -1) && + ((plr[myplr].SpdList[i]._iMiscId == IMID_SCROLL) || + (plr[myplr].SpdList[i]._iMiscId == IMID_TSCROLL)) && + (plr[myplr].SpdList[i]._iSpell == plr[myplr]._pRSpell)) { + return(TRUE); + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void UseStaffCharge(int pnum) +{ + if ((plr[pnum].Hand1Item._itype != -1) && + (plr[pnum].Hand1Item._iMiscId == IMID_STAFF || + plr[myplr].Hand1Item._iMiscId == IMID_UNIQUE) && + (plr[pnum].Hand1Item._iSpell == plr[pnum]._pRSpell) && + (plr[pnum].Hand1Item._iCharges > 0)) { + plr[pnum].Hand1Item._iCharges--; + CalcPlrStaff(pnum); + return; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL UseStaff() +{ + if (curs != GLOVE_CURS) return(FALSE); + if ((plr[myplr].Hand1Item._itype != -1) && + (plr[myplr].Hand1Item._iMiscId == IMID_STAFF || + plr[myplr].Hand1Item._iMiscId == IMID_UNIQUE) && + (plr[myplr].Hand1Item._iSpell == plr[myplr]._pRSpell) && + (plr[myplr].Hand1Item._iCharges > 0)) { + return(TRUE); + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL UseStaffSBook(int spl) +{ + if (curs != GLOVE_CURS) return(FALSE); + if ((plr[myplr].Hand1Item._itype != -1) && + (plr[myplr].Hand1Item._iMiscId == IMID_STAFF || + plr[myplr].Hand1Item._iMiscId == IMID_UNIQUE) && + (plr[myplr].Hand1Item._iSpell == spl) && + (plr[myplr].Hand1Item._iCharges > 0)) { + return(TRUE); + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL CheckUsable(int pnum, int cii) +{ + int c, idata; + BOOL rv; + + // Can't use items on my body, just in my inv + rv = FALSE; + if (cii <= 5) return(rv); + if (cii <= 46) { + c = cii - 7; + idata = plr[pnum].InvList[c].IDidx; + if (AllItemsList[idata].iUsable) rv = TRUE; + } else { + c = cii - 47; + idata = plr[pnum].SpdList[c].IDidx; + if (AllItemsList[idata].iUsable) rv = TRUE; + } + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +extern int dropGoldValue; + +void StartGoldDrop() +{ + // Save the index of the gold pile + initialDropGoldIndex = cursinvitem; + + if (cursinvitem <= 46) // Gold item is in InvList + // Save the value of the gold pile + initialDropGoldValue = plr[myplr].InvList[cursinvitem-7]._ivalue; + else // Gold item is in SpdList + // Save the value of the gold pile + initialDropGoldValue = plr[myplr].SpdList[cursinvitem-47]._ivalue; + + // Set flag so drop gold functionality is enabled + dropGoldFlag = TRUE; + // Initialize the drop gold value when right click gold pile + dropGoldValue = 0; + + if (talkflag) TalkEnd(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL UseInvItem(int pnum, int cii) +{ + int c, idata, it; + ItemStruct *Item; + BOOL speedlist; + + // Don't use while dead + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) return TRUE; + // Don't use unless glove curs + if (curs != GLOVE_CURS) return TRUE; + // Don't use during stores + if (stextflag != STORE_NONE) return TRUE; + + // Can't use items on my body, just in my inv + if (cii <= 5) return FALSE; + if (cii <= 46) { + c = cii - 7; + Item = &plr[pnum].InvList[c]; + speedlist = FALSE; + } else { + if (talkflag) return TRUE; + c = cii - 47; + Item = &plr[pnum].SpdList[c]; + speedlist = TRUE; + } + + idata = Item->IDidx; + switch (idata) + { + case IDI_MUSHROOM: + sfxdelay = 10; + #if !IS_VERSION(SHAREWARE) + if (plr[pnum]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR95; + else if (plr[pnum]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE95; + else if (plr[pnum]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE95; + else if (plr[pnum]._pClass == CLASS_MONK) sfxdnum = PS_MONK95; + else if (plr[pnum]._pClass == CLASS_BARD) sfxdnum = PS_BARD95; + else if (plr[pnum]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN95; + #endif + return TRUE; + case IDI_FUNGALTM: + PlaySFX(IS_IBOOK); + sfxdelay = 10; + if (plr[pnum]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR29; + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE29; + else if (plr[pnum]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE29; + else if (plr[pnum]._pClass == CLASS_MONK) sfxdnum = PS_MONK29; + else if (plr[pnum]._pClass == CLASS_BARD) sfxdnum = PS_BARD29; + else if (plr[pnum]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN29; + #endif + return TRUE; + } + if (!AllItemsList[idata].iUsable) + return FALSE; + if (!Item->_iStatFlag) { + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR13); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE13); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE13); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySFX(PS_MONK13); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySFX(PS_BARD13); + else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN13); + #endif + return TRUE; + } else { + // Was the item chosen a pile of gold + if ((Item->_iMiscId == IMID_NONE) && (Item->_itype == IT_GOLD)) + { + StartGoldDrop(); + return TRUE;; + } + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + + if ((Item->_iMiscId == IMID_SCROLL) && (currlevel == 0) && + (spelldata[Item->_iSpell].sTownSpell == FALSE)) return TRUE; + if ((Item->_iMiscId == IMID_TSCROLL) && (currlevel == 0) && + (spelldata[Item->_iSpell].sTownSpell == FALSE)) return TRUE; + if ((Item->_iMiscId > IMID_FIRSTRUNE) && + (Item->_iMiscId < IMID_LASTRUNE) && + (currlevel == 0)) return TRUE; + it = ItemCAnimTbl[Item->_iCurs]; + if (Item->_iMiscId == IMID_BOOK) PlaySFX(IS_RBOOK); + else if (pnum == myplr) PlaySFX(ItemInvSnds[it]); + UseItem(pnum, Item->_iMiscId, Item->_iSpell); + + if (speedlist) + { + if (plr[pnum].SpdList[c]._iMiscId == IMID_FULLNOTE) + { + InitQTextMsg(TXT_SKULLJRNL7); + invflag = FALSE; +// PlaySFX(HSFX_SKULLJRNL7); + return TRUE; + } + RemoveSpdBarItem(pnum, c); + } + else + { + // Don't delete map of doom when used + if (plr[pnum].InvList[c]._iMiscId == IMID_MAPOFDOOM) return TRUE; + if (plr[pnum].InvList[c]._iMiscId == IMID_FULLNOTE) + { + InitQTextMsg(TXT_SKULLJRNL7); + invflag = FALSE; +// PlaySFX(HSFX_SKULLJRNL7); + return TRUE; + } + RemoveInvItem(pnum, c); + } + } + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoTelekinesis() +{ + if (cursobj != -1) { + NetSendCmdParam1(TRUE, CMD_OPOBJT, cursobj); + } + if (cursitem != -1) { + NetSendCmdGItem(TRUE, CMD_REQUESTAGITEM, myplr, myplr, cursitem); + } + BOOL M_Talker (int); + if ((cursmonst != -1) && (!M_Talker(cursmonst)) && (monster[cursmonst].mtalkmsg == 0)) { + NetSendCmdParam1(TRUE, CMD_KNOCKBACK, cursmonst); + } + + NewCursor(GLOVE_CURS); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +long CalculateGold(int pnum) +{ + int i; + long gold; + + // Initialize gold + gold = 0; + // Find the gold in the speedbar list + for (i = 0; i < MAXSPD; i++) { + if (plr[pnum].SpdList[i]._itype == IT_GOLD) { + gold += plr[pnum].SpdList[i]._ivalue; + force_redraw = FULLDRAW; + } + } + // Find the gold in the inventory list + for (i = 0; i < plr[pnum]._pNumInv; i++) { + if (plr[pnum].InvList[i]._itype == IT_GOLD) + gold += plr[pnum].InvList[i]._ivalue; + } + + return(gold); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL DropItemBeforeTrig() +/*-----------------------------------------------------------------------** +** DESCRIPTION: Drops the item the player has in hand before talking to a +** towner or entering a level. +** INPUT: None +** RETURN: TRUE = The item was dropped successfully +** FALSE = The item could not be dropped. +/*-----------------------------------------------------------------------*/ +{ + if (TryInvPut()) { + NetSendCmdPItem(TRUE,CMD_PUTITEM,cursmx,cursmy); + NewCursor(GLOVE_CURS); + return TRUE; + } + return FALSE; +} + +int GetHighRingValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_RING + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_RING + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + + return itemValue; +} + +int GetHighBowValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_BOW + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_BOW + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + + return itemValue; +} + +int GetHighStaffValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_STAFF + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_STAFF + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + + return itemValue; +} + +int GetHighSwordValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_SWORD + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_SWORD + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + + return itemValue; +} + +int GetHighHelmValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_HELM + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_HELM + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + + return itemValue; +} + +int GetHighShieldValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_SHIELD + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_SHIELD + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + + return itemValue; +} + +int GetHighArmorValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && (plr[myPlr].InvBody[i]._itype == IT_ARMOR + || plr[myPlr].InvBody[i]._itype == IT_MARMOR + || plr[myPlr].InvBody[i]._itype == IT_HARMOR ) + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && (plr[myPlr].InvList[i]._itype == IT_ARMOR + || plr[myPlr].InvList[i]._itype == IT_MARMOR + || plr[myPlr].InvList[i]._itype == IT_HARMOR) + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + + return itemValue; +} + +int GetHighMaceValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_MACE + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_MACE + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + return itemValue; +} + +int GetHighAmuletValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_AMULET + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_AMULET + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + return itemValue; +} + +int GetHighAxeValue(int myPlr) +{ + int itemValue = 0; + int i; + + for (i =0; i < NUM_INVLOC; ++i) + { + if (plr[myPlr].InvBody[i]._iClass != -1 + && plr[myPlr].InvBody[i]._itype == IT_AXE + && itemValue < plr[myPlr].InvBody[i]._iIvalue) + { + itemValue = plr[myPlr].InvBody[i]._iIvalue; + } + } + for (i =0; i < MAXINV; ++i) + { + if (plr[myPlr].InvList[i]._iClass != -1 + && plr[myPlr].InvList[i]._itype == IT_AXE + && itemValue < plr[myPlr].InvList[i]._iIvalue) + { + itemValue = plr[myPlr].InvList[i]._iIvalue; + } + } + + return itemValue; +} + diff --git a/src/INV.H b/src/INV.H new file mode 100644 index 0000000..11f2d9a --- /dev/null +++ b/src/INV.H @@ -0,0 +1,96 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/INV.H 3 2/14/97 11:23a Dbrevik $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern BOOL invflag; +extern BOOL drawsbarflag; + + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +void InitInv(); + +void DrawInv(); +void DrawSpdBar(); + +void FreeInvGFX(); + +void CheckInvScrn(); +void CheckSpdBar(); + +void InvGetItem(int, int); +void AutoGetItem(int, int); +int FindGetItem(int, WORD, int); +void SyncGetItem(int, int, int, WORD, int); + +int InvPutItem(int, int, int); +int SyncPutItem(int, + int, + int, + int, + WORD, + int, + BOOL, + int, + int, + int, + int, + int, + DWORD, + int, + int, + int, + int, + int, + int); +BOOL TryInvPut(); + +char CheckInvHLight(); +void RemoveInvItem(int, int); + +void CheckInvPaste(int, int, int); +// drb.patch1.start.02/10/97 +//void SyncInvPaste(int pnum, BYTE bLoc, int idx, WORD icreateinfo, int iseed); +void SyncInvPaste(int pnum, BYTE bLoc, int idx, WORD icreateinfo, int iseed, BOOL Id); +// drb.patch1.end.02/10/97 +void CheckInvCut(int, int, int); +void SyncInvCut(int pnum, BYTE bLoc); + +BOOL CheckUsable(int, int); +BOOL UseInvItem(int, int); + +void RemoveScroll(int); +BOOL UseScroll(); + +void UseStaffCharge(int); +BOOL UseStaff(); +BOOL UseStaffSBook(int); + +BOOL AutoPlace(int, int, int, int, BOOL); +BOOL SpecialAutoPlace(int, int, int, int, BOOL); +void DoTelekinesis(); + +long CalculateGold(int pnum); +void RemoveSpdBarItem(int pnum, int iv); + +BOOL DropItemBeforeTrig(); +int GetHighRingValue(int /* myPlr */); +int GetHighBowValue(int /* myPlr */); +int GetHighStaffValue(int /* myPlr */); +int GetHighSwordValue(int /* myPlr */); +int GetHighHelmValue(int /* myPlr */); +int GetHighArmorValue(int /* myPlr */); +int GetHighMaceValue(int /* myPlr */); +int GetHighAmuletValue(int /* myPlr */); +int GetHighAxeValue(int /* myPlr */); +int GetHighShieldValue(int /* myPlr */); diff --git a/src/ITEMDAT.CPP b/src/ITEMDAT.CPP new file mode 100644 index 0000000..1106ecf --- /dev/null +++ b/src/ITEMDAT.CPP @@ -0,0 +1,2255 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Items file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/ITEMDAT.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "items.h" +#include "itemdat.h" +#include "spells.h" + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +// There is an enumeration which should match the order of the items in +// this list in items.h + +ItemDataStruct AllItemsList[] = { + // These first few must remain in this order + // Must be first + { IRND_NORMAL, IC_GOLD, IL_INV, ITEM_GOLD, IT_GOLD, ITEMID_NONE, "Gold", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, TRUE, 0, 0 }, + // Initial items + // Warrior init weapon + { IRND_NO, IC_WEAP, IL_HAND, ITEM_SHORTSRD, IT_SWORD, ITEMID_NONE, "Short Sword", NULL, + 2, 20, // Min level, durability + 2, 6, 0, 0, // Min damage, max damage, min ac, max ac + 18, 0, 0, // Min Str, Min Mag, Min Dex + 0, IMID_NONE, 0, FALSE, 50, 50 }, // Attr Flags, Misc Id, Spell, usable item, item value + // Warrior init shield + { IRND_NO, IC_ARMOR, IL_HAND, ITEM_BUCKLER, IT_SHIELD, ITEMID_NONE, "Buckler", NULL, + 2, 10, // Min level, durability + 0, 0, 3, 3, // Min damage, max damage, min ac, max ac + 0, 0, 0, // Min Str, Min Mag, Min Dex + 0, IMID_NONE, 0, FALSE, 50, 50 }, // Attr Flags, Misc Id, Spell, usable item, item value + // Warrior init club + { IRND_NO, IC_WEAP, IL_HAND, ITEM_CLUB, IT_MACE, ITEMID_CLUB, "Club", NULL, + 1, 20, + 1, 6, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 20, 20 }, + // Rogue init weapon + { IRND_NO, IC_WEAP, IL_2HAND, ITEM_SHORTBOW, IT_BOW, ITEMID_NONE, "Short Bow", NULL, + 1, 30, // Min level, durability + 1, 4, 0, 0, // Min damage, max damage, min ac, max ac + 0, 0, 0, // Min Str, Min Mag, Min Dex + 0, IMID_NONE, 0, FALSE, 100, 100 }, // Attr Flags, Misc Id, Spell, usable item, item value + // Sorceror init weapon + { IRND_NO, IC_WEAP, IL_2HAND, ITEM_SHRTSTAFF, IT_STAFF, ITEMID_NONE, "Short Staff of Mana", NULL, + 1, 25, // Min level, durability + 2, 4, 0, 0, // Min damage, max damage, min ac, max ac + 0, 20, 0, // Min Str, Min Mag, Min Dex + 0, IMID_STAFF, SPL_MANA, FALSE, 520, 520 }, // Attr Flags, Misc Id, Spell, usable item, item value + + // Start of Quest items + // The Butcher's Cleaver of DEATH! + { IRND_NO, IC_WEAP, IL_2HAND, ITEM_CLEAVER, IT_AXE, ITEMID_CLEAVER, "Cleaver", NULL, + 10, 10, + 4, 24, 0, 0, + 0, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 2000, 2000 }, + // Helm of life stealing from The Skeleton King + { IRND_NO, IC_ARMOR, IL_HEAD, ITEM_SKCROWN, IT_HELM, ITEMID_SKCROWN, "The Undead Crown", NULL, + 0, 50, + 0, 0, 15, 15, + 0, 0, 0, + IAF_SKING, IMID_UNIQUE, 0, FALSE, 10000, 10000 }, + // Empyrean band from meteor (infravision ring) + { IRND_NO, IC_ITEM, IL_RING, ITEM_EMPYBAND, IT_RING, ITEMID_IRING, "Empyrean Band", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 8000, 8000 }, + // Rock from rock quest + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_ROCK, IT_MISC, ITEMID_NONE, "Magic Rock", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + // Optic Amulet from the Halls of the Blind quest + { IRND_NO, IC_ITEM, IL_NECK, ITEM_AMULET, IT_AMULET, ITEMID_OPTAMULET, "Optic Amulet", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 5000, 5000 }, + // Ring of Truth for Poison Water Quest + { IRND_NO, IC_ITEM, IL_RING, ITEM_BLUERING, IT_RING, ITEMID_TRING, "Ring of Truth", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 1000, 1000 }, + // Banner from banner quest + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_INNSIGN, IT_MISC, ITEMID_NONE, "Tavern Sign", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + // Harlequin Crest from banner quest + { IRND_NO, IC_ARMOR, IL_HEAD, ITEM_SKLCAP2, IT_HELM, ITEMID_HALCREST, "Harlequin Crest", NULL, + 0, 15, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 15, 20 }, + // Veil of Steel for the Veil of Steel quest + { IRND_NO, IC_ARMOR, IL_HEAD, ITEM_GRTHELM, IT_HELM, ITEMID_STEELVEIL, "Veil of Steel", NULL, + 0, 60, + 0, 0, 18, 18, + 0, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 0, 0 }, + // Golden Elixor for the Veil of Steel quest + { IRND_NO, IC_ITEM, IL_INV, ITEM_GOLDENELIX, IT_MISC, ITEMID_ELIXIR, "Golden Elixir", NULL, + 15, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + // Anvil for anvil of fury quest + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_ANVIL, IT_MISC, ITEMID_NONE, "Anvil of Fury", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + // Black Mushroom for the quest by the same the name + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_MUSHROOM, IT_MISC, ITEMID_NONE, "Black Mushroom", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + // The brain for the Black Mushroom quest + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_BRAIN, IT_MISC, ITEMID_NONE, "Brain", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + // Fungal Tome + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_BOOK4, IT_MISC, ITEMID_NONE, "Fungal Tome", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + // Elixir for the Black Mushroom quest + { IRND_NO, IC_ITEM, IL_INV, ITEM_SPECTRAL, IT_MISC, ITEMID_ELIXIR, "Spectral Elixir", NULL, + 15, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_SPECTRAL, 0, FALSE, 0, 0 }, + // Stones for the Stones of Blood quest + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_BLOODGEM, IT_MISC, ITEMID_NONE, "Blood Stone", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + + // Map for Demon Crypt quest (was Map of Doom quest) + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_MAP, IT_MISC, ITEMID_MAP, "Cathedral Map", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_MAPOFDOOM, 0, TRUE, 0, 0 }, + + // The infamous ear + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_EAR1, IT_MISC, ITEMID_NONE, "Heart", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_EAR, 0, FALSE, 0, 0 }, + + // end of quest items + + // Initial/Useful level items + { IRND_NO, IC_ITEM, IL_INV, ITEM_REDBTL, IT_MISC, ITEMID_NONE, "Potion of Healing", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PLHEAL, 0, TRUE, 50, 50 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_BLUEBTL2, IT_MISC, ITEMID_NONE, "Potion of Mana", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PMANA, 0, TRUE, 50, 50 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Identify", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_SCROLL, SPL_IDENTIFY, TRUE, 200, 200 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Town Portal", NULL, + 4, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_SCROLL, SPL_TOWN, TRUE, 200, 200 }, + +/*-----------------------------------------------------------------------*/ + + // The next few entries are for expansion + { IRND_NO, IC_ARMOR, IL_BODY, ITEM_ARKARMOR, IT_MARMOR, ITEMID_ARMOFVAL, "Arkaine's Valor", NULL, + 0, 40, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 0, 0 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_BREDBTL, IT_MISC, ITEMID_NONE, "Potion of Full Healing", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PHEAL, 0, TRUE, 150, 150 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_BLUEBTL, IT_MISC, ITEMID_NONE, "Potion of Full Mana", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PFMANA, 0, TRUE, 150, 150 }, + { IRND_NO, IC_WEAP, IL_HAND, ITEM_BROADSRD, IT_SWORD, ITEMID_GRISWOLD, "Griswold's Edge", NULL, + 8, 50, + 4, 12, 0, 0, + 40, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 750, 750 }, + { IRND_NO, IC_ARMOR, IL_BODY, ITEM_ARMRCOW, IT_HARMOR, ITEMID_ARMRCOW, "Bovine Plate", NULL, + 0, 40, + 0, 0, 0, 0, + 50, 0, 0, + 0, IMID_UNIQUE, 0, FALSE, 0, 0 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_BISHOPSTF, IT_MISC, ITEMID_LAZSTAFF, "Staff of Lazarus", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Resurrect", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_TSCROLL, SPL_RESURRECT, TRUE, 250, 250 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_BLKBTL, IT_MISC, ITEMID_NONE, "Blacksmith Oil", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_OILBLKSM, 0, TRUE, 100, 100 }, + { IRND_NO, IC_WEAP, IL_2HAND, ITEM_SHRTSTAFF, IT_STAFF, ITEMID_NONE, "Short Staff", NULL, // Monk inital staff + 1, 25, // Min level, durablity + 2, 4, 0, 0, // Min damage, max damage, min ac, max ac + 0, 0, 0, // Min Str, Min Mag, Min Dex + 0, IMID_NONE, 0, FALSE, 20, 20 }, // Attr Flags, Misc Id, Spell, usable item, item value + { IRND_NO, IC_WEAP, IL_HAND, ITEM_SHORTSRD, IT_SWORD, ITEMID_NONE, "Sword", NULL, // Bard sword + 2, 8, // Min level, durability + 1, 5, 0, 0, // Min damage, max damage, min ac, max ac + 15, 0, 20, // Min Str, Min Mag, Min Dex + 0, IMID_NONE, 0, FALSE, 20, 20 }, // Attr Flags, Misc Id, Spell, usable item, item value + { IRND_NO, IC_WEAP, IL_HAND, ITEM_DAGGER2, IT_SWORD, ITEMID_NONE, "Dagger", NULL, // Bard Dagger + 1, 16, // Min level, durability + 1, 4, 0, 0, // Min damage, max damage, min ac, max ac + 0, 0, 0, // Min Str, Min Mag, Min Dex + 0, IMID_NONE, 0, FALSE, 20, 20 }, // Attr Flags, Misc Id, Spell, usable item, item value + + // Bomb to open up Festering Nest + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_RUNEBOMB, IT_MISC, ITEMID_NONE, "Rune Bomb", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_THEODORE, IT_MISC, ITEMID_NONE, "Theodore", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + + // the Auric Amulet + { IRND_NO, IC_ITEM, IL_NECK, ITEM_AMULGOLD, IT_MISC, ITEMID_NONE, "Auric Amulet", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_AURIC, 0, FALSE, 100, 100 }, + + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_TORNPAPER1, IT_MISC, ITEMID_NONE, "Torn Note 1", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_TORNPAPER2, IT_MISC, ITEMID_NONE, "Torn Note 2", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_TORNPAPER3, IT_MISC, ITEMID_NONE, "Torn Note 3", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_WHOLEPAPER, IT_MISC, ITEMID_NONE, "Reconstructed Note", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_FULLNOTE, 0, TRUE, 0, 0 }, + + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_SUITBRWN, IT_MISC, ITEMID_NONE, "Brown Suit", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + + { IRND_NO, IC_SPECIAL, IL_INV, ITEM_SUITGREY, IT_MISC, ITEMID_NONE, "Grey Suit", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, + +/*-----------------------------------------------------------------------*/ + + // From here down just list of avail items + // Helmets and caps + { IRND_NORMAL, IC_ARMOR, IL_HEAD, ITEM_LCAP, IT_HELM, ITEMID_NONE, "Cap", "Cap", + 1, 15, + 0, 0, 1, 3, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 15, 20 }, + { IRND_NORMAL, IC_ARMOR, IL_HEAD, ITEM_SKLCAP, IT_HELM, ITEMID_SKULLCAP, "Skull Cap", "Cap", + 4, 20, + 0, 0, 2, 4, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 25, 30 }, + { IRND_NORMAL, IC_ARMOR, IL_HEAD, ITEM_FHELM, IT_HELM, ITEMID_HELM, "Helm", "Helm", + 8, 30, + 0, 0, 4, 6, + 25, 0, 0, + 0, IMID_NONE, 0, FALSE, 40, 70 }, + { IRND_NORMAL, IC_ARMOR, IL_HEAD, ITEM_HELM, IT_HELM, ITEMID_NONE, "Full Helm", "Helm", + 12, 35, + 0, 0, 6, 8, + 35, 0, 0, + 0, IMID_NONE, 0, FALSE, 90, 130 }, + { IRND_NORMAL, IC_ARMOR, IL_HEAD, ITEM_CROWN2, IT_HELM, ITEMID_CROWN, "Crown", "Crown", + 16, 40, + 0, 0, 8, 12, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 200, 300 }, + { IRND_NORMAL, IC_ARMOR, IL_HEAD, ITEM_FHELM3, IT_HELM, ITEMID_GREATHELM, "Great Helm", "Helm", + 20, 60, + 0, 0, 10, 15, + 50, 0, 0, + 0, IMID_NONE, 0, FALSE, 400, 500 }, + + // Body armor + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_CAPE, IT_ARMOR, ITEMID_CAPE, "Cape", "Cape", + 1, 12, + 0, 0, 1, 5, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 10, 50 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_RAGS, IT_ARMOR, ITEMID_RAGS, "Rags", "Rags", + 1, 6, + 0, 0, 2, 6, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 5, 25 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_CLOAK, IT_ARMOR, ITEMID_CLOAK, "Cloak", "Cloak", + 2, 18, + 0, 0, 3, 7, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 40, 70 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_ROBE, IT_ARMOR, ITEMID_ROBE, "Robe", "Robe", + 3, 24, + 0, 0, 4, 7, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 75, 125 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_QARMOR, IT_ARMOR, ITEMID_NONE, "Quilted Armor", "Armor", + 4, 30, + 0, 0, 7, 10, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 200, 300 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_LARMOR, IT_ARMOR, ITEMID_LEATHER, "Leather Armor", "Armor", + 6, 35, + 0, 0, 10, 13, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 300, 400 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_HLARMOR, IT_ARMOR, ITEMID_NONE, "Hard Leather Armor", "Armor", + 7, 40, + 0, 0, 11, 14, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 450, 550 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_STDARMOR, IT_ARMOR, ITEMID_STDLEATHER, "Studded Leather Armor", "Armor", + 9, 45, + 0, 0, 15, 17, + 20, 0, 0, + 0, IMID_NONE, 0, FALSE, 700, 800 }, + +#if !IS_VERSION(SHAREWARE) +// shareware version doesn't support medium and heavy armor classes + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_RINGMAIL, IT_MARMOR, ITEMID_NONE, "Ring Mail", "Mail", + 11, 50, + 0, 0, 17, 20, + 25, 0, 0, + 0, IMID_NONE, 0, FALSE, 900, 1100 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_CHARMOR, IT_MARMOR, ITEMID_CHAINMAIL, "Chain Mail", "Mail", + 13, 55, + 0, 0, 18, 22, + 30, 0, 0, + 0, IMID_NONE, 0, FALSE, 1250, 1750 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_SCLARMOR, IT_MARMOR, ITEMID_NONE, "Scale Mail", "Mail", + 15, 60, + 0, 0, 23, 28, + 35, 0, 0, + 0, IMID_NONE, 0, FALSE, 2300, 2800 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_BPLATE, IT_HARMOR, ITEMID_BREASTPLATE, "Breast Plate", "Plate", + 16, 80, + 0, 0, 20, 24, + 40, 0, 0, + 0, IMID_NONE, 0, FALSE, 2800, 3200 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_SPLTARMOR, IT_MARMOR, ITEMID_NONE, "Splint Mail", "Mail", + 17, 65, + 0, 0, 30, 35, + 40, 0, 0, + 0, IMID_NONE, 0, FALSE, 3250, 3750 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_PARMOR, IT_HARMOR, ITEMID_PLATEMAIL, "Plate Mail", "Plate", + 19, 75, + 0, 0, 42, 50, + 60, 0, 0, + 0, IMID_NONE, 0, FALSE, 4600, 5400 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_PARMOR, IT_HARMOR, ITEMID_NONE, "Field Plate", "Plate", + 21, 80, + 0, 0, 40, 45, + 65, 0, 0, + 0, IMID_NONE, 0, FALSE, 5800, 6200 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_PARMOR3, IT_HARMOR, ITEMID_NONE, "Gothic Plate", "Plate", + 23, 100, + 0, 0, 50, 60, + 80, 0, 0, + 0, IMID_NONE, 0, FALSE, 8000, 10000 }, + { IRND_NORMAL, IC_ARMOR, IL_BODY, ITEM_PARMOR2, IT_HARMOR, ITEMID_FULLPLATE, "Full Plate Mail", "Plate", + 25, 90, + 0, 0, 60, 75, + 90, 0, 0, + 0, IMID_NONE, 0, FALSE, 6500, 8000 }, +#endif + + // Shields + { IRND_NORMAL, IC_ARMOR, IL_HAND, ITEM_BUCKLER, IT_SHIELD, ITEMID_BUCKLER, "Buckler", "Shield", + 1, 16, + 0, 0, 1, 5, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 30, 70 }, + { IRND_NORMAL, IC_ARMOR, IL_HAND, ITEM_WSHIELD, IT_SHIELD, ITEMID_SMALLSHLD, "Small Shield", "Shield", + 5, 24, + 0, 0, 3, 8, + 25, 0, 0, + 0, IMID_NONE, 0, FALSE, 90, 130 }, + { IRND_NORMAL, IC_ARMOR, IL_HAND, ITEM_KITESHLD, IT_SHIELD, ITEMID_LARGESHLD, "Large Shield", "Shield", + 9, 32, + 0, 0, 5, 10, + 40, 0, 0, + 0, IMID_NONE, 0, FALSE, 200, 300 }, + { IRND_NORMAL, IC_ARMOR, IL_HAND, ITEM_HVYSHIELD, IT_SHIELD, ITEMID_KITESHLD, "Kite Shield", "Shield", + 14, 40, + 0, 0, 8, 15, + 50, 0, 0, + 0, IMID_NONE, 0, FALSE, 400, 700 }, + { IRND_NORMAL, IC_ARMOR, IL_HAND, ITEM_TSHIELD, IT_SHIELD, ITEMID_TOWERSHLD, "Tower Shield", "Shield", + 20, 50, + 0, 0, 12, 20, + 60, 0, 0, + 0, IMID_NONE, 0, FALSE, 850, 1200 }, + { IRND_NORMAL, IC_ARMOR, IL_HAND, ITEM_LRGSHLD, IT_SHIELD, ITEMID_TOWERSHLD, "Gothic Shield", "Shield", + 23, 60, + 0, 0, 14, 18, + 80, 0, 0, + 0, IMID_NONE, 0, FALSE, 2300, 2700 }, + + // Potions + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_REDBTL, IT_MISC, ITEMID_NONE, "Potion of Healing", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PLHEAL, 0, TRUE, 50, 50 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BREDBTL, IT_MISC, ITEMID_NONE, "Potion of Full Healing", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PHEAL, 0, TRUE, 150, 150 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLUEBTL2, IT_MISC, ITEMID_NONE, "Potion of Mana", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PMANA, 0, TRUE, 50, 50 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLUEBTL, IT_MISC, ITEMID_NONE, "Potion of Full Mana", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PFMANA, 0, TRUE, 150, 150 }, +/* removed 11/23 by dave + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLKBTL, IT_MISC, ITEMID_NONE, "Potion of Experience", NULL, + 20, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_PEXP, 0, TRUE, 0, 0 }, +*/ + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_GOLDBTL, IT_MISC, ITEMID_NONE, "Potion of Rejuvenation", NULL, + 3, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_REJUV, 0, TRUE, 120, 120 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_YELBTL, IT_MISC, ITEMID_NONE, "Potion of Full Rejuvenation", NULL, + 7, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_FREJUV, 0, TRUE, 600, 600 }, + + // Oils removed 11/21 by dave + // Oils back in for hellfire 7/30 by donald + + // Oils + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLKBTL, IT_MISC, ITEMID_NONE, "Blacksmith Oil", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_OILBLKSM, 0, TRUE, 100, 100 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLKBTL, IT_MISC, ITEMID_NONE, "Oil of Accuracy", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_OILACC, 0, TRUE, 500, 500 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLKBTL, IT_MISC, ITEMID_NONE, "Oil of Sharpness", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_OILSHRP, 0, TRUE, 500, 500 }, + + // a random oil + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLKBTL, IT_MISC, ITEMID_NONE, "Oil", NULL, + 10, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_OIL, 0, TRUE, 0, 0 }, + + // Elixirs + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_LTBLUEBTL, IT_MISC, ITEMID_NONE, "Elixir of Strength", NULL, + 15, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_ESTR, 0, TRUE, 5000, 5000 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_ORGBTL, IT_MISC, ITEMID_NONE, "Elixir of Magic", NULL, + 15, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_EMAG, 0, TRUE, 5000, 5000 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BLKBTL2, IT_MISC, ITEMID_NONE, "Elixir of Dexterity", NULL, + 15, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_EDEX, 0, TRUE, 5000, 5000 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_WHTEBTL, IT_MISC, ITEMID_NONE, "Elixir of Vitality", NULL, + 20, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_EVIT, 0, TRUE, 5000, 5000 }, + + // Scrolls +/* { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Firebolt", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_TSCROLL, SPL_FIREBOLT, TRUE, 50, 50 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Charged Bolt", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_TSCROLL, SPL_CBOLT, TRUE, 50, 50 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Holy Bolt", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_TSCROLL, SPL_HBOLT, TRUE, 50, 50 }, +*/ + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Healing", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_SCROLL, SPL_HEAL, TRUE, 50, 50 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Search", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_SCROLL, SPL_SHOWMAGITEMS, TRUE, 50, 50 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Lightning", NULL, + 4, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_TSCROLL, SPL_LIGHTNING, TRUE, 150, 150 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Identify", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_SCROLL, SPL_IDENTIFY, TRUE, 100, 100 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Resurrect", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_TSCROLL, SPL_RESURRECT, TRUE, 250, 250 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Fire Wall", NULL, + 4, 0, + 0, 0, 0, 0, + 0, 17, 0, + 0, IMID_TSCROLL, SPL_WALL, TRUE, 400, 400 }, +/* { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Telekinesis", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 21, 0, + 0, IMID_TSCROLL, SPL_TELEKINESIS, TRUE, 50, 50 }, +*/ + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Inferno", NULL, + 1, 0, + 0, 0, 0, 0, + 0, 19, 0, + 0, IMID_TSCROLL, SPL_FLAME, TRUE, 100, 100 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Town Portal", NULL, + 4, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_SCROLL, SPL_TOWN, TRUE, 200, 200 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Flash", NULL, + 6, 0, + 0, 0, 0, 0, + 0, 21, 0, + 0, IMID_TSCROLL, SPL_FLASH, TRUE, 500, 500 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Infravision", NULL, + 8, 0, + 0, 0, 0, 0, + 0, 23, 0, + 0, IMID_SCROLL, SPL_INFRA, TRUE, 600, 600 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Phasing", NULL, + 6, 0, + 0, 0, 0, 0, + 0, 25, 0, + 0, IMID_SCROLL, SPL_PHASE, TRUE, 200, 200 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Mana Shield", NULL, + 8, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_SCROLL, SPL_MANASHLD, TRUE, 1200, 1200 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Flame Wave", NULL, + 10, 0, + 0, 0, 0, 0, + 0, 29, 0, + 0, IMID_TSCROLL, SPL_WAVE, TRUE, 650, 650 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Fireball", NULL, + 8, 0, + 0, 0, 0, 0, + 0, 31, 0, + 0, IMID_TSCROLL, SPL_FIREBALL, TRUE, 300, 300 }, +#if IS_VERSION(RETAIL) + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Stone Curse", NULL, + 6, 0, + 0, 0, 0, 0, + 0, 33, 0, + 0, IMID_TSCROLL, SPL_STONE, TRUE, 800, 800 }, +#endif + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Chain Lightning", NULL, + 10, 0, + 0, 0, 0, 0, + 0, 35, 0, + 0, IMID_TSCROLL, SPL_CHAIN, TRUE, 750, 750 }, +#if IS_VERSION(RETAIL) + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Guardian", NULL, + 12, 0, + 0, 0, 0, 0, + 0, 47, 0, + 0, IMID_TSCROLL, SPL_GUARDIAN, TRUE, 950, 950 }, + { IRND_NO, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Non Item", NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 }, +#endif + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Nova", NULL, + 14, 0, + 0, 0, 0, 0, + 0, 57, 0, + 0, IMID_SCROLL, SPL_NOVA, TRUE, 1300, 1300 }, +#if IS_VERSION(RETAIL) + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Golem", NULL, + 10, 0, + 0, 0, 0, 0, + 0, 51, 0, + 0, IMID_TSCROLL, SPL_GOLEM, TRUE, 1100, 1100 }, + +// used to be scroll of blood boil - no longer in game - rjs + { IRND_NO, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of None", NULL, + 99, 0, + 0, 0, 0, 0, + 0, 61, 0, + 0, IMID_TSCROLL, SPL_NONE, TRUE, 1000, 1000 }, + +#endif + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Teleport", NULL, + 14, 0, + 0, 0, 0, 0, + 0, 81, 0, + 0, IMID_SCROLL, SPL_TELE, TRUE, 3000, 3000 }, +#if IS_VERSION(RETAIL) + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Apocalypse", NULL, + 22, 0, + 0, 0, 0, 0, + 0, 117, 0, + 0, IMID_SCROLL, SPL_APOCA, TRUE, 2000, 2000 }, +#endif +/* { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Bone Spirit", NULL, + 14, 0, + 0, 0, 0, 0, + 0, 35, 0, + 0, IMID_TSCROLL, SPL_, TRUE, 2000, 2000 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_SCROLL, IT_MISC, ITEMID_NONE, "Scroll of Blood Star", NULL, + 20, 0, + 0, 0, 0, 0, + 0, 35, 0, + 0, IMID_TSCROLL, SPL_, TRUE, 2000, 2000 }, +*/ + + // Books + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BOOK, IT_MISC, ITEMID_NONE, "Book of ", NULL, + 2, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_BOOK, 0, TRUE, 0, 0 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BOOK, IT_MISC, ITEMID_NONE, "Book of ", NULL, + 8, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_BOOK, 0, TRUE, 0, 0 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BOOK, IT_MISC, ITEMID_NONE, "Book of ", NULL, + 14, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_BOOK, 0, TRUE, 0, 0 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_BOOK, IT_MISC, ITEMID_NONE, "Book of ", NULL, + 20, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_BOOK, 0, TRUE, 0, 0 }, + // Bladed weapons + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_DAGGER2, IT_SWORD, ITEMID_DAGGER, "Dagger", "Dagger", + 1, 16, + 1, 4, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 60, 60 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_SHORTSRD, IT_SWORD, ITEMID_NONE, "Short Sword", "Sword", + 1, 24, + 2, 6, 0, 0, + 18, 0, 0, + 0, IMID_NONE, 0, FALSE, 120, 120 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_SCIMITAR, IT_SWORD, ITEMID_FALCHION, "Falchion", "Sword", + 2, 20, + 4, 8, 0, 0, + 30, 0, 0, + 0, IMID_NONE, 0, FALSE, 250, 250 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_SCIMITAR2, IT_SWORD, ITEMID_SCIMITAR, "Scimitar", "Sword", + 4, 28, + 3, 7, 0, 0, + 23, 0, 23, + 0, IMID_NONE, 0, FALSE, 200, 200 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_CLAYMORE, IT_SWORD, ITEMID_CLAYMORE, "Claymore", "Sword", + 5, 36, + 1, 12, 0, 0, + 35, 0, 0, + 0, IMID_NONE, 0, FALSE, 450, 450 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_BLADE, IT_SWORD, ITEMID_NONE, "Blade", "Blade", + 4, 30, + 3, 8, 0, 0, + 25, 0, 30, + 0, IMID_NONE, 0, FALSE, 280, 280 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_SABRE, IT_SWORD, ITEMID_SABRE, "Sabre", "Sabre", + 1, 45, + 1, 8, 0, 0, + 17, 0, 0, + 0, IMID_NONE, 0, FALSE, 170, 170 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_LONGSRD, IT_SWORD, ITEMID_LONGSWORD, "Long Sword", "Sword", + 6, 40, + 2, 10, 0, 0, + 30, 0, 30, + 0, IMID_NONE, 0, FALSE, 350, 350 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_BROADSRD, IT_SWORD, ITEMID_BROADSWORD, "Broad Sword", "Sword", + 8, 50, + 4, 12, 0, 0, + 40, 0, 0, + 0, IMID_NONE, 0, FALSE, 750, 750 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_BASTSRD, IT_SWORD, ITEMID_BASTSWORD, "Bastard Sword", "Sword", + 10, 60, + 6, 15, 0, 0, + 50, 0, 0, + 0, IMID_NONE, 0, FALSE, 1000, 1000 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_2HSWORD, IT_SWORD, ITEMID_2HANDSWORD, "Two-Handed Sword", "Sword", + 14, 75, + 8, 16, 0, 0, + 65, 0, 0, + 0, IMID_NONE, 0, FALSE, 1800, 1800 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_GRTSWORD, IT_SWORD, ITEMID_GREATSWORD, "Great Sword", "Sword", + 17, 100, + 10, 20, 0, 0, + 75, 0, 0, + 0, IMID_NONE, 0, FALSE, 3000, 3000 }, + + // Axes + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_SMALLAXE, IT_AXE, ITEMID_SMALLAXE, "Small Axe", "Axe", + 2, 24, + 2, 10, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 150, 150 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_HANDAXE, IT_AXE, ITEMID_NONE, "Axe", "Axe", + 4, 32, + 4, 12, 0, 0, + 22, 0, 0, + 0, IMID_NONE, 0, FALSE, 450, 450 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_LRGAXE, IT_AXE, ITEMID_LARGEAXE, "Large Axe", "Axe", + 6, 40, + 6, 16, 0, 0, + 30, 0, 0, + 0, IMID_NONE, 0, FALSE, 750, 750 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_BROADAXE, IT_AXE, ITEMID_BROADAXE, "Broad Axe", "Axe", + 8, 50, + 8, 20, 0, 0, + 50, 0, 0, + 0, IMID_NONE, 0, FALSE, 1000, 1000 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_BTLAXE, IT_AXE, ITEMID_BATTLEAXE, "Battle Axe", "Axe", + 10, 60, + 10, 25, 0, 0, + 65, 0, 0, + 0, IMID_NONE, 0, FALSE, 1500, 1500 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_WICKAXE, IT_AXE, ITEMID_GREATAXE, "Great Axe", "Axe", + 12, 75, + 12, 30, 0, 0, + 80, 0, 0, + 0, IMID_NONE, 0, FALSE, 2500, 2500 }, + + // Blunt weapons + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_MACE, IT_MACE, ITEMID_MACE, "Mace", "Mace", + 2, 32, + 1, 8, 0, 0, + 16, 0, 0, + 0, IMID_NONE, 0, FALSE, 200, 200 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_MORNSTAR, IT_MACE, ITEMID_MORNSTAR, "Morning Star", "Mace", + 3, 40, + 1, 10, 0, 0, + 26, 0, 0, + 0, IMID_NONE, 0, FALSE, 300, 300 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_SMLWARHAM, IT_MACE, ITEMID_WARHAMMER, "War Hammer", "Hammer", + 5, 50, + 5, 9, 0, 0, + 40, 0, 0, + 0, IMID_NONE, 0, FALSE, 600, 600 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_CLUB2, IT_MACE, ITEMID_CLUB, "Spiked Club", "Club", + 4, 20, + 3, 6, 0, 0, + 18, 0, 0, + 0, IMID_NONE, 0, FALSE, 225, 225 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_CLUB, IT_MACE, ITEMID_CLUB, "Club", "Club", + 1, 20, + 1, 6, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 20, 20 }, + { IRND_NORMAL, IC_WEAP, IL_HAND, ITEM_FLAIL, IT_MACE, ITEMID_FLAIL, "Flail", "Flail", + 7, 36, + 2, 12, 0, 0, + 30, 0, 0, + 0, IMID_NONE, 0, FALSE, 500, 500 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_MAUL, IT_MACE, ITEMID_MAUL, "Maul", "Maul", + 10, 50, + 6, 20, 0, 0, + 55, 0, 0, + 0, IMID_NONE, 0, FALSE, 900, 900 }, + + // Bows + { IRND_DOUBLE, IC_WEAP, IL_2HAND, ITEM_SHORTBOW, IT_BOW, ITEMID_SHORTBOW, "Short Bow", "Bow", + 1, 30, + 1, 4, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 100, 100 }, + { IRND_DOUBLE, IC_WEAP, IL_2HAND, ITEM_LONGBOW, IT_BOW, ITEMID_BOW, "Hunter's Bow", "Bow", + 3, 40, + 2, 5, 0, 0, + 20, 0, 35, + 0, IMID_NONE, 0, FALSE, 350, 350 }, + { IRND_DOUBLE, IC_WEAP, IL_2HAND, ITEM_LONGBOW, IT_BOW, ITEMID_LONGBOW, "Long Bow", "Bow", + 5, 35, + 1, 6, 0, 0, + 25, 0, 30, + 0, IMID_NONE, 0, FALSE, 250, 250 }, + { IRND_DOUBLE, IC_WEAP, IL_2HAND, ITEM_HNTRBOW, IT_BOW, ITEMID_COMPBOW, "Composite Bow", "Bow", + 7, 45, + 3, 6, 0, 0, + 25, 0, 40, + 0, IMID_NONE, 0, FALSE, 600, 600 }, + { IRND_DOUBLE, IC_WEAP, IL_2HAND, ITEM_SBATLBOW, IT_BOW, ITEMID_NONE, "Short Battle Bow", "Bow", + 9, 45, + 3, 7, 0, 0, + 30, 0, 50, + 0, IMID_NONE, 0, FALSE, 750, 750 }, + { IRND_DOUBLE, IC_WEAP, IL_2HAND, ITEM_STLLONGBOW, IT_BOW, ITEMID_LBATTLEBOW, "Long Battle Bow", "Bow", + 11, 50, + 1, 10, 0, 0, + 30, 0, 60, + 0, IMID_NONE, 0, FALSE, 1000, 1000 }, + { IRND_DOUBLE, IC_WEAP, IL_2HAND, ITEM_SWARBOW, IT_BOW, ITEMID_NONE, "Short War Bow", "Bow", + 15, 55, + 4, 8, 0, 0, + 35, 0, 70, + 0, IMID_NONE, 0, FALSE, 1500, 1500 }, + { IRND_DOUBLE, IC_WEAP, IL_2HAND, ITEM_STLLONGBOW, IT_BOW, ITEMID_LWARBOW, "Long War Bow", "Bow", + 19, 60, + 1, 14, 0, 0, + 45, 0, 80, + 0, IMID_NONE, 0, FALSE, 2000, 2000 }, + // Staffs + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_SHRTSTAFF, IT_STAFF, ITEMID_SHORTSTAFF, "Short Staff", "Staff", + 1, 25, + 2, 4, 0, 0, + 0, 0, 0, + 0, IMID_STAFF, 0, FALSE, 30, 30 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_IRONSTAFF, IT_STAFF, ITEMID_LONGSTAFF, "Long Staff", "Staff", + 4, 35, + 4, 8, 0, 0, + 0, 0, 0, + 0, IMID_STAFF, 0, FALSE, 100, 100 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_COMPSTF, IT_STAFF, ITEMID_COMPSTAFF, "Composite Staff", "Staff", + 6, 45, + 5, 10, 0, 0, + 0, 0, 0, + 0, IMID_STAFF, 0, FALSE, 500, 500 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_SHRTSTAFF, IT_STAFF, ITEMID_QTRSTAFF, "Quarter Staff", "Staff", + 9, 55, + 6, 12, 0, 0, + 20, 0, 0, + 0, IMID_STAFF, 0, FALSE, 1000, 1000 }, + { IRND_NORMAL, IC_WEAP, IL_2HAND, ITEM_STLSTAFF, IT_STAFF, ITEMID_WARSTAFF, "War Staff", "Staff", + 12, 75, + 8, 16, 0, 0, + 30, 0, 0, + 0, IMID_STAFF, 0, FALSE, 1500, 1500 }, + + // Rings + { IRND_NORMAL, IC_ITEM, IL_RING, ITEM_SLVRRING, IT_RING, ITEMID_RING, "Ring", "Ring", + 5, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_RING, 0, FALSE, 1000, 1000 }, + { IRND_NORMAL, IC_ITEM, IL_RING, ITEM_SLVRRING, IT_RING, ITEMID_RING, "Ring", "Ring", + 10, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_RING, 0, FALSE, 1000, 1000 }, + { IRND_NORMAL, IC_ITEM, IL_RING, ITEM_SLVRRING, IT_RING, ITEMID_RING, "Ring", "Ring", + 15, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_RING, 0, FALSE, 1000, 1000 }, + + // Amulet + { IRND_NORMAL, IC_ITEM, IL_NECK, ITEM_AMULET1, IT_AMULET, ITEMID_AMULET, "Amulet", "Amulet", + 8, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_AMULET, 0, FALSE, 1200, 1200 }, + { IRND_NORMAL, IC_ITEM, IL_NECK, ITEM_AMULET1, IT_AMULET, ITEMID_AMULET, "Amulet", "Amulet", + 16, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_AMULET, 0, FALSE, 1200, 1200 }, + + + // Runes + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_FIRERUNE1, IT_MISC, ITEMID_NONE, "Rune of Fire", "Rune", + 1, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_RUNEFIRE, 0, TRUE, 100, 100 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_LIGHTRUNE1, IT_MISC, ITEMID_NONE, "Rune of Lightning", "Rune", + 3, 0, + 0, 0, 0, 0, + 0, 13, 0, + 0, IMID_RUNELIGHT, 0, TRUE, 200, 200 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_FIRERUNE2, IT_MISC, ITEMID_NONE, "Greater Rune of Fire", "Rune", + 7, 0, + 0, 0, 0, 0, + 0, 42, 0, + 0, IMID_RUNEIMMOLATE, 0, TRUE, 400, 400 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_LIGHTRUNE2, IT_MISC, ITEMID_NONE, "Greater Rune of Lightning", "Rune", + 7, 0, + 0, 0, 0, 0, + 0, 42, 0, + 0, IMID_RUNENOVA, 0, TRUE, 500, 500 }, + { IRND_NORMAL, IC_ITEM, IL_INV, ITEM_STONERUNE, IT_MISC, ITEMID_NONE, "Rune of Stone", "Rune", + 7, 0, + 0, 0, 0, 0, + 0, 25, 0, + 0, IMID_RUNESTONE, 0, TRUE, 300, 300 }, + + + // Min level, durablity + // Min damage, max damage, min ac, max ac + // Min Str, Min Mag, Min Dex + // Attr Flags, Misc Id, Spell, usable item, item value + + // Data stopper + { IRND_NO, 0, -1, 0, 0, ITEMID_NONE, NULL, NULL, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, + 0, IMID_NONE, 0, FALSE, 0, 0 } +}; + +/*-----------------------------------------------------------------------* +** Item Power lists +**-----------------------------------------------------------------------*/ + +// Prefix, Power, min, max, level, armor/shield/weapon/staff/bow/ring, good(10)/evil(01)/either(00), Double, item good (TRUE), min val, max val +const PLStruct PL_Prefix[] = { + { "Tin", PL_NTOHIT, 6, 10, 3, 0x001011, 0x00, TRUE, FALSE, 0, 0, -3 }, + { "Brass", PL_NTOHIT, 1, 5, 1, 0x001011, 0x00, TRUE, FALSE, 0, 0, -2 }, + { "Bronze", PL_TOHIT, 1, 5, 1, 0x001011, 0x00, TRUE, TRUE, 100, 500, 2 }, + { "Iron", PL_TOHIT, 6, 10, 4, 0x001011, 0x00, TRUE, TRUE, 600, 1000, 3 }, + { "Steel", PL_TOHIT, 11, 15, 6, 0x001011, 0x00, TRUE, TRUE, 1100, 1500, 5 }, + { "Silver", PL_TOHIT, 16, 20, 9, 0x001011, 0x10, TRUE, TRUE, 1600, 2000, 7 }, + { "Gold", PL_TOHIT, 21, 30, 12, 0x001011, 0x10, TRUE, TRUE, 2100, 3000, 9 }, + { "Platinum", PL_TOHIT, 31, 40, 16, 0x001010, 0x10, TRUE, TRUE, 3100, 4000, 11 }, + { "Mithril", PL_TOHIT, 41, 60, 20, 0x001010, 0x10, TRUE, TRUE, 4100, 6000, 13 }, + { "Meteoric", PL_TOHIT, 61, 80, 23, 0x001010, 0x00, TRUE, TRUE, 6100, 10000, 15 }, + { "Weird", PL_TOHIT, 81, 100, 35, 0x001010, 0x00, TRUE, TRUE, 10100, 14000, 17 }, + { "Strange", PL_TOHIT, 101, 150, 60, 0x001010, 0x00, TRUE, TRUE, 14100, 20000, 20 }, + + { "Useless", PL_NTODAM, 100, 100, 5, 0x001110, 0x00, TRUE, FALSE, 0, 0, -8 }, + { "Bent", PL_NTODAM, 50, 75, 3, 0x001110, 0x00, TRUE, FALSE, 0, 0, -4 }, + { "Weak", PL_NTODAM, 25, 45, 1, 0x001110, 0x00, TRUE, FALSE, 0, 0, -3 }, + { "Jagged", PL_TODAM, 20, 35, 4, 0x001110, 0x00, TRUE, TRUE, 250, 450, 3 }, + { "Deadly", PL_TODAM, 36, 50, 6, 0x001110, 0x00, TRUE, TRUE, 500, 700, 4 }, + { "Heavy", PL_TODAM, 51, 65, 9, 0x001110, 0x00, TRUE, TRUE, 750, 950, 5 }, + { "Vicious", PL_TODAM, 66, 80, 12, 0x001110, 0x01, TRUE, TRUE, 1000, 1450, 8 }, + { "Brutal", PL_TODAM, 81, 95, 16, 0x001110, 0x00, TRUE, TRUE, 1500, 1950, 10 }, + { "Massive", PL_TODAM, 96, 110, 20, 0x001110, 0x00, TRUE, TRUE, 2000, 2450, 13 }, + { "Savage", PL_TODAM, 111, 125, 23, 0x001010, 0x00, TRUE, TRUE, 2500, 3000, 15 }, + { "Ruthless", PL_TODAM, 126, 150, 35, 0x001010, 0x00, TRUE, TRUE, 10100, 15000, 17 }, + { "Merciless", PL_TODAM, 151, 175, 60, 0x001010, 0x00, TRUE, TRUE, 15000, 20000, 20 }, + + { "Clumsy", PL_NDAHT, 50, 75, 5, 0x001110, 0x00, TRUE, FALSE, 0, 0, -7 }, + { "Dull", PL_NDAHT, 25, 45, 1, 0x001110, 0x00, TRUE, FALSE, 0, 0, -5 }, + { "Sharp", PL_DAHT, 20, 35, 1, 0x001110, 0x00, TRUE, FALSE, 350, 950, 5 }, + { "Fine", PL_DAHT, 36, 50, 6, 0x001110, 0x00, TRUE, TRUE, 1100, 1700, 7 }, + { "Warrior's", PL_DAHT, 51, 65, 10, 0x001110, 0x00, TRUE, TRUE, 1850, 2450, 13 }, + { "Soldier's", PL_DAHT, 66, 80, 15, 0x001100, 0x00, TRUE, TRUE, 2600, 3950, 17 }, + { "Lord's", PL_DAHT, 81, 95, 19, 0x001100, 0x00, TRUE, TRUE, 4100, 5950, 21 }, + { "Knight's", PL_DAHT, 96, 110, 23, 0x001100, 0x00, TRUE, TRUE, 6100, 8450, 26 }, + { "Master's", PL_DAHT, 111, 125, 28, 0x001100, 0x00, TRUE, TRUE, 8600, 13000, 30 }, + { "Champion's", PL_DAHT, 126, 150, 40, 0x001100, 0x00, TRUE, TRUE, 15200, 24000, 33 }, + { "King's", PL_DAHT, 151, 175, 28, 0x001100, 0x00, TRUE, TRUE, 24100, 35000, 38 }, + + { "Vulnerable", PL_NAC, 51, 100, 3, 0x110000, 0x00, TRUE, FALSE, 0, 0, -3 }, + { "Rusted", PL_NAC, 25, 50, 1, 0x110000, 0x00, TRUE, FALSE, 0, 0, -2 }, + { "Fine", PL_AC, 20, 30, 1, 0x110000, 0x00, TRUE, TRUE, 20, 100, 2 }, + { "Strong", PL_AC, 31, 40, 3, 0x110000, 0x00, TRUE, TRUE, 120, 200, 3 }, + { "Grand", PL_AC, 41, 55, 6, 0x110000, 0x00, TRUE, TRUE, 220, 300, 5 }, + { "Valiant", PL_AC, 56, 70, 10, 0x110000, 0x00, TRUE, TRUE, 320, 400, 7 }, + { "Glorious", PL_AC, 71, 90, 14, 0x110000, 0x10, TRUE, TRUE, 420, 600, 9 }, + { "Blessed", PL_AC, 91, 110, 19, 0x110000, 0x10, TRUE, TRUE, 620, 800, 11 }, + { "Saintly", PL_AC, 111, 130, 24, 0x110000, 0x10, TRUE, TRUE, 820, 1200, 13 }, + { "Awesome", PL_AC, 131, 150, 28, 0x110000, 0x10, TRUE, TRUE, 1220, 2000, 15 }, + { "Holy", PL_AC, 151, 170, 35, 0x110000, 0x10, TRUE, TRUE, 5200, 6000, 17 }, + { "Godly", PL_AC, 171, 200, 60, 0x110000, 0x10, TRUE, TRUE, 6200, 7000, 20 }, + + { "Red", PL_RFIRE, 10, 20, 4, 0x111111, 0x00, FALSE, TRUE, 500, 1500, 2 }, + { "Crimson", PL_RFIRE, 21, 30, 10, 0x111111, 0x00, FALSE, TRUE, 2100, 3000, 2 }, + { "Crimson", PL_RFIRE, 31, 40, 16, 0x111111, 0x00, FALSE, TRUE, 3100, 4000, 2 }, + { "Garnet", PL_RFIRE, 41, 50, 20, 0x111111, 0x00, FALSE, TRUE, 8200, 12000, 3 }, + { "Ruby", PL_RFIRE, 51, 60, 26, 0x111111, 0x00, FALSE, TRUE, 17100, 20000, 5 }, + { "Blue", PL_RLGHT, 10, 20, 4, 0x111111, 0x00, FALSE, TRUE, 500, 1500, 2 }, + { "Azure", PL_RLGHT, 21, 30, 10, 0x111111, 0x00, FALSE, TRUE, 2100, 3000, 2 }, + { "Lapis", PL_RLGHT, 31, 40, 16, 0x111111, 0x00, FALSE, TRUE, 3100, 4000, 2 }, + { "Cobalt", PL_RLGHT, 41, 50, 20, 0x111111, 0x00, FALSE, TRUE, 8200, 12000, 3 }, + { "Sapphire", PL_RLGHT, 51, 60, 26, 0x111111, 0x00, FALSE, TRUE, 17100, 20000, 5 }, + { "White", PL_RMAG, 10, 20, 4, 0x111111, 0x00, FALSE, TRUE, 500, 1500, 2 }, + { "Pearl", PL_RMAG, 21, 30, 10, 0x111111, 0x00, FALSE, TRUE, 2100, 3000, 2 }, + { "Ivory", PL_RMAG, 31, 40, 16, 0x111111, 0x00, FALSE, TRUE, 3100, 4000, 2 }, + { "Crystal", PL_RMAG, 41, 50, 20, 0x111111, 0x00, FALSE, TRUE, 8200, 12000, 3 }, + { "Diamond", PL_RMAG, 51, 60, 26, 0x111111, 0x00, FALSE, TRUE, 17100, 20000, 5 }, + { "Topaz", PL_RALL, 10, 15, 8, 0x111111, 0x00, FALSE, TRUE, 2000, 5000, 3 }, + { "Amber", PL_RALL, 16, 20, 12, 0x111111, 0x00, FALSE, TRUE, 7400, 10000, 3 }, + { "Jade", PL_RALL, 21, 30, 18, 0x111111, 0x00, FALSE, TRUE, 11000, 15000, 3 }, + { "Obsidian", PL_RALL, 31, 40, 24, 0x111111, 0x00, FALSE, TRUE, 24000, 40000, 4 }, + { "Emerald", PL_RALL, 41, 50, 31, 0x011110, 0x00, FALSE, TRUE, 61000, 75000, 7 }, + + { "Hyena's", PL_NMANA, 11, 25, 4, 0x000101, 0x00, FALSE, FALSE, 100, 1000, -2 }, + { "Frog's", PL_NMANA, 1, 10, 1, 0x000101, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "Spider's", PL_MANA, 10, 15, 1, 0x000101, 0x01, FALSE, TRUE, 500, 1000, 2 }, + { "Raven's", PL_MANA, 15, 20, 5, 0x000101, 0x00, FALSE, TRUE, 1100, 2000, 3 }, + { "Snake's", PL_MANA, 21, 30, 9, 0x000101, 0x00, FALSE, TRUE, 2100, 4000, 5 }, + { "Serpent's", PL_MANA, 30, 40, 15, 0x000101, 0x00, FALSE, TRUE, 4100, 6000, 7 }, + { "Drake's", PL_MANA, 41, 50, 21, 0x000101, 0x00, FALSE, TRUE, 6100, 10000, 9 }, + { "Dragon's", PL_MANA, 51, 60, 27, 0x000101, 0x00, FALSE, TRUE, 10100, 15000, 11 }, + { "Wyrm's", PL_MANA, 61, 80, 35, 0x000100, 0x00, FALSE, TRUE, 15100, 19000, 12 }, + { "Hydra's", PL_MANA, 81, 100, 60, 0x000100, 0x00, FALSE, TRUE, 19100, 30000, 13 }, + + { "Angel's", PL_SLVL, 1, 1, 15, 0x000100, 0x10, FALSE, TRUE, 25000, 25000, 2 }, + { "Arch-Angel's", PL_SLVL, 2, 2, 25, 0x000100, 0x10, FALSE, TRUE, 50000, 50000, 3 }, + { "Plentiful", PL_CHRG, 2, 2, 4, 0x000100, 0x00, FALSE, TRUE, 2000, 2000, 2 }, + { "Bountiful", PL_CHRG, 3, 3, 9, 0x000100, 0x00, FALSE, TRUE, 3000, 3000, 3 }, + +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) + { "Flaming", PL_FHIT, 1, 10, 7, 0x001100, 0x00, FALSE, TRUE, 5000, 5000, 2 }, + { "Lightning", PL_LHIT, 2, 20, 18, 0x001100, 0x00, FALSE, TRUE, 10000, 10000, 2 }, +#endif + + { "Jester's", PL_RNDDAM, 1, 1, 7, 0x001000, 0x00, FALSE, TRUE, 1200, 1200, 3 }, + { "Crystalline", PL_FRAGILE, 30, 70, 5, 0x001000, 0x00, FALSE, TRUE, 1000, 3000, 3 }, + { "Doppelganger's", PL_DOPPEL, 81, 95, 11, 0x001100, 0x00, FALSE, TRUE, 2000, 2400, 10}, + + + { "", -1, 0, 0, 0, 0, 0, FALSE, 0, 0 } // Stopper +}; + +// Suffix, Power, min, max, level, armor/shield/weapon/staff/bow/ring, good(10)/evil(01)/either(00), Double +const PLStruct PL_Suffix[] = { + { "quality", PL_DAMADD, 1, 2, 2, 0x001110, 0x00, FALSE, TRUE, 100, 200, 2 }, + { "maiming", PL_DAMADD, 3, 5, 7, 0x001110, 0x00, FALSE, TRUE, 1300, 1500, 3 }, + { "slaying", PL_DAMADD, 6, 8, 15, 0x001000, 0x00, FALSE, TRUE, 2600, 3000, 5 }, + { "gore", PL_DAMADD, 9, 12, 25, 0x001000, 0x00, FALSE, TRUE, 4100, 5000, 8 }, + { "carnage", PL_DAMADD, 13, 16, 35, 0x001000, 0x00, FALSE, TRUE, 5100, 10000, 10 }, + { "slaughter", PL_DAMADD, 17, 20, 60, 0x001000, 0x00, FALSE, TRUE, 10100, 15000, 13 }, + + { "pain", PL_GETHIT, 2, 4, 4, 0x110001, 0x01, FALSE, FALSE, 0, 0, -4 }, + { "tears", PL_GETHIT, 1, 1, 2, 0x110001, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "health", PL_NGETHIT, 1, 1, 2, 0x110001, 0x10, FALSE, TRUE, 200, 200, 2 }, + { "protection", PL_NGETHIT, 2, 2, 6, 0x110000, 0x10, FALSE, TRUE, 400, 800, 4 }, + { "absorption", PL_NGETHIT, 3, 3, 12, 0x110000, 0x10, FALSE, TRUE, 1001, 2500, 10 }, + { "deflection", PL_NGETHIT, 4, 4, 20, 0x100000, 0x10, FALSE, TRUE, 2500, 6500, 15 }, + { "osmosis", PL_NGETHIT, 5, 6, 50, 0x100000, 0x10, FALSE, TRUE, 7500, 10000, 20 }, + + { "frailty", PL_NSTR, 6, 10, 3, 0x111011, 0x01, FALSE, FALSE, 0, 0, -3 }, + { "weakness", PL_NSTR, 1, 5, 1, 0x111111, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "strength", PL_STR, 1, 5, 1, 0x111111, 0x00, FALSE, TRUE, 200, 1000, 2 }, + { "might", PL_STR, 6, 10, 5, 0x111011, 0x00, FALSE, TRUE, 1200, 2000, 3 }, + { "power", PL_STR, 11, 15, 11, 0x111011, 0x00, FALSE, TRUE, 2200, 3000, 4 }, + { "giants", PL_STR, 16, 20, 17, 0x101011, 0x00, FALSE, TRUE, 3200, 5000, 7 }, + { "titans", PL_STR, 21, 30, 23, 0x001001, 0x00, FALSE, TRUE, 5200, 10000, 10 }, + + { "paralysis", PL_NDEX, 6, 10, 3, 0x111011, 0x01, FALSE, FALSE, 0,0, -3 }, + { "atrophy", PL_NDEX, 1, 5, 1, 0x111111, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "dexterity", PL_DEX, 1, 5, 1, 0x111111, 0x00, FALSE, TRUE, 200, 1000, 2 }, + { "skill", PL_DEX, 6, 10, 5, 0x111011, 0x00, FALSE, TRUE, 1200, 2000, 3 }, + { "accuracy", PL_DEX, 11, 15, 11, 0x111011, 0x00, FALSE, TRUE, 2200, 3000, 4 }, + { "precision", PL_DEX, 16, 20, 17, 0x101011, 0x00, FALSE, TRUE, 3200, 5000, 7 }, + { "perfection", PL_DEX, 21, 30, 23, 0x000011, 0x00, FALSE, TRUE, 5200, 10000, 10 }, + + { "the fool", PL_NMAG, 6, 10, 3, 0x111111, 0x01, FALSE, FALSE, 0, 0, -3 }, + { "dyslexia", PL_NMAG, 1, 5, 1, 0x111111, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "magic", PL_MAG, 1, 5, 1, 0x111111, 0x00, FALSE, TRUE, 200, 1000, 2 }, + { "the mind", PL_MAG, 6, 10, 5, 0x111111, 0x00, FALSE, TRUE, 1200, 2000, 3 }, + { "brilliance", PL_MAG, 11, 15, 11, 0x111111, 0x00, FALSE, TRUE, 2200, 3000, 4 }, + { "sorcery", PL_MAG, 16, 20, 17, 0x101111, 0x00, FALSE, TRUE, 3200, 5000, 7 }, + { "wizardry", PL_MAG, 21, 30, 23, 0x000101, 0x00, FALSE, TRUE, 5200, 10000, 10 }, + + { "illness", PL_NVIT, 6, 10, 3, 0x111111, 0x01, FALSE, FALSE, 0, 0, -3 }, + { "disease", PL_NVIT, 1, 5, 1, 0x111111, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "vitality", PL_VIT, 1, 5, 1, 0x111111, 0x10, FALSE, TRUE, 200, 1000, 2 }, + { "zest", PL_VIT, 6, 10, 5, 0x111011, 0x10, FALSE, TRUE, 1200, 2000, 3 }, + { "vim", PL_VIT, 11, 15, 11, 0x111011, 0x10, FALSE, TRUE, 2200, 3000, 4 }, + { "vigor", PL_VIT, 16, 20, 17, 0x101011, 0x10, FALSE, TRUE, 3200, 5000, 7 }, + { "life", PL_VIT, 21, 30, 23, 0x000001, 0x10, FALSE, TRUE, 5200, 10000, 10 }, + + { "trouble", PL_NSTATS, 6, 10, 12, 0x111111, 0x01, FALSE, FALSE, 0, 0, -10 }, + { "the pit", PL_NSTATS, 1, 5, 5, 0x111111, 0x01, FALSE, FALSE, 0, 0, -5 }, + { "the sky", PL_STATS, 1, 3, 5, 0x111111, 0x00, FALSE, TRUE, 800, 4000, 5 }, + { "the moon", PL_STATS, 4, 7, 11, 0x111111, 0x00, FALSE, TRUE, 4800, 8000, 10 }, + { "the stars", PL_STATS, 8, 11, 17, 0x101011, 0x00, FALSE, TRUE, 8800, 12000, 15 }, + { "the heavens", PL_STATS, 12, 15, 25, 0x001011, 0x00, FALSE, TRUE, 12800, 20000, 20 }, + { "the zodiac", PL_STATS, 16, 20, 30, 0x000001, 0x00, FALSE, TRUE, 20800, 40000, 30 }, + + { "the vulture", PL_NHP, 11, 25, 4, 0x110001, 0x01, FALSE, FALSE, 0, 0, -4 }, + { "the jackal", PL_NHP, 1, 10, 1, 0x110001, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "the fox", PL_HP, 10, 15, 1, 0x110001, 0x00, FALSE, TRUE, 100, 1000, 2 }, + { "the jaguar", PL_HP, 16, 20, 5, 0x110001, 0x00, FALSE, TRUE, 1100, 2000, 3 }, + { "the eagle", PL_HP, 21, 30, 9, 0x110001, 0x00, FALSE, TRUE, 2100, 4000, 5 }, + { "the wolf", PL_HP, 30, 40, 15, 0x110001, 0x00, FALSE, TRUE, 4100, 6000, 7 }, + { "the tiger", PL_HP, 41, 50, 21, 0x110001, 0x00, FALSE, TRUE, 6100, 10000, 9 }, + { "the lion", PL_HP, 51, 60, 27, 0x100001, 0x00, FALSE, TRUE, 10100, 15000, 11 }, + { "the mammoth", PL_HP, 61, 80, 35, 0x100000, 0x00, FALSE, TRUE, 15100, 19000, 12 }, + { "the whale", PL_HP, 81, 100, 60, 0x100000, 0x00, FALSE, TRUE, 19100, 30000, 13 }, + + { "fragility", PL_NDUR, 100, 100, 3, 0x111000, 0x01, FALSE, FALSE, 0, 0, -4 }, + { "brittleness", PL_NDUR, 26, 75, 1, 0x111000, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "sturdiness", PL_DUR, 26, 75, 1, 0x111100, 0x00, FALSE, TRUE, 100, 100, 2 }, + { "craftsmanship", PL_DUR, 51, 100, 6, 0x111100, 0x00, FALSE, TRUE, 200, 200, 2 }, + { "structure", PL_DUR, 101, 200, 12, 0x111100, 0x00, FALSE, TRUE, 300, 300, 2 }, + { "the ages", PL_IND, 0, 0, 25, 0x111100, 0x00, FALSE, TRUE, 600, 600, 5 }, + + { "the dark", PL_NLIGHT, 4, 4, 6, 0x101001, 0x01, FALSE, FALSE, 0, 0, -3 }, + { "the night", PL_NLIGHT, 2, 2, 3, 0x101001, 0x01, FALSE, FALSE, 0, 0, -2 }, + { "light", PL_LIGHT, 2, 2, 4, 0x101001, 0x10, FALSE, TRUE, 750, 750, 2 }, + { "radiance", PL_LIGHT, 4, 4, 8, 0x101001, 0x10, FALSE, TRUE, 1500, 1500, 3 }, + + { "flame", PL_FARROW, 1, 3, 1, 0x000010, 0x00, FALSE, TRUE, 2000, 2000, 2 }, + { "fire", PL_FARROW, 1, 6, 11, 0x000010, 0x00, FALSE, TRUE, 4000, 4000, 4 }, + { "burning", PL_FARROW, 1, 16, 35, 0x000010, 0x00, FALSE, TRUE, 6000, 6000, 6 }, +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) + { "shock", PL_LARROW, 1, 6, 13, 0x000010, 0x00, FALSE, TRUE, 6000, 6000, 2 }, + { "lightning", PL_LARROW, 1, 10, 21, 0x000010, 0x00, FALSE, TRUE, 8000, 8000, 4 }, + { "thunder", PL_LARROW, 1, 20, 60, 0x000010, 0x00, FALSE, TRUE, 12000, 12000, 6 }, +#endif + { "many", PL_DUR, 100, 100, 3, 0x000010, 0x00, FALSE, TRUE, 750, 750, 2 }, + { "plenty", PL_DUR, 200, 200, 7, 0x000010, 0x00, FALSE, TRUE, 1500, 1500, 3 }, + +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) + { "thorns", PL_THORN, 1, 3, 1, 0x110000, 0x00, FALSE, TRUE, 500, 500, 2 }, + { "corruption", PL_LMANA, 0, 0, 5, 0x111000, 0x01, FALSE, FALSE, -1000, -1000, 2 }, + + { "thieves", PL_TRAPDAM, 0, 0, 11, 0x110001, 0x00, FALSE, TRUE, 1500, 1500, 2 }, + { "the bear", PL_BEAR, 0, 0, 5, 0x001110, 0x01, FALSE, TRUE, 750, 750, 2 }, + + { "the bat", PL_BAT, 3, 3, 8, 0x001000, 0x00, FALSE, TRUE, 7500, 7500, 3 }, + { "vampires", PL_BAT, 5, 5, 19, 0x001000, 0x00, FALSE, TRUE, 15000, 15000, 3 }, + { "the leech", PL_LEECH, 3, 3, 8, 0x001000, 0x00, FALSE, TRUE, 7500, 7500, 3 }, + { "blood", PL_LEECH, 5, 5, 19, 0x001000, 0x00, FALSE, TRUE, 15000, 15000, 3 }, + + { "piercing", PL_ENAC, 1, 1, 1, 0x001010, 0x00, FALSE, TRUE, 1000, 1000, 3 }, + { "puncturing", PL_ENAC, 2, 2, 9, 0x001010, 0x00, FALSE, TRUE, 2000, 2000, 6 }, + { "bashing", PL_ENAC, 3, 3, 17, 0x001000, 0x00, FALSE, TRUE, 4000, 4000, 12 }, + + { "readiness", PL_ATANIM, 1, 1, 1, 0x001110, 0x00, FALSE, TRUE, 2000, 2000, 2 }, + { "swiftness", PL_ATANIM, 2, 2, 10, 0x001110, 0x00, FALSE, TRUE, 4000, 4000, 4 }, + { "speed", PL_ATANIM, 3, 3, 19, 0x001100, 0x00, FALSE, TRUE, 8000, 8000, 8 }, + { "haste", PL_ATANIM, 4, 4, 27, 0x001100, 0x00, FALSE, TRUE, 16000, 16000, 16 }, + { "balance", PL_HTANIM, 1, 1, 1, 0x100001, 0x00, FALSE, TRUE, 2000, 2000, 2 }, + { "stability", PL_HTANIM, 2, 2, 10, 0x100001, 0x00, FALSE, TRUE, 4000, 4000, 4 }, + { "harmony", PL_HTANIM, 3, 3, 20, 0x100001, 0x00, FALSE, TRUE, 8000, 8000, 8 }, + + { "blocking", PL_BLANIM, 1, 1, 5, 0x010000, 0x00, FALSE, TRUE, 4000, 4000, 4 }, + + { "devastation", PL_DEVAST, 1, 1, 1, 0x001110, 0x00, FALSE, TRUE, 1200, 1200, 3 }, + { "decay", PL_DECAY, 150, 250, 1, 0x001110, 0x00, FALSE, TRUE, 200, 200, 2 }, + { "peril", PL_PERIL, 1, 1, 5, 0x001110, 0x00, FALSE, TRUE, 500, 500, 1 }, + +#endif + + { "", -1, 0, 0, 0, 0, 0, FALSE, FALSE, 0, 0 } // Stopper +}; + +/*-----------------------------------------------------------------------* +** Unique items list +**-----------------------------------------------------------------------*/ + +// Item name, item id, level, number of Powers, value, avail for shareware +// Power, param1, param2 +const UItemStruct UniqueItemList[] = { + + // This must go at the beginning of the list because so the butcher can give it out + { "The Butcher's Cleaver", ITEMID_CLEAVER, 1, 3, 3650, + PL_STR, 10, 10, + PL_DAMAGE, 4, 24, + PL_DURNUM, 10, 10, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "The Undead Crown", ITEMID_SKCROWN, 1, 3, 16650, + PL_SKING, 0, 0, + PL_ACTUALAC, 8, 8, + PL_GFX, ITEM_CROWN, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Empyrean Band", ITEMID_IRING, 1, 4, 8000, + PL_STATS, 2, 2, + PL_LIGHT, 2, 2, + PL_HTANIM, 1, 1, + PL_TRAPDAM, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Optic Amulet", ITEMID_OPTAMULET, 1, 5, 9750, + PL_LIGHT, 2, 2, + PL_RLGHT, 20, 20, + PL_NGETHIT, 1, 1, + PL_MAG, 5, 5, + PL_GFX, ITEM_AMULET, 0, + 0, 0, 0 + }, + + { "Ring of Truth", ITEMID_TRING, 1, 4, 9100, + PL_HP, 10, 10, + PL_NGETHIT, 1, 1, + PL_RALL, 10, 10, + PL_GFX, ITEM_BLUERING, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Harlequin Crest", ITEMID_HALCREST, 1, 6, 4000, + PL_NACTULAC, 3, 3, + PL_NGETHIT, 1, 1, + PL_STATS, 2, 2, + PL_HP, 7, 7, + PL_MANA, 7, 7, + PL_GFX, ITEM_HARLEQ, 0, + }, + { "Veil of Steel", ITEMID_STEELVEIL, 1, 6, 63800, + PL_RALL, 50, 50, + PL_NLIGHT, 2, 2, + PL_AC, 60, 60, + PL_NMANA, 30, 30, + PL_STR, 15, 15, + PL_VIT, 15, 15 + }, + { "Arkaine's Valor", ITEMID_ARMOFVAL, 1, 4, 42000, + PL_ACTUALAC, 25, 25, + PL_VIT, 10, 10, + PL_NGETHIT, 3, 3, + PL_HTANIM, 3, 3, + 0, 0, 0, + 0, 0, 0 + }, + { "Griswold's Edge", ITEMID_GRISWOLD, 1, 6, 42000, + PL_FHIT, 1, 10, + PL_TOHIT, 25, 25, + PL_ATANIM, 2, 2, + PL_BEAR, 0, 0, + PL_MANA, 20, 20, + PL_NHP, 20, 20 + }, + { "Bovine Plate", ITEMID_ARMRCOW, 1, 6, 400, + PL_ACTUALAC, 150, 150, + PL_IND, 0, 0, + PL_LIGHT, 5, 5, + PL_RALL, 30, 30, + PL_NMANA, 50, 50, + PL_SLVL, -2, -2, + }, +#if 0 + { "Lightforge", ITEMID_MACE, 1, 6, 26675, + PL_LIGHT, 4, 4, + PL_TODAM, 150, 150, + PL_TOHIT, 25, 25, + PL_FHIT, 10, 20, + PL_IND, 0, 0, + PL_STATS, 8, 8 + }, +#endif + /* + { "Azurewrath", ITEMID_BASTSWORD, 1, 5, 66500, + PL_DAMDEMON, 200, 200, + PL_TOHIT, 40, 40, + PL_LHIT, 10, 20, + PL_STR, 15, 15, + PL_RMAG, 100, 100, + 0, 0, 0 + }, + { "Blackest Blade", ITEMID_SCIMITAR, 1, 5, 23667, + PL_MANA, 50, 50, + PL_RALL, 25, 25, + PL_TOHIT, 20, 20, + PL_TODAM, 100, 100, + PL_CONST, 0, 0, + 0, 0, 0 + }, + { "Codex of Enlightenment", ITEMID_BOOK, 1, 4, 5000, + PL_X, 0, 0, + PL_X, 0, 0, + PL_X, 0, 0, + PL_GFX, ITEM_BOOK3, 0, + 0, 0, 0, + 0, 0, 0 + }, +*/ + // From here down are random unique items + // Bow + { "The Rift Bow", ITEMID_SHORTBOW, 1, 3, 1800, + PL_RNDARW, 0, 0, + PL_DAMADD, 2, 2, + PL_NDEX, 3, 3, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "The Needler", ITEMID_SHORTBOW, 2, 4, 8900, + PL_TOHIT, 50, 50, + PL_DAMAGE, 1, 3, + PL_ATANIM, 2, 2, + PL_GFX, ITEM_CROSBOW, 0, + 0, 0, 0, + 0, 0, 0 + }, + +#if IS_VERSION(RETAIL) || IS_VERSION(BETA) + { "The Celestial Bow", ITEMID_LONGBOW, 2, 4, 1200, + PL_NSTRREQ, 0, 0, + PL_DAMADD, 2, 2, + PL_ACTUALAC, 5, 5, + PL_GFX, ITEM_HNTRBOW, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Deadly Hunter", ITEMID_COMPBOW, 3, 4, 8750, + PL_DAMDEMON, 10, 10, + PL_TOHIT, 20, 20, + PL_NMAG, 5, 5, + PL_GFX, ITEM_COMPBOW, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Bow of the Dead", ITEMID_COMPBOW, 5, 6, 2500, + PL_TOHIT, 10, 10, + PL_DEX, 4, 4, + PL_NVIT, 3, 3, + PL_NLIGHT, 2, 2, + PL_DURNUM, 30, 30, + PL_GFX, ITEM_COMPBOW, 0 + }, +#endif + + { "The Blackoak Bow", ITEMID_LONGBOW, 5, 4, 2500, + PL_DEX, 10, 10, + PL_NVIT, 10, 10, + PL_TODAM, 50, 50, + PL_NLIGHT, 1, 1, + 0, 0, 0, + 0, 0, 0 + }, + +#if IS_VERSION(RETAIL) + { "Flamedart", ITEMID_BOW, 10, 4, 14250, + PL_FARROW, 0, 0, + PL_FHIT, 1, 6, + PL_TOHIT, 20, 20, + PL_RFIRE, 40, 40, + 0, 0, 0, + 0, 0, 0 + }, + { "Fleshstinger", ITEMID_LONGBOW, 13, 4, 16500, + PL_DEX, 15, 15, + PL_TOHIT, 40, 40, + PL_TODAM, 80, 80, + PL_DUR, 6, 6, + 0, 0, 0, + 0, 0, 0 + }, + { "Windforce", ITEMID_LWARBOW, 17, 4, 37750, + PL_STR, 5, 5, + PL_TODAM, 200, 200, + PL_BEAR, 0, 0, + PL_GFX, ITEM_WINDFOR, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Eaglehorn", ITEMID_LBATTLEBOW, 26, 5, 42500, + PL_DEX, 20, 20, + PL_TOHIT, 50, 50, + PL_TODAM, 100, 100, + PL_IND, 0, 0, + PL_GFX, ITEM_COMPBOW, 0, + 0, 0, 0 + }, + + // Sword + { "Gonnagal's Dirk", ITEMID_DAGGER, 1, 5, 7040, + PL_NDEX, 5, 5, + PL_DAMADD, 4, 4, + PL_ATANIM, 2, 2, + PL_RFIRE, 25, 25, + PL_GFX, ITEM_DAGGER4, 0, + 0, 0, 0 + }, + { "The Defender", ITEMID_SABRE, 1, 3, 2000, + PL_ACTUALAC, 5, 5, + PL_VIT, 5, 5, + PL_NTOHIT, 5, 5, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Gryphons Claw", ITEMID_FALCHION, 1, 4, 1000, + PL_TODAM, 100, 100, + PL_NMAG, 2, 2, + PL_NDEX, 5, 5, + PL_GFX, ITEM_KNTSWORD, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Black Razor", ITEMID_DAGGER, 1, 4, 2000, + PL_TODAM, 150, 150, + PL_VIT, 2, 2, + PL_DURNUM, 5, 5, + PL_GFX, ITEM_DAGGER3, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Gibbous Moon", ITEMID_BROADSWORD, 2, 4, 6660, + PL_STATS, 2, 2, + PL_TODAM, 25, 25, + PL_MANA, 15, 15, + PL_NLIGHT, 3, 3, + 0, 0, 0, + 0, 0, 0 + }, + { "Ice Shank", ITEMID_LONGSWORD, 3, 3, 5250, + PL_RFIRE, 40, 40, + PL_DURNUM, 15, 15, + PL_STR, 5, 10, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "The Executioner's Blade", ITEMID_FALCHION, 3, 5, 7080, + PL_TODAM, 150, 150, + PL_NHP, 10, 10, + PL_NLIGHT, 1, 1, + PL_DUR, 200, 200, + PL_GFX, ITEM_FALCHION, 0, + 0, 0, 0 + }, + { "The Bonesaw", ITEMID_CLAYMORE, 6, 6, 4400, + PL_DAMADD, 10, 10, + PL_STR, 10, 10, + PL_NMAG, 5, 5, + PL_NDEX, 5, 5, + PL_HP, 10, 10, + PL_NMANA, 10, 10 + }, + { "Shadowhawk", ITEMID_BROADSWORD, 8, 4, 13750, + PL_NLIGHT, 2, 2, + PL_LEECH, 5, 5, + PL_TOHIT, 15, 15, + PL_RALL, 5, 5, + 0, 0, 0, + 0, 0, 0 + }, + { "Wizardspike", ITEMID_DAGGER, 11, 5, 12920, + PL_MAG, 15, 15, + PL_MANA, 35, 35, + PL_TOHIT, 25, 25, + PL_RALL, 15, 15, + PL_GFX, ITEM_DAGGER1, 0, + 0, 0, 0 + }, + { "Lightsabre", ITEMID_SABRE, 13, 4, 19150, + PL_LIGHT, 2, 2, + PL_LHIT, 1, 10, + PL_TOHIT, 20, 20, + PL_RLGHT, 50, 50, + 0, 0, 0, + 0, 0, 0 + }, + { "The Falcon's Talon", ITEMID_SCIMITAR, 15, 5, 7867, + PL_ATANIM, 4, 4, + PL_TOHIT, 20, 20, + PL_NTODAM, 33, 33, + PL_DEX, 10, 10, + PL_GFX, ITEM_KNTSWORD, 0, + 0, 0, 0 + }, + { "Inferno", ITEMID_LONGSWORD, 17, 4, 34600, + PL_FHIT, 2, 12, + PL_LIGHT, 3, 3, + PL_MANA, 20, 20, + PL_RFIRE, 80, 80, + 0, 0, 0, + 0, 0, 0 + }, + { "Doombringer", ITEMID_BASTSWORD, 19, 5, 18250, + PL_TOHIT, 25, 25, + PL_TODAM, 250, 250, + PL_NSTATS, 5, 5, + PL_NHP, 25, 25, + PL_NLIGHT, 2, 2, + 0, 0, 0 + }, + { "The Grizzly", ITEMID_2HANDSWORD, 23, 6, 50000, + PL_STR, 20, 20, + PL_NVIT, 5, 5, + PL_TODAM, 200, 200, + PL_BEAR, 0, 0, + PL_DUR, 100, 100, + PL_GFX, ITEM_GRIZZLY, 0 + }, + { "The Grandfather", ITEMID_GREATSWORD, 27, 6, 119800, + PL_ONEHAND, 0, 0, + PL_STATS, 5, 5, + PL_TOHIT, 20, 20, + PL_TODAM, 70, 70, + PL_HP, 20, 20, + PL_GFX, ITEM_GRANDPA, 0 + }, + // Axe + { "The Mangler", ITEMID_LARGEAXE, 2, 5, 2850, + PL_TODAM, 200, 200, + PL_NDEX, 5, 5, + PL_NMAG, 5, 5, + PL_NMANA, 10, 10, + PL_GFX, ITEM_HANDAXE, 0, + 0, 0, 0 + }, + { "Sharp Beak", ITEMID_LARGEAXE, 2, 4, 2850, + PL_HP, 20, 20, + PL_NMAG, 10, 10, + PL_NMANA, 10, 10, + PL_GFX, ITEM_WICKAXE, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "BloodSlayer", ITEMID_BROADAXE, 3, 5, 2500, + PL_TODAM, 100, 100, + PL_DAMDEMON, 50, 50, + PL_NSTATS, 5, 5, + PL_SLVL, -1, -1, + PL_GFX, ITEM_HANDAXE, 0, + 0, 0, 0 + }, + { "The Celestial Axe", ITEMID_BATTLEAXE, 4, 4, 14100, + PL_NSTRREQ, 0, 0, + PL_TOHIT, 15, 15, + PL_HP, 15, 15, + PL_NSTR, 15, 15, + 0, 0, 0, + 0, 0, 0 + }, + { "Wicked Axe", ITEMID_LARGEAXE, 5, 6, 31150, + PL_TOHIT, 30, 30, + PL_DEX, 10, 10, + PL_NVIT, 10, 10, + PL_NGETHIT, 1, 6, + PL_IND, 0, 0, + PL_GFX, ITEM_WICKAXE, 0, + }, + { "Stonecleaver", ITEMID_BROADAXE, 7, 5, 23900, + PL_HP, 30, 30, + PL_TOHIT, 20, 20, + PL_TODAM, 50, 50, + PL_RLGHT, 40, 40, + PL_GFX, ITEM_AXE, 0, + 0, 0, 0 + }, + { "Aguinara's Hatchet", ITEMID_SMALLAXE, 12, 3, 24800, + PL_SLVL, 1, 1, + PL_MAG, 10, 10, + PL_RMAG, 80, 80, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Hellslayer", ITEMID_BATTLEAXE, 15, 5, 26200, + PL_STR, 8, 8, + PL_VIT, 8, 8, + PL_TODAM, 100, 100, + PL_HP, 25, 25, + PL_NMANA, 25, 25, + 0, 0, 0 + }, + { "Messerschmidt's Reaver", ITEMID_GREATAXE, 25, 6, 58000, + PL_TODAM, 200, 200, + PL_DAMADD, 15, 15, + PL_STATS, 5, 5, + PL_NHP, 50, 50, + PL_FHIT, 2, 12, + PL_GFX, ITEM_REAVER, 0 + }, + // Mace + + { "Crackrust", ITEMID_MACE, 1, 5, 11375, + PL_STATS, 2, 2, + PL_IND, 0, 0, + PL_RALL, 15, 15, + PL_TODAM, 50, 50, + PL_SLVL, -1, -1, + 0, 0, 0 + }, + { "Hammer of Jholm", ITEMID_MAUL, 1, 4, 8700, + PL_TODAM, 4, 10, + PL_IND, 0, 0, + PL_STR, 3, 3, + PL_TOHIT, 15, 15, + 0, 0, 0, + 0, 0, 0 + }, + { "Civerb's Cudgel", ITEMID_MACE, 1, 3, 2000, + PL_DAMDEMON, 35, 35, + PL_NDEX, 5, 5, + PL_NMAG, 2, 2, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "The Celestial Star", ITEMID_FLAIL, 2, 5, 7810, + PL_NSTRREQ, 0, 0, + PL_LIGHT, 2, 2, + PL_DAMADD, 10, 10, + PL_NACTULAC, 8, 8, + PL_GFX, ITEM_FLAIL, 0, + 0, 0, 0 + }, + { "Baranar's Star", ITEMID_MORNSTAR, 5, 6, 6850, + PL_TOHIT, 12, 12, + PL_TODAM, 80, 80, + PL_ATANIM, 1, 1, + PL_VIT, 4, 4, + PL_NDEX, 4, 4, + PL_DURNUM, 60, 60 + }, + { "Gnarled Root", ITEMID_CLUB, 9, 6, 9820, + PL_TOHIT, 20, 20, + PL_TODAM, 300, 300, + PL_DEX, 10, 10, + PL_MAG, 5, 5, + PL_RALL, 10, 10, + PL_NACTULAC, 10, 10 + }, + { "The Cranium Basher", ITEMID_MAUL, 12, 6, 36500, + PL_DAMADD, 20, 20, + PL_STR, 15, 15, + PL_IND, 0, 0, + PL_NMANA, 150, 150, + PL_RALL, 5, 5, + PL_GFX, ITEM_MAUL, 0 + }, + { "Schaefer's Hammer", ITEMID_WARHAMMER, 16, 6, 56125, + PL_NTODAM, 100, 100, + PL_LHIT, 1, 50, + PL_HP, 50, 50, + PL_TOHIT, 30, 30, + PL_RLGHT, 80, 80, + PL_LIGHT, 1, 1 + }, + { "Dreamflange", ITEMID_MACE, 26, 5, 26450, + PL_MAG, 30, 30, + PL_MANA, 50, 50, + PL_RMAG, 50, 50, + PL_LIGHT, 2, 2, + PL_SLVL, 1, 1, + 0, 0, 0 + }, + // Staff + { "Staff of Shadows", ITEMID_LONGSTAFF, 2, 5, 1250, + PL_NMAG, 10, 10, + PL_TOHIT, 10, 10, + PL_TODAM, 60, 60, + PL_NLIGHT, 2, 2, + PL_ATANIM, 1, 1, + 0, 0, 0 + }, + { "Immolator", ITEMID_LONGSTAFF, 4, 4, 3900, + PL_RFIRE, 20, 20, + PL_FHIT, 4, 4, + PL_MANA, 10, 10, + PL_NVIT, 5, 5, + 0, 0, 0, + 0, 0, 0 + }, + { "Storm Spire", ITEMID_WARSTAFF, 8, 4, 22500, + PL_RLGHT, 50, 50, + PL_LHIT, 2, 8, + PL_STR, 10, 10, + PL_NMAG, 10, 10, + 0, 0, 0, + 0, 0, 0 + }, + { "Gleamsong", ITEMID_SHORTSTAFF, 8, 4, 6520, + PL_MANA, 25, 25, + PL_NSTR, 3, 3, + PL_NVIT, 3, 3, + PL_SPELL, SPL_PHASE, 76, + 0, 0, 0, + 0, 0, 0 + }, + { "Thundercall", ITEMID_COMPSTAFF, 14, 5, 22250, + PL_TOHIT, 35, 35, + PL_LHIT, 1, 10, + PL_SPELL, SPL_LIGHTNING, 76, + PL_RLGHT, 30, 30, + PL_LIGHT, 2, 2, + 0, 0, 0 + }, + { "The Protector", ITEMID_SHORTSTAFF, 16, 6, 17240, + PL_VIT, 5, 5, + PL_NGETHIT, 5, 5, + PL_ACTUALAC, 40, 40, + PL_SPELL, SPL_HEAL, 86, + PL_THORN, 1, 3, + PL_GFX, ITEM_PROTECT, 0 + }, + { "Naj's Puzzler", ITEMID_LONGSTAFF, 18, 5, 34000, + PL_MAG, 20, 20, + PL_DEX, 10, 10, + PL_RALL, 20, 20, + PL_SPELL, SPL_TELE, 57, + PL_NHP, 25, 25, + 0, 0, 0 + }, + { "Mindcry", ITEMID_QTRSTAFF, 20, 4, 41500, + PL_MAG, 15, 15, + PL_SPELL, SPL_GUARDIAN, 69, + PL_RALL, 15, 15, + PL_SLVL, 1, 1, + 0, 0, 0, + 0, 0, 0 + }, + { "Rod of Onan", ITEMID_WARSTAFF, 22, 3, 44167, + PL_SPELL, SPL_GOLEM, 50, + PL_TODAM, 100, 100, + PL_STATS, 5, 5, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + + // Cap / Helmet + { "Helm of Sprits", ITEMID_HELM, 1, 2, 7525, + PL_LEECH, 5, 5, + PL_GFX, ITEM_CROWN, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Thinking Cap", ITEMID_SKULLCAP, 6, 5, 2020, + PL_MANA, 30, 30, + PL_SLVL, 2, 2, + PL_RALL, 20, 20, + PL_DURNUM, 1, 1, + PL_GFX, ITEM_SKLCAP2, 0, + 0, 0, 0 + }, + { "OverLord's Helm", ITEMID_HELM, 7, 6, 12500, + PL_STR, 20, 20, + PL_DEX, 15, 15, + PL_VIT, 5, 5, + PL_NMAG, 20, 20, + PL_DURNUM, 15, 15, + PL_GFX, ITEM_SAMHELM, 0 + }, + { "Fool's Crest", ITEMID_HELM, 12, 5, 10150, + PL_NSTATS, 4, 4, + PL_HP, 100, 100, + PL_GETHIT, 1, 6, + PL_THORN, 1, 3, + PL_GFX, ITEM_JESTER, 0, + 0, 0, 0 + }, + { "Gotterdamerung", ITEMID_GREATHELM, 21, 6, 54900, + PL_STATS, 20, 20, + PL_ACTUALAC, 60, 60, + PL_NGETHIT, 4, 4, + PL_ZERORES, 0, 0, + PL_NLIGHT, 4, 4, + PL_GFX, ITEM_GRTHELM, 0 + }, + { "Royal Circlet", ITEMID_CROWN, 27, 5, 24875, + PL_STATS, 10, 10, + PL_MANA, 40, 40, + PL_ACTUALAC, 40, 40, + PL_LIGHT, 1, 1, + PL_GFX, ITEM_MCROWN, 0, + 0, 0, 0 + }, + + // Armor + { "Torn Flesh of Souls", ITEMID_RAGS, 2, 5, 4825, + PL_ACTUALAC, 8, 8, + PL_VIT, 10, 10, + PL_NGETHIT, 1, 1, + PL_IND, 0, 0, + PL_GFX, ITEM_FLESH, 0, + 0, 0, 0 + }, + { "The Gladiator's Bane", ITEMID_STDLEATHER, 6, 4, 3450, + PL_ACTUALAC, 25, 25, + PL_NGETHIT, 2, 2, + PL_DUR, 200, 200, + PL_NSTATS, 3, 3, + 0, 0, 0, + 0, 0, 0 + }, + { "The Rainbow Cloak", ITEMID_CLOAK, 2, 6, 4900, + PL_ACTUALAC, 10, 10, + PL_STATS, 1, 1, + PL_RALL, 10, 10, + PL_HP, 5, 5, + PL_DUR, 50, 50, + PL_GFX, ITEM_HVYROBE, 0 + }, + { "Leather of Aut", ITEMID_LEATHER, 4, 5, 10550, + PL_ACTUALAC, 15, 15, + PL_STR, 5, 5, + PL_NMAG, 5, 5, + PL_DEX, 5, 5, + PL_IND, 0, 0, + 0, 0, 0 + }, + { "Wisdom's Wrap", ITEMID_ROBE, 5, 6, 6200, + PL_MAG, 5, 5, + PL_MANA, 10, 10, + PL_RLGHT, 25, 25, + PL_ACTUALAC, 15, 15, + PL_NGETHIT, 1, 1, + PL_GFX, ITEM_HVYROBE, 0 + }, + { "Sparking Mail", ITEMID_CHAINMAIL, 9, 2, 15750, + PL_ACTUALAC, 30, 30, + PL_LHIT, 1, 10, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Scavenger Carapace", ITEMID_BREASTPLATE, 13, 4, 14000, + PL_NGETHIT, 15, 15, + PL_NACTULAC, 30, 30, + PL_DEX, 5, 5, + PL_RLGHT, 40, 40, + 0, 0, 0, + 0, 0, 0 + }, + { "Nightscape", ITEMID_CAPE, 16, 6, 11600, + PL_HTANIM, 2, 2, + PL_NLIGHT, 4, 4, + PL_ACTUALAC, 15, 15, + PL_DEX, 3, 3, + PL_RALL, 20, 20, + PL_GFX, ITEM_HVYROBE, 0, + }, + { "Naj's Light Plate", ITEMID_PLATEMAIL, 19, 6, 78700, + PL_NSTRREQ, 0, 0, + PL_MAG, 5, 5, + PL_MANA, 20, 20, + PL_RALL, 20, 20, + PL_SLVL, 1, 1, + PL_GFX, ITEM_NAJARMOR, 0 + }, + { "Demonspike Coat", ITEMID_FULLPLATE, 25, 5, 251175, + PL_ACTUALAC, 100, 100, + PL_NGETHIT, 6, 6, + PL_STR, 10, 10, + PL_IND, 0, 0, + PL_RFIRE, 50, 50, + 0, 0, 0 + }, + // Shield + { "The Deflector", ITEMID_BUCKLER, 1, 5, 1500, + PL_ACTUALAC, 7, 7, + PL_RALL, 10, 10, + PL_NTODAM, 20, 20, + PL_NTOHIT, 5, 5, + PL_GFX, ITEM_BUCKLER, 0, + 0, 0, 0 + }, + { "Split Skull Shield", ITEMID_BUCKLER, 1, 6, 2025, + PL_ACTUALAC, 10, 10, + PL_HP, 10, 10, + PL_STR, 2, 2, + PL_NLIGHT, 1, 1, + PL_DURNUM, 15, 15, + PL_GFX, ITEM_SKULLSHLD, 0 + }, + { "Dragon's Breach", ITEMID_KITESHLD, 2, 6, 19200, + PL_RFIRE, 25, 25, + PL_STR, 5, 5, + PL_ACTUALAC, 20, 20, + PL_NMAG, 5, 5, + PL_IND, 0, 0, + PL_GFX, ITEM_WOLFSHLD, 0 + }, + { "Blackoak Shield", ITEMID_SMALLSHLD, 4, 6, 5725, + PL_DEX, 10, 10, + PL_NVIT, 10, 10, + PL_ACTUALAC, 18, 18, + PL_NLIGHT, 1, 1, + PL_DUR, 150, 150, + PL_GFX, ITEM_IRONSHLD, 0 + }, + { "Holy Defender", ITEMID_LARGESHLD, 10, 6, 13800, + PL_ACTUALAC, 15, 15, + PL_NGETHIT, 2, 2, + PL_RFIRE, 20, 20, + PL_DUR, 200, 200, + PL_BLANIM, 1, 1, + PL_GFX, ITEM_IRONSHLD, 0 + }, + { "Stormshield", ITEMID_TOWERSHLD, 24, 6, 49000, + PL_ACTUALAC, 40, 40, + PL_GETHIT, 4, 4, + PL_STR, 10, 10, + PL_IND, 0, 0, + PL_BLANIM, 1, 1, + PL_GFX, ITEM_LRGSHLD, 0 + }, + + // Ring + { "Bramble", ITEMID_RING, 1, 4, 1000, + PL_NSTATS, 2, 2, + PL_DAMADD, 3, 3, + PL_MANA, 10, 10, + PL_GFX, ITEM_WOODRING, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Ring of Regha", ITEMID_RING, 1, 6, 4175, + PL_MAG, 10, 10, + PL_RMAG, 10, 10, + PL_LIGHT, 1, 1, + PL_NSTR, 3, 3, + PL_NDEX, 3, 3, + PL_GFX, ITEM_3JRING, 0, + }, + { "The Bleeder", ITEMID_RING, 2, 4, 8500, + PL_RMAG, 20, 20, + PL_MANA, 30, 30, + PL_NHP, 10, 10, + PL_GFX, ITEM_1JRING, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Constricting Ring", ITEMID_RING, 5, 3, 62000, + PL_RALL, 75, 75, + PL_CONST, 0, 0, + PL_GFX, ITEM_BRNRING, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Ring of Engagement", ITEMID_RING, 11, 5, 12476, + PL_NGETHIT, 1, 2, + PL_THORN, 1, 3, + PL_ACTUALAC, 5, 5, + PL_ENAC, 4, 12, + PL_GFX, ITEM_MJRING, 0, + 0, 0, 0 + }, + // added 7/30/97 by donald + { "Giant's Knuckle", ITEMID_RING, 8, 3, 8000, + PL_STR, 60, 60, + PL_NDEX, 30, 30, + PL_GFX, ITEM_RINGGIANTS, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Mercurial Ring", ITEMID_RING, 8, 3, 8000, + PL_DEX, 60, 60, + PL_NSTR, 30, 30, + PL_GFX, ITEM_MERCRING, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Xorine's Ring", ITEMID_RING, 8, 3, 8000, + PL_MAG, 60, 60, + PL_NSTR, 30, 30, + PL_GFX, ITEM_MERLINRING, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Karik's Ring", ITEMID_RING, 8, 3, 8000, + PL_VIT, 60, 60, + PL_NMAG, 30, 30, + PL_GFX, ITEM_KARIKSRING, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + + { "Ring of Magma", ITEMID_RING, 8, 4, 8000, + PL_RFIRE, 60, 60, + PL_NRLGHT, 30, 30, + PL_NRMAG, 30, 30, + PL_GFX, ITEM_RINGMAGMA, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Ring of the Mystics", ITEMID_RING, 8, 4, 8000, + PL_RMAG, 60, 60, + PL_NRFIRE, 30, 30, + PL_NRLGHT, 30, 30, + PL_GFX, ITEM_RINGMYSTIC, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Ring of Thunder", ITEMID_RING, 8, 4, 8000, + PL_RLGHT, 60, 60, + PL_NRFIRE, 30, 30, + PL_NRMAG, 30, 30, + PL_GFX, ITEM_RINGTHUND, 0, + 0, 0, 0, + 0, 0, 0 + }, + + { "Amulet of Warding", ITEMID_AMULET, 12, 3, 30000, + PL_RALL, 40, 40, + PL_NHP, 100, 100, + PL_GFX, ITEM_AMULWARD, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Gnat Sting", ITEMID_BOW, 15, 5, 30000, + PL_NUMARWS, 3, 3, + PL_DAMAGE, 1, 2, + PL_ATANIM, 1, 1, + PL_IND, 0, 0, + PL_GFX, ITEM_BOWSPEED, 0, + 0, 0, 0 + }, + { "Flambeau", ITEMID_COMPBOW, 11, 4, 30000, + PL_HITADD, 15, 20, + PL_DAMAGE, 0, 0, + PL_IND, 0, 0, + PL_GFX, ITEM_BOWVULCAN, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Armor of Gloom", ITEMID_FULLPLATE, 25, 5, 200000, + PL_NSTRREQ, 0, 0, + PL_ACTUALAC, 225, 225, + PL_ZERORES, 0, 0, + PL_NLIGHT, 2, 2, + PL_GFX, ITEM_ARMRDARK, 0, + 0, 0, 0 + }, + + { "Blitzen", ITEMID_COMPBOW, 13, 4, 30000, + PL_HARQUN, 10, 15, + PL_DAMAGE, 0, 0, + PL_IND, 0, 0, + PL_GFX, ITEM_BOWDECAY, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Thunderclap", ITEMID_WARHAMMER, 13, 6, 30000, + PL_HARQUN2, 3, 6, + PL_STR, 20, 20, + PL_RLGHT, 30, 30, + PL_LIGHT, 2, 2, + PL_IND, 0, 0, + PL_GFX, ITEM_HAMRTHUND, 0 + }, + { "Shirotachi", ITEMID_GREATSWORD, 21, 4, 36000, + PL_ONEHAND, 0, 0, + PL_ATANIM, 4, 4, + PL_ENAC, 2, 2, + PL_LHIT, 6, 6, + 0, 0, 0, + 0, 0, 0 + }, + { "Eater of Souls", ITEMID_2HANDSWORD, 23, 6, 42000, + PL_IND, 0, 0, + PL_HP, 50, 50, + PL_LEECH, 5, 5, + PL_BAT, 5, 5, + PL_CONST, 0, 0, + PL_GFX, ITEM_SWORDEDGE, 0 + }, + { "Diamondedge", ITEMID_LONGSWORD, 17, 6, 42000, + PL_DURNUM, 10, 10, + PL_TOHIT, 50, 50, + PL_TODAM, 100, 100, + PL_RLGHT, 50, 50, + PL_ACTUALAC, 10, 10, + PL_GFX, ITEM_SWRDCRYSTL, 0 + }, + { "Bone Chain Armor", ITEMID_CHAINMAIL, 13, 3, 36000, + PL_ACTUALAC, 40, 40, + PL_UNDEADAC, 0, 0, + PL_GFX, ITEM_ARMRBONECH, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Demon Plate Armor", ITEMID_FULLPLATE, 25, 3, 80000, + PL_ACTUALAC, 80, 80, + PL_DEMONAC, 0, 0, + PL_GFX, ITEM_ARMRDMNPLT, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Acolyte's Amulet", ITEMID_AMULET, 10, 2, 10000, + PL_ACOLYTE, 50, 50, + PL_GFX, ITEM_AMULACOLYT, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Gladiator's Ring", ITEMID_RING, 10, 2, 10000, + PL_GLADIATR, 40, 40, + PL_GFX, ITEM_RINGGLADTR, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, + + // Book +/* { "Zhar the Mad's Memoirs", ITEMID_NONE, 6, 4, 4000, + PL_NMANA, 10, 10, + PL_NMAG, 10, 10, + PL_SLVL, 1, 1, + PL_GFX, ITEM_BOOK1, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "T'farc Evol's Tomb", ITEMID_NONE, 8, 4, 5000, + PL_MAG, 15, 15, + PL_NMANA, 25, 25, + PL_SLVL, 1, 1, + PL_GFX, ITEM_BOOK2, 0, + 0, 0, 0, + 0, 0, 0 + }, + // Amulet + { "Yulm's Mystic Amulet", ITEMID_AMULET, 1, 4, 1200, + PL_MAG, 10, 10, + PL_RALL, 10, 10, + PL_NSTATS, 5, 5, + PL_GFX, ITEM_AMULET2, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Torka's Amulet of Power", ITEMID_AMULET, 2, 4, 19700, + PL_SLVL, 1, 1, + PL_MAG, 5, 5, + PL_LEECH, 5, 5, + PL_GFX, ITEM_AMULET2, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Amulet of the Dead", ITEMID_AMULET, 12, 4, 5000, + PL_NMANA, 20, 20, + PL_X, 0, 0,//(NW) + PL_X, 0, 0,//(NW) + PL_GFX, ITEM_AMULET4, 0, + 0, 0, 0, + 0, 0, 0 + }, + { "Scarab Amulet", ITEMID_AMULET, 18, 3, 5000, + PL_STATS, 5, 5, + PL_X, 0, 0,//(NW) + PL_GFX, ITEM_AMULET3, 0, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0 + }, +*/ +#endif + + { "", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Stopper +}; + diff --git a/src/ITEMDAT.H b/src/ITEMDAT.H new file mode 100644 index 0000000..d4f50c8 --- /dev/null +++ b/src/ITEMDAT.H @@ -0,0 +1,301 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/ITEMDAT.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Powers List +**-----------------------------------------------------------------------*/ + +#define PL_TOHIT 0 // To hit +#define PL_NTOHIT 1 // Negative to hit +#define PL_TODAM 2 // Damage amount % +#define PL_NTODAM 3 // Negative damage amount % +#define PL_DAHT 4 // Damage and to hit % +#define PL_NDAHT 5 // Negative damage and to hit % +#define PL_AC 6 // Armor Class % increase +#define PL_NAC 7 // Negative % Armor Class + +#define PL_RFIRE 8 // Resistance to fire % +#define PL_RLGHT 9 // Resistance to lightning % +#define PL_RMAG 10 // Resistance to misc magic % +#define PL_RALL 11 // Resistance to all + +//#define PL_SCOST 12 // Spell cost (-) (removed by drb for multiplayer pickup flag) +//#define PL_SDUR 13 // Spell duration (removed by drb for unique crash) +#define PL_SLVL 14 // Spell levels + +#define PL_CHRG 15 // Staff charges + +#define PL_FHIT 16 // Fire hit +#define PL_LHIT 17 // Lightning hit +#define PL_CHAOS 18 //not in game + +#define PL_STR 19 // Strength attribute +#define PL_NSTR 20 // Negative strength attribute +#define PL_MAG 21 // Magic attribute +#define PL_NMAG 22 // Negative magic attribute +#define PL_DEX 23 // Dexterity attribute +#define PL_NDEX 24 // Negative dexterity attribute +#define PL_VIT 25 // Vitality attribute +#define PL_NVIT 26 // Negative vitality attribute +#define PL_STATS 27 // All attributes +#define PL_NSTATS 28 // Negative all attributes + +#define PL_GETHIT 29 // Add to every get hit +#define PL_NGETHIT 30 // Subtract from every get hit + +#define PL_HP 31 // Hit points attribute +#define PL_NHP 32 // Negative hit points attribute +#define PL_MANA 33 // Mana attribute +#define PL_NMANA 34 // Negative mana attribute + +#define PL_DUR 35 // Add to item's durability % +#define PL_NDUR 36 // Subtract from item's durability % +#define PL_IND 37 // Infinite durability + +#define PL_LIGHT 38 // Add to player's light source +#define PL_NLIGHT 39 // Subtract from player's light source + +#define PL_INVIS 40 //not in game Player invisible from radius + +#define PL_NUMARWS 41 // Shoots multiple arrows +#define PL_FARROW 42 // Fire arrows +#define PL_LARROW 43 // Lightning arrows + +#define PL_GFX 44 // Change to unique graphic + +#define PL_THORN 45 // When item deals damage user gets damaged too +#define PL_LMANA 46 // Player looses all mana/ can't regen +#define PL_NOHEAL 47 // User can't heal +#define PL_FEAR 48 // When monster is struck, runs in fear (50%-ML) +#define PL_RABID 49 //not in game +#define PL_HITADD 50 // Half damage is added to player's hp +#define PL_SEEINVIS 51 //not in game See invisible +#define PL_TRAPDAM 52 // Half trap damage +#define PL_BEAR 53 // Knock monster back a square (if poss) +#define PL_MNOHEAL 54 // Monster no longer heals +#define PL_BAT 55 // Damage done adds to mana +#define PL_LEECH 56 // Damage dones adds to life +#define PL_ENAC 57 // Reduces the enemies ac by this +#define PL_ATANIM 58 // Attack anim quicker +#define PL_HTANIM 59 // Hit anim quicker +#define PL_BLANIM 60 // Block anim quicker + +#define PL_DAMADD 61 // Damage Hit point modifier + +// From here down, from uniques + +#define PL_RNDARW 62 // Random arrow speeds +#define PL_DAMAGE 63 // Changes weapon damage to (param1-param2) +#define PL_DURNUM 64 // Durability set to param1 +#define PL_NSTRREQ 65 // No minimum strength requirement +#define PL_SPELL 66 // Add charges to your staff +#define PL_FALCON 67 // Skips frames 1-3 of swing anim +#define PL_ONEHAND 68 // Change item to one handed +#define PL_DAMDEMON 69 // damage vs. demon only +#define PL_ZERORES 70 // All resistance equal to zero +#define PL_HYPER 71 // Hyperspace spell (param1 charges) +#define PL_CONST 72 // Constricting +#define PL_SKING 73 // Skeleton king power (life stealing) +#define PL_INFRA 74 // Infravision +#define PL_ACTUALAC 75 // Actual Armor Class +#define PL_HARQUN 76 // +(Armor Class)HP +#define PL_HARQUN2 77 // +(Mana/10)armor +#define PL_HARQUN3 78 // +(30-charlevel) resist fire +#define PL_NACTULAC 79 // Negative actual armor class +#define PL_NRFIRE 80 // Resistance to fire % (negative) +#define PL_NRLGHT 81 // Resistance to lightning % (negative) +#define PL_NRMAG 82 // Resistance to misc magic % (negative) +#define PL_NRALL 83 // Resistance to all % (negative) +#define PL_DEVAST 84 +#define PL_DECAY 85 +#define PL_PERIL 86 +#define PL_RNDDAM 87 +#define PL_FRAGILE 88 +#define PL_DOPPEL 89 +#define PL_DEMONAC 90 +#define PL_UNDEADAC 91 +#define PL_ACOLYTE 92 +#define PL_GLADIATR 93 +#define PL_X 94 // Unknown???? TEMP-------- + +/*-----------------------------------------------------------------------** +** Power List Bit flags +**-----------------------------------------------------------------------*/ + +#define PLF_ARMOR 0x100000 +#define PLF_SHIELD 0x010000 +#define PLF_WEAPON 0x001000 +#define PLF_STAFF 0x000100 +#define PLF_BOW 0x000010 +#define PLF_RING 0x000001 + +/*-----------------------------------------------------------------------** +** Item Misc Id +**-----------------------------------------------------------------------*/ + +#define IMID_NONE 0 // No misc ability +#define IMID_FIRSTPOT 1 +#define IMID_PHEAL 2 // Potion of full heal +#define IMID_PLHEAL 3 // Potion of Light heal +#define IMID_PSHEAL 4 // Potion of Serious heal +#define IMID_PDHEAL 5 // Potion of Deadly heal +#define IMID_PMANA 6 // Potion of Mana +#define IMID_PFMANA 7 // Potion of Full mana +#define IMID_PEXP 8 // Potion of Experience +#define IMID_PNEXP 9 // Potion of Negative Experience +#define IMID_ESTR 10 // Elixir of Strength +#define IMID_EMAG 11 // Elixir of Magic +#define IMID_EDEX 12 // Elixir of Dexterity +#define IMID_EVIT 13 // Elixir of Vitality +#define IMID_ENSTR 14 // Elixir of Negative Strength +#define IMID_ENMAG 15 // Elixir of Negative Magic +#define IMID_ENDEX 16 // Elixir of Negative Dexerity +#define IMID_ENVIT 17 // Elixir of Negative Vitaltiy +#define IMID_REJUV 18 +#define IMID_FREJUV 19 +#define IMID_LASTPOT 20 + +#define IMID_SCROLL 21 // Scroll of spell +#define IMID_TSCROLL 22 // Scroll of targeted spell +#define IMID_STAFF 23 // Item with a spell + +#define IMID_BOOK 24 // Book of spell +#define IMID_RING 25 +#define IMID_AMULET 26 + +#define IMID_UNIQUE 27 // Unique item so no magic / magic already built in + +#define IMID_MEAT 28 // Slab of meat + +#define IMID_FIRSTOIL 29 +#define IMID_OIL 30 +#define IMID_OILACC 31 +#define IMID_OILMAST 32 +#define IMID_OILSHRP 33 +#define IMID_OILDEATH 34 +#define IMID_OILSKILL 35 +#define IMID_OILBLKSM 36 +#define IMID_OILFORT 37 +#define IMID_OILPERM 38 +#define IMID_OILHARD 39 +#define IMID_OILIMPER 40 +#define IMID_LASTOIL 41 + +#define IMID_MAPOFDOOM 42 // The end quest map of doom item + +#define IMID_EAR 43 +#define IMID_SPECTRAL 44 + +#define IMID_BOMB 45 + +#define IMID_FIRSTRUNE 46 +#define IMID_RUNEFIRE 47 +#define IMID_RUNELIGHT 48 +#define IMID_RUNENOVA 49 +#define IMID_RUNEIMMOLATE 50 +#define IMID_RUNESTONE 51 +#define IMID_LASTRUNE 52 + +#define IMID_AURIC 53 + +#define IMID_FULLNOTE 54 + +/*-----------------------------------------------------------------------** +** Item Id's +**-----------------------------------------------------------------------*/ + +#define ITEMID_NONE 0 + +#define ITEMID_SHORTBOW 1 +#define ITEMID_LONGBOW 2 +#define ITEMID_BOW 3 +#define ITEMID_COMPBOW 4 +#define ITEMID_LWARBOW 5 +#define ITEMID_LBATTLEBOW 6 + +#define ITEMID_DAGGER 7 +#define ITEMID_FALCHION 8 +#define ITEMID_CLAYMORE 9 +#define ITEMID_BROADSWORD 10 +#define ITEMID_SABRE 11 +#define ITEMID_SCIMITAR 12 +#define ITEMID_LONGSWORD 13 +#define ITEMID_BASTSWORD 14 +#define ITEMID_2HANDSWORD 15 +#define ITEMID_GREATSWORD 16 + +#define ITEMID_CLEAVER 17 +#define ITEMID_LARGEAXE 18 +#define ITEMID_BROADAXE 19 +#define ITEMID_SMALLAXE 20 +#define ITEMID_BATTLEAXE 21 +#define ITEMID_GREATAXE 22 + +#define ITEMID_MACE 23 +#define ITEMID_MORNSTAR 24 +#define ITEMID_CLUB 25 +#define ITEMID_MAUL 26 +#define ITEMID_WARHAMMER 27 +#define ITEMID_FLAIL 28 + +#define ITEMID_LONGSTAFF 29 +#define ITEMID_SHORTSTAFF 30 +#define ITEMID_COMPSTAFF 31 +#define ITEMID_QTRSTAFF 32 +#define ITEMID_WARSTAFF 33 + +#define ITEMID_SKULLCAP 34 +#define ITEMID_HELM 35 +#define ITEMID_GREATHELM 36 +#define ITEMID_CROWN 37 + +#define ITEMID_RAGS 39 +#define ITEMID_STDLEATHER 40 +#define ITEMID_CLOAK 41 +#define ITEMID_ROBE 42 +#define ITEMID_CHAINMAIL 43 +#define ITEMID_LEATHER 44 +#define ITEMID_BREASTPLATE 45 +#define ITEMID_CAPE 46 +#define ITEMID_PLATEMAIL 47 +#define ITEMID_FULLPLATE 48 + +#define ITEMID_BUCKLER 49 +#define ITEMID_SMALLSHLD 50 +#define ITEMID_LARGESHLD 51 +#define ITEMID_KITESHLD 52 +#define ITEMID_TOWERSHLD 53 + +#define ITEMID_RING 54 +#define ITEMID_BOOK 55 +#define ITEMID_AMULET 56 + +#define ITEMID_SKCROWN 57 +#define ITEMID_IRING 58 +#define ITEMID_OPTAMULET 59 +#define ITEMID_TRING 60 +#define ITEMID_HALCREST 61 +#define ITEMID_MAP 62 +#define ITEMID_ELIXIR 63 +#define ITEMID_ARMOFVAL 64 +#define ITEMID_STEELVEIL 65 +#define ITEMID_GRISWOLD 66 +#define ITEMID_LGTFORGE 67 +#define ITEMID_LAZSTAFF 68 +#define ITEMID_ARMRCOW 69// dude! + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern ItemDataStruct AllItemsList[]; +extern const PLStruct PL_Prefix[]; +extern const PLStruct PL_Suffix[]; +extern const UItemStruct UniqueItemList[]; diff --git a/src/ITEMS.BAK b/src/ITEMS.BAK new file mode 100644 index 0000000..cf01bea --- /dev/null +++ b/src/ITEMS.BAK @@ -0,0 +1,5532 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Items file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/ITEMS.CPP 4 2/06/97 6:08p Jessmac $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "objects.h" +#include "items.h" +#include "itemdat.h" +#include "engine.h" +#include "gendung.h" +#include "player.h" +#include "control.h" +#include "monster.h" +#include "spells.h" +#include "quests.h" +#include "cursor.h" +#include "effects.h" +#include "lighting.h" +#include "stores.h" +#include "spelldat.h" +#include "scrollrt.h" +#include "inv.h" +#include "msg.h" +#include "multi.h" +#include "monstdat.h" +#include "doom.h" +#include "missiles.h" +#include "minitext.h" +#include "storm.h" +#include "DRLG_l1.h" +#include "packplr.h" + + +void RecreateTownItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue); +void SaveItemPower(int i, int power, int param1, int param2, int minval, int maxval, int multval); +void GetItemPower(int i, int minlvl, int maxlvl, long flgs, BOOL onlygood); +void GetItemAttrs(int i, int idata, int lvl); +void SetupItem(int); +void RecalcStoreStats(); +void SpawnMap(); +void DeleteItem(int ii, int i); + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ +CornerStoneType CornerStone; +extern char gszProgKey[]; + +int GOLD_VMAX = 5000; +ItemStruct item[MAXITEMS+1]; +long numitems = 0; + +int itemactive[MAXITEMS]; +int itemavail[MAXITEMS]; +int tem; + +//PATCH1.JMM +ItemGetRecordStruct itemgets[MAXITEMS]; +int gnNumGetRecords = 0; +//ENDPATCH1.JMM + + + +BOOL UniqueItemFlag[MAXUITEMS]; +BOOL uitemflag; +ItemStruct curruitem; +#if CHEATS +extern BOOL itemcheat; + +BOOL davecheat = FALSE; +#endif + +BOOL itemhold[3][3]; + + +#define MAXOIL 10 + +int OilLvlTbl[MAXOIL]= { 1, 10, 1, 10, 4, 1, 5, 17, 1, 10 }; +int OilValue[MAXOIL] = { 500, 2500, 500, 2500, 1500, 100, 2500, 15000, 500, 2500 }; +int OilIdVal[MAXOIL] = { + IMID_OILACC, + IMID_OILMAST, + IMID_OILSHRP, + IMID_OILDEATH, + IMID_OILSKILL, + IMID_OILBLKSM, + IMID_OILFORT, + IMID_OILPERM, + IMID_OILHARD, + IMID_OILIMPER +}; +char OilStr[MAXOIL][25] = { + "Oil of Accuracy", + "Oil of Mastery", + "Oil of Sharpness", + "Oil of Death", + "Oil of Skill", + "Blacksmith Oil", + "Oil of Fortitude", + "Oil of Permanence", + "Oil of Hardening", + "Oil of Imperviousness" +}; + +BYTE ItemCAnimTbl[] = { + // 1x1 + 20, // ITEM_BLUEBTL + 16, // ITEM_SCROLL + 16, // ITEM_SCROLL2 + 16, // ITEM_SCROLL3 + 4, // ITEM_1GOLD + 4, // ITEM_3GOLD + 4, // ITEM_5GOLD + 12, // ITEM_GOLDRING + 12, // ITEM_1JRING + 12, // ITEM_WOODRING + 12, // ITEM_BLUERING + 12, // ITEM_3JRING + 12, // ITEM_SLVRRING + 12, // ITEM_MJRING + 12, // ITEM_BRNRING + 21, // ITEM_SPECTRAL + 21, // ITEM_3COLORPOT + 25, // ITEM_GOLDENELIX + 12, // ITEM_EMPYBAND + 28, // ITEM_EAR1 + 28, // ITEM_EAR2 + 28, // ITEM_EAR3 + 38, // ITEM_SPHERE + 38, // ITEM_CUBE + 38, // ITEM_PYRIMID + 32, // ITEM_BLOODGEM + 38, // ITEM_JSPHERE + 38, // ITEM_JCUBE + 38, // ITEM_JPYRIMID + 24, // ITEM_VILE + 24, // ITEM_BLKBTL + 26, // ITEM_WHTEBTL + 2, // ITEM_REDBTL + 25, // ITEM_YELBTL + 22, // ITEM_ORGBTL + 23, // ITEM_BREDBTL + 24, // ITEM_BLKBTL2 + 25, // ITEM_GOLDBTL + 27, // ITEM_LTBLUEBTL + 27, // ITEM_BLUEBTL2 + 29, // ITEM_BRAIN + 0, // ITEM_CLAW + 0, // ITEM_FANG + 0, // ITEM_BREAD + 12, // ITEM_AMULET + 12, // ITEM_AMULET1 + 12, // ITEM_AMULET2 + 12, // ITEM_AMULET3 + 12, // ITEM_AMULET4 + 0, // ITEM_POUCH1 + //35, // ITEM_DOHICKY + //39, // ITEM_THEODORE + //36, // ITEM_PAPER1 + //36, // ITEM_PAPER2 + //36, // ITEM_PAPER3 + //37, // ITEM_PAPER4 + // 1x2 + 8, // ITEM_DAGGER1 + 8, // ITEM_DAGGER2 + 0, // ITEM_BIGBOTTLE + 8, // ITEM_DAGGER3 + 8, // ITEM_DAGGER4 + 8, // ITEM_DAGGER5 + // 1x3 + 8, // ITEM_BLADE + 8, // ITEM_BASTSRD + 8, // ITEM_FALCHION + 6, // ITEM_MACE + 8, // ITEM_LONGSRD + 8, // ITEM_BROADSRD + 8, // ITEM_SCIMITAR + 6, // ITEM_MORNSTAR + 8, // ITEM_SHORTSRD + 8, // ITEM_CLAYMORE + 6, // ITEM_CLUB + 8, // ITEM_SABRE + 8, // ITEM_KNTSWORD + 6, // ITEM_CLUB1 + 6, // ITEM_CLUB2 + 6, // ITEM_CLUB3 + 8, // ITEM_SCIMITAR2 + 8, // ITEM_MAGSWORD + 8, // ITEM_SKULSWORD + // 2x2 + 5, // ITEM_HELM + 9, // ITEM_ROCK + 13, // ITEM_SKCROWN + 13, // ITEM_CROWN + 13, // ITEM_MCROWN + 5, // ITEM_JESTER + 5, // ITEM_HARLEQ + 5, // ITEM_FHELM + 15, // ITEM_BUCKLER + 5, // ITEM_FHELM2 + 5, // ITEM_GRTHELM + 18, // ITEM_BOOK1 + 18, // ITEM_BOOK2 + 18, // ITEM_BOOK3 + 30, // ITEM_MUSHROOM + 5, // ITEM_SKLCAP + 5, // ITEM_LCAP + 14, // ITEM_FLESH + 5, // ITEM_SKLCAP2 + 14, // ITEM_CLOTHES + 13, // ITEM_CROWN2 + 16, // ITEM_MAP + 18, // ITEM_BOOK4 + 5, // ITEM_FHELM3 + 5, // ITEM_SAMHELM + // 2x3 + 7, // ITEM_LRGSHIELD + 1, // ITEM_BTLAXE + 3, // ITEM_LONGBOW + 17, // ITEM_PARMOR + 1, // ITEM_AXE + 15, // ITEM_WSHIELD + 10, // ITEM_CLEAVER + 14, // ITEM_STDARMOR + 3, // ITEM_COMPBOW + 11, // ITEM_SHRTSTAFF + 8, // ITEM_2HSWORD + 0, // ITEM_CHARMOR + 1, // ITEM_SMALLAXE + 7, // ITEM_HVYSHIELD + 0, // ITEM_SCLARMOR + 7, // ITEM_SMLSHIELD + 15, // ITEM_SKULLSHLD + 7, // ITEM_WOLFSHLD + 3, // ITEM_SHORTBOW + 3, // ITEM_STLLONGBOW + 3, // ITEM_STLSHRTBOW + 6, // ITEM_SMLWARHAM + 6, // ITEM_MAUL + 11, // ITEM_IRONSTAFF + 11, // ITEM_STLSTAFF + 11, // ITEM_LONGSTAFF + 31, // ITEM_INNSIGN + 14, // ITEM_HLARMOR + 14, // ITEM_RAGS + 14, // ITEM_QARMOR + 6, // ITEM_BALLNCHN + 6, // ITEM_FLAIL + 7, // ITEM_TSHIELD + 3, // ITEM_HNTRBOW + 8, // ITEM_GRTSWORD + 14, // ITEM_LARMOR + 0, // ITEM_SPLTARMOR + 14, // ITEM_ROBE + 14, // ITEM_HVYROBE + 0, // ITEM_RINGARMOR + 33, // ITEM_ANVIL + 1, // ITEM_BROADAXE + 1, // ITEM_LRGAXE + 1, // ITEM_WICKAXE + 1, // ITEM_HANDAXE + 1, // ITEM_GREATAXE + 7, // ITEM_IRONSHLD + 7, // ITEM_KITESHLD + 7, // ITEM_LRGSHLD + 14, // ITEM_CLOAK + 14, // ITEM_CAPE + 17, // ITEM_PARMOR2 + 17, // ITEM_PARMOR3 + 17, // ITEM_BPLATE + 0, // ITEM_RINGMAIL + 34, // ITEM_BISHOPSTF + 1, // ITEM_GEMGRTAXE + 0, // ITEM_ARKARMOR + 3, // ITEM_CROSBOW + 17, // ITEM_NAJARMOR + 8, // ITEM_GRIZZLY + 8, // ITEM_GRANDPA + 6, // ITEM_PROTECT + 1, // ITEM_REAVER + 3, // ITEM_WINDFOR + 3, // ITEM_SWARBOW + 11, // ITEM_COMPSTF + 3, // ITEM_SBATLBOW +// Misc +// 4, // ITEM_GOLD + +// new 1x1 + 12, // ITEM_MERLINRING + 12, // ITEM_MANARING + 12, // ITEM_AMULWARD + 12, // ITEM_NECMAGIC + 12, // ITEM_NECHEALTH + 12, // ITEM_KARIKSRING + 12, // ITEM_RINGGROUND + 12, // ITEM_AMULPROT + 12, // ITEM_MERCRING + 12, // ITEM_RINGTHUND + 12, // ITEM_NECTRUTH + 12, // ITEM_RINGGIANTS + 12, // ITEM_AMULGOLD + 12, // ITEM_RINGMYSTIC + 12, // ITEM_RINGCOPPER + 12, // ITEM_AMULACOLYT + 12, // ITEM_RINGMAGMA + 12, // ITEM_NECPURIFY + 12, // ITEM_RINGGLADTR + 35, // ITEM_RUNEBOMB +// new 1x3 + 8, // ITEM_SWORDEDGE + 8, // ITEM_SWORDGLAM + 8, // ITEM_SWORDSERR +// new 2x3 + 17, // ITEM_ARMRDARK + 0, // ITEM_ARMRBONECH + 6, // ITEM_HAMRTHUND + 8, // ITEM_SWRDCRYSTL + 11, // ITEM_STAFJESTER + 11, // ITEM_STAFMANA + 3, // ITEM_BOWVULCAN + 3, // ITEM_BOWSPEED + 1, // ITEM_AXEANCIENT + 6, // ITEM_CLUBCARNAG + 6, // ITEM_MACEDARK + 6, // ITEM_CLUBDECAY + 1, // ITEM_AXEDECAY + 8, // ITEM_SWRDDECAY + 6, // ITEM_MACEDECAY + 11, // ITEM_STAFDECAY + 3, // ITEM_BOWDECAY + 6, // ITEM_CLUBOUCH + 8, // ITEM_SWRDDEVAST + 1, // ITEM_AXEDEVAST + 6, // ITEM_MORNDEVAST + 6 // ITEM_MACEDEVAST + + }; + + +char *ItemFiles[] = { + "Armor2", // 0 + "Axe", // 1 + "FBttle", // 2 + "Bow", // 3 + "GoldFlip", // 4 + "Helmut", // 5 + "Mace", // 6 + "Shield", // 7 + "SwrdFlip", // 8 + "Rock", // 9 + "Cleaver", // 10 + "Staff", // 11 + "Ring", // 12 + "CrownF", // 13 + "LArmor", // 14 + "WShield", // 15 + "Scroll", // 16 + "FPlateAr", // 17 + "FBook", // 18 + "Food", // 19 + "FBttleBB", // 20 + "FBttleDY", // 21 + "FBttleOR", // 22 + "FBttleBR", // 23 + "FBttleBL", // 24 + "FBttleBY", // 25 + "FBttleWH", // 26 + "FBttleDB", // 27 + "FEar", // 28 + "FBrain", // 29 + "FMush", // 30 + "Innsign", // 31 + "Bldstn", // 32 + "Fanvil", // 33 + "FLazStaf", // 34 + "bombs1", // 35 + "halfps1", // 36 + "wholeps1", // 37 + "runes1", // 38 + "teddys1" // 39 +}; +#define ITEMFTYPES (sizeof(ItemFiles)/sizeof(char *)) + +BYTE *itemanims[ITEMFTYPES]; + +byte ItemAnimLs[ITEMFTYPES] = { + 15, // Armor2 + 13, // Axe + 16, // FBttle + 13, // Bow + 10, // GoldFlip + 13, // Helmut + 13, // Mace + 13, // Shield + 13, // SwrdFlip + 10, // Rock + 13, // Cleaver + 13, // Staff + 13, // Ring + 13, // Crown + 13, // LArmor + 13, // WShield + 13, // Scroll + 13, // FPlateAr + 13, // FBook + 1, // Food + 16, // FBttleBB + 16, // FBttleDY + 16, // FBttleOR + 16, // FBttleBR + 16, // FBttleBL + 16, // FBttleBY + 16, // FBttleWH + 16, // FBttleDB + 13, // FEar + 12, // FBrain + 12, // FMush + 13, // Innsign + 13, // Bldstn + 13, // Fanvil + 8, // FLazStaf + 10, // nest bomb + 13, // half paper + 13, // whole paper + 10, // runes + 12 // teddy bear +}; + +int ItemAnimSnds[ITEMFTYPES] = { + IS_FHARM, // Armor2 + IS_FAXE, // Axe + IS_FPOT, // FBttle + IS_FBOW, // Bow + IS_GOLD, // GoldFlip + IS_FCAP, // Helmet + IS_FSWOR, // Mace + IS_FSHLD, // Shield + IS_FSWOR, // SwrdFlip + IS_FROCK, // Rock + IS_FAXE, // Cleaver + IS_FSTAF, // Staff + IS_FRING, // Ring + IS_FCAP, // Crown + IS_FLARM, // LArmor + IS_FSHLD, // WShield + IS_FSCRL, // Scroll + IS_FHARM, // FPlateAr + IS_FBOOK, // FBook + IS_FLARM, // Food + IS_FPOT, // FBttleBB + IS_FPOT, // FBttleDY + IS_FPOT, // FBttleOR + IS_FPOT, // FBttleBR + IS_FPOT, // FBttleBL + IS_FPOT, // FBttleBY + IS_FPOT, // FBttleWH + IS_FPOT, // FBttleDB + IS_FBODY, // FEar + IS_FBODY, // FBrain + IS_FMUSH, // FMush + IS_ISIGN, // Innsign + IS_FBLST, // Bldstn + IS_FANVL, // Fanvil + IS_FSTAF, // FLazStaf + IS_FROCK, // Bomb + IS_FSCRL, // Half Paper + IS_FSCRL, // Whole Paper + IS_FROCK, // Rune + IS_FMUSH, // Theo +}; + +int ItemInvSnds[ITEMFTYPES] = { + IS_IHARM, // Armor2 + IS_IAXE, // Axe + IS_IPOT, // FBttle + IS_IBOW, // Bow + IS_GOLD, // GoldFlip + IS_ICAP, // Helmet + IS_ISWORD, // Mace + IS_ISHIEL, // Shield + IS_ISWORD, // SwrdFlip + IS_IROCK, // Rock + IS_IAXE, // Cleaver + IS_ISTAF, // Staff + IS_IRING, // Ring + IS_ICAP, // Crown + IS_ILARM, // LArmor + IS_ISHIEL, // WShield + IS_ISCROL, // Scroll + IS_IHARM, // FPlateAr + IS_IBOOK, // FBook + IS_IHARM, // Food + IS_IPOT, // FBttleBB + IS_IPOT, // FBttleDY + IS_IPOT, // FBttleOR + IS_IPOT, // FBttleBR + IS_IPOT, // FBttleBL + IS_IPOT, // FBttleBY + IS_IPOT, // FBttleWH + IS_IPOT, // FBttleDB + IS_IBODY, // FEar + IS_IBODY, // FBrain + IS_IMUSH, // FMush + IS_ISIGN, // Innsign + IS_IBLST, // Bldstn + IS_IANVL, // Fanvil + IS_ISTAF, // FLazStaf + IS_IROCK, // Bomb + IS_ISCROL, // Half Paper + IS_ISCROL, // Whole Paper + IS_IROCK, // Rune + IS_IMUSH // Theo +}; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitItemGFX() { + for (int i = 0; i < ITEMFTYPES; i++) { + char filestr[64]; + sprintf(filestr, "Items\\%s.CEL", ItemFiles[i]); + app_assert(! itemanims[i]); + itemanims[i] = LoadFileInMemSig(filestr,NULL,'IGFX'); + } + + ZeroMemory(UniqueItemFlag,sizeof(UniqueItemFlag)); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL ItemPlace(int xp, int yp) { + if (dMonster[xp][yp] != 0) return FALSE; + if (dPlayer[xp][yp] != 0) return FALSE; + if (dItem[xp][yp] != 0) return FALSE; + if (dObject[xp][yp] != 0) return FALSE; + if (dFlags[xp][yp] & BFLAG_SETPC) return FALSE; + if (nSolidTable[dPiece[xp][yp]]) return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void AddInitItems() { + int j = random(11, 3) + 3; + for (int i = 0; i < j; i++) { + int ii = itemavail[0]; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + + int xx = random(12, DMAXX - DIRTEDGE) + (DIRTEDGED2); + int yy = random(12, DMAXY - DIRTEDGE) + (DIRTEDGED2); + while (! ItemPlace(xx, yy)) { + xx = random(12, DMAXX - DIRTEDGE) + (DIRTEDGED2); + yy = random(12, DMAXY - DIRTEDGE) + (DIRTEDGED2); + } + + item[ii]._ix = xx; + item[ii]._iy = yy; + dItem[xx][yy] = ii + 1; + item[ii]._iSeed = GetRndSeed(); + SetRndSeed(item[ii]._iSeed); + if (random(12, 2)) GetItemAttrs(ii, IDI_HEAL, currlevel); + else GetItemAttrs(ii, IDI_MANA, currlevel); + item[ii]._iCreateInfo = currlevel + ICI_PREGEN; + SetupItem(ii); + item[ii]._iAnimFrame = item[ii]._iAnimLen; + item[ii]._iAnimFlag = FALSE; + item[ii]._iSelFlag = ISEL_FLR; + DeltaAddItem(ii); + numitems++; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitItems() { + int i; + + DROPLOG("Initing items...\n"); + // Setup a gold item + GetItemAttrs(0, 0, 1); + golditem = item[0]; + golditem._iStatFlag = TRUE; + + numitems = 0; + for (i = 0; i < MAXITEMS; i++) { + item[i]._itype = 0; + item[i]._ix = 0; + item[i]._iy = 0; + item[i]._iAnimFlag = FALSE; + item[i]._iSelFlag = ISEL_NONE; + item[i]._iIdentified = FALSE; + item[i]._iPostDraw = FALSE; + } + + for (i = 0; i < MAXITEMS; i++) { + itemavail[i] = i; + itemactive[i] = 0; + } + + if (!setlevel) { + + int rs = GetRndSeed(); + + if (QuestStatus(Q_ROCK)) { + SpawnRock(); + } + if (QuestStatus(Q_ANVIL)) { + SpawnQuestItem(IDI_ANVIL, (setpc_x << 1) + 11 + DIRTEDGED2, (setpc_y << 1) + 11 + DIRTEDGED2, FALSE, ISEL_FLR); + } + if (currlevel > 0 && currlevel < 16) + AddInitItems(); + } + + uitemflag = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CalcPlrItemVals(int p, BOOL Loadgfx) +{ + int mind, maxd, tac, g, d, i, mi; + int bdam, btohit, bac; + int sadd, madd, dadd, vadd; + int fr, lr, mr; + int dmod, ghit, lrad; + int ihp, imana; + int spllvladd; + int enac; + int fmin, fmax, lmin, lmax; + long iflgs, iflgs2; + __int64 spl, t; + + app_assert((DWORD) p < MAX_PLRS); + + mind = 0; + maxd = 0; + tac = 0; + bdam = 0; + btohit = 0; + bac = 0; + iflgs = 0; + iflgs2 = 0; + sadd = 0; + madd = 0; + dadd = 0; + vadd = 0; + spl = 0; + fr = 0; + lr = 0; + mr = 0; + dmod = 0; + ghit = 0; + lrad = PLRLRAD; + ihp = 0; + imana = 0; + spllvladd = 0; + enac = 0; + fmin = 0; + fmax = 0; + lmin = 0; + lmax = 0; + for (i = 0; i < 7; i++) { + const ItemStruct * itm = &plr[p].InvBody[i]; + if (itm->_itype == -1) continue; + if (! itm->_iStatFlag) continue; + + mind += itm->_iMinDam; + maxd += itm->_iMaxDam; + tac += itm->_iAC; + + t = 1; + if (itm->_iSpell != 0) + spl |= t << (itm->_iSpell - 1); + + // don't give benefit of unidentified magic items + if (itm->_iMagical != IMAGIC_NONE && ! itm->_iIdentified) + continue; + + bdam += itm->_iPLDam; + btohit += itm->_iPLToHit; + + if (itm->_iPLAC) { + int tmpac = (itm->_iAC * itm->_iPLAC) / 100; + if (tmpac == 0) tmpac = 1; + bac += tmpac; + } + + iflgs |= itm->_iFlags; + iflgs2 |= itm->_iFlags2; + sadd += itm->_iPLStr; + madd += itm->_iPLMag; + dadd += itm->_iPLDex; + vadd += itm->_iPLVit; + fr += itm->_iPLFR; + lr += itm->_iPLLR; + mr += itm->_iPLMR; + dmod += itm->_iPLDamMod; + ghit += itm->_iPLGetHit; + lrad += itm->_iPLLight; + ihp += itm->_iPLHP; + imana += itm->_iPLMana; + spllvladd += itm->_iSplLvlAdd; + enac += itm->_iPLEnAc; + fmin += itm->_iFMinDam; + fmax += itm->_iFMaxDam; + lmin += itm->_iLMinDam; + lmax += itm->_iLMaxDam; + } + + // If I have no weapons, then make it min of 1-1, if shield only, 1-3 + if (mind == 0 && maxd == 0) { + mind = 1; + maxd = 1; + if ((plr[p].Hand1Item._itype == IT_SHIELD) && (plr[p].Hand1Item._iStatFlag)) + maxd = 3; + if ((plr[p].Hand2Item._itype == IT_SHIELD) && (plr[p].Hand2Item._iStatFlag)) + maxd = 3; + + // monks have fists of fury. + if (plr[p]._pClass == CLASS_MONK) + { + mind = max(mind,plr[p]._pLevel >> 1); + maxd = max(maxd,plr[p]._pLevel); + } + } + + plr[p]._pIMinDam = mind; + plr[p]._pIMaxDam = maxd; + plr[p]._pIAC = tac; + plr[p]._pIBonusDam = bdam; + plr[p]._pIBonusToHit = btohit; + plr[p]._pIBonusAC = bac; + plr[p]._pIFlags = iflgs; + plr[p]._pIFlags2 = iflgs2; + plr[p]._pIBonusDamMod = dmod; + plr[p]._pIGetHit = ghit; + if (lrad < 2) lrad = 2; + if (lrad > 15) lrad = 15; + if ((plr[p]._pLightRad != lrad ) && (p == myplr)) { + ChangeLightRadius(plr[p]._plid, lrad); + if (lrad < 10) ChangeVisionRadius(plr[p]._pvid, 10); + else ChangeVisionRadius(plr[p]._pvid, lrad); + plr[p]._pLightRad = lrad; + } + + plr[p]._pStrength = plr[p]._pBaseStr + sadd; + if (plr[myplr]._pStrength <= 0) plr[myplr]._pStrength = 0; + plr[p]._pMagic = plr[p]._pBaseMag + madd; + if (plr[myplr]._pMagic <= 0) plr[myplr]._pMagic = 0; + plr[p]._pDexterity = plr[p]._pBaseDex + dadd; + if (plr[myplr]._pDexterity <= 0) plr[myplr]._pDexterity = 0; + plr[p]._pVitality = plr[p]._pBaseVit + vadd; + if (plr[myplr]._pVitality <= 0) plr[myplr]._pVitality = 0; + + if (plr[p]._pClass == CLASS_ROGUE) + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200; + else if (plr[p]._pClass == CLASS_MONK) + { + if (plr[p].Hand1Item._itype == IT_STAFF || // bonus for staff + plr[p].Hand2Item._itype == IT_STAFF || + (plr[p].Hand1Item._itype == -1 && // bonus for no weapons. + plr[p].Hand2Item._itype == -1) + ) + { + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 150; + } + else + { + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 300; + } + } + else if (plr[p]._pClass == CLASS_BARD) + { + // GWPif ((plr[p].Hand1Item._itype == IT_SWORD // bonus for single handed swords + // GWP && plr[p].Hand1Item._iLoc != IL_2HAND) + // GWP ||( plr[p].Hand2Item._itype == IT_SWORD + // GWP && plr[p].Hand2Item._iLoc != IL_2HAND) + // GWP ) + if (plr[p].Hand1Item._itype == IT_SWORD // bonus for using a sword. + || plr[p].Hand2Item._itype == IT_SWORD) + { + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200; + } + else if (plr[p].Hand1Item._itype == IT_BOW + || plr[p].Hand2Item._itype == IT_BOW) + { + // Better than a monk or warrior with a bow but not as good as a rogue. + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 250; + } + else + { + plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100; + } + } + else + plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100; + + plr[p]._pISpells = spl; + if ((plr[p]._pRSplType == SPT_ITEM) /*|| plr[p]._pRSplType == SPT_SCROLL)*/ + && ((plr[p]._pISpells & (((__int64)1) << (plr[p]._pRSpell-1))) == 0)) { + plr[p]._pRSpell = -1; + plr[p]._pRSplType = SPT_NONE; + force_redraw = FULLDRAW; + } + plr[p]._pISplLvlAdd = spllvladd; + + plr[p]._pIEnAc = enac; + + if (iflgs & IAF_ZERORES) { + mr = 0; + fr = 0; + lr = 0; + } + if (mr > RESIST_MAX) mr = RESIST_MAX; + plr[p]._pMagResist = mr; + if (fr > RESIST_MAX) fr = RESIST_MAX; + plr[p]._pFireResist = fr; + if (lr > RESIST_MAX) lr = RESIST_MAX; + plr[p]._pLghtResist = lr; + + if (plr[p]._pClass == CLASS_WARRIOR) vadd = vadd << 1; + if (plr[p]._pClass == CLASS_ROGUE || + plr[p]._pClass == CLASS_MONK || + plr[p]._pClass == CLASS_BARD ) vadd += (vadd >> 1); + ihp += (vadd << HP_SHIFT); + if (plr[p]._pClass == CLASS_SORCEROR) madd = madd << 1; + if (plr[p]._pClass == CLASS_ROGUE || + plr[p]._pClass == CLASS_MONK || + plr[p]._pClass == CLASS_BARD ) madd += (madd >> 1); + imana += (madd << MANA_SHIFT); + + plr[p]._pHitPoints = plr[p]._pHPBase + ihp; + plr[p]._pMaxHP = plr[p]._pMaxHPBase + ihp; + if ((p == myplr) && (plr[p]._pHitPoints >> HP_SHIFT) <= 0) + SetPlayerHitPoints(p, 0); + + plr[p]._pMana = plr[p]._pManaBase + imana; + plr[p]._pMaxMana = plr[p]._pMaxManaBase + imana; + + plr[p]._pIFMinDam = fmin; + plr[p]._pIFMaxDam = fmax; + plr[p]._pILMinDam = lmin; + plr[p]._pILMaxDam = lmax; + + + if (iflgs & IAF_INFRAVISION) plr[p]._pInfraFlag = TRUE; + else plr[p]._pInfraFlag = FALSE; + + plr[p]._pBlockFlag = FALSE; + if (plr[p]._pClass == CLASS_MONK) + { + if ((plr[p].Hand1Item._itype == IT_STAFF) && + (plr[p].Hand1Item._iStatFlag)) + { + plr[p]._pBlockFlag = TRUE; + plr[p]._pIFlags |= IAF_BLANIM; + } + + if ((plr[p].Hand2Item._itype == IT_STAFF) && + (plr[p].Hand2Item._iStatFlag)) + { + plr[p]._pBlockFlag = TRUE; + plr[p]._pIFlags |= IAF_BLANIM; + } + + if ((plr[p].Hand1Item._iClass == IC_WEAP) && + (plr[p].Hand1Item._iLoc != IL_2HAND) && + (plr[p].Hand2Item._itype == -1)) + { + plr[p]._pBlockFlag = TRUE; + } + + if ((plr[p].Hand2Item._iClass == IC_WEAP) && + (plr[p].Hand2Item._iLoc != IL_2HAND) && + (plr[p].Hand1Item._itype == -1)) + { + plr[p]._pBlockFlag = TRUE; + } + } +#if defined (HELLFIRE2) + else if (plr[p]._pClass == CLASS_BARD) + { + if ((plr[p].Hand1Item._itype == IT_SWORD) && + (plr[p].Hand1Item._iStatFlag)) + { + plr[p]._pBlockFlag = TRUE; + plr[p]._pIFlags |= IAF_BLANIM; + } + + if ((plr[p].Hand2Item._itype == IT_SWORD) && + (plr[p].Hand2Item._iStatFlag)) + { + plr[p]._pBlockFlag = TRUE; + plr[p]._pIFlags |= IAF_BLANIM; + } + } +#endif + + plr[p]._pwtype = WEAP_H2H; + // Determine which graphics to use + g = PGFX_NGUY; + if ((plr[p].Hand1Item._itype != -1) && + (plr[p].Hand1Item._iClass == IC_WEAP) && + (plr[p].Hand1Item._iStatFlag)) g = plr[p].Hand1Item._itype; + if ((plr[p].Hand2Item._itype != -1) && + (plr[p].Hand2Item._iClass == IC_WEAP) && + (plr[p].Hand2Item._iStatFlag)) g = plr[p].Hand2Item._itype; + switch (g) { + case IT_SWORD: + g = PGFX_XGUY; + break; + case IT_MACE: + g = PGFX_ZGUY; + break; + case IT_BOW: + plr[p]._pwtype = WEAP_RANGE; + g = PGFX_BGUY; + break; + case IT_AXE: + g = PGFX_FGUY; + break; + case IT_STAFF: + g = PGFX_TGUY; + break; + } + if ((plr[p].Hand1Item._itype == IT_SHIELD) && (plr[p].Hand1Item._iStatFlag)) { + plr[p]._pBlockFlag = TRUE; + g++; + } + if ((plr[p].Hand2Item._itype == IT_SHIELD) && (plr[p].Hand2Item._iStatFlag)) { + plr[p]._pBlockFlag = TRUE; + g++; + } + + #if IS_VERSION(RETAIL) || IS_VERSION(BETA) + if ((plr[p].BodyItem._itype == IT_MARMOR) && (plr[p].BodyItem._iStatFlag)) + { + if (plr[p]._pClass == CLASS_MONK) + { + plr[p]._pIAC += plr[p]._pLevel >> 1; // Monks get 1/2 level bonus while wearing light armor. + } + g += 16; + } + else if ((plr[p].BodyItem._itype == IT_HARMOR) && (plr[p].BodyItem._iStatFlag)) + { + g += 32; + } + else + { + if (plr[p]._pClass == CLASS_MONK) + { + plr[p]._pIAC += plr[p]._pLevel << 1; // Monks get 2x level bonus for no armor. + } + } + #endif + + if ((plr[p]._pgfxnum != g) && (Loadgfx)) { + plr[p]._pgfxnum = g; + plr[p]._pGFXLoad = 0; // Clear all graphics loaded flag + LoadPlrGFX(p, PGL_STAND); + SetPlrAnims(p); + d = plr[p]._pdir; + + app_assert(plr[p]._pNAnim[d]); + plr[p]._pAnimData = plr[p]._pNAnim[d]; + plr[p]._pAnimLen = plr[p]._pNFrames; + plr[p]._pAnimFrame = 1; + plr[p]._pAnimCnt = 0; + plr[p]._pAnimDelay = 3; + plr[p]._pAnimWidth = plr[p]._pNWidth; + plr[p]._pAnimWidth2 = (plr[p]._pNWidth - 64) >> 1; + } + else { + plr[p]._pgfxnum = g; + } + + for (i = 0; i < nummissiles; i++) { + mi = missileactive[i]; + if (missile[mi]._mitype == MIT_MANASHIELD && missile[mi]._misource == p) { + missile[mi]._miVar1 = plr[p]._pHitPoints; + missile[mi]._miVar2 = plr[p]._pHPBase; + } + } + + if (plr[p].NeckItem._itype != -1 && plr[p].NeckItem.IDidx == IDI_AURIC) + { + GOLD_VMAX = 10000; + } + else + { + int old_vmax = GOLD_VMAX; + + GOLD_VMAX = 5000; + + if (old_vmax != GOLD_VMAX) + StripTopGold(p); + } + + drawmanaflag = TRUE; + drawhpflag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrScrolls(int p) { + int i; + __int64 t; + + plr[p]._pScrlSpells = 0; + for (i = 0; i < plr[p]._pNumInv; i++) { + if (plr[p].InvList[i]._itype != -1) { + if (((plr[p].InvList[i]._iMiscId == IMID_SCROLL) || + (plr[p].InvList[i]._iMiscId == IMID_TSCROLL)) && + (plr[p].InvList[i]._iStatFlag)) { + t = 1; + plr[p]._pScrlSpells |= (t << plr[p].InvList[i]._iSpell-1); + } + } + } + for (i = 0; i < MAXSPD; i++) { + if (plr[p].SpdList[i]._itype != -1) { + if (((plr[p].SpdList[i]._iMiscId == IMID_SCROLL) || + (plr[p].SpdList[i]._iMiscId == IMID_TSCROLL)) && + (plr[p].SpdList[i]._iStatFlag)) { + t = 1; + plr[p]._pScrlSpells |= (t << plr[p].SpdList[i]._iSpell-1); + } + } + } + + if ((plr[p]._pRSplType == SPT_SCROLL) + && ((plr[p]._pScrlSpells & (1 << (plr[p]._pRSpell-1))) == 0)) { + plr[p]._pRSpell = -1; + plr[p]._pRSplType = SPT_NONE; + force_redraw = FULLDRAW; + } + +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrStaff(int p) { + plr[p]._pISpells = 0; + if (plr[p].Hand1Item._itype == -1) return; + if (!plr[p].Hand1Item._iStatFlag) return; + if (plr[p].Hand1Item._iCharges > 0) { + __int64 t = 1; + plr[p]._pISpells |= t << (plr[p].Hand1Item._iSpell - 1); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcSelfItems(int pnum) { + int i; + ItemStruct * pi; + PlayerStruct * p = &plr[pnum]; + BOOL sf, changeflag; + int sa = 0; + int ma = 0; + int da = 0; + + // assume everything works, and calc potential + to str, mag, dex + pi = &p->InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) { + if (pi->_itype == -1) continue; + pi->_iStatFlag = TRUE; + if (!pi->_iIdentified) continue; + sa += pi->_iPLStr; + ma += pi->_iPLMag; + da += pi->_iPLDex; + } + + do { + changeflag = FALSE; + pi = &p->InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) { + if (pi->_itype == -1) continue; + if (!pi->_iStatFlag) continue; + sf = TRUE; + if ((p->_pBaseStr + sa) < pi->_iMinStr) sf = FALSE; + if ((p->_pBaseMag + ma) < pi->_iMinMag) sf = FALSE; + if ((p->_pBaseDex + da) < pi->_iMinDex) sf = FALSE; + if (!sf) { + changeflag = TRUE; + pi->_iStatFlag = FALSE; + if (pi->_iIdentified) { + sa -= pi->_iPLStr; + ma -= pi->_iPLMag; + da -= pi->_iPLDex; + } + } + } + } while (changeflag); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static BOOL ItemMinStats(const PlayerStruct * p,const ItemStruct * x) { + if (p->_pMagic < (byte)x->_iMinMag) return FALSE; + if (p->_pStrength < x->_iMinStr) return FALSE; + if (p->_pDexterity < x->_iMinDex) return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrItemMin(int pnum) { + int i; + ItemStruct * pi; + PlayerStruct * p = &plr[pnum]; + + // handle inventory + pi = &p->InvList[0]; + for (i = p->_pNumInv; i--; pi++) + pi->_iStatFlag = ItemMinStats(p,pi); + + // handle speedbar + pi = &p->SpdList[0]; + for (i = MAXSPD; i--; pi++) { + if (pi->_itype == -1) continue; + pi->_iStatFlag = ItemMinStats(p,pi); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrBookVals(int p) +{ + int i, slvl; + + void WitchBookLevel(int); + if (currlevel == 0) { + for (i = 1; witchitem[i]._itype != -1; i++) + WitchBookLevel(i); + } + + for (i = 0; i < plr[p]._pNumInv; i++) { + if ((plr[p].InvList[i]._itype == IT_MISC) && (plr[p].InvList[i]._iMiscId == IMID_BOOK)) { + plr[p].InvList[i]._iMinMag = spelldata[plr[p].InvList[i]._iSpell].sMinInt; + slvl = plr[p]._pSplLvl[plr[p].InvList[i]._iSpell]; + while (slvl != 0) { + plr[p].InvList[i]._iMinMag += ((plr[p].InvList[i]._iMinMag * 20) / 100); + slvl--; + if ((plr[p].InvList[i]._iMinMag + ((plr[p].InvList[i]._iMinMag * 20) / 100)) > 255) { + plr[p].InvList[i]._iMinMag = 255; + slvl = 0; + } + } + plr[p].InvList[i]._iStatFlag = ItemMinStats(&plr[p], &plr[p].InvList[i]); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrInv(int p, BOOL Loadgfx) { + CalcPlrItemMin(p); + CalcSelfItems(p); + CalcPlrItemVals(p, Loadgfx); + CalcPlrItemMin(p); + if (p == myplr) { + CalcPlrBookVals(p); + CalcPlrScrolls(p); + CalcPlrStaff(p); + } + if ((p == myplr) && (currlevel == 0)) RecalcStoreStats(); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPlrHandItem(ItemStruct *h, int idata) { + const ItemDataStruct * pAllItem = &AllItemsList[idata]; + + ZeroMemory(h,sizeof(ItemStruct)); + h->_itype = pAllItem->itype; + h->_iCurs = pAllItem->iCurs; + strcpy(h->_iName, pAllItem->iName); + strcpy(h->_iIName, pAllItem->iName); + h->_iLoc = pAllItem->iLoc; + h->_iClass = pAllItem->iClass; + h->_iMinDam = pAllItem->iMinDam; + h->_iMaxDam = pAllItem->iMaxDam; + h->_iAC = pAllItem->iMinAC; + h->_iMiscId = pAllItem->iMiscId; + h->_iSpell = pAllItem->iSpell; + if (pAllItem->iMiscId == IMID_STAFF) h->_iCharges = 18; // was 40 + h->_iMaxCharges = h->_iCharges; + h->_iDurability = pAllItem->iDurability; + h->_iMaxDur = pAllItem->iDurability; + h->_iMinStr = pAllItem->iMinStr; + h->_iMinMag = pAllItem->iMinMag; + h->_iMinDex = pAllItem->iMinDex; + h->_ivalue = pAllItem->iValue; + h->_iIvalue = pAllItem->iValue; + h->_iPrePower = -1; + h->_iSufPower = -1; + h->IDidx = idata; + h->_iMagical = IMAGIC_NONE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GetPlrHandSeed(ItemStruct *h) +{ + h->_iSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GetGoldSeed(int pnum, ItemStruct *h) +{ + int i, ii, s; + BOOL doneflag; + + do { + doneflag = TRUE; + s = GetRndSeed(); + for (i = 0; i < numitems; i++) { + ii = itemactive[i]; + if (item[ii]._iSeed == s) doneflag = FALSE; + } + if (pnum == myplr) { + for (i = 0; i < plr[pnum]._pNumInv; i++) + if (plr[pnum].InvList[i]._iSeed == s) doneflag = FALSE; + } + } while (!doneflag); + h->_iSeed = s; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPlrHandSeed(ItemStruct *h, int iseed) +{ + h->_iSeed = iseed; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPlrHandGoldCurs(ItemStruct *h) +{ + if (h->_ivalue >= GOLD_VT2) { + h->_iCurs = ITEM_5GOLD; + } else { + if (h->_ivalue <= GOLD_VT1) h->_iCurs = ITEM_1GOLD; + else h->_iCurs = ITEM_3GOLD; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CreatePlrItems(int p) { + int i; + ItemStruct * pi; + + // zero out carried items + pi = &plr[p].InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) + pi->_itype = -1; + + // zero inventory + ZeroMemory(plr[p].InvGrid,sizeof(plr[p].InvGrid)); + pi = &plr[p].InvList[0]; + for (i = MAXINV; i--; pi++) + pi->_itype = -1; + plr[p]._pNumInv = 0; + + // zero speedbar + pi = &plr[p].SpdList[0]; + for (i = MAXSPD; i--; pi++) + pi->_itype = -1; + + switch (plr[p]._pClass) { + case CLASS_WARRIOR : + // Sword in left + SetPlrHandItem(&plr[p].Hand1Item, IDI_WARRIOR); + GetPlrHandSeed(&plr[p].Hand1Item); + + // Shield in right + SetPlrHandItem(&plr[p].Hand2Item, IDI_WARRSHLD); + GetPlrHandSeed(&plr[p].Hand2Item); + +#if CHEATS + if (!davecheat) { + SetPlrHandItem(&plr[p].HoldItem, IDI_WARRCLUB); + GetPlrHandSeed(&plr[p].HoldItem); + AutoPlace(p, 0, 1, 3, TRUE); + } +#else + // Club in inv + SetPlrHandItem(&plr[p].HoldItem, IDI_WARRCLUB); + GetPlrHandSeed(&plr[p].HoldItem); + AutoPlace(p, 0, 1, 3, TRUE); +#endif + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + break; + + case CLASS_ROGUE : + #if !IS_VERSION(SHAREWARE) + // Bow in both hands + SetPlrHandItem(&plr[p].Hand1Item, IDI_ROGUE); + GetPlrHandSeed(&plr[p].Hand1Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + case CLASS_SORCEROR : + #if !IS_VERSION(SHAREWARE) + // Staff in both hands + SetPlrHandItem(&plr[p].Hand1Item, IDI_SORCEROR); + GetPlrHandSeed(&plr[p].Hand1Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); // was mana + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); // was mana + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + case CLASS_MONK : + #if !IS_VERSION(SHAREWARE) + // Bow in both hands + SetPlrHandItem(&plr[p].Hand1Item, IDI_MONK); + GetPlrHandSeed(&plr[p].Hand1Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + case CLASS_BARD : + #if !IS_VERSION(SHAREWARE) + // Bow in both hands + SetPlrHandItem(&plr[p].Hand1Item, IDI_BARD); + GetPlrHandSeed(&plr[p].Hand1Item); + SetPlrHandItem(&plr[p].Hand2Item, IDI_BARDDAGGER); + GetPlrHandSeed(&plr[p].Hand2Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + } + + SetPlrHandItem(&plr[p].HoldItem, IDI_GOLD); + GetPlrHandSeed(&plr[p].HoldItem); +#if CHEATS + if (!davecheat) { + // 100 Gold + plr[p].HoldItem._ivalue = 100; + plr[p].HoldItem._iCurs = ITEM_1GOLD; + plr[p]._pGold = plr[p].HoldItem._ivalue; + i = plr[p]._pNumInv; + plr[p].InvList[i] = plr[p].HoldItem; + plr[p]._pNumInv++; + plr[p].InvGrid[30] = plr[p]._pNumInv; + } + else { + // 200000 Gold + plr[p].HoldItem._ivalue = 5000; + plr[p].HoldItem._iCurs = ITEM_5GOLD; + plr[p]._pGold = 200000; + for (int j = 0; j < 40; j++) { + GetGoldSeed(p, &plr[p].HoldItem); + i = plr[p]._pNumInv; + plr[p].InvList[i] = plr[p].HoldItem; + plr[p]._pNumInv++; + plr[p].InvGrid[j] = plr[p]._pNumInv; + } + } +#else + // 100 Gold + plr[p].HoldItem._ivalue = 100; + plr[p].HoldItem._iCurs = ITEM_1GOLD; + plr[p]._pGold = plr[p].HoldItem._ivalue; + i = plr[p]._pNumInv; + plr[p].InvList[i] = plr[p].HoldItem; + plr[p]._pNumInv++; + plr[p].InvGrid[30] = plr[p]._pNumInv; +#endif + + CalcPlrItemVals(p,FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL ItemSpaceOk(int i, int j) +{ + int pn, oi; + + if ((i < 0) || (i >= DMAXX) || (j < 0) || (j >= DMAXY)) return(FALSE); + if (dMonster[i][j] != 0) return(FALSE); + if (dPlayer[i][j] != 0) return(FALSE); + if (dItem[i][j] != 0) return(FALSE); + if (dObject[i][j] != 0) { + if (dObject[i][j] > 0) oi = dObject[i][j]-1; + else oi = -(dObject[i][j]+1); + if (object[oi]._oSolidFlag) return(FALSE); + } + if (dObject[i+1][j+1] > 0) { + oi = dObject[i+1][j+1]-1; + if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE); + } + if (dObject[i+1][j+1] < 0) { + oi = -(dObject[i+1][j+1]+1); + if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE); + } + if ((dObject[i+1][j] > 0) && (dObject[i][j+1] > 0)) { + oi = dObject[i+1][j]-1; + if (object[oi]._oSelFlag != OSEL_NONE) { + oi = dObject[i][j+1]-1; + if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE); + } + } + pn = dPiece[i][j]; + if (nSolidTable[pn]) return(FALSE); + return(TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +void DaveISpaceOk(int inum) +{ + int i,j; + + for (j = 0; j < MAXDUNY; j++) { + for (i = 0; i < MAXDUNX; i++) { + if (dItem[i][j] == inum+1) + app_fatal("Item in map already"); + } + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL GetItemSpace(int x, int y, char inum) +{ + int i,j,xx,yy,rs; + BOOL savail; + + // Try surrounding squares + yy = 0; + for (j = (y-1); j <= (y+1); j++) { + xx = 0; + for (i = (x-1); i <= (x+1); i++) { + itemhold[xx][yy] = ItemSpaceOk(i,j); + xx++; + } + yy++; + } + + savail = FALSE; + for (yy = 0; yy < 3; yy++) { + for (xx = 0; xx < 3; xx++) { + if (itemhold[xx][yy]) savail = TRUE; + } + } + + // Must go here so same number of rnd calls on multiplayer machines + rs = random(13, 15) + 1; + + // No fit, no good + if (!savail) return(FALSE); + + // Place item + xx = 0; + yy = 0; + while (rs > 0) { + if (itemhold[xx][yy]) rs--; + if (rs > 0) { + xx++; + if (xx == 3) { + xx = 0; + yy++; + if (yy == 3) yy = 0; + } + } + } + xx = xx + x - 1; + yy = yy + y - 1; + item[inum]._ix = xx; + item[inum]._iy = yy; + //DaveISpaceOk(inum); + dItem[xx][yy] = inum + 1; + return(TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetSuperItemSpace(int x, int y, char inum) +{ + // try normal method first + if (GetItemSpace(x, y, inum)) return; + + int xx, yy; + + // radial search outward until a space is found + for (int l = 2; l < 50; l++) { + for (int j = -l; j <= l; j++) { + yy = y + j; + for (int i = -l; i <= l; i++) { + xx = x + i; + if (! ItemSpaceOk(xx,yy)) continue; + + // drop it + item[inum]._ix = xx; + item[inum]._iy = yy; + //DaveISpaceOk(inum); + dItem[xx][yy] = inum + 1; + return; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetSuperItemLoc(int x, int y, int &xx, int &yy) +{ + // radial search outward until a space is found + for (int l = 1; l < 50; l++) { + for (int j = -l; j <= l; j++) { + yy = y + j; + for (int i = -l; i <= l; i++) { + xx = x + i; + if (ItemSpaceOk(xx,yy)) // found it + return; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CalcItemValue(int i) +{ + int v = item[i]._iVMult1 + item[i]._iVMult2; + if (v > 0) v = item[i]._ivalue * v; + if (v < 0) v = item[i]._ivalue / v; + v += item[i]._iVAdd1 + item[i]._iVAdd2; + if (v <= 0) v = 1; + item[i]._iIvalue = v; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetBookSpell(int i, int lvl) +{ + + if (lvl == 0) lvl = 1; + int rv = random(14, SPL_LAST) + 1; + + #if IS_VERSION(SHAREWARE) + if (lvl > 5) lvl = 5; + #endif + + int bs = SPL_FIREBOLT; + int s = SPL_FIREBOLT; + while (rv > 0) { + if ((spelldata[s].sBookLvl != -1) && (lvl >= spelldata[s].sBookLvl)) { + rv--; + bs = s; + } + + s++; + if ((gbMaxPlayers == 1) && (s == SPL_RESURRECT)) s++; + if ((gbMaxPlayers == 1) && (s == SPL_HEALOTHER)) s++; + if (s == SPL_LAST) s = SPL_FIREBOLT; + } + strcat(item[i]._iName, spelldata[bs].sNameText); + strcat(item[i]._iIName, spelldata[bs].sNameText); + item[i]._iSpell = bs; + item[i]._iMinMag = spelldata[bs].sMinInt; + item[i]._ivalue += spelldata[bs].sBookCost; + item[i]._iIvalue += spelldata[bs].sBookCost; + if (spelldata[bs].sType == ST_FIRE) item[i]._iCurs = ITEM_BOOK3; + if (spelldata[bs].sType == ST_LIGHT) item[i]._iCurs = ITEM_BOOK; + if (spelldata[bs].sType == ST_MISC) item[i]._iCurs = ITEM_BOOK2; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetStaffPower(int i, int lvl, int bs, BOOL onlygood) +{ + int pre; + int l[256], nl; + int j, aii; + int preidx; + char istr[128]; + BOOL addok; + + // Prefix only (for a staff w/ spell) + pre = random(15, 10); + + preidx = -1; + +#if CHEATS + if ((pre == 0) || (cheatflag) || (onlygood)) { +#else + if ((pre == 0) || (onlygood)) { +#endif + nl = 0; + for (j = 0; PL_Prefix[j].PLPower != -1; j++) { + if (((PL_Prefix[j].PLIType & PLF_STAFF) != 0) && (PL_Prefix[j].PLMinLvl <= lvl)) { + addok = TRUE; + if ((onlygood) && (!PL_Prefix[j].PLOk)) addok = FALSE; + + if (addok) { + l[nl] = j; + nl++; + if (PL_Prefix[j].PLDouble) { + l[nl] = j; + nl++; + } + } + } + } + if (nl != 0) { + preidx = l[random(16, nl)]; + sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); + strcpy(item[i]._iIName, istr); + item[i]._iMagical = IMAGIC_MAGIC; + SaveItemPower(i, PL_Prefix[preidx].PLPower, PL_Prefix[preidx].PLParam1, PL_Prefix[preidx].PLParam2, PL_Prefix[preidx].PLMinVal, PL_Prefix[preidx].PLMaxVal, PL_Prefix[preidx].PLMultVal); + item[i]._iPrePower = PL_Prefix[preidx].PLPower; + } + } + if (!InfoFit(item[i]._iIName)) { + aii = item[i].IDidx; + strcpy(item[i]._iIName, AllItemsList[aii].iSName); + if (preidx != -1) { + sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); + strcpy(item[i]._iIName, istr); + } + sprintf(istr, "%s of %s", item[i]._iIName, spelldata[bs].sNameText); + strcpy(item[i]._iIName, istr); + if (!item[i]._iMagical) strcpy(item[i]._iName, item[i]._iIName); + } + CalcItemValue(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetStaffSpell(int i, int lvl, BOOL onlygood) +{ + int rv, s, bs, l; + char tstr[64]; + int maxc, minc; + + if (random(17, 4) == 0) GetItemPower(i, lvl >> 1, lvl, PLF_STAFF, onlygood); + else { + l = lvl >> 1; + if (l == 0) l = 1; + rv = random(18, SPL_LAST) + 1; + + #if IS_VERSION(SHAREWARE) + if (lvl > 10) lvl = 10; + #endif + + s = SPL_FIREBOLT; + while (rv > 0) { + if ((spelldata[s].sStaffLvl != -1) && (l >= spelldata[s].sStaffLvl)) { + rv--; + bs = s; + } + s++; + if ((gbMaxPlayers == 1) && (s == SPL_RESURRECT)) s++; + if ((gbMaxPlayers == 1) && (s == SPL_HEALOTHER)) s++; + if (s == SPL_LAST) s = SPL_FIREBOLT; + } + sprintf(tstr, "%s of %s", item[i]._iName, spelldata[bs].sNameText); + //Check to see if string will fit + if (!InfoFit(tstr)) { + sprintf(tstr, "Staff of %s", spelldata[bs].sNameText); + } + strcpy(item[i]._iName, tstr); + strcpy(item[i]._iIName, tstr); + item[i]._iSpell = bs; + minc = spelldata[bs].sStaffMin; + maxc = spelldata[bs].sStaffMax; + item[i]._iCharges = random(19, maxc-minc+1) + minc; + item[i]._iMaxCharges = item[i]._iCharges; + item[i]._iMinMag = spelldata[bs].sMinInt; + int v = (spelldata[bs].sStaffCost * item[i]._iCharges) / 5; + item[i]._ivalue += v; + item[i]._iIvalue += v; + GetStaffPower(i, lvl, bs, onlygood); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetOilType(int i, int lvl) +{ + int n, ro, roi, j; + char OilIndexList[30]; + + if (gbMaxPlayers == 1) { + if (lvl == 0) lvl = 1; + n = 0; + for (j=0; j < MAXOIL; j++) { + if (OilLvlTbl[j] <= lvl) { + OilIndexList[n] = j; + n++; + } + } + ro = random(165, n); + roi = OilIndexList[ro]; + } else { + ro = random(165, 2); + if (ro == 0) roi = 5; + else roi = 6; + } + + strcpy(item[i]._iName, OilStr[roi]); + strcpy(item[i]._iIName, OilStr[roi]); + item[i]._iMiscId = OilIdVal[roi]; + item[i]._ivalue = OilValue[roi]; + item[i]._iIvalue = OilValue[roi]; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetItemAttrs(int i, int idata, int lvl) +{ + int rndv; + + item[i]._itype = AllItemsList[idata].itype; + item[i]._iCurs = AllItemsList[idata].iCurs; + strcpy(item[i]._iName, AllItemsList[idata].iName); + strcpy(item[i]._iIName, AllItemsList[idata].iName); + item[i]._iLoc = AllItemsList[idata].iLoc; + item[i]._iClass = AllItemsList[idata].iClass; + item[i]._iMinDam = AllItemsList[idata].iMinDam; + item[i]._iMaxDam = AllItemsList[idata].iMaxDam; + item[i]._iAC = random(20, AllItemsList[idata].iMaxAC - AllItemsList[idata].iMinAC + 1) + AllItemsList[idata].iMinAC; + item[i]._iFlags = AllItemsList[idata].iFlags; + item[i]._iFlags2 = 0; + item[i]._iMiscId = AllItemsList[idata].iMiscId; + item[i]._iSpell = AllItemsList[idata].iSpell; + item[i]._iMagical = IMAGIC_NONE; + + item[i]._ivalue = AllItemsList[idata].iValue; + item[i]._iIvalue = AllItemsList[idata].iValue; + + item[i]._iVAdd1 = 0; + item[i]._iVMult1 = 0; + item[i]._iVAdd2 = 0; + item[i]._iVMult2 = 0; + + item[i]._iPLDam = 0; + item[i]._iPLToHit = 0; + item[i]._iPLAC = 0; + + item[i]._iPLStr = 0; + item[i]._iPLMag = 0; + item[i]._iPLDex = 0; + item[i]._iPLVit = 0; + + item[i]._iCharges = 0; + item[i]._iMaxCharges = 0; + + item[i]._iDurability = AllItemsList[idata].iDurability; + item[i]._iMaxDur = AllItemsList[idata].iDurability; + item[i]._iMinStr = AllItemsList[idata].iMinStr; + item[i]._iMinMag = AllItemsList[idata].iMinMag; + item[i]._iMinDex = AllItemsList[idata].iMinDex; + + item[i]._iPLFR = 0; + item[i]._iPLLR = 0; + item[i]._iPLMR = 0; + + item[i].IDidx = idata; + + item[i]._iPLDamMod = 0; + item[i]._iPLGetHit = 0; + item[i]._iPLLight = 0; + + item[i]._iSplLvlAdd = 0; + + item[i]._iRequest = FALSE; + + item[i]._iFMinDam = 0; + item[i]._iFMaxDam = 0; + item[i]._iLMinDam = 0; + item[i]._iLMaxDam = 0; + + item[i]._iPLEnAc = 0; + + item[i]._iPLMana = 0; + item[i]._iPLHP = 0; + + item[i]._iPrePower = -1; + item[i]._iSufPower = -1; + item[i]._iFlags = 0; + item[i]._iFlags2 = 0; + + if (item[i]._iMiscId == IMID_BOOK) GetBookSpell(i, lvl); + + if (item[i]._iMiscId == IMID_OIL) GetOilType(i, lvl); + + if (item[i]._itype == IT_GOLD) { + if (gnDifficulty == D_NORMAL) + rndv = (currlevel * 5) + random(21, currlevel * 10); + if (gnDifficulty == D_NIGHTMARE) + rndv = ((currlevel + 16) * 5) + random(21, (currlevel + 16) * 10); + if (gnDifficulty == D_HELL) + rndv = ((currlevel + 32) * 5) + random(21, (currlevel + 32) * 10); + if (leveltype == 4) rndv += (rndv >> 3); + if (rndv > 5000) rndv = 5000; + item[i]._ivalue = rndv; + if (rndv >= GOLD_VT2) { + item[i]._iCurs = ITEM_5GOLD; + } else { + if (rndv <= GOLD_VT1) item[i]._iCurs = ITEM_1GOLD; + else item[i]._iCurs = ITEM_3GOLD; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndPL(int param1, int param2) +{ + return(random(22, param2 - param1 + 1) + param1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PLVal(int pv, int p1, int p2, int minv, int maxv) +{ + if (p1 == p2) return(minv); + if (minv == maxv) return(minv); + return((((((pv - p1) * 100) / (p2 - p1)) * (maxv - minv)) / 100) + minv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SaveItemPower(int i, int power, int param1, int param2, int minval, int maxval, int multval) +{ + int r, r2; + + r = RndPL(param1, param2); + switch (power) { + case PL_TOHIT: + item[i]._iPLToHit += r; + break; + case PL_NTOHIT: + item[i]._iPLToHit -= r; + break; + case PL_TODAM: + item[i]._iPLDam += r; + break; + case PL_NTODAM: + item[i]._iPLDam -= r; + break; + case PL_DOPPEL: + item[i]._iFlags2 |= IAF2_CLONE; + // fall through + case PL_DAHT: + r = RndPL(param1, param2); + item[i]._iPLDam += r; + if (param1 == 20) r2 = RndPL(1, 5); + if (param1 == 36) r2 = RndPL(6, 10); + if (param1 == 51) r2 = RndPL(11, 15); + if (param1 == 66) r2 = RndPL(16, 20); + if (param1 == 81) r2 = RndPL(21, 30); + if (param1 == 96) r2 = RndPL(31, 40); + if (param1 == 111) r2 = RndPL(41, 50); + if (param1 == 126) r2 = RndPL(51, 75); + if (param1 == 151) r2 = RndPL(76, 100); + item[i]._iPLToHit += r2; + break; + + case PL_NDAHT: + item[i]._iPLDam -= r; + if (param1 == 25) r2 = RndPL(1, 5); + if (param1 == 50) r2 = RndPL(6, 10); + item[i]._iPLToHit -= r2; + break; + case PL_AC: + item[i]._iPLAC += r; + break; + case PL_NAC: + item[i]._iPLAC -= r; + break; + case PL_ACTUALAC: + item[i]._iAC = r; + break; + case PL_NACTULAC: + item[i]._iAC -= r; + break; + case PL_RFIRE: + item[i]._iPLFR += r; + break; + case PL_RLGHT: + item[i]._iPLLR += r; + break; + case PL_RMAG: + item[i]._iPLMR += r; + break; + case PL_RALL: + item[i]._iPLFR += r; + item[i]._iPLLR += r; + item[i]._iPLMR += r; + if (item[i]._iPLFR < 0) item[i]._iPLFR = 0; + if (item[i]._iPLLR < 0) item[i]._iPLLR = 0; + if (item[i]._iPLMR < 0) item[i]._iPLMR = 0; + break; + case PL_SLVL: + item[i]._iSplLvlAdd = r; + break; + case PL_CHRG : + item[i]._iCharges = item[i]._iCharges * param1; + item[i]._iMaxCharges = item[i]._iCharges; + break; + case PL_SPELL : + item[i]._iSpell = param1; + item[i]._iCharges = param2; + item[i]._iMaxCharges = param2; + break; + case PL_FHIT: + item[i]._iFlags |= IAF_FIREHIT; + item[i]._iFlags &= ~IAF_LIGHTHIT; + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 0; + item[i]._iLMaxDam = 0; + break; + case PL_LHIT: + item[i]._iFlags |= IAF_LIGHTHIT; + item[i]._iFlags &= ~IAF_FIREHIT; + item[i]._iLMinDam = param1; + item[i]._iLMaxDam = param2; + item[i]._iFMinDam = 0; + item[i]._iFMaxDam = 0; + break; + case PL_STR: + item[i]._iPLStr += r; + break; + case PL_NSTR: + item[i]._iPLStr -= r; + break; + case PL_MAG: + item[i]._iPLMag += r; + break; + case PL_NMAG: + item[i]._iPLMag -= r; + break; + case PL_DEX: + item[i]._iPLDex += r; + break; + case PL_NDEX: + item[i]._iPLDex -= r; + break; + case PL_VIT: + item[i]._iPLVit += r; + break; + case PL_NVIT: + item[i]._iPLVit -= r; + break; + case PL_STATS: + item[i]._iPLStr += r; + item[i]._iPLMag += r; + item[i]._iPLDex += r; + item[i]._iPLVit += r; + break; + case PL_NSTATS: + item[i]._iPLStr -= r; + item[i]._iPLMag -= r; + item[i]._iPLDex -= r; + item[i]._iPLVit -= r; + break; + case PL_GETHIT: + item[i]._iPLGetHit += r; + break; + case PL_NGETHIT: + item[i]._iPLGetHit -= r; + break; + case PL_HP: + item[i]._iPLHP += (r << HP_SHIFT); + break; + case PL_NHP: + item[i]._iPLHP -= (r << HP_SHIFT); + break; + case PL_MANA: + item[i]._iPLMana += (r << MANA_SHIFT); + drawmanaflag = TRUE; + break; + case PL_NMANA: + item[i]._iPLMana -= (r << MANA_SHIFT); + drawmanaflag = TRUE; + break; + case PL_DUR: + r2 = (item[i]._iMaxDur * r) / 100; + item[i]._iMaxDur += r2; + item[i]._iDurability += r2; + break; + case PL_FRAGILE: + item[i]._iPLDam += 140 + r * 2; + // fall through + case PL_NDUR: + r2 = (item[i]._iMaxDur * r) / 100; + item[i]._iMaxDur -= r2; + if (item[i]._iMaxDur < 1) item[i]._iMaxDur = 1; + item[i]._iDurability = item[i]._iMaxDur; + break; + case PL_IND: + item[i]._iDurability = INFINITE_DUR; + item[i]._iMaxDur = INFINITE_DUR; + break; + case PL_LIGHT: + item[i]._iPLLight += param1; + break; + case PL_NLIGHT: + item[i]._iPLLight -= param1; + break; + case PL_NUMARWS: + item[i]._iFlags |= IAF_RABID; // unused -> multimissile --donald + break; + case PL_FARROW: + item[i]._iFlags |= IAF_FIREARROW; + item[i]._iFlags &= ~IAF_LARROW; + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 0; + item[i]._iLMaxDam = 0; + break; + case PL_LARROW: + item[i]._iFlags |= IAF_LARROW; + item[i]._iFlags &= ~IAF_FIREARROW; + item[i]._iLMinDam = param1; + item[i]._iLMaxDam = param2; + item[i]._iFMinDam = 0; + item[i]._iFMaxDam = 0; + break; + case PL_HITADD: // usurped for fireball arrows... + item[i]._iFlags |= (IAF_LARROW | IAF_FIREARROW); + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 0; + item[i]._iLMaxDam = 0; + break; + case PL_THORN: + item[i]._iFlags |= IAF_THORN; + break; + case PL_LMANA: + item[i]._iFlags |= IAF_LMANA; + drawmanaflag = TRUE; + break; + case PL_NOHEAL: + item[i]._iFlags |= IAF_NOHEAL; + break; + case PL_TRAPDAM: + item[i]._iFlags |= IAF_TRAPDAM; + break; + case PL_BEAR: + item[i]._iFlags |= IAF_KNOCKBACK; + break; + case PL_DAMDEMON: + item[i]._iFlags |= IAF_DAMDEMON; + break; + case PL_ZERORES: + item[i]._iFlags |= IAF_ZERORES; + break; + case PL_MNOHEAL: + item[i]._iFlags |= IAF_MNOHEAL; + break; + case PL_BAT: + if (param1 == 3) item[i]._iFlags |= IAF_BAT10; + if (param1 == 5) item[i]._iFlags |= IAF_BAT20; + drawmanaflag = TRUE; + break; + case PL_LEECH: + if (param1 == 3) item[i]._iFlags |= IAF_LEECH10; + if (param1 == 5) item[i]._iFlags |= IAF_LEECH20; + drawhpflag = TRUE; + break; + case PL_ENAC: + item[i]._iPLEnAc = param1; + break; + case PL_ATANIM: + if (param1 == 1) item[i]._iFlags |= IAF_ATANIM1; + if (param1 == 2) item[i]._iFlags |= IAF_ATANIM2; + if (param1 == 3) item[i]._iFlags |= IAF_ATANIM3; + if (param1 == 4) item[i]._iFlags |= IAF_ATANIM4; + break; + case PL_HTANIM: + if (param1 == 1) item[i]._iFlags |= IAF_HTANIM1; + if (param1 == 2) item[i]._iFlags |= IAF_HTANIM2; + if (param1 == 3) item[i]._iFlags |= IAF_HTANIM3; + break; + case PL_BLANIM: + item[i]._iFlags |= IAF_BLANIM; + break; + case PL_DAMADD: + item[i]._iPLDamMod += r; + break; + case PL_RNDARW: + item[i]._iFlags |= IAF_RNDARROW; + break; + case PL_DAMAGE: + item[i]._iMinDam = param1; + item[i]._iMaxDam = param2; + break; + case PL_DURNUM: + item[i]._iDurability = param1; + item[i]._iMaxDur = param1; + break; + case PL_FALCON: + item[i]._iFlags |= IAF_ATANIM3; + break; + case PL_ONEHAND: + item[i]._iLoc = IL_HAND; + break; + case PL_CONST: + item[i]._iFlags |= IAF_CONSTRICT; + break; + case PL_SKING: + item[i]._iFlags |= IAF_SKING; + break; + case PL_INFRA: + item[i]._iFlags |= IAF_INFRAVISION; + break; + case PL_NSTRREQ: + item[i]._iMinStr = 0; + break; + case PL_GFX: + item[i]._iCurs = param1; + break; + case PL_HARQUN: // usurped for lightning arrows + item[i]._iFlags |= (IAF_LARROW | IAF_FIREARROW); + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 1; + item[i]._iLMaxDam = 0; +#if 0 + //rjs item[i]._iPLHP = (byte)plr[myplr]._pArmorClass + plr[myplr]._pIBonusAC + plr[myplr]._pIAC; + item[i]._iPLHP = plr[myplr]._pIBonusAC + plr[myplr]._pIAC; + item[i]._iPLHP += (plr[myplr]._pDexterity / 5); + item[i]._iPLHP = item[i]._iPLHP << HP_SHIFT; +#endif + break; + case PL_HARQUN2: + item[i]._iFlags |= (IAF_LIGHTHIT | IAF_FIREHIT); + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 2; + item[i]._iLMaxDam = 0; +// item[i]._iAC += ((plr[myplr]._pMaxManaBase >> MANA_SHIFT) / 10); + break; + case PL_HARQUN3: + item[i]._iPLFR = 30 - plr[myplr]._pLevel; + if (item[i]._iPLFR < 0) item[i]._iPLFR = 0; + break; + case PL_NRFIRE: + item[i]._iPLFR -= r; + break; + case PL_NRLGHT: + item[i]._iPLLR -= r; + break; + case PL_NRMAG: + item[i]._iPLMR -= r; + break; + case PL_NRALL: + item[i]._iPLFR -= r; + item[i]._iPLLR -= r; + item[i]._iPLMR -= r; + break; + case PL_DEVAST: + item[i]._iFlags2 |= IAF2_DEVASTATION; + break; + case PL_DECAY: + item[i]._iFlags2 |= IAF2_DECAY; + item[i]._iPLDam += r; + break; + case PL_PERIL: + item[i]._iFlags2 |= IAF2_PERIL; + break; + case PL_RNDDAM: + item[i]._iFlags2 |= IAF2_JESTER; + break; + + case PL_DEMONAC: + item[i]._iFlags2 |= IAF2_DEMONAC; + break; + case PL_UNDEADAC: + item[i]._iFlags2 |= IAF2_UNDEADAC; + break; + + case PL_ACOLYTE: + r2 = ((plr[myplr]._pMaxManaBase >> MANA_SHIFT) * 50 / 100); + item[i]._iPLMana -= (r2 << MANA_SHIFT); + item[i]._iPLHP += (r2 << HP_SHIFT); + break; + case PL_GLADIATR: + r2 = ((plr[myplr]._pMaxHPBase >> HP_SHIFT) * 40 / 100); + item[i]._iPLHP -= (r2 << HP_SHIFT); + item[i]._iPLMana += (r2 << MANA_SHIFT); + break; + } + if ((item[i]._iVAdd1 == 0) && (item[i]._iVMult1 == 0)) { + item[i]._iVAdd1 = PLVal(r, param1, param2, minval, maxval); + item[i]._iVMult1 = multval; + } else { + item[i]._iVAdd2 = PLVal(r, param1, param2, minval, maxval); + item[i]._iVMult2 = multval; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetItemPower(int i, int minlvl, int maxlvl, long flgs, BOOL onlygood) +{ + int pre, post; + int l[256], nl; + int j, aii; + int preidx, sufidx; + char istr[128]; + byte goe; + + pre = random(23, 4); // Pre modifier (20%) + post = random(23, 3); // Post modifirer (66%) + // if no pre modifier, make sure post modifier + if ((pre != 0) && (post == 0)) { + if (random(23, 2)) post = 1; + else pre = 0; + } + + preidx = -1; + sufidx = -1; + goe = 0; + + // if not any only good item, then 67% chance of good, 33% chance of anything + if ((!onlygood) && (random(0, 3))) onlygood = TRUE; + + if (pre == 0) { + nl = 0; + for (j = 0; PL_Prefix[j].PLPower != -1; j++) { + if (((PL_Prefix[j].PLIType & flgs) != 0) && + (PL_Prefix[j].PLMinLvl >= minlvl) && + (PL_Prefix[j].PLMinLvl <= maxlvl) + ) { + if (onlygood && !PL_Prefix[j].PLOk) continue; + if ((flgs == PLF_STAFF) && (PL_Prefix[j].PLPower == PL_CHRG)) continue; + + l[nl] = j; + nl++; + if (PL_Prefix[j].PLDouble) { + l[nl] = j; + nl++; + } + } + } + if (nl != 0) { + preidx = l[random(23, nl)]; + sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); + strcpy(item[i]._iIName, istr); + item[i]._iMagical = IMAGIC_MAGIC; + SaveItemPower(i, PL_Prefix[preidx].PLPower, PL_Prefix[preidx].PLParam1, PL_Prefix[preidx].PLParam2, PL_Prefix[preidx].PLMinVal, PL_Prefix[preidx].PLMaxVal, PL_Prefix[preidx].PLMultVal); + item[i]._iPrePower = PL_Prefix[preidx].PLPower; + goe = PL_Prefix[preidx].PLGOE; + } + } + if (post != 0) { + nl = 0; + for (j = 0; PL_Suffix[j].PLPower != -1; j++) { + if (((PL_Suffix[j].PLIType & flgs) != 0) && + (PL_Suffix[j].PLMinLvl >= minlvl) && + (PL_Suffix[j].PLMinLvl <= maxlvl) && + ((goe | PL_Suffix[j].PLGOE) != 0x11) + ) { + if (onlygood && !PL_Suffix[j].PLOk) continue; + + l[nl] = j; + nl++; + } + } + if (nl != 0) { + sufidx = l[random(23, nl)]; + sprintf(istr, "%s of %s", item[i]._iIName, PL_Suffix[sufidx].PLName); + strcpy(item[i]._iIName, istr); + item[i]._iMagical = IMAGIC_MAGIC; + SaveItemPower(i, PL_Suffix[sufidx].PLPower, PL_Suffix[sufidx].PLParam1, PL_Suffix[sufidx].PLParam2, PL_Suffix[sufidx].PLMinVal, PL_Suffix[sufidx].PLMaxVal, PL_Suffix[sufidx].PLMultVal); + item[i]._iSufPower = PL_Suffix[sufidx].PLPower; + } + } + if (!InfoFit(item[i]._iIName)) { + aii = item[i].IDidx; + strcpy(item[i]._iIName, AllItemsList[aii].iSName); + if (preidx != -1) { + sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); + strcpy(item[i]._iIName, istr); + } + if (sufidx != -1) { + sprintf(istr, "%s of %s", item[i]._iIName, PL_Suffix[sufidx].PLName); + strcpy(item[i]._iIName, istr); + } + } + if ((preidx != -1) || (sufidx != -1)) CalcItemValue(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetItemBonus(int i, int idata, int minlvl, int maxlvl, BOOL onlygood) +{ + if (item[i]._iClass == IC_GOLD) return; + if (minlvl > 25) minlvl = 25; + + switch(item[i]._itype) { + case IT_SWORD : + case IT_AXE: + case IT_MACE: + GetItemPower(i, minlvl, maxlvl, PLF_WEAPON, onlygood); + break; + case IT_BOW: + GetItemPower(i, minlvl, maxlvl, PLF_BOW, onlygood); + break; + case IT_SHIELD: + GetItemPower(i, minlvl, maxlvl, PLF_SHIELD, onlygood); + break; + case IT_ARMOR: + case IT_HELM: + case IT_MARMOR: + case IT_HARMOR: + GetItemPower(i, minlvl, maxlvl, PLF_ARMOR, onlygood); + break; + case IT_STAFF: + GetStaffSpell(i, maxlvl, onlygood); + break; + case IT_RING: + case IT_AMULET: + GetItemPower(i, minlvl, maxlvl, PLF_RING, onlygood); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetupItem(int i) +{ + int it; + + DROPLOG("SetupItem: setting up object %d!\n",i); + + it = ItemCAnimTbl[item[i]._iCurs]; + item[i]._iAnimData = itemanims[it]; + item[i]._iAnimLen = ItemAnimLs[it]; + item[i]._iAnimWidth = 96; + item[i]._iAnimWidth2 = 16; + item[i]._iIdentified = FALSE; + item[i]._iPostDraw = FALSE; + if (plr[myplr].pLvlLoad == LVLCHANGE_OFF) { + item[i]._iAnimFrame = 1; + item[i]._iAnimFlag = TRUE; + item[i]._iSelFlag = ISEL_NONE; + } else { + item[i]._iAnimFrame = item[i]._iAnimLen; + item[i]._iAnimFlag = FALSE; + item[i]._iSelFlag = ISEL_FLR; + } +} + +/*-----------------------------------------------------------------------* +** Choose an item type from a monster +**-----------------------------------------------------------------------*/ + +int RndItem(int m) +{ + int r; + int ril[512]; // Max 512 items + int ri, i; + + // Unique item? + if (monster[m].MData->mTreasure & T_U) + return(-((monster[m].MData->mTreasure & T_MASK) + 1)); + + if (monster[m].MData->mTreasure & T_NONE) return(0); + +#if CHEATS + if (davedebug) r = 100; + else r = random(24, 100); + if (!cheatflag && (r > 40)) return(0); + if (!cheatflag && (random(24, 100) > 25)) return(IDI_GOLD+1); +#else + r = random(24, 100); + if (r > 40) return(0); + // Gold 75% of the time + if (random(24, 100) > 25) return(IDI_GOLD+1); +#endif + + ri = 0; + for (i = 0; AllItemsList[i].iLoc != -1; i++) { + if ((AllItemsList[i].iRnd == IRND_DOUBLE) && + (monster[m].mLevel >= AllItemsList[i].iMinMLvl)) ril[ri++] = i; + if (AllItemsList[i].iRnd && + (monster[m].mLevel >= AllItemsList[i].iMinMLvl)) ril[ri++] = i; + if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) ri--; + if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) ri--; + } + r = random(24, ri); + return(ril[r]+1); +} + +/*-----------------------------------------------------------------------* +** Choose an item type for a good or unique item +**-----------------------------------------------------------------------*/ + +int RndUItem(int m) +{ + int ril[512]; // Max 512 items + int ri, i; + BOOL okflag; + + // Unique item? + if (m != -1) { + if ((monster[m].MData->mTreasure & T_U) && (gbMaxPlayers == 1)) + return(-((monster[m].MData->mTreasure & T_MASK) + 1)); + } + + ri = 0; + for (i = 0; AllItemsList[i].iLoc != -1; i++) { + okflag = TRUE; + if (!AllItemsList[i].iRnd) okflag = FALSE; + if (m != -1) { + if (monster[m].mLevel < AllItemsList[i].iMinMLvl) okflag = FALSE; + } else { + if ((currlevel << 1) < AllItemsList[i].iMinMLvl) okflag = FALSE; + } + if (AllItemsList[i].itype == IT_MISC) okflag = FALSE; + if (AllItemsList[i].itype == IT_GOLD) okflag = FALSE; + if (AllItemsList[i].itype == IT_FOOD) okflag = FALSE; + if (AllItemsList[i].iMiscId == IMID_BOOK) okflag = TRUE; + if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) okflag = FALSE; + if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) okflag = FALSE; + if (okflag) ril[ri++] = i; + } + return(ril[random(25, ri)]); +} + +/*-----------------------------------------------------------------------* +** Choose any type of item +**-----------------------------------------------------------------------*/ + +int RndAllItems() +{ + int r; + int ril[512]; // Max 512 items + int ri, i; + +#if CHEATS + if (!cheatflag && !itemcheat && (random(26, 100) > 25)) return(IDI_GOLD); +#else + // Gold 75% of the time + if (random(26, 100) > 25) return(IDI_GOLD); +#endif + + ri = 0; + for (i = 0; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && ((currlevel << 1) >= AllItemsList[i].iMinMLvl)) ril[ri++] = i; + if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) ri--; + if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) ri--; + } + r = random(26, ri); + return(ril[r]); +} + +/*-----------------------------------------------------------------------* +** Choose an item of a specific type +**-----------------------------------------------------------------------*/ + +int RndTypeItems(int itype, int imid, int level) +{ + int ril[512]; // Max 512 items + int ri, i; + BOOL okflag; + + ri = 0; + for (i = 0; AllItemsList[i].iLoc != -1; i++) { + okflag = TRUE; + if (!AllItemsList[i].iRnd) okflag = FALSE; + if ((level << 1) < AllItemsList[i].iMinMLvl) okflag = FALSE; + if (AllItemsList[i].itype != itype) okflag = FALSE; + if ((imid != -1) && (AllItemsList[i].iMiscId != imid)) okflag = FALSE; + if (okflag && ri < 512) + ril[ri++] = i; + } + return(ril[random(27, ri)]); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int CheckUnique(int i, int lvl, int uper, BOOL recreate) +{ + int j, idata; + BYTE uok[MAXUITEMS]; + int numu, u; + +#if CHEATS + if (!davedebug || !cheatflag) { + if (random(28, 100) > uper) return(-1); + } +#else + if (random(28, 100) > uper) return(-1); +#endif + + numu = 0; + ZeroMemory(uok,sizeof(uok)); + for (j = 0; UniqueItemList[j].UIItemId != -1; j++) { + idata = item[i].IDidx; + if (UniqueItemList[j].UIItemId != AllItemsList[idata].iItemId) continue; + if (lvl < UniqueItemList[j].UIMinLvl) continue; + if (!recreate && UniqueItemFlag[j] && (gbMaxPlayers == 1)) continue; + uok[j] = TRUE; + numu++; + } + + if (numu == 0) return(-1); + u = random(29, 10); + j = 0; + while (numu > 0) { + if (uok[j]) numu--; + if (numu > 0) { + j++; + if (j == MAXUITEMS) j = 0; + } + } + return(j); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetUniqueItem(int i, int uid) +{ + // Generated + UniqueItemFlag[uid] = TRUE; + // Save abilities + SaveItemPower(i, UniqueItemList[uid].UIPower1, UniqueItemList[uid].UIParam1, UniqueItemList[uid].UIParam2, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 1) + SaveItemPower(i, UniqueItemList[uid].UIPower2, UniqueItemList[uid].UIParam3, UniqueItemList[uid].UIParam4, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 2) + SaveItemPower(i, UniqueItemList[uid].UIPower3, UniqueItemList[uid].UIParam5, UniqueItemList[uid].UIParam6, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 3) + SaveItemPower(i, UniqueItemList[uid].UIPower4, UniqueItemList[uid].UIParam7, UniqueItemList[uid].UIParam8, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 4) + SaveItemPower(i, UniqueItemList[uid].UIPower5, UniqueItemList[uid].UIParam9, UniqueItemList[uid].UIParam10, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 5) + SaveItemPower(i, UniqueItemList[uid].UIPower6, UniqueItemList[uid].UIParam11, UniqueItemList[uid].UIParam12, 0, 0, 1); + // Save name + strcpy(item[i]._iIName, UniqueItemList[uid].UIName); + item[i]._iIvalue = UniqueItemList[uid].UIValue; + if (item[i]._iMiscId == IMID_UNIQUE) item[i]._iSeed = uid; // Save index into UniqueItemList + item[i]._iUid = uid; // Save index into Unique Item List + item[i]._iMagical = IMAGIC_UNIQUE; + item[i]._iCreateInfo |= ICI_UNIQUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnUnique(int uid, int x, int y) +{ + int ii, itype; + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + itype = 0; + while (AllItemsList[itype].iItemId != UniqueItemList[uid].UIItemId) itype++; + GetItemAttrs(ii, itype, currlevel); + GetUniqueItem(ii, uid); + SetupItem(ii); + numitems++; + } +} + + +/*-----------------------------------------------------------------------* +** Items in dungeon have lower durs +**-----------------------------------------------------------------------*/ + +void ItemRndDur(int ii) +{ + if (item[ii]._iDurability == 0) return; + if (item[ii]._iDurability == INFINITE_DUR) return; + item[ii]._iDurability = random(0, item[ii]._iMaxDur >> 1) + (item[ii]._iMaxDur >> 2) + 1; +} + +/*-----------------------------------------------------------------------* +** Setup an item and determine magics +**-----------------------------------------------------------------------*/ + +void SetupAllItems(int ii, int idx, int iseed, int lvl, int uper, BOOL onlygood, BOOL recreate, BOOL pregen) +{ + int iblvl, uid; + + item[ii]._iSeed = iseed; + SetRndSeed(iseed); + GetItemAttrs(ii, idx, lvl >> 1); + item[ii]._iCreateInfo = lvl; + if (pregen) item[ii]._iCreateInfo |= ICI_PREGEN; + if (onlygood) item[ii]._iCreateInfo |= ICI_ONLYGOOD; + if (uper == 15) item[ii]._iCreateInfo |= ICI_UPER15; + else if (uper == 1) item[ii]._iCreateInfo |= ICI_UPER1; + if (item[ii]._iMiscId != IMID_UNIQUE) { + iblvl = -1; + if (random(32, 100) <= 10) iblvl = lvl; + else if (random(33, 100) <= lvl) iblvl = lvl; + // Force rings, amulets, and staffs to be magical + if ((iblvl == -1) && (item[ii]._iMiscId == IMID_STAFF)) iblvl = lvl; + if ((iblvl == -1) && (item[ii]._iMiscId == IMID_RING)) iblvl = lvl; + if ((iblvl == -1) && (item[ii]._iMiscId == IMID_AMULET)) iblvl = lvl; + if (onlygood) iblvl = lvl; +#if CHEATS + if (cheatflag) iblvl = lvl; +#endif + if (uper == 15) iblvl = lvl + 4; + if (iblvl != -1) { + uid = CheckUnique(ii, iblvl, uper, recreate); + if (uid == -1) + GetItemBonus(ii, idx, iblvl >> 1, iblvl, onlygood); + else { + GetUniqueItem(ii, uid); + item[ii]._iCreateInfo |= ICI_UNIQUE; + } + } + if (item[ii]._iMagical != IMAGIC_UNIQUE) ItemRndDur(ii); + } else { + // if it is something they wield, then get the attributes + if (item[ii]._iLoc != IL_INV) GetUniqueItem(ii, iseed); + } + SetupItem(ii); +} + +/*-----------------------------------------------------------------------* +** Create any item from a monster (or unqiue if monster gives one up) +**-----------------------------------------------------------------------*/ + +void SpawnItem(int m, int x, int y, BOOL sendmsg) +{ + int ii, idx; + BOOL onlygood; + + if ((monster[m]._uniqtype != 0) || + ((monster[m].MData->mTreasure & T_U) && (gbMaxPlayers != 1))) { + // If unique, make sure we get something good + idx = RndUItem(m); + if (idx < 0) { + SpawnUnique(-(idx+1), x, y); + return; + } + onlygood = TRUE; + } else { + // special code to pop out brain for Mushroom Quest + if (quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE + && quests[Q_BKMUSHRM]._qvar1 == QS_MUSHGIVEN) { + idx = IDI_BRAIN; + quests[Q_BKMUSHRM]._qvar1 = QS_BRAINSPAWNED; + } + else + { + idx = RndItem(m); + if (idx == 0) return; + if (idx > 0) { + idx--; + onlygood = FALSE; + } else { + SpawnUnique(-(idx+1), x, y); + return; + } + } + } + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + if (monster[m]._uniqtype != 0) SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 15, onlygood, FALSE, FALSE); +#if CHEATS + else if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 15, TRUE, FALSE, FALSE); +#endif + else SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 1, onlygood, FALSE, FALSE); + + numitems++; + if (sendmsg) NetSendCmdDItem(FALSE, ii); + } +} + + +/*-----------------------------------------------------------------------* +** Only used for quest (single player) +**-----------------------------------------------------------------------*/ + +void CreateItem(int uid, int x, int y) +{ + int ii, idx; + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + idx = 0; + while (AllItemsList[idx].iItemId != UniqueItemList[uid].UIItemId) idx++; + GetItemAttrs(ii, idx, currlevel); + GetUniqueItem(ii, uid); + SetupItem(ii); + item[ii]._iMagical = IMAGIC_UNIQUE; + numitems++; + } +} + + +/*-----------------------------------------------------------------------* +** Create any item from an object, etc (chest, barrel, sarc) +**-----------------------------------------------------------------------*/ + +void CreateRndItem(int x, int y, BOOL onlygood, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + + if (onlygood) idx = RndUItem(-1); + else idx = RndAllItems(); + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), currlevel << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), currlevel << 1, 1, onlygood, FALSE, delta); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetupAllUseful(int ii, int iseed, int lvl) +{ + int idx; + + item[ii]._iSeed = iseed; + SetRndSeed(iseed); + +#if 0 + if (random(34, 2)) idx = IDI_HEAL; + else idx = IDI_MANA; + + // added 7/30/97 by donald + if (!random(34, 8)) idx = IDI_OILACC; + + if ((lvl > 1) && (random(34, 3) == 0)) idx = IDI_PORTAL; +#else + // why call random() so many times? + + switch(random(34,7)) + { + case 0: idx = IDI_PORTAL; if (lvl > 1) break; // else fallthrough + case 1: + case 2: idx = IDI_HEAL; break; + case 3: idx = IDI_PORTAL; if (lvl > 1) break; // else fallthrough + case 4: + case 5: idx = IDI_MANA; break; + default:idx = IDI_OILACC; break; + } +#endif + + GetItemAttrs(ii, idx, lvl); + item[ii]._iCreateInfo = ICI_USEFUL + lvl; + SetupItem(ii); +} + +/*-----------------------------------------------------------------------* +** Rnd item, but only health, mana, or id +**-----------------------------------------------------------------------*/ + +void CreateRndUseful(int pnum, int x, int y, BOOL sendmsg) +{ + int ii; + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + SetupAllUseful(ii, GetRndSeed(), currlevel); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +** Create any item of a specific type +**-----------------------------------------------------------------------*/ + +void CreateTypeItem(int x, int y, BOOL onlygood, int itype, int imisc, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + + if (itype != IT_GOLD) idx = RndTypeItems(itype, imisc, currlevel); + else idx = 0; + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), currlevel << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), currlevel << 1, 1, onlygood, FALSE, delta); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +** Recreate any item with the proper info +**-----------------------------------------------------------------------*/ + +void RecreateItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue) +{ + int uper; + BOOL onlygood, uavail, pregen; + + // PATCH1.JMM + #if 0 + int i, nIndex; + for(i = 0; i < numitems; i++) { + nIndex = itemactive[i]; + + if(((item[nIndex]._iSeed == iseed) && (item[nIndex]._iCreateInfo == icreateinfo) && (item[nIndex].IDidx == idx))) + DROPLOG(" Creating dupped item: idx->%8.8x seed->%8.8x ci->%8.8x\n",idx,iseed,icreateinfo); + + app_assert(!((item[nIndex]._iSeed == iseed) && (item[nIndex]._iCreateInfo == icreateinfo) && (item[nIndex].IDidx == idx))); + } + #endif + // ENDPATCH1.JMM + + + // Gold + if (idx == IDI_GOLD) { + SetPlrHandItem(&item[ii], idx); + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = icreateinfo; + item[ii]._ivalue = ivalue; + if (item[ii]._ivalue >= GOLD_VT2) { + item[ii]._iCurs = ITEM_5GOLD; + } else { + if (ivalue <= GOLD_VT1) item[ii]._iCurs = ITEM_1GOLD; + else item[ii]._iCurs = ITEM_3GOLD; + } + } else { + // One the the players initial items? + if (icreateinfo == 0) { + SetPlrHandItem(&item[ii], idx); + SetPlrHandSeed(&item[ii], iseed); + } else { + // From town? + if (icreateinfo & ICI_TOWNMASK) RecreateTownItem(ii, idx, icreateinfo, iseed, ivalue); + else { + // From dungeon + if ((icreateinfo & ICI_USEFUL) == ICI_USEFUL) { + SetupAllUseful(ii, iseed, icreateinfo & ICI_LVLMASK); + } else { + uper = 0; + onlygood = FALSE; + uavail = FALSE; + pregen = FALSE; + if (icreateinfo & ICI_UPER1) uper = 1; + if (icreateinfo & ICI_UPER15) uper = 15; + if (icreateinfo & ICI_ONLYGOOD) onlygood = TRUE; + if (icreateinfo & ICI_UNIQUE) uavail = TRUE; + if (icreateinfo & ICI_PREGEN) pregen = TRUE; + SetupAllItems(ii, idx, iseed, icreateinfo & ICI_LVLMASK, uper, onlygood, uavail, pregen); + } + } + } + } +} + +/*-----------------------------------------------------------------------* +** Recreate any ear with the proper info +**-----------------------------------------------------------------------*/ + +void RecreateEar(int ii, WORD ic, int iseed, BOOL Id, int dur, int mdur, int ch, int mch, int ivalue, int ibuff) +{ + SetPlrHandItem(&item[ii], IDI_EAR); + tempstr[0] = (ic >> 8) & 0x7f; + tempstr[1] = ic & 0x7f; + tempstr[2] = (iseed >> 24) & 0x7f; + tempstr[3] = (iseed >> 16) & 0x7f; + tempstr[4] = (iseed >> 8) & 0x7f; + tempstr[5] = iseed & 0x7f; + tempstr[6] = Id & 0x7f; + tempstr[7] = dur & 0x7f; + tempstr[8] = mdur & 0x7f; + tempstr[9] = ch & 0x7f; + tempstr[10] = mch & 0x7f; + tempstr[11] = (ivalue >> 8) & 0x7f; + tempstr[12] = (ibuff >> 24) & 0x7f; + tempstr[13] = (ibuff >> 16) & 0x7f; + tempstr[14] = (ibuff >> 8) & 0x7f; + tempstr[15] = ibuff & 0x7f; + tempstr[16] = 0; + sprintf(item[ii]._iName, "Ear of %s", tempstr); + item[ii]._iCurs = ((ivalue >> 6) & 0x3) + ITEM_EAR1; + item[ii]._ivalue = ivalue & 0x3f; + item[ii]._iCreateInfo = ic; + item[ii]._iSeed = iseed; +} + + +const char * sgszCornerstone = "SItem"; + +void CornerstoneSave() +{ + if (!CornerStone.Initted) + return; + + PkItemStruct pki; + + if (CornerStone.item.IDidx >= 0) + { + PackItem(&pki, &(CornerStone.item)); + SRegSaveData(gszProgKey,sgszCornerstone,0, &pki, sizeof(PkItemStruct)); + } + else + { + SRegSaveData(gszProgKey,sgszCornerstone, 0, "", 1); + } +} + +void CornerstoneRestore(int x, int y) +{ + // read the info out of the options file + PkItemStruct pki; + + if (x == 0 || y == 0) + return; + + CornerStone.item.IDidx = 0; + CornerStone.Initted = TRUE; + + DWORD bytesread = 0; + if (! SRegLoadData(gszProgKey,sgszCornerstone, 0, &pki, sizeof(PkItemStruct), &bytesread) || + bytesread != sizeof(PkItemStruct)) + { + if (dItem[x][y] != 0) + { + // clear the square + int ii = dItem[x][y] - 1; + for (int i = 0; i < numitems; ++i) + if (itemactive[i] == ii) + { + DeleteItem(ii, i); + break; + } + dItem[x][y] = 0; + } + return; + } + + // create a new item slot + int ii = itemavail[0]; + dItem[x][y] = ii+1; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + + UnPackItem(&pki, &item[ii]); + item[ii]._ix = x; + item[ii]._iy = y; + + DROPLOG("CornerstoneRestore: respawning object %d!\n",ii); + RespawnItem(ii, FALSE); + CornerStone.item = item[ii]; + + numitems++; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnQuestItem(int itemid, int x,int y, int randarea, int selflag) +{ + int i,j; + BOOL failed; + + if (randarea) { + int tries = 0; + do { + if (++tries > 1000 && randarea > 1) + --randarea; + x = random(0, DMAXX); + y = random(0, DMAXY); + failed = FALSE; + for (i = 0; i < randarea && !failed; i++) + for (j = 0; j < randarea && !failed; j++) + failed = !ItemSpaceOk(x + i, y + j); + } while (failed); + } + + if (numitems < MAXITEMS) { + i = itemavail[0]; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = i; + item[i]._ix = x; + item[i]._iy = y; + dItem[x][y] = i + 1; + GetItemAttrs(i, itemid, currlevel); + SetupItem(i); + item[i]._iPostDraw = TRUE; + if (selflag != ISEL_NONE) { + // selflag indicates creation of post-flippy item + item[i]._iSelFlag = selflag; + item[i]._iAnimFrame = item[i]._iAnimLen; + item[i]._iAnimFlag = FALSE; + } + + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SpawnRock() +{ + int i, ii, ostand; + int xx,yy; + BOOL done = FALSE; + + for (i = 0; i < numobjects && !done; i++) { + ostand = objectactive[i]; + done = (object[ostand]._otype == 23); // OBJ_STAND + + + } + if(done) + { + ii = itemavail[0]; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + xx = item[ii]._ix = object[ostand]._ox; + yy = item[ii]._iy = object[ostand]._oy; + dItem[xx][yy] = ii + 1; + GetItemAttrs(ii, IDI_ROCK, currlevel); + SetupItem(ii); + item[ii]._iSelFlag = ISEL_TOP; + item[ii]._iPostDraw = TRUE; + item[ii]._iAnimFrame = 11; + + numitems++; + } +} + +void SpawnSomething(int what, int xx, int yy) +{ + int ii = itemavail[0]; + + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + item[ii]._ix = xx; + item[ii]._iy = yy; + dItem[xx][yy] = ii + 1; + GetItemAttrs(ii, what, currlevel); + SetupItem(ii); + item[ii]._iSelFlag = ISEL_TOP; + item[ii]._iPostDraw = TRUE; + item[ii]._iAnimFrame = item[ii]._iAnimLen; + item[ii]._iIdentified = TRUE; + + numitems++; +} + +void SpawnMap(int xx, int yy) +{ + SpawnSomething(IDI_MAPOFDOOM, xx, yy); +} + +void SpawnBomb(int xx, int yy) +{ + SpawnSomething(IDI_RUNEBOMB, xx, yy); +} + +void SpawnBear(int xx, int yy) +{ + SpawnSomething(IDI_THEODORE, xx, yy); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RespawnItem(int i, BOOL FlipFlag) +{ + int it; + + DROPLOG(" RespawnItem: Respawning item %d!\n",i); + + it = ItemCAnimTbl[item[i]._iCurs]; + item[i]._iAnimData = itemanims[it]; + item[i]._iAnimLen = ItemAnimLs[it]; + item[i]._iAnimWidth = 96; + item[i]._iAnimWidth2 = 16; + item[i]._iPostDraw = FALSE; + item[i]._iRequest = FALSE; + if (FlipFlag) { + item[i]._iAnimFrame = 1; + item[i]._iAnimFlag = TRUE; + item[i]._iSelFlag = ISEL_NONE; + } else { + item[i]._iAnimFrame = item[i]._iAnimLen; + item[i]._iAnimFlag = FALSE; + item[i]._iSelFlag = ISEL_FLR; + } + if (item[i]._iCurs == ITEM_ROCK) { + item[i]._iSelFlag = ISEL_FLR; + PlaySfxLoc(ItemAnimSnds[it], item[i]._ix, item[i]._iy); + } + if (item[i]._iCurs == ITEM_INNSIGN) item[i]._iSelFlag = ISEL_FLR; + if (item[i]._iCurs == ITEM_ANVIL) item[i]._iSelFlag = ISEL_FLR; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DeleteItem(int ii, int i) +{ + itemavail[MAXITEMS - numitems] = ii; + numitems--; + if ((numitems > 0) && (i != numitems)) { + itemactive[i] = itemactive[numitems]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int idoppely = DIRTEDGED2; + +void ItemDoppel() +{ + int idoppelx; + ItemStruct *i; + + if (gbMaxPlayers == 1) return; + + for (idoppelx = DIRTEDGED2; idoppelx < (DIRTEDGED2+80); idoppelx++) { + if (dItem[idoppelx][idoppely]) { + i = &item[dItem[idoppelx][idoppely] - 1]; + if ((i->_ix != idoppelx) || (i->_iy != idoppely)) + dItem[idoppelx][idoppely] = 0; + } + } + idoppely++; + if (idoppely == DIRTEDGED2+80) idoppely = DIRTEDGED2; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ProcessItems() +{ + int i, ii, it; + + VerifyItemActiveList(); + + for (i = 0; i < numitems; i++) { + ii = itemactive[i]; + + // Animate Spell GFX + if (item[ii]._iAnimFlag) { + item[ii]._iAnimFrame++; + if (item[ii]._iCurs == ITEM_ROCK) { + if ((item[ii]._iSelFlag == ISEL_FLR) && (item[ii]._iAnimFrame == 11)) + item[ii]._iAnimFrame = 1; + if ((item[ii]._iSelFlag == ISEL_TOP) && (item[ii]._iAnimFrame == 21)) + item[ii]._iAnimFrame = 11; + } else { + if (item[ii]._iAnimFrame == (item[ii]._iAnimLen >> 1)) { + it = ItemCAnimTbl[item[ii]._iCurs]; + PlaySfxLoc(ItemAnimSnds[it], item[ii]._ix, item[ii]._iy); + } + if (item[ii]._iAnimFrame >= item[ii]._iAnimLen) { + item[ii]._iAnimFrame = item[ii]._iAnimLen; + item[ii]._iAnimFlag = FALSE; + item[ii]._iSelFlag = ISEL_FLR; + } + } + } + } + + ItemDoppel(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void FreeItemGFX() +{ + for (int i = 0; i < ITEMFTYPES; i++) + DiabloFreePtr(itemanims[i]); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncItemAnim(int ii) +{ + int a; + + a = ItemCAnimTbl[item[ii]._iCurs]; + item[ii]._iAnimData = itemanims[a]; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetItemStr(int i) { + + switch (item[i]._itype) { + case IT_GOLD: { + int nGold = item[i]._ivalue; + const char * get_pieces_str(int nGold); + sprintf(infostr,"%i gold %s",nGold,get_pieces_str(nGold)); + } + break; + + default : + int s = item[i]._itype; + if (item[i]._iIdentified) strcpy(infostr, item[i]._iIName); + else strcpy(infostr, item[i]._iName); + if (item[i]._iMagical == IMAGIC_MAGIC) infoclr = ICOLOR_BLUE; + if (item[i]._iMagical == IMAGIC_UNIQUE) infoclr = ICOLOR_GOLD; + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckIdentify(int pnum, int cii) { + ItemStruct * pi; + if (cii < NUM_INVLOC) + pi = &plr[pnum].InvBody[cii]; + else + pi = &plr[pnum].InvList[cii - NUM_INVLOC]; + pi->_iIdentified = TRUE; + CalcPlrInv(pnum,TRUE); + + if (pnum == myplr) + NewCursor(GLOVE_CURS); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void RepairItem(ItemStruct *i, int lvl) { + int d, rep; + + if (i->_iDurability == i->_iMaxDur) return; + // If item already has zero durability, wipe it out + if (i->_iMaxDur <= 0) { + i->_itype = -1; + return; + } + rep = 0; + do { + rep += random(37, lvl) + lvl; + d = i->_iMaxDur / (9 + lvl); + if (d < 1) d = 1; + i->_iMaxDur -= d; + // If I have no max durability, break + if (i->_iMaxDur == 0) { + i->_itype = -1; + return; + } + } while ((i->_iDurability + rep) < i->_iMaxDur); + i->_iDurability += rep; + if (i->_iDurability > i->_iMaxDur) + i->_iDurability = i->_iMaxDur; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoRepair(int pnum, int cii) { + PlayerStruct * p = &plr[pnum]; + PlaySfxLoc(IS_REPAIR, p->_px, p->_py); + + ItemStruct * pi; + if (cii < NUM_INVLOC) + pi = &p->InvBody[cii]; + else + pi = &p->InvList[cii - NUM_INVLOC]; + RepairItem(pi,p->_pLevel); + CalcPlrInv(pnum,TRUE); + + if (pnum == myplr) + NewCursor(GLOVE_CURS); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void RechargeItem(ItemStruct *i, int r) { + if (i->_iCharges == i->_iMaxCharges) return; + + do { + i->_iMaxCharges--; + if (i->_iMaxCharges == 0) { + //i->_itype = -1; + return; + } + i->_iCharges += r; + } while (i->_iCharges < i->_iMaxCharges); + + if (i->_iCharges > i->_iMaxCharges) i->_iCharges = i->_iMaxCharges; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoRecharge(int pnum, int cii) { + PlayerStruct * p = &plr[pnum]; + + ItemStruct * pi; + if (cii < NUM_INVLOC) pi = &p->InvBody[cii]; + else pi = &p->InvList[cii - NUM_INVLOC]; +// rmw.patch1.start.1/14/97 +// if (pi->_itype == IT_STAFF) { + if ((pi->_itype == IT_STAFF) && (pi->_iSpell != SPL_NONE)) { +// rmw.patch1.end.1/14/97 + int sp = pi->_iSpell; + int r = spelldata[sp].sBookLvl; + r = random(38, p->_pLevel / r) + 1; + + RechargeItem(pi, r); + CalcPlrInv(pnum, TRUE); + } + + if (pnum == myplr) NewCursor(GLOVE_CURS); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static BOOL OilItem(ItemStruct * i,const PlayerStruct * p) { + int v; + + if (i->_iClass == IC_ITEM) return(FALSE); + if (i->_iClass == IC_GOLD) return(FALSE); + if (i->_iClass == IC_SPECIAL) return(FALSE); + switch(p->_pOilType) { + case IMID_OILACC : + case IMID_OILMAST : + case IMID_OILSHRP : + if (i->_iClass == IC_ARMOR) return(FALSE); + break; + case IMID_OILDEATH : + if (i->_iClass == IC_ARMOR) return(FALSE); + if (i->_itype == IT_BOW) return(FALSE); + break; + case IMID_OILHARD : + case IMID_OILIMPER : + if (i->_iClass == IC_WEAP) return(FALSE); + break; + } + + switch(p->_pOilType) { + case IMID_OILACC : + if (i->_iPLToHit >= 50) break; + i->_iPLToHit += random(68, 2) + 1; + break; + case IMID_OILMAST : + if (i->_iPLToHit >= 100) break; + i->_iPLToHit += random(68, 3) + 3; + break; + case IMID_OILSHRP : + if (i->_iMaxDam - i->_iMinDam >= 30) break; + i->_iMaxDam += 1; + break; + case IMID_OILDEATH : + if (i->_iMaxDam - i->_iMinDam >= 30) break; + i->_iMinDam += 1; + i->_iMaxDam += 2; + break; + case IMID_OILSKILL : + v = random(68, 6) + 5; + + if (i->_iMinStr > v) { + i->_iMinStr -= v; + } + else { + i->_iMinStr = 0; + } + + if (i->_iMinMag > v) { + i->_iMinMag -= v; + } + else { + i->_iMinMag = 0; + } + + if (i->_iMinDex > v) { + i->_iMinDex -= v; + } + else { + i->_iMinDex = 0; + } + break; + case IMID_OILBLKSM : + if (i->_iMaxDur == INFINITE_DUR) break; +// i->_iDurability = (i->_iDurability + (random(68, 5) + 2)); +// i->_iMaxDur = (i->_iMaxDur + (random(68, 9) + 7)); + if (i->_iDurability < i->_iMaxDur) + { + // fix by 20% + int tmp = i->_iDurability + ((i->_iMaxDur + 4) / 5); + if (tmp > i->_iMaxDur) + tmp = i->_iMaxDur; + i->_iDurability = tmp; + } + else + { + if (i->_iMaxDur >= 100) break; + i->_iMaxDur += 1; + i->_iDurability = i->_iMaxDur; + } + break; + case IMID_OILFORT : + if (i->_iMaxDur == INFINITE_DUR) break; + if (i->_iMaxDur >= 200) break; + v = random(68, 41) + 10; + i->_iMaxDur += v; + i->_iDurability += v; + break; + case IMID_OILPERM : + i->_iDurability = INFINITE_DUR; + i->_iMaxDur = INFINITE_DUR; + break; + case IMID_OILHARD : + if (i->_iAC >= 60) break; + i->_iAC += random(68, 2) + 1; + break; + case IMID_OILIMPER : + if (i->_iAC >= 120) break; + i->_iAC += random(68, 3) + 3; + break; + } + + return(TRUE); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoOil(int pnum, int cii) { + ItemStruct * pi; + PlayerStruct * p = &plr[pnum]; + if (cii < NUM_INVLOC) switch (cii) { + case INVLOC_HEAD: + case INVLOC_HAND1: + case INVLOC_HAND2: + case INVLOC_BODY: + pi = &p->InvBody[cii]; + break; + + default: + return; + } + else { + pi = &p->InvList[cii - NUM_INVLOC]; + } + + if (OilItem(pi,p)) { + CalcPlrInv(pnum,TRUE); + if (pnum == myplr) NewCursor(GLOVE_CURS); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PrintItemOil(char IDidx) +{ + switch(IDidx) { + case IMID_OILACC : + strcpy(tempstr, "increases a weapon's"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "chance to hit"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILMAST : + strcpy(tempstr, "greatly increases a"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "weapon's chance to hit"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILSHRP : + strcpy(tempstr, "increases a weapon's"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "damage potential"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILDEATH : + strcpy(tempstr, "greatly increases a weapon's"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "damage potential - not bows"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILSKILL : + strcpy(tempstr, "reduces attributes needed"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "to use armor or weapons"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILBLKSM : + strcpy(tempstr, "restores 20% of an"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "item's durability"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILFORT : + strcpy(tempstr, "increases an item's"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "current and max durability"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILPERM : + strcpy(tempstr, "makes an item indestructible"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILHARD : + strcpy(tempstr, "increases the armor class"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "of armor and shields"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILIMPER : + strcpy(tempstr, "greatly increases the armor"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "class of armor and shields"); + AddPanelString(tempstr, TEXT_CENTER); + break; +// potions + case IMID_PHEAL : + strcpy(tempstr, "fully recover life"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PLHEAL : + strcpy(tempstr, "recover partial life"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PSHEAL : + strcpy(tempstr, "recover life"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PDHEAL : + strcpy(tempstr, "deadly heal"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PMANA : + strcpy(tempstr, "recover mana"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PFMANA : + strcpy(tempstr, "fully recover mana"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ESTR : + strcpy(tempstr, "increase strength"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_EMAG : + strcpy(tempstr, "increase magic"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_EDEX : + strcpy(tempstr, "increase dexterity"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_EVIT : + strcpy(tempstr, "increase vitality"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ENSTR : + strcpy(tempstr, "decrease strength"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ENMAG : + strcpy(tempstr, "decrease strength"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ENDEX : + strcpy(tempstr, "decrease dexterity"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ENVIT : + strcpy(tempstr, "decrease vitality"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_REJUV : + strcpy(tempstr, "recover life and mana"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_FREJUV : + strcpy(tempstr, "fully recover life and mana"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_RUNEFIRE: + case IMID_RUNEIMMOLATE: + strcpy(tempstr, "sets fire trap"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_RUNELIGHT: + case IMID_RUNENOVA: + strcpy(tempstr, "sets lightning trap"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_RUNESTONE: + strcpy(tempstr, "sets petrification trap"); + AddPanelString(tempstr, TEXT_CENTER); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PrintItemPower(char plidx,const ItemStruct * x) { + int v; + + switch(plidx) { + case PL_TOHIT: + case PL_NTOHIT: + sprintf(tempstr, "chance to hit : %+i%%", x->_iPLToHit); + break; + case PL_TODAM: + case PL_NTODAM: + sprintf(tempstr, "%+i%% damage", x->_iPLDam); + break; + case PL_DAHT: + case PL_NDAHT: + sprintf(tempstr, "to hit: %+i%%, %+i%% damage", x->_iPLToHit, x->_iPLDam); + break; + case PL_AC: + case PL_NAC: + sprintf(tempstr, "%+i%% armor", x->_iPLAC); + break; + case PL_ACTUALAC: + sprintf(tempstr, "armor class: %i", x->_iAC); + break; + case PL_NACTULAC: + sprintf(tempstr, "armor class: %i", x->_iAC); + break; + case PL_RFIRE: + case PL_NRFIRE: + if (x->_iPLFR < 75) + sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR); + else + sprintf(tempstr, "Resist Fire : 75%% MAX"); + break; + case PL_RLGHT: + case PL_NRLGHT: + if (x->_iPLLR < 75) + sprintf(tempstr, "Resist Lightning : %+i%%", x->_iPLLR); + else + sprintf(tempstr, "Resist Lightning : 75%% MAX"); + break; + case PL_RMAG: + case PL_NRMAG: + if (x->_iPLMR < 75) + sprintf(tempstr, "Resist Magic : %+i%%", x->_iPLMR); + else + sprintf(tempstr, "Resist Magic : 75%% MAX"); + break; + case PL_RALL: + case PL_NRALL: + if (x->_iPLFR < 75) sprintf(tempstr, "Resist All : %+i%%", x->_iPLFR); + if (x->_iPLFR >= 75) sprintf(tempstr, "Resist All : 75%% MAX"); + break; + case PL_SLVL: + if (x->_iSplLvlAdd == 1 ) strcpy(tempstr, "spells are increased 1 level"); + if (x->_iSplLvlAdd == 2 ) strcpy(tempstr, "spells are increased 2 levels"); + if (x->_iSplLvlAdd < 1 ) strcpy(tempstr, "spells are decreased 1 level"); + break; + case PL_CHRG: + strcpy(tempstr, "Extra charges"); + break; + case PL_SPELL: + sprintf(tempstr, "%i %s charges", x->_iMaxCharges, spelldata[x->_iSpell].sNameText); + break; + case PL_FHIT: + if (x->_iFMinDam == x->_iFMaxDam) + sprintf(tempstr, "Fire hit damage: %i", x->_iFMinDam); + else + sprintf(tempstr, "Fire hit damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); + break; + case PL_LHIT: + if (x->_iLMinDam == x->_iLMaxDam) + sprintf(tempstr, "Lightning hit damage: %i", x->_iLMinDam); + else + sprintf(tempstr, "Lightning hit damage: %i-%i", x->_iLMinDam, x->_iLMaxDam); + break; + case PL_STR: + case PL_NSTR: + sprintf(tempstr, "%+i to strength", x->_iPLStr); + break; + case PL_MAG: + case PL_NMAG: + sprintf(tempstr, "%+i to magic", x->_iPLMag); + break; + case PL_DEX: + case PL_NDEX: + sprintf(tempstr, "%+i to dexterity", x->_iPLDex); + break; + case PL_VIT: + case PL_NVIT: + sprintf(tempstr, "%+i to vitality", x->_iPLVit); + break; + case PL_STATS: + case PL_NSTATS: + sprintf(tempstr, "%+i to all attributes", x->_iPLStr); + break; + case PL_GETHIT: + case PL_NGETHIT: + sprintf(tempstr, "%+i damage from enemies", x->_iPLGetHit); + break; + case PL_HP: + case PL_NHP: + sprintf(tempstr, "Hit Points : %+i", (x->_iPLHP >> HP_SHIFT)); + break; + case PL_MANA: + case PL_NMANA: + sprintf(tempstr, "Mana : %+i", (x->_iPLMana >> MANA_SHIFT)); + break; + case PL_DUR: + strcpy(tempstr, "high durability"); + break; + case PL_NDUR: + strcpy(tempstr, "decreased durability"); + break; + case PL_IND: + strcpy(tempstr, "indestructible"); + break; + case PL_LIGHT: + v = x->_iPLLight * 10; + sprintf(tempstr, "+%i%% light radius", v); + break; + case PL_NLIGHT: + v = -x->_iPLLight * 10; + sprintf(tempstr, "-%i%% light radius", v); + break; + case PL_NUMARWS: + sprintf(tempstr, "multiple arrows per shot"); + break; + case PL_FARROW: + if (x->_iFMinDam == x->_iFMaxDam) + sprintf(tempstr, "fire arrows damage: %i", x->_iFMinDam); + else + sprintf(tempstr, "fire arrows damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); + break; + case PL_LARROW: + if (x->_iLMinDam == x->_iLMaxDam) + sprintf(tempstr, "lightning arrows damage %i", x->_iLMinDam); + else + sprintf(tempstr, "lightning arrows damage %i-%i", x->_iLMinDam, x->_iLMaxDam); + break; + case PL_HITADD: // usurped for fireball arrows... + if (x->_iFMinDam == x->_iFMaxDam) + sprintf(tempstr, "fireball damage: %i", x->_iFMinDam); + else + sprintf(tempstr, "fireball damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); + break; + case PL_THORN: + strcpy(tempstr, "attacker takes 1-3 damage"); + break; + case PL_LMANA: + strcpy(tempstr, "user loses all mana"); + break; + case PL_NOHEAL: + strcpy(tempstr, "you can't heal"); + break; + case PL_TRAPDAM: + strcpy(tempstr, "absorbs half of trap damage"); + break; + case PL_BEAR: + strcpy(tempstr, "knocks target back"); + break; + case PL_DAMDEMON: + strcpy(tempstr, "+200% damage vs. demons"); + break; + case PL_ZERORES: + strcpy(tempstr, "All Resistance equals 0"); + break; + case PL_MNOHEAL: + strcpy(tempstr, "hit monster doesn't heal"); + break; + case PL_BAT: + if (x->_iFlags & IAF_BAT10) strcpy(tempstr, "hit steals 3% mana"); + if (x->_iFlags & IAF_BAT20) strcpy(tempstr, "hit steals 5% mana"); + break; + case PL_LEECH: + if (x->_iFlags & IAF_LEECH10) strcpy(tempstr, "hit steals 3% life"); + if (x->_iFlags & IAF_LEECH20) strcpy(tempstr, "hit steals 5% life"); + break; + case PL_ENAC: + strcpy(tempstr, "penetrates target's armor"); + break; + case PL_ATANIM: + if (x->_iFlags & IAF_ATANIM1) strcpy(tempstr, "quick attack"); + if (x->_iFlags & IAF_ATANIM2) strcpy(tempstr, "fast attack"); + if (x->_iFlags & IAF_ATANIM3) strcpy(tempstr, "faster attack"); + if (x->_iFlags & IAF_ATANIM4) strcpy(tempstr, "fastest attack"); + break; + case PL_HTANIM: + if (x->_iFlags & IAF_HTANIM1) strcpy(tempstr, "fast hit recovery"); + if (x->_iFlags & IAF_HTANIM2) strcpy(tempstr, "faster hit recovery"); + if (x->_iFlags & IAF_HTANIM3) strcpy(tempstr, "fastest hit recovery"); + break; + case PL_BLANIM: + strcpy(tempstr, "fast block"); + break; + case PL_DAMADD: + sprintf(tempstr, "adds %i points to damage", x->_iPLDamMod); + break; + case PL_RNDARW: + strcpy(tempstr, "fires random speed arrows"); + break; + case PL_DAMAGE: + sprintf(tempstr, "unusual item damage"); + break; + case PL_DURNUM: + strcpy(tempstr, "altered durability"); + break; + case PL_FALCON: + strcpy(tempstr, "Faster attack swing"); + // not used + break; + case PL_ONEHAND: + strcpy(tempstr, "one handed sword"); + break; + case PL_CONST: + strcpy(tempstr, "constantly lose hit points"); + break; + case PL_SKING: + strcpy(tempstr, "life stealing"); + break; + case PL_NSTRREQ: + strcpy(tempstr, "no strength requirement"); + break; + case PL_INFRA: + strcpy(tempstr, "see with infravision"); + break; + case PL_GFX: + strcpy(tempstr, " "); + break; + case PL_HARQUN: + if (x->_iFMinDam == x->_iFMaxDam) + sprintf(tempstr, "lightning damage: %i", x->_iFMinDam); + else + sprintf(tempstr, "lightning damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); +// strcpy(tempstr, "Armor class added to life"); + break; + case PL_HARQUN2: + strcpy(tempstr, "charged bolts on hits"); +// strcpy(tempstr, "10% of mana added to armor"); + break; + case PL_HARQUN3: + if (x->_iPLFR <= 0) sprintf(tempstr, " "); + else if (x->_iPLFR >= 1) sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR); + break; + case PL_DEVAST: + strcpy(tempstr, "occasional triple damage"); + break; + case PL_DECAY: + sprintf(tempstr, "decaying %+i%% damage", x->_iPLDam); + break; + case PL_PERIL: + strcpy(tempstr, "2x dmg to monst, 1x to you"); + break; + case PL_RNDDAM: + strcpy(tempstr, "Random 0 - 500% damage"); + break; + case PL_FRAGILE: + sprintf(tempstr, "low dur, %+i%% damage", x->_iPLDam); + break; + case PL_DOPPEL: + sprintf(tempstr, "to hit: %+i%%, %+i%% damage", x->_iPLToHit, x->_iPLDam); + break; + case PL_DEMONAC: + sprintf(tempstr, "extra AC vs demons"); + break; + case PL_UNDEADAC: + sprintf(tempstr, "extra AC vs undead"); + break; + case PL_ACOLYTE: + sprintf(tempstr, "50%% Mana moved to Health"); + break; + case PL_GLADIATR: + sprintf(tempstr, "40%% Health moved to Mana"); + break; + + default: + strcpy(tempstr, "Another ability (NW)"); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawUBack() +{ + DrawCel(88, 487, pSTextBoxCels, 1, 271); + app_assert(gpBuffer); + + __asm { + mov edi,dword ptr [gpBuffer] + add edi,371803 + + xor eax,eax + mov edx,148 +_YLp: mov ecx,132 +_XLp1: stosb + inc edi + loop _XLp1 + stosb + sub edi,1033 + mov ecx,132 +_XLp2: inc edi + stosb + loop _XLp2 + sub edi,1032 + dec edx + jnz _YLp + mov ecx,132 +_XLp3: stosb + inc edi + loop _XLp3 + stosb + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PrintUString(int x, int y, BOOL cjustflag, char str[], char col) +{ + long boffset; + int sl,i,w,tw,yy; + + yy = SStringY[y]; + boffset = nBuffWTbl[yy + 204] + x + 96; + sl = strlen(str); + w = 0; + if (cjustflag) { + tw = 0; + for (i = 0; i < sl; i++) { + BYTE c = char2print(str[i]); + c = fonttrans[c]; + tw += fontkern[c]+1; + } + if (tw < 257) w = (257 - tw) >> 1; + boffset += w; + } + for (i = 0; i < sl; i++) { + BYTE c = char2print(str[i]); + c = fonttrans[c]; + w += fontkern[c]+1; + if ((c != 0) && (w <= 257)) DrawPanelFont(boffset, c, col); + boffset += fontkern[c]+1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawULine(int y) +{ + long doffset; + + app_assert(gpBuffer); + doffset = nBuffWTbl[SStringY[y] + 198] + 90; + __asm { + mov esi,dword ptr [gpBuffer] + mov edi,esi + add esi,142170 + add edi,dword ptr [doffset] + + mov ebx,502 + + mov edx,3 +_YLp: mov ecx,66 + rep movsd + movsw + add esi,ebx + add edi,ebx + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawUniqueInfo() +{ + int u,y; + + if (chrflag || questlog) return; + u = curruitem._iUid; + DrawUBack(); + PrintUString(0, 2, TRUE, UniqueItemList[u].UIName, ICOLOR_GOLD); + DrawULine(5); + PrintItemPower(UniqueItemList[u].UIPower1, &curruitem); + y = (6 - UniqueItemList[u].UINumPL) + 8; + PrintUString(0, y, TRUE, tempstr, ICOLOR_WHITE); + if (UniqueItemList[u].UINumPL > 1) { + PrintItemPower(UniqueItemList[u].UIPower2, &curruitem); + PrintUString(0, y+2, TRUE, tempstr, ICOLOR_WHITE); + } + if (UniqueItemList[u].UINumPL > 2) { + PrintItemPower(UniqueItemList[u].UIPower3, &curruitem); + PrintUString(0, y+4, TRUE, tempstr, ICOLOR_WHITE); + } + if (UniqueItemList[u].UINumPL > 3) { + PrintItemPower(UniqueItemList[u].UIPower4, &curruitem); + PrintUString(0, y+6, TRUE, tempstr, ICOLOR_WHITE); + } + if (UniqueItemList[u].UINumPL > 4) { + PrintItemPower(UniqueItemList[u].UIPower5, &curruitem); + PrintUString(0, y+8, TRUE, tempstr, ICOLOR_WHITE); + } + if (UniqueItemList[u].UINumPL > 5) { + PrintItemPower(UniqueItemList[u].UIPower6, &curruitem); + PrintUString(0, y+10, TRUE, tempstr, ICOLOR_WHITE); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PrintItemMisc(const ItemStruct * x) +{ + if (x->_iMiscId == IMID_SCROLL) { + strcpy(tempstr, "Right-click to read"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_TSCROLL) { + strcpy(tempstr, "Right-click to read, then"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "left-click to target"); + AddPanelString(tempstr, TEXT_CENTER); + } + if ((x->_iMiscId >= IMID_FIRSTPOT) && (x->_iMiscId <= IMID_LASTPOT)) { + PrintItemOil(x->_iMiscId); + strcpy(tempstr, "Right click to use"); + AddPanelString(tempstr, TEXT_CENTER); + } + if ((x->_iMiscId > IMID_FIRSTOIL) && (x->_iMiscId < IMID_LASTOIL)) { + PrintItemOil(x->_iMiscId); + strcpy(tempstr, "Right click to use"); + AddPanelString(tempstr, TEXT_CENTER); + } + if ((x->_iMiscId > IMID_FIRSTRUNE) && (x->_iMiscId < IMID_LASTRUNE)) { + PrintItemOil(x->_iMiscId); + strcpy(tempstr, "Right click to use"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_BOOK) { + strcpy(tempstr, "Right click to read"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_MAPOFDOOM) { + strcpy(tempstr, "Right click to view"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_EAR) { + sprintf(tempstr, "Level : %i", x->_ivalue); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_AURIC) { + strcpy(tempstr, "Doubles gold capacity"); + AddPanelString(tempstr, TEXT_CENTER); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PrintItemDetails(const ItemStruct * x) +{ + if (x->_iClass == IC_WEAP) { + if (x->_iMinDam == x->_iMaxDam) + { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "damage: %i Indestructible", x->_iMinDam); + else + sprintf(tempstr, "damage: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur); + } + else + { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "damage: %i-%i Indestructible", x->_iMinDam, x->_iMaxDam); + else + sprintf(tempstr, "damage: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur); + } + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iClass == IC_ARMOR) { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "armor: %i Indestructible", x->_iAC); + else + sprintf(tempstr, "armor: %i Dur: %i/%i", x->_iAC, x->_iDurability, x->_iMaxDur); + AddPanelString(tempstr, TEXT_CENTER); + } + if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) { + if (x->_iMinDam == x->_iMaxDam) + sprintf(tempstr, "dam: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur); + else + sprintf(tempstr, "dam: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur); + sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iPrePower != -1) { + PrintItemPower(x->_iPrePower, x); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iSufPower != -1) { + PrintItemPower(x->_iSufPower, x); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMagical == IMAGIC_UNIQUE) { + AddPanelString("unique item", TEXT_CENTER); + uitemflag = TRUE; + curruitem = *x; + } + PrintItemMisc(x); + if ((x->_iMinStr + x->_iMinMag + x->_iMinDex) != 0) { + strcpy(tempstr, "Required:"); + if (x->_iMinStr != 0) sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr); + if (x->_iMinMag != 0) sprintf(tempstr, "%s %i Mag", tempstr, (byte) x->_iMinMag); + if (x->_iMinDex != 0) sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex); + AddPanelString(tempstr, TEXT_CENTER); + } + pinfoflag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PrintItemDur(const ItemStruct * x) +{ + if (x->_iClass == IC_WEAP) { + if (x->_iMinDam == x->_iMaxDam) + { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "damage: %i Indestructible", x->_iMinDam); + else + sprintf(tempstr, "damage: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur); + } + else + { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "damage: %i-%i Indestructible", x->_iMinDam, x->_iMaxDam); + else + sprintf(tempstr, "damage: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur); + } + AddPanelString(tempstr, TEXT_CENTER); + if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) { + sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMagical) { + AddPanelString("Not Identified", TEXT_CENTER); + } + } + if (x->_iClass == IC_ARMOR) { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "armor: %i Indestructible", x->_iAC); + else + sprintf(tempstr, "armor: %i Dur: %i/%i", x->_iAC, x->_iDurability, x->_iMaxDur); + AddPanelString(tempstr, TEXT_CENTER); + if (x->_iMagical) { + AddPanelString("Not Identified", TEXT_CENTER); + } + if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) { + sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); + AddPanelString(tempstr, TEXT_CENTER); + } + } + if ((x->_itype == IT_RING) || (x->_itype == IT_AMULET)) { + AddPanelString("Not Identified", TEXT_CENTER); + } + PrintItemMisc(x); + if ((x->_iMinStr + x->_iMinMag + x->_iMinDex) != 0) { + strcpy(tempstr, "Required:"); + if (x->_iMinStr != 0) sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr); + if (x->_iMinMag != 0) sprintf(tempstr, "%s %i Mag", tempstr, (byte) x->_iMinMag); + if (x->_iMinDex != 0) sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex); + AddPanelString(tempstr, TEXT_CENTER); + } + pinfoflag = TRUE; +} + +/*-------------------------------------------------------------------------* +**-------------------------------------------------------------------------*/ + +void UseItem(int p, int Mid, int spl) +{ + long l; + __int64 t; + + switch(Mid) { + case IMID_MEAT : + case IMID_PLHEAL : + l = plr[p]._pMaxHP >> (HP_SHIFT + 2); + l = ((random(39, l) + (l >> 1)) << HP_SHIFT); + if (plr[p]._pClass == CLASS_WARRIOR) l = l << 1; + if (plr[p]._pClass == CLASS_ROGUE) l += (l >> 1); + plr[p]._pHitPoints += l; + if (plr[p]._pHitPoints > plr[p]._pMaxHP) plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase += l; + if (plr[p]._pHPBase > plr[p]._pMaxHPBase) plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + break; + case IMID_PHEAL : + plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + break; + case IMID_PMANA : + l = plr[p]._pMaxMana >> (MANA_SHIFT + 2); + l = ((random(40, l) + (l >> 1)) << MANA_SHIFT); + if (plr[p]._pClass == CLASS_SORCEROR) l = l << 1; + if (plr[p]._pClass == CLASS_ROGUE) l += (l >> 1); + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pMana += l; + if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase += l; + if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + } + break; + case IMID_PFMANA : + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + } + break; + case IMID_ESTR : + ModifyPlrStr(p, 1); + break; + case IMID_EMAG : + ModifyPlrMag(p, 1); + + // also give full mana potion effect + plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + + break; + case IMID_EDEX : + ModifyPlrDex(p, 1); + break; + case IMID_EVIT : + ModifyPlrVit(p, 1); + + // heal the player, too + plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + + break; + case IMID_BOOK : + t = 1; + plr[p]._pMemSpells |= (t << spl-1); + if (plr[p]._pSplLvl[spl] < SPELLCAP) plr[p]._pSplLvl[spl]++; + plr[p]._pMana += spelldata[spl].sManaCost << MANA_SHIFT; + if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase += spelldata[spl].sManaCost << MANA_SHIFT; + if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase; + if (p == myplr) CalcPlrBookVals(p); + drawmanaflag = TRUE; + break; + case IMID_REJUV : + l = plr[p]._pMaxHP >> (HP_SHIFT + 2); + l = ((random(39, l) + (l >> 1)) << HP_SHIFT); + if (plr[p]._pClass == CLASS_WARRIOR) l = l << 1; + if (plr[p]._pClass == CLASS_ROGUE) l += (l >> 1); + plr[p]._pHitPoints += l; + if (plr[p]._pHitPoints > plr[p]._pMaxHP) plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase += l; + if (plr[p]._pHPBase > plr[p]._pMaxHPBase) plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + l = plr[p]._pMaxMana >> (MANA_SHIFT + 2); + l = ((random(40, l) + (l >> 1)) << MANA_SHIFT); + if (plr[p]._pClass == CLASS_SORCEROR) l = l << 1; + if (plr[p]._pClass == CLASS_ROGUE) l += (l >> 1); + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pMana += l; + if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase += l; + if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + } + break; + case IMID_FREJUV : + plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + } + break; + case IMID_OILACC : + case IMID_OILMAST : + case IMID_OILSHRP : + case IMID_OILDEATH : + case IMID_OILSKILL : + case IMID_OILBLKSM : + case IMID_OILFORT : + case IMID_OILPERM : + case IMID_OILHARD : + case IMID_OILIMPER : + plr[p]._pOilType = Mid; + if (p == myplr) { + if (sbookflag) sbookflag = FALSE; + if (!invflag) invflag = TRUE; + NewCursor(OIL_CURS); + } + break; + case IMID_SCROLL: + if (spelldata[spl].sTargeted) { + plr[p]._pTSpell = spl; + //plr[p]._pTSplType = SPT_SCROLL; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + } else { + ClrPlrPath(p); + plr[p]._pSpell = spl; + //plr[p]._pSplType = SPT_SCROLL; + plr[p]._pSplType = SPT_NONE; + plr[p]._pSplFrom = SPL_FROMSB; + plr[p].destAction = PCMD_SPELL; + plr[p].destParam1 = cursmx; + plr[p].destParam2 = cursmy; + } + break; + case IMID_TSCROLL: + if (spelldata[spl].sTargeted) { + plr[p]._pTSpell = spl; + //plr[p]._pTSplType = SPT_SCROLL; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + } else { + ClrPlrPath(p); + plr[p]._pSpell = spl; + //plr[p]._pSplType = SPT_SCROLL; + plr[p]._pSplType = SPT_NONE; + plr[p]._pSplFrom = SPL_FROMSB; + plr[p].destAction = PCMD_SPELL; + plr[p].destParam1 = cursmx; + plr[p].destParam2 = cursmy; + } + break; + case IMID_MAPOFDOOM: + InitMapOfDoomView(); + break; + case IMID_SPECTRAL: + ModifyPlrStr(p, 3); + ModifyPlrMag(p, 3); + ModifyPlrDex(p, 3); + ModifyPlrVit(p, 3); + break; + case IMID_RUNEFIRE: + plr[p]._pTSpell = SPL_RUNEOFFIRE; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_RUNELIGHT: + plr[p]._pTSpell = SPL_RUNEOFLIGHT; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_RUNEIMMOLATE: + plr[p]._pTSpell = SPL_RUNEOFIMMOLATION; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_RUNENOVA: + plr[p]._pTSpell = SPL_RUNEOFNOVA; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_RUNESTONE: + plr[p]._pTSpell = SPL_RUNEOFSTONE; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#define MAX_STORE_VAL 140000 +#define MAX_WIRT_VAL 90000 // Wirts stuff is 150% of normal + +BOOL StoreStatOk(ItemStruct *h) +{ + BOOL sf = TRUE; + if (plr[myplr]._pStrength < h->_iMinStr) sf = FALSE; + else if (plr[myplr]._pMagic < (byte)h->_iMinMag) sf = FALSE; + else if (plr[myplr]._pDexterity < h->_iMinDex) sf = FALSE; + return(sf); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL SmithItemOk(int i) +{ + BOOL rv; + + rv = TRUE; + // Selling oil is too powerful for the money received. +// if (AllItemsList[i].iMiscId > IMID_FIRSTOIL && +// AllItemsList[i].iMiscId < IMID_LASTOIL) rv = TRUE; +// else + if (AllItemsList[i].itype == IT_MISC) rv = FALSE; + + if (AllItemsList[i].itype == IT_GOLD) rv = FALSE; + if (AllItemsList[i].itype == IT_FOOD) rv = FALSE; + if (AllItemsList[i].itype == IT_STAFF) rv = FALSE; + if (AllItemsList[i].itype == IT_RING) rv = FALSE; + if (AllItemsList[i].itype == IT_AMULET) rv = FALSE; + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndSmithItem(int lvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && SmithItemOk(i) && + (lvl >= AllItemsList[i].iMinMLvl)) { + ril[ri++] = i; + if (AllItemsList[i].iRnd == IRND_DOUBLE) ril[ri++] = i; + } + } + return(ril[random(50, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void BubbleSwapItem(ItemStruct * a, ItemStruct * b) +{ + ItemStruct h; + + h = *a; + *a = *b; + *b = h; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SortSmith() +{ + int j, k; + BOOL sorted; + + for (k = 0; smithitem[k+1]._itype != -1; k++); + sorted = FALSE; + while ((k > 0) && (!sorted)) { + sorted = TRUE; + for (j = 0; j < k; j++) { + if (smithitem[j].IDidx > smithitem[j+1].IDidx) { + BubbleSwapItem(&smithitem[j], &smithitem[j+1]); + sorted = FALSE; + } + } + k--; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnSmith(int lvl) +{ + int itype; + int i,nsi; + ItemStruct const holditem = item[0]; + + nsi = random(50, 10) + 10; + for (i = 0; i < nsi; i++) { + do { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndSmithItem(lvl) - 1; + GetItemAttrs(0, itype, lvl); + } while (item[0]._iIvalue > MAX_STORE_VAL); + smithitem[i] = item[0]; + smithitem[i]._iCreateInfo = lvl | ICI_SMITH; + smithitem[i]._iIdentified = TRUE; + smithitem[i]._iStatFlag = StoreStatOk(&smithitem[i]); + } + for (i = nsi; i < MAXSMITHITEMS; i++) smithitem[i]._itype = -1; + SortSmith(); + item[0] = holditem; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PremiumItemOk(int i) +{ + BOOL rv; + + rv = TRUE; + if (AllItemsList[i].itype == IT_MISC) rv = FALSE; + else if (AllItemsList[i].itype == IT_GOLD) rv = FALSE; + else if (AllItemsList[i].itype == IT_FOOD) rv = FALSE; + else if (AllItemsList[i].itype == IT_STAFF) rv = FALSE; + if (gbMaxPlayers != 1) { + if (AllItemsList[i].iMiscId == IMID_OIL) rv = FALSE; + else if (AllItemsList[i].itype == IT_RING) rv = FALSE; + else if (AllItemsList[i].itype == IT_AMULET) rv = FALSE; + } + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndPremiumItem(int minlvl, int maxlvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && PremiumItemOk(i) && + (AllItemsList[i].iMinMLvl >= minlvl) && + (AllItemsList[i].iMinMLvl <= maxlvl)) { + ril[ri++] = i; + } + } + return(ril[random(50, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnOnePremium(int i, int plvl, int myplr) +{ + int itype; + ItemStruct const holditem = item[0]; + int const maxval = MAX_STORE_VAL; + int ivalue; + int iCount = 0; + int maxPlrStr = GetMaxStr(plr[myplr]._pClass); + int maxPlrDex = GetMaxDex(plr[myplr]._pClass); + int maxPlrMag = GetMaxMag(plr[myplr]._pClass); + + // Test in case of bonus + if (maxPlrStr < plr[myplr]._pStrength) + { + maxPlrStr = plr[myplr]._pStrength; + } + maxPlrStr = (int)(maxPlrStr * 1.2); + + if (maxPlrDex < plr[myplr]._pDexterity) + { + maxPlrDex = plr[myplr]._pDexterity; + } + maxPlrDex = (int)(maxPlrDex * 1.2); + + if (maxPlrMag < plr[myplr]._pMagic) + { + maxPlrMag = plr[myplr]._pMagic; + } + maxPlrMag = (int)(maxPlrMag * 1.2); + + +#if CHEATS + if ((plvl > 30) || (davecheat)) plvl = 30; +#else + if (plvl > 30) plvl = 30; +#endif + if (plvl < 1) plvl = 1; + + do { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndPremiumItem(plvl>>2, plvl) - 1; + GetItemAttrs(0, itype, plvl); + GetItemBonus(0, itype, plvl>>1, plvl, TRUE); + + ivalue = 0; + + switch (item[0]._itype) + { + case IT_ARMOR: + case IT_MARMOR: + case IT_HARMOR: + ivalue = GetHighArmorValue(myplr); + break; + case IT_AXE: + ivalue = GetHighAxeValue(myplr); + break; + case IT_BOW: + ivalue = GetHighBowValue(myplr); + break; + case IT_MACE: + ivalue = GetHighMaceValue(myplr); + break; + case IT_SWORD: + ivalue = GetHighSwordValue(myplr); + break; + case IT_HELM: + ivalue = GetHighHelmValue(myplr); + break; + case IT_STAFF: + ivalue = GetHighStaffValue(myplr); + break; + case IT_RING: + ivalue = GetHighRingValue(myplr); + break; + case IT_AMULET: + ivalue = GetHighAmuletValue(myplr); + break; + } + ivalue = (int)(0.8 * ivalue); + + ++iCount; + + // GWP Make sure we can actually use it. + } while ((item[0]._iIvalue > maxval + || item[0]._iMinStr > maxPlrStr + || item[0]._iMinMag > maxPlrMag + || item[0]._iMinDex > maxPlrDex + || item[0]._iIvalue < ivalue) // already have better. + && iCount < 150 // prevent infinite loops. + ); + + premiumitem[i] = item[0]; + premiumitem[i]._iCreateInfo = plvl | ICI_PREMIUM; + premiumitem[i]._iIdentified = TRUE; + premiumitem[i]._iStatFlag = StoreStatOk(&premiumitem[i]); + item[0] = holditem; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int premiumlvladd[MAXPREMIUM] = { -1, -1, 0, 0, 0, 0, 1, 1, 2, 3 }; + +void SpawnPremium(int myplr) +{ + int lvl = plr[myplr]._pLevel; + int i; + + // Empty slots? + if (numpremium < MAXPREMIUM) { + for (i = 0; i < MAXPREMIUM; ++i) { + if (premiumitem[i]._itype == -1) + SpawnOnePremium(i, premiumlevel + premiumlvladd[i], myplr); + } + numpremium = MAXPREMIUM; + } + // New items? + while (premiumlevel < lvl) { + premiumlevel++; + premiumitem[0] = premiumitem[2]; + premiumitem[1] = premiumitem[3]; + premiumitem[2] = premiumitem[4]; + premiumitem[3] = premiumitem[5]; + premiumitem[4] = premiumitem[6]; + premiumitem[5] = premiumitem[7]; + premiumitem[6] = premiumitem[8]; + SpawnOnePremium(7, premiumlevel + premiumlvladd[6], myplr); + premiumitem[8] = premiumitem[9]; + SpawnOnePremium(9, premiumlevel + premiumlvladd[7], myplr); + } + +#if 10 != MAXPREMIUM +#error "Fix code for new MAXPREMIUM" +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL WitchItemOk(int i) +{ + BOOL rv; + + rv = FALSE; + if (AllItemsList[i].itype == IT_MISC) rv = TRUE; + if (AllItemsList[i].itype == IT_STAFF) rv = TRUE; + // Will already have the next one + if (AllItemsList[i].iMiscId == IMID_PMANA) rv = FALSE; + if (AllItemsList[i].iMiscId == IMID_PFMANA) rv = FALSE; + if (AllItemsList[i].iSpell == SPL_TOWN) rv = FALSE; + // no healing + if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = FALSE; + if (AllItemsList[i].iMiscId == IMID_PLHEAL) rv = FALSE; + // no oils + if (AllItemsList[i].iMiscId > IMID_FIRSTOIL && + AllItemsList[i].iMiscId < IMID_LASTOIL) + rv = FALSE; + // None of these in single player + if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) rv = FALSE; + if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) rv = FALSE; + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndWitchItem(int lvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && WitchItemOk(i) && + (lvl >= AllItemsList[i].iMinMLvl)) ril[ri++] = i; + } + return(ril[random(51, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SortWitch() +{ + int j, k; + BOOL sorted; + + for (k = 3; witchitem[k+1]._itype != -1; k++); + sorted = FALSE; + while ((k > 3) && (!sorted)) { + sorted = TRUE; + for (j = 3; j < k; j++) { + if (witchitem[j].IDidx > witchitem[j+1].IDidx) { + BubbleSwapItem(&witchitem[j], &witchitem[j+1]); + sorted = FALSE; + } + } + k--; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void WitchBookLevel(int ii) +{ + if (witchitem[ii]._iMiscId != IMID_BOOK) return; + witchitem[ii]._iMinMag = spelldata[witchitem[ii]._iSpell].sMinInt; + int slvl = plr[myplr]._pSplLvl[witchitem[ii]._iSpell]; + while (slvl != 0) { + witchitem[ii]._iMinMag += ((witchitem[ii]._iMinMag * 20) / 100); + slvl--; + if ((witchitem[ii]._iMinMag + ((witchitem[ii]._iMinMag * 20) / 100)) > 255) { + witchitem[ii]._iMinMag = 255; + slvl = 0; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnWitch(int lvl) +{ + int itype, iblvl; + int i,nsi; + + // Will always have mana (endless supply) + GetItemAttrs(0, IDI_MANA, 1); + witchitem[0] = item[0]; + witchitem[0]._iCreateInfo = lvl; + witchitem[0]._iStatFlag = TRUE; + GetItemAttrs(0, IDI_FULLMANA, 1); + witchitem[1] = item[0]; + witchitem[1]._iCreateInfo = lvl; + witchitem[1]._iStatFlag = TRUE; + GetItemAttrs(0, IDI_PORTAL, 1); + witchitem[2] = item[0]; + witchitem[2]._iCreateInfo = lvl; + witchitem[2]._iStatFlag = TRUE; + + nsi = random(51, 8) + 10; + for (i = 3; i < nsi; i++) { + do { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndWitchItem(lvl) - 1; + GetItemAttrs(0, itype, lvl); + iblvl = -1; + if (random(51, 100) <= 5) iblvl = lvl << 1; + // Force staffs to be magical + if ((iblvl == -1) && (item[0]._iMiscId == IMID_STAFF)) iblvl = lvl << 1; +#if CHEATS + if (cheatflag) iblvl = lvl << 1; +#endif + if (iblvl != -1) GetItemBonus(0, itype, iblvl >> 1, iblvl, TRUE); + } while (item[0]._iIvalue > MAX_STORE_VAL); + witchitem[i] = item[0]; + witchitem[i]._iCreateInfo = lvl | ICI_WITCH; + witchitem[i]._iIdentified = TRUE; + WitchBookLevel(i); + witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]); + //WitchBookLevel(i); + } + for (i = nsi; i < MAXWITCHITEMS; i++) witchitem[i]._itype = -1; + SortWitch(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndBoyItem(int lvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && PremiumItemOk(i) && + (lvl >= AllItemsList[i].iMinMLvl)) ril[ri++] = i; + } + return(ril[random(49, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnBoy(int lvl) +{ + int itype; + + if ((boylevel < (lvl >> 1)) || (boyitem._itype == -1)) { + do { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndBoyItem(lvl) - 1; + GetItemAttrs(0, itype, lvl); + // Always magical + GetItemBonus(0, itype, lvl, lvl << 1, TRUE); + } while (item[0]._iIvalue > MAX_WIRT_VAL); + boyitem = item[0]; + boyitem._iCreateInfo = lvl | ICI_BOY; + boyitem._iIdentified = TRUE; + boyitem._iStatFlag = StoreStatOk(&boyitem); + boylevel = lvl >> 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL HealerItemOk(int i) +{ + BOOL rv; + + rv = FALSE; + if (AllItemsList[i].itype != IT_MISC) return(FALSE); + // Heal scrolls + if ((AllItemsList[i].iMiscId == IMID_SCROLL) && (AllItemsList[i].iSpell == SPL_HEAL)) rv = TRUE; + // Will always have Resurrect scrolls (multiplayer only) + if ((AllItemsList[i].iMiscId == IMID_TSCROLL) && (AllItemsList[i].iSpell == SPL_RESURRECT) && (gbMaxPlayers != 1)) rv = FALSE; + // Heal Other scroll (multiplayer only) + if ((AllItemsList[i].iMiscId == IMID_TSCROLL) && (AllItemsList[i].iSpell == SPL_HEALOTHER) && (gbMaxPlayers != 1)) rv = TRUE; + // Elixirs + if (gbMaxPlayers == 1) { + if (AllItemsList[i].iMiscId == IMID_ESTR + && plr[myplr]._pBaseStr < MaxStats[plr[myplr]._pClass][0]) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_EMAG + && plr[myplr]._pBaseMag < MaxStats[plr[myplr]._pClass][1]) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_EDEX + && plr[myplr]._pBaseDex < MaxStats[plr[myplr]._pClass][2]) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_EVIT + && plr[myplr]._pBaseVit < MaxStats[plr[myplr]._pClass][3]) rv = TRUE; + } + // Potions + if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_REJUV) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_FREJUV) rv = TRUE; + // Will always have these + else if (AllItemsList[i].iMiscId == IMID_PLHEAL) rv = FALSE; + else if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = FALSE; + // No mana + else if (AllItemsList[i].iMiscId == IMID_PMANA) rv = FALSE; + else if (AllItemsList[i].iMiscId == IMID_PFMANA) rv = FALSE; + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndHealerItem(int lvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && HealerItemOk(i) && + (lvl >= AllItemsList[i].iMinMLvl)) ril[ri++] = i; + } + return(ril[random(50, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SortHealer() +{ + int j, k; + BOOL sorted; + + for (k = 2; healitem[k+1]._itype != -1; k++); + sorted = FALSE; + while ((k > 2) && (!sorted)) { + sorted = TRUE; + for (j = 2; j < k; j++) { + if (healitem[j].IDidx > healitem[j+1].IDidx) { + BubbleSwapItem(&healitem[j], &healitem[j+1]); + sorted = FALSE; + } + } + k--; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnHealer(int lvl) +{ + int itype; + int i,nsi,srnd; + + // Will always have healing (endless supply) + GetItemAttrs(0, IDI_HEAL, 1); + healitem[0] = item[0]; + healitem[0]._iCreateInfo = lvl; + healitem[0]._iStatFlag = TRUE; + GetItemAttrs(0, IDI_FULLHEAL, 1); + healitem[1] = item[0]; + healitem[1]._iCreateInfo = lvl; + healitem[1]._iStatFlag = TRUE; + if (gbMaxPlayers != 1) { + GetItemAttrs(0, IDI_RESURRECT, 1); + healitem[2] = item[0]; + healitem[2]._iCreateInfo = lvl; + healitem[2]._iStatFlag = TRUE; + srnd = 3; + } else srnd = 2; + + nsi = random(50, 8) + 10; + for (i = srnd; i < nsi; i++) { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndHealerItem(lvl) - 1; + GetItemAttrs(0, itype, lvl); + healitem[i] = item[0]; + healitem[i]._iCreateInfo = lvl | ICI_HEALER; + healitem[i]._iIdentified = TRUE; + healitem[i]._iStatFlag = StoreStatOk(&healitem[i]); + } + for (i = nsi; i < MAXHEALITEMS; i++) healitem[i]._itype = -1; + SortHealer(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnStoreGold() +{ + // Setup a gold item to place in inv if they sell + GetItemAttrs(0, 0, 1); + golditem = item[0]; + golditem._iStatFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreateSmithItem(int ii, int idx, int lvl, int iseed) +{ + SetRndSeed(iseed); + int itype = RndSmithItem(lvl) - 1; + GetItemAttrs(ii, itype, lvl); + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = lvl | ICI_SMITH; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreatePremiumItem(int ii, int idx, int plvl, int iseed) +{ + SetRndSeed(iseed); + int itype = RndPremiumItem(plvl>>2, plvl) - 1; + GetItemAttrs(ii, itype, plvl); + GetItemBonus(ii, itype, plvl>>1, plvl, TRUE); + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = plvl | ICI_PREMIUM; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreateBoyItem(int ii, int idx, int lvl, int iseed) +{ + SetRndSeed(iseed); + int itype = RndBoyItem(lvl) - 1; + GetItemAttrs(ii, itype, lvl); + // Always magical + GetItemBonus(ii, itype, lvl, lvl << 1, TRUE); + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = lvl | ICI_BOY; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreateWitchItem(int ii, int idx, int lvl, int iseed) +{ + if ((idx == IDI_MANA) || (idx == IDI_FULLMANA) || (idx == IDI_PORTAL)) { + GetItemAttrs(ii, idx, lvl); + } else { + SetRndSeed(iseed); + int itype = RndWitchItem(lvl) - 1; + GetItemAttrs(ii, itype, lvl); + int iblvl = -1; + if (random(51, 100) <= 5) iblvl = lvl << 1; + // Force staffs to be magical + if ((iblvl == -1) && (item[ii]._iMiscId == IMID_STAFF)) iblvl = lvl << 1; +#if CHEATS + if (cheatflag) iblvl = lvl << 1; +#endif + if (iblvl != -1) GetItemBonus(ii, itype, iblvl >> 1, iblvl, TRUE); + } + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = lvl | ICI_WITCH; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreateHealerItem(int ii, int idx, int lvl, int iseed) +{ + if ((idx == IDI_HEAL) || (idx == IDI_FULLHEAL) || (idx == IDI_RESURRECT)) { + GetItemAttrs(ii, idx, lvl); + } else { + SetRndSeed(iseed); + int itype = RndHealerItem(lvl) - 1; + GetItemAttrs(ii, itype, lvl); + } + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = lvl | ICI_HEALER; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +** Recreate any item with the proper info +**-----------------------------------------------------------------------*/ + +void RecreateTownItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue) +{ + if (icreateinfo & ICI_SMITH) RecreateSmithItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); + else if (icreateinfo & ICI_PREMIUM) RecreatePremiumItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); + else if (icreateinfo & ICI_BOY) RecreateBoyItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); + else if (icreateinfo & ICI_WITCH) RecreateWitchItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); + else if (icreateinfo & ICI_HEALER) RecreateHealerItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DaveGold() +{ + int i,j; + + for (j = 0; j < MAXINV; j++) { + if (plr[myplr].InvGrid[j] == 0) { + i = plr[myplr]._pNumInv; + SetPlrHandItem(&plr[myplr].InvList[i], IDI_GOLD); + GetGoldSeed(myplr, &plr[myplr].InvList[i]); + plr[myplr].InvList[i]._ivalue = 5000; + plr[myplr].InvList[i]._iCurs = ITEM_5GOLD; + plr[myplr].InvList[i]._iStatFlag = TRUE; + plr[myplr]._pGold += 5000; + plr[myplr]._pNumInv++; + plr[myplr].InvGrid[j] = plr[myplr]._pNumInv; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DaveNewPremium() +{ + numpremium = 0; + for (int i = 0; i < MAXPREMIUM; i++) premiumitem[i]._itype = -1; + SpawnPremium(30); + for (i = 0; i < MAXWITCHITEMS; i++) witchitem[i]._itype = -1; + SpawnWitch(30); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DaveCleanUp() +{ + int i,j; + + for (j = 0; j < MAXINV; j++) { + if (plr[myplr].InvGrid[j] > 0) { + i = plr[myplr].InvGrid[j]-1; + if (plr[myplr].InvList[i]._itype == IT_GOLD) RemoveInvItem(myplr, i); + } + } + for (j = 0; j < MAXSPD; j++) { + if (plr[myplr].SpdList[j]._itype == IT_GOLD) plr[myplr].SpdList[j]._itype = -1; + } + plr[myplr]._pGold = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DaveSpells() +{ + for (int i = SPL_FIREBOLT; i < SPL_LAST; i++) { + if (spelldata[i].sBookLvl != -1) { + __int64 t = 1; + plr[myplr]._pMemSpells |= (t << (i-1)); + plr[myplr]._pSplLvl[i] = 10; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DaveSetSpell(int spl, int lvl) +{ + __int64 t = 1; + plr[myplr]._pMemSpells |= (t << (spl-1)); + plr[myplr]._pSplLvl[spl] = lvl; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DaveSpells2() +{ + DaveSetSpell(SPL_FIREBOLT, 8); + DaveSetSpell(SPL_CBOLT, 11); + DaveSetSpell(SPL_HBOLT, 10); + DaveSetSpell(SPL_HEAL, 7); + DaveSetSpell(SPL_HEALOTHER, 5); + DaveSetSpell(SPL_LIGHTNING, 9); + DaveSetSpell(SPL_WALL, 5); + DaveSetSpell(SPL_TELEKINESIS, 3); + DaveSetSpell(SPL_TOWN, 3); + DaveSetSpell(SPL_FLASH, 3); + DaveSetSpell(SPL_PHASE, 2); + DaveSetSpell(SPL_MANASHLD, 2); + DaveSetSpell(SPL_WAVE, 4); + DaveSetSpell(SPL_FIREBALL, 3); + DaveSetSpell(SPL_STONE, 1); + DaveSetSpell(SPL_CHAIN, 1); + DaveSetSpell(SPL_GUARDIAN, 4); + DaveSetSpell(SPL_ELEMENT, 3); + DaveSetSpell(SPL_NOVA, 1); + DaveSetSpell(SPL_GOLEM, 2); + DaveSetSpell(SPL_BSTAR, 1); + DaveSetSpell(SPL_BONESPIRIT, 1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RecalcStoreStats() +{ + int i; + + for (i = 0; i < MAXSMITHITEMS; i++) + if (smithitem[i]._itype != -1) smithitem[i]._iStatFlag = StoreStatOk(&smithitem[i]); + for (i = 0; i < MAXPREMIUM; i++) + if (premiumitem[i]._itype != -1) premiumitem[i]._iStatFlag = StoreStatOk(&premiumitem[i]); + for (i = 0; i < MAXWITCHITEMS; i++) + if (witchitem[i]._itype != -1) witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]); + for (i = 0; i < MAXHEALITEMS; i++) + if (healitem[i]._itype != -1) healitem[i]._iStatFlag = StoreStatOk(&healitem[i]); + boyitem._iStatFlag = StoreStatOk(&boyitem); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int ItemNoFlippy() +/*-----------------------------------------------------------------------** +** DESCRIPTION: Makes it so a newly created item will not have a flippy. +** INPUT: None +** RETURN: r = The item number if needed. +/*-----------------------------------------------------------------------*/ +{ + int r; + + r = itemactive[numitems-1]; + item[r]._iAnimFrame = item[r]._iAnimLen; + item[r]._iAnimFlag = FALSE; + item[r]._iSelFlag = ISEL_FLR; + + return r; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if CHEATS +void DaveQuestText() +{ + if (!tstQMsgIndexFlag) { + tstQMsgFlag = TRUE; + InitQTextMsg(tstQMsgIndex); + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CreateSpellBook(int x, int y, int ispell, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + BOOL done = FALSE; + + int bookminlevel = spelldata[ispell].sBookLvl + 1; + + if (bookminlevel < 1) // unavailable + return; + + idx = RndTypeItems(IT_MISC, IMID_BOOK, currlevel); + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + //Loop until we get the book requested + do { + SetupAllItems(ii, idx, GetRndSeed(), /* currlevel */ bookminlevel << 1, 1, TRUE, FALSE, delta); + if ((item[ii]._iMiscId == IMID_BOOK) && + (item[ii]._iSpell == ispell)) { + done = TRUE; + } + } while (!done); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CreateMagicArmor(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + BOOL done = FALSE; + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + //Loop until we get the armor requested + idx = RndTypeItems(imisc, IMID_NONE, currlevel); + do { +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), currlevel << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), currlevel << 1, 1, TRUE, FALSE, delta); + if (item[ii]._iCurs == icurs) { + done = TRUE; + } else idx = RndTypeItems(imisc, IMID_NONE, currlevel); + } while (!done); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CreateAmulet(int x, int y, int level, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + bool done = false; + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + //Loop until we get the amulet requested + idx = RndTypeItems(IT_AMULET, IMID_AMULET, level); + do { +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), level << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), level << 1, 1, TRUE, FALSE, delta); + if (item[ii]._iCurs == ITEM_AMULET1) { + done = true; + } else idx = RndTypeItems(IT_AMULET, IMID_AMULET, level); + } while (!done); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CreateMagicWeapon(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + BOOL done = FALSE; + int const imid = (imisc == IT_STAFF) ? IMID_STAFF : IMID_NONE; + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + //Loop until we get the weapon requested + idx = RndTypeItems(imisc, imid, currlevel); + do { +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), currlevel << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), currlevel << 1, 1, TRUE, FALSE, delta); + if (item[ii]._iCurs == icurs) { + done = TRUE; + } else idx = RndTypeItems(imisc, imid, currlevel); + } while (!done); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + + +// PATCH1.JMM +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void DeleteGetRecord( int nIndex ) { + app_assert(nIndex < gnNumGetRecords); + app_assert(gnNumGetRecords > 0); + + gnNumGetRecords--; + + if(gnNumGetRecords == 0) + return; + + itemgets[nIndex].nIndex = itemgets[gnNumGetRecords].nIndex; + itemgets[nIndex].nSeed = itemgets[gnNumGetRecords].nSeed; + itemgets[nIndex].wCI = itemgets[gnNumGetRecords].wCI; + itemgets[nIndex].dwTimestamp = itemgets[gnNumGetRecords].dwTimestamp; +} + + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#define RESEND_TIME 6000 // number of milliseconds to keep a getrecord around + +BOOL CheckGetRecord( int nSeed, WORD wCI, int nIndex ) { + DWORD dwCurr = GetTickCount(); + int i; + + for(i = 0; i < gnNumGetRecords; i++) { + if( (dwCurr - itemgets[i].dwTimestamp) > RESEND_TIME ) { + DeleteGetRecord( i ); + i--; + continue; + } + + if( (nSeed == itemgets[i].nSeed) && (wCI == itemgets[i].wCI) && (nIndex == itemgets[i].nIndex) ) + return FALSE; + + } + + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddGetRecord( int nSeed, WORD wCI, int nIndex ) { + DWORD dwCurr = GetTickCount(); + + if(gnNumGetRecords == MAXITEMS) + return; + + itemgets[gnNumGetRecords].dwTimestamp = dwCurr; + itemgets[gnNumGetRecords].nSeed = nSeed; + itemgets[gnNumGetRecords].wCI = wCI; + itemgets[gnNumGetRecords].nIndex = nIndex; + + gnNumGetRecords++; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RemoveGetRecord( int nSeed, WORD wCI, int nIndex ) { + DWORD dwCurr = GetTickCount(); + int i; + + for(i = 0; i < gnNumGetRecords; i++) { + if( (dwCurr - itemgets[i].dwTimestamp) > RESEND_TIME ) { + DeleteGetRecord( i ); + i--; + continue; + } + + if( (nSeed == itemgets[i].nSeed) && (wCI == itemgets[i].wCI) && (nIndex == itemgets[i].nIndex) ) { + DeleteGetRecord( i ); + return; + } + + } + +} + + +//ENDPATCH1.JMM diff --git a/src/ITEMS.CPP b/src/ITEMS.CPP new file mode 100644 index 0000000..e402f17 --- /dev/null +++ b/src/ITEMS.CPP @@ -0,0 +1,5992 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Items file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/ITEMS.CPP 4 2/06/97 6:08p Jessmac $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "objects.h" +#include "items.h" +#include "itemdat.h" +#include "engine.h" +#include "gendung.h" +#include "player.h" +#include "control.h" +#include "monster.h" +#include "spells.h" +#include "quests.h" +#include "cursor.h" +#include "effects.h" +#include "lighting.h" +#include "stores.h" +#include "spelldat.h" +#include "scrollrt.h" +#include "inv.h" +#include "msg.h" +#include "multi.h" +#include "monstdat.h" +#include "doom.h" +#include "missiles.h" +#include "minitext.h" +#include "storm.h" +#include "DRLG_l1.h" +#include "packplr.h" +#include "textdat.h" + + +void RecreateTownItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue); +void SaveItemPower(int i, int power, int param1, int param2, int minval, int maxval, int multval); +void GetItemPower(int i, int minlvl, int maxlvl, long flgs, BOOL onlygood); +void GetItemAttrs(int i, int idata, int lvl); +void SetupItem(int); +void RecalcStoreStats(); +void SpawnMap(); +void DeleteItem(int ii, int i); + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ +CornerStoneType CornerStone; +extern char gszProgKey[]; + +int GOLD_VMAX = 5000; +const int GOLD_DOUBLE_VMAX = 2 * GOLD_VMAX; +ItemStruct item[MAXITEMS+1]; +long numitems = 0; + +int itemactive[MAXITEMS]; +int itemavail[MAXITEMS]; +int tem; + +//PATCH1.JMM +ItemGetRecordStruct itemgets[MAXITEMS]; +int gnNumGetRecords = 0; +//ENDPATCH1.JMM + + + +BOOL UniqueItemFlag[MAXUITEMS]; +BOOL uitemflag; +ItemStruct curruitem; +#if CHEATS +extern BOOL itemcheat; + +BOOL davecheat = FALSE; +#endif + +BOOL itemhold[3][3]; + + +#define MAXOIL 10 + +int OilLvlTbl[MAXOIL]= { 1, 10, 1, 10, 4, 1, 5, 17, 1, 10 }; +int OilValue[MAXOIL] = { 500, 2500, 500, 2500, 1500, 100, 2500, 15000, 500, 2500 }; +int OilIdVal[MAXOIL] = { + IMID_OILACC, + IMID_OILMAST, + IMID_OILSHRP, + IMID_OILDEATH, + IMID_OILSKILL, + IMID_OILBLKSM, + IMID_OILFORT, + IMID_OILPERM, + IMID_OILHARD, + IMID_OILIMPER +}; +char OilStr[MAXOIL][25] = { + "Oil of Accuracy", + "Oil of Mastery", + "Oil of Sharpness", + "Oil of Death", + "Oil of Skill", + "Blacksmith Oil", + "Oil of Fortitude", + "Oil of Permanence", + "Oil of Hardening", + "Oil of Imperviousness" +}; + +BYTE ItemCAnimTbl[ITEM_LAST_ID] = { + // 1x1 + 20, // ITEM_BLUEBTL + 16, // ITEM_SCROLL + 16, // ITEM_SCROLL2 + 16, // ITEM_SCROLL3 + 4, // ITEM_1GOLD + 4, // ITEM_3GOLD + 4, // ITEM_5GOLD + 12, // ITEM_GOLDRING + 12, // ITEM_1JRING + 12, // ITEM_WOODRING + 12, // ITEM_BLUERING + 12, // ITEM_3JRING + 12, // ITEM_SLVRRING + 12, // ITEM_MJRING + 12, // ITEM_BRNRING + 21, // ITEM_SPECTRAL + 21, // ITEM_3COLORPOT + 25, // ITEM_GOLDENELIX + 12, // ITEM_EMPYBAND + 28, // ITEM_EAR1 + 28, // ITEM_EAR2 + 28, // ITEM_EAR3 + 38, // ITEM_SPHERE + 38, // ITEM_CUBE + 38, // ITEM_PYRIMID + 32, // ITEM_BLOODGEM + 38, // ITEM_JSPHERE + 38, // ITEM_JCUBE + 38, // ITEM_JPYRIMID + 24, // ITEM_VILE + 24, // ITEM_BLKBTL + 26, // ITEM_WHTEBTL + 2, // ITEM_REDBTL + 25, // ITEM_YELBTL + 22, // ITEM_ORGBTL + 23, // ITEM_BREDBTL + 24, // ITEM_BLKBTL2 + 25, // ITEM_GOLDBTL + 27, // ITEM_LTBLUEBTL + 27, // ITEM_BLUEBTL2 + 29, // ITEM_BRAIN + 0, // ITEM_CLAW + 0, // ITEM_FANG + 0, // ITEM_BREAD + 12, // ITEM_AMULET + 12, // ITEM_AMULET1 + 12, // ITEM_AMULET2 + 12, // ITEM_AMULET3 + 12, // ITEM_AMULET4 + 0, // ITEM_POUCH1 + // 1x2 + 8, // ITEM_DAGGER1 + 8, // ITEM_DAGGER2 + 0, // ITEM_BIGBOTTLE + 8, // ITEM_DAGGER3 + 8, // ITEM_DAGGER4 + 8, // ITEM_DAGGER5 + // 1x3 + 8, // ITEM_BLADE + 8, // ITEM_BASTSRD + 8, // ITEM_FALCHION + 6, // ITEM_MACE + 8, // ITEM_LONGSRD + 8, // ITEM_BROADSRD + 8, // ITEM_SCIMITAR + 6, // ITEM_MORNSTAR + 8, // ITEM_SHORTSRD + 8, // ITEM_CLAYMORE + 6, // ITEM_CLUB + 8, // ITEM_SABRE + 8, // ITEM_KNTSWORD + 6, // ITEM_CLUB1 + 6, // ITEM_CLUB2 + 6, // ITEM_CLUB3 + 8, // ITEM_SCIMITAR2 + 8, // ITEM_MAGSWORD + 8, // ITEM_SKULSWORD + // 2x2 + 5, // ITEM_HELM + 9, // ITEM_ROCK + 13, // ITEM_SKCROWN + 13, // ITEM_CROWN + 13, // ITEM_MCROWN + 5, // ITEM_JESTER + 5, // ITEM_HARLEQ + 5, // ITEM_FHELM + 15, // ITEM_BUCKLER + 5, // ITEM_FHELM2 + 5, // ITEM_GRTHELM + 18, // ITEM_BOOK1 + 18, // ITEM_BOOK2 + 18, // ITEM_BOOK3 + 30, // ITEM_MUSHROOM + 5, // ITEM_SKLCAP + 5, // ITEM_LCAP + 14, // ITEM_FLESH + 5, // ITEM_SKLCAP2 + 14, // ITEM_CLOTHES + 13, // ITEM_CROWN2 + 16, // ITEM_MAP + 18, // ITEM_BOOK4 + 5, // ITEM_FHELM3 + 5, // ITEM_SAMHELM + // 2x3 + 7, // ITEM_LRGSHIELD + 1, // ITEM_BTLAXE + 3, // ITEM_LONGBOW + 17, // ITEM_PARMOR + 1, // ITEM_AXE + 15, // ITEM_WSHIELD + 10, // ITEM_CLEAVER + 14, // ITEM_STDARMOR + 3, // ITEM_COMPBOW + 11, // ITEM_SHRTSTAFF + 8, // ITEM_2HSWORD + 0, // ITEM_CHARMOR + 1, // ITEM_SMALLAXE + 7, // ITEM_HVYSHIELD + 0, // ITEM_SCLARMOR + 7, // ITEM_SMLSHIELD + 15, // ITEM_SKULLSHLD + 7, // ITEM_WOLFSHLD + 3, // ITEM_SHORTBOW + 3, // ITEM_STLLONGBOW + 3, // ITEM_STLSHRTBOW + 6, // ITEM_SMLWARHAM + 6, // ITEM_MAUL + 11, // ITEM_IRONSTAFF + 11, // ITEM_STLSTAFF + 11, // ITEM_LONGSTAFF + 31, // ITEM_INNSIGN + 14, // ITEM_HLARMOR + 14, // ITEM_RAGS + 14, // ITEM_QARMOR + 6, // ITEM_BALLNCHN + 6, // ITEM_FLAIL + 7, // ITEM_TSHIELD + 3, // ITEM_HNTRBOW + 8, // ITEM_GRTSWORD + 14, // ITEM_LARMOR + 0, // ITEM_SPLTARMOR + 14, // ITEM_ROBE + 14, // ITEM_HVYROBE + 0, // ITEM_RINGARMOR + 33, // ITEM_ANVIL + 1, // ITEM_BROADAXE + 1, // ITEM_LRGAXE + 1, // ITEM_WICKAXE + 1, // ITEM_HANDAXE + 1, // ITEM_GREATAXE + 7, // ITEM_IRONSHLD + 7, // ITEM_KITESHLD + 7, // ITEM_LRGSHLD + 14, // ITEM_CLOAK + 14, // ITEM_CAPE + 17, // ITEM_PARMOR2 + 17, // ITEM_PARMOR3 + 17, // ITEM_BPLATE + 0, // ITEM_RINGMAIL + 34, // ITEM_BISHOPSTF + 1, // ITEM_GEMGRTAXE + 0, // ITEM_ARKARMOR + 3, // ITEM_CROSBOW + 17, // ITEM_NAJARMOR + 8, // ITEM_GRIZZLY + 8, // ITEM_GRANDPA + 6, // ITEM_PROTECT + 1, // ITEM_REAVER + 3, // ITEM_WINDFOR + 3, // ITEM_SWARBOW + 11, // ITEM_COMPSTF + 3, // ITEM_SBATLBOW +// Misc +// 4, // ITEM_GOLD + +// new 1x1 + 12, // ITEM_MERLINRING + 12, // ITEM_MANARING + 12, // ITEM_AMULWARD + 12, // ITEM_NECMAGIC + 12, // ITEM_NECHEALTH + 12, // ITEM_KARIKSRING + 12, // ITEM_RINGGROUND + 12, // ITEM_AMULPROT + 12, // ITEM_MERCRING + 12, // ITEM_RINGTHUND + 12, // ITEM_NECTRUTH + 12, // ITEM_RINGGIANTS + 12, // ITEM_AMULGOLD + 12, // ITEM_RINGMYSTIC + 12, // ITEM_RINGCOPPER + 12, // ITEM_AMULACOLYT + 12, // ITEM_RINGMAGMA + 12, // ITEM_NECPURIFY + 12, // ITEM_RINGGLADTR + 35, // ITEM_RUNEBOMB + 39, // ITEM_THEODORE + 36, // ITEM_TORNPAPER1 + 36, // ITEM_TORNPAPER2 + 36, // ITEM_TORNPAPER3 + 37, // ITEM_WHOLEPAPER + 38, // ITEM_FIRERUNE1 + 38, // ITEM_FIRERUNE2 + 38, // ITEM_LIGHTRUNE1 + 38, // ITEM_LIGHTRUNE2 + 38, // ITEM_STONERUNE +// new 2x2 + 41, + 42, +// new 1x3 + 8, // ITEM_SWORDEDGE + 8, // ITEM_SWORDGLAM + 8, // ITEM_SWORDSERR +// new 2x3 + 17, // ITEM_ARMRDARK + 0, // ITEM_ARMRBONECH + 6, // ITEM_HAMRTHUND + 8, // ITEM_SWRDCRYSTL + 11, // ITEM_STAFJESTER + 11, // ITEM_STAFMANA + 3, // ITEM_BOWVULCAN + 3, // ITEM_BOWSPEED + 1, // ITEM_AXEANCIENT + 6, // ITEM_CLUBCARNAG + 6, // ITEM_MACEDARK + 6, // ITEM_CLUBDECAY + 1, // ITEM_AXEDECAY + 8, // ITEM_SWRDDECAY + 6, // ITEM_MACEDECAY + 11, // ITEM_STAFDECAY + 3, // ITEM_BOWDECAY + 6, // ITEM_CLUBOUCH + 8, // ITEM_SWRDDEVAST + 1, // ITEM_AXEDEVAST + 6, // ITEM_MORNDEVAST + 6, // ITEM_MACEDEVAST + 17, // ITEM_ARMRDMNPLT + 40, + }; + + +char *ItemFiles[] = { + "Armor2", // 0 + "Axe", // 1 + "FBttle", // 2 + "Bow", // 3 + "GoldFlip", // 4 + "Helmut", // 5 + "Mace", // 6 + "Shield", // 7 + "SwrdFlip", // 8 + "Rock", // 9 + "Cleaver", // 10 + "Staff", // 11 + "Ring", // 12 + "CrownF", // 13 + "LArmor", // 14 + "WShield", // 15 + "Scroll", // 16 + "FPlateAr", // 17 + "FBook", // 18 + "Food", // 19 + "FBttleBB", // 20 + "FBttleDY", // 21 + "FBttleOR", // 22 + "FBttleBR", // 23 + "FBttleBL", // 24 + "FBttleBY", // 25 + "FBttleWH", // 26 + "FBttleDB", // 27 + "FEar", // 28 + "FBrain", // 29 + "FMush", // 30 + "Innsign", // 31 + "Bldstn", // 32 + "Fanvil", // 33 + "FLazStaf", // 34 + "bombs1", // 35 + "halfps1", // 36 + "wholeps1", // 37 + "runes1", // 38 + "teddys1", // 39 + "cows1", // 40 + "donkys1", // 41 + "mooses1", // 42 +}; +#define ITEMFTYPES (sizeof(ItemFiles)/sizeof(char *)) + +BYTE *itemanims[ITEMFTYPES]; + +byte ItemAnimLs[ITEMFTYPES] = { + 15, // Armor2 + 13, // Axe + 16, // FBttle + 13, // Bow + 10, // GoldFlip + 13, // Helmut + 13, // Mace + 13, // Shield + 13, // SwrdFlip + 10, // Rock + 13, // Cleaver + 13, // Staff + 13, // Ring + 13, // Crown + 13, // LArmor + 13, // WShield + 13, // Scroll + 13, // FPlateAr + 13, // FBook + 1, // Food + 16, // FBttleBB + 16, // FBttleDY + 16, // FBttleOR + 16, // FBttleBR + 16, // FBttleBL + 16, // FBttleBY + 16, // FBttleWH + 16, // FBttleDB + 13, // FEar + 12, // FBrain + 12, // FMush + 13, // Innsign + 13, // Bldstn + 13, // Fanvil + 8, // FLazStaf + 10, // nest bomb + 16, // half paper + 16, // whole paper + 10, // runes + 10, // teddy bear + 15, + 15, + 15, +}; + +int ItemAnimSnds[ITEMFTYPES] = { + IS_FHARM, // Armor2 + IS_FAXE, // Axe + IS_FPOT, // FBttle + IS_FBOW, // Bow + IS_GOLD, // GoldFlip + IS_FCAP, // Helmet + IS_FSWOR, // Mace + IS_FSHLD, // Shield + IS_FSWOR, // SwrdFlip + IS_FROCK, // Rock + IS_FAXE, // Cleaver + IS_FSTAF, // Staff + IS_FRING, // Ring + IS_FCAP, // Crown + IS_FLARM, // LArmor + IS_FSHLD, // WShield + IS_FSCRL, // Scroll + IS_FHARM, // FPlateAr + IS_FBOOK, // FBook + IS_FLARM, // Food + IS_FPOT, // FBttleBB + IS_FPOT, // FBttleDY + IS_FPOT, // FBttleOR + IS_FPOT, // FBttleBR + IS_FPOT, // FBttleBL + IS_FPOT, // FBttleBY + IS_FPOT, // FBttleWH + IS_FPOT, // FBttleDB + IS_FBODY, // FEar + IS_FBODY, // FBrain + IS_FMUSH, // FMush + IS_ISIGN, // Innsign + IS_FBLST, // Bldstn + IS_FANVL, // Fanvil + IS_FSTAF, // FLazStaf + IS_FROCK, // Bomb + IS_FSCRL, // Half Paper + IS_FSCRL, // Whole Paper + IS_FROCK, // Rune + IS_FMUSH, // Theo + IS_FHARM, // Cow Armor + IS_FLARM, // + IS_FLARM, // +}; + +int ItemInvSnds[ITEMFTYPES] = { + IS_IHARM, // Armor2 + IS_IAXE, // Axe + IS_IPOT, // FBttle + IS_IBOW, // Bow + IS_GOLD, // GoldFlip + IS_ICAP, // Helmet + IS_ISWORD, // Mace + IS_ISHIEL, // Shield + IS_ISWORD, // SwrdFlip + IS_IROCK, // Rock + IS_IAXE, // Cleaver + IS_ISTAF, // Staff + IS_IRING, // Ring + IS_ICAP, // Crown + IS_ILARM, // LArmor + IS_ISHIEL, // WShield + IS_ISCROL, // Scroll + IS_IHARM, // FPlateAr + IS_IBOOK, // FBook + IS_IHARM, // Food + IS_IPOT, // FBttleBB + IS_IPOT, // FBttleDY + IS_IPOT, // FBttleOR + IS_IPOT, // FBttleBR + IS_IPOT, // FBttleBL + IS_IPOT, // FBttleBY + IS_IPOT, // FBttleWH + IS_IPOT, // FBttleDB + IS_IBODY, // FEar + IS_IBODY, // FBrain + IS_IMUSH, // FMush + IS_ISIGN, // Innsign + IS_IBLST, // Bldstn + IS_IANVL, // Fanvil + IS_ISTAF, // FLazStaf + IS_IROCK, // Bomb + IS_ISCROL, // Half Paper + IS_ISCROL, // Whole Paper + IS_IROCK, // Rune + IS_IMUSH, // Theo + IS_IHARM, // Cow Armor + IS_ILARM, // + IS_ILARM, // +}; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int GetEffLevel() +{ + int efflevel = currlevel; + if (currlevel >= HIVESTART && currlevel <= HIVEEND) + efflevel = currlevel - HIVESTART + 9; + if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND) + efflevel = currlevel - CRYPTSTART + 14; + + return efflevel; +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitItemGFX() { + for (int i = 0; i < ITEMFTYPES; i++) { + char filestr[64]; + sprintf(filestr, "Items\\%s.CEL", ItemFiles[i]); + app_assert(! itemanims[i]); + itemanims[i] = LoadFileInMemSig(filestr,NULL,'IGFX'); + } + + ZeroMemory(UniqueItemFlag,sizeof(UniqueItemFlag)); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL ItemPlace(int xp, int yp) { + if (dMonster[xp][yp] != 0) return FALSE; + if (dPlayer[xp][yp] != 0) return FALSE; + if (dItem[xp][yp] != 0) return FALSE; + if (dObject[xp][yp] != 0) return FALSE; + if (dFlags[xp][yp] & BFLAG_SETPC) return FALSE; + if (nSolidTable[dPiece[xp][yp]]) return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void AddInitItems() { + + int efflevel = GetEffLevel(); + int j = random(11, 3) + 3; + for (int i = 0; i < j; i++) { + int ii = itemavail[0]; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + + int xx = random(12, DMAXX - DIRTEDGE) + (DIRTEDGED2); + int yy = random(12, DMAXY - DIRTEDGE) + (DIRTEDGED2); + while (! ItemPlace(xx, yy)) { + xx = random(12, DMAXX - DIRTEDGE) + (DIRTEDGED2); + yy = random(12, DMAXY - DIRTEDGE) + (DIRTEDGED2); + } + + item[ii]._ix = xx; + item[ii]._iy = yy; + dItem[xx][yy] = ii + 1; + item[ii]._iSeed = GetRndSeed(); + SetRndSeed(item[ii]._iSeed); + if (random(12, 2)) GetItemAttrs(ii, IDI_HEAL, efflevel); + else GetItemAttrs(ii, IDI_MANA, efflevel); + item[ii]._iCreateInfo = efflevel + ICI_PREGEN; + SetupItem(ii); + item[ii]._iAnimFrame = item[ii]._iAnimLen; + item[ii]._iAnimFlag = FALSE; + item[ii]._iSelFlag = ISEL_FLR; + DeltaAddItem(ii); + numitems++; + } +} + +static void AddNote() +{ + int xx, yy; + + do + { + xx = random(12, DMAXX - DIRTEDGE) + (DIRTEDGED2); + yy = random(12, DMAXY - DIRTEDGE) + (DIRTEDGED2); + } while (! ItemPlace(xx, yy)); + + int idi; + switch(currlevel) + { + case CRYPTSTART+2: + idi = IDI_NOTE3; + break; + case CRYPTSTART+1: + idi = IDI_NOTE2; + break; + default: + idi = IDI_NOTE1; + break; + } + SpawnQuestItem(idi, xx, yy, FALSE, ISEL_FLR); + +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitItems() { + int i; + + DROPLOG("Initing items...\n"); + // Setup a gold item + GetItemAttrs(0, 0, 1); + golditem = item[0]; + golditem._iStatFlag = TRUE; + + numitems = 0; + for (i = 0; i < MAXITEMS; i++) { + item[i]._itype = 0; + item[i]._ix = 0; + item[i]._iy = 0; + item[i]._iAnimFlag = FALSE; + item[i]._iSelFlag = ISEL_NONE; + item[i]._iIdentified = FALSE; + item[i]._iPostDraw = FALSE; + } + + for (i = 0; i < MAXITEMS; i++) { + itemavail[i] = i; + itemactive[i] = 0; + } + + if (!setlevel) { + + int rs = GetRndSeed(); + + if (QuestStatus(Q_ROCK)) { + SpawnRock(); + } + if (QuestStatus(Q_ANVIL)) { + SpawnQuestItem(IDI_ANVIL, (setpc_x << 1) + 11 + DIRTEDGED2, (setpc_y << 1) + 11 + DIRTEDGED2, FALSE, ISEL_FLR); + } + if (gbCowsuit) + if (currlevel == HIVEEND) + SpawnQuestItem(IDI_SUITBRWN, 25, 25, 3, ISEL_FLR); + if (gbCowsuit) + if (currlevel == HIVESTART+2) + SpawnQuestItem(IDI_SUITGREY, 25, 25, 3, ISEL_FLR); + + if (currlevel > 0 && currlevel < 16) + AddInitItems(); + if (currlevel >= CRYPTSTART && currlevel <= CRYPTSTART+2) + AddNote(); + } + + uitemflag = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CalcPlrItemVals(int p, BOOL Loadgfx) +{ + int mind, maxd, tac, g, d, i, mi; + int bdam, btohit, bac; + int sadd, madd, dadd, vadd; + int fr, lr, mr; + int dmod, ghit, lrad; + int ihp, imana; + int spllvladd; + int enac; + int fmin, fmax, lmin, lmax; + long iflgs, iflgs2; + __int64 spl, t; + + app_assert((DWORD) p < MAX_PLRS); + + mind = 0; + maxd = 0; + tac = 0; + bdam = 0; + btohit = 0; + bac = 0; + iflgs = 0; + iflgs2 = 0; + sadd = 0; + madd = 0; + dadd = 0; + vadd = 0; + spl = 0; + fr = 0; + lr = 0; + mr = 0; + dmod = 0; + ghit = 0; + lrad = PLRLRAD; + ihp = 0; + imana = 0; + spllvladd = 0; + enac = 0; + fmin = 0; + fmax = 0; + lmin = 0; + lmax = 0; + for (i = 0; i < 7; i++) { + const ItemStruct * itm = &plr[p].InvBody[i]; + if (itm->_itype == -1) continue; + if (! itm->_iStatFlag) continue; + + mind += itm->_iMinDam; + maxd += itm->_iMaxDam; + tac += itm->_iAC; + + t = 1; + if (itm->_iSpell != 0) + spl |= t << (itm->_iSpell - 1); + + // don't give benefit of unidentified magic items + if (itm->_iMagical != IMAGIC_NONE && ! itm->_iIdentified) + continue; + + bdam += itm->_iPLDam; + btohit += itm->_iPLToHit; + + if (itm->_iPLAC) { + int tmpac = (itm->_iAC * itm->_iPLAC) / 100; + if (tmpac == 0) tmpac = 1; + bac += tmpac; + } + + iflgs |= itm->_iFlags; + iflgs2 |= itm->_iFlags2; + sadd += itm->_iPLStr; + madd += itm->_iPLMag; + dadd += itm->_iPLDex; + vadd += itm->_iPLVit; + fr += itm->_iPLFR; + lr += itm->_iPLLR; + mr += itm->_iPLMR; + dmod += itm->_iPLDamMod; + ghit += itm->_iPLGetHit; + lrad += itm->_iPLLight; + ihp += itm->_iPLHP; + imana += itm->_iPLMana; + spllvladd += itm->_iSplLvlAdd; + enac += itm->_iPLEnAc; + fmin += itm->_iFMinDam; + fmax += itm->_iFMaxDam; + lmin += itm->_iLMinDam; + lmax += itm->_iLMaxDam; + } + + // If I have no weapons, then make it min of 1-1, if shield only, 1-3 + if (mind == 0 && maxd == 0) { + mind = 1; + maxd = 1; + if ((plr[p].Hand1Item._itype == IT_SHIELD) && (plr[p].Hand1Item._iStatFlag)) + maxd = 3; + if ((plr[p].Hand2Item._itype == IT_SHIELD) && (plr[p].Hand2Item._iStatFlag)) + maxd = 3; + + // monks have fists of fury. + if (plr[p]._pClass == CLASS_MONK) + { + mind = max(mind,plr[p]._pLevel >> 1); + maxd = max(maxd,plr[p]._pLevel); + } + } + + if ((plr[p]._pSpellFlags & SF_RAGE) == SF_RAGE) { + sadd += 2 * plr[p]._pLevel; + dadd += plr[p]._pLevel + (plr[p]._pLevel/2); + vadd += 2 * plr[p]._pLevel; + } + + if ((plr[p]._pSpellFlags & SF_LETHERGY) == SF_LETHERGY) { + sadd -= 2 * plr[p]._pLevel; + dadd -= plr[p]._pLevel + (plr[p]._pLevel/2); + vadd -= 2 * plr[p]._pLevel; + } + + plr[p]._pIMinDam = mind; + plr[p]._pIMaxDam = maxd; + plr[p]._pIAC = tac; + plr[p]._pIBonusDam = bdam; + plr[p]._pIBonusToHit = btohit; + plr[p]._pIBonusAC = bac; + plr[p]._pIFlags = iflgs; + plr[p]._pIFlags2 = iflgs2; + plr[p]._pIBonusDamMod = dmod; + plr[p]._pIGetHit = ghit; + if (lrad < 2) lrad = 2; + if (lrad > 15) lrad = 15; + if ((plr[p]._pLightRad != lrad ) && (p == myplr)) { + ChangeLightRadius(plr[p]._plid, lrad); + if (lrad < 10) ChangeVisionRadius(plr[p]._pvid, 10); + else ChangeVisionRadius(plr[p]._pvid, lrad); + plr[p]._pLightRad = lrad; + } + + plr[p]._pStrength = plr[p]._pBaseStr + sadd; + if (plr[myplr]._pStrength <= 0) plr[myplr]._pStrength = 0; + plr[p]._pMagic = plr[p]._pBaseMag + madd; + if (plr[myplr]._pMagic <= 0) plr[myplr]._pMagic = 0; + plr[p]._pDexterity = plr[p]._pBaseDex + dadd; + if (plr[myplr]._pDexterity <= 0) plr[myplr]._pDexterity = 0; + plr[p]._pVitality = plr[p]._pBaseVit + vadd; + if (plr[myplr]._pVitality <= 0) plr[myplr]._pVitality = 0; + + if (plr[p]._pClass == CLASS_ROGUE) + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200; + else if (plr[p]._pClass == CLASS_MONK) + { + if (plr[p].Hand1Item._itype == IT_STAFF || // bonus for staff + plr[p].Hand2Item._itype == IT_STAFF || + (plr[p].Hand1Item._itype == -1 && // bonus for no weapons. + plr[p].Hand2Item._itype == -1) + ) + { + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 150; + } + else + { + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 300; + } + } + else if (plr[p]._pClass == CLASS_BARD) + { + if (plr[p].Hand1Item._itype == IT_SWORD // bonus for using a sword. + || plr[p].Hand2Item._itype == IT_SWORD) + { + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 150; + } + else if (plr[p].Hand1Item._itype == IT_BOW + || plr[p].Hand2Item._itype == IT_BOW) + { + // Better than a monk or warrior with a bow but not as good as a rogue. + plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 250; + } + else + { + plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100; + } + } + else if (plr[p]._pClass == CLASS_BARBARIAN) + { + if (plr[p].Hand1Item._itype == IT_AXE + || plr[p].Hand2Item._itype == IT_AXE) + { + plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 75; + } + else if (plr[p].Hand1Item._itype == IT_MACE + || plr[p].Hand2Item._itype == IT_MACE) + { + plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 75; + } + else if (plr[p].Hand1Item._itype == IT_BOW + || plr[p].Hand2Item._itype == IT_BOW) + { + // As bad as it gets + plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 300; + } + else + { + plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100; + } + + if (plr[p].Hand1Item._itype == IT_SHIELD || plr[p].Hand2Item._itype == IT_SHIELD) + { + // remove 1/2 the AC for the shield. + if (plr[p].Hand1Item._itype == IT_SHIELD) + { + plr[p]._pIAC -= plr[p].Hand1Item._iAC / 2; + } + else if (plr[p].Hand2Item._itype == IT_SHIELD) + { + plr[p]._pIAC -= plr[p].Hand2Item._iAC / 2; + } + } + else + { + // Bonus for not using a shield. + if ( !(plr[p].Hand1Item._itype == IT_STAFF || plr[p].Hand2Item._itype == IT_STAFF || + plr[p].Hand1Item._itype == IT_BOW || plr[p].Hand2Item._itype == IT_BOW) + ) + { + plr[p]._pDamageMod += (plr[p]._pVitality * plr[p]._pLevel) / 100; + } + } + // Barbarians have a natural armor (Thick skin) + plr[p]._pIAC += plr[p]._pLevel/4; + } + else + plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100; + + plr[p]._pISpells = spl; + if ((plr[p]._pRSplType == SPT_ITEM) /*|| plr[p]._pRSplType == SPT_SCROLL)*/ + && ((plr[p]._pISpells & (((__int64)1) << (plr[p]._pRSpell-1))) == 0)) { + plr[p]._pRSpell = -1; + plr[p]._pRSplType = SPT_NONE; + force_redraw = FULLDRAW; + } + plr[p]._pISplLvlAdd = spllvladd; + + plr[p]._pIEnAc = enac; + + if (plr[p]._pClass == CLASS_BARBARIAN) // Barbarians have a natural bonus. + { + mr += plr[p]._pLevel; + fr += plr[p]._pLevel; + lr += plr[p]._pLevel; + } + + if ((plr[p]._pSpellFlags & SF_LETHERGY) == SF_LETHERGY) // Lethergy causes a loss of strength + { + mr -= plr[p]._pLevel; + fr -= plr[p]._pLevel; + lr -= plr[p]._pLevel; + } + + if (iflgs & IAF_ZERORES) { + mr = 0; + fr = 0; + lr = 0; + } + + if (mr > RESIST_MAX) mr = RESIST_MAX; + else if (mr < 0) mr = 0; + plr[p]._pMagResist = mr; + + if (fr > RESIST_MAX) fr = RESIST_MAX; + else if (fr < 0) fr = 0; + plr[p]._pFireResist = fr; + + if (lr > RESIST_MAX) lr = RESIST_MAX; + else if (lr < 0) lr = 0; + plr[p]._pLghtResist = lr; + + if (plr[p]._pClass == CLASS_WARRIOR) + { + vadd = vadd << 1; + } + else if (plr[p]._pClass == CLASS_BARBARIAN) + { + vadd *= 2; + vadd += (vadd >> 2); + } + else if (plr[p]._pClass == CLASS_ROGUE || + plr[p]._pClass == CLASS_MONK || + plr[p]._pClass == CLASS_BARD ) + { + vadd += (vadd >> 1); + } + ihp += (vadd << HP_SHIFT); + if (plr[p]._pClass == CLASS_SORCEROR) + madd = madd << 1; // 2 * madd + if (plr[p]._pClass == CLASS_ROGUE || + plr[p]._pClass == CLASS_MONK ) + madd += (madd >> 1); // 1.5 * madd + else if ( plr[p]._pClass == CLASS_BARD ) + madd += (madd >> 1) + (madd >> 2); // 1.75 * madd + + imana += (madd << MANA_SHIFT); + + plr[p]._pHitPoints = plr[p]._pHPBase + ihp; + plr[p]._pMaxHP = plr[p]._pMaxHPBase + ihp; + + if (plr[p]._pHitPoints > plr[p]._pMaxHP) + plr[p]._pHitPoints = plr[p]._pMaxHP; + + if ((p == myplr) && (plr[p]._pHitPoints >> HP_SHIFT) <= 0) + SetPlayerHitPoints(p, 0); + + plr[p]._pMana = plr[p]._pManaBase + imana; + plr[p]._pMaxMana = plr[p]._pMaxManaBase + imana; + + if (plr[p]._pMana > plr[p]._pMaxMana) + plr[p]._pMana = plr[p]._pMaxMana; + + plr[p]._pIFMinDam = fmin; + plr[p]._pIFMaxDam = fmax; + plr[p]._pILMinDam = lmin; + plr[p]._pILMaxDam = lmax; + + + if (iflgs & IAF_INFRAVISION) plr[p]._pInfraFlag = TRUE; + else plr[p]._pInfraFlag = FALSE; + + plr[p]._pBlockFlag = FALSE; + if (plr[p]._pClass == CLASS_MONK) + { + if ((plr[p].Hand1Item._itype == IT_STAFF) && + (plr[p].Hand1Item._iStatFlag)) + { + plr[p]._pBlockFlag = TRUE; + plr[p]._pIFlags |= IAF_BLANIM; + } + + if ((plr[p].Hand2Item._itype == IT_STAFF) && + (plr[p].Hand2Item._iStatFlag)) + { + plr[p]._pBlockFlag = TRUE; + plr[p]._pIFlags |= IAF_BLANIM; + } + + if ((plr[p].Hand1Item._itype == -1) && + (plr[p].Hand2Item._itype == -1)) + { + plr[p]._pBlockFlag = TRUE; + } + + if ((plr[p].Hand1Item._iClass == IC_WEAP) && + (plr[p].Hand1Item._iLoc != IL_2HAND) && + (plr[p].Hand2Item._itype == -1)) + { + plr[p]._pBlockFlag = TRUE; + } + + if ((plr[p].Hand2Item._iClass == IC_WEAP) && + (plr[p].Hand2Item._iLoc != IL_2HAND) && + (plr[p].Hand1Item._itype == -1)) + { + plr[p]._pBlockFlag = TRUE; + } + } +#if 0 + // No Block art + else if (plr[p]._pClass == CLASS_BARD) + { + if ((plr[p].Hand1Item._itype == IT_SWORD) && + (plr[p].Hand1Item._iStatFlag)) + { + plr[p]._pBlockFlag = TRUE; + plr[p]._pIFlags |= IAF_BLANIM; + } + + if ((plr[p].Hand2Item._itype == IT_SWORD) && + (plr[p].Hand2Item._iStatFlag)) + { + plr[p]._pBlockFlag = TRUE; + plr[p]._pIFlags |= IAF_BLANIM; + } + } +#endif + + plr[p]._pwtype = WEAP_H2H; + // Determine which graphics to use + g = PGFX_NGUY; + if ((plr[p].Hand1Item._itype != -1) && + (plr[p].Hand1Item._iClass == IC_WEAP) && + (plr[p].Hand1Item._iStatFlag)) g = plr[p].Hand1Item._itype; + if ((plr[p].Hand2Item._itype != -1) && + (plr[p].Hand2Item._iClass == IC_WEAP) && + (plr[p].Hand2Item._iStatFlag)) g = plr[p].Hand2Item._itype; + switch (g) { + case IT_SWORD: + g = PGFX_XGUY; + break; + case IT_MACE: + g = PGFX_ZGUY; + break; + case IT_BOW: + plr[p]._pwtype = WEAP_RANGE; + g = PGFX_BGUY; + break; + case IT_AXE: + g = PGFX_FGUY; + break; + case IT_STAFF: + g = PGFX_TGUY; + break; + } + if ((plr[p].Hand1Item._itype == IT_SHIELD) && (plr[p].Hand1Item._iStatFlag)) { + plr[p]._pBlockFlag = TRUE; + g++; + } + if ((plr[p].Hand2Item._itype == IT_SHIELD) && (plr[p].Hand2Item._iStatFlag)) { + plr[p]._pBlockFlag = TRUE; + g++; + } + + #if IS_VERSION(RETAIL) || IS_VERSION(BETA) + if ((plr[p].BodyItem._itype == IT_HARMOR) && (plr[p].BodyItem._iStatFlag)) + { + if ((plr[p]._pClass == CLASS_MONK) && + (plr[p].BodyItem._iMagical == IMAGIC_UNIQUE)) + plr[p]._pIAC += plr[p]._pLevel >> 1; // Monks get 1/2 level bonus while wearing medium armor. + g += 32; + } + else if ((plr[p].BodyItem._itype == IT_MARMOR) && (plr[p].BodyItem._iStatFlag)) + { + if (plr[p]._pClass == CLASS_MONK) + { + if (plr[p].BodyItem._iMagical == IMAGIC_UNIQUE) + plr[p]._pIAC += plr[p]._pLevel << 1; // Monks get 2x level bonus while wearing light armor. + else + plr[p]._pIAC += plr[p]._pLevel >> 1; // Monks get 1/2 level bonus while wearing medium armor. + } + g += 16; + } + else + { + if (plr[p]._pClass == CLASS_MONK) + { + plr[p]._pIAC += plr[p]._pLevel << 1; // Monks get 2x level bonus for light/no armor. + } + } + #endif + + if ((plr[p]._pgfxnum != g) && (Loadgfx)) { + plr[p]._pgfxnum = g; + plr[p]._pGFXLoad = 0; // Clear all graphics loaded flag + LoadPlrGFX(p, PGL_STAND); + SetPlrAnims(p); + d = plr[p]._pdir; + + app_assert(plr[p]._pNAnim[d]); + plr[p]._pAnimData = plr[p]._pNAnim[d]; + plr[p]._pAnimLen = plr[p]._pNFrames; + plr[p]._pAnimFrame = 1; + plr[p]._pAnimCnt = 0; + plr[p]._pAnimDelay = 3; + plr[p]._pAnimWidth = plr[p]._pNWidth; + plr[p]._pAnimWidth2 = (plr[p]._pNWidth - 64) >> 1; + } + else { + plr[p]._pgfxnum = g; + } + + for (i = 0; i < nummissiles; i++) { + mi = missileactive[i]; + if (missile[mi]._mitype == MIT_MANASHIELD && missile[mi]._misource == p) { + missile[mi]._miVar1 = plr[p]._pHitPoints; + missile[mi]._miVar2 = plr[p]._pHPBase; + break; + } + } + + if (plr[p].NeckItem._itype != -1 && plr[p].NeckItem.IDidx == IDI_AURIC) + { + GOLD_VMAX = GOLD_DOUBLE_VMAX; + } + else + { + int const old_vmax = GOLD_VMAX; + + GOLD_VMAX = GOLD_DOUBLE_VMAX/2; + + if (old_vmax != GOLD_VMAX) + StripTopGold(p); + } + + drawmanaflag = TRUE; + drawhpflag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrScrolls(int p) { + int i; + __int64 t; + + plr[p]._pScrlSpells = 0; + for (i = 0; i < plr[p]._pNumInv; i++) { + if (plr[p].InvList[i]._itype != -1) { + if (((plr[p].InvList[i]._iMiscId == IMID_SCROLL) || + (plr[p].InvList[i]._iMiscId == IMID_TSCROLL)) && + (plr[p].InvList[i]._iStatFlag)) { + t = 1; + plr[p]._pScrlSpells |= (t << plr[p].InvList[i]._iSpell-1); + } + } + } + for (i = 0; i < MAXSPD; i++) { + if (plr[p].SpdList[i]._itype != -1) { + if (((plr[p].SpdList[i]._iMiscId == IMID_SCROLL) || + (plr[p].SpdList[i]._iMiscId == IMID_TSCROLL)) && + (plr[p].SpdList[i]._iStatFlag)) { + t = 1; + plr[p]._pScrlSpells |= (t << plr[p].SpdList[i]._iSpell-1); + } + } + } + + if ((plr[p]._pRSplType == SPT_SCROLL) + && ((plr[p]._pScrlSpells & (1 << (plr[p]._pRSpell-1))) == 0)) { + plr[p]._pRSpell = -1; + plr[p]._pRSplType = SPT_NONE; + force_redraw = FULLDRAW; + } + +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrStaff(int p) { + plr[p]._pISpells = 0; + if (plr[p].Hand1Item._itype == -1) return; + if (!plr[p].Hand1Item._iStatFlag) return; + if (plr[p].Hand1Item._iCharges > 0) { + __int64 t = 1; + plr[p]._pISpells |= t << (plr[p].Hand1Item._iSpell - 1); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcSelfItems(int pnum) { + int i; + ItemStruct * pi; + PlayerStruct * p = &plr[pnum]; + BOOL sf, changeflag; + int sa = 0; + int ma = 0; + int da = 0; + + // assume everything works, and calc potential + to str, mag, dex + pi = &p->InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) { + if (pi->_itype == -1) continue; + pi->_iStatFlag = TRUE; + if (!pi->_iIdentified) continue; + sa += pi->_iPLStr; + ma += pi->_iPLMag; + da += pi->_iPLDex; + } + + do { + changeflag = FALSE; + pi = &p->InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) { + if (pi->_itype == -1) continue; + if (!pi->_iStatFlag) continue; + sf = TRUE; + if ((p->_pBaseStr + sa) < pi->_iMinStr) sf = FALSE; + if ((p->_pBaseMag + ma) < pi->_iMinMag) sf = FALSE; + if ((p->_pBaseDex + da) < pi->_iMinDex) sf = FALSE; + if (!sf) { + changeflag = TRUE; + pi->_iStatFlag = FALSE; + if (pi->_iIdentified) { + sa -= pi->_iPLStr; + ma -= pi->_iPLMag; + da -= pi->_iPLDex; + } + } + } + } while (changeflag); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static BOOL ItemMinStats(const PlayerStruct * p,const ItemStruct * x) { + if (p->_pMagic < (byte)x->_iMinMag) return FALSE; + if (p->_pStrength < x->_iMinStr) return FALSE; + if (p->_pDexterity < x->_iMinDex) return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrItemMin(int pnum) { + int i; + ItemStruct * pi; + PlayerStruct * p = &plr[pnum]; + + // handle inventory + pi = &p->InvList[0]; + for (i = p->_pNumInv; i--; pi++) + pi->_iStatFlag = ItemMinStats(p,pi); + + // handle speedbar + pi = &p->SpdList[0]; + for (i = MAXSPD; i--; pi++) { + if (pi->_itype == -1) continue; + pi->_iStatFlag = ItemMinStats(p,pi); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrBookVals(int p) +{ + int i, slvl; + + void WitchBookLevel(int); + if (currlevel == 0) { + for (i = 1; witchitem[i]._itype != -1; i++) + WitchBookLevel(i); + } + + for (i = 0; i < plr[p]._pNumInv; i++) { + if ((plr[p].InvList[i]._itype == IT_MISC) && (plr[p].InvList[i]._iMiscId == IMID_BOOK)) { + plr[p].InvList[i]._iMinMag = spelldata[plr[p].InvList[i]._iSpell].sMinInt; + slvl = plr[p]._pSplLvl[plr[p].InvList[i]._iSpell]; + while (slvl != 0) { + plr[p].InvList[i]._iMinMag += ((plr[p].InvList[i]._iMinMag * 20) / 100); + slvl--; + if ((plr[p].InvList[i]._iMinMag + ((plr[p].InvList[i]._iMinMag * 20) / 100)) > 255) { + plr[p].InvList[i]._iMinMag = 255; + slvl = 0; + } + } + plr[p].InvList[i]._iStatFlag = ItemMinStats(&plr[p], &plr[p].InvList[i]); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CalcPlrInv(int p, BOOL Loadgfx) { + CalcPlrItemMin(p); + CalcSelfItems(p); + CalcPlrItemVals(p, Loadgfx); + CalcPlrItemMin(p); + if (p == myplr) { + CalcPlrBookVals(p); + CalcPlrScrolls(p); + CalcPlrStaff(p); + } + if ((p == myplr) && (currlevel == 0)) RecalcStoreStats(); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPlrHandItem(ItemStruct *h, int idata) { + const ItemDataStruct * pAllItem = &AllItemsList[idata]; + + ZeroMemory(h,sizeof(ItemStruct)); + h->_itype = pAllItem->itype; + h->_iCurs = pAllItem->iCurs; + strcpy(h->_iName, pAllItem->iName); + strcpy(h->_iIName, pAllItem->iName); + h->_iLoc = pAllItem->iLoc; + h->_iClass = pAllItem->iClass; + h->_iMinDam = pAllItem->iMinDam; + h->_iMaxDam = pAllItem->iMaxDam; + h->_iAC = pAllItem->iMinAC; + h->_iMiscId = pAllItem->iMiscId; + h->_iSpell = pAllItem->iSpell; + if (pAllItem->iMiscId == IMID_STAFF) h->_iCharges = 18; // was 40 + h->_iMaxCharges = h->_iCharges; + h->_iDurability = pAllItem->iDurability; + h->_iMaxDur = pAllItem->iDurability; + h->_iMinStr = pAllItem->iMinStr; + h->_iMinMag = pAllItem->iMinMag; + h->_iMinDex = pAllItem->iMinDex; + h->_ivalue = pAllItem->iValue; + h->_iIvalue = pAllItem->iValue; + h->_iPrePower = -1; + h->_iSufPower = -1; + h->IDidx = idata; + h->_iMagical = IMAGIC_NONE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GetPlrHandSeed(ItemStruct *h) +{ + h->_iSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GetGoldSeed(int pnum, ItemStruct *h) +{ + int i, ii, s; + BOOL doneflag; + + do { + doneflag = TRUE; + s = GetRndSeed(); + for (i = 0; i < numitems; i++) { + ii = itemactive[i]; + if (item[ii]._iSeed == s) doneflag = FALSE; + } + if (pnum == myplr) { + for (i = 0; i < plr[pnum]._pNumInv; i++) + if (plr[pnum].InvList[i]._iSeed == s) doneflag = FALSE; + } + } while (!doneflag); + h->_iSeed = s; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPlrHandSeed(ItemStruct *h, int iseed) +{ + h->_iSeed = iseed; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPlrHandGoldCurs(ItemStruct *h) +{ + if (h->_ivalue >= GOLD_VT2) { + h->_iCurs = ITEM_5GOLD; + } else { + if (h->_ivalue <= GOLD_VT1) h->_iCurs = ITEM_1GOLD; + else h->_iCurs = ITEM_3GOLD; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CreatePlrItems(int p) { + int i; + ItemStruct * pi; + + // zero out carried items + pi = &plr[p].InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) + pi->_itype = -1; + + // zero inventory + ZeroMemory(plr[p].InvGrid,sizeof(plr[p].InvGrid)); + pi = &plr[p].InvList[0]; + for (i = MAXINV; i--; pi++) + pi->_itype = -1; + plr[p]._pNumInv = 0; + + // zero speedbar + pi = &plr[p].SpdList[0]; + for (i = MAXSPD; i--; pi++) + pi->_itype = -1; + + switch (plr[p]._pClass) { + case CLASS_WARRIOR : + // Sword in left + SetPlrHandItem(&plr[p].Hand1Item, IDI_WARRIOR); + GetPlrHandSeed(&plr[p].Hand1Item); + + // Shield in right + SetPlrHandItem(&plr[p].Hand2Item, IDI_WARRSHLD); + GetPlrHandSeed(&plr[p].Hand2Item); + +#if CHEATS + if (!davecheat) { + SetPlrHandItem(&plr[p].HoldItem, IDI_WARRCLUB); + GetPlrHandSeed(&plr[p].HoldItem); + AutoPlace(p, 0, 1, 3, TRUE); + } +#else + // Club in inv + SetPlrHandItem(&plr[p].HoldItem, IDI_WARRCLUB); + GetPlrHandSeed(&plr[p].HoldItem); + AutoPlace(p, 0, 1, 3, TRUE); +#endif + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + break; + + case CLASS_ROGUE : + #if !IS_VERSION(SHAREWARE) + // Bow in both hands + SetPlrHandItem(&plr[p].Hand1Item, IDI_ROGUE); + GetPlrHandSeed(&plr[p].Hand1Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + case CLASS_SORCEROR : + #if !IS_VERSION(SHAREWARE) + // Staff in both hands + SetPlrHandItem(&plr[p].Hand1Item, IDI_SORCEROR); + GetPlrHandSeed(&plr[p].Hand1Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); // was mana + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); // was mana + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + case CLASS_MONK : + #if !IS_VERSION(SHAREWARE) + // Bow in both hands + SetPlrHandItem(&plr[p].Hand1Item, IDI_MONK); + GetPlrHandSeed(&plr[p].Hand1Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + case CLASS_BARD : + #if !IS_VERSION(SHAREWARE) + // Bow in both hands + SetPlrHandItem(&plr[p].Hand1Item, IDI_BARD); + GetPlrHandSeed(&plr[p].Hand1Item); + SetPlrHandItem(&plr[p].Hand2Item, IDI_BARDDAGGER); + GetPlrHandSeed(&plr[p].Hand2Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + case CLASS_BARBARIAN : + #if !IS_VERSION(SHAREWARE) + // Club in left + SetPlrHandItem(&plr[p].Hand1Item, IDI_BARBARIAN); + GetPlrHandSeed(&plr[p].Hand1Item); + + // Shield in right + SetPlrHandItem(&plr[p].Hand2Item, IDI_BARSHLD); + GetPlrHandSeed(&plr[p].Hand2Item); + SetPlrHandItem(&plr[p].SpdList[0], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[0]); + SetPlrHandItem(&plr[p].SpdList[1], IDI_HEAL); + GetPlrHandSeed(&plr[p].SpdList[1]); + #endif + break; + + } + + SetPlrHandItem(&plr[p].HoldItem, IDI_GOLD); + GetPlrHandSeed(&plr[p].HoldItem); +#if CHEATS + if (!davecheat) { + // 100 Gold + plr[p].HoldItem._ivalue = 100; + plr[p].HoldItem._iCurs = ITEM_1GOLD; + plr[p]._pGold = plr[p].HoldItem._ivalue; + i = plr[p]._pNumInv; + plr[p].InvList[i] = plr[p].HoldItem; + plr[p]._pNumInv++; + plr[p].InvGrid[30] = plr[p]._pNumInv; + } + else { + // 200000 Gold + plr[p].HoldItem._ivalue = 5000; + plr[p].HoldItem._iCurs = ITEM_5GOLD; + plr[p]._pGold = 200000; + for (int j = 0; j < 40; j++) { + GetGoldSeed(p, &plr[p].HoldItem); + i = plr[p]._pNumInv; + plr[p].InvList[i] = plr[p].HoldItem; + plr[p]._pNumInv++; + plr[p].InvGrid[j] = plr[p]._pNumInv; + } + } +#else + // 100 Gold + plr[p].HoldItem._ivalue = 100; + plr[p].HoldItem._iCurs = ITEM_1GOLD; + plr[p]._pGold = plr[p].HoldItem._ivalue; + i = plr[p]._pNumInv; + plr[p].InvList[i] = plr[p].HoldItem; + plr[p]._pNumInv++; + plr[p].InvGrid[30] = plr[p]._pNumInv; +#endif + + CalcPlrItemVals(p,FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL ItemSpaceOk(int i, int j) +{ + int pn, oi; + + if ((i < 0) || (i >= DMAXX) || (j < 0) || (j >= DMAXY)) return(FALSE); + if (dMonster[i][j] != 0) return(FALSE); + if (dPlayer[i][j] != 0) return(FALSE); + if (dItem[i][j] != 0) return(FALSE); + if (dObject[i][j] != 0) { + if (dObject[i][j] > 0) oi = dObject[i][j]-1; + else oi = -(dObject[i][j]+1); + if (object[oi]._oSolidFlag) return(FALSE); + } + if (dObject[i+1][j+1] > 0) { + oi = dObject[i+1][j+1]-1; + if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE); + } + if (dObject[i+1][j+1] < 0) { + oi = -(dObject[i+1][j+1]+1); + if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE); + } + if ((dObject[i+1][j] > 0) && (dObject[i][j+1] > 0)) { + oi = dObject[i+1][j]-1; + if (object[oi]._oSelFlag != OSEL_NONE) { + oi = dObject[i][j+1]-1; + if (object[oi]._oSelFlag != OSEL_NONE) return(FALSE); + } + } + pn = dPiece[i][j]; + if (nSolidTable[pn]) return(FALSE); + return(TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +#if CHEATS +void DaveISpaceOk(int inum) +{ + int i,j; + + for (j = 0; j < MAXDUNY; j++) { + for (i = 0; i < MAXDUNX; i++) { + if (dItem[i][j] == inum+1) + app_fatal("Item in map already"); + } + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL GetItemSpace(int x, int y, char inum) +{ + int i,j,xx,yy,rs; + BOOL savail; + + // Try surrounding squares + yy = 0; + for (j = (y-1); j <= (y+1); j++) { + xx = 0; + for (i = (x-1); i <= (x+1); i++) { + itemhold[xx][yy] = ItemSpaceOk(i,j); + xx++; + } + yy++; + } + + savail = FALSE; + for (yy = 0; yy < 3; yy++) { + for (xx = 0; xx < 3; xx++) { + if (itemhold[xx][yy]) savail = TRUE; + } + } + + // Must go here so same number of rnd calls on multiplayer machines + rs = random(13, 15) + 1; + + // No fit, no good + if (!savail) return(FALSE); + + // Place item + xx = 0; + yy = 0; + while (rs > 0) { + if (itemhold[xx][yy]) rs--; + if (rs > 0) { + xx++; + if (xx == 3) { + xx = 0; + yy++; + if (yy == 3) yy = 0; + } + } + } + xx = xx + x - 1; + yy = yy + y - 1; + item[inum]._ix = xx; + item[inum]._iy = yy; + //DaveISpaceOk(inum); + dItem[xx][yy] = inum + 1; + return(TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetSuperItemSpace(int x, int y, char inum) +{ + // try normal method first + if (GetItemSpace(x, y, inum)) return; + + int xx, yy; + + // radial search outward until a space is found + for (int l = 2; l < 50; l++) { + for (int j = -l; j <= l; j++) { + yy = y + j; + for (int i = -l; i <= l; i++) { + xx = x + i; + if (! ItemSpaceOk(xx,yy)) continue; + + // drop it + item[inum]._ix = xx; + item[inum]._iy = yy; + //DaveISpaceOk(inum); + dItem[xx][yy] = inum + 1; + return; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetSuperItemLoc(int x, int y, int &xx, int &yy) +{ + // radial search outward until a space is found + for (int l = 1; l < 50; l++) { + for (int j = -l; j <= l; j++) { + yy = y + j; + for (int i = -l; i <= l; i++) { + xx = x + i; + if (ItemSpaceOk(xx,yy)) // found it + return; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CalcItemValue(int i) +{ + int v = item[i]._iVMult1 + item[i]._iVMult2; + if (v > 0) v = item[i]._ivalue * v; + if (v < 0) v = item[i]._ivalue / v; + v += item[i]._iVAdd1 + item[i]._iVAdd2; + if (v <= 0) v = 1; + item[i]._iIvalue = v; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetBookSpell(int i, int lvl) +{ + + if (lvl == 0) lvl = 1; + int rv = random(14, SPL_LAST) + 1; + + #if IS_VERSION(SHAREWARE) + if (lvl > 5) lvl = 5; + #endif + + int bs = SPL_FIREBOLT; + int s = SPL_FIREBOLT; + while (rv > 0) { + if ((spelldata[s].sBookLvl != -1) && (lvl >= spelldata[s].sBookLvl)) { + rv--; + bs = s; + } + + s++; + if ((gbMaxPlayers == 1) && (s == SPL_RESURRECT)) s++; + if ((gbMaxPlayers == 1) && (s == SPL_HEALOTHER)) s++; + if (s == SPL_LAST) s = SPL_FIREBOLT; + } + strcat(item[i]._iName, spelldata[bs].sNameText); + strcat(item[i]._iIName, spelldata[bs].sNameText); + item[i]._iSpell = bs; + item[i]._iMinMag = spelldata[bs].sMinInt; + item[i]._ivalue += spelldata[bs].sBookCost; + item[i]._iIvalue += spelldata[bs].sBookCost; + if (spelldata[bs].sType == ST_FIRE) item[i]._iCurs = ITEM_BOOK3; + else if (spelldata[bs].sType == ST_LIGHT) item[i]._iCurs = ITEM_BOOK; + else if (spelldata[bs].sType == ST_MISC) item[i]._iCurs = ITEM_BOOK2; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetStaffPower(int i, int lvl, int bs, BOOL onlygood) +{ + int pre; + int l[256], nl; + int j, aii; + int preidx; + char istr[128]; + BOOL addok; + + // Prefix only (for a staff w/ spell) + pre = random(15, 10); + + preidx = -1; + +#if CHEATS + if ((pre == 0) || (cheatflag) || (onlygood)) { +#else + if ((pre == 0) || (onlygood)) { +#endif + nl = 0; + for (j = 0; PL_Prefix[j].PLPower != -1; j++) { + if (((PL_Prefix[j].PLIType & PLF_STAFF) != 0) && (PL_Prefix[j].PLMinLvl <= lvl)) { + addok = TRUE; + if ((onlygood) && (!PL_Prefix[j].PLOk)) addok = FALSE; + + if (addok) { + l[nl] = j; + nl++; + if (PL_Prefix[j].PLDouble) { + l[nl] = j; + nl++; + } + } + } + } + if (nl != 0) { + preidx = l[random(16, nl)]; + sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); + strcpy(item[i]._iIName, istr); + item[i]._iMagical = IMAGIC_MAGIC; + SaveItemPower(i, PL_Prefix[preidx].PLPower, PL_Prefix[preidx].PLParam1, PL_Prefix[preidx].PLParam2, PL_Prefix[preidx].PLMinVal, PL_Prefix[preidx].PLMaxVal, PL_Prefix[preidx].PLMultVal); + item[i]._iPrePower = PL_Prefix[preidx].PLPower; + } + } + if (!InfoFit(item[i]._iIName)) { + aii = item[i].IDidx; + strcpy(item[i]._iIName, AllItemsList[aii].iSName); + if (preidx != -1) { + sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); + strcpy(item[i]._iIName, istr); + } + sprintf(istr, "%s of %s", item[i]._iIName, spelldata[bs].sNameText); + strcpy(item[i]._iIName, istr); + if (!item[i]._iMagical) strcpy(item[i]._iName, item[i]._iIName); + } + CalcItemValue(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetStaffSpell(int i, int lvl, BOOL onlygood) +{ + int rv, s, bs, l; + char tstr[64]; + int maxc, minc; + + //if (random(17, 4) == 0) GetItemPower(i, lvl >> 1, lvl, PLF_STAFF, onlygood); + //else +//{ + l = lvl >> 1; + if (l == 0) l = 1; + rv = random(18, SPL_LAST) + 1; + + #if IS_VERSION(SHAREWARE) + if (lvl > 10) lvl = 10; + #endif + + s = SPL_FIREBOLT; + while (rv > 0) { + if ((spelldata[s].sStaffLvl != -1) && (l >= spelldata[s].sStaffLvl)) { + rv--; + bs = s; + } + s++; + if ((gbMaxPlayers == 1) && (s == SPL_RESURRECT)) s++; + if ((gbMaxPlayers == 1) && (s == SPL_HEALOTHER)) s++; + if (s == SPL_LAST) s = SPL_FIREBOLT; + } + sprintf(tstr, "%s of %s", item[i]._iName, spelldata[bs].sNameText); + //Check to see if string will fit + if (!InfoFit(tstr)) { + sprintf(tstr, "Staff of %s", spelldata[bs].sNameText); + } + strcpy(item[i]._iName, tstr); + strcpy(item[i]._iIName, tstr); + item[i]._iSpell = bs; + minc = spelldata[bs].sStaffMin; + maxc = spelldata[bs].sStaffMax; + item[i]._iCharges = random(19, maxc-minc+1) + minc; + item[i]._iMaxCharges = item[i]._iCharges; + item[i]._iMinMag = spelldata[bs].sMinInt; + int v = (spelldata[bs].sStaffCost * item[i]._iCharges) / 5; + item[i]._ivalue += v; + item[i]._iIvalue += v; + GetStaffPower(i, lvl, bs, onlygood); +//} +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetOilType(int i, int lvl) +{ + int n, ro, roi, j; + char OilIndexList[30]; + + if (gbMaxPlayers == 1) { + if (lvl == 0) lvl = 1; + n = 0; + for (j=0; j < MAXOIL; j++) { + if (OilLvlTbl[j] <= lvl) { + OilIndexList[n] = j; + n++; + } + } + ro = random(165, n); + roi = OilIndexList[ro]; + } else { + ro = random(165, 2); + if (ro == 0) roi = 5; + else roi = 6; + } + + strcpy(item[i]._iName, OilStr[roi]); + strcpy(item[i]._iIName, OilStr[roi]); + item[i]._iMiscId = OilIdVal[roi]; + item[i]._ivalue = OilValue[roi]; + item[i]._iIvalue = OilValue[roi]; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetItemAttrs(int i, int idata, int lvl) +{ + int rndv; + + item[i]._itype = AllItemsList[idata].itype; + item[i]._iCurs = AllItemsList[idata].iCurs; + strcpy(item[i]._iName, AllItemsList[idata].iName); + strcpy(item[i]._iIName, AllItemsList[idata].iName); + item[i]._iLoc = AllItemsList[idata].iLoc; + item[i]._iClass = AllItemsList[idata].iClass; + item[i]._iMinDam = AllItemsList[idata].iMinDam; + item[i]._iMaxDam = AllItemsList[idata].iMaxDam; + item[i]._iAC = random(20, AllItemsList[idata].iMaxAC - AllItemsList[idata].iMinAC + 1) + AllItemsList[idata].iMinAC; + item[i]._iFlags = AllItemsList[idata].iFlags; + item[i]._iFlags2 = 0; + item[i]._iMiscId = AllItemsList[idata].iMiscId; + item[i]._iSpell = AllItemsList[idata].iSpell; + item[i]._iMagical = IMAGIC_NONE; + + item[i]._ivalue = AllItemsList[idata].iValue; + item[i]._iIvalue = AllItemsList[idata].iValue; + + item[i]._iVAdd1 = 0; + item[i]._iVMult1 = 0; + item[i]._iVAdd2 = 0; + item[i]._iVMult2 = 0; + + item[i]._iPLDam = 0; + item[i]._iPLToHit = 0; + item[i]._iPLAC = 0; + + item[i]._iPLStr = 0; + item[i]._iPLMag = 0; + item[i]._iPLDex = 0; + item[i]._iPLVit = 0; + + item[i]._iCharges = 0; + item[i]._iMaxCharges = 0; + + item[i]._iDurability = AllItemsList[idata].iDurability; + item[i]._iMaxDur = AllItemsList[idata].iDurability; + item[i]._iMinStr = AllItemsList[idata].iMinStr; + item[i]._iMinMag = AllItemsList[idata].iMinMag; + item[i]._iMinDex = AllItemsList[idata].iMinDex; + + item[i]._iPLFR = 0; + item[i]._iPLLR = 0; + item[i]._iPLMR = 0; + + item[i].IDidx = idata; + + item[i]._iPLDamMod = 0; + item[i]._iPLGetHit = 0; + item[i]._iPLLight = 0; + + item[i]._iSplLvlAdd = 0; + + item[i]._iRequest = FALSE; + + item[i]._iFMinDam = 0; + item[i]._iFMaxDam = 0; + item[i]._iLMinDam = 0; + item[i]._iLMaxDam = 0; + + item[i]._iPLEnAc = 0; + + item[i]._iPLMana = 0; + item[i]._iPLHP = 0; + + item[i]._iPrePower = -1; + item[i]._iSufPower = -1; + item[i]._iFlags = 0; + item[i]._iFlags2 = 0; + + if (item[i]._iMiscId == IMID_BOOK) GetBookSpell(i, lvl); + + if (item[i]._iMiscId == IMID_OIL) GetOilType(i, lvl); + + int efflevel = GetEffLevel(); + + if (item[i]._itype == IT_GOLD) { + if (gnDifficulty == D_NORMAL) + rndv = (efflevel * 5) + random(21, efflevel * 10); + else if (gnDifficulty == D_NIGHTMARE) + rndv = ((efflevel + 16) * 5) + random(21, (efflevel + 16) * 10); + else if (gnDifficulty == D_HELL) + rndv = ((efflevel + 32) * 5) + random(21, (efflevel + 32) * 10); + + if (leveltype == 4) rndv += (rndv >> 3); + if (rndv > 5000) rndv = 5000; + item[i]._ivalue = rndv; + if (rndv >= GOLD_VT2) { + item[i]._iCurs = ITEM_5GOLD; + } else { + if (rndv <= GOLD_VT1) item[i]._iCurs = ITEM_1GOLD; + else item[i]._iCurs = ITEM_3GOLD; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndPL(int param1, int param2) +{ + return(random(22, param2 - param1 + 1) + param1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PLVal(int pv, int p1, int p2, int minv, int maxv) +{ + if (p1 == p2) return(minv); + if (minv == maxv) return(minv); + return((((((pv - p1) * 100) / (p2 - p1)) * (maxv - minv)) / 100) + minv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SaveItemPower(int i, int power, int param1, int param2, int minval, int maxval, int multval) +{ + int r, r2; + + r = RndPL(param1, param2); + switch (power) { + case PL_TOHIT: + item[i]._iPLToHit += r; + break; + case PL_NTOHIT: + item[i]._iPLToHit -= r; + break; + case PL_TODAM: + item[i]._iPLDam += r; + break; + case PL_NTODAM: + item[i]._iPLDam -= r; + break; + case PL_DOPPEL: + item[i]._iFlags2 |= IAF2_CLONE; + // fall through + case PL_DAHT: + r = RndPL(param1, param2); + item[i]._iPLDam += r; + if (param1 == 20) r2 = RndPL(1, 5); + if (param1 == 36) r2 = RndPL(6, 10); + if (param1 == 51) r2 = RndPL(11, 15); + if (param1 == 66) r2 = RndPL(16, 20); + if (param1 == 81) r2 = RndPL(21, 30); + if (param1 == 96) r2 = RndPL(31, 40); + if (param1 == 111) r2 = RndPL(41, 50); + if (param1 == 126) r2 = RndPL(51, 75); + if (param1 == 151) r2 = RndPL(76, 100); + item[i]._iPLToHit += r2; + break; + + case PL_NDAHT: + item[i]._iPLDam -= r; + if (param1 == 25) r2 = RndPL(1, 5); + if (param1 == 50) r2 = RndPL(6, 10); + item[i]._iPLToHit -= r2; + break; + case PL_AC: + item[i]._iPLAC += r; + break; + case PL_NAC: + item[i]._iPLAC -= r; + break; + case PL_ACTUALAC: + item[i]._iAC = r; + break; + case PL_NACTULAC: + item[i]._iAC -= r; + break; + case PL_RFIRE: + item[i]._iPLFR += r; + break; + case PL_RLGHT: + item[i]._iPLLR += r; + break; + case PL_RMAG: + item[i]._iPLMR += r; + break; + case PL_RALL: + item[i]._iPLFR += r; + item[i]._iPLLR += r; + item[i]._iPLMR += r; + if (item[i]._iPLFR < 0) item[i]._iPLFR = 0; + if (item[i]._iPLLR < 0) item[i]._iPLLR = 0; + if (item[i]._iPLMR < 0) item[i]._iPLMR = 0; + break; + case PL_SLVL: + item[i]._iSplLvlAdd = r; + break; + case PL_CHRG : + item[i]._iCharges = item[i]._iCharges * param1; + item[i]._iMaxCharges = item[i]._iCharges; + break; + case PL_SPELL : + item[i]._iSpell = param1; + item[i]._iCharges = param2; + item[i]._iMaxCharges = param2; + break; + case PL_FHIT: + item[i]._iFlags |= IAF_FIREHIT; + item[i]._iFlags &= ~IAF_LIGHTHIT; + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 0; + item[i]._iLMaxDam = 0; + break; + case PL_LHIT: + item[i]._iFlags |= IAF_LIGHTHIT; + item[i]._iFlags &= ~IAF_FIREHIT; + item[i]._iLMinDam = param1; + item[i]._iLMaxDam = param2; + item[i]._iFMinDam = 0; + item[i]._iFMaxDam = 0; + break; + case PL_STR: + item[i]._iPLStr += r; + break; + case PL_NSTR: + item[i]._iPLStr -= r; + break; + case PL_MAG: + item[i]._iPLMag += r; + break; + case PL_NMAG: + item[i]._iPLMag -= r; + break; + case PL_DEX: + item[i]._iPLDex += r; + break; + case PL_NDEX: + item[i]._iPLDex -= r; + break; + case PL_VIT: + item[i]._iPLVit += r; + break; + case PL_NVIT: + item[i]._iPLVit -= r; + break; + case PL_STATS: + item[i]._iPLStr += r; + item[i]._iPLMag += r; + item[i]._iPLDex += r; + item[i]._iPLVit += r; + break; + case PL_NSTATS: + item[i]._iPLStr -= r; + item[i]._iPLMag -= r; + item[i]._iPLDex -= r; + item[i]._iPLVit -= r; + break; + case PL_GETHIT: + item[i]._iPLGetHit += r; + break; + case PL_NGETHIT: + item[i]._iPLGetHit -= r; + break; + case PL_HP: + item[i]._iPLHP += (r << HP_SHIFT); + break; + case PL_NHP: + item[i]._iPLHP -= (r << HP_SHIFT); + break; + case PL_MANA: + item[i]._iPLMana += (r << MANA_SHIFT); + drawmanaflag = TRUE; + break; + case PL_NMANA: + item[i]._iPLMana -= (r << MANA_SHIFT); + drawmanaflag = TRUE; + break; + case PL_DUR: + r2 = (item[i]._iMaxDur * r) / 100; + item[i]._iMaxDur += r2; + item[i]._iDurability += r2; + break; + case PL_FRAGILE: + item[i]._iPLDam += 140 + r * 2; + // fall through + case PL_NDUR: + r2 = (item[i]._iMaxDur * r) / 100; + item[i]._iMaxDur -= r2; + if (item[i]._iMaxDur < 1) item[i]._iMaxDur = 1; + item[i]._iDurability = item[i]._iMaxDur; + break; + case PL_IND: + item[i]._iDurability = INFINITE_DUR; + item[i]._iMaxDur = INFINITE_DUR; + break; + case PL_LIGHT: + item[i]._iPLLight += param1; + break; + case PL_NLIGHT: + item[i]._iPLLight -= param1; + break; + case PL_NUMARWS: + item[i]._iFlags |= IAF_RABID; // unused -> multimissile --donald + break; + case PL_FARROW: + item[i]._iFlags |= IAF_FIREARROW; + item[i]._iFlags &= ~IAF_LARROW; + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 0; + item[i]._iLMaxDam = 0; + break; + case PL_LARROW: + item[i]._iFlags |= IAF_LARROW; + item[i]._iFlags &= ~IAF_FIREARROW; + item[i]._iLMinDam = param1; + item[i]._iLMaxDam = param2; + item[i]._iFMinDam = 0; + item[i]._iFMaxDam = 0; + break; + case PL_HITADD: // usurped for fireball arrows... + item[i]._iFlags |= (IAF_LARROW | IAF_FIREARROW); + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 0; + item[i]._iLMaxDam = 0; + break; + case PL_THORN: + item[i]._iFlags |= IAF_THORN; + break; + case PL_LMANA: + item[i]._iFlags |= IAF_LMANA; + drawmanaflag = TRUE; + break; + case PL_NOHEAL: + item[i]._iFlags |= IAF_NOHEAL; + break; + case PL_TRAPDAM: + item[i]._iFlags |= IAF_TRAPDAM; + break; + case PL_BEAR: + item[i]._iFlags |= IAF_KNOCKBACK; + break; + case PL_DAMDEMON: + item[i]._iFlags |= IAF_DAMDEMON; + break; + case PL_ZERORES: + item[i]._iFlags |= IAF_ZERORES; + break; + case PL_MNOHEAL: + item[i]._iFlags |= IAF_MNOHEAL; + break; + case PL_BAT: + if (param1 == 3) item[i]._iFlags |= IAF_BAT10; + if (param1 == 5) item[i]._iFlags |= IAF_BAT20; + drawmanaflag = TRUE; + break; + case PL_LEECH: + if (param1 == 3) item[i]._iFlags |= IAF_LEECH10; + if (param1 == 5) item[i]._iFlags |= IAF_LEECH20; + drawhpflag = TRUE; + break; + case PL_ENAC: + item[i]._iPLEnAc = param1; + break; + case PL_ATANIM: + if (param1 == 1) item[i]._iFlags |= IAF_ATANIM1; + if (param1 == 2) item[i]._iFlags |= IAF_ATANIM2; + if (param1 == 3) item[i]._iFlags |= IAF_ATANIM3; + if (param1 == 4) item[i]._iFlags |= IAF_ATANIM4; + break; + case PL_HTANIM: + if (param1 == 1) item[i]._iFlags |= IAF_HTANIM1; + if (param1 == 2) item[i]._iFlags |= IAF_HTANIM2; + if (param1 == 3) item[i]._iFlags |= IAF_HTANIM3; + break; + case PL_BLANIM: + item[i]._iFlags |= IAF_BLANIM; + break; + case PL_DAMADD: + item[i]._iPLDamMod += r; + break; + case PL_RNDARW: + item[i]._iFlags |= IAF_RNDARROW; + break; + case PL_DAMAGE: + item[i]._iMinDam = param1; + item[i]._iMaxDam = param2; + break; + case PL_DURNUM: + item[i]._iDurability = param1; + item[i]._iMaxDur = param1; + break; + case PL_FALCON: + item[i]._iFlags |= IAF_ATANIM3; + break; + case PL_ONEHAND: + item[i]._iLoc = IL_HAND; + break; + case PL_CONST: + item[i]._iFlags |= IAF_CONSTRICT; + break; + case PL_SKING: + item[i]._iFlags |= IAF_SKING; + break; + case PL_INFRA: + item[i]._iFlags |= IAF_INFRAVISION; + break; + case PL_NSTRREQ: + item[i]._iMinStr = 0; + break; + case PL_GFX: + item[i]._iCurs = param1; + break; + case PL_HARQUN: // usurped for lightning arrows + item[i]._iFlags |= (IAF_LARROW | IAF_FIREARROW); + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 1; + item[i]._iLMaxDam = 0; +#if 0 + //rjs item[i]._iPLHP = (byte)plr[myplr]._pArmorClass + plr[myplr]._pIBonusAC + plr[myplr]._pIAC; + item[i]._iPLHP = plr[myplr]._pIBonusAC + plr[myplr]._pIAC; + item[i]._iPLHP += (plr[myplr]._pDexterity / 5); + item[i]._iPLHP = item[i]._iPLHP << HP_SHIFT; +#endif + break; + case PL_HARQUN2: + item[i]._iFlags |= (IAF_LIGHTHIT | IAF_FIREHIT); + item[i]._iFMinDam = param1; + item[i]._iFMaxDam = param2; + item[i]._iLMinDam = 2; + item[i]._iLMaxDam = 0; +// item[i]._iAC += ((plr[myplr]._pMaxManaBase >> MANA_SHIFT) / 10); + break; + case PL_HARQUN3: + item[i]._iPLFR = 30 - plr[myplr]._pLevel; + if (item[i]._iPLFR < 0) item[i]._iPLFR = 0; + break; + case PL_NRFIRE: + item[i]._iPLFR -= r; + break; + case PL_NRLGHT: + item[i]._iPLLR -= r; + break; + case PL_NRMAG: + item[i]._iPLMR -= r; + break; + case PL_NRALL: + item[i]._iPLFR -= r; + item[i]._iPLLR -= r; + item[i]._iPLMR -= r; + break; + case PL_DEVAST: + item[i]._iFlags2 |= IAF2_DEVASTATION; + break; + case PL_DECAY: + item[i]._iFlags2 |= IAF2_DECAY; + item[i]._iPLDam += r; + break; + case PL_PERIL: + item[i]._iFlags2 |= IAF2_PERIL; + break; + case PL_RNDDAM: + item[i]._iFlags2 |= IAF2_JESTER; + break; + + case PL_DEMONAC: + item[i]._iFlags2 |= IAF2_DEMONAC; + break; + case PL_UNDEADAC: + item[i]._iFlags2 |= IAF2_UNDEADAC; + break; + + case PL_ACOLYTE: + r2 = ((plr[myplr]._pMaxManaBase >> MANA_SHIFT) * 50 / 100); + item[i]._iPLMana -= (r2 << MANA_SHIFT); + item[i]._iPLHP += (r2 << HP_SHIFT); + break; + case PL_GLADIATR: + r2 = ((plr[myplr]._pMaxHPBase >> HP_SHIFT) * 40 / 100); + item[i]._iPLHP -= (r2 << HP_SHIFT); + item[i]._iPLMana += (r2 << MANA_SHIFT); + break; + } + if ((item[i]._iVAdd1 == 0) && (item[i]._iVMult1 == 0)) { + item[i]._iVAdd1 = PLVal(r, param1, param2, minval, maxval); + item[i]._iVMult1 = multval; + } else { + item[i]._iVAdd2 = PLVal(r, param1, param2, minval, maxval); + item[i]._iVMult2 = multval; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetItemPower(int i, int minlvl, int maxlvl, long flgs, BOOL onlygood) +{ + int pre, post; + int l[256], nl; + int j, aii; + int preidx, sufidx; + char istr[128]; + byte goe; + + pre = random(23, 4); // Pre modifier (20%) + post = random(23, 3); // Post modifirer (66%) + // if no pre modifier, make sure post modifier + if ((pre != 0) && (post == 0)) { + if (random(23, 2)) post = 1; + else pre = 0; + } + + preidx = -1; + sufidx = -1; + goe = 0; + + // if not any only good item, then 67% chance of good, 33% chance of anything + if ((!onlygood) && (random(0, 3))) onlygood = TRUE; + + if (pre == 0) { + nl = 0; + for (j = 0; PL_Prefix[j].PLPower != -1; j++) { + if (((PL_Prefix[j].PLIType & flgs) != 0) && + (PL_Prefix[j].PLMinLvl >= minlvl) && + (PL_Prefix[j].PLMinLvl <= maxlvl) + ) { + if (onlygood && !PL_Prefix[j].PLOk) continue; + if ((flgs == PLF_STAFF) && (PL_Prefix[j].PLPower == PL_CHRG)) continue; + + l[nl] = j; + nl++; + if (PL_Prefix[j].PLDouble) { + l[nl] = j; + nl++; + } + } + } + if (nl != 0) { + preidx = l[random(23, nl)]; + sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); + strcpy(item[i]._iIName, istr); + item[i]._iMagical = IMAGIC_MAGIC; + SaveItemPower(i, PL_Prefix[preidx].PLPower, PL_Prefix[preidx].PLParam1, PL_Prefix[preidx].PLParam2, PL_Prefix[preidx].PLMinVal, PL_Prefix[preidx].PLMaxVal, PL_Prefix[preidx].PLMultVal); + item[i]._iPrePower = PL_Prefix[preidx].PLPower; + goe = PL_Prefix[preidx].PLGOE; + } + } + if (post != 0) { + nl = 0; + for (j = 0; PL_Suffix[j].PLPower != -1; j++) { + if (((PL_Suffix[j].PLIType & flgs) != 0) && + (PL_Suffix[j].PLMinLvl >= minlvl) && + (PL_Suffix[j].PLMinLvl <= maxlvl) && + ((goe | PL_Suffix[j].PLGOE) != 0x11) + ) { + if (onlygood && !PL_Suffix[j].PLOk) continue; + + l[nl] = j; + nl++; + } + } + if (nl != 0) { + sufidx = l[random(23, nl)]; + sprintf(istr, "%s of %s", item[i]._iIName, PL_Suffix[sufidx].PLName); + strcpy(item[i]._iIName, istr); + item[i]._iMagical = IMAGIC_MAGIC; + SaveItemPower(i, PL_Suffix[sufidx].PLPower, PL_Suffix[sufidx].PLParam1, PL_Suffix[sufidx].PLParam2, PL_Suffix[sufidx].PLMinVal, PL_Suffix[sufidx].PLMaxVal, PL_Suffix[sufidx].PLMultVal); + item[i]._iSufPower = PL_Suffix[sufidx].PLPower; + } + } + if (!InfoFit(item[i]._iIName)) { + aii = item[i].IDidx; + if (AllItemsList[aii].iSName) + strcpy(item[i]._iIName, AllItemsList[aii].iSName); + else + item[i]._iName[0] = 0; + + if (preidx != -1) { + sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); + strcpy(item[i]._iIName, istr); + } + if (sufidx != -1) { + sprintf(istr, "%s of %s", item[i]._iIName, PL_Suffix[sufidx].PLName); + strcpy(item[i]._iIName, istr); + } + } + if ((preidx != -1) || (sufidx != -1)) CalcItemValue(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetItemBonus(int i, int idata, int minlvl, int maxlvl, BOOL onlygood, bool SpellsOk) +{ + if (item[i]._iClass == IC_GOLD) return; + if (minlvl > 25) minlvl = 25; + + switch(item[i]._itype) { + case IT_SWORD : + case IT_AXE: + case IT_MACE: + GetItemPower(i, minlvl, maxlvl, PLF_WEAPON, onlygood); + break; + case IT_BOW: + GetItemPower(i, minlvl, maxlvl, PLF_BOW, onlygood); + break; + case IT_SHIELD: + GetItemPower(i, minlvl, maxlvl, PLF_SHIELD, onlygood); + break; + case IT_ARMOR: + case IT_HELM: + case IT_MARMOR: + case IT_HARMOR: + GetItemPower(i, minlvl, maxlvl, PLF_ARMOR, onlygood); + break; + case IT_STAFF: + if (SpellsOk) + GetStaffSpell(i, maxlvl, onlygood); + else + GetItemPower(i, minlvl, maxlvl, PLF_STAFF, onlygood); + break; + case IT_RING: + case IT_AMULET: + GetItemPower(i, minlvl, maxlvl, PLF_RING, onlygood); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetupItem(int i) +{ + int it; + + DROPLOG("SetupItem: setting up object %d!\n",i); + + it = ItemCAnimTbl[item[i]._iCurs]; + item[i]._iAnimData = itemanims[it]; + item[i]._iAnimLen = ItemAnimLs[it]; + item[i]._iAnimWidth = 96; + item[i]._iAnimWidth2 = 16; + item[i]._iIdentified = FALSE; + item[i]._iPostDraw = FALSE; + if (plr[myplr].pLvlLoad == LVLCHANGE_OFF) { + item[i]._iAnimFrame = 1; + item[i]._iAnimFlag = TRUE; + item[i]._iSelFlag = ISEL_NONE; + } else { + item[i]._iAnimFrame = item[i]._iAnimLen; + item[i]._iAnimFlag = FALSE; + item[i]._iSelFlag = ISEL_FLR; + } +} + +/*-----------------------------------------------------------------------* +** Choose an item type from a monster +**-----------------------------------------------------------------------*/ + +int RndItem(int m) +{ + int r; + int ril[512]; // Max 512 items + int ri, i; + + // Unique item? + if (monster[m].MData->mTreasure & T_U) + return(-((monster[m].MData->mTreasure & T_MASK) + 1)); + + if (monster[m].MData->mTreasure & T_NONE) return(0); + +#if CHEATS + if (davedebug) r = 100; + else r = random(24, 100); + if (!cheatflag && (r > 40)) return(0); + if (!cheatflag && (random(24, 100) > 25)) return(IDI_GOLD+1); +#else + r = random(24, 100); + if (r > 40) return(0); + // Gold 75% of the time + if (random(24, 100) > 25) return(IDI_GOLD+1); +#endif + + ri = 0; + for (i = 0; AllItemsList[i].iLoc != -1; i++) { + if ((AllItemsList[i].iRnd == IRND_DOUBLE) && + (monster[m].mLevel >= AllItemsList[i].iMinMLvl) + && ri < 512) ril[ri++] = i; + if (AllItemsList[i].iRnd && + (monster[m].mLevel >= AllItemsList[i].iMinMLvl) + && ri < 512) ril[ri++] = i; + if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) ri--; + if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) ri--; + } + r = random(24, ri); + return(ril[r]+1); +} + +/*-----------------------------------------------------------------------* +** Choose an item type for a good or unique item +**-----------------------------------------------------------------------*/ + +int RndUItem(int m) +{ + int ril[512]; // Max 512 items + int ri, i; + BOOL okflag; + + // Unique item? + if (m != -1) { + if ((monster[m].MData->mTreasure & T_U) && (gbMaxPlayers == 1)) + return(-((monster[m].MData->mTreasure & T_MASK) + 1)); + } + int efflevel = GetEffLevel(); + + ri = 0; + for (i = 0; AllItemsList[i].iLoc != -1; i++) { + okflag = TRUE; + if (!AllItemsList[i].iRnd) okflag = FALSE; + if (m != -1) { + if (monster[m].mLevel < AllItemsList[i].iMinMLvl) okflag = FALSE; + } else { + if ((efflevel << 1) < AllItemsList[i].iMinMLvl) okflag = FALSE; + } + if (AllItemsList[i].itype == IT_MISC) okflag = FALSE; + if (AllItemsList[i].itype == IT_GOLD) okflag = FALSE; + if (AllItemsList[i].itype == IT_FOOD) okflag = FALSE; + if (AllItemsList[i].iMiscId == IMID_BOOK) okflag = TRUE; + if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) okflag = FALSE; + if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) okflag = FALSE; + if (okflag && ri < 512) ril[ri++] = i; + } + return(ril[random(25, ri)]); +} + +/*-----------------------------------------------------------------------* +** Choose any type of item +**-----------------------------------------------------------------------*/ + +int RndAllItems() +{ + int r; + int ril[512]; // Max 512 items + int ri, i; + +#if CHEATS + if (!cheatflag && !itemcheat && (random(26, 100) > 25)) return(IDI_GOLD); +#else + // Gold 75% of the time + if (random(26, 100) > 25) return(IDI_GOLD); +#endif + int efflevel = GetEffLevel(); + + ri = 0; + for (i = 0; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && ((efflevel << 1) >= AllItemsList[i].iMinMLvl) + && ri < 512) ril[ri++] = i; + if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) ri--; + if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) ri--; + } + r = random(26, ri); + return(ril[r]); +} + +/*-----------------------------------------------------------------------* +** Choose an item of a specific type +**-----------------------------------------------------------------------*/ + +int RndTypeItems(int itype, int imid, int level) +{ + int ril[512]; // Max 512 items + int ri, i; + BOOL okflag; + + ri = 0; + for (i = 0; AllItemsList[i].iLoc != -1; i++) { + okflag = TRUE; + if (!AllItemsList[i].iRnd) okflag = FALSE; + if ((level << 1) < AllItemsList[i].iMinMLvl) okflag = FALSE; + if (AllItemsList[i].itype != itype) okflag = FALSE; + if ((imid != -1) && (AllItemsList[i].iMiscId != imid)) okflag = FALSE; + if (okflag && ri < 512) + ril[ri++] = i; + } + return(ril[random(27, ri)]); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int CheckUnique(int i, int lvl, int uper, BOOL recreate) +{ + int j, idata; + BYTE uok[MAXUITEMS]; + int numu, u; + +#if CHEATS + if (!davedebug || !cheatflag) { + if (random(28, 100) > uper) return(-1); + } +#else + if (random(28, 100) > uper) return(-1); +#endif + + numu = 0; + ZeroMemory(uok,sizeof(uok)); + for (j = 0; UniqueItemList[j].UIItemId != -1; j++) { + idata = item[i].IDidx; + if (UniqueItemList[j].UIItemId != AllItemsList[idata].iItemId) continue; + if (lvl < UniqueItemList[j].UIMinLvl) continue; + if (!recreate && UniqueItemFlag[j] && (gbMaxPlayers == 1)) continue; + uok[j] = TRUE; + numu++; + } + + if (numu == 0) return(-1); + u = random(29, 10); + j = 0; + while (numu > 0) { + if (uok[j]) numu--; + if (numu > 0) { + j++; + if (j == MAXUITEMS) j = 0; + } + } + return(j); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetUniqueItem(int i, int uid) +{ + // Generated + UniqueItemFlag[uid] = TRUE; + // Save abilities + SaveItemPower(i, UniqueItemList[uid].UIPower1, UniqueItemList[uid].UIParam1, UniqueItemList[uid].UIParam2, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 1) + SaveItemPower(i, UniqueItemList[uid].UIPower2, UniqueItemList[uid].UIParam3, UniqueItemList[uid].UIParam4, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 2) + SaveItemPower(i, UniqueItemList[uid].UIPower3, UniqueItemList[uid].UIParam5, UniqueItemList[uid].UIParam6, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 3) + SaveItemPower(i, UniqueItemList[uid].UIPower4, UniqueItemList[uid].UIParam7, UniqueItemList[uid].UIParam8, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 4) + SaveItemPower(i, UniqueItemList[uid].UIPower5, UniqueItemList[uid].UIParam9, UniqueItemList[uid].UIParam10, 0, 0, 1); + if (UniqueItemList[uid].UINumPL > 5) + SaveItemPower(i, UniqueItemList[uid].UIPower6, UniqueItemList[uid].UIParam11, UniqueItemList[uid].UIParam12, 0, 0, 1); + // Save name + strcpy(item[i]._iIName, UniqueItemList[uid].UIName); + item[i]._iIvalue = UniqueItemList[uid].UIValue; + if (item[i]._iMiscId == IMID_UNIQUE) item[i]._iSeed = uid; // Save index into UniqueItemList + item[i]._iUid = uid; // Save index into Unique Item List + item[i]._iMagical = IMAGIC_UNIQUE; + item[i]._iCreateInfo |= ICI_UNIQUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnUnique(int uid, int x, int y) +{ + int ii, itype; + + int efflevel = GetEffLevel(); + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + itype = 0; + while (AllItemsList[itype].iItemId != UniqueItemList[uid].UIItemId) itype++; + GetItemAttrs(ii, itype, efflevel); + GetUniqueItem(ii, uid); + SetupItem(ii); + numitems++; + } +} + + +/*-----------------------------------------------------------------------* +** Items in dungeon have lower durs +**-----------------------------------------------------------------------*/ + +void ItemRndDur(int ii) +{ + if (item[ii]._iDurability == 0) return; + if (item[ii]._iDurability == INFINITE_DUR) return; + item[ii]._iDurability = random(0, item[ii]._iMaxDur >> 1) + (item[ii]._iMaxDur >> 2) + 1; +} + +/*-----------------------------------------------------------------------* +** Setup an item and determine magics +**-----------------------------------------------------------------------*/ + +void SetupAllItems(int ii, int idx, int iseed, int lvl, int uper, BOOL onlygood, BOOL recreate, BOOL pregen) +{ + int iblvl, uid; + + item[ii]._iSeed = iseed; + SetRndSeed(iseed); + GetItemAttrs(ii, idx, lvl >> 1); + item[ii]._iCreateInfo = lvl; + if (pregen) item[ii]._iCreateInfo |= ICI_PREGEN; + if (onlygood) item[ii]._iCreateInfo |= ICI_ONLYGOOD; + if (uper == 15) item[ii]._iCreateInfo |= ICI_UPER15; + else if (uper == 1) item[ii]._iCreateInfo |= ICI_UPER1; + if (item[ii]._iMiscId != IMID_UNIQUE) { + iblvl = -1; + if (random(32, 100) <= 10) iblvl = lvl; + else if (random(33, 100) <= lvl) iblvl = lvl; + // Force rings, amulets, and staffs to be magical + if ((iblvl == -1) && (item[ii]._iMiscId == IMID_STAFF)) iblvl = lvl; + if ((iblvl == -1) && (item[ii]._iMiscId == IMID_RING)) iblvl = lvl; + if ((iblvl == -1) && (item[ii]._iMiscId == IMID_AMULET)) iblvl = lvl; + if (onlygood) iblvl = lvl; +#if CHEATS + if (cheatflag) iblvl = lvl; +#endif + if (uper == 15) iblvl = lvl + 4; + if (iblvl != -1) { + uid = CheckUnique(ii, iblvl, uper, recreate); + if (uid == -1) + GetItemBonus(ii, idx, iblvl >> 1, iblvl, onlygood, true); + else { + GetUniqueItem(ii, uid); + item[ii]._iCreateInfo |= ICI_UNIQUE; + } + } + if (item[ii]._iMagical != IMAGIC_UNIQUE) ItemRndDur(ii); + } else { + // if it is something they wield, then get the attributes + if (item[ii]._iLoc != IL_INV) GetUniqueItem(ii, iseed); + } + SetupItem(ii); +} + +/*-----------------------------------------------------------------------* +** Create any item from a monster (or unqiue if monster gives one up) +**-----------------------------------------------------------------------*/ + +void SpawnItem(int m, int x, int y, BOOL sendmsg) +{ + int ii, idx; + BOOL onlygood; + + if ((monster[m]._uniqtype != 0) || + ((monster[m].MData->mTreasure & T_U) && (gbMaxPlayers != 1))) { + // If unique, make sure we get something good + idx = RndUItem(m); + if (idx < 0) { + SpawnUnique(-(idx+1), x, y); + return; + } + onlygood = TRUE; + } else { + // special code to pop out brain for Mushroom Quest + if (quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE + && quests[Q_BKMUSHRM]._qvar1 == QS_MUSHGIVEN) { + idx = IDI_BRAIN; + quests[Q_BKMUSHRM]._qvar1 = QS_BRAINSPAWNED; + } + else + { + idx = RndItem(m); + if (idx == 0) return; + if (idx > 0) { + idx--; + onlygood = FALSE; + } else { + SpawnUnique(-(idx+1), x, y); + return; + } + } + } + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + if (monster[m]._uniqtype != 0) SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 15, onlygood, FALSE, FALSE); +#if CHEATS + else if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 15, TRUE, FALSE, FALSE); +#endif + else SetupAllItems(ii, idx, GetRndSeed(), monster[m].MData->mLevel, 1, onlygood, FALSE, FALSE); + + numitems++; + if (sendmsg) NetSendCmdDItem(FALSE, ii); + } +} + + +/*-----------------------------------------------------------------------* +** Only used for quest (single player) +**-----------------------------------------------------------------------*/ + +void CreateItem(int uid, int x, int y) +{ + int ii, idx; + + int efflevel = GetEffLevel(); + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + idx = 0; + while (AllItemsList[idx].iItemId != UniqueItemList[uid].UIItemId) idx++; + GetItemAttrs(ii, idx, efflevel); + GetUniqueItem(ii, uid); + SetupItem(ii); + item[ii]._iMagical = IMAGIC_UNIQUE; + numitems++; + } +} + + +/*-----------------------------------------------------------------------* +** Create any item from an object, etc (chest, barrel, sarc) +**-----------------------------------------------------------------------*/ + +void CreateRndItem(int x, int y, BOOL onlygood, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + + int efflevel = GetEffLevel(); + + if (onlygood) idx = RndUItem(-1); + else idx = RndAllItems(); + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 1, onlygood, FALSE, delta); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetupAllUseful(int ii, int iseed, int lvl) +{ + int idx; + + item[ii]._iSeed = iseed; + SetRndSeed(iseed); + +#if 0 + if (random(34, 2)) idx = IDI_HEAL; + else idx = IDI_MANA; + + // added 7/30/97 by donald + if (!random(34, 8)) idx = IDI_OILACC; + + if ((lvl > 1) && (random(34, 3) == 0)) idx = IDI_PORTAL; +#else + // why call random() so many times? + + switch(random(34,7)) + { + case 0: idx = IDI_PORTAL; if (lvl > 1) break; // else fallthrough + case 1: + case 2: idx = IDI_HEAL; break; + case 3: idx = IDI_PORTAL; if (lvl > 1) break; // else fallthrough + case 4: + case 5: idx = IDI_MANA; break; + default:idx = IDI_OILACC; break; + } +#endif + + GetItemAttrs(ii, idx, lvl); + item[ii]._iCreateInfo = ICI_USEFUL + lvl; + SetupItem(ii); +} + +/*-----------------------------------------------------------------------* +** Rnd item, but only health, mana, or id +**-----------------------------------------------------------------------*/ + +void CreateRndUseful(int pnum, int x, int y, BOOL sendmsg) +{ + int ii; + + int efflevel = GetEffLevel(); + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + SetupAllUseful(ii, GetRndSeed(), efflevel); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +** Create any item of a specific type +**-----------------------------------------------------------------------*/ + +void CreateTypeItem(int x, int y, BOOL onlygood, int itype, int imisc, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + + int efflevel = GetEffLevel(); + + if (itype != IT_GOLD) idx = RndTypeItems(itype, imisc, efflevel); + else idx = 0; + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 1, onlygood, FALSE, delta); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +** Recreate any item with the proper info +**-----------------------------------------------------------------------*/ + +void RecreateItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue) +{ + int uper; + BOOL onlygood, uavail, pregen; + + // PATCH1.JMM + #if 0 + int i, nIndex; + for(i = 0; i < numitems; i++) { + nIndex = itemactive[i]; + + if(((item[nIndex]._iSeed == iseed) && (item[nIndex]._iCreateInfo == icreateinfo) && (item[nIndex].IDidx == idx))) + DROPLOG(" Creating dupped item: idx->%8.8x seed->%8.8x ci->%8.8x\n",idx,iseed,icreateinfo); + + app_assert(!((item[nIndex]._iSeed == iseed) && (item[nIndex]._iCreateInfo == icreateinfo) && (item[nIndex].IDidx == idx))); + } + #endif + // ENDPATCH1.JMM + + + // Gold + if (idx == IDI_GOLD) { + SetPlrHandItem(&item[ii], idx); + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = icreateinfo; + item[ii]._ivalue = ivalue; + if (item[ii]._ivalue >= GOLD_VT2) { + item[ii]._iCurs = ITEM_5GOLD; + } else { + if (ivalue <= GOLD_VT1) item[ii]._iCurs = ITEM_1GOLD; + else item[ii]._iCurs = ITEM_3GOLD; + } + } else { + // One the the players initial items? + if (icreateinfo == 0) { + SetPlrHandItem(&item[ii], idx); + SetPlrHandSeed(&item[ii], iseed); + } else { + // From town? + if (icreateinfo & ICI_TOWNMASK) RecreateTownItem(ii, idx, icreateinfo, iseed, ivalue); + else { + // From dungeon + if ((icreateinfo & ICI_USEFUL) == ICI_USEFUL) { + SetupAllUseful(ii, iseed, icreateinfo & ICI_LVLMASK); + } else { + uper = 0; + onlygood = FALSE; + uavail = FALSE; + pregen = FALSE; + if (icreateinfo & ICI_UPER1) uper = 1; + if (icreateinfo & ICI_UPER15) uper = 15; + if (icreateinfo & ICI_ONLYGOOD) onlygood = TRUE; + if (icreateinfo & ICI_UNIQUE) uavail = TRUE; + if (icreateinfo & ICI_PREGEN) pregen = TRUE; + SetupAllItems(ii, idx, iseed, icreateinfo & ICI_LVLMASK, uper, onlygood, uavail, pregen); + } + } + } + } +} + +/*-----------------------------------------------------------------------* +** Recreate any ear with the proper info +**-----------------------------------------------------------------------*/ + +void RecreateEar(int ii, WORD ic, int iseed, BOOL Id, int dur, int mdur, int ch, int mch, int ivalue, int ibuff) +{ + SetPlrHandItem(&item[ii], IDI_EAR); + tempstr[0] = (ic >> 8) & 0x7f; + tempstr[1] = ic & 0x7f; + tempstr[2] = (iseed >> 24) & 0x7f; + tempstr[3] = (iseed >> 16) & 0x7f; + tempstr[4] = (iseed >> 8) & 0x7f; + tempstr[5] = iseed & 0x7f; + tempstr[6] = Id & 0x7f; + tempstr[7] = dur & 0x7f; + tempstr[8] = mdur & 0x7f; + tempstr[9] = ch & 0x7f; + tempstr[10] = mch & 0x7f; + tempstr[11] = (ivalue >> 8) & 0x7f; + tempstr[12] = (ibuff >> 24) & 0x7f; + tempstr[13] = (ibuff >> 16) & 0x7f; + tempstr[14] = (ibuff >> 8) & 0x7f; + tempstr[15] = ibuff & 0x7f; + tempstr[16] = 0; + sprintf(item[ii]._iName, "Ear of %s", tempstr); + item[ii]._iCurs = ((ivalue >> 6) & 0x3) + ITEM_EAR1; + item[ii]._ivalue = ivalue & 0x3f; + item[ii]._iCreateInfo = ic; + item[ii]._iSeed = iseed; +} + + +const char * sgszCornerstone = "SItem"; + +void CornerstoneSave() +{ + if (!CornerStone.Initted) + return; + + PkItemStruct pki; + + if (CornerStone.item.IDidx >= 0) + { + PackItem(&pki, &(CornerStone.item)); + SRegSaveData(gszProgKey,sgszCornerstone,0, &pki, sizeof(PkItemStruct)); + } + else + { + SRegSaveData(gszProgKey,sgszCornerstone, 0, "", 1); + } +} + +void CornerstoneRestore(int x, int y) +{ + if (CornerStone.Initted) + return; + + // read the info out of the options file + PkItemStruct pki; + + if (x == 0 || y == 0) + return; + + CornerStone.item.IDidx = 0; + CornerStone.Initted = TRUE; + + if (dItem[x][y] != 0) + { + // clear the square + int ii = dItem[x][y] - 1; + for (int i = 0; i < numitems; ++i) + if (itemactive[i] == ii) + { + DeleteItem(ii, i); + break; + } + dItem[x][y] = 0; + } + + DWORD bytesread = 0; + if (! SRegLoadData(gszProgKey,sgszCornerstone, 0, &pki, sizeof(PkItemStruct), &bytesread)) + return; + + if (bytesread != sizeof(PkItemStruct)) + return; + + // create a new item slot + int ii = itemavail[0]; + dItem[x][y] = ii+1; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + + UnPackItem(&pki, &item[ii]); + item[ii]._ix = x; + item[ii]._iy = y; + + DROPLOG("CornerstoneRestore: respawning object %d!\n",ii); + RespawnItem(ii, FALSE); + CornerStone.item = item[ii]; + + numitems++; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnQuestItem(int itemid, int x,int y, int randarea, int selflag) +{ + int i,j; + BOOL failed; + + int efflevel = GetEffLevel(); + + if (randarea) { + int tries = 0; + do { + if (++tries > 1000 && randarea > 1) + --randarea; + x = random(0, DMAXX); + y = random(0, DMAXY); + failed = FALSE; + for (i = 0; i < randarea && !failed; i++) + for (j = 0; j < randarea && !failed; j++) + failed = !ItemSpaceOk(x + i, y + j); + } while (failed); + } + + if (numitems < MAXITEMS) { + i = itemavail[0]; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = i; + item[i]._ix = x; + item[i]._iy = y; + dItem[x][y] = i + 1; + GetItemAttrs(i, itemid, efflevel); + SetupItem(i); + item[i]._iPostDraw = TRUE; + if (selflag != ISEL_NONE) { + // selflag indicates creation of post-flippy item + item[i]._iSelFlag = selflag; + item[i]._iAnimFrame = item[i]._iAnimLen; + item[i]._iAnimFlag = FALSE; + } + + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SpawnRock() +{ + int i, ii, ostand; + int xx,yy; + BOOL done = FALSE; + + for (i = 0; i < numobjects && !done; i++) { + ostand = objectactive[i]; + done = (object[ostand]._otype == 23); // OBJ_STAND + } + + int efflevel = GetEffLevel(); + + if(done) + { + ii = itemavail[0]; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + xx = item[ii]._ix = object[ostand]._ox; + yy = item[ii]._iy = object[ostand]._oy; + dItem[xx][yy] = ii + 1; + GetItemAttrs(ii, IDI_ROCK, efflevel); + SetupItem(ii); + item[ii]._iSelFlag = ISEL_TOP; + item[ii]._iPostDraw = TRUE; + item[ii]._iAnimFrame = 11; + + numitems++; + } +} + +void SpawnSomething(int what, int xx, int yy) +{ + int ii = itemavail[0]; + + int efflevel = GetEffLevel(); + + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + item[ii]._ix = xx; + item[ii]._iy = yy; + dItem[xx][yy] = ii + 1; + GetItemAttrs(ii, what, efflevel); + SetupItem(ii); + item[ii]._iSelFlag = ISEL_TOP; + item[ii]._iPostDraw = TRUE; + item[ii]._iAnimFrame = 1; // item[ii]._iAnimLen; + item[ii]._iAnimFlag = TRUE; + item[ii]._iIdentified = TRUE; + + numitems++; +} + +void SpawnMap(int xx, int yy) +{ + SpawnSomething(IDI_MAPOFDOOM, xx, yy); +} + +void SpawnBomb(int xx, int yy) +{ + SpawnSomething(IDI_RUNEBOMB, xx, yy); +} + +void SpawnBear(int xx, int yy) +{ + SpawnSomething(IDI_THEODORE, xx, yy); +} + +void SpawnCowArmor(int xx, int yy) +{ + CreateItem(UID_ARMRCOW, xx, yy); +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RespawnItem(int i, BOOL FlipFlag) +{ + int it; + + DROPLOG(" RespawnItem: Respawning item %d!\n",i); + + it = ItemCAnimTbl[item[i]._iCurs]; + item[i]._iAnimData = itemanims[it]; + item[i]._iAnimLen = ItemAnimLs[it]; + item[i]._iAnimWidth = 96; + item[i]._iAnimWidth2 = 16; + item[i]._iPostDraw = FALSE; + item[i]._iRequest = FALSE; + if (FlipFlag) { + item[i]._iAnimFrame = 1; + item[i]._iAnimFlag = TRUE; + item[i]._iSelFlag = ISEL_NONE; + } else { + item[i]._iAnimFrame = item[i]._iAnimLen; + item[i]._iAnimFlag = FALSE; + item[i]._iSelFlag = ISEL_FLR; + } + if (item[i]._iCurs == ITEM_ROCK) { + item[i]._iSelFlag = ISEL_FLR; + PlaySfxLoc(ItemAnimSnds[it], item[i]._ix, item[i]._iy); + } + if (item[i]._iCurs == ITEM_INNSIGN) item[i]._iSelFlag = ISEL_FLR; + if (item[i]._iCurs == ITEM_ANVIL) item[i]._iSelFlag = ISEL_FLR; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DeleteItem(int ii, int i) +{ + itemavail[MAXITEMS - numitems] = ii; + numitems--; + if ((numitems > 0) && (i != numitems)) { + itemactive[i] = itemactive[numitems]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int idoppely = DIRTEDGED2; + +void ItemDoppel() +{ + int idoppelx; + ItemStruct *i; + + if (gbMaxPlayers == 1) return; + + for (idoppelx = DIRTEDGED2; idoppelx < (DIRTEDGED2+80); idoppelx++) { + if (dItem[idoppelx][idoppely]) { + i = &item[dItem[idoppelx][idoppely] - 1]; + if ((i->_ix != idoppelx) || (i->_iy != idoppely)) + dItem[idoppelx][idoppely] = 0; + } + } + idoppely++; + if (idoppely == DIRTEDGED2+80) idoppely = DIRTEDGED2; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ProcessItems() +{ + int i, ii, it; + + VerifyItemActiveList(); + + for (i = 0; i < numitems; i++) { + ii = itemactive[i]; + + // Animate Spell GFX + if (item[ii]._iAnimFlag) { + item[ii]._iAnimFrame++; + if (item[ii]._iCurs == ITEM_ROCK) { + if ((item[ii]._iSelFlag == ISEL_FLR) && (item[ii]._iAnimFrame == 11)) + item[ii]._iAnimFrame = 1; + if ((item[ii]._iSelFlag == ISEL_TOP) && (item[ii]._iAnimFrame == 21)) + item[ii]._iAnimFrame = 11; + } else { + if (item[ii]._iAnimFrame == (item[ii]._iAnimLen >> 1)) { + it = ItemCAnimTbl[item[ii]._iCurs]; + PlaySfxLoc(ItemAnimSnds[it], item[ii]._ix, item[ii]._iy); + } + if (item[ii]._iAnimFrame >= item[ii]._iAnimLen) { + item[ii]._iAnimFrame = item[ii]._iAnimLen; + item[ii]._iAnimFlag = FALSE; + item[ii]._iSelFlag = ISEL_FLR; + } + } + } + } + + ItemDoppel(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void FreeItemGFX() +{ + for (int i = 0; i < ITEMFTYPES; i++) + DiabloFreePtr(itemanims[i]); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncItemAnim(int ii) +{ + int a; + + a = ItemCAnimTbl[item[ii]._iCurs]; + item[ii]._iAnimData = itemanims[a]; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetItemStr(int i) { + + switch (item[i]._itype) { + case IT_GOLD: { + int nGold = item[i]._ivalue; + const char * get_pieces_str(int nGold); + sprintf(infostr,"%i gold %s",nGold,get_pieces_str(nGold)); + } + break; + + default : + int s = item[i]._itype; + if (item[i]._iIdentified) strcpy(infostr, item[i]._iIName); + else strcpy(infostr, item[i]._iName); + if (item[i]._iMagical == IMAGIC_MAGIC) infoclr = ICOLOR_BLUE; + if (item[i]._iMagical == IMAGIC_UNIQUE) infoclr = ICOLOR_GOLD; + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckIdentify(int pnum, int cii) { + ItemStruct * pi; + if (cii < NUM_INVLOC) + pi = &plr[pnum].InvBody[cii]; + else + pi = &plr[pnum].InvList[cii - NUM_INVLOC]; + pi->_iIdentified = TRUE; + CalcPlrInv(pnum,TRUE); + + if (pnum == myplr) + NewCursor(GLOVE_CURS); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void RepairItem(ItemStruct *i, int lvl) { + int d, rep; + + if (i->_iDurability == i->_iMaxDur) return; + // If item already has zero durability, wipe it out + if (i->_iMaxDur <= 0) { + i->_itype = -1; + return; + } + rep = 0; + do { + rep += random(37, lvl) + lvl; + d = i->_iMaxDur / (9 + lvl); + if (d < 1) d = 1; + i->_iMaxDur -= d; + // If I have no max durability, break + if (i->_iMaxDur == 0) { + i->_itype = -1; + return; + } + } while ((i->_iDurability + rep) < i->_iMaxDur); + i->_iDurability += rep; + if (i->_iDurability > i->_iMaxDur) + i->_iDurability = i->_iMaxDur; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoRepair(int pnum, int cii) { + PlayerStruct * p = &plr[pnum]; + PlaySfxLoc(IS_REPAIR, p->_px, p->_py); + + ItemStruct * pi; + if (cii < NUM_INVLOC) + pi = &p->InvBody[cii]; + else + pi = &p->InvList[cii - NUM_INVLOC]; + RepairItem(pi,p->_pLevel); + CalcPlrInv(pnum,TRUE); + + if (pnum == myplr) + NewCursor(GLOVE_CURS); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void RechargeItem(ItemStruct *i, int r) { + if (i->_iCharges == i->_iMaxCharges) return; + + do { + i->_iMaxCharges--; + if (i->_iMaxCharges == 0) { + //i->_itype = -1; + return; + } + i->_iCharges += r; + } while (i->_iCharges < i->_iMaxCharges); + + if (i->_iCharges > i->_iMaxCharges) i->_iCharges = i->_iMaxCharges; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoRecharge(int pnum, int cii) { + PlayerStruct * p = &plr[pnum]; + + ItemStruct * pi; + if (cii < NUM_INVLOC) pi = &p->InvBody[cii]; + else pi = &p->InvList[cii - NUM_INVLOC]; +// rmw.patch1.start.1/14/97 +// if (pi->_itype == IT_STAFF) { + if ((pi->_itype == IT_STAFF) && (pi->_iSpell != SPL_NONE)) { +// rmw.patch1.end.1/14/97 + int sp = pi->_iSpell; + int r = spelldata[sp].sBookLvl; + r = random(38, p->_pLevel / r) + 1; + + RechargeItem(pi, r); + CalcPlrInv(pnum, TRUE); + } + + if (pnum == myplr) NewCursor(GLOVE_CURS); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static BOOL OilItem(ItemStruct * i,const PlayerStruct * p) { + int v; + + if (i->_iClass == IC_ITEM) return(FALSE); + if (i->_iClass == IC_GOLD) return(FALSE); + if (i->_iClass == IC_SPECIAL) return(FALSE); + switch(p->_pOilType) { + case IMID_OILACC : + case IMID_OILMAST : + case IMID_OILSHRP : + if (i->_iClass == IC_ARMOR) return(FALSE); + break; + case IMID_OILDEATH : + if (i->_iClass == IC_ARMOR) return(FALSE); + if (i->_itype == IT_BOW) return(FALSE); + break; + case IMID_OILHARD : + case IMID_OILIMPER : + if (i->_iClass == IC_WEAP) return(FALSE); + break; + } + + switch(p->_pOilType) { + case IMID_OILACC : + if (i->_iPLToHit >= 50) break; + i->_iPLToHit += random(68, 2) + 1; + break; + case IMID_OILMAST : + if (i->_iPLToHit >= 100) break; + i->_iPLToHit += random(68, 3) + 3; + break; + case IMID_OILSHRP : + if (i->_iMaxDam - i->_iMinDam >= 30) break; + i->_iMaxDam += 1; + break; + case IMID_OILDEATH : + if (i->_iMaxDam - i->_iMinDam >= 30) break; + i->_iMinDam += 1; + i->_iMaxDam += 2; + break; + case IMID_OILSKILL : + v = random(68, 6) + 5; + + if (i->_iMinStr > v) { + i->_iMinStr -= v; + } + else { + i->_iMinStr = 0; + } + + if (i->_iMinMag > v) { + i->_iMinMag -= v; + } + else { + i->_iMinMag = 0; + } + + if (i->_iMinDex > v) { + i->_iMinDex -= v; + } + else { + i->_iMinDex = 0; + } + break; + case IMID_OILBLKSM : + if (i->_iMaxDur == INFINITE_DUR) break; +// i->_iDurability = (i->_iDurability + (random(68, 5) + 2)); +// i->_iMaxDur = (i->_iMaxDur + (random(68, 9) + 7)); + if (i->_iDurability < i->_iMaxDur) + { + // fix by 20% + int tmp = i->_iDurability + ((i->_iMaxDur + 4) / 5); + if (tmp > i->_iMaxDur) + tmp = i->_iMaxDur; + i->_iDurability = tmp; + } + else + { + if (i->_iMaxDur >= 100) break; + i->_iMaxDur += 1; + i->_iDurability = i->_iMaxDur; + } + break; + case IMID_OILFORT : + if (i->_iMaxDur == INFINITE_DUR) break; + if (i->_iMaxDur >= 200) break; + v = random(68, 41) + 10; + i->_iMaxDur += v; + i->_iDurability += v; + break; + case IMID_OILPERM : + i->_iDurability = INFINITE_DUR; + i->_iMaxDur = INFINITE_DUR; + break; + case IMID_OILHARD : + if (i->_iAC >= 60) break; + i->_iAC += random(68, 2) + 1; + break; + case IMID_OILIMPER : + if (i->_iAC >= 120) break; + i->_iAC += random(68, 3) + 3; + break; + } + + return(TRUE); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoOil(int pnum, int cii) { + ItemStruct * pi; + PlayerStruct * p = &plr[pnum]; + if (cii < NUM_INVLOC) switch (cii) { + case INVLOC_HEAD: + case INVLOC_HAND1: + case INVLOC_HAND2: + case INVLOC_BODY: + pi = &p->InvBody[cii]; + break; + + default: + return; + } + else { + pi = &p->InvList[cii - NUM_INVLOC]; + } + + if (OilItem(pi,p)) { + CalcPlrInv(pnum,TRUE); + if (pnum == myplr) NewCursor(GLOVE_CURS); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PrintItemOil(char IDidx) +{ + switch(IDidx) { + case IMID_OILACC : + strcpy(tempstr, "increases a weapon's"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "chance to hit"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILMAST : + strcpy(tempstr, "greatly increases a"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "weapon's chance to hit"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILSHRP : + strcpy(tempstr, "increases a weapon's"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "damage potential"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILDEATH : + strcpy(tempstr, "greatly increases a weapon's"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "damage potential - not bows"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILSKILL : + strcpy(tempstr, "reduces attributes needed"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "to use armor or weapons"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILBLKSM : + strcpy(tempstr, "restores 20% of an"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "item's durability"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILFORT : + strcpy(tempstr, "increases an item's"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "current and max durability"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILPERM : + strcpy(tempstr, "makes an item indestructible"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILHARD : + strcpy(tempstr, "increases the armor class"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "of armor and shields"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_OILIMPER : + strcpy(tempstr, "greatly increases the armor"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "class of armor and shields"); + AddPanelString(tempstr, TEXT_CENTER); + break; +// potions + case IMID_PHEAL : + strcpy(tempstr, "fully recover life"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PLHEAL : + strcpy(tempstr, "recover partial life"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PSHEAL : + strcpy(tempstr, "recover life"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PDHEAL : + strcpy(tempstr, "deadly heal"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PMANA : + strcpy(tempstr, "recover mana"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_PFMANA : + strcpy(tempstr, "fully recover mana"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ESTR : + strcpy(tempstr, "increase strength"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_EMAG : + strcpy(tempstr, "increase magic"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_EDEX : + strcpy(tempstr, "increase dexterity"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_EVIT : + strcpy(tempstr, "increase vitality"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ENSTR : + strcpy(tempstr, "decrease strength"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ENMAG : + strcpy(tempstr, "decrease strength"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ENDEX : + strcpy(tempstr, "decrease dexterity"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_ENVIT : + strcpy(tempstr, "decrease vitality"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_REJUV : + strcpy(tempstr, "recover life and mana"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_FREJUV : + strcpy(tempstr, "fully recover life and mana"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_RUNEFIRE: + case IMID_RUNEIMMOLATE: + strcpy(tempstr, "sets fire trap"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_RUNELIGHT: + case IMID_RUNENOVA: + strcpy(tempstr, "sets lightning trap"); + AddPanelString(tempstr, TEXT_CENTER); + break; + case IMID_RUNESTONE: + strcpy(tempstr, "sets petrification trap"); + AddPanelString(tempstr, TEXT_CENTER); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PrintItemPower(char plidx,const ItemStruct * x) { + int v; + + switch(plidx) { + case PL_TOHIT: + case PL_NTOHIT: + sprintf(tempstr, "chance to hit : %+i%%", x->_iPLToHit); + break; + case PL_TODAM: + case PL_NTODAM: + sprintf(tempstr, "%+i%% damage", x->_iPLDam); + break; + case PL_DAHT: + case PL_NDAHT: + sprintf(tempstr, "to hit: %+i%%, %+i%% damage", x->_iPLToHit, x->_iPLDam); + break; + case PL_AC: + case PL_NAC: + sprintf(tempstr, "%+i%% armor", x->_iPLAC); + break; + case PL_ACTUALAC: + sprintf(tempstr, "armor class: %i", x->_iAC); + break; + case PL_NACTULAC: + sprintf(tempstr, "armor class: %i", x->_iAC); + break; + case PL_RFIRE: + case PL_NRFIRE: + if (x->_iPLFR < 75) + sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR); + else + sprintf(tempstr, "Resist Fire : 75%% MAX"); + break; + case PL_RLGHT: + case PL_NRLGHT: + if (x->_iPLLR < 75) + sprintf(tempstr, "Resist Lightning : %+i%%", x->_iPLLR); + else + sprintf(tempstr, "Resist Lightning : 75%% MAX"); + break; + case PL_RMAG: + case PL_NRMAG: + if (x->_iPLMR < 75) + sprintf(tempstr, "Resist Magic : %+i%%", x->_iPLMR); + else + sprintf(tempstr, "Resist Magic : 75%% MAX"); + break; + case PL_RALL: + case PL_NRALL: + if (x->_iPLFR < 75) sprintf(tempstr, "Resist All : %+i%%", x->_iPLFR); + if (x->_iPLFR >= 75) sprintf(tempstr, "Resist All : 75%% MAX"); + break; + case PL_SLVL: +#if 0 + if (x->_iSplLvlAdd == 1 ) strcpy(tempstr, "spells are increased 1 level"); + if (x->_iSplLvlAdd == 2 ) strcpy(tempstr, "spells are increased 2 levels"); + if (x->_iSplLvlAdd < 1 ) strcpy(tempstr, "spells are decreased 1 level"); +#endif + if (x->_iSplLvlAdd == 1) strcpy(tempstr, "spells are increased 1 level"); + else if (x->_iSplLvlAdd > 1 ) sprintf(tempstr, "spells are increased %i levels", x->_iSplLvlAdd); + else if (x->_iSplLvlAdd == -1) strcpy(tempstr, "spells are decreased 1 level"); + else if (x->_iSplLvlAdd < -1 ) sprintf(tempstr, "spells are decreased %i levels", x->_iSplLvlAdd); + else if (x->_iSplLvlAdd == 0 ) strcpy(tempstr, "spell levels unchanged (?)"); + break; + case PL_CHRG: + strcpy(tempstr, "Extra charges"); + break; + case PL_SPELL: + sprintf(tempstr, "%i %s charges", x->_iMaxCharges, spelldata[x->_iSpell].sNameText); + break; + case PL_FHIT: + if (x->_iFMinDam == x->_iFMaxDam) + sprintf(tempstr, "Fire hit damage: %i", x->_iFMinDam); + else + sprintf(tempstr, "Fire hit damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); + break; + case PL_LHIT: + if (x->_iLMinDam == x->_iLMaxDam) + sprintf(tempstr, "Lightning hit damage: %i", x->_iLMinDam); + else + sprintf(tempstr, "Lightning hit damage: %i-%i", x->_iLMinDam, x->_iLMaxDam); + break; + case PL_STR: + case PL_NSTR: + sprintf(tempstr, "%+i to strength", x->_iPLStr); + break; + case PL_MAG: + case PL_NMAG: + sprintf(tempstr, "%+i to magic", x->_iPLMag); + break; + case PL_DEX: + case PL_NDEX: + sprintf(tempstr, "%+i to dexterity", x->_iPLDex); + break; + case PL_VIT: + case PL_NVIT: + sprintf(tempstr, "%+i to vitality", x->_iPLVit); + break; + case PL_STATS: + case PL_NSTATS: + sprintf(tempstr, "%+i to all attributes", x->_iPLStr); + break; + case PL_GETHIT: + case PL_NGETHIT: + sprintf(tempstr, "%+i damage from enemies", x->_iPLGetHit); + break; + case PL_HP: + case PL_NHP: + sprintf(tempstr, "Hit Points : %+i", (x->_iPLHP >> HP_SHIFT)); + break; + case PL_MANA: + case PL_NMANA: + sprintf(tempstr, "Mana : %+i", (x->_iPLMana >> MANA_SHIFT)); + break; + case PL_DUR: + strcpy(tempstr, "high durability"); + break; + case PL_NDUR: + strcpy(tempstr, "decreased durability"); + break; + case PL_IND: + strcpy(tempstr, "indestructible"); + break; + case PL_LIGHT: + v = x->_iPLLight * 10; + sprintf(tempstr, "+%i%% light radius", v); + break; + case PL_NLIGHT: + v = -x->_iPLLight * 10; + sprintf(tempstr, "-%i%% light radius", v); + break; + case PL_NUMARWS: + sprintf(tempstr, "multiple arrows per shot"); + break; + case PL_FARROW: + if (x->_iFMinDam == x->_iFMaxDam) + sprintf(tempstr, "fire arrows damage: %i", x->_iFMinDam); + else + sprintf(tempstr, "fire arrows damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); + break; + case PL_LARROW: + if (x->_iLMinDam == x->_iLMaxDam) + sprintf(tempstr, "lightning arrows damage %i", x->_iLMinDam); + else + sprintf(tempstr, "lightning arrows damage %i-%i", x->_iLMinDam, x->_iLMaxDam); + break; + case PL_HITADD: // usurped for fireball arrows... + if (x->_iFMinDam == x->_iFMaxDam) + sprintf(tempstr, "fireball damage: %i", x->_iFMinDam); + else + sprintf(tempstr, "fireball damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); + break; + case PL_THORN: + strcpy(tempstr, "attacker takes 1-3 damage"); + break; + case PL_LMANA: + strcpy(tempstr, "user loses all mana"); + break; + case PL_NOHEAL: + strcpy(tempstr, "you can't heal"); + break; + case PL_TRAPDAM: + strcpy(tempstr, "absorbs half of trap damage"); + break; + case PL_BEAR: + strcpy(tempstr, "knocks target back"); + break; + case PL_DAMDEMON: + strcpy(tempstr, "+200% damage vs. demons"); + break; + case PL_ZERORES: + strcpy(tempstr, "All Resistance equals 0"); + break; + case PL_MNOHEAL: + strcpy(tempstr, "hit monster doesn't heal"); + break; + case PL_BAT: + if (x->_iFlags & IAF_BAT10) strcpy(tempstr, "hit steals 3% mana"); + if (x->_iFlags & IAF_BAT20) strcpy(tempstr, "hit steals 5% mana"); + break; + case PL_LEECH: + if (x->_iFlags & IAF_LEECH10) strcpy(tempstr, "hit steals 3% life"); + if (x->_iFlags & IAF_LEECH20) strcpy(tempstr, "hit steals 5% life"); + break; + case PL_ENAC: + strcpy(tempstr, "penetrates target's armor"); + break; + case PL_ATANIM: + if (x->_iFlags & IAF_ATANIM1) strcpy(tempstr, "quick attack"); + if (x->_iFlags & IAF_ATANIM2) strcpy(tempstr, "fast attack"); + if (x->_iFlags & IAF_ATANIM3) strcpy(tempstr, "faster attack"); + if (x->_iFlags & IAF_ATANIM4) strcpy(tempstr, "fastest attack"); + break; + case PL_HTANIM: + if (x->_iFlags & IAF_HTANIM1) strcpy(tempstr, "fast hit recovery"); + if (x->_iFlags & IAF_HTANIM2) strcpy(tempstr, "faster hit recovery"); + if (x->_iFlags & IAF_HTANIM3) strcpy(tempstr, "fastest hit recovery"); + break; + case PL_BLANIM: + strcpy(tempstr, "fast block"); + break; + case PL_DAMADD: + sprintf(tempstr, "adds %i points to damage", x->_iPLDamMod); + break; + case PL_RNDARW: + strcpy(tempstr, "fires random speed arrows"); + break; + case PL_DAMAGE: + sprintf(tempstr, "unusual item damage"); + break; + case PL_DURNUM: + strcpy(tempstr, "altered durability"); + break; + case PL_FALCON: + strcpy(tempstr, "Faster attack swing"); + // not used + break; + case PL_ONEHAND: + strcpy(tempstr, "one handed sword"); + break; + case PL_CONST: + strcpy(tempstr, "constantly lose hit points"); + break; + case PL_SKING: + strcpy(tempstr, "life stealing"); + break; + case PL_NSTRREQ: + strcpy(tempstr, "no strength requirement"); + break; + case PL_INFRA: + strcpy(tempstr, "see with infravision"); + break; + case PL_GFX: + strcpy(tempstr, " "); + break; + case PL_HARQUN: + if (x->_iFMinDam == x->_iFMaxDam) + sprintf(tempstr, "lightning damage: %i", x->_iFMinDam); + else + sprintf(tempstr, "lightning damage: %i-%i", x->_iFMinDam, x->_iFMaxDam); +// strcpy(tempstr, "Armor class added to life"); + break; + case PL_HARQUN2: + strcpy(tempstr, "charged bolts on hits"); +// strcpy(tempstr, "10% of mana added to armor"); + break; + case PL_HARQUN3: + if (x->_iPLFR <= 0) sprintf(tempstr, " "); + else if (x->_iPLFR >= 1) sprintf(tempstr, "Resist Fire : %+i%%", x->_iPLFR); + break; + case PL_DEVAST: + strcpy(tempstr, "occasional triple damage"); + break; + case PL_DECAY: + sprintf(tempstr, "decaying %+i%% damage", x->_iPLDam); + break; + case PL_PERIL: + strcpy(tempstr, "2x dmg to monst, 1x to you"); + break; + case PL_RNDDAM: + strcpy(tempstr, "Random 0 - 500% damage"); + break; + case PL_FRAGILE: + sprintf(tempstr, "low dur, %+i%% damage", x->_iPLDam); + break; + case PL_DOPPEL: + sprintf(tempstr, "to hit: %+i%%, %+i%% damage", x->_iPLToHit, x->_iPLDam); + break; + case PL_DEMONAC: + sprintf(tempstr, "extra AC vs demons"); + break; + case PL_UNDEADAC: + sprintf(tempstr, "extra AC vs undead"); + break; + case PL_ACOLYTE: + sprintf(tempstr, "50%% Mana moved to Health"); + break; + case PL_GLADIATR: + sprintf(tempstr, "40%% Health moved to Mana"); + break; + + default: + strcpy(tempstr, "Another ability (NW)"); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawUBack() +{ + DrawCel(88, 487, pSTextBoxCels, 1, 271); + app_assert(gpBuffer); + + __asm { + mov edi,dword ptr [gpBuffer] + add edi,371803 + + xor eax,eax + mov edx,148 +_YLp: mov ecx,132 +_XLp1: stosb + inc edi + loop _XLp1 + stosb + sub edi,1033 + mov ecx,132 +_XLp2: inc edi + stosb + loop _XLp2 + sub edi,1032 + dec edx + jnz _YLp + mov ecx,132 +_XLp3: stosb + inc edi + loop _XLp3 + stosb + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PrintUString(int x, int y, BOOL cjustflag, char str[], char col) +{ + long boffset; + int sl,i,w,tw,yy; + + yy = SStringY[y]; + boffset = nBuffWTbl[yy + 204] + x + 96; + sl = strlen(str); + w = 0; + if (cjustflag) { + tw = 0; + for (i = 0; i < sl; i++) { + BYTE c = char2print(str[i]); + c = fonttrans[c]; + tw += fontkern[c]+1; + } + if (tw < 257) w = (257 - tw) >> 1; + boffset += w; + } + for (i = 0; i < sl; i++) { + BYTE c = char2print(str[i]); + c = fonttrans[c]; + w += fontkern[c]+1; + if ((c != 0) && (w <= 257)) DrawPanelFont(boffset, c, col); + boffset += fontkern[c]+1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawULine(int y) +{ + long doffset; + + app_assert(gpBuffer); + doffset = nBuffWTbl[SStringY[y] + 198] + 90; + __asm { + mov esi,dword ptr [gpBuffer] + mov edi,esi + add esi,142170 + add edi,dword ptr [doffset] + + mov ebx,502 + + mov edx,3 +_YLp: mov ecx,66 + rep movsd + movsw + add esi,ebx + add edi,ebx + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawUniqueInfo() +{ + int u,y; + + if (chrflag || questlog) return; + u = curruitem._iUid; + DrawUBack(); + PrintUString(0, 2, TRUE, UniqueItemList[u].UIName, ICOLOR_GOLD); + DrawULine(5); + PrintItemPower(UniqueItemList[u].UIPower1, &curruitem); + y = (6 - UniqueItemList[u].UINumPL) + 8; + PrintUString(0, y, TRUE, tempstr, ICOLOR_WHITE); + if (UniqueItemList[u].UINumPL > 1) { + PrintItemPower(UniqueItemList[u].UIPower2, &curruitem); + PrintUString(0, y+2, TRUE, tempstr, ICOLOR_WHITE); + } + if (UniqueItemList[u].UINumPL > 2) { + PrintItemPower(UniqueItemList[u].UIPower3, &curruitem); + PrintUString(0, y+4, TRUE, tempstr, ICOLOR_WHITE); + } + if (UniqueItemList[u].UINumPL > 3) { + PrintItemPower(UniqueItemList[u].UIPower4, &curruitem); + PrintUString(0, y+6, TRUE, tempstr, ICOLOR_WHITE); + } + if (UniqueItemList[u].UINumPL > 4) { + PrintItemPower(UniqueItemList[u].UIPower5, &curruitem); + PrintUString(0, y+8, TRUE, tempstr, ICOLOR_WHITE); + } + if (UniqueItemList[u].UINumPL > 5) { + PrintItemPower(UniqueItemList[u].UIPower6, &curruitem); + PrintUString(0, y+10, TRUE, tempstr, ICOLOR_WHITE); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PrintItemMisc(const ItemStruct * x) +{ + if (x->_iMiscId == IMID_SCROLL) { + strcpy(tempstr, "Right-click to read"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_TSCROLL) { + strcpy(tempstr, "Right-click to read, then"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "left-click to target"); + AddPanelString(tempstr, TEXT_CENTER); + } + if ((x->_iMiscId >= IMID_FIRSTPOT) && (x->_iMiscId <= IMID_LASTPOT)) { + PrintItemOil(x->_iMiscId); + strcpy(tempstr, "Right click to use"); + AddPanelString(tempstr, TEXT_CENTER); + } + if ((x->_iMiscId > IMID_FIRSTOIL) && (x->_iMiscId < IMID_LASTOIL)) { + PrintItemOil(x->_iMiscId); + strcpy(tempstr, "Right click to use"); + AddPanelString(tempstr, TEXT_CENTER); + } + if ((x->_iMiscId > IMID_FIRSTRUNE) && (x->_iMiscId < IMID_LASTRUNE)) { + PrintItemOil(x->_iMiscId); + strcpy(tempstr, "Right click to use"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_BOOK) { + strcpy(tempstr, "Right click to read"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_FULLNOTE) + { + strcpy(tempstr, "Right click to read"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_MAPOFDOOM) { + strcpy(tempstr, "Right click to view"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_EAR) { + sprintf(tempstr, "Level : %i", x->_ivalue); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMiscId == IMID_AURIC) { + strcpy(tempstr, "Doubles gold capacity"); + AddPanelString(tempstr, TEXT_CENTER); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PrintItemDetails(const ItemStruct * x) +{ + if (x->_iClass == IC_WEAP) { + if (x->_iMinDam == x->_iMaxDam) + { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "damage: %i Indestructible", x->_iMinDam); + else + sprintf(tempstr, "damage: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur); + } + else + { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "damage: %i-%i Indestructible", x->_iMinDam, x->_iMaxDam); + else + sprintf(tempstr, "damage: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur); + } + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iClass == IC_ARMOR) { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "armor: %i Indestructible", x->_iAC); + else + sprintf(tempstr, "armor: %i Dur: %i/%i", x->_iAC, x->_iDurability, x->_iMaxDur); + AddPanelString(tempstr, TEXT_CENTER); + } + if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) { + if (x->_iMinDam == x->_iMaxDam) + sprintf(tempstr, "dam: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur); + else + sprintf(tempstr, "dam: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur); + sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iPrePower != -1) { + PrintItemPower(x->_iPrePower, x); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iSufPower != -1) { + PrintItemPower(x->_iSufPower, x); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMagical == IMAGIC_UNIQUE) { + AddPanelString("unique item", TEXT_CENTER); + uitemflag = TRUE; + curruitem = *x; + } + PrintItemMisc(x); + if ((x->_iMinStr + x->_iMinMag + x->_iMinDex) != 0) { + strcpy(tempstr, "Required:"); + if (x->_iMinStr != 0) sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr); + if (x->_iMinMag != 0) sprintf(tempstr, "%s %i Mag", tempstr, (byte) x->_iMinMag); + if (x->_iMinDex != 0) sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex); + AddPanelString(tempstr, TEXT_CENTER); + } + pinfoflag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PrintItemDur(const ItemStruct * x) +{ + if (x->_iClass == IC_WEAP) { + if (x->_iMinDam == x->_iMaxDam) + { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "damage: %i Indestructible", x->_iMinDam); + else + sprintf(tempstr, "damage: %i Dur: %i/%i", x->_iMinDam, x->_iDurability, x->_iMaxDur); + } + else + { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "damage: %i-%i Indestructible", x->_iMinDam, x->_iMaxDam); + else + sprintf(tempstr, "damage: %i-%i Dur: %i/%i", x->_iMinDam, x->_iMaxDam, x->_iDurability, x->_iMaxDur); + } + AddPanelString(tempstr, TEXT_CENTER); + if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) { + sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); + AddPanelString(tempstr, TEXT_CENTER); + } + if (x->_iMagical) { + AddPanelString("Not Identified", TEXT_CENTER); + } + } + if (x->_iClass == IC_ARMOR) { + if (x->_iMaxDur == INFINITE_DUR) + sprintf(tempstr, "armor: %i Indestructible", x->_iAC); + else + sprintf(tempstr, "armor: %i Dur: %i/%i", x->_iAC, x->_iDurability, x->_iMaxDur); + AddPanelString(tempstr, TEXT_CENTER); + if (x->_iMagical) { + AddPanelString("Not Identified", TEXT_CENTER); + } + if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) { + sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); + AddPanelString(tempstr, TEXT_CENTER); + } + } + if ((x->_itype == IT_RING) || (x->_itype == IT_AMULET)) { + AddPanelString("Not Identified", TEXT_CENTER); + } + PrintItemMisc(x); + if ((x->_iMinStr + x->_iMinMag + x->_iMinDex) != 0) { + strcpy(tempstr, "Required:"); + if (x->_iMinStr != 0) sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr); + if (x->_iMinMag != 0) sprintf(tempstr, "%s %i Mag", tempstr, (byte) x->_iMinMag); + if (x->_iMinDex != 0) sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex); + AddPanelString(tempstr, TEXT_CENTER); + } + pinfoflag = TRUE; +} + +/*-------------------------------------------------------------------------* +**-------------------------------------------------------------------------*/ + +void UseItem(int p, int Mid, int spl) +{ + long l; + __int64 t; + + switch(Mid) { + case IMID_MEAT : + case IMID_PLHEAL : + l = plr[p]._pMaxHP >> (HP_SHIFT + 2); + l = ((random(39, l) + (l >> 1)) << HP_SHIFT); + if (plr[p]._pClass == CLASS_WARRIOR + || plr[p]._pClass == CLASS_BARBARIAN) l = l << 1; + if (plr[p]._pClass == CLASS_ROGUE || + plr[p]._pClass == CLASS_MONK || + plr[p]._pClass == CLASS_BARD) l += (l >> 1); + plr[p]._pHitPoints += l; + if (plr[p]._pHitPoints > plr[p]._pMaxHP) plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase += l; + if (plr[p]._pHPBase > plr[p]._pMaxHPBase) plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + break; + case IMID_PHEAL : + plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + break; + case IMID_PMANA : + l = plr[p]._pMaxMana >> (MANA_SHIFT + 2); + l = ((random(40, l) + (l >> 1)) << MANA_SHIFT); + if (plr[p]._pClass == CLASS_SORCEROR) l = l << 1; + if (plr[p]._pClass == CLASS_ROGUE || + plr[p]._pClass == CLASS_MONK || + plr[p]._pClass == CLASS_BARD) l += (l >> 1); + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pMana += l; + if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase += l; + if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + } + break; + case IMID_PFMANA : + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + } + break; + case IMID_ESTR : + ModifyPlrStr(p, 1); + break; + case IMID_EMAG : + ModifyPlrMag(p, 1); + + // also give full mana potion effect + plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + + break; + case IMID_EDEX : + ModifyPlrDex(p, 1); + break; + case IMID_EVIT : + ModifyPlrVit(p, 1); + + // heal the player, too + plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + + break; + case IMID_BOOK : + t = 1; + plr[p]._pMemSpells |= (t << spl-1); + if (plr[p]._pSplLvl[spl] < SPELLCAP) plr[p]._pSplLvl[spl]++; + plr[p]._pMana += spelldata[spl].sManaCost << MANA_SHIFT; + if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase += spelldata[spl].sManaCost << MANA_SHIFT; + if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase; + if (p == myplr) CalcPlrBookVals(p); + drawmanaflag = TRUE; + break; + case IMID_REJUV : + l = plr[p]._pMaxHP >> (HP_SHIFT + 2); + l = ((random(39, l) + (l >> 1)) << HP_SHIFT); + if (plr[p]._pClass == CLASS_WARRIOR + || plr[p]._pClass == CLASS_BARBARIAN) l = l << 1; + if (plr[p]._pClass == CLASS_ROGUE) l += (l >> 1); + plr[p]._pHitPoints += l; + if (plr[p]._pHitPoints > plr[p]._pMaxHP) plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase += l; + if (plr[p]._pHPBase > plr[p]._pMaxHPBase) plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + l = plr[p]._pMaxMana >> (MANA_SHIFT + 2); + l = ((random(40, l) + (l >> 1)) << MANA_SHIFT); + if (plr[p]._pClass == CLASS_SORCEROR) l = l << 1; + if (plr[p]._pClass == CLASS_ROGUE) l += (l >> 1); + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pMana += l; + if (plr[p]._pMana > plr[p]._pMaxMana) plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase += l; + if (plr[p]._pManaBase > plr[p]._pMaxManaBase) plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + } + break; + case IMID_FREJUV : + plr[p]._pHitPoints = plr[p]._pMaxHP; + plr[p]._pHPBase = plr[p]._pMaxHPBase; + drawhpflag = TRUE; + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pMana = plr[p]._pMaxMana; + plr[p]._pManaBase = plr[p]._pMaxManaBase; + drawmanaflag = TRUE; + } + break; + case IMID_OILACC : + case IMID_OILMAST : + case IMID_OILSHRP : + case IMID_OILDEATH : + case IMID_OILSKILL : + case IMID_OILBLKSM : + case IMID_OILFORT : + case IMID_OILPERM : + case IMID_OILHARD : + case IMID_OILIMPER : + plr[p]._pOilType = Mid; + if (p == myplr) { + if (sbookflag) sbookflag = FALSE; + if (!invflag) invflag = TRUE; + NewCursor(OIL_CURS); + } + break; + case IMID_SCROLL: + if (spelldata[spl].sTargeted) { + plr[p]._pTSpell = spl; + //plr[p]._pTSplType = SPT_SCROLL; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + } else { + ClrPlrPath(p); + plr[p]._pSpell = spl; + //plr[p]._pSplType = SPT_SCROLL; + plr[p]._pSplType = SPT_NONE; + plr[p]._pSplFrom = SPL_FROMSB; + plr[p].destAction = PCMD_SPELL; + plr[p].destParam1 = cursmx; + plr[p].destParam2 = cursmy; + } + break; + case IMID_TSCROLL: + if (spelldata[spl].sTargeted) { + plr[p]._pTSpell = spl; + //plr[p]._pTSplType = SPT_SCROLL; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + } else { + ClrPlrPath(p); + plr[p]._pSpell = spl; + //plr[p]._pSplType = SPT_SCROLL; + plr[p]._pSplType = SPT_NONE; + plr[p]._pSplFrom = SPL_FROMSB; + plr[p].destAction = PCMD_SPELL; + plr[p].destParam1 = cursmx; + plr[p].destParam2 = cursmy; + } + break; + case IMID_MAPOFDOOM: + InitMapOfDoomView(); + break; + case IMID_SPECTRAL: + ModifyPlrStr(p, 3); + ModifyPlrMag(p, 3); + ModifyPlrDex(p, 3); + ModifyPlrVit(p, 3); + break; + case IMID_RUNEFIRE: + plr[p]._pTSpell = SPL_RUNEOFFIRE; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_RUNELIGHT: + plr[p]._pTSpell = SPL_RUNEOFLIGHT; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_RUNEIMMOLATE: + plr[p]._pTSpell = SPL_RUNEOFIMMOLATION; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_RUNENOVA: + plr[p]._pTSpell = SPL_RUNEOFNOVA; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_RUNESTONE: + plr[p]._pTSpell = SPL_RUNEOFSTONE; + plr[p]._pTSplType = SPT_NONE; + if (p == myplr) { + NewCursor(TARGET_CURS); + } + break; + case IMID_FULLNOTE: +// InitQTextMsg(TXT_SKULLJRNL7); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#define MAX_STORE_VAL 200000 +#define MAX_WIRT_VAL 200000 // Wirts stuff is 75% of normal + +BOOL StoreStatOk(ItemStruct *h) +{ + BOOL sf = TRUE; + if (plr[myplr]._pStrength < h->_iMinStr) sf = FALSE; + else if (plr[myplr]._pMagic < (byte)h->_iMinMag) sf = FALSE; + else if (plr[myplr]._pDexterity < h->_iMinDex) sf = FALSE; + return(sf); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL SmithItemOk(int i) +{ + BOOL rv; + + rv = TRUE; + // Selling oil is too powerful for the money received. +// if (AllItemsList[i].iMiscId > IMID_FIRSTOIL && +// AllItemsList[i].iMiscId < IMID_LASTOIL) rv = TRUE; +// else + if (AllItemsList[i].itype == IT_MISC) rv = FALSE; + + if (AllItemsList[i].itype == IT_GOLD) rv = FALSE; + if (AllItemsList[i].itype == IT_FOOD) rv = FALSE; + if (AllItemsList[i].itype == IT_STAFF + && AllItemsList[i].iSpell != 0) rv = FALSE; + if (AllItemsList[i].itype == IT_RING) rv = FALSE; + if (AllItemsList[i].itype == IT_AMULET) rv = FALSE; + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndSmithItem(int lvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && SmithItemOk(i) && + (lvl >= AllItemsList[i].iMinMLvl) + && ri < 512) { + ril[ri++] = i; + if (AllItemsList[i].iRnd == IRND_DOUBLE + && ri < 512) ril[ri++] = i; + } + } + return(ril[random(50, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void BubbleSwapItem(ItemStruct * a, ItemStruct * b) +{ + ItemStruct h; + + h = *a; + *a = *b; + *b = h; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SortSmith() +{ + int j, k; + BOOL sorted; + + for (k = 0; smithitem[k+1]._itype != -1; k++); + sorted = FALSE; + while ((k > 0) && (!sorted)) { + sorted = TRUE; + for (j = 0; j < k; j++) { + if (smithitem[j].IDidx > smithitem[j+1].IDidx) { + BubbleSwapItem(&smithitem[j], &smithitem[j+1]); + sorted = FALSE; + } + } + k--; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnSmith(int lvl) +{ + int itype; + int i,nsi; + ItemStruct const holditem = item[0]; + + nsi = random(50, (MAXSMITHITEMS - 10)) + 10; + for (i = 0; i < nsi; i++) { + do { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndSmithItem(lvl) - 1; + GetItemAttrs(0, itype, lvl); + } while (item[0]._iIvalue > MAX_STORE_VAL); + smithitem[i] = item[0]; + smithitem[i]._iCreateInfo = lvl | ICI_SMITH; + smithitem[i]._iIdentified = TRUE; + smithitem[i]._iStatFlag = StoreStatOk(&smithitem[i]); + } + for (i = nsi; i < MAXSMITHITEMS; i++) smithitem[i]._itype = -1; + SortSmith(); + item[0] = holditem; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PremiumItemOk(int i) +{ + BOOL rv; + + rv = TRUE; + if (AllItemsList[i].itype == IT_MISC) rv = FALSE; + else if (AllItemsList[i].itype == IT_GOLD) rv = FALSE; + else if (AllItemsList[i].itype == IT_FOOD) rv = FALSE; + if (gbMaxPlayers != 1) { + if (AllItemsList[i].iMiscId == IMID_OIL) rv = FALSE; + else if (AllItemsList[i].itype == IT_RING) rv = FALSE; + else if (AllItemsList[i].itype == IT_AMULET) rv = FALSE; + } + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndPremiumItem(int minlvl, int maxlvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && PremiumItemOk(i) && + (AllItemsList[i].iMinMLvl >= minlvl) && + (AllItemsList[i].iMinMLvl <= maxlvl) && + ri < 512) { + ril[ri++] = i; + } + } + return(ril[random(50, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SpawnOnePremium(int i, int plvl, int myplr, bool noSpells) +{ + int itype; + ItemStruct const holditem = item[0]; + int const maxval = MAX_STORE_VAL; + int ivalue; + int iCount = 0; + int maxPlrStr = GetMaxStr(plr[myplr]._pClass); + int maxPlrDex = GetMaxDex(plr[myplr]._pClass); + int maxPlrMag = GetMaxMag(plr[myplr]._pClass); + + // Test in case of bonus + if (maxPlrStr < plr[myplr]._pStrength) + { + maxPlrStr = plr[myplr]._pStrength; + } + maxPlrStr = (int)(maxPlrStr * 1.2); + + if (maxPlrDex < plr[myplr]._pDexterity) + { + maxPlrDex = plr[myplr]._pDexterity; + } + maxPlrDex = (int)(maxPlrDex * 1.2); + + if (maxPlrMag < plr[myplr]._pMagic) + { + maxPlrMag = plr[myplr]._pMagic; + } + maxPlrMag = (int)(maxPlrMag * 1.2); + + +#if CHEATS + if ((plvl > 30) || (davecheat)) plvl = 30; +#else + if (plvl > 30) plvl = 30; +#endif + if (plvl < 1) plvl = 1; + + do { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndPremiumItem(plvl>>2, plvl) - 1; + GetItemAttrs(0, itype, plvl); + GetItemBonus(0, itype, plvl>>1, plvl, TRUE, noSpells); + + ivalue = 0; + + switch (item[0]._itype) + { + case IT_ARMOR: + case IT_MARMOR: + case IT_HARMOR: + ivalue = GetHighArmorValue(myplr); + break; + case IT_SHIELD: + ivalue = GetHighShieldValue(myplr); + break; + case IT_AXE: + ivalue = GetHighAxeValue(myplr); + break; + case IT_BOW: + ivalue = GetHighBowValue(myplr); + break; + case IT_MACE: + ivalue = GetHighMaceValue(myplr); + break; + case IT_SWORD: + ivalue = GetHighSwordValue(myplr); + break; + case IT_HELM: + ivalue = GetHighHelmValue(myplr); + break; + case IT_STAFF: + ivalue = GetHighStaffValue(myplr); + break; + case IT_RING: + ivalue = GetHighRingValue(myplr); + break; + case IT_AMULET: + ivalue = GetHighAmuletValue(myplr); + break; + } + ivalue = (int)(0.8 * ivalue); + + ++iCount; + + // GWP Make sure we can actually use it. + } while ((item[0]._iIvalue > maxval + || item[0]._iMinStr > maxPlrStr + || item[0]._iMinMag > maxPlrMag + || item[0]._iMinDex > maxPlrDex + || item[0]._iIvalue < ivalue) // already have better. + && iCount < 150 // prevent infinite loops. + ); + + premiumitem[i] = item[0]; + premiumitem[i]._iCreateInfo = plvl | ICI_PREMIUM; + premiumitem[i]._iIdentified = TRUE; + premiumitem[i]._iStatFlag = StoreStatOk(&premiumitem[i]); + item[0] = holditem; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int premiumlvladd[MAXPREMIUM] = { -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3 }; + +void SpawnPremium(int myplr) +{ + int lvl = plr[myplr]._pLevel; + int i; + + // Empty slots? + if (numpremium < MAXPREMIUM) { + for (i = 0; i < MAXPREMIUM; ++i) { + if (premiumitem[i]._itype == -1) + SpawnOnePremium(i, premiumlevel + premiumlvladd[i], myplr, false); + } + numpremium = MAXPREMIUM; + } + // New items? + while (premiumlevel < lvl) { + premiumlevel++; + premiumitem[0] = premiumitem[3]; + premiumitem[1] = premiumitem[4]; + premiumitem[2] = premiumitem[5]; + premiumitem[3] = premiumitem[6]; + premiumitem[4] = premiumitem[7]; + premiumitem[5] = premiumitem[8]; + premiumitem[6] = premiumitem[9]; + premiumitem[7] = premiumitem[10]; + premiumitem[8] = premiumitem[11]; + premiumitem[9] = premiumitem[12]; + SpawnOnePremium(10, premiumlevel + premiumlvladd[10], myplr, false); + premiumitem[11] = premiumitem[13]; + SpawnOnePremium(12, premiumlevel + premiumlvladd[12], myplr, false); + premiumitem[13] = premiumitem[14]; + SpawnOnePremium(14, premiumlevel + premiumlvladd[14], myplr, false); + } + +#if 15 != MAXPREMIUM +#error "Fix code for new MAXPREMIUM" +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL WitchItemOk(int i) +{ + BOOL rv; + + rv = FALSE; + if (AllItemsList[i].itype == IT_MISC) rv = TRUE; + else if (AllItemsList[i].itype == IT_STAFF) rv = TRUE; + + // Will already have the next one + if (AllItemsList[i].iMiscId == IMID_PMANA) rv = FALSE; + else if (AllItemsList[i].iMiscId == IMID_PFMANA) rv = FALSE; + + if (AllItemsList[i].iSpell == SPL_TOWN) rv = FALSE; + // no healing + if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = FALSE; + else if (AllItemsList[i].iMiscId == IMID_PLHEAL) rv = FALSE; + + // no oils + if (AllItemsList[i].iMiscId > IMID_FIRSTOIL && + AllItemsList[i].iMiscId < IMID_LASTOIL) + rv = FALSE; + // None of these in single player + if (AllItemsList[i].iSpell == SPL_RESURRECT && gbMaxPlayers == 1) rv = FALSE; + else if (AllItemsList[i].iSpell == SPL_HEALOTHER && gbMaxPlayers == 1) rv = FALSE; + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndWitchItem(int lvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; ++i) { + if (AllItemsList[i].iRnd && WitchItemOk(i) && + (lvl >= AllItemsList[i].iMinMLvl) && + ri < 512) + { + ril[ri++] = i; + } + } + return(ril[random(51, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SortWitch() +{ + int j, k; + BOOL sorted; + + for (k = 3; witchitem[k+1]._itype != -1; k++); + sorted = FALSE; + while ((k > 3) && (!sorted)) { + sorted = TRUE; + for (j = 3; j < k; j++) { + if (witchitem[j].IDidx > witchitem[j+1].IDidx) { + BubbleSwapItem(&witchitem[j], &witchitem[j+1]); + sorted = FALSE; + } + } + k--; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void WitchBookLevel(int ii) +{ + if (witchitem[ii]._iMiscId != IMID_BOOK) + return; + + witchitem[ii]._iMinMag = spelldata[witchitem[ii]._iSpell].sMinInt; + int slvl = plr[myplr]._pSplLvl[witchitem[ii]._iSpell]; + + while (slvl != 0) { + witchitem[ii]._iMinMag += ((witchitem[ii]._iMinMag * 20) / 100); + slvl--; + if ((witchitem[ii]._iMinMag + ((witchitem[ii]._iMinMag * 20) / 100)) > 255) { + witchitem[ii]._iMinMag = 255; + slvl = 0; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnWitch(int lvl) +{ + int itype, iblvl; + int i; + int start = 3; + + int const nsi = random(51, (MAXWITCHITEMS - 10)) + 10; + int const max_number_of_books = random(3, 1 + (IDI_LAST_BOOK - IDI_FIRST_BOOK)); + int number_of_books; + + // Will always have mana (endless supply) + GetItemAttrs(0, IDI_MANA, 1); + witchitem[0] = item[0]; + witchitem[0]._iCreateInfo = lvl; + witchitem[0]._iStatFlag = TRUE; + GetItemAttrs(0, IDI_FULLMANA, 1); + witchitem[1] = item[0]; + witchitem[1]._iCreateInfo = lvl; + witchitem[1]._iStatFlag = TRUE; + GetItemAttrs(0, IDI_PORTAL, 1); + witchitem[2] = item[0]; + witchitem[2]._iCreateInfo = lvl; + witchitem[2]._iStatFlag = TRUE; + for (i = IDI_FIRST_BOOK, number_of_books = 0; + i <= IDI_LAST_BOOK + && number_of_books < max_number_of_books; + ++i) + { + + if ( WitchItemOk(i) + && lvl >= AllItemsList[i].iMinMLvl + ) + { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + volatile int dummy = random(0, 1); // to sync with below + + GetItemAttrs(0, i, lvl); + witchitem[start] = item[0]; + witchitem[start]._iCreateInfo = lvl | ICI_WITCH; + witchitem[start]._iIdentified = TRUE; + WitchBookLevel(start); + witchitem[start]._iStatFlag = StoreStatOk(&witchitem[start]); + ++start; + ++number_of_books; + } + } + + for (i = start; i < nsi; ++i) { + do { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndWitchItem(lvl) - 1; + GetItemAttrs(0, itype, lvl); + iblvl = -1; + if (random(51, 100) <= 5) iblvl = lvl << 1; + // Force staffs to be magical + if ((iblvl == -1) && (item[0]._iMiscId == IMID_STAFF)) iblvl = lvl << 1; +#if CHEATS + if (cheatflag) iblvl = lvl << 1; +#endif + if (iblvl != -1) GetItemBonus(0, itype, iblvl >> 1, iblvl, TRUE, true); + } while (item[0]._iIvalue > MAX_STORE_VAL); + witchitem[i] = item[0]; + witchitem[i]._iCreateInfo = lvl | ICI_WITCH; + witchitem[i]._iIdentified = TRUE; + WitchBookLevel(i); + witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]); + //WitchBookLevel(i); + } + for (i = nsi; i < MAXWITCHITEMS; i++) witchitem[i]._itype = -1; + SortWitch(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndBoyItem(int lvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; ++i) { + if (AllItemsList[i].iRnd && PremiumItemOk(i) && + (lvl >= AllItemsList[i].iMinMLvl) && + ri < 512) ril[ri++] = i; + } + return(ril[random(49, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnBoy(int lvl) +{ + int itype; + int ivalue; + int iCount = 0; + int maxPlrStr = GetMaxStr(plr[myplr]._pClass); + int maxPlrDex = GetMaxDex(plr[myplr]._pClass); + int maxPlrMag = GetMaxMag(plr[myplr]._pClass); + int const PlayerClass = plr[myplr]._pClass; + + // Test in case of bonus + if (maxPlrStr < plr[myplr]._pStrength) + { + maxPlrStr = plr[myplr]._pStrength; + } + maxPlrStr = (int)(maxPlrStr * 1.2); + + if (maxPlrDex < plr[myplr]._pDexterity) + { + maxPlrDex = plr[myplr]._pDexterity; + } + maxPlrDex = (int)(maxPlrDex * 1.2); + + if (maxPlrMag < plr[myplr]._pMagic) + { + maxPlrMag = plr[myplr]._pMagic; + } + maxPlrMag = (int)(maxPlrMag * 1.2); + + + + if ((boylevel < (lvl >> 1)) || (boyitem._itype == -1)) { + do { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndBoyItem(lvl) - 1; + GetItemAttrs(0, itype, lvl); + // Always magical + GetItemBonus(0, itype, lvl, lvl << 1, TRUE, true); + ivalue = 0; + + int const itemType = item[0]._itype; + + switch (itemType) + { + case IT_ARMOR: + case IT_MARMOR: + case IT_HARMOR: + ivalue = GetHighArmorValue(myplr); + break; + case IT_SHIELD: + ivalue = GetHighShieldValue(myplr); + break; + case IT_AXE: + ivalue = GetHighAxeValue(myplr); + break; + case IT_BOW: + ivalue = GetHighBowValue(myplr); + break; + case IT_MACE: + ivalue = GetHighMaceValue(myplr); + break; + case IT_SWORD: + ivalue = GetHighSwordValue(myplr); + break; + case IT_HELM: + ivalue = GetHighHelmValue(myplr); + break; + case IT_STAFF: + ivalue = GetHighStaffValue(myplr); + break; + case IT_RING: + ivalue = GetHighRingValue(myplr); + break; + case IT_AMULET: + ivalue = GetHighAmuletValue(myplr); + break; + } + ivalue = (int)(0.8 * ivalue); + + ++iCount; + + if (iCount < 200) // prevent infinite loops. + { + switch (PlayerClass) + { + case CLASS_WARRIOR: + if (itemType == IT_BOW + || itemType == IT_STAFF) + ivalue = INT_MAX; + break; + case CLASS_ROGUE: + if (itemType == IT_SWORD + || itemType == IT_STAFF + || itemType == IT_AXE + || itemType == IT_MACE + || itemType == IT_SHIELD) + ivalue = INT_MAX; + break; + case CLASS_SORCEROR: + if (itemType == IT_STAFF + || itemType == IT_AXE + || itemType == IT_BOW + || itemType == IT_MACE) + ivalue = INT_MAX; + break; + case CLASS_MONK: + if (itemType == IT_BOW + || itemType == IT_MARMOR + || itemType == IT_SHIELD + || itemType == IT_MACE) + ivalue = INT_MAX; + break; + case CLASS_BARD: + if (itemType == IT_AXE + || itemType == IT_MACE + || itemType == IT_STAFF) + ivalue = INT_MAX; + break; + case CLASS_BARBARIAN: + if (itemType == IT_BOW + || itemType == IT_STAFF) + ivalue = INT_MAX; + break; + } + } + + + } while ((item[0]._iIvalue > MAX_WIRT_VAL + || item[0]._iMinStr > maxPlrStr + || item[0]._iMinMag > maxPlrMag + || item[0]._iMinDex > maxPlrDex + || item[0]._iIvalue < ivalue) // already have better. + && iCount < 250 // prevent infinite loops. + ); + boyitem = item[0]; + boyitem._iCreateInfo = lvl | ICI_BOY; + boyitem._iIdentified = TRUE; + boyitem._iStatFlag = StoreStatOk(&boyitem); + boylevel = lvl >> 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL HealerItemOk(int i) +{ + BOOL rv; + + rv = FALSE; + if (AllItemsList[i].itype != IT_MISC) return(FALSE); + // Heal scrolls + if ((AllItemsList[i].iMiscId == IMID_SCROLL) && (AllItemsList[i].iSpell == SPL_HEAL)) rv = TRUE; + // Will always have Resurrect scrolls (multiplayer only) + if ((AllItemsList[i].iMiscId == IMID_TSCROLL) && (AllItemsList[i].iSpell == SPL_RESURRECT) && (gbMaxPlayers != 1)) rv = FALSE; + // Heal Other scroll (multiplayer only) + if ((AllItemsList[i].iMiscId == IMID_TSCROLL) && (AllItemsList[i].iSpell == SPL_HEALOTHER) && (gbMaxPlayers != 1)) rv = TRUE; + // Elixirs + if (gbMaxPlayers == 1) { + if (AllItemsList[i].iMiscId == IMID_ESTR + && plr[myplr]._pBaseStr < MaxStats[plr[myplr]._pClass][0]) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_EMAG + && plr[myplr]._pBaseMag < MaxStats[plr[myplr]._pClass][1]) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_EDEX + && plr[myplr]._pBaseDex < MaxStats[plr[myplr]._pClass][2]) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_EVIT + && plr[myplr]._pBaseVit < MaxStats[plr[myplr]._pClass][3]) rv = TRUE; + } + // Potions + if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_REJUV) rv = TRUE; + else if (AllItemsList[i].iMiscId == IMID_FREJUV) rv = TRUE; + // Will always have these + else if (AllItemsList[i].iMiscId == IMID_PLHEAL) rv = FALSE; + else if (AllItemsList[i].iMiscId == IMID_PHEAL) rv = FALSE; + // No mana + else if (AllItemsList[i].iMiscId == IMID_PMANA) rv = FALSE; + else if (AllItemsList[i].iMiscId == IMID_PFMANA) rv = FALSE; + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int RndHealerItem(int lvl) +{ + int ril[512]; // Max 512 items + int ri, i; + + ri = 0; + for (i = 1; AllItemsList[i].iLoc != -1; i++) { + if (AllItemsList[i].iRnd && HealerItemOk(i) && + (lvl >= AllItemsList[i].iMinMLvl) && + ri < 512) ril[ri++] = i; + } + return(ril[random(50, ri)]+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SortHealer() +{ + int j, k; + BOOL sorted; + + for (k = 2; healitem[k+1]._itype != -1; k++); + sorted = FALSE; + while ((k > 2) && (!sorted)) { + sorted = TRUE; + for (j = 2; j < k; j++) { + if (healitem[j].IDidx > healitem[j+1].IDidx) { + BubbleSwapItem(&healitem[j], &healitem[j+1]); + sorted = FALSE; + } + } + k--; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnHealer(int lvl) +{ + int itype; + int i,nsi,srnd; + + // Will always have healing (endless supply) + GetItemAttrs(0, IDI_HEAL, 1); + healitem[0] = item[0]; + healitem[0]._iCreateInfo = lvl; + healitem[0]._iStatFlag = TRUE; + GetItemAttrs(0, IDI_FULLHEAL, 1); + healitem[1] = item[0]; + healitem[1]._iCreateInfo = lvl; + healitem[1]._iStatFlag = TRUE; + if (gbMaxPlayers != 1) { + GetItemAttrs(0, IDI_RESURRECT, 1); + healitem[2] = item[0]; + healitem[2]._iCreateInfo = lvl; + healitem[2]._iStatFlag = TRUE; + srnd = 3; + } else srnd = 2; + + nsi = random(50, (MAXHEALITEMS - 10)) + 10; + for (i = srnd; i < nsi; i++) { + item[0]._iSeed = GetRndSeed(); + SetRndSeed(item[0]._iSeed); + itype = RndHealerItem(lvl) - 1; + GetItemAttrs(0, itype, lvl); + healitem[i] = item[0]; + healitem[i]._iCreateInfo = lvl | ICI_HEALER; + healitem[i]._iIdentified = TRUE; + healitem[i]._iStatFlag = StoreStatOk(&healitem[i]); + } + for (i = nsi; i < MAXHEALITEMS; i++) healitem[i]._itype = -1; + SortHealer(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnStoreGold() +{ + // Setup a gold item to place in inv if they sell + GetItemAttrs(0, 0, 1); + golditem = item[0]; + golditem._iStatFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreateSmithItem(int ii, int idx, int lvl, int iseed) +{ + SetRndSeed(iseed); + int itype = RndSmithItem(lvl) - 1; + GetItemAttrs(ii, itype, lvl); + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = lvl | ICI_SMITH; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreatePremiumItem(int ii, int idx, int plvl, int iseed) +{ + SetRndSeed(iseed); + int itype = RndPremiumItem(plvl>>2, plvl) - 1; + GetItemAttrs(ii, itype, plvl); + GetItemBonus(ii, itype, plvl>>1, plvl, TRUE, false); + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = plvl | ICI_PREMIUM; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreateBoyItem(int ii, int idx, int lvl, int iseed) +{ + SetRndSeed(iseed); + int itype = RndBoyItem(lvl) - 1; + GetItemAttrs(ii, itype, lvl); + // Always magical + GetItemBonus(ii, itype, lvl, lvl << 1, TRUE, true); + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = lvl | ICI_BOY; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreateWitchItem(int ii, int idx, int lvl, int iseed) +{ + if ((idx == IDI_MANA) + || (idx == IDI_FULLMANA) + || (idx == IDI_PORTAL)) + { + GetItemAttrs(ii, idx, lvl); + } else if( idx >= IDI_FIRST_BOOK && idx <= IDI_LAST_BOOK) { + SetRndSeed(iseed); + volatile int dummy = random(0, 1); // to sync with below + GetItemAttrs(ii, idx, lvl); + } else { + SetRndSeed(iseed); + int itype = RndWitchItem(lvl) - 1; + GetItemAttrs(ii, itype, lvl); + int iblvl = -1; + if (random(51, 100) <= 5) iblvl = lvl << 1; + // Force staffs to be magical + if ((iblvl == -1) && (item[ii]._iMiscId == IMID_STAFF)) iblvl = lvl << 1; +#if CHEATS + if (cheatflag) iblvl = lvl << 1; +#endif + if (iblvl != -1) GetItemBonus(ii, itype, iblvl >> 1, iblvl, TRUE, true); + } + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = lvl | ICI_WITCH; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RecreateHealerItem(int ii, int idx, int lvl, int iseed) +{ + if ((idx == IDI_HEAL) || (idx == IDI_FULLHEAL) || (idx == IDI_RESURRECT)) { + GetItemAttrs(ii, idx, lvl); + } else { + SetRndSeed(iseed); + int itype = RndHealerItem(lvl) - 1; + GetItemAttrs(ii, itype, lvl); + } + item[ii]._iSeed = iseed; + item[ii]._iCreateInfo = lvl | ICI_HEALER; + item[ii]._iIdentified = TRUE; +} + +/*-----------------------------------------------------------------------* +** Recreate any item with the proper info +**-----------------------------------------------------------------------*/ + +void RecreateTownItem(int ii, int idx, WORD icreateinfo, int iseed, int ivalue) +{ + if (icreateinfo & ICI_SMITH) RecreateSmithItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); + else if (icreateinfo & ICI_PREMIUM) RecreatePremiumItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); + else if (icreateinfo & ICI_BOY) RecreateBoyItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); + else if (icreateinfo & ICI_WITCH) RecreateWitchItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); + else if (icreateinfo & ICI_HEALER) RecreateHealerItem(ii, idx, icreateinfo & ICI_LVLMASK, iseed); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#if CHEATS +void DaveGold() +{ + int i,j; + + for (j = 0; j < MAXINV; j++) { + if (plr[myplr].InvGrid[j] == 0) { + i = plr[myplr]._pNumInv; + SetPlrHandItem(&plr[myplr].InvList[i], IDI_GOLD); + GetGoldSeed(myplr, &plr[myplr].InvList[i]); + plr[myplr].InvList[i]._ivalue = 5000; + plr[myplr].InvList[i]._iCurs = ITEM_5GOLD; + plr[myplr].InvList[i]._iStatFlag = TRUE; + plr[myplr]._pGold += 5000; + plr[myplr]._pNumInv++; + plr[myplr].InvGrid[j] = plr[myplr]._pNumInv; + } + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#if CHEATS +void DaveNewPremium() +{ + numpremium = 0; + for (int i = 0; i < MAXPREMIUM; i++) premiumitem[i]._itype = -1; + SpawnPremium(30); + for (i = 0; i < MAXWITCHITEMS; i++) witchitem[i]._itype = -1; + SpawnWitch(30); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#if CHEATS +void DaveCleanUp() +{ + int i,j; + + for (j = 0; j < MAXINV; j++) { + if (plr[myplr].InvGrid[j] > 0) { + i = plr[myplr].InvGrid[j]-1; + if (plr[myplr].InvList[i]._itype == IT_GOLD) RemoveInvItem(myplr, i); + } + } + for (j = 0; j < MAXSPD; j++) { + if (plr[myplr].SpdList[j]._itype == IT_GOLD) plr[myplr].SpdList[j]._itype = -1; + } + plr[myplr]._pGold = 0; +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#if CHEATS +void DaveSpells() +{ + for (int i = SPL_FIREBOLT; i < SPL_LAST; i++) { + if (spelldata[i].sBookLvl != -1) { + __int64 t = 1; + plr[myplr]._pMemSpells |= (t << (i-1)); + plr[myplr]._pSplLvl[i] = 10; + } + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#if CHEATS +void DaveSetSpell(int spl, int lvl) +{ + __int64 t = 1; + plr[myplr]._pMemSpells |= (t << (spl-1)); + plr[myplr]._pSplLvl[spl] = lvl; +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#if CHEATS +void DaveSpells2() +{ + DaveSetSpell(SPL_FIREBOLT, 8); + DaveSetSpell(SPL_CBOLT, 11); + DaveSetSpell(SPL_HBOLT, 10); + DaveSetSpell(SPL_HEAL, 7); + DaveSetSpell(SPL_HEALOTHER, 5); + DaveSetSpell(SPL_LIGHTNING, 9); + DaveSetSpell(SPL_WALL, 5); + DaveSetSpell(SPL_TELEKINESIS, 3); + DaveSetSpell(SPL_TOWN, 3); + DaveSetSpell(SPL_FLASH, 3); + DaveSetSpell(SPL_PHASE, 2); + DaveSetSpell(SPL_MANASHLD, 2); + DaveSetSpell(SPL_WAVE, 4); + DaveSetSpell(SPL_FIREBALL, 3); + DaveSetSpell(SPL_STONE, 1); + DaveSetSpell(SPL_CHAIN, 1); + DaveSetSpell(SPL_GUARDIAN, 4); + DaveSetSpell(SPL_ELEMENT, 3); + DaveSetSpell(SPL_NOVA, 1); + DaveSetSpell(SPL_GOLEM, 2); + DaveSetSpell(SPL_BSTAR, 1); + DaveSetSpell(SPL_BONESPIRIT, 1); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RecalcStoreStats() +{ + int i; + + for (i = 0; i < MAXSMITHITEMS; i++) + if (smithitem[i]._itype != -1) smithitem[i]._iStatFlag = StoreStatOk(&smithitem[i]); + for (i = 0; i < MAXPREMIUM; i++) + if (premiumitem[i]._itype != -1) premiumitem[i]._iStatFlag = StoreStatOk(&premiumitem[i]); + for (i = 0; i < MAXWITCHITEMS; i++) + if (witchitem[i]._itype != -1) witchitem[i]._iStatFlag = StoreStatOk(&witchitem[i]); + for (i = 0; i < MAXHEALITEMS; i++) + if (healitem[i]._itype != -1) healitem[i]._iStatFlag = StoreStatOk(&healitem[i]); + boyitem._iStatFlag = StoreStatOk(&boyitem); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int ItemNoFlippy() +/*-----------------------------------------------------------------------** +** DESCRIPTION: Makes it so a newly created item will not have a flippy. +** INPUT: None +** RETURN: r = The item number if needed. +/*-----------------------------------------------------------------------*/ +{ + int r; + + r = itemactive[numitems-1]; + item[r]._iAnimFrame = item[r]._iAnimLen; + item[r]._iAnimFlag = FALSE; + item[r]._iSelFlag = ISEL_FLR; + + return r; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if CHEATS +void DaveQuestText() +{ + if (!tstQMsgIndexFlag) { + tstQMsgFlag = TRUE; + InitQTextMsg(tstQMsgIndex); + } +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CreateSpellBook(int x, int y, int ispell, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + BOOL done = FALSE; + + int bookminlevel = spelldata[ispell].sBookLvl + 1; + + if (bookminlevel < 1) // unavailable + return; + + idx = RndTypeItems(IT_MISC, IMID_BOOK, bookminlevel); + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + //Loop until we get the book requested + do { + SetupAllItems(ii, idx, GetRndSeed(), /* currlevel */ bookminlevel << 1, 1, TRUE, FALSE, delta); + if ((item[ii]._iMiscId == IMID_BOOK) && + (item[ii]._iSpell == ispell)) { + done = TRUE; + } + } while (!done); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CreateMagicArmor(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + BOOL done = FALSE; + + int efflevel = GetEffLevel(); + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + //Loop until we get the armor requested + idx = RndTypeItems(imisc, IMID_NONE, efflevel); + do { +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 1, TRUE, FALSE, delta); + if (item[ii]._iCurs == icurs) { + done = TRUE; + } else idx = RndTypeItems(imisc, IMID_NONE, efflevel); + } while (!done); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CreateAmulet(int x, int y, int level, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + bool done = false; + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + //Loop until we get the amulet requested + idx = RndTypeItems(IT_AMULET, IMID_AMULET, level); + do { +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), level << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), level << 1, 1, TRUE, FALSE, delta); + if (item[ii]._iCurs == ITEM_AMULET1) { + done = true; + } else idx = RndTypeItems(IT_AMULET, IMID_AMULET, level); + } while (!done); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CreateMagicWeapon(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta) +{ + int ii, idx; + BOOL done = FALSE; + int const imid = (imisc == IT_STAFF) ? IMID_STAFF : IMID_NONE; + + int efflevel = GetEffLevel(); + + if (numitems < MAXITEMS) { + ii = itemavail[0]; + GetSuperItemSpace(x,y,ii); + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + //Loop until we get the weapon requested + idx = RndTypeItems(imisc, imid, efflevel); + do { +#if CHEATS + if (itemcheat) + SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 15, TRUE, FALSE, delta); + else +#endif + SetupAllItems(ii, idx, GetRndSeed(), efflevel << 1, 1, TRUE, FALSE, delta); + if (item[ii]._iCurs == icurs) { + done = TRUE; + } else idx = RndTypeItems(imisc, imid, efflevel); + } while (!done); + if (sendmsg) NetSendCmdDItem(FALSE, ii); + if (delta) DeltaAddItem(ii); + numitems++; + } +} + + +// PATCH1.JMM +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void DeleteGetRecord( int nIndex ) { + app_assert(nIndex < gnNumGetRecords); + app_assert(gnNumGetRecords > 0); + + gnNumGetRecords--; + + if(gnNumGetRecords == 0) + return; + + itemgets[nIndex].nIndex = itemgets[gnNumGetRecords].nIndex; + itemgets[nIndex].nSeed = itemgets[gnNumGetRecords].nSeed; + itemgets[nIndex].wCI = itemgets[gnNumGetRecords].wCI; + itemgets[nIndex].dwTimestamp = itemgets[gnNumGetRecords].dwTimestamp; +} + + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#define RESEND_TIME 6000 // number of milliseconds to keep a getrecord around + +BOOL CheckGetRecord( int nSeed, WORD wCI, int nIndex ) { + DWORD dwCurr = GetTickCount(); + int i; + + for(i = 0; i < gnNumGetRecords; i++) { + if( (dwCurr - itemgets[i].dwTimestamp) > RESEND_TIME ) { + DeleteGetRecord( i ); + i--; + continue; + } + + if( (nSeed == itemgets[i].nSeed) && (wCI == itemgets[i].wCI) && (nIndex == itemgets[i].nIndex) ) + return FALSE; + + } + + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddGetRecord( int nSeed, WORD wCI, int nIndex ) { + DWORD dwCurr = GetTickCount(); + + if(gnNumGetRecords == MAXITEMS) + return; + + itemgets[gnNumGetRecords].dwTimestamp = dwCurr; + itemgets[gnNumGetRecords].nSeed = nSeed; + itemgets[gnNumGetRecords].wCI = wCI; + itemgets[gnNumGetRecords].nIndex = nIndex; + + gnNumGetRecords++; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RemoveGetRecord( int nSeed, WORD wCI, int nIndex ) { + DWORD dwCurr = GetTickCount(); + int i; + + for(i = 0; i < gnNumGetRecords; i++) { + if( (dwCurr - itemgets[i].dwTimestamp) > RESEND_TIME ) { + DeleteGetRecord( i ); + i--; + continue; + } + + if( (nSeed == itemgets[i].nSeed) && (wCI == itemgets[i].wCI) && (nIndex == itemgets[i].nIndex) ) { + DeleteGetRecord( i ); + return; + } + + } + +} + + +//ENDPATCH1.JMM diff --git a/src/ITEMS.H b/src/ITEMS.H new file mode 100644 index 0000000..80826ee --- /dev/null +++ b/src/ITEMS.H @@ -0,0 +1,905 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/ITEMS.H 3 2/06/97 6:08p Jessmac $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXITEMS 127 + +#define MAXUITEMS 128 // Max number of uniques + +#define TEMPAVAIL 127 + +#define ITEM_RND -1 + +#define INFINITE_DUR 255 + +#define GOLD_VT1 1000 // Gold gfx transition from 1 to several +#define GOLD_VT2 2500 // Gold gfx transition from several to many +//#define GOLD_VMAX 5000 // Max gold in an inv slot +extern int GOLD_VMAX; +extern const int GOLD_DOUBLE_VMAX; + +// Used for cursors +// 1x1 +typedef enum { + ITEM_BLUEBTL = 0, + ITEM_SCROLL , // 1 + ITEM_SCROLL2 , // 2 + ITEM_SCROLL3 , // 3 + ITEM_1GOLD , // 4 + ITEM_3GOLD , // 5 + ITEM_5GOLD , // 6 + ITEM_GOLDRING , // 7 + ITEM_1JRING , // 8 + ITEM_WOODRING , // 9 + ITEM_BLUERING , // 10 + ITEM_3JRING , // 11 + ITEM_SLVRRING , // 12 + ITEM_MJRING , // 13 + ITEM_BRNRING , // 14 + ITEM_SPECTRAL , // 15 + ITEM_3COLORPOT , // 16 + ITEM_GOLDENELIX , // 17 + ITEM_EMPYBAND , // 18 + ITEM_EAR1 , // 19 + ITEM_EAR2 , // 20 + ITEM_EAR3 , // 21 + ITEM_SPHERE , // 22 + ITEM_CUBE , // 23 + ITEM_PYRIMID , // 24 + ITEM_BLOODGEM , // 25 + ITEM_JSPHERE , // 26 + ITEM_JCUBE , // 27 + ITEM_JPYRIMID , // 28 + ITEM_VILE , // 29 + ITEM_BLKBTL , // 30 + ITEM_WHTEBTL , // 31 + ITEM_REDBTL , // 32 + ITEM_YELBTL , // 33 + ITEM_ORGBTL , // 34 + ITEM_BREDBTL , // 35 + ITEM_BLKBTL2 , // 36 + ITEM_GOLDBTL , // 37 + ITEM_LTBLUEBTL , // 38 + ITEM_BLUEBTL2 , // 39 + ITEM_BRAIN , // 40 + ITEM_CLAW , // 41 + ITEM_FANG , // 42 + ITEM_BREAD , // 43 + ITEM_AMULET , // 44 + ITEM_AMULET1 , // 45 + ITEM_AMULET2 , // 46 + ITEM_AMULET3 , // 47 + ITEM_AMULET4 , // 48 + ITEM_POUCH1 , // 49 +// 1x2 + ITEM_DAGGER1 , // 50 + ITEM_DAGGER2 , // 51 + ITEM_BIGBOTTLE , // 52 + ITEM_DAGGER3 , // 53 + ITEM_DAGGER4 , // 54 + ITEM_DAGGER5 , // 55 +// 1x3 + ITEM_BLADE , // 56 + ITEM_BASTSRD , // 57 + ITEM_FALCHION , // 58 + ITEM_MACE , // 59 + ITEM_LONGSRD , // 60 + ITEM_BROADSRD , // 61 + ITEM_SCIMITAR , // 62 + ITEM_MORNSTAR , // 63 + ITEM_SHORTSRD , // 64 + ITEM_CLAYMORE , // 65 + ITEM_CLUB , // 66 + ITEM_SABRE , // 67 + ITEM_KNTSWORD , // 68 + ITEM_CLUB1 , // 69 + ITEM_CLUB2 , // 70 + ITEM_CLUB3 , // 71 + ITEM_SCIMITAR2 , // 72 + ITEM_MAGSWORD , // 73 + ITEM_SKULSWORD , // 74 +// 2x2 + ITEM_HELM , // 75 + ITEM_ROCK , // 76 + ITEM_CROWN , // 77 + ITEM_SKCROWN , // 78 + ITEM_MCROWN , // 79 + ITEM_JESTER , // 80 + ITEM_HARLEQ , // 81 + ITEM_FHELM , // 82 + ITEM_BUCKLER , // 83 + ITEM_FHELM2 , // 84 + ITEM_GRTHELM , // 85 + ITEM_BOOK2 , // 86 + ITEM_BOOK3 , // 87 + ITEM_BOOK , // 88 + ITEM_MUSHROOM , // 89 + ITEM_SKLCAP , // 90 + ITEM_LCAP , // 91 + ITEM_FLESH , // 92 + ITEM_SKLCAP2 , // 93 + ITEM_CLOTHES , // 94 + ITEM_CROWN2 , // 95 + ITEM_MAP , // 96 + ITEM_BOOK4 , // 97 + ITEM_FHELM3 , // 98 + ITEM_SAMHELM , // 99 +///#define ITEM_MUSHROOM 100 +// 2x3 + ITEM_COMPSHLD , // 100 + ITEM_BTLAXE , // 101 + ITEM_LONGBOW , // 102 + ITEM_PARMOR , // 103 + ITEM_AXE , // 104 + ITEM_WSHIELD , // 105 + ITEM_CLEAVER , // 106 + ITEM_STDARMOR , // 107 + ITEM_COMPBOW , // 108 + ITEM_SHRTSTAFF , // 109 + ITEM_2HSWORD , // 110 + ITEM_CHARMOR , // 111 + ITEM_SMALLAXE , // 112 + ITEM_HVYSHIELD , // 113 + ITEM_SCLARMOR , // 114 + ITEM_SMLSHLD , // 115 + ITEM_SKULLSHLD , // 116 + ITEM_WOLFSHLD , // 117 + ITEM_SHORTBOW , // 118 + ITEM_STLLONGBOW , // 119 + ITEM_STLSHRTBOW , // 120 + ITEM_SMLWARHAM , // 121 + ITEM_MAUL , // 122 + ITEM_IRONSTAFF , // 123 + ITEM_STLSTAFF , // 124 + ITEM_LONGSTAFF , // 125 + ITEM_INNSIGN , // 126 + ITEM_HLARMOR , // 127 + ITEM_RAGS , // 128 + ITEM_QARMOR , // 129 + ITEM_BALLNCHN , // 130 + ITEM_FLAIL , // 131 + ITEM_TSHIELD , // 132 + ITEM_HNTRBOW , // 133 + ITEM_GRTSWORD , // 134 + ITEM_LARMOR , // 135 + ITEM_SPLTARMOR , // 136 + ITEM_ROBE , // 137 + ITEM_HVYROBE , // 138 + ITEM_RINGARMOR , // 139 + ITEM_ANVIL , // 140 //#define ITEM_OBOLISK 140 + ITEM_BROADAXE , // 141 + ITEM_LRGAXE , // 142 + ITEM_WICKAXE , // 143 + ITEM_HANDAXE , // 144 + ITEM_GREATAXE , // 145 + ITEM_IRONSHLD , // 146 + ITEM_KITESHLD , // 147 + ITEM_LRGSHLD , // 148 + ITEM_CLOAK , // 149 + ITEM_CAPE , // 150 + ITEM_PARMOR2 , // 151 + ITEM_PARMOR3 , // 152 + ITEM_BPLATE , // 153 + ITEM_RINGMAIL , // 154 + ITEM_BISHOPSTF , // 155 + ITEM_GEMGRTAXE , // 156 + ITEM_ARKARMOR , // 157 + + ITEM_CROSBOW , // 158 + ITEM_NAJARMOR , // 159 + ITEM_GRIZZLY , // 160 + ITEM_GRANDPA , // 161 + ITEM_PROTECT , // 162 + ITEM_REAVER , // 163 + ITEM_WINDFOR , // 164 + ITEM_SWARBOW , // 165 + ITEM_COMPSTF , // 166 + ITEM_SBATLBOW , // 167 + + ITEM_GOLD , // 168 + +// New 1x1 + ITEM_MERLINRING = 168, // 168 // intentional duplicate to gold. + ITEM_MANARING , // 169 + ITEM_AMULWARD , // 170 + ITEM_NECMAGIC , // 171 + ITEM_NECHEALTH , // 172 + ITEM_KARIKSRING , // 173 + ITEM_RINGGROUND , // 174 + ITEM_AMULPROT , // 175 + ITEM_MERCRING , // 176 + ITEM_RINGTHUND , // 177 + ITEM_NECTRUTH , // 178 + ITEM_RINGGIANTS , // 179 + ITEM_AMULGOLD , // 180 + ITEM_RINGMYSTIC , // 181 + ITEM_RINGCOPPER , // 182 + ITEM_AMULACOLYT , // 183 + ITEM_RINGMAGMA , // 184 + ITEM_NECPURIFY , // 185 + ITEM_RINGGLADTR , // 186 + ITEM_RUNEBOMB , // 187 + ITEM_THEODORE , + ITEM_TORNPAPER1 , + ITEM_TORNPAPER2 , + ITEM_TORNPAPER3 , + ITEM_WHOLEPAPER , + ITEM_FIRERUNE1 , + ITEM_FIRERUNE2 , + ITEM_LIGHTRUNE1 , + ITEM_LIGHTRUNE2 , + ITEM_STONERUNE , + +// new 2x2 + ITEM_SUITGREY, + ITEM_SUITBRWN, + +// new 1x3 + ITEM_SWORDEDGE , // 188 + ITEM_SWORDGLAM , // 189 + ITEM_SWORDSERR , // 190 + +// new 2x3 + ITEM_ARMRDARK , // 191 + ITEM_ARMRBONECH , // 192 + ITEM_HAMRTHUND , // 193 + ITEM_SWRDCRYSTL , // 194 + ITEM_STAFJESTER , // 195 + ITEM_STAFMANA , // 196 + ITEM_BOWVULCAN , // 197 + ITEM_BOWSPEED , // 198 + ITEM_AXEANCIENT , // 199 + ITEM_CLUBCARNAG , // 200 + ITEM_MACEDARK , // 201 + ITEM_CLUBDECAY , // 202 + ITEM_AXEDECAY , // 203 + ITEM_SWRDDECAY , // 204 + ITEM_MACEDECAY , // 205 + ITEM_STAFDECAY , // 206 + ITEM_BOWDECAY , // 207 + ITEM_CLUBOUCH , // 208 + ITEM_SWRDDEVAST , // 209 + ITEM_AXEDEVAST , // 210 + ITEM_MORNDEVAST , // 211 + ITEM_MACEDEVAST, // 212 + ITEM_ARMRDMNPLT, + ITEM_ARMRCOW, + + ITEM_LAST_ID +} ITEM_IDS; + + +// Split later + +// Used for plr gfx +#define IT_MISC 0 +#define IT_SWORD 1 +#define IT_AXE 2 +#define IT_BOW 3 +#define IT_MACE 4 +#define IT_SHIELD 5 +#define IT_ARMOR 6 +#define IT_HELM 7 +#define IT_MARMOR 8 +#define IT_HARMOR 9 +#define IT_STAFF 10 +#define IT_GOLD 11 +#define IT_RING 12 +#define IT_AMULET 13 +#define IT_FOOD 14 + +// Used for inv location +#define IL_HAND 1 +#define IL_2HAND 2 +#define IL_BODY 3 +#define IL_HEAD 4 +#define IL_RING 5 +#define IL_NECK 6 +#define IL_INV 7 +#define IL_SPD 8 + +// Item classification for treasure types +#define IC_WEAP 1 +#define IC_ARMOR 2 +#define IC_ITEM 3 +#define IC_GOLD 4 +#define IC_SPECIAL 5 + +// Set item indexes for first non-random items +enum _item_indexes { + IDI_GOLD=0, // Item Data Table indexes +// Init items + IDI_WARRIOR, + IDI_WARRSHLD, + IDI_WARRCLUB, + IDI_ROGUE, + IDI_SORCEROR, +// Quest items + IDI_FIRSTQUEST, + IDI_CLEAVER=IDI_FIRSTQUEST, + IDI_SKCROWN, // Same as cleaver + IDI_INFRARING, // Same as cleaver + IDI_ROCK, + IDI_OPTAMULET, + IDI_TRING, // Same as cleaver + IDI_BANNER, + IDI_HARCREST, // Same as cleaver + IDI_STEELVEIL, // Same as cleaver + IDI_GLDNELIX, // Golden Elixor + IDI_ANVIL, // Anvil of Dawn + IDI_MUSHROOM, // Black Mushroom + IDI_BRAIN, // Brain + IDI_FUNGALTM, // Fungal Tome + IDI_SPECELIX, // Spectral Elixir + IDI_BLDSTONE, // Blood Stones + IDI_MAPOFDOOM, + IDI_LASTQUEST=IDI_MAPOFDOOM, +// Ears + IDI_EAR, +// Useful item + IDI_HEAL, + IDI_MANA, + IDI_IDENTIFY, + IDI_PORTAL, +// New items + IDI_ARMOFVAL, // Same as cleaver + IDI_FULLHEAL, + IDI_FULLMANA, + IDI_GRISWOLD, + IDI_ARMRCOW, + IDI_LAZSTAFF, + IDI_RESURRECT, + IDI_OILACC, + IDI_MONK, + IDI_BARD, + IDI_BARDDAGGER, + IDI_RUNEBOMB, + IDI_THEODORE, + IDI_AURIC, + IDI_NOTE1, + IDI_NOTE2, + IDI_NOTE3, + IDI_FULLNOTE, + IDI_SUITBRWN, + IDI_SUITGREY, + // Items for randomizing. + // Helmets and caps + IDI_CAP, + IDI_SKULLCAP, + IDI_HELM, + IDI_FULLHELM, + IDI_CROWN, + IDI_GREATHEALM, + // Body Armor + IDI_CAPE, + IDI_RAGS, + IDI_CLOAK, + IDI_ROBE, + IDI_QUILTED_ARMOR, + IDI_LEATHER_ARMOR, + IDI_HARD_LEATHER_ARMOR, + IDI_STUDDED_LEATHER_ARMOR, + IDI_RING_MAIL, + IDI_CHAIN_MAIL, + IDI_SCALE_MAIL, + IDI_BREAST_PLATE, + IDI_SPLINT_MAIL, + IDI_PLATE_MAIL, + IDI_FIELD_PLATE, + IDI_GOTHIC_PLATE, + IDI_FULL_PLATE_MAIL, + IDI_BUCKLER, + IDI_SMALL_SHIELD, + IDI_LARGE_SHIELD, + IDI_KITE_SHIELD, + IDI_TOWER_SHIELD, + IDI_GOTHIC_SHIELD, + IDI_POTION_OF_HEALING, + IDI_POTION_OF_FULL_HEALING, + IDI_POTION_OF_MANA, + IDI_POTION_OF_FULL_MANA, + // unused IDI_POTION_OF_EXPERIENCE, + IDI_POTION_OF_REJUVENATION, + IDI_POTION_OF_FULL_REJUVENATION, + IDI_BLACKSMITH_OIL, + IDI_OIL_OF_ACCURACY, + IDI_OIL_OF_SHARPNESS, + IDI_OIL, // random attributes. + IDI_ELIXIR_OF_STRENGTH, + IDI_ELIXIR_OF_MAGIC, + IDI_ELIXIR_OF_DEXTERITY, + IDI_ELIXIR_OF_VITALITY, + // unused IDI_SCROLL_OF_FIREBOLT, + // unused IDI_SCROLL_OF_CHARGED_BOLT, + // unused IDI_SCROLL_OF_HOLY_BOLT, + IDI_SCROLL_OF_HEALING, + IDI_SCROLL_OF_SEARCH, + IDI_SCROLL_OF_LIGHTNING, + IDI_SCROLL_OF_IDENTIFY, + IDI_SCROLL_OF_RESURRECT, + IDI_SCROLL_OF_FIREWALL, + // unused IDI_SCROLL_OF_TELEKINESIS, + IDI_SCROLL_OF_INFERNO, + IDI_SCROLL_OF_TOWN_PORTAL, + IDI_SCROLL_OF_FLASH, + IDI_SCROLL_OF_INFRAVISION, + IDI_SCROLL_OF_PHASING, + IDI_SCROLL_OF_MANA_SHIELD, + IDI_SCROLL_OF_FLAMEWAVE, + IDI_SCROLL_OF_FIREBALL, + IDI_SCROLL_OF_STONECURSE, + IDI_SCROLL_OF_CHAIN_LIGHTNING, + IDI_SCROLL_OF_GUARDIAN, + IDI_UNUSED_SCROLL, + IDI_SCROLL_OF_NOVA, + IDI_SCROLL_OF_GOLEM, + IDI_SCROLL_OF_BLOODBOIL, // unused + IDI_SCROLL_OF_TELEPORT, + IDI_SCROLL_OF_APOCALYPSE, + // unused IDI_SCROLL_OF_BONESPIRIT, + // unused IDI_SCROLL_OF_BLOODSTAR, + IDI_FIRST_BOOK, + IDI_SECOND_BOOK, + IDI_THIRD_BOOK, + IDI_LAST_BOOK, + IDI_DAGGER, + IDI_SHORT_SWORD, + IDI_FALCHION, + IDI_SCIMITAR, + IDI_CLAYMORE, + IDI_BLADE, + IDI_SABRE, + IDI_LONG_SWORD, + IDI_BROAD_SWORD, + IDI_BASTARD_SWORD, + IDI_TWO_HANDED_SWORD, + IDI_GREAT_SWORD, + IDI_SMALL_AXE, + IDI_AXE, + IDI_LARGE_AXE, + IDI_BROAD_AXE, + IDI_BATTLE_AXE, + IDI_GREAT_AXE, + IDI_MACE, + IDI_MORNINGSTAR, + IDI_WAR_HAMMER, + IDI_SPIKED_CLUB, + IDI_CLUB, + IDI_FLAIL, + IDI_MAUL, + IDI_SHORT_BOW, + IDI_HUNTERS_BOW, + IDI_LONG_BOW, + IDI_COMPOSITE_BOW, + IDI_SHORT_WAR_BOW, + IDI_LONG_WAR_BOW, + IDI_SHORT_STAFF, + IDI_LONG_STAFF, + IDI_COMPOSITE_STAFF, + IDI_QUARTER_STAFF, + IDI_WAR_STAFF, + IDI_FIRST_RING, + IDI_SECOND_RING, + IDI_LAST_RING, + IDI_FIRST_AMULET, + IDI_LAST_AMULET, + IDI_RUNE_OF_FIRE, + IDI_RUNE_OF_LIGHTNING, + IDI_GREATER_RUNE_OF_FIRE, + IDI_GREATER_RUNE_OF_LIGHTNING, + IDI_RUNE_OF_STONE, + + // Insert any new items above this line. + IDI_LAST_RANDOM_ITEM + +}; + +#define IDI_BARBARIAN IDI_SPIKED_CLUB +#define IDI_BARSHLD IDI_WARRSHLD + +#define IAF_INFRAVISION 0x00000001 +#define IAF_SKING 0x00000002 +#define IAF_RNDARROW 0x00000004 +#define IAF_FIREARROW 0x00000008 +#define IAF_FIREHIT 0x00000010 +#define IAF_LIGHTHIT 0x00000020 +#define IAF_CONSTRICT 0x00000040 +#define IAF_NOMANA 0x00000080 +#define IAF_NOHEAL 0x00000100 +#define IAF_RABID 0x00000200 // not in game +#define IAF_HALFTRAP 0x00000400 // not in game -called TRAPDAM +#define IAF_KNOCKBACK 0x00000800 +#define IAF_MNOHEAL 0x00001000 +#define IAF_BAT10 0x00002000 +#define IAF_BAT20 0x00004000 +#define IAF_ALLBAT (IAF_BAT10 | IAF_BAT20) +#define IAF_LEECH10 0x00008000 +#define IAF_LEECH20 0x00010000 +#define IAF_ALLLEECH (IAF_LEECH10 | IAF_LEECH20) +#define IAF_ATANIM1 0x00020000 +#define IAF_ATANIM2 0x00040000 +#define IAF_ATANIM3 0x00080000 +#define IAF_ATANIM4 0x00100000 +#define IAF_ALLATANIM (IAF_ATANIM1 | IAF_ATANIM2 | IAF_ATANIM3 | IAF_ATANIM4 ) +#define IAF_HTANIM1 0x00200000 +#define IAF_HTANIM2 0x00400000 +#define IAF_HTANIM3 0x00800000 +#define IAF_ALLHTANIM (IAF_HTANIM1 | IAF_HTANIM2 | IAF_HTANIM3) +#define IAF_BLANIM 0x01000000 +#define IAF_LARROW 0x02000000 +#define IAF_THORN 0x04000000 +#define IAF_LMANA 0x08000000 +#define IAF_TRAPDAM 0x10000000 +#define IAF_OMEHAND 0x20000000 +#define IAF_DAMDEMON 0x40000000 +#define IAF_ZERORES 0x80000000 + +#define IAF2_DEVASTATION 0x00000001 +#define IAF2_DECAY 0x00000002 +#define IAF2_PERIL 0x00000004 +#define IAF2_JESTER 0x00000008 +#define IAF2_CLONE 0x00000010 +#define IAF2_DEMONAC 0x00000020 +#define IAF2_UNDEADAC 0x00000040 + +#define ISEL_NONE 0 // Items start out unselectable +#define ISEL_FLR 1 // Most items +#define ISEL_TOP 2 // Items on objects usually +#define ISEL_ALL 3 // Large (2 square) items + +#define IMAGIC_NONE 0 +#define IMAGIC_MAGIC 1 +#define IMAGIC_UNIQUE 2 + +// Item re-creation information +// Creation bits are as follows: +// bit# desc +// 1-6 Level +// 7 Item Goodonly (T/F) +// 8,9 Unique percentage (0 = 0%, 1 = 15%, 2 = 1%) +// 8&9 Useful item only +// 10 Unique item +// 11 Spawned by Blacksmith +// 12 Spawned by Blacksmith premium +// 13 Spawned by Pegboy +// 14 Spawned by Witch +// 15 Spawned by Healer +#define ICI_USEFUL 0x0180 +#define ICI_UPER1 0x0100 +#define ICI_UPER15 0x0080 +#define ICI_ONLYGOOD 0x0040 +#define ICI_UNIQUE 0x0200 +#define ICI_SMITH 0x0400 +#define ICI_PREMIUM 0x0800 +#define ICI_BOY 0x1000 +#define ICI_WITCH 0x2000 +#define ICI_HEALER 0x4000 +#define ICI_PREGEN 0x8000 + +#define ICI_LVLMASK 0x003f +#define ICI_TOWNMASK 0x7c00 +#define ICI_PREGENMASK 0x7fff + +// Unique item index list +#define UID_CLEAVER 0 // Butcher's cleaver +#define UID_SKCROWN 1 // Skeleton King's crown +#define UID_INFRARING 2 // Infravision ring +#define UID_OPTAMULET 3 // Optic Amulet +#define UID_TRING 4 // Ring of truth +#define UID_HARCREST 5 // Harlequin Crest +#define UID_STEELVEIL 6 // Veil of Steel +#define UID_ARMOFVAL 7 // Armor of Valor +#define UID_GRISWOLD 8 // Griswold's Edge +#define UID_ARMRCOW 9 // Cow Armor +#define UID_LGTFORGE 9 + +// item no random spawn, normal random spawn, or double chance random spawn +#define IRND_NO 0 +#define IRND_NORMAL 1 +#define IRND_DOUBLE 2 + +#define RESIST_MAX 75 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + + +typedef struct { + char *PLName; // Name of power + int PLPower; // Power type + int PLParam1; // Misc param 1 + int PLParam2; // Misc param 2 + char PLMinLvl; // Min dungeon level of power appearing + long PLIType; // Item type (armor/shield/weapon/staff/bow/ring) + byte PLGOE; // Good/Evil/Either + BOOL PLDouble; // Double chance of spawning (more common magic) + BOOL PLOk; // Item good or bad + int PLMinVal; // Item min value modifier + int PLMaxVal; // Item max value modifier + int PLMultVal; // Item value multiplier +} PLStruct; + +typedef struct { + char *UIName; // Unique item name + char UIItemId; // Item id for base stats + char UIMinLvl; // Min level can be found at + char UINumPL; // Number of power list items + int UIValue; // Items value + char UIPower1; // Power 1 and 2 params + int UIParam1; + int UIParam2; + char UIPower2; // Power 2 and 2 params + int UIParam3; + int UIParam4; + char UIPower3; // Power 3 and 2 params + int UIParam5; + int UIParam6; + char UIPower4; // Power 4 and 2 params + int UIParam7; + int UIParam8; + char UIPower5; // Power 5 and 2 params + int UIParam9; + int UIParam10; + char UIPower6; // Power 6 and 2 params + int UIParam11; + int UIParam12; +} UItemStruct; + +typedef struct { + BOOL iRnd; // Random item or special + char iClass; // Item classification + char iLoc; // Item Body Location + int iCurs; // Item cursor gfx + char itype; // Item type + char iItemId; // Item id# + char *iName; // name + char *iSName; // short name + char iMinMLvl; // Min monster level to drop it + int iDurability; // Durability of the item + int iMinDam; // Min damage + int iMaxDam; // Max damage + int iMinAC; // Min Armor Class + int iMaxAC; // Max Armor Class + char iMinStr; // Min Strength stat to use item + char iMinMag; // Min Magic stat to use item + char iMinDex; // Min Dexterity stat to use item + long iFlags; // Item ability flags + int iMiscId; // Misc item uses id + long iSpell; // item spell + BOOL iUsable; // Usable item? + int iValue; // item min value + int iMaxValue; // item max value +} ItemDataStruct; + +// PATCH1.JMM +typedef struct { + int nSeed; + WORD wCI; + int nIndex; + DWORD dwTimestamp; +} ItemGetRecordStruct; +// ENDPATCH1.JMM + +typedef struct { + int _iSeed; // item seed to generate itself + WORD _iCreateInfo; // item re-creation info + int _itype; // item type + int _ix; // item map x + int _iy; // item map y + BOOL _iAnimFlag; // Does this item animate? + BYTE *_iAnimData; // Data pointer to anim tables + int _iAnimLen; // number of anim frames + int _iAnimFrame; // current anim frame + long _iAnimWidth; // Width of anim + long _iAnimWidth2; // (Width - 64) >> 1 of anim +// PATCH1.JMM + // FLAG IS NO LONGER USED + //BOOL _iDelFlag; // Delete this item + BOOL _iInvalid; +// ENDPATCH1.JMM + + char _iSelFlag; // Select top, floor, or all + BOOL _iPostDraw; // Draw after objects or before? + + BOOL _iIdentified; // Has item been identified? + char _iMagical; // (No/Reg/Unique) Does the item have magical attributes? + char _iName[64]; // item name + char _iIName[64]; // identified name + char _iLoc; // item body location + char _iClass; // item classification + int _iCurs; // item cursor type + int _ivalue; // item value + int _iIvalue; // item identified value + int _iMinDam; // item min damage + int _iMaxDam; // item max damage + int _iAC; // item armor class + long _iFlags; // item ability flags + int _iMiscId; // Misc item uses id + int _iSpell; // item spell + + int _iCharges; // random number of charges + int _iMaxCharges; // Max Charges of a staff + + int _iDurability; // How much strength until it breaks + int _iMaxDur; // Max Durability + + int _iPLDam; // Power List damage multiplier + int _iPLToHit; // Power List to hit increase + int _iPLAC; // Power List AC increase + int _iPLStr; // Power List Strength increase + int _iPLMag; // Power List Magic increase + int _iPLDex; // Power List Dexterity increase + int _iPLVit; // Power List Vitality increase + int _iPLFR; // Power List Fire resistance + int _iPLLR; // Power List Lightning resistance + int _iPLMR; // Power List Misc Magic resistance + long _iPLMana; // Power List Mana + long _iPLHP; // Power List Hit Points + int _iPLDamMod; // Power List damage modifier (num, not %) + int _iPLGetHit; // Power List Get hit modifier (+/-) + int _iPLLight; // Power List light radius + char _iSplLvlAdd; // What to add to each spell level + + char _iRequest; // If item has be requested to be picked up (drb 12/9) + int _iUid; // If unique item, index into unique table (drb 12/8) + + int _iFMinDam; // Fire hit min damage + int _iFMaxDam; // Fire hit max damage + int _iLMinDam; // Lightning hit min damage + int _iLMaxDam; // Lightning hit max damage + + int _iPLEnAc; // Enemy armor class reduced by this amount + + char _iPrePower; // Power List index for prefix + char _iSufPower; // Power List index for suffix + + int _iVAdd1; // value add #1 + int _iVMult1; // value multiplier #1 + int _iVAdd2; // value add #2 + int _iVMult2; // value multiplier #2 + + char _iMinStr; // Min Strength stat to use item + byte _iMinMag; // Min Magic stat to use item + char _iMinDex; // Min Dexterity stat to use item + BOOL _iStatFlag; // Draw with red filter or not + int IDidx; // AllItemsData index + char _oldlight; // Old prelight val + long _iFlags2; // item ability flags +} ItemStruct; + +#define SAVE_ITEM_SIZE sizeof(ItemStruct) + + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern ItemStruct item[MAXITEMS+1]; +extern long numitems; + +extern int itemactive[MAXITEMS]; +extern int itemavail[MAXITEMS]; + +// PATCH1.JMM +extern ItemGetRecordStruct itemgets[MAXITEMS]; +extern int gnNumGetRecords; +// ENDPATCH1.JMM + +extern BOOL UniqueItemFlag[MAXUITEMS]; +extern BOOL uitemflag; + +extern int ItemInvSnds[]; +extern BYTE ItemCAnimTbl[]; +#if CHEATS +extern BOOL davecheat; +extern int tstQMsgSpd; +extern int tstQMsgIndex; +extern BOOL tstQMsgFlag; +extern BOOL tstQMsgIndexFlag; +#endif + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitItems(); +void ProcessItems(); +void InitItemGFX(); +void FreeItemGFX(); +void DaveGold(); +void DaveNewPremium(); +void DaveCleanUp(); +void DaveSpells(); +void DaveSpells2(); +void DaveQuestText(); + +BOOL ItemSpaceOk(int, int); + +void SpawnItem(int, int, int, BOOL); // Called by monsters +void SpawnUnique(int, int, int); // Called by monsters +void RespawnItem(int ii, BOOL FlipFlag); // Called by plr placing object back + +void CreateItem(int, int, int); // Spawn a specific item at x, y +void CreateRndItem(int, int, BOOL, BOOL, BOOL); // Spawn any item around x,y (item level >= (currlevel*2)) +void CreateRndUseful(int, int, int, BOOL); // Spawn either health, mana, or identify +void CreateTypeItem(int, int, BOOL, int, int, BOOL, BOOL); // Spawn a specific type of item +void CreateSpellBook(int x, int y, int ispell, BOOL sendmsg, BOOL delta); //Spawn a specific spell book +void CreateMagicArmor(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta); //Spawn specific magical armor +void CreateAmulet(int x, int y, int level, BOOL sendmsg, BOOL delta); //Spawn an amulet +void CreateMagicWeapon(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta); //Spawn specific magical weapon + +void RecreateItem(int, int, WORD, int, int); +void RecreateEar(int, WORD, int, BOOL, int, int, int, int, int, int); + +void SyncItemAnim(int); + +void GetItemStr(int); + +void CalcPlrItemVals(int,BOOL); +void CalcPlrScrolls(int); +void CalcPlrStaff(int); +void CalcPlrItemMin(int); +void CalcPlrInv(int,BOOL); + +void CreatePlrItems(int); + +void SpawnRock(); + +void CheckIdentify(int, int); +void DoRepair(int, int); +void DoRecharge(int, int); +void DoOil(int, int); + +void PrintItemPower(char,const ItemStruct * x); +void PrintItemDetails(const ItemStruct * x); +void PrintItemDur(const ItemStruct * x); + +void UseItem(int, int, int); + +void SpawnSmith(int); +void SpawnPremium(int); +void SpawnWitch(int); +void SpawnBoy(int); +void SpawnHealer(int); +void SpawnStoreGold(); +void SpawnQuestItem(int itemid, int x,int y, int randarea, int selflag); + +void DrawUniqueInfo(); + +void GetItemAttrs(int i, int idata, int lvl); + +int ItemNoFlippy(); +void GetSuperItemLoc(int x, int y, int &xx, int &yy); + +// PATCH1.JMM +BOOL CheckGetRecord( int nSeed, WORD wCI, int nIndex ); +void AddGetRecord( int nSeed, WORD wCI, int nIndex ); +void RemoveGetRecord( int nSeed, WORD wCI, int nIndex ); +// ENDPATCH1.JMM + +void SetPlrHandItem(ItemStruct *h, int idata); +void GetPlrHandSeed(ItemStruct *h); + +typedef struct { + int x; + int y; + BOOL Initted; + ItemStruct item; +} CornerStoneType; + +extern CornerStoneType CornerStone; + +extern void CornerstoneRestore(int x, int y); +extern void CornerstoneSave(); diff --git a/src/ITEMS.HSV b/src/ITEMS.HSV new file mode 100644 index 0000000..7f039cf --- /dev/null +++ b/src/ITEMS.HSV @@ -0,0 +1,752 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/ITEMS.H 3 2/06/97 6:08p Jessmac $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXITEMS 127 + +#define MAXUITEMS 128 // Max number of uniques + +#define TEMPAVAIL 127 + +#define ITEM_RND -1 + +#define INFINITE_DUR 255 + +#define GOLD_VT1 1000 // Gold gfx transition from 1 to several +#define GOLD_VT2 2500 // Gold gfx transition from several to many +//#define GOLD_VMAX 5000 // Max gold in an inv slot +extern int GOLD_VMAX; + +// Used for cursors +// 1x1 +enum { + ITEM_BLUEBTL = 0, + ITEM_SCROLL , // 1 + ITEM_SCROLL2 , // 2 + ITEM_SCROLL3 , // 3 + ITEM_1GOLD , // 4 + ITEM_3GOLD , // 5 + ITEM_5GOLD , // 6 + ITEM_GOLDRING , // 7 + ITEM_1JRING , // 8 + ITEM_WOODRING , // 9 + ITEM_BLUERING , // 10 + ITEM_3JRING , // 11 + ITEM_SLVRRING , // 12 + ITEM_MJRING , // 13 + ITEM_BRNRING , // 14 + ITEM_SPECTRAL , // 15 + ITEM_3COLORPOT , // 16 + ITEM_GOLDENELIX , // 17 + ITEM_EMPYBAND , // 18 + ITEM_EAR1 , // 19 + ITEM_EAR2 , // 20 + ITEM_EAR3 , // 21 + ITEM_SPHERE , // 22 + ITEM_CUBE , // 23 + ITEM_PYRIMID , // 24 + ITEM_BLOODGEM , // 25 + ITEM_JSPHERE , // 26 + ITEM_JCUBE , // 27 + ITEM_JPYRIMID , // 28 + ITEM_VILE , // 29 + ITEM_BLKBTL , // 30 + ITEM_WHTEBTL , // 31 + ITEM_REDBTL , // 32 + ITEM_YELBTL , // 33 + ITEM_ORGBTL , // 34 + ITEM_BREDBTL , // 35 + ITEM_BLKBTL2 , // 36 + ITEM_GOLDBTL , // 37 + ITEM_LTBLUEBTL , // 38 + ITEM_BLUEBTL2 , // 39 + ITEM_BRAIN , // 40 + ITEM_CLAW , // 41 + ITEM_FANG , // 42 + ITEM_BREAD , // 43 + ITEM_AMULET , // 44 + ITEM_AMULET1 , // 45 + ITEM_AMULET2 , // 46 + ITEM_AMULET3 , // 47 + ITEM_AMULET4 , // 48 + ITEM_POUCH1 , // 49 + // Add these back in when you can read them from the .cel file. + //ITEM_DOHICKY , + //ITEM_THEODORE , + //ITEM_PAPER1 , + //ITEM_PAPER2 , + //ITEM_PAPER3 , + //ITEM_PAPER4 , +// 1x2 + ITEM_DAGGER1 , // 50 + ITEM_DAGGER2 , // 51 + ITEM_BIGBOTTLE , // 52 + ITEM_DAGGER3 , // 53 + ITEM_DAGGER4 , // 54 + ITEM_DAGGER5 , // 55 +// 1x3 + ITEM_BLADE , // 56 + ITEM_BASTSRD , // 57 + ITEM_FALCHION , // 58 + ITEM_MACE , // 59 + ITEM_LONGSRD , // 60 + ITEM_BROADSRD , // 61 + ITEM_SCIMITAR , // 62 + ITEM_MORNSTAR , // 63 + ITEM_SHORTSRD , // 64 + ITEM_CLAYMORE , // 65 + ITEM_CLUB , // 66 + ITEM_SABRE , // 67 + ITEM_KNTSWORD , // 68 + ITEM_CLUB1 , // 69 + ITEM_CLUB2 , // 70 + ITEM_CLUB3 , // 71 + ITEM_SCIMITAR2 , // 72 + ITEM_MAGSWORD , // 73 + ITEM_SKULSWORD , // 74 +// 2x2 + ITEM_HELM , // 75 + ITEM_ROCK , // 76 + ITEM_CROWN , // 77 + ITEM_SKCROWN , // 78 + ITEM_MCROWN , // 79 + ITEM_JESTER , // 80 + ITEM_HARLEQ , // 81 + ITEM_FHELM , // 82 + ITEM_BUCKLER , // 83 + ITEM_FHELM2 , // 84 + ITEM_GRTHELM , // 85 + ITEM_BOOK2 , // 86 + ITEM_BOOK3 , // 87 + ITEM_BOOK , // 88 + ITEM_MUSHROOM , // 89 + ITEM_SKLCAP , // 90 + ITEM_LCAP , // 91 + ITEM_FLESH , // 92 + ITEM_SKLCAP2 , // 93 + ITEM_CLOTHES , // 94 + ITEM_CROWN2 , // 95 + ITEM_MAP , // 96 + ITEM_BOOK4 , // 97 + ITEM_FHELM3 , // 98 + ITEM_SAMHELM , // 99 +///#define ITEM_MUSHROOM, // 100 +// 2x3 + ITEM_COMPSHLD , // 100 + ITEM_BTLAXE , // 101 + ITEM_LONGBOW , // 102 + ITEM_PARMOR , // 103 + ITEM_AXE , // 104 + ITEM_WSHIELD , // 105 + ITEM_CLEAVER , // 106 + ITEM_STDARMOR , // 107 + ITEM_COMPBOW , // 108 + ITEM_SHRTSTAFF , // 109 + ITEM_2HSWORD , // 110 + ITEM_CHARMOR , // 111 + ITEM_SMALLAXE , // 112 + ITEM_HVYSHIELD , // 113 + ITEM_SCLARMOR , // 114 + ITEM_SMLSHLD , // 115 + ITEM_SKULLSHLD , // 116 + ITEM_WOLFSHLD , // 117 + ITEM_SHORTBOW , // 118 + ITEM_STLLONGBOW , // 119 + ITEM_STLSHRTBOW , // 120 + ITEM_SMLWARHAM , // 121 + ITEM_MAUL , // 122 + ITEM_IRONSTAFF , // 123 + ITEM_STLSTAFF , // 124 + ITEM_LONGSTAFF , // 125 + ITEM_INNSIGN , // 126 + ITEM_HLARMOR , // 127 + ITEM_RAGS , // 128 + ITEM_QARMOR , // 129 + ITEM_BALLNCHN , // 130 + ITEM_FLAIL , // 131 + ITEM_TSHIELD , // 132 + ITEM_HNTRBOW , // 133 + ITEM_GRTSWORD , // 134 + ITEM_LARMOR , // 135 + ITEM_SPLTARMOR , // 136 + ITEM_ROBE , // 137 + ITEM_HVYROBE , // 138 + ITEM_RINGARMOR , // 139 + ITEM_ANVIL , // 140 //#define ITEM_OBOLISK 140 + ITEM_BROADAXE , // 141 + ITEM_LRGAXE , // 142 + ITEM_WICKAXE , // 143 + ITEM_HANDAXE , // 144 + ITEM_GREATAXE , // 145 + ITEM_IRONSHLD , // 146 + ITEM_KITESHLD , // 147 + ITEM_LRGSHLD , // 148 + ITEM_CLOAK , // 149 + ITEM_CAPE , // 150 + ITEM_PARMOR2 , // 151 + ITEM_PARMOR3 , // 152 + ITEM_BPLATE , // 153 + ITEM_RINGMAIL , // 154 + ITEM_BISHOPSTF , // 155 + ITEM_GEMGRTAXE , // 156 + ITEM_ARKARMOR , // 157 + + ITEM_CROSBOW , // 158 + ITEM_NAJARMOR , // 159 + ITEM_GRIZZLY , // 160 + ITEM_GRANDPA , // 161 + ITEM_PROTECT , // 162 + ITEM_REAVER , // 163 + ITEM_WINDFOR , // 164 + ITEM_SWARBOW , // 165 + ITEM_COMPSTF , // 166 + ITEM_SBATLBOW , // 167 + + ITEM_GOLD , // 168 + +// New 1x1 + ITEM_MERLINRING , // 168 + ITEM_MANARING , // 169 + ITEM_AMULWARD , // 170 + ITEM_NECMAGIC , // 171 + ITEM_NECHEALTH , // 172 + ITEM_KARIKSRING , // 173 + ITEM_RINGGROUND , // 174 + ITEM_AMULPROT , // 175 + ITEM_MERCRING , // 176 + ITEM_RINGTHUND , // 177 + ITEM_NECTRUTH , // 178 + ITEM_RINGGIANTS , // 179 + ITEM_AMULGOLD , // 180 + ITEM_RINGMYSTIC , // 181 + ITEM_RINGCOPPER , // 182 + ITEM_AMULACOLYT , // 183 + ITEM_RINGMAGMA , // 184 + ITEM_NECPURIFY , // 185 + ITEM_RINGGLADTR , // 186 + ITEM_RUNEBOMB , // 187 + +// new 1x3 + ITEM_SWORDEDGE , // 188 + ITEM_SWORDGLAM , // 189 + ITEM_SWORDSERR , // 190 + +// new 2x3 + ITEM_ARMRDARK , // 191 + ITEM_ARMRBONECH , // 192 + ITEM_HAMRTHUND , // 193 + ITEM_SWRDCRYSTL , // 194 + ITEM_STAFJESTER , // 195 + ITEM_STAFMANA , // 196 + ITEM_BOWVULCAN , // 197 + ITEM_BOWSPEED , // 198 + ITEM_AXEANCIENT , // 199 + ITEM_CLUBCARNAG , // 200 + ITEM_MACEDARK , // 201 + ITEM_CLUBDECAY , // 202 + ITEM_AXEDECAY , // 203 + ITEM_SWRDDECAY , // 204 + ITEM_MACEDECAY , // 205 + ITEM_STAFDECAY , // 206 + ITEM_BOWDECAY , // 207 + ITEM_CLUBOUCH , // 208 + ITEM_SWRDDEVAST , // 209 + ITEM_AXEDEVAST , // 210 + ITEM_MORNDEVAST , // 211 + ITEM_MACEDEVAST , // 212 +}; + +// Split later + +// Used for plr gfx +#define IT_MISC 0 +#define IT_SWORD 1 +#define IT_AXE 2 +#define IT_BOW 3 +#define IT_MACE 4 +#define IT_SHIELD 5 +#define IT_ARMOR 6 +#define IT_HELM 7 +#define IT_MARMOR 8 +#define IT_HARMOR 9 +#define IT_STAFF 10 +#define IT_GOLD 11 +#define IT_RING 12 +#define IT_AMULET 13 +#define IT_FOOD 14 + +// Used for inv location +#define IL_HAND 1 +#define IL_2HAND 2 +#define IL_BODY 3 +#define IL_HEAD 4 +#define IL_RING 5 +#define IL_NECK 6 +#define IL_INV 7 +#define IL_SPD 8 + +// Item classification for treasure types +#define IC_WEAP 1 +#define IC_ARMOR 2 +#define IC_ITEM 3 +#define IC_GOLD 4 +#define IC_SPECIAL 5 + +// Set item indexes for first non-random items +enum _item_indexes { + IDI_GOLD=0, // Item Data Table indexes +// Init items + IDI_WARRIOR, + IDI_WARRSHLD, + IDI_WARRCLUB, + IDI_ROGUE, + IDI_SORCEROR, +// Quest items + IDI_FIRSTQUEST, + IDI_CLEAVER=IDI_FIRSTQUEST, + IDI_SKCROWN, // Same as cleaver + IDI_INFRARING, // Same as cleaver + IDI_ROCK, + IDI_OPTAMULET, + IDI_TRING, // Same as cleaver + IDI_BANNER, + IDI_HARCREST, // Same as cleaver + IDI_STEELVEIL, // Same as cleaver + IDI_GLDNELIX, // Golden Elixor + IDI_ANVIL, // Anvil of Dawn + IDI_MUSHROOM, // Black Mushroom + IDI_BRAIN, // Brain + IDI_FUNGALTM, // Fungal Tome + IDI_SPECELIX, // Spectral Elixir + IDI_BLDSTONE, // Blood Stones + IDI_MAPOFDOOM, + IDI_LASTQUEST=IDI_MAPOFDOOM, +// Ears + IDI_EAR, +// Useful item + IDI_HEAL, + IDI_MANA, + IDI_IDENTIFY, + IDI_PORTAL, +// New items + IDI_ARMOFVAL, // Same as cleaver + IDI_FULLHEAL, + IDI_FULLMANA, + IDI_GRISWOLD, + IDI_LGTFORGE, + IDI_LAZSTAFF, + IDI_RESURRECT, + IDI_OILACC, + IDI_MONK, + IDI_BARD, + IDI_BARDDAGGER, + IDI_RUNEBOMB, + IDI_THEODORE, + IDI_AURIC +}; + +#define IAF_INFRAVISION 0x00000001 +#define IAF_SKING 0x00000002 +#define IAF_RNDARROW 0x00000004 +#define IAF_FIREARROW 0x00000008 +#define IAF_FIREHIT 0x00000010 +#define IAF_LIGHTHIT 0x00000020 +#define IAF_CONSTRICT 0x00000040 +#define IAF_NOMANA 0x00000080 +#define IAF_NOHEAL 0x00000100 +#define IAF_RABID 0x00000200 // not in game +#define IAF_HALFTRAP 0x00000400 // not in game -called TRAPDAM +#define IAF_KNOCKBACK 0x00000800 +#define IAF_MNOHEAL 0x00001000 +#define IAF_BAT10 0x00002000 +#define IAF_BAT20 0x00004000 +#define IAF_ALLBAT (IAF_BAT10 | IAF_BAT20) +#define IAF_LEECH10 0x00008000 +#define IAF_LEECH20 0x00010000 +#define IAF_ALLLEECH (IAF_LEECH10 | IAF_LEECH20) +#define IAF_ATANIM1 0x00020000 +#define IAF_ATANIM2 0x00040000 +#define IAF_ATANIM3 0x00080000 +#define IAF_ATANIM4 0x00100000 +#define IAF_ALLATANIM (IAF_ATANIM1 | IAF_ATANIM2 | IAF_ATANIM3 | IAF_ATANIM4 ) +#define IAF_HTANIM1 0x00200000 +#define IAF_HTANIM2 0x00400000 +#define IAF_HTANIM3 0x00800000 +#define IAF_ALLHTANIM (IAF_HTANIM1 | IAF_HTANIM2 | IAF_HTANIM3) +#define IAF_BLANIM 0x01000000 +#define IAF_LARROW 0x02000000 +#define IAF_THORN 0x04000000 +#define IAF_LMANA 0x08000000 +#define IAF_TRAPDAM 0x10000000 +#define IAF_OMEHAND 0x20000000 +#define IAF_DAMDEMON 0x40000000 +#define IAF_ZERORES 0x80000000 + +#define IAF2_DEVASTATION 0x00000001 +#define IAF2_DECAY 0x00000002 +#define IAF2_PERIL 0x00000004 +#define IAF2_JESTER 0x00000008 +#define IAF2_CLONE 0x00000010 +#define IAF2_DEMONAC 0x00000020 +#define IAF2_UNDEADAC 0x00000040 + +#define ISEL_NONE 0 // Items start out unselectable +#define ISEL_FLR 1 // Most items +#define ISEL_TOP 2 // Items on objects usually +#define ISEL_ALL 3 // Large (2 square) items + +#define IMAGIC_NONE 0 +#define IMAGIC_MAGIC 1 +#define IMAGIC_UNIQUE 2 + +// Item re-creation information +// Creation bits are as follows: +// bit# desc +// 1-6 Level +// 7 Item Goodonly (T/F) +// 8,9 Unique percentage (0 = 0%, 1 = 15%, 2 = 1%) +// 8&9 Useful item only +// 10 Unique item +// 11 Spawned by Blacksmith +// 12 Spawned by Blacksmith premium +// 13 Spawned by Pegboy +// 14 Spawned by Witch +// 15 Spawned by Healer +#define ICI_USEFUL 0x0180 +#define ICI_UPER1 0x0100 +#define ICI_UPER15 0x0080 +#define ICI_ONLYGOOD 0x0040 +#define ICI_UNIQUE 0x0200 +#define ICI_SMITH 0x0400 +#define ICI_PREMIUM 0x0800 +#define ICI_BOY 0x1000 +#define ICI_WITCH 0x2000 +#define ICI_HEALER 0x4000 +#define ICI_PREGEN 0x8000 + +#define ICI_LVLMASK 0x003f +#define ICI_TOWNMASK 0x7c00 +#define ICI_PREGENMASK 0x7fff + +// Unique item index list +#define UID_CLEAVER 0 // Butcher's cleaver +#define UID_SKCROWN 1 // Skeleton King's crown +#define UID_INFRARING 2 // Infravision ring +#define UID_OPTAMULET 3 // Optic Amulet +#define UID_TRING 4 // Ring of truth +#define UID_HARCREST 5 // Harlequin Crest +#define UID_STEELVEIL 6 // Veil of Steel +#define UID_ARMOFVAL 7 // Armor of Valor +#define UID_GRISWOLD 8 // Griswold's Edge +#define UID_LGTFORGE 9 // LightForge + +// item no random spawn, normal random spawn, or double chance random spawn +#define IRND_NO 0 +#define IRND_NORMAL 1 +#define IRND_DOUBLE 2 + +#define RESIST_MAX 75 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + + +typedef struct { + char *PLName; // Name of power + int PLPower; // Power type + int PLParam1; // Misc param 1 + int PLParam2; // Misc param 2 + char PLMinLvl; // Min dungeon level of power appearing + long PLIType; // Item type (armor/shield/weapon/staff/bow/ring) + byte PLGOE; // Good/Evil/Either + BOOL PLDouble; // Double chance of spawning (more common magic) + BOOL PLOk; // Item good or bad + int PLMinVal; // Item min value modifier + int PLMaxVal; // Item max value modifier + int PLMultVal; // Item value multiplier +} PLStruct; + +typedef struct { + char *UIName; // Unique item name + char UIItemId; // Item id for base stats + char UIMinLvl; // Min level can be found at + char UINumPL; // Number of power list items + int UIValue; // Items value + char UIPower1; // Power 1 and 2 params + int UIParam1; + int UIParam2; + char UIPower2; // Power 2 and 2 params + int UIParam3; + int UIParam4; + char UIPower3; // Power 3 and 2 params + int UIParam5; + int UIParam6; + char UIPower4; // Power 4 and 2 params + int UIParam7; + int UIParam8; + char UIPower5; // Power 5 and 2 params + int UIParam9; + int UIParam10; + char UIPower6; // Power 6 and 2 params + int UIParam11; + int UIParam12; +} UItemStruct; + +typedef struct { + BOOL iRnd; // Random item or special + char iClass; // Item classification + char iLoc; // Item Body Location + int iCurs; // Item cursor gfx + char itype; // Item type + char iItemId; // Item id# + char *iName; // name + char *iSName; // short name + char iMinMLvl; // Min monster level to drop it + int iDurability; // Durability of the item + int iMinDam; // Min damage + int iMaxDam; // Max damage + int iMinAC; // Min Armor Class + int iMaxAC; // Max Armor Class + char iMinStr; // Min Strength stat to use item + char iMinMag; // Min Magic stat to use item + char iMinDex; // Min Dexterity stat to use item + long iFlags; // Item ability flags + int iMiscId; // Misc item uses id + long iSpell; // item spell + BOOL iUsable; // Usable item? + int iValue; // item min value + int iMaxValue; // item max value +} ItemDataStruct; + +// PATCH1.JMM +typedef struct { + int nSeed; + WORD wCI; + int nIndex; + DWORD dwTimestamp; +} ItemGetRecordStruct; +// ENDPATCH1.JMM + +typedef struct { + int _iSeed; // item seed to generate itself + WORD _iCreateInfo; // item re-creation info + int _itype; // item type + int _ix; // item map x + int _iy; // item map y + BOOL _iAnimFlag; // Does this item animate? + BYTE *_iAnimData; // Data pointer to anim tables + int _iAnimLen; // number of anim frames + int _iAnimFrame; // current anim frame + long _iAnimWidth; // Width of anim + long _iAnimWidth2; // (Width - 64) >> 1 of anim +// PATCH1.JMM + // FLAG IS NO LONGER USED + //BOOL _iDelFlag; // Delete this item + BOOL _iInvalid; +// ENDPATCH1.JMM + + char _iSelFlag; // Select top, floor, or all + BOOL _iPostDraw; // Draw after objects or before? + + BOOL _iIdentified; // Has item been identified? + char _iMagical; // (No/Reg/Unique) Does the item have magical attributes? + char _iName[64]; // item name + char _iIName[64]; // identified name + char _iLoc; // item body location + char _iClass; // item classification + int _iCurs; // item cursor type + int _ivalue; // item value + int _iIvalue; // item identified value + int _iMinDam; // item min damage + int _iMaxDam; // item max damage + int _iAC; // item armor class + long _iFlags; // item ability flags + int _iMiscId; // Misc item uses id + int _iSpell; // item spell + + int _iCharges; // random number of charges + int _iMaxCharges; // Max Charges of a staff + + int _iDurability; // How much strength until it breaks + int _iMaxDur; // Max Durability + + int _iPLDam; // Power List damage multiplier + int _iPLToHit; // Power List to hit increase + int _iPLAC; // Power List AC increase + int _iPLStr; // Power List Strength increase + int _iPLMag; // Power List Magic increase + int _iPLDex; // Power List Dexterity increase + int _iPLVit; // Power List Vitality increase + int _iPLFR; // Power List Fire resistance + int _iPLLR; // Power List Lightning resistance + int _iPLMR; // Power List Misc Magic resistance + long _iPLMana; // Power List Mana + long _iPLHP; // Power List Hit Points + int _iPLDamMod; // Power List damage modifier (num, not %) + int _iPLGetHit; // Power List Get hit modifier (+/-) + int _iPLLight; // Power List light radius + char _iSplLvlAdd; // What to add to each spell level + + char _iRequest; // If item has be requested to be picked up (drb 12/9) + int _iUid; // If unique item, index into unique table (drb 12/8) + + int _iFMinDam; // Fire hit min damage + int _iFMaxDam; // Fire hit max damage + int _iLMinDam; // Lightning hit min damage + int _iLMaxDam; // Lightning hit max damage + + int _iPLEnAc; // Enemy armor class reduced by this amount + + char _iPrePower; // Power List index for prefix + char _iSufPower; // Power List index for suffix + + int _iVAdd1; // value add #1 + int _iVMult1; // value multiplier #1 + int _iVAdd2; // value add #2 + int _iVMult2; // value multiplier #2 + + char _iMinStr; // Min Strength stat to use item + byte _iMinMag; // Min Magic stat to use item + char _iMinDex; // Min Dexterity stat to use item + BOOL _iStatFlag; // Draw with red filter or not + int IDidx; // AllItemsData index + char _oldlight; // Old prelight val + long _iFlags2; // item ability flags +} ItemStruct; + +#define SAVE_ITEM_SIZE sizeof(ItemStruct) + + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern ItemStruct item[MAXITEMS+1]; +extern long numitems; + +extern int itemactive[MAXITEMS]; +extern int itemavail[MAXITEMS]; + +// PATCH1.JMM +extern ItemGetRecordStruct itemgets[MAXITEMS]; +extern int gnNumGetRecords; +// ENDPATCH1.JMM + +extern BOOL UniqueItemFlag[MAXUITEMS]; +extern BOOL uitemflag; + +extern int ItemInvSnds[]; +extern BYTE ItemCAnimTbl[]; +#if CHEATS +extern BOOL davecheat; +extern int tstQMsgSpd; +extern int tstQMsgIndex; +extern BOOL tstQMsgFlag; +extern BOOL tstQMsgIndexFlag; +#endif + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitItems(); +void ProcessItems(); +void InitItemGFX(); +void FreeItemGFX(); +void DaveGold(); +void DaveNewPremium(); +void DaveCleanUp(); +void DaveSpells(); +void DaveSpells2(); +void DaveQuestText(); + +BOOL ItemSpaceOk(int, int); + +void SpawnItem(int, int, int, BOOL); // Called by monsters +void SpawnUnique(int, int, int); // Called by monsters +void RespawnItem(int ii, BOOL FlipFlag); // Called by plr placing object back + +void CreateItem(int, int, int); // Spawn a specific item at x, y +void CreateRndItem(int, int, BOOL, BOOL, BOOL); // Spawn any item around x,y (item level >= (currlevel*2)) +void CreateRndUseful(int, int, int, BOOL); // Spawn either health, mana, or identify +void CreateTypeItem(int, int, BOOL, int, int, BOOL, BOOL); // Spawn a specific type of item +void CreateSpellBook(int x, int y, int ispell, BOOL sendmsg, BOOL delta); //Spawn a specific spell book +void CreateMagicArmor(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta); //Spawn specific magical armor +void CreateAmulet(int x, int y, int level, BOOL sendmsg, BOOL delta); //Spawn an amulet +void CreateMagicWeapon(int x, int y, int imisc, int icurs, BOOL sendmsg, BOOL delta); //Spawn specific magical weapon + +void RecreateItem(int, int, WORD, int, int); +void RecreateEar(int, WORD, int, BOOL, int, int, int, int, int, int); + +void SyncItemAnim(int); + +void GetItemStr(int); + +void CalcPlrItemVals(int,BOOL); +void CalcPlrScrolls(int); +void CalcPlrStaff(int); +void CalcPlrItemMin(int); +void CalcPlrInv(int,BOOL); + +void CreatePlrItems(int); + +void SpawnRock(); + +void CheckIdentify(int, int); +void DoRepair(int, int); +void DoRecharge(int, int); +void DoOil(int, int); + +void PrintItemPower(char,const ItemStruct * x); +void PrintItemDetails(const ItemStruct * x); +void PrintItemDur(const ItemStruct * x); + +void UseItem(int, int, int); + +void SpawnSmith(int); +void SpawnPremium(int); +void SpawnWitch(int); +void SpawnBoy(int); +void SpawnHealer(int); +void SpawnStoreGold(); +void SpawnQuestItem(int itemid, int x,int y, int randarea, int selflag); + +void DrawUniqueInfo(); + +void GetItemAttrs(int i, int idata, int lvl); + +int ItemNoFlippy(); +void GetSuperItemLoc(int x, int y, int &xx, int &yy); + +// PATCH1.JMM +BOOL CheckGetRecord( int nSeed, WORD wCI, int nIndex ); +void AddGetRecord( int nSeed, WORD wCI, int nIndex ); +void RemoveGetRecord( int nSeed, WORD wCI, int nIndex ); +// ENDPATCH1.JMM + +void SetPlrHandItem(ItemStruct *h, int idata); +void GetPlrHandSeed(ItemStruct *h); + +typedef struct { + int x; + int y; + BOOL Initted; + ItemStruct item; +} CornerStoneType; + +extern CornerStoneType CornerStone; + +extern void CornerstoneRestore(int x, int y); +extern void CornerstoneSave(); diff --git a/src/LIGHTING.CPP b/src/LIGHTING.CPP new file mode 100644 index 0000000..09711ca --- /dev/null +++ b/src/LIGHTING.CPP @@ -0,0 +1,1178 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Radial lighting ONLY +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/LIGHTING.CPP 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "lighting.h" +#include "gendung.h" +#include "engine.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "math.h" +#include "automap.h" + +/*-----------------------------------------------------------------------*/ + +#define PAUSEBANDS 224 // Pause band starting color +#define PAUSEBANDE PAUSEBANDS+15 // Pause band ending color + +/*-----------------------------------------------------------------------*/ + +// light test +int lnum = 0; + +/*-----------------------------------------------------------------------** +** Global variables +**-----------------------------------------------------------------------*/ + +extern "C" { + BYTE *pLightTbl; + char lightmax; +} + +int lightflag = 0; + +LightListStruct LightList[MAXLIGHTS]; +BYTE lightactive[MAXLIGHTS]; +int numlights; +BOOL dolighting; + +LightListStruct VisionList[MAXVISION]; +int numvision; +BOOL dovision; +int visionid; + +/*-----------------------------------------------------------------------** +** File variables +**-----------------------------------------------------------------------*/ + +// table of inc/dec for crawling the lighting radius (clockwise starting with N) +char CrawlTable[2749] = { + 1, 0, 0, + 4, 0, 1, 0, -1, -1, 0, 1, 0, + 16, 0, 2, 0, -2, -1, 2, 1, 2, -1, -2, 1, -2, -1, 1, 1, 1, -1, -1, 1, -1, -2, 1, 2, 1, -2, -1, 2, -1, + -2, 0, 2, 0, + 24, 0, 3, 0, -3, -1, 3, 1, 3, -1, -3, 1, -3, -2, 3, 2, 3, -2, -3, 2, -3, -2, 2, 2, 2, -2, -2, 2, -2, + -3, 2, 3, 2, -3, -2, 3, -2, -3, 1, 3, 1, -3, -1, 3, -1, -3, 0, 3, 0, + 32, 0, 4, 0, -4, -1, 4, 1, 4, -1, -4, 1, -4, -2, 4, 2, 4, -2, -4, 2, -4, -3, 4, 3, 4, -3, -4, 3, -4, + -3, 3, 3, 3, -3, -3, 3, -3, -4, 3, 4, 3, -4, -3, 4, -3, -4, 2, 4, 2, -4, -2, 4, -2, + -4, 1, 4, 1, -4, -1, 4, -1, -4, 0, 4, 0, + 40, 0, 5, 0, -5, -1, 5, 1, 5, -1, -5, 1, -5, -2, 5, 2, 5, -2, -5, 2, -5, -3, 5, 3, 5, -3, -5, 3, -5, + -4, 5, 4, 5, -4, -5, 4, -5, -4, 4, 4, 4, -4, -4, 4, -4, -5, 4, 5, 4, -5, -4, 5, -4, + -5, 3, 5, 3, -5, -3, 5, -3, -5, 2, 5, 2, -5, -2, 5, -2, -5, 1, 5, 1, -5, -1, 5, -1, + -5, 0, 5, 0, + 48, 0, 6, 0, -6, -1, 6, 1, 6, -1, -6, 1, -6, -2, 6, 2, 6, -2, -6, 2, -6, -3, 6, 3, 6, -3, -6, 3, -6, + -4, 6, 4, 6, -4, -6, 4, -6, -5, 6, 5, 6, -5, -6, 5, -6, -5, 5, 5, 5, -5, -5, 5, -5, + -6, 5, 6, 5, -6, -5, 6, -5, -6, 4, 6, 4, -6, -4, 6, -4, -6, 3, 6, 3, -6, -3, 6, -3, + -6, 2, 6, 2, -6, -2, 6, -2, -6, 1, 6, 1, -6, -1, 6, -1, -6, 0, 6, 0, + 56, 0, 7, 0, -7, -1, 7, 1, 7, -1, -7, 1, -7, -2, 7, 2, 7, -2, -7, 2, -7, -3, 7, 3, 7, -3, -7, 3, -7, + -4, 7, 4, 7, -4, -7, 4, -7, -5, 7, 5, 7, -5, -7, 5, -7, -6, 7, 6, 7, -6, -7, 6, -7, + -6, 6, 6, 6, -6, -6, 6, -6, -7, 6, 7, 6, -7, -6, 7, -6, -7, 5, 7, 5, -7, -5, 7, -5, + -7, 4, 7, 4, -7, -4, 7, -4, -7, 3, 7, 3, -7, -3, 7, -3, -7, 2, 7, 2, -7, -2, 7, -2, + -7, 1, 7, 1, -7, -1, 7, -1, -7, 0, 7, 0, + 64, 0, 8, 0, -8, -1, 8, 1, 8, -1, -8, 1, -8, -2, 8, 2, 8, -2, -8, 2, -8, -3, 8, 3, 8, -3, -8, 3, -8, + -4, 8, 4, 8, -4, -8, 4, -8, -5, 8, 5, 8, -5, -8, 5, -8, -6, 8, 6, 8, -6, -8, 6, -8, + -7, 8, 7, 8, -7, -8, 7, -8, -7, 7, 7, 7, -7, -7, 7, -7, -8, 7, 8, 7, -8, -7, 8, -7, + -8, 6, 8, 6, -8, -6, 8, -6, -8, 5, 8, 5, -8, -5, 8, -5, -8, 4, 8, 4, -8, -4, 8, -4, + -8, 3, 8, 3, -8, -3, 8, -3, -8, 2, 8, 2, -8, -2, 8, -2, -8, 1, 8, 1, -8, -1, 8, -1, + -8, 0, 8, 0, + 72, 0, 9, 0, -9, -1, 9, 1, 9, -1, -9, 1, -9, -2, 9, 2, 9, -2, -9, 2, -9, -3, 9, 3, 9, -3, -9, 3, -9, + -4, 9, 4, 9, -4, -9, 4, -9, -5, 9, 5, 9, -5, -9, 5, -9, -6, 9, 6, 9, -6, -9, 6, -9, + -7, 9, 7, 9, -7, -9, 7, -9, -8, 9, 8, 9, -8, -9, 8, -9, -8, 8, 8, 8, -8, -8, 8, -8, + -9, 8, 9, 8, -9, -8, 9, -8, -9, 7, 9, 7, -9, -7, 9, -7, -9, 6, 9, 6, -9, -6, 9, -6, + -9, 5, 9, 5, -9, -5, 9, -5, -9, 4, 9, 4, -9, -4, 9, -4, -9, 3, 9, 3, -9, -3, 9, -3, + -9, 2, 9, 2, -9, -2, 9, -2, -9, 1, 9, 1, -9, -1, 9, -1, -9, 0, 9, 0, + 80, 0, 10, 0,-10, -1, 10, 1, 10, -1,-10, 1,-10, -2, 10, 2, 10, -2,-10, 2,-10, -3, 10, 3, 10, -3,-10, 3,-10, + -4, 10, 4, 10, -4,-10, 4,-10, -5, 10, 5, 10, -5,-10, 5,-10, -6, 10, 6, 10, -6,-10, 6,-10, + -7, 10, 7, 10, -7,-10, 7,-10, -8, 10, 8, 10, -8,-10, 8,-10, -9, 10, 9, 10, -9,-10, 9,-10, + -9, 9, 9, 9, -9, -9, 9, -9,-10, 9, 10, 9,-10, -9, 10, -9,-10, 8, 10, 8,-10, -8, 10, -8, + -10, 7, 10, 7,-10, -7, 10, -7,-10, 6, 10, 6,-10, -6, 10, -6,-10, 5, 10, 5,-10, -5, 10, -5, + -10, 4, 10, 4,-10, -4, 10, -4,-10, 3, 10, 3,-10, -3, 10, -3,-10, 2, 10, 2,-10, -2, 10, -2, + -10, 1, 10, 1,-10, -1, 10, -1,-10, 0, 10, 0, + 88, 0, 11, 0,-11, -1, 11, 1, 11, -1,-11, 1,-11, -2, 11, 2, 11, -2,-11, 2,-11, -3, 11, 3, 11, -3,-11, 3,-11, + -4, 11, 4, 11, -4,-11, 4,-11, -5, 11, 5, 11, -5,-11, 5,-11, -6, 11, 6, 11, -6,-11, 6,-11, + -7, 11, 7, 11, -7,-11, 7,-11, -8, 11, 8, 11, -8,-11, 8,-11, -9, 11, 9, 11, -9,-11, 9,-11, + -10, 11, 10, 11,-10,-11, 10,-11,-10, 10, 10, 10,-10,-10, 10,-10,-11, 10, 11, 10,-11,-10, 11,-10, + -11, 9, 11, 9,-11, -9, 11, -9,-11, 8, 11, 8,-11, -8, 11, -8,-11, 7, 11, 7,-11, -7, 11, -7, + -11, 6, 11, 6,-11, -6, 11, -6,-11, 5, 11, 5,-11, -5, 11, -5,-11, 4, 11, 4,-11, -4, 11, -4, + -11, 3, 11, 3,-11, -3, 11, -3,-11, 2, 11, 2,-11, -2, 11, -2,-11, 1, 11, 1,-11, -1, 11, -1, + -11, 0, 11, 0, + 96, 0, 12, 0,-12, -1, 12, 1, 12, -1,-12, 1,-12, -2, 12, 2, 12, -2,-12, 2,-12, -3, 12, 3, 12, -3,-12, 3,-12, + -4, 12, 4, 12, -4,-12, 4,-12, -5, 12, 5, 12, -5,-12, 5,-12, -6, 12, 6, 12, -6,-12, 6,-12, + -7, 12, 7, 12, -7,-12, 7,-12, -8, 12, 8, 12, -8,-12, 8,-12, -9, 12, 9, 12, -9,-12, 9,-12, + -10, 12, 10, 12,-10,-12, 10,-12,-11, 12, 11, 12,-11,-12, 11,-12,-11, 11, 11, 11,-11,-11, 11,-11, + -12, 11, 12, 11,-12,-11, 12,-11,-12, 10, 12, 10,-12,-10, 12,-10,-12, 9, 12, 9,-12, -9, 12, -9, + -12, 8, 12, 8,-12, -8, 12, -8,-12, 7, 12, 7,-12, -7, 12, -7,-12, 6, 12, 6,-12, -6, 12, -6, + -12, 5, 12, 5,-12, -5, 12, -5,-12, 4, 12, 4,-12, -4, 12, -4,-12, 3, 12, 3,-12, -3, 12, -3, + -12, 2, 12, 2,-12, -2, 12, -2,-12, 1, 12, 1,-12, -1, 12, -1,-12, 0, 12, 0, +104, 0, 13, 0,-13, -1, 13, 1, 13, -1,-13, 1,-13, -2, 13, 2, 13, -2,-13, 2,-13, -3, 13, 3, 13, -3,-13, 3,-13, + -4, 13, 4, 13, -4,-13, 4,-13, -5, 13, 5, 13, -5,-13, 5,-13, -6, 13, 6, 13, -6,-13, 6,-13, + -7, 13, 7, 13, -7,-13, 7,-13, -8, 13, 8, 13, -8,-13, 8,-13, -9, 13, 9, 13, -9,-13, 9,-13, + -10, 13, 10, 13,-10,-13, 10,-13,-11, 13, 11, 13,-11,-13, 11,-13,-12, 13, 12, 13,-12,-13, 12,-13, + -12, 12, 12, 12,-12,-12, 12,-12,-13, 12, 13, 12,-13,-12, 13,-12,-13, 11, 13, 11,-13,-11, 13,-11, + -13, 10, 13, 10,-13,-10, 13,-10,-13, 9, 13, 9,-13, -9, 13, -9,-13, 8, 13, 8,-13, -8, 13, -8, + -13, 7, 13, 7,-13, -7, 13, -7,-13, 6, 13, 6,-13, -6, 13, -6,-13, 5, 13, 5,-13, -5, 13, -5, + -13, 4, 13, 4,-13, -4, 13, -4,-13, 3, 13, 3,-13, -3, 13, -3,-13, 2, 13, 2,-13, -2, 13, -2, + -13, 1, 13, 1,-13, -1, 13, -1,-13, 0, 13, 0, +112, 0, 14, 0,-14, -1, 14, 1, 14, -1,-14, 1,-14, -2, 14, 2, 14, -2,-14, 2,-14, -3, 14, 3, 14, -3,-14, 3,-14, + -4, 14, 4, 14, -4,-14, 4,-14, -5, 14, 5, 14, -5,-14, 5,-14, -6, 14, 6, 14, -6,-14, 6,-14, + -7, 14, 7, 14, -7,-14, 7,-14, -8, 14, 8, 14, -8,-14, 8,-14, -9, 14, 9, 14, -9,-14, 9,-14, + -10, 14, 10, 14,-10,-14, 10,-14,-11, 14, 11, 14,-11,-14, 11,-14,-12, 14, 12, 14,-12,-14, 12,-14, + -13, 14, 13, 14,-13,-14, 13,-14,-13, 13, 13, 13,-13,-13, 13,-13,-14, 13, 14, 13,-14,-13, 14,-13, + -14, 12, 14, 12,-14,-12, 14,-12,-14, 11, 14, 11,-14,-11, 14,-11,-14, 10, 14, 10,-14,-10, 14,-10, + -14, 9, 14, 9,-14, -9, 14, -9,-14, 8, 14, 8,-14, -8, 14, -8,-14, 7, 14, 7,-14, -7, 14, -7, + -14, 6, 14, 6,-14, -6, 14, -6,-14, 5, 14, 5,-14, -5, 14, -5,-14, 4, 14, 4,-14, -4, 14, -4, + -14, 3, 14, 3,-14, -3, 14, -3,-14, 2, 14, 2,-14, -2, 14, -2,-14, 1, 14, 1,-14, -1, 14, -1, + -14, 0, 14, 0, +120, 0, 15, 0,-15, -1, 15, 1, 15, -1,-15, 1,-15, -2, 15, 2, 15, -2,-15, 2,-15, -3, 15, 3, 15, -3,-15, 3,-15, + -4, 15, 4, 15, -4,-15, 4,-15, -5, 15, 5, 15, -5,-15, 5,-15, -6, 15, 6, 15, -6,-15, 6,-15, + -7, 15, 7, 15, -7,-15, 7,-15, -8, 15, 8, 15, -8,-15, 8,-15, -9, 15, 9, 15, -9,-15, 9,-15, + -10, 15, 10, 15,-10,-15, 10,-15,-11, 15, 11, 15,-11,-15, 11,-15,-12, 15, 12, 15,-12,-15, 12,-15, + -13, 15, 13, 15,-13,-15, 13,-15,-14, 15, 14, 15,-14,-15, 14,-15,-14, 14, 14, 14,-14,-14, 14,-14, + -15, 14, 15, 14,-15,-14, 15,-14,-15, 13, 15, 13,-15,-13, 15,-13,-15, 12, 15, 12,-15,-12, 15,-12, + -15, 11, 15, 11,-15,-11, 15,-11,-15, 10, 15, 10,-15,-10, 15,-10,-15, 9, 15, 9,-15, -9, 15, -9, + -15, 8, 15, 8,-15, -8, 15, -8,-15, 7, 15, 7,-15, -7, 15, -7,-15, 6, 15, 6,-15, -6, 15, -6, + -15, 5, 15, 5,-15, -5, 15, -5,-15, 4, 15, 4,-15, -4, 15, -4,-15, 3, 15, 3,-15, -3, 15, -3, + -15, 2, 15, 2,-15, -2, 15, -2,-15, 1, 15, 1,-15, -1, 15, -1,-15, 0, 15, 0, +(char)128, 0, 16, 0,-16, -1, 16, 1, 16, -1,-16, 1,-16, -2, 16, 2, 16, -2,-16, 2,-16, -3, 16, 3, 16, -3,-16, 3,-16, + -4, 16, 4, 16, -4,-16, 4,-16, -5, 16, 5, 16, -5,-16, 5,-16, -6, 16, 6, 16, -6,-16, 6,-16, + -7, 16, 7, 16, -7,-16, 7,-16, -8, 16, 8, 16, -8,-16, 8,-16, -9, 16, 9, 16, -9,-16, 9,-16, + -10, 16, 10, 16,-10,-16, 10,-16,-11, 16, 11, 16,-11,-16, 11,-16,-12, 16, 12, 16,-12,-16, 12,-16, + -13, 16, 13, 16,-13,-16, 13,-16,-14, 16, 14, 16,-14,-16, 14,-16,-15, 16, 15, 16,-15,-16, 15,-16, + -15, 15, 15, 15,-15,-15, 15,-15,-16, 15, 16, 15,-16,-15, 16,-15,-16, 14, 16, 14,-16,-14, 16,-14, + -16, 13, 16, 13,-16,-13, 16,-13,-16, 12, 16, 12,-16,-12, 16,-12,-16, 11, 16, 11,-16,-11, 16,-11, + -16, 10, 16, 10,-16,-10, 16,-10,-16, 9, 16, 9,-16, -9, 16, -9,-16, 8, 16, 8,-16, -8, 16, -8, + -16, 7, 16, 7,-16, -7, 16, -7,-16, 6, 16, 6,-16, -6, 16, -6,-16, 5, 16, 5,-16, -5, 16, -5, + -16, 4, 16, 4,-16, -4, 16, -4,-16, 3, 16, 3,-16, -3, 16, -3,-16, 2, 16, 2,-16, -2, 16, -2, + -16, 1, 16, 1,-16, -1, 16, -1,-16, 0, 16, 0, +(char)136, 0, 17, 0,-17, -1, 17, 1, 17, -1,-17, 1,-17, -2, 17, 2, 17, -2,-17, 2,-17, -3, 17, 3, 17, -3,-17, 3,-17, + -4, 17, 4, 17, -4,-17, 4,-17, -5, 17, 5, 17, -5,-17, 5,-17, -6, 17, 6, 17, -6,-17, 6,-17, + -7, 17, 7, 17, -7,-17, 7,-17, -8, 17, 8, 17, -8,-17, 8,-17, -9, 17, 9, 17, -9,-17, 9,-17, + -10, 17, 10, 17,-10,-17, 10,-17,-11, 17, 11, 17,-11,-17, 11,-17,-12, 17, 12, 17,-12,-17, 12,-17, + -13, 17, 13, 17,-13,-17, 13,-17,-14, 17, 14, 17,-14,-17, 14,-17,-15, 17, 15, 17,-15,-17, 15,-17, + -16, 17, 16, 17,-16,-17, 16,-17,-16, 16, 16, 16,-16,-16, 16,-16,-17, 16, 17, 16,-17,-16, 17,-16, + -17, 15, 17, 15,-17,-15, 17,-15,-17, 14, 17, 14,-17,-14, 17,-14,-17, 13, 17, 13,-17,-13, 17,-13, + -17, 12, 17, 12,-17,-12, 17,-12,-17, 11, 17, 11,-17,-11, 17,-11,-17, 10, 17, 10,-17,-10, 17,-10, + -17, 9, 17, 9,-17, -9, 17, -9,-17, 8, 17, 8,-17, -8, 17, -8,-17, 7, 17, 7,-17, -7, 17, -7, + -17, 6, 17, 6,-17, -6, 17, -6,-17, 5, 17, 5,-17, -5, 17, -5,-17, 4, 17, 4,-17, -4, 17, -4, + -17, 3, 17, 3,-17, -3, 17, -3,-17, 2, 17, 2,-17, -2, 17, -2,-17, 1, 17, 1,-17, -1, 17, -1, + -17, 0, 17, 0, +(char)144, 0, 18, 0,-18, -1, 18, 1, 18, -1,-18, 1,-18, -2, 18, 2, 18, -2,-18, 2,-18, -3, 18, 3, 18, -3,-18, 3,-18, + -4, 18, 4, 18, -4,-18, 4,-18, -5, 18, 5, 18, -5,-18, 5,-18, -6, 18, 6, 18, -6,-18, 6,-18, + -7, 18, 7, 18, -7,-18, 7,-18, -8, 18, 8, 18, -8,-18, 8,-18, -9, 18, 9, 18, -9,-18, 9,-18, + -10, 18, 10, 18,-10,-18, 10,-18,-11, 18, 11, 18,-11,-18, 11,-18,-12, 18, 12, 18,-12,-18, 12,-18, + -13, 18, 13, 18,-13,-18, 13,-18,-14, 18, 14, 18,-14,-18, 14,-18,-15, 18, 15, 18,-15,-18, 15,-18, + -16, 18, 16, 18,-16,-18, 16,-18,-17, 18, 17, 18,-17,-18, 17,-18,-17, 17, 17, 17,-17,-17, 17,-17, + -18, 17, 18, 17,-18,-17, 18,-17,-18, 16, 18, 16,-18,-16, 18,-16,-18, 15, 18, 15,-18,-15, 18,-15, + -18, 14, 18, 14,-18,-14, 18,-14,-18, 13, 18, 13,-18,-13, 18,-13,-18, 12, 18, 12,-18,-12, 18,-12, + -18, 11, 18, 11,-18,-11, 18,-11,-18, 10, 18, 10,-18,-10, 18,-10,-18, 9, 18, 9,-18, -9, 18, -9, + -18, 8, 18, 8,-18, -8, 18, -8,-18, 7, 18, 7,-18, -7, 18, -7,-18, 6, 18, 6,-18, -6, 18, -6, + -18, 5, 18, 5,-18, -5, 18, -5,-18, 4, 18, 4,-18, -4, 18, -4,-18, 3, 18, 3,-18, -3, 18, -3, + -18, 2, 18, 2,-18, -2, 18, -2,-18, 1, 18, 1,-18, -1, 18, -1,-18, 0, 18, 0 +}; + +// points to corresponding radius in above table +char * pCrawlEntry[19] = { + &(CrawlTable[0]), // 0 + &(CrawlTable[3]), // 1 + &(CrawlTable[12]), // 2 + &(CrawlTable[45]), // 3 + &(CrawlTable[94]), // 4 + &(CrawlTable[159]), // 5 + &(CrawlTable[240]), // 6 + &(CrawlTable[337]), // 7 + &(CrawlTable[450]), // 8 + &(CrawlTable[579]), // 9 + &(CrawlTable[724]), // 10 + &(CrawlTable[885]), // 11 + &(CrawlTable[1062]), // 12 + &(CrawlTable[1255]), // 13 + &(CrawlTable[1464]), // 14 + &(CrawlTable[1689]), // 15 + &(CrawlTable[1930]), // 16 + &(CrawlTable[2187]), // 17 + &(CrawlTable[2460]) // 18 +}; + +BYTE vCrawlTable[23][30] = { + {1,0, 2,0, 3,0, 4,0, 5,0, 6,0, 7,0, 8,0, 9,0, 10,0, 11,0, 12,0, 13,0, 14,0, 15,0}, // 0 + {1,0, 2,0, 3,0, 4,0, 5,0, 6,0, 7,0, 8,1, 9,1, 10,1, 11,1, 12,1, 13,1, 14,1, 15,1}, // 1 + {1,0, 2,0, 3,0, 4,1, 5,1, 6,1, 7,1, 8,1, 9,1, 10,1, 11,1, 12,2, 13,2, 14,2, 15,2}, // 2 + {1,0, 2,0, 3,1, 4,1, 5,1, 6,1, 7,1, 8,2, 9,2, 10,2, 11,2, 12,2, 13,3, 14,3, 15,3}, // 3 + {1,0, 2,1, 3,1, 4,1, 5,1, 6,2, 7,2, 8,2, 9,3, 10,3, 11,3, 12,3, 13,4, 14,4, 0,0}, // 4 + {1,0, 2,1, 3,1, 4,1, 5,2, 6,2, 7,3, 8,3, 9,3, 10,4, 11,4, 12,4, 13,5, 14,5, 0,0}, // 5 + {1,0, 2,1, 3,1, 4,2, 5,2, 6,3, 7,3, 8,3, 9,4, 10,4, 11,5, 12,5, 13,6, 14,6, 0,0}, // 6 + {1,1, 2,1, 3,2, 4,2, 5,3, 6,3, 7,4, 8,4, 9,5, 10,5, 11,6, 12,6, 13,7, 0,0, 0,0}, // 7 + {1,1, 2,1, 3,2, 4,2, 5,3, 6,4, 7,4, 8,5, 9,6, 10,6, 11,7, 12,7, 12,8, 13,8, 0,0}, // 8 + {1,1, 2,2, 3,2, 4,3, 5,4, 6,5, 7,5, 8,6, 9,7, 10,7, 10,8, 11,8, 12,9, 0,0, 0,0}, // 9 + {1,1, 2,2, 3,3, 4,4, 5,5, 6,5, 7,6, 8,7, 9,8, 10,9, 11,9, 11,10, 0,0, 0,0, 0,0}, // 10 + {1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7, 8,8, 9,9, 10,10, 11,11, 0,0, 0,0, 0,0, 0,0}, // 11 + {1,1, 2,2, 3,3, 4,4, 5,5, 5,6, 6,7, 7,8, 8,9, 9,10, 9,11, 10,11, 0,0, 0,0, 0,0}, // 12 + {1,1, 2,2, 2,3, 3,4, 4,5, 5,6, 5,7, 6,8, 7,9, 7,10, 8,10, 8,11, 9,12, 0,0, 0,0}, // 13 + {1,1, 1,2, 2,3, 2,4, 3,5, 4,6, 4,7, 5,8, 6,9, 6,10, 7,11, 7,12, 8,12, 8,13, 0,0}, // 14 + {1,1, 1,2, 2,3, 2,4, 3,5, 3,6, 4,7, 4,8, 5,9, 5,10, 6,11, 6,12, 7,13, 0,0, 0,0}, // 15 + {0,1, 1,2, 1,3, 2,4, 2,5, 3,6, 3,7, 3,8, 4,9, 4,10, 5,11, 5,12, 6,13, 6,14, 0,0}, // 16 + {0,1, 1,2, 1,3, 1,4, 2,5, 2,6, 3,7, 3,8, 3,9, 4,10, 4,11, 4,12, 5,13, 5,14, 0,0}, // 17 + {0,1, 1,2, 1,3, 1,4, 1,5, 2,6, 2,7, 2,8, 3,9, 3,10, 3,11, 3,12, 4,13, 4,14, 0,0}, // 18 + {0,1, 0,2, 1,3, 1,4, 1,5, 1,6, 1,7, 2,8, 2,9, 2,10, 2,11, 2,12, 3,13, 3,14, 3,15}, // 19 + {0,1, 0,2, 0,3, 1,4, 1,5, 1,6, 1,7, 1,8, 1,9, 1,10, 1,11, 2,12, 2,13, 2,14, 2,15}, // 20 + {0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 1,8, 1,9, 1,10, 1,11, 1,12, 1,13, 1,14, 1,15}, // 21 + {0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 0,8, 0,9, 0,10, 0,11, 0,12, 0,13, 0,14, 0,15} // 22 +}; + +BYTE LightLvls[16][128]; + + +BYTE LightLvls4[18][18] = { + { 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 1 + { 0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 2 + { 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 3 + { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 4 + { 0, 0, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 1 + { 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 6 + { 0, 0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 7 + { 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 8 + { 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3}, // 9 + { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3}, // 2 + { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3}, // 11 + { 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3}, // 12 + { 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3}, // 13 + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3}, // 14 + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3}, // 3 + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3}, // 16 + { 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3}, // 17 + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2} // 18 +}; + +BYTE Dist[64][256]; + +BYTE RadiusAdj[23] = {0,0,0,0,1,1,1,2,2,2,3,4,3,2,2,2,1,1,1,0,0,0,0}; + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RotateOffset(int &x, int &y, int &rx, int &ry, int &ox, int &oy, int &ax, int &ay) +{ + int tmp; + + ax = 0; + ay = 0; + + // rotate rx,ry by 90 deg. clockwise + tmp = rx; + rx = 7-ry; + ry = tmp; + + // rotate origin by 90 deg. clockwise + tmp = ox; + ox = 7-oy; + oy = tmp; + + // set x,y to rx,ry shifted relative to origin + x = rx - ox; + y = ry - oy; + + // bring them back into 0..7 range + if(x < 0) + { + x += 8; + ax = 1; + } + if(y < 0) + { + y += 8; + ay = 1; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoLighting (int nXPos, int nYPos, int nRadius, int Lnum) +{ + int LightVal; + int nCrawlX, nCrawlY; + int i, j; + int dist; + int xoff=0,yoff=0; // offset into tile, where tile is broken + // into 8x8 grid for increased distance resolution. + int rxoff, ryoff; // rotated offsets + int orgx=0, orgy=0; + int addx=0, addy=0; + int dtab; + int maxleft,maxright,maxup,maxdown; // clipping vars: offsets from nXPos,nYpos; absolute vals + + if(Lnum >= 0) + { + xoff = LightList[Lnum]._xoff; + yoff = LightList[Lnum]._yoff; + + if(xoff < 0) + { + xoff += 8; + nXPos--; + } + if(yoff < 0) + { + yoff += 8; + nYPos--; + } + } + rxoff = xoff; + ryoff = yoff; + + if((nXPos - 15) < 0) + maxleft = nXPos + 1; + else + maxleft = 15; + if((nXPos + 15) > MAXDUNX) + maxright = MAXDUNX - nXPos; + else + maxright = 15; + if((nYPos - 15) < 0) + maxup = nYPos + 1; + else + maxup = 15; + if((nYPos + 15) > MAXDUNY) + maxdown = MAXDUNY - nYPos; + else + maxdown = 15; + + if (currlevel < HIVESTART) + dLight[nXPos][nYPos] = 0; + else + if(dLight[nXPos][nYPos] > LightLvls[nRadius][0]) + dLight[nXPos][nYPos] = LightLvls[nRadius][0]; + + + // Quadrant 1 + // |x + // --- + // | + dtab = xoff + 8*yoff; + + for (j = 0; j < maxup; j++) + { + for (i = 1; i < maxright; i++) + { + dist = Dist[dtab][i+j*16]; + if(dist < 128) + { + nCrawlX = nXPos + i; + nCrawlY = nYPos + j; + LightVal = LightLvls[nRadius][dist]; + if(LightVal < dLight[nCrawlX][nCrawlY]) + dLight[nCrawlX][nCrawlY] = LightVal; + } + } + } + + // Quadrant 2 + // | + // --- + // |x + + RotateOffset(xoff,yoff, rxoff,ryoff, orgx,orgy, addx,addy); + dtab = xoff + 8*yoff; + for (j = 0; j < maxdown; j++) + { + for (i = 1; i < maxright; i++) + { + dist = Dist[dtab][(i+addx)+(j+addy)*16]; + if(dist < 128) + { + nCrawlX = nXPos + j; + nCrawlY = nYPos - i; + LightVal = LightLvls[nRadius][dist]; + if(LightVal < dLight[nCrawlX][nCrawlY]) + dLight[nCrawlX][nCrawlY] = LightVal; + } + } + } + + // Quadrant 3 + // | + // --- + // x| + RotateOffset(xoff,yoff, rxoff,ryoff, orgx,orgy, addx,addy); + dtab = xoff + 8*yoff; + for (j = 0; j < maxdown; j++) + { + for (i = 1; i < maxleft; i++) + { + dist = Dist[dtab][(i+addx)+(j+addy)*16]; + if(dist < 128) + { + nCrawlX = nXPos - i; + nCrawlY = nYPos - j; + LightVal = LightLvls[nRadius][dist]; + if(LightVal < dLight[nCrawlX][nCrawlY]) + dLight[nCrawlX][nCrawlY] = LightVal; + } + } + } + + // Quadrant 4 + // x| + // --- + // | + RotateOffset(xoff,yoff, rxoff,ryoff, orgx,orgy, addx,addy); + dtab = xoff + 8*yoff; + for (j = 0; j < maxup; j++) + { + for (i = 1; i < maxleft; i++) + { + dist = Dist[dtab][(i+addx)+(j+addy)*16]; + if(dist < 128) + { + nCrawlX = nXPos - j; + nCrawlY = nYPos + i; + LightVal = LightLvls[nRadius][dist]; + if(LightVal < dLight[nCrawlX][nCrawlY]) + dLight[nCrawlX][nCrawlY] = LightVal; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoUnLight (int nXPos, int nYPos, int nRadius) +{ + int i, j; + int x1,y1,x2,y2; + + nRadius++; + y1 = nYPos - nRadius; + y2 = nYPos + nRadius; + x1 = nXPos - nRadius; + x2 = nXPos + nRadius; + if (y1 < 0) y1 = 0; + if (y2 > DMAXY) y2 = DMAXY; + if (x1 < 0) x1 = 0; + if (x2 > DMAXX) x2 = DMAXX; + for (j = y1; j < y2; j++) { + for (i = x1; i < x2; i++) dLight[i][j] = dSaveLight[i][j]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoUnVision (int nXPos, int nYPos, int nRadius) +{ + int i, j; + int x1,y1,x2,y2; + + nRadius++; + y1 = nYPos - nRadius; + y2 = nYPos + nRadius; + x1 = nXPos - nRadius; + x2 = nXPos + nRadius; + if (y1 < 0) y1 = 0; + if (y2 > DMAXY) y2 = DMAXY; + if (x1 < 0) x1 = 0; + if (x2 > DMAXX) x2 = DMAXX; + for (i = x1; i < x2; i++) { + for (j = y1; j < y2; j++) dFlags[i][j] &= ~(BFLAG_VISIBLE | BFLAG_MONSTACTIVE); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoVision (int nXPos, int nYPos, int nRadius, BOOL doautomap, BOOL visible) +{ + int nCrawlX, nCrawlY, nLineLen; + int nBlockerFlag; + int i, j, k, v; + int x1adj, x2adj, y1adj, y2adj; + + // handle origin separately. Why? I don't know. + if (nXPos >= 0 && nXPos <= DMAXX && nYPos >= 0 && nYPos <= DMAXY) { + if (doautomap) { + if (dFlags[nXPos][nYPos] >= 0) SetAutomapView(nXPos, nXPos); + dFlags[nXPos][nYPos] |= BFLAG_AUTOMAP; + } + if (visible) + dFlags[nXPos][nYPos] |= BFLAG_VISIBLE; + dFlags[nXPos][nYPos] |= BFLAG_MONSTACTIVE; + } + + for (k = 0; k < 4; k ++) { + for (j = 0; j < 23; j ++) { + + nBlockerFlag = 0; + nLineLen = (nRadius - RadiusAdj[j]) << 1; + + for (i = 0; i < nLineLen && !nBlockerFlag; i += 2) { + x1adj = 0; + x2adj = 0; + y1adj = 0; + y2adj = 0; + + switch (k) { + case 0: + nCrawlX = nXPos + vCrawlTable[j][i]; + nCrawlY = nYPos + vCrawlTable[j][i + 1]; + if (vCrawlTable[j][i] > 0 && vCrawlTable[j][i+1] > 0) { + x1adj = -1; + y2adj = -1; + } + break; + case 1: + nCrawlX = nXPos - vCrawlTable[j][i]; + nCrawlY = nYPos - vCrawlTable[j][i + 1]; + if ((vCrawlTable[j][i] > 0) && (vCrawlTable[j][i+1] > 0)) { + y1adj = 1; + x2adj = 1; + } + break; + case 2: + nCrawlX = nXPos + vCrawlTable[j][i]; + nCrawlY = nYPos - vCrawlTable[j][i + 1]; + if (vCrawlTable[j][i] > 0 && vCrawlTable[j][i+1] > 0) { + x1adj = -1; + y2adj = 1; + } + break; + case 3: + nCrawlX = nXPos - vCrawlTable[j][i]; + nCrawlY = nYPos + vCrawlTable[j][i + 1]; + if (vCrawlTable[j][i] > 0 && vCrawlTable[j][i+1] > 0) { + y1adj = -1; + x2adj = 1; + } + break; + } + + if (nCrawlX >= 0 && nCrawlX <= DMAXX && nCrawlY >= 0 && nCrawlY <= DMAXY) { + + nBlockerFlag = nBlockTable[dPiece[nCrawlX][nCrawlY]]; + + if (!nBlockTable[dPiece[nCrawlX + x1adj][nCrawlY + y1adj]] + || !nBlockTable[dPiece[nCrawlX + x2adj][nCrawlY + y2adj]]) { + if (doautomap) { + if (dFlags[nCrawlX][nCrawlY] >= 0) SetAutomapView(nCrawlX, nCrawlY); + dFlags[nCrawlX][nCrawlY] |= BFLAG_AUTOMAP; + } + if (visible) + dFlags[nCrawlX][nCrawlY] |= BFLAG_VISIBLE; + + dFlags[nCrawlX][nCrawlY] |= BFLAG_MONSTACTIVE; + if (!nBlockerFlag) { + v = dTransVal[nCrawlX][nCrawlY]; + if (v != 0) TransList[v] = TRUE; + } + } + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void FreeLightTable() { + DiabloFreePtr(pLightTbl); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitLightTable() +{ + // Palettes for 16 light values + app_assert(! pLightTbl); + pLightTbl = DiabloAllocPtrSig(LIGHTSIZE,'LGTt'); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void MakeLightTable() +{ + int i,j,k,idx,tlen; + BYTE ev,sv; + BYTE *InfraTemp; + BYTE *itp, *pLT; + int x,y; + int rad; + int d; + int a,b; + double ftmp, radiusmod; + + // Palettes for 16 light values + pLT = pLightTbl; + + idx = 0; + if (light4flag) tlen = 3; + else tlen = 15; + for (i = 0; i < tlen; i++) { + *pLT++ = 0; + for (j = 0; j < 8; j++) { + sv = idx + (j * 16); + ev = 15 + (j * 16); + for (k = 0; k < 16; k++) { + if ((k != 0) || (j != 0)) *pLT++ = sv; + if (sv < ev) sv++; + else sv = ev = 0; + } + } + for (j = 16; j < 20; j++) { + sv = (idx >> 1) + (j * 8); + ev = 7 + (j * 8); + for (k = 0; k < 8; k++) { + *pLT++ = sv; + if (sv < ev) sv++; + else sv = ev = 0; + } + } + for (j = 10; j < 16; j++) { + sv = idx + (j * 16); + ev = 15 + (j * 16); + for (k = 0; k < 16; k++) { + *pLT++ = sv; + if (sv < ev) sv++; + else sv = ev = 0; + if (sv == 255) sv = ev = 0; + } + } + if (light4flag) idx += 5; + else idx++; + } + for (j = 0; j < 256; j++) + *pLT++ = 0; + + + // Init fading for blood + if (leveltype == 4) { + byte bloodfadehold[16]; + pLT = pLightTbl; + for (i = 0; i < tlen; i++) { + int d = tlen - i; + int a = tlen / d; + int r = tlen % d; + int tr = d; + int ta = 0; + sv = 1; + bloodfadehold[0] = 0; + for (k = 1; k < 16; k++) { + bloodfadehold[k] = sv; + tr += r; + if ((tr > d) && (k < 15)) { + k++; + tr -= d; + bloodfadehold[k] = sv; + } + ta++; + if (ta == a) { + sv++; + ta = 0; + } + } + *pLT++ = 0; + for (k = 1; k < 16; k++) *pLT++ = bloodfadehold[k]; + for (k = 15; k > 0; k--) *pLT++ = bloodfadehold[k]; + *pLT = 1; + pLT += 225; + } + *pLT++ = 0; + for (j = 1; j < 32; j++) *pLT++ = 1; + pLT += 224; + } + if (currlevel >= HIVESTART) { + pLT = pLightTbl; + for (i = 0; i < tlen; i++) + { + *pLT++ = 0; +// for (j = 1; j < 9; j++) // 16 is the number of rotated colors. JKE + for (j = 1; j < 16; j++) + *pLT++ = j; +// pLT += 247; + pLT += 240; + } + *pLT++ = 0; + for (j = 1; j < 16; j++) *pLT++ = 1; + pLT += 240; + + } + + // Load infra vision table + InfraTemp = LoadFileInMemSig("PlrGFX\\Infra.TRN",NULL,'LGTt'); + itp = InfraTemp; + for (j = 0; j < 256; j++) *pLT++ = *itp++; + DiabloFreePtr(InfraTemp); + + // Load stone curse table + InfraTemp = LoadFileInMemSig("PlrGFX\\Stone.TRN",NULL,'LGTt'); + itp = InfraTemp; + for (j = 0; j < 256; j++) *pLT++ = *itp++; + DiabloFreePtr(InfraTemp); + + // Create pause table + for (j = 0; j < 8; j++) { + for (sv = PAUSEBANDS+2; sv < PAUSEBANDE; sv++) { + if ((j == 0) && (sv == PAUSEBANDS+2)) *pLT++ = 0; + else *pLT++ = sv; + } + *pLT++ = 0; + *pLT++ = 0; + *pLT++ = 0; + } + for (j = 0; j < 4; j++) { + sv = PAUSEBANDS; + for (i = PAUSEBANDS; i < PAUSEBANDE; i+=2) { + *pLT++ = sv; + sv += 2; + } + } + for (j = 0; j < 6; j++) { + for (sv = PAUSEBANDS; sv < PAUSEBANDE; sv++) *pLT++ = sv; + *pLT++ = 0; + } + + // Doron's new smooth light tables + for(rad = 0; rad < 16; rad++) + { + for(i = 0; i < 128; i++) + { + if(i > 8*(rad+1)) + LightLvls[rad][i] = 15; + else + { + ftmp = (double)15*i/((double)8*(rad+1)); + // round + LightLvls[rad][i] = (BYTE)(ftmp + 0.5); + } + } + } +// if (currlevel >= HIVESTART && currlevel < CRYPTSTART) + if (currlevel >= HIVESTART) + { + for(rad = 0; rad < 16; rad++) // avoid divide by zero + { + radiusmod = (sqrt((double)(16 - rad)))/128.0; + radiusmod *= radiusmod; + for(i = 0; i < 128; i++) + { + LightLvls[15-rad][i] = 15 - (BYTE)(radiusmod * (double)((128 - i) * (128 - i))); + if (LightLvls[15-rad][i] > 15) + LightLvls[15-rad][i] = 0; + LightLvls[15-rad][i] = LightLvls[15-rad][i] - (BYTE)((15-rad)/2); + if (LightLvls[15-rad][i] > 15) + LightLvls[15-rad][i] = 0; + } + } + } + // Distance Table + for(j = 0; j < 8; j++) + { + for(i = 0; i < 8; i++) + { + d = i + j*8; + for(y = 0; y < 16; y++) + { + for(x = 0; x < 16; x++) + { + a = (x<<3)-i; + b = (y<<3)-j; + ftmp = (BYTE)sqrt((double)(a*a + b*b)); + // round + ftmp += (ftmp < 0) ? -0.5:0.5; + + Dist[d][x+16*y] = (BYTE)ftmp; + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ResetLight () +{ + if (lightflag == 0) { + FillMemory(dLight,sizeof(dLight),lightmax); + for (int i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (currlevel != plr[i].plrlevel) continue; + DoLighting(plr[i]._px, plr[i]._py, plr[i]._pLightRad, -1); + } + } + else { + ZeroMemory(dLight,sizeof(dLight)); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ToggleLight () +{ + lightflag ^= 1; + if (lightflag == 0) { + CopyMemory(dLight,dSaveLight,sizeof(dLight)); + for (int i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (currlevel != plr[i].plrlevel) continue; + DoLighting(plr[i]._px, plr[i]._py, plr[i]._pLightRad, -1); + } + } + else { + ZeroMemory(dLight,sizeof(dLight)); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitLightMax() +{ + if (light4flag) lightmax = 3; + else lightmax = 15; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitLighting() +{ + int i; + + numlights = 0; + dolighting = FALSE; + lightflag = 0; + for(i = 0; i < MAXLIGHTS; i++) + lightactive[i] = i; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int AddLight(int x, int y, int r) +{ + int lid; + + if (lightflag != 0) return(-1); + lid = -1; + if (numlights < MAXLIGHTS) { + lid = lightactive[numlights++]; + LightList[lid]._lx = x; + LightList[lid]._ly = y; + LightList[lid]._lradius = r; + LightList[lid]._xoff = 0; + LightList[lid]._yoff = 0; + LightList[lid]._ldel = FALSE; + LightList[lid]._lunflag = FALSE; + dolighting = TRUE; + } + return(lid); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddUnLight(int i) +{ + if (lightflag != 0) return; + if (i == -1) return; + + LightList[i]._ldel = TRUE; + dolighting = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ChangeLightRadius(int i, int r) +{ + if (lightflag != 0) return; + if (i == -1) return; + + LightList[i]._lunflag = TRUE; + LightList[i]._lunx = LightList[i]._lx; + LightList[i]._luny = LightList[i]._ly; + LightList[i]._lunr = LightList[i]._lradius; + LightList[i]._lradius = r; + dolighting = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ChangeLightXY(int i, int x, int y) +{ + if (lightflag != 0) return; + if (i == -1) return; + + LightList[i]._lunflag = TRUE; + LightList[i]._lunx = LightList[i]._lx; + LightList[i]._luny = LightList[i]._ly; + LightList[i]._lunr = LightList[i]._lradius; + LightList[i]._lx = x; + LightList[i]._ly = y; + dolighting = TRUE; +} + +/*-----------------------------------------------------------------------* + * + * ChangeLightOff + * + * For increased lighting effect, we specify a position (-8..8,-8..8) + * within each dungeon grid coordinate. This is _xoff and _yoff. +**-----------------------------------------------------------------------*/ +void ChangeLightOff(int i, int x, int y) +{ + if (lightflag != 0) return; + if (i == -1) return; + + LightList[i]._lunflag = TRUE; + LightList[i]._lunx = LightList[i]._lx; + LightList[i]._luny = LightList[i]._ly; + LightList[i]._lunr = LightList[i]._lradius; + LightList[i]._xoff = x; + LightList[i]._yoff = y; + dolighting = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ChangeLight(int i, int x, int y, int r) +{ + if (lightflag != 0) return; + if (i == -1) return; + + LightList[i]._lunflag = TRUE; + LightList[i]._lunx = LightList[i]._lx; + LightList[i]._luny = LightList[i]._ly; + LightList[i]._lunr = LightList[i]._lradius; + LightList[i]._lx = x; + LightList[i]._ly = y; + LightList[i]._lradius = r; + dolighting = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ProcessLightList() +{ + int i,j; + BYTE temp; + + if (lightflag != 0) return; + if (dolighting) { + for (j = 0; j < numlights; j++) { + i = lightactive[j]; + if (LightList[i]._ldel) DoUnLight(LightList[i]._lx, LightList[i]._ly, LightList[i]._lradius); + if (LightList[i]._lunflag) { + DoUnLight(LightList[i]._lunx, LightList[i]._luny, LightList[i]._lunr); + LightList[i]._lunflag = FALSE; + } + } + for (j = 0; j < numlights; j++) { + i = lightactive[j]; + if (!LightList[i]._ldel) + { + DoLighting(LightList[i]._lx, LightList[i]._ly, LightList[i]._lradius, i); + } + } + for (j = 0; j < numlights; ) { + i = lightactive[j]; + if (LightList[i]._ldel) { + temp = lightactive[--numlights]; + lightactive[numlights] = lightactive[j]; + lightactive[j] = temp; + } + else + j++; + } + } + dolighting = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SavePreLighting() +{ + CopyMemory(dSaveLight,dLight,sizeof(dSaveLight)); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitVision() +{ + int i; + + numvision = 0; + dovision = FALSE; + visionid = 1; + + for (i = 0; i < TransVal; i++) TransList[i] = FALSE; + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int AddVision(int x, int y, int r, BOOL mine) +{ + int vid; + + //if (lightflag != 0) return(-1); + if (numvision < MAXVISION) { + VisionList[numvision]._lx = x; + VisionList[numvision]._ly = y; + VisionList[numvision]._lradius = r; + vid = visionid++; + VisionList[numvision]._lid = vid; + VisionList[numvision]._ldel = FALSE; + VisionList[numvision]._lunflag = FALSE; + VisionList[numvision]._lflags = mine ? LFLAG_MINE : 0; + numvision++; + dovision = TRUE; + } + return(vid); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddUnVision(int id) +{ + int i; + + //if (lightflag != 0) return; + for (i = 0; i < numvision; i++) { + if (VisionList[i]._lid == id) { + VisionList[i]._ldel = TRUE; + dovision = TRUE; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ChangeVisionRadius(int id, int r) +{ + int i; + + //if (lightflag != 0) return; + for (i = 0; i < numvision; i++) { + if (VisionList[i]._lid == id) { + VisionList[i]._lunflag = TRUE; + VisionList[i]._lunx = VisionList[i]._lx; + VisionList[i]._luny = VisionList[i]._ly; + VisionList[i]._lunr = VisionList[i]._lradius; + VisionList[i]._lradius = r; + dovision = TRUE; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ChangeVisionXY(int id, int x, int y) +{ + int i; + + //if (lightflag != 0) return; + for (i = 0; i < numvision; i++) { + if (VisionList[i]._lid == id) { + VisionList[i]._lunflag = TRUE; + VisionList[i]._lunx = VisionList[i]._lx; + VisionList[i]._luny = VisionList[i]._ly; + VisionList[i]._lunr = VisionList[i]._lradius; + VisionList[i]._lx = x; + VisionList[i]._ly = y; + dovision = TRUE; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ChangeVision(int id, int x, int y, int r) +{ + int i; + + //if (lightflag != 0) return; + for (i = 0; i < numvision; i++) { + if (VisionList[i]._lid == id) { + VisionList[i]._lunflag = TRUE; + VisionList[i]._lunx = VisionList[i]._lx; + VisionList[i]._luny = VisionList[i]._ly; + VisionList[i]._lunr = VisionList[i]._lradius; + VisionList[i]._lx = x; + VisionList[i]._ly = y; + VisionList[i]._lradius = r; + dovision = TRUE; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ProcessVisionList() +{ + int i; + BOOL delflag; + + //if (lightflag != 0) return; + if (dovision) { + for (i = 0; i < numvision; i++) { + if (VisionList[i]._ldel) DoUnVision(VisionList[i]._lx, VisionList[i]._ly, VisionList[i]._lradius); + if (VisionList[i]._lunflag) { + DoUnVision(VisionList[i]._lunx, VisionList[i]._luny, VisionList[i]._lunr); + VisionList[i]._lunflag = FALSE; + } + } + for (i = 0; i < TransVal; i++) TransList[i] = FALSE; + for (i = 0; i < numvision; i++) + if (!VisionList[i]._ldel) + DoVision(VisionList[i]._lx, VisionList[i]._ly, VisionList[i]._lradius, + VisionList[i]._lflags & LFLAG_MINE, VisionList[i]._lflags & LFLAG_MINE); + do { + delflag = FALSE; + for (i = 0; i < numvision; i++) { + if (VisionList[i]._ldel) { + numvision--; + if ((numvision > 0) && (i != numvision)) VisionList[i] = VisionList[numvision]; + delflag = TRUE; + } + } + } while (delflag); + } + dovision = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void BloodCycle() +{ + int i,k,tlen; + BYTE h; + BYTE *pLT; + + // Cycle the blood + pLT = pLightTbl; + if (light4flag) tlen = 4; + else tlen = 16; + if (leveltype == 4) { + pLT = pLightTbl; + for (i = 0; i < tlen; i++) { + pLT++; + h = *pLT; + for (k = 0; k < 30; k++) { + *pLT = *(pLT+1); + *pLT++; + } + *pLT = h; + pLT += 225; + } + } +} diff --git a/src/LIGHTING.H b/src/LIGHTING.H new file mode 100644 index 0000000..a017b1b --- /dev/null +++ b/src/LIGHTING.H @@ -0,0 +1,132 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/LIGHTING.H 1 1/22/97 2:06p Dgartner $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define LIGHTSIZE 27*256 + +#define MAXLIGHTS 32 +#define MAXVISION 32 +#define MAXTRANS 32 + +#define PLRLRAD 10 // Player light radius +#define PLRVRAD 10 // Player vision radius + +#define HALF_T 1 +#define HALF_B 2 +#define HALF_R 3 +#define HALF_L 4 +#define QTR_UR 5 +#define QTR_LR 6 +#define QTR_UL 7 +#define QTR_LL 8 +#define VERT_T 9 +#define VERT_B 10 +#define VERT_LINE 11 +#define HORT_L 12 +#define HORT_R 13 +#define HORT_LINE 14 +#define SELF 15 +#define WHOLE 16 +#define NEG_WHOLE 17 + +#define LIGHT_NORM 0 // Normal lighting +#define LIGHT_INFRA 1 // Infravision +#define LIGHT_STONE 2 // Stone curse +#define LIGHT_GREY 3 // Pause & death +#define LIGHT_U 4 // Unique monster transform 3-11 + +#define LFLAG_MINE 1 // whether or not my player is the source + // (used in ProcessVision) + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + int _lx; + int _ly; + int _lradius; + int _lid; + BOOL _ldel; + BOOL _lunflag; + BOOL _lneg; + int _lunx; + int _luny; + int _lunr; + int _xoff; + int _yoff; + BOOL _lflags; +} LightListStruct; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern int lightflag; +extern BYTE vCrawlTable[23][30]; +extern BYTE RadiusAdj[23]; +//extern int CrawlTable[2061]; +extern char CrawlTable[2749]; +extern char * pCrawlEntry[19]; + +extern LightListStruct LightList[MAXLIGHTS]; +extern BYTE lightactive[MAXLIGHTS]; +extern int numlights; +extern BOOL dolighting; +extern "C" { + extern char lightmax; + extern BYTE *pLightTbl; +} +extern LightListStruct VisionList[MAXVISION]; +extern int numvision; +extern BOOL dovision; +extern int visionid; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void DoLighting (int, int, int, int); +void DoUnLight (int, int, int); + +void InitLighting(); +void InitLightMax(); +int AddLight(int, int, int); +void AddUnLight(int); +void ChangeLightRadius(int, int); +void ChangeLightXY(int, int, int); +void ChangeLight(int, int, int, int); +void ChangeLightOff(int id, int x, int y); +void ProcessLightList(); + +void SavePreLighting(); + +void DoVision (int, int, int, BOOL, BOOL); +void DoUnVision (int, int, int); + +void InitVision(); +int AddVision(int, int, int, BOOL); +void AddUnVision(int); +void ChangeVisionRadius(int, int); +void ChangeVisionXY(int, int, int); +void ChangeVision(int, int, int, int); +void ProcessVisionList(); + +void ResetLight(); +void ToggleLight(); + +void InitLightTable(); +void MakeLightTable(); +void FreeLightTable(); + +void BloodCycle(); diff --git a/src/LOADSAVE.CPP b/src/LOADSAVE.CPP new file mode 100644 index 0000000..eefb76f --- /dev/null +++ b/src/LOADSAVE.CPP @@ -0,0 +1,768 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Game Menu file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/LOADSAVE.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include +#include "sound.h" +#include "engine.h" +#include "gendung.h" +#include "palette.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "dead.h" +#include "objects.h" +#include "spells.h" +#include "missiles.h" +#include "quests.h" +#include "trigs.h" +#include "lighting.h" +#include "control.h" +#include "inv.h" +#include "interfac.h" +#include "town.h" +#include "stores.h" +#include "cursor.h" +#include "automap.h" +#include "multi.h" +#include "doom.h" +#include "portal.h" + +/*-----------------------------------------------------------------------* +** extern +**-----------------------------------------------------------------------*/ +DWORD CalcEncodeDstBytes(DWORD dwSrcBytes); +void CreateSaveLevelName(char szName[MAX_PATH]); +void CreateLoadLevelName(char szName[MAX_PATH]); +void CreateSaveGameName(char szName[MAX_PATH]); +void WriteSaveFile(const char * pszName,BYTE * pbData,DWORD dwLen,DWORD dwEncodeLen); +BYTE * ReadSaveFile(const char * pszName,DWORD * pdwLen); +void SyncPlrAnim(int); +void DestroyTempSaves(); +void MoveTempSavesToPermanent(); +void RedoPlayerVision(); + + +/*-----------------------------------------------------------------------* +** private +**-----------------------------------------------------------------------*/ +// Save only these bits in the dFlags +#define BFLAG_SAVEMASK (BFLAG_AUTOMAP | BFLAG_VISIBLE | BFLAG_PLRLR | BFLAG_MONSTLR | BFLAG_SETPC) + +// save file buffer size +#define FILEBUFF 362147 + +// pointer into save file buffer +static BYTE *tbuff; + +#define SHAREWARE_ID 'SHAR' +#define BETA_ID 'BETA' +#define RETAIL_ID 'RETL' +#define HELLFIRE_ID 'HELF' + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static char BLoad() { + return *tbuff++; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int ILoad() { + int rv; + // drb old because we used to think ints were 16 bit +/* if ((*tbuff & 0x80) != 0) rv = -1 & 0xffff0000; + else rv = 0; + rv |= *tbuff++ << 8; + rv |= *tbuff++;*/ + rv = *tbuff++ << 24; + rv |= *tbuff++ << 16; + rv |= *tbuff++ << 8; + rv |= *tbuff++; + return(rv); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static long LLoad() { + long rv; + + rv = *tbuff++ << 24; + rv |= *tbuff++ << 16; + rv |= *tbuff++ << 8; + rv |= *tbuff++; + return(rv); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL OLoad() { + if (*tbuff++ == 1) return(TRUE); + else return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadPlr(int i) { + memcpy(&plr[i], tbuff, SAVE_PLAYER_SIZE); + tbuff += SAVE_PLAYER_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadMonst(int i) { + memcpy(&monster[i], tbuff, SAVE_MONSTER_SIZE); + tbuff += SAVE_MONSTER_SIZE; + SyncMonsterAnim(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadMissile(int i) { + memcpy(&missile[i], tbuff, SAVE_MISSILE_SIZE); + tbuff += SAVE_MISSILE_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadSpell(int i) { + tbuff += 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadObject(int i) { + memcpy(&object[i], tbuff, SAVE_OBJECT_SIZE); + tbuff += SAVE_OBJECT_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadItem(int i) { + memcpy(&item[i], tbuff, SAVE_ITEM_SIZE); + tbuff += SAVE_ITEM_SIZE; + SyncItemAnim(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadPremium(int i) { + memcpy(&premiumitem[i], tbuff, SAVE_ITEM_SIZE); + tbuff += SAVE_ITEM_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadQuest(int i) { + memcpy(&quests[i], tbuff, SAVE_QUEST_SIZE); + tbuff += SAVE_QUEST_SIZE; + + // where to go back to + ReturnLvlX = ILoad(); + ReturnLvlY = ILoad(); + ReturnLvl = ILoad(); + ReturnLvlT = ILoad(); + + // Map of doom + doomtime = ILoad(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadLight(int i) { + memcpy(&LightList[i], tbuff, sizeof(LightListStruct)); + tbuff += sizeof(LightListStruct); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadVision(int i) { + memcpy(&VisionList[i], tbuff, sizeof(LightListStruct)); + tbuff += sizeof(LightListStruct); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void LoadPortal(int i) { + memcpy(&portal[i], tbuff, sizeof(PortalStruct)); + tbuff += sizeof(PortalStruct); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GM_LoadGame(BOOL firstflag) { +#if !IS_VERSION(BETA) + int i,j; + int hvx, hvy; + int hnummonsters, hnumitems, hnummissiles, hnumobjects; + + app_assert(gbMaxPlayers == 1); + FreeGameMem(); + + // since we are loading an existing game, any temporary + // save files which were created can be removed + DestroyTempSaves(); + + DWORD dwLen; + char szName[MAX_PATH]; + CreateSaveGameName(szName); + BYTE *LoadBuff = ReadSaveFile(szName,&dwLen); + tbuff = LoadBuff; + + DWORD dwVersion = LLoad(); + #if IS_VERSION(SHAREWARE) + if (dwVersion != SHAREWARE_ID) app_fatal("Invalid save file"); + #elif IS_VERSION(BETA) + if (dwVersion != BETA_ID) app_fatal("Invalid save file"); + #elif IS_VERSION(RETAIL) + //if (dwVersion != RETAIL_ID) app_fatal("Invalid save file"); + if (dwVersion != HELLFIRE_ID) app_fatal("Invalid save file"); + #else + #error No version defined + #endif + + setlevel = OLoad(); + setlvlnum = ILoad(); + currlevel = ILoad(); + leveltype = ILoad(); + hvx = ILoad(); + hvy = ILoad(); + invflag = OLoad(); + chrflag = OLoad(); + hnummonsters = ILoad(); + hnumitems = ILoad(); + hnummissiles = ILoad(); + hnumobjects = ILoad(); + + for (i = 0; i < NUMLEVELS; i++) { + glSeedTbl[i] = LLoad(); + gnLevelTypeTbl[i] = ILoad(); + } + + // Load player info + LoadPlr(myplr); + gnDifficulty = plr[myplr]._gnDifficulty; + if (gnDifficulty < D_NORMAL || gnDifficulty > D_HELL) + gnDifficulty = D_NORMAL; + + // Load quest info + for (i = 0; i < MAXQUESTS; i++) LoadQuest(i); + + // Load town portal info + for (i = 0; i < MAXPORTAL; i++) LoadPortal(i); + + LoadGameLevel(firstflag, LVL_NODIR); + + SyncInitPlr(myplr); + SyncPlrAnim(myplr); + + ViewX = hvx; + ViewY = hvy; + nummonsters = hnummonsters; + numitems = hnumitems; + nummissiles = hnummissiles; + numobjects = hnumobjects; + + for (i = 0; i < MONSTERTYPES; i++) monstkills[i] = LLoad(); + + if (leveltype != 0) { + // Load monster block + for (i = 0; i < MAXMONSTERS; i++) monstactive[i] = ILoad(); + for (i = 0; i < nummonsters; i++) LoadMonst(monstactive[i]); + // Load missile block + for (i = 0; i < MAXMISSILES; i++) missileactive[i] = BLoad(); + for (i = 0; i < MAXMISSILES; i++) missileavail[i] = BLoad(); + for (i = 0; i < nummissiles; i++) LoadMissile(missileactive[i]); + // Load object block + for (i = 0; i < MAXOBJECTS; i++) objectactive[i] = BLoad(); + for (i = 0; i < MAXOBJECTS; i++) objectavail[i] = BLoad(); + for (i = 0; i < numobjects; i++) LoadObject(objectactive[i]); + for (i = 0; i < numobjects; i++) SyncObjectAnim(objectactive[i]); + // Load light and vision + numlights = ILoad(); + for (i = 0; i < MAXLIGHTS; i++) lightactive[i] = BLoad(); + for (i = 0; i < numlights; i++) LoadLight(lightactive[i]); + visionid = ILoad(); + numvision = ILoad(); + for (i = 0; i < numvision; i++) LoadVision(i); + } + // Load item block + for (i = 0; i < MAXITEMS; i++) itemactive[i] = BLoad(); + for (i = 0; i < MAXITEMS; i++) itemavail[i] = BLoad(); + for (i = 0; i < numitems; i++) LoadItem(itemactive[i]); + for (i = 0; i < MAXUITEMS; i++) UniqueItemFlag[i] = OLoad(); + + // Load map info + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dLight[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dFlags[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dPlayer[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dItem[i][j] = BLoad(); + + if (leveltype != 0) { + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dMonster[i][j] = ILoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dDead[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dObject[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dLight[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dSaveLight[i][j] = BLoad(); + for (j = 0; j < AUTOMAPY; j++) + for (i = 0; i < AUTOMAPX; i++) automapview[i][j] = OLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dMissile[i][j] = BLoad(); + } + + numpremium = ILoad(); + premiumlevel = ILoad(); + for (i = 0; i < MAXPREMIUM; i++) LoadPremium(i); + + automapflag = OLoad(); + automapscale = ILoad(); + + DiabloFreePtr(LoadBuff); + + // Misc sync routines + SyncAutomap(); + ResyncQuests(); + if (leveltype) + ProcessLightList(); + RedoPlayerVision(); + ProcessVisionList(); + SyncMissAnim(); + + ResetPal(); + SetCursor(GLOVE_CURS); + gbProcessPlayers = TRUE; +#endif +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void BSave(char v) { + *tbuff++ = v; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void ISave(int v) { + // Changed because we used to thing ints were 16 bit, but they are 32 +/* *tbuff++ = (char) (v >> 8); + *tbuff++ = (char) v;*/ + *tbuff++ = (char) (v >> 24); + *tbuff++ = (char) (v >> 16); + *tbuff++ = (char) (v >> 8); + *tbuff++ = (char) (v >> 0); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void LSave(long v) { + *tbuff++ = (char) (v >> 24); + *tbuff++ = (char) (v >> 16); + *tbuff++ = (char) (v >> 8); + *tbuff++ = (char) (v >> 0); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void OSave(BOOL v) { + if (v) *tbuff++ = 1; + else *tbuff++ = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SavePlr(int i) { + memcpy(tbuff, &plr[i], SAVE_PLAYER_SIZE); + tbuff += SAVE_PLAYER_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SaveMonst(int i) { + memcpy(tbuff, &monster[i], SAVE_MONSTER_SIZE); + tbuff += SAVE_MONSTER_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SaveMissile(int i) { + memcpy(tbuff, &missile[i], SAVE_MISSILE_SIZE); + tbuff += SAVE_MISSILE_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SaveSpell(int i) { + tbuff += 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SaveObject(int i) { + memcpy(tbuff, &object[i], SAVE_OBJECT_SIZE); + tbuff += SAVE_OBJECT_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SaveItem(int i) { + memcpy(tbuff, &item[i], SAVE_ITEM_SIZE); + tbuff += SAVE_ITEM_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SavePremium(int i) { + memcpy(tbuff, &premiumitem[i], SAVE_ITEM_SIZE); + tbuff += SAVE_ITEM_SIZE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SaveQuest(int i) { + memcpy(tbuff, &quests[i], SAVE_QUEST_SIZE); + tbuff += SAVE_QUEST_SIZE; + ISave(ReturnLvlX); + ISave(ReturnLvlY); + ISave(ReturnLvl); + ISave(ReturnLvlT); + ISave(doomtime); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SaveLight(int i) { + memcpy(tbuff, &LightList[i], sizeof(LightListStruct)); + tbuff += sizeof(LightListStruct); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SaveVision(int i) { + memcpy(tbuff, &VisionList[i], sizeof(LightListStruct)); + tbuff += sizeof(LightListStruct); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void SavePortal(int i) { + memcpy(tbuff, &portal[i], sizeof(PortalStruct)); + tbuff += sizeof(PortalStruct); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GM_SaveGame() { +#if !IS_VERSION(BETA) + BYTE *SaveBuff; + int i,j; + + // allocate a ptr large enough for save file + encode data + app_assert(gbMaxPlayers == 1); + SaveBuff = DiabloAllocPtrSig(CalcEncodeDstBytes(FILEBUFF),'SAVt'); + tbuff = SaveBuff; + + #if IS_VERSION(SHAREWARE) + LSave(SHAREWARE_ID); + #elif IS_VERSION(BETA) + LSave(BETA_ID); + #elif IS_VERSION(RETAIL) + //LSave(RETAIL_ID); + LSave(HELLFIRE_ID); + #else + #error No version defined + #endif + + OSave(setlevel); + ISave(setlvlnum); + ISave(currlevel); + ISave(leveltype); + ISave(ViewX); + ISave(ViewY); + OSave(invflag); + OSave(chrflag); + ISave(nummonsters); + ISave(numitems); + ISave(nummissiles); + ISave(numobjects); + + for (i = 0; i < NUMLEVELS; i++) { + LSave(glSeedTbl[i]); + ISave(gnLevelTypeTbl[i]); + } + + // Save player info + plr[myplr]._gnDifficulty = gnDifficulty; + SavePlr(myplr); + + // Save quest info + for (i = 0; i < MAXQUESTS; i++) SaveQuest(i); + + // Save town portal info + for (i = 0; i < MAXPORTAL; i++) SavePortal(i); + + for (i = 0; i < MONSTERTYPES; i++) LSave(monstkills[i]); + + if (leveltype != 0) { + // Save monster block + for (i = 0; i < MAXMONSTERS; i++) ISave(monstactive[i]); + for (i = 0; i < nummonsters; i++) SaveMonst(monstactive[i]); + // Save missile block + for (i = 0; i < MAXMISSILES; i++) BSave(missileactive[i]); + for (i = 0; i < MAXMISSILES; i++) BSave(missileavail[i]); + for (i = 0; i < nummissiles; i++) SaveMissile(missileactive[i]); + // Save object block + for (i = 0; i < MAXOBJECTS; i++) BSave(objectactive[i]); + for (i = 0; i < MAXOBJECTS; i++) BSave(objectavail[i]); + for (i = 0; i < numobjects; i++) SaveObject(objectactive[i]); + // Save light and vision + ISave(numlights); + for (i = 0; i < MAXLIGHTS; i++) BSave(lightactive[i]); + for (i = 0; i < numlights; i++) SaveLight(lightactive[i]); + ISave(visionid); + ISave(numvision); + for (i = 0; i < numvision; i++) SaveVision(i); + } + // Save item block + for (i = 0; i < MAXITEMS; i++) BSave(itemactive[i]); + for (i = 0; i < MAXITEMS; i++) BSave(itemavail[i]); + for (i = 0; i < numitems; i++) SaveItem(itemactive[i]); + for (i = 0; i < MAXUITEMS; i++) OSave(UniqueItemFlag[i]); + + // Save map info + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dLight[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dFlags[i][j] & BFLAG_SAVEMASK); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dPlayer[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dItem[i][j]); + + if (leveltype != 0) { + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) ISave(dMonster[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dDead[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dObject[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dLight[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dSaveLight[i][j]); + for (j = 0; j < AUTOMAPY; j++) + for (i = 0; i < AUTOMAPX; i++) OSave(automapview[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dMissile[i][j]); + } + ISave(numpremium); + ISave(premiumlevel); + for (i = 0; i < MAXPREMIUM; i++) SavePremium(i); + + OSave(automapflag); + ISave(automapscale); + + char szName[MAX_PATH]; + CreateSaveGameName(szName); + + // when we allocated SaveBuff, we made sure to include enough + // bytes for the encryption information + WriteSaveFile( + szName, + SaveBuff, + tbuff - SaveBuff, + CalcEncodeDstBytes(tbuff - SaveBuff) + ); + + DiabloFreePtr(SaveBuff); + gbValidSaveFile = TRUE; + + // take all the temporary save files which have accumulated + // during the course of gameplay and make them part of the + // permanent save game + MoveTempSavesToPermanent(); + + void UpdatePlayerFile(); + UpdatePlayerFile(); +#endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SaveLevel() +{ +#if !IS_VERSION(BETA) + BYTE *SaveBuff; + int i,j; + + // make sure this code doesn't get called in multiplayer + // or everyone will have different results... + app_assert(gbMaxPlayers == 1); + if (currlevel == 0) glSeedTbl[0] = GetRndSeed(); + + // allocate a ptr large enough for save file + encode data + SaveBuff = DiabloAllocPtrSig(CalcEncodeDstBytes(FILEBUFF),'SAVt'); + tbuff = SaveBuff; + + // Moved here to sync dead unique monsters drb 12/15 + if (leveltype != 0) { + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dDead[i][j]); + } + + ISave(nummonsters); + ISave(numitems); + ISave(numobjects); + + if (leveltype != 0) { + // Save monster block + for (i = 0; i < MAXMONSTERS; i++) ISave(monstactive[i]); + for (i = 0; i < nummonsters; i++) SaveMonst(monstactive[i]); + // Save object block + for (i = 0; i < MAXOBJECTS; i++) BSave(objectactive[i]); + for (i = 0; i < MAXOBJECTS; i++) BSave(objectavail[i]); + for (i = 0; i < numobjects; i++) SaveObject(objectactive[i]); + } + // Save item block + for (i = 0; i < MAXITEMS; i++) BSave(itemactive[i]); + for (i = 0; i < MAXITEMS; i++) BSave(itemavail[i]); + for (i = 0; i < numitems; i++) SaveItem(itemactive[i]); + + // Save map info + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) + BSave(dFlags[i][j] & BFLAG_SAVEMASK); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dItem[i][j]); + + if (leveltype != 0) { + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) ISave(dMonster[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dObject[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dLight[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dSaveLight[i][j]); + for (j = 0; j < AUTOMAPY; j++) + for (i = 0; i < AUTOMAPX; i++) OSave(automapview[i][j]); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) BSave(dMissile[i][j]); + } + + app_assert(FILEBUFF >= tbuff - SaveBuff); + char szName[MAX_PATH]; + CreateSaveLevelName(szName); + + // when we allocated SaveBuff, we made sure to include enough + // bytes for the encryption information + WriteSaveFile( + szName, + SaveBuff, + tbuff - SaveBuff, + CalcEncodeDstBytes(tbuff - SaveBuff) + ); + + DiabloFreePtr(SaveBuff); + if (!setlevel) plr[myplr]._pLvlVisited[currlevel] = TRUE; + else plr[myplr]._pSLvlVisited[setlvlnum] = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void LoadLevel() { +#if !IS_VERSION(BETA) + int i,j; + + DWORD LoadSize; + char szName[MAX_PATH]; + CreateLoadLevelName(szName); + BYTE * LoadBuff = ReadSaveFile(szName,&LoadSize); + tbuff = LoadBuff; + + if (leveltype != 0) { + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dDead[i][j] = BLoad(); + SyncUniqDead(); + } + + nummonsters = ILoad(); + numitems = ILoad(); + numobjects = ILoad(); + + if (leveltype != 0) { + // Load monster block + for (i = 0; i < MAXMONSTERS; i++) monstactive[i] = ILoad(); + for (i = 0; i < nummonsters; i++) LoadMonst(monstactive[i]); + // Load object block + for (i = 0; i < MAXOBJECTS; i++) objectactive[i] = BLoad(); + for (i = 0; i < MAXOBJECTS; i++) objectavail[i] = BLoad(); + for (i = 0; i < numobjects; i++) LoadObject(objectactive[i]); + for (i = 0; i < numobjects; i++) SyncObjectAnim(objectactive[i]); + } + // Load item block + for (i = 0; i < MAXITEMS; i++) itemactive[i] = BLoad(); + for (i = 0; i < MAXITEMS; i++) itemavail[i] = BLoad(); + for (i = 0; i < numitems; i++) LoadItem(itemactive[i]); + + // Load map info + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dFlags[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dItem[i][j] = BLoad(); + + if (leveltype != 0) { + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dMonster[i][j] = ILoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dObject[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dLight[i][j] = BLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dSaveLight[i][j] = BLoad(); + for (j = 0; j < AUTOMAPY; j++) + for (i = 0; i < AUTOMAPX; i++) automapview[i][j] = OLoad(); + for (j = 0; j < MAXDUNY; j++) + for (i = 0; i < MAXDUNX; i++) dMissile[i][j] = 0; + } + + // Misc sync routines + SyncAutomap(); + ResyncQuests(); + SyncPortals(); + + // player lighting needs to be reset because players enter level at different + // location than where they leave + dolighting = TRUE; + for (i = 0; i < MAX_PLRS; i++) { + if (plr[i].plractive && currlevel == plr[i].plrlevel) + LightList[plr[i]._plid]._lunflag = TRUE; + } + + DiabloFreePtr(LoadBuff); +#endif +} diff --git a/src/MAINMENU.CPP b/src/MAINMENU.CPP new file mode 100644 index 0000000..5504ca9 --- /dev/null +++ b/src/MAINMENU.CPP @@ -0,0 +1,203 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Main Menu +** +** (C)1996 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MAINMENU.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "diabloui.h" +#include "items.h" +#include "gendung.h" +#include "player.h" +#include "multi.h" +#include "sound.h" + + +/*-----------------------------------------------------------------------** +// externs +**-----------------------------------------------------------------------*/ +extern char gszPrintVersion[]; +void CALLBACK menusnd_play(LPBYTE lpWave); +BOOL CALLBACK UiEnumHeroes(ENUMHEROPROC enumproc); +BOOL CALLBACK UiCreateHero(TPUIHEROINFO heroinfo); +BOOL CALLBACK UiDeleteHero(TPUIHEROINFO heroinfo); +BOOL CALLBACK UiGetDefaultCharStats(int heroclass, TPUIDEFSTATS defaultstats); +void CALLBACK menusnd_play(LPCSTR pszFile); +void play_movie(const char * pszMovie,BOOL bAllowCancel); +BOOL StartGame(BOOL bNewGame,BOOL bSinglePlayer); +extern DWORD gbWalkOn; +extern const char *sgszWalkId; +extern char gszProgKey[]; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define PIXELS_PER_SEC 16 + +char gszHero[MAX_NAME_LEN]; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void menu_music() { + static int snMusic = MUSIC_INTRO; + music_start(snMusic); + +#if !IS_VERSION(SHAREWARE) + // look for a music track which is not the town, cause it's + // too wimpy for initial theme music, and is not l1, cause the + // players will hear waaaay too much of l1 music + do { + snMusic++; // next track + if (snMusic == NUM_MUSIC) snMusic = 0; // handle wrap + } while (snMusic == MUSIC_TOWN || snMusic == MUSIC_L1); +#endif +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL do_menu(DWORD selection) { + if (selection == SELHERO_PREVIOUS) + return TRUE; + + music_stop(); + + BOOL bResult = StartGame( + selection != SELHERO_CONTINUE, // new game ? + selection != SELHERO_CONNECT // single player game ? + ); + + if (bResult) menu_music(); + return bResult; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL DoSinglePlayer() { + while (1) { + gbMaxPlayers = 1; + DWORD selection = 0; + + if (!SRegLoadValue( gszProgKey,sgszWalkId,0,&gbWalkOn)) + { + gbWalkOn = TRUE; + } + + if (! UiSelHeroSingDialog( + UiEnumHeroes, + UiCreateHero, + UiDeleteHero, + UiGetDefaultCharStats, + &selection, + gszHero, + &gnDifficulty, + gbAllowBard, + gbAllowBarbarian + )) app_fatal(TEXT("Unable to display SelHeroSing")); + + if (selection == SELHERO_PREVIOUS) + return TRUE; + if (! do_menu(selection)) + return FALSE; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL DoMultiPlayer() { + while (1) { + gbMaxPlayers = MAX_PLRS; + DWORD selection = 0; + gbWalkOn = FALSE; + if (! UiSelHeroMultDialog( + UiEnumHeroes, + UiCreateHero, + UiDeleteHero, + UiGetDefaultCharStats, + &selection, + gszHero, + gbAllowBard, + gbAllowBarbarian + )) app_fatal(TEXT("Can't load multiplayer dialog")); + + if (selection == SELHERO_PREVIOUS) + return TRUE; + if (! do_menu(selection)) + return FALSE; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static void play_intro() { + music_stop(); + play_movie("gendata\\Hellfire.smk",TRUE); + menu_music(); +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DiabloMenu() { + menu_music(); + + BOOL bDone = FALSE; + while (! bDone) { + DWORD selection = 0; + if (! UiMainMenuDialog(gszPrintVersion, + &selection, + gbAllowMultiPlayer, + menusnd_play)) + app_fatal(TEXT("Unable to display mainmenu")); + + switch (selection) { + case MAINMENU_SINGLE_PLAYER: + #if IS_VERSION(BETA) + app_warning("Not available in beta version"); + #else + if (! DoSinglePlayer()) bDone = TRUE; + #endif + break; + + case MAINMENU_MULTIPLAYER: + if (! DoMultiPlayer()) bDone = TRUE; + break; + + case MAINMENU_ATTRACT_MODE: + // it crashes after 20 minutes, so stop doing this. + + break; + case MAINMENU_REPLAY_INTRO: + if (! bActive) break; + #if !IS_VERSION(SHAREWARE) + play_intro(); + #endif + break; + + case MAINMENU_SHOW_CREDITS: + UiCreditsDialog(PIXELS_PER_SEC); + break; + + case MAINMENU_SUPPORT: + UiSupportDialog(PIXELS_PER_SEC); + break; + + case MAINMENU_EXIT_DIABLO: + bDone = TRUE; + break; + } + } + + music_stop(); +} diff --git a/src/MAINMENU.H b/src/MAINMENU.H new file mode 100644 index 0000000..4fe0ea3 --- /dev/null +++ b/src/MAINMENU.H @@ -0,0 +1,19 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1996 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/MAINMENU.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void DiabloMenu(); diff --git a/src/MINITEXT.CPP b/src/MINITEXT.CPP new file mode 100644 index 0000000..d8cc054 --- /dev/null +++ b/src/MINITEXT.CPP @@ -0,0 +1,287 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Miniquest Text file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "minitext.h" +#include "textdat.h" +#include "engine.h" +#include "scrollrt.h" +#include "quests.h" +#include "effects.h" +#include "items.h" +#include "gendung.h" + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define KERNSPACE 2 + +static const BYTE qfonttrans[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 0, 37, 49, 38, 0, 39, 40, 47, 42, 43, 41, 45, 52, 44, 53, 55, // 32-47 + 36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 51, 50, 48, 46, 49, 54, // 48-63 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 64-79 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 0, 43, 0, 0, // 80-95 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 96-111 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 48, 0, 49, 0, 0 }; // 112-127 + +/*char qfontkern[56] = { 8, // Space/Invalid + 24, 16, 19, 20, 15, 15, 19, 18, 8, 8, 18, 14, 24, 20, 23, 15, // a-p + 24, 20, 16, 21, 24, 25, 32, 24, 25, 18, // q-z + 8, 16, 17, 17, 16, 16, 17, 16, 16, 24, // 1-0 + 8, 15, 26, 23, 13, 9, 8, 10, 13, 12, 8, 15, 15, 8, 8, 8, 8, 16, 17 }; // misc */ + +static const BYTE qfontkern[56] = { 5, // Space/Invalid + 15, 10, 13, 14, 10, 9, 13, 11, 5, 5, 11, 10, 16, 13, 16, 10, // a-p + 15, 12, 10, 14, 17, 17, 22, 17, 16, 11, // q-z + 5, 11, 11, 11, 10, 11, 11, 11, 11, 15, // 1-0 + 5, 10, 18, 15, 8, 6, 6, 7, 10, 9, 6, 10, 10, 5, 5, 5, 5, 11, 12 }; // misc + +BYTE qtextflag; +static BYTE *pMedTextCels; +static BYTE *pTextBoxCels; +static const char *qtextptr; +static int qtexty; +int qtextSpd; +static int qtextDelay; +static DWORD sgLastScroll; + +//Quest text scrolling rate 1 = slowest, 5 = normal, 9 = fastest +int qtextDelaySpd[10] = { 2, 4, 6, 8, 0, -1, -2, -3, -4 }; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#define MQTEXTX1 112 +#define MQTEXTY1 241 +#define MQTEXTW 543 +#define MQTEXTY2 469 +#define MQTEXTNL 38 + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreeQuestText() { + DiabloFreePtr(pMedTextCels); + DiabloFreePtr(pTextBoxCels); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitQuestText() { + app_assert(! pMedTextCels); + pMedTextCels = LoadFileInMemSig("Data\\MedTextS.CEL",NULL,'MINI'); + pTextBoxCels = LoadFileInMemSig("Data\\TextBox.CEL",NULL,'MINI'); + qtextflag = FALSE; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitQTextMsg(int m) { + app_assert((DWORD) m < gdwAllTextEntries); + if (alltext[m].scrlltxt) + { + questlog = FALSE; + qtextflag = TRUE; + qtextptr = alltext[m].txtstr; + qtexty = MQTEXTY2 + 31; + qtextSpd = qtextDelaySpd[alltext[m].txtspd-1]; + qtextDelay = qtextSpd; + sgLastScroll = GetTickCount(); + #if CHEATS + if ((currlevel == 0) && (davecheat)) { + qtextSpd = qtextDelaySpd[tstQMsgSpd-1]; + qtextDelay = qtextSpd; + } + #endif + } + PlaySFX(alltext[m].sfxnr); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DrawQTextBack() +{ + DrawCel(88, 487, pTextBoxCels, 1, 591); + app_assert(gpBuffer); + __asm { + mov edi,dword ptr [gpBuffer] + add edi,371803 + + xor eax,eax + mov edx,148 +_YLp: mov ecx,292 +_XLp1: stosb + inc edi + loop _XLp1 + stosb + sub edi,1353 + mov ecx,292 +_XLp2: inc edi + stosb + loop _XLp2 + sub edi,1352 + dec edx + jnz _YLp + mov ecx,292 +_XLp3: stosb + inc edi + loop _XLp3 + stosb + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawQTextCel (long xp, long yp, BYTE *pCelBuff, long nCel) +{ + BYTE *pTo, *pY1, *pY2; + long RLELen; + + app_assert(gpBuffer); + pTo = gpBuffer + nBuffWTbl[yp] + xp; + pY1 = gpBuffer + nBuffWTbl[MQTEXTY1-32]; + pY2 = gpBuffer + nBuffWTbl[MQTEXTY2]; + __asm { + mov ebx,dword ptr [pCelBuff] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] + sub eax,dword ptr [ebx] + mov dword ptr [RLELen],eax + + mov esi,dword ptr [pCelBuff] + add esi,dword ptr [ebx] + + mov edi,dword ptr [pTo] // Dest + + mov ebx,dword ptr [RLELen] + add ebx,esi + +_T1Lp1: mov edx,22 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [pY1] + jb _T1C + cmp edi,dword ptr [pY2] + ja _T1C + mov ecx,eax + shr ecx,1 + jnc _T1w + movsb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + movsw + jecxz _T1x +_T1Lp3: rep movsd + jmp _T1x +_T1C: add esi,eax + add edi,eax +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,790 + cmp ebx,esi + jnz _T1Lp1 + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawQText() +{ + const char *p, *pt, *pnl; + char tempstr[128]; + int tx, ty; + int l, i; + BOOL doneflag; + + DrawQTextBack(); + + p = qtextptr; + pnl = NULL; + tx = MQTEXTX1; + ty = qtexty; + + doneflag = FALSE; + while (!doneflag) { + l = 0; + pt = p; + for (i = 0; (*pt != '\n') && (*pt != '|') && (l < MQTEXTW); i++) { + BYTE c = char2print(*pt++); + if (c != 0) { + tempstr[i] = c; + c = qfonttrans[c]; + l += qfontkern[c] + KERNSPACE; + } else i--; + } + tempstr[i] = 0; + if (*pt == '|') { + tempstr[i] = 0; + doneflag = TRUE; + } else if (*pt == '\n') { + pt++; + } else while ((tempstr[i] != ' ') && (i > 0)) { + tempstr[i] = 0; + i--; + } + for (i = 0; tempstr[i] != 0; i++) { + BYTE c = char2print(tempstr[i]); + c = qfonttrans[c]; + // while (*p == 0) p++; <<< this look awfully dangerous -- pat + p++; + if (*p == '\n') p++; + if (c != 0) DrawQTextCel(tx, ty, pMedTextCels, c); + tx += qfontkern[c] + KERNSPACE; + } + if (pnl == NULL) pnl = p; + tx = MQTEXTX1; + ty += MQTEXTNL; + if (ty > (MQTEXTY2+32)) doneflag = TRUE; + } + + //Delay for text scrolling + DWORD currTime = GetTickCount(); + do { + if (qtextSpd <= 0) { //Go faster + qtexty--; + qtexty += qtextSpd; + } else { //Go slower + qtextDelay--; + if (qtextDelay != 0) qtexty--; + } + if (qtextDelay == 0) qtextDelay = qtextSpd; + + if (qtexty <= (MQTEXTY1-32)) { + qtexty += MQTEXTNL; + qtextptr = pnl; + if (*qtextptr == '|') qtextflag = FALSE; // done? + break; + } + sgLastScroll += 1000/GAME_FRAMES_PER_SECOND; + } while (currTime-sgLastScroll < 0x7FFFFFFF); +} + diff --git a/src/MINITEXT.H b/src/MINITEXT.H new file mode 100644 index 0000000..732e993 --- /dev/null +++ b/src/MINITEXT.H @@ -0,0 +1,43 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/MINITEXT.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + char *txtstr; // String to be called + BOOL scrlltxt; // will text scroll ? + BOOL txtspd; // text speed + int sfxnr; // Sound effect to be called +} TextDataStruct; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern BYTE qtextflag; +extern int qtextSpd; +extern int qtextDelaySpd[10]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +void InitQuestText(); +void DrawQText(); +void FreeQuestText(); + +void InitQTextMsg(int); + +void DrawQTextBack(); + diff --git a/src/MISDAT.CPP b/src/MISDAT.CPP new file mode 100644 index 0000000..b8be083 --- /dev/null +++ b/src/MISDAT.CPP @@ -0,0 +1,1886 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Missiles data file +** +** (C)1996 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MISDAT.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "effects.h" +#include "missiles.h" +#include "misdat.h" + +void AddLArrow(int, int, int, int, int, int, char, int, int); +void AddArrow(int, int, int, int, int, int, char, int, int); +void AddRndTeleport(int, int, int, int, int, int, char, int, int); +void AddFirebolt(int, int, int, int, int, int, char, int, int); +void AddMagmaball(int, int, int, int, int, int, char, int, int); +void AddTeleport(int, int, int, int, int, int, char, int, int); +void AddLightball(int, int, int, int, int, int, char, int, int); +void AddLightwall(int, int, int, int, int, int, char, int, int); +void AddFirewall(int, int, int, int, int, int, char, int, int); +void AddFireball(int, int, int, int, int, int, char, int, int); +void AddLightctrl(int, int, int, int, int, int, char, int, int); +void AddLightning(int, int, int, int, int, int, char, int, int); +void AddMisexp(int, int, int, int, int, int, char, int, int); +void AddTown(int, int, int, int, int, int, char, int, int); +void AddFlash(int, int, int, int, int, int, char, int, int); +void AddFlash2(int, int, int, int, int, int, char, int, int); +void AddManashield(int, int, int, int, int, int, char, int, int); +void AddFiremove(int, int, int, int, int, int, char, int, int); +void AddGuardian(int, int, int, int, int, int, char, int, int); +void AddChain(int, int, int, int, int, int, char, int, int); +//void AddChainball(int, int, int, int, int, int, char, int, int); +void AddBlood(int, int, int, int, int, int, char, int, int); +void AddRage(int, int, int, int, int, int, char, int, int); +void AddBone(int, int, int, int, int, int, char, int, int); +void AddMetal(int, int, int, int, int, int, char, int, int); +void AddRhino(int, int, int, int, int, int, char, int, int); +void AddFireman(int, int, int, int, int, int, char, int, int); +void AddFlare(int, int, int, int, int, int, char, int, int); +//void AddDoom(int, int, int, int, int, int, char, int, int); +void AddFireonly(int, int, int, int, int, int, char, int, int); +void AddStone(int, int, int, int, int, int, char, int, int); +void AddBloodR(int, int, int, int, int, int, char, int, int); +void AddSpurt(int, int, int, int, int, int, char, int, int); +void AddBoom(int, int, int, int, int, int, char, int, int); +void AddHeal(int, int, int, int, int, int, char, int, int); +void AddMana(int, int, int, int, int, int, char, int, int); +void AddFMana(int, int, int, int, int, int, char, int, int); +void AddHealOther(int, int, int, int, int, int, char, int, int); +void AddIdentify(int, int, int, int, int, int, char, int, int); +void AddFirewallC(int, int, int, int, int, int, char, int, int); +void AddInfra(int, int, int, int, int, int, char, int, int); +void AddWave(int, int, int, int, int, int, char, int, int); +void AddNova(int, int, int, int, int, int, char, int, int); +void AddBoil(int, int, int, int, int, int, char, int, int); +void AddRepair(int, int, int, int, int, int, char, int, int); +void AddRecharge(int, int, int, int, int, int, char, int, int); +void AddDisarm(int, int, int, int, int, int, char, int, int); +void AddApoca(int, int, int, int, int, int, char, int, int); +void AddFlame(int, int, int, int, int, int, char, int, int); +void AddFlamec(int, int, int, int, int, int, char, int, int); +void AddKrull(int, int, int, int, int, int, char, int, int); +void AddCbolt(int, int, int, int, int, int, char, int, int); +void AddHbolt(int, int, int, int, int, int, char, int, int); +void AddResurrect(int, int, int, int, int, int, char, int, int); +void AddResurrectBeam(int, int, int, int, int, int, char, int, int); +void AddTelekinesis(int, int, int, int, int, int, char, int, int); +void AddAcid(int, int, int, int, int, int, char, int, int); +void AddAcidpud(int, int, int, int, int, int, char, int, int); +void AddGolem(int, int, int, int, int, int, char, int, int); +void AddElement(int, int, int, int, int, int, char, int, int); +void AddEther(int, int, int, int, int, int, char, int, int); +void AddBoneSpirit(int, int, int, int, int, int, char, int, int); +void AddWeapexp(int, int, int, int, int, int, char, int, int); +void AddRportal(int, int, int, int, int, int, char, int, int); +void AddDiabApoca(int, int, int, int, int, int, char, int, int); +void AddSpecialArrow(int, int, int, int, int, int, char, int, int); +void AddFBArrow(int, int, int, int, int, int, char, int, int); +void AddLTArrow(int, int, int, int, int, int, char, int, int); +void AddCBArrow(int, int, int, int, int, int, char, int, int); +void AddHBArrow(int, int, int, int, int, int, char, int, int); +void AddTeleStairs(int, int, int, int, int, int, char, int, int); +void AddReflect(int, int, int, int, int, int, char, int, int); +void AddBerserk(int, int, int, int, int, int, char, int, int); +void AddFlameBox(int, int, int, int, int, int, char, int, int); +void AddDisEnchant(int, int, int, int, int, int, char, int, int); +void AddManaRemove(int, int, int, int, int, int, char, int, int); +void AddShowMagicItems(int, int, int, int, int, int, char, int, int); +void AddAura(int, int, int, int, int, int, char, int, int); +void AddAura2(int, int, int, int, int, int, char, int, int); +void AddSpiralFireBall(int, int, int, int, int, int, char, int, int); +void AddRuneOfFire(int, int, int, int, int, int, char, int, int); +void AddRuneOfLight(int, int, int, int, int, int, char, int, int); +void AddRuneOfNova(int, int, int, int, int, int, char, int, int); +void AddRuneOfImmolation(int, int, int, int, int, int, char, int, int); +void AddRuneOfStone(int, int, int, int, int, int, char, int, int); +void AddBigExplosion(int, int, int, int, int, int, char, int, int); +void AddHorkSpawn(int, int, int, int, int, int, char, int, int); +void AddRandom(int, int, int, int, int, int, char, int, int); +void AddReallyBigExp(int, int, int, int, int, int, char, int, int); + +void MI_Dummy(int); +void MI_Manashield(int); +void MI_SetManashield(int); +void MI_LArrow(int); +void MI_Arrow(int); +void MI_Firebolt(int); +void MI_Lightball(int); +void MI_Lightwall(int); +void MI_Firewall(int); +void MI_Fireball(int); +void MI_Lightctrl(int); +void MI_Lightning(int); +void MI_Misexp(int); +void MI_Town(int); +void MI_Flash(int); +void MI_Flash2(int); +void MI_Manashield(int); +void MI_Firemove(int); +void MI_Guardian(int); +void MI_Chain(int); +//void MI_Chainball(int); +void MI_Blood(int); +void MI_Rage(int); +void MI_Rhino(int); +void MI_Fireman(int); +void MI_Misexp(int); +void MI_Teleport(int); +//void MI_Doom(int); +void MI_Stone(int); +void MI_Boom(int); +void MI_FirewallC(int); +void MI_LightwallC(int); +void MI_Infra(int); +void MI_Apoca(int); +void MI_Wave(int); +void MI_Nova(int); +void MI_FireNova(int); +void MI_Boil(int); +void MI_Flame(int); +void MI_Flamec(int); +void MI_Krull(int); +void MI_Cbolt(int); +void MI_Hbolt(int); +void MI_Acid(int); +void MI_Acidsplat(int); +void MI_Acidpud(int); +void MI_Ether(int); +void MI_Element(int); +void MI_ResurrectBeam(int); +void MI_Weapexp(int); +void MI_Rportal(int); +void MI_Golem(int); +void MI_Bonespirit(int); +void MI_SpecialArrow(int); +void MI_LTArrow(int); +void MI_FlameBox(int); +void MI_LightBox(int); +void MI_ShowMagicItems(int); +void MI_Aura(int); +void MI_Aura2(int); +void MI_SpiralFireBall(int); +void MI_Rune(int); +void MI_BigExplosion(int); +void MI_HorkSpawn(int); +void MI_Reflect(int); + + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +MissileData missiledata[NUMBER_OF_MISSILE_TYPES] = +{ + { MIT_ARROW, // #defines name of missile for ease of use + AddArrow, // procedure for creating one of these missiles + MI_Arrow, // procedure to run each frame + TRUE, // draw missile flag + MIS_WEAP, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_ARROW, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FIREBOLT, // #defines name of missile for ease of use + AddFirebolt, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIREBOLT, // file# of missile gfx table + LS_FBOLT1, // missile launch sound + LS_FIRIMP2 }, // missile impact sound + + { MIT_GUARDIAN, // #defines name of missile for ease of use + AddGuardian, // procedure for creating one of these missiles + MI_Guardian, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_GUARDIAN, // file# of missile gfx table + LS_GUARD, // missile launch sound + LS_GUARDLAN }, // missile impact sound + + { MIT_PHASE, // #defines name of missile for ease of use + AddRndTeleport, // procedure for creating one of these missiles + MI_Teleport, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_TELEPORT, // missile launch sound + -1 }, // missile impact sound + + { MIT_LIGHTBALL, // #defines name of missile for ease of use + AddLightball, // procedure for creating one of these missiles + MI_Lightball, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FIREWALL, // #defines name of missile for ease of use + AddFirewall, // procedure for creating one of these missiles + MI_Firewall, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIRE, // file# of missile gfx table + LS_WALLLOOP, // missile launch sound + LS_FIRIMP2 }, // missile impact sound + + { MIT_FIREBALL, // #defines name of missile for ease of use + AddFireball, // procedure for creating one of these missiles + MI_Fireball, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIREBOLT, // file# of missile gfx table + LS_FBOLT1, // missile launch sound + LS_FIRIMP2 }, // missile impact sound + + { MIT_LIGHTCTRL, // #defines name of missile for ease of use + AddLightctrl, // procedure for creating one of these missiles + MI_Lightctrl, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_LIGHTNING, // #defines name of missile for ease of use + AddLightning, // procedure for creating one of these missiles + MI_Lightning, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + LS_LNING1, // missile launch sound + LS_ELECIMP1 }, // missile impact sound + + { MIT_MISEXP, // #defines name of missile for ease of use + AddMisexp, // procedure for creating one of these missiles + MI_Misexp, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_EXP1, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_TOWN, // #defines name of missile for ease of use + AddTown, // procedure for creating one of these missiles + MI_Town, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_TOWN, // file# of missile gfx table + LS_SENTINEL, // missile launch sound + LS_ELEMENTL }, // missile impact sound + + { MIT_FLASH, // #defines name of missile for ease of use + AddFlash, // procedure for creating one of these missiles + MI_Flash, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_FLASH1, // file# of missile gfx table + LS_NOVA, // missile launch sound + LS_ELECIMP1 }, // missile impact sound + + { MIT_FLASH2, // #defines name of missile for ease of use + AddFlash2, // procedure for creating one of these missiles + MI_Flash2, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_FLASH2, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_MANASHIELD, // #defines name of missile for ease of use + AddManashield, // procedure for creating one of these missiles + MI_SetManashield, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_MANASHLD, // file# of missile gfx table + LS_MSHIELD, // missile launch sound + -1 }, // missile impact sound + + { MIT_FIREMOVE, // #defines name of missile for ease of use + AddFiremove, // procedure for creating one of these missiles + MI_Firemove, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIRE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_CHAIN, // #defines name of missile for ease of use + AddChain, // procedure for creating one of these missiles + MI_Chain, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + LS_LNING1, // missile launch sound + LS_ELECIMP1 }, // missile impact sound + + { MIT_CHAINBALL, // #defines name of missile for ease of use + NULL, // procedure for creating one of these missiles + NULL, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_BLOOD, // #defines name of missile for ease of use + AddBlood, // procedure for creating one of these missiles + MI_Blood, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_BLOOD, // file# of missile gfx table + LS_BLODSTAR, // missile launch sound + LS_BLSIMPT }, // missile impact sound + + { MIT_BONE, // #defines name of missile for ease of use + AddBone, // procedure for creating one of these missiles + MI_Blood, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_BONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_METAL, // #defines name of missile for ease of use + AddMetal, // procedure for creating one of these missiles + MI_Blood, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_METAL, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_RHINO, // #defines name of missile for ease of use + AddRhino, // procedure for creating one of these missiles + MI_Rhino, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_MAGMABALL, // #defines name of missile for ease of use + AddMagmaball, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_MAGBALL, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_THINLIGHTCTRL, // #defines name of missile for ease of use + AddLightctrl, // procedure for creating one of these missiles + MI_Lightctrl, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_THINLIGHT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_THINLIGHT, // #defines name of missile for ease of use + AddLightning, // procedure for creating one of these missiles + MI_Lightning, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_THINLIGHT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FLARE, // #defines name of missile for ease of use + AddFlare, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_FLARE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FLAREXP, // #defines name of missile for ease of use + AddMisexp, // procedure for creating one of these missiles + MI_Misexp, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_FLAREXP, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_TELE, // #defines name of missile for ease of use + AddTeleport, // procedure for creating one of these missiles + MI_Teleport, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_ELEMENTL, // missile launch sound + -1 }, // missile impact sound + + { MIT_FARROW, // #defines name of missile for ease of use + AddLArrow, // procedure for creating one of these missiles + MI_LArrow, // procedure to run each frame + TRUE, // draw missile flag + MIS_WEAP, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FARROW, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_DOOM, // #defines name of missile for ease of use + NULL, // procedure for creating one of these missiles + NULL, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_DOOM, // file# of missile gfx table + LS_DSERP, // missile launch sound + -1 }, // missile impact sound + + { MIT_FIREONLY, // #defines name of missile for ease of use + AddFireonly, // procedure for creating one of these missiles + MI_Firewall, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIRE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_STONE, // #defines name of missile for ease of use + AddStone, // procedure for creating one of these missiles + MI_Stone, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_SCURIMP, // missile launch sound + -1 }, // missile impact sound + + { MIT_BLOODR, // #defines name of missile for ease of use + AddBloodR, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_INVIS, // #defines name of missile for ease of use + NULL, // procedure for creating one of these missiles + NULL, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_INVISIBL, // missile launch sound + -1 }, // missile impact sound + + { MIT_GOLEM, // #defines name of missile for ease of use + AddGolem, // procedure for creating one of these missiles + MI_Golem, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_GOLUM, // missile launch sound + -1 }, // missile impact sound + + { MIT_ETHER, // #defines name of missile for ease of use + AddEther, // procedure for creating one of these missiles + MI_Ether, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_ETHER, // file# of missile gfx table + LS_ETHEREAL, // missile launch sound + -1 }, // missile impact sound + + { MIT_SPURT, // #defines name of missile for ease of use + AddSpurt, // procedure for creating one of these missiles + MI_Blood, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_SPURT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_BOOM, // #defines name of missile for ease of use + AddBoom, // procedure for creating one of these missiles + MI_Boom, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_BOOM, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_HEAL, // #defines name of missile for ease of use + AddHeal, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FIREWALLC, // #defines name of missile for ease of use + AddFirewallC, // procedure for creating one of these missiles + MI_FirewallC, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIRE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_INFRA, // #defines name of missile for ease of use + AddInfra, // procedure for creating one of these missiles + MI_Infra, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_INFRAVIS, // missile launch sound + -1 }, // missile impact sound + + { MIT_IDENTIFY, // #defines name of missile for ease of use + AddIdentify, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_WAVE, // #defines name of missile for ease of use + AddWave, // procedure for creating one of these missiles + MI_Wave, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIRE, // file# of missile gfx table + LS_FLAMWAVE, // missile launch sound + -1 }, // missile impact sound + + { MIT_NOVA, // #defines name of missile for ease of use + AddNova, // procedure for creating one of these missiles + MI_Nova, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + LS_NOVA, // missile launch sound + -1 }, // missile impact sound + +#if 0 + { MIT_BLDBOIL, // #defines name of missile for ease of use + AddBoil, // procedure for creating one of these missiles + MI_Boil, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + LS_BLODBOIL }, // missile impact sound +#else + { MIT_RAGE, // #defines name of missile for ease of use + AddRage, // procedure for creating one of these missiles + MI_Rage, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound +#endif + + { MIT_APOCA, // #defines name of missile for ease of use + AddApoca, // procedure for creating one of these missiles + MI_Apoca, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_BOOM, // file# of missile gfx table + LS_APOC, // missile launch sound + -1 }, // missile impact sound + + { MIT_REPAIR, // #defines name of missile for ease of use + AddRepair, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_RECHARGE, // #defines name of missile for ease of use + AddRecharge, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_DISARM, // #defines name of missile for ease of use + AddDisarm, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_TRAPDIS, // missile launch sound + -1 }, // missile impact sound + + { MIT_FLAME, // #defines name of missile for ease of use + AddFlame, // procedure for creating one of these missiles + MI_Flame, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FLAMES, // file# of missile gfx table + //MF_LIGHTNING, // file# of missile gfx table + LS_SPOUTSTR, // missile launch sound + -1 }, // missile impact sound + + { MIT_FLAMEC, // #defines name of missile for ease of use + AddFlamec, // procedure for creating one of these missiles + MI_Flamec, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FIREMAN, // #defines name of missile for ease of use + AddFireman, // procedure for creating one of these missiles + MI_Fireman, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_KRULL, // #defines name of missile for ease of use + AddKrull, // procedure for creating one of these missiles + MI_Krull, // procedure to run each frame + TRUE, // draw missile flag + MIS_WEAP, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_KRULL, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_CBOLT, // #defines name of missile for ease of use + AddCbolt, // procedure for creating one of these missiles + MI_Cbolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_CBOLT, // file# of missile gfx table + LS_CBOLT, // missile launch sound + -1 }, // missile impact sound + + { MIT_HBOLT, // #defines name of missile for ease of use + AddHbolt, // procedure for creating one of these missiles + MI_Hbolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_HBOLT, // file# of missile gfx table + LS_HOLYBOLT, // missile launch sound + LS_ELECIMP1 }, // missile impact sound + + { MIT_RESURRECT, // #defines name of missile for ease of use + AddResurrect, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + LS_RESUR }, // missile impact sound + + { MIT_TELEKINESIS, // #defines name of missile for ease of use + AddTelekinesis, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_ETHEREAL, // missile launch sound + -1 }, // missile impact sound + + { MIT_LARROW, // #defines name of missile for ease of use + AddLArrow, // procedure for creating one of these missiles + MI_LArrow, // procedure to run each frame + TRUE, // draw missile flag + MIS_WEAP, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LARROW, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_ACID, // #defines name of missile for ease of use + AddAcid, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_ACID, // missile resistance type (fire, light, misc, none) + MF_ACID, // file# of missile gfx table + LS_ACID, // missile launch sound + -1 }, // missile impact sound + + { MIT_ACIDSPLAT, // #defines name of missile for ease of use + AddMisexp, // procedure for creating one of these missiles + MI_Acidsplat, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_ACID, // missile resistance type (fire, light, misc, none) + MF_ACIDSPLAT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_ACIDPUD, // #defines name of missile for ease of use + AddAcidpud, // procedure for creating one of these missiles + MI_Acidpud, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_ACID, // missile resistance type (fire, light, misc, none) + MF_ACIDPUD, // file# of missile gfx table + LS_PUDDLE, // missile launch sound + -1 }, // missile impact sound + + { MIT_HEALOTHER, // #defines name of missile for ease of use + AddHealOther, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_ELEMENT, // #defines name of missile for ease of use + AddElement, // procedure for creating one of these missiles + MI_Element, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIRERUN, // file# of missile gfx table + LS_ELEMENTL, // missile launch sound + -1 }, // missile impact sound + + { MIT_RESURRECTBEAM, // #defines name of missile for ease of use + AddResurrectBeam, // procedure for creating one of these missiles + MI_ResurrectBeam, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_RESURRECT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_BONESPIRIT, // #defines name of missile for ease of use + AddBoneSpirit, // procedure for creating one of these missiles + MI_Bonespirit, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_BONESPIRIT, // file# of missile gfx table + LS_BONESP, // missile launch sound + LS_BSIMPCT }, // missile impact sound + + { MIT_WEAPEXP, // #defines name of missile for ease of use + AddWeapexp, // procedure for creating one of these missiles + MI_Weapexp, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_RPORTAL, // #defines name of missile for ease of use + AddRportal, // procedure for creating one of these missiles + MI_Rportal, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_RPORTAL, // file# of missile gfx table + LS_SENTINEL, // missile launch sound + LS_ELEMENTL }, // missile impact sound + + { MIT_FIREPLAR, // #defines name of missile for ease of use + AddBoom, // procedure for creating one of these missiles + MI_Boom, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_FIREPLAR, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_DIABAPOCA, // #defines name of missile for ease of use + AddDiabApoca, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_MANA, // #defines name of missile for ease of use + AddMana, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FMANA, // #defines name of missile for ease of use + AddFMana, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_LIGHTWALL, // #defines name of missile for ease of use + AddLightwall, // procedure for creating one of these missiles + MI_Lightwall, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + LS_LMAG, // missile launch sound + LS_ELECIMP1 }, // missile impact sound + + { MIT_LIGHTWALLC, // #defines name of missile for ease of use + AddFirewallC, // procedure for creating one of these missiles + MI_LightwallC, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_IMMOLATION, // #defines name of missile for ease of use + AddNova, // procedure for creating one of these missiles + MI_FireNova, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIREBOLT, // file# of missile gfx table + LS_FBOLT1, // missile launch sound + LS_FIRIMP2 }, // missile impact sound + + { MIT_SPECARROW, // #defines name of missile for ease of use + AddSpecialArrow, // procedure for creating one of these missiles + MI_SpecialArrow, // procedure to run each frame + TRUE, // draw missile flag + MIS_WEAP, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_ARROW, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FBARROW, // #defines name of missile for ease of use + AddFBArrow, // procedure for creating one of these missiles + MI_Fireball, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIREBOLT, // file# of missile gfx table + PS_FB_BFIRE, // missile launch sound + LS_FIRIMP2 }, // missile impact sound + + { MIT_LTARROW, // #defines name of missile for ease of use + AddLTArrow, // procedure for creating one of these missiles + MI_LTArrow, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + PS_FB_BFIRE, // missile launch sound + -1 }, // missile impact sound + + { MIT_CBARROW, // #defines name of missile for ease of use + AddCBArrow, // procedure for creating one of these missiles + MI_Cbolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_CBOLT, // file# of missile gfx table + LS_CBOLT, // missile launch sound + -1 }, // missile impact sound + + { MIT_HBARROW, // #defines name of missile for ease of use + AddHBArrow, // procedure for creating one of these missiles + MI_Hbolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_HBOLT, // file# of missile gfx table + LS_HOLYBOLT, // missile launch sound + LS_ELECIMP1 }, // missile impact sound + + { MIT_TELESTAIRS, // #defines name of missile for ease of use + AddTeleStairs, // procedure for creating one of these missiles + MI_Teleport, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + LS_ETHEREAL, // missile launch sound + -1 }, // missile impact sound + + { MIT_REFLECT, // #defines name of missile for ease of use + AddReflect, // procedure for creating one of these missiles + MI_Reflect, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_REFLECTSHLD, // file# of missile gfx table + LS_MSHIELD, // missile launch sound + -1 }, // missile impact sound + + { MIT_BERSERK, // #defines name of missile for ease of use + AddBerserk, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_FLAMEBOX, // #defines name of missile for ease of use + AddFlameBox, // procedure for creating one of these missiles + MI_FlameBox, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIRE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_DISENCHANT, // #defines name of missile for ease of use + AddDisEnchant, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_MANAREMOVE, // #defines name of missile for ease of use + AddManaRemove, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + IS_CAST7, // missile launch sound + -1 }, // missile impact sound + + { MIT_LIGHTBOX, // #defines name of missile for ease of use + AddFlameBox, // procedure for creating one of these missiles + MI_LightBox, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_LGHT, // missile resistance type (fire, light, misc, none) + MF_LIGHTNING, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_SHOWMAGITEMS, // #defines name of missile for ease of use + AddShowMagicItems, // procedure for creating one of these missiles + MI_ShowMagicItems, // procedure to run each frame + FALSE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_AURA, // #defines name of missile for ease of use + AddAura, // procedure for creating one of these missiles + MI_Aura, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_FLASH1, // file# of missile gfx table + -1, // missile launch sound + LS_ELECIMP1 }, // missile impact sound + + { MIT_AURA2, // #defines name of missile for ease of use + AddAura2, // procedure for creating one of these missiles + MI_Aura2, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_FLASH2, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_SPIRALFIREBALL, // #defines name of missile for ease of use + AddSpiralFireBall, // procedure for creating one of these missiles + MI_SpiralFireBall, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_FIREBOLT, // file# of missile gfx table + LS_FBOLT1, // missile launch sound + LS_FIRIMP2 }, // missile impact sound + + { MIT_RUNEOFFIRE, // #defines name of missile for ease of use + AddRuneOfFire, // procedure for creating one of these missiles + MI_Rune, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_RUNEHOTSPOT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_RUNEOFLIGHT, // #defines name of missile for ease of use + AddRuneOfLight, // procedure for creating one of these missiles + MI_Rune, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_RUNEHOTSPOT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_RUNEOFNOVA, // #defines name of missile for ease of use + AddRuneOfNova, // procedure for creating one of these missiles + MI_Rune, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_RUNEHOTSPOT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_RUNEOFIMMOLATION, // #defines name of missile for ease of use + AddRuneOfImmolation, // procedure for creating one of these missiles + MI_Rune, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_RUNEHOTSPOT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_RUNEOFSTONE, // #defines name of missile for ease of use + AddRuneOfStone, // procedure for creating one of these missiles + MI_Rune, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_RUNEHOTSPOT, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_BIGEXPLOSION, // #defines name of missile for ease of use + AddBigExplosion, // procedure for creating one of these missiles + MI_BigExplosion, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_FIRE, // missile resistance type (fire, light, misc, none) + MF_BIGEXP, // file# of missile gfx table + LS_BIGEXP, // missile launch sound + LS_BIGEXP }, // missile impact sound + + { MIT_HORKSPAWN, // #defines name of missile for ease of use + AddHorkSpawn, // procedure for creating one of these missiles + MI_HorkSpawn, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_HORKSPAWN, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_RANDOM, // #defines name of missile for ease of use + AddRandom, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_OPENNEST, // #defines name of missile for ease of use + AddReallyBigExp, // procedure for creating one of these missiles + MI_Dummy, // procedure to run each frame + FALSE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_NONE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_ORANGEFLARE, // #defines name of missile for ease of use + AddFlare, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_ORANGEFLARE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_BLUEFLARE, // #defines name of missile for ease of use + AddFlare, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_BLUE2FLARE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_REDFLARE, // #defines name of missile for ease of use + AddFlare, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_REDFLARE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_YELLOWFLARE, // #defines name of missile for ease of use + AddFlare, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_YELLOWFLARE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_BLUE2FLARE, // #defines name of missile for ease of use + AddFlare, // procedure for creating one of these missiles + MI_Firebolt, // procedure to run each frame + TRUE, // draw missile flag + MIS_SPL, // missile type (weapon, spell, none) + MIMT_MISC, // missile resistance type (fire, light, misc, none) + MF_BLUE2FLARE, // file# of missile gfx table + -1, // missile launch sound + -1 }, // missile impact sound + + { MIT_YELLOWEXPLOSION, // #defines name of missile for ease of use + AddMisexp, // procedure for creating one of these missiles + MI_Misexp, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_YELLOWEXPLOSION, // file# of missile gfx table + LS_FIRIMP2, // missile launch sound + -1 }, // missile impact sound + + { MIT_REDEXPLOSION, // #defines name of missile for ease of use + AddMisexp, // procedure for creating one of these missiles + MI_Misexp, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_REDEXPLOSION, // file# of missile gfx table + LS_FIRIMP2, // missile launch sound + -1 }, // missile impact sound + + { MIT_BLUEEXPLOSION, // #defines name of missile for ease of use + AddMisexp, // procedure for creating one of these missiles + MI_Misexp, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_BLUEEXPLOSION, // file# of missile gfx table + LS_FIRIMP2, // missile launch sound + -1 }, // missile impact sound + + { MIT_BLUE2EXPLOSION, // #defines name of missile for ease of use + AddMisexp, // procedure for creating one of these missiles + MI_Misexp, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_BLUE2EXPLOSION, // file# of missile gfx table + LS_FIRIMP2, // missile launch sound + -1 }, // missile impact sound + + { MIT_ORANGEEXPLOSION, // #defines name of missile for ease of use + AddMisexp, // procedure for creating one of these missiles + MI_Misexp, // procedure to run each frame + TRUE, // draw missile flag + MIS_NONE, // missile type (weapon, spell, none) + MIMT_NONE, // missile resistance type (fire, light, misc, none) + MF_ORANGEEXPLOSION, // file# of missile gfx table + LS_FIRIMP2, // missile launch sound + -1 }, // missile impact sound + +}; + + +MisFileData misfiledata[] = +{ + { MF_ARROW, // #defines name of missile file for ease of use + 1, // amount of files + "Arrows", // path for cels + MFF_STATIC, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FIREBOLT, // #defines name of missile file for ease of use + 16, // amount of files + "Fireba", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 }, // number of anim frames + { 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96 }, // anim width + { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 } }, // anim width2 + + { MF_GUARDIAN, // #defines name of missile file for ease of use + 3, // amount of files + "Guard", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15, 14, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_LIGHTNING, // #defines name of missile file for ease of use + 1, // amount of files + "Lghning", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FIRE, // #defines name of missile file for ease of use + 2, // amount of files + "Firewal", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 13, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_EXP1, // #defines name of missile file for ease of use + 1, // amount of files + "MagBlos", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_TOWN, // #defines name of missile file for ease of use + 2, // amount of files + "Portal", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FLASH1, // #defines name of missile file for ease of use + 1, // amount of files + "Bluexfr", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FLASH2, // #defines name of missile file for ease of use + 1, // amount of files + "Bluexbk", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_MANASHLD, // #defines name of missile file for ease of use + 1, // amount of files + "Manashld", // path for cels + MFF_STATIC, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BLOOD, // #defines name of missile file for ease of use + 4, // amount of files + "Blood", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BONE, // #defines name of missile file for ease of use + 3, // amount of files + "Bone", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_METAL, // #defines name of missile file for ease of use + 3, // amount of files + "Metlhit", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FARROW, // #defines name of missile file for ease of use + 16, // amount of files + "Farrow", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, // number of anim frames + { 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96 }, // anim width + { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 } }, // anim width2 + + { MF_DOOM, // #defines name of missile file for ease of use + 9, // amount of files + "Doom", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_GOLEM, // #defines name of missile file for ease of use + 1, // amount of files + " ", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_SPURT, // #defines name of missile file for ease of use + 2, // amount of files + "Blodbur", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BOOM, // #defines name of missile file for ease of use + 1, // amount of files + "Newexp", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_STONE, // #defines name of missile file for ease of use + 1, // amount of files + "Shatter1", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BIGEXP, // #defines name of missile file for ease of use + 1, // amount of files + "Bigexp", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FLAMES, // #defines name of missile file for ease of use + 1, // amount of files + "Inferno", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_THINLIGHT, // #defines name of missile file for ease of use + 1, // amount of files + "Thinlght", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FLARE, // #defines name of missile file for ease of use + 1, // amount of files + "Flare", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FLAREXP, // #defines name of missile file for ease of use + 1, // amount of files + "Flareexp", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_MAGBALL, // #defines name of missile file for ease of use + 8, // amount of files + "Magball", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 32, 32, 32, 32, 32, 32, 32, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_KRULL, // #defines name of missile file for ease of use + 1, // amount of files + "Krull", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + + { MF_CBOLT, // #defines name of missile file for ease of use + 1, // amount of files + "Miniltng", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_HBOLT, // #defines name of missile file for ease of use + 16, // amount of files + "Holy", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 }, // number of anim frames + { 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96 }, // anim width + { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 } }, // anim width2 + + { MF_HEXPL, // #defines name of missile file for ease of use + 1, // amount of files + "Holyexpl", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_LARROW, // #defines name of missile file for ease of use + 16, // amount of files + "Larrow", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 }, // number of anim frames + { 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96 }, // anim width + { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 } }, // anim width2 + + { MF_FAEXP, // #defines name of missile file for ease of use + 1, // amount of files + "Firarwex", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_ACID, // #defines name of missile file for ease of use + 16, // amount of files + "Acidbf", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, // number of anim frames + { 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96 }, // anim width + { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 } }, // anim width2 + + { MF_ACIDSPLAT, // #defines name of missile file for ease of use + 1, // amount of files + "Acidspla", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_ACIDPUD, // #defines name of missile file for ease of use + 2, // amount of files + "Acidpud" , // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 9, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96,96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16,16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_ETHER, // #defines name of missile file for ease of use + 1, // amount of files + "Ethrshld", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FIRERUN, // #defines name of missile file for ease of use + 8, // amount of files + "Firerun", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 12, 12, 12, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_RESURRECT, // #defines name of missile file for ease of use + 1, // amount of files + "Ressur1", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BONESPIRIT, // #defines name of missile file for ease of use + 9, // amount of files + "Sklball", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 16, 16, 16, 16, 16, 16, 16, 8, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_RPORTAL, // #defines name of missile file for ease of use + 2, // amount of files + "Rportal", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_FIREPLAR, // #defines name of missile file for ease of use + 1, // amount of files + "Fireplar", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 160,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BFLARE, // #defines name of missile file for ease of use + 1, // amount of files + "Scubmisb", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BFLAREXP, // #defines name of missile file for ease of use + 1, // amount of files + "Scbsexpb", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_CFLARE, // #defines name of missile file for ease of use + 1, // amount of files + "Scubmisc", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_CFLAREXP, // #defines name of missile file for ease of use + 1, // amount of files + "Scbsexpc", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_DFLARE, // #defines name of missile file for ease of use + 1, // amount of files + "Scubmisd", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_DFLAREXP, // #defines name of missile file for ease of use + 1, // amount of files + "Scbsexpd", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_HORKSPAWN, // #defines name of missile file for ease of use + 8, // amount of files + "spawns", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96,96,96,96,96,96,96,96, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 16,16,16,16,16,16,16,16, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_REFLECTSHLD, // #defines name of missile file for ease of use + 1, // amount of files + "reflect", // path for cels + MFF_STATIC, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + {160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + {160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_ORANGEFLARE, // #defines name of missile file for ease of use + 16, // amount of files + "ms_ora", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 }, // number of anim frames + { 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96 }, // anim width + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 } }, // anim width2 + + { MF_BLUEFLARE, // #defines name of missile file for ease of use + 16, // amount of files + "ms_bla", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 }, // number of anim frames + { 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96 }, // anim width + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 } }, // anim width2 + + { MF_REDFLARE, // #defines name of missile file for ease of use + 16, // amount of files + "ms_reb", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 }, // number of anim frames + { 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96 }, // anim width + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 } }, // anim width2 + + { MF_YELLOWFLARE, // #defines name of missile file for ease of use + 16, // amount of files + "ms_yeb", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 }, // number of anim frames + { 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96 }, // anim width + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 } }, // anim width2 + + { MF_RUNEHOTSPOT, // #defines name of missile file for ease of use + 1, // amount of files + "rglows1", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_YELLOWEXPLOSION, // #defines name of missile file for ease of use + 1, // amount of files + "ex_yel2", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BLUEEXPLOSION, // #defines name of missile file for ease of use + 1, // amount of files + "ex_blu2", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_REDEXPLOSION, // #defines name of missile file for ease of use + 1, // amount of files + "ex_red3", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BLUE2FLARE, // #defines name of missile file for ease of use + 16, // amount of files + "ms_blb", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 }, // number of anim frames + { 96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96 }, // anim width + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 } }, // anim width2 + + { MF_ORANGEEXPLOSION, // #defines name of missile file for ease of use + 1, // amount of files + "ex_ora1", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { -12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + + { MF_BLUE2EXPLOSION, // #defines name of missile file for ease of use + 1, // amount of files + "ex_blu3", // path for cels + MFF_MONSTONLY, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, // anim width2 + +// END OF LIST INDICATOR + { MF_NONE, // #defines name of missile file for ease of use + 0, // amount of files + "", // path for cels + NULL, // flags, e.g., MFF_MONSTONLY + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // data pointers to anim tables + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim delay amount + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // number of anim frames + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // anim width + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } // anim width2 +}; + diff --git a/src/MISDAT.H b/src/MISDAT.H new file mode 100644 index 0000000..3eba664 --- /dev/null +++ b/src/MISDAT.H @@ -0,0 +1,135 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1996 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MISDAT.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ +typedef void (*MIADDPRC)(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam); +typedef void (*MIPROC)(int i); + +#define MIS_WEAP 0 +#define MIS_SPL 1 +#define MIS_NONE 2 + +// Missile Magic Type +#define MIMT_NONE 0 +#define MIMT_FIRE 1 +#define MIMT_LGHT 2 +#define MIMT_MISC 3 +#define MIMT_ACID 4 + +// Missile File Flags +#define MFF_MONSTONLY 1 // Only loaded for particular monsters +#define MFF_STATIC 2 // Do not animate -- one frame per direction +#define MFF_MULTI 4 // All directions of anim are in one file + +#define MF_NONE 255 +#define MF_STARTLOAD 0 +#define MF_ARROW 0 +#define MF_FIREBOLT 1 +#define MF_GUARDIAN 2 +#define MF_LIGHTNING 3 +#define MF_FIRE 4 +#define MF_EXP1 5 +#define MF_TOWN 6 +#define MF_FLASH1 7 +#define MF_FLASH2 8 +#define MF_MANASHLD 9 +#define MF_BLOOD 10 +#define MF_BONE 11 +#define MF_METAL 12 +#define MF_FARROW 13 +#define MF_DOOM 14 +#define MF_GOLEM 15 +#define MF_SPURT 16 +#define MF_BOOM 17 +#define MF_STONE 18 +#define MF_BIGEXP 19 +#define MF_FLAMES 20 +#define MF_THINLIGHT 21 +#define MF_FLARE 22 +#define MF_FLAREXP 23 +#define MF_MAGBALL 24 +#define MF_KRULL 25 +#define MF_CBOLT 26 +#define MF_HBOLT 27 +#define MF_HEXPL 28 +#define MF_LARROW 29 +#define MF_FAEXP 30 +#define MF_ACID 31 +#define MF_ACIDSPLAT 32 +#define MF_ACIDPUD 33 +#define MF_ETHER 34 +#define MF_FIRERUN 35 +#define MF_RESURRECT 36 +#define MF_BONESPIRIT 37 +#define MF_RPORTAL 38 +#define MF_FIREPLAR 39 +#define MF_BFLARE 40 +#define MF_BFLAREXP 41 +#define MF_CFLARE 42 +#define MF_CFLAREXP 43 +#define MF_DFLARE 44 +#define MF_DFLAREXP 45 +#define MF_HORKSPAWN 46 +#define MF_REFLECTSHLD 47 +#define MF_ORANGEFLARE 48 +#define MF_BLUEFLARE 49 +#define MF_REDFLARE 50 +#define MF_YELLOWFLARE 51 +#define MF_RUNEHOTSPOT 52 +#define MF_YELLOWEXPLOSION 53 +#define MF_BLUEEXPLOSION 54 +#define MF_REDEXPLOSION 55 +#define MF_BLUE2FLARE 56 +#define MF_ORANGEEXPLOSION 57 +#define MF_BLUE2EXPLOSION 58 + + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ +typedef struct { + BYTE mName; // #defines name of missile for ease of use + MIADDPRC mAddProc; // procedure for creating one of these missiles + MIPROC mProc; // procedure to run each frame + BOOL mDraw; // missile draw or not flag + BYTE mType; // missile type (weapon, spell, none) + BYTE mResist; // missile resistance type (fire, light, misc, none) + BYTE mFileNum; // file# of missile gfx table + int mlSFX; // missile launch sound + int miSFX; // missile impact sound +} MissileData; + +typedef struct { + BYTE mAnimName; // #defines name of missile file for ease of use + BYTE mAnimFAmt; // amount of files + char *mAnimPath; // path for cels + BOOL mFlags; // e.g. MFF_MONSTOLY + BYTE *mAnimData[16]; // data pointer to anim tables + BYTE mAnimDelay[16]; // anim delay amount + BYTE mAnimLen[16]; // number of anim frames + long mAnimWidth[16]; // anim width + long mAnimWidth2[16]; // anim width2 +} MisFileData; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern MissileData missiledata[]; +extern MisFileData misfiledata[]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ diff --git a/src/MISSILES.CPP b/src/MISSILES.CPP new file mode 100644 index 0000000..2e6915c --- /dev/null +++ b/src/MISSILES.CPP @@ -0,0 +1,7451 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Missiles file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MISSILES.CPP 3 2/25/97 2:27p Jmcreynolds $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include +#include +#include "sound.h" +#include "missiles.h" +#include "misdat.h" +#include "engine.h" +#include "gendung.h" +#include "lighting.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "monstdat.h" +#include "monstint.h" +#include "control.h" +#include "objects.h" +#include "objdat.h" +#include "spells.h" +#include "cursor.h" +#include "dead.h" +#include "effects.h" +#include "palette.h" +#include "inv.h" +#include "msg.h" +#include "quests.h" +#include "itemdat.h" +#include "multi.h" +#include "trigs.h" +#include "scrollrt.h" + +#define MONOPRINT 1 + +/*-----------------------------------------------------------------------* +** Constants +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +#define CEL_EXT ".CL2" +#else +#define CEL_EXT ".CEL" +#endif + + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +MissileStruct missile[MAXMISSILES]; +int nummissiles; + +static int missilevars[MAXMISSILES][3]; //0 missile num; 1 var1; 2 var2 +static int nummissilevars; + +int missileactive[MAXMISSILES]; +int missileavail[MAXMISSILES]; + +int XDirAdd[8] = { 1, 0, -1, -1, -1, 0, 1, 1 }; +int YDirAdd[8] = { 1, 1, 1, 0, -1, -1, -1, 0 }; + +// Indexes into the CrawlTable. +static int const CrawlNum[19] = { 0, 3, 12, 45, 94, 159, 240, 337, 450, 579, 724, + 885, 1062, 1255, 1464, 1689, 1930, 2187, 2460 }; + +BOOL ManashieldFlag; +BOOL MissilePreFlag; + +typedef BOOL (*CHECKFUNC)(int x, int y); + +static void GetMissilePos(int i); +void SetMissDir(int mi, int dir); + +/*-----------------------------------------------------------------------** +**----------------------- General use routines --------------------------** +**-----------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GetDamageAmt(int i, int * mind, int * maxd) +{ + int k, sl; + + app_assert(myplr < MAX_PLRS && myplr >= 0); + app_assert(i < 64 && i >= 0); + sl = plr[myplr]._pSplLvl[i] + plr[myplr]._pISplLvlAdd; + + switch (i) { + case SPL_FIREBOLT: + *mind = 1 + (plr[myplr]._pMagic >> 3) + sl; + *maxd = 10 + (plr[myplr]._pMagic >> 3) + sl; + break; + case SPL_HEAL: + *mind = 1 + plr[myplr]._pLevel + sl; + if (plr[myplr]._pClass == CLASS_WARRIOR + || plr[myplr]._pClass == CLASS_MONK + || plr[myplr]._pClass == CLASS_BARBARIAN) *mind = *mind << 1; + else if (plr[myplr]._pClass == CLASS_ROGUE || + plr[myplr]._pClass == CLASS_BARD) *mind += (*mind >> 1); + *maxd = 10; + for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 4; + for (k = 0; k < sl; ++k) *maxd += 6; + if (plr[myplr]._pClass == CLASS_WARRIOR + || plr[myplr]._pClass == CLASS_MONK + || plr[myplr]._pClass == CLASS_BARBARIAN) *maxd = *maxd << 1; + else if (plr[myplr]._pClass == CLASS_ROGUE || + plr[myplr]._pClass == CLASS_BARD) *maxd += (*maxd >> 1); + *mind = -1; + *maxd = -1; + break; + case SPL_LIGHTNING: + case SPL_RUNEOFLIGHT: + *mind = 2; + *maxd = plr[myplr]._pLevel + 2; + break; + case SPL_FLASH: + *mind = plr[myplr]._pLevel; + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *mind += *mind >> 1; + *maxd = *mind << 1; // this is not actual(below is) - its a kludge to make it seem acurate text wise + /**maxd = 0; + for (k = 0; k <= plr[myplr]._pLevel; ++k) *maxd += 20; + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + *maxd += *maxd >> 1;*/ + break; + case SPL_IDENTIFY: + case SPL_TOWN: + case SPL_STONE: + case SPL_RUNEOFSTONE: + case SPL_INFRA: + case SPL_PHASE: + case SPL_MANASHLD: + case SPL_DOOM: + case SPL_BLOODR: + case SPL_INVIS: + //case SPL_BLOODB: + case SPL_RAGE: + case SPL_TELE: + case SPL_ETHER: + case SPL_REPAIR: + case SPL_RECHARGE: + case SPL_DISARM: + case SPL_RESURRECT: + case SPL_TELEKINESIS: + case SPL_BONESPIRIT: + case SPL_TELESTAIRS: + case SPL_REFLECT: + case SPL_BERSERK: + case SPL_SHOWMAGITEMS: + *mind = -1; + *maxd = -1; + break; + case SPL_WALL: + case SPL_LTWALL: + case SPL_RINGOFFIRE: + *mind = ((2 + plr[myplr]._pLevel) << 2) >> 1; + *maxd = ((20 + plr[myplr]._pLevel) << 2) >> 1; + break; + case SPL_FIREBALL: + case SPL_RUNEOFFIRE: + *mind = (2 + plr[myplr]._pLevel) << 1; + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *maxd = (20 + plr[myplr]._pLevel) << 1; + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + break; + case SPL_GUARDIAN: + *mind = 1 + (plr[myplr]._pLevel >> 1); + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *maxd = 10 + (plr[myplr]._pLevel >> 1); + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + break; + case SPL_CHAIN: + // this is not actual - its a kludge to make it seem acurate text wise + *mind = 2 << 1; + *maxd = (plr[myplr]._pLevel + 2) << 1; + break; + case SPL_WAVE: + // this is not actual - its a kludge to make it seem acurate text wise + *mind = ((1 + plr[myplr]._pLevel) << 2) + ((1 + plr[myplr]._pLevel) << 1); + *maxd = ((10 + plr[myplr]._pLevel) << 2) + ((10 + plr[myplr]._pLevel) << 1); + break; + case SPL_NOVA: + case SPL_IMMOLATION: + case SPL_RUNEOFIMMOLATION: + case SPL_RUNEOFNOVA: + // this is not actual - its a kludge to make it seem acurate text wise + *mind = (5 + plr[myplr]._pLevel) >> 1; + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *mind = (*mind << 2) + *mind; + *maxd = (30 + plr[myplr]._pLevel) >> 1; + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + *maxd = (*maxd << 2) + *maxd; + break; + case SPL_FLAME: + *mind = 2; + *mind += *mind >> 1; + *maxd = (plr[myplr]._pLevel + 4); + *maxd += *maxd >> 1; + break; + case SPL_GOLEM: + *mind = 11; + *maxd = 17; + break; + case SPL_APOCA: + *mind = 0; + for (k = 0; k < plr[myplr]._pLevel; ++k) *mind += 1; + *maxd = 0; + for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 6; + break; + case SPL_ELEMENT: + *mind = (2 + plr[myplr]._pLevel) << 1; + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *maxd = (20 + plr[myplr]._pLevel) << 1; + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + break; + case SPL_CBOLT: + *mind = 1; + *maxd = 1 + (plr[myplr]._pMagic >> 2); + break; + case SPL_HBOLT: + *mind = 9 + plr[myplr]._pLevel; + *maxd = 18 + plr[myplr]._pLevel; + break; + case SPL_HEALOTHER: + *mind = 1 + plr[myplr]._pLevel + sl; + if (plr[myplr]._pClass == CLASS_WARRIOR + || plr[myplr]._pClass == CLASS_MONK + || plr[myplr]._pClass == CLASS_BARBARIAN) *mind = *mind << 1; + if (plr[myplr]._pClass == CLASS_ROGUE || + plr[myplr]._pClass == CLASS_BARD ) *mind += (*mind >> 1); + *maxd = 10; + for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 4; + for (k = 0; k < sl; ++k) *maxd += 6; + if (plr[myplr]._pClass == CLASS_WARRIOR + || plr[myplr]._pClass == CLASS_MONK + || plr[myplr]._pClass == CLASS_BARBARIAN) *maxd = *maxd << 1; + if (plr[myplr]._pClass == CLASS_ROGUE || + plr[myplr]._pClass == CLASS_BARD ) *maxd += (*maxd >> 1); + *mind = -1; + *maxd = -1; + break; + case SPL_BSTAR: + *mind = ((plr[myplr]._pMagic>>1)-(plr[myplr]._pMagic>>3)) + (sl << 1) + sl; + *maxd = *mind; + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int CheckBlock(int fx, int fy, int tx, int ty) +{ + int pn, dir, coll; + + coll = 0; + + while ((fx != tx) || (fy != ty)) { + dir = GetDirection(fx, fy, tx, ty); + fx += XDirAdd[dir]; + fy += YDirAdd[dir]; + app_assert(fx < MAXDUNX && fx >= 0); + app_assert(fy < MAXDUNY && fy >= 0); + pn = dPiece[fx][fy]; + app_assert(pn <= MAXTILES && pn >= 0); + if (nSolidTable[pn]) coll = 1; + } + + return coll; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int FindClosest(int sx, int sy, int rad) +{ + int cr, cidx, cent, cne, mid, tx, ty; + + if (rad > 19) rad = 19; + + for (cr = 1; cr < rad; ++cr) { + cidx = CrawlNum[cr]; + cent = cidx + 1; + for (cne = CrawlTable[cidx]; cne > 0; --cne) { + tx = sx + CrawlTable[cent]; + ty = sy + CrawlTable[(cent + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + mid = dMonster[tx][ty]; + if ((mid > 0) && (CheckBlock(sx, sy, tx, ty) == 0)) + return (mid - 1); + } + cent += 2; + } + } + + return (-1); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static bool SetMissileLocation(int i, int *sx, int *sy, int rad) +{ + bool success = false; + + if (rad > 19) rad = 19; + + for (int cr = 0; cr < rad && !success; ++cr) { + int const cidx = CrawlNum[cr]; + int cent = cidx + 1; + for (int cne = CrawlTable[cidx]; cne > 0; --cne, cent += 2) { + int const tx = *sx + CrawlTable[cent]; + int const ty = *sy + CrawlTable[(cent + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int const pn = dPiece[tx][ty]; + if (!nSolidTable[pn] + && dObject[tx][ty] == 0 + && dMissile[tx][ty] == 0) { + missile[i]._mix = tx; + missile[i]._miy = ty; + *sx = tx; + *sy = ty; + success = true; + break; + } + } + } + } + + return (success); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int GetSpellLevel(int id, int sn) +{ + int rv; + + app_assert(id < MAX_PLRS && id >= 0); + app_assert(sn < 64 && sn >= 0); + if (id == myplr) + rv = plr[id]._pSplLvl[sn] + plr[id]._pISplLvlAdd; + else + rv = 1; + if (rv < 0 ) rv = 0; + return (rv); +} + +#if 0 // UNUSED +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RndBlood(int x, int y, int type, int dam, int hp) +{ + int pct, str; + + app_assert(hp != 0); + str = 0; + pct = (dam * 100) / hp; + if (pct > 65) str = 1; + if (pct > 80) str = 2; + if (pct > 90) str = 3; + str = 1; + + //AddMissile(x, y, str, 0, 0, type, 0, myplr, 0); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static int GetDirection8(int x1, int y1, int x2, int y2) +{ + BYTE const Dirs[16][16] = { + { 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 + { 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1 + { 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2 + { 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // 3 + { 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // 4 + { 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, // 5 + { 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 6 + { 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 7 + { 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 8 + { 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 9 + { 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 10 + { 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 11 + { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 12 + { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 13 + { 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 14 + { 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }};// 15 + + BYTE const lrtoul[3] = { 3, 4, 5 }; + BYTE const urtoll[3] = { 3, 2, 1 }; + BYTE const lltour[3] = { 7, 6, 5 }; + BYTE const ultolr[3] = { 7, 0, 1 }; + + int mx, my, md; + + mx = abs(x2 - x1); + if (mx > 15) mx = 15; + my = abs(y2 - y1); + if (my > 15) my = 15; + md = Dirs[my][mx]; + + if (x1 > x2) { + if (y1 > y2) md = lrtoul[md]; + else md = urtoll[md]; + } else { + if (y1 > y2) md = lltour[md]; + else md = ultolr[md]; + } + + return (md); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static int GetDirection16(int x1, int y1, int x2, int y2) +{ + const BYTE Dirs[16][16] = { + { 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 + { 4, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1 + { 4, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2 + { 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // 3 + { 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 4 + { 4, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 5 + { 4, 4, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 }, // 6 + { 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 }, // 7 + { 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1 }, // 8 + { 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1 }, // 9 + { 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1 }, // 10 + { 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1 }, // 11 + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }, // 12 + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }, // 13 + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2 }, // 14 + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2 }};// 15 + + BYTE const lrtoul[5] = { 6, 7, 8, 9, 10 }; + BYTE const urtoll[5] = { 6, 5, 4, 3, 2 }; + BYTE const lltour[5] = { 14, 13, 12, 11, 10 }; + BYTE const ultolr[5] = { 14, 15, 0, 1, 2 }; + + + int mx = abs(x2 - x1); + if (mx > 15) mx = 15; + + int my = abs(y2 - y1); + if (my > 15) my = 15; + + int md = Dirs[my][mx]; + + if (x1 > x2) { + if (y1 > y2) md = lrtoul[md]; + else md = urtoll[md]; + } else { + if (y1 > y2) md = lltour[md]; + else md = ultolr[md]; + } + + return (md); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DeleteMissile(int mi, int i) +{ + app_assert(nummissiles <= MAXMISSILES); + missileavail[MAXMISSILES - nummissiles] = mi; + --nummissiles; + + if ((nummissiles > 0) && (i != nummissiles)) { + app_assert(i < MAXMISSILES); + missileactive[i] = missileactive[nummissiles]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void GetMissileVel(int i, int sx, int sy, int dx, int dy, int v) +{ + app_assert(i < MAXMISSILES && i >= 0); + + double const dxp = (((dx - sx) << 5) - ((dy - sy) << 5)) << 16; + double const dyp = (((dx - sx) << 5) + ((dy - sy) << 5)) << 16; + double const dr = sqrt((dxp * dxp) + (dyp * dyp)); + + missile[i]._mixvel = static_cast(((v << 16) * dxp) / dr); + missile[i]._miyvel = static_cast(((v << 15) * dyp) / dr); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void PutMissile(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + int const mx = missile[i]._mix; + int const my = missile[i]._miy; + + if (mx <= 0 || my <= 0 || mx >= DMAXX || my >= DMAXY) + missile[i]._miDelFlag = TRUE; + + if (!missile[i]._miDelFlag) { + dFlags[mx][my] |= BFLAG_MISSILE; + if (dMissile[mx][my] == 0) dMissile[mx][my] = static_cast(i + 1); + else dMissile[mx][my] = -1; + if (missile[i]._miPreFlag) MissilePreFlag = TRUE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static BYTE GetDirNum(int mi) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + return (misfiledata[(missile[mi]._miAnimType)].mAnimFAmt >= 8) ? missile[mi]._mimfnum : 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void GetMissilePos(int i) +{ + long mx, my; + long dx, dy; + long lx, ly; // lighting offsets + + app_assert(i < MAXMISSILES && i >= 0); + mx = missile[i]._mitxoff >> 16; + my = missile[i]._mityoff >> 16; + dx = (mx + (my << 1)); + dy = ((my << 1) - mx); + + if (dx < 0) { + lx = -((-dx) >> 3); + dx = -((-dx) >> 6); + } else { + lx = dx >> 3; + dx = dx >> 6; + } + + if (dy < 0) { + ly = -((-dy) >> 3); + dy = -((-dy) >> 6); + } else { + ly = dy >> 3; + dy = dy >> 6; + } + + missile[i]._mix = dx + missile[i]._misx; + missile[i]._miy = dy + missile[i]._misy; + missile[i]._mixoff = mx - ((dx - dy) << 5); + missile[i]._miyoff = my - ((dx + dy) << 4); + ChangeLightOff(missile[i]._mlid, lx - (dx << 3), ly - (dy << 3)); +} + +/*-----------------------------------------------------------------------* + * MoveMissilePos + * + * Adjusts missile's drawing location to prevent overlapping tiles + * Written specifically for monster missiles (e.g., Rhino), which are large. +**-----------------------------------------------------------------------*/ + +static void MoveMissilePos(int i) +{ + int dx,dy; + int mx,my; + + app_assert(i < MAXMISSILES && i >= 0); + switch (missile[i]._mimfnum) { + case 0 : // Down + dx = 1; + dy = 1; + break; + case 1 : // Down Left + dx = 1; + dy = 1; + break; + case 2 : // Left + dx = 0; + dy = 1; + break; + case 3 : // Up Left + dx = 0; + dy = 0; + break; + case 4 : // Up + dx = 0; + dy = 0; + break; + case 5 : // Up Right + dx = 0; + dy = 0; + break; + case 6 : // Right + dx = 1; + dy = 0; + break; + case 7 : // Down Right + dx = 1; + dy = 1; + break; + } + + mx = missile[i]._mix + dx; + my = missile[i]._miy + dy; + + // note -- _misource is the monster which became this missile + if (PosOkMonst(missile[i]._misource,mx,my)) { + missile[i]._mix += dx; + missile[i]._miy += dy; + missile[i]._mixoff -= ((dx - dy) << 5); + missile[i]._miyoff -= ((dx + dy) << 4); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL MonsterTrapHit(int m, int mindam, int maxdam, int dist, int t, byte shift) +{ + int hit, hper; + long dam; + int mor; // monster's resist type + int mir; + BOOL resist = FALSE; + BOOL ret; + + app_assert(m < MAXMONSTERS && m >= 0); + if (monster[m].mtalkmsg != 0) return FALSE; + + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) return FALSE; + + app_assert(monster[m].MType != NULL); + if(monster[m].MType->mtype == MT_ILLWEAV && monster[m]._mgoal == MG_RUN_AWAY) + return FALSE; + + if (monster[m]._mmode == MM_MISSILE) return(FALSE); + + mir = missiledata[t].mResist; + mor = monster[m].mMagicRes; + if( (mor & M_IM && mir == MIMT_MISC) + || (mor & M_IF && mir == MIMT_FIRE) + || (mor & M_IL && mir == MIMT_LGHT)) + return FALSE; + + if( (mor & M_RM && mir == MIMT_MISC) + || (mor & M_RF && mir == MIMT_FIRE) + || (mor & M_RL && mir == MIMT_LGHT)) + resist = TRUE; + + hit = random(68, 100); + hper = 90 - monster[m].mArmorClass - dist; + if (hper < 5) hper = 5; + if (hper > 95) hper = 95; + if (CheckMonsterHit(m, ret)) + return(ret); +#if CHEATS + else if((hit < hper) || simplecheat || cheatflag || (monster[m]._mmode == MM_STONE)) { +#else + else if((hit < hper) || (monster[m]._mmode == MM_STONE)) { +#endif + dam = random(68, maxdam - mindam + 1) + mindam; + if (shift == 0) dam = dam << HP_SHIFT; + if (resist) + monster[m]._mhitpoints -= dam >> 2; + else + monster[m]._mhitpoints -= dam; + +#if CHEATS + if (simplecheat || cheatflag) monster[m]._mhitpoints = 0; +#endif + // rjs - x2 dam if stone - if (monster[m]._mmode == MM_STONE) monster[m]._mhitpoints -= dam; + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) { + if (monster[m]._mmode == MM_STONE) { + M_StartKill(m, -1); + monster[m]._mmode = MM_STONE; + } else M_StartKill(m, -1); + } + else if(resist) + { + PlayEffect(m, MS_GOTHIT); + } + else + { + if (monster[m]._mmode == MM_STONE) { + if (m > 3) M_StartHit(m, -1, dam); // dont let golems get hit + monster[m]._mmode = MM_STONE; + } else { + if (m > 3) M_StartHit(m, -1, dam); // dont let golems get hit + } + } + return(TRUE); + } else return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL MonsterMHit(int pnum, int m, int mindam, int maxdam, int dist, int t, byte shift) +{ + int hit, hper; + long dam; + int mor; // monster's resist type + int mir; // missile resistance category + BOOL resist = FALSE; + BOOL ret; + + app_assert(m < MAXMONSTERS && m >= 0); + if (monster[m].mtalkmsg != 0) return(FALSE); + + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) return(FALSE); + + app_assert(monster[m].MData != NULL); + if ((t == MIT_HBOLT) && + (monster[m].MType->mtype != MT_DIABLO) && + (monster[m].MData->mMonstClass != MC_UNDEAD)) return(FALSE); + + app_assert(monster[m].MType != NULL); + if(monster[m].MType->mtype == MT_ILLWEAV && monster[m]._mgoal == MG_RUN_AWAY) + return FALSE; + + if (monster[m]._mmode == MM_MISSILE) return(FALSE); + + mir = missiledata[t].mResist; + mor = monster[m].mMagicRes; + if( (mor & M_IM && mir == MIMT_MISC) + || (mor & M_IF && mir == MIMT_FIRE) + || (mor & M_IL && mir == MIMT_LGHT) + || (mor & M_IA && mir == MIMT_ACID)) + return FALSE; + + if( (mor & M_RM && mir == MIMT_MISC) + || (mor & M_RF && mir == MIMT_FIRE) + || (mor & M_RL && mir == MIMT_LGHT)) + resist = TRUE; + + if (t == MIT_HBOLT) + { + if ((monster[m].MType->mtype == MT_DIABLO) || + (monster[m].MType->mtype == MT_BONED2)) + resist = TRUE; + } + + hit = random(69, 100); + if (pnum != -1) { + if (missiledata[t].mType == MIS_WEAP) { + hper = BASE_TO_HIT + plr[pnum]._pLevel - monster[m].mArmorClass - plr[pnum]._pIEnAc; + hper += plr[pnum]._pDexterity + plr[pnum]._pIBonusToHit; + hper -= (dist * dist) >> 1; + if (plr[pnum]._pClass == CLASS_ROGUE) hper += 20; + if (plr[pnum]._pClass == CLASS_WARRIOR + || plr[pnum]._pClass == CLASS_BARD) hper += 10; + } else { + hper = BASE_TO_HIT + plr[pnum]._pMagic - (monster[m].mLevel << 1) - dist; + if (plr[pnum]._pClass == CLASS_SORCEROR) hper += 20; + else if (plr[pnum]._pClass == CLASS_BARD) hper += 10; + } + } + else { + hper = random(71,75) - (monster[m].mLevel * 2); + } + + if (hper < 5) hper = 5; + if (hper > 95) hper = 95; + if (monster[m]._mmode == MM_STONE) hit = 0; + if (CheckMonsterHit(m, ret)) + return(ret); +#if CHEATS + else if((hit < hper) || cheatflag || simplecheat) { +#else + else if (hit < hper) { +#endif + if (t == MIT_BONESPIRIT) + dam = (monster[m]._mhitpoints / 3) >> HP_SHIFT; + else + dam = random(70, maxdam - mindam + 1) + mindam; + if (missiledata[t].mType == MIS_WEAP) { + dam += (dam * plr[pnum]._pIBonusDam) / 100; + dam += plr[pnum]._pIBonusDamMod; + if (plr[pnum]._pClass == CLASS_ROGUE) dam += plr[pnum]._pDamageMod; + else dam += (plr[pnum]._pDamageMod >> 1); + } + if (shift == 0) dam = dam << HP_SHIFT; + if (resist) dam = dam >> 2; + if (pnum == myplr) monster[m]._mhitpoints -= dam; + + if (plr[pnum]._pIFlags & IAF_MNOHEAL) monster[m]._mFlags |= MFLAG_NOHEAL; +#if CHEATS + //if (pnum == myplr && cheatflag) monster[m]._mhitpoints = 0; +#endif + //rjs - x2 stone dam - if (pnum == myplr && monster[m]._mmode == MM_STONE) monster[m]._mhitpoints -= dam; + + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) { + if (monster[m]._mmode == MM_STONE) { + M_StartKill(m, pnum); + monster[m]._mmode = MM_STONE; + } else M_StartKill(m, pnum); + //(old) AddPlrExperience(pnum, monster[m].mLevel, monster[m].mExp); + //(new, but moved) AddPlrMonstExper(monster[m].mLevel, monster[m].mExp, monster[m].mWhoHit); + } + else if(resist) + { + PlayEffect(m, MS_GOTHIT); + } + else + { + if (monster[m]._mmode == MM_STONE) { + if (m > 3) M_StartHit(m, pnum, dam); + monster[m]._mmode = MM_STONE; + } else { + if ((missiledata[t].mType == MIS_WEAP) && (plr[pnum]._pIFlags & IAF_KNOCKBACK)) M_GetKnockback(m); + if (m > 3) M_StartHit(m, pnum, dam); + } + } + // wake up monster if it's inactive + if(!monster[m]._msquelch) + { + monster[m]._msquelch = 255; + monster[m]._lastx = plr[pnum]._px; + monster[m]._lasty = plr[pnum]._py; + } + return(TRUE); + } else return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PlayerMHit(int pnum, int m, int dist, int mind, int maxd, int mtype, byte shift, BOOL earflag, bool *wasBlocked) +{ + int hit, hper, tac; + long dam; + int blk, blkper, blkdir; + int resper = 0; + + *wasBlocked = false; + app_assert(pnum < MAX_PLRS && pnum >= 0); + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) return(FALSE); + if (plr[pnum]._pInvincible) return(FALSE); + if (((plr[pnum]._pSpellFlags & SF_ETHER) != 0) && (missiledata[mtype].mType == MIS_WEAP)) return(FALSE); + + hit = random(72, 100); +#if CHEATS + if (simplecheat || cheatflag) hit = 1000; +#endif + if (missiledata[mtype].mType == MIS_WEAP) { + // rjs tac = (byte)plr[pnum]._pArmorClass + plr[pnum]._pIAC + plr[pnum]._pIBonusAC; + tac = plr[pnum]._pIAC + plr[pnum]._pIBonusAC; + tac += (plr[pnum]._pDexterity / 5); + if (m != -1) hper = 30 + monster[m].mHit - tac + ((monster[m].mLevel - plr[pnum]._pLevel) << 1) - (dist << 1); + else hper = 100 - (tac >> 1) - (dist << 1); + } else { + if (m != -1) hper = 40 + (monster[m].mLevel << 1) - (plr[pnum]._pLevel << 1) - (dist << 1); + else hper = 40; + } + if (hper < 10) hper = 10; + if ((currlevel == 14) && (hper < 20)) hper = 20; + if ((currlevel == 15) && (hper < 25)) hper = 25; + if ((currlevel == 16) && (hper < 30)) hper = 30; + if (((plr[pnum]._pmode == PM_STAND) || (plr[pnum]._pmode == PM_ATTACK)) && (plr[pnum]._pBlockFlag)) blk = random(73, 100); + else blk = 100; + if (shift == 1) blk = 100; // can't block continous damage spells + if (mtype == MIT_ACIDPUD) blk = 100; // can't block acid puddles (drb) + if (m != -1) blkper = plr[pnum]._pBaseToBlk + plr[pnum]._pDexterity - ((monster[m].mLevel - plr[pnum]._pLevel) << 1); + else blkper = plr[pnum]._pBaseToBlk + plr[pnum]._pDexterity; + if (blkper < 0) blkper = 0; + if (blkper > 100) blkper = 100; + switch(missiledata[mtype].mResist) { + case MIMT_FIRE: + resper = plr[pnum]._pFireResist; + break; + case MIMT_LGHT: + resper = plr[pnum]._pLghtResist; + break; + case MIMT_MISC: + case MIMT_ACID: + resper = plr[pnum]._pMagResist; + break; + default: + resper = 0; + break; + } + if (hit < hper) { + // Hit, so calc damage + if (mtype == MIT_BONESPIRIT) { + dam = plr[pnum]._pHitPoints / 3; + } else { + if (shift == 0) { + dam = (maxd - mind + 1) << HP_SHIFT; + dam = random(75, dam) + (mind << HP_SHIFT); + if (plr[pnum]._pIFlags & IAF_TRAPDAM) dam = dam >> 1; + dam += (plr[pnum]._pIGetHit << HP_SHIFT); + if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT); + } else { + dam = maxd - mind + 1; + dam = random(75, dam) + mind; + if (plr[pnum]._pIFlags & IAF_TRAPDAM) dam = dam >> 1; + dam += plr[pnum]._pIGetHit; + if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT); + } + } + + // Did I block? + if (blk < blkper) { + if (m != -1) blkdir = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[m]._mx, monster[m]._my); + else blkdir = plr[pnum]._pdir; + *wasBlocked = true; + StartPlrBlock(pnum, blkdir); + return(TRUE); + } + // Did I resist? + if (resper > 0) { + dam -= (dam * resper) / 100; + if (pnum == myplr) { + plr[pnum]._pHitPoints -= dam; + plr[pnum]._pHPBase -= dam; + } + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + } + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - plr[pnum]._pHitPoints = 0; + StartPlrKill(pnum, earflag); + } + else { + // No get hit + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR69, plr[pnum]._px, plr[pnum]._py); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySfxLoc(PS_BARBARIAN69, plr[pnum]._px, plr[pnum]._py); + #endif + + //PlaySfxLoc(PS_LGHIT, plr[pnum]._px, plr[pnum]._py); + drawhpflag = TRUE; + } + return(TRUE); + } else { + if (pnum == myplr) { + plr[pnum]._pHitPoints -= dam; + plr[pnum]._pHPBase -= dam; + } + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + } + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - plr[pnum]._pHitPoints = 0; + StartPlrKill(pnum, earflag); + } else StartPlrHit(pnum, dam, FALSE); + return(TRUE); + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static BOOL Plr2PlrMHit(int pnum, int p, int mindam, int maxdam, int dist, int mtype, byte shift, bool *wasBlocked) +{ + int hit, hper, tac; + long dam; + int blk, blkper, blkdir; + int resper; + + // pnum is missiles source + // p is missiles dest + + app_assert(p < MAX_PLRS && p >= 0); + *wasBlocked = false; + if (plr[p]._pInvincible) return(FALSE); + if (mtype == MIT_HBOLT) return(FALSE); + if (((plr[p]._pSpellFlags & SF_ETHER) != 0) && (missiledata[mtype].mType == MIS_WEAP)) return(FALSE); + + switch(missiledata[mtype].mResist) { + case MIMT_FIRE: + resper = plr[p]._pFireResist; + break; + case MIMT_LGHT: + resper = plr[p]._pLghtResist; + break; + case MIMT_MISC: + case MIMT_ACID: + resper = plr[p]._pMagResist; + break; + default: + resper = 0; + break; + } + hit = random(69, 100); + if (missiledata[mtype].mType == MIS_WEAP) { + //rjs tac = (byte)plr[p]._pArmorClass + plr[p]._pIAC + plr[p]._pIBonusAC; + tac = plr[p]._pIAC + plr[p]._pIBonusAC; + tac += (plr[p]._pDexterity / 5); + hper = BASE_TO_HIT + plr[pnum]._pLevel - tac; + hper += plr[pnum]._pDexterity + plr[pnum]._pIBonusToHit; + hper -= (dist * dist) >> 1; + if (plr[pnum]._pClass == CLASS_ROGUE) hper += 20; + if (plr[pnum]._pClass == CLASS_WARRIOR + || plr[pnum]._pClass == CLASS_BARD) hper += 10; + } else { + hper = BASE_TO_HIT + plr[pnum]._pMagic - (plr[p]._pLevel << 1) - dist; + if (plr[pnum]._pClass == CLASS_SORCEROR ) hper += 20; + else if (plr[pnum]._pClass == CLASS_BARD) hper += 10; + } + if (hper < 5) hper = 5; + if (hper > 95) hper = 95; + if (hit < hper) { + // Hit, calc blk % + if (((plr[p]._pmode == PM_STAND) || (plr[p]._pmode == PM_ATTACK)) && (plr[p]._pBlockFlag)) blk = random(73, 100); + else blk = 100; + if (shift == 1) blk = 100; // can't block continous damage spells + blkper = plr[p]._pBaseToBlk + plr[p]._pDexterity - ((plr[pnum]._pLevel - plr[p]._pLevel) << 1); + if (blkper < 0) blkper = 0; + if (blkper > 100) blkper = 100; + // Hit, so calc damage + if (mtype == MIT_BONESPIRIT) { + dam = plr[p]._pHitPoints / 3; + } else { + dam = random(70, maxdam - mindam + 1) + mindam; + if (missiledata[mtype].mType == MIS_WEAP) { + dam += (dam * plr[pnum]._pIBonusDam) / 100; + dam += plr[pnum]._pIBonusDamMod + plr[pnum]._pDamageMod; + } + if (shift == 0) dam = dam << HP_SHIFT; + } + // NEW! Take 1/2 damage from plr spells (drb 11/23) + if (missiledata[mtype].mType != MIS_WEAP) dam = dam >> 1; + // Did I resist? + if (resper > 0) { + dam -= (dam * resper) / 100; + // No get hit + if (pnum == myplr) NetSendCmdDamage(TRUE, p, dam); + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR69, plr[pnum]._px, plr[pnum]._py); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySfxLoc(PS_BARBARIAN69, plr[pnum]._px, plr[pnum]._py); + #endif + + //PlaySfxLoc(PS_LGHIT, plr[p]._px, plr[p]._py); + return(TRUE); + } else { + // Did I block? + if (blk < blkper) { + blkdir = GetDirection(plr[p]._px, plr[p]._py, plr[pnum]._px, plr[pnum]._py); + StartPlrBlock(p, blkdir); + *wasBlocked = true; + return(TRUE); + } else { + if (pnum == myplr) NetSendCmdDamage(TRUE, p, dam); + StartPlrHit(p, dam, FALSE); + return(TRUE); + } + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void CheckMissileCol(int i, int mindam, int maxdam, byte shift, int mx, int my, byte nodel) +{ + int pn,oi; + BOOL earflag; + bool wasBlocked; + + if (!(i < MAXMISSILES && i >= 0)) return; + if (!(mx < MAXDUNX && mx >= 0)) return; + if (!(my < MAXDUNY && my >= 0)) return; + + if (missile[i]._micaster == MI_ENEMYBOTH || missile[i]._misource == -1){ + // Traps and fire and lightning walls. + if (dMonster[mx][my] > 0) { + if (missile[i]._micaster == MI_ENEMYBOTH) { + if (MonsterMHit(missile[i]._misource, dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } else { + if (MonsterTrapHit(dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + } + if (dPlayer[mx][my] > 0) { + if (missile[i]._miAnimType == MF_FIRE + || missile[i]._miAnimType == MF_LIGHTNING) earflag = TRUE; + else earflag = FALSE; + if (PlayerMHit(dPlayer[mx][my] - 1, -1, missile[i]._midist, mindam, maxdam, missile[i]._mitype, shift, earflag, &wasBlocked)) { + if (wasBlocked) + { + int newdir = missile[i]._mimfnum + (random(10, 2) ? 1 : -1); + int numdirsAvail = misfiledata[missile[i]._miAnimType].mAnimFAmt; + if (newdir < 0) + newdir = numdirsAvail - 1; + else if (newdir > numdirsAvail) + newdir = 0; + + SetMissDir(i, newdir); // Changes the animation, but the missile keeps going. + } + else + { + if (nodel == 0) missile[i]._mirange = 0; + } + missile[i]._miHitFlag = TRUE; + } + } + } else { + if (missile[i]._micaster == MI_ENEMYMONST) { + if (dMonster[mx][my] > 0) { + if (MonsterMHit(missile[i]._misource, dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } else { + if ((dMonster[mx][my] < 0) && (monster[-(dMonster[mx][my] + 1)]._mmode == MM_STONE)) { + if (MonsterMHit(missile[i]._misource, -(dMonster[mx][my] + 1), mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + } + if ((dPlayer[mx][my] > 0) && ((dPlayer[mx][my]-1) != missile[i]._misource)) { + if (Plr2PlrMHit(missile[i]._misource, dPlayer[mx][my]-1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift, &wasBlocked)) { + if (wasBlocked) + { + int newdir = missile[i]._mimfnum + (random(10, 2) ? 1 : -1); + int numdirsAvail = misfiledata[missile[i]._miAnimType].mAnimFAmt; + if (newdir < 0) + newdir = numdirsAvail - 1; + else if (newdir > numdirsAvail) + newdir = 0; + + SetMissDir(i, newdir); // Changes the animation, but the missile keeps going. + } + else + { + if (nodel == 0) missile[i]._mirange = 0; + } + missile[i]._miHitFlag = TRUE; + } + } + } else { + if (((monster[missile[i]._misource]._mFlags & MFLAG_MID) != 0) && ((dMonster[mx][my] > 0) && (monster[(dMonster[mx][my] - 1)]._mFlags & MFLAG_MKILLER) != 0)) { + if (MonsterTrapHit(dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + if (dPlayer[mx][my] > 0) { + if (PlayerMHit(dPlayer[mx][my] - 1, missile[i]._misource, missile[i]._midist, mindam, maxdam, missile[i]._mitype, shift, FALSE, &wasBlocked)) { + if (wasBlocked) + { + int newdir = missile[i]._mimfnum + (random(10, 2) ? 1 : -1); + int numdirsAvail = misfiledata[missile[i]._miAnimType].mAnimFAmt; + if (newdir < 0) + newdir = numdirsAvail - 1; + else if (newdir > numdirsAvail) + newdir = 0; + + SetMissDir(i, newdir); // Changes the animation, but the missile keeps going. + } + else + { + if (nodel == 0) missile[i]._mirange = 0; + } + missile[i]._miHitFlag = TRUE; + } + } + } + } + + if (dObject[mx][my] != 0) { + if (dObject[mx][my] > 0) oi = dObject[mx][my] - 1; + else oi = -(dObject[mx][my] + 1); + if (!object[oi]._oMissFlag) { + if (object[oi]._oBreak == OBJ_BREAKABLE) BreakObject(-1, oi); + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = FALSE; + } + } + + pn = dPiece[mx][my]; + app_assert(pn <= MAXTILES && pn >= 0); + if (nMissileTable[pn]) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = FALSE; + } + + if ((missile[i]._mirange == 0) && (missiledata[missile[i]._mitype].miSFX != -1)) { + PlaySfxLoc(missiledata[missile[i]._mitype].miSFX, missile[i]._mix, missile[i]._miy); + } +} + +static void SetMissAnim(int mi, int animtype) +{ + int dir; + + app_assert(mi < MAXMISSILES && mi >= 0); + dir = missile[mi]._mimfnum; + missile[mi]._miAnimType = animtype; + + missile[mi]._miAnimFlags = misfiledata[animtype].mFlags; + missile[mi]._miAnimData = misfiledata[animtype].mAnimData[dir]; + missile[mi]._miAnimDelay = misfiledata[animtype].mAnimDelay[dir]; + missile[mi]._miAnimLen = misfiledata[animtype].mAnimLen[dir]; + missile[mi]._miAnimWidth = misfiledata[animtype].mAnimWidth[dir]; + missile[mi]._miAnimWidth2 = misfiledata[animtype].mAnimWidth2[dir]; + missile[mi]._miAnimCnt = 0; + missile[mi]._miAnimFrame = 1; +} + + +void SetMissDir(int mi, int dir) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mimfnum = dir; + SetMissAnim(mi, missile[mi]._miAnimType); +} + +/*-----------------------------------------------------------------------** +**---------------------- Initialization Routines ------------------------** +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +void ILoadMissileGFX(BYTE mf) { + int i; + char strbuff[256]; + BYTE *p; + MisFileData * pMisDat; + + pMisDat = &misfiledata[mf]; + if (pMisDat->mFlags & MFF_MULTI) { + // All directions are packed into one file + sprintf(strbuff,"Missiles\\%s" CEL_EXT, pMisDat->mAnimPath); + p = LoadFileInMemSig(strbuff,NULL,'MISS'); + for (i = 0; i < pMisDat->mAnimFAmt; ++i) + pMisDat->mAnimData[i] = p + (reinterpret_cast(p))[i]; + } + else if (pMisDat->mAnimFAmt == 1) { + sprintf(strbuff,"Missiles\\%s" CEL_EXT, pMisDat->mAnimPath); + if(! pMisDat->mAnimData[0]) + pMisDat->mAnimData[0] = LoadFileInMemSig(strbuff,NULL,'MISS'); + } + else { + for (i = 0; i < pMisDat->mAnimFAmt; ++i) { + sprintf(strbuff, "Missiles\\%s%i" CEL_EXT, pMisDat->mAnimPath, i + 1); + if(! pMisDat->mAnimData[i]) + pMisDat->mAnimData[i] = LoadFileInMemSig(strbuff,NULL,'MISS'); + } + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +void ILoadMissileGFX(BYTE mf) { + int i; + char strbuff[256]; + BYTE *p; + + if (misfiledata[mf].mFlags & MFF_MULTI) { + // All directions are packed into one file + sprintf(strbuff,"Missiles\\%s.CEL", misfiledata[mf].mAnimPath); + p = LoadFileInMemSig(strbuff,NULL,'MISS'); + for (i = 0; i < misfiledata[mf].mAnimFAmt; ++i) { + misfiledata[mf].mAnimData[i] = p + *reintrepret_cast(p + (i<<2)); + } + } + else if (misfiledata[mf].mAnimFAmt == 1) { + sprintf(strbuff,"Missiles\\%s.CEL", misfiledata[mf].mAnimPath); + if(! misfiledata[mf].mAnimData[0]) + misfiledata[mf].mAnimData[0] = LoadFileInMemSig(strbuff,NULL,'MISS'); + } else { + for (i = 0; i < misfiledata[mf].mAnimFAmt; ++i) { + sprintf(strbuff, "Missiles\\%s%i.CEL", misfiledata[mf].mAnimPath, i + 1); + if(! misfiledata[mf].mAnimData[i]) + misfiledata[mf].mAnimData[i] = LoadFileInMemSig(strbuff,NULL,'MISS'); + } + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitMissileGFX() +{ + int i; + + for (i = 0; misfiledata[i].mAnimFAmt; ++i) { + if (!(misfiledata[i].mFlags & MFF_MONSTONLY)) { + ILoadMissileGFX(i); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void FreeMissileFile(int i) +{ + int j; + void * y; + + if (misfiledata[i].mFlags & MFF_MULTI) + { + if(misfiledata[i].mAnimData[0]) + { + y = static_cast (misfiledata[i].mAnimData[0] - (misfiledata[i].mAnimFAmt << 2)); + DiabloFreePtr(y); + misfiledata[i].mAnimData[0] = NULL; + } + } + else + { + for (j = 0; j < misfiledata[i].mAnimFAmt; ++j) + if(misfiledata[i].mAnimData[j]) + { + DiabloFreePtr(misfiledata[i].mAnimData[j]); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreeMissileGFX() +{ + int i; + + for (i = 0; misfiledata[i].mAnimFAmt; ++i) { + if (!(misfiledata[i].mFlags & MFF_MONSTONLY)) { + FreeMissileFile(i); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void IFreeMissileGFX() +{ + int i; + + for (i = 0; misfiledata[i].mAnimFAmt; ++i) + if(misfiledata[i].mFlags & MFF_MONSTONLY) + FreeMissileFile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitMissiles() +{ + int i, j, mx; + + // Delete any active infravision/ etheralize + HighLightAllItems = false; + plr[myplr]._pSpellFlags &= ~SF_ETHER; + if (plr[myplr]._pInfraFlag == TRUE) { + app_assert(nummissiles <= MAXMISSILES); + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + app_assert(mx < MAXMISSILES && mx >= 0); + if ((missile[mx]._mitype == MIT_INFRA) && (missile[mx]._misource == myplr)) + CalcPlrItemVals(missile[mx]._misource,TRUE); + } + } + + if (((plr[myplr]._pSpellFlags & SF_RAGE) == SF_RAGE) + || ((plr[myplr]._pSpellFlags & SF_LETHERGY) == SF_LETHERGY)) + { + plr[myplr]._pSpellFlags &= ~SF_RAGE; + plr[myplr]._pSpellFlags &= ~SF_LETHERGY; + app_assert(nummissiles <= MAXMISSILES); + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + app_assert(mx < MAXMISSILES && mx >= 0); + if ((missile[mx]._mitype == MIT_RAGE) && (missile[mx]._misource == myplr)) + { + int const diffHpts = plr[myplr]._pMaxHP - plr[myplr]._pHitPoints; + CalcPlrItemVals(myplr,TRUE); + plr[myplr]._pHitPoints -= missile[mx]._miVar2 + diffHpts; + if (plr[myplr]._pHitPoints < (1 << HP_SHIFT)) { + // Don't quite die. + plr[myplr]._pHitPoints = 1 << HP_SHIFT; + } + } + } + } + + nummissiles = 0; + for (i = 0; i < MAXMISSILES; ++i) { + missileavail[i] = i; + missileactive[i] = 0; + } + + nummissilevars = 0; + for (i = 0; i < MAXMISSILES; ++i) { + missilevars[i][0] = -1; + missilevars[i][1] = 0; + missilevars[i][2] = 0; + } + + for (j = 0; j < DMAXY; ++j) { + for (i = 0; i < DMAXX; ++i) { + dFlags[i][j] = dFlags[i][j] & ~BFLAG_MISSILE; + } + } + + // Zero out all the reflect spells. + //for (j = 0; j < gbMaxPlayers; ++j) { + // plr[j]._pReflectCount = 0; + //} + plr[myplr]._pReflectCount = 0; +} + +/*-----------------------------------------------------------------------** +**------------------ Missile Initialization Routines --------------------** +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddReallyBigExp(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + AddMissile (80, 62, 80, 62, midir, MIT_BIGEXPLOSION, mienemy, id, dam, 0); + AddMissile (80, 63, 80, 62, midir, MIT_BIGEXPLOSION, mienemy, id, dam, 0); + AddMissile (81, 62, 80, 62, midir, MIT_BIGEXPLOSION, mienemy, id, dam, 0); + AddMissile (81, 63, 80, 62, midir, MIT_BIGEXPLOSION, mienemy, id, dam, 0); + missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfFire(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (LineClear(sx, sy, dx, dy)) + { + if (id >= 0) { + UseMana(id, SPL_RUNEOFFIRE); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_BIGEXPLOSION; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + } + else missile[mi]._miDelFlag = TRUE; + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfLight(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (LineClear(sx, sy, dx, dy)) + { + if (id >= 0) { + UseMana(id, SPL_RUNEOFLIGHT); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_LIGHTBALL; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + } + else missile[mi]._miDelFlag = TRUE; + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfNova(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (LineClear(sx, sy, dx, dy)) + { + if (id >= 0) { + UseMana(id, SPL_RUNEOFNOVA); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_NOVA; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + } + else missile[mi]._miDelFlag = TRUE; + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfImmolation(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (LineClear(sx, sy, dx, dy)) + { + if (id >= 0) { + UseMana(id, SPL_RUNEOFIMMOLATION); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_IMMOLATION; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + + } + else missile[mi]._miDelFlag = TRUE; + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfStone(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (LineClear(sx, sy, dx, dy)) + { + if (id >= 0) { + UseMana(id, SPL_RUNEOFSTONE); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_STONE; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + } + else missile[mi]._miDelFlag = TRUE; + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddReflect(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + if (plr[id]._pReflectCount < 0) + plr[id]._pReflectCount = 0; + + plr[id]._pReflectCount += ((missile[mi]._mispllvl) ? missile[mi]._mispllvl : 2 ) * plr[id]._pLevel; + UseMana(id, SPL_REFLECT); + } + missile[mi]._mirange = 0; + missile[mi]._miDelFlag = FALSE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBerserk(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._misource = id; + + // search in a 5 radius around tile clicked for monster + for (int k = 0; k < 6; ++k) { + int const l = CrawlNum[k]; + int j = l + 1; + for (int i = CrawlTable[l]; i > 0; --i, j += 2) { + int const tx = dx + CrawlTable[j]; + int const ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int mid = dMonster[tx][ty]; + if (mid > 0) --mid; + else mid = -(mid + 1); + + if ((mid > 3) + && (monster[mid]._uniqtype == 0) + && (monster[mid]._mAi != AI_DIABLO) + && (monster[mid]._mmode != MM_FADEIN) + && (monster[mid]._mmode != MM_FADEOUT) + //&& (monster[mid]._mmode != MM_DEATH) + && ((monster[mid].mMagicRes & M_IM) == 0) + && (((monster[mid].mMagicRes & M_RM) == 0) || + (((monster[mid].mMagicRes & M_RM) == M_RM) && 0 == random(99, 2))) + && (monster[mid]._mmode != MM_MISSILE)) { + i = -99; + k = 6; + int const SpellLevel = GetSpellLevel(id, SPL_BERSERK); + monster[mid]._mFlags |= MFLAG_BERSERK | MFLAG_MKILLER; + monster[mid].mMinDamage = static_cast(SpellLevel + monster[mid].mMinDamage * (1.0 + (0.01 * (random(145,10) + 20)))); + monster[mid].mMaxDamage = static_cast(SpellLevel + monster[mid].mMaxDamage * (1.0 + (0.01 * (random(145,10) + 20)))); + monster[mid].mMinDamage2 = static_cast(SpellLevel + monster[mid].mMinDamage2 * (1.0 + (0.01 * (random(145,10) + 20)))); + monster[mid].mMaxDamage2 = static_cast(SpellLevel + monster[mid].mMaxDamage2 * (1.0 + (0.01 * (random(145,10) + 20)))); + + monster[mid].mlid = AddLight(monster[mid]._mx, monster[mid]._my, + ((currlevel >= HIVESTART && currlevel <= HIVEEND) ? 9 : 3)); + + UseMana(id, SPL_BERSERK); + break; + } + } + } + } + } + missile[mi]._mirange = 0; + missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddHorkSpawn(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + + GetMissileVel(mi, sx, sy, dx, dy, 8); + missile[mi]._mirange = 9; + missile[mi]._miVar1 = midir; + PutMissile(mi); +} + +void AddRandom(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + + // Let the random spell do the call, otherwise staff's use up 2 charges. + // if (id >= 0) { + // UseMana(id, SPL_RANDOM); + // } + int mitype = MIT_FIREBOLT; + int const r = random(255, 10); + switch(r) + { + case 0: // fall through + case 1: mitype = MIT_FIREBOLT; break; + case 2: mitype = MIT_FIREBALL; break; + case 3: mitype = MIT_FIREWALLC; break; + case 4: mitype = MIT_GUARDIAN; break; + case 5: mitype = MIT_CHAIN; break; + case 6: mitype = MIT_TOWN; UseMana(id, SPL_TOWN); break; + case 7: mitype = MIT_TELE; break; + case 8: mitype = MIT_APOCA; break; + case 9: mitype = MIT_STONE; break; + default: break; + } + AddMissile (sx, sy, dx, dy, midir, mitype, + missile[mi]._micaster, missile[mi]._misource, + 0, missile[mi]._mispllvl); + + missile[mi]._miDelFlag = TRUE; + missile[mi]._mirange = 0; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddDisEnchant(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._misource = id; + + // search in a 3 radius around chest trap for players. + for (int k = 0; k < 3; ++k) { + int const l = CrawlNum[k]; + int j = l + 1; + for (int i = CrawlTable[l]; i > 0; --i, j += 2) { + int const tx = sx + CrawlTable[j]; + int const ty = sy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int pid = dPlayer[tx][ty]; + + if (pid == 0) + continue; + + if (pid > 0) --pid; + else pid = -(pid + 1); + + + int newidata; + BOOL everplayed = FALSE; + + // Belt items only. + for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) + { + newidata = -1; + + if (plr[pid].SpdList[splIndex]._itype == IT_MISC) + { + int what; + int const killed = random(205, 2); + if (!killed) + continue; + + switch(plr[pid].SpdList[splIndex]._iMiscId) { + case IMID_PLHEAL: + case IMID_PMANA: + RemoveSpdBarItem(pid, splIndex); + continue; + + case IMID_REJUV: + what = random(205, 2); + switch(what) + { + case 0: + newidata = ItemMiscIdIdx(IMID_PLHEAL); + break; + default: + newidata = ItemMiscIdIdx(IMID_PMANA); + break; + } + + case IMID_PHEAL: + newidata = ItemMiscIdIdx(IMID_PLHEAL); + break; + case IMID_PFMANA: + newidata = ItemMiscIdIdx(IMID_PMANA); + break; + case IMID_FREJUV: + what = random(205, 3); + switch(what) + { + case 0: + newidata = ItemMiscIdIdx(IMID_PFMANA); + break; + case 1: + newidata = ItemMiscIdIdx(IMID_PHEAL); + break; + default: + newidata = ItemMiscIdIdx(IMID_REJUV); + break; + } + break; + + default: + continue; + } + } + if (newidata != -1) { + SetPlrHandItem(&plr[pid].HoldItem, newidata); + GetPlrHandSeed(&plr[pid].HoldItem); + plr[pid].HoldItem._iStatFlag = TRUE; + plr[pid].SpdList[splIndex] = plr[pid].HoldItem; + } + if (!everplayed) + { + PlaySfxLoc(IS_URN, tx, ty); + everplayed = TRUE; + } + } + force_redraw = FULLDRAW; + } + } + } + missile[mi]._mirange = 0; + missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddManaRemove(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._misource = id; + + // search in a 3 radius around chest trap for players. + for (int k = 0; k < 3; ++k) { + int const l = CrawlNum[k]; + int j = l + 1; + for (int i = CrawlTable[l]; i > 0; --i, j += 2) { + int const tx = sx + CrawlTable[j]; + int const ty = sy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int pid = dPlayer[tx][ty]; + + if (pid == 0) + continue; + + if (pid > 0) --pid; + else pid = -(pid + 1); + + plr[pid]._pMana = 0; + plr[pid]._pManaBase = plr[pid]._pMana - (plr[pid]._pMaxMana - plr[pid]._pMaxManaBase); + CalcPlrInv(pid, FALSE); + drawmanaflag = TRUE; + PlaySfxLoc(TSFX_COW7, tx, ty); + } + } + } + missile[mi]._mirange = 0; + missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES && mi >= 0); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + if (mienemy == MI_ENEMYMONST) { + int av=32; + if (plr[id]._pClass == CLASS_ROGUE) av += plr[id]._pLevel>>2; + else if (plr[id]._pClass == CLASS_WARRIOR + || plr[id]._pClass == CLASS_BARD) av += plr[id]._pLevel>>3; + if (plr[id]._pIFlags & IAF_ATANIM1) av += 1; + if (plr[id]._pIFlags & IAF_ATANIM2) av += 2; + if (plr[id]._pIFlags & IAF_ATANIM3) av += 4; + if (plr[id]._pIFlags & IAF_ATANIM4) av += 8; + + GetMissileVel(mi,sx,sy,dx,dy,av); + } else GetMissileVel(mi,sx,sy,dx,dy,32); + + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 5); + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int av; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + if (mienemy == MI_ENEMYMONST) { + av = 32; + if (plr[id]._pIFlags & IAF_RNDARROW) av = random(64, 32) + 16; // rnd arrow speed + if (plr[id]._pClass == CLASS_ROGUE) av += (plr[id]._pLevel-1) >> 2; // rouge level speed increase + else if (plr[id]._pClass == CLASS_WARRIOR + || plr[id]._pClass == CLASS_BARD) av += (plr[id]._pLevel-1) >> 3; // warrior level speed increase + + if (plr[id]._pIFlags & IAF_ATANIM1) av += 1; + if (plr[id]._pIFlags & IAF_ATANIM2) av += 2; + if (plr[id]._pIFlags & IAF_ATANIM3) av += 4; + if (plr[id]._pIFlags & IAF_ATANIM4) av += 8; + + GetMissileVel(mi,sx,sy,dx,dy,av); + } else GetMissileVel(mi,sx,sy,dx,dy,32); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miAnimFrame = GetDirection16(sx,sy,dx,dy) + 1; + + missile[mi]._mirange = 256; + + //PutMissile(mi); +} + +void AddSpecialArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int extraspeed = 0; + +// if ((sx == dx) && (sy == dy)) { +// dx += XDirAdd[midir]; +// dy += YDirAdd[midir]; +// } + + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST) + { + if (plr[id]._pClass == CLASS_ROGUE) + extraspeed = (plr[id]._pLevel-1) >> 2; // rogue level speed increase + else if (plr[id]._pClass == CLASS_WARRIOR + || plr[id]._pClass == CLASS_BARD) + extraspeed = (plr[id]._pLevel-1) >> 3; // warrior level speed increase + + if (plr[id]._pIFlags & IAF_ATANIM1) extraspeed += 1; + if (plr[id]._pIFlags & IAF_ATANIM2) extraspeed += 2; + if (plr[id]._pIFlags & IAF_ATANIM3) extraspeed += 4; + if (plr[id]._pIFlags & IAF_ATANIM4) extraspeed += 8; + } + + missile[mi]._mirange = 1; + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + missile[mi]._miVar3 = extraspeed; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GetVileMissPos(int mi, int dx, int dy) +{ + int xx, yy; + app_assert(mi < MAXMISSILES && mi >= 0); + for (int l = 1; l < 50; ++l) { + for (int j = -l; j <= l; ++j) { + yy = dy + j; + for (int i = -l; i <= l; ++i) { + xx = dx + i; + if (PosOkPlayer(myplr,xx,yy)) { + missile[mi]._mix = xx; + missile[mi]._miy = yy; + return; + } + } + } + } + // There is just no way it will ever reach here + missile[mi]._mix = dx; + missile[mi]._miy = dy; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#define DIST(x,y,d) (abs(x) < d && abs(y) < d) + +// Flag for fireman missile +#define MIF_DIDHIT 1 + +#define MINAWAY 3 +#define MAXAWAY 6 + +void AddRndTeleport(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_PHASE) || !PRE_BETA + int pn, r1, r2; + + int nTries = 0; + do { + // don't get stuck in an infinite loop... + if (++nTries > 500) { + r1 = 0; + r2 = 0; + break; + } + + r1 = random(58, MAXAWAY - MINAWAY) + MINAWAY + 1; + r2 = random(58, MAXAWAY - MINAWAY) + MINAWAY + 1; + if (random(58, 2) == 1) r1 = -r1; + if (random(58, 2) == 1) r2 = -r2; + + r1 = sx + r1; + r2 = sy + r2; + + if (r1 > MAXDUNX + || r1 < 0 + || r2 > MAXDUNY + || r2 < 0) + continue; + + pn = dPiece[r1][r2]; + } while (nSolidTable[pn] != 0 + || dObject[r1][r2] != 0 + || dMonster[r1][r2] != 0); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mirange = 2; + missile[mi]._miVar1 = 0; + +// special code for Vile Betrayer quest + if ((setlevel) && (setlvlnum == 5)) { + int oi = dObject[dx][dy]-1; + if ((object[oi]._otype == OBJ_MCIRCLE1) || (object[oi]._otype == OBJ_MCIRCLE2)) { + missile[mi]._mix = dx; + missile[mi]._miy = dy; + if (!PosOkPlayer(myplr, dx, dy)) GetVileMissPos(mi, dx, dy); + } + } + else { + missile[mi]._mix = r1; + missile[mi]._miy = r2; + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_PHASE); + } + +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +#undef max +void AddTeleStairs(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int minDist = std::numeric_limits::is_specialized && std::numeric_limits::is_bounded + ? std::numeric_limits::max() : 99999; + if (id >= 0) { + sx = plr[id]._px; + sy = plr[id]._py; + } + + int rx = sx; + int ry = sy; + + for (int i = 0;i < numtrigs && i < MAXTRIGGERS; ++i) { + if (trigs[i]._tmsg == WM_DIABTWARPUP + || trigs[i]._tmsg == WM_DIABPREVLVL + || trigs[i]._tmsg == WM_DIABNEXTLVL + || trigs[i]._tmsg == WM_DIABRTNLVL) { + + int triggerx; + int triggery; + + if ((leveltype == 1 || leveltype == 2) + && (trigs[i]._tmsg == WM_DIABNEXTLVL + || trigs[i]._tmsg == WM_DIABPREVLVL + || trigs[i]._tmsg == WM_DIABRTNLVL) ){ + triggerx = trigs[i]._tx; + triggery = trigs[i]._ty + 1; + } + else { + triggerx = trigs[i]._tx + 1; + triggery = trigs[i]._ty; + } + + int xdiff = sx - triggerx; + xdiff *= xdiff; + int ydiff = sy - triggery; + ydiff *= ydiff; + int const NewDist = xdiff + ydiff; + + if (NewDist < minDist) + { + minDist = NewDist; + rx = triggerx; + ry = triggery; + } + + } + } + + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mirange = 2; + missile[mi]._miVar1 = 0; + missile[mi]._mix = rx; + missile[mi]._miy = ry; + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_TELESTAIRS); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFirebolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBOLT) || !PRE_BETA + int sp, i, mx; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + + app_assert(mi < MAXMISSILES && mi >= 0); + if (micaster == MI_ENEMYMONST) + { + app_assert(nummissiles <= MAXMISSILES); + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + app_assert(mx < MAXMISSILES && mx >= 0); + if ((missile[mx]._mitype == MIT_GUARDIAN) && + (missile[mx]._misource == id) && (missile[mx]._miVar3 == mi)) { + break; + } + } + if (i == nummissiles) UseMana(id, SPL_FIREBOLT); + + if (id != -1) { + sp = 16 + (missile[mi]._mispllvl << 1); + if (sp >= 63) sp = 63; + } else sp = 16; + } + else + sp = 26; + + GetMissileVel(mi,sx,sy,dx,dy,sp); + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddMagmaball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + + app_assert(mi < MAXMISSILES && mi >= 0); + // Graphics don't line up, so we have to move them... + missile[mi]._mitxoff += 3*missile[mi]._mixvel; + missile[mi]._mityoff += 3*missile[mi]._miyvel; + + GetMissilePos(mi); + + if ((missile[mi]._mixvel >> 16) == 0 + && (missile[mi]._miyvel >> 16) == 0) + { + missile[mi]._mirange = 1; + } + else + { + missile[mi]._mirange = 256; + } + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddKrull(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; +// missile[mi]._mlid = AddLight(sx, sy, 8); + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_TELE) || !PRE_BETA + int i, pn; + int k, l, j; + int tx, ty; + + app_assert(dx < MAXDUNX && dx >= 0); + app_assert(dy < MAXDUNY && dy >= 0); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + if ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty] | dPlayer[tx][ty]) == 0) { + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = tx; + missile[mi]._misy = ty; + missile[mi]._miDelFlag = FALSE; + k = 6; + break; + } + } + j += 2; + } + } + + if (missile[mi]._miDelFlag == FALSE) { + UseMana(id, SPL_TELE); + missile[mi]._mirange = 2; + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLightball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = dam; + + missile[mi]._miAnimFrame = random(63, 8) + 1; + + missile[mi]._mirange = 255; + + if (id < 0) { + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + } else { + missile[mi]._miVar1 = plr[id]._px; + missile[mi]._miVar2 = plr[id]._py; + } + + //PutMissile(mi); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLightwall(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = dam; + + missile[mi]._miAnimFrame = random(63, 8) + 1; + + missile[mi]._mirange = 255 + (255 * missile[mi]._mispllvl); + + if (id < 0) { + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + } else { + missile[mi]._miVar1 = plr[id]._px; + missile[mi]._miVar2 = plr[id]._py; + } + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFirewall(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = (random(53, 10) + random(53, 10) + 2 + (id > 0) ? plr[id]._pLevel : currlevel) << 4; + missile[mi]._midam = missile[mi]._midam >> 1; + + GetMissileVel(mi,sx,sy,dx,dy,16); + + missile[mi]._mirange = 10 * (missile[mi]._mispllvl + 1); + + if (mienemy != MI_ENEMYMONST || id < 0) // trap or somesuch + { + missile[mi]._mirange = missile[mi]._mirange + currlevel; + } + else + { + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + } + missile[mi]._mirange = missile[mi]._mirange << 4; + + missile[mi]._miVar1 = missile[mi]._mirange - missile[mi]._miAnimLen; + missile[mi]._miVar2 = 0; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFireball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int i; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST) + { + missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + + i = 16 + (missile[mi]._mispllvl << 1); + if (i > 50) i = 50; + + UseMana(id, SPL_FIREBALL); + } + else + { + i = 16; + } + + GetMissileVel(mi,sx,sy,dx,dy,i); + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = sx; + missile[mi]._miVar5 = sy; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBigExplosion(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST || mienemy == MI_ENEMYBOTH) + { + missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1; + for (int i = missile[mi]._mispllvl; i > 0; --i) + { + missile[mi]._midam += (missile[mi]._midam >> 3); + } + + dam = missile[mi]._midam; + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix-1, missile[mi]._miy-1, 1); + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix , missile[mi]._miy-1, 1); + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix+1, missile[mi]._miy-1, 1); + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix-1, missile[mi]._miy , 1); + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix , missile[mi]._miy , 1); + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix+1, missile[mi]._miy , 1); + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix-1, missile[mi]._miy+1, 1); + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix , missile[mi]._miy+1, 1); + CheckMissileCol(mi, dam, dam, 0, missile[mi]._mix+1, missile[mi]._miy+1, 1); + } + + missile[mi]._mlid = AddLight(sx, sy, 8); + SetMissDir(mi, 0); + missile[mi]._miDelFlag = FALSE; + + missile[mi]._mirange = missile[mi]._miAnimLen - 1; + + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddSpiralFireBall(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int i; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST) + { + missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + + i = 16 + (missile[mi]._mispllvl << 1); + if (i > 50) i = 50; + + UseMana(id, SPL_FIREBALL); + } + else + { + i = 16; + } + + GetMissileVel(mi,sx,sy,dx,dy,i); + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = sx; + missile[mi]._miVar5 = sy; + missile[mi]._miVar6 = 2; + missile[mi]._miVar7 = 2; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +void AddFBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int i; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST) + { + i = 16 + missile[mi]._mispllvl; + if (i > 50) i = 50; + +// UseMana(id, SPL_FIREBALL); + } + else + { + i = 16; + } + + GetMissileVel(mi,sx,sy,dx,dy,i); + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = sx; + missile[mi]._miVar5 = sy; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLightctrl(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (dam == 0 && mienemy == MI_ENEMYMONST) UseMana(id, SPL_LIGHTNING); // if not 0 - probably is chain lightning + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + + GetMissileVel(mi,sx,sy,dx,dy,32); + + missile[mi]._miAnimFrame = random(52, 8) + 1; + + missile[mi]._mirange = 256; +} + +void AddLTArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + GetMissileVel(mi,sx,sy,dx,dy,32); + missile[mi]._miAnimFrame = random(52, 8) + 1; + + missile[mi]._mirange = 255; + + if (id < 0) { + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + } else { + missile[mi]._miVar1 = plr[id]._px; + missile[mi]._miVar2 = plr[id]._py; + } + + missile[mi]._midam <<= HP_SHIFT; + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLightning(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA + // Note: midir is used to pass in the missile # of the root of the lightning chain. + // A negative midir means that this is not part of a chain. + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._misx = dx; + missile[mi]._misy = dy; + + if(midir >= 0) + { + missile[mi]._mixoff = missile[midir]._mixoff; + missile[mi]._miyoff = missile[midir]._miyoff; + missile[mi]._mitxoff = missile[midir]._mitxoff; + missile[mi]._mityoff = missile[midir]._mityoff; + } + + missile[mi]._miAnimFrame = random(52, 8) + 1; + + if (midir >= 0 && mienemy != MI_ENEMYPLR && id != -1) { + missile[mi]._mirange = 6 + (missile[mi]._mispllvl >> 1); + } else { + if (midir >= 0 && id != -1) { + missile[mi]._mirange = 10; + } else missile[mi]._mirange = 8; + } + + missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 4); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddMisexp(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + + if (mienemy != MI_ENEMYMONST && id > 0) { + app_assert(id < MAXMONSTERS); + app_assert(monster[id].MType != NULL); + switch (monster[id].MType->mtype) + { + case MT_SUCCUBUS: + SetMissAnim(mi,MF_FLAREXP); + break; + case MT_SNOWWICH: + SetMissAnim(mi,MF_BFLAREXP); + break; + case MT_HLSPWN: + SetMissAnim(mi,MF_DFLAREXP); + break; + case MT_SOLBRNR: + SetMissAnim(mi,MF_CFLAREXP); + break; + } + } + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mix = missile[dx]._mix; + missile[mi]._miy = missile[dx]._miy; + missile[mi]._misx = missile[dx]._misx; + missile[mi]._misy = missile[dx]._misy; + missile[mi]._mixoff = missile[dx]._mixoff; + missile[mi]._miyoff = missile[dx]._miyoff; + missile[mi]._mitxoff = missile[dx]._mitxoff; + missile[mi]._mityoff = missile[dx]._mityoff; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + + missile[mi]._mirange = missile[mi]._miAnimLen; + missile[mi]._miVar1 = 0; + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddWeapexp(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = dx; + + missile[mi]._mimfnum = 0; + if (dx == 1) SetMissAnim(mi, MF_EXP1); + else SetMissAnim(mi, MF_CBOLT); + missile[mi]._mirange = missile[mi]._miAnimLen - 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL CheckIfTrig(int x, int y) +{ + int i; + + app_assert(numtrigs <= MAXTRIGGERS); + for (i = 0; i < numtrigs; ++i) + if (((x == trigs[i]._tx) && (y == trigs[i]._ty)) || + ((abs(trigs[i]._tx-x) < 2) && (abs(trigs[i]._ty-y) < 2))) return(TRUE); + + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddTown(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_TOWN) || !PRE_BETA + int i, pn; + int k, l, j; + int tx, ty, mx; + + app_assert(mi < MAXMISSILES && mi >= 0); + if (currlevel != 0) { + missile[mi]._miDelFlag = TRUE; + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + app_assert(pn <= MAXTILES && pn >= 0); + if (((nSolidTable[pn] | dObject[tx][ty] | nMissileTable[pn] | + dPlayer[tx][ty] | dMissile[tx][ty]) == 0) && + (!CheckIfTrig(tx, ty))) { + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = tx; + missile[mi]._misy = ty; + missile[mi]._miDelFlag = FALSE; + k = 6; + break; + } + } + j += 2; + } + } + } else { + tx = dx; + ty = dy; + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = tx; + missile[mi]._misy = ty; + missile[mi]._miDelFlag = FALSE; + } + + missile[mi]._mirange = 100; + missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen); + missile[mi]._miVar2 = 0; + + // Move current portal? + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + if ((missile[mx]._mitype == MIT_TOWN) && + (mx != mi) && + (missile[mx]._misource == id)) { + missile[mx]._mirange = 0; + } + } + + PutMissile(mi); + + if (id == myplr && missile[mi]._miDelFlag == FALSE && currlevel != 0) { + if (!setlevel) NetSendCmdLocParam3(TRUE, CMD_ACTIVATEPORTAL, tx, ty, currlevel, leveltype, FALSE); + else NetSendCmdLocParam3(TRUE, CMD_ACTIVATEPORTAL, tx, ty, setlvlnum, leveltype, TRUE); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlash(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST) { + if (id != -1) { + missile[mi]._midam = 0; + for (i = 0; i <= plr[id]._pLevel; ++i) missile[mi]._midam += random(55, 20) + 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + missile[mi]._midam += missile[mi]._midam >> 1; + UseMana(id, SPL_FLASH); + } else { + missile[mi]._midam = (currlevel >> 1); + } + } + else + missile[mi]._midam = monster[id].mLevel << 1; + + missile[mi]._mirange = 19; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddAura(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + +#if defined(HELLFIRE2) + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST) { + if (id != -1) { + missile[mi]._midam = 0; + missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id]._pLevel : 1); + plr[id]._pBaseToBlk += 50; + UseMana(id, SPL_AURA); + } + } +#endif + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddAura2(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST) { + if (id != -1) { + missile[mi]._midam = 0; + missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id]._pLevel : 1); + } + } + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlash2(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES && mi >= 0); + if (mienemy == MI_ENEMYMONST) + { + if (id != -1) { + missile[mi]._midam = 0; + for (i = 0; i <= plr[id]._pLevel; ++i) missile[mi]._midam += random(56, 2) + 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + missile[mi]._midam += missile[mi]._midam >> 1; + } else { + missile[mi]._midam = (currlevel >> 1); + } + } + + missile[mi]._miPreFlag = TRUE; + + missile[mi]._mirange = 19; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddManashield(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mirange = ((plr[id]._pLevel << 4) << 1) + (plr[id]._pLevel << 4); + + missile[mi]._miVar1 = plr[id]._pHitPoints; + missile[mi]._miVar2 = plr[id]._pHPBase; + + missile[mi]._miVar8 = KILL_UNKNOWN; // killed by unknown source (inited) + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_MANASHLD); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFiremove(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = random(59, 10) + 1 + plr[id]._pLevel; + + GetMissileVel(mi,sx,sy,dx,dy,16); + + missile[mi]._mirange = 255; + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + + ++missile[mi]._mix; + ++missile[mi]._miy; + missile[mi]._miyoff-=32; +//PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddGuardian(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_GUARDIAN) || !PRE_BETA + int i, pn; + int k, l, j; + int tx, ty; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = random(62, 10) + 1 + (plr[id]._pLevel >> 1); + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + + missile[mi]._miDelFlag = TRUE; + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + app_assert(tx < MAXDUNX && tx >= 0); + app_assert(ty < MAXDUNY && ty >= 0); + pn = dPiece[tx][ty]; + app_assert(pn <= MAXTILES); + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + //if ((dFlags[tx][ty] & BFLAG_VISIBLE) && + if ((LineClear(sx, sy, tx, ty)) && + ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty] | nMissileTable[pn] | dMissile[tx][ty]) == 0)) { + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = tx; + missile[mi]._misy = ty; + missile[mi]._miDelFlag = FALSE; + UseMana(id, SPL_GUARDIAN); + k = 6; + break; + } + } + j += 2; + } + } + + if (missile[mi]._miDelFlag == TRUE) return; + missile[mi]._misource = id; + missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 1); + + missile[mi]._mirange = (plr[id]._pLevel >> 1) + missile[mi]._mispllvl; + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + if (missile[mi]._mirange > 30) missile[mi]._mirange = 30; + missile[mi]._mirange = missile[mi]._mirange << 4; + if (missile[mi]._mirange < 30) missile[mi]._mirange = 30; + + missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen); + missile[mi]._miVar2 = 0; + missile[mi]._miVar3 = 1; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddChain(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_CHAIN) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + + missile[mi]._mirange = 1; + UseMana(id, SPL_CHAIN); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddChainOLD(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int i, k, j, mx; + + if (dam == 0) { + k = 0; + j = -1; + for (i = 0; i < nummissilevars; ++i) { + mx = missilevars[i][0]; + if (mx >= 0 && missile[mx]._mitype == MIT_CHAIN && missile[mx]._miVar8 > k) k = missile[mx]._miVar8; + if (mx < 0) j = i; + } + ++k; + missile[mi]._miVar8 = k; + if (j == -1) { + ++nummissilevars; + j = nummissilevars; + } + missilevars[j][0] = mi; + missilevars[j][1] = MIT_CHAIN; + missilevars[j][2] = 0; + } else { + for (i = 0; i < nummissilevars; ++i) { + mx = missilevars[i][0]; + if (mx >= 0 && missile[mx]._mitype == MIT_CHAIN && missile[mx]._miVar8 == dam) missilevars[i][2]++; + } + } + + k = 0; + missile[mi]._midam = 0; + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + if (missile[mx]._mitype == MIT_CHAIN && missile[mx]._midam > k) k = missile[mx]._midam; + if (missile[mx]._mitype == MIT_CHAINBALL && missile[mx]._miVar1 > k) k = missile[mx]._miVar1; + } + ++k; + missile[mi]._midam = k; + + missile[mi]._mirange = 12 + GetSpellLevel(id, SPL_LIGHTNING); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + missile[mi]._miVar5 = dx; + missile[mi]._miVar6 = dy; + missile[mi]._miVar7 = 0; + + UseMana(id, SPL_CHAIN); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddChainballOLD(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int i, mx; + + missile[mi]._miVar1 = dam; + missile[mi]._miVar2 = 0; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + if ((missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._miVar2 == 1) && (missile[mx]._midam == dam)) { + missile[mi]._miVar2 = missile[mx]._miVar2; + missile[mi]._miVar3 = missile[mx]._miVar3; + missile[mi]._miVar4 = missile[mx]._miVar4; + } + if ((missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._midam == dam)) + missile[mi]._miVar8 = missile[mx]._miVar8; + } + + if (dMonster[sx][sy] != 0) { + missile[mi]._miVar5 = sx; + missile[mi]._miVar6 = sy; + } else { + missile[mi]._miVar5 = 0; + missile[mi]._miVar6 = 0; + } + + missile[mi]._midam = (random(61, plr[id]._pLevel) + random(61, 6) + 4) << HP_SHIFT; + + GetMissileVel(mi, sx, sy, dx, dy, 16); + + missile[mi]._mirange = ((plr[id]._pLevel << 4) << 1) + (GetSpellLevel(id, SPL_CHAIN) << 4); + + PutMissile(mi); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBlood(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam) +{ + SetMissDir(mi, str); + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = 0; + + missile[mi]._miLightFlag = TRUE; + + missile[mi]._mirange = 250; + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBone(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam) +{ + if (str > 3) str = 2; + SetMissDir(mi, str); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = 0; + + missile[mi]._miLightFlag = TRUE; + + missile[mi]._mirange = 250; + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddMetal(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam) +{ + if (str > 3) str = 2; + SetMissDir(mi, str); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = 0; + + missile[mi]._miLightFlag = TRUE; + + missile[mi]._mirange = (missile[mi]._miAnimLen); + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRhino(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + AnimStruct *anim; + + app_assert(id < MAXMONSTERS && id >= 0); + app_assert(monster[id].MType != NULL); + if (EquivMonst(monster[id].MType->mtype, MT_HORNED)) + anim = &monster[id].MType->Anims[MA_SPECIAL]; + else if (EquivMonst(monster[id].MType->mtype, MT_NSNAKE)) + anim = &monster[id].MType->Anims[MA_ATTACK]; + else + anim = &monster[id].MType->Anims[MA_WALK]; + + GetMissileVel(mi,sx,sy,dx,dy,18); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mimfnum = midir; + missile[mi]._miAnimFlags = NULL; + missile[mi]._miAnimData = anim->Cels[midir]; + missile[mi]._miAnimDelay = anim->Rate; + missile[mi]._miAnimLen = anim->Frames; + missile[mi]._miAnimWidth = monster[id].MType->mAnimWidth; + missile[mi]._miAnimWidth2 = monster[id].MType->mAnimWidth2; + missile[mi]._miAnimAdd = 1; + if (EquivMonst(monster[id].MType->mtype, MT_NSNAKE)) + missile[mi]._miAnimFrame = 7; + + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + + missile[mi]._miLightFlag = TRUE; + if(monster[id]._uniqtype) { + missile[mi]._miUniqTrans = monster[id]._uniqtrans+1; + missile[mi]._mlid = monster[id].mlid; + } + + missile[mi]._mirange = 256; + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFireman(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + AnimStruct *anim; + + app_assert(id < MAXMONSTERS && id >= 0); + app_assert(monster[id].MType != NULL); + anim = &monster[id].MType->Anims[MA_WALK]; + + GetMissileVel(mi,sx,sy,dx,dy,16); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mimfnum = midir; + missile[mi]._miAnimFlags = NULL; + missile[mi]._miAnimData = anim->Cels[midir]; + missile[mi]._miAnimDelay = anim->Rate; + missile[mi]._miAnimLen = anim->Frames; + missile[mi]._miAnimWidth = monster[id].MType->mAnimWidth; + missile[mi]._miAnimWidth2 = monster[id].MType->mAnimWidth2; + missile[mi]._miAnimAdd = 1; + + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + + missile[mi]._miLightFlag = TRUE; + if(monster[id]._uniqtype) + missile[mi]._miUniqTrans = monster[id]._uniqtrans+1; + + dMonster[monster[id]._mx][monster[id]._my] = 0; + + missile[mi]._mirange = 256; + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlare(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int d; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + GetMissileVel(mi,sx,sy,dx,dy,16); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + if (mienemy == MI_ENEMYMONST) { + UseMana(id, SPL_BSTAR); + d = 5; + //for (k = missile[mi]._mispllvl; k > 0; --k) d -= 1; + //if (d <= 0) d = 1; +#if CHEATS + if (simplecheat || cheatflag) d = 0; +#endif + + plr[id]._pHitPoints -= (d << HP_SHIFT); + plr[id]._pHPBase -= (d << HP_SHIFT); + drawhpflag = TRUE; + + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } + } else { + if (id > 0) { + if (monster[id].MType->mtype == MT_SUCCUBUS) SetMissAnim(mi,MF_FLARE); + if (monster[id].MType->mtype == MT_SNOWWICH) SetMissAnim(mi,MF_BFLARE); + if (monster[id].MType->mtype == MT_HLSPWN) SetMissAnim(mi,MF_DFLARE); + if (monster[id].MType->mtype == MT_SOLBRNR) SetMissAnim(mi,MF_CFLARE); + } + } + + if (misfiledata[missile[mi]._miAnimType].mAnimFAmt == 16) { + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + } + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddAcid(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + app_assert(mi < MAXMISSILES && mi >= 0); + if ((missile[mi]._mixvel >> 16) == 0 + && (missile[mi]._miyvel >> 16) == 0) + { + missile[mi]._mirange = 1; + } + else + { + missile[mi]._mirange = 15 + 5*(monster[id]._mint+1); + } + missile[mi]._mlid = -1; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddDoom(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int i, j, k, l; + int mid; + + // search in a 5 radius around tile clicked for monster + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + mid = dMonster[(dx + CrawlTable[j])][(dy + CrawlTable[(j + 1)])]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) { + missile[mi]._miVar1 = dx + CrawlTable[j]; + missile[mi]._miVar2 = dy + CrawlTable[j + 1]; + missile[mi]._miVar3 = mid; + i = -99; + k = 6; + break; + } + } + j += 2; + } + } + + // if no monsters found in search + if (i != -99) { + missile[mi]._miDelFlag = TRUE; + return; + } + + GetMissileVel(mi, sx, sy, missile[mi]._miVar1, missile[mi]._miVar2, 16); + SetMissDir(mi, GetDirection(sx, sy, missile[mi]._miVar1, missile[mi]._miVar2)); + + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + missile[mi]._misource = id; + missile[mi]._midam = 26; + + missile[mi]._mirange = ((plr[id]._pLevel << 4) >> 2) + (plr[id]._pLevel << 4) ; + for (i = GetSpellLevel(id, SPL_DOOM); i > 0; --i) missile[mi]._mirange += ((missile[mi]._mirange << 4) >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + + UseMana(id, SPL_DOOM); + PutMissile(mi); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFireonly(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = dam; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + + missile[mi]._mirange = 50; + missile[mi]._miVar1 = missile[mi]._mirange - missile[mi]._miAnimLen; + missile[mi]._miVar2 = 0; + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddAcidpud(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int monst; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + + missile[mi]._mixoff = 0; + missile[mi]._miyoff = 0; +/* + missile[mi]._misx = missile[dx]._misx; + missile[mi]._misy = missile[dx]._misy; + missile[mi]._mixoff = missile[dx]._mixoff; + missile[mi]._miyoff = missile[dx]._miyoff; + missile[mi]._mitxoff = missile[dx]._mitxoff; + missile[mi]._mityoff = missile[dx]._mityoff; +*/ + + missile[mi]._miLightFlag = TRUE; + +// MoveMissilePos(mi); + + monst = missile[mi]._misource; + missile[mi]._mirange = random(50,15) + 40*(monster[monst]._mint + 1); + + missile[mi]._miPreFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddStone(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_STONE) || !PRE_BETA + int i, j, k, l, tx, ty; + int mid; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._misource = id; + + // search in a 5 radius around tile clicked for monster + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + mid = dMonster[tx][ty]; + if (mid > 0) --mid; + else mid = -(mid + 1); + if ((mid > 3) + && (monster[mid]._mAi != AI_DIABLO) + && (monster[mid].MType->mtype != MT_NKR) + && (monster[mid]._mmode != MM_FADEIN) + && (monster[mid]._mmode != MM_FADEOUT) + //&& (monster[mid]._mmode != MM_DEATH) + && (monster[mid]._mmode != MM_MISSILE)) { + i = -99; + k = 6; + missile[mi]._miVar1 = monster[mid]._mmode; + missile[mi]._miVar2 = mid; + monster[mid]._mmode = MM_STONE; + break; + } + } + j += 2; + } + } + + // if no monsters found in search + if (i != -99) { + missile[mi]._miDelFlag = TRUE; + return; + } + + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = missile[mi]._mix; + missile[mi]._misy = missile[mi]._miy; + + missile[mi]._mirange = 6 + missile[mi]._mispllvl; + //if (missile[mi]._mirange == 0) missile[mi]._mirange = 1; + //for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + if (missile[mi]._mirange > 15) missile[mi]._mirange = 15; + missile[mi]._mirange = missile[mi]._mirange << 4; + UseMana(id, SPL_STONE); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddInvis(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int i; + + missile[mi]._mirange = plr[id]._pLevel << 4; + for (i = GetSpellLevel(id, SPL_INVIS); i > 0; --i) missile[mi]._mirange += ((missile[mi]._mirange << 4) >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + UseMana(id, SPL_INVIS); + missile[mi]._miDelFlag = TRUE; +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddGolem(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_GOLEM) || !PRE_BETA + int i, mx; + //int tx, ty, k, j, l; + + app_assert(mi < MAXMISSILES && mi >= 0); + + missile[mi]._miDelFlag = FALSE; + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + if ((missile[mx]._mitype == MIT_GOLEM) && (mx != mi) && + (missile[mx]._misource == id)) { + missile[mi]._miDelFlag = TRUE; + return; + } + } + + /*for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + if ((LineClear(sx, sy, tx, ty)) && + ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty]) == 0)) {*/ + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar4 = dx; + missile[mi]._miVar5 = dy; + if ((monster[id]._mx != 1 || monster[id]._my != 0) && (id == myplr)) M_StartKill(id, id); + //missile[mi]._miDelFlag = FALSE; + UseMana(id, SPL_GOLEM); + /*k = 6; + break; + } + } + j += 2; + } + }*/ +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddEther(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_ETHER) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mirange = (plr[id]._pLevel << 4) >> 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + + missile[mi]._miVar1 = plr[id]._pHitPoints; + missile[mi]._miVar2 = plr[id]._pHPBase; + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_ETHER); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBloodR(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_BLOODR) || !PRE_BETA + int manaval; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + return; // spell deleted - left code here just in case + + if (!(plr[id]._pIFlags & IAF_LMANA)) { + plr[id]._pHitPoints -= (10 << HP_SHIFT); + plr[id]._pHPBase -= (10 << HP_SHIFT); + + manaval = ((missile[mi]._mispllvl + 8) << MANA_SHIFT); + plr[id]._pMana += manaval; + plr[id]._pManaBase += manaval; + + if (plr[id]._pMana > plr[id]._pMaxMana) plr[id]._pMana = plr[id]._pMaxMana; + if (plr[id]._pManaBase > plr[id]._pMaxManaBase) plr[id]._pManaBase = plr[id]._pMaxManaBase; + + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } + } + + UseMana(id, SPL_BLOODR); + drawhpflag = TRUE; + missile[mi]._miDelFlag = TRUE; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddSpurt(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = dam; + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + missile[mi]._misource = id; + + if (dam == 1) + SetMissDir(mi, 0); + else + SetMissDir(mi, 1); + + missile[mi]._miLightFlag = TRUE; + + missile[mi]._mirange = missile[mi]._miAnimLen; + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBoom(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mix = dx; + missile[mi]._miy = dy; + missile[mi]._misx = dx; + missile[mi]._misy = dy; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + missile[mi]._midam = dam; + + missile[mi]._mirange = missile[mi]._miAnimLen; + missile[mi]._miVar1 = 0; + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddHeal(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_HEAL) || !PRE_BETA + int i; + long l; + + l = (random(57, 10) + 1) << HP_SHIFT; + for (i = 0; i < plr[id]._pLevel; ++i) l += ((random(57, 4) + 1) << HP_SHIFT); + app_assert(mi < MAXMISSILES && mi >= 0); + for (i = 0; i < missile[mi]._mispllvl; ++i) l += ((random(57, 6) + 1) << HP_SHIFT); + if (plr[id]._pClass == CLASS_WARRIOR + || plr[id]._pClass == CLASS_BARBARIAN + || plr[id]._pClass == CLASS_MONK) l = l << 1; + if (plr[id]._pClass == CLASS_ROGUE + || plr[id]._pClass == CLASS_BARD) l += (l >> 1); + plr[id]._pHitPoints += l; + if (plr[id]._pHitPoints > plr[id]._pMaxHP) plr[id]._pHitPoints = plr[id]._pMaxHP; + plr[id]._pHPBase += l; + if (plr[id]._pHPBase > plr[id]._pMaxHPBase) plr[id]._pHPBase = plr[id]._pMaxHPBase; + + UseMana(id, SPL_HEAL); + drawhpflag = TRUE; + + missile[mi]._miDelFlag = TRUE; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddMana(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_HEAL) || !PRE_BETA + int i; + long l; + + l = (random(57, 10) + 1) << MANA_SHIFT; + for (i = 0; i < plr[id]._pLevel; ++i) l += ((random(57, 4) + 1) << MANA_SHIFT); + app_assert(mi < MAXMISSILES && mi >= 0); + for (i = 0; i < missile[mi]._mispllvl; ++i) l += ((random(57, 6) + 1) << MANA_SHIFT); + if (plr[id]._pClass == CLASS_SORCEROR) l = l << 1; + if (plr[id]._pClass == CLASS_ROGUE + || plr[id]._pClass == CLASS_BARD) l += (l >> 1); + + plr[id]._pMana += l; + if (plr[id]._pMana > plr[id]._pMaxMana) plr[id]._pMana = plr[id]._pMaxMana; + plr[id]._pManaBase += l; + if (plr[id]._pManaBase > plr[id]._pMaxManaBase) plr[id]._pManaBase = plr[id]._pMaxManaBase; + + UseMana(id, SPL_MANA); + drawmanaflag = TRUE; + + missile[mi]._miDelFlag = TRUE; + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +void AddFMana(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_HEAL) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + plr[id]._pMana = plr[id]._pMaxMana; + plr[id]._pManaBase = plr[id]._pMaxManaBase; + UseMana(id, SPL_FMANA); + drawmanaflag = TRUE; +#endif + missile[mi]._miDelFlag = TRUE; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_HEALOTHER) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_HEALOTHER); + if (id == myplr) { + NewCursor(HEALOTHER_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddElement(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_ELEMENT) || !PRE_BETA + int i; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + //missile[mi]._midam = 0; + //for (i = 0; i < plr[id]._pLevel; ++i) missile[mi]._midam += random(67, 6) + 1; + //for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + missile[mi]._midam = missile[mi]._midam >> 1; + + GetMissileVel(mi, sx, sy, dx, dy, 16); + SetMissDir(mi, GetDirection8(sx, sy, dx, dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = dx; + missile[mi]._miVar5 = dy; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + UseMana(id, SPL_ELEMENT); + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddIdentify(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_IDENTIFY) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_IDENTIFY); + if (id == myplr) { + if (sbookflag) sbookflag = FALSE; + if (!invflag) invflag = TRUE; + NewCursor(IDENTIFY_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFirewallC(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int i, pn; + int k, l, j; + int tx, ty; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + //if ((dFlags[tx][ty] & BFLAG_VISIBLE) && ((sx != tx) || (sy != ty)) && + if ((LineClear(sx, sy, tx, ty)) && ((sx != tx) || (sy != ty)) && + ((nSolidTable[pn] | dObject[tx][ty]) == 0)) { + missile[mi]._miVar1 = tx; + missile[mi]._miVar2 = ty; + missile[mi]._miVar5 = tx; + missile[mi]._miVar6 = ty; + missile[mi]._miDelFlag = FALSE; + k = 6; + break; + } + } + j += 2; + } + } + + if (missile[mi]._miDelFlag == TRUE) return; + + missile[mi]._miVar7 = 0; + missile[mi]._miVar8 = 0; + + //midir = GetDirection(sx, sy, tx, ty); + missile[mi]._miVar3 = (midir - 2) & 0x0007; + missile[mi]._miVar4 = (midir + 2) & 0x0007; + + missile[mi]._mirange = 7; + UseMana(id, SPL_WALL); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlameBox(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + + if (mienemy == MI_ENEMYMONST){ + UseMana(id, SPL_RINGOFFIRE); + } + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miDelFlag = FALSE; + + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + missile[mi]._miVar5 = 0; + missile[mi]._miVar6 = 0; + missile[mi]._miVar7 = 0; + missile[mi]._miVar8 = 0; + + missile[mi]._mirange = 7; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddShowMagicItems(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = FALSE; + + missile[mi]._miVar1 = id; + missile[mi]._miVar2 = 0; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + missile[mi]._miVar5 = 0; + missile[mi]._miVar6 = 0; + missile[mi]._miVar7 = 0; + missile[mi]._miVar8 = 0; + + HighLightAllItems = true; + missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id]._pLevel : 1); + if (mienemy == MI_ENEMYMONST){ + UseMana(id, SPL_SHOWMAGITEMS); + } + + for(int i = 0; i < nummissiles; ++i) { + int const miActive = missileactive[i]; + if (miActive != mi) { + MissileStruct * const pMiss = &missile[miActive]; + + if (pMiss->_miVar1 == id + && pMiss->_mitype == MIT_SHOWMAGITEMS) { + + // to prevent ridiculous overflow. + if (pMiss->_mirange < (INT_MAX - missile[mi]._mirange)) { + pMiss->_mirange += missile[mi]._mirange; + } + missile[mi]._miDelFlag = TRUE; + break; + } + } + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddInfra(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_INFRA) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mirange = 99 << 4; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_INFRA); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddWave(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WAVE) || !PRE_BETA + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + missile[mi]._mirange = 1; + missile[mi]._miAnimFrame = 4; + UseMana(id, SPL_WAVE); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddNova(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_NOVA) || !PRE_BETA + int k; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + if (id != -1) { + missile[mi]._midam = random(66, 6) + random(66, 6) + random(66, 6) + random(66, 6) + random(66, 6); + missile[mi]._midam += 5 + plr[id]._pLevel; + missile[mi]._midam = missile[mi]._midam >> 1; + for (k = missile[mi]._mispllvl; k > 0; --k) missile[mi]._midam += (missile[mi]._midam >> 3); + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_NOVA); + } else { + missile[mi]._midam = random(66, 3) + random(66, 3) + random(66, 3); + missile[mi]._midam += (currlevel >> 1); + } + missile[mi]._mirange = 1; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBoil(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + // not in game + missile[mi]._miDelFlag = TRUE; + return; +/* +#if (PRE_BETA && PRE_BLOODB) || !PRE_BETA + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + missile[mi]._mirange = 1; +#else + missile[mi]._miDelFlag = TRUE; +#endif*/ +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRage(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id != -1) { + if ((0 == (SF_RAGE & plr[id]._pSpellFlags)) // Only one rage at a time. + && (0 == (SF_LETHERGY & plr[id]._pSpellFlags)) // Can't rage while lethargic either. + && plr[id]._pHitPoints > (plr[id]._pLevel << HP_SHIFT)) { // And not too weak. + const int Sounds[NUM_CLASSES] = { PS_WARR70, + PS_ROGUE70, + PS_MAGE70, + PS_MAGE70, // monk + PS_BARD70, + PS_BARBARIAN70 }; + UseMana(id, SPL_RAGE); + missile[mi]._miVar1 = id; + int const hps = (plr[id]._pLevel * 6) << HP_SHIFT; + plr[id]._pSpellFlags |= SF_RAGE; + missile[mi]._miVar2 = hps; + missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id]._pLevel : 1); + CalcPlrItemVals(id, TRUE); + force_redraw = FULLDRAW; + PlaySfxLoc(Sounds[plr[id]._pClass], plr[id]._px, plr[id]._py); + } + else { + // Too weak to become enraged. + missile[mi]._miDelFlag = TRUE; + } + } + else { + missile[mi]._miDelFlag = TRUE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRepair(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_REPAIR) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_REPAIR); + if (id == myplr) { + if (sbookflag) sbookflag = FALSE; + if (!invflag) invflag = TRUE; + NewCursor(REPAIR_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRecharge(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_RECHARGE) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_RECHARGE); + if (id == myplr) { + if (sbookflag) sbookflag = FALSE; + if (!invflag) invflag = TRUE; + NewCursor(RECHARGE_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddDisarm(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_DISARM) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_DISARM); + if (id == myplr) { + NewCursor(DISARM_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddApoca(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_APOCA) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miVar1 = 8; + missile[mi]._miVar2 = sy - missile[mi]._miVar1; + missile[mi]._miVar3 = sy + missile[mi]._miVar1; + missile[mi]._miVar4 = sx - missile[mi]._miVar1; + missile[mi]._miVar5 = sx + missile[mi]._miVar1; + missile[mi]._miVar6 = missile[mi]._miVar4; + + if (missile[mi]._miVar2 <= 0) missile[mi]._miVar2 = 1; + if (missile[mi]._miVar3 >= MAXDUNY) missile[mi]._miVar3 = MAXDUNY - 1; + if (missile[mi]._miVar4 <= 0) missile[mi]._miVar4 = 1; + if (missile[mi]._miVar5 >= MAXDUNX) missile[mi]._miVar5 = MAXDUNX - 1; + + for (i = 0; i < plr[id]._pLevel; ++i) missile[mi]._midam += random(67, 6) + 1; + + missile[mi]._mirange = 255; + missile[mi]._miDelFlag = FALSE; + UseMana(id, SPL_APOCA); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlame(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int seqno) +{ +#if (PRE_BETA && PRE_FLAME) || !PRE_BETA + // seqno: the number of flame chunk for this spell instance + int i; + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miVar2 = 0; + //for (i = 0; i < 2 - seqno; ++i) { + for (i = seqno; i > 0; --i) { + missile[mi]._miVar2 += 5; + } + + missile[mi]._misx = dx; + missile[mi]._misy = dy; + + missile[mi]._mixoff = missile[midir]._mixoff; + missile[mi]._miyoff = missile[midir]._miyoff; + missile[mi]._mitxoff = missile[midir]._mitxoff; + missile[mi]._mityoff = missile[midir]._mityoff; + missile[mi]._mirange = 20 + missile[mi]._miVar2; + missile[mi]._mlid = AddLight(sx, sy, 1); + + if (mienemy == MI_ENEMYMONST) { + missile[mi]._midam = (random(79, plr[id]._pLevel) + random(79, 2) + 2) << 3; + missile[mi]._midam += missile[mi]._midam >> 1; + //missile[mi]._midam = plr[id]._pLevel << 2; + //for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + //missile[mi]._midam = missile[mi]._midam << 1 + missile[mi]._midam; + } else { + missile[mi]._midam = random(77, monster[id].mMaxDamage - monster[id].mMinDamage + 1) + monster[id].mMinDamage; + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlamec(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLAME) || !PRE_BETA + //int k; + //int tsx, tsy; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + GetMissileVel(mi, sx, sy, dx, dy, 32); + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_FLAME); + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._mirange = 256; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddCbolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + if (micaster == MI_ENEMYMONST) + { + if (id == myplr) { + missile[mi]._mirnd = random(63, 15) + 1; + // INSERT send seed code + } else { + // INSERT get seed from network message for syncing + // used as a number idx not a seed so no SetRndSeed necessary + missile[mi]._mirnd = random(63, 15) + 1; + } + missile[mi]._midam = random(68, plr[id]._pMagic >> 2) + 1; + //for (i = missile[mi]._mispllvl; i > 0; --i) ++missile[mi]._midam; + } + else + { + missile[mi]._mirnd = random(63, 15) + 1; + missile[mi]._midam = 15; + } + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + missile[mi]._miAnimFrame = random(63, 8) + 1; + missile[mi]._mlid = AddLight(sx, sy, 5); + GetMissileVel(mi, sx, sy, dx, dy, 8); + + missile[mi]._miVar1 = 5; + missile[mi]._miVar2 = midir; + missile[mi]._miVar3 = 0; + + missile[mi]._mirange = 256; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +void AddCBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + if (micaster == MI_ENEMYMONST) + { + if (id == myplr) { + missile[mi]._mirnd = random(63, 15) + 1; + // INSERT send seed code + } else { + // INSERT get seed from network message for syncing + // used as a number idx not a seed so no SetRndSeed necessary + missile[mi]._mirnd = random(63, 15) + 1; + } + } + else + { + missile[mi]._mirnd = random(63, 15) + 1; + missile[mi]._midam = 15; + } + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + missile[mi]._miAnimFrame = random(63, 8) + 1; + missile[mi]._mlid = AddLight(sx, sy, 5); + GetMissileVel(mi, sx, sy, dx, dy, 8); + + missile[mi]._miVar1 = 5; + missile[mi]._miVar2 = midir; + missile[mi]._miVar3 = 0; + + missile[mi]._mirange = 256; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddHbolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA + int sp; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES && mi >= 0); + if (id != -1) { + sp = 16 + (missile[mi]._mispllvl << 1); + if (sp >= 63) sp = 63; + } else sp = 16; + + GetMissileVel(mi, sx, sy, dx, dy, sp); + SetMissDir(mi, GetDirection16(sx, sy, dx, dy)); + + missile[mi]._mirange = 256; + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + missile[mi]._midam = random(69, 10) + 9 + plr[id]._pLevel; + + UseMana(id, SPL_HBOLT); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +void AddHBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA + int sp; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES && mi >= 0); + if (id != -1) { + sp = 16 + (missile[mi]._mispllvl << 1); + if (sp >= 63) sp = 63; + } else sp = 16; + + GetMissileVel(mi, sx, sy, dx, dy, sp); + SetMissDir(mi, GetDirection16(sx, sy, dx, dy)); + + missile[mi]._mirange = 256; + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddResurrect(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA + UseMana(id, SPL_RESURRECT); + if (id == myplr) { + NewCursor(RESURRECT_CURS); + } +#endif + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddResurrectBeam(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mix = dx; + missile[mi]._miy = dy; + missile[mi]._misx = missile[mi]._mix; + missile[mi]._misy = missile[mi]._miy; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + missile[mi]._mirange = misfiledata[MF_RESURRECT].mAnimLen[0]; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddTelekinesis(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_TELEKINESIS) || !PRE_BETA + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_TELEKINESIS); + if (id == myplr) { + NewCursor(TELE_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddBoneSpirit(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int d, mid, mx, my; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + GetMissileVel(mi, sx, sy, dx, dy, 16); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + if (mienemy == MI_ENEMYMONST) { + UseMana(id, SPL_BONESPIRIT); + d = 6; + +#if CHEATS + if (simplecheat || cheatflag) d = 0; +#endif + + plr[id]._pHitPoints -= (d << HP_SHIFT); + plr[id]._pHPBase -= (d << HP_SHIFT); + drawhpflag = TRUE; + + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } + + if (dPlayer[dx][dy] != 0) { + missile[mi]._miVar6 = 1; + if (dPlayer[dx][dy] > 0) mid = dPlayer[dx][dy] - 1; + else mid = -(dPlayer[dx][dy] + 1); + mx = plr[mid]._px; + my = plr[mid]._py; + } else { + missile[mi]._miVar6 = 0; + if (dMonster[dx][dy] <= 0) mid = FindClosest(sx, sy, 19); + else mid = dMonster[dx][dy] - 1; + mx = monster[mid]._mx; + my = monster[mid]._my; + } + + if (mid > 0) { + missile[mi]._miVar3 = mid; + GetMissileVel(mi, sx, sy, mx, my, 16); + SetMissDir(mi, GetDirection8(sx, sy, mx, my)); + } + } + + PutMissile(mi); +} + +*/ +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBoneSpirit(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_BONESPIRIT) || !PRE_BETA + int d; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._midam = 0; + + GetMissileVel(mi, sx, sy, dx, dy, 16); + SetMissDir(mi, GetDirection8(sx, sy, dx, dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = dx; + missile[mi]._miVar5 = dy; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + if (mienemy == MI_ENEMYMONST) { + UseMana(id, SPL_BONESPIRIT); + d = 6; +#if CHEATS + if (simplecheat || cheatflag) d = 0; +#endif + plr[id]._pHitPoints -= (d << HP_SHIFT); + plr[id]._pHPBase -= (d << HP_SHIFT); + drawhpflag = TRUE; + + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } + + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRportal(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + + missile[mi]._mirange = 100; + missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen); + missile[mi]._miVar2 = 0; + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddDiabApoca(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + BOOL LineClear(int x1, int y1, int x2, int y2); + int pnum; + + for (pnum = 0; pnum < gbMaxPlayers; ++pnum) + { + if (plr[pnum].plractive + && LineClear(sx,sy,plr[pnum]._pfutx, plr[pnum]._pfuty)) + AddMissile(0, 0, plr[pnum]._pfutx, plr[pnum]._pfuty, 0, MIT_FIREPLAR, mienemy, id, dam, 0); + } + app_assert(mi < MAXMISSILES && mi >= 0); + missile[mi]._miDelFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int AddMissile(int sx, int sy, int v1, int v2, int midir, int mitype, char micaster, int id, int v3, int spllvl) +{ + // v1 and v2 are usually dx and dy (this can be different per missile) + // v3 is usually damage amount + + // check if exceeded number of missiles + if (nummissiles >= MAXMISSILES - 1) + return -1; + + // get next missile id that is available + int const mi = missileavail[0]; + missileavail[0] = missileavail[MAXMISSILES - nummissiles - 1]; + missileactive[nummissiles] = mi; + ++nummissiles; + + // Zero out the data first. + memset(&missile[mi], 0, sizeof(MissileStruct)); + + // do some standard missile setups + missile[mi]._mitype = mitype; + missile[mi]._micaster = micaster; + missile[mi]._misource = id; + missile[mi]._miAnimType = missiledata[mitype].mFileNum; + missile[mi]._miDrawFlag = missiledata[mitype].mDraw; + + missile[mi]._mispllvl = spllvl; + + missile[mi]._mimfnum = midir; + if (missile[mi]._miAnimType != MF_NONE + && misfiledata[(missile[mi]._miAnimType)].mAnimFAmt >= 8) + SetMissDir(mi, midir); + else + SetMissDir(mi, 0); + + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._mixoff = 0; + missile[mi]._miyoff = 0; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + missile[mi]._mitxoff = 0; + missile[mi]._mityoff = 0; + + missile[mi]._miDelFlag = FALSE; + missile[mi]._miAnimAdd = 1; + + missile[mi]._miLightFlag = FALSE; + missile[mi]._miPreFlag = FALSE; + missile[mi]._miUniqTrans = FALSE; + missile[mi]._midam = v3; + missile[mi]._miHitFlag = FALSE; + missile[mi]._midist = 0; + missile[mi]._mlid = -1; + missile[mi]._mirnd = 0; + + if (missiledata[mitype].mlSFX != -1) + PlaySfxLoc(missiledata[mitype].mlSFX, missile[mi]._mix, missile[mi]._miy); + + missiledata[mitype].mAddProc(mi, sx, sy, v1, v2, midir, micaster, id, v3); + + return mi; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*int ChainBounceOLD (int i, int sx, int sy) +{ + int j, mi, mx, dir; + + if (dMonster[sx][sy] != 0) { + + if (dMonster[sx][sy] > 0) mi = dMonster[sx][sy] - 1; + else mi = -(dMonster[sx][sy] + 1); + + if ((monster[mi]._mhitpoints >> HP_SHIFT) > 0) { + for (j = 0; j < nummissilevars; ++j) { + mx = missilevars[j][0]; + if ((mx >= 0) && (missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._miVar8 == missile[i]._miVar8) && + (missilevars[j][2] >= (plr[(missile[i]._misource)]._pLevel >> 1))) { + missilevars[j][0] = -1; + return 3; + } + } + dir = GetDirection(missile[i]._mix, missile[i]._miy, sx, sy); + AddMissile(missile[i]._mix, missile[i]._miy, sx, sy, dir, MIT_CHAIN, MI_ENEMYMONST, missile[i]._misource, missile[i]._miVar8); + return 1; + } + } + + return 0; +}*/ + +extern BOOL LineClear(int x1, int y1, int x2, int y2); +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int Sentfire(int i, int sx, int sy) +{ + int ex, dir; + + ex = 0; + app_assert(i < MAXMISSILES && i >= 0); + if (LineClear(missile[i]._mix, missile[i]._miy, sx, sy) + && (dMonster[sx][sy] > 0) + && ((monster[(dMonster[sx][sy] - 1)]._mhitpoints >> HP_SHIFT) > 0) + && ((dMonster[sx][sy]-1) > 3)) { + dir = GetDirection(missile[i]._mix, missile[i]._miy, sx, sy); + missile[i]._miVar3 = missileavail[0]; // get next mid + AddMissile(missile[i]._mix, missile[i]._miy, sx, sy, dir, MIT_FIREBOLT, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam, GetSpellLevel(missile[i]._misource, SPL_FIREBOLT)); + ex = -1; + } + + if (ex == -1) { + SetMissDir(i, 2); + missile[i]._miVar2 = 3; + } + + return (ex); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Dummy(int i) +{} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_HorkSpawn(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + + + --missile[i]._mirange; + CheckMissileCol(i, 0, 0, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange <= 0) + { + missile[i]._miDelFlag = TRUE; + for (int k = 0; k<2; ++k) + { + int const l = CrawlNum[k]; + int j = l + 1; + for (int m = CrawlTable[l]; m > 0; --m, j += 2) { + int const tx = missile[i]._mix + CrawlTable[j]; + int const ty = missile[i]._miy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int const pn = dPiece[tx][ty]; + if(nSolidTable[pn] == 0 + && dMonster[tx][ty] == 0 + && dPlayer[tx][ty] == 0 + && dObject[tx][ty] == 0) { + m = -99; + k = 6; + int const hs = AddMonster(tx, ty, missile[i]._miVar1, 1, TRUE); + M_StartStand(hs, missile[i]._miVar1); + break; + } + } + } + } + } + else { + ++missile[i]._midist; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + } + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Rune(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + int const tx = missile[i]._mix; + int const ty = missile[i]._miy; + + int mid = dMonster[tx][ty]; + int pid = dPlayer[tx][ty]; + + if (mid || pid) + { + + int dir; + + if (mid != 0) + { + if (mid > 0) --mid; + else mid = -(mid + 1); + + dir = GetDirection(missile[i]._mix, missile[i]._miy, + monster[mid]._mx, monster[mid]._my); + } + else + { + if (pid > 0) --pid; + else pid = -(pid + 1); + + dir = GetDirection(missile[i]._mix, missile[i]._miy, + plr[pid]._px, plr[pid]._py); + } + + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + + AddMissile(tx, ty, tx, ty, dir, missile[i]._miVar1, MI_ENEMYBOTH, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + } + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Golem(int i) +{ +#if (PRE_BETA && PRE_GOLEM) || !PRE_BETA + int id, pn; + int j, k, l, m; + int tx, ty; + + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + + if (monster[id]._mx == 1 && monster[id]._my == 0) { + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (m = CrawlTable[l]; m > 0; --m) { + tx = missile[i]._miVar4 + CrawlTable[j]; + ty = missile[i]._miVar5 + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + if ((LineClear(missile[i]._miVar1, missile[i]._miVar2, tx, ty)) && + ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty]) == 0)) { + k = 6; + SpawnGolum(id, tx, ty, i); + break; + } + } + j += 2; + } + } + } + missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_SetManashield(int i) +{ +#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA + ManashieldFlag = 1; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_LArrow(int i) +{ + int p, mind, maxd, rst; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + p = missile[i]._misource; + if (missile[i]._miAnimType != MF_CBOLT && missile[i]._miAnimType != MF_EXP1) { + ++missile[i]._midist; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + if (p != -1) { + if (missile[i]._micaster == MI_ENEMYMONST) { + mind = plr[p]._pIMinDam; + maxd = plr[p]._pIMaxDam; + } else { + mind = monster[p].mMinDamage; + maxd = monster[p].mMaxDamage; + } + } else { + mind = currlevel + random(68, 10) + 1; + maxd = (currlevel * 2) + random(68, 10) + 1; + } + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) { + rst = missiledata[(missile[i]._mitype)].mResist; + missiledata[(missile[i]._mitype)].mResist = MIMT_NONE; + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0); + missiledata[(missile[i]._mitype)].mResist = rst; + } + + if (missile[i]._mirange == 0) { + missile[i]._mimfnum = 0; + missile[i]._mitxoff -= missile[i]._mixvel; + missile[i]._mityoff -= missile[i]._miyvel; + GetMissilePos(i); + if (missile[i]._mitype == MIT_LARROW) { + SetMissAnim(i, MF_CBOLT); + missile[i]._mirange = missile[i]._miAnimLen - 1; + } else { + SetMissAnim(i, MF_EXP1); + missile[i]._mirange = missile[i]._miAnimLen - 1; + } + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 5); + } + } + } else { + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, 5 + missile[i]._miAnimFrame); + rst = missiledata[(missile[i]._mitype)].mResist; + // drb.patch1.start.02/25/97 + if (missile[i]._mitype == MIT_LARROW) { + if (p != -1) { + mind = plr[p]._pILMinDam; + maxd = plr[p]._pILMaxDam; + } else { + mind = currlevel + random(68, 10) + 1; + maxd = (currlevel * 2) + random(68, 10) + 1; + } + missiledata[MIT_LARROW].mResist = MIMT_LGHT; + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 1); + } + if (missile[i]._mitype == MIT_FARROW) { + if (p != -1) { + mind = plr[p]._pIFMinDam; + maxd = plr[p]._pIFMaxDam; + } else { + mind = currlevel + random(68, 10) + 1; + maxd = (currlevel * 2) + random(68, 10) + 1; + } + missiledata[MIT_FARROW].mResist = MIMT_FIRE; + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 1); + } + // endpatch1.2/25/97 + missiledata[(missile[i]._mitype)].mResist = rst; + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Arrow(int i) +{ + int p, mind, maxd; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + ++missile[i]._midist; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + p = missile[i]._misource; + if (p != -1) { + if (missile[i]._micaster == MI_ENEMYMONST) { + mind = plr[p]._pIMinDam; + maxd = plr[p]._pIMaxDam; + } else { + mind = monster[p].mMinDamage; + maxd = monster[p].mMaxDamage; + } + } else { + mind = currlevel; + maxd = currlevel * 2; + } + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Firebolt(int i) +{ +#if (PRE_BETA && PRE_FIREBOLT) || !PRE_BETA + int omx, omy, d, p; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + + if (missile[i]._mitype == MIT_BONESPIRIT && missile[i]._mimfnum == 8) { + if (missile[i]._mirange == 0) { + if(missile[i]._mlid >= 0) AddUnLight(missile[i]._mlid); + missile[i]._miDelFlag = TRUE; + PlaySfxLoc(LS_BSIMPCT, missile[i]._mix, missile[i]._miy); + } + PutMissile(i); + return; + } + + omx = missile[i]._mitxoff; + omy = missile[i]._mityoff; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + p = missile[i]._misource; + if (p != -1) { + if (missile[i]._micaster == MI_ENEMYMONST) { + switch(missile[i]._mitype) { + case MIT_FLARE: + d = ((plr[p]._pMagic>>1)-(plr[p]._pMagic>>3)) + (missile[i]._mispllvl << 1) + missile[i]._mispllvl; + break; + case MIT_FIREBOLT: + d = random(75, 10) + 1 + (plr[p]._pMagic >> 3) + missile[i]._mispllvl; + break; + case MIT_BONESPIRIT: + //d = (monster[missile[i]._miVar3]._mhitpoints >> HP_SHIFT) >> 1; + d = 0; + break; + } + } else d = (random(77, monster[p].mMaxDamage - monster[p].mMinDamage + 1) + monster[p].mMinDamage); + } else d = random(78, currlevel << 1) + currlevel; + + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, d, d, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + missile[i]._mitxoff = omx; + missile[i]._mityoff = omy; + GetMissilePos(i); + switch(missile[i]._mitype) { + case MIT_FLARE: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_FLAREXP, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_FIREBOLT: + case MIT_MAGMABALL: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_MISEXP, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_YELLOWFLARE: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_YELLOWEXPLOSION, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_REDFLARE: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_REDEXPLOSION, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_BLUEFLARE: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_BLUEEXPLOSION, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_BLUE2FLARE: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_BLUE2EXPLOSION, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_ORANGEFLARE: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_ORANGEEXPLOSION, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_ACID: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_ACIDSPLAT, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_BONESPIRIT: + SetMissDir(i, 8); + missile[i]._mirange = 7; + missile[i]._miDelFlag = FALSE; + PutMissile(i); + return; + } + if(missile[i]._mlid >= 0) AddUnLight(missile[i]._mlid); + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + if(missile[i]._mlid >= 0) ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8); + } + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Lightball(int i) +{ + int j, tx, ty, oi; + + app_assert(i < MAXMISSILES && i >= 0); + tx = missile[i]._miVar1; + ty = missile[i]._miVar2; + + --missile[i]._mirange; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + + GetMissilePos(i); + j = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + + // fix for shires and fireing nova - rjs + if (dObject[tx][ty] != 0 && tx == missile[i]._mix && ty == missile[i]._miy) { + if (dObject[tx][ty] > 0) oi = dObject[tx][ty] - 1; + else oi = -(dObject[tx][ty] + 1); + if (object[oi]._otype == OBJ_SHRINEL || object[oi]._otype == OBJ_SHRINER) missile[i]._mirange = j; + } + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Lightwall(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + + --missile[i]._mirange; + + int const j = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Krull(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + + GetMissilePos(i); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Acidpud(int i) +{ + int range; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + +// GetMissilePos(i); + range = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + missile[i]._mirange = range; // CheckMissileCol clears range if there's a collision, + // but this missile sticks around even after a collision + +// MoveMissilePos(i); + + if (missile[i]._mirange == 0) + { + if(missile[i]._mimfnum) + missile[i]._miDelFlag = TRUE; + else + { + SetMissDir(i, 1); + missile[i]._mirange = missile[i]._miAnimLen; + } + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Firewall(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int ExpLight[14] = {2,3,4,5,5,6,7,8,9,10,11,12,12}; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + + if (missile[i]._mirange == missile[i]._miVar1) { + SetMissDir(i, 1); + missile[i]._miAnimFrame = random(83, 11) + 1; + } + + if (missile[i]._mirange == missile[i]._miAnimLen - 1) { + SetMissDir(i, 0); + missile[i]._miAnimFrame = 13; + missile[i]._miAnimAdd = -1; + } + + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 1); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + if ((missile[i]._mimfnum != 0) && (missile[i]._mirange != 0) && + (missile[i]._miAnimAdd != -1) && (missile[i]._miVar2 < 12)) { + + if (missile[i]._miVar2 == 0) + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ++missile[i]._miVar2; + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Fireball(int i) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int dam, px, py, id, mx, my; + + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + dam = missile[i]._midam; + + //dam = missile[i]._mispllvl; // rjs test + //missiledata[(missile[i]._mitype)].mResist = MIMT_NONE; + + --missile[i]._mirange; + + if (missile[i]._micaster == MI_ENEMYMONST) { + px = plr[id]._px; + py = plr[id]._py; + } else { + px = monster[id]._mx; + py = monster[id]._my; + } + + if (missile[i]._miAnimType == MF_BIGEXP) { + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); + return; + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) { + mx = missile[i]._mix; + my = missile[i]._miy; + + ChangeLight(missile[i]._mlid, mx, my, missile[i]._miAnimFrame); + + if (CheckBlock(px, py, mx , my ) == 0) CheckMissileCol(i, dam, dam, 0, mx, my, 1); + if (CheckBlock(px, py, mx , my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my + 1, 1); + if (CheckBlock(px, py, mx , my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my - 1, 1); + if (CheckBlock(px, py, mx + 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my, 1); + if (CheckBlock(px, py, mx + 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my - 1, 1); + if (CheckBlock(px, py, mx + 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my + 1, 1); + if (CheckBlock(px, py, mx - 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my, 1); + if (CheckBlock(px, py, mx - 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my + 1, 1); + if (CheckBlock(px, py, mx - 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my - 1, 1); + + //++missile[i]._mix; + //++missile[i]._miy; + //missile[i]._miyoff -= 32; + + if ((!TransList[dTransVal[mx][my]]) || + ((missile[i]._mixvel < 0) && + ((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) || + (TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) { + ++missile[i]._mix; + ++missile[i]._miy; + missile[i]._miyoff -= 32; + } + + if (((missile[i]._miyvel > 0) && + ((TransList[dTransVal[mx+1][my]] && nSolidTable[dPiece[mx+1][my]]) || + (TransList[dTransVal[mx-1][my]] && nSolidTable[dPiece[mx-1][my]])))) { + missile[i]._miyoff -= 32; + } + + if (((missile[i]._mixvel > 0) && + ((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) || + (TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) { + missile[i]._mixoff -= 32; + } + + missile[i]._mimfnum = 0; + SetMissAnim(i, MF_BIGEXP); + missile[i]._mirange = missile[i]._miAnimLen - 1; + + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8); + } + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_BigExplosion(int i) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + + app_assert(i < MAXMISSILES && i >= 0); + + --missile[i]._mirange; + + if (missile[i]._mirange <= 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +#endif +} + + +/*-----------------------------------------------------------------------* + // Doesn't work yet. GWP +**-----------------------------------------------------------------------*/ +void MI_SpiralFireBall(int i) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int px, py, mx, my; + + app_assert(i < MAXMISSILES && i >= 0); + int const id = missile[i]._misource; + int const dam = missile[i]._midam; + + + int xcurve; + int ycurve; + + // Set the direction into a spiral. + if (missile[i]._miVar7 < 0) { + missile[i]._miVar6 *= 2; + missile[i]._miVar7 = missile[i]._miVar6; + + --missile[i]._mimfnum; + if (missile[i]._mimfnum < 0) + missile[i]._mimfnum = 7; + } + else --missile[i]._miVar7; + + switch (missile[i]._mimfnum) { + case 0: // Down + xcurve = missile[i]._mixvel; + ycurve = 0; + break; + case 1: // Down left + xcurve = missile[i]._mixvel; + ycurve = missile[i]._miyvel; + break; + case 2: // Left + xcurve = 0; + ycurve = missile[i]._miyvel; + break; + case 3: // Up Left + xcurve = missile[i]._mixvel; + ycurve = missile[i]._miyvel; + break; + case 4: // Up + xcurve = missile[i]._mixvel; + ycurve = 0; + break; + case 5: // Up right + xcurve = missile[i]._mixvel; + ycurve = missile[i]._miyvel; + break; + case 6: // Right + xcurve = 0; + ycurve = missile[i]._miyvel; + break; + case 7: // Down Right + xcurve = missile[i]._mixvel; + ycurve = missile[i]._miyvel; + break; + } + + + --missile[i]._mirange; + + if (missile[i]._micaster == MI_ENEMYMONST) { + px = plr[id]._px; + py = plr[id]._py; + } else { + px = monster[id]._mx; + py = monster[id]._my; + } + + if (missile[i]._miAnimType == MF_BIGEXP) { + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); + return; + } + + missile[i]._mitxoff += xcurve; + missile[i]._mityoff += ycurve; + GetMissilePos(i); + + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) { + mx = missile[i]._mix; + my = missile[i]._miy; + + ChangeLight(missile[i]._mlid, mx, my, missile[i]._miAnimFrame); + + if (CheckBlock(px, py, mx , my ) == 0) CheckMissileCol(i, dam, dam, 0, mx, my, 1); + if (CheckBlock(px, py, mx , my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my + 1, 1); + if (CheckBlock(px, py, mx , my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my - 1, 1); + if (CheckBlock(px, py, mx + 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my, 1); + if (CheckBlock(px, py, mx + 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my - 1, 1); + if (CheckBlock(px, py, mx + 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my + 1, 1); + if (CheckBlock(px, py, mx - 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my, 1); + if (CheckBlock(px, py, mx - 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my + 1, 1); + if (CheckBlock(px, py, mx - 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my - 1, 1); + + //++missile[i]._mix; + //++missile[i]._miy; + //missile[i]._miyoff -= 32; + + if ((!TransList[dTransVal[mx][my]]) || + ((missile[i]._mixvel < 0) && + ((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) || + (TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) { + ++missile[i]._mix; + ++missile[i]._miy; + missile[i]._miyoff -= 32; + } + + if (((missile[i]._miyvel > 0) && + ((TransList[dTransVal[mx+1][my]] && nSolidTable[dPiece[mx+1][my]]) || + (TransList[dTransVal[mx-1][my]] && nSolidTable[dPiece[mx-1][my]])))) { + missile[i]._miyoff -= 32; + } + + if (((missile[i]._mixvel > 0) && + ((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) || + (TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) { + missile[i]._mixoff -= 32; + } + + missile[i]._mimfnum = 0; + SetMissAnim(i, MF_BIGEXP); + missile[i]._mirange = missile[i]._miAnimLen - 1; + + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8); + } + } + + missile[i]._miDelFlag = TRUE; + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Lightctrl(int i) +{ +#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA + int pn, dam, p, mx, my; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + dam = 0; + + p = missile[i]._misource; + if (p != -1) { + if (missile[i]._micaster == MI_ENEMYMONST) { + dam = random(79, plr[p]._pLevel) + random(79, 2) + 2; + dam = dam << HP_SHIFT; + } else { + dam = (random(80, monster[p].mMaxDamage - monster[p].mMinDamage + 1) + monster[p].mMinDamage) << 1; + } + } else { + dam = random(81, currlevel) + (currlevel << 1); + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + mx = missile[i]._mix; + my = missile[i]._miy; + + app_assert(mx < MAXDUNX && mx >= 0); + app_assert(my < MAXDUNY && my >= 0); + pn = dPiece[mx][my]; + app_assert(pn <= MAXTILES && pn >= 0); + if (missile[i]._misource == -1) { + if ((mx != missile[i]._misx) || (my != missile[i]._misy)) + if (nMissileTable[pn]) missile[i]._mirange = 0; + } else { + if (nMissileTable[pn]) missile[i]._mirange = 0; + } + + if ((!nMissileTable[pn]) && ((mx != missile[i]._miVar1) || (my != missile[i]._miVar2)) && + (mx > 0) && (my > 0) && (mx < DMAXX) && (my < DMAXY)) { + // Add LIGHTNING if the player or trap threw this, otherwise add THINLIGHT for thin demon + if (missile[i]._misource != -1) { + if (missile[i]._micaster == MI_ENEMYPLR && EquivMonst(monster[missile[i]._misource].MType->mtype, MT_STORM)) + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_THINLIGHT, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl); + else + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl); + } else { + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl); + } + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + } + + if ((missile[i]._mirange == 0) || (mx <= 0) || (my <= 0) || (mx >= DMAXX) || (my > DMAXY)) + missile[i]._miDelFlag = TRUE; +#endif +} + +void MI_LTArrow(int i) +{ +#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA + int pn, mx, my; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + mx = missile[i]._mix; + my = missile[i]._miy; + + app_assert(mx < MAXDUNX && mx >= 0); + app_assert(my < MAXDUNY && my >= 0); + pn = dPiece[mx][my]; + app_assert(pn <= MAXTILES && pn >= 0); + if (missile[i]._misource == -1) { + if ((mx != missile[i]._misx) || (my != missile[i]._misy)) + if (nMissileTable[pn]) missile[i]._mirange = 0; + } else { + if (nMissileTable[pn]) missile[i]._mirange = 0; + } + + if ((!nMissileTable[pn]) && ((mx != missile[i]._miVar1) || (my != missile[i]._miVar2)) && + (mx > 0) && (my > 0) && (mx < DMAXX) && (my < DMAXY)) { + // Add LIGHTNING if the player or trap threw this, otherwise add THINLIGHT for thin demon + if (missile[i]._misource != -1) { + if (missile[i]._micaster == MI_ENEMYPLR && EquivMonst(monster[missile[i]._misource].MType->mtype, MT_STORM)) + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_THINLIGHT, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + else + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + } else { + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + } + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + } + + if ((missile[i]._mirange == 0) || (mx <= 0) || (my <= 0) || (mx >= DMAXX) || (my > DMAXY)) + missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Lightning(int i) +{ +#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA + int j; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + + j = missile[i]._mirange; + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Town(int i) +{ +#if (PRE_BETA && PRE_TOWN) || !PRE_BETA + int p; + + int ExpLight[17] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15}; + + app_assert(i < MAXMISSILES && i >= 0); + if (missile[i]._mirange > 1) --missile[i]._mirange; + + if (missile[i]._mirange == missile[i]._miVar1) { + SetMissDir(i, 1); + } + + if ((currlevel != 0) && (missile[i]._mimfnum != 1) && (missile[i]._mirange != 0)) { + if (missile[i]._miVar2 == 0) + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ++missile[i]._miVar2; + } + + for (p = 0; p < MAX_PLRS; ++p) { + if (! plr[p].plractive) continue; + if (currlevel != plr[p].plrlevel) continue; + if (plr[p]._pLvlChanging) continue; + if (plr[p]._pmode != PM_STAND) continue; + if (plr[p]._px != missile[i]._mix) continue; + if (plr[p]._py != missile[i]._miy) continue; + + ClrPlrPath(p); + if (p == myplr) { + NetSendCmdParam1(TRUE,CMD_WARP,missile[i]._misource); + plr[p]._pmode = PM_NEWLVL; + } + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Flash(int i) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[missile[i]._misource]._pInvincible = TRUE; + --missile[i]._mirange; + + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy+1, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy+1, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy+1, 1); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[(missile[i]._misource)]._pInvincible = FALSE; + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Aura(int i) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + int const id = missile[i]._misource; + + if ((missile[i]._micaster == MI_ENEMYMONST) && (id != -1)) { + missile[i]._mix = plr[id]._px; + missile[i]._miy = plr[id]._py; + missile[i]._mitxoff = plr[id]._pxoff << 16; + missile[i]._mityoff = plr[id]._pyoff << 16; + } + --missile[i]._mirange; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[(missile[i]._misource)]._pBaseToBlk -= 50; + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Aura2(int i) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) { + missile[i]._mix = plr[missile[i]._misource]._pfutx; + missile[i]._miy = plr[missile[i]._misource]._pfuty; + } + --missile[i]._mirange; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Flash2(int i) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[(missile[i]._misource)]._pInvincible = TRUE; + --missile[i]._mirange; + + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy-1, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy-1, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy-1, 1); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[(missile[i]._misource)]._pInvincible = FALSE; + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Reflect(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + int const id = missile[i]._misource; + + // Reset by GetMissilePos() + // missile[i]._mix = plr[id]._px; + // missile[i]._miy = plr[id]._py; + missile[i]._mitxoff = plr[id]._pxoff << 16; + missile[i]._mityoff = plr[id]._pyoff << 16; + + // These hard coded numbers are fudge factors to get the %$^& art to + // align up. + if (plr[id]._pmode == PM_WALK3) { + missile[i]._misx = plr[id]._pfutx + 2; + missile[i]._misy = plr[id]._pfuty + -1; + } else { + missile[i]._misx = plr[id]._px + 2; + missile[i]._misy = plr[id]._py + -1; + } + + GetMissilePos(i); + + if (plr[id]._pmode == PM_WALK3) { + if (plr[id]._pdir == DIR_L) ++missile[i]._mix; + else ++missile[i]._miy; + } + + if (id != myplr && + currlevel != plr[id].plrlevel) { + missile[i]._miDelFlag = TRUE; + } + + if (plr[id]._pReflectCount <= 0) + { + missile[i]._miDelFlag = TRUE; + NetSendCmd(TRUE, CMD_ENDREFLECT); + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Manashield(int i) +{ +#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA + int j, id; + long diff, pct; + + //--missile[i]._mirange; + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + + missile[i]._mix = plr[id]._px; + missile[i]._miy = plr[id]._py; + missile[i]._mitxoff = plr[id]._pxoff << 16; + missile[i]._mityoff = plr[id]._pyoff << 16; + + if (plr[id]._pmode == PM_WALK3) { + missile[i]._misx = plr[id]._pfutx; + missile[i]._misy = plr[id]._pfuty; + } else { + missile[i]._misx = plr[id]._px; + missile[i]._misy = plr[id]._py; + } + + GetMissilePos(i); + + if (plr[id]._pmode == PM_WALK3) { + if (plr[id]._pdir == DIR_L) ++missile[i]._mix; + else ++missile[i]._miy; + } + + if (id != myplr) { + if (currlevel != plr[id].plrlevel) missile[i]._miDelFlag = TRUE; + PutMissile(i); + return; + } + + if (plr[id]._pMana <= 0 || (!plr[id].plractive)) missile[i]._mirange = 0; + + if (plr[id]._pHitPoints < missile[i]._miVar1) { + diff = missile[i]._miVar1 - plr[id]._pHitPoints; + pct = 0; + for (j = 0; j < missile[i]._mispllvl && j < 7; ++j) pct += 3; + if (pct > 0) diff = diff - (diff / pct); + if (diff < 0) diff = 0; + drawmanaflag = TRUE; + drawhpflag = TRUE; + if (plr[id]._pMana >= diff) { + plr[id]._pHitPoints = missile[i]._miVar1; + plr[id]._pHPBase = missile[i]._miVar2; + plr[id]._pMana -= diff; + plr[id]._pManaBase -= diff; + } else { + plr[id]._pHitPoints -= (diff - plr[id]._pMana); + plr[id]._pHPBase -= (diff - plr[id]._pMana); + plr[id]._pMana = 0; + plr[id]._pManaBase = -(plr[id]._pMaxMana - plr[id]._pMaxManaBase); + missile[i]._mirange = 0; + missile[i]._miDelFlag = TRUE; + if (plr[id]._pHitPoints < 0) SetPlayerHitPoints(id, 0); + if (((plr[id]._pHitPoints >> HP_SHIFT) == 0) && (id == myplr)) + StartPlrKill(id, missile[i]._miVar8); + } + } + + missile[i]._miVar1 = plr[id]._pHitPoints; + missile[i]._miVar2 = plr[id]._pHPBase; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + NetSendCmd(TRUE, CMD_ENDSHIELD); + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Ether(int i) +{ +#if (PRE_BETA && PRE_ETHER) || !PRE_BETA + int id; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + id = missile[i]._misource; + + missile[i]._mix = plr[id]._px; + missile[i]._miy = plr[id]._py; + missile[i]._mitxoff = plr[id]._pxoff << 16; + missile[i]._mityoff = plr[id]._pyoff << 16; + + if (plr[id]._pmode == PM_WALK3) { + missile[i]._misx = plr[id]._pfutx; + missile[i]._misy = plr[id]._pfuty; + } else { + missile[i]._misx = plr[id]._px; + missile[i]._misy = plr[id]._py; + } + + GetMissilePos(i); + + if (plr[id]._pmode == PM_WALK3) { + if (plr[id]._pdir == DIR_L) ++missile[i]._mix; + else ++missile[i]._miy; + } + + plr[id]._pSpellFlags |= SF_ETHER; + + if (missile[i]._mirange == 0 || plr[id]._pHitPoints <= 0) { + missile[i]._miDelFlag = TRUE; + plr[id]._pSpellFlags &= ~SF_ETHER; + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Firemove(int i) +{ + int j; + int ExpLight[14] = {2,3,4,5,5,6,7,8,9,10,11,12,12}; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mix; + --missile[i]._miy; + missile[i]._miyoff+=32; + + ++missile[i]._miVar1; + + if (missile[i]._miVar1 == missile[i]._miAnimLen) { + SetMissDir(i, 1); + missile[i]._miAnimFrame = random(82, 11) + 1; + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + j = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + if ((missile[i]._mimfnum == 0) && (missile[i]._mirange != 0)) { + if (missile[i]._miVar2 == 0) + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ++missile[i]._miVar2; + } + else if ((missile[i]._mix != missile[i]._miVar3) || (missile[i]._miy != missile[i]._miVar4)) { + missile[i]._miVar3 = missile[i]._mix; + missile[i]._miVar4 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar3, missile[i]._miVar4, 8); + } + ++missile[i]._mix; + ++missile[i]._miy; + missile[i]._miyoff-=32; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Guardian(int i) +{ +#if (PRE_BETA && PRE_GUARDIAN) || !PRE_BETA + int j, k, sx, sy, sx1, sy1, ex; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + if (missile[i]._miVar2 > 0) --missile[i]._miVar2; + + if ((missile[i]._mirange == missile[i]._miVar1) || ((missile[i]._mimfnum == 2) && + (missile[i]._miVar2 == 0))) { + SetMissDir(i, 1); + } + + if ((missile[i]._mirange % 16) == 0) { + ex = 0; + for (k = 0; (k < 23) && (ex != -1); ++k) { + for (j = 10; (j >= 0) && (ex != -1); j-=2) { + if (vCrawlTable[k][j] == 0 && vCrawlTable[k][j + 1] == 0) break; + if ((sx1 != vCrawlTable[k][j]) || (sy1 != vCrawlTable[k][j + 1])) { + sx = missile[i]._mix + vCrawlTable[k][j]; + sy = missile[i]._miy + vCrawlTable[k][j+1]; + ex = Sentfire(i, sx, sy); + if (ex == -1) break; + + sx = missile[i]._mix - vCrawlTable[k][j]; + sy = missile[i]._miy - vCrawlTable[k][j+1]; + ex = Sentfire(i, sx, sy); + if (ex == -1) break; + + sx = missile[i]._mix + vCrawlTable[k][j]; + sy = missile[i]._miy - vCrawlTable[k][j+1]; + ex = Sentfire(i, sx, sy); + if (ex == -1) break; + + sx = missile[i]._mix - vCrawlTable[k][j]; + sy = missile[i]._miy + vCrawlTable[k][j+1]; + ex = Sentfire(i, sx, sy); + if (ex == -1) break; + + sx1 = vCrawlTable[k][j]; + sy1 = vCrawlTable[k][j + 1]; + } + } + } + } + + if (missile[i]._mirange == 14) { + SetMissDir(i, 0); + missile[i]._miAnimFrame = 15; + missile[i]._miAnimAdd = -1; + } + + missile[i]._miVar3 += missile[i]._miAnimAdd; + if (missile[i]._miVar3 > 15) { + missile[i]._miVar3 = 15; + } else { + if (missile[i]._miVar3 > 0) + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, missile[i]._miVar3); + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Chain(int i) +{ +#if (PRE_BETA && PRE_CHAIN) || !PRE_BETA + int sx, sy, id, dir; + int l, n, m, k, rad; + int tx, ty; + + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + sx = missile[i]._mix; + sy = missile[i]._miy; + + dir = GetDirection(sx, sy, missile[i]._miVar1, missile[i]._miVar2); + AddMissile(sx, sy, missile[i]._miVar1, missile[i]._miVar2, dir, MIT_LIGHTCTRL, MI_ENEMYMONST, id, 1, missile[i]._mispllvl); + + rad = 3 + missile[i]._mispllvl; + if (rad > 19) rad = 19; + for (m = 1; m < rad; ++m) { + n = CrawlNum[m]; + l = n + 1; + for (k = CrawlTable[n]; k > 0; --k) { + tx = sx + CrawlTable[l]; + ty = sy + CrawlTable[(l + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + if ((dMonster[tx][ty]) > 0) { + dir = GetDirection(sx, sy, tx, ty); + AddMissile(sx, sy, tx, ty, dir, MIT_LIGHTCTRL, MI_ENEMYMONST, id, 1, missile[i]._mispllvl); + } + } + l += 2; + } + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void MI_ChainOLD(int i) +{ + int dir; + + if ((missile[i]._mirange % 3) == 0) { + dir = GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar5, missile[i]._miVar6); + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._miVar5, missile[i]._miVar6, dir, MIT_CHAINBALL, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam); + ++missile[i]._miVar7; + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void MI_ChainballOLD(int i) +{ + int mx, id; + int k, l, m, n, rad; + + --missile[i]._mirange; + id = missile[i]._misource; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + if ((missile[i]._miVar2 == 1) && (missile[i]._mix == missile[i]._miVar3) && (missile[i]._miy == missile[i]._miVar4)) { + missile[i]._miVar2 = 0; + missile[i]._mirange = 0; + + k = 0; + for (l = 0; l < nummissiles; ++l) { + mx = missileactive[l]; + if (missile[mx]._mitype == MIT_CHAINBALL && missile[i]._miVar1 == missile[mx]._miVar1) ++k; + if ((missile[mx]._mitype == MIT_CHAIN) && (missile[i]._miVar1 == missile[mx]._midam)) + k+=((4 + (GetSpellLevel(id, SPL_LIGHTNING) / 3)) - missile[mx]._miVar7); + } + + if (k == 1) { + rad = 6 + GetSpellLevel(id, SPL_CHAIN); + if (rad > 19) rad = 19; + for (m = 1; m < rad; ++m) { + n = CrawlNum[m]; + l = n + 1; + for (k = CrawlTable[n]; k > 0; --k) { + if (ChainBounce (i, missile[i]._mix + CrawlTable[l], missile[i]._miy + CrawlTable[(l + 1)]) > 0) { + m = rad; + break; + } + l += 2; + } + } + } + } else { + if ((missile[i]._mix != missile[i]._miVar5) || (missile[i]._miy != missile[i]._miVar6)) + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._miHitFlag == TRUE && missile[i]._mirange == 0 && missile[i]._miVar2 == 0) { + for (l = 0; l < nummissiles; ++l) { + mx = missileactive[l]; + if ((missile[mx]._mitype == MIT_CHAIN && missile[i]._miVar1 == missile[mx]._midam) || + (missile[mx]._mitype == MIT_CHAINBALL && missile[i]._miVar1 == missile[mx]._miVar1)) { + missile[mx]._miVar2 = 1; // flag hit and cont until v3, v4 + missile[mx]._miVar3 = missile[i]._mix; // x of hit + missile[mx]._miVar4 = missile[i]._miy; // y of hit + } + } + } + } + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Blood(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + if (missile[i]._miAnimFrame == missile[i]._miAnimLen) { +// missile[i]._miAnimFrame = missile[i]._miAnimLen; + missile[i]._miPreFlag = TRUE; + } + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Weapexp(int i) +{ + int id, mind, maxd; + int ExpLight[10] = {9,10,11,12,11,10,8,6,4,2}; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + + id = missile[i]._misource; + if (missile[i]._miVar2 == 1) { + mind = plr[id]._pIFMinDam; + maxd = plr[id]._pIFMaxDam; + missiledata[missile[i]._mitype].mResist = MIMT_FIRE; + } else { + mind = plr[id]._pILMinDam; + maxd = plr[id]._pILMaxDam; + missiledata[missile[i]._mitype].mResist = MIMT_LGHT; + } + + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._miVar1 == 0) { + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]); + } else { + if (missile[i]._mirange != 0) + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]); + } + + ++missile[i]._miVar1; + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + return; + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Misexp(int i) +{ + int ExpLight[15] = {9,10,11,12,11,10,8,6,4,2,1,0,0,0,0}; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + return; + } + + if (missile[i]._miVar1 == 0) { + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]); + } else { + if (missile[i]._mirange != 0) + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]); + } + + ++missile[i]._miVar1; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Acidsplat(int i) +{ + int monst; + int dam; + + app_assert(i < MAXMISSILES && i >= 0); + if (missile[i]._mirange == missile[i]._miAnimLen) { + ++missile[i]._mix; + ++missile[i]._miy; + missile[i]._miyoff-=32; + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + monst = missile[i]._misource; + dam = (monster[monst].MData->mLevel < 2) ? 1:2; + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_ACIDPUD, MI_ENEMYPLR, missile[i]._misource, dam, missile[i]._mispllvl); + return; + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Teleport(int i) +{ +#if (PRE_BETA && PRE_TELE) || !PRE_BETA + int id; + + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + + //sprintf(tempstr, "X: %i Y: %i FX: %i FY: %i", plr[myplr]._px, plr[myplr]._py, plr[myplr]._pfutx, plr[myplr]._pfuty); + //AddPanelString(tempstr, TEXT_LEFT); + + --missile[i]._mirange; + if (missile[i]._mirange <= 0) { + missile[i]._miDelFlag = TRUE; + return; + } + + dPlayer[(plr[id]._px)][(plr[id]._py)] = 0; + PlrClrTrans(plr[id]._px, plr[id]._py); + plr[id]._px = missile[i]._mix; + plr[id]._py = missile[i]._miy; + plr[id]._pfutx = plr[id]._px; + plr[id]._pfuty = plr[id]._py; + plr[id]._poldx = plr[id]._px; + plr[id]._poldy = plr[id]._py; + PlrDoTrans(plr[id]._px, plr[id]._py); + missile[i]._miVar1 = 1; + dPlayer[(plr[id]._px)][(plr[id]._py)] = 1 + (char)id; + + if (leveltype != 0) { + ChangeLightXY(plr[id]._plid, plr[id]._px, plr[id]._py); + ChangeVisionXY(plr[id]._pvid, plr[id]._px, plr[id]._py); + } + + if (id == myplr) { + ViewX = plr[id]._px - ScrollInfo._sdx; + ViewY = plr[id]._py - ScrollInfo._sdy; + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void MI_Doom(int i) +{ + int k, l, m, n; + int mid; + + --missile[i]._mirange; + + // check if monster moved + mid = dMonster[(missile[i]._miVar1)][(missile[i]._miVar2)]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + } + + // if he did search again + if (mid != missile[i]._miVar3) { + for (m = 0; m < 6; ++m) { + n = CrawlNum[m]; + l = n + 1; + for (k = CrawlTable[n]; k > 0; --k) { + mid = dMonster[((missile[i]._miVar1) + CrawlTable[l])][((missile[i]._miVar2) + CrawlTable[(l + 1)])]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + if (mid == missile[i]._miVar3) { + missile[i]._miVar1 += CrawlTable[l]; + missile[i]._miVar2 += CrawlTable[l + 1]; + k = -99; + m = 6; + break; + } + } + l += 2; + } + } + + // if monster killed before doom kills it + if (k != -99) { + missile[i]._miDelFlag = TRUE; + PutMissile(i); + return; + } + + // get new velocity and directions + GetMissileVel(i, missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2, 16); + SetMissDir(i, GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2)); + } + + + // move missile + if (missile[i]._mimfnum != 9) { + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + } + + // get mid for current missile pos - for checking if target monster killed + mid = dMonster[(missile[i]._mix)][(missile[i]._miy)]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + } + + // check for collision if not followed monster dont end missile + k = missile[i]._mirange; + if ((missile[i]._mix != plr[myplr]._px) || (missile[i]._miy != plr[myplr]._py)) CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + if ((missile[i]._mirange == 0) && (mid != missile[i]._miVar3) && (missile[i]._miHitFlag == TRUE)) missile[i]._mirange = k; + + // if target monster not dead halt missile in place + if ((missile[i]._mirange == 0) && (mid == missile[i]._miVar3)) { + missile[i]._mirange = k; + if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) { + if (missile[i]._mimfnum != 9) { + SetMissDir(i, 9); + } + } else { + // target is killed so re-search + for (m = 1; m < 6; ++m) { + n = CrawlNum[m]; + l = n + 1; + for (k = CrawlTable[n]; k > 0; --k) { + mid = dMonster[((missile[i]._miVar1) + CrawlTable[l])][((missile[i]._miVar2) + CrawlTable[(l + 1)])]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) { + missile[i]._miVar1 += CrawlTable[l]; + missile[i]._miVar2 += CrawlTable[l + 1]; + missile[i]._miVar3 = mid; + k = -99; + m = 6; + break; + } + } + l += 2; + } + } + + // get new velocity and directions + if (k == 0) missile[i]._mirange = 0; + else { + GetMissileVel(i, missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2, 16); + SetMissDir(i, GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2)); + } + } + } + + // delete or place missile + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Stone (int i) +{ +#if (PRE_BETA && PRE_STONE) || !PRE_BETA + int m; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + m = missile[i]._miVar2; + + if (monster[m]._mhitpoints == 0 && missile[i]._miAnimType != MF_STONE) { + SetMissAnim(i, MF_STONE); + missile[i]._mirange = 11; + } + + + if (monster[m]._mmode != MM_STONE) missile[i]._miDelFlag = TRUE; + + else { + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + if (monster[m]._mhitpoints > 0) { +// app_assert(dMonster[monster[m]._mx][monster[m]._my] == m+1 +// || dMonster[monster[m]._mx][monster[m]._my] == -(m+1)); + monster[m]._mmode = missile[i]._miVar1; + } + else AddDead(monster[m]._mx, monster[m]._my, stonendx, monster[m]._mdir); + } + + if (missile[i]._miAnimType == MF_STONE) PutMissile(i); + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Boom(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + if (missile[i]._miVar1 == 0) CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 1); + if (missile[i]._miHitFlag == TRUE) missile[i]._miVar1 = 1; + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Rhino(int i) +{ + int mix,miy; + int mix2, miy2; + int omx, omy; + int monst; + BOOL placemiss = FALSE; + + app_assert(i < MAXMISSILES && i >= 0); + monst = missile[i]._misource; + + app_assert(monst < MAXMONSTERS && monst >= 0); + if (monster[monst]._mmode != MM_MISSILE) { // monster got blood-boiled or something + missile[i]._miDelFlag = TRUE; + return; + } + + GetMissilePos(i); + + omx = missile[i]._mix; + omy = missile[i]._miy; + + dMonster[omx][omy] = NULL; + + if (monster[monst]._mAi == AI_SNAKE) + { + // Snake should stop a few frames before it enters player's square + // So we run its animation a few frames ahead here and test below + // to see if the square is available + missile[i]._mitxoff += 2*missile[i]._mixvel; + missile[i]._mityoff += 2*missile[i]._miyvel; + + GetMissilePos(i); + + mix2 = missile[i]._mix; + miy2 = missile[i]._miy; + + missile[i]._mitxoff -= 1*missile[i]._mixvel; + missile[i]._mityoff -= 1*missile[i]._miyvel; + } + else + { + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + } + + GetMissilePos(i); + + mix = missile[i]._mix; + miy = missile[i]._miy; + + + if (PosOkMonst(monst, mix, miy) + && (monster[monst]._mAi != AI_SNAKE || PosOkMonst(monst, mix2, miy2))) + { + dMonster[mix][miy] = -(monst + 1); + monster[monst]._mx = monster[monst]._moldx = monster[monst]._mfutx = mix; + monster[monst]._my = monster[monst]._moldy = monster[monst]._mfuty = miy; + + if(monster[monst]._uniqtype) + ChangeLightXY(missile[i]._mlid, mix, miy); + + MoveMissilePos(i); + PutMissile(i); + } + else + { + MissToMonst(i,omx,omy); + missile[i]._miDelFlag = TRUE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Fireman(int i) +{ + int mix,miy; + int omx, omy; + int id, m; + BOOL placemiss = FALSE; + int px,py, p; + + GetMissilePos(i); + + app_assert(i < MAXMISSILES && i >= 0); + omx = missile[i]._mix; + omy = missile[i]._miy; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + + GetMissilePos(i); + + m = missile[i]._misource; + mix = missile[i]._mix; + miy = missile[i]._miy; + + p = monster[m]._menemy; + if ((monster[m]._mFlags & MFLAG_MID) == 0) { + px = plr[p]._px; + py = plr[p]._py; + } else { + px = monster[p]._mx; + py = monster[p]._my; + } + + if((mix != omx || miy != omy) + && + ((missile[i]._miVar1 & MIF_DIDHIT + && !DIST(omx-px, omy-py, 4)) + || missile[i]._miVar2 > 1) + && PosOkMonst(missile[i]._misource, omx, omy) + ) + { + // return to monster domain + MissToMonst(i,omx, omy); + missile[i]._miDelFlag = TRUE; + } + + else + if ((monster[m]._mFlags & MFLAG_MID) == 0) id = dPlayer[mix][miy]; + else id = dMonster[mix][miy]; + if(!PosOkMissile(mix, miy) + || (id > 0 && !(missile[i]._miVar1 & MIF_DIDHIT))) + { + // bounce away + missile[i]._mixvel = -missile[i]._mixvel; + missile[i]._miyvel = -missile[i]._miyvel; + missile[i]._mimfnum = opposite[missile[i]._mimfnum]; + missile[i]._miAnimData = monster[m].MType->Anims[MA_WALK].Cels[missile[i]._mimfnum]; + + ++missile[i]._miVar2; + + if(id > 0) + { + missile[i]._miVar1 |= MIF_DIDHIT; + } + placemiss = TRUE; + } + else + placemiss = TRUE; + + if(placemiss) + { +// ChangeLightXY(monster[m].mlid, monster[m]._mx, monster[m]._my); + + MoveMissilePos(i); + PutMissile(i); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_FirewallC(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int tx, ty, pn, id; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + id = missile[i]._misource; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + else { + // if you take this out of here the wall will go though everything (hence using the nsolidtable) + //if (missile[i]._miVar1 >= MAXDUNX || missile[i]._miVar2 >= MAXDUNY) + // app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar1,missile[i]._miVar2); + pn = dPiece[missile[i]._miVar1][missile[i]._miVar2]; + app_assert(pn <= MAXTILES && pn >= 0); + tx = missile[i]._miVar1 + XDirAdd[missile[i]._miVar3]; + ty = missile[i]._miVar2 + YDirAdd[missile[i]._miVar3]; + if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(missile[i]._miVar1, missile[i]._miVar2, missile[i]._miVar1, missile[i]._miVar2, plr[id]._pdir, MIT_FIREWALL, MI_ENEMYBOTH, id, 0, missile[i]._mispllvl); + missile[i]._miVar1 = tx; + missile[i]._miVar2 = ty; + } else missile[i]._miVar8 = 1; + + // if you take this out of here the wall will go though everything (hence using the nsolidtable) + //if (missile[i]._miVar5 >= MAXDUNX || missile[i]._miVar6 >= MAXDUNY) + // app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar5,missile[i]._miVar6); + pn = dPiece[missile[i]._miVar5][missile[i]._miVar6]; + app_assert(pn <= MAXTILES && pn >= 0); + tx = missile[i]._miVar5 + XDirAdd[missile[i]._miVar4]; + ty = missile[i]._miVar6 + YDirAdd[missile[i]._miVar4]; + if (nMissileTable[pn] == 0 && missile[i]._miVar7 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(missile[i]._miVar5, missile[i]._miVar6, missile[i]._miVar5, missile[i]._miVar6, plr[id]._pdir, MIT_FIREWALL, MI_ENEMYBOTH, id, 0, missile[i]._mispllvl); + missile[i]._miVar5 = tx; + missile[i]._miVar6 = ty; + } else missile[i]._miVar7 = 1; + } +#endif +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_FlameBox(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + missile[i]._miDelFlag = TRUE; + int const id = missile[i]._micaster; + int const l = CrawlNum[3]; + int j = l + 1; + int const dam = ((random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : currlevel)) << 4) >> 1; + + for (int m = CrawlTable[l]; m > 0; --m, j+=2) { + int const tx = missile[i]._miVar1 + CrawlTable[j]; + int const ty = missile[i]._miVar2 + CrawlTable[j + 1]; + + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int const pn = dPiece[tx][ty]; + + if (!nSolidTable[pn] && dObject[tx][ty] == 0 + && LineClear(missile[i]._mix, missile[i]._miy, tx, ty) + ) + { + if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(tx, ty, tx, ty, 0, MIT_FIREWALL, MI_ENEMYBOTH, id, dam, missile[i]._mispllvl); + } else missile[i]._miVar8 = 1; + + } + } + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_LightBox(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + missile[i]._miDelFlag = TRUE; + int const id = missile[i]._micaster; + int const l = CrawlNum[3]; + int j = l + 1; + int const dam = ((random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : currlevel)) << 4) >> 1; + + for (int m = CrawlTable[l]; m > 0; --m, j+=2) { + int const tx = missile[i]._miVar1 + CrawlTable[j]; + int const ty = missile[i]._miVar2 + CrawlTable[j + 1]; + + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int const pn = dPiece[tx][ty]; + + if (!nSolidTable[pn] && dObject[tx][ty] == 0 + && LineClear(missile[i]._mix, missile[i]._miy, tx, ty) + ) + { + if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(tx, ty, tx, ty, 0, MIT_LIGHTWALL, MI_ENEMYBOTH, id, dam, missile[i]._mispllvl); + } else missile[i]._miVar8 = 1; + + } + } + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_ShowMagicItems(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + + --missile[i]._mirange; + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + int const id = missile[i]._miVar1; + PlaySfxLoc(IS_CAST7, plr[id]._px, plr[id]._py); + HighLightAllItems = false; + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_LightwallC(int i) +{ +// GWP 9/4/97 +// Copy of MI_FirewallC with switched to call the MIT_LIGHTWALL instead of MIT_FIREWALL +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int tx, ty, pn; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + + int const id = missile[i]._misource; + int const dam = (random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : 0)) << 4; + + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + else { + // if you take this out of here the wall will go though everything (hence using the nsolidtable) + //if (missile[i]._miVar1 >= MAXDUNX || missile[i]._miVar2 >= MAXDUNY) + // app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar1,missile[i]._miVar2); + pn = dPiece[missile[i]._miVar1][missile[i]._miVar2]; + app_assert(pn <= MAXTILES && pn >= 0); + tx = missile[i]._miVar1 + XDirAdd[missile[i]._miVar3]; + ty = missile[i]._miVar2 + YDirAdd[missile[i]._miVar3]; + if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(missile[i]._miVar1, missile[i]._miVar2, missile[i]._miVar1, missile[i]._miVar2, plr[id]._pdir, MIT_LIGHTWALL, MI_ENEMYBOTH, id, dam, missile[i]._mispllvl); + missile[i]._miVar1 = tx; + missile[i]._miVar2 = ty; + } else missile[i]._miVar8 = 1; + + // if you take this out of here the wall will go though everything (hence using the nsolidtable) + //if (missile[i]._miVar5 >= MAXDUNX || missile[i]._miVar6 >= MAXDUNY) + // app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar5,missile[i]._miVar6); + pn = dPiece[missile[i]._miVar5][missile[i]._miVar6]; + app_assert(pn <= MAXTILES && pn >= 0); + tx = missile[i]._miVar5 + XDirAdd[missile[i]._miVar4]; + ty = missile[i]._miVar6 + YDirAdd[missile[i]._miVar4]; + if (nMissileTable[pn] == 0 && missile[i]._miVar7 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(missile[i]._miVar5, missile[i]._miVar6, missile[i]._miVar5, missile[i]._miVar6, plr[id]._pdir, MIT_LIGHTWALL, MI_ENEMYBOTH, id, dam, missile[i]._mispllvl); + missile[i]._miVar5 = tx; + missile[i]._miVar6 = ty; + } else missile[i]._miVar7 = 1; + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Infra(int i) +{ +#if (PRE_BETA && PRE_INFRA) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + plr[(missile[i]._misource)]._pInfraFlag = TRUE; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + CalcPlrItemVals(missile[i]._misource,TRUE); + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Apoca(int i) +{ +#if (PRE_BETA && PRE_APOCA) || !PRE_BETA + int j, k, id; + BOOL exit; + + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + + exit = FALSE; + for (j = missile[i]._miVar2; (j < missile[i]._miVar3) && (exit == FALSE); ++j) { + for (k = missile[i]._miVar4; (k < missile[i]._miVar5) && (exit == FALSE); ++k) { + if (dMonster[k][j] > 3 + && nSolidTable[(dPiece[k][j])] == 0 + && LineClear(missile[i]._mix, missile[i]._miy, k, j)) { + AddMissile(k, j, k, j, plr[id]._pdir, MIT_BOOM, MI_ENEMYMONST, id, missile[i]._midam, 0); + exit = TRUE; + } + } + if (exit == FALSE) missile[i]._miVar4 = missile[i]._miVar6; + } + + if (exit == TRUE) { + missile[i]._miVar2 = j - 1; + missile[i]._miVar4 = k; + } else missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Wave(int i) +{ +#if (PRE_BETA && PRE_WAVE) || !PRE_BETA + int dira, dirb, nxa, nya, nxb, nyb; + int pn, sd, j, f1, f2, id, sx, sy, dx, dy; + + f1 = 0; + f2 = 0; + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + + sd = GetDirection(sx, sy, dx, dy); + dira = (sd - 2) & 0x0007; + dirb = (sd + 2) & 0x0007; + nxa = sx + XDirAdd[sd]; + nya = sy + YDirAdd[sd]; + + //if (nxa >= MAXDUNX || nya >= MAXDUNY) + // app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxa,nya); + pn = dPiece[nxa][nya]; + app_assert(pn <= MAXTILES && pn >= 0); + if (nMissileTable[pn] == 0) { + AddMissile(nxa, nya, nxa + XDirAdd[sd], nya + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl); + + nxa += XDirAdd[dira]; + nya += YDirAdd[dira]; + nxb = sx + XDirAdd[sd] + XDirAdd[dirb]; + nyb = sy + YDirAdd[sd] + YDirAdd[dirb]; + for (j = 0; j < (2 + (missile[i]._mispllvl>>1)); ++j) { + //if (nxa >= MAXDUNX || nya >= MAXDUNY) + // app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxa,nya); + pn = dPiece[nxa][nya]; + app_assert(pn <= MAXTILES && pn >= 0); + if (nMissileTable[pn] == 0 && f1 == 0 && nxa > 0 && nxa < MAXDUNX && nya > 0 && nya < MAXDUNY) { + AddMissile(nxa, nya, nxa + XDirAdd[sd], nya + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl); + nxa += XDirAdd[dira]; + nya += YDirAdd[dira]; + } else f1 = 1; + + //if (nxb >= MAXDUNX || nyb >= MAXDUNY) + // app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxb,nyb); + pn = dPiece[nxb][nyb]; + app_assert(pn <= MAXTILES && pn >= 0); + if (nMissileTable[pn] == 0 && f2 == 0 && nxb > 0 && nxb < MAXDUNX && nyb > 0 && nyb < MAXDUNY) { + AddMissile(nxb, nyb, nxb + XDirAdd[sd], nyb + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl); + nxb += XDirAdd[dirb]; + nyb += YDirAdd[dirb]; + } else f2 = 1; + } + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#define RAD 6 + +void MI_Nova(int i) +{ +#if (PRE_BETA && PRE_NOVA) || !PRE_BETA + int k, id, sx, sy, dir, en; + int sx1, sy1, dam, dx, dy; + + sx1 = sy1 = 0; + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + dam = missile[i]._midam; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + if (id != -1) { + dir = plr[id]._pdir; + en = MI_ENEMYMONST; + } else { + dir = 0; + en = MI_ENEMYPLR; + } + + for (k = 0; k < 23; ++k) { + if ((sx1 != vCrawlTable[k][RAD]) || (sy1 != vCrawlTable[k][RAD + 1])) { + dx = sx + vCrawlTable[k][RAD]; + dy = sy + vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl); + + dx = sx - vCrawlTable[k][RAD]; + dy = sy - vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl); + + dx = sx - vCrawlTable[k][RAD]; + dy = sy + vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl); + + dx = sx + vCrawlTable[k][RAD]; + dy = sy - vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl); + + sx1 = vCrawlTable[k][RAD]; + sy1 = vCrawlTable[k][RAD + 1]; + } + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MI_FireNova(int i) +{ +#if (PRE_BETA && PRE_NOVA) || !PRE_BETA + int k, id, sx, sy, dir, en; + int sx1, sy1, dam, dx, dy; + + sx1 = sy1 = 0; + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + dam = missile[i]._midam; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + if (id != -1) { + dir = plr[id]._pdir; + en = MI_ENEMYMONST; + } else { + dir = 0; + en = MI_ENEMYPLR; + } + + for (k = 0; k < 23; ++k) { + if ((sx1 != vCrawlTable[k][RAD]) || (sy1 != vCrawlTable[k][RAD + 1])) { + dx = sx + vCrawlTable[k][RAD]; + dy = sy + vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl); + + dx = sx - vCrawlTable[k][RAD]; + dy = sy - vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl); + + dx = sx - vCrawlTable[k][RAD]; + dy = sy + vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl); + + dx = sx + vCrawlTable[k][RAD]; + dy = sy - vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl); + + sx1 = vCrawlTable[k][RAD]; + sy1 = vCrawlTable[k][RAD + 1]; + } + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif +} + +void MI_SpecialArrow(int i) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int id, sx, sy, dir, en; + int sx1, sy1, dam, dx, dy; + + sx1 = sy1 = 0; + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + dam = missile[i]._midam; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + int extraspeed = missile[i]._miVar3; + + int mitype = MIT_ARROW; + if (id != -1) { + dir = plr[id]._pdir; + en = MI_ENEMYMONST; + switch(plr[id]._pILMinDam) + { + case 0: mitype = MIT_FBARROW; break; + case 1: mitype = MIT_LTARROW; break; + case 2: mitype = MIT_CBARROW; break; + case 3: mitype = MIT_HBARROW; break; + default: break; + } + } else { + dir = 0; + en = MI_ENEMYPLR; + } + + AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed); + if (mitype == MIT_CBARROW) + { + AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed); + AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed); + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Boil(int i) +{ + app_assert(i < MAXMISSILES && i >= 0); + missile[i]._miDelFlag = TRUE; + return; + +/*#if (PRE_BETA && PRE_BLOODB) || !PRE_BETA + int j, mid, id, dx, dy, pct; + long dm; + + BOOL M_Talker (int); + + id = missile[i]._misource; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + mid = dMonster[dx][dy]; + + if (mid > 0) --mid; + else mid = -(mid + 1); + if (mid > 0) { + if ((M_Talker(mid) && monster[mid].mtalkmsg != 0) || ((plr[id]._pLevel - 6 + missile[i]._mispllvl) <= monster[mid].mLevel)) { + missile[i]._miDelFlag = TRUE; + return; + } + + if (monster[mid].mMagicRes & M_IM) return; + + dm = monster[mid]._mhitpoints; + monster[mid]._mhitpoints = 0; + M_StartKill(mid, id); + AddPlrExperience(id, monster[mid].mLevel, monster[mid].mExp); + dMonster[monster[mid]._mx][monster[mid]._my] = 0; + monster[mid]._mDelFlag = TRUE; + AddMissile(monster[mid]._mx, monster[mid]._my, monster[mid]._mx, monster[mid]._my, plr[id]._pdir, MIT_SPURT, MI_ENEMYMONST, id, (random(87, 2) + 1), 0); + AddDead(monster[mid]._mx, monster[mid]._my, spurtndx, monster[mid]._mdir); + + pct = 0; + for (j = 0; j < missile[i]._mispllvl && j < 5; ++j) pct += 10; + //dm = (monster[mid]._mmaxhp >> 1); + if (pct > 0) dm -= (dm / pct); + plr[id]._pHitPoints -= dm; + plr[id]._pHPBase -= dm; + + if (plr[id]._pHitPoints > plr[id]._pMaxHP) { + plr[id]._pHitPoints = plr[id]._pMaxHP; + plr[id]._pHPBase = plr[id]._pMaxHPBase; + } + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } else StartPlrHit(id, dm); + + PlaySfxLoc(LS_BLODBOIL, monster[mid]._mx, monster[mid]._my); + UseMana(id, SPL_BLOODB); + } + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif*/ +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Rage(int i) +{ +#if !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + + --missile[i]._mirange; + if (missile[i]._mirange == 0) { + int const pid = missile[i]._miVar1; + if ((plr[pid]._pSpellFlags & SF_RAGE) == SF_RAGE) { + int const Sounds[NUM_CLASSES] = { PS_WARR72, + PS_ROGUE72, + PS_MAGE72, + PS_MAGE72, // monk + PS_BARD72, + PS_BARBARIAN72 }; + plr[pid]._pSpellFlags &= ~SF_RAGE; + plr[pid]._pSpellFlags |= SF_LETHERGY; + missile[i]._mirange = 245 + (10 * missile[i]._mispllvl) + (2 * (pid > 0) ? plr[pid]._pLevel : 1); + int const diffHpts = plr[pid]._pMaxHP - plr[pid]._pHitPoints; + CalcPlrItemVals(pid, TRUE); + + plr[pid]._pHitPoints -= diffHpts; + if (plr[pid]._pHitPoints < (1 << HP_SHIFT)) { + // Don't quite die. + plr[pid]._pHitPoints = 1 << HP_SHIFT; + } + force_redraw = FULLDRAW; + PlaySfxLoc(Sounds[plr[pid]._pClass], plr[pid]._px, plr[pid]._py); + } + else { + int const Sounds[NUM_CLASSES] = { PS_WARR72, + PS_ROGUE72, + PS_MAGE72, + PS_MAGE72, // monk + PS_BARD72, + PS_BARBARIAN72 }; + missile[i]._miDelFlag = TRUE; + plr[pid]._pSpellFlags &= ~SF_LETHERGY; + int const diffHpts = plr[pid]._pMaxHP - plr[pid]._pHitPoints; + CalcPlrItemVals(pid, TRUE); + plr[pid]._pHitPoints -= missile[i]._miVar2 + diffHpts; + if (plr[pid]._pHitPoints < (1 << HP_SHIFT)) { + // Don't quite die. + plr[pid]._pHitPoints = 1 << HP_SHIFT; + } + force_redraw = FULLDRAW; + PlaySfxLoc(Sounds[plr[pid]._pClass], plr[pid]._px, plr[pid]._py); + } + } +#endif +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Flame(int i) +{ +#if (PRE_BETA && PRE_FLAME) || !PRE_BETA + int k, id; + + app_assert(i < MAXMISSILES && i >= 0); + id = missile[i]._misource; + --missile[i]._mirange; + --missile[i]._miVar2; + + k = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag == TRUE)) missile[i]._mirange = k; + if (missile[i]._miVar2 == 0) missile[i]._miAnimFrame = 20; + if (missile[i]._miVar2 <= 0) { + k = missile[i]._miAnimFrame; + if (k > 11) k = 24 - k; + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, k); + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + if (missile[i]._miVar2 <= 0) PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Flamec(int i) +{ +#if (PRE_BETA && PRE_FLAME) || !PRE_BETA + int id, pn; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + id = missile[i]._misource; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + app_assert(missile[i]._mix < MAXDUNX && missile[i]._mix >= 0); + app_assert(missile[i]._miy < MAXDUNY && missile[i]._miy >= 0); + pn = dPiece[missile[i]._mix][missile[i]._miy]; + app_assert(pn <= MAXTILES && pn >= 0); + if (nMissileTable[pn] == 0) + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_FLAME, missile[i]._micaster, id, missile[i]._miVar3, missile[i]._mispllvl); + else + missile[i]._mirange = 0; + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ++missile[i]._miVar3; + } + + if (missile[i]._mirange == 0 || missile[i]._miVar3 == 3) missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Cbolt(int i) +{ +#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA + int bpath[16] = { -1, 0, 1, -1, 0, 1, -1, -1, 0, 0, 1, 1, 0, 1, -1, 0 }; + int sx, sy, dx, dy, md; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + if (missile[i]._miAnimType != MF_LIGHTNING) { + if (missile[i]._miVar3 == 0) { + md = (missile[i]._miVar2 + bpath[missile[i]._mirnd]) & 0x07; + missile[i]._mirnd = (missile[i]._mirnd + 1) & 0x0f; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = sx + XDirAdd[md]; + dy = sy + YDirAdd[md]; + GetMissileVel(i, sx, sy, dx, dy, 8); + missile[i]._miVar3 = 16; + } else --missile[i]._miVar3; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) { + missile[i]._miVar1 = 8; + missile[i]._mimfnum = 0; + missile[i]._mixoff = 0; + missile[i]._miyoff = 0; + SetMissAnim(i, MF_LIGHTNING); + missile[i]._mirange = missile[i]._miAnimLen; + GetMissilePos(i); + } + + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, missile[i]._miVar1); + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Hbolt(int i) +{ +#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA + int dam; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + if (missile[i]._miAnimType != MF_HEXPL) { + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + + GetMissilePos(i); + + dam = missile[i]._midam; + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) { + missile[i]._mitxoff -= missile[i]._mixvel; + missile[i]._mityoff -= missile[i]._miyvel; + GetMissilePos(i); + missile[i]._mimfnum = 0; + SetMissAnim(i, MF_HEXPL); + missile[i]._mirange = missile[i]._miAnimLen - 1; + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8); + } + } + } else { + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, 7 + missile[i]._miAnimFrame); + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Element(int i) +{ +#if (PRE_BETA && PRE_ELEMENT) || !PRE_BETA + int j, mid, sd, dam; + int cx, cy, px, py, id; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + dam = missile[i]._midam; + id = missile[i]._misource; + + if (missile[i]._miAnimType == MF_BIGEXP) { + cx = missile[i]._mix; + cy = missile[i]._miy; + px = plr[id]._px; + py = plr[id]._py; + ChangeLight(missile[i]._mlid, cx, cy, missile[i]._miAnimFrame); + + if (CheckBlock(px, py, cx , cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy, 1); + if (CheckBlock(px, py, cx , cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy + 1, 1); + if (CheckBlock(px, py, cx , cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy - 1, 1); + if (CheckBlock(px, py, cx + 1, cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy, 1); + if (CheckBlock(px, py, cx + 1, cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy - 1, 1); + if (CheckBlock(px, py, cx + 1, cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy + 1, 1); + if (CheckBlock(px, py, cx - 1, cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy, 1); + if (CheckBlock(px, py, cx - 1, cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy + 1, 1); + if (CheckBlock(px, py, cx - 1, cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy - 1, 1); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); + return; + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + cx = missile[i]._mix; + cy = missile[i]._miy; + + j = missile[i]._mirange; + CheckMissileCol(i, dam, dam, 0, cx, cy, 0); + + if (missile[i]._miVar3 == 0) { + //if (missile[i]._mirange == 0 && missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + //if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag != TRUE)) missile[i]._miVar3 = 1; + if ((cx == missile[i]._miVar4) && (cy == missile[i]._miVar5)) missile[i]._miVar3 = 1; + } + + if (missile[i]._miVar3 == 1) { + missile[i]._miVar3 = 2; + missile[i]._mirange = 255; + mid = FindClosest(cx, cy, 19); + if (mid > 0) { + sd = GetDirection8(cx, cy, monster[mid]._mx, monster[mid]._my); + SetMissDir(i, sd); + GetMissileVel(i, cx, cy, monster[mid]._mx, monster[mid]._my, 16); + } else { + sd = plr[id]._pdir; + SetMissDir(i, sd); + GetMissileVel(i, cx, cy, cx + XDirAdd[sd], cy + YDirAdd[sd], 16); + } + } + + if ((cx != missile[i]._miVar1) || (cy != missile[i]._miVar2)) { + missile[i]._miVar1 = cx; + missile[i]._miVar2 = cy; + ChangeLight(missile[i]._mlid, cx, cy, 8); + } + + if (missile[i]._mirange == 0) { + missile[i]._mimfnum = 0; + SetMissAnim(i, MF_BIGEXP); + missile[i]._mirange = missile[i]._miAnimLen - 1; + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Bonespirit(int i) +{ +#if (PRE_BETA && PRE_BONESPIRIT) || !PRE_BETA + int j, mid, sd, dam; + int cx, cy, id; + + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + dam = missile[i]._midam; + id = missile[i]._misource; + + if (missile[i]._mimfnum == 8) { + cx = missile[i]._mix; + cy = missile[i]._miy; + //px = plr[id]._px; + //py = plr[id]._py; + ChangeLight(missile[i]._mlid, cx, cy, missile[i]._miAnimFrame); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); + return; + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + cx = missile[i]._mix; + cy = missile[i]._miy; + + j = missile[i]._mirange; + CheckMissileCol(i, dam, dam, 0, cx, cy, 0); + + if (missile[i]._miVar3 == 0) { + //if (missile[i]._mirange == 0 && missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + //if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag != TRUE)) missile[i]._miVar3 = 1; + if ((cx == missile[i]._miVar4) && (cy == missile[i]._miVar5)) missile[i]._miVar3 = 1; + } + + if (missile[i]._miVar3 == 1) { + missile[i]._miVar3 = 2; + missile[i]._mirange = 255; + mid = FindClosest(cx, cy, 19); + if (mid > 0) { + missile[i]._midam = (monster[mid]._mhitpoints >> HP_SHIFT) >> 1; + sd = GetDirection8(cx, cy, monster[mid]._mx, monster[mid]._my); + SetMissDir(i, sd); + GetMissileVel(i, cx, cy, monster[mid]._mx, monster[mid]._my, 16); + } else { + sd = plr[id]._pdir; + SetMissDir(i, sd); + GetMissileVel(i, cx, cy, cx + XDirAdd[sd], cy + YDirAdd[sd], 16); + } + } + + if ((cx != missile[i]._miVar1) || (cy != missile[i]._miVar2)) { + missile[i]._miVar1 = cx; + missile[i]._miVar2 = cy; + ChangeLight(missile[i]._mlid, cx, cy, 8); + } + + if (missile[i]._mirange == 0) { + SetMissDir(i, 8); + missile[i]._mirange = 7; + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_ResurrectBeam(int i) +{ +#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA + app_assert(i < MAXMISSILES && i >= 0); + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Rportal(int i) +{ + int ExpLight[17] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15}; + + app_assert(i < MAXMISSILES && i >= 0); + if (missile[i]._mirange > 1) --missile[i]._mirange; + + if (missile[i]._mirange == missile[i]._miVar1) { + SetMissDir(i, 1); + } + + if ((currlevel != 0) && (missile[i]._mimfnum != 1) && (missile[i]._mirange != 0)) { + if (missile[i]._miVar2 == 0) + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ++missile[i]._miVar2; + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ProcessMissiles () +{ + int i, mi; + + + for (i = 0; i < nummissiles; ++i) { + mi = missileactive[i]; + dFlags[missile[mi]._mix][missile[mi]._miy] &= BFMASK_MISSILE; + dMissile[missile[mi]._mix][missile[mi]._miy] = 0; + // Preventative code to prevent going off into the hinderlands. + if (missile[mi]._mix < 0 || missile[mi]._mix >= (MAXDUNX - 1)|| + missile[mi]._miy < 0 || missile[mi]._miy >= (MAXDUNY - 1) ) + { + missile[mi]._miDelFlag = TRUE; + } + } + + i = 0; + while (i < nummissiles) { + mi = missileactive[i]; + if (missile[mi]._miDelFlag) { + DeleteMissile(mi, i); + i = 0; + } else ++i; + } + + MissilePreFlag = FALSE; + ManashieldFlag = 0; + for (i = 0; i < nummissiles; ++i) { + mi = missileactive[i]; + + missiledata[missile[mi]._mitype].mProc(mi); + + if(!(missile[mi]._miAnimFlags & MFF_STATIC)) + { + ++missile[mi]._miAnimCnt; + if (missile[mi]._miAnimCnt >= missile[mi]._miAnimDelay) { + missile[mi]._miAnimCnt = 0; + missile[mi]._miAnimFrame += missile[mi]._miAnimAdd; + if (missile[mi]._miAnimFrame > missile[mi]._miAnimLen) missile[mi]._miAnimFrame = 1; + if (missile[mi]._miAnimFrame < 1) missile[mi]._miAnimFrame = missile[mi]._miAnimLen; + } + } + } + + if (ManashieldFlag) { + for (i = 0; i < nummissiles; ++i) { + mi = missileactive[i]; + if (missile[mi]._mitype == MIT_MANASHIELD) MI_Manashield(mi); + } + } + + i = 0; + while (i < nummissiles) { + mi = missileactive[i]; + if (missile[mi]._miDelFlag == TRUE) { + DeleteMissile(mi, i); + i = 0; + } else ++i; + } +} + +void SyncMissAnim() +{ + int i,mi; + + for (i = 0; i < nummissiles; ++i) + { + app_assert(i < MAXMISSILES && i >= 0); + mi = missileactive[i]; + + app_assert(mi < MAXMISSILES && mi >= 0); + MissileStruct *Miss = &missile[mi]; + + Miss->_miAnimData = misfiledata[Miss->_miAnimType].mAnimData[Miss->_mimfnum]; + + if (Miss->_mitype == MIT_RHINO) + { + AnimStruct *anim; + + if (EquivMonst(monster[Miss->_misource].MType->mtype, MT_HORNED)) + anim = &monster[Miss->_misource].MType->Anims[MA_SPECIAL]; + else if (EquivMonst(monster[Miss->_misource].MType->mtype, MT_NSNAKE)) + anim = &monster[Miss->_misource].MType->Anims[MA_ATTACK]; + else + anim = &monster[Miss->_misource].MType->Anims[MA_WALK]; + + missile[mi]._miAnimData = anim->Cels[Miss->_mimfnum]; + } + // need similar section for Fireman + } +} + +/*-----------------------------------------------------------------------* +** Used when we need to "emergency" delete missiles +**-----------------------------------------------------------------------*/ +void ClearMissileSpot(int mi) +{ + app_assert(mi < MAXMISSILES && mi >= 0); + dFlags[missile[mi]._mix][missile[mi]._miy] &= BFMASK_MISSILE; + dMissile[missile[mi]._mix][missile[mi]._miy] = 0; +} diff --git a/src/MISSILES.H b/src/MISSILES.H new file mode 100644 index 0000000..866170f --- /dev/null +++ b/src/MISSILES.H @@ -0,0 +1,220 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/MISSILES.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXMISSILES 125 + +#define MIT_ARROW 0 +#define MIT_FIREBOLT 1 +#define MIT_GUARDIAN 2 +#define MIT_PHASE 3 +#define MIT_LIGHTBALL 4 +#define MIT_FIREWALL 5 +#define MIT_FIREBALL 6 +#define MIT_LIGHTCTRL 7 +#define MIT_LIGHTNING 8 +#define MIT_MISEXP 9 +#define MIT_TOWN 10 +#define MIT_FLASH 11 +#define MIT_FLASH2 12 +#define MIT_MANASHIELD 13 +#define MIT_FIREMOVE 14 +#define MIT_CHAIN 15 +#define MIT_CHAINBALL 16 +#define MIT_BLOOD 17 +#define MIT_BONE 18 +#define MIT_METAL 19 +#define MIT_RHINO 20 +#define MIT_MAGMABALL 21 +#define MIT_THINLIGHTCTRL 22 +#define MIT_THINLIGHT 23 +#define MIT_FLARE 24 +#define MIT_FLAREXP 25 +#define MIT_TELE 26 +#define MIT_FARROW 27 +#define MIT_DOOM 28 +#define MIT_FIREONLY 29 +#define MIT_STONE 30 +#define MIT_BLOODR 31 +#define MIT_INVIS 32 +#define MIT_GOLEM 33 +#define MIT_ETHER 34 +#define MIT_SPURT 35 +#define MIT_BOOM 36 +#define MIT_HEAL 37 +#define MIT_FIREWALLC 38 +#define MIT_INFRA 39 +#define MIT_IDENTIFY 40 +#define MIT_WAVE 41 +#define MIT_NOVA 42 +//#define MIT_BLDBOIL 43 +#define MIT_RAGE 43 +#define MIT_APOCA 44 +#define MIT_REPAIR 45 +#define MIT_RECHARGE 46 +#define MIT_DISARM 47 +#define MIT_FLAME 48 +#define MIT_FLAMEC 49 +#define MIT_FIREMAN 50 +#define MIT_KRULL 51 +#define MIT_CBOLT 52 +#define MIT_HBOLT 53 +#define MIT_RESURRECT 54 +#define MIT_TELEKINESIS 55 +#define MIT_LARROW 56 +#define MIT_ACID 57 +#define MIT_ACIDSPLAT 58 +#define MIT_ACIDPUD 59 +#define MIT_HEALOTHER 60 +#define MIT_ELEMENT 61 +#define MIT_RESURRECTBEAM 62 +#define MIT_BONESPIRIT 63 +#define MIT_WEAPEXP 64 +#define MIT_RPORTAL 65 +#define MIT_FIREPLAR 66 +#define MIT_DIABAPOCA 67 +#define MIT_MANA 68 +#define MIT_FMANA 69 +#define MIT_LIGHTWALL 70 +#define MIT_LIGHTWALLC 71 +#define MIT_IMMOLATION 72 +#define MIT_SPECARROW 73 +#define MIT_FBARROW 74 +#define MIT_LTARROW 75 +#define MIT_CBARROW 76 +#define MIT_HBARROW 77 +#define MIT_TELESTAIRS 78 +#define MIT_REFLECT 79 +#define MIT_BERSERK 80 +#define MIT_FLAMEBOX 81 +#define MIT_DISENCHANT 82 +#define MIT_MANAREMOVE 83 +#define MIT_LIGHTBOX 84 +#define MIT_SHOWMAGITEMS 85 +#define MIT_AURA 86 +#define MIT_AURA2 87 +#define MIT_SPIRALFIREBALL 88 +#define MIT_RUNEOFFIRE 89 +#define MIT_RUNEOFLIGHT 90 +#define MIT_RUNEOFNOVA 91 +#define MIT_RUNEOFIMMOLATION 92 +#define MIT_RUNEOFSTONE 93 +#define MIT_BIGEXPLOSION 94 +#define MIT_HORKSPAWN 95 +#define MIT_RANDOM 96 +#define MIT_OPENNEST 97 +#define MIT_ORANGEFLARE 98 +#define MIT_BLUEFLARE 99 +#define MIT_REDFLARE 100 +#define MIT_YELLOWFLARE 101 +#define MIT_BLUE2FLARE 102 +#define MIT_YELLOWEXPLOSION 103 +#define MIT_REDEXPLOSION 104 +#define MIT_BLUEEXPLOSION 105 +#define MIT_BLUE2EXPLOSION 106 +#define MIT_ORANGEEXPLOSION 107 + +#define NUMBER_OF_MISSILE_TYPES (1 + MIT_ORANGEEXPLOSION) + +#define MI_ENEMYMONST 0 +#define MI_ENEMYPLR 1 +#define MI_ENEMYBOTH 2 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + int _mitype; // missile type + int _mix; // missile map x + int _miy; // missile map y + long _mixoff; // offset x from left of map tile + long _miyoff; // offset y from bottom of map tile + long _mixvel; // current x rate + long _miyvel; // current y rate + int _misx; // missile map start x + int _misy; // missile map start y + long _mitxoff; // missile total offset from start x + long _mityoff; // missile total offset from start y + int _mimfnum; // current facing direction + int _mispllvl; // level of missile + BOOL _miDelFlag; // delete flag + BYTE _miAnimType; // data pointer to anim tables + BOOL _miAnimFlags; // various animation related flags + BYTE *_miAnimData; // Data pointer to anim tables + int _miAnimDelay; // anim delay amount + int _miAnimLen; // number of anim frames + long _miAnimWidth; // anim width + long _miAnimWidth2; // anim width2 + int _miAnimCnt; // current anim delay value + int _miAnimAdd; // anim number to add to next frame (-1 backwards) + int _miAnimFrame; // current anim frame + BOOL _miDrawFlag; // draw missile at all + BOOL _miLightFlag; // draw with light sourcing? + BOOL _miPreFlag; // draw missile behind plr,monsters,objects + BOOL _miUniqTrans; // draw missile with special palette translation + int _mirange; // max range of missile + int _misource; // which monster/plr shot me + int _micaster; // monst/plr/damages both. + int _midam; // missile damage + BOOL _miHitFlag; // did it hit a monster or plr? + int _midist; // how long have I been traveling + int _mlid; // light id + int _mirnd; // random seed + long _miVar1; // scratch var 1 + long _miVar2; // scratch var 2 + long _miVar3; // scratch var 3 + long _miVar4; // scratch var 4 + long _miVar5; // scratch var 5 + long _miVar6; // scratch var 6 + long _miVar7; // scratch var 7 + long _miVar8; // scratch var 8 +} MissileStruct; +#define SAVE_MISSILE_SIZE sizeof(MissileStruct) + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern int nummissiles; +extern int missileactive[MAXMISSILES]; +extern int missileavail[MAXMISSILES]; +extern BOOL MissilePreFlag; +extern MissileStruct missile[MAXMISSILES]; +extern int XDirAdd[8]; +extern int YDirAdd[8]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitMissileGFX(); +void FreeMissileGFX(); +void ILoadMissileGFX(BYTE); +void IFreeMissileGFX(); +void InitMissiles(); + +void ProcessMissiles(); +int AddMissile(int, int, int, int, int, int, char, int, int, int); + +//void RndBlood (int, int, int, int, int); + +BOOL MonsterTrapHit(int, int, int, int, int, byte); +BOOL PlayerMHit(int, int, int, int, int, int, byte, BOOL, bool *); +int GetSpellLevel(int, int); +void GetDamageAmt(int, int *, int *); + +void SyncMissAnim(); + +void ClearMissileSpot(int mi); diff --git a/src/MISSILES.SAV b/src/MISSILES.SAV new file mode 100644 index 0000000..159028c --- /dev/null +++ b/src/MISSILES.SAV @@ -0,0 +1,6889 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Missiles file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MISSILES.CPP 3 2/25/97 2:27p Jmcreynolds $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include +#include +#include "sound.h" +#include "missiles.h" +#include "misdat.h" +#include "engine.h" +#include "gendung.h" +#include "lighting.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "monstdat.h" +#include "monstint.h" +#include "control.h" +#include "objects.h" +#include "objdat.h" +#include "spells.h" +#include "cursor.h" +#include "dead.h" +#include "effects.h" +#include "palette.h" +#include "inv.h" +#include "msg.h" +#include "quests.h" +#include "itemdat.h" +#include "multi.h" +#include "trigs.h" +#include "scrollrt.h" + +/*-----------------------------------------------------------------------* +** Constants +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +#define CEL_EXT ".CL2" +#else +#define CEL_EXT ".CEL" +#endif + + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +MissileStruct missile[MAXMISSILES]; +int nummissiles; + +static int missilevars[MAXMISSILES][3]; //0 missile num; 1 var1; 2 var2 +static int nummissilevars; + +int missileactive[MAXMISSILES]; +int missileavail[MAXMISSILES]; + +int XDirAdd[8] = { 1, 0, -1, -1, -1, 0, 1, 1 }; +int YDirAdd[8] = { 1, 1, 1, 0, -1, -1, -1, 0 }; + +// Indexes into the CrawlTable. +static int const CrawlNum[19] = { 0, 3, 12, 45, 94, 159, 240, 337, 450, 579, 724, + 885, 1062, 1255, 1464, 1689, 1930, 2187, 2460 }; + +BOOL ManashieldFlag; +BOOL MissilePreFlag; + +typedef BOOL (*CHECKFUNC)(int x, int y); + +static void GetMissilePos(int i); + +/*-----------------------------------------------------------------------** +**----------------------- General use routines --------------------------** +**-----------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GetDamageAmt(int i, int * mind, int * maxd) +{ + int k, sl; + + app_assert(myplr < MAX_PLRS); + app_assert(i < 64); + sl = plr[myplr]._pSplLvl[i] + plr[myplr]._pISplLvlAdd; + + switch (i) { + case SPL_FIREBOLT: + *mind = 1 + (plr[myplr]._pMagic >> 3) + sl; + *maxd = 10 + (plr[myplr]._pMagic >> 3) + sl; + break; + case SPL_HEAL: + *mind = 1 + plr[myplr]._pLevel + sl; + if (plr[myplr]._pClass == CLASS_WARRIOR) *mind = *mind << 1; + else if (plr[myplr]._pClass == CLASS_ROGUE || + plr[myplr]._pClass == CLASS_BARD) *mind += (*mind >> 1); + *maxd = 10; + for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 4; + for (k = 0; k < sl; ++k) *maxd += 6; + if (plr[myplr]._pClass == CLASS_WARRIOR) *maxd = *maxd << 1; + else if (plr[myplr]._pClass == CLASS_ROGUE || + plr[myplr]._pClass == CLASS_BARD) *maxd += (*maxd >> 1); + *mind = -1; + *maxd = -1; + break; + case SPL_LIGHTNING: + *mind = 2; + *maxd = plr[myplr]._pLevel + 2; + break; + case SPL_FLASH: + *mind = plr[myplr]._pLevel; + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *mind += *mind >> 1; + *maxd = *mind << 1; // this is not actual(below is) - its a kludge to make it seem acurate text wise + /**maxd = 0; + for (k = 0; k <= plr[myplr]._pLevel; ++k) *maxd += 20; + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + *maxd += *maxd >> 1;*/ + break; + case SPL_IDENTIFY: + case SPL_TOWN: + case SPL_STONE: + case SPL_INFRA: + case SPL_PHASE: + case SPL_MANASHLD: + case SPL_DOOM: + case SPL_BLOODR: + case SPL_INVIS: + case SPL_BLOODB: + case SPL_TELE: + case SPL_ETHER: + case SPL_REPAIR: + case SPL_RECHARGE: + case SPL_DISARM: + case SPL_RESURRECT: + case SPL_TELEKINESIS: + case SPL_BONESPIRIT: + *mind = -1; + *maxd = -1; + break; + case SPL_WALL: + *mind = ((2 + plr[myplr]._pLevel) << 2) >> 1; + *maxd = ((20 + plr[myplr]._pLevel) << 2) >> 1; + break; + case SPL_FIREBALL: + *mind = (2 + plr[myplr]._pLevel) << 1; + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *maxd = (20 + plr[myplr]._pLevel) << 1; + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + break; + case SPL_GUARDIAN: + *mind = 1 + (plr[myplr]._pLevel >> 1); + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *maxd = 10 + (plr[myplr]._pLevel >> 1); + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + break; + case SPL_CHAIN: + // this is not actual - its a kludge to make it seem acurate text wise + *mind = 2 << 1; + *maxd = (plr[myplr]._pLevel + 2) << 1; + break; + case SPL_WAVE: + // this is not actual - its a kludge to make it seem acurate text wise + *mind = ((1 + plr[myplr]._pLevel) << 2) + ((1 + plr[myplr]._pLevel) << 1); + *maxd = ((10 + plr[myplr]._pLevel) << 2) + ((10 + plr[myplr]._pLevel) << 1); + break; + case SPL_NOVA: + // this is not actual - its a kludge to make it seem acurate text wise + *mind = (5 + plr[myplr]._pLevel) >> 1; + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *mind = (*mind << 2) + *mind; + *maxd = (30 + plr[myplr]._pLevel) >> 1; + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + *maxd = (*maxd << 2) + *maxd; + break; + case SPL_FLAME: + *mind = 2; + *mind += *mind >> 1; + *maxd = (plr[myplr]._pLevel + 4); + *maxd += *maxd >> 1; + break; + case SPL_GOLEM: + *mind = 11; + *maxd = 17; + break; + case SPL_APOCA: + *mind = 0; + for (k = 0; k < plr[myplr]._pLevel; ++k) *mind += 1; + *maxd = 0; + for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 6; + break; + case SPL_ELEMENT: + *mind = (2 + plr[myplr]._pLevel) << 1; + for (k = sl; k > 0; --k) *mind += (*mind >> 3); + *maxd = (20 + plr[myplr]._pLevel) << 1; + for (k = sl; k > 0; --k) *maxd += (*maxd >> 3); + break; + case SPL_CBOLT: + *mind = 1; + *maxd = 1 + (plr[myplr]._pMagic >> 2); + break; + case SPL_HBOLT: + *mind = 9 + plr[myplr]._pLevel; + *maxd = 18 + plr[myplr]._pLevel; + break; + case SPL_HEALOTHER: + *mind = 1 + plr[myplr]._pLevel + sl; + if (plr[myplr]._pClass == CLASS_WARRIOR) *mind = *mind << 1; + if (plr[myplr]._pClass == CLASS_ROGUE || + plr[myplr]._pClass == CLASS_BARD ) *mind += (*mind >> 1); + *maxd = 10; + for (k = 0; k < plr[myplr]._pLevel; ++k) *maxd += 4; + for (k = 0; k < sl; ++k) *maxd += 6; + if (plr[myplr]._pClass == CLASS_WARRIOR) *maxd = *maxd << 1; + if (plr[myplr]._pClass == CLASS_ROGUE || + plr[myplr]._pClass == CLASS_BARD ) *maxd += (*maxd >> 1); + *mind = -1; + *maxd = -1; + break; + case SPL_BSTAR: + *mind = ((plr[myplr]._pMagic>>1)-(plr[myplr]._pMagic>>3)) + (sl << 1) + sl; + *maxd = *mind; + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int CheckBlock(int fx, int fy, int tx, int ty) +{ + int pn, dir, coll; + + coll = 0; + + while ((fx != tx) || (fy != ty)) { + dir = GetDirection(fx, fy, tx, ty); + fx += XDirAdd[dir]; + fy += YDirAdd[dir]; + app_assert(fx < MAXDUNX); + app_assert(fy < MAXDUNY); + pn = dPiece[fx][fy]; + app_assert(pn <= MAXTILES); + if (nSolidTable[pn]) coll = 1; + } + + return coll; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int FindClosest(int sx, int sy, int rad) +{ + int cr, cidx, cent, cne, mid, tx, ty; + + if (rad > 19) rad = 19; + + for (cr = 1; cr < rad; ++cr) { + cidx = CrawlNum[cr]; + cent = cidx + 1; + for (cne = CrawlTable[cidx]; cne > 0; --cne) { + tx = sx + CrawlTable[cent]; + ty = sy + CrawlTable[(cent + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + mid = dMonster[tx][ty]; + if ((mid > 0) && (CheckBlock(sx, sy, tx, ty) == 0)) + return (mid - 1); + } + cent += 2; + } + } + + return (-1); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static bool SetMissileLocation(int i, int *sx, int *sy, int rad) +{ + bool success = false; + + if (rad > 19) rad = 19; + + for (int cr = 1; cr < rad && !success; ++cr) { + int const cidx = CrawlNum[cr]; + int cent = cidx + 1; + for (int cne = CrawlTable[cidx]; cne > 0; --cne, cent += 2) { + int const tx = *sx + CrawlTable[cent]; + int const ty = *sy + CrawlTable[(cent + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int const pn = dPiece[tx][ty]; + if (!nSolidTable[pn] && dObject[tx][ty] == 0) { + missile[i]._mix = tx; + missile[i]._miy = ty; + *sx = tx; + *sy = ty; + success = true; + break; + } + } + } + } + + return (success); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int GetSpellLevel(int id, int sn) +{ + int rv; + + app_assert(id < MAX_PLRS); + app_assert(sn < 64); + if (id == myplr) + rv = plr[id]._pSplLvl[sn] + plr[id]._pISplLvlAdd; + else + rv = 1; + if (rv < 0 ) rv = 0; + return (rv); +} + +#if 0 // UNUSED +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RndBlood(int x, int y, int type, int dam, int hp) +{ + int pct, str; + + app_assert(hp != 0); + str = 0; + pct = (dam * 100) / hp; + if (pct > 65) str = 1; + if (pct > 80) str = 2; + if (pct > 90) str = 3; + str = 1; + + //AddMissile(x, y, str, 0, 0, type, 0, myplr, 0); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static int GetDirection8(int x1, int y1, int x2, int y2) +{ + BYTE const Dirs[16][16] = { + { 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 + { 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1 + { 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2 + { 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // 3 + { 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // 4 + { 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, // 5 + { 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 6 + { 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 7 + { 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 8 + { 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 9 + { 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 10 + { 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 11 + { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 12 + { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 13 + { 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 14 + { 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }};// 15 + + BYTE const lrtoul[3] = { 3, 4, 5 }; + BYTE const urtoll[3] = { 3, 2, 1 }; + BYTE const lltour[3] = { 7, 6, 5 }; + BYTE const ultolr[3] = { 7, 0, 1 }; + + int mx, my, md; + + mx = abs(x2 - x1); + if (mx > 15) mx = 15; + my = abs(y2 - y1); + if (my > 15) my = 15; + md = Dirs[my][mx]; + + if (x1 > x2) { + if (y1 > y2) md = lrtoul[md]; + else md = urtoll[md]; + } else { + if (y1 > y2) md = lltour[md]; + else md = ultolr[md]; + } + + return (md); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static int GetDirection16(int x1, int y1, int x2, int y2) +{ + const BYTE Dirs[16][16] = { + { 99, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 + { 4, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1 + { 4, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2 + { 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // 3 + { 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 4 + { 4, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // 5 + { 4, 4, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1 }, // 6 + { 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 }, // 7 + { 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1 }, // 8 + { 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1 }, // 9 + { 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1 }, // 10 + { 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1 }, // 11 + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }, // 12 + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }, // 13 + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2 }, // 14 + { 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2 }};// 15 + + const BYTE lrtoul[5] = { 6, 7, 8, 9, 10 }; + const BYTE urtoll[5] = { 6, 5, 4, 3, 2 }; + const BYTE lltour[5] = { 14, 13, 12, 11, 10 }; + const BYTE ultolr[5] = { 14, 15, 0, 1, 2 }; + + int mx, my, md; + + mx = abs(x2 - x1); + if (mx > 15) mx = 15; + my = abs(y2 - y1); + if (my > 15) my = 15; + md = Dirs[my][mx]; + + if (x1 > x2) { + if (y1 > y2) md = lrtoul[md]; + else md = urtoll[md]; + } else { + if (y1 > y2) md = lltour[md]; + else md = ultolr[md]; + } + + return (md); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DeleteMissile(int mi, int i) +{ + app_assert(nummissiles <= MAXMISSILES); + missileavail[MAXMISSILES - nummissiles] = mi; + --nummissiles; + + if ((nummissiles > 0) && (i != nummissiles)) { + app_assert(i < MAXMISSILES); + missileactive[i] = missileactive[nummissiles]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void GetMissileVel(int i, int sx, int sy, int dx, int dy, int v) +{ + double dxp, dyp, dr; + + dxp = (((dx - sx) << 5) - ((dy - sy) << 5)) << 16; + dyp = (((dx - sx) << 5) + ((dy - sy) << 5)) << 16; + dr = sqrt((dxp * dxp) + (dyp * dyp)); + app_assert(i < MAXMISSILES); + missile[i]._mixvel = static_cast(((v << 16) * dxp) / dr); + missile[i]._miyvel = static_cast(((v << 15) * dyp) / dr); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void PutMissile(int i) +{ + int mx, my; + + app_assert(i < MAXMISSILES); + mx = missile[i]._mix; + my = missile[i]._miy; + + if (mx <= 0 || my <= 0 || mx >= DMAXX || my >= DMAXY) + missile[i]._miDelFlag = TRUE; + + if (!missile[i]._miDelFlag) { + dFlags[mx][my] |= BFLAG_MISSILE; + if (dMissile[mx][my] == 0) dMissile[mx][my] = (char)i + 1; + else dMissile[mx][my] = -1; + if (missile[i]._miPreFlag) MissilePreFlag = TRUE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static BYTE GetDirNum(int mi) +{ + app_assert(mi < MAXMISSILES); + return (misfiledata[(missile[mi]._miAnimType)].mAnimFAmt >= 8) ? missile[mi]._mimfnum : 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void GetMissilePos(int i) +{ + long mx, my; + long dx, dy; + long lx, ly; // lighting offsets + + app_assert(i < MAXMISSILES); + mx = missile[i]._mitxoff >> 16; + my = missile[i]._mityoff >> 16; + dx = (mx + (my << 1)); + dy = ((my << 1) - mx); + + if (dx < 0) { + lx = -((-dx) >> 3); + dx = -((-dx) >> 6); + } else { + lx = dx >> 3; + dx = dx >> 6; + } + + if (dy < 0) { + ly = -((-dy) >> 3); + dy = -((-dy) >> 6); + } else { + ly = dy >> 3; + dy = dy >> 6; + } + + missile[i]._mix = dx + missile[i]._misx; + missile[i]._miy = dy + missile[i]._misy; + missile[i]._mixoff = mx - ((dx - dy) << 5); + missile[i]._miyoff = my - ((dx + dy) << 4); + ChangeLightOff(missile[i]._mlid, lx - (dx << 3), ly - (dy << 3)); +} + +/*-----------------------------------------------------------------------* + * MoveMissilePos + * + * Adjusts missile's drawing location to prevent overlapping tiles + * Written specifically for monster missiles (e.g., Rhino), which are large. +**-----------------------------------------------------------------------*/ + +static void MoveMissilePos(int i) +{ + int dx,dy; + int mx,my; + + app_assert(i < MAXMISSILES); + switch (missile[i]._mimfnum) { + case 0 : // Down + dx = 1; + dy = 1; + break; + case 1 : // Down Left + dx = 1; + dy = 1; + break; + case 2 : // Left + dx = 0; + dy = 1; + break; + case 3 : // Up Left + dx = 0; + dy = 0; + break; + case 4 : // Up + dx = 0; + dy = 0; + break; + case 5 : // Up Right + dx = 0; + dy = 0; + break; + case 6 : // Right + dx = 1; + dy = 0; + break; + case 7 : // Down Right + dx = 1; + dy = 1; + break; + } + + mx = missile[i]._mix + dx; + my = missile[i]._miy + dy; + + // note -- _misource is the monster which became this missile + if (PosOkMonst(missile[i]._misource,mx,my)) { + missile[i]._mix += dx; + missile[i]._miy += dy; + missile[i]._mixoff -= ((dx - dy) << 5); + missile[i]._miyoff -= ((dx + dy) << 4); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL MonsterTrapHit(int m, int mindam, int maxdam, int dist, int t, byte shift) +{ + int hit, hper; + long dam; + int mor; // monster's resist type + int mir; + BOOL resist = FALSE; + BOOL ret; + + app_assert(m < MAXMONSTERS); + if (monster[m].mtalkmsg != 0) return FALSE; + + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) return FALSE; + + app_assert(monster[m].MType != NULL); + if(monster[m].MType->mtype == MT_ILLWEAV && monster[m]._mgoal == MG_RUN_AWAY) + return FALSE; + + if (monster[m]._mmode == MM_MISSILE) return(FALSE); + + mir = missiledata[t].mResist; + mor = monster[m].mMagicRes; + if( (mor & M_IM && mir == MIMT_MISC) + || (mor & M_IF && mir == MIMT_FIRE) + || (mor & M_IL && mir == MIMT_LGHT)) + return FALSE; + + if( (mor & M_RM && mir == MIMT_MISC) + || (mor & M_RF && mir == MIMT_FIRE) + || (mor & M_RL && mir == MIMT_LGHT)) + resist = TRUE; + + hit = random(68, 100); + hper = 90 - monster[m].mArmorClass - dist; + if (hper < 5) hper = 5; + if (hper > 95) hper = 95; + if (CheckMonsterHit(m, ret)) + return(ret); +#if CHEATS + else if((hit < hper) || simplecheat || cheatflag || (monster[m]._mmode == MM_STONE)) { +#else + else if((hit < hper) || (monster[m]._mmode == MM_STONE)) { +#endif + dam = random(68, maxdam - mindam + 1) + mindam; + if (shift == 0) dam = dam << HP_SHIFT; + if (resist) + monster[m]._mhitpoints -= dam >> 2; + else + monster[m]._mhitpoints -= dam; + +#if CHEATS + if (simplecheat || cheatflag) monster[m]._mhitpoints = 0; +#endif + // rjs - x2 dam if stone - if (monster[m]._mmode == MM_STONE) monster[m]._mhitpoints -= dam; + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) { + if (monster[m]._mmode == MM_STONE) { + M_StartKill(m, -1); + monster[m]._mmode = MM_STONE; + } else M_StartKill(m, -1); + } + else if(resist) + { + PlayEffect(m, MS_GOTHIT); + } + else + { + if (monster[m]._mmode == MM_STONE) { + if (m > 3) M_StartHit(m, -1, dam); // dont let golems get hit + monster[m]._mmode = MM_STONE; + } else { + if (m > 3) M_StartHit(m, -1, dam); // dont let golems get hit + } + } + return(TRUE); + } else return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL MonsterMHit(int pnum, int m, int mindam, int maxdam, int dist, int t, byte shift) +{ + int hit, hper; + long dam; + int mor; // monster's resist type + int mir; // missile resistance category + BOOL resist = FALSE; + BOOL ret; + + app_assert(m < MAXMONSTERS); + if (monster[m].mtalkmsg != 0) return(FALSE); + + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) return(FALSE); + + app_assert(monster[m].MData != NULL); + if ((t == MIT_HBOLT) && + (monster[m].MType->mtype != MT_DIABLO) && + (monster[m].MData->mMonstClass != MC_UNDEAD)) return(FALSE); + + app_assert(monster[m].MType != NULL); + if(monster[m].MType->mtype == MT_ILLWEAV && monster[m]._mgoal == MG_RUN_AWAY) + return FALSE; + + if (monster[m]._mmode == MM_MISSILE) return(FALSE); + + mir = missiledata[t].mResist; + mor = monster[m].mMagicRes; + if( (mor & M_IM && mir == MIMT_MISC) + || (mor & M_IF && mir == MIMT_FIRE) + || (mor & M_IL && mir == MIMT_LGHT) + || (mor & M_IA && mir == MIMT_ACID)) + return FALSE; + + if( (mor & M_RM && mir == MIMT_MISC) + || (mor & M_RF && mir == MIMT_FIRE) + || (mor & M_RL && mir == MIMT_LGHT)) + resist = TRUE; + + hit = random(69, 100); + if (missiledata[t].mType == MIS_WEAP) { + hper = BASE_TO_HIT + plr[pnum]._pLevel - monster[m].mArmorClass - plr[pnum]._pIEnAc; + hper += plr[pnum]._pDexterity + plr[pnum]._pIBonusToHit; + hper -= (dist * dist) >> 1; + if (plr[pnum]._pClass == CLASS_ROGUE) hper += 20; + if (plr[pnum]._pClass == CLASS_WARRIOR || + plr[pnum]._pClass == CLASS_BARD) hper += 10; + } else { + hper = BASE_TO_HIT + plr[pnum]._pMagic - (monster[m].mLevel << 1) - dist; + if (plr[pnum]._pClass == CLASS_SORCEROR) hper += 20; + else if (plr[pnum]._pClass == CLASS_BARD) hper += 10; + } + if (hper < 5) hper = 5; + if (hper > 95) hper = 95; + if (monster[m]._mmode == MM_STONE) hit = 0; + if (CheckMonsterHit(m, ret)) + return(ret); +#if CHEATS + else if((hit < hper) || cheatflag || simplecheat) { +#else + else if (hit < hper) { +#endif + if (t == MIT_BONESPIRIT) + dam = (monster[m]._mhitpoints / 3) >> HP_SHIFT; + else + dam = random(70, maxdam - mindam + 1) + mindam; + if (missiledata[t].mType == MIS_WEAP) { + dam += (dam * plr[pnum]._pIBonusDam) / 100; + dam += plr[pnum]._pIBonusDamMod; + if (plr[pnum]._pClass == CLASS_ROGUE) dam += plr[pnum]._pDamageMod; + else dam += (plr[pnum]._pDamageMod >> 1); + } + if (shift == 0) dam = dam << HP_SHIFT; + if (resist) dam = dam >> 2; + if (pnum == myplr) monster[m]._mhitpoints -= dam; + + if (plr[pnum]._pIFlags & IAF_MNOHEAL) monster[m]._mFlags |= MFLAG_NOHEAL; +#if CHEATS + //if (pnum == myplr && cheatflag) monster[m]._mhitpoints = 0; +#endif + //rjs - x2 stone dam - if (pnum == myplr && monster[m]._mmode == MM_STONE) monster[m]._mhitpoints -= dam; + + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) { + if (monster[m]._mmode == MM_STONE) { + M_StartKill(m, pnum); + monster[m]._mmode = MM_STONE; + } else M_StartKill(m, pnum); + //(old) AddPlrExperience(pnum, monster[m].mLevel, monster[m].mExp); + //(new, but moved) AddPlrMonstExper(monster[m].mLevel, monster[m].mExp, monster[m].mWhoHit); + } + else if(resist) + { + PlayEffect(m, MS_GOTHIT); + } + else + { + if (monster[m]._mmode == MM_STONE) { + if (m > 3) M_StartHit(m, pnum, dam); + monster[m]._mmode = MM_STONE; + } else { + if ((missiledata[t].mType == MIS_WEAP) && (plr[pnum]._pIFlags & IAF_KNOCKBACK)) M_GetKnockback(m); + if (m > 3) M_StartHit(m, pnum, dam); + } + } + // wake up monster if it's inactive + if(!monster[m]._msquelch) + { + monster[m]._msquelch = 255; + monster[m]._lastx = plr[pnum]._px; + monster[m]._lasty = plr[pnum]._py; + } + return(TRUE); + } else return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PlayerMHit(int pnum, int m, int dist, int mind, int maxd, int mtype, byte shift, BOOL earflag) +{ + int hit, hper, tac; + long dam; + int blk, blkper, blkdir; + int resper = 0; + + app_assert(pnum < MAX_PLRS); + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) return(FALSE); + if (plr[pnum]._pInvincible) return(FALSE); + if (((plr[pnum]._pSpellFlags & SF_ETHER) != 0) && (missiledata[mtype].mType == MIS_WEAP)) return(FALSE); + + hit = random(72, 100); +#if CHEATS + if (simplecheat || cheatflag) hit = 1000; +#endif + if (missiledata[mtype].mType == MIS_WEAP) { + // rjs tac = (byte)plr[pnum]._pArmorClass + plr[pnum]._pIAC + plr[pnum]._pIBonusAC; + tac = plr[pnum]._pIAC + plr[pnum]._pIBonusAC; + tac += (plr[pnum]._pDexterity / 5); + if (m != -1) hper = 30 + monster[m].mHit - tac + ((monster[m].mLevel - plr[pnum]._pLevel) << 1) - (dist << 1); + else hper = 100 - (tac >> 1) - (dist << 1); + } else { + if (m != -1) hper = 40 + (monster[m].mLevel << 1) - (plr[pnum]._pLevel << 1) - (dist << 1); + else hper = 40; + } + if (hper < 10) hper = 10; + if ((currlevel == 14) && (hper < 20)) hper = 20; + if ((currlevel == 15) && (hper < 25)) hper = 25; + if ((currlevel == 16) && (hper < 30)) hper = 30; + if (((plr[pnum]._pmode == PM_STAND) || (plr[pnum]._pmode == PM_ATTACK)) && (plr[pnum]._pBlockFlag)) blk = random(73, 100); + else blk = 100; + if (shift == 1) blk = 100; // can't block continous damage spells + if (mtype == MIT_ACIDPUD) blk = 100; // can't block acid puddles (drb) + if (m != -1) blkper = plr[pnum]._pBaseToBlk + plr[pnum]._pDexterity - ((monster[m].mLevel - plr[pnum]._pLevel) << 1); + else blkper = plr[pnum]._pBaseToBlk + plr[pnum]._pDexterity; + if (blkper < 0) blkper = 0; + if (blkper > 100) blkper = 100; + switch(missiledata[mtype].mResist) { + case MIMT_FIRE: + resper = plr[pnum]._pFireResist; + break; + case MIMT_LGHT: + resper = plr[pnum]._pLghtResist; + break; + case MIMT_MISC: + case MIMT_ACID: + resper = plr[pnum]._pMagResist; + break; + default: + resper = 0; + break; + } + if (hit < hper) { + // Hit, so calc damage + if (mtype == MIT_BONESPIRIT) { + dam = plr[pnum]._pHitPoints / 3; + } else { + if (shift == 0) { + dam = (maxd - mind + 1) << HP_SHIFT; + dam = random(75, dam) + (mind << HP_SHIFT); + if (plr[pnum]._pIFlags & IAF_TRAPDAM) dam = dam >> 1; + dam += (plr[pnum]._pIGetHit << HP_SHIFT); + if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT); + } else { + dam = maxd - mind + 1; + dam = random(75, dam) + mind; + if (plr[pnum]._pIFlags & IAF_TRAPDAM) dam = dam >> 1; + dam += plr[pnum]._pIGetHit; + if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT); + } + } + + // Did I resist? + if (resper > 0) { + dam -= (dam * resper) / 100; + if (pnum == myplr) { + plr[pnum]._pHitPoints -= dam; + plr[pnum]._pHPBase -= dam; + } + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + } + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - plr[pnum]._pHitPoints = 0; + StartPlrKill(pnum, earflag); + } + else { + // No get hit + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR69, plr[pnum]._px, plr[pnum]._py); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD69, plr[pnum]._px, plr[pnum]._py); + #endif + + //PlaySfxLoc(PS_LGHIT, plr[pnum]._px, plr[pnum]._py); + drawhpflag = TRUE; + } + return(TRUE); + } else { + // Did I block? + if (blk < blkper) { + if (m != -1) blkdir = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[m]._mx, monster[m]._my); + else blkdir = plr[pnum]._pdir; + StartPlrBlock(pnum, blkdir); + return(TRUE); + } else { + if (pnum == myplr) { + plr[pnum]._pHitPoints -= dam; + plr[pnum]._pHPBase -= dam; + } + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + } + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - plr[pnum]._pHitPoints = 0; + StartPlrKill(pnum, earflag); + } else StartPlrHit(pnum, dam, FALSE); + return(TRUE); + } + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL Plr2PlrMHit(int pnum, int p, int mindam, int maxdam, int dist, int mtype, byte shift) +{ + int hit, hper, tac; + long dam; + int blk, blkper, blkdir; + int resper; + + // pnum is missiles source + // p is missiles dest + + app_assert(p < MAX_PLRS); + if (plr[p]._pInvincible) return(FALSE); + if (mtype == MIT_HBOLT) return(FALSE); + if (((plr[p]._pSpellFlags & SF_ETHER) != 0) && (missiledata[mtype].mType == MIS_WEAP)) return(FALSE); + + switch(missiledata[mtype].mResist) { + case MIMT_FIRE: + resper = plr[p]._pFireResist; + break; + case MIMT_LGHT: + resper = plr[p]._pLghtResist; + break; + case MIMT_MISC: + case MIMT_ACID: + resper = plr[p]._pMagResist; + break; + default: + resper = 0; + break; + } + hit = random(69, 100); + if (missiledata[mtype].mType == MIS_WEAP) { + //rjs tac = (byte)plr[p]._pArmorClass + plr[p]._pIAC + plr[p]._pIBonusAC; + tac = plr[p]._pIAC + plr[p]._pIBonusAC; + tac += (plr[p]._pDexterity / 5); + hper = BASE_TO_HIT + plr[pnum]._pLevel - tac; + hper += plr[pnum]._pDexterity + plr[pnum]._pIBonusToHit; + hper -= (dist * dist) >> 1; + if (plr[pnum]._pClass == CLASS_ROGUE) hper += 20; + if (plr[pnum]._pClass == CLASS_WARRIOR) hper += 10; + } else { + hper = BASE_TO_HIT + plr[pnum]._pMagic - (plr[p]._pLevel << 1) - dist; + if (plr[pnum]._pClass == CLASS_SORCEROR) hper += 20; + } + if (hper < 5) hper = 5; + if (hper > 95) hper = 95; + if (hit < hper) { + // Hit, calc blk % + if (((plr[p]._pmode == PM_STAND) || (plr[p]._pmode == PM_ATTACK)) && (plr[p]._pBlockFlag)) blk = random(73, 100); + else blk = 100; + if (shift == 1) blk = 100; // can't block continous damage spells + blkper = plr[p]._pBaseToBlk + plr[p]._pDexterity - ((plr[pnum]._pLevel - plr[p]._pLevel) << 1); + if (blkper < 0) blkper = 0; + if (blkper > 100) blkper = 100; + // Hit, so calc damage + if (mtype == MIT_BONESPIRIT) { + dam = plr[p]._pHitPoints / 3; + } else { + dam = random(70, maxdam - mindam + 1) + mindam; + if (missiledata[mtype].mType == MIS_WEAP) { + dam += (dam * plr[pnum]._pIBonusDam) / 100; + dam += plr[pnum]._pIBonusDamMod + plr[pnum]._pDamageMod; + } + if (shift == 0) dam = dam << HP_SHIFT; + } + // NEW! Take 1/2 damage from plr spells (drb 11/23) + if (missiledata[mtype].mType != MIS_WEAP) dam = dam >> 1; + // Did I resist? + if (resper > 0) { + dam -= (dam * resper) / 100; + // No get hit + if (pnum == myplr) NetSendCmdDamage(TRUE, p, dam); + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR69, plr[pnum]._px, plr[pnum]._py); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD69, plr[pnum]._px, plr[pnum]._py); + #endif + + //PlaySfxLoc(PS_LGHIT, plr[p]._px, plr[p]._py); + return(TRUE); + } else { + // Did I block? + if (blk < blkper) { + blkdir = GetDirection(plr[p]._px, plr[p]._py, plr[pnum]._px, plr[pnum]._py); + StartPlrBlock(p, blkdir); + return(TRUE); + } else { + if (pnum == myplr) NetSendCmdDamage(TRUE, p, dam); + StartPlrHit(p, dam, FALSE); + return(TRUE); + } + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void CheckMissileCol(int i, int mindam, int maxdam, byte shift, int mx, int my, byte nodel) +{ + int pn,oi; + BOOL earflag; + + app_assert(i < MAXMISSILES); + app_assert(mx < MAXDUNX); + app_assert(my < MAXDUNY); + if ((missile[i]._miAnimType == MF_FIRE) + || (missile[i]._miAnimType == MF_LIGHTNING && missile[i]._mixvel == 0 && missile[i]._miyvel == 0) + || (missile[i]._misource == -1)) { + if (dMonster[mx][my] > 0) { + if (missile[i]._miAnimType == MF_FIRE + || missile[i]._miAnimType == MF_LIGHTNING) { + if (MonsterMHit(missile[i]._misource, dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } else { + if (MonsterTrapHit(dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + } + if (dPlayer[mx][my] > 0) { + if (missile[i]._miAnimType == MF_FIRE + || missile[i]._miAnimType == MF_LIGHTNING) earflag = TRUE; + else earflag = FALSE; + if (PlayerMHit(dPlayer[mx][my] - 1, -1, missile[i]._midist, mindam, maxdam, missile[i]._mitype, shift, earflag)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + } else { + if (missile[i]._micaster == MI_ENEMYMONST) { + if (dMonster[mx][my] > 0) { + if (MonsterMHit(missile[i]._misource, dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } else { + if ((dMonster[mx][my] < 0) && (monster[-(dMonster[mx][my] + 1)]._mmode == MM_STONE)) { + if (MonsterMHit(missile[i]._misource, -(dMonster[mx][my] + 1), mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + } + if ((dPlayer[mx][my] > 0) && ((dPlayer[mx][my]-1) != missile[i]._misource)) { + if (Plr2PlrMHit(missile[i]._misource, dPlayer[mx][my]-1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + } else { + if (((monster[missile[i]._misource]._mFlags & MFLAG_MID) != 0) && ((dMonster[mx][my] > 0) && (monster[(dMonster[mx][my] - 1)]._mFlags & MFLAG_MKILLER) != 0)) { + if (MonsterTrapHit(dMonster[mx][my] - 1, mindam, maxdam, missile[i]._midist, missile[i]._mitype, shift)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + if (dPlayer[mx][my] > 0) { + if (PlayerMHit(dPlayer[mx][my] - 1, missile[i]._misource, missile[i]._midist, mindam, maxdam, missile[i]._mitype, shift, FALSE)) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = TRUE; + } + } + } + } + + if (dObject[mx][my] != 0) { + if (dObject[mx][my] > 0) oi = dObject[mx][my] - 1; + else oi = -(dObject[mx][my] + 1); + if (!object[oi]._oMissFlag) { + if (object[oi]._oBreak == OBJ_BREAKABLE) BreakObject(-1, oi); + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = FALSE; + } + } + + pn = dPiece[mx][my]; + app_assert(pn <= MAXTILES); + if (nMissileTable[pn]) { + if (nodel == 0) missile[i]._mirange = 0; + missile[i]._miHitFlag = FALSE; + } + + if ((missile[i]._mirange == 0) && (missiledata[missile[i]._mitype].miSFX != -1)) { + PlaySfxLoc(missiledata[missile[i]._mitype].miSFX, missile[i]._mix, missile[i]._miy); + } +} + +static void SetMissAnim(int mi, int animtype) +{ + int dir; + + app_assert(mi < MAXMISSILES); + dir = missile[mi]._mimfnum; + missile[mi]._miAnimType = animtype; + + missile[mi]._miAnimFlags = misfiledata[animtype].mFlags; + missile[mi]._miAnimData = misfiledata[animtype].mAnimData[dir]; + missile[mi]._miAnimDelay = misfiledata[animtype].mAnimDelay[dir]; + missile[mi]._miAnimLen = misfiledata[animtype].mAnimLen[dir]; + missile[mi]._miAnimWidth = misfiledata[animtype].mAnimWidth[dir]; + missile[mi]._miAnimWidth2 = misfiledata[animtype].mAnimWidth2[dir]; + missile[mi]._miAnimCnt = 0; + missile[mi]._miAnimFrame = 1; +} + + +void SetMissDir(int mi, int dir) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._mimfnum = dir; + SetMissAnim(mi, missile[mi]._miAnimType); +} + +/*-----------------------------------------------------------------------** +**---------------------- Initialization Routines ------------------------** +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +void ILoadMissileGFX(BYTE mf) { + int i; + char strbuff[256]; + BYTE *p; + MisFileData * pMisDat; + + pMisDat = &misfiledata[mf]; + if (pMisDat->mFlags & MFF_MULTI) { + // All directions are packed into one file + sprintf(strbuff,"Missiles\\%s" CEL_EXT, pMisDat->mAnimPath); + p = LoadFileInMemSig(strbuff,NULL,'MISS'); + for (i = 0; i < pMisDat->mAnimFAmt; ++i) + pMisDat->mAnimData[i] = p + (reinterpret_cast(p))[i]; + } + else if (pMisDat->mAnimFAmt == 1) { + sprintf(strbuff,"Missiles\\%s" CEL_EXT, pMisDat->mAnimPath); + if(! pMisDat->mAnimData[0]) + pMisDat->mAnimData[0] = LoadFileInMemSig(strbuff,NULL,'MISS'); + } + else { + for (i = 0; i < pMisDat->mAnimFAmt; ++i) { + sprintf(strbuff, "Missiles\\%s%i" CEL_EXT, pMisDat->mAnimPath, i + 1); + if(! pMisDat->mAnimData[i]) + pMisDat->mAnimData[i] = LoadFileInMemSig(strbuff,NULL,'MISS'); + } + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +void ILoadMissileGFX(BYTE mf) { + int i; + char strbuff[256]; + BYTE *p; + + if (misfiledata[mf].mFlags & MFF_MULTI) { + // All directions are packed into one file + sprintf(strbuff,"Missiles\\%s.CEL", misfiledata[mf].mAnimPath); + p = LoadFileInMemSig(strbuff,NULL,'MISS'); + for (i = 0; i < misfiledata[mf].mAnimFAmt; ++i) { + misfiledata[mf].mAnimData[i] = p + *static_cast(p + (i<<2)); + } + } + else if (misfiledata[mf].mAnimFAmt == 1) { + sprintf(strbuff,"Missiles\\%s.CEL", misfiledata[mf].mAnimPath); + if(! misfiledata[mf].mAnimData[0]) + misfiledata[mf].mAnimData[0] = LoadFileInMemSig(strbuff,NULL,'MISS'); + } else { + for (i = 0; i < misfiledata[mf].mAnimFAmt; ++i) { + sprintf(strbuff, "Missiles\\%s%i.CEL", misfiledata[mf].mAnimPath, i + 1); + if(! misfiledata[mf].mAnimData[i]) + misfiledata[mf].mAnimData[i] = LoadFileInMemSig(strbuff,NULL,'MISS'); + } + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitMissileGFX() +{ + int i; + + for (i = 0; misfiledata[i].mAnimFAmt; ++i) { + if (!(misfiledata[i].mFlags & MFF_MONSTONLY)) { + ILoadMissileGFX(i); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void FreeMissileFile(int i) +{ + int j; + void * y; + + if (misfiledata[i].mFlags & MFF_MULTI) + { + if(misfiledata[i].mAnimData[0]) + { + y = static_cast (misfiledata[i].mAnimData[0] - (misfiledata[i].mAnimFAmt << 2)); + DiabloFreePtr(y); + misfiledata[i].mAnimData[0] = NULL; + } + } + else + { + for (j = 0; j < misfiledata[i].mAnimFAmt; ++j) + if(misfiledata[i].mAnimData[j]) + { + DiabloFreePtr(misfiledata[i].mAnimData[j]); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreeMissileGFX() +{ + int i; + + for (i = 0; misfiledata[i].mAnimFAmt; ++i) { + if (!(misfiledata[i].mFlags & MFF_MONSTONLY)) { + FreeMissileFile(i); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void IFreeMissileGFX() +{ + int i; + + for (i = 0; misfiledata[i].mAnimFAmt; ++i) + if(misfiledata[i].mFlags & MFF_MONSTONLY) + FreeMissileFile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitMissiles() +{ + int i, j, mx; + + // Delete any active infravision/ etheralize + plr[myplr]._pSpellFlags &= ~SF_ETHER; + if (plr[myplr]._pInfraFlag == TRUE) { + app_assert(nummissiles <= MAXMISSILES); + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + app_assert(mx < MAXMISSILES); + if ((missile[mx]._mitype == MIT_INFRA) && (missile[mx]._misource == myplr)) + CalcPlrItemVals(missile[mx]._misource,TRUE); + } + } + + nummissiles = 0; + for (i = 0; i < MAXMISSILES; ++i) { + missileavail[i] = i; + missileactive[i] = 0; + } + + nummissilevars = 0; + for (i = 0; i < MAXMISSILES; ++i) { + missilevars[i][0] = -1; + missilevars[i][1] = 0; + missilevars[i][2] = 0; + } + + for (j = 0; j < DMAXY; ++j) { + for (i = 0; i < DMAXX; ++i) { + dFlags[i][j] = dFlags[i][j] & ~BFLAG_MISSILE; + } + } +} + +/*-----------------------------------------------------------------------** +**------------------ Missile Initialization Routines --------------------** +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfFire(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + UseMana(id, SPL_RUNEOFFIRE); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_MISEXP; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfLight(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + UseMana(id, SPL_RUNEOFLIGHT); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_LIGHTBALL; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfNova(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + UseMana(id, SPL_RUNEOFNOVA); + } + if (SetMissileLocation(mi, &sx, &sy, 10)) { + missile[mi]._miVar1 = MIT_NOVA; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(sx, sy, 8); + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfImmolation(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + UseMana(id, SPL_RUNEOFIMMOLATION); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_IMMOLATION; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRuneOfStone(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + UseMana(id, SPL_RUNEOFSTONE); + } + if (SetMissileLocation(mi, &dx, &dy, 10)) { + missile[mi]._miVar1 = MIT_STONE; + missile[mi]._miDelFlag = FALSE; + missile[mi]._mlid = AddLight(dx, dy, 8); + } + else missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddReflect(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + if (plr[id]._pReflectCount < 0) + plr[id]._pReflectCount = 0; + + plr[id]._pReflectCount += GetSpellLevel(id, SPL_REFLECT) * plr[id]._pLevel; + UseMana(id, SPL_REFLECT); + } + missile[mi]._mirange = 0; + missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBerserk(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (id >= 0) { + + app_assert(mi < MAXMISSILES); + missile[mi]._misource = id; + + // search in a 5 radius around tile clicked for monster + for (int k = 0; k < 6; ++k) { + int const l = CrawlNum[k]; + int j = l + 1; + for (int i = CrawlTable[l]; i > 0; --i, j += 2) { + int const tx = dx + CrawlTable[j]; + int const ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int mid = dMonster[tx][ty]; + if (mid > 0) --mid; + else mid = -(mid + 1); + + if ((mid > 3) + && (monster[mid]._uniqtype == 0) + && (monster[mid]._mAi != AI_DIABLO) + && (monster[mid]._mmode != MM_FADEIN) + && (monster[mid]._mmode != MM_FADEOUT) + //&& (monster[mid]._mmode != MM_DEATH) + && (monster[mid]._mmode != MM_MISSILE)) { + i = -99; + k = 6; + int const SpellLevel = GetSpellLevel(id, SPL_BERSERK); + monster[mid]._mFlags |= MFLAG_BERSERK | MFLAG_MKILLER; + monster[mid].mMinDamage = static_cast(SpellLevel + monster[mid].mMinDamage * (1.0 + (0.01 * (random(145,10) + 20)))); + monster[mid].mMaxDamage = static_cast(SpellLevel + monster[mid].mMaxDamage * (1.0 + (0.01 * (random(145,10) + 20)))); + monster[mid].mMinDamage2 = static_cast(SpellLevel + monster[mid].mMinDamage2 * (1.0 + (0.01 * (random(145,10) + 20)))); + monster[mid].mMaxDamage2 = static_cast(SpellLevel + monster[mid].mMaxDamage2 * (1.0 + (0.01 * (random(145,10) + 20)))); + UseMana(id, SPL_BERSERK); + break; + } + } + } + } + } + missile[mi]._mirange = 0; + missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddDisEnchant(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._misource = id; + + // search in a 3 radius around chest trap for players. + for (int k = 0; k < 3; ++k) { + int const l = CrawlNum[k]; + int j = l + 1; + for (int i = CrawlTable[l]; i > 0; --i, j += 2) { + int const tx = sx + CrawlTable[j]; + int const ty = sy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int pid = dPlayer[tx][ty]; + + if (pid == 0) + continue; + + if (pid > 0) --pid; + else pid = -(pid + 1); + + // Belt items only. + if (random(205, 2)) { + // distroy healing and mana potions && 1/2 rejuvination. + for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) { + if (plr[pid].SpdList[splIndex]._itype == IT_MISC + && (plr[pid].SpdList[splIndex]._iMiscId == IMID_PLHEAL + || plr[pid].SpdList[splIndex]._iMiscId == IMID_PHEAL + || plr[pid].SpdList[splIndex]._iMiscId == IMID_PMANA + || plr[pid].SpdList[splIndex]._iMiscId == IMID_PFMANA + || plr[pid].SpdList[splIndex]._iMiscId == IMID_REJUV) + ) { + RemoveSpdBarItem(pid, splIndex); + } + else if (plr[pid].SpdList[splIndex]._iMiscId == IMID_FREJUV){ + int const idata = ItemMiscIdIdx(IMID_REJUV); + SetPlrHandItem(&plr[pid].HoldItem, idata); + GetPlrHandSeed(&plr[pid].HoldItem); + plr[pid].HoldItem._iStatFlag = TRUE; + plr[pid].SpdList[splIndex] = plr[pid].HoldItem; + } + } + } + else if (random(206, 2)) { + // downgrade full potions to partial + // Partical go away. + for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) { + if (plr[pid].SpdList[splIndex]._itype == IT_MISC ) { + switch (plr[pid].SpdList[splIndex]._iMiscId) + { + case IMID_PHEAL: + { + int const idata = ItemMiscIdIdx(IMID_PLHEAL); + SetPlrHandItem(&plr[pid].HoldItem, idata); + GetPlrHandSeed(&plr[pid].HoldItem); + plr[pid].HoldItem._iStatFlag = TRUE; + plr[pid].SpdList[splIndex] = plr[pid].HoldItem; + } + break; + case IMID_PFMANA: + { + int const idata = ItemMiscIdIdx(IMID_PMANA); + SetPlrHandItem(&plr[pid].HoldItem, idata); + GetPlrHandSeed(&plr[pid].HoldItem); + plr[pid].HoldItem._iStatFlag = TRUE; + plr[pid].SpdList[splIndex] = plr[pid].HoldItem; + } + break; + case IMID_FREJUV: + { + int const idata = ItemMiscIdIdx(IMID_REJUV); + SetPlrHandItem(&plr[pid].HoldItem, idata); + GetPlrHandSeed(&plr[pid].HoldItem); + plr[pid].HoldItem._iStatFlag = TRUE; + plr[pid].SpdList[splIndex] = plr[pid].HoldItem; + } + break; + case IMID_PMANA: + case IMID_PLHEAL: + case IMID_REJUV: + RemoveSpdBarItem(pid, splIndex); + break; + } + force_redraw = FULLDRAW; + } + } + } + else if (random(207, 2)) { + // convert rejuventation to healing or mana. + for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) { + if (plr[pid].SpdList[splIndex]._itype == IT_MISC ) { + if(plr[pid].SpdList[splIndex]._iMiscId == IMID_REJUV) { + int const idata = ItemMiscIdIdx(random(210,2) ? IMID_PLHEAL : IMID_PMANA); + SetPlrHandItem(&plr[pid].HoldItem, idata); + GetPlrHandSeed(&plr[pid].HoldItem); + plr[pid].HoldItem._iStatFlag = TRUE; + plr[pid].SpdList[splIndex] = plr[pid].HoldItem; + } + else if(plr[pid].SpdList[splIndex]._iMiscId == IMID_FREJUV) { + int const idata = ItemMiscIdIdx(random(211,2) ? IMID_PHEAL : IMID_PFMANA); + SetPlrHandItem(&plr[pid].HoldItem, idata); + GetPlrHandSeed(&plr[pid].HoldItem); + plr[pid].HoldItem._iStatFlag = TRUE; + plr[pid].SpdList[splIndex] = plr[pid].HoldItem; + } + force_redraw = FULLDRAW; + } + } + } + else if (random(208, 5)) { + // distroy scrolls and oils. + for (int splIndex = 0; splIndex < MAXSPD; ++splIndex) { + if ( (plr[pid].SpdList[splIndex]._iMiscId > IMID_FIRSTOIL + && plr[pid].SpdList[splIndex]._iMiscId < IMID_LASTOIL) + || plr[pid].SpdList[splIndex]._iMiscId == IMID_SCROLL + || plr[pid].SpdList[splIndex]._iMiscId == IMID_TSCROLL + ) { + RemoveSpdBarItem(pid, splIndex); + } + } + } + } + } + } + missile[mi]._mirange = 0; + missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddManaRemove(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._misource = id; + + // search in a 3 radius around chest trap for players. + for (int k = 0; k < 3; ++k) { + int const l = CrawlNum[k]; + int j = l + 1; + for (int i = CrawlTable[l]; i > 0; --i, j += 2) { + int const tx = sx + CrawlTable[j]; + int const ty = sy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int pid = dPlayer[tx][ty]; + + if (pid == 0) + continue; + + if (pid > 0) --pid; + else pid = -(pid + 1); + + plr[pid]._pMana = 0; + plr[pid]._pManaBase = plr[pid]._pMana - (plr[pid]._pMaxMana - plr[pid]._pMaxManaBase); + CalcPlrInv(pid, FALSE); + drawmanaflag = TRUE; + } + } + } + missile[mi]._mirange = 0; + missile[mi]._miDelFlag = TRUE; + + app_assert(mi < MAXMISSILES); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + if (mienemy == MI_ENEMYMONST) { + if (plr[id]._pClass == CLASS_ROGUE) GetMissileVel(mi,sx,sy,dx,dy,31+(plr[id]._pLevel>>2)); + else if (plr[id]._pClass == CLASS_WARRIOR) GetMissileVel(mi,sx,sy,dx,dy,31+(plr[id]._pLevel>>3)); + else GetMissileVel(mi,sx,sy,dx,dy,32); + } else GetMissileVel(mi,sx,sy,dx,dy,32); + + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 5); + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int av; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + if (mienemy == MI_ENEMYMONST) { + av = 32; + if (plr[id]._pIFlags & IAF_RNDARROW) av = random(64, 32) + 16; // rnd arrow speed + if (plr[id]._pClass == CLASS_ROGUE) av += (plr[id]._pLevel-1) >> 2; // rouge level speed increase + if (plr[id]._pClass == CLASS_WARRIOR) av += (plr[id]._pLevel-1) >> 3; // warrior level speed increase + GetMissileVel(mi,sx,sy,dx,dy,av); + } else GetMissileVel(mi,sx,sy,dx,dy,32); + + app_assert(mi < MAXMISSILES); + missile[mi]._miAnimFrame = GetDirection16(sx,sy,dx,dy) + 1; + + missile[mi]._mirange = 256; + + //PutMissile(mi); +} + +void AddSpecialArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int extraspeed = 0; + +// if ((sx == dx) && (sy == dy)) { +// dx += XDirAdd[midir]; +// dy += YDirAdd[midir]; +// } + + app_assert(mi < MAXMISSILES); + if (mienemy == MI_ENEMYMONST) + { + if (plr[id]._pClass == CLASS_ROGUE) + extraspeed = (plr[id]._pLevel-1) >> 2; // rogue level speed increase + else if (plr[id]._pClass == CLASS_WARRIOR) + extraspeed = (plr[id]._pLevel-1) >> 3; // warrior level speed increase + } + + missile[mi]._mirange = 1; + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + missile[mi]._miVar3 = extraspeed; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void GetVileMissPos(int mi, int dx, int dy) +{ + int xx, yy; + app_assert(mi < MAXMISSILES); + for (int l = 1; l < 50; ++l) { + for (int j = -l; j <= l; ++j) { + yy = dy + j; + for (int i = -l; i <= l; ++i) { + xx = dx + i; + if (PosOkPlayer(myplr,xx,yy)) { + missile[mi]._mix = xx; + missile[mi]._miy = yy; + return; + } + } + } + } + // There is just no way it will ever reach here + missile[mi]._mix = dx; + missile[mi]._miy = dy; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#define DIST(x,y,d) (abs(x) < d && abs(y) < d) + +// Flag for fireman missile +#define MIF_DIDHIT 1 + +#define MINAWAY 3 +#define MAXAWAY 6 + +void AddRndTeleport(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_PHASE) || !PRE_BETA + int pn, r1, r2; + + int nTries = 0; + do { + // don't get stuck in an infinite loop... + if (++nTries > 500) { + r1 = 0; + r2 = 0; + break; + } + + r1 = random(58, MAXAWAY - MINAWAY) + MINAWAY + 1; + r2 = random(58, MAXAWAY - MINAWAY) + MINAWAY + 1; + if (random(58, 2) == 1) r1 = -r1; + if (random(58, 2) == 1) r2 = -r2; + pn = dPiece[sx + r1][sy + r2]; + } while (nSolidTable[pn] != 0 || dObject[sx + r1][sy + r2] != 0 || dMonster[sx + r1][sy + r2] != 0); + + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = 2; + missile[mi]._miVar1 = 0; + +// special code for Vile Betrayer quest + if ((setlevel) && (setlvlnum == 5)) { + int oi = dObject[dx][dy]-1; + if ((object[oi]._otype == OBJ_MCIRCLE1) || (object[oi]._otype == OBJ_MCIRCLE2)) { + missile[mi]._mix = dx; + missile[mi]._miy = dy; + if (!PosOkPlayer(myplr, dx, dy)) GetVileMissPos(mi, dx, dy); + } + } + else { + missile[mi]._mix = sx + r1; + missile[mi]._miy = sy + r2; + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_PHASE); + } + +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +#undef max +void AddTeleStairs(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int minDist = std::numeric_limits::is_specialized && std::numeric_limits::is_bounded + ? std::numeric_limits::max() : 99999; + if (id >= 0) { + sx = plr[id]._px; + sy = plr[id]._py; + } + + int rx = sx; + int ry = sy; + + for (int i = 0;i < numtrigs && i < MAXTRIGGERS; ++i) { + if (trigs[i]._tmsg == WM_DIABTWARPUP + || trigs[i]._tmsg == WM_DIABPREVLVL + || trigs[i]._tmsg == WM_DIABNEXTLVL + || trigs[i]._tmsg == WM_DIABRTNLVL) { + + int triggerx; + int triggery; + + if ((leveltype == 1 || leveltype == 2) + && (trigs[i]._tmsg == WM_DIABNEXTLVL + || trigs[i]._tmsg == WM_DIABPREVLVL + || trigs[i]._tmsg == WM_DIABRTNLVL) ){ + triggerx = trigs[i]._tx; + triggery = trigs[i]._ty + 1; + } + else { + triggerx = trigs[i]._tx + 1; + triggery = trigs[i]._ty; + } + + int xdiff = sx - triggerx; + xdiff *= xdiff; + int ydiff = sy - triggery; + ydiff *= ydiff; + int const NewDist = xdiff + ydiff; + + if (NewDist < minDist) + { + minDist = NewDist; + rx = triggerx; + ry = triggery; + } + + } + } + + + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = 2; + missile[mi]._miVar1 = 0; + missile[mi]._mix = rx; + missile[mi]._miy = ry; + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_TELESTAIRS); + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFirebolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBOLT) || !PRE_BETA + int sp, i, mx; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + + app_assert(mi < MAXMISSILES); + if (micaster == MI_ENEMYMONST) + { + app_assert(nummissiles <= MAXMISSILES); + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + app_assert(mx < MAXMISSILES); + if ((missile[mx]._mitype == MIT_GUARDIAN) && + (missile[mx]._misource == id) && (missile[mx]._miVar3 == mi)) { + break; + } + } + if (i == nummissiles) UseMana(id, SPL_FIREBOLT); + + if (id != -1) { + sp = 16 + (missile[mi]._mispllvl << 1); + if (sp >= 63) sp = 63; + } else sp = 16; + } + else + sp = 26; + + GetMissileVel(mi,sx,sy,dx,dy,sp); + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddMagmaball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + + app_assert(mi < MAXMISSILES); + // Graphics don't line up, so we have to move them... + missile[mi]._mitxoff += 3*missile[mi]._mixvel; + missile[mi]._mityoff += 3*missile[mi]._miyvel; + + GetMissilePos(mi); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddKrull(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; +// missile[mi]._mlid = AddLight(sx, sy, 8); + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddTeleport(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_TELE) || !PRE_BETA + int i, pn; + int k, l, j; + int tx, ty; + + app_assert(dx < MAXDUNX); + app_assert(dy < MAXDUNY); + + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + if ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty] | dPlayer[tx][ty]) == 0) { + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = tx; + missile[mi]._misy = ty; + missile[mi]._miDelFlag = FALSE; + k = 6; + break; + } + } + j += 2; + } + } + + if (missile[mi]._miDelFlag == FALSE) { + UseMana(id, SPL_TELE); + missile[mi]._mirange = 2; + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLightball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + app_assert(mi < MAXMISSILES); + missile[mi]._midam = dam; + + missile[mi]._miAnimFrame = random(63, 8) + 1; + + missile[mi]._mirange = 255; + + if (id < 0) { + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + } else { + missile[mi]._miVar1 = plr[id]._px; + missile[mi]._miVar2 = plr[id]._py; + } + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFirewall(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES); + missile[mi]._midam = (random(53, 10) + random(53, 10) + 2 + (id > 0) ? plr[id]._pLevel : currlevel) << 4; + missile[mi]._midam = missile[mi]._midam >> 1; + + GetMissileVel(mi,sx,sy,dx,dy,16); + + missile[mi]._mirange = 10; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += 10; + + if (mienemy != MI_ENEMYMONST || id < 0) // trap or somesuch + { + missile[mi]._mirange = missile[mi]._mirange + currlevel; + } + else + { + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + } + missile[mi]._mirange = missile[mi]._mirange << 4; + + missile[mi]._miVar1 = missile[mi]._mirange - missile[mi]._miAnimLen; + missile[mi]._miVar2 = 0; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFireball(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int i; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES); + if (mienemy == MI_ENEMYMONST) + { + missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + + i = 16 + (missile[mi]._mispllvl << 1); + if (i > 50) i = 50; + + UseMana(id, SPL_FIREBALL); + } + else + { + i = 16; + } + + GetMissileVel(mi,sx,sy,dx,dy,i); + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = sx; + missile[mi]._miVar5 = sy; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddSpiralFireBall(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int i; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES); + if (mienemy == MI_ENEMYMONST) + { + missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + + i = 16 + (missile[mi]._mispllvl << 1); + if (i > 50) i = 50; + + UseMana(id, SPL_FIREBALL); + } + else + { + i = 16; + } + + GetMissileVel(mi,sx,sy,dx,dy,i); + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = sx; + missile[mi]._miVar5 = sy; + missile[mi]._miVar6 = 2; + missile[mi]._miVar7 = 2; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +void AddFBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int i; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES); + if (mienemy == MI_ENEMYMONST) + { + i = 16 + missile[mi]._mispllvl; + if (i > 50) i = 50; + +// UseMana(id, SPL_FIREBALL); + } + else + { + i = 16; + } + + GetMissileVel(mi,sx,sy,dx,dy,i); + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = sx; + missile[mi]._miVar5 = sy; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLightctrl(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + if (dam == 0 && mienemy == MI_ENEMYMONST) UseMana(id, SPL_LIGHTNING); // if not 0 - probably is chain lightning + + app_assert(mi < MAXMISSILES); + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + + GetMissileVel(mi,sx,sy,dx,dy,32); + + missile[mi]._miAnimFrame = random(52, 8) + 1; + + missile[mi]._mirange = 256; +} + +void AddLTArrow(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + GetMissileVel(mi,sx,sy,dx,dy,32); + missile[mi]._miAnimFrame = random(52, 8) + 1; + + missile[mi]._mirange = 255; + + if (id < 0) { + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + } else { + missile[mi]._miVar1 = plr[id]._px; + missile[mi]._miVar2 = plr[id]._py; + } + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddLightning(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA + // Note: midir is used to pass in the missile # of the root of the lightning chain. + // A negative midir means that this is not part of a chain. + + app_assert(mi < MAXMISSILES); + missile[mi]._misx = dx; + missile[mi]._misy = dy; + + if(midir >= 0) + { + missile[mi]._mixoff = missile[midir]._mixoff; + missile[mi]._miyoff = missile[midir]._miyoff; + missile[mi]._mitxoff = missile[midir]._mitxoff; + missile[mi]._mityoff = missile[midir]._mityoff; + } + + missile[mi]._miAnimFrame = random(52, 8) + 1; + + if (midir >= 0 && mienemy != MI_ENEMYPLR && id != -1) { + missile[mi]._mirange = 6 + (missile[mi]._mispllvl >> 1); + } else { + if (midir >= 0 && id != -1) { + missile[mi]._mirange = 10; + } else missile[mi]._mirange = 8; + } + + missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 4); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddMisexp(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + + if (mienemy != MI_ENEMYMONST && id > 0) { + app_assert(id < MAXMONSTERS); + app_assert(monster[id].MType != NULL); + switch (monster[id].MType->mtype) + { + case MT_SUCCUBUS: + SetMissAnim(mi,MF_FLAREXP); + break; + case MT_SNOWWICH: + SetMissAnim(mi,MF_BFLAREXP); + break; + case MT_HLSPWN: + SetMissAnim(mi,MF_DFLAREXP); + break; + case MT_SOLBRNR: + SetMissAnim(mi,MF_CFLAREXP); + break; + } + } + + app_assert(mi < MAXMISSILES); + missile[mi]._mix = missile[dx]._mix; + missile[mi]._miy = missile[dx]._miy; + missile[mi]._misx = missile[dx]._misx; + missile[mi]._misy = missile[dx]._misy; + missile[mi]._mixoff = missile[dx]._mixoff; + missile[mi]._miyoff = missile[dx]._miyoff; + missile[mi]._mitxoff = missile[dx]._mitxoff; + missile[mi]._mityoff = missile[dx]._mityoff; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + + missile[mi]._mirange = missile[mi]._miAnimLen; + missile[mi]._miVar1 = 0; + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddWeapexp(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = dx; + + missile[mi]._mimfnum = 0; + if (dx == 1) SetMissAnim(mi, MF_EXP1); + else SetMissAnim(mi, MF_CBOLT); + missile[mi]._mirange = missile[mi]._miAnimLen - 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL CheckIfTrig(int x, int y) +{ + int i; + + app_assert(numtrigs <= MAXTRIGGERS); + for (i = 0; i < numtrigs; ++i) + if (((x == trigs[i]._tx) && (y == trigs[i]._ty)) || + ((abs(trigs[i]._tx-x) < 2) && (abs(trigs[i]._ty-y) < 2))) return(TRUE); + + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddTown(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_TOWN) || !PRE_BETA + int i, pn; + int k, l, j; + int tx, ty, mx; + + app_assert(mi < MAXMISSILES); + if (currlevel != 0) { + missile[mi]._miDelFlag = TRUE; + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + app_assert(pn <= MAXTILES); + if (((nSolidTable[pn] | dObject[tx][ty] | nMissileTable[pn] | + dPlayer[tx][ty] | dMissile[tx][ty]) == 0) && + (!CheckIfTrig(tx, ty))) { + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = tx; + missile[mi]._misy = ty; + missile[mi]._miDelFlag = FALSE; + k = 6; + break; + } + } + j += 2; + } + } + } else { + tx = dx; + ty = dy; + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = tx; + missile[mi]._misy = ty; + missile[mi]._miDelFlag = FALSE; + } + + missile[mi]._mirange = 100; + missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen); + missile[mi]._miVar2 = 0; + + // Move current portal? + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + if ((missile[mx]._mitype == MIT_TOWN) && + (mx != mi) && + (missile[mx]._misource == id)) { + missile[mx]._mirange = 0; + } + } + + PutMissile(mi); + + if (id == myplr && missile[mi]._miDelFlag == FALSE && currlevel != 0) { + if (!setlevel) NetSendCmdLocParam3(TRUE, CMD_ACTIVATEPORTAL, tx, ty, currlevel, leveltype, FALSE); + else NetSendCmdLocParam3(TRUE, CMD_ACTIVATEPORTAL, tx, ty, setlvlnum, leveltype, TRUE); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlash(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES); + if (mienemy == MI_ENEMYMONST) { + if (id != -1) { + missile[mi]._midam = 0; + for (i = 0; i <= plr[id]._pLevel; ++i) missile[mi]._midam += random(55, 20) + 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + missile[mi]._midam += missile[mi]._midam >> 1; + UseMana(id, SPL_FLASH); + } else { + missile[mi]._midam = (currlevel >> 1); + } + } + else + missile[mi]._midam = monster[id].mLevel << 1; + + missile[mi]._mirange = 19; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddAura(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + +#if defined(HELLFIRE2) + app_assert(mi < MAXMISSILES); + if (mienemy == MI_ENEMYMONST) { + if (id != -1) { + missile[mi]._midam = 0; + missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id].plrlevel : 1); + plr[id]._pBaseToBlk += 50; + UseMana(id, SPL_AURA); + } + } +#endif + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddAura2(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + + app_assert(mi < MAXMISSILES); + if (mienemy == MI_ENEMYMONST) { + if (id != -1) { + missile[mi]._midam = 0; + missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id].plrlevel : 1); + } + } + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlash2(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES); + if (mienemy == MI_ENEMYMONST) + { + if (id != -1) { + missile[mi]._midam = 0; + for (i = 0; i <= plr[id]._pLevel; ++i) missile[mi]._midam += random(56, 2) + 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + missile[mi]._midam += missile[mi]._midam >> 1; + } else { + missile[mi]._midam = (currlevel >> 1); + } + } + + missile[mi]._miPreFlag = TRUE; + + missile[mi]._mirange = 19; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddManashield(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = ((plr[id]._pLevel << 4) << 1) + (plr[id]._pLevel << 4); + + missile[mi]._miVar1 = plr[id]._pHitPoints; + missile[mi]._miVar2 = plr[id]._pHPBase; + + missile[mi]._miVar8 = KILL_UNKNOWN; // killed by unknown source (inited) + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_MANASHLD); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFiremove(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._midam = random(59, 10) + 1 + plr[id]._pLevel; + + GetMissileVel(mi,sx,sy,dx,dy,16); + + missile[mi]._mirange = 255; + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + + ++missile[mi]._mix; + ++missile[mi]._miy; + missile[mi]._miyoff-=32; +//PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddGuardian(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_GUARDIAN) || !PRE_BETA + int i, pn; + int k, l, j; + int tx, ty; + + app_assert(mi < MAXMISSILES); + missile[mi]._midam = random(62, 10) + 1 + (plr[id]._pLevel >> 1); + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + + missile[mi]._miDelFlag = TRUE; + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + app_assert(tx < MAXDUNX); + app_assert(ty < MAXDUNY); + pn = dPiece[tx][ty]; + app_assert(pn <= MAXTILES); + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + //if ((dFlags[tx][ty] & BFLAG_VISIBLE) && + if ((LineClear(sx, sy, tx, ty)) && + ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty] | nMissileTable[pn] | dMissile[tx][ty]) == 0)) { + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = tx; + missile[mi]._misy = ty; + missile[mi]._miDelFlag = FALSE; + UseMana(id, SPL_GUARDIAN); + k = 6; + break; + } + } + j += 2; + } + } + + if (missile[mi]._miDelFlag == TRUE) return; + missile[mi]._misource = id; + missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 1); + + missile[mi]._mirange = (plr[id]._pLevel >> 1) + missile[mi]._mispllvl; + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + if (missile[mi]._mirange > 30) missile[mi]._mirange = 30; + missile[mi]._mirange = missile[mi]._mirange << 4; + if (missile[mi]._mirange < 30) missile[mi]._mirange = 30; + + missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen); + missile[mi]._miVar2 = 0; + missile[mi]._miVar3 = 1; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddChain(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_CHAIN) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + + missile[mi]._mirange = 1; + UseMana(id, SPL_CHAIN); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddChainOLD(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int i, k, j, mx; + + if (dam == 0) { + k = 0; + j = -1; + for (i = 0; i < nummissilevars; ++i) { + mx = missilevars[i][0]; + if (mx >= 0 && missile[mx]._mitype == MIT_CHAIN && missile[mx]._miVar8 > k) k = missile[mx]._miVar8; + if (mx < 0) j = i; + } + ++k; + missile[mi]._miVar8 = k; + if (j == -1) { + ++nummissilevars; + j = nummissilevars; + } + missilevars[j][0] = mi; + missilevars[j][1] = MIT_CHAIN; + missilevars[j][2] = 0; + } else { + for (i = 0; i < nummissilevars; ++i) { + mx = missilevars[i][0]; + if (mx >= 0 && missile[mx]._mitype == MIT_CHAIN && missile[mx]._miVar8 == dam) missilevars[i][2]++; + } + } + + k = 0; + missile[mi]._midam = 0; + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + if (missile[mx]._mitype == MIT_CHAIN && missile[mx]._midam > k) k = missile[mx]._midam; + if (missile[mx]._mitype == MIT_CHAINBALL && missile[mx]._miVar1 > k) k = missile[mx]._miVar1; + } + ++k; + missile[mi]._midam = k; + + missile[mi]._mirange = 12 + GetSpellLevel(id, SPL_LIGHTNING); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + missile[mi]._miVar5 = dx; + missile[mi]._miVar6 = dy; + missile[mi]._miVar7 = 0; + + UseMana(id, SPL_CHAIN); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddChainballOLD(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int i, mx; + + missile[mi]._miVar1 = dam; + missile[mi]._miVar2 = 0; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + if ((missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._miVar2 == 1) && (missile[mx]._midam == dam)) { + missile[mi]._miVar2 = missile[mx]._miVar2; + missile[mi]._miVar3 = missile[mx]._miVar3; + missile[mi]._miVar4 = missile[mx]._miVar4; + } + if ((missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._midam == dam)) + missile[mi]._miVar8 = missile[mx]._miVar8; + } + + if (dMonster[sx][sy] != 0) { + missile[mi]._miVar5 = sx; + missile[mi]._miVar6 = sy; + } else { + missile[mi]._miVar5 = 0; + missile[mi]._miVar6 = 0; + } + + missile[mi]._midam = (random(61, plr[id]._pLevel) + random(61, 6) + 4) << HP_SHIFT; + + GetMissileVel(mi, sx, sy, dx, dy, 16); + + missile[mi]._mirange = ((plr[id]._pLevel << 4) << 1) + (GetSpellLevel(id, SPL_CHAIN) << 4); + + PutMissile(mi); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBlood(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam) +{ + SetMissDir(mi, str); + app_assert(mi < MAXMISSILES); + missile[mi]._midam = 0; + + missile[mi]._miLightFlag = TRUE; + + missile[mi]._mirange = 250; + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBone(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam) +{ + if (str > 3) str = 2; + SetMissDir(mi, str); + + app_assert(mi < MAXMISSILES); + missile[mi]._midam = 0; + + missile[mi]._miLightFlag = TRUE; + + missile[mi]._mirange = 250; + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddMetal(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam) +{ + if (str > 3) str = 2; + SetMissDir(mi, str); + + app_assert(mi < MAXMISSILES); + missile[mi]._midam = 0; + + missile[mi]._miLightFlag = TRUE; + + missile[mi]._mirange = (missile[mi]._miAnimLen); + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRhino(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + AnimStruct *anim; + + app_assert(id < MAXMONSTERS); + app_assert(monster[id].MType != NULL); + if (EquivMonst(monster[id].MType->mtype, MT_HORNED)) + anim = &monster[id].MType->Anims[MA_SPECIAL]; + else if (EquivMonst(monster[id].MType->mtype, MT_NSNAKE)) + anim = &monster[id].MType->Anims[MA_ATTACK]; + else + anim = &monster[id].MType->Anims[MA_WALK]; + + GetMissileVel(mi,sx,sy,dx,dy,18); + + app_assert(mi < MAXMISSILES); + missile[mi]._mimfnum = midir; + missile[mi]._miAnimFlags = NULL; + missile[mi]._miAnimData = anim->Cels[midir]; + missile[mi]._miAnimDelay = anim->Rate; + missile[mi]._miAnimLen = anim->Frames; + missile[mi]._miAnimWidth = monster[id].MType->mAnimWidth; + missile[mi]._miAnimWidth2 = monster[id].MType->mAnimWidth2; + missile[mi]._miAnimAdd = 1; + if (EquivMonst(monster[id].MType->mtype, MT_NSNAKE)) + missile[mi]._miAnimFrame = 7; + + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + + missile[mi]._miLightFlag = TRUE; + if(monster[id]._uniqtype) { + missile[mi]._miUniqTrans = monster[id]._uniqtrans+1; + missile[mi]._mlid = monster[id].mlid; + } + + missile[mi]._mirange = 256; + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFireman(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + AnimStruct *anim; + + app_assert(id < MAXMONSTERS); + app_assert(monster[id].MType != NULL); + anim = &monster[id].MType->Anims[MA_WALK]; + + GetMissileVel(mi,sx,sy,dx,dy,16); + + app_assert(mi < MAXMISSILES); + missile[mi]._mimfnum = midir; + missile[mi]._miAnimFlags = NULL; + missile[mi]._miAnimData = anim->Cels[midir]; + missile[mi]._miAnimDelay = anim->Rate; + missile[mi]._miAnimLen = anim->Frames; + missile[mi]._miAnimWidth = monster[id].MType->mAnimWidth; + missile[mi]._miAnimWidth2 = monster[id].MType->mAnimWidth2; + missile[mi]._miAnimAdd = 1; + + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + + missile[mi]._miLightFlag = TRUE; + if(monster[id]._uniqtype) + missile[mi]._miUniqTrans = monster[id]._uniqtrans+1; + + dMonster[monster[id]._mx][monster[id]._my] = 0; + + missile[mi]._mirange = 256; + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlare(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int d; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + GetMissileVel(mi,sx,sy,dx,dy,16); + + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + if (mienemy == MI_ENEMYMONST) { + UseMana(id, SPL_BSTAR); + d = 5; + //for (k = missile[mi]._mispllvl; k > 0; --k) d -= 1; + //if (d <= 0) d = 1; +#if CHEATS + if (simplecheat || cheatflag) d = 0; +#endif + + plr[id]._pHitPoints -= (d << HP_SHIFT); + plr[id]._pHPBase -= (d << HP_SHIFT); + drawhpflag = TRUE; + + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } + } else { + if (id > 0) { + if (monster[id].MType->mtype == MT_SUCCUBUS) SetMissAnim(mi,MF_FLARE); + if (monster[id].MType->mtype == MT_SNOWWICH) SetMissAnim(mi,MF_BFLARE); + if (monster[id].MType->mtype == MT_HLSPWN) SetMissAnim(mi,MF_DFLARE); + if (monster[id].MType->mtype == MT_SOLBRNR) SetMissAnim(mi,MF_CFLARE); + } + } + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddAcid(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + GetMissileVel(mi,sx,sy,dx,dy,16); + + SetMissDir(mi, GetDirection16(sx,sy,dx,dy)); + + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = 15 + 5*(monster[id]._mint+1); + missile[mi]._mlid = -1; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddDoom(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int i, j, k, l; + int mid; + + // search in a 5 radius around tile clicked for monster + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + mid = dMonster[(dx + CrawlTable[j])][(dy + CrawlTable[(j + 1)])]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) { + missile[mi]._miVar1 = dx + CrawlTable[j]; + missile[mi]._miVar2 = dy + CrawlTable[j + 1]; + missile[mi]._miVar3 = mid; + i = -99; + k = 6; + break; + } + } + j += 2; + } + } + + // if no monsters found in search + if (i != -99) { + missile[mi]._miDelFlag = TRUE; + return; + } + + GetMissileVel(mi, sx, sy, missile[mi]._miVar1, missile[mi]._miVar2, 16); + SetMissDir(mi, GetDirection(sx, sy, missile[mi]._miVar1, missile[mi]._miVar2)); + + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + missile[mi]._misource = id; + missile[mi]._midam = 26; + + missile[mi]._mirange = ((plr[id]._pLevel << 4) >> 2) + (plr[id]._pLevel << 4) ; + for (i = GetSpellLevel(id, SPL_DOOM); i > 0; --i) missile[mi]._mirange += ((missile[mi]._mirange << 4) >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + + UseMana(id, SPL_DOOM); + PutMissile(mi); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFireonly(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._midam = dam; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + + missile[mi]._mirange = 50; + missile[mi]._miVar1 = missile[mi]._mirange - missile[mi]._miAnimLen; + missile[mi]._miVar2 = 0; + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddAcidpud(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int monst; + + app_assert(mi < MAXMISSILES); + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + + missile[mi]._mixoff = 0; + missile[mi]._miyoff = 0; +/* + missile[mi]._misx = missile[dx]._misx; + missile[mi]._misy = missile[dx]._misy; + missile[mi]._mixoff = missile[dx]._mixoff; + missile[mi]._miyoff = missile[dx]._miyoff; + missile[mi]._mitxoff = missile[dx]._mitxoff; + missile[mi]._mityoff = missile[dx]._mityoff; +*/ + + missile[mi]._miLightFlag = TRUE; + +// MoveMissilePos(mi); + + monst = missile[mi]._misource; + missile[mi]._mirange = random(50,15) + 40*(monster[monst]._mint + 1); + + missile[mi]._miPreFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddStone(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_STONE) || !PRE_BETA + int i, j, k, l, tx, ty; + int mid; + + app_assert(mi < MAXMISSILES); + missile[mi]._misource = id; + + // search in a 5 radius around tile clicked for monster + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + mid = dMonster[tx][ty]; + if (mid > 0) --mid; + else mid = -(mid + 1); + if ((mid > 3) + && (monster[mid]._mAi != AI_DIABLO) + && (monster[mid]._mmode != MM_FADEIN) + && (monster[mid]._mmode != MM_FADEOUT) + //&& (monster[mid]._mmode != MM_DEATH) + && (monster[mid]._mmode != MM_MISSILE)) { + i = -99; + k = 6; + missile[mi]._miVar1 = monster[mid]._mmode; + missile[mi]._miVar2 = mid; + monster[mid]._mmode = MM_STONE; + break; + } + } + j += 2; + } + } + + // if no monsters found in search + if (i != -99) { + missile[mi]._miDelFlag = TRUE; + return; + } + + missile[mi]._mix = tx; + missile[mi]._miy = ty; + missile[mi]._misx = missile[mi]._mix; + missile[mi]._misy = missile[mi]._miy; + + missile[mi]._mirange = 6 + missile[mi]._mispllvl; + //if (missile[mi]._mirange == 0) missile[mi]._mirange = 1; + //for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + if (missile[mi]._mirange > 15) missile[mi]._mirange = 15; + missile[mi]._mirange = missile[mi]._mirange << 4; + UseMana(id, SPL_STONE); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddInvis(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int i; + + missile[mi]._mirange = plr[id]._pLevel << 4; + for (i = GetSpellLevel(id, SPL_INVIS); i > 0; --i) missile[mi]._mirange += ((missile[mi]._mirange << 4) >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + UseMana(id, SPL_INVIS); + missile[mi]._miDelFlag = TRUE; +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddGolem(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_GOLEM) || !PRE_BETA + int i, mx; + //int tx, ty, k, j, l; + + app_assert(mi < MAXMISSILES); + + missile[mi]._miDelFlag = FALSE; + for (i = 0; i < nummissiles; ++i) { + mx = missileactive[i]; + if ((missile[mx]._mitype == MIT_GOLEM) && (mx != mi) && + (missile[mx]._misource == id)) { + missile[mi]._miDelFlag = TRUE; + return; + } + } + + /*for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + if ((LineClear(sx, sy, tx, ty)) && + ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty]) == 0)) {*/ + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar4 = dx; + missile[mi]._miVar5 = dy; + if ((monster[id]._mx != 1 || monster[id]._my != 0) && (id == myplr)) M_StartKill(id, id); + //missile[mi]._miDelFlag = FALSE; + UseMana(id, SPL_GOLEM); + /*k = 6; + break; + } + } + j += 2; + } + }*/ +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddEther(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_ETHER) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = (plr[id]._pLevel << 4) >> 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + + missile[mi]._miVar1 = plr[id]._pHitPoints; + missile[mi]._miVar2 = plr[id]._pHPBase; + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_ETHER); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBloodR(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_BLOODR) || !PRE_BETA + int manaval; + + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + return; // spell deleted - left code here just in case + + if (!(plr[id]._pIFlags & IAF_LMANA)) { + plr[id]._pHitPoints -= (10 << HP_SHIFT); + plr[id]._pHPBase -= (10 << HP_SHIFT); + + manaval = ((missile[mi]._mispllvl + 8) << MANA_SHIFT); + plr[id]._pMana += manaval; + plr[id]._pManaBase += manaval; + + if (plr[id]._pMana > plr[id]._pMaxMana) plr[id]._pMana = plr[id]._pMaxMana; + if (plr[id]._pManaBase > plr[id]._pMaxManaBase) plr[id]._pManaBase = plr[id]._pMaxManaBase; + + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } + } + + UseMana(id, SPL_BLOODR); + drawhpflag = TRUE; + missile[mi]._miDelFlag = TRUE; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddSpurt(int mi, int sx, int sy, int str, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._midam = dam; + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + missile[mi]._misource = id; + + if (dam == 1) + SetMissDir(mi, 0); + else + SetMissDir(mi, 1); + + missile[mi]._miLightFlag = TRUE; + + missile[mi]._mirange = missile[mi]._miAnimLen; + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBoom(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._mix = dx; + missile[mi]._miy = dy; + missile[mi]._misx = dx; + missile[mi]._misy = dy; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + missile[mi]._midam = dam; + + missile[mi]._mirange = missile[mi]._miAnimLen; + missile[mi]._miVar1 = 0; + + //PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddHeal(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_HEAL) || !PRE_BETA + int i; + long l; + + l = (random(57, 10) + 1) << HP_SHIFT; + for (i = 0; i < plr[id]._pLevel; ++i) l += ((random(57, 4) + 1) << HP_SHIFT); + app_assert(mi < MAXMISSILES); + for (i = 0; i < missile[mi]._mispllvl; ++i) l += ((random(57, 6) + 1) << HP_SHIFT); + if (plr[id]._pClass == CLASS_WARRIOR) l = l << 1; + if (plr[id]._pClass == CLASS_ROGUE) l += (l >> 1); + plr[id]._pHitPoints += l; + if (plr[id]._pHitPoints > plr[id]._pMaxHP) plr[id]._pHitPoints = plr[id]._pMaxHP; + plr[id]._pHPBase += l; + if (plr[id]._pHPBase > plr[id]._pMaxHPBase) plr[id]._pHPBase = plr[id]._pMaxHPBase; + + UseMana(id, SPL_HEAL); + drawhpflag = TRUE; + + missile[mi]._miDelFlag = TRUE; + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddMana(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_HEAL) || !PRE_BETA + int i; + long l; + + l = (random(57, 10) + 1) << MANA_SHIFT; + for (i = 0; i < plr[id]._pLevel; ++i) l += ((random(57, 4) + 1) << MANA_SHIFT); + app_assert(mi < MAXMISSILES); + for (i = 0; i < missile[mi]._mispllvl; ++i) l += ((random(57, 6) + 1) << MANA_SHIFT); + if (plr[id]._pClass == CLASS_SORCEROR) l = l << 1; + if (plr[id]._pClass == CLASS_ROGUE) l += (l >> 1); + + plr[id]._pMana += l; + if (plr[id]._pMana > plr[id]._pMaxMana) plr[id]._pMana = plr[id]._pMaxMana; + plr[id]._pManaBase += l; + if (plr[id]._pManaBase > plr[id]._pMaxManaBase) plr[id]._pManaBase = plr[id]._pMaxManaBase; + + UseMana(id, SPL_MANA); + drawmanaflag = TRUE; + + missile[mi]._miDelFlag = TRUE; + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +void AddFMana(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_HEAL) || !PRE_BETA + app_assert(mi < MAXMISSILES); + plr[id]._pMana = plr[id]._pMaxMana; + plr[id]._pManaBase = plr[id]._pMaxManaBase; + UseMana(id, SPL_FMANA); + drawmanaflag = TRUE; +#endif + missile[mi]._miDelFlag = TRUE; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddHealOther(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_HEALOTHER) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_HEALOTHER); + if (id == myplr) { + NewCursor(HEALOTHER_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddElement(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_ELEMENT) || !PRE_BETA + int i; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + //missile[mi]._midam = 0; + //for (i = 0; i < plr[id]._pLevel; ++i) missile[mi]._midam += random(67, 6) + 1; + //for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + app_assert(mi < MAXMISSILES); + missile[mi]._midam = (random(60, 10) + random(60, 10) + 2 + plr[id]._pLevel) << 1; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + missile[mi]._midam = missile[mi]._midam >> 1; + + GetMissileVel(mi, sx, sy, dx, dy, 16); + SetMissDir(mi, GetDirection8(sx, sy, dx, dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = dx; + missile[mi]._miVar5 = dy; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + UseMana(id, SPL_ELEMENT); + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddIdentify(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_IDENTIFY) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_IDENTIFY); + if (id == myplr) { + if (sbookflag) sbookflag = FALSE; + if (!invflag) invflag = TRUE; + NewCursor(IDENTIFY_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFirewallC(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int i, pn; + int k, l, j; + int tx, ty; + + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (i = CrawlTable[l]; i > 0; --i) { + tx = dx + CrawlTable[j]; + ty = dy + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + //if ((dFlags[tx][ty] & BFLAG_VISIBLE) && ((sx != tx) || (sy != ty)) && + if ((LineClear(sx, sy, tx, ty)) && ((sx != tx) || (sy != ty)) && + ((nSolidTable[pn] | dObject[tx][ty]) == 0)) { + missile[mi]._miVar1 = tx; + missile[mi]._miVar2 = ty; + missile[mi]._miVar5 = tx; + missile[mi]._miVar6 = ty; + missile[mi]._miDelFlag = FALSE; + k = 6; + break; + } + } + j += 2; + } + } + + if (missile[mi]._miDelFlag == TRUE) return; + + missile[mi]._miVar7 = 0; + missile[mi]._miVar8 = 0; + + //midir = GetDirection(sx, sy, tx, ty); + missile[mi]._miVar3 = (midir - 2) & 0x0007; + missile[mi]._miVar4 = (midir + 2) & 0x0007; + + missile[mi]._mirange = 7; + UseMana(id, SPL_WALL); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlameBox(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + + if (mienemy == MI_ENEMYMONST){ + UseMana(id, SPL_RINGOFFIRE); + } + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miDelFlag = FALSE; + + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + missile[mi]._miVar5 = 0; + missile[mi]._miVar6 = 0; + missile[mi]._miVar7 = 0; + missile[mi]._miVar8 = 0; + + missile[mi]._mirange = 7; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddShowMagicItems(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = FALSE; + + missile[mi]._miVar1 = 0; + missile[mi]._miVar2 = 0; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + missile[mi]._miVar5 = 0; + missile[mi]._miVar6 = 0; + missile[mi]._miVar7 = 0; + missile[mi]._miVar8 = 0; + + HighLightAllItems = true; + missile[mi]._mirange = 245 + (10 * missile[mi]._mispllvl) + (2 * (id > 0) ? plr[id].plrlevel : 1); + if (mienemy == MI_ENEMYMONST){ + UseMana(id, SPL_SHOWMAGITEMS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddInfra(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_INFRA) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES); + missile[mi]._mirange = 99 << 4; + for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._mirange += (missile[mi]._mirange >> 3); + missile[mi]._mirange = missile[mi]._mirange + ((plr[id]._pISplDur * missile[mi]._mirange) >> 7); + + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_INFRA); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddWave(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_WAVE) || !PRE_BETA + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = 0; + missile[mi]._mirange = 1; + missile[mi]._miAnimFrame = 4; + UseMana(id, SPL_WAVE); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddNova(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_NOVA) || !PRE_BETA + int k; + + app_assert(mi < MAXMISSILES); + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + if (id != -1) { + missile[mi]._midam = random(66, 6) + random(66, 6) + random(66, 6) + random(66, 6) + random(66, 6); + missile[mi]._midam += 5 + plr[id]._pLevel; + missile[mi]._midam = missile[mi]._midam >> 1; + for (k = missile[mi]._mispllvl; k > 0; --k) missile[mi]._midam += (missile[mi]._midam >> 3); + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_NOVA); + } else { + missile[mi]._midam = random(66, 3) + random(66, 3) + random(66, 3); + missile[mi]._midam += (currlevel >> 1); + } + missile[mi]._mirange = 1; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBoil(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + // not in game + missile[mi]._miDelFlag = TRUE; + return; +/* +#if (PRE_BETA && PRE_BLOODB) || !PRE_BETA + missile[mi]._miVar1 = dx; + missile[mi]._miVar2 = dy; + missile[mi]._mirange = 1; +#else + missile[mi]._miDelFlag = TRUE; +#endif*/ +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRepair(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_REPAIR) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_REPAIR); + if (id == myplr) { + if (sbookflag) sbookflag = FALSE; + if (!invflag) invflag = TRUE; + NewCursor(REPAIR_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRecharge(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_RECHARGE) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_RECHARGE); + if (id == myplr) { + if (sbookflag) sbookflag = FALSE; + if (!invflag) invflag = TRUE; + NewCursor(RECHARGE_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddDisarm(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_DISARM) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_DISARM); + if (id == myplr) { + NewCursor(DISARM_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddApoca(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_APOCA) || !PRE_BETA + int i; + + app_assert(mi < MAXMISSILES); + missile[mi]._miVar1 = 8; + missile[mi]._miVar2 = sy - missile[mi]._miVar1; + missile[mi]._miVar3 = sy + missile[mi]._miVar1; + missile[mi]._miVar4 = sx - missile[mi]._miVar1; + missile[mi]._miVar5 = sx + missile[mi]._miVar1; + missile[mi]._miVar6 = missile[mi]._miVar4; + + if (missile[mi]._miVar2 <= 0) missile[mi]._miVar2 = 1; + if (missile[mi]._miVar3 >= MAXDUNY) missile[mi]._miVar3 = MAXDUNY - 1; + if (missile[mi]._miVar4 <= 0) missile[mi]._miVar4 = 1; + if (missile[mi]._miVar5 >= MAXDUNX) missile[mi]._miVar5 = MAXDUNX - 1; + + for (i = 0; i < plr[id]._pLevel; ++i) missile[mi]._midam += random(67, 6) + 1; + + missile[mi]._mirange = 255; + missile[mi]._miDelFlag = FALSE; + UseMana(id, SPL_APOCA); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlame(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int seqno) +{ +#if (PRE_BETA && PRE_FLAME) || !PRE_BETA + // seqno: the number of flame chunk for this spell instance + int i; + + app_assert(mi < MAXMISSILES); + missile[mi]._miVar2 = 0; + //for (i = 0; i < 2 - seqno; ++i) { + for (i = seqno; i > 0; --i) { + missile[mi]._miVar2 += 5; + } + + missile[mi]._misx = dx; + missile[mi]._misy = dy; + + missile[mi]._mixoff = missile[midir]._mixoff; + missile[mi]._miyoff = missile[midir]._miyoff; + missile[mi]._mitxoff = missile[midir]._mitxoff; + missile[mi]._mityoff = missile[midir]._mityoff; + missile[mi]._mirange = 20 + missile[mi]._miVar2; + missile[mi]._mlid = AddLight(sx, sy, 1); + + if (mienemy == MI_ENEMYMONST) { + missile[mi]._midam = (random(79, plr[id]._pLevel) + random(79, 2) + 2) << 3; + missile[mi]._midam += missile[mi]._midam >> 1; + //missile[mi]._midam = plr[id]._pLevel << 2; + //for (i = missile[mi]._mispllvl; i > 0; --i) missile[mi]._midam += (missile[mi]._midam >> 3); + //missile[mi]._midam = missile[mi]._midam << 1 + missile[mi]._midam; + } else { + missile[mi]._midam = random(77, monster[id].mMaxDamage - monster[id].mMinDamage + 1) + monster[id].mMinDamage; + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddFlamec(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_FLAME) || !PRE_BETA + //int k; + //int tsx, tsy; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + GetMissileVel(mi, sx, sy, dx, dy, 32); + if (mienemy == MI_ENEMYMONST) UseMana(id, SPL_FLAME); + + app_assert(mi < MAXMISSILES); + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._mirange = 256; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddCbolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA + app_assert(mi < MAXMISSILES); + if (micaster == MI_ENEMYMONST) + { + if (id == myplr) { + missile[mi]._mirnd = random(63, 15) + 1; + // INSERT send seed code + } else { + // INSERT get seed from network message for syncing + // used as a number idx not a seed so no SetRndSeed necessary + missile[mi]._mirnd = random(63, 15) + 1; + } + missile[mi]._midam = random(68, plr[id]._pMagic >> 2) + 1; + //for (i = missile[mi]._mispllvl; i > 0; --i) ++missile[mi]._midam; + } + else + { + missile[mi]._mirnd = random(63, 15) + 1; + missile[mi]._midam = 15; + } + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + missile[mi]._miAnimFrame = random(63, 8) + 1; + missile[mi]._mlid = AddLight(sx, sy, 5); + GetMissileVel(mi, sx, sy, dx, dy, 8); + + missile[mi]._miVar1 = 5; + missile[mi]._miVar2 = midir; + missile[mi]._miVar3 = 0; + + missile[mi]._mirange = 256; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +void AddCBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA + app_assert(mi < MAXMISSILES); + if (micaster == MI_ENEMYMONST) + { + if (id == myplr) { + missile[mi]._mirnd = random(63, 15) + 1; + // INSERT send seed code + } else { + // INSERT get seed from network message for syncing + // used as a number idx not a seed so no SetRndSeed necessary + missile[mi]._mirnd = random(63, 15) + 1; + } + } + else + { + missile[mi]._mirnd = random(63, 15) + 1; + missile[mi]._midam = 15; + } + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + missile[mi]._miAnimFrame = random(63, 8) + 1; + missile[mi]._mlid = AddLight(sx, sy, 5); + GetMissileVel(mi, sx, sy, dx, dy, 8); + + missile[mi]._miVar1 = 5; + missile[mi]._miVar2 = midir; + missile[mi]._miVar3 = 0; + + missile[mi]._mirange = 256; + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddHbolt(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA + int sp; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES); + if (id != -1) { + sp = 16 + (missile[mi]._mispllvl << 1); + if (sp >= 63) sp = 63; + } else sp = 16; + + GetMissileVel(mi, sx, sy, dx, dy, sp); + SetMissDir(mi, GetDirection16(sx, sy, dx, dy)); + + missile[mi]._mirange = 256; + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + missile[mi]._midam = random(69, 10) + 9 + plr[id]._pLevel; + + UseMana(id, SPL_HBOLT); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +void AddHBArrow(int mi, int sx, int sy, int dx, int dy, int midir, char micaster, int id, int dam) +{ +#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA + int sp; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES); + if (id != -1) { + sp = 16 + (missile[mi]._mispllvl << 1); + if (sp >= 63) sp = 63; + } else sp = 16; + + GetMissileVel(mi, sx, sy, dx, dy, sp); + SetMissDir(mi, GetDirection16(sx, sy, dx, dy)); + + missile[mi]._mirange = 256; + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + //PutMissile(mi); +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddResurrect(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA + UseMana(id, SPL_RESURRECT); + if (id == myplr) { + NewCursor(RESURRECT_CURS); + } +#endif + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddResurrectBeam(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._mix = dx; + missile[mi]._miy = dy; + missile[mi]._misx = missile[mi]._mix; + missile[mi]._misy = missile[mi]._miy; + missile[mi]._mixvel = 0; + missile[mi]._miyvel = 0; + missile[mi]._mirange = misfiledata[MF_RESURRECT].mAnimLen[0]; +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddTelekinesis(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_TELEKINESIS) || !PRE_BETA + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; + UseMana(id, SPL_TELEKINESIS); + if (id == myplr) { + NewCursor(TELE_CURS); + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void AddBoneSpirit(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + int d, mid, mx, my; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + GetMissileVel(mi, sx, sy, dx, dy, 16); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._mlid = AddLight(sx, sy, 8); + + if (mienemy == MI_ENEMYMONST) { + UseMana(id, SPL_BONESPIRIT); + d = 6; + +#if CHEATS + if (simplecheat || cheatflag) d = 0; +#endif + + plr[id]._pHitPoints -= (d << HP_SHIFT); + plr[id]._pHPBase -= (d << HP_SHIFT); + drawhpflag = TRUE; + + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } + + if (dPlayer[dx][dy] != 0) { + missile[mi]._miVar6 = 1; + if (dPlayer[dx][dy] > 0) mid = dPlayer[dx][dy] - 1; + else mid = -(dPlayer[dx][dy] + 1); + mx = plr[mid]._px; + my = plr[mid]._py; + } else { + missile[mi]._miVar6 = 0; + if (dMonster[dx][dy] <= 0) mid = FindClosest(sx, sy, 19); + else mid = dMonster[dx][dy] - 1; + mx = monster[mid]._mx; + my = monster[mid]._my; + } + + if (mid > 0) { + missile[mi]._miVar3 = mid; + GetMissileVel(mi, sx, sy, mx, my, 16); + SetMissDir(mi, GetDirection8(sx, sy, mx, my)); + } + } + + PutMissile(mi); +} + +*/ +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddBoneSpirit(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ +#if (PRE_BETA && PRE_BONESPIRIT) || !PRE_BETA + int d; + + if ((sx == dx) && (sy == dy)) { + dx += XDirAdd[midir]; + dy += YDirAdd[midir]; + } + + app_assert(mi < MAXMISSILES); + missile[mi]._midam = 0; + + GetMissileVel(mi, sx, sy, dx, dy, 16); + SetMissDir(mi, GetDirection8(sx, sy, dx, dy)); + + missile[mi]._mirange = 256; + + missile[mi]._miVar1 = sx; + missile[mi]._miVar2 = sy; + missile[mi]._miVar3 = 0; + missile[mi]._miVar4 = dx; + missile[mi]._miVar5 = dy; + + missile[mi]._mlid = AddLight(sx, sy, 8); + + if (mienemy == MI_ENEMYMONST) { + UseMana(id, SPL_BONESPIRIT); + d = 6; +#if CHEATS + if (simplecheat || cheatflag) d = 0; +#endif + plr[id]._pHitPoints -= (d << HP_SHIFT); + plr[id]._pHPBase -= (d << HP_SHIFT); + drawhpflag = TRUE; + + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } + + } +#else + missile[mi]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddRportal(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + app_assert(mi < MAXMISSILES); + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + + missile[mi]._mirange = 100; + missile[mi]._miVar1 = missile[mi]._mirange - (missile[mi]._miAnimLen); + missile[mi]._miVar2 = 0; + + PutMissile(mi); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddDiabApoca(int mi, int sx, int sy, int dx, int dy, int midir, char mienemy, int id, int dam) +{ + BOOL LineClear(int x1, int y1, int x2, int y2); + int pnum; + + for (pnum = 0; pnum < gbMaxPlayers; ++pnum) + { + if (plr[pnum].plractive + && LineClear(sx,sy,plr[pnum]._pfutx, plr[pnum]._pfuty)) + AddMissile(0, 0, plr[pnum]._pfutx, plr[pnum]._pfuty, 0, MIT_FIREPLAR, mienemy, id, dam, 0); + } + app_assert(mi < MAXMISSILES); + missile[mi]._miDelFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int AddMissile(int sx, int sy, int v1, int v2, int midir, int mitype, char micaster, int id, int v3, int spllvl) +{ + // v1 and v2 are usually dx and dy (this can be different per missile) + // v3 is usually damage amount + + int mi; + + // check if exceeded number of missiles + if (nummissiles >= MAXMISSILES) + return -1; + + // get next missile id that is available + mi = missileavail[0]; + missileavail[0] = missileavail[MAXMISSILES - nummissiles - 1]; + missileactive[nummissiles] = mi; + ++nummissiles; + + // Zero out the data first. + memset(&missile[mi], 0, sizeof(MissileStruct)); + + // do some standard missile setups + missile[mi]._mitype = mitype; + missile[mi]._micaster = micaster; + missile[mi]._misource = id; + missile[mi]._miAnimType = missiledata[mitype].mFileNum; + missile[mi]._miDrawFlag = missiledata[mitype].mDraw; + + missile[mi]._mispllvl = spllvl; + + missile[mi]._mimfnum = midir; + if (missile[mi]._miAnimType != MF_NONE + && misfiledata[(missile[mi]._miAnimType)].mAnimFAmt >= 8) + SetMissDir(mi, midir); + else + SetMissDir(mi, 0); + + missile[mi]._mix = sx; + missile[mi]._miy = sy; + missile[mi]._mixoff = 0; + missile[mi]._miyoff = 0; + missile[mi]._misx = sx; + missile[mi]._misy = sy; + missile[mi]._mitxoff = 0; + missile[mi]._mityoff = 0; + + missile[mi]._miDelFlag = FALSE; + missile[mi]._miAnimAdd = 1; + + missile[mi]._miLightFlag = FALSE; + missile[mi]._miPreFlag = FALSE; + missile[mi]._miUniqTrans = FALSE; + missile[mi]._midam = v3; + missile[mi]._miHitFlag = FALSE; + missile[mi]._midist = 0; + missile[mi]._mlid = -1; + missile[mi]._mirnd = 0; + + if (missiledata[mitype].mlSFX != -1) + PlaySfxLoc(missiledata[mitype].mlSFX, missile[mi]._mix, missile[mi]._miy); + + missiledata[mitype].mAddProc(mi, sx, sy, v1, v2, midir, micaster, id, v3); + + return mi; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*int ChainBounceOLD (int i, int sx, int sy) +{ + int j, mi, mx, dir; + + if (dMonster[sx][sy] != 0) { + + if (dMonster[sx][sy] > 0) mi = dMonster[sx][sy] - 1; + else mi = -(dMonster[sx][sy] + 1); + + if ((monster[mi]._mhitpoints >> HP_SHIFT) > 0) { + for (j = 0; j < nummissilevars; ++j) { + mx = missilevars[j][0]; + if ((mx >= 0) && (missile[mx]._mitype == MIT_CHAIN) && (missile[mx]._miVar8 == missile[i]._miVar8) && + (missilevars[j][2] >= (plr[(missile[i]._misource)]._pLevel >> 1))) { + missilevars[j][0] = -1; + return 3; + } + } + dir = GetDirection(missile[i]._mix, missile[i]._miy, sx, sy); + AddMissile(missile[i]._mix, missile[i]._miy, sx, sy, dir, MIT_CHAIN, MI_ENEMYMONST, missile[i]._misource, missile[i]._miVar8); + return 1; + } + } + + return 0; +}*/ + +extern BOOL LineClear(int x1, int y1, int x2, int y2); +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int Sentfire(int i, int sx, int sy) +{ + int ex, dir; + + ex = 0; + app_assert(i < MAXMISSILES); + if (LineClear(missile[i]._mix, missile[i]._miy, sx, sy) + && (dMonster[sx][sy] > 0) + && ((monster[(dMonster[sx][sy] - 1)]._mhitpoints >> HP_SHIFT) > 0) + && ((dMonster[sx][sy]-1) > 3)) { + dir = GetDirection(missile[i]._mix, missile[i]._miy, sx, sy); + missile[i]._miVar3 = missileavail[0]; // get next mid + AddMissile(missile[i]._mix, missile[i]._miy, sx, sy, dir, MIT_FIREBOLT, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam, GetSpellLevel(missile[i]._misource, SPL_FIREBOLT)); + ex = -1; + } + + if (ex == -1) { + SetMissDir(i, 2); + missile[i]._miVar2 = 3; + } + + return (ex); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Dummy(int i) +{} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Rune(int i) +{ + int const tx = missile[i]._mix; + int const ty = missile[i]._miy; + int mid = dMonster[tx][ty]; + int pid = dPlayer[tx][ty]; + + if (mid != 0 + || pid != 0) { + + int dir; + + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + + dir = GetDirection(missile[i]._mixoff, missile[i]._miyoff, + monster[mid]._mxoff, monster[mid]._myoff); + } + else { + if (pid > 0) --pid; + else pid = -(pid + 1); + + dir = GetDirection(missile[i]._mixoff, missile[i]._miyoff, + plr[pid]._pxoff, plr[pid]._pyoff); + } + if (missile[i]._miVar1 == MIT_MISEXP){ + AddMissile(tx, ty, i, 0, dir, missile[i]._miVar1, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + } + else { + AddMissile(tx, ty, tx, ty, dir, missile[i]._miVar1, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + } + missile[i]._miDelFlag = TRUE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Golem(int i) +{ +#if (PRE_BETA && PRE_GOLEM) || !PRE_BETA + int id, pn; + int j, k, l, m; + int tx, ty; + + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + + if (monster[id]._mx == 1 && monster[id]._my == 0) { + for (k = 0; k < 6; ++k) { + l = CrawlNum[k]; + j = l + 1; + for (m = CrawlTable[l]; m > 0; --m) { + tx = missile[i]._miVar4 + CrawlTable[j]; + ty = missile[i]._miVar5 + CrawlTable[(j + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + pn = dPiece[tx][ty]; + if ((LineClear(missile[i]._miVar1, missile[i]._miVar2, tx, ty)) && + ((nSolidTable[pn] | dMonster[tx][ty] | dObject[tx][ty]) == 0)) { + k = 6; + SpawnGolum(id, tx, ty, i); + break; + } + } + j += 2; + } + } + } + missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_SetManashield(int i) +{ +#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA + ManashieldFlag = 1; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_LArrow(int i) +{ + int p, mind, maxd, rst; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + p = missile[i]._misource; + if (missile[i]._miAnimType != MF_CBOLT && missile[i]._miAnimType != MF_EXP1) { + ++missile[i]._midist; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + if (p != -1) { + if (missile[i]._micaster == MI_ENEMYMONST) { + mind = plr[p]._pIMinDam; + maxd = plr[p]._pIMaxDam; + } else { + mind = monster[p].mMinDamage; + maxd = monster[p].mMaxDamage; + } + } else { + mind = currlevel + random(68, 10) + 1; + maxd = (currlevel * 2) + random(68, 10) + 1; + } + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) { + rst = missiledata[(missile[i]._mitype)].mResist; + missiledata[(missile[i]._mitype)].mResist = MIMT_NONE; + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0); + missiledata[(missile[i]._mitype)].mResist = rst; + } + + if (missile[i]._mirange == 0) { + missile[i]._mimfnum = 0; + missile[i]._mitxoff -= missile[i]._mixvel; + missile[i]._mityoff -= missile[i]._miyvel; + GetMissilePos(i); + if (missile[i]._mitype == MIT_LARROW) { + SetMissAnim(i, MF_CBOLT); + missile[i]._mirange = missile[i]._miAnimLen - 1; + } else { + SetMissAnim(i, MF_EXP1); + missile[i]._mirange = missile[i]._miAnimLen - 1; + } + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 5); + } + } + } else { + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, 5 + missile[i]._miAnimFrame); + rst = missiledata[(missile[i]._mitype)].mResist; + // drb.patch1.start.02/25/97 + if (missile[i]._mitype == MIT_LARROW) { + if (p != -1) { + mind = plr[p]._pILMinDam; + maxd = plr[p]._pILMaxDam; + } else { + mind = currlevel + random(68, 10) + 1; + maxd = (currlevel * 2) + random(68, 10) + 1; + } + missiledata[MIT_LARROW].mResist = MIMT_LGHT; + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 1); + } + if (missile[i]._mitype == MIT_FARROW) { + if (p != -1) { + mind = plr[p]._pIFMinDam; + maxd = plr[p]._pIFMaxDam; + } else { + mind = currlevel + random(68, 10) + 1; + maxd = (currlevel * 2) + random(68, 10) + 1; + } + missiledata[MIT_FARROW].mResist = MIMT_FIRE; + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 1); + } + // endpatch1.2/25/97 + missiledata[(missile[i]._mitype)].mResist = rst; + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Arrow(int i) +{ + int p, mind, maxd; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + ++missile[i]._midist; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + p = missile[i]._misource; + if (p != -1) { + if (missile[i]._micaster == MI_ENEMYMONST) { + mind = plr[p]._pIMinDam; + maxd = plr[p]._pIMaxDam; + } else { + mind = monster[p].mMinDamage; + maxd = monster[p].mMaxDamage; + } + } else { + mind = currlevel; + maxd = currlevel * 2; + } + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Firebolt(int i) +{ +#if (PRE_BETA && PRE_FIREBOLT) || !PRE_BETA + int omx, omy, d, p; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + + if (missile[i]._mitype == MIT_BONESPIRIT && missile[i]._mimfnum == 8) { + if (missile[i]._mirange == 0) { + if(missile[i]._mlid >= 0) AddUnLight(missile[i]._mlid); + missile[i]._miDelFlag = TRUE; + PlaySfxLoc(LS_BSIMPCT, missile[i]._mix, missile[i]._miy); + } + PutMissile(i); + return; + } + + omx = missile[i]._mitxoff; + omy = missile[i]._mityoff; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + p = missile[i]._misource; + if (p != -1) { + if (missile[i]._micaster == MI_ENEMYMONST) { + switch(missile[i]._mitype) { + case MIT_FLARE: + d = ((plr[p]._pMagic>>1)-(plr[p]._pMagic>>3)) + (missile[i]._mispllvl << 1) + missile[i]._mispllvl; + break; + case MIT_FIREBOLT: + d = random(75, 10) + 1 + (plr[p]._pMagic >> 3) + missile[i]._mispllvl; + break; + case MIT_BONESPIRIT: + //d = (monster[missile[i]._miVar3]._mhitpoints >> HP_SHIFT) >> 1; + d = 0; + break; + } + } else d = (random(77, monster[p].mMaxDamage - monster[p].mMinDamage + 1) + monster[p].mMinDamage); + } else d = random(78, currlevel << 1) + currlevel; + + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, d, d, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + missile[i]._mitxoff = omx; + missile[i]._mityoff = omy; + GetMissilePos(i); + switch(missile[i]._mitype) { + case MIT_FLARE: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_FLAREXP, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_FIREBOLT: + case MIT_MAGMABALL: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_MISEXP, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_ACID: + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_ACIDSPLAT, missile[i]._micaster, missile[i]._misource, 0, 0); + break; + case MIT_BONESPIRIT: + SetMissDir(i, 8); + missile[i]._mirange = 7; + missile[i]._miDelFlag = FALSE; + PutMissile(i); + return; + } + if(missile[i]._mlid >= 0) AddUnLight(missile[i]._mlid); + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + if(missile[i]._mlid >= 0) ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8); + } + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Lightball(int i) +{ + int j, tx, ty, oi; + + app_assert(i < MAXMISSILES); + tx = missile[i]._miVar1; + ty = missile[i]._miVar2; + + --missile[i]._mirange; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + + GetMissilePos(i); + j = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + + // fix for shires and fireing nova - rjs + if (dObject[tx][ty] != 0 && tx == missile[i]._mix && ty == missile[i]._miy) { + if (dObject[tx][ty] > 0) oi = dObject[tx][ty] - 1; + else oi = -(dObject[tx][ty] + 1); + if (object[oi]._otype == OBJ_SHRINEL || object[oi]._otype == OBJ_SHRINER) missile[i]._mirange = j; + } + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Krull(int i) +{ + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + + GetMissilePos(i); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Acidpud(int i) +{ + int range; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + +// GetMissilePos(i); + range = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + missile[i]._mirange = range; // CheckMissileCol clears range if there's a collision, + // but this missile sticks around even after a collision + +// MoveMissilePos(i); + + if (missile[i]._mirange == 0) + { + if(missile[i]._mimfnum) + missile[i]._miDelFlag = TRUE; + else + { + SetMissDir(i, 1); + missile[i]._mirange = missile[i]._miAnimLen; + } + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Firewall(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int ExpLight[14] = {2,3,4,5,5,6,7,8,9,10,11,12,12}; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + + if (missile[i]._mirange == missile[i]._miVar1) { + SetMissDir(i, 1); + missile[i]._miAnimFrame = random(83, 11) + 1; + } + + if (missile[i]._mirange == missile[i]._miAnimLen - 1) { + SetMissDir(i, 0); + missile[i]._miAnimFrame = 13; + missile[i]._miAnimAdd = -1; + } + + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 1); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + if ((missile[i]._mimfnum != 0) && (missile[i]._mirange != 0) && + (missile[i]._miAnimAdd != -1) && (missile[i]._miVar2 < 12)) { + + if (missile[i]._miVar2 == 0) + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ++missile[i]._miVar2; + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Fireball(int i) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int dam, px, py, id, mx, my; + + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + dam = missile[i]._midam; + + //dam = missile[i]._mispllvl; // rjs test + //missiledata[(missile[i]._mitype)].mResist = MIMT_NONE; + + --missile[i]._mirange; + + if (missile[i]._micaster == MI_ENEMYMONST) { + px = plr[id]._px; + py = plr[id]._py; + } else { + px = monster[id]._mx; + py = monster[id]._my; + } + + if (missile[i]._miAnimType == MF_BIGEXP) { + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); + return; + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) { + mx = missile[i]._mix; + my = missile[i]._miy; + + ChangeLight(missile[i]._mlid, mx, my, missile[i]._miAnimFrame); + + if (CheckBlock(px, py, mx , my ) == 0) CheckMissileCol(i, dam, dam, 0, mx, my, 1); + if (CheckBlock(px, py, mx , my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my + 1, 1); + if (CheckBlock(px, py, mx , my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my - 1, 1); + if (CheckBlock(px, py, mx + 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my, 1); + if (CheckBlock(px, py, mx + 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my - 1, 1); + if (CheckBlock(px, py, mx + 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my + 1, 1); + if (CheckBlock(px, py, mx - 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my, 1); + if (CheckBlock(px, py, mx - 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my + 1, 1); + if (CheckBlock(px, py, mx - 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my - 1, 1); + + //++missile[i]._mix; + //++missile[i]._miy; + //missile[i]._miyoff -= 32; + + if ((!TransList[dTransVal[mx][my]]) || + ((missile[i]._mixvel < 0) && + ((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) || + (TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) { + ++missile[i]._mix; + ++missile[i]._miy; + missile[i]._miyoff -= 32; + } + + if (((missile[i]._miyvel > 0) && + ((TransList[dTransVal[mx+1][my]] && nSolidTable[dPiece[mx+1][my]]) || + (TransList[dTransVal[mx-1][my]] && nSolidTable[dPiece[mx-1][my]])))) { + missile[i]._miyoff -= 32; + } + + if (((missile[i]._mixvel > 0) && + ((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) || + (TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) { + missile[i]._mixoff -= 32; + } + + missile[i]._mimfnum = 0; + SetMissAnim(i, MF_BIGEXP); + missile[i]._mirange = missile[i]._miAnimLen - 1; + + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8); + } + } + + PutMissile(i); +#endif +} + + +/*-----------------------------------------------------------------------* + // Doesn't work yet. GWP +**-----------------------------------------------------------------------*/ +void MI_SpiralFireBall(int i) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int px, py, mx, my; + + app_assert(i < MAXMISSILES); + int const id = missile[i]._misource; + int const dam = missile[i]._midam; + + + int xcurve; + int ycurve; + + // Set the direction into a spiral. + if (missile[i]._miVar7 < 0) { + missile[i]._miVar6 *= 2; + missile[i]._miVar7 = missile[i]._miVar6; + + --missile[i]._mimfnum; + if (missile[i]._mimfnum < 0) + missile[i]._mimfnum = 7; + } + else --missile[i]._miVar7; + + switch (missile[i]._mimfnum) { + case 0: // Down + xcurve = missile[i]._mixvel; + ycurve = 0; + break; + case 1: // Down left + xcurve = missile[i]._mixvel; + ycurve = missile[i]._miyvel; + break; + case 2: // Left + xcurve = 0; + ycurve = missile[i]._miyvel; + break; + case 3: // Up Left + xcurve = missile[i]._mixvel; + ycurve = missile[i]._miyvel; + break; + case 4: // Up + xcurve = missile[i]._mixvel; + ycurve = 0; + break; + case 5: // Up right + xcurve = missile[i]._mixvel; + ycurve = missile[i]._miyvel; + break; + case 6: // Right + xcurve = 0; + ycurve = missile[i]._miyvel; + break; + case 7: // Down Right + xcurve = missile[i]._mixvel; + ycurve = missile[i]._miyvel; + break; + } + + + --missile[i]._mirange; + + if (missile[i]._micaster == MI_ENEMYMONST) { + px = plr[id]._px; + py = plr[id]._py; + } else { + px = monster[id]._mx; + py = monster[id]._my; + } + + if (missile[i]._miAnimType == MF_BIGEXP) { + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); + return; + } + + missile[i]._mitxoff += xcurve; + missile[i]._mityoff += ycurve; + GetMissilePos(i); + + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) { + mx = missile[i]._mix; + my = missile[i]._miy; + + ChangeLight(missile[i]._mlid, mx, my, missile[i]._miAnimFrame); + + if (CheckBlock(px, py, mx , my ) == 0) CheckMissileCol(i, dam, dam, 0, mx, my, 1); + if (CheckBlock(px, py, mx , my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my + 1, 1); + if (CheckBlock(px, py, mx , my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx, my - 1, 1); + if (CheckBlock(px, py, mx + 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my, 1); + if (CheckBlock(px, py, mx + 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my - 1, 1); + if (CheckBlock(px, py, mx + 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx + 1, my + 1, 1); + if (CheckBlock(px, py, mx - 1, my ) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my, 1); + if (CheckBlock(px, py, mx - 1, my + 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my + 1, 1); + if (CheckBlock(px, py, mx - 1, my - 1) == 0) CheckMissileCol(i, dam, dam, 0, mx - 1, my - 1, 1); + + //++missile[i]._mix; + //++missile[i]._miy; + //missile[i]._miyoff -= 32; + + if ((!TransList[dTransVal[mx][my]]) || + ((missile[i]._mixvel < 0) && + ((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) || + (TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) { + ++missile[i]._mix; + ++missile[i]._miy; + missile[i]._miyoff -= 32; + } + + if (((missile[i]._miyvel > 0) && + ((TransList[dTransVal[mx+1][my]] && nSolidTable[dPiece[mx+1][my]]) || + (TransList[dTransVal[mx-1][my]] && nSolidTable[dPiece[mx-1][my]])))) { + missile[i]._miyoff -= 32; + } + + if (((missile[i]._mixvel > 0) && + ((TransList[dTransVal[mx][my+1]] && nSolidTable[dPiece[mx][my+1]]) || + (TransList[dTransVal[mx][my-1]] && nSolidTable[dPiece[mx][my-1]])))) { + missile[i]._mixoff -= 32; + } + + missile[i]._mimfnum = 0; + SetMissAnim(i, MF_BIGEXP); + missile[i]._mirange = missile[i]._miAnimLen - 1; + + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8); + } + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Lightctrl(int i) +{ +#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA + int pn, dam, p, mx, my; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + dam = 0; + + p = missile[i]._misource; + if (p != -1) { + if (missile[i]._micaster == MI_ENEMYMONST) { + dam = random(79, plr[p]._pLevel) + random(79, 2) + 2; + dam = dam << HP_SHIFT; + } else { + dam = (random(80, monster[p].mMaxDamage - monster[p].mMinDamage + 1) + monster[p].mMinDamage) << 1; + } + } else { + dam = random(81, currlevel) + (currlevel << 1); + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + mx = missile[i]._mix; + my = missile[i]._miy; + + app_assert(mx < MAXDUNX); + app_assert(my < MAXDUNY); + pn = dPiece[mx][my]; + app_assert(pn <= MAXTILES); + if (missile[i]._misource == -1) { + if ((mx != missile[i]._misx) || (my != missile[i]._misy)) + if (nMissileTable[pn]) missile[i]._mirange = 0; + } else { + if (nMissileTable[pn]) missile[i]._mirange = 0; + } + + if ((!nMissileTable[pn]) && ((mx != missile[i]._miVar1) || (my != missile[i]._miVar2)) && + (mx > 0) && (my > 0) && (mx < DMAXX) && (my < DMAXY)) { + // Add LIGHTNING if the player or trap threw this, otherwise add THINLIGHT for thin demon + if (missile[i]._misource != -1) { + if (missile[i]._micaster == MI_ENEMYPLR && EquivMonst(monster[missile[i]._misource].MType->mtype, MT_STORM)) + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_THINLIGHT, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl); + else + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl); + } else { + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, dam, missile[i]._mispllvl); + } + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + } + + if ((missile[i]._mirange == 0) || (mx <= 0) || (my <= 0) || (mx >= DMAXX) || (my > DMAXY)) + missile[i]._miDelFlag = TRUE; +#endif +} + +void MI_LTArrow(int i) +{ +#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA + int pn, mx, my; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + mx = missile[i]._mix; + my = missile[i]._miy; + + app_assert(mx < MAXDUNX); + app_assert(my < MAXDUNY); + pn = dPiece[mx][my]; + app_assert(pn <= MAXTILES); + if (missile[i]._misource == -1) { + if ((mx != missile[i]._misx) || (my != missile[i]._misy)) + if (nMissileTable[pn]) missile[i]._mirange = 0; + } else { + if (nMissileTable[pn]) missile[i]._mirange = 0; + } + + if ((!nMissileTable[pn]) && ((mx != missile[i]._miVar1) || (my != missile[i]._miVar2)) && + (mx > 0) && (my > 0) && (mx < DMAXX) && (my < DMAXY)) { + // Add LIGHTNING if the player or trap threw this, otherwise add THINLIGHT for thin demon + if (missile[i]._misource != -1) { + if (missile[i]._micaster == MI_ENEMYPLR && EquivMonst(monster[missile[i]._misource].MType->mtype, MT_STORM)) + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_THINLIGHT, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + else + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + } else { + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_LIGHTNING, missile[i]._micaster, missile[i]._misource, missile[i]._midam, missile[i]._mispllvl); + } + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + } + + if ((missile[i]._mirange == 0) || (mx <= 0) || (my <= 0) || (mx >= DMAXX) || (my > DMAXY)) + missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Lightning(int i) +{ +#if (PRE_BETA && PRE_LIGHTNING) || !PRE_BETA + int j; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + + j = missile[i]._mirange; + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Town(int i) +{ +#if (PRE_BETA && PRE_TOWN) || !PRE_BETA + int p; + + int ExpLight[17] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15}; + + app_assert(i < MAXMISSILES); + if (missile[i]._mirange > 1) --missile[i]._mirange; + + if (missile[i]._mirange == missile[i]._miVar1) { + SetMissDir(i, 1); + } + + if ((currlevel != 0) && (missile[i]._mimfnum != 1) && (missile[i]._mirange != 0)) { + if (missile[i]._miVar2 == 0) + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ++missile[i]._miVar2; + } + + for (p = 0; p < MAX_PLRS; ++p) { + if (! plr[p].plractive) continue; + if (currlevel != plr[p].plrlevel) continue; + if (plr[p]._pLvlChanging) continue; + if (plr[p]._pmode != PM_STAND) continue; + if (plr[p]._px != missile[i]._mix) continue; + if (plr[p]._py != missile[i]._miy) continue; + + ClrPlrPath(p); + if (p == myplr) { + NetSendCmdParam1(TRUE,CMD_WARP,missile[i]._misource); + plr[p]._pmode = PM_NEWLVL; + } + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Flash(int i) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + app_assert(i < MAXMISSILES); + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[missile[i]._misource]._pInvincible = TRUE; + --missile[i]._mirange; + + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy+1, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy+1, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy+1, 1); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[(missile[i]._misource)]._pInvincible = FALSE; + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Aura(int i) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + app_assert(i < MAXMISSILES); + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) { + missile[i]._mix = plr[missile[i]._misource]._pfutx; + missile[i]._miy = plr[missile[i]._misource]._pfuty; + } + --missile[i]._mirange; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[(missile[i]._misource)]._pBaseToBlk -= 50; + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Aura2(int i) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + app_assert(i < MAXMISSILES); + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) { + missile[i]._mix = plr[missile[i]._misource]._pfutx; + missile[i]._miy = plr[missile[i]._misource]._pfuty; + } + --missile[i]._mirange; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Flash2(int i) +{ +#if (PRE_BETA && PRE_FLASH) || !PRE_BETA + app_assert(i < MAXMISSILES); + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[(missile[i]._misource)]._pInvincible = TRUE; + --missile[i]._mirange; + + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix-1, missile[i]._miy-1, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy-1, 1); + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix+1, missile[i]._miy-1, 1); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + if ((missile[i]._micaster == MI_ENEMYMONST) && (missile[i]._misource != -1)) + plr[(missile[i]._misource)]._pInvincible = FALSE; + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Manashield(int i) +{ +#if (PRE_BETA && PRE_MANASHLD) || !PRE_BETA + int j, id; + long diff, pct; + + //--missile[i]._mirange; + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + + missile[i]._mix = plr[id]._px; + missile[i]._miy = plr[id]._py; + missile[i]._mitxoff = plr[id]._pxoff << 16; + missile[i]._mityoff = plr[id]._pyoff << 16; + + if (plr[id]._pmode == PM_WALK3) { + missile[i]._misx = plr[id]._pfutx; + missile[i]._misy = plr[id]._pfuty; + } else { + missile[i]._misx = plr[id]._px; + missile[i]._misy = plr[id]._py; + } + + GetMissilePos(i); + + if (plr[id]._pmode == PM_WALK3) { + if (plr[id]._pdir == DIR_L) ++missile[i]._mix; + else ++missile[i]._miy; + } + + if (id != myplr) { + if (currlevel != plr[id].plrlevel) missile[i]._miDelFlag = TRUE; + PutMissile(i); + return; + } + + if (plr[id]._pMana <= 0 || (!plr[id].plractive)) missile[i]._mirange = 0; + + if (plr[id]._pHitPoints < missile[i]._miVar1) { + diff = missile[i]._miVar1 - plr[id]._pHitPoints; + pct = 0; + for (j = 0; j < missile[i]._mispllvl && j < 7; ++j) pct += 3; + if (pct > 0) diff = diff - (diff / pct); + if (diff < 0) diff = 0; + drawmanaflag = TRUE; + drawhpflag = TRUE; + if (plr[id]._pMana >= diff) { + plr[id]._pHitPoints = missile[i]._miVar1; + plr[id]._pHPBase = missile[i]._miVar2; + plr[id]._pMana -= diff; + plr[id]._pManaBase -= diff; + } else { + plr[id]._pHitPoints -= (diff - plr[id]._pMana); + plr[id]._pHPBase -= (diff - plr[id]._pMana); + plr[id]._pMana = 0; + plr[id]._pManaBase = -(plr[id]._pMaxMana - plr[id]._pMaxManaBase); + missile[i]._mirange = 0; + missile[i]._miDelFlag = TRUE; + if (plr[id]._pHitPoints < 0) SetPlayerHitPoints(id, 0); + if (((plr[id]._pHitPoints >> HP_SHIFT) == 0) && (id == myplr)) + StartPlrKill(id, missile[i]._miVar8); + } + } + + missile[i]._miVar1 = plr[id]._pHitPoints; + missile[i]._miVar2 = plr[id]._pHPBase; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + NetSendCmd(TRUE, CMD_ENDSHIELD); + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Ether(int i) +{ +#if (PRE_BETA && PRE_ETHER) || !PRE_BETA + int id; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + id = missile[i]._misource; + + missile[i]._mix = plr[id]._px; + missile[i]._miy = plr[id]._py; + missile[i]._mitxoff = plr[id]._pxoff << 16; + missile[i]._mityoff = plr[id]._pyoff << 16; + + if (plr[id]._pmode == PM_WALK3) { + missile[i]._misx = plr[id]._pfutx; + missile[i]._misy = plr[id]._pfuty; + } else { + missile[i]._misx = plr[id]._px; + missile[i]._misy = plr[id]._py; + } + + GetMissilePos(i); + + if (plr[id]._pmode == PM_WALK3) { + if (plr[id]._pdir == DIR_L) ++missile[i]._mix; + else ++missile[i]._miy; + } + + plr[id]._pSpellFlags |= SF_ETHER; + + if (missile[i]._mirange == 0 || plr[id]._pHitPoints <= 0) { + missile[i]._miDelFlag = TRUE; + plr[id]._pSpellFlags &= ~SF_ETHER; + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Firemove(int i) +{ + int j; + int ExpLight[14] = {2,3,4,5,5,6,7,8,9,10,11,12,12}; + + app_assert(i < MAXMISSILES); + --missile[i]._mix; + --missile[i]._miy; + missile[i]._miyoff+=32; + + ++missile[i]._miVar1; + + if (missile[i]._miVar1 == missile[i]._miAnimLen) { + SetMissDir(i, 1); + missile[i]._miAnimFrame = random(82, 11) + 1; + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + j = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + if ((missile[i]._mimfnum == 0) && (missile[i]._mirange != 0)) { + if (missile[i]._miVar2 == 0) + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ++missile[i]._miVar2; + } + else if ((missile[i]._mix != missile[i]._miVar3) || (missile[i]._miy != missile[i]._miVar4)) { + missile[i]._miVar3 = missile[i]._mix; + missile[i]._miVar4 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar3, missile[i]._miVar4, 8); + } + ++missile[i]._mix; + ++missile[i]._miy; + missile[i]._miyoff-=32; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Guardian(int i) +{ +#if (PRE_BETA && PRE_GUARDIAN) || !PRE_BETA + int j, k, sx, sy, sx1, sy1, ex; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + if (missile[i]._miVar2 > 0) --missile[i]._miVar2; + + if ((missile[i]._mirange == missile[i]._miVar1) || ((missile[i]._mimfnum == 2) && + (missile[i]._miVar2 == 0))) { + SetMissDir(i, 1); + } + + if ((missile[i]._mirange % 16) == 0) { + ex = 0; + for (k = 0; (k < 23) && (ex != -1); ++k) { + for (j = 10; (j >= 0) && (ex != -1); j-=2) { + if (vCrawlTable[k][j] == 0 && vCrawlTable[k][j + 1] == 0) break; + if ((sx1 != vCrawlTable[k][j]) || (sy1 != vCrawlTable[k][j + 1])) { + sx = missile[i]._mix + vCrawlTable[k][j]; + sy = missile[i]._miy + vCrawlTable[k][j+1]; + ex = Sentfire(i, sx, sy); + if (ex == -1) break; + + sx = missile[i]._mix - vCrawlTable[k][j]; + sy = missile[i]._miy - vCrawlTable[k][j+1]; + ex = Sentfire(i, sx, sy); + if (ex == -1) break; + + sx = missile[i]._mix + vCrawlTable[k][j]; + sy = missile[i]._miy - vCrawlTable[k][j+1]; + ex = Sentfire(i, sx, sy); + if (ex == -1) break; + + sx = missile[i]._mix - vCrawlTable[k][j]; + sy = missile[i]._miy + vCrawlTable[k][j+1]; + ex = Sentfire(i, sx, sy); + if (ex == -1) break; + + sx1 = vCrawlTable[k][j]; + sy1 = vCrawlTable[k][j + 1]; + } + } + } + } + + if (missile[i]._mirange == 14) { + SetMissDir(i, 0); + missile[i]._miAnimFrame = 15; + missile[i]._miAnimAdd = -1; + } + + missile[i]._miVar3 += missile[i]._miAnimAdd; + if (missile[i]._miVar3 > 15) { + missile[i]._miVar3 = 15; + } else { + if (missile[i]._miVar3 > 0) + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, missile[i]._miVar3); + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Chain(int i) +{ +#if (PRE_BETA && PRE_CHAIN) || !PRE_BETA + int sx, sy, id, dir; + int l, n, m, k, rad; + int tx, ty; + + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + sx = missile[i]._mix; + sy = missile[i]._miy; + + dir = GetDirection(sx, sy, missile[i]._miVar1, missile[i]._miVar2); + AddMissile(sx, sy, missile[i]._miVar1, missile[i]._miVar2, dir, MIT_LIGHTCTRL, MI_ENEMYMONST, id, 1, missile[i]._mispllvl); + + rad = 3 + missile[i]._mispllvl; + if (rad > 19) rad = 19; + for (m = 1; m < rad; ++m) { + n = CrawlNum[m]; + l = n + 1; + for (k = CrawlTable[n]; k > 0; --k) { + tx = sx + CrawlTable[l]; + ty = sy + CrawlTable[(l + 1)]; + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + if ((dMonster[tx][ty]) > 0) { + dir = GetDirection(sx, sy, tx, ty); + AddMissile(sx, sy, tx, ty, dir, MIT_LIGHTCTRL, MI_ENEMYMONST, id, 1, missile[i]._mispllvl); + } + } + l += 2; + } + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void MI_ChainOLD(int i) +{ + int dir; + + if ((missile[i]._mirange % 3) == 0) { + dir = GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar5, missile[i]._miVar6); + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._miVar5, missile[i]._miVar6, dir, MIT_CHAINBALL, MI_ENEMYMONST, missile[i]._misource, missile[i]._midam); + ++missile[i]._miVar7; + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void MI_ChainballOLD(int i) +{ + int mx, id; + int k, l, m, n, rad; + + --missile[i]._mirange; + id = missile[i]._misource; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + if ((missile[i]._miVar2 == 1) && (missile[i]._mix == missile[i]._miVar3) && (missile[i]._miy == missile[i]._miVar4)) { + missile[i]._miVar2 = 0; + missile[i]._mirange = 0; + + k = 0; + for (l = 0; l < nummissiles; ++l) { + mx = missileactive[l]; + if (missile[mx]._mitype == MIT_CHAINBALL && missile[i]._miVar1 == missile[mx]._miVar1) ++k; + if ((missile[mx]._mitype == MIT_CHAIN) && (missile[i]._miVar1 == missile[mx]._midam)) + k+=((4 + (GetSpellLevel(id, SPL_LIGHTNING) / 3)) - missile[mx]._miVar7); + } + + if (k == 1) { + rad = 6 + GetSpellLevel(id, SPL_CHAIN); + if (rad > 19) rad = 19; + for (m = 1; m < rad; ++m) { + n = CrawlNum[m]; + l = n + 1; + for (k = CrawlTable[n]; k > 0; --k) { + if (ChainBounce (i, missile[i]._mix + CrawlTable[l], missile[i]._miy + CrawlTable[(l + 1)]) > 0) { + m = rad; + break; + } + l += 2; + } + } + } + } else { + if ((missile[i]._mix != missile[i]._miVar5) || (missile[i]._miy != missile[i]._miVar6)) + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._miHitFlag == TRUE && missile[i]._mirange == 0 && missile[i]._miVar2 == 0) { + for (l = 0; l < nummissiles; ++l) { + mx = missileactive[l]; + if ((missile[mx]._mitype == MIT_CHAIN && missile[i]._miVar1 == missile[mx]._midam) || + (missile[mx]._mitype == MIT_CHAINBALL && missile[i]._miVar1 == missile[mx]._miVar1)) { + missile[mx]._miVar2 = 1; // flag hit and cont until v3, v4 + missile[mx]._miVar3 = missile[i]._mix; // x of hit + missile[mx]._miVar4 = missile[i]._miy; // y of hit + } + } + } + } + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Blood(int i) +{ + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + if (missile[i]._miAnimFrame == missile[i]._miAnimLen) { +// missile[i]._miAnimFrame = missile[i]._miAnimLen; + missile[i]._miPreFlag = TRUE; + } + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Weapexp(int i) +{ + int id, mind, maxd; + int ExpLight[10] = {9,10,11,12,11,10,8,6,4,2}; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + + id = missile[i]._misource; + if (missile[i]._miVar2 == 1) { + mind = plr[id]._pIFMinDam; + maxd = plr[id]._pIFMaxDam; + missiledata[missile[i]._mitype].mResist = MIMT_FIRE; + } else { + mind = plr[id]._pILMinDam; + maxd = plr[id]._pILMaxDam; + missiledata[missile[i]._mitype].mResist = MIMT_LGHT; + } + + CheckMissileCol(i, mind, maxd, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._miVar1 == 0) { + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]); + } else { + if (missile[i]._mirange != 0) + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]); + } + + ++missile[i]._miVar1; + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + return; + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Misexp(int i) +{ + int ExpLight[10] = {9,10,11,12,11,10,8,6,4,2}; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + return; + } + + if (missile[i]._miVar1 == 0) { + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]); + } else { + if (missile[i]._mirange != 0) + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar1)]); + } + + ++missile[i]._miVar1; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Acidsplat(int i) +{ + int monst; + int dam; + + app_assert(i < MAXMISSILES); + if (missile[i]._mirange == missile[i]._miAnimLen) { + ++missile[i]._mix; + ++missile[i]._miy; + missile[i]._miyoff-=32; + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + monst = missile[i]._misource; + dam = (monster[monst].MData->mLevel < 2) ? 1:2; + AddMissile(missile[i]._mix, missile[i]._miy, i, 0, missile[i]._mimfnum, MIT_ACIDPUD, MI_ENEMYPLR, missile[i]._misource, dam, missile[i]._mispllvl); + return; + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Teleport(int i) +{ +#if (PRE_BETA && PRE_TELE) || !PRE_BETA + int id; + + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + + //sprintf(tempstr, "X: %i Y: %i FX: %i FY: %i", plr[myplr]._px, plr[myplr]._py, plr[myplr]._pfutx, plr[myplr]._pfuty); + //AddPanelString(tempstr, TEXT_LEFT); + + --missile[i]._mirange; + if (missile[i]._mirange <= 0) { + missile[i]._miDelFlag = TRUE; + return; + } + + dPlayer[(plr[id]._px)][(plr[id]._py)] = 0; + PlrClrTrans(plr[id]._px, plr[id]._py); + plr[id]._px = missile[i]._mix; + plr[id]._py = missile[i]._miy; + plr[id]._pfutx = plr[id]._px; + plr[id]._pfuty = plr[id]._py; + plr[id]._poldx = plr[id]._px; + plr[id]._poldy = plr[id]._py; + PlrDoTrans(plr[id]._px, plr[id]._py); + missile[i]._miVar1 = 1; + dPlayer[(plr[id]._px)][(plr[id]._py)] = 1 + (char)id; + + if (leveltype != 0) { + ChangeLightXY(plr[id]._plid, plr[id]._px, plr[id]._py); + ChangeVisionXY(plr[id]._pvid, plr[id]._px, plr[id]._py); + } + + if (id == myplr) { + ViewX = plr[id]._px - ScrollInfo._sdx; + ViewY = plr[id]._py - ScrollInfo._sdy; + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +/*void MI_Doom(int i) +{ + int k, l, m, n; + int mid; + + --missile[i]._mirange; + + // check if monster moved + mid = dMonster[(missile[i]._miVar1)][(missile[i]._miVar2)]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + } + + // if he did search again + if (mid != missile[i]._miVar3) { + for (m = 0; m < 6; ++m) { + n = CrawlNum[m]; + l = n + 1; + for (k = CrawlTable[n]; k > 0; --k) { + mid = dMonster[((missile[i]._miVar1) + CrawlTable[l])][((missile[i]._miVar2) + CrawlTable[(l + 1)])]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + if (mid == missile[i]._miVar3) { + missile[i]._miVar1 += CrawlTable[l]; + missile[i]._miVar2 += CrawlTable[l + 1]; + k = -99; + m = 6; + break; + } + } + l += 2; + } + } + + // if monster killed before doom kills it + if (k != -99) { + missile[i]._miDelFlag = TRUE; + PutMissile(i); + return; + } + + // get new velocity and directions + GetMissileVel(i, missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2, 16); + SetMissDir(i, GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2)); + } + + + // move missile + if (missile[i]._mimfnum != 9) { + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + } + + // get mid for current missile pos - for checking if target monster killed + mid = dMonster[(missile[i]._mix)][(missile[i]._miy)]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + } + + // check for collision if not followed monster dont end missile + k = missile[i]._mirange; + if ((missile[i]._mix != plr[myplr]._px) || (missile[i]._miy != plr[myplr]._py)) CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + if ((missile[i]._mirange == 0) && (mid != missile[i]._miVar3) && (missile[i]._miHitFlag == TRUE)) missile[i]._mirange = k; + + // if target monster not dead halt missile in place + if ((missile[i]._mirange == 0) && (mid == missile[i]._miVar3)) { + missile[i]._mirange = k; + if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) { + if (missile[i]._mimfnum != 9) { + SetMissDir(i, 9); + } + } else { + // target is killed so re-search + for (m = 1; m < 6; ++m) { + n = CrawlNum[m]; + l = n + 1; + for (k = CrawlTable[n]; k > 0; --k) { + mid = dMonster[((missile[i]._miVar1) + CrawlTable[l])][((missile[i]._miVar2) + CrawlTable[(l + 1)])]; + if (mid != 0) { + if (mid > 0) --mid; + else mid = -(mid + 1); + if ((monster[mid]._mhitpoints >> HP_SHIFT) > 0) { + missile[i]._miVar1 += CrawlTable[l]; + missile[i]._miVar2 += CrawlTable[l + 1]; + missile[i]._miVar3 = mid; + k = -99; + m = 6; + break; + } + } + l += 2; + } + } + + // get new velocity and directions + if (k == 0) missile[i]._mirange = 0; + else { + GetMissileVel(i, missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2, 16); + SetMissDir(i, GetDirection(missile[i]._mix, missile[i]._miy, missile[i]._miVar1, missile[i]._miVar2)); + } + } + } + + // delete or place missile + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +}*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Stone (int i) +{ +#if (PRE_BETA && PRE_STONE) || !PRE_BETA + int m; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + m = missile[i]._miVar2; + + if (monster[m]._mhitpoints == 0 && missile[i]._miAnimType != MF_STONE) { + SetMissAnim(i, MF_STONE); + missile[i]._mirange = 11; + } + + + if (monster[m]._mmode != MM_STONE) missile[i]._miDelFlag = TRUE; + + else { + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + if (monster[m]._mhitpoints > 0) { +// app_assert(dMonster[monster[m]._mx][monster[m]._my] == m+1 +// || dMonster[monster[m]._mx][monster[m]._my] == -(m+1)); + monster[m]._mmode = missile[i]._miVar1; + } + else AddDead(monster[m]._mx, monster[m]._my, stonendx, monster[m]._mdir); + } + + if (missile[i]._miAnimType == MF_STONE) PutMissile(i); + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Boom(int i) +{ + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + if (missile[i]._miVar1 == 0) CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 1); + if (missile[i]._miHitFlag == TRUE) missile[i]._miVar1 = 1; + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Rhino(int i) +{ + int mix,miy; + int mix2, miy2; + int omx, omy; + int monst; + BOOL placemiss = FALSE; + + app_assert(i < MAXMISSILES); + monst = missile[i]._misource; + + app_assert(monst < MAXMONSTERS); + if (monster[monst]._mmode != MM_MISSILE) { // monster got blood-boiled or something + missile[i]._miDelFlag = TRUE; + return; + } + + GetMissilePos(i); + + omx = missile[i]._mix; + omy = missile[i]._miy; + + dMonster[omx][omy] = NULL; + + if (monster[monst]._mAi == AI_SNAKE) + { + // Snake should stop a few frames before it enters player's square + // So we run its animation a few frames ahead here and test below + // to see if the square is available + missile[i]._mitxoff += 2*missile[i]._mixvel; + missile[i]._mityoff += 2*missile[i]._miyvel; + + GetMissilePos(i); + + mix2 = missile[i]._mix; + miy2 = missile[i]._miy; + + missile[i]._mitxoff -= 1*missile[i]._mixvel; + missile[i]._mityoff -= 1*missile[i]._miyvel; + } + else + { + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + } + + GetMissilePos(i); + + mix = missile[i]._mix; + miy = missile[i]._miy; + + + if (PosOkMonst(monst, mix, miy) + && (monster[monst]._mAi != AI_SNAKE || PosOkMonst(monst, mix2, miy2))) + { + dMonster[mix][miy] = -(monst + 1); + monster[monst]._mx = monster[monst]._moldx = monster[monst]._mfutx = mix; + monster[monst]._my = monster[monst]._moldy = monster[monst]._mfuty = miy; + + if(monster[monst]._uniqtype) + ChangeLightXY(missile[i]._mlid, mix, miy); + + MoveMissilePos(i); + PutMissile(i); + } + else + { + MissToMonst(i,omx,omy); + missile[i]._miDelFlag = TRUE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Fireman(int i) +{ + int mix,miy; + int omx, omy; + int id, m; + BOOL placemiss = FALSE; + int px,py, p; + + GetMissilePos(i); + + app_assert(i < MAXMISSILES); + omx = missile[i]._mix; + omy = missile[i]._miy; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + + GetMissilePos(i); + + m = missile[i]._misource; + mix = missile[i]._mix; + miy = missile[i]._miy; + + p = monster[m]._menemy; + if ((monster[m]._mFlags & MFLAG_MID) == 0) { + px = plr[p]._px; + py = plr[p]._py; + } else { + px = monster[p]._mx; + py = monster[p]._my; + } + + if((mix != omx || miy != omy) + && + ((missile[i]._miVar1 & MIF_DIDHIT + && !DIST(omx-px, omy-py, 4)) + || missile[i]._miVar2 > 1) + && PosOkMonst(missile[i]._misource, omx, omy) + ) + { + // return to monster domain + MissToMonst(i,omx, omy); + missile[i]._miDelFlag = TRUE; + } + + else + if ((monster[m]._mFlags & MFLAG_MID) == 0) id = dPlayer[mix][miy]; + else id = dMonster[mix][miy]; + if(!PosOkMissile(mix, miy) + || (id > 0 && !(missile[i]._miVar1 & MIF_DIDHIT))) + { + // bounce away + missile[i]._mixvel = -missile[i]._mixvel; + missile[i]._miyvel = -missile[i]._miyvel; + missile[i]._mimfnum = opposite[missile[i]._mimfnum]; + missile[i]._miAnimData = monster[m].MType->Anims[MA_WALK].Cels[missile[i]._mimfnum]; + + ++missile[i]._miVar2; + + if(id > 0) + { + missile[i]._miVar1 |= MIF_DIDHIT; + } + placemiss = TRUE; + } + else + placemiss = TRUE; + + if(placemiss) + { +// ChangeLightXY(monster[m].mlid, monster[m]._mx, monster[m]._my); + + MoveMissilePos(i); + PutMissile(i); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_FirewallC(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int tx, ty, pn, id; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + id = missile[i]._misource; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + else { + // if you take this out of here the wall will go though everything (hence using the nsolidtable) + //if (missile[i]._miVar1 >= MAXDUNX || missile[i]._miVar2 >= MAXDUNY) + // app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar1,missile[i]._miVar2); + pn = dPiece[missile[i]._miVar1][missile[i]._miVar2]; + app_assert(pn <= MAXTILES); + tx = missile[i]._miVar1 + XDirAdd[missile[i]._miVar3]; + ty = missile[i]._miVar2 + YDirAdd[missile[i]._miVar3]; + if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(missile[i]._miVar1, missile[i]._miVar2, missile[i]._miVar1, missile[i]._miVar2, plr[id]._pdir, MIT_FIREWALL, MI_ENEMYMONST, id, 0, missile[i]._mispllvl); + missile[i]._miVar1 = tx; + missile[i]._miVar2 = ty; + } else missile[i]._miVar8 = 1; + + // if you take this out of here the wall will go though everything (hence using the nsolidtable) + //if (missile[i]._miVar5 >= MAXDUNX || missile[i]._miVar6 >= MAXDUNY) + // app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar5,missile[i]._miVar6); + pn = dPiece[missile[i]._miVar5][missile[i]._miVar6]; + app_assert(pn <= MAXTILES); + tx = missile[i]._miVar5 + XDirAdd[missile[i]._miVar4]; + ty = missile[i]._miVar6 + YDirAdd[missile[i]._miVar4]; + if (nMissileTable[pn] == 0 && missile[i]._miVar7 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(missile[i]._miVar5, missile[i]._miVar6, missile[i]._miVar5, missile[i]._miVar6, plr[id]._pdir, MIT_FIREWALL, MI_ENEMYMONST, id, 0, missile[i]._mispllvl); + missile[i]._miVar5 = tx; + missile[i]._miVar6 = ty; + } else missile[i]._miVar7 = 1; + } +#endif +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_FlameBox(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + app_assert(i < MAXMISSILES); + missile[i]._miDelFlag = TRUE; + int const id = missile[i]._micaster; + int const l = CrawlNum[3]; + int j = l + 1; + int const dam = ((random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : currlevel)) << 4) >> 1; + + for (int m = CrawlTable[l]; m > 0; --m, j+=2) { + int const tx = missile[i]._miVar1 + CrawlTable[j]; + int const ty = missile[i]._miVar2 + CrawlTable[j + 1]; + + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int const pn = dPiece[tx][ty]; + + if (!nSolidTable[pn] && dObject[tx][ty] == 0) + { + if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(tx, ty, tx, ty, 0, MIT_FIREWALL, MI_ENEMYMONST, id, dam, missile[i]._mispllvl); + } else missile[i]._miVar8 = 1; + + } + } + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_LightBox(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + app_assert(i < MAXMISSILES); + missile[i]._miDelFlag = TRUE; + int const id = missile[i]._micaster; + int const l = CrawlNum[3]; + int j = l + 1; + int const dam = ((random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : currlevel)) << 4) >> 1; + + for (int m = CrawlTable[l]; m > 0; --m, j+=2) { + int const tx = missile[i]._miVar1 + CrawlTable[j]; + int const ty = missile[i]._miVar2 + CrawlTable[j + 1]; + + if (tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + int const pn = dPiece[tx][ty]; + + if (!nSolidTable[pn] && dObject[tx][ty] == 0) + { + if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(tx, ty, tx, ty, 0, MIT_LIGHTWALL, MI_ENEMYMONST, id, dam, missile[i]._mispllvl); + } else missile[i]._miVar8 = 1; + + } + } + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_ShowMagicItems(int i) +{ +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + app_assert(i < MAXMISSILES); + + --missile[i]._mirange; + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + HighLightAllItems = false; + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_LightwallC(int i) +{ +// GWP 9/4/97 +// Copy of MI_FirewallC with switched to call the MIT_LIGHTWALL instead of MIT_FIREWALL +#if (PRE_BETA && PRE_WALL) || !PRE_BETA + int tx, ty, pn; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + + int const id = missile[i]._misource; + int const dam = ((random(53, 10) + random(53, 10) + 2 + ((id > 0) ? plr[id]._pLevel : 0)) << 4) >> 1; + + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + else { + // if you take this out of here the wall will go though everything (hence using the nsolidtable) + //if (missile[i]._miVar1 >= MAXDUNX || missile[i]._miVar2 >= MAXDUNY) + // app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar1,missile[i]._miVar2); + pn = dPiece[missile[i]._miVar1][missile[i]._miVar2]; + app_assert(pn <= MAXTILES); + tx = missile[i]._miVar1 + XDirAdd[missile[i]._miVar3]; + ty = missile[i]._miVar2 + YDirAdd[missile[i]._miVar3]; + if (nMissileTable[pn] == 0 && missile[i]._miVar8 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(missile[i]._miVar1, missile[i]._miVar2, missile[i]._miVar1, missile[i]._miVar2, plr[id]._pdir, MIT_LIGHTWALL, MI_ENEMYMONST, id, dam, missile[i]._mispllvl); + missile[i]._miVar1 = tx; + missile[i]._miVar2 = ty; + } else missile[i]._miVar8 = 1; + + // if you take this out of here the wall will go though everything (hence using the nsolidtable) + //if (missile[i]._miVar5 >= MAXDUNX || missile[i]._miVar6 >= MAXDUNY) + // app_fatal("Tried placing firewall piece off edge of map at (%d,%d)",missile[i]._miVar5,missile[i]._miVar6); + pn = dPiece[missile[i]._miVar5][missile[i]._miVar6]; + app_assert(pn <= MAXTILES); + tx = missile[i]._miVar5 + XDirAdd[missile[i]._miVar4]; + ty = missile[i]._miVar6 + YDirAdd[missile[i]._miVar4]; + if (nMissileTable[pn] == 0 && missile[i]._miVar7 == 0 && tx > 0 && tx < MAXDUNX && ty > 0 && ty < MAXDUNY) { + AddMissile(missile[i]._miVar5, missile[i]._miVar6, missile[i]._miVar5, missile[i]._miVar6, plr[id]._pdir, MIT_LIGHTWALL, MI_ENEMYMONST, id, dam, missile[i]._mispllvl); + missile[i]._miVar5 = tx; + missile[i]._miVar6 = ty; + } else missile[i]._miVar7 = 1; + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Infra(int i) +{ +#if (PRE_BETA && PRE_INFRA) || !PRE_BETA + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + plr[(missile[i]._misource)]._pInfraFlag = TRUE; + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + CalcPlrItemVals(missile[i]._misource,TRUE); + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Apoca(int i) +{ +#if (PRE_BETA && PRE_APOCA) || !PRE_BETA + int j, k, id; + BOOL exit; + + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + + exit = FALSE; + for (j = missile[i]._miVar2; (j < missile[i]._miVar3) && (exit == FALSE); ++j) { + for (k = missile[i]._miVar4; (k < missile[i]._miVar5) && (exit == FALSE); ++k) { + if (dMonster[k][j] > 3 && nSolidTable[(dPiece[k][j])] == 0) { + AddMissile(k, j, k, j, plr[id]._pdir, MIT_BOOM, MI_ENEMYMONST, id, missile[i]._midam, 0); + exit = TRUE; + } + } + if (exit == FALSE) missile[i]._miVar4 = missile[i]._miVar6; + } + + if (exit == TRUE) { + missile[i]._miVar2 = j - 1; + missile[i]._miVar4 = k; + } else missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Wave(int i) +{ +#if (PRE_BETA && PRE_WAVE) || !PRE_BETA + int dira, dirb, nxa, nya, nxb, nyb; + int pn, sd, j, f1, f2, id, sx, sy, dx, dy; + + f1 = 0; + f2 = 0; + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + + sd = GetDirection(sx, sy, dx, dy); + dira = (sd - 2) & 0x0007; + dirb = (sd + 2) & 0x0007; + nxa = sx + XDirAdd[sd]; + nya = sy + YDirAdd[sd]; + + //if (nxa >= MAXDUNX || nya >= MAXDUNY) + // app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxa,nya); + pn = dPiece[nxa][nya]; + app_assert(pn <= MAXTILES); + if (nMissileTable[pn] == 0) { + AddMissile(nxa, nya, nxa + XDirAdd[sd], nya + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl); + + nxa += XDirAdd[dira]; + nya += YDirAdd[dira]; + nxb = sx + XDirAdd[sd] + XDirAdd[dirb]; + nyb = sy + YDirAdd[sd] + YDirAdd[dirb]; + for (j = 0; j < (2 + (missile[i]._mispllvl>>1)); ++j) { + //if (nxa >= MAXDUNX || nya >= MAXDUNY) + // app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxa,nya); + pn = dPiece[nxa][nya]; + app_assert(pn <= MAXTILES); + if (nMissileTable[pn] == 0 && f1 == 0 && nxa > 0 && nxa < MAXDUNX && nya > 0 && nya < MAXDUNY) { + AddMissile(nxa, nya, nxa + XDirAdd[sd], nya + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl); + nxa += XDirAdd[dira]; + nya += YDirAdd[dira]; + } else f1 = 1; + + //if (nxb >= MAXDUNX || nyb >= MAXDUNY) + // app_fatal("Tried placing flamewave piece off edge of map at (%d,%d)",nxb,nyb); + pn = dPiece[nxb][nyb]; + app_assert(pn <= MAXTILES); + if (nMissileTable[pn] == 0 && f2 == 0 && nxb > 0 && nxb < MAXDUNX && nyb > 0 && nyb < MAXDUNY) { + AddMissile(nxb, nyb, nxb + XDirAdd[sd], nyb + YDirAdd[sd], plr[id]._pdir, MIT_FIREMOVE, MI_ENEMYMONST, id, 0, missile[i]._mispllvl); + nxb += XDirAdd[dirb]; + nyb += YDirAdd[dirb]; + } else f2 = 1; + } + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#define RAD 6 + +void MI_Nova(int i) +{ +#if (PRE_BETA && PRE_NOVA) || !PRE_BETA + int k, id, sx, sy, dir, en; + int sx1, sy1, dam, dx, dy; + + sx1 = sy1 = 0; + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + dam = missile[i]._midam; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + if (id != -1) { + dir = plr[id]._pdir; + en = MI_ENEMYMONST; + } else { + dir = 0; + en = MI_ENEMYPLR; + } + + for (k = 0; k < 23; ++k) { + if ((sx1 != vCrawlTable[k][RAD]) || (sy1 != vCrawlTable[k][RAD + 1])) { + dx = sx + vCrawlTable[k][RAD]; + dy = sy + vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl); + + dx = sx - vCrawlTable[k][RAD]; + dy = sy - vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl); + + dx = sx - vCrawlTable[k][RAD]; + dy = sy + vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl); + + dx = sx + vCrawlTable[k][RAD]; + dy = sy - vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_LIGHTBALL, en, id, dam, missile[i]._mispllvl); + + sx1 = vCrawlTable[k][RAD]; + sy1 = vCrawlTable[k][RAD + 1]; + } + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MI_FireNova(int i) +{ +#if (PRE_BETA && PRE_NOVA) || !PRE_BETA + int k, id, sx, sy, dir, en; + int sx1, sy1, dam, dx, dy; + + sx1 = sy1 = 0; + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + dam = missile[i]._midam; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + if (id != -1) { + dir = plr[id]._pdir; + en = MI_ENEMYMONST; + } else { + dir = 0; + en = MI_ENEMYPLR; + } + + for (k = 0; k < 23; ++k) { + if ((sx1 != vCrawlTable[k][RAD]) || (sy1 != vCrawlTable[k][RAD + 1])) { + dx = sx + vCrawlTable[k][RAD]; + dy = sy + vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl); + + dx = sx - vCrawlTable[k][RAD]; + dy = sy - vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl); + + dx = sx - vCrawlTable[k][RAD]; + dy = sy + vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl); + + dx = sx + vCrawlTable[k][RAD]; + dy = sy - vCrawlTable[k][RAD + 1]; + AddMissile(sx, sy, dx, dy, dir, MIT_FBARROW, en, id, dam, missile[i]._mispllvl); + + sx1 = vCrawlTable[k][RAD]; + sy1 = vCrawlTable[k][RAD + 1]; + } + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif +} + +void MI_SpecialArrow(int i) +{ +#if (PRE_BETA && PRE_FIREBALL) || !PRE_BETA + int id, sx, sy, dir, en; + int sx1, sy1, dam, dx, dy; + + sx1 = sy1 = 0; + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + dam = missile[i]._midam; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + int extraspeed = missile[i]._miVar3; + + int mitype = MIT_ARROW; + if (id != -1) { + dir = plr[id]._pdir; + en = MI_ENEMYMONST; + switch(plr[id]._pILMinDam) + { + case 0: mitype = MIT_FBARROW; break; + case 1: mitype = MIT_LTARROW; break; + case 2: mitype = MIT_CBARROW; break; + case 3: mitype = MIT_HBARROW; break; + default: break; + } + } else { + dir = 0; + en = MI_ENEMYPLR; + } + + AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed); + if (mitype == MIT_CBARROW) + { + AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed); + AddMissile(sx, sy, dx, dy, dir, mitype, en, id, dam, extraspeed); + } + + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Boil(int i) +{ + app_assert(i < MAXMISSILES); + missile[i]._miDelFlag = TRUE; + return; + +/*#if (PRE_BETA && PRE_BLOODB) || !PRE_BETA + int j, mid, id, dx, dy, pct; + long dm; + + BOOL M_Talker (int); + + id = missile[i]._misource; + dx = missile[i]._miVar1; + dy = missile[i]._miVar2; + mid = dMonster[dx][dy]; + + if (mid > 0) --mid; + else mid = -(mid + 1); + if (mid > 0) { + if ((M_Talker(mid) && monster[mid].mtalkmsg != 0) || ((plr[id]._pLevel - 6 + missile[i]._mispllvl) <= monster[mid].mLevel)) { + missile[i]._miDelFlag = TRUE; + return; + } + + if (monster[mid].mMagicRes & M_IM) return; + + dm = monster[mid]._mhitpoints; + monster[mid]._mhitpoints = 0; + M_StartKill(mid, id); + AddPlrExperience(id, monster[mid].mLevel, monster[mid].mExp); + dMonster[monster[mid]._mx][monster[mid]._my] = 0; + monster[mid]._mDelFlag = TRUE; + AddMissile(monster[mid]._mx, monster[mid]._my, monster[mid]._mx, monster[mid]._my, plr[id]._pdir, MIT_SPURT, MI_ENEMYMONST, id, (random(87, 2) + 1), 0); + AddDead(monster[mid]._mx, monster[mid]._my, spurtndx, monster[mid]._mdir); + + pct = 0; + for (j = 0; j < missile[i]._mispllvl && j < 5; ++j) pct += 10; + //dm = (monster[mid]._mmaxhp >> 1); + if (pct > 0) dm -= (dm / pct); + plr[id]._pHitPoints -= dm; + plr[id]._pHPBase -= dm; + + if (plr[id]._pHitPoints > plr[id]._pMaxHP) { + plr[id]._pHitPoints = plr[id]._pMaxHP; + plr[id]._pHPBase = plr[id]._pMaxHPBase; + } + if (plr[id]._pHitPoints <= 0) { + // rjs - manashld fix? - plr[id]._pHitPoints = 0; + StartPlrKill(id, FALSE); + } else StartPlrHit(id, dm); + + PlaySfxLoc(LS_BLODBOIL, monster[mid]._mx, monster[mid]._my); + UseMana(id, SPL_BLOODB); + } + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; +#endif*/ +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Flame(int i) +{ +#if (PRE_BETA && PRE_FLAME) || !PRE_BETA + int k, id; + + app_assert(i < MAXMISSILES); + id = missile[i]._misource; + --missile[i]._mirange; + --missile[i]._miVar2; + + k = missile[i]._mirange; + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 1, missile[i]._mix, missile[i]._miy, 0); + if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag == TRUE)) missile[i]._mirange = k; + if (missile[i]._miVar2 == 0) missile[i]._miAnimFrame = 20; + if (missile[i]._miVar2 <= 0) { + k = missile[i]._miAnimFrame; + if (k > 11) k = 24 - k; + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, k); + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + if (missile[i]._miVar2 <= 0) PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Flamec(int i) +{ +#if (PRE_BETA && PRE_FLAME) || !PRE_BETA + int id, pn; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + id = missile[i]._misource; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + app_assert(missile[i]._mix < MAXDUNX); + app_assert(missile[i]._miy < MAXDUNY); + pn = dPiece[missile[i]._mix][missile[i]._miy]; + app_assert(pn <= MAXTILES); + if (nMissileTable[pn] == 0) + AddMissile(missile[i]._mix, missile[i]._miy, missile[i]._misx, missile[i]._misy, i, MIT_FLAME, missile[i]._micaster, id, missile[i]._miVar3, missile[i]._mispllvl); + else + missile[i]._mirange = 0; + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ++missile[i]._miVar3; + } + + if (missile[i]._mirange == 0 || missile[i]._miVar3 == 3) missile[i]._miDelFlag = TRUE; +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Cbolt(int i) +{ +#if (PRE_BETA && PRE_CBOLT) || !PRE_BETA + int bpath[16] = { -1, 0, 1, -1, 0, 1, -1, -1, 0, 0, 1, 1, 0, 1, -1, 0 }; + int sx, sy, dx, dy, md; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + if (missile[i]._miAnimType != MF_LIGHTNING) { + if (missile[i]._miVar3 == 0) { + md = (missile[i]._miVar2 + bpath[missile[i]._mirnd]) & 0x07; + missile[i]._mirnd = (missile[i]._mirnd + 1) & 0x0f; + sx = missile[i]._mix; + sy = missile[i]._miy; + dx = sx + XDirAdd[md]; + dy = sy + YDirAdd[md]; + GetMissileVel(i, sx, sy, dx, dy, 8); + missile[i]._miVar3 = 16; + } else --missile[i]._miVar3; + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + + CheckMissileCol(i, missile[i]._midam, missile[i]._midam, 0, missile[i]._mix, missile[i]._miy, 0); + if (missile[i]._miHitFlag == TRUE) { + missile[i]._miVar1 = 8; + missile[i]._mimfnum = 0; + missile[i]._mixoff = 0; + missile[i]._miyoff = 0; + SetMissAnim(i, MF_LIGHTNING); + missile[i]._mirange = missile[i]._miAnimLen; + GetMissilePos(i); + } + + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, missile[i]._miVar1); + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Hbolt(int i) +{ +#if (PRE_BETA && PRE_HBOLT) || !PRE_BETA + int dam; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + if (missile[i]._miAnimType != MF_HEXPL) { + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + + GetMissilePos(i); + + dam = missile[i]._midam; + if ((missile[i]._mix != missile[i]._misx) || (missile[i]._miy != missile[i]._misy)) + CheckMissileCol(i, dam, dam, 0, missile[i]._mix, missile[i]._miy, 0); + + if (missile[i]._mirange == 0) { + missile[i]._mitxoff -= missile[i]._mixvel; + missile[i]._mityoff -= missile[i]._miyvel; + GetMissilePos(i); + missile[i]._mimfnum = 0; + SetMissAnim(i, MF_HEXPL); + missile[i]._mirange = missile[i]._miAnimLen - 1; + } else { + if ((missile[i]._mix != missile[i]._miVar1) || (missile[i]._miy != missile[i]._miVar2)) { + missile[i]._miVar1 = missile[i]._mix; + missile[i]._miVar2 = missile[i]._miy; + ChangeLight(missile[i]._mlid, missile[i]._miVar1, missile[i]._miVar2, 8); + } + } + } else { + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, 7 + missile[i]._miAnimFrame); + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + } + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Element(int i) +{ +#if (PRE_BETA && PRE_ELEMENT) || !PRE_BETA + int j, mid, sd, dam; + int cx, cy, px, py, id; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + dam = missile[i]._midam; + id = missile[i]._misource; + + if (missile[i]._miAnimType == MF_BIGEXP) { + cx = missile[i]._mix; + cy = missile[i]._miy; + px = plr[id]._px; + py = plr[id]._py; + ChangeLight(missile[i]._mlid, cx, cy, missile[i]._miAnimFrame); + + if (CheckBlock(px, py, cx , cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy, 1); + if (CheckBlock(px, py, cx , cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy + 1, 1); + if (CheckBlock(px, py, cx , cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx, cy - 1, 1); + if (CheckBlock(px, py, cx + 1, cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy, 1); + if (CheckBlock(px, py, cx + 1, cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy - 1, 1); + if (CheckBlock(px, py, cx + 1, cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx + 1, cy + 1, 1); + if (CheckBlock(px, py, cx - 1, cy ) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy, 1); + if (CheckBlock(px, py, cx - 1, cy + 1) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy + 1, 1); + if (CheckBlock(px, py, cx - 1, cy - 1) == 0) CheckMissileCol(i, dam, dam, 1, cx - 1, cy - 1, 1); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); + return; + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + cx = missile[i]._mix; + cy = missile[i]._miy; + + j = missile[i]._mirange; + CheckMissileCol(i, dam, dam, 0, cx, cy, 0); + + if (missile[i]._miVar3 == 0) { + //if (missile[i]._mirange == 0 && missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + //if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag != TRUE)) missile[i]._miVar3 = 1; + if ((cx == missile[i]._miVar4) && (cy == missile[i]._miVar5)) missile[i]._miVar3 = 1; + } + + if (missile[i]._miVar3 == 1) { + missile[i]._miVar3 = 2; + missile[i]._mirange = 255; + mid = FindClosest(cx, cy, 19); + if (mid > 0) { + sd = GetDirection8(cx, cy, monster[mid]._mx, monster[mid]._my); + SetMissDir(i, sd); + GetMissileVel(i, cx, cy, monster[mid]._mx, monster[mid]._my, 16); + } else { + sd = plr[id]._pdir; + SetMissDir(i, sd); + GetMissileVel(i, cx, cy, cx + XDirAdd[sd], cy + YDirAdd[sd], 16); + } + } + + if ((cx != missile[i]._miVar1) || (cy != missile[i]._miVar2)) { + missile[i]._miVar1 = cx; + missile[i]._miVar2 = cy; + ChangeLight(missile[i]._mlid, cx, cy, 8); + } + + if (missile[i]._mirange == 0) { + missile[i]._mimfnum = 0; + SetMissAnim(i, MF_BIGEXP); + missile[i]._mirange = missile[i]._miAnimLen - 1; + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Bonespirit(int i) +{ +#if (PRE_BETA && PRE_BONESPIRIT) || !PRE_BETA + int j, mid, sd, dam; + int cx, cy, id; + + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + dam = missile[i]._midam; + id = missile[i]._misource; + + if (missile[i]._mimfnum == 8) { + cx = missile[i]._mix; + cy = missile[i]._miy; + //px = plr[id]._px; + //py = plr[id]._py; + ChangeLight(missile[i]._mlid, cx, cy, missile[i]._miAnimFrame); + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); + return; + } + + missile[i]._mitxoff += missile[i]._mixvel; + missile[i]._mityoff += missile[i]._miyvel; + GetMissilePos(i); + cx = missile[i]._mix; + cy = missile[i]._miy; + + j = missile[i]._mirange; + CheckMissileCol(i, dam, dam, 0, cx, cy, 0); + + if (missile[i]._miVar3 == 0) { + //if (missile[i]._mirange == 0 && missile[i]._miHitFlag == TRUE) missile[i]._mirange = j; + //if ((missile[i]._mirange == 0) && (missile[i]._miHitFlag != TRUE)) missile[i]._miVar3 = 1; + if ((cx == missile[i]._miVar4) && (cy == missile[i]._miVar5)) missile[i]._miVar3 = 1; + } + + if (missile[i]._miVar3 == 1) { + missile[i]._miVar3 = 2; + missile[i]._mirange = 255; + mid = FindClosest(cx, cy, 19); + if (mid > 0) { + missile[i]._midam = (monster[mid]._mhitpoints >> HP_SHIFT) >> 1; + sd = GetDirection8(cx, cy, monster[mid]._mx, monster[mid]._my); + SetMissDir(i, sd); + GetMissileVel(i, cx, cy, monster[mid]._mx, monster[mid]._my, 16); + } else { + sd = plr[id]._pdir; + SetMissDir(i, sd); + GetMissileVel(i, cx, cy, cx + XDirAdd[sd], cy + YDirAdd[sd], 16); + } + } + + if ((cx != missile[i]._miVar1) || (cy != missile[i]._miVar2)) { + missile[i]._miVar1 = cx; + missile[i]._miVar2 = cy; + ChangeLight(missile[i]._mlid, cx, cy, 8); + } + + if (missile[i]._mirange == 0) { + SetMissDir(i, 8); + missile[i]._mirange = 7; + } + + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_ResurrectBeam(int i) +{ +#if (PRE_BETA && PRE_RESURRECT) || !PRE_BETA + app_assert(i < MAXMISSILES); + --missile[i]._mirange; + if (missile[i]._mirange == 0) missile[i]._miDelFlag = TRUE; + PutMissile(i); +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MI_Rportal(int i) +{ + int ExpLight[17] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15}; + + app_assert(i < MAXMISSILES); + if (missile[i]._mirange > 1) --missile[i]._mirange; + + if (missile[i]._mirange == missile[i]._miVar1) { + SetMissDir(i, 1); + } + + if ((currlevel != 0) && (missile[i]._mimfnum != 1) && (missile[i]._mirange != 0)) { + if (missile[i]._miVar2 == 0) + missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ChangeLight(missile[i]._mlid, missile[i]._mix, missile[i]._miy, ExpLight[(missile[i]._miVar2)]); + ++missile[i]._miVar2; + } + + if (missile[i]._mirange == 0) { + missile[i]._miDelFlag = TRUE; + AddUnLight(missile[i]._mlid); + } + + PutMissile(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ProcessMissiles () +{ + int i, mi; + + + for (i = 0; i < nummissiles; ++i) { + mi = missileactive[i]; + dFlags[missile[mi]._mix][missile[mi]._miy] &= BFMASK_MISSILE; + dMissile[missile[mi]._mix][missile[mi]._miy] = 0; + } + + i = 0; + while (i < nummissiles) { + mi = missileactive[i]; + if (missile[mi]._miDelFlag) { + DeleteMissile(mi, i); + i = 0; + } else ++i; + } + + MissilePreFlag = FALSE; + ManashieldFlag = 0; + for (i = 0; i < nummissiles; ++i) { + mi = missileactive[i]; + + missiledata[missile[mi]._mitype].mProc(mi); + + if(!(missile[mi]._miAnimFlags & MFF_STATIC)) + { + ++missile[mi]._miAnimCnt; + if (missile[mi]._miAnimCnt >= missile[mi]._miAnimDelay) { + missile[mi]._miAnimCnt = 0; + missile[mi]._miAnimFrame += missile[mi]._miAnimAdd; + if (missile[mi]._miAnimFrame > missile[mi]._miAnimLen) missile[mi]._miAnimFrame = 1; + if (missile[mi]._miAnimFrame < 1) missile[mi]._miAnimFrame = missile[mi]._miAnimLen; + } + } + } + + if (ManashieldFlag) { + for (i = 0; i < nummissiles; ++i) { + mi = missileactive[i]; + if (missile[mi]._mitype == MIT_MANASHIELD) MI_Manashield(mi); + } + } + + i = 0; + while (i < nummissiles) { + mi = missileactive[i]; + if (missile[mi]._miDelFlag) { + DeleteMissile(mi, i); + i = 0; + } else ++i; + } +} + +void SyncMissAnim() +{ + int i,mi; + + for (i = 0; i < nummissiles; ++i) + { + app_assert(i < MAXMISSILES); + mi = missileactive[i]; + + app_assert(mi < MAXMISSILES); + MissileStruct *Miss = &missile[mi]; + + Miss->_miAnimData = misfiledata[Miss->_miAnimType].mAnimData[Miss->_mimfnum]; + + if (Miss->_mitype == MIT_RHINO) + { + AnimStruct *anim; + + if (EquivMonst(monster[Miss->_misource].MType->mtype, MT_HORNED)) + anim = &monster[Miss->_misource].MType->Anims[MA_SPECIAL]; + else if (EquivMonst(monster[Miss->_misource].MType->mtype, MT_NSNAKE)) + anim = &monster[Miss->_misource].MType->Anims[MA_ATTACK]; + else + anim = &monster[Miss->_misource].MType->Anims[MA_WALK]; + + missile[mi]._miAnimData = anim->Cels[Miss->_mimfnum]; + } + // need similar section for Fireman + } +} + +/*-----------------------------------------------------------------------* +** Used when we need to "emergency" delete missiles +**-----------------------------------------------------------------------*/ +void ClearMissileSpot(int mi) +{ + app_assert(mi < MAXMISSILES); + dFlags[missile[mi]._mix][missile[mi]._miy] &= BFMASK_MISSILE; + dMissile[missile[mi]._mix][missile[mi]._miy] = 0; +} diff --git a/src/MONO.CPP b/src/MONO.CPP new file mode 100644 index 0000000..d3d19b4 --- /dev/null +++ b/src/MONO.CPP @@ -0,0 +1,93 @@ +#include "mono.h" + + +// Allocate space for the MonoDriver data. +// and Call the constructor for one MonoDevice data object. +MonoDevice::DeviceData MonoDevice::MDA; + +MonoDevice::DeviceData::DeviceData() : + fhDevice (CreateFile("\\\\.\\DARKMONO.VXD", 0, 0, NULL, NULL, + FILE_FLAG_DELETE_ON_CLOSE, NULL)), + fEnabled((fhDevice != INVALID_HANDLE_VALUE)), + fNextRow(0), + fNextCol(0) +{ + ClearScreen(); +} + +MonoDevice::DeviceData::~DeviceData() +{ + if( Status() ) + { + CloseHandle(fhDevice); + fEnabled = false; + fhDevice = INVALID_HANDLE_VALUE; + fNextRow = 0; + fNextCol = 0; + } +} + +int MonoDevice::PutString( int row, int col, char const * string ) +{ + int Result = 0; + if( Status() && row < HEIGHT && col < WIDTH) + { + short buff[3 + 41]; // allow WIDTH character string + int len = strlen( string ); + Result = len; + int bufferLen = 0; + + for (;len > 0; len -= WIDTH, ++row, col=0, string += bufferLen ) + { + bufferLen = ((len + col) > WIDTH)? WIDTH - (len + col) : len; + if (row >= HEIGHT) + row = 0; + buff[0] = static_cast(row); + buff[1] = static_cast(col); + buff[2] = static_cast(bufferLen); + if( buff[2] > (WIDTH - col) ) + { + buff[2] = (WIDTH - col); + strncpy( reinterpret_cast(buff + 3), string, buff[2] ); + } + else + strcpy( reinterpret_cast(buff + 3), string ); + + DeviceIoControl(MDA.fhDevice, PUT_STRING, + &(buff[0]), sizeof( buff ), NULL, 0, NULL, NULL); + } + + } + return Result; +} + +void __cdecl MonoDevice::Printf( int row, int col, char const * const format, ... ) +{ + if( Status() ) + { + char strbuf [ 256 ]; + va_list argptr; + + va_start(argptr,format); + vsprintf(strbuf,format,argptr); + va_end(argptr); + + PutString( row, col, strbuf ); + } +} + +void __cdecl MonoDevice::Printf( char const * const format, ... ) +{ + if( Status() ) + { + char strbuf [ 256 ]; + va_list argptr; + + va_start(argptr,format); + vsprintf(strbuf,format,argptr); + va_end(argptr); + + PutString( strbuf ); + } +} + diff --git a/src/MONO.H b/src/MONO.H new file mode 100644 index 0000000..1dbaa17 --- /dev/null +++ b/src/MONO.H @@ -0,0 +1,223 @@ + +/* ======================================================================== + Copyright (c) 1990,1997 Synergistic Software + All Rights Reserved + Author: + ======================================================================== */ + + +#ifndef _MONO_H_ +#define _MONO_H_ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +//#ifdef __BORLANDC__ +//#pragma option -a4 +//#endif +//#ifdef _MSC_VER +//#pragma pack(push,4) +//#endif + +// Define __cdecl for non Microsoft compilers. +#if (!defined(_MSC_VER) && !defined(__cdecl) ) +#define __cdecl +#endif + +// This class is to help put text strings out to a monochrome monitor under +// Windows95. +// It requires the DARKMONO.VXD driver to be installed to work. +// It does do line wrapping. +// There is no stored buffer of the text, so no scrolling. + +class MonoDevice +{ +private: + // Helper class to do auto initialization and to keep from opening the + // driver more than once. + class DeviceData { + private: + friend class MonoDevice; + explicit DeviceData(); + inline bool Status() const; + + + HANDLE fhDevice; + bool fEnabled; + int fNextRow; + int fNextCol; + + protected: + public: + ~DeviceData(); + }; + + enum MonoDimisions + { + WIDTH = 80, + HEIGHT = 24 + }; + + enum MonoFunctions + { + MONO_VERSION = 1, + CURSOR_ON = 2, + CURSOR_OFF = 3, + SET_ATTRIBUTE = 4, + CLEAR_SCREEN = 5, + PUT_CHAR = 6, + PUT_STRING = 7 + }; + + // Can't create or distroy one of these. + MonoDevice(); + ~MonoDevice(); + + // Can only have one Monochrome display. + static DeviceData MDA; +public: + typedef enum Attrib + { + ERASE =0x00,NORM =0x07, NORM_BLNK =0x87, + INVRS =0x70,UNDRLN =0x01, UNDRLN_BLNK =0x81, + INVRS_BLNK=0xF0,HI =0x0F, HI_BLNK =0x8F, + HI_UNDRLN=0x09, HI_UNDRLN_BLNK=0x89 + }; + + + static inline bool Status() { return MDA.Status(); } + static inline bool IsEnabled(); + static inline void Enable(); + static inline void Disable(); + static inline void SetAttribute( Attrib attribute ); + static inline void CursorOn(); + static inline void CursorOff(); + static inline void ClearScreen( char fill = ERASE); + static inline bool PutChar( int row, int col, char value ); + static inline bool PutChar( char value ); + static int PutString( int row, int col, char const * const string ); + static inline int PutString( char const * const string ); + static void __cdecl Printf( int row, int col, char const * const format, ... ); + static void __cdecl Printf(char const * const format, ... ); +}; + +inline bool MonoDevice::DeviceData::Status() const +{ + return fhDevice != INVALID_HANDLE_VALUE && fEnabled; +} + +inline bool MonoDevice::IsEnabled() +{ + return MDA.fEnabled; +} + +inline void MonoDevice::Enable() +{ + MDA.fEnabled = true; +} + +inline void MonoDevice::Disable() +{ + MDA.fEnabled = false; +} + +inline void MonoDevice::SetAttribute( Attrib attribute ) +{ + if( Status() ) + { + unsigned char attr = static_cast(attribute); + DeviceIoControl(MDA.fhDevice, SET_ATTRIBUTE, + &attr, sizeof( attr ), + NULL, 0, NULL, NULL); + } +} + +inline void MonoDevice::CursorOn() +{ + if( Status() ) + DeviceIoControl(MDA.fhDevice, CURSOR_ON, + NULL, 0, NULL, 0, NULL, NULL); +} + +inline void MonoDevice::CursorOff() +{ + if( Status() ) + DeviceIoControl(MDA.fhDevice, CURSOR_OFF, + NULL, 0, NULL, 0, NULL, NULL); +} + +inline void MonoDevice::ClearScreen( char fill ) +{ + if( Status() ) + { + DeviceIoControl(MDA.fhDevice, CLEAR_SCREEN, + &fill, sizeof( fill ), NULL, 0, NULL, NULL); + MDA.fNextRow = 0; + MDA.fNextCol = 0; + } +} + +inline bool MonoDevice::PutChar( int row, int col, char value ) +{ + bool Result = false; + + if( Status() && row < HEIGHT && col < WIDTH) + { + short buff[3]; + buff[0] = static_cast(row); + buff[1] = static_cast(col); + buff[2] = value; // high byte doesn't matter + DeviceIoControl(MDA.fhDevice, PUT_CHAR, + &(buff[0]), sizeof( buff ), NULL, 0, NULL, NULL); + Result = true; + } + return Result; +} + +inline bool MonoDevice::PutChar( char value ) +{ + bool const Result = PutChar (MDA.fNextCol, MDA.fNextRow, value); + if (Result) + { + ++MDA.fNextCol; + if (MDA.fNextCol > WIDTH) + { + MDA.fNextCol = 0; + ++MDA.fNextRow; + if (MDA.fNextRow > HEIGHT) + { + MDA.fNextRow = 0; + } + } + } + return Result; +} + +inline int MonoDevice::PutString( char const * const string ) +{ + int const Result = PutString(MDA.fNextRow, MDA.fNextCol, string); + MDA.fNextCol += Result % WIDTH; + if (MDA.fNextCol > WIDTH) + { + MDA.fNextCol %= WIDTH; + ++MDA.fNextRow; + } + MDA.fNextRow += Result / WIDTH; + if (MDA.fNextRow > HEIGHT) + { + MDA.fNextRow %= HEIGHT; + } + return Result; +} + + +//#ifdef __BORLANDC__ +//#pragma option -a. +//#endif +//#ifdef _MSC_VER +//#pragma pack(pop) +//#endif + +#endif diff --git a/src/MONO_C.CPP b/src/MONO_C.CPP new file mode 100644 index 0000000..9e4ecea --- /dev/null +++ b/src/MONO_C.CPP @@ -0,0 +1,148 @@ +#ifdef _DEBUG +#include +#include +#include +#include +#include +#include + +#include "mono_c.h" + + + +//--------------------------------------------------------------------------- + + +bool mono_getExist( void ) +{ + return MonoDevice::Status() ? true : false; // Returns TRUE, if device detected +} // else returns FALSE + +int mono_getEnable( void ) +{ + return MonoDevice::IsEnabled() ? true : false; // Returns ON, if device enabled +} // else returns OFF + +void mono_setEnable( int flag ) // flag = TRUE - use mono device +{ // flag = FALSE - don't use + if( flag == TRUE ) + MonoDevice::Enable(); + else + MonoDevice::Disable(); +} + + + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +void mono_cls(void) +{ + MonoDevice::ClearScreen( ' ' ); +} + + +//--------------------------------------------------------------------------- + +void mono_putc( short x, short y, char c) +{ + MDA.PutChar( y, x, c ); +} + + +//--------------------------------------------------------------------------- + +void mono_puts( short x, short y, char const * const str ) +{ + MDA.PutString( y, x, str ); +} + + +//--------------------------------------------------------------------------- + +void __cdecl mono_printf( short x, short y, char const * const format, ... ) +{ + char strbuf [ 256 ]; + va_list argptr; + va_start(argptr,format); + vsprintf(strbuf,format,argptr); + va_end(argptr); + MDA.PutString( y, x, strbuf ); +} + + +//--------------------------------------------------------------------------- + +void mono_dump ( short port ) +{ +/* + if( MDA.IsEnabled() && MDA.Status() ) + { + char linefeed[3] = "\r\n"; + int fp; + char lptPort[] = "LPTx"; + lptPort[3] = port + '0'; //set LPT port + + short *ptr = 0;//(short *)(_x386_zero_base_ptr + MONOBASE); + short i; + short ch; + short attribute; + short col = 0; + if ((fp = open(lptPort, O_WRONLY) ) >= 0) + { + // Output screen + for (i=0; i>8; + ch = (*ptr) & 0x00ff; + (*ptr) = 0x0fdb; //display a progress character + + if (attribute == MONO_NORM) + write(fp, "(s0B", 5); //Normal on + else + write(fp, "(s7B", 5); //BOLD on + + if (!ch) + ch = ' '; // char 0 is also a space on the mono + write(fp, &ch, 1); //write the character + + if (++col == MONOWIDTH) //Next line? + { + col = 0; + write(fp,&linefeed,2); + } + (*ptr) = (attribute<<8)+ch; //remove progress character + ptr++; + } + + close(fp); + } + } +*/ +} + + +//--------------------------------------------------------------------------- + +void mono_setAttrib( MonoAttrib attrib ) +{ + MDA.SetAttribute( attrib ); +} + +MonoAttrib mono_getAttrib() +{ + return MONO_NORM; +} + +//--------------------------------------------------------------------------- + +void mono_setHardwareCursor( int flag ) // flag = TRUE - use mono device +{ // flag = FALSE - don't use + if( flag ) + MDA.CursorOn(); + else + MDA.CursorOff(); +} + +#endif + \ No newline at end of file diff --git a/src/MONO_C.H b/src/MONO_C.H new file mode 100644 index 0000000..e5bd566 --- /dev/null +++ b/src/MONO_C.H @@ -0,0 +1,36 @@ +#ifdef _DEBUG +#ifndef _MONO_C_H_ +#define _MONO_C_H_ + +#include "mono.h" + +//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +// +// Global Function Declarations +// +//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° + +void mono_setAttrib( MonoAttrib aVal ); +MonoAttrib mono_getAttrib( void ); + + + +int mono_getExist ( void ); +int mono_getEnable( void ); +void mono_setEnable( int flag ); + +void mono_cls ( void ); + +void mono_putc ( short x, short y, char c ); +void mono_puts ( short x, short y, char const * const str ); +void __cdecl mono_printf( short x, short y, char const * const format, ... ); + +void mono_dump ( short port = 1); + +void mono_setHardwareCursor( int flag ); + + + +#endif +#endif + \ No newline at end of file diff --git a/src/MONSTDAT.CPP b/src/MONSTDAT.CPP new file mode 100644 index 0000000..8c7c9d1 --- /dev/null +++ b/src/MONSTDAT.CPP @@ -0,0 +1,6268 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Monsters Data file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MONSTDAT.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "cursor.h" +#include "monster.h" +#include "monstdat.h" +#include "minitext.h" +#include "textdat.h" +#include "items.h" + + +#if RLE_DRAW +#define CEL_EXT ".CL2" +#else +#define CEL_EXT ".CEL" +#endif + + +/*-----------------------------------------------------------------------** +** Image width, Image size in K bytes +** Image files +** Special animation +** Sound files +** Special sound +** Trans file?, Transformation file name +** Neutral, Walk, Attack, Get Hit, Death, Special (# frames) +** Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) +** Name +** Min, Max dungeon level +** Monster level ranking (1 = easy, 30 = hardest) +** Min, Max hitpoints +** Intelligence (0 = easiest, 3 = hardest of type) +** Hit% #1 +** Hit check frame #1 +** Min, Max damage #1 +** Hit% #2 +** Hit check frame #2 +** Min, Max damage #2 +** Armor Class +** Magic resist +** Monster Class +** Selection Flags +** Experience points +**-----------------------------------------------------------------------*/ + +MonsterData monsterdata[] = +{ +// MT_NZOMBIE + { 128, 799, // Image width, Image size + "Monsters\\Zombie\\Zombie%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Zombie\\Zombie%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 11, 24, 12, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Zombie", // Name + 1, 3, // Min, Max dungeon level + 1, // Monster level ranking (1 = easy, 30 = hardest) + 4, 7, // Min, Max hitpoints + AI_ZOMBIE, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 10, // Hit% #1 + 8, // Hit check frame #1 + 2, 5, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 5, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 54}, // Experience points + +// MT_BZOMBIE + { 128, 799, // Image width, Image size + "Monsters\\Zombie\\Zombie%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Zombie\\Zombie%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Zombie\\Bluered.TRN", // Trans file?, Transformation file name + { 11, 24, 12, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Ghoul", // Name + 2, 4, // Min, Max dungeon level + 2, // Monster level ranking (1 = easy, 30 = hardest) + 7, 11, // Min, Max hitpoints + AI_ZOMBIE, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 10, // Hit% #1 + 8, // Hit check frame #1 + 3, 10, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 10, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 58 }, // Experience points + +// MT_GZOMBIE + { 128, 799, // Image width, Image size + "Monsters\\Zombie\\Zombie%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Zombie\\Zombie%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Zombie\\Grey.TRN", // Trans file?, Transformation file name + { 11, 24, 12, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Rotting Carcass", // Name + 2, 6, // Min, Max dungeon level + 4, // Monster level ranking (1 = easy, 30 = hardest) + 15, 25, // Min, Max hitpoints + AI_ZOMBIE, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 25, // Hit% #1 + 8, // Hit check frame #1 + 5, 15, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 15, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II+M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 136 }, // Experience points + +// MT_YZOMBIE + { 128, 799, // Image width, Image size + "Monsters\\Zombie\\Zombie%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Zombie\\Zombie%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Zombie\\Yellow.TRN", // Trans file?, Transformation file name + { 11, 24, 12, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Black Death", // Name + 4, 8, // Min, Max dungeon level + 6, // Monster level ranking (1 = easy, 30 = hardest) + 25, 40, // Min, Max hitpoints + AI_ZOMBIE, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 30, // Hit% #1 + 8, // Hit check frame #1 + 6, 22, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 20, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II+M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 240 }, // Experience points + +// MT_RFALLSP + { 128, 543, // Image width, Image size + "Monsters\\FalSpear\\Phall%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\FalSpear\\Phall%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\FalSpear\\FallenT.TRN", // Trans file?, Transformation file name + { 11, 11, 13, 11, 18, 13 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Fallen One", // Name + 1, 3, // Min, Max dungeon level + 1, // Monster level ranking (1 = easy, 30 = hardest) + 1, 4, // Min, Max hitpoints + AI_FALLEN, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 15, // Hit% #1 + 7, // Hit check frame #1 + 1, 3, // Min, Max damage #1 + 0, // Hit% #2 + 5, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_NONE, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 46 }, // Experience points + +// MT_DFALLSP + { 128, 543, // Image width, Image size + "Monsters\\FalSpear\\Phall%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\FalSpear\\Phall%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\FalSpear\\Dark.TRN", // Trans file?, Transformation file name + { 11, 11, 13, 11, 18, 13 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Carver", // Name + 2, 5, // Min, Max dungeon level + 3, // Monster level ranking (1 = easy, 30 = hardest) + 4, 8, // Min, Max hitpoints + AI_FALLEN, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 20, // Hit% #1 + 7, // Hit check frame #1 + 2, 5, // Min, Max damage #1 + 0, // Hit% #2 + 5, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 5, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_NONE, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 80 }, // Experience points + +// MT_YFALLSP + { 128, 543, // Image width, Image size + "Monsters\\FalSpear\\Phall%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\FalSpear\\Phall%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 11, 11, 13, 11, 18, 13 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Devil Kin", // Name + 3, 7, // Min, Max dungeon level + 5, // Monster level ranking (1 = easy, 30 = hardest) + 12, 24, // Min, Max hitpoints + AI_FALLEN, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 25, // Hit% #1 + 7, // Hit check frame #1 + 3, 7, // Min, Max damage #1 + 0, // Hit% #2 + 5, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 10, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 155 }, // Experience points + +// MT_BFALLSP + { 128, 543, // Image width, Image size + "Monsters\\FalSpear\\Phall%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\FalSpear\\Phall%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\FalSpear\\Blue.TRN", // Trans file?, Transformation file name + { 11, 11, 13, 11, 18, 13 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Dark One", // Name + 5, 9, // Min, Max dungeon level + 7, // Monster level ranking (1 = easy, 30 = hardest) + 20, 36, // Min, Max hitpoints + AI_FALLEN, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 30, // Hit% #1 + 7, // Hit check frame #1 + 4, 8, // Min, Max damage #1 + 0, // Hit% #2 + 5, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 15, // Armor Class + MC_ANIMAL, // Monster Class + M_II, // Magic resist + M_II+M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 255 }, // Experience points + +// MT_WSKELAX + { 128, 553, // Image width, Image size + "Monsters\\SkelAxe\\SklAx%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelAxe\\SklAx%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\SkelAxe\\White.TRN", // Trans file?, Transformation file name + { 12, 8, 13, 6, 17, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 5, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Skeleton", // Name + 1, 3, // Min, Max dungeon level + 1, // Monster level ranking (1 = easy, 30 = hardest) + 2, 4, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 0, // Intelligence + 20, // Hit% #1 + 8, // Hit check frame #1 + 1, 4, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 64 }, // Experience points + +// MT_TSKELAX + { 128, 553, // Image width, Image size + "Monsters\\SkelAxe\\SklAx%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelAxe\\SklAx%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\SkelAxe\\Skelt.TRN", // Trans file?, Transformation file name + { 12, 8, 13, 6, 17, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Corpse Axe", // Name + 2, 5, // Min, Max dungeon level + 2, // Monster level ranking (1 = easy, 30 = hardest) + 4, 7, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 25, // Hit% #1 + 8, // Hit check frame #1 + 3, 5, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 68 }, // Experience points + +// MT_RSKELAX + { 128, 553, // Image width, Image size + "Monsters\\SkelAxe\\SklAx%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelAxe\\SklAx%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 8, 13, 6, 17, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Burning Dead", // Name + 2, 6, // Min, Max dungeon level + 4, // Monster level ranking (1 = easy, 30 = hardest) + 8, 12, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 30, // Hit% #1 + 8, // Hit check frame #1 + 3, 7, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 5, // Armor Class + MC_UNDEAD, // Monster Class + M_RF+M_IM+M_II, // Magic resist + M_IF+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 154 }, // Experience points + +// MT_XSKELAX + { 128, 553, // Image width, Image size + "Monsters\\SkelAxe\\SklAx%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelAxe\\SklAx%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\SkelAxe\\Black.TRN", // Trans file?, Transformation file name + { 12, 8, 13, 6, 17, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Horror", // Name + 4, 8, // Min, Max dungeon level + 6, // Monster level ranking (1 = easy, 30 = hardest) + 12, 20, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 35, // Hit% #1 + 8, // Hit check frame #1 + 4, 9, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 15, // Armor Class + MC_UNDEAD, // Monster Class + M_RL+M_IM+M_II, // Magic resist + M_RL+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 264 }, // Experience points + +// MT_RFALLSD + { 128, 623, // Image width, Image size + "Monsters\\FalSword\\Fall%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\FalSword\\Fall%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\FalSword\\FallenT.TRN", // Trans file?, Transformation file name + { 12, 12, 13, 11, 14, 15 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Fallen One", // Name + 1, 3, // Min, Max dungeon level + 1, // Monster level ranking (1 = easy, 30 = hardest) + 2, 5, // Min, Max hitpoints + AI_FALLEN, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 15, // Hit% #1 + 8, // Hit check frame #1 + 1, 4, // Min, Max damage #1 + 0, // Hit% #2 + 5, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 10, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_NONE, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 52 }, // Experience points + +// MT_DFALLSD + { 128, 623, // Image width, Image size + "Monsters\\FalSword\\Fall%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\FalSword\\Fall%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\FalSword\\Dark.TRN", // Trans file?, Transformation file name + { 12, 12, 13, 11, 14, 15 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Carver", // Name + 2, 5, // Min, Max dungeon level + 3, // Monster level ranking (1 = easy, 30 = hardest) + 5, 9, // Min, Max hitpoints + AI_FALLEN, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 20, // Hit% #1 + 8, // Hit check frame #1 + 2, 7, // Min, Max damage #1 + 0, // Hit% #2 + 5, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 15, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_NONE, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 90 }, // Experience points + +// MT_YFALLSD + { 128, 623, // Image width, Image size + "Monsters\\FalSword\\Fall%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\FalSword\\Fall%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 12, 13, 11, 14, 15 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Devil Kin", // Name + 3, 7, // Min, Max dungeon level + 5, // Monster level ranking (1 = easy, 30 = hardest) + 16, 24, // Min, Max hitpoints + AI_FALLEN, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 25, // Hit% #1 + 8, // Hit check frame #1 + 4, 10, // Min, Max damage #1 + 0, // Hit% #2 + 5, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 20, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 180 }, // Experience points + +// MT_BFALLSD + { 128, 623, // Image width, Image size + "Monsters\\FalSword\\Fall%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\FalSword\\Fall%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\FalSword\\Blue.TRN", // Trans file?, Transformation file name + { 12, 12, 13, 11, 14, 15 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Dark One", // Name + 5, 9, // Min, Max dungeon level + 7, // Monster level ranking (1 = easy, 30 = hardest) + 24, 36, // Min, Max hitpoints + AI_FALLEN, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 30, // Hit% #1 + 8, // Hit check frame #1 + 4, 12, // Min, Max damage #1 + 0, // Hit% #2 + 5, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 25, // Armor Class + MC_ANIMAL, // Monster Class + M_II, // Magic resist + M_II+M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 280 }, // Experience points + +// MT_NSCAV + { 128, 410, // Image width, Image size + "Monsters\\Scav\\Scav%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Scav\\Scav%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 8, 12, 6, 20, 11 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Scavenger", // Name + 1, 4, // Min, Max dungeon level + 2, // Monster level ranking (1 = easy, 30 = hardest) + 3, 6, // Min, Max hitpoints + AI_SCAV, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 20, // Hit% #1 + 7, // Hit check frame #1 + 1, 5, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 10, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 80 }, // Experience points + +// MT_BSCAV + { 128, 410, // Image width, Image size + "Monsters\\Scav\\Scav%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Scav\\Scav%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Scav\\ScavBr.TRN", // Trans file?, Transformation file name + { 12, 8, 12, 6, 20, 11 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Plague Eater", // Name + 3, 6, // Min, Max dungeon level + 4, // Monster level ranking (1 = easy, 30 = hardest) + 12, 24, // Min, Max hitpoints + AI_SCAV, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 30, // Hit% #1 + 7, // Hit check frame #1 + 1, 8, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 20, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 188 }, // Experience points + +// MT_WSCAV + { 128, 410, // Image width, Image size + "Monsters\\Scav\\Scav%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Scav\\Scav%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Scav\\ScavBe.TRN", // Trans file?, Transformation file name + { 12, 8, 12, 6, 20, 11 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Shadow Beast", // Name + 4, 8, // Min, Max dungeon level + 6, // Monster level ranking (1 = easy, 30 = hardest) + 24, 36, // Min, Max hitpoints + AI_SCAV, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 35, // Hit% #1 + 7, // Hit check frame #1 + 3, 12, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 25, // Armor Class + MC_ANIMAL, // Monster Class + M_II, // Magic resist + M_II+M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 375 }, // Experience points + +// MT_YSCAV + { 128, 410, // Image width, Image size + "Monsters\\Scav\\Scav%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Scav\\Scav%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Scav\\ScavW.TRN", // Trans file?, Transformation file name + { 12, 8, 12, 6, 20, 11 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Bone Gasher", // Name + 6, 10, // Min, Max dungeon level + 8, // Monster level ranking (1 = easy, 30 = hardest) + 28, 40, // Min, Max hitpoints + AI_SCAV, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 35, // Hit% #1 + 7, // Hit check frame #1 + 5, 15, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_ANIMAL, // Monster Class + M_RM+M_II, // Magic resist + M_II+M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 552 }, // Experience points + +// MT_WSKELBW + { 128, 567, // Image width, Image size + "Monsters\\SkelBow\\SklBw%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelBow\\SklBw%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\SkelBow\\White.TRN", // Trans file?, Transformation file name + { 9, 8, 16, 5, 16, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Skeleton", // Name + 2, 5, // Min, Max dungeon level + 3, // Monster level ranking (1 = easy, 30 = hardest) + 2, 4, // Min, Max hitpoints + AI_SKELBOW, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 15, // Hit% #1 + 12, // Hit check frame #1 + 1, 2, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 110 }, // Experience points + +// MT_TSKELBW + { 128, 567, // Image width, Image size + "Monsters\\SkelBow\\SklBw%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelBow\\SklBw%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\SkelBow\\Skelt.TRN", // Trans file?, Transformation file name + { 9, 8, 16, 5, 16, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Corpse Bow", // Name + 3, 7, // Min, Max dungeon level + 5, // Monster level ranking (1 = easy, 30 = hardest) + 8, 16, // Min, Max hitpoints + AI_SKELBOW, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 25, // Hit% #1 + 12, // Hit check frame #1 + 1, 4, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 210 }, // Experience points + +// MT_RSKELBW + { 128, 567, // Image width, Image size + "Monsters\\SkelBow\\SklBw%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelBow\\SklBw%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 9, 8, 16, 5, 16, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Burning Dead", // Name + 5, 9, // Min, Max dungeon level + 7, // Monster level ranking (1 = easy, 30 = hardest) + 10, 24, // Min, Max hitpoints + AI_SKELBOW, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 30, // Hit% #1 + 12, // Hit check frame #1 + 1, 6, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 5, // Armor Class + MC_UNDEAD, // Monster Class + M_RF+M_IM+M_II, // Magic resist + M_IF+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 364 }, // Experience points + +// MT_XSKELBW + { 128, 567, // Image width, Image size + "Monsters\\SkelBow\\SklBw%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelBow\\SklBw%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\SkelBow\\Black.TRN", // Trans file?, Transformation file name + { 9, 8, 16, 5, 16, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Horror", // Name + 7, 11, // Min, Max dungeon level + 9, // Monster level ranking (1 = easy, 30 = hardest) + 15, 45, // Min, Max hitpoints + AI_SKELBOW, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 35, // Hit% #1 + 12, // Hit check frame #1 + 2, 9, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 15, // Armor Class + MC_UNDEAD, // Monster Class + M_RL+M_IM+M_II, // Magic resist + M_RL+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 594 }, // Experience points + +// MT_WSKELSD + { 128, 575, // Image width, Image size + "Monsters\\SkelSd\\SklSr%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelSd\\SklSr%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\SkelSd\\White.TRN", // Trans file?, Transformation file name + { 13, 8, 12, 7, 15, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Skeleton Captain", // Name + 1, 4, // Min, Max dungeon level + 2, // Monster level ranking (1 = easy, 30 = hardest) + 3, 6, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 20, // Hit% #1 + 8, // Hit check frame #1 + 2, 7, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 10, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 90 }, // Experience points + +// MT_TSKELSD + { 128, 575, // Image width, Image size + "Monsters\\SkelSd\\SklSr%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelSd\\SklSr%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\SkelSd\\Skelt.TRN", // Trans file?, Transformation file name + { 13, 8, 12, 7, 15, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Corpse Captain", // Name + 2, 6, // Min, Max dungeon level + 4, // Monster level ranking (1 = easy, 30 = hardest) + 12, 20, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 30, // Hit% #1 + 8, // Hit check frame #1 + 3, 9, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 5, // Armor Class + MC_UNDEAD, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 200 }, // Experience points + +// MT_RSKELSD + { 128, 575, // Image width, Image size + "Monsters\\SkelSd\\SklSr%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelSd\\SklSr%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 8, 12, 7, 15, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Burning Dead Captain", // Name + 4, 8, // Min, Max dungeon level + 6, // Monster level ranking (1 = easy, 30 = hardest) + 16, 30, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 35, // Hit% #1 + 8, // Hit check frame #1 + 4, 10, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 15, // Armor Class + MC_UNDEAD, // Monster Class + M_RF+M_IM+M_II, // Magic resist + M_IF+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 393 }, // Experience points + +// MT_XSKELSD + { 128, 575, // Image width, Image size + "Monsters\\SkelSd\\SklSr%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SkelSd\\SklSr%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\SkelSd\\Black.TRN", // Trans file?, Transformation file name + { 13, 8, 12, 7, 15, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Horror Captain", // Name + 6, 10, // Min, Max dungeon level + 8, // Monster level ranking (1 = easy, 30 = hardest) + 35, 50, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 40, // Hit% #1 + 8, // Hit check frame #1 + 5, 14, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_UNDEAD, // Monster Class + M_RL+M_IM+M_II, // Magic resist + M_RL+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 604 }, // Experience points + +// MT_INVILORD + { 128, 800/*2000*/, // Image width, Image size + "Monsters\\TSneak\\TSneak%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\TSneak\\Sneakl%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 13, 15, 11, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Invisible Lord", // Name + 36, 39, // Min, Max dungeon level + 14, // Monster level ranking (1 = easy, 30 = hardest) + 278, 278, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 65, // Hit% #1 + 8, // Hit check frame #1 + 16, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_RF+M_RL+M_II, // Magic resist + M_RM+M_RF+M_RL+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2000 }, // Experience points + +// MT_SNEAK + { 128, 992, // Image width, Image size + "Monsters\\Sneak\\Sneak%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Sneak\\Sneak%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 16, 8, 12, 8, 24, 15 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hidden", // Name + 3, 8, // Min, Max dungeon level + 5, // Monster level ranking (1 = easy, 30 = hardest) + 8, 24, // Min, Max hitpoints + AI_SNEAK, + MFLAG_INVISIBLE, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 35, // Hit% #1 + 8, // Hit check frame #1 + 3, 6, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 25, // Armor Class + MC_DEMON, // Monster Class + M_NONE, // Magic resist + M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 278 }, // Experience points + +// MT_STALKER + { 128, 992, // Image width, Image size + "Monsters\\Sneak\\Sneak%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Sneak\\Sneak%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Sneak\\Sneakv2.TRN", // Trans file?, Transformation file name + { 16, 8, 12, 8, 24, 15 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Stalker", // Name + 8, 12, // Min, Max dungeon level + 9, // Monster level ranking (1 = easy, 30 = hardest) + 30, 45, // Min, Max hitpoints + AI_SNEAK, + MFLAG_INVISIBLE|MFLAG_PATH, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 40, // Hit% #1 + 8, // Hit check frame #1 + 8, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_DEMON, // Monster Class + M_NONE, // Magic resist + M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 630 }, // Experience points + +// MT_UNSEEN + { 128, 992, // Image width, Image size + "Monsters\\Sneak\\Sneak%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Sneak\\Sneak%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Sneak\\Sneakv3.TRN", // Trans file?, Transformation file name + { 16, 8, 12, 8, 24, 15 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Unseen", // Name + 10, 14, // Min, Max dungeon level + 11, // Monster level ranking (1 = easy, 30 = hardest) + 35, 50, // Min, Max hitpoints + AI_SNEAK, + MFLAG_INVISIBLE|MFLAG_PATH, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 45, // Hit% #1 + 8, // Hit check frame #1 + 12, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 935 }, // Experience points + +// MT_ILLWEAV + { 128, 992, // Image width, Image size + "Monsters\\Sneak\\Sneak%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Sneak\\Sneak%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Sneak\\Sneakv1.TRN", // Trans file?, Transformation file name + { 16, 8, 12, 8, 24, 15 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Illusion Weaver", // Name + 14, 18, // Min, Max dungeon level + 13, // Monster level ranking (1 = easy, 30 = hardest) + 40, 60, // Min, Max hitpoints + AI_SNEAK, + MFLAG_INVISIBLE|MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 16, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_RF, // Magic resist + M_IM+M_RF+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1500 }, // Experience points + +// MT_LRDSAYTR + { 160, 800 /*2000*/, // Image width, Image size + "Monsters\\GoatLord\\GoatL%c" CEL_EXT, // Image files + FALSE, // Special animation +// "Monsters\\GoatLord\\Goatl%c%i.WAV", // Sound files + "Monsters\\newsfx\\Satyr%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 13, 14, 9, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Satyr Lord", // Name + 40, 43, // Min, Max dungeon level + 28, // Monster level ranking (1 = easy, 30 = hardest) + 160, 200, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 90, // Hit% #1 + 8, // Hit check frame #1 + 20, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_ANIMAL, // Monster Class + M_RL+M_RF, // Magic resist + M_RM+M_IL+M_IF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2800 }, // Experience points + +// MT_NGOATMC + { 128, 1030, // Image width, Image size + "Monsters\\GoatMace\\Goat%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\GoatMace\\Goat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 8, 12, 6, 20, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Flesh Clan", // Name + 6, 10, // Min, Max dungeon level + 8, // Monster level ranking (1 = easy, 30 = hardest) + 30, 45, // Min, Max hitpoints + AI_GOATMC, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 50, // Hit% #1 + 8, // Hit check frame #1 + 4, 10, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 40, // Armor Class + MC_DEMON, // Monster Class + M_NONE, // Magic resist + M_NONE, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 460 }, // Experience points + +// MT_BGOATMC + { 128, 1030, // Image width, Image size + "Monsters\\GoatMace\\Goat%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\GoatMace\\Goat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\GoatMace\\Beige.TRN", // Trans file?, Transformation file name + { 12, 8, 12, 6, 20, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Stone Clan", // Name + 8, 12, // Min, Max dungeon level + 10, // Monster level ranking (1 = easy, 30 = hardest) + 40, 55, // Min, Max hitpoints + AI_GOATMC, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 6, 12, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 40, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 685 }, // Experience points + +// MT_RGOATMC + { 128, 1030, // Image width, Image size + "Monsters\\GoatMace\\Goat%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\GoatMace\\Goat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\GoatMace\\Red.TRN", // Trans file?, Transformation file name + { 12, 8, 12, 6, 20, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Fire Clan", // Name + 10, 14, // Min, Max dungeon level + 12, // Monster level ranking (1 = easy, 30 = hardest) + 50, 65, // Min, Max hitpoints + AI_GOATMC, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 70, // Hit% #1 + 8, // Hit check frame #1 + 8, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 45, // Armor Class + MC_DEMON, // Monster Class + M_RF, // Magic resist + M_IF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 906 }, // Experience points + +// MT_GGOATMC + { 128, 1030, // Image width, Image size + "Monsters\\GoatMace\\Goat%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\GoatMace\\Goat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\GoatMace\\Gray.TRN", // Trans file?, Transformation file name + { 12, 8, 12, 6, 20, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Night Clan", // Name + 12, 16, // Min, Max dungeon level + 14, // Monster level ranking (1 = easy, 30 = hardest) + 55, 70, // Min, Max hitpoints + AI_GOATMC, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 8, // Hit check frame #1 + 10, 20, // Min, Max damage #1 + 15, // Hit% #2 + 0, // Hit check frame #2 + 30, 30, // Min, Max damage #2 + 50, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1190 }, // Experience points + +// MT_FIEND + { 96, 364, // Image width, Image size + "Monsters\\Bat\\Bat%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Bat\\Bat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Bat\\red.trn", // Trans file?, Transformation file name + { 9, 13, 10, 9, 13, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Fiend", // Name + 2, 5, // Min, Max dungeon level + 3, // Monster level ranking (1 = easy, 30 = hardest) + 3, 6, // Min, Max hitpoints + AI_BAT, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 35, // Hit% #1 + 5, // Hit check frame #1 + 1, 6, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_NONE, // Magic resist2 + T_NONE, // Treasure + MSEL_FLY, // Selection Type + 102 }, // Experience points + +// MT_BLINK + { 96, 364, // Image width, Image size + "Monsters\\Bat\\Bat%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Bat\\Bat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 9, 13, 10, 9, 13, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Blink", // Name + 5, 9, // Min, Max dungeon level + 7, // Monster level ranking (1 = easy, 30 = hardest) + 12, 28, // Min, Max hitpoints + AI_BAT, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 45, // Hit% #1 + 5, // Hit check frame #1 + 1, 8, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 15, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_NONE, // Magic resist2 + T_NONE, // Treasure + MSEL_FLY, // Selection Type + 340 }, // Experience points + +// MT_GLOOM + { 96, 364, // Image width, Image size + "Monsters\\Bat\\Bat%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Bat\\Bat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Bat\\grey.trn", // Trans file?, Transformation file name + { 9, 13, 10, 9, 13, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Gloom", // Name + 7, 11, // Min, Max dungeon level + 9, // Monster level ranking (1 = easy, 30 = hardest) + 28, 36, // Min, Max hitpoints + AI_BAT, + MFLAG_PATH, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 70, // Hit% #1 + 5, // Hit check frame #1 + 4, 12, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 35, // Armor Class + MC_ANIMAL, // Monster Class + M_RM, // Magic resist + M_RM+M_II, // Magic resist2 + T_NONE, // Treasure + MSEL_FLY, // Selection Type + 509 }, // Experience points + +// MT_FAMILIAR + { 96, 364, // Image width, Image size + "Monsters\\Bat\\Bat%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Bat\\Bat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Bat\\orange.trn", // Trans file?, Transformation file name + { 9, 13, 10, 9, 13, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Familiar", // Name + 11, 15, // Min, Max dungeon level + 13, // Monster level ranking (1 = easy, 30 = hardest) + 20, 35, // Min, Max hitpoints + AI_BAT, + MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 50, // Hit% #1 + 5, // Hit check frame #1 + 4, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 35, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_IL, // Magic resist + M_RM+M_IL+M_II, // Magic resist2 + T_NONE, // Treasure + MSEL_FLY, // Selection Type + 448 }, // Experience points + +// MT_NGOATBW + { 128, 1040, // Image width, Image size + "Monsters\\GoatBow\\GoatB%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\GoatBow\\GoatB%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 8, 16, 6, 20, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Flesh Clan", // Name + 6, 10, // Min, Max dungeon level + 8, // Monster level ranking (1 = easy, 30 = hardest) + 20, 35, // Min, Max hitpoints + AI_GOATBOW, + MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 35, // Hit% #1 + 13, // Hit check frame #1 + 1, 7, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 35, // Armor Class + MC_DEMON, // Monster Class + M_NONE, // Magic resist + M_NONE, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 448 }, // Experience points + +// MT_BGOATBW + { 128, 1040, // Image width, Image size + "Monsters\\GoatBow\\GoatB%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\GoatBow\\GoatB%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\GoatBow\\Beige.TRN", // Trans file?, Transformation file name + { 12, 8, 16, 6, 20, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Stone Clan", // Name + 8, 12, // Min, Max dungeon level + 10, // Monster level ranking (1 = easy, 30 = hardest) + 30, 40, // Min, Max hitpoints + AI_GOATBOW, + MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 40, // Hit% #1 + 13, // Hit check frame #1 + 2, 9, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 35, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 645 }, // Experience points + +// MT_RGOATBW + { 128, 1040, // Image width, Image size + "Monsters\\GoatBow\\GoatB%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\GoatBow\\GoatB%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\GoatBow\\Red.TRN", // Trans file?, Transformation file name + { 12, 8, 16, 6, 20, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Fire Clan", // Name + 10, 14, // Min, Max dungeon level + 12, // Monster level ranking (1 = easy, 30 = hardest) + 40, 50, // Min, Max hitpoints + AI_GOATBOW, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 45, // Hit% #1 + 13, // Hit check frame #1 + 3, 11, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 35, // Armor Class + MC_DEMON, // Monster Class + M_RF, // Magic resist + M_IF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 822 }, // Experience points + +// MT_GGOATBW + { 128, 1040, // Image width, Image size + "Monsters\\GoatBow\\GoatB%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\GoatBow\\GoatB%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\GoatBow\\Gray.TRN", // Trans file?, Transformation file name + { 12, 8, 16, 6, 20, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Night Clan", // Name + 12, 16, // Min, Max dungeon level + 14, // Monster level ranking (1 = easy, 30 = hardest) + 50, 65, // Min, Max hitpoints + AI_GOATBOW, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 50, // Hit% #1 + 13, // Hit check frame #1 + 4, 13, // Min, Max damage #1 + 15, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 40, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1092 }, // Experience points + +// MT_NACID + { 128, 716, // Image width, Image size + "Monsters\\Acid\\Acid%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 8, 12, 8, 16, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Acid Beast", // Name + 10, 14, // Min, Max dungeon level + 11, // Monster level ranking (1 = easy, 30 = hardest) + 40, 66, // Min, Max hitpoints + AI_ACID, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 40, // Hit% #1 + 8, // Hit check frame #1 + 4, 12, // Min, Max damage #1 + 25, // Hit% #2 + 8, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_ANIMAL, // Monster Class + M_IA, // Magic resist + M_IA+M_IM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 846 }, // Experience points + +// MT_RACID + { 128, 716, // Image width, Image size + "Monsters\\Acid\\Acid%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Acid\\AcidBlk.TRN", // Trans file?, Transformation file name + { 13, 8, 12, 8, 16, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Poison Spitter", // Name + 14, 18, // Min, Max dungeon level + 15, // Monster level ranking (1 = easy, 30 = hardest) + 60, 85, // Min, Max hitpoints + AI_ACID, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 45, // Hit% #1 + 8, // Hit check frame #1 + 4, 16, // Min, Max damage #1 + 25, // Hit% #2 + 8, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_ANIMAL, // Monster Class + M_IA, // Magic resist + M_IA+M_IM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1248 }, // Experience points + +// MT_BACID + { 128, 716, // Image width, Image size + "Monsters\\Acid\\Acid%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Acid\\AcidB.TRN", // Trans file?, Transformation file name + { 13, 8, 12, 8, 16, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Pit Beast", // Name + 18, 22, // Min, Max dungeon level + 21, // Monster level ranking (1 = easy, 30 = hardest) + 80, 110, // Min, Max hitpoints + AI_ACID, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 55, // Hit% #1 + 8, // Hit check frame #1 + 8, 18, // Min, Max damage #1 + 35, // Hit% #2 + 8, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 35, // Armor Class + MC_ANIMAL, // Monster Class + M_IA|M_RM, // Magic resist + M_IA|M_IM|M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2060 }, // Experience points + +// MT_XACID + { 128, 716, // Image width, Image size + "Monsters\\Acid\\Acid%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Acid\\AcidR.TRN", // Trans file?, Transformation file name + { 13, 8, 12, 8, 16, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Lava Maw", // Name + 22, 27, // Min, Max dungeon level + 25, // Monster level ranking (1 = easy, 30 = hardest) + 100, 150, // Min, Max hitpoints + AI_ACID, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 65, // Hit% #1 + 8, // Hit check frame #1 + 10, 20, // Min, Max damage #1 + 40, // Hit% #2 + 8, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 35, // Armor Class + MC_ANIMAL, // Monster Class + M_IA|M_RM|M_IF, // Magic resist + M_IA|M_IM|M_IF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2940 }, // Experience points + +// MT_SKING + { 160, 1010, // Image width, Image size + "Monsters\\SKing\\SKing%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\SKing\\SKing%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\SkelAxe\\White.TRN", // Trans file?, Transformation file name + { 8, 6, 16, 6, 16, 6 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 2 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Skeleton King", // Name + 6, 6, // Min, Max dungeon level + 9, // Monster level ranking (1 = easy, 30 = hardest) + 140, 140, // Min, Max hitpoints + AI_SKELKING, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 6, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_UNDEAD, // Monster Class + M_RF+M_RL+M_IM+M_II, // Magic resist + M_IF+M_IL+M_IM+M_II, // Magic resist2 + T_U+UID_SKCROWN, // Treasure + MSEL_BIG, // Selection Type + 570 }, // Experience points + +// MT_CLEAVER + { 128, 980, // Image width, Image size + "Monsters\\FatC\\FatC%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\FatC\\FatC%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 8, 12, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 1, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "The Butcher", // Name + 0, 0, // Min, Max dungeon level + 1, // Monster level ranking (1 = easy, 30 = hardest) + 320, 320, // Min, Max hitpoints + AI_CLEAVER, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 50, // Hit% #1 + 8, // Hit check frame #1 + 6, 12, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_RL, // Magic resist + M_IF+M_IL+M_RM, // Magic resist2 + T_U+UID_CLEAVER, // Treasure + MSEL_REG, // Selection Type + 710 }, // Experience points + +// MT_FAT + { 128, 1130, // Image width, Image size + "Monsters\\Fat\\Fat%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Fat\\Fat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 8, 10, 15, 6, 16, 10 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Overlord", // Name + 8, 12, // Min, Max dungeon level + 10, // Monster level ranking (1 = easy, 30 = hardest) + 60, 80, // Min, Max hitpoints + AI_FAT, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 55, // Hit% #1 + 8, // Hit check frame #1 + 6, 12, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 55, // Armor Class + MC_DEMON, // Monster Class + M_NONE, // Magic resist + M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 635 }, // Experience points + +// MT_MUDMAN + { 128, 1130, // Image width, Image size + "Monsters\\Fat\\Fat%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Fat\\Fat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Fat\\Blue.TRN", // Trans file?, Transformation file name + { 8, 10, 15, 6, 16, 10 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Mud Man", // Name + 13, 17, // Min, Max dungeon level + 14, // Monster level ranking (1 = easy, 30 = hardest) + 100, 125, // Min, Max hitpoints + AI_FAT, + MFLAG_PATH, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 8, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_NONE, // Magic resist + M_IL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1165 }, // Experience points + +// MT_TOAD + { 128, 1130, // Image width, Image size + "Monsters\\Fat\\Fat%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Fat\\Fat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Fat\\FatB.TRN", // Trans file?, Transformation file name + { 8, 10, 15, 6, 16, 10 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Toad Demon", // Name + 15, 19, // Min, Max dungeon level + 16, // Monster level ranking (1 = easy, 30 = hardest) + 135, 160, // Min, Max hitpoints + AI_FAT, + MFLAG_PATH, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 70, // Hit% #1 + 8, // Hit check frame #1 + 8, 16, // Min, Max damage #1 + 40, // Hit% #2 + 0, // Hit check frame #2 + 8, 20, // Min, Max damage #2 + 65, // Armor Class + MC_DEMON, // Monster Class + M_IM, // Magic resist + M_IM+M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1380 }, // Experience points + +// MT_FLAYED + { 128, 1130, // Image width, Image size + "Monsters\\Fat\\Fat%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Fat\\Fat%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Fat\\FatF.TRN", // Trans file?, Transformation file name + { 8, 10, 15, 6, 16, 10 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 4, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Flayed One", // Name + 19, 23, // Min, Max dungeon level + 20, // Monster level ranking (1 = easy, 30 = hardest) + 160, 200, // Min, Max hitpoints + AI_FAT, + MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 85, // Hit% #1 + 8, // Hit check frame #1 + 10, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_IF, // Magic resist + M_IM+M_IF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2058 }, // Experience points + +// MT_WYRM + { 160, 2420, // Image width, Image size + "Monsters\\Worm\\Worm%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Fat\\Fat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 13, 13, 11, 19, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Wyrm", // Name + 9, 13, // Min, Max dungeon level + 11, // Monster level ranking (1 = easy, 30 = hardest) + 60, 90, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 40, // Hit% #1 + 8, // Hit check frame #1 + 4, 10, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 25, // Armor Class + MC_ANIMAL, // Monster Class + M_RM, // Magic resist + M_RM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 660 }, // Experience points + +// MT_CAVSLUG + { 160, 2420, // Image width, Image size + "Monsters\\Worm\\Worm%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Fat\\Fat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 13, 13, 11, 19, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Cave Slug", // Name + 11, 15, // Min, Max dungeon level + 13, // Monster level ranking (1 = easy, 30 = hardest) + 75, 110, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 50, // Hit% #1 + 8, // Hit check frame #1 + 6, 13, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_ANIMAL, // Monster Class + M_RM, // Magic resist + M_RM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 994 }, // Experience points + +// MT_DVLWYRM + { 160, 2420, // Image width, Image size + "Monsters\\Worm\\Worm%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Fat\\Fat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 13, 13, 11, 19, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Devil Wyrm", // Name + 13, 17, // Min, Max dungeon level + 15, // Monster level ranking (1 = easy, 30 = hardest) + 100, 140, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 55, // Hit% #1 + 8, // Hit check frame #1 + 8, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_ANIMAL, // Monster Class + M_RM+M_RF, // Magic resist + M_RM+M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1320 }, // Experience points + +// MT_DEVOUR + { 160, 2420, // Image width, Image size + "Monsters\\Worm\\Worm%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Fat\\Fat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 13, 13, 11, 19, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Devourer", // Name + 15, 19, // Min, Max dungeon level + 17, // Monster level ranking (1 = easy, 30 = hardest) + 125, 200, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 10, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 35, // Armor Class + MC_ANIMAL, // Monster Class + M_RM+M_RF+M_II, // Magic resist + M_RM+M_RF+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1827 }, // Experience points + +// MT_NMAGMA + { 128, 1680, // Image width, Image size + "Monsters\\Magma\\Magma%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Magma\\Magma%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 8, 10, 14, 7, 18, 18 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Magma Demon", // Name + 14, 17, // Min, Max dungeon level + 13, // Monster level ranking (1 = easy, 30 = hardest) + 50, 70, // Min, Max hitpoints + AI_MAGMA, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 45, // Hit% #1 + 4, // Hit check frame #1 + 2, 10, // Min, Max damage #1 + 50, // Hit% #2 + 13, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 45, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_IM, // Magic resist + M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1076 }, // Experience points + +// MT_YMAGMA + { 128, 1680, // Image width, Image size + "Monsters\\Magma\\Magma%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Magma\\Magma%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Magma\\Yellow.TRN", // Trans file?, Transformation file name + { 8, 10, 14, 7, 18, 18 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Blood Stone", // Name + 15, 19, // Min, Max dungeon level + 14, // Monster level ranking (1 = easy, 30 = hardest) + 55, 75, // Min, Max hitpoints + AI_MAGMA, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 50, // Hit% #1 + 4, // Hit check frame #1 + 2, 12, // Min, Max damage #1 + 50, // Hit% #2 + 14, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 45, // Armor Class + MC_DEMON, // Monster Class + M_IF+M_IM, // Magic resist + M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1309 }, // Experience points + +// MT_BMAGMA + { 128, 1680, // Image width, Image size + "Monsters\\Magma\\Magma%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Magma\\Magma%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Magma\\Blue.TRN", // Trans file?, Transformation file name + { 8, 10, 14, 7, 18, 18 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hell Stone", // Name + 16, 20, // Min, Max dungeon level + 16, // Monster level ranking (1 = easy, 30 = hardest) + 60, 80, // Min, Max hitpoints + AI_MAGMA, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 4, // Hit check frame #1 + 2, 20, // Min, Max damage #1 + 60, // Hit% #2 + 14, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_DEMON, // Monster Class + M_IF+M_IM, // Magic resist + M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1680 }, // Experience points + +// MT_WMAGMA + { 128, 1680, // Image width, Image size + "Monsters\\Magma\\Magma%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Magma\\Magma%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Magma\\Wierd.TRN", // Trans file?, Transformation file name + { 8, 10, 14, 7, 18, 18 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Lava Lord", // Name + 17, 21, // Min, Max dungeon level + 18, // Monster level ranking (1 = easy, 30 = hardest) + 70, 85, // Min, Max hitpoints + AI_MAGMA, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 75, // Hit% #1 + 4, // Hit check frame #1 + 4, 24, // Min, Max damage #1 + 60, // Hit% #2 + 14, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_IF+M_IM, // Magic resist + M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2124 }, // Experience points + +// MT_HORNED + { 160, 1630, // Image width, Image size + "Monsters\\Rhino\\Rhino%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Rhino\\Rhino%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 8, 8, 14, 6, 16, 6 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Horned Demon", // Name + 12, 16, // Min, Max dungeon level + 13, // Monster level ranking (1 = easy, 30 = hardest) + 40, 80, // Min, Max hitpoints + AI_RHINO, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 7, // Hit check frame #1 + 2, 16, // Min, Max damage #1 + 100, // Hit% #2 + 0, // Hit check frame #2 + 5, 32, // Min, Max damage #2 + 40, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1172 }, // Experience points + +// MT_MUDRUN + { 160, 1630, // Image width, Image size + "Monsters\\Rhino\\Rhino%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Rhino\\Rhino%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Rhino\\Orange.TRN", // Trans file?, Transformation file name + { 8, 8, 14, 6, 16, 6 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Mud Runner", // Name + 14, 18, // Min, Max dungeon level + 15, // Monster level ranking (1 = easy, 30 = hardest) + 50, 90, // Min, Max hitpoints + AI_RHINO, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 70, // Hit% #1 + 7, // Hit check frame #1 + 6, 18, // Min, Max damage #1 + 100, // Hit% #2 + 0, // Hit check frame #2 + 12,36, // Min, Max damage #2 + 45, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1404 }, // Experience points + +// MT_FROSTC + { 160, 1630, // Image width, Image size + "Monsters\\Rhino\\Rhino%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Rhino\\Rhino%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Rhino\\Blue.TRN", // Trans file?, Transformation file name + { 8, 8, 14, 6, 16, 6 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Frost Charger", // Name + 16, 20, // Min, Max dungeon level + 17, // Monster level ranking (1 = easy, 30 = hardest) + 60, 100, // Min, Max hitpoints + AI_RHINO, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 7, // Hit check frame #1 + 8, 20, // Min, Max damage #1 + 100, // Hit% #2 + 0, // Hit check frame #2 + 20, 40, // Min, Max damage #2 + 50, // Armor Class + MC_ANIMAL, // Monster Class + M_RL+M_IM, // Magic resist + M_RL+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1720 }, // Experience points + +// MT_OBLORD + { 160, 1630, // Image width, Image size + "Monsters\\Rhino\\Rhino%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Rhino\\Rhino%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Rhino\\RhinoB.TRN", // Trans file?, Transformation file name + { 8, 8, 14, 6, 16, 6 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Obsidian Lord", // Name + 18, 22, // Min, Max dungeon level + 19, // Monster level ranking (1 = easy, 30 = hardest) + 70, 110, // Min, Max hitpoints + AI_RHINO, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 90, // Hit% #1 + 7, // Hit check frame #1 + 10, 22, // Min, Max damage #1 + 100, // Hit% #2 + 0, // Hit check frame #2 + 20, 50, // Min, Max damage #2 + 55, // Armor Class + MC_ANIMAL, // Monster Class + M_RL+M_IM, // Magic resist + M_IL+M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1809 }, // Experience points + +// MT_BONEDMN + { 128, 1740, // Image width, Image size + "Monsters\\Demskel\\Demskl%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Thin\\Thin%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, "Monsters\\Thin\\Thinv3.TRN", // Trans file?, Transformation file name + { 10, 8, 20, 6, 24, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "oldboned", // Name + 46, 47, // Min, Max dungeon level + 12, // Monster level ranking (1 = easy, 30 = hardest) + 70, 70, // Min, Max hitpoints + AI_STORM, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 6, 14, // Min, Max damage #1 + 12, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_DEMON, // Monster Class + M_IM+M_II, // Magic resist + M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1344 }, // Experience points + +// MT_REDDTH + { 160, 1740, // Image width, Image size + "Monsters\\Thin\\Thin%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Thin\\Thin%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Thin\\Thinv3.TRN", // Trans file?, Transformation file name + { 8, 8, 18, 4, 17, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Red Death", // Name + 14, 18, // Min, Max dungeon level + 16, // Monster level ranking (1 = easy, 30 = hardest) + 96, 96, // Min, Max hitpoints + AI_STORM, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 75, // Hit% #1 + 5, // Hit check frame #1 + 10, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_IM+M_IF, // Magic resist + M_IM+M_IF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2168 }, // Experience points + +// MT_LTCHDMN + { 160, 1740, // Image width, Image size + "Monsters\\Thin\\Thin%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Thin\\Thin%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Thin\\Thinv3.TRN", // Trans file?, Transformation file name + { 8, 8, 18, 4, 17, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Litch Demon", // Name + 16, 20, // Min, Max dungeon level + 18, // Monster level ranking (1 = easy, 30 = hardest) + 110, 110, // Min, Max hitpoints + AI_STORM, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 5, // Hit check frame #1 + 10, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 45, // Armor Class + MC_DEMON, // Monster Class + M_IM+M_IL+M_II, // Magic resist + M_IM+M_IL+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2736 }, // Experience points + +// MT_UDEDBLRG + { 160, 1740, // Image width, Image size + "Monsters\\Thin\\Thin%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Thin\\Thin%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Thin\\Thinv3.TRN", // Trans file?, Transformation file name + { 8, 8, 18, 4, 17, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Undead Balrog", // Name + 20, 24, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 130, 130, // Min, Max hitpoints + AI_STORM, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 85, // Hit% #1 + 5, // Hit check frame #1 + 12, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 65, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_RL+M_IM+M_II, // Magic resist + M_RF+M_RL+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3575 }, // Experience points + +// MT_INCIN + { 128, 1460, // Image width, Image size + "Monsters\\Fireman\\FireM%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 14, 19, 20, 8, 14, 23 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Incinerator", // Name + 40, 43, // Min, Max dungeon level + 16, // Monster level ranking (1 = easy, 30 = hardest) + 30, 45, // Min, Max hitpoints + AI_FIREMAN, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 75, // Hit% #1 + 8, // Hit check frame #1 + 8, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 25, // Armor Class + MC_DEMON, // Monster Class + M_IF+M_IM, // Magic resist + M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1888 }, // Experience points + +// MT_FLAMLRD + { 128, 1460, // Image width, Image size + "Monsters\\Fireman\\FireM%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 14, 19, 20, 8, 14, 23 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Flame Lord", // Name + 42, 45, // Min, Max dungeon level + 18, // Monster level ranking (1 = easy, 30 = hardest) + 40, 55, // Min, Max hitpoints + AI_FIREMAN, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 75, // Hit% #1 + 8, // Hit check frame #1 + 10, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 25, // Armor Class + MC_DEMON, // Monster Class + M_IF+M_IM, // Magic resist + M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2250 }, // Experience points + +// MT_DOOMFIRE + { 128, 1460, // Image width, Image size + "Monsters\\Fireman\\FireM%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 14, 19, 20, 8, 14, 23 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Doom Fire", // Name + 44, 47, // Min, Max dungeon level + 20, // Monster level ranking (1 = easy, 30 = hardest) + 50, 65, // Min, Max hitpoints + AI_FIREMAN, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 8, // Hit check frame #1 + 12, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_IF+M_IM, // Magic resist + M_RL+M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2740 }, // Experience points + +// MT_HELLBURN + { 128, 1460, // Image width, Image size + "Monsters\\Fireman\\FireM%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 14, 19, 20, 8, 14, 23 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hell Burner", // Name + 46, 47, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 60, 80, // Min, Max hitpoints + AI_FIREMAN, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 85, // Hit% #1 + 8, // Hit check frame #1 + 15, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_IF+M_IM, // Magic resist + M_RL+M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 3355 }, // Experience points + +// MT_STORM + { 160, 1740, // Image width, Image size + "Monsters\\Thin\\Thin%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Thin\\Thin%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Thin\\Thinv3.TRN", // Trans file?, Transformation file name + { 8, 8, 18, 4, 17, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Red Storm", // Name + 17, 21, // Min, Max dungeon level + 18, // Monster level ranking (1 = easy, 30 = hardest) + 55, 110, // Min, Max hitpoints + AI_STORM, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 5, // Hit check frame #1 + 8, 18, // Min, Max damage #1 + 75, // Hit% #2 + 8, // Hit check frame #2 + 4, 16, // Min, Max damage #2 + 30, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_IM, // Magic resist + M_IM+M_IL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2160 }, // Experience points + +// MT_RSTORM + { 160, 1740, // Image width, Image size + "Monsters\\Thin\\Thin%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Thin\\Thin%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 8, 8, 18, 4, 17, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Storm Rider", // Name + 19, 23, // Min, Max dungeon level + 20, // Monster level ranking (1 = easy, 30 = hardest) + 60, 120, // Min, Max hitpoints + AI_STORM, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 5, // Hit check frame #1 + 8, 18, // Min, Max damage #1 + 80, // Hit% #2 + 8, // Hit check frame #2 + 4, 16, // Min, Max damage #2 + 30, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_IL, // Magic resist + M_IM+M_IL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2391 }, // Experience points + +// MT_STORML + { 160, 1740, // Image width, Image size + "Monsters\\Thin\\Thin%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Thin\\Thin%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Thin\\Thinv2.TRN", // Trans file?, Transformation file name + { 8, 8, 18, 4, 17, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Storm Lord", // Name + 21, 25, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 75, 135, // Min, Max hitpoints + AI_STORM, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 85, // Hit% #1 + 5, // Hit check frame #1 + 12, 24, // Min, Max damage #1 + 75, // Hit% #2 + 8, // Hit check frame #2 + 4, 16, // Min, Max damage #2 + 35, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_IL, // Magic resist + M_IM+M_IL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2775 }, // Experience points + +// MT_MAEL + { 160, 1740, // Image width, Image size + "Monsters\\Thin\\Thin%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Thin\\Thin%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Thin\\Thinv1.TRN", // Trans file?, Transformation file name + { 8, 8, 18, 4, 17, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Maelstorm", // Name + 23, 27, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 90, 150, // Min, Max hitpoints + AI_STORM, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 90, // Hit% #1 + 5, // Hit check frame #1 + 12, 28, // Min, Max damage #1 + 75, // Hit% #2 + 8, // Hit check frame #2 + 4, 16, // Min, Max damage #2 + 40, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_II+M_IL, // Magic resist + M_IM+M_II+M_IL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3177 }, // Experience points + + // MT_BIGFALL + { 128, 800 /*1650*/, // Image width, Image size + "Monsters\\BigFall\\Fallg%c" CEL_EXT, // Image files + TRUE, // Special animation +// "Monsters\\BigFall\\Bfal%c%i.WAV", // Sound files + "Monsters\\newsfx\\KBrute%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 8, 11, 8, 17, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 2, 2 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Devil Kin Brute", // Name + 40, 43, // Min, Max dungeon level + 27, // Monster level ranking (1 = easy, 30 = hardest) + 120, 160, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 100, // Hit% #1 + 6, // Hit check frame #1 + 18, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_ANIMAL, // Monster Class + M_RF+M_RL, // Magic resist + M_RF+M_RL+M_RM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2400 }, // Experience points + + // MT_WINGED + { 160, 1650, // Image width, Image size + "Monsters\\Gargoyle\\Gargo%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Gargoyle\\Gargo%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 14, 14, 14, 10, 18, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 2 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Winged-Demon", // Name + 8, 12, // Min, Max dungeon level + 9, // Monster level ranking (1 = easy, 30 = hardest) + 45, 60, // Min, Max hitpoints + AI_GARG, + MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 50, // Hit% #1 + 7, // Hit check frame #1 + 10, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 45, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_II+M_IM, // Magic resist + M_IF+M_II+M_IM, // Magic resist2 + 0, // Treasure + MSEL_FLY, // Selection Type + 662 }, // Experience points + +// MT_GARGOYLE + { 160, 1650, // Image width, Image size + "Monsters\\Gargoyle\\Gargo%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Gargoyle\\Gargo%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Gargoyle\\GarE.TRN", // Trans file?, Transformation file name + { 14, 14, 14, 10, 18, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 2 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Gargoyle", // Name + 12, 16, // Min, Max dungeon level + 13, // Monster level ranking (1 = easy, 30 = hardest) + 60, 90, // Min, Max hitpoints + AI_GARG, + MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 65, // Hit% #1 + 7, // Hit check frame #1 + 10, 16, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 45, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_II+M_IM, // Magic resist + M_IL+M_II+M_IM, // Magic resist2 + 0, // Treasure + MSEL_FLY, // Selection Type + 1205 }, // Experience points + +// MT_BLOODCLW + { 160, 1650, // Image width, Image size + "Monsters\\Gargoyle\\Gargo%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Gargoyle\\Gargo%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Gargoyle\\GargBr.TRN", // Trans file?, Transformation file name + { 14, 14, 14, 10, 18, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Blood Claw", // Name + 16, 20, // Min, Max dungeon level + 19, // Monster level ranking (1 = easy, 30 = hardest) + 75, 125, // Min, Max hitpoints + AI_GARG, + MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 7, // Hit check frame #1 + 14, 22, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_DEMON, // Monster Class + M_II+M_IM+M_IF, // Magic resist + M_IF+M_RL+M_II+M_IM, // Magic resist2 + 0, // Treasure + MSEL_FLY, // Selection Type + 1873 }, // Experience points + +// MT_DEATHW + { 160, 1650, // Image width, Image size + "Monsters\\Gargoyle\\Gargo%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Gargoyle\\Gargo%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Gargoyle\\GargB.TRN", // Trans file?, Transformation file name + { 14, 14, 14, 10, 18, 14 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Death Wing", // Name + 18, 22, // Min, Max dungeon level + 23, // Monster level ranking (1 = easy, 30 = hardest) + 90, 150, // Min, Max hitpoints + AI_GARG, + MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 95, // Hit% #1 + 7, // Hit check frame #1 + 16, 28, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_II+M_IM+M_IL, // Magic resist + M_RF+M_IL+M_II+M_IM, // Magic resist2 + 0, // Treasure + MSEL_FLY, // Selection Type + 2278 }, // Experience points + +// MT_MEGA + { 160, 2220, // Image width, Image size + "Monsters\\Mega\\Mega%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Mega\\Mega%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 6, 7, 14, 1, 24, 5 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 2, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Slayer", // Name + 19, 23, // Min, Max dungeon level + 20, // Monster level ranking (1 = easy, 30 = hardest) + 120, 140, // Min, Max hitpoints + AI_MEGA, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 100, // Hit% #1 + 8, // Hit check frame #1 + 12, 20, // Min, Max damage #1 + 0, // Hit% #2 + 3, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_IF, // Magic resist + M_RM+M_IF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2300 }, // Experience points + +// MT_GUARD + { 160, 2220, // Image width, Image size + "Monsters\\Mega\\Mega%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Mega\\Mega%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Mega\\Guard.TRN", // Trans file?, Transformation file name + { 6, 7, 14, 1, 24, 5 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 2, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Guardian", // Name + 21, 25, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 140, 160, // Min, Max hitpoints + AI_MEGA, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 110, // Hit% #1 + 8, // Hit check frame #1 + 14, 22, // Min, Max damage #1 + 0, // Hit% #2 + 3, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 65, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_IF, // Magic resist + M_RM+M_IF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2714 }, // Experience points + +// MT_VTEXLRD + { 160, 2220, // Image width, Image size + "Monsters\\Mega\\Mega%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Mega\\Mega%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Mega\\Vtexl.TRN", // Trans file?, Transformation file name + { 6, 7, 14, 1, 24, 5 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 2, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Vortex Lord", // Name + 23, 26, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 160, 180, // Min, Max hitpoints + AI_MEGA, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 8, // Hit check frame #1 + 18, 24, // Min, Max damage #1 + 0, // Hit% #2 + 3, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_IF+M_II, // Magic resist + M_RM+M_RL+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3252 }, // Experience points + +// MT_BALROG + { 160, 2220, // Image width, Image size + "Monsters\\Mega\\Mega%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Mega\\Mega%c%i.WAV", // Sound files + TRUE, // Special sound + TRUE, "Monsters\\Mega\\Balr.TRN", // Trans file?, Transformation file name + { 6, 7, 14, 1, 24, 5 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 2, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Balrog", // Name + 25, 29, // Min, Max dungeon level + 26, // Monster level ranking (1 = easy, 30 = hardest) + 180, 200, // Min, Max hitpoints + AI_MEGA, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 130, // Hit% #1 + 8, // Hit check frame #1 + 22, 30, // Min, Max damage #1 + 0, // Hit% #2 + 3, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 75, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_IF+M_II, // Magic resist + M_RM+M_RL+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3643 }, // Experience points + +// MT_NSNAKE + { 160, 1270, // Image width, Image size + "Monsters\\Snake\\Snake%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Snake\\Snake%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 11, 13, 5, 18, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Cave Viper", // Name + 20, 24, // Min, Max dungeon level + 21, // Monster level ranking (1 = easy, 30 = hardest) + 100, 150, // Min, Max hitpoints + AI_SNAKE, + MFLAG_PATH, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 90, // Hit% #1 + 8, // Hit check frame #1 + 8, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_IM, // Magic resist + M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2725 }, // Experience points + +// MT_RSNAKE + { 160, 1270, // Image width, Image size + "Monsters\\Snake\\Snake%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Snake\\Snake%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Snake\\SnakR.TRN", // Trans file?, Transformation file name + { 12, 11, 13, 5, 18, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Fire Drake", // Name + 22, 26, // Min, Max dungeon level + 23, // Monster level ranking (1 = easy, 30 = hardest) + 120, 170, // Min, Max hitpoints + AI_SNAKE, + MFLAG_PATH, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 105, // Hit% #1 + 8, // Hit check frame #1 + 12, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 65, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_IM, // Magic resist + M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3139 }, // Experience points + +// MT_BSNAKE + { 160, 1270, // Image width, Image size + "Monsters\\Snake\\Snake%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Snake\\Snake%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Snake\\Snakg.TRN", // Trans file?, Transformation file name + { 12, 11, 13, 5, 18, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Gold Viper", // Name + 24, 27, // Min, Max dungeon level + 25, // Monster level ranking (1 = easy, 30 = hardest) + 140, 180, // Min, Max hitpoints + AI_SNAKE, + MFLAG_PATH, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 8, // Hit check frame #1 + 15, 26, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_IM, // Magic resist + M_RL+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3540 }, // Experience points + +// MT_GSNAKE + { 160, 1270, // Image width, Image size + "Monsters\\Snake\\Snake%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Snake\\Snake%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Snake\\Snakb.TRN", // Trans file?, Transformation file name + { 12, 11, 13, 5, 18, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 1, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Azure Drake", // Name + 28, 30, // Min, Max dungeon level + 27, // Monster level ranking (1 = easy, 30 = hardest) + 160, 200, // Min, Max hitpoints + AI_SNAKE, + MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 130, // Hit% #1 + 8, // Hit check frame #1 + 18, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 75, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_RL, // Magic resist + M_IL+M_RF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3791 }, // Experience points + +// MT_NBLACK + { 160, 2120, // Image width, Image size + "Monsters\\Black\\Black%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Black\\Black%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 8, 8, 16, 4, 24, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Black Knight", // Name + 23, 27, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 150, 150, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 110, // Hit% #1 + 8, // Hit check frame #1 + 15, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 75, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_RM+M_II, // Magic resist + M_RM+M_IL+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3360 }, // Experience points + +// MT_RTBLACK + { 160, 2120, // Image width, Image size + "Monsters\\Black\\Black%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Black\\Black%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Black\\BlkKntRT.TRN", // Trans file?, Transformation file name + { 8, 8, 16, 4, 24, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Doom Guard", // Name + 25, 29, // Min, Max dungeon level + 26, // Monster level ranking (1 = easy, 30 = hardest) + 165, 165, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 130, // Hit% #1 + 8, // Hit check frame #1 + 18, 25, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 75, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_RM+M_II, // Magic resist + M_RM+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3650 }, // Experience points + +// MT_BTBLACK + { 160, 2120, // Image width, Image size + "Monsters\\Black\\Black%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Black\\Black%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Black\\BlkKntBT.TRN", // Trans file?, Transformation file name + { 8, 8, 16, 4, 24, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Steel Lord", // Name + 27, 30, // Min, Max dungeon level + 28, // Monster level ranking (1 = easy, 30 = hardest) + 180, 180, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 8, // Hit check frame #1 + 20, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 80, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_RM+M_IF+M_II, // Magic resist + M_RL+M_IM+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 4252 }, // Experience points + +// MT_RBLACK + { 160, 2120, // Image width, Image size + "Monsters\\Black\\Black%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Black\\Black%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Black\\BlkKntBe.TRN", // Trans file?, Transformation file name + { 8, 8, 16, 4, 24, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Blood Knight", // Name + 24, 26, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 200, 200, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 130, // Hit% #1 + 8, // Hit check frame #1 + 25, 35, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 85, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_IL+M_II+M_IM, // Magic resist + M_RF+M_IL+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 5130 }, // Experience points + +// MT_UNRAV + { 96, 484, // Image width, Image size + "Monsters\\Unrav\\Unrav%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Shred%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 10, 12, 5, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "The Shredded", // Name + 32, 35, // Min, Max dungeon level + 23, // Monster level ranking (1 = easy, 30 = hardest) + 70, 90, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 75, // Hit% #1 + 7, // Hit check frame #1 + 4, 12, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 65, // Armor Class + MC_UNDEAD, // Monster Class + M_RF+M_RL+M_II, // Magic resist + M_RF+M_RL+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 900 }, // Experience points + +// MT_HOLOWONE + { 96, 484, // Image width, Image size + "Monsters\\Unrav\\Unrav%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 10, 12, 5, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hollow One", // Name + 34, 37, // Min, Max dungeon level + 27, // Monster level ranking (1 = easy, 30 = hardest) + 135, 240, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 75, // Hit% #1 + 7, // Hit check frame #1 + 12, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 75, // Armor Class + MC_UNDEAD, // Monster Class + M_RL+M_IM+M_IF+M_II, // Magic resist + M_RL+M_IM+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 4374 }, // Experience points + +// MT_PAINMSTR + { 96, 484, // Image width, Image size + "Monsters\\Unrav\\Unrav%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 10, 12, 5, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Pain Master", // Name + 36, 39, // Min, Max dungeon level + 29, // Monster level ranking (1 = easy, 30 = hardest) + 110, 200, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 7, // Hit check frame #1 + 16, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 80, // Armor Class + MC_UNDEAD, // Monster Class + M_RL+M_IM+M_IF+M_II, // Magic resist + M_RL+M_IM+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 5147 }, // Experience points + +// MT_REALWEAV + { 96, 484, // Image width, Image size + "Monsters\\Unrav\\Unrav%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Acid\\Acid%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 10, 12, 5, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Reality Weaver", // Name + 38, 39, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 135, 240, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 85, // Hit% #1 + 7, // Hit check frame #1 + 20, 35, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 85, // Armor Class + MC_UNDEAD, // Monster Class + M_RM+M_IL+M_IF+M_II, // Magic resist + M_RM+M_IL+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 5925 }, // Experience points + +// MT_SUCCUBUS + { 128, 980, // Image width, Image size + "Monsters\\Succ\\Scbs%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Succ\\Scbs%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 14, 8, 16, 7, 24, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Succubus", // Name + 22, 26, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 120, 150, // Min, Max hitpoints + AI_SUCC, + MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 100, // Hit% #1 + 10, // Hit check frame #1 + 1, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_RM, // Magic resist + M_IM+M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 3696 }, // Experience points + +// MT_SNOWWICH + { 128, 980, // Image width, Image size + "Monsters\\Succ\\Scbs%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Succ\\Scbs%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Succ\\Succb.TRN", // Trans file?, Transformation file name + { 14, 8, 16, 7, 24, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Snow Witch", // Name + 25, 28, // Min, Max dungeon level + 26, // Monster level ranking (1 = easy, 30 = hardest) + 135, 175, // Min, Max hitpoints + AI_SUCC, + MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 110, // Hit% #1 + 10, // Hit check frame #1 + 1, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 65, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_II, // Magic resist + M_IM+M_II+M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 4084 }, // Experience points + +// MT_HLSPWN + { 128, 980, // Image width, Image size + "Monsters\\Succ\\Scbs%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Succ\\Scbs%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Succ\\Succrw.TRN", // Trans file?, Transformation file name + { 14, 8, 16, 7, 24, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hell Spawn", // Name + 27, 30, // Min, Max dungeon level + 28, // Monster level ranking (1 = easy, 30 = hardest) + 150, 200, // Min, Max hitpoints + AI_SUCC, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 115, // Hit% #1 + 10, // Hit check frame #1 + 1, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 75, // Armor Class + MC_ANIMAL, // Monster Class + M_RM+M_IL, // Magic resist + M_IM+M_IF+M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 4480 }, // Experience points + +// MT_SOLBRNR + { 128, 980, // Image width, Image size + "Monsters\\Succ\\Scbs%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\Succ\\Scbs%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Succ\\Succbw.TRN", // Trans file?, Transformation file name + { 14, 8, 16, 7, 24, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Soul Burner", // Name + 28, 30, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 140, 225, // Min, Max hitpoints + AI_SUCC, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 10, // Hit check frame #1 + 1, 35, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 85, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_RL+M_IF, // Magic resist + M_IM+M_IL+M_IF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 4644 }, // Experience points + +// MT_COUNSLR + { 128, 2000, // Image width, Image size + "Monsters\\Mage\\Mage%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Mage\\Mage%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 1, 20, 8, 28, 20 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Counselor", // Name + 24, 26, // Min, Max dungeon level + 25, // Monster level ranking (1 = easy, 30 = hardest) + 70, 70, // Min, Max hitpoints + AI_COUNSLR, + MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 90, // Hit% #1 + 8, // Hit check frame #1 + 8, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_RL+M_RF, // Magic resist + M_RM+M_RL+M_RF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 4070 }, // Experience points + +// MT_MAGISTR + { 128, 2000, // Image width, Image size + "Monsters\\Mage\\Mage%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Mage\\Mage%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Mage\\Cnselg.TRN", // Trans file?, Transformation file name + { 12, 1, 20, 8, 28, 20 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Magistrate", // Name + 26, 28, // Min, Max dungeon level + 27, // Monster level ranking (1 = easy, 30 = hardest) + 85, 85, // Min, Max hitpoints + AI_COUNSLR, + MFLAG_CHECKDOORS, // ai related flags + 1, // Intelligence (0 = easiest, 3 = hardest of type) + 100, // Hit% #1 + 8, // Hit check frame #1 + 10, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_RL+M_II+M_IF,// Magic resist + M_IM+M_RL+M_II+M_IF,// Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 4478 }, // Experience points + +// MT_CABALIST + { 128, 2000, // Image width, Image size + "Monsters\\Mage\\Mage%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Mage\\Mage%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Mage\\Cnselgd.TRN", // Trans file?, Transformation file name + { 12, 1, 20, 8, 28, 20 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Cabalist", // Name + 28, 30, // Min, Max dungeon level + 29, // Monster level ranking (1 = easy, 30 = hardest) + 120, 120, // Min, Max hitpoints + AI_COUNSLR, + MFLAG_CHECKDOORS, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 110, // Hit% #1 + 8, // Hit check frame #1 + 14, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_RF+M_II+M_IL, // Magic resist + M_IM+M_RF+M_II+M_IL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 4929 }, // Experience points + +// MT_ADVOCATE + { 128, 2000, // Image width, Image size + "Monsters\\Mage\\Mage%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Mage\\Mage%c%i.WAV", // Sound files + FALSE, // Special sound + TRUE, "Monsters\\Mage\\Cnselbk.TRN", // Trans file?, Transformation file name + { 12, 1, 20, 8, 28, 20 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Advocate", // Name + 30, 30, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 145, 145, // Min, Max hitpoints + AI_COUNSLR, + MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 8, // Hit check frame #1 + 15, 25, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 0, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_IL+M_II+M_IM, // Magic resist + M_IM+M_IL+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 4968 }, // Experience points + +// MT_GOLEM + { 96, 386, // Image width, Image size + "Monsters\\Golem\\Golem%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Golem\\Golm%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 0, 16, 12, 0, 12, 20 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Golem", // Name + 0, 0, // Min, Max dungeon level + 12, // Monster level ranking (1 = easy, 30 = hardest) + 1, 1, // Min, Max hitpoints (calc in SPAWNGOLUM) + AI_GOLUM, // AI type + MFLAG_CHECKDOORS, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 0, // Hit% #1 (calc in SPAWNGOLUM) + 7, // Hit check frame #1 + 1, 1, // Min, Max damage #1 (calc in SPAWNGOLUM) + //0, 0, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 1, // Armor Class (calc in SPAWNGOLUM) + MC_DEMON, // Monster Class + 0, // Magic resist + 0, // Magic resist2 + 0, // Treasure + MSEL_NONE, // Selection Type + 0 }, // Experience points + +// MT_DIABLO + { 160, 2000, // Image width, Image size + "Monsters\\Diablo\\Diablo%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\Diablo\\Diablo%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 16, 6, 16, 2, 16, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "The Dark Lord", // Name + 50, 50, // Min, Max dungeon level + 45, // Monster level ranking (1 = easy, 30 = hardest) + 3333, 3333, // Min, Max hitpoints + AI_DIABLO, + MFLAG_KNOCKBACK|MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 220, // Hit% #1 + 4, // Hit check frame #1 + 30, 60, // Min, Max damage #1 + 0, // Hit% #2 + 11, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 90, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_RL+M_IM+M_II, // Magic resist + M_RF+M_RL+M_IM+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 31666 }, // Experience points + +// MT_DARKMAGE + { 128, 1060, // Image width, Image size + "Monsters\\DarkMage\\Dmage%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\DarkMage\\Dmag%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 6, 1, 21, 6, 23, 18 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "The Arch-Litch Malignus", // Name + 40, 41 /*24, 24*/, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 160, 160, // Min, Max hitpoints + AI_COUNSLR, + MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 8, // Hit check frame #1 + 20, 40, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_DEMON, // Monster Class + M_RM+M_RL+M_RF+M_II, // Magic resist + M_IM+M_IL+M_IF+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 4968 }, // Experience points + +//---------------------// +// New Monsters // +//---------------------// + +// Festering Nest + + { 188, 800 /*1250*/, // Image width, Image size + "Monsters\\Fork\\Fork%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\HBoar%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 10, 15, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hellboar", // Name + 32, 35, // Min, Max dungeon level + 23, // Monster level ranking (1 = easy, 30 = hardest) + 80, 100, // Min, Max hitpoints + AI_SKELSD, // eventually AI_RHINO? + MFLAG_PATH|MFLAG_KNOCKBACK, // ai related flags + 2, // Intelligence (0 = easiest, 3 = hardest of type) + 70, // Hit% #1 + 7, // Hit check frame #1 + 16, 24, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_DEMON, // Monster Class + M_NONE, // Magic resist + M_RL+M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 750}, // Experience points + + { 64, 305, // Image width, Image size + "Monsters\\Scorp\\Scorp%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Stingr%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 10, 12, 6, 15, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Stinger", // Name + 32, 35, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 30, 40, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 85, // Hit% #1 + 8, // Hit check frame #1 + 1, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RL, // Magic resist2 + 0, // Treasure + MSEL_FLR, // Selection Type + 500}, // Experience points + + { 156, 800 /*1156*/, // Image width, Image size + "Monsters\\Eye\\Eye%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\psyco%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 13, 13, 7, 21, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Psychorb", // Name + 32, 35, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 20, 30, // Min, Max hitpoints + AI_PSYCHORB, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 8, // Hit check frame #1 + 10, 10, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 40, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RF, // Magic resist2 + 0, // Treasure + MSEL_FLY, // Selection Type + 450}, // Experience points + + { 148, 800/*1000*/, // Image width, Image size + "Monsters\\Spider\\Spider%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\SLord%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 10, 15, 6, 20, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Arachnon", // Name + 32, 35, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 60, 80, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 50, // Hit% #1 + 8, // Hit check frame #1 + 5, 15, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 500}, // Experience points + + { 128, 800/*2000*/, // Image width, Image size + "Monsters\\TSneak\\TSneak%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\FTwin%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 13, 13, 15, 11, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Felltwin", // Name + 32, 35, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 50, 70, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 70, // Hit% #1 + 8, // Hit check frame #1 + 10, 18, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_DEMON, // Monster Class + M_II, // Magic resist + M_RF+M_RL+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 600}, // Experience points + + { 164, 520, // Image width, Image size + "Monsters\\Spawn\\Spawn%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\HSpawn%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 15, 12, 14, 11, 14, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hork Spawn", // Name + 34, 37, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 30, 30, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 10, 25, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 25, // Armor Class + MC_DEMON, // Monster Class + M_RM, // Magic resist + M_RM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 250}, // Experience points + + { 86, 305, // Image width, Image size + "Monsters\\WScorp\\WScorp%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Stingr%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 10, 12, 6, 15, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Venomtail", // Name + 36, 39, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 40, 50, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 85, // Hit% #1 + 8, // Hit check frame #1 + 1, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_ANIMAL, // Monster Class + M_RL, // Magic resist + M_IL, // Magic resist2 + 0, // Treasure + MSEL_FLR, // Selection Type + 1000}, // Experience points + + { 140, 800 /*1200*/, // Image width, Image size + "Monsters\\Eye2\\Eye2%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Psyco%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 13, 13, 7, 21, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Necromorb",// Name + 36, 39, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 30, 40, // Min, Max hitpoints + AI_NECROMORB, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 8, // Hit check frame #1 + 20, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_ANIMAL, // Monster Class + M_RF, // Magic resist + M_RL+M_IF, // Magic resist2 + 0, // Treasure + MSEL_FLY, // Selection Type + 1100}, // Experience points + + { 148, 800/*1100*/, // Image width, Image size + "Monsters\\bSpidr\\bSpidr%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\newsfx\\SLord%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 10, 15, 6, 20, 10 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Spider Lord", // Name + 36, 39, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 80, 100, // Min, Max hitpoints + AI_ACID, + MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 8, 20, // Min, Max damage #1 + 75, // Hit% #2 + 8, // Hit check frame #2 + 10, 10, // Min, Max damage #2 + 60, // Armor Class + MC_ANIMAL, // Monster Class + M_RL, // Magic resist + M_RF+M_IL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1250}, // Experience points + + { 176, 800 /* 1700 */, // Image width, Image size + "Monsters\\Clasp\\Clasp%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Lworm%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 12, 15, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Lashworm", // Name + 36, 39, // Min, Max dungeon level + 20, // Monster level ranking (1 = easy, 30 = hardest) + 30, 30, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 90, // Hit% #1 + 8, // Hit check frame #1 + 12, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 50, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 600}, // Experience points + + { 192, 800 /*1080*/, // Image width, Image size + "Monsters\\AntWorm\\Worm%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\TchAnt%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 14, 12, 12, 6, 20, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Torchant", // Name + 36, 39, // Min, Max dungeon level + 22, // Monster level ranking (1 = easy, 30 = hardest) + 60, 80, // Min, Max hitpoints + AI_HELLBAT, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 75, // Hit% #1 + 8, // Hit check frame #1 + 20, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_ANIMAL, // Monster Class + M_IF, // Magic resist + M_RL+M_RM+M_IF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 1250}, // Experience points + + { 138, 800/*2000*/, // Image width, Image size + "Monsters\\HorkD\\HorkD%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\newsfx\\HDemon%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 15, 8, 16, 6, 16, 9 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 2 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hork Demon", // Name + 36, 37, // Min, Max dungeon level + 27, // Monster level ranking (1 = easy, 30 = hardest) + 120, 160, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 60, // Hit% #1 + 8, // Hit check frame #1 + 20, 35, // Min, Max damage #1 + 80, // Hit% #2 + 8, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 80, // Armor Class + MC_DEMON, // Monster Class + M_RL, // Magic resist + M_RM+M_IL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2000}, // Experience points + + { 198, 800 /* 2000 */, // Image width, Image size + "Monsters\\Hellbug\\Hellbg%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\newsfx\\Defile%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 8, 8, 14, 6, 14, 12 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hell Bug", // Name + 38, 39, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 240, 240, // Min, Max hitpoints + AI_SKELSD, + MFLAG_PATH, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 110, // Hit% #1 + 8, // Hit check frame #1 + 20, 30, // Min, Max damage #1 + 90, // Hit% #2 + 8, // Hit check frame #2 + 50, 60, // Min, Max damage #2 + 80, // Armor Class + MC_DEMON, // Monster Class + M_RF+M_RM+M_IL, // Magic resist + M_RM+M_IF+M_IL, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 5000}, // Experience points + + +// Demon Crypt + + { 124, 800, // Image width, Image size + "Monsters\\Gravdg\\Gravdg%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\newsfx\\GDiggr%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 24, 24, 12, 6, 16, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Gravedigger", // Name + 40, 41, // Min, Max dungeon level + 26, // Monster level ranking (1 = easy, 30 = hardest) + 120, 240, // Min, Max hitpoints + AI_SCAV, + MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 80, // Hit% #1 + 6, // Hit check frame #1 + 2, 12, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 20, // Armor Class + MC_UNDEAD, // Monster Class + M_IL+M_II, // Magic resist + M_RF+M_RM+M_IL+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 2000}, // Experience points + + { 104, 550, // Image width, Image size + "Monsters\\Rat\\Rat%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\TmbRat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 11, 8, 12, 6, 20, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Tomb Rat", // Name + 40, 43, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 80, 120, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 8, // Hit check frame #1 + 12, 25, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 30, // Armor Class + MC_ANIMAL, // Monster Class + M_NONE, // Magic resist + M_RF+M_RL, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 1800}, // Experience points + + { 96, 550, // Image width, Image size + "Monsters\\Hellbat\\Helbat%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\HelBat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 18, 16, 14, 6, 18, 11}, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0}, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Firebat", // Name + 40, 43, // Min, Max dungeon level + 24, // Monster level ranking (1 = easy, 30 = hardest) + 60, 80, // Min, Max hitpoints + AI_FIREBAT, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 100, // Hit% #1 + 8, // Hit check frame #1 + 15, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_ANIMAL, // Monster Class + M_IF, // Magic resist + M_RL+M_RM+M_IF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 2400}, // Experience points + + { 128, 1740, // Image width, Image size + "Monsters\\Demskel\\Demskl%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\newsfx\\SWing%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, "Monsters\\Thin\\Thinv3.TRN", // Trans file?, Transformation file name + { 10, 8, 20, 6, 24, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Skullwing", // Name + 40, 43, // Min, Max dungeon level + 27, // Monster level ranking (1 = easy, 30 = hardest) + 70, 70, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 75, // Hit% #1 + 7, // Hit check frame #1 + 15, 20, // Min, Max damage #1 + 75, // Hit% #2 + 9, // Hit check frame #2 + 15, 20, // Min, Max damage #2 + 80, // Armor Class + MC_UNDEAD, // Monster Class + M_RF+M_RL+M_II, // Magic resist + M_RF+M_RL+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3000 }, // Experience points + + { 96, 800 /*1109*/, // Image width, Image size + "Monsters\\Lich\\Lich%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Lich%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 10, 10, 7, 21, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 2, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Lich", // Name + 40, 43, // Min, Max dungeon level + 25, // Monster level ranking (1 = easy, 30 = hardest) + 80, 100, // Min, Max hitpoints + AI_LICH, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 100, // Hit% #1 + 8, // Hit check frame #1 + 15, 20, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 60, // Armor Class + MC_UNDEAD, // Monster Class + M_RL+M_II, // Magic resist + M_RF+M_RM+M_IL+M_II, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 3000}, // Experience points + + { 154, 800 /* 1100 */, // Image width, Image size + "Monsters\\Bubba\\Bubba%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Crypt%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 8, 18, 12, 8, 21, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Crypt Demon", // Name + 42, 45, // Min, Max dungeon level + 28, // Monster level ranking (1 = easy, 30 = hardest) + 200, 240, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 100, // Hit% #1 + 8, // Hit check frame #1 + 20, 40, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 85, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_RF+M_IM, // Magic resist + M_RL+M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 3200}, // Experience points + + { 96, 550, // Image width, Image size + "Monsters\\Hellbat2\\bhelbt%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\newsfx\\HelBat%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 18, 16, 14, 6, 18, 11 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Hellbat", // Name + 44, 47, // Min, Max dungeon level + 29, // Monster level ranking (1 = easy, 30 = hardest) + 100, 140, // Min, Max hitpoints + AI_HELLBAT, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 110, // Hit% #1 + 8, // Hit check frame #1 + 30, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 80, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_RM+M_IF, // Magic resist + M_IL+M_RM+M_IF, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 3600}, // Experience points + + { 128, 1740, // Image width, Image size + "Monsters\\Demskel\\Demskl%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\newsfx\\SWing%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, "Monsters\\Thin\\Thinv3.TRN", // Trans file?, Transformation file name + { 10, 8, 20, 6, 24, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 3, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Bone Demon", // Name + 44, 47, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 240, 280, // Min, Max hitpoints + AI_BONED, + 0, // ai related flags + 0, // Intelligence (0 = easiest, 3 = hardest of type) + 100, // Hit% #1 + 8, // Hit check frame #1 + 40, 50, // Min, Max damage #1 + 160, // Hit% #2 + 12, // Hit check frame #2 + 50, 50, // Min, Max damage #2 + 50, // Armor Class + MC_UNDEAD, // Monster Class + M_IF+M_IL+M_II, // Magic resist + M_IF+M_IL+M_II, // Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 5000 }, // Experience points + + { 136, 800 /*1109*/, // Image width, Image size + "Monsters\\Lich2\\Lich2%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Lich%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 10, 10, 7, 21, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 2, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Arch Lich", // Name + 44, 47, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 180, 200, // Min, Max hitpoints + AI_ARCHLICH, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 8, // Hit check frame #1 + 30, 30, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 75, // Armor Class + MC_UNDEAD, // Monster Class + M_RF+M_RM+M_IL+M_II,// Magic resist + M_IF+M_IM+M_IL+M_II,// Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 4000}, // Experience points + + { 180, 800 /*1000*/, // Image width, Image size + "Monsters\\Byclps\\Byclps%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Biclop%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 10, 11, 16, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 2, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Biclops", // Name + 44, 47, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 200, 240, // Min, Max hitpoints + AI_SKELSD, + MFLAG_KNOCKBACK|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 90, // Hit% #1 + 8, // Hit check frame #1 + 40, 50, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 80, // Armor Class + MC_DEMON, // Monster Class + M_RL, // Magic resist + M_RL+M_RF, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 4000}, // Experience points + + { 164, 800 /* 1700 */, // Image width, Image size + "Monsters\\Flesh\\Flesh%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\FleshT%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 15, 24, 15, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Flesh Thing", // Name + 44, 47, // Min, Max dungeon level + 28, // Monster level ranking (1 = easy, 30 = hardest) + 300, 400, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 150, // Hit% #1 + 8, // Hit check frame #1 + 12, 18, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 70, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_RF+M_RM, // Magic resist + M_RL+M_RF+M_RM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 4000}, // Experience points + + { 180, 800 /* 1600 */, // Image width, Image size + "Monsters\\Reaper\\Reap%c" CEL_EXT, // Image files + FALSE, // Special animation + "Monsters\\newsfx\\Reaper%c%i.WAV", // Sound files + FALSE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 12, 10, 14, 6, 16, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 2, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Reaper", // Name + 44, 47, // Min, Max dungeon level + 30, // Monster level ranking (1 = easy, 30 = hardest) + 260, 300, // Min, Max hitpoints + AI_SKELSD, + 0, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 120, // Hit% #1 + 8, // Hit check frame #1 + 30, 35, // Min, Max damage #1 + 0, // Hit% #2 + 0, // Hit check frame #2 + 0, 0, // Min, Max damage #2 + 90, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_IF+M_IM, // Magic resist + M_IL+M_IF+M_IM, // Magic resist2 + 0, // Treasure + MSEL_REG, // Selection Type + 6000}, // Experience points + + { 226, 1200/* 2100 */, // Image width, Image size + "Monsters\\Nkr\\Nkr%c" CEL_EXT, // Image files + TRUE, // Special animation + "Monsters\\newsfx\\Nakrul%c%i.WAV", // Sound files + TRUE, // Special sound + FALSE, NULL, // Trans file?, Transformation file name + { 2, 6, 16, 3, 16, 16 }, // Neutral, Walk, Attack, Get Hit, Death, Special (# frames) + { 0, 0, 0, 0, 0, 0 }, // Neutral, Walk, Attack, Get Hit, Death, Special (anim delays) + "Na-Krul", // Name + 60, 60, // Min, Max dungeon level + 40, // Monster level ranking (1 = easy, 30 = hardest) + 1332, 1332, // Min, Max hitpoints + AI_SKELSD, + MFLAG_KNOCKBACK|MFLAG_PATH|MFLAG_CHECKDOORS, // ai related flags + 3, // Intelligence (0 = easiest, 3 = hardest of type) + 150, // Hit% #1 + 7, // Hit check frame #1 + 40, 50, // Min, Max damage #1 + 150, // Hit% #2 + 10, // Hit check frame #2 + 40, 50, // Min, Max damage #2 + 125, // Armor Class + MC_DEMON, // Monster Class + M_RL+M_IF+M_IM+M_II,// Magic resist + M_IL+M_IF+M_IM+M_II,// Magic resist2 + 0, // Treasure + MSEL_BIG, // Selection Type + 13333}, // Experience points + +}; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +int MonstConvTbl[] = { + + MT_NZOMBIE, + MT_BZOMBIE, + MT_GZOMBIE, + MT_YZOMBIE, + + MT_RFALLSP, + MT_DFALLSP, + MT_YFALLSP, + MT_BFALLSP, + + MT_WSKELAX, + MT_TSKELAX, + MT_RSKELAX, + MT_XSKELAX, + + MT_RFALLSD, + MT_DFALLSD, + MT_YFALLSD, + MT_BFALLSD, + + MT_NSCAV, + MT_BSCAV, + MT_WSCAV, + MT_YSCAV, + + MT_WSKELBW, + MT_TSKELBW, + MT_RSKELBW, + MT_XSKELBW, + + MT_WSKELSD, + MT_TSKELSD, + MT_RSKELSD, + MT_XSKELSD, + + //MT_INVILORD, + + MT_SNEAK, + MT_STALKER, + MT_UNSEEN, + MT_ILLWEAV, + + //MT_LRDSAYTR, + + MT_NGOATMC, + MT_BGOATMC, + MT_RGOATMC, + MT_GGOATMC, + + MT_FIEND, + MT_GLOOM, + MT_BLINK, + MT_FAMILIAR, + + MT_NGOATBW, + MT_BGOATBW, + MT_RGOATBW, + MT_GGOATBW, + + MT_NACID, + MT_RACID, + MT_BACID, + MT_XACID, + + MT_SKING, + MT_FAT, + MT_MUDMAN, + MT_TOAD, + MT_FLAYED, + + MT_WYRM, + MT_CAVSLUG, + MT_DEVOUR, + MT_DVLWYRM, + + MT_NMAGMA, + MT_YMAGMA, + MT_BMAGMA, + MT_WMAGMA, + MT_HORNED, + MT_MUDRUN, + MT_FROSTC, + MT_OBLORD, + MT_BONEDMN, + MT_REDDTH, + MT_LTCHDMN, + MT_UDEDBLRG, + + 0, + 0, + 0, + 0, + + MT_INCIN, + MT_FLAMLRD, + MT_DOOMFIRE, + MT_HELLBURN, + + 0, + 0, + 0, + 0, + + MT_RSTORM, + MT_STORM, + MT_STORML, + MT_MAEL, + + MT_WINGED, + MT_GARGOYLE, + MT_BLOODCLW, + MT_DEATHW, + MT_MEGA, + MT_GUARD, + MT_VTEXLRD, + MT_BALROG, + MT_NSNAKE, + MT_RSNAKE, + + MT_GSNAKE, + MT_BSNAKE, + + MT_NBLACK, + MT_RTBLACK, + MT_BTBLACK, + MT_RBLACK, + MT_UNRAV, + MT_HOLOWONE, + MT_PAINMSTR, + MT_REALWEAV, + MT_SUCCUBUS, + MT_SNOWWICH, + MT_HLSPWN, + MT_SOLBRNR, + MT_COUNSLR, + MT_MAGISTR, + MT_CABALIST, + MT_ADVOCATE, + + 0, + MT_DIABLO, + 0, + MT_GOLEM, + 0, //BlackWound + 0, //SinWar + 0, + 0, //Lazarus + 0, //Warlord + 0, //FleshDoom + 0, //Snotspil + 0, //Temptress + 0, //Lachdanan + MT_BIGFALL, + MT_DARKMAGE, + + + MT_FORK, + MT_SCORP, + MT_EYE, + MT_SPIDER, + MT_FELLTWIN, + MT_SPAWN, + MT_SCORP, + MT_EYE, + MT_SPIDER, + MT_LASH, + MT_ANT, + MT_HORKD, + MT_BUG, + + MT_GRAVDG, + MT_RAT, + MT_HELLBAT, + MT_BONED, + MT_LICH, + MT_BUBBA, + MT_HELLBAT, + MT_BONED, + MT_LICH, + MT_BYCLPS, + MT_FLESH, + MT_REAPER, + MT_NKR, +}; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +int MonstAvailTbl[] = { + MAT_SW, // MT_NZOMBIE + MAT_SW, // MT_BZOMBIE + MAT_SW, // MT_GZOMBIE + MAT_SW, // MT_YZOMBIE + + MAT_SW, // MT_RFALLSP + MAT_SW, // MT_DFALLSP + MAT_SW, // MT_YFALLSP + MAT_SW, // MT_BFALLSP + + MAT_SW, // MT_WSKELAX + MAT_SW, // MT_TSKELAX + MAT_SW, // MT_RSKELAX + MAT_SW, // MT_XSKELAX + + MAT_SW, // MT_RFALLSD + MAT_SW, // MT_DFALLSD + MAT_SW, // MT_YFALLSD + MAT_SW, // MT_BFALLSD + + MAT_SW, // MT_NSCAV + MAT_SW, // MT_BSCAV + MAT_SW, // MT_WSCAV + MAT_SW, // MT_YSCAV + + MAT_SW, // MT_WSKELBW + MAT_SW, // MT_TSKELBW + MAT_SW, // MT_RSKELBW + MAT_SW, // MT_XSKELBW + + MAT_SW, // MT_WSKELSD + MAT_SW, // MT_TSKELSD + MAT_SW, // MT_RSKELSD + MAT_SW, // MT_XSKELSD + + MAT_NO, // MT_INVILORD 8/15 + + MAT_YES, // MT_SNEAK + MAT_YES, // MT_STALKER + MAT_YES, // MT_UNSEEN + MAT_YES, // MT_ILLWEAV + + MAT_YES, // MT_LRDSAYTR 8/15 + + MAT_YES, // MT_NGOATMC + MAT_YES, // MT_BGOATMC + MAT_YES, // MT_RGOATMC + MAT_YES, // MT_GGOATMC + + MAT_SW, // MT_FIEND + MAT_SW, // MT_BLINK + MAT_SW, // MT_GLOOM + MAT_SW, // MT_FAMILIAR + + MAT_YES, // MT_NGOATBW + MAT_YES, // MT_BGOATBW + MAT_YES, // MT_RGOATBW + MAT_YES, // MT_GGOATBW + + MAT_YES, // MT_NACID + MAT_YES, // MT_RACID + MAT_YES, // MT_BACID + MAT_YES, // MT_XACID + + MAT_NO, // MT_SKING + + MAT_NO, // MT_CLEAVER + + MAT_YES, // MT_FAT + MAT_YES, // MT_MUDMAN + MAT_YES, // MT_TOAD + MAT_YES, // MT_FLAYED + + MAT_NO, // MT_WYRM + MAT_NO, // MT_CAVSLUG + MAT_NO, // MT_DVLWYRM + MAT_NO, // MT_DEVOUR + + MAT_YES, // MT_NMAGMA + MAT_YES, // MT_YMAGMA + MAT_YES, // MT_BMAGMA + MAT_YES, // MT_WMAGMA + + MAT_YES, // MT_HORNED + MAT_YES, // MT_MUDRUN + MAT_YES, // MT_FROSTC + MAT_YES, // MT_OBLORD + + MAT_NO, // MT_BONEDMN 8/15 + MAT_NO, // MT_REDDTH + MAT_NO, // MT_LTCHDMN + MAT_NO, // MT_UDEDBLRG + + MAT_NO, // MT_INCIN 8/15 + MAT_NO, // MT_FLAMLRD 8/15 + MAT_NO, // MT_DOOMFIRE 8/15 + MAT_NO, // MT_HELLBURN 8/15 + + MAT_YES, // MT_STORM + MAT_YES, // MT_RSTORM + MAT_YES, // MT_STORML + MAT_YES, // MT_MAEL + + MAT_YES, // MT_BIGFALL 8/15 + + MAT_YES, // MT_WINGED + MAT_YES, // MT_GARGOYLE + MAT_YES, // MT_BLOODCLW + MAT_YES, // MT_DEATHW + + MAT_YES, // MT_MEGA + MAT_YES, // MT_GUARD + MAT_YES, // MT_VTEXLRD + MAT_YES, // MT_BALROG + + MAT_YES, // MT_NSNAKE + MAT_YES, // MT_RSNAKE + MAT_YES, // MT_BSNAKE + MAT_YES, // MT_GSNAKE + + MAT_YES, // MT_NBLACK + MAT_YES, // MT_RTBLACK + MAT_YES, // MT_BTBLACK + MAT_YES, // MT_RBLACK + + MAT_YES, // MT_UNRAV + MAT_NO, // MT_HOLOWONE + MAT_NO, // MT_PAINMSTR + MAT_NO, // MT_REALWEAV + + MAT_YES, // MT_SUCCUBUS + MAT_YES, // MT_SNOWICH + MAT_YES, // MT_HLSPWN + MAT_YES, // MT_SOLBURNR + + MAT_YES, // MT_COUNSLR + MAT_YES, // MT_MAGISTR + MAT_YES, // MT_CABALIST + MAT_YES, // MT_ADVOCATE + + MAT_NO, // MT_GOLEM + + MAT_NO, // MT_DIABLO + + MAT_NO, // MT_DARKMAGE 8/15 + + MAT_YES, // MT_FORK + MAT_YES, // MT_SCORP + MAT_YES, // MT_EYE + MAT_YES, // MT_SPIDER + MAT_YES, // MT_INVILORD + MAT_YES, // MT_SPAWN + MAT_YES, // MT_SCORP2 + MAT_YES, // MT_EYE2 + MAT_YES, // MT_SPIDER2 + MAT_YES, // MT_LASH + MAT_YES, // MT_ANT + MAT_NO, // MT_HORKD + MAT_NO, // MT_BUG + + MAT_YES, // MT_GRAVDG + MAT_YES, // MT_RAT + MAT_YES, // MT_HELLBAT + MAT_YES, // MT_BONED + MAT_YES, // MT_LICH + MAT_YES, // MT_BUBBA + MAT_YES, // MT_HELLBAT2 + MAT_YES, // MT_BONED2 + MAT_YES, // MT_LICH2 + MAT_YES, // MT_BYCLPS + MAT_YES, // MT_FLESH + MAT_YES, // MT_REAPER + MAT_NO, // MT_NKR +}; + +UniqMonstStruct UniqMonst[] = +{ +#if IS_VERSION(RETAIL) + // The first few are quest monsters and must go in this order for indexing + { + MT_NGOATMC, // i.e. MT_SKELSD + "Gharbad the Weak", // Monster Name + "BSDB", // Translation filename + 4, // level on which it appears + 120, // Hit Points + AI_GARBUD, // AI type + 3, // AI level + 8, // min damage + 16, // max damage + M_IL+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + TXT_GARB1 // Talking monster message number + }, + + { + MT_SKING, // i.e. MT_SKELSD + "Skeleton King", // Monster Name + "GENRL", // Translation filename + 0, // level on which it appears + 240, // Hit Points + AI_SKELKING, // AI type + 3, // AI level + 6, // min damage + 16, // max damage + M_RF+M_RL+M_IM+M_II, // Magic resistance + UN_PACK, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_COUNSLR, // i.e. MT_SKELSD *** Has to be the first level 8 monster loaded *** + "Zhar the Mad", // Monster Name + "GENERAL", // Translation filename + 8, // level on which it appears + 360, // Hit Points + AI_ZHAR, // AI type + 3, // AI level + 16, // min damage + 40, // max damage + M_RF+M_RL+M_IM, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + TXT_ZHAR1 // Talking monster message number + }, + + { + MT_BFALLSP, // i.e. MT_SKELSD + "Snotspill", // Monster Name + "BNG", // Translation filename + 4, // level on which it appears + 220, // Hit Points + AI_SNOTSPIL, // AI type + 3, // AI level + 10, // min damage + 18, // max damage + M_RL, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + TXT_BOL1 // Talking monster message number + }, + + { + MT_ADVOCATE, // i.e. MT_SKELSD + "Arch-Bishop Lazarus", // Monster Name + "GENERAL", // Translation filename + 0, // level on which it appears + 600, // Hit Points + AI_LAZURUS, // AI type + 3, // AI level + 30, // min damage + 50, // max damage + M_RF+M_RL+M_IM+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + TXT_VB1 // Talking monster message number + }, + + { + MT_HLSPWN, // i.e. MT_SKELSD + "Red Vex", // Monster Name + "REDV", // Translation filename + 0, // level on which it appears + 400, // Hit Points + AI_LAZHELP, // AI type + 3, // AI level + 30, // min damage + 50, // max damage + M_RF+M_IM+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + TXT_VB1 // Talking monster message number + }, + + { + MT_HLSPWN, // i.e. MT_SKELSD + "BlackJade", // Monster Name + "BLKJD", // Translation filename + 0, // level on which it appears + 400, // Hit Points + AI_LAZHELP, // AI type + 3, // AI level + 30, // min damage + 50, // max damage + M_RL+M_IM+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + TXT_VB1 // Talking monster message number + }, + + { + MT_RBLACK, // i.e. MT_SKELSD + "Lachdanan", // Monster Name + "BHKA", // Translation filename + 14, // level on which it appears + 500, // Hit Points + AI_LACHDANAN, // AI type + 3, // AI level + 0, // min damage + 0, // max damage + 0, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + TXT_VEIL1 // Talking monster message number + }, + + { + MT_BTBLACK, // i.e. MT_SKELSD + "Warlord of Blood", // Monster Name + "GENERAL", // Translation filename + 13, // level on which it appears + 850, // Hit Points + AI_WARLORD, // AI type + 3, // AI level + 35, // min damage + 50, // max damage + M_IF+M_IL+M_IM+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + TXT_WARLRD1 // Talking monster message number + }, + + { + MT_CLEAVER, // i.e. MT_SKELSD + "The Butcher", // Monster Name + "GENRL", // Translation filename + 0, // level on which it appears + 220, // Hit Points + AI_CLEAVER, // AI type + 3, // AI level + 6, // min damage + 12, // max damage + M_RF+M_RL+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_HORKD, // i.e. MT_SKELSD + "Hork Demon", // Monster Name + "GENRL", // Translation filename + 19, // level on which it appears + 300, // Hit Points + AI_HORKDEMON, // AI type + 3, // AI level + 20, // min damage + 35, // max damage + M_RL, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BUG, // i.e. MT_SKELSD + "The Defiler", // Monster Name + "GENRL", // Translation filename + 20, // level on which it appears + 480, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 30, // min damage + 40, // max damage + M_RF+M_RM+M_IL, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NKR, // i.e. MT_SKELSD + "Na-Krul", // Monster Name + "GENRL", // Translation filename + 0, // level on which it appears + 1332, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 40, // min damage + 50, // max damage + M_IL+M_IF+M_IM+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + // From here down are random unique monsters + { + MT_TSKELAX, // i.e. MT_SKELSD + "Bonehead Keenaxe", // Monster Name + "BHKA", // Translation filename + 2, // level on which it appears + 91, // Hit Points + AI_SKELSD, // AI type + 2, // AI level + 4, // min damage + 10, // max damage + M_II+M_IM, // Magic resistance + UN_L|UN_H, // Unique attributes, i.e., pack leader + 100, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RFALLSD, // i.e. MT_SKELSD + "Bladeskin the Slasher",// Monster Name + "BSTS", // Translation filename + 2, // level on which it appears + 51, // Hit Points + AI_FALLEN, // AI type + 0, // AI level + 6, // min damage + 18, // max damage + M_RF, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 45, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NZOMBIE, // i.e. MT_SKELSD + "Soulpus", // Monster Name + "GENERAL", // Translation filename + 2, // level on which it appears + 133, // Hit Points + AI_ZOMBIE, // AI type + 0, // AI level + 4, // min damage + 8, // max damage + M_RF+M_RL, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RFALLSP, // i.e. MT_SKELSD + "Pukerat the Unclean", // Monster Name + "PTU", // Translation filename + 2, // level on which it appears + 77, // Hit Points + AI_FALLEN, // AI type + 3, // AI level + 1, // min damage + 5, // max damage + M_RF, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_WSKELAX, // i.e. MT_SKELSD + "Boneripper", // Monster Name + "BR", // Translation filename + 2, // level on which it appears + 54, // Hit Points + AI_BAT, // AI type + 0, // AI level + 6, // min damage + 15, // max damage + M_IF+M_II+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NZOMBIE, // i.e. MT_SKELSD + "Rotfeast the Hungry", // Monster Name + "ETH", // Translation filename + 2, // level on which it appears + 85, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 4, // min damage + 12, // max damage + M_II+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_DFALLSD, // i.e. MT_SKELSD + "Gutshank the Quick", // Monster Name + "GTQ", // Translation filename + 3, // level on which it appears + 66, // Hit Points + AI_BAT, // AI type + 2, // AI level + 6, // min damage + 16, // max damage + M_RF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_TSKELSD, // i.e. MT_SKELSD + "Brokenhead Bangshield", // Monster Name + "BHBS", // Translation filename + 3, // level on which it appears + 108, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 12, // min damage + 20, // max damage + M_RL+M_II+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_YFALLSP, // i.e. MT_SKELSD + "Bongo", // Monster Name + "BNG", // Translation filename + 3, // level on which it appears + 178, // Hit Points + AI_FALLEN, // AI type + 3, // AI level + 9, // min damage + 21, // max damage + M_NONE, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BZOMBIE, // i.e. MT_SKELSD + "Rotcarnage", // Monster Name + "RCRN", // Translation filename + 3, // level on which it appears + 102, // Hit Points + AI_ZOMBIE, // AI type + 3, // AI level + 9, // min damage + 24, // max damage + M_RL+M_II+M_IM, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 45, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NSCAV, // i.e. MT_SKELSD + "Shadowbite", // Monster Name + "SHBT", // Translation filename + 2, // level on which it appears + 60, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 3, // min damage + 20, // max damage + M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_WSKELBW, // i.e. MT_SKELSD + "Deadeye", // Monster Name + "DE", // Translation filename + 2, // level on which it appears + 49, // Hit Points + AI_GOATBOW, // AI type + 0, // AI level + 6, // min damage + 9, // max damage + M_RF+M_II+M_IM, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RSKELAX, // i.e. MT_SKELSD + "Madeye the Dead", // Monster Name + "MTD", // Translation filename + 4, // level on which it appears + 75, // Hit Points + AI_BAT, // AI type + 0, // AI level + 9, // min damage + 21, // max damage + M_IF+M_IM, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 30, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BSCAV, // i.e. MT_SKELSD + "El Chupacabras", // Monster Name + "GENERAL", // Translation filename + 3, // level on which it appears + 120, // Hit Points + AI_GOATMC, // AI type + 0, // AI level + 10, // min damage + 18, // max damage + M_RF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 30, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_TSKELBW, // i.e. MT_SKELSD + "Skullfire", // Monster Name + "SKFR", // Translation filename + 3, // level on which it appears + 125, // Hit Points + AI_GOATBOW, // AI type + 1, // AI level + 6, // min damage + 10, // max damage + M_IF, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 100, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_SNEAK, // i.e. MT_SKELSD + "Warpskull", // Monster Name + "TSPO", // Translation filename + 3, // level on which it appears + 117, // Hit Points + AI_SNEAK, // AI type + 2, // AI level + 6, // min damage + 18, // max damage + M_RF+M_RL, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_GZOMBIE, // i.e. MT_SKELSD + "Goretongue", // Monster Name + "PMR", // Translation filename + 3, // level on which it appears + 156, // Hit Points + AI_SKELSD, // AI type + 1, // AI level + 15, // min damage + 30, // max damage + M_II+M_IM, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_WSCAV, // i.e. MT_SKELSD + "Pulsecrawler", // Monster Name + "BHKA", // Translation filename + 4, // level on which it appears + 150, // Hit Points + AI_SCAV, // AI type + 0, // AI level + 16, // min damage + 20, // max damage + M_RL+M_IF, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 45, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BLINK, // i.e. MT_SKELSD + "Moonbender", // Monster Name + "GENERAL", // Translation filename + 4, // level on which it appears + 135, // Hit Points + AI_BAT, // AI type + 0, // AI level + 9, // min damage + 27, // max damage + M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BLINK, // i.e. MT_SKELSD + "Wrathraven", // Monster Name + "GENERAL", // Translation filename + 5, // level on which it appears + 135, // Hit Points + AI_BAT, // AI type + 2, // AI level + 9, // min damage + 22, // max damage + M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_YSCAV, // i.e. MT_SKELSD + "Spineeater", // Monster Name + "GENERAL", // Translation filename + 4, // level on which it appears + 180, // Hit Points + AI_SCAV, // AI type + 1, // AI level + 18, // min damage + 25, // max damage + M_IL+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RSKELBW, // i.e. MT_SKELSD + "Blackash the Burning", // Monster Name + "BASHTB", // Translation filename + 4, // level on which it appears + 120, // Hit Points + AI_GOATBOW, // AI type + 0, // AI level + 6, // min damage + 16, // max damage + M_IF+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BFALLSD, // i.e. MT_SKELSD + "Shadowcrow", // Monster Name + "GENERAL", // Translation filename + 5, // level on which it appears + 270, // Hit Points + AI_SNEAK, // AI type + 2, // AI level + 12, // min damage + 25, // max damage + M_NONE, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_LRDSAYTR, // i.e. MT_SKELSD + "Blightstone the Weak", // Monster Name + "BHKA", // Translation filename + 4, // level on which it appears + 360, // Hit Points + AI_SKELSD, // AI type + 0, // AI level + 4, // min damage + 12, // max damage + M_RL+M_IM, // Magic resistance + UN_L|UN_H, // Unique attributes, i.e., pack leader + 70, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_FAT, // i.e. MT_SKELSD + "Bilefroth the Pit Master", // Monster Name + "BFTP", // Translation filename + 6, // level on which it appears + 210, // Hit Points + AI_BAT, // AI type + 1, // AI level + 16, // min damage + 23, // max damage + M_RL+M_IM+M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NGOATBW, // i.e. MT_SKELSD + "Bloodskin Darkbow", // Monster Name + "BSDB", // Translation filename + 5, // level on which it appears + 207, // Hit Points + AI_GOATBOW, // AI type + 0, // AI level + 3, // min damage + 16, // max damage + M_RF+M_RL, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 55, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_GLOOM, // i.e. MT_SKELSD + "Foulwing", // Monster Name + "DB", // Translation filename + 5, // level on which it appears + 246, // Hit Points + AI_RHINO, // AI type + 3, // AI level + 12, // min damage + 28, // max damage + M_RF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_XSKELSD, // i.e. MT_SKELSD + "Shadowdrinker", // Monster Name + "SHDR", // Translation filename + 5, // level on which it appears + 300, // Hit Points + AI_SNEAK, // AI type + 1, // AI level + 18, // min damage + 26, // max damage + M_RF+M_RL+M_II+M_IM, // Magic resistance + UN_A, // Unique attributes, i.e., pack leader + 45, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_UNSEEN, // i.e. MT_SKELSD + "Hazeshifter", // Monster Name + "BHKA", // Translation filename + 5, // level on which it appears + 285, // Hit Points + AI_SNEAK, // AI type + 3, // AI level + 18, // min damage + 30, // max damage + M_IL+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NACID, // i.e. MT_SKELSD + "Deathspit", // Monster Name + "BFDS", // Translation filename + 6, // level on which it appears + 303, // Hit Points + AI_ACIDUNIQ, // AI type + 0, // AI level + 12, // min damage + 32, // max damage + M_RL+M_RF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RGOATMC, // i.e. MT_SKELSD + "Bloodgutter", // Monster Name + "BGBL", // Translation filename + 6, // level on which it appears + 315, // Hit Points + AI_BAT, // AI type + 1, // AI level + 24, // min damage + 34, // max damage + M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BGOATMC, // i.e. MT_SKELSD + "Deathshade Fleshmaul", // Monster Name + "DSFM", // Translation filename + 6, // level on which it appears + 276, // Hit Points + AI_RHINO, // AI type + 0, // AI level + 12, // min damage + 24, // max damage + M_RF+M_IM, // Magic resistance + UN_A, // Unique attributes, i.e., pack leader + 65, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_WYRM, // i.e. MT_SKELSD + "Warmaggot the Mad", // Monster Name + "GENERAL", // Translation filename + 6, // level on which it appears + 246, // Hit Points + AI_BAT, // AI type + 3, // AI level + 15, // min damage + 30, // max damage + M_RL, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_STORM, // i.e. MT_SKELSD + "Glasskull the Jagged", // Monster Name + "BHKA", // Translation filename + 7, // level on which it appears + 354, // Hit Points + AI_STORM, // AI type + 0, // AI level + 18, // min damage + 30, // max damage + M_IM+M_II+M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RGOATBW, // i.e. MT_SKELSD + "Blightfire", // Monster Name + "BLF", // Translation filename + 7, // level on which it appears + 321, // Hit Points + AI_SUCC, // AI type + 2, // AI level + 13, // min damage + 21, // max damage + M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_GARGOYLE, // i.e. MT_SKELSD + "Nightwing the Cold", // Monster Name + "GENERAL", // Translation filename + 7, // level on which it appears + 342, // Hit Points + AI_BAT, // AI type + 1, // AI level + 18, // min damage + 26, // max damage + M_RL+M_IM+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_GGOATBW, // i.e. MT_SKELSD + "Gorestone", // Monster Name + "GENERAL", // Translation filename + 7, // level on which it appears + 303, // Hit Points + AI_GOATBOW, // AI type + 1, // AI level + 15, // min damage + 28, // max damage + M_RL+M_II, // Magic resistance + UN_L|UN_H, // Unique attributes, i.e., pack leader + 70, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BMAGMA, // i.e. MT_SKELSD + "Bronzefist Firestone", // Monster Name + "GENERAL", // Translation filename + 8, // level on which it appears + 360, // Hit Points + AI_MAGMA, // AI type + 0, // AI level + 30, // min damage + 36, // max damage + M_RF+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_INCIN, // i.e. MT_SKELSD + "Wrathfire the Doomed", // Monster Name + "WFTD", // Translation filename + 8, // level on which it appears + 270, // Hit Points + AI_SKELSD, // AI type + 2, // AI level + 20, // min damage + 30, // max damage + M_RF+M_RL+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NMAGMA, // i.e. MT_SKELSD + "Firewound the Grim", // Monster Name + "BHKA", // Translation filename + 8, // level on which it appears + 303, // Hit Points + AI_MAGMA, // AI type + 0, // AI level + 18, // min damage + 22, // max damage + M_RF+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_MUDMAN, // i.e. MT_SKELSD + "Baron Sludge", // Monster Name + "BSM", // Translation filename + 8, // level on which it appears + 315, // Hit Points + AI_SNEAK, // AI type + 3, // AI level + 25, // min damage + 34, // max damage + M_RF+M_RL+M_IM+M_II, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 75, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_GGOATMC, // i.e. MT_SKELSD + "Blighthorn Steelmace", // Monster Name + "BHSM", // Translation filename + 7, // level on which it appears + 250, // Hit Points + AI_RHINO, // AI type + 0, // AI level + 20, // min damage + 28, // max damage + M_RL, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 45, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RACID, // i.e. MT_SKELSD + "Chaoshowler", // Monster Name + "GENERAL", // Translation filename + 8, // level on which it appears + 240, // Hit Points + AI_ACIDUNIQ, // AI type + 0, // AI level + 12, // min damage + 20, // max damage + 0, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_REDDTH, // i.e. MT_SKELSD + "Doomgrin the Rotting", // Monster Name + "GENERAL", // Translation filename + 8, // level on which it appears + 405, // Hit Points + AI_STORM, // AI type + 3, // AI level + 25, // min damage + 50, // max damage + M_RL+M_RF+M_IM+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_FLAMLRD, // i.e. MT_SKELSD + "Madburner", // Monster Name + "GENERAL", // Translation filename + 9, // level on which it appears + 270, // Hit Points + AI_STORM, // AI type + 0, // AI level + 20, // min damage + 40, // max damage + M_IF+M_IL+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_LTCHDMN, // i.e. MT_SKELSD + "Bonesaw the Litch", // Monster Name + "GENERAL", // Translation filename + 9, // level on which it appears + 495, // Hit Points + AI_STORM, // AI type + 2, // AI level + 30, // min damage + 55, // max damage + M_RF+M_RL+M_II+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_MUDRUN, // i.e. MT_SKELSD + "Breakspine", // Monster Name + "GENERAL", // Translation filename + 9, // level on which it appears + 351, // Hit Points + AI_RHINO, // AI type + 0, // AI level + 25, // min damage + 34, // max damage + M_RF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_REDDTH, // i.e. MT_SKELSD + "Devilskull Sharpbone", // Monster Name + "GENERAL", // Translation filename + 9, // level on which it appears + 444, // Hit Points + AI_STORM, // AI type + 1, // AI level + 25, // min damage + 40, // max damage + M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_STORM, // i.e. MT_SKELSD + "Brokenstorm", // Monster Name + "GENERAL", // Translation filename + 9, // level on which it appears + 411, // Hit Points + AI_STORM, // AI type + 2, // AI level + 25, // min damage + 36, // max damage + M_IL, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RSTORM, // i.e. MT_SKELSD + "Stormbane", // Monster Name + "GENERAL", // Translation filename + 9, // level on which it appears + 555, // Hit Points + AI_STORM, // AI type + 3, // AI level + 30, // min damage + 30, // max damage + M_IL, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_TOAD, // i.e. MT_SKELSD + "Oozedrool", // Monster Name + "GENERAL", // Translation filename + 9, // level on which it appears + 483, // Hit Points + AI_FAT, // AI type + 3, // AI level + 25, // min damage + 30, // max damage + M_RL, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BLOODCLW, // i.e. MT_SKELSD + "Goldblight of the Flame", // Monster Name + "GENERAL", // Translation filename + 10, // level on which it appears + 405, // Hit Points + AI_GARG, // AI type + 0, // AI level + 15, // min damage + 35, // max damage + M_IF+M_IM, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 80, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_OBLORD, // i.e. MT_SKELSD + "Blackstorm", // Monster Name + "GENERAL", // Translation filename + 10, // level on which it appears + 525, // Hit Points + AI_RHINO, // AI type + 3, // AI level + 20, // min damage + 40, // max damage + M_IL+M_IM, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 90, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RACID, // i.e. MT_SKELSD + "Plaguewrath", // Monster Name + "GENERAL", // Translation filename + 10, // level on which it appears + 450, // Hit Points + AI_ACIDUNIQ, // AI type + 2, // AI level + 20, // min damage + 30, // max damage + M_RF+M_IM+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RSTORM, // i.e. MT_SKELSD + "The Flayer", // Monster Name + "GENERAL", // Translation filename + 10, // level on which it appears + 501, // Hit Points + AI_STORM, // AI type + 1, // AI level + 20, // min damage + 35, // max damage + M_RF+M_RM+M_IL+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_FROSTC, // i.e. MT_SKELSD + "Bluehorn", // Monster Name + "GENERAL", // Translation filename + 11, // level on which it appears + 477, // Hit Points + AI_RHINO, // AI type + 1, // AI level + 25, // min damage + 30, // max damage + M_RF+M_IM, // Magic resistance + UN_L|UN_A, // Unique attributes, i.e., pack leader + 90, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_HELLBURN, // i.e. MT_SKELSD + "Warpfire Hellspawn", // Monster Name + "GENERAL", // Translation filename + 11, // level on which it appears + 525, // Hit Points + AI_FIREMAN, // AI type + 3, // AI level + 10, // min damage + 40, // max damage + M_RM+M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NSNAKE, // i.e. MT_SKELSD + "Fangspeir", // Monster Name + "GENERAL", // Translation filename + 11, // level on which it appears + 444, // Hit Points + AI_SKELSD, // AI type + 1, // AI level + 15, // min damage + 32, // max damage + M_IF+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_UDEDBLRG, // i.e. MT_SKELSD + "Festerskull", // Monster Name + "GENERAL", // Translation filename + 11, // level on which it appears + 600, // Hit Points + AI_STORM, // AI type + 2, // AI level + 15, // min damage + 30, // max damage + M_IM+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_NBLACK, // i.e. MT_SKELSD + "Lionskull the Bent", // Monster Name + "GENERAL", // Translation filename + 12, // level on which it appears + 525, // Hit Points + AI_SKELSD, // AI type + 2, // AI level + 25, // min damage + 25, // max damage + M_IM+M_IF+M_IL+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_COUNSLR, // i.e. MT_SKELSD + "Blacktongue", // Monster Name + "GENERAL", // Translation filename + 12, // level on which it appears + 360, // Hit Points + AI_COUNSLR, // AI type + 3, // AI level + 15, // min damage + 30, // max damage + M_RF+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_DEATHW, // i.e. MT_SKELSD + "Viletouch", // Monster Name + "GENERAL", // Translation filename + 12, // level on which it appears + 525, // Hit Points + AI_GARG, // AI type + 3, // AI level + 20, // min damage + 40, // max damage + M_IL+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RSNAKE, // i.e. MT_SKELSD + "Viperflame", // Monster Name + "GENERAL", // Translation filename + 12, // level on which it appears + 570, // Hit Points + AI_SKELSD, // AI type + 1, // AI level + 25, // min damage + 35, // max damage + M_RL+M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BSNAKE, // i.e. MT_SKELSD + "Fangskin", // Monster Name + "BHKA", // Translation filename + 14, // level on which it appears + 681, // Hit Points + AI_SKELSD, // AI type + 2, // AI level + 15, // min damage + 50, // max damage + M_RL+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_SUCCUBUS, // i.e. MT_SKELSD + "Witchfire the Unholy", // Monster Name + "GENERAL", // Translation filename + 12, // level on which it appears + 444, // Hit Points + AI_SUCC, // AI type + 3, // AI level + 10, // min damage + 20, // max damage + M_RL+M_IF+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BALROG, // i.e. MT_SKELSD + "Blackskull", // Monster Name + "BHKA", // Translation filename + 13, // level on which it appears + 750, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 25, // min damage + 40, // max damage + M_RL+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_UNRAV, // i.e. MT_SKELSD + "Soulslash", // Monster Name + "GENERAL", // Translation filename + 12, // level on which it appears + 450, // Hit Points + AI_SKELSD, // AI type + 0, // AI level + 25, // min damage + 25, // max damage + M_IM+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_VTEXLRD, // i.e. MT_SKELSD + "Windspawn", // Monster Name + "GENERAL", // Translation filename + 12, // level on which it appears + 711, // Hit Points + AI_SKELSD, // AI type + 1, // AI level + 35, // min damage + 40, // max damage + M_IF+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_GSNAKE, // i.e. MT_SKELSD + "Lord of the Pit", // Monster Name + "GENERAL", // Translation filename + 13, // level on which it appears + 762, // Hit Points + AI_SKELSD, // AI type + 2, // AI level + 25, // min damage + 42, // max damage + M_RF+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RTBLACK, // i.e. MT_SKELSD + "Rustweaver", // Monster Name + "GENERAL", // Translation filename + 13, // level on which it appears + 400, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 1, // min damage + 60, // max damage + M_IF+M_IL+M_IM+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_HOLOWONE, // i.e. MT_SKELSD + "Howlingire the Shade", // Monster Name + "GENERAL", // Translation filename + 13, // level on which it appears + 450, // Hit Points + AI_SKELSD, // AI type + 2, // AI level + 40, // min damage + 75, // max damage + M_RF+M_RL, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_MAEL, // i.e. MT_SKELSD + "Doomcloud", // Monster Name + "GENERAL", // Translation filename + 13, // level on which it appears + 612, // Hit Points + AI_STORM, // AI type + 1, // AI level + 1, // min damage + 60, // max damage + M_RF+M_IL, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_PAINMSTR, // i.e. MT_SKELSD + "Bloodmoon Soulfire", // Monster Name + "GENERAL", // Translation filename + 13, // level on which it appears + 684, // Hit Points + AI_SKELSD, // AI type + 1, // AI level + 15, // min damage + 40, // max damage + M_RF+M_RL+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_SNOWWICH, // i.e. MT_SKELSD + "Witchmoon", // Monster Name + "GENERAL", // Translation filename + 13, // level on which it appears + 310, // Hit Points + AI_SUCC, // AI type + 3, // AI level + 30, // min damage + 40, // max damage + M_RL, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_VTEXLRD, // i.e. MT_SKELSD + "Gorefeast", // Monster Name + "GENERAL", // Translation filename + 13, // level on which it appears + 771, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 20, // min damage + 55, // max damage + M_RF+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RTBLACK, // i.e. MT_SKELSD + "Graywar the Slayer", // Monster Name + "GENERAL", // Translation filename + 14, // level on which it appears + 672, // Hit Points + AI_SKELSD, // AI type + 1, // AI level + 30, // min damage + 50, // max damage + M_RL+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_MAGISTR, // i.e. MT_SKELSD + "Dreadjudge", // Monster Name + "GENERAL", // Translation filename + 14, // level on which it appears + 540, // Hit Points + AI_COUNSLR, // AI type + 1, // AI level + 30, // min damage + 40, // max damage + M_RF+M_RL+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_HLSPWN, // i.e. MT_SKELSD + "Stareye the Witch", // Monster Name + "GENERAL", // Translation filename + 14, // level on which it appears + 726, // Hit Points + AI_SUCC, // AI type + 2, // AI level + 30, // min damage + 50, // max damage + M_IF, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_BTBLACK, // i.e. MT_SKELSD + "Steelskull the Hunter", // Monster Name + "GENERAL", // Translation filename + 14, // level on which it appears + 831, // Hit Points + AI_SKELSD, // AI type + 3, // AI level + 40, // min damage + 50, // max damage + M_RL+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_RBLACK, // i.e. MT_SKELSD + "Sir Gorash", // Monster Name + "GENERAL", // Translation filename + 16, // level on which it appears + 1050, // Hit Points + AI_SKELSD, // AI type + 1, // AI level + 20, // min damage + 60, // max damage + M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_CABALIST, // i.e. MT_SKELSD + "The Vizier", // Monster Name + "GENERAL", // Translation filename + 15, // level on which it appears + 850, // Hit Points + AI_COUNSLR, // AI type + 2, // AI level + 25, // min damage + 40, // max damage + M_IF, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_REALWEAV, // i.e. MT_SKELSD + "Zamphir", // Monster Name + "GENERAL", // Translation filename + 15, // level on which it appears + 891, // Hit Points + AI_SKELSD, // AI type + 2, // AI level + 30, // min damage + 50, // max damage + M_RF+M_RL+M_II+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_HLSPWN, // i.e. MT_SKELSD + "Bloodlust", // Monster Name + "GENERAL", // Translation filename + 15, // level on which it appears + 825, // Hit Points + AI_SUCC, // AI type + 1, // AI level + 20, // min damage + 55, // max damage + M_IL+M_IM+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_HLSPWN, // i.e. MT_SKELSD + "Webwidow", // Monster Name + "GENERAL", // Translation filename + 16, // level on which it appears + 774, // Hit Points + AI_SUCC, // AI type + 1, // AI level + 20, // min damage + 50, // max damage + M_IF+M_IM+M_II, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_SOLBRNR, // i.e. MT_SKELSD + "Fleshdancer", // Monster Name + "GENERAL", // Translation filename + 16, // level on which it appears + 999, // Hit Points + AI_SUCC, // AI type + 3, // AI level + 30, // min damage + 50, // max damage + M_RF+M_II+M_IM, // Magic resistance + 0, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_OBLORD, // i.e. MT_SKELSD + "Grimspike", // Monster Name + "GENERAL", // Translation filename + 19, // level on which it appears + 534, // Hit Points + AI_SNEAK, // AI type + 1, // AI level + 25, // min damage + 40, // max damage + M_RF+M_II+M_IM, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, + + { + MT_STORML, // i.e. MT_SKELSD + "Doomlock", // Monster Name + "GENERAL", // Translation filename + 28, // level on which it appears + 534, // Hit Points + AI_SNEAK, // AI type + 1, // AI level + 35, // min damage + 55, // max damage + M_RF+M_RL+M_IM+M_II, // Magic resistance + UN_L, // Unique attributes, i.e., pack leader + 0, // parameter to unique attribute + 0, // " + 0 // Talking monster message number + }, +#endif + + { -1, NULL, NULL, 0, 0, 0, 0, 0, 0, 0 } // Stopper + +}; + diff --git a/src/MONSTDAT.H b/src/MONSTDAT.H new file mode 100644 index 0000000..3698dec --- /dev/null +++ b/src/MONSTDAT.H @@ -0,0 +1,301 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/MONSTDAT.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +// Monster Type +#define MT_NZOMBIE 0 +#define MT_BZOMBIE 1 +#define MT_GZOMBIE 2 +#define MT_YZOMBIE 3 + +#define MT_RFALLSP 4 +#define MT_DFALLSP 5 +#define MT_YFALLSP 6 +#define MT_BFALLSP 7 + +#define MT_WSKELAX 8 +#define MT_TSKELAX 9 +#define MT_RSKELAX 10 +#define MT_XSKELAX 11 + +#define MT_RFALLSD 12 +#define MT_DFALLSD 13 +#define MT_YFALLSD 14 +#define MT_BFALLSD 15 + +#define MT_NSCAV 16 +#define MT_BSCAV 17 +#define MT_WSCAV 18 +#define MT_YSCAV 19 + +#define MT_WSKELBW 20 +#define MT_TSKELBW 21 +#define MT_RSKELBW 22 +#define MT_XSKELBW 23 + +#define MT_WSKELSD 24 +#define MT_TSKELSD 25 +#define MT_RSKELSD 26 +#define MT_XSKELSD 27 + +#define MT_INVILORD 28 + +#define MT_SNEAK 29 +#define MT_STALKER 30 +#define MT_UNSEEN 31 +#define MT_ILLWEAV 32 + +#define MT_LRDSAYTR 33 + +#define MT_NGOATMC 34 +#define MT_BGOATMC 35 +#define MT_RGOATMC 36 +#define MT_GGOATMC 37 + +#define MT_FIEND 38 +#define MT_BLINK 39 +#define MT_GLOOM 40 +#define MT_FAMILIAR 41 + +#define MT_NGOATBW 42 +#define MT_BGOATBW 43 +#define MT_RGOATBW 44 +#define MT_GGOATBW 45 + +#define MT_NACID 46 +#define MT_RACID 47 +#define MT_BACID 48 +#define MT_XACID 49 + +#define MT_SKING 50 + +#define MT_CLEAVER 51 + +#define MT_FAT 52 +#define MT_MUDMAN 53 +#define MT_TOAD 54 +#define MT_FLAYED 55 + +#define MT_WYRM 56 +#define MT_CAVSLUG 57 +#define MT_DVLWYRM 58 +#define MT_DEVOUR 59 + +#define MT_NMAGMA 60 +#define MT_YMAGMA 61 +#define MT_BMAGMA 62 +#define MT_WMAGMA 63 + +#define MT_HORNED 64 +#define MT_MUDRUN 65 +#define MT_FROSTC 66 +#define MT_OBLORD 67 + +#define MT_BONEDMN 68 +#define MT_REDDTH 69 +#define MT_LTCHDMN 70 +#define MT_UDEDBLRG 71 + +#define MT_INCIN 72 +#define MT_FLAMLRD 73 +#define MT_DOOMFIRE 74 +#define MT_HELLBURN 75 + +#define MT_STORM 76 +#define MT_RSTORM 77 +#define MT_STORML 78 +#define MT_MAEL 79 + +#define MT_BIGFALL 80 + +#define MT_WINGED 81 +#define MT_GARGOYLE 82 +#define MT_BLOODCLW 83 +#define MT_DEATHW 84 + +#define MT_MEGA 85 +#define MT_GUARD 86 +#define MT_VTEXLRD 87 +#define MT_BALROG 88 + +#define MT_NSNAKE 89 +#define MT_RSNAKE 90 +#define MT_BSNAKE 91 +#define MT_GSNAKE 92 + +#define MT_NBLACK 93 +#define MT_RTBLACK 94 +#define MT_BTBLACK 95 +#define MT_RBLACK 96 + +#define MT_UNRAV 97 +#define MT_HOLOWONE 98 +#define MT_PAINMSTR 99 +#define MT_REALWEAV 100 + +#define MT_SUCCUBUS 101 +#define MT_SNOWWICH 102 +#define MT_HLSPWN 103 +#define MT_SOLBRNR 104 + +#define MT_COUNSLR 105 +#define MT_MAGISTR 106 +#define MT_CABALIST 107 +#define MT_ADVOCATE 108 + +#define MT_GOLEM 109 + +#define MT_DIABLO 110 +#define MT_DARKMAGE 111 + +#define MT_FORK 112 +#define MT_SCORP 113 +#define MT_EYE 114 +#define MT_SPIDER 115 +#define MT_FELLTWIN 116 +#define MT_SPAWN 117 +#define MT_SCORP2 118 +#define MT_EYE2 119 +#define MT_SPIDER2 120 +#define MT_LASH 121 +#define MT_ANT 122 +#define MT_HORKD 123 +#define MT_BUG 124 + +#define MT_GRAVDG 125 +#define MT_RAT 126 +#define MT_HELLBAT 127 +#define MT_BONED 128 +#define MT_LICH 129 +#define MT_BUBBA 130 +#define MT_HELLBAT2 131 +#define MT_BONED2 132 +#define MT_LICH2 133 +#define MT_BYCLPS 134 +#define MT_FLESH 135 +#define MT_REAPER 136 +#define MT_NKR 137 + +#define LASTMT 138 + +// Temp unique monster identification +#define MU_GARBUD 0 +#define MU_SKELKING 1 +#define MU_ZHAR 2 +#define MU_SNOTSPIL 3 +#define MU_LAZARUS 4 +#define MU_REDVEX 5 +#define MU_BLKJADE 6 +#define MU_LACHDA 7 +#define MU_WARLORD 8 +#define MU_CLEAVER 9 +#define MU_HORKDEMON 10 +#define MU_DEFILER 11 +#define MU_NAKRUL 12 + +// Image data sizes +#define IMG_MAX 4000 + +// Unique Monster Attributes +#define UN_PACK 0x0001 // monster has pack surrounding him +#define UN_STICK 0x0002 // monster pack sticks near leader -- must be used w/UN_PACK +#define UN_H 0x0004 // modified hit points +#define UN_A 0x0008 // modified armor +#define UN_L (UN_PACK|UN_STICK) + +// Monster Classes +#define MC_UNDEAD 0 +#define MC_DEMON 1 +#define MC_ANIMAL 2 + +// Monster resists +#define M_NONE 0x0000 // No resist +#define M_RM 0x0001 // resist magic +#define M_RF 0x0002 // resist fire +#define M_RL 0x0004 // resist lightning +#define M_IM 0x0008 // immune to magic +#define M_IF 0x0010 // immune to fire +#define M_IL 0x0020 // immune to lightning +#define M_II 0x0040 // immune to infravision +#define M_IA 0x0080 // immune to acid + +#define T_U 0x8000 // Unique +#define T_NONE 0x4000 +//#define Unused 0x2000 +//#define Unused 0x1000 +#define T_MASK 0x0fff + +// Monster availability +#define MAT_NO 0 // Not available +#define MAT_SW 1 // Shareware + Normal +#define MAT_YES 2 // Normal only + + +#define AI_ZOMBIE 0 +#define AI_FAT 1 +#define AI_SKELSD 2 +#define AI_SKELBOW 3 +#define AI_SCAV 4 +#define AI_RHINO 5 +#define AI_GOATMC 6 +#define AI_GOATBOW 7 +#define AI_FALLEN 8 +#define AI_MAGMA 9 +#define AI_SKELKING 10 +#define AI_BAT 11 +#define AI_GARG 12 +#define AI_CLEAVER 13 +#define AI_SUCC 14 +#define AI_SNEAK 15 +#define AI_STORM 16 +#define AI_FIREMAN 17 +#define AI_GARBUD 18 +#define AI_ACID 19 +#define AI_ACIDUNIQ 20 +#define AI_GOLUM 21 +#define AI_ZHAR 22 +#define AI_SNOTSPIL 23 +#define AI_SNAKE 24 +#define AI_COUNSLR 25 +#define AI_MEGA 26 +#define AI_DIABLO 27 +#define AI_LAZURUS 28 +#define AI_LAZHELP 29 +#define AI_LACHDANAN 30 +#define AI_WARLORD 31 +#define AI_FIREBAT 32 +#define AI_HELLBAT 33 +#define AI_HORKDEMON 34 +#define AI_LICH 35 +#define AI_ARCHLICH 36 +#define AI_PSYCHORB 37 +#define AI_NECROMORB 38 +#define AI_BONED 39 +#define NUM_AI (1 + AI_BONED) + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern MonsterData monsterdata[]; +extern int MonstConvTbl[]; +extern int MonstAvailTbl[]; +extern UniqMonstStruct UniqMonst[]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ diff --git a/src/MONSTER.CPP b/src/MONSTER.CPP new file mode 100644 index 0000000..560819e --- /dev/null +++ b/src/MONSTER.CPP @@ -0,0 +1,7722 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Monsters file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MONSTER.CPP 3 1/23/97 7:22p Rseis $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "debug.h" +#include "monster.h" +#include "monstdat.h" +#include "engine.h" +#include "gendung.h" +#include "lighting.h" +#include "items.h" +#include "itemdat.h" +#include "player.h" +#include "effects.h" +#include "dead.h" +#include "missiles.h" +#include "misdat.h" +#include "control.h" +#include "objects.h" +#include "objdat.h" +#include "path.h" +#include "quests.h" +#include "minitext.h" +#include "textdat.h" +#include "monstint.h" +#include "msg.h" +#include "inv.h" +#include "multi.h" +#include "trigs.h" +#include "themes.h" +#include "drlg_l4.h" +#include "towners.h" +#include "setmaps.h" +#include "palette.h" +#include "scrollrt.h" +#include "cursor.h" +#include "drlg_l1.h" +#include "spells.h" + + +/*-----------------------------------------------------------------------* +** Function Prototypes +**-----------------------------------------------------------------------*/ +BOOL LineClear(int x1, int y1, int x2, int y2); +int M_GetDir(int i); + +typedef BOOL (*CHECKFUNC)(int x, int y); +typedef BOOL (*CHECKFUNC1)(int arg1, int x, int y); +BOOL LineClearF(CHECKFUNC Clear, int x1, int y1, int x2, int y2); +BOOL LineClearF1(CHECKFUNC1 Clear, int arg, int x1, int y1, int x2, int y2); +BOOL CheckNoSolid(int x, int y); +BOOL PosOkMissile(int x, int y); +int M_SpawnSkel(int x, int y, int dir); +void M_Teleport(int i); +void PlaceGroup(int, int, BOOL, int); +void ClrAllMonsters(); +BOOL PosOkMonst2(int i, int x, int y); +BOOL PosOkMonst3(int i, int x, int y); +BOOL effect_is_playing(int nSFX); + +void SpawnMap(int x, int y); +void SpawnBear(int x, int y); + +extern const TextDataStruct alltext[]; + +//void DaveMonstMap(BOOL initupdate, int pnum); + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +MonsterStruct monster[MAXMONSTERS]; +long nummonsters; +int totalmonsters; + +// monstactive -- indexes into monster[] +int monstactive[MAXMONSTERS]; // [0..nummonsters-1] -- active monsters + // [nummonsters..MAXMONSTERS-1] -- available monsters + +int nummtypes = 0; +long monstimgtot; +int gfxflags; +int uniquetrans; // index to next available unique monster palette translation + +int mleveltypes[NUMLEVELS][MAX_LVLMTYPES]; + +long monstkills[MONSTERTYPES]; + +static char sgszInvalidMonstName[] = "Invalid Monster"; + +/*-----------------------------------------------------------------------* +** Defines +**-----------------------------------------------------------------------*/ +#define PACK_MEMBER 1 +#define PACK_NOMEMBER 2 + +#define INITMONSTRAD 15 // Initial vision radius for no monsters + +/*-----------------------------------------------------------------------* +** Macros +**-----------------------------------------------------------------------*/ +#define InBounds(x,y) (0 <= (y) && (y) < MAXDUNY && 0 <= (x) && (x) < MAXDUNX) +#define WALKMODE(m) ((m) == MM_WALK || (m) == MM_WALK2 || (m) == MM_WALK3) +#define Sign(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0) +#define Mod(val, x) ((val) < 0 ? (val)+(x) : (val) >= (x) ? (val)-(x) : (val)) + +/*-----------------------------------------------------------------------* +** File Variables +**-----------------------------------------------------------------------*/ +// I had to add this variable, because _mVar2 seems like +// it must have been trashed, since sound never came on again -- pjw +static BYTE sgbSaveSoundOn; + + // 16 32 64 +int MWVel[24][3] = { {0x100,0x200,0x400}, // 1 frame + {0x80,0x100,0x200}, // 2 frame + {0x55,0xaa,0x155}, // 3 frame + {0x40,0x80,0x100}, // 4 frame + {0x33,0x66,0xcc}, // 5 frame + {0x2a,0x55,0xaa}, // 6 frame + {0x24,0x49,0x92}, // 7 frame + {0x20,0x40,0x80}, // 8 frame + {0x1c,0x38,0x71}, // 9 frame + {0x1a,0x33,0x66}, // 10 frame + {0x17,0x2e,0x5d}, // 11 frame + {0x15,0x2a,0x55}, // 12 frame + {0x13,0x27,0x4e}, // 13 frame + {0x12,0x24,0x49}, // 14 frame + {0x11,0x22,0x44}, // 15 frame + {0x10,0x20,0x40}, // 16 frame + {0x0f,0x1e,0x3c}, // 17 frame + {0x0e,0x1c,0x39}, // 18 frame + {0x0d,0x1a,0x36}, // 19 frame + {0x0c,0x19,0x33}, // 20 frame + {0x0c,0x18,0x30}, // 21 frame + {0x0b,0x17,0x2e}, // 22 frame + {0x0b,0x16,0x2c}, // 23 frame + {0x0a,0x15,0x2a} }; // 24 frame + +// Muli-player monster multiplier % +/*int MPMM[4] = { 100, // 1 player + 150, // 2 player + 175, // 3 player + 200 }; // 4 player*/ + +CMonster Monsters[MAX_LVLMTYPES]; + +char animletter[] = "nwahds"; +int left[] = {7,0,1,2,3,4,5,6}; +int right[] = {1,2,3,4,5,6,7,0}; +int opposite[] = {4,5,6,7,0,1,2,3}; +int offset_x[] = {1,0,-1,-1,-1,0,1,1}; +int offset_y[] = {1,1,1,0,-1,-1,-1,0}; +static const infront_x[] = { 1, 0,-1, -1, -1, 0, 1, 1}; +static const infront_y[] = { 1, 1, 1, 0, -1, -1, -1, 0}; +int rnd5[] = { 5, 10, 15, 20 }; +int rnd10[] = { 10, 15, 20, 30 }; +int rnd20[] = { 20, 30, 40, 50 }; +int rnd60[] = { 60, 70, 80, 90 }; + + +void MAI_Zombie(int); +void MAI_Fat(int); +void MAI_SkelSd(int); +void MAI_SkelBow(int); +void MAI_Scav(int); +void MAI_Rhino(int); +void MAI_GoatMc(int); +void MAI_GoatBow(int); +void MAI_Fallen(int); +void MAI_Magma(int); +void MAI_SkelKing(int); +void MAI_Bat(int); +void MAI_Garg(int); +void MAI_Cleaver(int); +void MAI_Succ(int); +void MAI_Lich(int); +void MAI_ArchLich(int); +void MAI_Psychorb(int); +void MAI_Necromorb(int); +void MAI_Sneak(int); +void MAI_Storm(int); +void MAI_Fireman(int i); +void MAI_Garbud(int); +void MAI_Acid(int); +void MAI_AcidUniq(int); +void MAI_Golum(int); +void MAI_Zhar(int); +void MAI_SnotSpil(int); +void MAI_Snake(int); +void MAI_Counselor(int); +void MAI_Mega(int); +void MAI_Diablo(int); +void MAI_Lazurus(int); +void MAI_Lazhelp(int); +void MAI_Lachdanan(int); +void MAI_Warlord(int); +void MAI_Firebat(int); +void MAI_Hellbat(int); +void MAI_HorkDemon(int); +void MAI_BoneDemon(int); + +void (*AiProc[NUM_AI])(int) = +{ + MAI_Zombie, + MAI_Fat, + MAI_SkelSd, + MAI_SkelBow, + MAI_Scav, + MAI_Rhino, + MAI_GoatMc, + MAI_GoatBow, + MAI_Fallen, + MAI_Magma, + MAI_SkelKing, + MAI_Bat, + MAI_Garg, + MAI_Cleaver, + MAI_Succ, + MAI_Sneak, + MAI_Storm, + MAI_Fireman, + MAI_Garbud, + MAI_Acid, + MAI_AcidUniq, + MAI_Golum, + MAI_Zhar, + MAI_SnotSpil, + MAI_Snake, + MAI_Counselor, + MAI_Mega, + MAI_Diablo, + MAI_Lazurus, + MAI_Lazhelp, + MAI_Lachdanan, + MAI_Warlord, + MAI_Firebat, + MAI_Hellbat, + MAI_HorkDemon, + MAI_Lich, + MAI_ArchLich, + MAI_Psychorb, + MAI_Necromorb, + MAI_BoneDemon, +}; + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void TranslateMonsterGFX(int monst, BOOL HasSpecial) +{ + app_assert((DWORD)monst < MAX_LVLMTYPES); + BYTE * pData = Monsters[monst].pTrans; + + for (int n = 256; n--; ++pData) { + if (*pData == 255) + *pData = 0; + } + int const nf = HasSpecial ? 6 : 5; + for (int j = 0; j < nf; ++j) { + if ((j == 1) && (Monsters[monst].mtype >= MT_COUNSLR) && (Monsters[monst].mtype <= MT_ADVOCATE)) continue; + for (int i = 0; i < 8; ++i) + TranslateCels(Monsters[monst].Anims[j].Cels[i], Monsters[monst].pTrans, Monsters[monst].Anims[j].Frames); + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +#if 0 // UNUSED +static BOOL MonstTaken(int i) +{ + int lev; + BOOL found = FALSE; + int m; + int templvl; // JKE + +// Temp hack for monsters JKE 7/30 + templvl = currlevel; +// if (templvl > 20) templvl -= 8; +// else if (templvl > 16) templvl -= 4; + +// for(lev = 0; lev <= currlevel && !found; ++lev) // JKE + for(lev = 0; lev <= templvl && !found; ++lev) + { + for(m = 0; m < MAX_LVLMTYPES && mleveltypes[m] && !found; ++m) + found = ((i < mleveltypes[lev][m]-1) + && + !strcmp(monsterdata[i].filename, monsterdata[mleveltypes[lev][m]-1].filename)); + } + return found; +} +#endif // UNUSED + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitLevelMonsters() +{ + int i; + + nummtypes = 0; + monstimgtot = 0; + gfxflags = 0; + + for (i = 0; i < MAX_LVLMTYPES; ++i) + Monsters[i].mPlaceFlags = 0; + + ClrAllMonsters(); + nummonsters = 0; + totalmonsters = MAXMONSTERS; // this value gets further restricted later on + + // active monsters list + for (i = 0; i < MAXMONSTERS; ++i) { + monstactive[i] = i; + } + uniquetrans = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int AddMonsterType(int type, int placeflag) +{ + int i; + BOOL done = FALSE; + + // check if this type is already being loaded + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (i = 0; i < nummtypes && !done; ++i) + done = Monsters[i].mtype == type; + --i; + + if (!done) + { + i = nummtypes++; + Monsters[i].mtype = type; + monstimgtot += monsterdata[type].mImgSize; + InitMonsterGFX(i); + InitMonsterSND(i); + } + + Monsters[i].mPlaceFlags |= placeflag; + + return i; +} + +/*-----------------------------------------------------------------------* + * GetLevelMTypes() + * + * Pick the monsters types to be placed in this level +**-----------------------------------------------------------------------*/ + +void GetLevelMTypes() +{ + int typelist[MONSTERTYPES]; + int nt, i; + int tidx, mt; + int minl,maxl; + char mamask; + int templvl; // temp hack JKE + + #if IS_VERSION(SHAREWARE) + mamask = MAT_SW; + #else + mamask = MAT_SW | MAT_YES; + #endif + + // Certain monsters are required for certain levels + + AddMonsterType(MT_GOLEM, MPFLAG_DONT); + + if (currlevel == 16) { + AddMonsterType(MT_ADVOCATE, MPFLAG_SCATTER); + AddMonsterType(MT_RBLACK, MPFLAG_SCATTER); + AddMonsterType(MT_DIABLO, MPFLAG_DONT); + return; + } + + if (currlevel == HIVESTART + 1) + { + AddMonsterType(MT_SPAWN, MPFLAG_SCATTER); + } + if (currlevel == HIVESTART + 2) + { + AddMonsterType(MT_SPAWN, MPFLAG_SCATTER); + AddMonsterType(MT_HORKD, MPFLAG_UNIQ); + } + if (currlevel == HIVEEND) + { + AddMonsterType(MT_BUG, MPFLAG_UNIQ); + } + if (currlevel == NA_KRUL_LEVEL /*CRYPTEND*/) + { + AddMonsterType(MT_LICH2, MPFLAG_SCATTER); + AddMonsterType(MT_NKR, MPFLAG_DONT); + } + + // Set levels load their own monster types + if (!setlevel) + { + if (QuestStatus(Q_BUTCHER)) { + AddMonsterType(MT_CLEAVER, MPFLAG_DONT); + } + + if (QuestStatus(Q_GARBUD)) { + AddMonsterType(UniqMonst[MU_GARBUD].mtype, MPFLAG_UNIQ); + } + + if (QuestStatus(Q_ZHAR)) { + AddMonsterType(UniqMonst[MU_ZHAR].mtype, MPFLAG_UNIQ); + } + + if (QuestStatus(Q_LTBANNER)) { + AddMonsterType(UniqMonst[MU_SNOTSPIL].mtype, MPFLAG_UNIQ); + } + + if (QuestStatus(Q_VEIL)) { + AddMonsterType(UniqMonst[MU_LACHDA].mtype, MPFLAG_UNIQ); + } + + if (QuestStatus(Q_WARLORD)) { + AddMonsterType(UniqMonst[MU_WARLORD].mtype, MPFLAG_UNIQ); + } + + if (gbMaxPlayers != 1 && currlevel == quests[Q_SKELKING]._qlevel) { + AddMonsterType(MT_SKING, MPFLAG_UNIQ); + + // Skelking requires skeleton minions + int skeltypes[LASTMT]; + int numskeltypes = 0; + + for (i = MT_WSKELAX; i <= MT_XSKELSD; ++i) + { + if (IsSkel(i)) + { + minl = ((monsterdata[i].mMinDLvl * 15) / 30) + 1; + maxl = ((monsterdata[i].mMaxDLvl * 15) / 30) + 1; + if ((currlevel >= minl) && (currlevel <= maxl) && (MonstAvailTbl[i] & mamask)) + skeltypes[numskeltypes++] = i; + } + } + AddMonsterType(skeltypes[random(88,numskeltypes)], MPFLAG_SCATTER); + } + + // Pick general monsters + + // Make list of available monster types for this level +// Temp hack monster JKE + templvl = currlevel; +// if (templvl > 20) templvl -=8; +// else if (templvl > 16) templvl -= 4; + + nt = 0; + for (i = 0; i < LASTMT; ++i) { + minl = ((monsterdata[i].mMinDLvl * 15) / 30) + 1; + maxl = ((monsterdata[i].mMaxDLvl * 15) / 30) + 1; +// if ((currlevel >= minl) && (currlevel <= maxl) && (MonstAvailTbl[i] & mamask)) { +// typelist[nt] = i; +// ++nt; +// } + // use templvl to patch over current level + if ((templvl >= minl) && (templvl <= maxl) && (MonstAvailTbl[i] & mamask)) { + typelist[nt] = i; + ++nt; + } + } + + if (monstdebug) + { + for(i = 0; i < debugmonsttypes; ++i) + AddMonsterType(DebugMonsters[i], MPFLAG_SCATTER); + } + else + { + while ((nt > 0) && (nummtypes < MAX_LVLMTYPES) && (monstimgtot < IMG_MAX)) { + // prune excessively large monsters + for (i = 0; i < nt; ) + { + if (monsterdata[typelist[i]].mImgSize > IMG_MAX - monstimgtot) + typelist[i] = typelist[--nt]; + else + ++i; + } + + if (nt) + { + tidx = random(88, nt); + mt = typelist[tidx]; + AddMonsterType(mt, MPFLAG_SCATTER); + typelist[tidx] = typelist[--nt]; + } + } + } + } + else if (setlvlnum == SL_SKELKING) { + AddMonsterType(MT_SKING, MPFLAG_UNIQ); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitMonsterGFX (int monst) +{ + int anim; + long i; + char strBuff[256]; + int mtype; + BYTE *p; + + app_assert((DWORD)monst < MAX_LVLMTYPES); + mtype = Monsters[monst].mtype; + for(anim = 0; anim < MAX_ANIMTYPE; ++anim) + { + if((!(animletter[anim] == 's' && !monsterdata[mtype].has_special)) && monsterdata[mtype].Frames[anim] > 0) + { + sprintf(strBuff, monsterdata[mtype].filename, animletter[anim]); + app_assert(! Monsters[monst].Anims[anim].CMem); + Monsters[monst].Anims[anim].CMem = LoadFileInMemSig(strBuff,NULL,'MONS'); + p = Monsters[monst].Anims[anim].CMem; + if (Monsters[monst].mtype == MT_GOLEM && (animletter[anim] == 's' || animletter[anim] == 'd')) { + for(i=0; i<8; ++i) Monsters[monst].Anims[anim].Cels[i] = p; + } else { + for(i=0; i<8; ++i) Monsters[monst].Anims[anim].Cels[i] = p + *(DWORD *)(p + (i<<2)); + } + } + Monsters[monst].Anims[anim].Frames = monsterdata[mtype].Frames[anim]; + Monsters[monst].Anims[anim].Rate = monsterdata[mtype].Rate[anim]; + } + Monsters[monst].mAnimWidth = monsterdata[mtype].mAnimWidth; + Monsters[monst].mAnimWidth2 = (monsterdata[mtype].mAnimWidth - 64) >> 1; + Monsters[monst].mMinHP = monsterdata[mtype].mMinHP; + Monsters[monst].mMaxHP = monsterdata[mtype].mMaxHP; + Monsters[monst].has_special = monsterdata[mtype].has_special; + Monsters[monst].mAFNum = monsterdata[mtype].mAFNum; + Monsters[monst].MData = &monsterdata[mtype]; + if (monsterdata[mtype].transflag) { + Monsters[monst].pTrans = LoadFileInMemSig(monsterdata[mtype].TransFile,NULL,'MONS'); + TranslateMonsterGFX(monst, monsterdata[mtype].has_special); + DiabloFreePtr(Monsters[monst].pTrans); + } + if (EquivMonst(mtype, MT_NMAGMA) && ((gfxflags & 0x0001) == 0)) { + gfxflags |= 0x0001; + ILoadMissileGFX(MF_MAGBALL); + } + + if (EquivMonst(mtype, MT_STORM) && ((gfxflags & 0x0002) == 0)) { + gfxflags |= 0x0002; + ILoadMissileGFX(MF_THINLIGHT); + } + + if ((mtype == MT_SUCCUBUS) && ((gfxflags & 0x0004) == 0)) { + gfxflags |= 0x0004; +// ILoadMissileGFX(MF_FLARE); already used for Blood Star +// ILoadMissileGFX(MF_FLAREXP); + } + + if (EquivMonst(mtype, MT_INCIN) && ((gfxflags & 0x0008) == 0)) { + gfxflags |= 0x0008; + ILoadMissileGFX(MF_KRULL); + } + + if ((EquivMonst(mtype, MT_NACID) || mtype == MT_SPIDER2) && + ((gfxflags & 0x0010) == 0)) { + gfxflags |= 0x0010; + ILoadMissileGFX(MF_ACID); + ILoadMissileGFX(MF_ACIDSPLAT); + ILoadMissileGFX(MF_ACIDPUD); + } + + if ((mtype == MT_SNOWWICH) && ((gfxflags & 0x0020) == 0)) { + gfxflags |= 0x0020; + ILoadMissileGFX(MF_BFLARE); + ILoadMissileGFX(MF_BFLAREXP); + } + if ((mtype == MT_HLSPWN) && ((gfxflags & 0x0040) == 0)) { + gfxflags |= 0x0040; + ILoadMissileGFX(MF_DFLARE); + ILoadMissileGFX(MF_DFLAREXP); + } + if ((mtype == MT_SOLBRNR) && ((gfxflags & 0x0080) == 0)) { + gfxflags |= 0x0080; + ILoadMissileGFX(MF_CFLARE); + ILoadMissileGFX(MF_CFLAREXP); + } + + if ((mtype == MT_LICH) && ((gfxflags & 0x0100) == 0)) + { + gfxflags |= 0x0100; + ILoadMissileGFX(MF_ORANGEFLARE); + ILoadMissileGFX(MF_ORANGEEXPLOSION); + } + + if ((mtype == MT_LICH2) && ((gfxflags & 0x0200) == 0)) + { + gfxflags |= 0x0200; + ILoadMissileGFX(MF_YELLOWFLARE); + ILoadMissileGFX(MF_YELLOWEXPLOSION); + } + + if ((mtype == MT_EYE || mtype == MT_BONED2) && ((gfxflags & 0x0400) == 0)) + { + gfxflags |= 0x0400; + ILoadMissileGFX(MF_BLUE2FLARE); + } + + if ((mtype == MT_EYE2) && ((gfxflags & 0x0800) == 0)) + { + gfxflags |= 0x0800; + ILoadMissileGFX(MF_REDFLARE); + ILoadMissileGFX(MF_REDEXPLOSION); + } + + + if ((mtype == MT_EYE) && ((gfxflags & 0x1000) == 0)) + { + gfxflags |= 0x1000; + ILoadMissileGFX(MF_BLUEEXPLOSION); + } + + if ((mtype == MT_BONED2) && ((gfxflags & 0x2000) == 0)) + { + gfxflags |= 0x2000; + ILoadMissileGFX(MF_BLUE2EXPLOSION); + } + + + if (mtype == MT_DIABLO) + ILoadMissileGFX(MF_FIREPLAR); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void ClearMVars(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + monster[i]._mVar1 = 0; + monster[i]._mVar2 = 0; + monster[i]._mVar3 = 0; + monster[i]._mVar4 = 0; + monster[i]._mVar5 = 0; + monster[i]._mVar6 = 0; + monster[i]._mVar7 = 0; + monster[i]._mVar8 = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + + +void InitMonster(int i, int rd, int mtype, int x, int y) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert((DWORD)mtype < MAX_LVLMTYPES); + CMonster *monst = &Monsters[mtype]; + app_assert(monst->MData != NULL); + + monster[i]._mdir = rd; + monster[i]._mx = x; + monster[i]._my = y; + monster[i]._mfutx = x; + monster[i]._mfuty = y; + monster[i]._moldx = x; + monster[i]._moldy = y; + + monster[i]._mMTidx = mtype; + monster[i]._mmode = MM_STAND; + monster[i].mName = monst->MData->mName; + monster[i].MType = monst; + monster[i].MData = monst->MData; + monster[i]._mAnimData = monst->Anims[MA_STAND].Cels[rd]; + monster[i]._mAnimDelay = monst->Anims[MA_STAND].Rate; + monster[i]._mAnimCnt = random(88, monster[i]._mAnimDelay - 1); + monster[i]._mAnimLen = monst->Anims[MA_STAND].Frames; + monster[i]._mAnimFrame = random(88, monster[i]._mAnimLen - 1) + 1; + if (monst->mtype == MT_DIABLO) { +// monster[i]._mmaxhp = (random(88, 1666 - 1666 + 1) + 1666) << HP_SHIFT; + monster[i]._mmaxhp = (random(88, 3333 - 3333 + 1) + 3333) << HP_SHIFT; + } else { + monster[i]._mmaxhp = (random(88, monst->mMaxHP - monst->mMinHP + 1) + monst->mMinHP) << HP_SHIFT; + } +/* if (gbMaxPlayers != 1) + monster[i]._mmaxhp = (monster[i]._mmaxhp * MPMM[gbActivePlayers-1]) / 100; + else + monster[i]._mmaxhp = monster[i]._mmaxhp >> 1; + if (monster[i]._mmaxhp < (1 << HP_SHIFT)) monster[i]._mmaxhp = 1 << HP_SHIFT;*/ + if (gbMaxPlayers == 1) { + monster[i]._mmaxhp = monster[i]._mmaxhp >> 1; + if (monster[i]._mmaxhp < (1 << HP_SHIFT)) monster[i]._mmaxhp = 1 << HP_SHIFT; + } + monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i]._mAi = monst->MData->mAi; + monster[i]._mint = monst->MData->mInt; + monster[i]._mgoal = MG_ATTACK; + monster[i]._mgoalvar1 = 0; + monster[i]._mgoalvar2 = 0; + monster[i]._mgoalvar3 = 0; + monster[i]._mgoalvar4 = 0; + monster[i]._pathcount = 0; + monster[i]._mDelFlag = FALSE; + monster[i]._uniqtype = 0; + monster[i]._msquelch = 0; + + monster[i].mlid = 0; + + monster[i]._mRndSeed = GetRndSeed(); + monster[i]._mAISeed = GetRndSeed(); + + monster[i].mWhoHit = 0; + + monster[i].mLevel = monst->MData->mLevel; + monster[i].mExp = monst->MData->mExp; + monster[i].mHit = monst->MData->mHit; + monster[i].mMinDamage = monst->MData->mMinDamage; + monster[i].mMaxDamage = monst->MData->mMaxDamage; + monster[i].mHit2 = monst->MData->mHit2; + monster[i].mMinDamage2 = monst->MData->mMinDamage2; + monster[i].mMaxDamage2 = monst->MData->mMaxDamage2; + monster[i].mArmorClass = monst->MData->mArmorClass; + monster[i].mMagicRes = monst->MData->mMagicRes; + monster[i].leader = 0; + monster[i].leaderflag = 0; + monster[i]._mFlags = monst->MData->mFlags; + monster[i].mtalkmsg = 0; + + if (monster[i]._mAi == AI_GARG) + { + monster[i]._mAnimData = monst->Anims[MA_SPECIAL].Cels[rd]; + monster[i]._mAnimFrame = 1; + monster[i]._mFlags |= MFLAG_STILL; + monster[i]._mmode = MM_SATTACK; + } + + if (gnDifficulty == D_NIGHTMARE) { + monster[i]._mmaxhp = (monster[i]._mmaxhp * 3) + (((gbMaxPlayers == 1) ? 50 : 100) << HP_SHIFT); + monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i].mLevel += 15; + monster[i].mExp = (monster[i].mExp << 1) + 2000; + monster[i].mHit += 85; + monster[i].mMinDamage = (monster[i].mMinDamage * 2) + 4; + monster[i].mMaxDamage = (monster[i].mMaxDamage * 2) + 4; + monster[i].mHit2 += 85; + monster[i].mMinDamage2 = (monster[i].mMinDamage2 * 2) + 4; + monster[i].mMaxDamage2 = (monster[i].mMaxDamage2 * 2) + 4; + monster[i].mArmorClass += 50; + } + else if (gnDifficulty == D_HELL) { + monster[i]._mmaxhp = (monster[i]._mmaxhp * 4) + (((gbMaxPlayers == 1) ? 100 : 200) << HP_SHIFT); + monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i].mLevel += 30; + monster[i].mExp = (monster[i].mExp << 2) + 4000; + monster[i].mHit += 120; + monster[i].mMinDamage = (monster[i].mMinDamage * 4) + 6; + monster[i].mMaxDamage = (monster[i].mMaxDamage * 4) + 6; + monster[i].mHit2 += 120; + monster[i].mMinDamage2 = (monster[i].mMinDamage2 * 4) + 6; + monster[i].mMaxDamage2 = (monster[i].mMaxDamage2 * 4) + 6; + monster[i].mArmorClass += 80; + monster[i].mMagicRes = monst->MData->mMagicRes2; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ClrAllMonsters() +{ + int i; + MonsterStruct *Monst; + + for (i = 0; i < MAXMONSTERS; ++i) { + Monst = &monster[i]; + ClearMVars(i); + + //track down freeloaders from previous levels by making them obvious + Monst->mName = sgszInvalidMonstName; + + Monst->_mgoal = 0; + Monst->_mmode = MM_STAND; + Monst->_mVar1 = MM_STAND; + Monst->_mVar2 = 0; + Monst->_mx = 0; + Monst->_my = 0; + Monst->_mfutx = 0; + Monst->_mfuty = 0; + Monst->_moldx = 0; + Monst->_moldy = 0; + Monst->_mdir = random(89, 8); + Monst->_mxvel = 0; + Monst->_myvel = 0; + Monst->_mAnimData = NULL; + Monst->_mAnimDelay = 0; + Monst->_mAnimCnt = 0; + Monst->_mAnimLen = 0; + Monst->_mAnimFrame = 0; + Monst->_mFlags = 0; + Monst->_mDelFlag = FALSE; + Monst->_menemy = random(89, gbActivePlayers); + Monst->_menemyx = plr[Monst->_menemy]._pfutx; + Monst->_menemyy = plr[Monst->_menemy]._pfuty; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL MonstPlace(int xp, int yp) { + if (xp < 0 || xp >= DMAXX || yp < 0 || yp >= DMAXY) return FALSE; + if (dMonster[xp][yp] != 0) return FALSE; + if (dPlayer[xp][yp] != 0) return FALSE; + if (dFlags[xp][yp] & BFLAG_MONSTACTIVE) return FALSE; + if (dFlags[xp][yp] & BFLAG_SETPC) return FALSE; + if (SolidLoc(xp,yp)) return FALSE; + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void PlaceMonster(int i, int mtype, int x, int y) +{ + int rd; + + // stoopid hack to NEVER get duplicate Na-Kruls + if (Monsters[mtype].mtype == MT_NKR) + { + int monstindex; + for (monstindex = 0; monstindex < nummonsters; ++monstindex) + if (monster[monstindex]._mMTidx == mtype || + monster[monstindex].MType->mtype == MT_NKR) + return; + } + + dMonster[x][y] = i + 1; + rd = random(90, 8); + InitMonster(i, rd, mtype, x, y); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void LoadUniMonstTrans(int uid) +{ + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void PlaceUniqueMonst(int uniqindex, int miniontype, int packsize) +{ + app_assert((DWORD)nummonsters < MAXMONSTERS); + UniqMonstStruct *Uniq = &UniqMonst[uniqindex]; + MonsterStruct *Monst = &monster[nummonsters]; + + int xp,yp; + int x,y; + BOOL done; + int count, count2; + char filestr[64]; + done = FALSE; + count2 = 0; + int uniqtype; + + // Check if too many uniques. Limit is unique palette translation table size + if((uniquetrans << 8) + 4864 >= LIGHTSIZE) + return; + + // find the index of the monster graphics + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (uniqtype = 0; uniqtype < nummtypes; ++uniqtype) + if (Monsters[uniqtype].mtype == UniqMonst[uniqindex].mtype) break; + app_assert(uniqtype < nummtypes); + + do + { + xp = random(91, DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(91, DMAXY - DIRTEDGE) + (DIRTEDGED2); + count = 0; + for(x = xp-3; x < xp+3; ++x) + for(y = yp-3; y < yp+3; ++y) + if(InBounds(x,y) && MonstPlace(x,y)) + ++count; + } while((count < 9 // try finding a clear spot + && ++count2 < 1000) // avoid infinite loop + || !MonstPlace(xp,yp)); // make sure there's at least + // a spot for the leader + + if(uniqindex == MU_SNOTSPIL) { + xp = (setpc_x << 1) + DIRTEDGED2 + 8; + yp = (setpc_y << 1) + DIRTEDGED2 + 12; + } + if(uniqindex == MU_WARLORD) { + xp = (setpc_x << 1) + DIRTEDGED2 + 6; + yp = (setpc_y << 1) + DIRTEDGED2 + 7; + } + if(uniqindex == MU_ZHAR) { + int i; + BOOL zharflag = TRUE; + for (i = 0; i < themeCount; ++i) { + if ((i == zharlib) && (zharflag == TRUE)) { + zharflag = FALSE; + xp = ((themeLoc[i].x << 1) + DIRTEDGED2)+4; + yp = ((themeLoc[i].y << 1) + DIRTEDGED2)+4; + } + } + } + if (gbMaxPlayers == 1) { + if(uniqindex == MU_LAZARUS) { + xp = 32; + yp = 46; + } + if(uniqindex == MU_REDVEX) { + xp = 40; + yp = 45; + } + if(uniqindex == MU_BLKJADE) { + xp = 38; + yp = 49; + } + if(uniqindex == MU_SKELKING) { + xp = 35; + yp = 47; + } + } else { + if(uniqindex == MU_LAZARUS) { + xp = (setpc_x << 1) + DIRTEDGED2 + 3; + yp = (setpc_y << 1) + DIRTEDGED2 + 6; + } + if(uniqindex == MU_REDVEX) { + xp = (setpc_x << 1) + DIRTEDGED2 + 5; + yp = (setpc_y << 1) + DIRTEDGED2 + 3; + } + if(uniqindex == MU_BLKJADE) { + xp = (setpc_x << 1) + DIRTEDGED2 + 5; + yp = (setpc_y << 1) + DIRTEDGED2 + 9; + } + } + + if (uniqindex == MU_CLEAVER) { + done = FALSE; + // Find certain tile where Butcher goes + for (yp = 0; yp < DMAXY && !done; ++yp) + for (xp = 0; xp < DMAXX && !done; ++xp) + done = (dPiece[xp][yp] == 367); + // NOTE: xp and yp get incremented an extra time after done=TRUE, but + // coincidentally, that's where we want to place butcher + } + + if (uniqindex == MU_NAKRUL) + { + if (Na_Krul.x == 0 || Na_Krul.y == 0) + { + Na_Krul.MIndex = -1; + return; + } + + xp = Na_Krul.x - 2; + yp = Na_Krul.y; + Na_Krul.MIndex = nummonsters; + } + + PlaceMonster(nummonsters, uniqtype, xp, yp); + Monst->_uniqtype = uniqindex+1; + if (Uniq->mlevel != 0) Monst->mLevel = Uniq->mlevel*2; + else Monst->mLevel += 5; + Monst->mExp = (Monst->mExp*2); + Monst->mName = Uniq->mName; + Monst->_mmaxhp = Uniq->mmaxhp << HP_SHIFT; +/* if (gbMaxPlayers != 1) + Monst->_mmaxhp = (Monst->_mmaxhp * MPMM[gbActivePlayers-1]) / 100; + else + Monst->_mmaxhp = Monst->_mmaxhp >> 1; + if (Monst->_mmaxhp < (1 << HP_SHIFT)) Monst->_mmaxhp = 1 << HP_SHIFT;*/ + if (gbMaxPlayers == 1) { + Monst->_mmaxhp = Monst->_mmaxhp >> 1; + if (Monst->_mmaxhp < (1 << HP_SHIFT)) Monst->_mmaxhp = 1 << HP_SHIFT; + } + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->_mAi = Uniq->mAi; + Monst->_mint = Uniq->mint; + Monst->mMinDamage = Uniq->mMinDamage; + Monst->mMaxDamage = Uniq->mMaxDamage; + Monst->mMinDamage2 = Uniq->mMinDamage; + Monst->mMaxDamage2 = Uniq->mMaxDamage; + Monst->mMagicRes = Uniq->mMagicRes; + Monst->mtalkmsg = Uniq->mtalkmsg; + // Don't light up the hork demon, it washes him out. + if ( uniqindex == MU_HORKDEMON) { + Monst->mlid = 0; + } + else { + Monst->mlid = AddLight(Monst->_mx, Monst->_my, 3); + } + if ((gbMaxPlayers != 1) && (Monst->_mAi == AI_LAZHELP)) Monst->mtalkmsg = 0; + if (Monst->mtalkmsg != 0) Monst->_mgoal = MG_TALK; + if (gnDifficulty == D_NIGHTMARE) { + Monst->_mmaxhp = (Monst->_mmaxhp * 3) + (((gbMaxPlayers == 1) ? 50 : 100) << HP_SHIFT); + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->mLevel += 15; + Monst->mExp = (Monst->mExp << 1) + 2000; + Monst->mMinDamage = (Monst->mMinDamage * 2) + 4; + Monst->mMaxDamage = (Monst->mMaxDamage * 2) + 4; + Monst->mMinDamage2 = (Monst->mMinDamage2 * 2) + 4; + Monst->mMaxDamage2 = (Monst->mMaxDamage2 * 2) + 4; + } + else if (gnDifficulty == D_HELL) { + Monst->_mmaxhp = (Monst->_mmaxhp * 4) + (((gbMaxPlayers == 1) ? 100 : 200) << HP_SHIFT); + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->mLevel += 30; + Monst->mExp = (Monst->mExp << 2) + 4000; + Monst->mMinDamage = (Monst->mMinDamage * 4) + 6; + Monst->mMaxDamage = (Monst->mMaxDamage * 4) + 6; + Monst->mMinDamage2 = (Monst->mMinDamage2 * 4) + 6; + Monst->mMaxDamage2 = (Monst->mMaxDamage2 * 4) + 6; + } + + // Load unique monster translations + sprintf(filestr, "Monsters\\Monsters\\%s.TRN", Uniq->mTFile); + app_assert((uniquetrans << 8) + 4864 < LIGHTSIZE); + LoadFileWithMem(filestr, pLightTbl + (uniquetrans << 8) + 4864); + Monst->_uniqtrans = uniquetrans; + ++uniquetrans; + + if(Uniq->mUnqAttr & UN_H) + { + Monst->mHit = Uniq->mUnqVar1; + Monst->mHit2 = Uniq->mUnqVar1; + } + if(Uniq->mUnqAttr & UN_A) + { + Monst->mArmorClass = Uniq->mUnqVar1; + } + + ++nummonsters; + + if(Uniq->mUnqAttr & UN_PACK) + { + PlaceGroup(miniontype, packsize, Uniq->mUnqAttr, nummonsters-1); + } + // quick fix for monsters that were gargoyles before they became unique + if (Monst->_mAi != AI_GARG) + { + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + Monst->_mAnimFrame = random(88, Monst->_mAnimLen - 1) + 1; + Monst->_mFlags &= ~MFLAG_STILL; + Monst->_mmode = MM_STAND; + } +} + +void Hose_NaKrul() +{ + if (currlevel == NA_KRUL_LEVEL) + { + int mi = Na_Krul.MIndex; + if (mi < 0 || mi >= nummonsters) + return; + + MonsterStruct *Monst = &monster[mi]; + PlayEffect(mi, MS_DEATH); + quests[Q_NA_KRUL]._qlog = FALSE; + + Monst->_mmaxhp = Monst->_mmaxhp / 2; + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->mArmorClass -= 50; + Monst->mMagicRes = 0x0000; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static void PlaceUniques() +{ + int u; + int mt; + BOOL done; + + //uniquetrans = 0; + for(u = 0; UniqMonst[u].mtype != -1; ++u) + { +#if CHEATS + if ((UniqMonst[u].mlevel == currlevel) + || (UniqMonst[u].mlevel && davedebug)) { +#else + if (UniqMonst[u].mlevel == currlevel) { +#endif + done = FALSE; + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for(mt = 0; mt < nummtypes && !done; ++mt) + done = Monsters[mt].mtype == UniqMonst[u].mtype; + --mt; + if ((u == MU_GARBUD) && (quests[Q_GARBUD]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if ((u == MU_ZHAR) && (quests[Q_ZHAR]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if ((u == MU_SNOTSPIL) && (quests[Q_LTBANNER]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if ((u == MU_LACHDA) && (quests[Q_VEIL]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if ((u == MU_WARLORD) && (quests[Q_WARLORD]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if(done) + { + PlaceUniqueMonst(u, mt, 8); + } + } + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static void PlaceQuestMonsters() +{ + int skeltype; + byte *setp; + + if (!setlevel) { + if (QuestStatus(Q_BUTCHER)) + PlaceUniqueMonst(MU_CLEAVER, 0, 0); + + if ((currlevel == quests[Q_SKELKING]._qlevel) && (gbMaxPlayers != 1)) + { + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (skeltype = 0; skeltype < nummtypes; ++skeltype) + if (IsSkel(Monsters[skeltype].mtype)) break; + app_assert(skeltype < nummtypes); + + PlaceUniqueMonst(MU_SKELKING, skeltype, 30); + } + + if (QuestStatus(Q_LTBANNER)) + { + setp = LoadFileInMemSig("Levels\\L1Data\\Banner1.DUN",NULL,'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + + if (QuestStatus(Q_BLOOD)) + { + setp = LoadFileInMemSig("Levels\\L2Data\\Blood2.DUN", NULL, 'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + + if (QuestStatus(Q_BLIND)) + { + setp = LoadFileInMemSig("Levels\\L2Data\\Blind2.DUN", NULL, 'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + + if (QuestStatus(Q_ANVIL)) + { + setp = LoadFileInMemSig("Levels\\L3Data\\Anvil.DUN",NULL,'MONS'); + SetMapMonsters(setp, ((setpc_x+1) << 1), ((setpc_y+1) << 1)); + DiabloFreePtr(setp); + } + + if (QuestStatus(Q_WARLORD)) + { + setp = LoadFileInMemSig("Levels\\L4Data\\Warlord.DUN",NULL,'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + AddMonsterType(UniqMonst[MU_WARLORD].mtype, MPFLAG_SCATTER); // to allow scatterable monst of mtype + } + + if (QuestStatus(Q_VEIL)) + { + AddMonsterType(UniqMonst[MU_LACHDA].mtype, MPFLAG_SCATTER); // to allow scatterable monst of mtype + } + + if (QuestStatus(Q_ZHAR)) { + if (zharlib == -1) + quests[Q_ZHAR]._qactive = QUEST_NOTAVAIL; + } + + if ((currlevel == quests[Q_BETRAYER]._qlevel) && (gbMaxPlayers != 1)) { + AddMonsterType(UniqMonst[MU_LAZARUS].mtype, MPFLAG_UNIQ); + AddMonsterType(UniqMonst[MU_REDVEX].mtype, MPFLAG_UNIQ); + PlaceUniqueMonst(MU_LAZARUS, 0, 0); + PlaceUniqueMonst(MU_REDVEX, 0, 0); + PlaceUniqueMonst(MU_BLKJADE, 0, 0); + setp = LoadFileInMemSig("Levels\\L4Data\\Vile1.DUN",NULL,'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + if (currlevel == NA_KRUL_LEVEL) + { + //if ((quests[Q_NA_KRUL]._qactive != QUEST_NOTAVAIL) && + // (quests[Q_NA_KRUL]._qlog)) + { + + int numminions = 2; + if (gnDifficulty == D_NIGHTMARE) + numminions = 4; + else if (gnDifficulty == D_HELL) + numminions = 6; + + // see if we already have a Na-Krul + Na_Krul.MIndex = -1; + + int uniqtype; + for (uniqtype = 0; uniqtype < nummtypes; ++uniqtype) + if (Monsters[uniqtype].mtype == UniqMonst[MU_NAKRUL].mtype) break; + + if (uniqtype < nummtypes) + { + int monstindex; + for (monstindex = 0; monstindex < nummonsters; ++monstindex) + { + if (monster[monstindex]._uniqtype != 0 || + monster[monstindex]._mMTidx == uniqtype) + { + Na_Krul.MIndex = monstindex; + break; + } + } + } + if (Na_Krul.MIndex == -1) // didn't find + { + PlaceUniqueMonst(MU_NAKRUL, 0, 0); + } + } + } + } + else if (setlvlnum == SL_SKELKING) { + PlaceUniqueMonst(MU_SKELKING, 0, 0); + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void PlaceGroup(int mtype, int num, BOOL leaderf, int leader) +{ + int xp, yp; + int x1, y1; + int j; + int placed = 0; + int try1 = 0; + int try2; + int rd; + + app_assert((DWORD)leader < MAXMONSTERS); + do + { + // Clear out the subset placed last time through the loop + while(placed) + { + --nummonsters; + --placed; + app_assert((DWORD)nummonsters < MAXMONSTERS); + app_assert((DWORD)monster[nummonsters]._mx < MAXDUNX); + app_assert((DWORD)monster[nummonsters]._my < MAXDUNY); + dMonster[monster[nummonsters]._mx][monster[nummonsters]._my] = 0; + } + + if(leaderf & UN_PACK) + { + rd = random(92, 8); + x1 = xp = monster[leader]._mx + offset_x[rd]; + y1 = yp = monster[leader]._my + offset_y[rd]; + } + else + { + do + { + x1 = xp = random(93, DMAXX - DIRTEDGE) + (DIRTEDGED2); + y1 = yp = random(93, DMAXY - DIRTEDGE) + (DIRTEDGED2); + } while (!MonstPlace(xp, yp)); + } + + if ((nummonsters + num) > totalmonsters) num = totalmonsters - nummonsters; + j = 0; + try2 = 0; + while (j < num && try2 < 100) { + if (MonstPlace(xp, yp) && (dTransVal[xp][yp] == dTransVal[x1][y1]) + && !((leaderf & UN_STICK) && !DIST(xp-x1,yp-y1,4))) { + PlaceMonster(nummonsters, mtype, xp, yp); + if(leaderf & UN_PACK) + { + monster[nummonsters]._mmaxhp *= 2; + monster[nummonsters]._mhitpoints = monster[nummonsters]._mmaxhp; + monster[nummonsters]._mint = monster[leader]._mint; + if (leaderf & UN_STICK) + { + monster[nummonsters].leader = leader; + monster[nummonsters].leaderflag = PACK_MEMBER; + monster[nummonsters]._mAi = monster[leader]._mAi; + } + // quick fix for monsters that were gargoyles before they became unique + if (monster[nummonsters]._mAi != AI_GARG) + { + monster[nummonsters]._mAnimData = monster[nummonsters].MType->Anims[MA_STAND].Cels[monster[nummonsters]._mdir]; + monster[nummonsters]._mAnimFrame = random(88, monster[nummonsters]._mAnimLen - 1) + 1; + monster[nummonsters]._mFlags &= ~MFLAG_STILL; + monster[nummonsters]._mmode = MM_STAND; + } + } + + ++nummonsters; + ++placed; + ++j; + } + else + ++try2; + xp += offset_x[random(94, 8)]; + yp += offset_x[random(94, 8)]; + } + } while((placed < num) && (++try1 < 10)); + if(leaderf & UN_STICK) + monster[leader].packsize = placed; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +void LoadDiabMonsts() +{ + BYTE *pSetPiece; + int xx, yy; + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab1.DUN",NULL,'STPC'); + xx = (diabquad1x << 1); + yy = (diabquad1y << 1); + SetMapMonsters(pSetPiece, xx, yy); + DiabloFreePtr(pSetPiece); + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab2a.DUN",NULL,'STPC'); + xx = (diabquad2x << 1); + yy = (diabquad2y << 1); + SetMapMonsters(pSetPiece, xx, yy); + DiabloFreePtr(pSetPiece); + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab3a.DUN",NULL,'STPC'); + xx = (diabquad3x << 1); + yy = (diabquad3y << 1); + SetMapMonsters(pSetPiece, xx, yy); + DiabloFreePtr(pSetPiece); + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab4a.DUN",NULL,'STPC'); + xx = (diabquad4x << 1); + yy = (diabquad4y << 1); + SetMapMonsters(pSetPiece, xx, yy); + DiabloFreePtr(pSetPiece); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitMonsters () +{ + int i, mtype; + int na, nt; + int scattertypes[LASTMT]; + int numscattypes = 0; + long fv,j; + int numplacemonsters; + int s,t; + +void DaveCheck2(); + if (gbMaxPlayers != 1) DaveCheck2(); + + // add 4 golem places first + // WARNING!! IF YOU CHANGE THIS YOU MUST TEST POSION WATER QUEST!!! + if (!setlevel) { + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + } + + // We will place the monsters seperately for 16 +#if !IS_VERSION(SHAREWARE) + if (!setlevel && currlevel == 16) { + LoadDiabMonsts(); + } +#endif + + // Monsters are not placed where bFlags[][] & BFLAG_MONSTACTIVE is set + // This prevents: 1) Monsters attacking players as they enter dungeon + // 2) Monsters setting off traps + + nt = numtrigs; + if (currlevel == 15) nt = 1; + for (i = 0; i < nt; ++i) + { + for (s = -2; s < 2; ++s) + for (t = -2; t < 2; ++t) + DoVision(trigs[i]._tx + s, trigs[i]._ty + t, INITMONSTRAD, FALSE, FALSE); + } + +#if !IS_VERSION(SHAREWARE) + PlaceQuestMonsters(); +#endif + + if (!setlevel) + { +#if !IS_VERSION(SHAREWARE) + PlaceUniques(); // Place uniques before any other monsters +#endif + // Calc a volume of monsters + fv = 0; + for (i = DIRTEDGED2; i < (DMAXY - (DIRTEDGED2)); ++i) { + for (j = DIRTEDGED2; j < (DMAXX - (DIRTEDGED2)); ++j) { + if (!SolidLoc(i,j)) ++fv; + } + } + numplacemonsters = fv / MONSTDENSITY; +#if 0 // Debugging = 1, normal = 0 + numplacemonsters = 1; +#else + if (gbMaxPlayers != 1) numplacemonsters += (numplacemonsters >> 1); +#endif + if (numplacemonsters + nummonsters > MAXMONSTERS - 10) + numplacemonsters = MAXMONSTERS - 10 - nummonsters; + + totalmonsters = nummonsters + numplacemonsters; + + +#ifndef PACKS_ONLY // switch for debugging pack AI + // Place scattered monsters + + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (i = 0; i < nummtypes; ++i) + { + if (Monsters[i].mPlaceFlags & MPFLAG_SCATTER) + scattertypes[numscattypes++] = i; + } + + while (nummonsters < totalmonsters) { + mtype = scattertypes[random(95, numscattypes)]; + + if (currlevel != 1 // no groups on level 1 + && random(95, 2)) + { + if (currlevel == 2 || // half-size groups on level 2 + (currlevel >= CRYPTSTART && currlevel <= CRYPTEND)) + na = random(95, 2) + 2; + else + na = random(95, 3) + 3; + } + else na = 1; + + PlaceGroup(mtype, na, FALSE, NULL); + } +#endif // PACKS_ONLY + } + + for (i = 0; i < nt; ++i) + { + for (s = -2; s < 2; ++s) + for (t = -2; t < 2; ++t) + DoUnVision(trigs[i]._tx + s, trigs[i]._ty + t, INITMONSTRAD); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetMapMonsters(BYTE *pMap, int startx, int starty) +{ + int i,j; + WORD rw,rh; + WORD *lm; + int mt,mx,my; + int mtype; + + // add 4 golem places first + // WARNING! IF YOU CHANGE THIS YOU MUST TEST THE POISON WATER QUEST!!!! + AddMonsterType(MT_GOLEM, MPFLAG_DONT); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + + if ((setlevel) && (setlvlnum == SL_VILEBETRAYER)) { + AddMonsterType(UniqMonst[MU_LAZARUS].mtype, MPFLAG_UNIQ); + AddMonsterType(UniqMonst[MU_REDVEX].mtype, MPFLAG_UNIQ); + AddMonsterType(UniqMonst[MU_BLKJADE].mtype, MPFLAG_UNIQ); + PlaceUniqueMonst(MU_LAZARUS, 0, 0); + PlaceUniqueMonst(MU_REDVEX, 0, 0); + PlaceUniqueMonst(MU_BLKJADE, 0, 0); + } + + + lm = (WORD *)pMap; + rw = *(lm++); + rh = *(lm++); + // Skip map + lm += rw * rh; + // Convert to index mini tile level instead of mega + rw = rw << 1; + rh = rh << 1; + // Skip treasure map + lm += rw * rh; + for (j = 0; j < rh; ++j) { + for (i = 0; i < rw; ++i) { + if (*lm != 0) { + mt = *lm; + mt = MonstConvTbl[mt-1]; + mtype = AddMonsterType(mt, MPFLAG_DONT); + mx = i + DIRTEDGED2 + startx; + my = j + DIRTEDGED2 + starty; + PlaceMonster(nummonsters++, mtype, mx, my); + } + ++lm; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DeleteMonster(int i) +{ + int temp; + + app_assert((DWORD)(nummonsters-1) < MAXMONSTERS); + app_assert((DWORD)i < MAXMONSTERS); + temp = monstactive[--nummonsters]; + monstactive[nummonsters] = monstactive[i]; + monstactive[i] = temp; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int AddMonster(int x, int y, int dir, int mtype, BOOL InMap) +{ + int i; + + if (nummonsters < MAXMONSTERS) { + i = monstactive[nummonsters++]; + if (InMap) dMonster[x][y] = i + 1; + InitMonster(i, dir, mtype, x, y); + return i; + } else return -1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CloneMonster(int m) +{ + if (monster[m].MType == NULL) + return; + int oldx = monster[m]._mx; + int oldy = monster[m]._my; + int dir = monster[m]._mdir; + + // try to find a place to put a new monster, next to old monster + int x, y, theta; + + for (theta = 0; theta < 8; ++theta) + { + x = oldx + offset_x[theta]; + y = oldy + offset_y[theta]; + + if (SolidLoc(x, y) || dPlayer[x][y] || dMonster[x][y]) + continue; + + if (!dObject[x][y]) + break; + + int oi = (dObject[x][y] > 0) ? (dObject[x][y] - 1) : -(dObject[x][y] + 1); + if (!object[oi]._oSolidFlag) + break; + } + if (theta >= 8) // no space + return; + + int mtype = monster[m].MType->mtype; + for (int i=0; i < MAX_LVLMTYPES; ++i) + { + if (Monsters[i].mtype == mtype) + break; + } + if (i < MAX_LVLMTYPES) + AddMonster(x, y, dir, i, TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void NewMonsterAnim(int i, AnimStruct &anim, int md) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert((DWORD)md < 8); + MonsterStruct *Monst = &monster[i]; + + Monst->_mAnimData = anim.Cels[md]; + Monst->_mAnimLen = anim.Frames; + Monst->_mAnimFrame = 1; + Monst->_mAnimCnt = 0; + Monst->_mAnimDelay = anim.Rate; + Monst->_mdir = md; + Monst->_mFlags &= ~(MFLAG_BACKWARDS|MFLAG_STILL); +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL M_Ranged (int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + if (monster[i]._mAi == AI_SKELBOW || + monster[i]._mAi == AI_GOATBOW || + monster[i]._mAi == AI_SUCC || + monster[i]._mAi == AI_LAZHELP) return TRUE; + + return FALSE; +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL M_Talker (int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + if (monster[i]._mAi == AI_LAZURUS || + monster[i]._mAi == AI_WARLORD || + monster[i]._mAi == AI_GARBUD || + monster[i]._mAi == AI_ZHAR || + monster[i]._mAi == AI_SNOTSPIL || + monster[i]._mAi == AI_LACHDANAN || + monster[i]._mAi == AI_LAZHELP) return TRUE; + + return FALSE; +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_Enemy (int i) +{ + int j; + int pnum, closest; + int bestdist; + bool bestsameroom; + + app_assert((DWORD)i < MAXMONSTERS); + MonsterStruct *Monst = &monster[i]; + BYTE enemyx,enemyy; + + closest = -1; + bestdist = -1; + bestsameroom = false; + + + if (Monst->_mFlags & MFLAG_BERSERK + || !(Monst->_mFlags & MFLAG_MKILLER) ) { + for(pnum = 0; pnum < MAX_PLRS; ++pnum) { + if (!plr[pnum].plractive + || currlevel != plr[pnum].plrlevel + || plr[pnum]._pLvlChanging + || ((plr[pnum]._pHitPoints >> HP_SHIFT) == 0) ) + continue; + + bool const sameroom = (dTransVal[Monst->_mx][Monst->_my] == dTransVal[plr[pnum]._px][plr[pnum]._py]); + int const dist = max(abs(Monst->_mx - plr[pnum]._px), abs(Monst->_my - plr[pnum]._py)); + + if ((sameroom && !bestsameroom) || ((sameroom || !bestsameroom) && dist < bestdist) || closest == -1) { + Monst->_mFlags &= ~MFLAG_MID; +// Monst->_mFlags &= ~MFLAG_MKILLER; + closest = pnum; + enemyx = plr[pnum]._pfutx; + enemyy = plr[pnum]._pfuty; + bestdist = dist; + bestsameroom = sameroom; + } + } + } + + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for (j = 0; j < nummonsters; ++j) { + + int const mi = monstactive[j]; + + if ((mi != i) && + ((monster[mi]._mhitpoints >> HP_SHIFT) > 0) && + ((monster[mi]._mx != 1) || (monster[mi]._my != 0)) && // special confus-o-matic code for inactive golum + ((!M_Talker(mi)) || monster[mi].mtalkmsg == 0) && + /*(DIST((monster[mi]._mx - Monst->_mx),(monster[mi]._my - Monst->_my),2)) &&*/ + ((Monst->_mFlags & MFLAG_MKILLER) || (Monst->_mFlags & MFLAG_BERSERK) || + ((DIST((monster[mi]._mx - Monst->_mx),(monster[mi]._my - Monst->_my),2)) || (M_Ranged(i)))) && + (Monst->_mFlags & MFLAG_MKILLER || (Monst->_mFlags & MFLAG_BERSERK) + || monster[mi]._mFlags & MFLAG_MKILLER)) { + + bool const sameroom = (dTransVal[Monst->_mx][Monst->_my] == dTransVal[monster[mi]._mx][monster[mi]._my]); + int const dist = max(abs(Monst->_mx - monster[mi]._mx), abs(Monst->_my - monster[mi]._my)); + + if ((sameroom && !bestsameroom) || ((sameroom || !bestsameroom) && dist < bestdist) || closest == -1) { + Monst->_mFlags |= MFLAG_MID; + closest = mi; + enemyx = monster[mi]._mfutx; + enemyy = monster[mi]._mfuty; + bestdist = dist; + bestsameroom = sameroom; + } + } + } + + // everyone dead? + if (closest != -1) + { + Monst->_menemy = closest; + Monst->_menemyx = enemyx; + Monst->_menemyy = enemyy; + Monst->_mFlags &= ~MFLAG_NOENEMY; + } + else + Monst->_mFlags |= MFLAG_NOENEMY; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static int M_GetDir(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + return GetDirection(monster[i]._mx, monster[i]._my, monster[i]._menemyx, monster[i]._menemyy); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_CheckEFlag(int i) +{ + int tx,ty,tv; + int t; + WORD *mt; + + app_assert((DWORD)i < MAXMONSTERS); + tx = monster[i]._mx - 1; + ty = monster[i]._my + 1; + tv = 0; + mt = &(dMT[tx][ty].mt[0]); + for(t = 2; t < 10; ++t) + tv |= mt[t]; + tv |= dSpecial[tx][ty]; + if (tv != 0) monster[i]._meflag = 1; + else monster[i]._meflag = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartStand(int i, int md) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + ClearMVars(i); + if (monster[i].MType->mtype == MT_GOLEM) + NewMonsterAnim(i, monster[i].MType->Anims[MA_WALK], md); + else + NewMonsterAnim(i, monster[i].MType->Anims[MA_STAND], md); + + monster[i]._mVar1 = monster[i]._mmode; + monster[i]._mVar2 = 0; // count how long he's been standing + monster[i]._mmode = MM_STAND; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); + + // Pick nearest enemy + M_Enemy(i); +} + +/*-----------------------------------------------------------------------* + * M_StartDelay + * + * Keeps monster in Stand animation for len frames + * Monster must be in Stand mode before entering Delay mode +**-----------------------------------------------------------------------*/ + +static void M_StartDelay(int i, int len) +{ + if(len > 0) + { + if (monster[i]._mAi == AI_LAZURUS) return; + app_assert((DWORD)i < MAXMONSTERS); + monster[i]._mVar2 = len; + monster[i]._mmode = MM_DELAY; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartSpStand(int i, int md) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + + monster[i]._mmode = MM_SPSTAND; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartWalk(int i, int xvel, int yvel, int xadd, int yadd, int EndDir) +{ + long fx,fy; + int pn; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + fx = monster[i]._mx + xadd; + fy = monster[i]._my + yadd; + app_assert((DWORD)fx < MAXDUNX); + app_assert((DWORD)fy < MAXDUNY); + pn = dPiece[fx][fy] - 1; + dMonster[fx][fy] = -1 - i; + monster[i]._mmode = MM_WALK; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mfutx = fx; + monster[i]._mfuty = fy; + monster[i]._mxvel = xvel; + monster[i]._myvel = yvel; + monster[i]._mVar1 = xadd; + monster[i]._mVar2 = yadd; + monster[i]._mVar3 = EndDir; + monster[i]._mdir = EndDir; + NewMonsterAnim(i, monster[i].MType->Anims[MA_WALK], EndDir); + monster[i]._mVar6 = 0; + monster[i]._mVar7 = 0; + monster[i]._mVar8 = 0; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartWalk2(int i, int xvel, int yvel, int xoff, int yoff, + int xadd, int yadd, int EndDir) +{ + long fx,fy; + int pn; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + fx = monster[i]._mx + xadd; + fy = monster[i]._my + yadd; + app_assert((DWORD)fx < MAXDUNX); + app_assert((DWORD)fy < MAXDUNY); + pn = dPiece[fx][fy] - 1; + app_assert((DWORD)monster[i]._mx < MAXDUNX); + app_assert((DWORD)monster[i]._my < MAXDUNY); + dMonster[monster[i]._mx][monster[i]._my] = -1 - i; + monster[i]._mVar1 = monster[i]._mx; + monster[i]._mVar2 = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mx = fx; + monster[i]._my = fy; + monster[i]._mfutx = fx; + monster[i]._mfuty = fy; + dMonster[fx][fy] = i + 1; + if( !(monster[i]._mFlags & MFLAG_INVISIBLE) + && monster[i].mlid != 0) { + ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my); + } + monster[i]._mxoff = xoff; + monster[i]._myoff = yoff; + monster[i]._mmode = MM_WALK2; + monster[i]._mxvel = xvel; + monster[i]._myvel = yvel; + monster[i]._mVar3 = EndDir; + monster[i]._mdir = EndDir; + NewMonsterAnim(i, monster[i].MType->Anims[MA_WALK], EndDir); + monster[i]._mVar6 = xoff << 4; + monster[i]._mVar7 = yoff << 4; + monster[i]._mVar8 = 0; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartWalk3(int i, int xvel, int yvel, int xoff, int yoff, + int xadd, int yadd, int txa, int tya, int EndDir) +{ + long fx,fy; + long tx,ty; + int pn, pn2; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + fx = monster[i]._mx + xadd; + fy = monster[i]._my + yadd; + tx = monster[i]._mx + txa; // Temp location for drawing + ty = monster[i]._my + tya; + if( !(monster[i]._mFlags & MFLAG_INVISIBLE) + && monster[i].mlid != 0) { + ChangeLightXY(monster[i].mlid, tx, ty); + } + app_assert((DWORD)fx < MAXDUNX); + app_assert((DWORD)fy < MAXDUNY); + pn = dPiece[fx][fy] - 1; + pn2 = dPiece[tx][ty] - 1; + app_assert((DWORD)monster[i]._mx < MAXDUNX); + app_assert((DWORD)monster[i]._my < MAXDUNY); + dMonster[monster[i]._mx][monster[i]._my] = -1 - i; + dMonster[fx][fy] = -1 - i; + monster[i]._mVar4 = tx; + monster[i]._mVar5 = ty; + dFlags[tx][ty] |= BFLAG_MONSTLR; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mfutx = fx; + monster[i]._mfuty = fy; + monster[i]._mxoff = xoff; + monster[i]._myoff = yoff; + monster[i]._mmode = MM_WALK3; + monster[i]._mxvel = xvel; + monster[i]._myvel = yvel; + monster[i]._mVar1 = fx; + monster[i]._mVar2 = fy; + monster[i]._mVar3 = EndDir; + monster[i]._mdir = EndDir; + NewMonsterAnim(i, monster[i].MType->Anims[MA_WALK], EndDir); + monster[i]._mVar6 = xoff << 4; + monster[i]._mVar7 = yoff << 4; + monster[i]._mVar8 = 0; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartAttack(int i) +{ + int md; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + md = M_GetDir(i); + NewMonsterAnim(i, monster[i].MType->Anims[MA_ATTACK], md); + + monster[i]._mmode = MM_ATTACK; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +** Ranged weapons +**-----------------------------------------------------------------------*/ + +static void M_StartRAttack(int i, int missile_type, int dam) +{ + int md; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + md = M_GetDir(i); + NewMonsterAnim(i, monster[i].MType->Anims[MA_ATTACK], md); + + monster[i]._mmode = MM_RATTACK; + monster[i]._mVar1 = missile_type; + monster[i]._mVar2 = dam; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +** Ranged Special weapons +**-----------------------------------------------------------------------*/ + +static void M_StartRSpAttack(int i, int missile_type, int dam) +{ + int md; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + md = M_GetDir(i); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + + monster[i]._mmode = MM_RSATTACK; + monster[i]._mVar1 = missile_type; + monster[i]._mVar2 = 0; + monster[i]._mVar3 = dam; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartSpAttack(int i) +{ + int md; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + md = M_GetDir(i); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + + monster[i]._mmode = MM_SATTACK; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* + * M_StartEat is the same as M_StartSpAttack except mdir isn't affected +**-----------------------------------------------------------------------*/ + +static void M_StartEat(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], monster[i]._mdir); + + monster[i]._mmode = MM_SATTACK; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_ClearSquares(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + int const mx = monster[i]._moldx; + int const my = monster[i]._moldy; + int const mt = -1 - i; + int const mt2 = i + 1; + app_assert((DWORD)(mx+1) < MAXDUNX); + app_assert((DWORD)(my+1) < MAXDUNY); + for (int y = my-1; y <= my+1; ++y) { + for (int x = mx-1; x <= mx+1; ++x) { + if (dMonster[x][y] == mt || dMonster[x][y] == mt2) { + dMonster[x][y] = 0; + } + } + } + + dFlags[mx+1][my+0] &= BFMASK_MONSTLR; + dFlags[mx+0][my+1] &= BFMASK_MONSTLR; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_GetKnockback(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + // knock back enemy if you can + int const d = (monster[i]._mdir + 4) & 0x7; + if (DirOK(i, d)) { + M_ClearSquares(i); + monster[i]._moldx += offset_x[d]; + monster[i]._moldy += offset_y[d]; + NewMonsterAnim(i, monster[i].MType->Anims[MA_GOTHIT], monster[i]._mdir); + monster[i]._mmode = MM_GOTHIT; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mx = monster[i]._moldx; + monster[i]._my = monster[i]._moldy; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); + M_ClearSquares(i); + app_assert((DWORD)monster[i]._mx < MAXDUNX); + app_assert((DWORD)monster[i]._my < MAXDUNY); + dMonster[monster[i]._mx][monster[i]._my] = i + 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_StartHit(int i, int pnum, int dam) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + if (pnum >= 0) monster[i].mWhoHit |= (1 << pnum); // Who damaged me + + if (pnum == myplr) { + extern void delta_monster_hp(int mi,long hp,BYTE bLevel); + delta_monster_hp(i,monster[i]._mhitpoints,currlevel); + NetSendCmdMonstDamage(FALSE,i,dam); + } + PlayEffect(i, MS_GOTHIT); + + // Sneaky demons always get hit + if (!EquivMonst(monster[i].MType->mtype, MT_SNEAK)) + // Other monsters only get hit if damage is severe + //if (((dam >> HP_SHIFT) < (monster[i].mLevel + 3)) && (!(plr[pnum]._pIFlags & IAF_KNOCKBACK))) + if ((dam >> HP_SHIFT) < (monster[i].mLevel + 3)) + return; + + // Set monster's enemy to be this player + if (pnum >= 0) { + monster[i]._menemy = pnum; + monster[i]._menemyx = plr[pnum]._pfutx; + monster[i]._menemyy = plr[pnum]._pfuty; + monster[i]._mFlags &= ~MFLAG_MID; + monster[i]._mdir = M_GetDir(i); + } + + // Check for special hits/teleports + if(monster[i].MType->mtype == MT_BLINK) { + M_Teleport(i); + } else { + if (EquivMonst(monster[i].MType->mtype, MT_NSCAV) || + monster[i].MType->mtype == MT_GRAVDG) { + // allow it to seek food again. + monster[i]._mgoal = MG_ATTACK; + monster[i]._mgoalvar1 = 0; + monster[i]._mgoalvar2 = 0; + } + } + if (monster[i]._mmode != MM_STONE) { + NewMonsterAnim(i, monster[i].MType->Anims[MA_GOTHIT], monster[i]._mdir); + monster[i]._mmode = MM_GOTHIT; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mx = monster[i]._moldx; + monster[i]._my = monster[i]._moldy; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); + M_ClearSquares(i); + dMonster[monster[i]._mx][monster[i]._my] = i + 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void M_DiabloDeath(int i, BOOL sendmsg) +{ + MonsterStruct *Monst = &monster[i]; + + // disable any other sounds from playing, for dramatic effect + #if !IS_VERSION(SHAREWARE) + PlaySFX(USFX_DIABLOD); + #endif + quests[Q_DIABLO]._qactive = QUEST_DONE; + if (sendmsg) NetSendCmdQuest(TRUE, Q_DIABLO); + sgbSaveSoundOn = gbSoundOn; + gbSoundOn = FALSE; + // disable player processing, so we can take over screen scrolling + gbProcessPlayers = FALSE; + // kill all other monsters on level + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for (int j = 0; j < nummonsters; ++j) { + int const k = monstactive[j]; + if (k != i && monster[i]._msquelch) { + NewMonsterAnim(k, monster[k].MType->Anims[MA_DEATH], monster[k]._mdir); + monster[k]._mmode = MM_DEATH; + monster[k]._mxoff = 0; + monster[k]._myoff = 0; + monster[k]._mVar1 = 0; + monster[k]._mx = monster[k]._moldx; + monster[k]._my = monster[k]._moldy; + monster[k]._mfutx = monster[k]._mx; + monster[k]._mfuty = monster[k]._my; + monster[k]._moldx = monster[k]._mx; + monster[k]._moldy = monster[k]._my; + M_CheckEFlag(k); + M_ClearSquares(k); + dMonster[monster[k]._mx][monster[k]._my] = k + 1; + } + } + AddLight(Monst->_mx, Monst->_my, 8); + DoVision(Monst->_mx, Monst->_my, 8, FALSE, TRUE); + // set up scrolling vars + int steps = max(abs(ViewX-Monst->_mx),abs(ViewY-Monst->_my)); + steps = min(20, steps); + + Monst->_mVar3 = ViewX << 16; // convert to fixed-point + Monst->_mVar4 = ViewY << 16; + // calculate scroll offsets + Monst->_mVar5 = (int)((double)(Monst->_mVar3 - (Monst->_mx << 16))/(double)steps); + Monst->_mVar6 = (int)((double)(Monst->_mVar4 - (Monst->_my << 16))/(double)steps); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M2MStartHit(int mid, int i, int dam) +{ + if ((DWORD)mid >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("Invalid monster %d getting hit by monster",mid); +#else + return; +#endif + } + if (monster[mid].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("Monster %d \"%s\" getting hit by monster: MType NULL",mid,monster[mid].mName); +#else + return; +#endif + } + + if (i >= 0) monster[i].mWhoHit |= (1 << i); // Who damaged me + + extern void delta_monster_hp(int mi,long hp, BYTE bLevel); + delta_monster_hp(mid, monster[mid]._mhitpoints, currlevel); + NetSendCmdMonstDamage(FALSE, mid, dam); + + PlayEffect(mid, MS_GOTHIT); + + // Sneaky demons always get hit + if (!EquivMonst(monster[mid].MType->mtype, MT_SNEAK)) + // Other monsters only get hit if damage is severe + if ((dam >> HP_SHIFT) < (monster[mid].mLevel + 3)) return; + + // face plr who hit me + if (i >= 0) monster[mid]._mdir = (monster[i]._mdir + 4) &0x07; + + // Check for special hits/teleports + if(monster[mid].MType->mtype == MT_BLINK) { + M_Teleport(mid); + } else { + if (EquivMonst(monster[mid].MType->mtype, MT_NSCAV) || + monster[mid].MType->mtype == MT_GRAVDG) { + // allow it to seek food again. + monster[mid]._mgoal = MG_ATTACK; + monster[mid]._mgoalvar1 = 0; + monster[mid]._mgoalvar2 = 0; + } + } + + if (monster[mid]._mmode != MM_STONE) { + if (monster[mid].MType->mtype != MT_GOLEM) { + NewMonsterAnim(mid, monster[mid].MType->Anims[MA_GOTHIT], monster[mid]._mdir); + monster[mid]._mmode = MM_GOTHIT; + } + + monster[mid]._mxoff = 0; + monster[mid]._myoff = 0; + monster[mid]._mx = monster[mid]._moldx; + monster[mid]._my = monster[mid]._moldy; + monster[mid]._mfutx = monster[mid]._mx; + monster[mid]._mfuty = monster[mid]._my; + monster[mid]._moldx = monster[mid]._mx; + monster[mid]._moldy = monster[mid]._my; + M_CheckEFlag(mid); + M_ClearSquares(mid); + dMonster[monster[mid]._mx][monster[mid]._my] = mid + 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void MonstKillEffect(int i, BOOL sendmsg) +{ + MonsterStruct *Monst = &monster[i]; + + if (QuestStatus(Q_GARBUD) && (Monst->mName == UniqMonst[MU_GARBUD].mName)) + CreateTypeItem(Monst->_mx+1, Monst->_my+1, TRUE, IT_MACE, IMID_NONE, TRUE, FALSE); + else if (Monst->mName == UniqMonst[MU_DEFILER].mName) + { + if (effect_is_playing(HSFX_DEFILER5)) + stream_stop(); + + quests[Q_DEFILER]._qlog = FALSE; + SpawnMap(Monst->_mx, Monst->_my); + } + else if (Monst->mName == UniqMonst[MU_HORKDEMON].mName) + { + if (gbTheo) + SpawnBear(Monst->_mx, Monst->_my); + else + CreateAmulet(Monst->_mx, Monst->_my, 13, FALSE, TRUE); + } + else if (Monst->MType->mtype == MT_SPAWN) + { + // do nothing + } + else if (Monst->MType->mtype == MT_NKR) + { + int whichEffect = (Na_Krul.Books)?HSFX_NA_KRUL4:HSFX_NA_KRUL5; + if (gbCowsuit) // override -- funny + whichEffect = HSFX_NA_KRUL6; + + if (effect_is_playing(whichEffect)) + stream_stop(); + + quests[Q_NA_KRUL]._qlog = FALSE; + Na_Krul.MIndex = -2; + CreateMagicWeapon(Monst->_mx, Monst->_my, IT_SWORD, ITEM_GRTSWORD, FALSE, TRUE); + CreateMagicWeapon(Monst->_mx, Monst->_my, IT_STAFF, ITEM_STLSTAFF, FALSE, TRUE); + CreateMagicWeapon(Monst->_mx, Monst->_my, IT_BOW, ITEM_STLLONGBOW, FALSE, TRUE); + CreateSpellBook (Monst->_mx, Monst->_my, SPL_APOCA, FALSE, TRUE); + } + else if (i > 3) + { + SpawnItem(i, Monst->_mx, Monst->_my, sendmsg); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void MonstStartKill(int i, int pnum, BOOL sendmsg) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined (_DEBUG) + app_fatal("MonstStartKill: Invalid monster %d",i); +#else + return; +#endif + } + + if (monster[i].MType == NULL) + { + //app_fatal("MonstStartKill: Monster %d \"%s\" MType NULL",i,monster[i].mName); + return; + } + + int md; + MonsterStruct *Monst = &monster[i]; + + // killer gets credit too, and divvy up exper + if (pnum >= 0) Monst->mWhoHit |= (1 << pnum); // Who killed me + + // rjs.patch1.start.1/23/97 - fixes golem giving exp when killed + //old. if (pnum < MAX_PLRS) AddPlrMonstExper(Monst->mLevel, Monst->mExp, Monst->mWhoHit); + if ((pnum < MAX_PLRS) && (i > MAX_PLRS)) AddPlrMonstExper(Monst->mLevel, Monst->mExp, Monst->mWhoHit); + // rjs.patch1.end.1/23/97 + + // Kill the monster (for myplr or other plr) + ++monstkills[Monst->MType->mtype]; + Monst->_mhitpoints = 0; + SetRndSeed(Monst->_mRndSeed); + MonstKillEffect(i, sendmsg); + +#if 0 + if (QuestStatus(Q_GARBUD) && (Monst->mName == UniqMonst[MU_GARBUD].mName)) + CreateTypeItem(Monst->_mx+1, Monst->_my+1, TRUE, IT_MACE, IMID_NONE, TRUE, FALSE); + else if (Monst->mName == UniqMonst[MU_DEFILER].mName) + { + quests[Q_DEFILER]._qlog = FALSE; + SpawnMap(Monst->_mx, Monst->_my); + } + else if (Monst->mName == UniqMonst[MU_HORKDEMON].mName) + if (gbTheo) + SpawnBear(Monst->_mx, Monst->_my); + else if (Monst->MType->mtype == MT_SPAWN) + { + // do nothing + } + else if (Monst->MType->mtype == MT_NKR) + { + quests[Q_NA_KRUL]._qlog = FALSE; + } + else if (i > 3) SpawnItem(i, Monst->_mx, Monst->_my, sendmsg); +#endif + + if (Monst->MType->mtype == MT_DIABLO) { + M_DiabloDeath(i, TRUE); + } + else + PlayEffect(i, MS_DEATH); + + if (pnum >= 0) md = M_GetDir(i); + else md = Monst->_mdir; + Monst->_mdir = md; + NewMonsterAnim(i, Monst->MType->Anims[MA_DEATH], md); + Monst->_mmode = MM_DEATH; + Monst->_mgoal = 0; + Monst->_mxoff = 0; + Monst->_myoff = 0; + Monst->_mVar1 = 0; + Monst->_mx = Monst->_moldx; + Monst->_my = Monst->_moldy; + Monst->_mfutx = Monst->_mx; + Monst->_mfuty = Monst->_my; + Monst->_moldx = Monst->_mx; + Monst->_moldy = Monst->_my; + M_CheckEFlag(i); + M_ClearSquares(i); + dMonster[Monst->_mx][Monst->_my] = i + 1; + CheckQuestKill(i, sendmsg); + // Send Fallen Ones running in fear + M_FallenFear(Monst->_mx, Monst->_my); + // Acid demon emits acid pool + if ((EquivMonst(Monst->MType->mtype, MT_NACID)) || + (Monst->MType->mtype == MT_SPIDER2)) + AddMissile(Monst->_mx, Monst->_my, 0, 0, 0, MIT_ACIDPUD, MI_ENEMYPLR, i, Monst->_mint + 1, 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M2MStartKill(int i, int mid) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M2MStartKill: Invalid monster (attacker) %d",i); +#else + return; +#endif + } + if ((DWORD)mid >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M2MStartKill: Invalid monster (killed) %d",mid); +#else + return; +#endif + } + if (monster[i].MType == NULL) + { + //app_fatal("M2MStartKill: Monster %d \"%s\" MType NULL",mid,monster[mid].mName); + return; + } + + int md; + + void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel); + delta_kill_monster(mid, monster[mid]._mx, monster[mid]._my, currlevel); + NetSendCmdLocParam1(FALSE, CMD_MONSTDEATH, monster[mid]._mx, monster[mid]._my, mid); + + monster[mid].mWhoHit |= (1 << i); // Who killed me + if (i < MAX_PLRS) AddPlrMonstExper(monster[mid].mLevel, monster[mid].mExp, monster[mid].mWhoHit); + + ++monstkills[monster[mid].MType->mtype]; + monster[mid]._mhitpoints = 0; + SetRndSeed(monster[mid]._mRndSeed); + + MonstKillEffect(mid, TRUE); +#if 0 + // @@@ needs to be fixed for multiplayer (death not synced, etc) + if (mid >= MAX_PLRS) SpawnItem(mid, monster[mid]._mx, monster[mid]._my, TRUE); +#endif + + if (monster[mid].MType->mtype == MT_DIABLO) { + M_DiabloDeath(mid, TRUE); + } + else + PlayEffect(mid, MS_DEATH); + //PlayEffect(mid, MS_DEATH); + md = (monster[i]._mdir + 4) & 0x07; + if (monster[mid].MType->mtype == MT_GOLEM) md = 0; + monster[mid]._mdir = md; + NewMonsterAnim(mid, monster[mid].MType->Anims[MA_DEATH], md); + monster[mid]._mmode = MM_DEATH; + monster[mid]._mxoff = 0; + monster[mid]._myoff = 0; + monster[mid]._mx = monster[mid]._moldx; + monster[mid]._my = monster[mid]._moldy; + monster[mid]._mfutx = monster[mid]._mx; + monster[mid]._mfuty = monster[mid]._my; + monster[mid]._moldx = monster[mid]._mx; + monster[mid]._moldy = monster[mid]._my; + M_CheckEFlag(mid); + M_ClearSquares(mid); + dMonster[monster[mid]._mx][monster[mid]._my] = mid + 1; + CheckQuestKill(mid, TRUE); + + // Send Fallen Ones running in fear + M_FallenFear(monster[mid]._mx, monster[mid]._my); + // Acid demon emits acid pool + if(EquivMonst(monster[mid].MType->mtype, MT_NACID)) + AddMissile(monster[mid]._mx, monster[mid]._my, 0, 0, 0, MIT_ACIDPUD, MI_ENEMYPLR, mid, monster[mid]._mint + 1, 0); + + M_StartStand(i, monster[i]._mdir); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartKill(int i, int pnum) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined (_DEBUG) + app_fatal("M_StartKill: Invalid monster %d",i); +#else + return; +#endif + } + // Send a message to everyone saying I killed the monster + if (myplr == pnum) { + void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel); + delta_kill_monster(i,monster[i]._mx,monster[i]._my,currlevel); + if (i != pnum) + NetSendCmdLocParam1(FALSE,CMD_MONSTDEATH,monster[i]._mx,monster[i]._my,i); + else + NetSendCmdLocParam1(FALSE,CMD_KILLGOLEM,monster[i]._mx,monster[i]._my,currlevel); + } + + MonstStartKill(i, pnum, TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_SyncStartKill(int i, int x, int y, int pnum) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_SyncStartKill: Invalid monster %d",i); +#else + return; +#endif + } + // Already dead? + if (monster[i]._mhitpoints == 0) return; + if (monster[i]._mmode == MM_DEATH) return; + + app_assert(pnum != myplr); + + if (!dMonster[x][y]) { + M_ClearSquares(i); + monster[i]._mx = x; + monster[i]._my = y; + monster[i]._moldx = x; + monster[i]._moldy = y; + } + MonstStartKill(i, pnum, FALSE); +// app_assert(dMonster[monster[i]._mx][monster[i]._my] == i+1 +// || dMonster[monster[i]._mx][monster[i]._my] == -(i+1)); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartFadein(int i, int md, BOOL backwards) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_StartFadein: Invalid monster %d",i); +#else + return; +#endif + } + + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_StartFadein: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return; +#endif + } + + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + + monster[i]._mmode = MM_FADEIN; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); + monster[i]._mdir = md; + monster[i]._mFlags &= ~MFLAG_INVISIBLE; + if (backwards) + { + monster[i]._mFlags |= MFLAG_BACKWARDS; + monster[i]._mAnimFrame = monster[i]._mAnimLen; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartFadeout(int i, int md, BOOL backwards) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_StartFadeout: Invalid monster %d",i); +#else + return; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_StartFadeout: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return; +#endif + } + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + monster[i]._mmode = MM_FADEOUT; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); + monster[i]._mdir = md; + if (backwards) + { + monster[i]._mFlags |= MFLAG_BACKWARDS; + monster[i]._mAnimFrame = monster[i]._mAnimLen; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_StartHeal(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_StartHeal: Invalid monster %d",i); +#else + return; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_StartHeal: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + Monst->_mAnimData = Monst->MType->Anims[MA_SPECIAL].Cels[Monst->_mdir]; + Monst->_mAnimFrame = Monst->MType->Anims[MA_SPECIAL].Frames; + Monst->_mFlags |= MFLAG_BACKWARDS; + Monst->_mmode = MM_HEAL; + Monst->_mVar1 = Monst->_mmaxhp / (16*(random(97, 5)+4)); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_ChangeLightOffset(int monst) +{ + if ((DWORD)monst >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_ChangeLightOffset: Invalid monster %d",monst); +#else + return; +#endif + } + int lx,ly; + int sign; + + lx = (monster[monst]._mxoff + (monster[monst]._myoff << 1)); + ly = ((monster[monst]._myoff << 1) - monster[monst]._mxoff); + + // Divide these values by 8, because lighting offsets have + // 8 subdivisions per tile. + if (lx < 0) + { + sign = -1; + lx = -lx; + } + else + sign = 1; + lx = lx >> 3; + lx *= sign; + + if (ly < 0) + { + sign = -1; + ly = -ly; + } + else + sign = 1; + ly = ly >> 3; + ly *= sign; + + if (monster[monst].mlid != 0) { + ChangeLightOff(monster[monst].mlid, lx, ly); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoStand(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoStand: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoStand: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->MType->mtype == MT_GOLEM) + Monst->_mAnimData = Monst->MType->Anims[MA_WALK].Cels[Monst->_mdir]; + else + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + if (Monst->_mAnimFrame == Monst->_mAnimLen) { + M_Enemy(i); + } + + ++Monst->_mVar2; + return RUN_DONE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoWalk(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoWalk: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoWalk: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + int rv; + + if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) { + dMonster[monster[i]._mx][monster[i]._my] = 0; + monster[i]._mx += monster[i]._mVar1; + monster[i]._my += monster[i]._mVar2; + dMonster[monster[i]._mx][monster[i]._my] = i + 1; + if( !(monster[i]._mFlags & MFLAG_INVISIBLE) + && monster[i].mlid != 0) { + ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my); + } + M_StartStand(i, monster[i]._mdir); + rv = RUN_AGAIN; +// DaveMonstMap(FALSE, 0); + } else { + if (monster[i]._mAnimCnt == 0) { + if (monster[i]._mVar8 == 0 && monster[i].MType->mtype == MT_FLESH) + { + PlayEffect(i, MS_SATTACK); + } + ++monster[i]._mVar8; + monster[i]._mVar6 += monster[i]._mxvel; + monster[i]._mVar7 += monster[i]._myvel; + monster[i]._mxoff = monster[i]._mVar6 >> 4; + monster[i]._myoff = monster[i]._mVar7 >> 4; + } + rv = RUN_DONE; + } + if( !(monster[i]._mFlags & MFLAG_INVISIBLE) + && monster[i].mlid != 0) + M_ChangeLightOffset(i); + + return (rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoWalk2(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoWalk2: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoWalk2: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + int rv; + + if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) { + dMonster[monster[i]._mVar1][monster[i]._mVar2] = 0; + if( !(monster[i]._mFlags & MFLAG_INVISIBLE) + && monster[i].mlid != 0) { + ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my); + } + M_StartStand(i, monster[i]._mdir); + rv = RUN_AGAIN; +// DaveMonstMap(FALSE, 0); + } else { + if (monster[i]._mAnimCnt == 0) { + if (monster[i]._mVar8 == 0 && monster[i].MType->mtype == MT_FLESH) + { + PlayEffect(i, MS_SATTACK); + } + ++monster[i]._mVar8; + monster[i]._mVar6 += monster[i]._mxvel; + monster[i]._mVar7 += monster[i]._myvel; + monster[i]._mxoff = monster[i]._mVar6 >> 4; + monster[i]._myoff = monster[i]._mVar7 >> 4; + } + rv = RUN_DONE; + } + if( !(monster[i]._mFlags & MFLAG_INVISIBLE) + && monster[i].mlid != 0) + M_ChangeLightOffset(i); + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoWalk3(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoWalk3: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoWalk3: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + int rv; + + if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) { + dMonster[monster[i]._mx][monster[i]._my] = 0; + monster[i]._mx = monster[i]._mVar1; + monster[i]._my = monster[i]._mVar2; + dFlags[monster[i]._mVar4][monster[i]._mVar5] &= BFMASK_MONSTLR; + dMonster[monster[i]._mx][monster[i]._my] = i + 1; + if( !(monster[i]._mFlags & MFLAG_INVISIBLE) + && monster[i].mlid != 0) { + ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my); + } + M_StartStand(i, monster[i]._mdir); + rv = RUN_AGAIN; +// DaveMonstMap(FALSE, 0); + } else { + if (monster[i]._mAnimCnt == 0) { + if (monster[i]._mVar8 == 0 && monster[i].MType->mtype == MT_FLESH) + { + PlayEffect(i, MS_SATTACK); + } + ++monster[i]._mVar8; + monster[i]._mVar6 += monster[i]._mxvel; + monster[i]._mVar7 += monster[i]._myvel; + monster[i]._mxoff = monster[i]._mVar6 >> 4; + monster[i]._myoff = monster[i]._mVar7 >> 4; + } + rv = RUN_DONE; + } + if(monster[i]._uniqtype && !(monster[i]._mFlags & MFLAG_INVISIBLE)) + M_ChangeLightOffset(i); + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_TryM2MHit(int i, int mid, int hper, int mind, int maxd) +{ + int hit, dam; + BOOL ret; + + if ((DWORD)mid >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_TryM2MHit: Invalid monster %d",mid); +#else + return; +#endif + } + if (monster[mid].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_TryM2MHit: Monster %d \"%s\" MType NULL",mid,monster[mid].mName); +#else + return; +#endif + } + + if ((monster[mid]._mhitpoints >> HP_SHIFT) <= 0) return; + if (monster[mid].MType->mtype == MT_ILLWEAV && monster[mid]._mgoal == MG_RUN_AWAY) return; + + hit = random(4, 100); + if (monster[mid]._mmode == MM_STONE) hit = 0; + + if (CheckMonsterHit(mid, ret)) { + return; + } else { + if (hit < hper) { + dam = random(5, maxd - mind + 1) + mind; + dam = dam << HP_SHIFT; + + monster[mid]._mhitpoints -= dam; + //rjs - x2 stone dam fix - if (monster[mid]._mmode == MM_STONE) monster[mid]._mhitpoints -= dam; + if ((monster[mid]._mhitpoints >> HP_SHIFT) <= 0) { + if (monster[mid]._mmode == MM_STONE) { + M2MStartKill(i, mid); + monster[mid]._mmode = MM_STONE; + } else M2MStartKill(i, mid); + } else { + if (monster[mid]._mmode == MM_STONE) { + M2MStartHit(mid, i, dam); + monster[mid]._mmode = MM_STONE; + } else M2MStartHit(mid, i, dam); + } + } + } + return; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_TryH2HHit: Invalid monster %d",i); +#else + return; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_TryH2HHit: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return; +#endif + } + + int hit, hper, tac; + long dam; + int dx, dy; + int blk, blkper, blkdir; + int mdam; + + if ((monster[i]._mFlags & MFLAG_MID) != 0) { + M_TryM2MHit(i, pnum, Hit, MinDam, MaxDam); + return; + } + + app_assert((DWORD)pnum < MAX_PLRS); + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) return; + if (plr[pnum]._pInvincible) return; + if ((plr[pnum]._pSpellFlags & SF_ETHER) != 0) return; + + dx = abs(monster[i]._mx - plr[pnum]._px); + dy = abs(monster[i]._my - plr[pnum]._py); + if ((dx < 2) && (dy < 2)) { + // Did I hit? + hit = random(98, 100); +#if CHEATS + if (simplecheat || cheatflag) hit = 1000; // TEMP! +#endif + //rjs tac = (byte)plr[pnum]._pArmorClass + plr[pnum]._pIAC + plr[pnum]._pIBonusAC; + tac = plr[pnum]._pIAC + plr[pnum]._pIBonusAC; + + if ((plr[pnum]._pIFlags2 & IAF2_DEMONAC) && + (monster[i].MData->mMonstClass == MC_DEMON)) + tac += 40; + if ((plr[pnum]._pIFlags2 & IAF2_UNDEADAC) && + (monster[i].MData->mMonstClass == MC_UNDEAD)) + tac += 20; + + tac += (plr[pnum]._pDexterity / 5); + hper = 30 + Hit - tac + ((monster[i].mLevel - plr[pnum]._pLevel) << 1); + if (hper < 15) hper = 15; + if ((currlevel == 14) && (hper < 20)) hper = 20; + if ((currlevel == 15) && (hper < 25)) hper = 25; + if ((currlevel == 16) && (hper < 30)) hper = 30; + if (((plr[pnum]._pmode == PM_STAND) || (plr[pnum]._pmode == PM_ATTACK)) && (plr[pnum]._pBlockFlag)) blk = random(98, 100); + else blk = 100; + blkper = plr[pnum]._pBaseToBlk + plr[pnum]._pDexterity - ((monster[i].mLevel - plr[pnum]._pLevel) << 1); + if (blkper < 0) blkper = 0; + if (blkper > 100) blkper = 100; + if (hit < hper) { + if (blk < blkper) { + blkdir = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mx, monster[i]._my); + StartPlrBlock(pnum, blkdir); + if (pnum == myplr + && plr[pnum]._pReflectCount > 0) { + --plr[pnum]._pReflectCount; + // Reflect back with 20->30% of the damage. + dam = (MaxDam - MinDam + 1) << HP_SHIFT; + dam = random(99, dam) + (MinDam << HP_SHIFT); + dam += (plr[pnum]._pIGetHit << HP_SHIFT); + if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT); + mdam = static_cast(dam * (0.01 * (random(100, 10) + 20))); + monster[i]._mhitpoints -= mdam; + dam -= mdam; + if (dam < 0) { + dam = 0; + } + if (monster[i]._mhitpoints >> HP_SHIFT <= 0) { + M_StartKill (i, pnum); + } else { + M_StartHit(i, pnum, mdam); + } + } + + + } else { + + + if (monster[i].MType->mtype == MT_YZOMBIE && pnum == myplr) + { + + // find manashield + int k; + int mi; + int msi = -1; + for (k = 0; k < nummissiles; ++k) { + mi = missileactive[k]; + if (missile[mi]._mitype == MIT_MANASHIELD && missile[mi]._misource == pnum) { + msi = mi; + } + } + + if(plr[pnum]._pMaxHP > 1 << HP_SHIFT ) + { + plr[pnum]._pMaxHP -= 1 << HP_SHIFT; + if(plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + if( msi >= 0 ) + missile[msi]._miVar1 = plr[pnum]._pHitPoints; + } + plr[pnum]._pMaxHPBase -= 1 << HP_SHIFT; + if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) { + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + if( msi >= 0 ) + missile[msi]._miVar2 = plr[pnum]._pHPBase; + } + } + + + } + + + + dam = (MaxDam - MinDam + 1) << HP_SHIFT; + dam = random(99, dam) + (MinDam << HP_SHIFT); + dam += (plr[pnum]._pIGetHit << HP_SHIFT); + if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT); + if (pnum == myplr) { + if (plr[pnum]._pReflectCount > 0) + { + --plr[pnum]._pReflectCount; + // Reflect back with 20->30% of the damage. + mdam = static_cast(dam * (0.01 * (random(100, 10) + 20))); + monster[i]._mhitpoints -= mdam; + dam -= mdam; + if (dam < 0) { + dam = 0; + } + if (monster[i]._mhitpoints >> HP_SHIFT <= 0) { + M_StartKill (i, pnum); + } else { + M_StartHit(i, pnum, mdam); + } + } + + plr[pnum]._pHitPoints -= dam; + plr[pnum]._pHPBase -= dam; + } + + + + + if (plr[pnum]._pIFlags & IAF_THORN) { + mdam = ((random (99, 3) + 1) << HP_SHIFT); + monster[i]._mhitpoints -= mdam; + if (monster[i]._mhitpoints >> HP_SHIFT <= 0) { + M_StartKill (i, pnum); + //(old) AddPlrExperience(pnum, monster[i].mLevel, monster[i].mExp); + //(new, but moved) AddPlrMonstExper(monster[i].mLevel, monster[i].mExp, monster[i].mWhoHit); + } else { + M_StartHit(i, pnum, mdam); + } + } + if (!(monster[i]._mFlags & IAF_MNOHEAL)) { + if (monster[i].MType->mtype == MT_SKING + && gbMaxPlayers != 1) + monster[i]._mhitpoints += dam; + } + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + } + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - plr[pnum]._pHitPoints = 0; + StartPlrKill(pnum, FALSE); + M_StartStand(i, monster[i]._mdir); + } else { + StartPlrHit(pnum, dam, FALSE); + + if (monster[i]._mFlags & MFLAG_KNOCKBACK) { + // make sure player is doing a hit animation + if (plr[pnum]._pmode != PM_GOTHIT) + StartPlrHit(pnum, 0, TRUE); + + // knock back enemy one square + int newx,newy,oldx,oldy; + + oldx = plr[pnum]._px; + oldy = plr[pnum]._py; + newx = oldx + offset_x[monster[i]._mdir]; + newy = oldy + offset_y[monster[i]._mdir]; + if(PosOkPlayer(pnum, newx, newy)) + { + plr[pnum]._px = newx; + plr[pnum]._py = newy; + FixPlayerLocation(pnum,plr[pnum]._pdir); + FixPlrWalkTags(pnum); + dPlayer[newx][newy] = pnum + 1; + SetPlayerOld(pnum); + } + } + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoAttack(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoAttack: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoAttack: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoAttack: Monster %d \"%s\" MData NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mAnimFrame == Monst->MData->mAFNum) { + M_TryH2HHit(i, Monst->_menemy, Monst->mHit, Monst->mMinDamage, Monst->mMaxDamage); + if (Monst->_mAi != AI_SNAKE) + PlayEffect(i, MS_ATTACK); + } + // Special code for Magma -- second punch + if (EquivMonst(Monst->MType->mtype, MT_NMAGMA) + && Monst->_mAnimFrame == 9) + { + M_TryH2HHit(i, Monst->_menemy, Monst->mHit+10, Monst->mMinDamage-2, Monst->mMaxDamage-2); + PlayEffect(i, MS_ATTACK); + } + // Special code for Storm -- second punch + if (EquivMonst(Monst->MType->mtype, MT_STORM) + && Monst->_mAnimFrame == 13) + { + M_TryH2HHit(i, Monst->_menemy, Monst->mHit-20, Monst->mMinDamage+4, Monst->mMaxDamage+4); + PlayEffect(i, MS_ATTACK); + } + // Special code for Snake -- play sound before attack frame + if (Monst->_mAi == AI_SNAKE && Monst->_mAnimFrame == 1) + PlayEffect(i, MS_ATTACK); + + if (Monst->_mAnimFrame == Monst->_mAnimLen) { + M_StartStand(i, Monst->_mdir); + return(RUN_AGAIN); + } else return (RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoRAttack(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoRAttack: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoRAttack: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoRAttack: Monster %d \"%s\" MData NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + int multimissiles; + int mi; + + if (monster[i]._mAnimFrame == monster[i].MData->mAFNum) { + if (monster[i]._mVar1 != -1) + { + if (monster[i]._mVar1 == MIT_CBOLT) + multimissiles = 3; + else + multimissiles = 1; + for (mi = 0; mi < multimissiles; ++mi) // special loop code to handle CBOLT, which must be cast 3 times + AddMissile(monster[i]._mx + infront_x[monster[i]._mdir], + monster[i]._my + infront_y[monster[i]._mdir], + monster[i]._menemyx, monster[i]._menemyy, monster[i]._mdir, monster[i]._mVar1, MI_ENEMYPLR, i, monster[i]._mVar2, 0); + } + PlayEffect(i, MS_ATTACK); + } + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return (RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoRSpAttack(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoRSpAttack: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoRSpAttack: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoRSpAttack: Monster %d \"%s\" MData NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2 && !monster[i]._mAnimCnt) { + AddMissile(monster[i]._mx + infront_x[monster[i]._mdir], + monster[i]._my + infront_y[monster[i]._mdir], + monster[i]._menemyx, monster[i]._menemyy, monster[i]._mdir, monster[i]._mVar1, MI_ENEMYPLR, i, monster[i]._mVar3, 0); + if (Monsters[i].Snds[MS_SATTACK].effect[0] != 0){ + PlayEffect(i, MS_SATTACK); + } + } + + // special code for Mega demon -- hold attack animation frame + if (monster[i]._mAi == AI_MEGA && monster[i]._mAnimFrame == 3) + { + if (!monster[i]._mVar2++) + monster[i]._mFlags |= MFLAG_STILL; + else if (monster[i]._mVar2 == 15) + monster[i]._mFlags &= ~MFLAG_STILL; + } + + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return (RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoSAttack(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoSAttack: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoSAttack: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoSAttack: Monster %d \"%s\" MData NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2) + M_TryH2HHit(i, monster[i]._menemy, monster[i].mHit2, monster[i].mMinDamage2, monster[i].mMaxDamage2); + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoFadein(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoFadein: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if ((monster[i]._mFlags & MFLAG_BACKWARDS && monster[i]._mAnimFrame == 1) + || (!(monster[i]._mFlags & MFLAG_BACKWARDS) && monster[i]._mAnimFrame == monster[i]._mAnimLen)) + { + M_StartStand(i, monster[i]._mdir); + monster[i]._mFlags &= ~MFLAG_BACKWARDS; + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoFadeout(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoFadeout: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + int mtype; + if ((monster[i]._mFlags & MFLAG_BACKWARDS && monster[i]._mAnimFrame == 1) + || (!(monster[i]._mFlags & MFLAG_BACKWARDS) && monster[i]._mAnimFrame == monster[i]._mAnimLen)) + { + app_assert(monster[i].MType != NULL); + mtype = monster[i].MType->mtype; + if (EquivMonst(mtype, MT_INCIN)) + monster[i]._mFlags &= ~MFLAG_BACKWARDS; + else + { + monster[i]._mFlags &= ~MFLAG_BACKWARDS; + monster[i]._mFlags |= MFLAG_INVISIBLE; + } + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoHeal(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoHeal: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (monster[i]._mFlags & MFLAG_NOHEAL) return RUN_DONE; + // Gargoyle turning back to stone + if(Monst->_mAnimFrame == 1) + { + Monst->_mFlags &= ~MFLAG_BACKWARDS; + Monst->_mFlags |= MFLAG_STILL; + if(Monst->_mhitpoints + Monst->_mVar1 < Monst->_mmaxhp) + Monst->_mhitpoints += Monst->_mVar1; + else + { + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->_mFlags &= ~MFLAG_STILL; + Monst->_mmode = MM_SATTACK; + } + } + return RUN_DONE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +int M_DoTalk(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoTalk: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + MonsterStruct *Monst = &monster[i]; + + M_StartStand(i, monster[i]._mdir); + Monst->_mgoal=MG_WAITTOTALK; + if (effect_is_playing(alltext[monster[i].mtalkmsg].sfxnr)) return RUN_DONE; + InitQTextMsg(monster[i].mtalkmsg); + if (monster[i].mName == UniqMonst[MU_GARBUD].mName) { + if (monster[i].mtalkmsg == TXT_GARB1) + quests[Q_GARBUD]._qactive = QUEST_NOTDONE; + quests[Q_GARBUD]._qlog = TRUE; + if (monster[i].mtalkmsg == TXT_GARB2) { + if(!(monster[i]._mFlags & MFLAG_DROP)) { + SpawnItem(i, monster[i]._mx+1, monster[i]._my+1, TRUE); + monster[i]._mFlags |= MFLAG_DROP; + } + } + } + if (monster[i].mName == UniqMonst[MU_ZHAR].mName) { + if (monster[i].mtalkmsg == TXT_ZHAR1) { + if(!(monster[i]._mFlags & MFLAG_DROP)) { + quests[Q_ZHAR]._qactive = QUEST_NOTDONE; + quests[Q_ZHAR]._qlog = TRUE; + CreateTypeItem(monster[i]._mx+1, monster[i]._my+1, FALSE, IT_MISC, IMID_BOOK, TRUE, FALSE); + monster[i]._mFlags |= MFLAG_DROP; + } + } + } + if (monster[i].mName == UniqMonst[MU_SNOTSPIL].mName) { + if ((monster[i].mtalkmsg == TXT_BOL1) && (!(monster[i]._mFlags & MFLAG_DROP))) { + app_assert(setpc_x != 0); + ObjChangeMap(setpc_x, setpc_y, setpc_x+(setpc_w>>1)+2, setpc_y+(setpc_h>>1)-2); + int const tren = TransVal; + TransVal = 9; + DRLG_MRectTrans(setpc_x, setpc_y, setpc_x+(setpc_w>>1)+4, setpc_y+(setpc_h>>1)); + TransVal = tren; + quests[Q_LTBANNER]._qvar1 = 2; + if (quests[Q_LTBANNER]._qactive == QUEST_NOTACTIVE) quests[Q_LTBANNER]._qactive = QUEST_NOTDONE; + monster[i]._mFlags |= MFLAG_DROP; + } + if (quests[Q_LTBANNER]._qvar1 < 2) { + sprintf(tempstr, "SS Talk = %i, Flags = %i", monster[i].mtalkmsg, monster[i]._mFlags); + app_fatal(tempstr); + } + } + if (monster[i].mName == UniqMonst[MU_LACHDA].mName) { + if (monster[i].mtalkmsg == TXT_VEIL1) { + quests[Q_VEIL]._qactive = QUEST_NOTDONE; + quests[Q_VEIL]._qlog = TRUE; + } + if ((monster[i].mtalkmsg == TXT_VEIL3) && (!(monster[i]._mFlags & MFLAG_DROP))) { + SpawnUnique(UID_STEELVEIL, monster[i]._mx+1, monster[i]._my+1); + monster[i]._mFlags |= MFLAG_DROP; + } + } + if (monster[i].mName == UniqMonst[MU_WARLORD].mName) { + app_assert(gbMaxPlayers == 1); + quests[Q_WARLORD]._qvar1 = 2; + } + if ((monster[i].mName == UniqMonst[MU_LAZARUS].mName) && (gbMaxPlayers != 1)) { + quests[Q_BETRAYER]._qvar1 = 6; + monster[i]._mgoal = MG_ATTACK; + monster[i]._msquelch = 255; + monster[i].mtalkmsg = 0; + } + return RUN_DONE; +} + +/*-----------------------------------------------------------------------* + * M_Teleport + * + * Teleports monster i to one of it's enemy's 8 adjacent squares. +**----------------------------------------------------------------------*/ + +void M_Teleport(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_Teleport: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + BOOL done = FALSE; + int mulx,muly; + int x,y; + int a,b; + int px,py; + + if (Monst->_mmode == MM_STONE) + return; + + px = Monst->_menemyx; + py = Monst->_menemyy; + + // randomize search direction + mulx = random(100,2)*2-1; + muly = random(100,2)*2-1; + for(a = -1; a <= 1 && !done; ++a) + for(b = -1; b < 1 && !done; ++b) + if(a || b) + { + x = px + a*mulx; + y = py + b*muly; + if(InBounds(x,y) + && x != Monst->_mx && y != Monst->_my) + if(PosOkMonst(i,x,y)) + done = TRUE; + } + if(done) + { + M_ClearSquares(i); + app_assert((DWORD)Monst->_mx < MAXDUNX); + app_assert((DWORD)Monst->_my < MAXDUNY); + dMonster[Monst->_mx][Monst->_my] = 0; + dMonster[x][y] = i+1; + // M_StartHit knocks monster back to oldx,oldy, so those are the members to set + Monst->_moldx = x; + Monst->_moldy = y; + Monst->_mdir = M_GetDir(i); + M_CheckEFlag(i); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoGotHit(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoGotHit: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoGotHit: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_UpdateLeader(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_UpdateLeader: Invalid monster %d",i); +#else + return; +#endif + } + int x,tmp; + + // check for pack leader + if(monster[i]._uniqtype && (UniqMonst[monster[i]._uniqtype-1].mUnqAttr & UN_STICK)) + // free the pack + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for(x = 0; x < nummonsters; ++x) + { + if(monster[tmp=monstactive[x]].leaderflag == PACK_MEMBER + && monster[tmp].leader == i) + { + monster[tmp].leaderflag = 0; + } + } + // check for pack member + if(monster[i].leaderflag == PACK_MEMBER) + --monster[monster[i].leader].packsize; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void play_movie(const char * pszMovie,BOOL bAllowCancel); +extern BOOL gbRunGame; +extern BOOL deathflag; +extern BYTE gbDoEnding; + +void DoEnding() { + // tell other players to view victory + if (gbMaxPlayers > 1) SNetLeaveGame(SNET_EXIT_PLAYERWON); + + //SetCursor(NO_CURSOR); + //FullBlit(TRUE); + //PaletteFadeOut(FADE_FAST); + music_stop(); + + // give SNet some more time to field messages + if (gbMaxPlayers > 1) Sleep(1000); + + #if !IS_VERSION(SHAREWARE) + LONG lMusicVol; + BOOL bMusicOn; + if (plr[myplr]._pClass == CLASS_WARRIOR + || plr[myplr]._pClass == CLASS_BARBARIAN) play_movie("gendata\\DiabVic2.smk",FALSE); + else if (plr[myplr]._pClass == CLASS_SORCEROR) play_movie("gendata\\DiabVic1.smk",FALSE); + else if (plr[myplr]._pClass == CLASS_MONK) play_movie("gendata\\DiabVic1.smk",FALSE); + else play_movie("gendata\\DiabVic3.smk",FALSE); + play_movie("gendata\\Diabend.smk",FALSE); + + // turn music to full volume + bMusicOn = gbMusicOn; + gbMusicOn = TRUE; + lMusicVol = music_volume(VOLUME_READ); + music_volume(VOLUME_MAX); + music_start(MUSIC_L2); + + extern BOOL gbLoopMovie; + gbLoopMovie = TRUE; + play_movie("gendata\\loopdend.smk",TRUE); + gbLoopMovie = FALSE; + #endif + + //ClrDraw(); + //FullBlit(FALSE); + //PaletteFadeOut(FADE_FAST); + + // restore music volume + #if !IS_VERSION(SHAREWARE) + music_stop(); + music_volume(lMusicVol); + gbMusicOn = bMusicOn; + #endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PrepDoEnding() { + // enable sound again + gbSoundOn = sgbSaveSoundOn; + gbDoEnding = TRUE; + gbRunGame = FALSE; + deathflag = FALSE; + + app_assert((DWORD)myplr < MAX_PLRS); + plr[myplr].pDiabloKillLevel = max( + plr[myplr].pDiabloKillLevel, + (DWORD) gnDifficulty + 1 + ); + + for (int i = 0; i < MAX_PLRS; ++i) { + plr[i]._pmode = PM_QUIT; + plr[i]._pInvincible = TRUE; + if (gbMaxPlayers > 1) { + if ((plr[i]._pHitPoints >> HP_SHIFT) == 0) + plr[i]._pHitPoints = 1 << HP_SHIFT; + if ((plr[i]._pMana >> MANA_SHIFT) == 0) + plr[i]._pMana = 1 << MANA_SHIFT; + } + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int M_DoDeath(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoDeath: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoDeath: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + ++monster[i]._mVar1; + if (monster[i].MType->mtype == MT_DIABLO) { + ViewX += Sign(monster[i]._mx - ViewX); + ViewY += Sign(monster[i]._my - ViewY); + if (monster[i]._mVar1 == 140) { + PrepDoEnding(); + } + } else { + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + if (monster[i]._uniqtype == 0) + AddDead(monster[i]._mx, monster[i]._my, monster[i].MType->mdeadval, monster[i]._mdir); + else + AddDead(monster[i]._mx, monster[i]._my, monster[i]._udeadval, monster[i]._mdir); + app_assert(!(dFlags[monster[i]._mx+1][monster[i]._my] & BFLAG_MONSTLR) + && !(dFlags[monster[i]._mx][monster[i]._my+1] & BFLAG_MONSTLR)); + dMonster[monster[i]._mx][monster[i]._my] = 0; + monster[i]._mDelFlag = TRUE; + M_UpdateLeader(i); + } + } + return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoSpStand(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoSpStand: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoSpStand: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2) { + PlayEffect(i, MS_SATTACK); + } + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +int M_DoDelay(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoDelay: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_DoDelay: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return RUN_DONE; +#endif + } + int md; + + md = M_GetDir(i); + monster[i]._mAnimData = monster[i].MType->Anims[MA_STAND].Cels[md]; + if (monster[i]._mAi == AI_LAZURUS) { + if ((monster[i]._mVar2 > 8) || (monster[i]._mVar2 < 0)) monster[i]._mVar2 = 8; + } + if(!monster[i]._mVar2--) + { + int tmp = monster[i]._mAnimFrame; + M_StartStand(i, monster[i]._mdir); // StartStand sets AnimFrame to 0 + monster[i]._mAnimFrame = tmp; // restore AnimFrame to avoid pop + // in case monster continues standing. + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoStone(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_DoStone: Invalid monster %d",i); +#else + return RUN_DONE; +#endif + } + if (monster[i]._mhitpoints == 0) { + dMonster[monster[i]._mx][monster[i]._my] = 0; + monster[i]._mDelFlag = TRUE; + } + return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_WalkDir(int i, int md) +{ + int mwi; + + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_WalkDir: Invalid monster %d",i); +#else + return; +#endif + } + mwi = monster[i].MType->Anims[MA_WALK].Frames - 1; + + switch (md) { + case M_DIRU : + M_StartWalk(i, 0, -MWVel[mwi][1], -1, -1, M_DIRU); + break; + case M_DIRUR : + M_StartWalk(i, MWVel[mwi][1], -MWVel[mwi][0], 0, -1, M_DIRUR); + break; + case M_DIRR : + M_StartWalk3(i, MWVel[mwi][2], 0, -32, -16, 1, -1, 1, 0, M_DIRR); + break; + case M_DIRDR : + M_StartWalk2(i, MWVel[mwi][1], MWVel[mwi][0], -32, -16, 1, 0, M_DIRDR); + break; + case M_DIRD : + M_StartWalk2(i, 0, MWVel[mwi][1], 0, -32, 1, 1, M_DIRD); + break; + case M_DIRDL : + M_StartWalk2(i, -MWVel[mwi][1], MWVel[mwi][0], 32, -16, 0, 1, M_DIRDL); + break; + case M_DIRL : + M_StartWalk3(i, -MWVel[mwi][2], 0, 32, -16, -1, 1, 0, 1, M_DIRL); + break; + case M_DIRUL : + M_StartWalk(i, -MWVel[mwi][1], -MWVel[mwi][0], -1 ,0, M_DIRUL); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GroupUnity(int i) +{ + int leader; + int tmp; + int m; + + // + // IMPLEMENT GROUP COHESION + // + + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("GroupUnity: Invalid monster %d",i); +#else + return; +#endif + } + if(monster[i].leaderflag) + { + leader = monster[i].leader; + + // test if there's a wall between monst and pack leader + tmp = LineClearF(CheckNoSolid, monster[i]._mx, monster[i]._my, + monster[leader]._mfutx, monster[leader]._mfuty); + if(!tmp && monster[i].leaderflag == PACK_MEMBER) + { + // have to leave pack + --monster[leader].packsize; + monster[i].leaderflag = PACK_NOMEMBER; + } + else if(tmp && monster[i].leaderflag == PACK_NOMEMBER + && DIST(monster[i]._mx - monster[leader]._mfutx, + monster[i]._my - monster[leader]._mfuty, 4)) + { + // rejoin pack + ++monster[leader].packsize; + monster[i].leaderflag = PACK_MEMBER; + } + } + + if(monster[i].leaderflag == PACK_MEMBER) + { + // make sure leader is active + if(monster[i]._msquelch > monster[leader]._msquelch) + { + monster[leader]._lastx = monster[i]._mx; + monster[leader]._lasty = monster[i]._my; + monster[leader]._msquelch = monster[i]._msquelch-1; + } + if (monster[leader]._mAi == AI_GARG && (monster[leader]._mFlags & MFLAG_STILL)) { + monster[leader]._mFlags &= ~MFLAG_STILL; + monster[leader]._mmode = MM_SATTACK; + } + } + else if(monster[i]._uniqtype && (UniqMonst[monster[i]._uniqtype-1].mUnqAttr & UN_STICK)) + { + // make sure all of pack is activated + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for(m = 0; m < nummonsters; ++m) + { + if(monster[tmp=monstactive[m]].leaderflag == PACK_MEMBER + && monster[tmp].leader == i) + { + if(monster[i]._msquelch > monster[tmp]._msquelch) + { + monster[tmp]._lastx = monster[i]._mx; + monster[tmp]._lasty = monster[i]._my; + monster[tmp]._msquelch = monster[i]._msquelch-1; + } + if (monster[tmp]._mAi == AI_GARG && (monster[tmp]._mFlags & MFLAG_STILL)) { + monster[tmp]._mFlags &= ~MFLAG_STILL; + monster[tmp]._mmode = MM_SATTACK; + } + } + } + } + // END OF GROUP COHESION +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_CallWalk(int i, int md) +{ + int mdtemp = md; + BOOL ok = FALSE; + ok = DirOK(i,md); + + if(random(101,2)) + ok = ok || DirOK(i, md = left[mdtemp]) || DirOK(i, md = right[mdtemp]); + else + ok = ok || DirOK(i, md = right[mdtemp]) || DirOK(i, md = left[mdtemp]); + + if(random(102,2)) + ok = ok || DirOK(i, md = right[right[mdtemp]]) || DirOK(i, md = left[left[mdtemp]]); + else + ok = ok || DirOK(i, md = left[left[mdtemp]]) || DirOK(i, md = right[right[mdtemp]]); + + if(ok) + M_WalkDir(i, md); + + return ok; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_PathWalk(int i) +{ + char path[MAXPATHLEN]; + static const char plr2monst[] = { 0, 5, 3, 7, 1, 4, 6, 0, 2 }; + + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_PathWalk: Invalid monster %d",i); +#else + return FALSE; +#endif + } + CHECKFUNC1 Check = (monster[i]._mFlags & MFLAG_CHECKDOORS) ? PosOkMonst3:PosOkMonst; + + int pathlen = FindPath(Check, i, monster[i]._mx, monster[i]._my, + monster[i]._menemyx, monster[i]._menemyy, + path); + if(pathlen) { + M_CallWalk(i, plr2monst[path[0]]); + return TRUE; + } + else + return FALSE; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_CallWalk2(int i, int md) +{ + int mdtemp = md; + BOOL ok = FALSE; + ok = DirOK(i,md); + + if(random(101,2)) + ok = ok || DirOK(i, md = left[mdtemp]) || DirOK(i, md = right[mdtemp]); + else + ok = ok || DirOK(i, md = right[mdtemp]) || DirOK(i, md = left[mdtemp]); + + if(ok) + M_WalkDir(i, md); + + return ok; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_DumbWalk(int i, int md) +{ + BOOL ok; + + ok = DirOK(i,md); + + if(ok) + M_WalkDir(i, md); + return ok; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_RoundWalk(int i, int md, int &dir) +{ + int mdtemp; + BOOL ok = FALSE; + + if(dir) + md = left[left[md]]; + else + md = right[right[md]]; + mdtemp = md; + + ok = DirOK(i,md); + if(!ok) + { + // Note: The use of || below is a trick: the second condition is not evaluated + // (and therefore md is not re-set) if the first condition evaluates TRUE. + + if(dir) + ok = DirOK(i, md = right[mdtemp]) || DirOK(i, md = right[right[mdtemp]]); + else + ok = DirOK(i, md = left[mdtemp]) || DirOK(i, md = left[left[mdtemp]]); + } + + if(ok) + M_WalkDir(i,md); + else + { + // Note: The value of md here is set according to the second condition of the + // || operators above. Therefore, md is, by design, the direction towards + // the player. + dir = !dir; + ok = M_CallWalk(i,opposite[mdtemp]); + } + return ok; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_Face(int i) +{ + int md; + + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("M_Face: Invalid monster %d",i); +#else + return; +#endif + } + if (monster[i]._msquelch) { + md = M_GetDir(i); + monster[i]._mdir = md; + if (monster[i].MType == NULL) + { +#if defined(_DEBUG) + app_fatal("M_Face: Monster %d \"%s\" MType NULL",i,monster[i].mName); +#else + return; +#endif + } + monster[i]._mAnimData = monster[i].MType->Anims[MA_STAND].Cels[md]; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Zombie(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Zombie: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int mx, my, md, v; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx -= Monst->_menemyx; + my -= Monst->_menemyy; + md = Monst->_mdir; + v = random(103,100); + + // Try attack + if (DIST(mx,my,2)) { + if (v < (10 + 2*Monst->_mint)) M_StartAttack(i); + } else { + // Try walk + if (v < (10 + 2*Monst->_mint)) { + // Check on distance from player + if(DIST(mx,my,4+2*Monst->_mint)) { + md = M_GetDir(i); + M_CallWalk(i, md); + } else { + if(random(104,100) < (20 + 2*Monst->_mint)) md = random(104,8); + M_DumbWalk(i, md); + } + } + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_SkelSd(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_SkelSd: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int mx, my, md; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + Monst->_mdir = md; + // Try attack + if (DIST(mx,my,2)) { + if (Monst->_mVar1 == MM_DELAY || random(105,100) < 20 + 2*Monst->_mint) + M_StartAttack(i); + else + M_StartDelay(i, random(105,10)+10 - 2*Monst->_mint); + } else { + // Try walk -- more likely to walk if already walking + if ((Monst->_mVar1 != MM_DELAY) && random(106,100) < 35 - 4*Monst->_mint) + M_StartDelay(i, random(106,10) + 15 - 2*Monst->_mint); + else + M_CallWalk(i, md); + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL MAI_Path(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Path: Invalid monster %d",i); +#else + return FALSE; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if ((Monst->MType->mtype != MT_GOLEM) // golum always ready to walk + && ((!Monst->_msquelch) + || (Monst->_mmode != MM_STAND) + || !(Monst->_mgoal == MG_ATTACK + || Monst->_mgoal == MG_WALK_AROUND1 + || Monst->_mgoal == MG_ATTACK2) + || (Monst->_mx == 1 && Monst->_my == 0))) // inactive golum + return FALSE; + if (!LineClearF1(PosOkMonst2, i,Monst->_mx,Monst->_my,Monst->_menemyx,Monst->_menemyy) + || (Monst->_pathcount >= 5 && Monst->_pathcount < 8)) + { + // Try Opening Door + if (Monst->_mFlags & MFLAG_CHECKDOORS) + MonstCheckDoors(i); + + if (++Monst->_pathcount >= 5) + { + if (M_PathWalk(i)) + return TRUE; + } + else // don't want to zero pathcount + return FALSE; + } + + if (Monst->MType->mtype != MT_GOLEM) Monst->_pathcount = 0; //path count for golum handled in ai + return FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Snake(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Snake: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int fx, fy, mx, my, md, pnum; + char pattern[] = { +1, +1, 0, -1, -1 , 0}; + int tmp; + + pnum = Monst->_menemy; + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + Monst->_mdir = md; + // Try attack + if (DIST(mx,my,2)) { + if (Monst->_mVar1 == MM_DELAY + || Monst->_mVar1 == MM_MISSILE + || random(105,100) < 20 + 1*Monst->_mint) + M_StartAttack(i); + else + M_StartDelay(i, random(105,10)+10 - 1*Monst->_mint); + } + else if (DIST(mx,my,3) + && LineClearF1(PosOkMonst, i,Monst->_mx,Monst->_my,fx,fy) + && Monst->_mVar1 != MM_MISSILE) + { + // Launch snake + if (AddMissile(Monst->_mx, Monst->_my, fx,fy, md, MIT_RHINO, pnum, i, 0, 0) != -1) { + PlayEffect(i, MS_ATTACK); + dMonster[Monst->_mx][Monst->_my] = -(i+1); + Monst->_mmode = MM_MISSILE; + } + } else { + // Try walk -- more likely to walk if already walking + if ((Monst->_mVar1 != MM_DELAY) && random(106,100) < 35 - 2*Monst->_mint) + M_StartDelay(i, random(106,10) + 15 - 1*Monst->_mint); + else + { + md = Mod(md + pattern[Monst->_mgoalvar1], 8); + if (++Monst->_mgoalvar1 > 5) + Monst->_mgoalvar1 = 0; + tmp = Mod(md - Monst->_mgoalvar2, 8); + if (tmp > 0) + { + if (tmp < 4) + Monst->_mgoalvar2 = Mod(Monst->_mgoalvar2 + 1, 8); + else if (tmp == 4) + Monst->_mgoalvar2 = md; + else + Monst->_mgoalvar2 = Mod(Monst->_mgoalvar2 - 1, 8); + } + app_assert(Monst->_mgoalvar2 >= 0 && Monst->_mgoalvar2 < 8); + if (!M_DumbWalk(i, Monst->_mgoalvar2)) + M_CallWalk2(i, Monst->_mdir); + } + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Bat(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Bat: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int mx, my, md, v, pnum; + int fx, fy; + + pnum = Monst->_menemy; + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + Monst->_mdir = md; + v = random(107,100); + if(Monst->_mgoal == MG_RUN_AWAY) + { + if(!Monst->_mgoalvar1) + { + M_CallWalk(i, opposite[md]); + ++Monst->_mgoalvar1; + } + else + { + if(random(108,2)) + M_CallWalk(i, left[md]); + else + M_CallWalk(i, right[md]); + Monst->_mgoal = MG_ATTACK; + } + } + else + { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + // Try attack + if ((Monst->MType->mtype == MT_GLOOM) + && (!DIST(mx,my,5) && v < 33 + 4*Monst->_mint) && + LineClearF1(PosOkMonst, i,Monst->_mx,Monst->_my,fx,fy)) + { + // Turn into missile + if (AddMissile(Monst->_mx, Monst->_my, fx, fy, md, MIT_RHINO, pnum, i, 0, 0) != -1) { + dMonster[Monst->_mx][Monst->_my] = -(i+1); + Monst->_mmode = MM_MISSILE; + } + } + else if (DIST(mx,my,2)) { + if (v < 8 + 4*Monst->_mint) + { + M_StartAttack(i); + + // After attacking, fly away + Monst->_mgoal = MG_RUN_AWAY; + Monst->_mgoalvar1 = 0; + + if(Monst->MType->mtype == MT_FAMILIAR) { + // Note: arg 5 is a signal to the lightning code. + // The code checks if this is != to arg 1, and if so, checks for + // collision. Normally, collision is only checked for when + // lightning moves, but in this case it won't move! + AddMissile(Monst->_menemyx, Monst->_menemyy, Monst->_menemyx+1, 0, -1, MIT_LIGHTNING, MI_ENEMYPLR, i, random(109,10)+1, 0); + } + } + } else { + // Try walk + if ((Monst->_mVar2 > 20 && v < (13 + Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (63 + Monst->_mint))) { + M_CallWalk(i, md); + } + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_SkelBow(int i) +{ + int mx, my, md, fx, fy; + BOOL walking = FALSE; + int v; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_SkelBow: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = M_GetDir(i); + Monst->_mdir = md; + + // Try walk + v = random(110,100); + if (DIST(mx,my,4) + && + ((Monst->_mVar2 > 20 + && v < 13 + 2*Monst->_mint) + || (WALKMODE(Monst->_mVar1) + && Monst->_mVar2 == 0 + && v < 63 + 2*Monst->_mint))) + { + walking = M_DumbWalk(i, opposite[md]); + } + fx = Monst->_menemyx; + fy = Monst->_menemyy; + if (!walking && (random(110,100) < 3+2*Monst->_mint) && + LineClear(Monst->_mx,Monst->_my,fx, fy)) + { + // Try attack + M_StartRAttack(i,MIT_ARROW,4); + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Fat(int i) +{ + int mx, my, md, v; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Fat: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = M_GetDir(i); + Monst->_mdir = md; + v = random(111,100); + // Try attack + if (DIST(mx,my,2)) { + if (v < (15 + 4*Monst->_mint)) M_StartAttack(i); + else if (v < (20 + 4*Monst->_mint)) M_StartSpAttack(i); + } else { + // Try walk + if ((Monst->_mVar2 > 20 && v < (20 + 4*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (70 + 4*Monst->_mint))) { + M_CallWalk(i, md); + } + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Sneak(int i) +{ + int mx, my, md, v; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Sneak: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int dist; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + if (dLight[mx][my] != lightmax) { + + mx -= Monst->_menemyx; + my -= Monst->_menemyy; + md = M_GetDir(i); + + dist = 5 - Monst->_mint; + + // If gothit, run away + if(Monst->_mVar1 == MM_GOTHIT) + { + Monst->_mgoal = MG_RUN_AWAY; + Monst->_mgoalvar1 = 0; // count run_away moves + } + // if far away enough, stop running away + else if(!DIST(mx,my,dist+3) || Monst->_mgoalvar1 > 8) + { + Monst->_mgoal = MG_ATTACK; + Monst->_mgoalvar1 = 0; + } + + if(Monst->_mgoal == MG_RUN_AWAY && !(Monst->_mFlags & MFLAG_NOENEMY)) + { + // Use special "owner location", i.e. the location of the player + // according to the computer which owns the player + // This is an attempt to reduce the amount of monster warping due to + // diverging paths on different computers + if (Monst->_mFlags & MFLAG_MID) { + md = GetDirection(Monst->_mx, Monst->_my, + monster[Monst->_menemy]._mx, monster[Monst->_menemy]._my); + } + else { + md = GetDirection(Monst->_mx, Monst->_my, + plr[Monst->_menemy]._pownerx, plr[Monst->_menemy]._pownery); + } + md = opposite[md]; + if(Monst->MType->mtype == MT_UNSEEN) + { + if(random(112,2)) + md = left[md]; + else + md = right[md]; + } + } + + Monst->_mdir = md; + + v = random(112,100); + // become visible + if(DIST(mx,my,dist) && (Monst->_mFlags & MFLAG_INVISIBLE)) + M_StartFadein(i,md,FALSE); + // become invisible + else if(!DIST(mx,my,dist+1) && !(Monst->_mFlags & MFLAG_INVISIBLE)) + M_StartFadeout(i,md,TRUE); + // Try attack + else if ((Monst->_mgoal == MG_RUN_AWAY) + || + ( !DIST(mx,my,2) + && + ((Monst->_mVar2 > 20 && v < (14 + 4*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (64 + 4*Monst->_mint))))) { + // Try walk + ++Monst->_mgoalvar1; + M_CallWalk(i, md); + } + // face dir + if (Monst->_mmode == MM_STAND) + { + if (DIST(mx,my,2) && (v < (10 + 4*Monst->_mint))) { + M_StartAttack(i); + } + else + { + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Fireman(int i) +{ + int mx, my, md, v, pnum; + int fx, fy; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Fireman: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND && Monst->_msquelch) { + pnum = Monst->_menemy; + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = M_GetDir(i); + + if(Monst->_mgoal == MG_ATTACK) + { + if(LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Launch monster missile + if (AddMissile(Monst->_mx, Monst->_my, fx,fy, md, MIT_FIREMAN, pnum, i, 0, 0) != -1) { + Monst->_mmode = MM_MISSILE; + Monst->_mgoal = MG_ATTACK2; + Monst->_mgoalvar1 = 0; + } + } + } + else if(Monst->_mgoal == MG_ATTACK2) + { + if(Monst->_mgoalvar1 == 3) + { + Monst->_mgoal = MG_ATTACK; + M_StartFadeout(i,md,TRUE); + } + else if(LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Try attack + M_StartRAttack(i,MIT_KRULL,4); + ++Monst->_mgoalvar1; + } + else + { + M_StartDelay(i, random(112,10) + 5); + ++Monst->_mgoalvar1; + } + } + + else if(Monst->_mgoal == MG_RUN_AWAY) + { + M_StartFadein(i, md,FALSE); + Monst->_mgoal = MG_ATTACK2; + } + + Monst->_mdir = md; + + v = random(112,100); + + if(Monst->_mmode == MM_STAND) + { + if(DIST(mx,my,2) && Monst->_mgoal == MG_ATTACK) + { + M_TryH2HHit(i, monster[i]._menemy, monster[i].mHit, monster[i].mMinDamage, monster[i].mMaxDamage); + Monst->_mgoal = MG_RUN_AWAY; + if(!M_CallWalk(i, opposite[md])) + { + M_StartFadein(i, md,FALSE); + Monst->_mgoal = MG_ATTACK2; + } + } + else + { + if(!M_CallWalk(i, md)) + { + if(Monst->_mgoal == MG_ATTACK || Monst->_mgoal == MG_RUN_AWAY) + { + M_StartFadein(i, md, FALSE); + Monst->_mgoal = MG_ATTACK2; + } + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Fallen(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Fallen: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int x,y; + int xpos,ypos; + int m; + int rad; + int mx,my; + int aitype; + + if (Monst->_mgoal == MG_ATTACK2) + { + if(Monst->_mgoalvar1) + --Monst->_mgoalvar1; + else + Monst->_mgoal = MG_ATTACK; + } + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) + { + if (Monst->_mgoal == MG_RUN_AWAY && Monst->_mgoalvar1-- == 0) + { + Monst->_mgoal = MG_ATTACK; + M_StartStand(i, opposite[Monst->_mdir]); + } + if (Monst->_mAnimFrame == Monst->_mAnimLen) { + if (random(113,4) == 0) + { + // start 'dance' + if (!(monster[i]._mFlags & MFLAG_NOHEAL)) { + M_StartSpStand(i, Monst->_mdir); + if(Monst->_mmaxhp - (2*Monst->_mint+2) >= Monst->_mhitpoints) + Monst->_mhitpoints += 2*Monst->_mint+2; + else + Monst->_mhitpoints = Monst->_mmaxhp; + } + // set surrounding monsters into relentless attack + rad = 2*Monst->_mint+4; + for(y = -rad; y <= rad; ++y) + { + for(x = -rad; x <= rad; ++x) + { + xpos = Monst->_mx + x; + ypos = Monst->_my + y; + if(InBounds(x,y)) + { + m = dMonster[xpos][ypos]; + if(m > 0) + { + --m; + aitype = monster[m]._mAi; + if(aitype == AI_FALLEN) + { + monster[m]._mgoal = MG_ATTACK2; + // Set # frames for crazy attack mode + monster[m]._mgoalvar1 = (2*Monst->_mint+7)*15; + } + } + } + } + } + } + } + else if (Monst->_mgoal == MG_RUN_AWAY) + { + M_CallWalk(i,Monst->_mdir); + } + else if (Monst->_mgoal == MG_ATTACK2) + { + // attack relentlessly + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if(DIST(mx,my,2)) + M_StartAttack(i); + else + M_CallWalk(i, M_GetDir(i)); + } + else + MAI_SkelSd(i); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Cleaver(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Cleaver: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int mx, my, md; + + if (Monst->_mmode == MM_STAND && Monst->_msquelch) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + Monst->_mdir = md; + // If close, attack + if (DIST(mx,my,2)) { + M_StartAttack(i); + } else { + // Try walk + M_CallWalk(i, md); + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Round(int i, BOOL special) +{ + int mx, my, md, v; + int fx, fy, dist; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Round: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(114,100); + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,4) && !random(115,4))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(116,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if( (Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) + { + Monst->_mgoal = MG_ATTACK; + } + else if(!M_RoundWalk(i,md,Monst->_mgoalvar2)) + M_StartDelay(i, random(125,10)+10); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (DIST(mx,my,2)) { + if (v < 23 + 2*Monst->_mint) + { + Monst->_mdir = md; + if(special && Monst->_mhitpoints < (Monst->_mmaxhp >> 1) && random(117,2)) + M_StartSpAttack(i); + else + M_StartAttack(i); + } + } + else if ((Monst->_mVar2 > 20 && v < (28 + 2*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (78 + 2*Monst->_mint))) { + M_CallWalk(i, md); + } + } + + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +void MAI_GoatMc(int i) +{ + MAI_Round(i, TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Ranged(int i, int missile_type, BOOL special) +{ + int fx, fy, mx, my, md; + BOOL walking = FALSE; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Ranged: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + if (Monst->_msquelch == 255 + || monster[i]._mFlags & MFLAG_MID) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = M_GetDir(i); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + Monst->_mdir = md; + + if (Monst->_mVar1 == MM_RATTACK) + { + // pause after each arrow + M_StartDelay(i, random(118,20)); + } + else if (DIST(mx,my,4) && random(119,100) < 70 + 10*Monst->_mint) + { + // retreat + walking = M_CallWalk(i, opposite[md]); + } + if (Monst->_mmode == MM_STAND) + { + if (LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Try attack + if(special) + M_StartRSpAttack(i,missile_type,4); + else + M_StartRAttack(i,missile_type,4); + } + else + // face dir + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } + } + else if(Monst->_msquelch // 0 < msquelch < 255 + && !(monster[i]._mFlags & MFLAG_MID)) // temp. golum fix + { + mx = Monst->_lastx; + my = Monst->_lasty; + md = GetDirection(Monst->_mx, Monst->_my, mx, my); + + M_CallWalk(i, md); + } + } +} + +void MAI_GoatBow(int i) +{ + MAI_Ranged(i,MIT_ARROW, FALSE); +} + +void MAI_Succ(int i) +{ + MAI_Ranged(i,MIT_FLARE, FALSE); +} + +void MAI_Lich(int i) +{ + MAI_Ranged(i,MIT_ORANGEFLARE, FALSE); +} + +void MAI_ArchLich(int i) +{ + MAI_Ranged(i,MIT_YELLOWFLARE, FALSE); +} + +void MAI_Psychorb(int i) +{ + MAI_Ranged(i,MIT_BLUEFLARE, FALSE); +} + +void MAI_Necromorb(int i) +{ + MAI_Ranged(i,MIT_REDFLARE, FALSE); +} + +void MAI_AcidUniq(int i) +{ + MAI_Ranged(i,MIT_ACID, TRUE); +} + +void MAI_Firebat(int i) +{ + MAI_Ranged(i,MIT_FIREBOLT, FALSE); +} + +void MAI_Hellbat(int i) +{ + MAI_Ranged(i,MIT_FIREBALL, FALSE); +} + +/*-----------------------------------------------------------------------* + * MAI_Scav + * + * MG_EAT is the scavenger's eat goal. + * _mgoalvar1 : =0 ==> no goal dest + * >0 ==> _mgoalvar1-1 is x coord of food + * _mgoalvar2 : _mgoalvar2-1 is y coord of food + * +**-----------------------------------------------------------------------*/ + +void MAI_Scav(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Scav: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int x,y; + BOOL done = FALSE; + + if (Monst->_mmode == MM_STAND) { + if(Monst->_mhitpoints < (Monst->_mmaxhp >> 1) && Monst->_mgoal != MG_EAT) + { + if(monster[i].leaderflag) + { + // leave pack permanently + --monster[monster[i].leader].packsize; + monster[i].leaderflag = 0; + } + Monst->_mgoal = MG_EAT; + Monst->_mgoalvar3 = 10; + } + + if (Monst->_mgoal == MG_EAT && Monst->_mgoalvar3) + { + --Monst->_mgoalvar3; + + // Are we on top of food? + if (dDead[Monst->_mx][Monst->_my]) + { + M_StartEat(i); + if (!(monster[i]._mFlags & MFLAG_NOHEAL)) { + int maxhp = (Monst->MType->mMaxHP << HP_SHIFT); + if (gbMaxPlayers == 1) + maxhp >>= 1; + + int healamt = maxhp >> 3; + Monst->_mhitpoints += healamt; + + // by eating, the monster can get to its species maximum + // in hit points... + if (Monst->_mhitpoints > maxhp) + Monst->_mhitpoints = maxhp; + if (Monst->_mmaxhp < Monst->_mhitpoints) + Monst->_mmaxhp = Monst->_mhitpoints; + + if (Monst->_mgoalvar3 <= 0 || // done eating + Monst->_mhitpoints == maxhp) + { + dDead[Monst->_mx][Monst->_my] = 0; // monster buried + } + } +// if ((Monst->_mhitpoints) >= (Monst->_mmaxhp >> 1) + (Monst->_mmaxhp >> 2)) + if ((Monst->_mhitpoints) == (Monst->_mmaxhp)) + { + Monst->_mgoal = MG_ATTACK; + Monst->_mgoalvar1 = 0; + Monst->_mgoalvar2 = 0; + } + } + else + { + if (!Monst->_mgoalvar1) + { + // Find food! + // Randomize search direction + if(random(120,2)) + { + for(y = -4; y <= 4 && !done; ++y) + for(x = -4; x <= 4 && !done; ++x) + if(InBounds(x,y)) + done = dDead[Monst->_mx + x][Monst->_my + y] + && LineClearF(CheckNoSolid, Monst->_mx,Monst->_my,Monst->_mx + x,Monst->_my + y); + --x; + --y; + } + else + { + for(y = 4; y >= -4 && !done; --y) + for(x = 4; x >= -4 && !done; --x) + if(InBounds(x,y)) + done = dDead[Monst->_mx + x][Monst->_my + y] + && LineClearF(CheckNoSolid,Monst->_mx,Monst->_my,Monst->_mx + x,Monst->_my + y); + ++x; + ++y; + } + if(done) + { + // Note: 1 is added to the following vars because + // 0 is reserved as a flag meaning undefined. + Monst->_mgoalvar1 = Monst->_mx + x +1; + Monst->_mgoalvar2 = Monst->_my + y +1; + } + } + if(Monst->_mgoalvar1) + { + x = Monst->_mgoalvar1 - 1; + y = Monst->_mgoalvar2 - 1; + Monst->_mdir = GetDirection(Monst->_mx, Monst->_my, x, y); + M_CallWalk(i, Monst->_mdir); + } + } + } + else +// if(Monst->_mmode == MM_STAND) + // none of the above cases applied, so resort to default behavior + MAI_SkelSd(i); + } +} + + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Garg(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Garg: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int mx, my; + int md; + + mx = Monst->_mx - Monst->_lastx; + my = Monst->_my - Monst->_lasty; + md = M_GetDir(i); + if(Monst->_msquelch && (Monst->_mFlags & MFLAG_STILL)) + { + M_Enemy(i); + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + + if(DIST(mx,my,Monst->_mint+2)) + Monst->_mFlags &= ~MFLAG_STILL; + } + else if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) + { + if(Monst->_mhitpoints < (Monst->_mmaxhp >> 1)) + { + // run away to get healed. + Monst->_mgoal = MG_RUN_AWAY; + } + if(Monst->_mgoal == MG_RUN_AWAY) + { + if(DIST(mx,my,Monst->_mint+2)) + { + if(!M_CallWalk(i,opposite[md])) + Monst->_mgoal = MG_ATTACK; + } + else + { + Monst->_mgoal = MG_ATTACK; + M_StartHeal(i); + + } + } + MAI_Round(i, FALSE); + } +} + + +/*-----------------------------------------------------------------------* + * MAI_RoundRanged + * + * Similar to MAI_Round, but does ranged attacks (throws lava) + * +**-----------------------------------------------------------------------*/ + +void MAI_RoundRanged(int i, int missile_type, BOOL checkdoors, int dam, BOOL lessmissiles) +{ + int fx, fy, mx, my, md, v, pnum; + int dist; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_RoundRanged: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + pnum = Monst->_menemy; + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(checkdoors && Monst->_msquelch < 255) + MonstCheckDoors(i); + + // Using random(10000) instead of random(100) for increased precision + // for small numbers, e.g. random(100) < (5 >> 1) + v = random(121,10000); + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,3) && !random(122,4 << lessmissiles))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(123,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if(Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + { + Monst->_mgoal = MG_ATTACK; + } + else if(v < (500 + 500*Monst->_mint) >> lessmissiles + && + LineClear(Monst->_mx, Monst->_my, fx, fy)) + { + // Missile Attack + M_StartRSpAttack(i,missile_type,dam); + } + else + M_RoundWalk(i,md,Monst->_mgoalvar2); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (((!DIST(mx,my,3) && v < (1000 + 500*Monst->_mint) >> lessmissiles) + || + v < (500 + 500*Monst->_mint) >> lessmissiles) + && + LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Missile Attack + M_StartRSpAttack(i,missile_type,dam); + } + else if (DIST(mx,my,2)) + { + if (v < 6000 + 1000*Monst->_mint) + { + Monst->_mdir = md; + M_StartAttack(i); + } + } + else if (((v=random(124,100)) < (5000 + 1000*Monst->_mint)) + || + (WALKMODE(Monst->_mVar1) + && + Monst->_mVar2 == 0 && v < (8000 + 1000*Monst->_mint))) + { + M_CallWalk(i, md); + } + } + + // face dir + if (Monst->_mmode == MM_STAND) + M_StartDelay(i, random(125,10)+5); + } +} + +void MAI_Magma(int i) +{ + MAI_RoundRanged(i, MIT_MAGMABALL, TRUE,4, FALSE); +} + +void MAI_Storm(int i) +{ + MAI_RoundRanged(i, MIT_THINLIGHTCTRL, TRUE,4, FALSE); +} + +void MAI_BoneDemon(int i) +{ + MAI_RoundRanged(i, MIT_BLUE2FLARE, TRUE,4, FALSE); +} + +void MAI_Acid(int i) +{ + MAI_RoundRanged(i, MIT_ACID, FALSE,4, TRUE); +} + +void MAI_Diablo(int i) +{ + MAI_RoundRanged(i, MIT_DIABAPOCA, FALSE, 40, FALSE); +} + +void MAI_RR2(int i, int mistype, int dam) +{ + int fx, fy, mx, my, md, v, pnum; + int dist; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_RR2: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if (!DIST(mx, my, 5)) + MAI_SkelSd(i); + else if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + pnum = Monst->_menemy; + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(121,100); + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || !DIST(mx,my,3)) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(123,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + Monst->_mgoalvar3 = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if(Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + { + Monst->_mgoal = MG_ATTACK; + } + else if (v < 80 + 5*Monst->_mint) + M_RoundWalk(i,md,Monst->_mgoalvar2); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (((!DIST(mx,my,3) && v < 10 + 5*Monst->_mint) + || + v < 5 + 5*Monst->_mint + || Monst->_mgoalvar3 == MG_WALK_AROUND1) + && + LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Missile Attack + M_StartRSpAttack(i,mistype,dam); + } + else if (DIST(mx,my,2)) + { + if (random(124,100) < 40 + 10*Monst->_mint) + { + Monst->_mdir = md; + if (random(124, 2)) + M_StartAttack(i); + else + // Missile Attack + M_StartRSpAttack(i,mistype,dam); + } + } + else if (((v=random(124,100)) < (50 + 10*Monst->_mint)) + || + (WALKMODE(Monst->_mVar1) + && + Monst->_mVar2 == 0 && v < (80 + 10*Monst->_mint))) + { + M_CallWalk(i, md); + } + Monst->_mgoalvar3 = MG_ATTACK; + } + + if (Monst->_mmode == MM_STAND) + M_StartDelay(i, random(125,10)+5); + } +} + +void MAI_Mega(int i) +{ + MAI_RR2(i, MIT_FLAMEC,0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MAI_Golum(int i) +{ + int ok, j, k, mid; + int mx, my, md; + BOOL have_enemy; + + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Golum: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mx == 1) && (Monst->_my == 0)) return; + + if (Monst->_mmode == MM_DEATH) return; + if (Monst->_mmode == MM_SPSTAND) return; + if (Monst->_mmode >= MM_WALK && Monst->_mmode <= MM_WALK3) return; + + if (!(monster[i]._mFlags & MFLAG_MID)) M_Enemy(i); + + have_enemy = !(Monst->_mFlags & MFLAG_NOENEMY); + + if (Monst->_mmode != MM_ATTACK) { + mx = Monst->_mx - monster[Monst->_menemy]._mfutx; + my = Monst->_my - monster[Monst->_menemy]._mfuty; + md = GetDirection(Monst->_mx, Monst->_my, monster[Monst->_menemy]._mx, monster[Monst->_menemy]._my); + Monst->_mdir = md; + + if (DIST(mx,my,2) && have_enemy) { + Monst->_menemyx = monster[Monst->_menemy]._mx; + Monst->_menemyy = monster[Monst->_menemy]._my; + if(!monster[Monst->_menemy]._msquelch) { + monster[Monst->_menemy]._msquelch = 255; + monster[Monst->_menemy]._lastx = Monst->_mx; + monster[Monst->_menemy]._lasty = Monst->_my; + for (j = 0; j < 5; ++j) { + for (k = 0; k < 5; ++k) { + mid = dMonster[monster[i]._mx - 2 + k][monster[i]._my - 2 + j]; + if (mid > 0) monster[mid]._msquelch = 255; + } + } + } + M_StartAttack(i); + } else { + if (!have_enemy || + !MAI_Path(i)) { + ++Monst->_pathcount; + if (Monst->_pathcount > 8) Monst->_pathcount = 5; + ok = M_CallWalk(i, plr[i]._pdir); + if (ok == FALSE) { + md = (md - 1) & 0x07; + for (j = 0; j < 8 && ok == FALSE; ++j) { + md = (md + 1) & 0x07; + ok = DirOK(i, md); + } + if (ok) + M_WalkDir(i, md); + } + } + } + } + +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_SkelKing(int i) +{ + int fx, fy, mx, my, md, v; + int dist; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_SkelKing: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + int nx,ny; // location for new skel spawn + int skel; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(126,100); + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,3) && !random(127,4))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(128,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if( (Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) + { + Monst->_mgoal = MG_ATTACK; + } + else if(!M_RoundWalk(i,md,Monst->_mgoalvar2)) + M_StartDelay(i, random(125,10)+10); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (gbMaxPlayers == 1 // no spawning in multi-player + && ((!DIST(mx,my,3) && v < 35 + 4*Monst->_mint) + || v < 6) + && + LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Spawn new Skeleton + nx = Monst->_mx + offset_x[md]; + ny = Monst->_my + offset_y[md]; + if (PosOkMonst(i,nx,ny) && nummonsters < MAXMONSTERS) + { +// skel = AddMonster(nx, ny, md, 1, TRUE); +// M_StartSpStand(skel, md); + skel = M_SpawnSkel(nx, ny, md); + M_StartSpStand(i, md); + } + } + else if (DIST(mx,my,2)) { + if (v < 20 + Monst->_mint) + { + Monst->_mdir = md; + M_StartAttack(i); + } + } + else if (((v=random(129,100)) < (25 + Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (75 + Monst->_mint))) { + M_CallWalk(i, md); + } + else + M_StartDelay(i, random(130,10)+10); + } + + // face dir + if (Monst->_mmode == MM_STAND) + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Rhino(int i) +{ + int fx, fy, mx, my, md, v; + int dist; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Rhino: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND && Monst->_msquelch) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(131,100); + if (DIST(mx,my,2)) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,5) && random(132,4))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(133,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if( (Monst->_mgoalvar1++ >= (dist << 1)) + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) + { + Monst->_mgoal = MG_ATTACK; + } + else if(!M_RoundWalk(i,md,Monst->_mgoalvar2)) + M_StartDelay(i, random(125,10)+10); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if ((!DIST(mx,my,5) && v < 43 + 2*Monst->_mint) && + LineClearF1(PosOkMonst, i,Monst->_mx,Monst->_my,fx,fy)) + { + // Launch rhino + if (AddMissile(Monst->_mx, Monst->_my, fx,fy, md, MIT_RHINO, Monst->_menemy, i, 0, 0) != -1) { + if (Monst->MData->snd_special) PlayEffect(i, MS_SATTACK); + dMonster[Monst->_mx][Monst->_my] = -(i+1); + Monst->_mmode = MM_MISSILE; + } + } + else if (DIST(mx,my,2)) { + if (v < 28 + 2*Monst->_mint) + { + Monst->_mdir = md; + M_StartAttack(i); + } + } + else if (((v=random(134,100)) < (33 + 2*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (83 + 2*Monst->_mint))) { + M_CallWalk(i, md); + } + else + M_StartDelay(i, random(135,10)+10); + } + + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + } +} + +void MAI_HorkDemon(int i) +{ + int v; + + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_HorkDemon: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND && Monst->_msquelch) { + int const fx = Monst->_menemyx; + int const fy = Monst->_menemyy; + int const mx = Monst->_mx - fx; + int const my = Monst->_my - fy; + int const md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(131,100); + if (DIST(mx,my,2)) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,5) && random(132,4))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(133,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + int const dist = max(abs(mx),abs(my)); + + if( (Monst->_mgoalvar1++ >= (dist << 1)) + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) + { + Monst->_mgoal = MG_ATTACK; + } + else if(!M_RoundWalk(i,md,Monst->_mgoalvar2)) + M_StartDelay(i, random(125,10)+10); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if ((!DIST(mx,my,3) && v < 43 + 2*Monst->_mint)) + { + // Launch Hork Spawn + int const Enemyd = Monst->_mdir; + int const nx = Monst->_mx + infront_x[Enemyd]; + int const ny = Monst->_my + infront_y[Enemyd]; + if (PosOkMonst(i,nx,ny) && nummonsters < MAXMONSTERS) { + M_StartRSpAttack(i, MIT_HORKSPAWN, 0); + } + } + else if (DIST(mx,my,2)) { + if (v < 28 + 2*Monst->_mint) + { + Monst->_mdir = md; + M_StartAttack(i); + } + } + else if (((v=random(134,100)) < (33 + 2*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (83 + 2*Monst->_mint))) { + M_CallWalk(i, md); + } + else + M_StartDelay(i, random(135,10)+10); + } + + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Counselor(int i) +{ + int fx, fy, mx, my, md, v; + int dist; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Counselor: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + static const BYTE counsmiss[] = { MIT_FIREBOLT, MIT_CBOLT, MIT_LIGHTCTRL, MIT_FIREBALL }; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(121,100); + if (Monst->_mgoal == MG_RUN_AWAY) + { + if (Monst->_mgoalvar1++ > 3) + { + Monst->_mgoal = MG_ATTACK; + M_StartFadein(i, md, TRUE); + } + else + M_CallWalk(i, opposite[md]); + } + else if(Monst->_mgoal == MG_WALK_AROUND1) + { + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + M_StartFadein(i, md, TRUE); + } + else if(Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + { + Monst->_mgoal = MG_ATTACK; + M_StartFadein(i, md, TRUE); + } + else + M_RoundWalk(i,md,Monst->_mgoalvar2); + } + else if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (DIST(mx,my,2)) + { + Monst->_mdir = md; + if (Monst->_mhitpoints < (Monst->_mmaxhp >> 1)) + { + // run away! + Monst->_mgoal = MG_RUN_AWAY; + Monst->_mgoalvar1 = 0; + M_StartFadeout(i, md, FALSE); + } + else if (Monst->_mVar1 == MM_DELAY || random(105,100) < 20 + 2*Monst->_mint) + { + M_StartRAttack(i,-1,0); + AddMissile(monster[i]._mx, monster[i]._my, 0, 0, monster[i]._mdir, MIT_FLASH, MI_ENEMYPLR, i, 4, 0); + AddMissile(monster[i]._mx, monster[i]._my, 0, 0, monster[i]._mdir, MIT_FLASH2, MI_ENEMYPLR, i, 4, 0); + } + else + M_StartDelay(i, random(105,10)+10 - 2*Monst->_mint); + } + else if (v < 50 + 5*Monst->_mint + && LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Missile Attack + M_StartRAttack(i, counsmiss[Monst->_mint], random(77, Monst->mMaxDamage - Monst->mMinDamage + 1) + Monst->mMinDamage); + } + else if (random(124, 100) < 30) + { + Monst->_mgoal = MG_WALK_AROUND1; + Monst->_mgoalvar1 = 0; + M_StartFadeout(i, md, FALSE); + } + else + M_StartDelay(i, random(105,10)+10 - 2*Monst->_mint); + } + + // face dir + if (Monst->_mmode == MM_STAND) + M_StartDelay(i, random(125,10)+5); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Garbud(int i) +{ + int mx, my, md; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Garbud: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if ((Monst->mtalkmsg < TXT_GARB4) && (Monst->mtalkmsg > (TXT_GARB1-1)) && !(dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_mgoal == MG_WAITTOTALK)) { + ++Monst->mtalkmsg; + Monst->_mgoal = MG_TALK; + } + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_GARB4) && !(effect_is_playing(USFX_GARBUD4)) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + } + if ((Monst->_mgoal == MG_ATTACK) || (Monst->_mgoal == MG_WALK_AROUND1)) { + MAI_Round(i, TRUE); + } + monster[i]._mdir = md; + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Zhar(int i) +{ + int mx, my, md, dist; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Zhar: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if ((Monst->mtalkmsg == TXT_ZHAR1) && !(dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_mgoal == MG_WAITTOTALK)) { + ++Monst->mtalkmsg; + Monst->_mgoal = MG_TALK; + } + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + dist = max(abs(mx), abs(my)); + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_ZHAR2) && !(effect_is_playing(USFX_ZHAR2)) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + } + if ((Monst->_mgoal == MG_ATTACK) || (Monst->_mgoal == MG_RUN_AWAY) || (Monst->_mgoal == MG_WALK_AROUND1)) { + MAI_Counselor(i); + } + monster[i]._mdir = md; + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_SnotSpil(int i) +{ + int mx, my, md, pnum; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_SnotSpil: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + pnum = Monst->_menemy; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if ((Monst->mtalkmsg == TXT_BOL1) && !(dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->mtalkmsg = TXT_BOL2; + Monst->_mgoal = MG_TALK; + } + if ((Monst->mtalkmsg == TXT_BOL2) && (quests[Q_LTBANNER]._qvar1 == 3)) { + Monst->mtalkmsg = 0; + Monst->_mgoal = MG_ATTACK; + } + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_BOL3) && !(effect_is_playing(USFX_SNOT3)) && (Monst->_mgoal == MG_WAITTOTALK)) { + int i = plr[pnum]._pvid; + ObjChangeMap(setpc_x, setpc_y, setpc_x + setpc_w + 1, setpc_y + setpc_h + 1); + quests[Q_LTBANNER]._qvar1 = 3; + extern void RedoPlayerVision(); + RedoPlayerVision(); + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + if (quests[Q_LTBANNER]._qvar1 == 3) { + if ((Monst->_mgoal == MG_ATTACK) || (Monst->_mgoal == MG_ATTACK2)) { + MAI_Fallen(i); + } + } + + } + monster[i]._mdir = md; + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Lazurus(int i) +{ + int mx, my, md; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Lazurus: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if (gbMaxPlayers == 1) { + if ((Monst->mtalkmsg == TXT_VB1) && (Monst->_mgoal == MG_TALK) + && (plr[myplr]._px == 35) && (plr[myplr]._py == 46)) { + PlayInGameMovie("gendata\\fprst3.smk"); + Monst->_mmode = MM_TALK; + quests[Q_BETRAYER]._qvar1 = 5; + } + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_VB1) && !(effect_is_playing(USFX_LAZ1)) && (Monst->_mgoal == MG_WAITTOTALK)) { + ObjChangeMapResync(1, 18, 20, 24); + extern void RedoPlayerVision(); + RedoPlayerVision(); + quests[Q_BETRAYER]._qvar1 = 6; + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + } + if (gbMaxPlayers != 1) { + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_VB1) && (Monst->_mgoal == MG_TALK) && (quests[Q_BETRAYER]._qvar1 <= 3)) { + Monst->_mmode = MM_TALK; + } + #endif + } + + } + if ((Monst->_mgoal == MG_ATTACK) || (Monst->_mgoal == MG_RUN_AWAY) || (Monst->_mgoal == MG_WALK_AROUND1)) { + MAI_Counselor(i); + } + monster[i]._mdir = md; + if ((Monst->_mmode == MM_STAND) || (Monst->_mmode == MM_TALK)) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Lazhelp(int i) +{ + int mx, my, md; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Lazhelp: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if (gbMaxPlayers == 1) { + if (quests[Q_BETRAYER]._qvar1 <= 5) + Monst->_mgoal = MG_TALK; + else { + Monst->_mgoal = MG_ATTACK; + Monst->mtalkmsg = 0; + } + } else if (gbMaxPlayers != 1) { + Monst->_mgoal = MG_ATTACK; + } + } + if (Monst->_mgoal == MG_ATTACK) { + MAI_Succ(i); + } + monster[i]._mdir = md; + } if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Lachdanan(int i) +{ + int mx, my, md, pnum; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Lachdanan: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + pnum = Monst->_menemy; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_VEIL1) && !(dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_mgoal == MG_WAITTOTALK)) { + ++Monst->mtalkmsg; + Monst->_mgoal = MG_TALK; + } + #endif + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_VEIL3) && !(effect_is_playing(USFX_LACH3)) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->mtalkmsg = 0; + quests[Q_VEIL]._qactive = QUEST_DONE; + M_StartKill(i, -1); + } + #endif + } + monster[i]._mdir = md; + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Warlord(int i) +{ + int mx, my, md; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MAI_Warlord: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if ((Monst->mtalkmsg == TXT_WARLRD1) && (Monst->_mgoal == MG_TALK)) { + Monst->_mmode = MM_TALK; + } + + #if !IS_VERSION(SHAREWARE) + BOOL effect_is_playing(int nSFX); + if ((Monst->mtalkmsg == TXT_WARLRD1) && !(effect_is_playing(USFX_WARLRD1)) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + } + if (Monst->_mgoal == MG_ATTACK) { + MAI_SkelSd(i); + } + monster[i]._mdir = md; + if ((Monst->_mmode == MM_STAND) || (Monst->_mmode == MM_TALK)) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DeleteMonsterList() +{ + int i, mi; + + // pseudo delete dead golems + for (i = 0; i < 4; ++i) { + if (monster[i]._mDelFlag) { + monster[i]._mx = 1; + monster[i]._my = 0; + monster[i]._mfutx = 0; + monster[i]._mfuty = 0; + monster[i]._moldx = 0; + monster[i]._moldy = 0; + monster[i]._mDelFlag = FALSE; + } + } + + i = 4; // this is to skip the golems + app_assert((DWORD)nummonsters <= MAXMONSTERS); + while (i < nummonsters) { + mi = monstactive[i]; + if (monster[mi]._mDelFlag) { + DeleteMonster(i); + i = 0; + } else ++i; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ProcessMonsters () +{ + int i, mi; + int raflag; + int mx, my; + MonsterStruct *Monst; + int oldmode; + + DeleteMonsterList(); + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for (i = 0; i < nummonsters; ++i) { + mi = monstactive[i]; + Monst = &monster[mi]; + raflag = RUN_DONE; + + // Try and run same AI's as best as possible in multiplayer + if (gbMaxPlayers > 1) { + SetRndSeed(Monst->_mAISeed); + Monst->_mAISeed = GetRndSeed(); + } + + // Turn regen + if (!(monster[mi]._mFlags & MFLAG_NOHEAL)) { + if ((Monst->_mhitpoints < Monst->_mmaxhp) && ((Monst->_mhitpoints >> HP_SHIFT) > 0)) { + if (Monst->mLevel > 1) + Monst->_mhitpoints += Monst->mLevel >> 1; + else + Monst->_mhitpoints += Monst->mLevel; + } + } + // Check if just activating + mx = Monst->_mx; + my = Monst->_my; + if ((dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_msquelch == 0)) { + #if !IS_VERSION(SHAREWARE) + if (Monst->MType->mtype == MT_CLEAVER) { + //if (gbMaxPlayers == 1) PlayInGameMovie("gendata\\fbutch3.smk"); + PlaySFX(USFX_CLEAVER); + } + if (Monst->MType->mtype == MT_NKR) { + if (gbCowsuit) + PlaySFX(HSFX_NA_KRUL6); + else if (Na_Krul.Books) + PlaySFX(HSFX_NA_KRUL4); + else + PlaySFX(HSFX_NA_KRUL5); + } + if (Monst->MType->mtype == MT_BUG) { + //if (gbMaxPlayers == 1) PlayInGameMovie("gendata\\fbutch3.smk"); + PlaySFX(HSFX_DEFILER5); + } + #endif + M_Enemy(mi); + } + + // Check if monster's enemy + if (Monst->_mFlags & MFLAG_MID) { + if ((DWORD)Monst->_menemy >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("Illegal enemy monster %d for monster \"%s\"",Monst->_menemy,Monst->mName); +#else + return; +#endif + } + Monst->_menemyx = Monst->_lastx = monster[Monst->_menemy]._mfutx; + Monst->_menemyy = Monst->_lasty = monster[Monst->_menemy]._mfuty; + } else { + // Deal with keeping a monster active for a while after its visibility flag + // goes off + if ((DWORD)Monst->_menemy >= MAX_PLRS) + { +#if defined(_DEBUG) + app_fatal("Illegal enemy player %d for monster \"%s\"",Monst->_menemy,Monst->mName); +#else + return; +#endif + } + Monst->_menemyx = plr[Monst->_menemy]._pfutx; + Monst->_menemyy = plr[Monst->_menemy]._pfuty; + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + Monst->_msquelch = 255; + Monst->_lastx = plr[Monst->_menemy]._pfutx; + Monst->_lasty = plr[Monst->_menemy]._pfuty; + } else if(Monst->_msquelch && (Monst->_mAi != MT_DIABLO)) --Monst->_msquelch; + } + + do { + // Run Monster's AI + + // Try Path Mode + if (Monst->_mFlags & MFLAG_PATH) + { + if (!MAI_Path(mi)) + AiProc[Monst->_mAi](mi); + } + else + AiProc[Monst->_mAi](mi); + + // Run Monster Mode + switch (oldmode = Monst->_mmode) { + case MM_STAND : + raflag = M_DoStand(mi); + break; + case MM_WALK : + raflag = M_DoWalk(mi); + break; + case MM_WALK2 : + raflag = M_DoWalk2(mi); + break; + case MM_WALK3: + raflag = M_DoWalk3(mi); + break; + case MM_ATTACK: + raflag = M_DoAttack(mi); + break; + case MM_RATTACK: + raflag = M_DoRAttack(mi); + break; + case MM_GOTHIT: + raflag = M_DoGotHit(mi); + break; + case MM_DEATH: + raflag = M_DoDeath(mi); + break; + case MM_SATTACK: + raflag = M_DoSAttack(mi); + break; + case MM_FADEIN: + raflag = M_DoFadein(mi); + break; + case MM_FADEOUT: + raflag = M_DoFadeout(mi); + break; + case MM_SPSTAND: + raflag = M_DoSpStand(mi); + break; + case MM_RSATTACK: + raflag = M_DoRSpAttack(mi); + break; + case MM_DELAY: + raflag = M_DoDelay(mi); + break; + case MM_MISSILE: + raflag = RUN_DONE; + break; + case MM_STONE: + raflag = M_DoStone(mi); + break; + case MM_HEAL: + raflag = M_DoHeal(mi); + break; + case MM_TALK: + raflag = M_DoTalk(mi); + break; + } + +/* for (int mm = 0; mm < nummonsters; ++mm) { + int mmi = monstactive[mm]; + app_assert(monster[mmi]._mDelFlag + || monster[mmi]._mmode == MM_MISSILE + || !monster[mmi]._msquelch + || mmi < 4 + || dMonster[monster[mmi]._mx][monster[mmi]._my] == mmi+1 + || dMonster[monster[mmi]._mx][monster[mmi]._my] == -(mmi+1)); + }*/ + + if(raflag != RUN_DONE) + GroupUnity(mi); + +// if (Monst->_msquelch) DaveMonstMap(FALSE, 0); + + } while (raflag != RUN_DONE); + + // Animate Monster + if (Monst->_mmode != MM_STONE) { + ++Monst->_mAnimCnt; + if (!(Monst->_mFlags & MFLAG_STILL)) + { + if (Monst->_mAnimCnt >= Monst->_mAnimDelay) { + Monst->_mAnimCnt = 0; + if(Monst->_mFlags & MFLAG_BACKWARDS) + { + --Monst->_mAnimFrame; + if (!Monst->_mAnimFrame) Monst->_mAnimFrame = Monst->_mAnimLen; + } + else + { + ++Monst->_mAnimFrame; + if (Monst->_mAnimFrame > Monst->_mAnimLen) Monst->_mAnimFrame = 1; + } + } + } + } + } + DeleteMonsterList(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreeMonsterGFX() +{ + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (int monst = 0; monst < nummtypes; ++monst) { + int mtype = Monsters[monst].mtype; + for (int anim = 0; anim < MAX_ANIMTYPE; ++anim) { + if(!(animletter[anim] == 's' && !monsterdata[mtype].has_special)) { + DiabloFreePtr(Monsters[monst].Anims[anim].CMem); + } + } + } + + IFreeMissileGFX(); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL DirOK(int i, int mdir) +{ + long fx, fy; + int tmp; + + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("DirOK: Invalid monster %d",i); +#else + return FALSE; +#endif + } + fx = monster[i]._mx + offset_x[mdir]; + fy = monster[i]._my + offset_y[mdir]; + if(! InBounds(fx,fy)) + return FALSE; + + if (! PosOkMonst(i, fx, fy)) + return FALSE; + + if (mdir == M_DIRR) { + if (SolidLoc(fx+0,fy+1)) return FALSE; + if (dFlags[fx+0][fy+1] & BFLAG_MONSTLR) return FALSE; + } + else if(mdir == M_DIRL) { + if (SolidLoc(fx+1,fy+0)) return FALSE; + if (dFlags[fx+1][fy+0] & BFLAG_MONSTLR) return FALSE; + } + else if (mdir == M_DIRU) { + if (SolidLoc(fx+1,fy+0)) return FALSE; + if (SolidLoc(fx+0,fy+1)) return FALSE; + } + else if (mdir == M_DIRD) { + if (SolidLoc(fx-1,fy+0)) return FALSE; + if (SolidLoc(fx+0,fy-1)) return FALSE; + } + + // check for group cohesion + if(monster[i].leaderflag == PACK_MEMBER) { + // make sure monster is close to leader + return DIST( + fx-monster[monster[i].leader]._mfutx, + fy-monster[monster[i].leader]._mfuty, + 4 + ); + } + + if (monster[i]._uniqtype && (UniqMonst[monster[i]._uniqtype-1].mUnqAttr & UN_STICK)) + { + int mcount = 0; + for (int x = fx - 3; x <= fx + 3; ++x) { + for (int y = fy - 3; y <= fy + 3; ++y) { + if (! InBounds(x,y)) continue; + + if((tmp = dMonster[x][y]) < 0) tmp = -tmp; + if (tmp != 0) --tmp; + app_assert(tmp >= 0); + + if (monster[tmp].leaderflag == PACK_MEMBER && + monster[tmp].leader == i && + monster[tmp]._mfutx == x && + monster[tmp]._mfuty == y) ++mcount; + } + } + + return (mcount == monster[i].packsize); + } + + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PosOkMissile(int x, int y) +{ + return !(nMissileTable[dPiece[x][y]] || (dFlags[x][y] & BFLAG_MONSTLR)); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL CheckNoSolid(int x, int y) +{ + return !nSolidTable[dPiece[x][y]]; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +BOOL LineClearF(CHECKFUNC Clear, int x1, int y1, int x2, int y2) +{ + int md; + BOOL done = FALSE; + + do + { + md = GetDirection(x1,y1,x2,y2); + x1 += offset_x[md]; + y1 += offset_y[md]; + done = !(*Clear)(x1, y1); + } while(!done && !(x1==x2 && y1==y2)); + return (x1 == x2) && (y1 == y2); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL LineClearF(CHECKFUNC Clear, int x1, int y1, int x2, int y2) +{ + // Bresenham line algorithm + // See Foley/van Dam, "Computer Graphics: Principles and Practice" + + int dx,dy; + int d; // test variable + int dincH; // Horizontal increment for d + int dincD; // Diagonal increment for d + int xincD,yincD; // Diagonal increments for minor axis + int xorg, yorg; + BOOL done = FALSE; + int tmp; + + xorg = x1; + yorg = y1; + + dx = x2 - x1; + dy = y2 - y1; + if(abs(dx) > abs(dy)) + { + // X is the major axis + if(dx < 0) + { + // swap endpoints + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + + dx = -dx; + dy = -dy; + } + if(dy > 0) + { + // pos. slope + d = 2*dy - dx; + dincH = 2*dy; + dincD = 2*(dy - dx); + yincD = 1; + } + else + { + // neg. slope + d = 2*dy + dx; + dincH = 2*dy; + dincD = 2*(dy + dx); + yincD = -1; + } + +// done = (x1 != xorg || y1 != yorg) && !(*Clear)(x1, y1); + + while(!done && !(x1 == x2 && y1 == y2)) + { + if((d <= 0) ^ (yincD < 0)) + { + d += dincH; + } + else + { + d += dincD; + y1 += yincD; + } + ++x1; + done = (x1 != xorg || y1 != yorg) && !(*Clear)(x1, y1); + } + } + else + { + // Y is the major axis + if(dy < 0) + { + // swap endpoints + tmp = y1; + y1 = y2; + y2 = tmp; + tmp = x1; + x1 = x2; + x2 = tmp; + + dy = -dy; + dx = -dx; + } + if(dx > 0) + { + // pos. slope + d = 2*dx - dy; + dincH = 2*dx; + dincD = 2*(dx - dy); + xincD = 1; + } + else + { + // neg. slope + d = 2*dx + dy; + dincH = 2*dx; + dincD = 2*(dx + dy); + xincD = -1; + } + +// done = (y1 != yorg || x1 != xorg) && !(*Clear)(x1, y1); + + while(!done && !(y1 == y2 && x1 == x2)) + { + if((d <= 0) ^ (xincD < 0)) + { + d += dincH; + } + else + { + d += dincD; + x1 += xincD; + } + ++y1; + done = (y1 != yorg || x1 != xorg) && !(*Clear)(x1, y1); + } + } + + return x1 == x2 && y1 == y2; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL LineClear(int x1, int y1, int x2, int y2) +{ + return LineClearF(PosOkMissile, x1, y1, x2, y2); +} + +/*-----------------------------------------------------------------------* + * LineClearF1 + * + * This is exactly the same routine as LineClearF, except its Check + * routine requires an extra argument +**-----------------------------------------------------------------------*/ + +BOOL LineClearF1(CHECKFUNC1 Clear, int monst, int x1, int y1, int x2, int y2) +{ + // Bresenham line algorithm + // See Foley/van Dam, "Computer Graphics: Principles and Practice" + + int dx,dy; + int d; // test variable + int dincH; // Horizontal increment for d + int dincD; // Diagonal increment for d + int xincD,yincD; // Diagonal increments for minor axis + int xorg, yorg; + BOOL done = FALSE; + int tmp; + + xorg = x1; + yorg = y1; + + dx = x2 - x1; + dy = y2 - y1; + if(abs(dx) > abs(dy)) + { + // X is the major axis + if(dx < 0) + { + // swap endpoints + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + + dx = -dx; + dy = -dy; + } + if(dy > 0) + { + // pos. slope + d = 2*dy - dx; + dincH = 2*dy; + dincD = 2*(dy - dx); + yincD = 1; + } + else + { + // neg. slope + d = 2*dy + dx; + dincH = 2*dy; + dincD = 2*(dy + dx); + yincD = -1; + } + + while(!done && !(x1 == x2 && y1 == y2)) + { + if((d <= 0) ^ (yincD < 0)) + { + d += dincH; + } + else + { + d += dincD; + y1 += yincD; + } + ++x1; + done = (x1 != xorg || y1 != yorg) && !Clear(monst, x1, y1); + } + } + else + { + // Y is the major axis + if(dy < 0) + { + // swap endpoints + tmp = y1; + y1 = y2; + y2 = tmp; + tmp = x1; + x1 = x2; + x2 = tmp; + + dy = -dy; + dx = -dx; + } + if(dx > 0) + { + // pos. slope + d = 2*dx - dy; + dincH = 2*dx; + dincD = 2*(dx - dy); + xincD = 1; + } + else + { + // neg. slope + d = 2*dx + dy; + dincH = 2*dx; + dincD = 2*(dx + dy); + xincD = -1; + } + + while(!done && !(y1 == y2 && x1 == x2)) + { + if((d <= 0) ^ (xincD < 0)) + { + d += dincH; + } + else + { + d += dincD; + x1 += xincD; + } + ++y1; + done = (y1 != yorg || x1 != xorg) && !Clear(monst, x1, y1); + } + } + + return x1 == x2 && y1 == y2; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncMonsterAnim(int m) +{ + int dir; + + if ((DWORD)m >= MAXMONSTERS || m < 0) + { +#if defined(_DEBUG) + app_fatal("SyncMonsterAnim: Invalid monster %d",m); +#else + return; +#endif + } + + app_assert(monster[m]._mMTidx < MAX_LVLMTYPES + && monster[m]._mMTidx >= 0); + monster[m].MType = &Monsters[monster[m]._mMTidx]; + monster[m].MData = Monsters[monster[m]._mMTidx].MData; + if(monster[m]._uniqtype) + monster[m].mName = UniqMonst[monster[m]._uniqtype-1].mName; + else { + app_assert(monster[m].MData != 0); + monster[m].mName = monster[m].MData->mName; + } + + dir = monster[m]._mdir; + switch (monster[m]._mmode) { + case MM_STAND : + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + break; + case MM_WALK : + monster[m]._mAnimData = monster[m].MType->Anims[MA_WALK].Cels[dir]; + break; + case MM_WALK2 : + monster[m]._mAnimData = monster[m].MType->Anims[MA_WALK].Cels[dir]; + break; + case MM_WALK3: + monster[m]._mAnimData = monster[m].MType->Anims[MA_WALK].Cels[dir]; + break; + case MM_ATTACK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_ATTACK].Cels[dir]; + break; + case MM_RATTACK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_ATTACK].Cels[dir]; + break; + case MM_GOTHIT: + monster[m]._mAnimData = monster[m].MType->Anims[MA_GOTHIT].Cels[dir]; + break; + case MM_DEATH: + monster[m]._mAnimData = monster[m].MType->Anims[MA_DEATH].Cels[dir]; + break; + case MM_SATTACK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_FADEIN: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_FADEOUT: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_SPSTAND: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_RSATTACK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_DELAY: + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + break; + case MM_HEAL: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_TALK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + break; + case MM_STONE: + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + monster[m]._mAnimFrame = 1; + monster[m]._mAnimLen = monster[m].MType->Anims[MA_STAND].Frames; + break; + case MM_MISSILE: + monster[m]._mAnimData = monster[m].MType->Anims[MA_ATTACK].Cels[dir]; + monster[m]._mAnimFrame = 1; + monster[m]._mAnimLen = monster[m].MType->Anims[MA_ATTACK].Frames; + break; + default: + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + monster[m]._mAnimFrame = 1; + monster[m]._mAnimLen = monster[m].MType->Anims[MA_STAND].Frames; + break; + } +} + + +/*-----------------------------------------------------------------------* +* When monster gets killed, make the fallen run in fear +**-----------------------------------------------------------------------*/ +void M_FallenFear(int x, int y) +{ + int i, mi; + int rundist; + int aitype; + + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for (i = 0; i < nummonsters; ++i) { + mi = monstactive[i]; + rundist = 0; + switch(monster[mi].MType->mtype) { + case MT_RFALLSD : + case MT_RFALLSP : + rundist = 7; + break; + case MT_DFALLSD : + case MT_DFALLSP : + rundist = 5; + break; + case MT_YFALLSD : + case MT_YFALLSP : + rundist = 3; + break; + case MT_BFALLSD : + case MT_BFALLSP : + rundist = 2; + break; + } + + aitype = monster[mi]._mAi; + if(aitype == AI_FALLEN) { + if (rundist + && DIST(x-monster[mi]._mx, y-monster[mi]._my, 5) + && ((monster[mi]._mhitpoints >> HP_SHIFT) > 0)) + { + monster[mi]._mgoal = MG_RUN_AWAY; + monster[mi]._mgoalvar1 = rundist; // run away for 'rundist' squares + // next direction will be away from monster that got hit + monster[mi]._mdir = GetDirection(x, y, monster[i]._mx, monster[i]._my); + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PrintMonstHistory(int mt) +{ + int res, minhp, maxhp; + + sprintf(tempstr, "Total kills : %i", monstkills[mt]); + AddPanelString(tempstr, TEXT_CENTER); + if (monstkills[mt] >= 30) { + minhp = monsterdata[mt].mMinHP; + maxhp = monsterdata[mt].mMaxHP; + if (gbMaxPlayers == 1) { + minhp = minhp >> 1; + maxhp = maxhp >> 1; + } + if (minhp < 1) minhp = 1; + if (maxhp < 1) maxhp = 1; + if (gnDifficulty == D_NIGHTMARE) { + minhp = (minhp * 3) + ((gbMaxPlayers == 1) ? 50 : 100); + maxhp = (maxhp * 3) + ((gbMaxPlayers == 1) ? 50 : 100); + } + else if (gnDifficulty == D_HELL) { + minhp = (minhp * 4) + ((gbMaxPlayers == 1) ? 100 : 200); + maxhp = (maxhp * 4) + ((gbMaxPlayers == 1) ? 100 : 200); + } + sprintf(tempstr, "Hit Points : %i-%i", minhp, maxhp); + AddPanelString(tempstr, TEXT_CENTER); + } + /*minhp = monster[cursmonst]._mhitpoints >> HP_SHIFT; + maxhp = monster[cursmonst]._mmaxhp >> HP_SHIFT; + sprintf(tempstr, "Hit Points : %i of %i", minhp, maxhp); + AddPanelString(tempstr, TEXT_CENTER);*/ + if (monstkills[mt] >= 15) { + if (gnDifficulty != D_HELL) + res = monsterdata[mt].mMagicRes; + else + res = monsterdata[mt].mMagicRes2; + res &= (M_RM|M_RF|M_RL|M_IM|M_IF|M_IL); + if (res == M_NONE) { + strcpy(tempstr, "No magic resistance"); + AddPanelString(tempstr, TEXT_CENTER); + } else { + if (res & (M_RM|M_RF|M_RL)) { + strcpy(tempstr, "Resists : "); + if (res & M_RM) strcat(tempstr, "Magic "); + if (res & M_RF) strcat(tempstr, "Fire "); + if (res & M_RL) strcat(tempstr, "Lightning "); + tempstr[strlen(tempstr)-1] = 0; + AddPanelString(tempstr, TEXT_CENTER); + } + if (res & (M_IM|M_IF|M_IL)) { + strcpy(tempstr, "Immune : "); + if (res & M_IM) strcat(tempstr, "Magic "); + if (res & M_IF) strcat(tempstr, "Fire "); + if (res & M_IL) strcat(tempstr, "Lightning "); + tempstr[strlen(tempstr)-1] = 0; + AddPanelString(tempstr, TEXT_CENTER); + } + } + } + pinfoflag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PrintUniqueHistory() +{ + int res; + + /*int minhp = monster[cursmonst]._mhitpoints >> HP_SHIFT; + int maxhp = monster[cursmonst]._mmaxhp >> HP_SHIFT; + sprintf(tempstr, "Hit Points : %i of %i", minhp, maxhp); + AddPanelString(tempstr, TEXT_CENTER);*/ + res = monster[cursmonst].mMagicRes; + res &= (M_RM|M_RF|M_RL|M_IM|M_IF|M_IL); + if (res == M_NONE) { + strcpy(tempstr, "No resistances"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "No Immunities"); + AddPanelString(tempstr, TEXT_CENTER); + } else { + if (res & (M_RM|M_RF|M_RL)) + strcpy(tempstr, "Some Magic Resistances"); + else + strcpy(tempstr, "No resistances"); + AddPanelString(tempstr, TEXT_CENTER); + if (res & (M_IM|M_IF|M_IL)) + strcpy(tempstr, "Some Magic Immunities"); + else + strcpy(tempstr, "No Immunities"); + AddPanelString(tempstr, TEXT_CENTER); + } + pinfoflag = TRUE; +} + +/*-----------------------------------------------------------------------* + * MissToMonst + * + * Used when Rhino charges and collides into something. +**-----------------------------------------------------------------------*/ + +void MissToMonst(int i, int x, int y) +{ + int oldx,oldy; + int newx,newy; + if ((DWORD)i >= MAXMISSILES) + { +#if defined(_DEBUG) + app_fatal("MissToMonst: Invalid missile %d",i); +#else + return; +#endif + } + MissileStruct *Miss = &missile[i]; + int m = Miss->_misource; + if ((DWORD)m >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("MissToMonst: Invalid monster %d",m); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[m]; + int pnum; + + app_assert(Monst->_mmode == MM_MISSILE); + + oldx = Miss->_mix; + oldy = Miss->_miy; + + dMonster[x][y] = m+1; + + Monst->_mdir = Miss->_mimfnum; + Monst->_mx = x; + Monst->_my = y; + M_StartStand(m, Monst->_mdir); + + if(EquivMonst(Monst->MType->mtype, MT_INCIN)) + M_StartFadein(m, Monst->_mdir, FALSE); + else { + if ((Monst->_mFlags & MFLAG_MID) == 0) + M_StartHit(m,-1,0); + else + M2MStartHit(m,-1,0); + } + + if ((Monst->_mFlags & MFLAG_MID) == 0) { + pnum = dPlayer[oldx][oldy]-1; + if((dPlayer[oldx][oldy] > 0) + && (Monst->MType->mtype != MT_GLOOM) + && !EquivMonst(Monst->MType->mtype, MT_INCIN)) + { + M_TryH2HHit(m, dPlayer[oldx][oldy]-1, 500, Monst->mMinDamage2, Monst->mMaxDamage2); + + // make sure player didn't go change location during h2hhit + if (pnum == dPlayer[oldx][oldy]-1 + && !EquivMonst(Monst->MType->mtype, MT_NSNAKE)) + { + // make sure player is doing a hit animation + if (plr[pnum]._pmode != PM_GOTHIT && plr[pnum]._pmode != PM_DEATH) + StartPlrHit(pnum, 0, TRUE); + + // knock opponent back one square + newx = oldx + offset_x[Monst->_mdir]; + newy = oldy + offset_y[Monst->_mdir]; + if(PosOkPlayer(pnum, newx, newy)) + { + plr[pnum]._px = newx; + plr[pnum]._py = newy; + FixPlayerLocation(pnum,plr[pnum]._pdir); + FixPlrWalkTags(pnum); + dPlayer[newx][newy] = pnum + 1; + SetPlayerOld(pnum); + } + } + } + } else { + if((dMonster[oldx][oldy] > 0) + && (Monst->MType->mtype != MT_GLOOM) && !EquivMonst(Monst->MType->mtype, MT_INCIN)) + { + M_TryM2MHit(m, dMonster[oldx][oldy]-1, 500, Monst->mMinDamage2, Monst->mMaxDamage2); + if (!EquivMonst(Monst->MType->mtype, MT_NSNAKE)) + { + // knock opponent back one square + newx = oldx + offset_x[Monst->_mdir]; + newy = oldy + offset_y[Monst->_mdir]; + if(PosOkMonst(dMonster[oldx][oldy]-1, newx, newy)) + { + // This assumes that monster got hit (since we use a 500% hit above) + // so we don't have to clean up his area, and we assume pnum is positive + pnum = dMonster[newx][newy] = dMonster[oldx][oldy]; + dMonster[oldx][oldy] = 0; + --pnum; + monster[pnum]._mfutx = monster[pnum]._mx = newx; + monster[pnum]._mfuty = monster[pnum]._my = newy; + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static bool CheckForMissileWalls(int i, int x, int y) +{ + bool ret = true; + int mi = dMissile[x][y]; + + if(mi && i >= 0) + { + bool fire = false; + bool lightwall = false; + + if(mi > 0) { + if(missile[mi]._mitype == MIT_FIREWALL) + fire = true; + else if ( missile[mi]._mitype == MIT_LIGHTWALL) + lightwall = true; + } else { + for(mi = 0; mi < nummissiles; ++mi) { + int const mx = missileactive[mi]; + + if (missile[mx]._mix == x && + missile[mx]._miy == y) { + if(missile[mx]._mitype == MIT_FIREWALL) { + fire = true; + break; + } + if (missile[mx]._mitype == MIT_LIGHTWALL) { + lightwall = true; + break; + } + } + } + } + if ((fire && !(monster[i].mMagicRes & M_IF)) || (fire && (monster[i].MType->mtype == MT_DIABLO))) + ret = FALSE; + if ((lightwall && !(monster[i].mMagicRes & M_IL)) || (lightwall && (monster[i].MType->mtype == MT_DIABLO))) + ret = FALSE; + } + + return ret; +} +/*-----------------------------------------------------------------------* + * PosOkMonst + * + * Map position (x,y) is ok for placement of a monster. +**-----------------------------------------------------------------------*/ + +BOOL PosOkMonst(int i, int x, int y) +{ + BOOL ret = TRUE; + ret = !SolidLoc(x, y) && !dPlayer[x][y] && !dMonster[x][y]; + int oi = dObject[x][y]; + + if(ret && oi) + { + if (oi > 0) oi -= 1; + else oi = -(oi + 1); + + if (object[oi]._oSolidFlag) ret = FALSE; + } + + if(ret) + { + ret = CheckForMissileWalls(i, x, y); + } + + return ret; +} + +/*-----------------------------------------------------------------------* + * PosOkMonst2 + * + * Map position (x,y) is ok for placement of a monster. + * Same as PosOkMonst, except ignores other monsters and players +**-----------------------------------------------------------------------*/ + +BOOL PosOkMonst2(int i, int x, int y) +{ + BOOL ret = TRUE; + int oi = dObject[x][y]; + + ret = !SolidLoc(x, y); + + if(ret && oi) + { + if (oi > 0) oi -= 1; + else oi = -(oi + 1); + + if (object[oi]._oSolidFlag) ret = FALSE; + } + if(ret) + { + ret = CheckForMissileWalls(i, x, y); + } + + return ret; +} + +/*-----------------------------------------------------------------------* + * PosOkMonst + * + * Map position (x,y) is ok for placement of a monster. + * Same as PosOkMonst3, except ignores doors +**-----------------------------------------------------------------------*/ + +BOOL PosOkMonst3(int i, int x, int y) +{ + BOOL ret = TRUE; + bool isdoor = false; + int oi = dObject[x][y]; + + if(oi) + { + if (oi > 0) oi -= 1; + else oi = -(oi + 1); + + int const objtype = object[oi]._otype; + isdoor = (objtype == OBJ_L1DOORL + || objtype == OBJ_L1DOORR + || objtype == OBJ_L2DOORL + || objtype == OBJ_L2DOORR + || objtype == OBJ_L3DOORL + || objtype == OBJ_L3DOORR); + if (object[oi]._oSolidFlag && !isdoor) + ret = FALSE; + } + + if (ret) + ret = (!SolidLoc(x, y) || isdoor) && !dPlayer[x][y] && !dMonster[x][y]; + + if(ret) + { + ret = CheckForMissileWalls(i, x, y); + } + + return ret; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL IsSkel(int mt) +{ + return EquivMonst(mt, MT_WSKELAX) + || EquivMonst(mt, MT_WSKELBW) + || EquivMonst(mt, MT_WSKELSD); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL IsGoat(int mt) +{ + return EquivMonst(mt, MT_NGOATMC) + || EquivMonst(mt, MT_NGOATBW); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_SpawnSkel(int x, int y, int dir) +{ + int i,j; + int skeltypes = 0; + int skel; + + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (i = 0; i < nummtypes; ++i) + if (IsSkel(Monsters[i].mtype)) + ++skeltypes; + + if (skeltypes) + { + j = random(136,skeltypes); + skeltypes = 0; + for (i = 0; i < nummtypes && skeltypes <= j; ++i) + if(IsSkel(Monsters[i].mtype)) + ++skeltypes; + --i; + skel = AddMonster(x, y, dir, i, TRUE); + if (skel != -1) M_StartSpStand(skel, dir); + return skel; + } + else + return -1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ActivateSpawn(int i, int x, int y, int dir) +{ + dMonster[x][y] = i + 1; + monster[i]._mx = x; + monster[i]._my = y; + monster[i]._mfutx = x; + monster[i]._mfuty = y; + monster[i]._moldx = x; + monster[i]._moldy = y; + M_StartSpStand(i, dir); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL SpawnSkeleton(int ii, int x, int y) +{ + int monstok[3][3]; + int i,j,xx,yy,rs; + BOOL savail; + + if (ii == -1) return FALSE; + // Try location first + if (PosOkMonst(-1, x, y)) { + ActivateSpawn(ii, x, y, GetDirection(x, y, x, y)); + } else { + // Try surrounding squares + savail = FALSE; + yy = 0; + for (j = (y-1); j <= (y+1); ++j) { + xx = 0; + for (i = (x-1); i <= (x+1); ++i) { + monstok[xx][yy] = PosOkMonst(-1, i,j); + savail |= monstok[xx][yy]; + ++xx; + } + ++yy; + } + + // No fit, no good + if (!savail) return(FALSE); + + // Place skeleton + rs = random(137,15) + 1; + xx = 0; + yy = 0; + while (rs > 0) { + if (monstok[xx][yy]) --rs; + if (rs > 0) { + ++xx; + if (xx == 3) { + xx = 0; + ++yy; + if (yy == 3) yy = 0; + } + } + } + xx = xx + x - 1; + yy = yy + y - 1; + ActivateSpawn(ii, xx, yy, GetDirection(xx, yy, x, y)); + } + return(TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PreSpawnSkeleton() +{ + int i,j; + int skeltypes = 0; + int skel; + + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (i = 0; i < nummtypes; ++i) + if (IsSkel(Monsters[i].mtype)) + ++skeltypes; + + if (skeltypes) + { + j = random(136,skeltypes); + skeltypes = 0; + for (i = 0; i < nummtypes && skeltypes <= j; ++i) + { + if(IsSkel(Monsters[i].mtype)) + ++skeltypes; + } + --i; + skel = AddMonster(0, 0, 0, i, FALSE); + if (skel != -1) M_StartStand(skel, 0); + return skel; + } + else + return -1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void TalktoMonster(int i) +{ + int pnum, itm; + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("TalktoMonster: Invalid monster %d",i); +#else + return; +#endif + } + MonsterStruct *Monst = &monster[i]; + pnum = Monst->_menemy; + + Monst->_mmode = MM_TALK; + + if ((Monst->_mAi != AI_SNOTSPIL) && (Monst->_mAi != AI_LACHDANAN)) + return; + + if (QuestStatus(Q_LTBANNER)) { + if ((quests[Q_LTBANNER]._qvar1 == 2) && (PlrHasItem(pnum, IDI_BANNER, itm))) { + RemoveInvItem(pnum, itm); + quests[Q_LTBANNER]._qactive = QUEST_DONE; + Monst->mtalkmsg = TXT_BOL3; + Monst->_mgoal = MG_TALK; + } + } + if (QuestStatus(Q_VEIL)) { + if ((Monst->mtalkmsg >= TXT_VEIL1) && (PlrHasItem(pnum, IDI_GLDNELIX, itm))) { + RemoveInvItem(pnum, itm); + Monst->mtalkmsg = TXT_VEIL3; + Monst->_mgoal = MG_TALK; + } + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnGolum(int i, int x, int y, int mi) +{ + if ((DWORD)i >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("SpawnGolum: Invalid monster %d",i); +#else + return; +#endif + } + dMonster[x][y] = i + 1; + monster[i]._mx = x; + monster[i]._my = y; + monster[i]._mfutx = x; + monster[i]._mfuty = y; + monster[i]._moldx = x; + monster[i]._moldy = y; + monster[i]._pathcount = 0; + + monster[i]._mmaxhp = ((plr[i]._pMaxMana/3)<<1) + (((missile[mi]._mispllvl << HP_SHIFT) << 3) + ((missile[mi]._mispllvl << HP_SHIFT) << 1)); + monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i].mArmorClass = 25; + monster[i].mHit = 40 + (plr[i]._pLevel << 1) + ((missile[mi]._mispllvl << 2) + (missile[mi]._mispllvl)); + monster[i].mMinDamage = 8 + (missile[mi]._mispllvl << 1); + monster[i].mMaxDamage = 16 + (missile[mi]._mispllvl << 1); + + monster[i]._mFlags |= MFLAG_MKILLER; + M_StartSpStand(i, 0); + M_Enemy(i); + + void NetSendCmdGolem(BYTE, BYTE, BYTE, BYTE, long, BYTE); + if (i == myplr) + NetSendCmdGolem(monster[i]._mx, monster[i]._my, monster[i]._mdir, monster[i]._menemy, monster[i]._mhitpoints, currlevel); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL CanTalkToMonst(int m) +{ + if ((DWORD)m >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("CanTalkToMonst: Invalid monster %d",m); +#else + return FALSE; +#endif + } + if (monster[m]._mgoal == MG_TALK) return(TRUE); + if (monster[m]._mgoal == MG_WAITTOTALK) return(TRUE); + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL CheckMonsterHit(int m, BOOL &ret) +{ + if ((DWORD)m >= MAXMONSTERS) + { +#if defined(_DEBUG) + app_fatal("CheckMonsterHit: Invalid monster %d",m); +#else + return FALSE; +#endif + } + if (monster[m]._mAi == AI_GARG && (monster[m]._mFlags & MFLAG_STILL)) + { + monster[m]._mFlags &= ~MFLAG_STILL; + monster[m]._mmode = MM_SATTACK; + ret = TRUE; + return(TRUE); + } + else if(EquivMonst(monster[m].MType->mtype, MT_COUNSLR) + && (monster[m]._mgoal != MG_ATTACK)) + { + ret = FALSE; + return TRUE; + } + return FALSE; +} + +//****************************************************************** +//****************************************************************** +int encode_enemy(int m) +{ + if (monster[m]._mFlags & MFLAG_MID) + return monster[m]._menemy + MAX_PLRS; + else + // enemy is player, guaranteed < MAX_PLRS + return monster[m]._menemy; +} + +//****************************************************************** +//****************************************************************** +void decode_enemy(int m, int enemy) +{ + if (enemy < MAX_PLRS) { + monster[m]._mFlags &= ~MFLAG_MID; + monster[m]._menemy = enemy; + monster[m]._menemyx = plr[enemy]._pfutx; + monster[m]._menemyy = plr[enemy]._pfuty; + } + else { + monster[m]._mFlags |= MFLAG_MID; + enemy -= MAX_PLRS; + monster[m]._menemy = enemy; + monster[m]._menemyx = monster[enemy]._mfutx; + monster[m]._menemyy = monster[enemy]._mfuty; + } +} diff --git a/src/MONSTER.H b/src/MONSTER.H new file mode 100644 index 0000000..199996e --- /dev/null +++ b/src/MONSTER.H @@ -0,0 +1,304 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/MONSTER.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXMONSTERS 200 + +#define MONSTERTYPES 200 + +//#define MAX_LVLMTYPES 16 //JKE 7/29 +#define MAX_LVLMTYPES 24 // new crypt level + +#define MONSTDENSITY 30 + +#define MFLAG_INVISIBLE 0x00000001 +#define MFLAG_BACKWARDS 0x00000002 +#define MFLAG_STILL 0x00000004 // Used for Gargoyles while they are stone +#define MFLAG_NOHEAL 0x00000008 // Monster can no longer heal itself +#define MFLAG_MID 0x00000010 // _menemy element indexes monsters[] (default is plr[]) +#define MFLAG_MKILLER 0x00000020 // monster is an attacker monster +#define MFLAG_DROP 0x00000040 // drop an item at special time +#define MFLAG_KNOCKBACK 0x00000080 // knock back enemy one square +#define MFLAG_PATH 0x00000100 // use path algorithm to navigate around obstacles +#define MFLAG_CHECKDOORS 0x00000200 // this monster has door-opening abilities +#define MFLAG_NOENEMY 0x00000400 // monster has no enemy (because there are none left) +#define MFLAG_BERSERK 0x00000800 // monster attacks everything. + +// Monster Placement Flags +#define MPFLAG_SCATTER 1 // scatter these all over +#define MPFLAG_DONT 2 // don't place -- taken care of elsewhere +#define MPFLAG_UNIQ 4 // place once, as in a unique + +#define MAX_ANIMTYPE 6 + +#define M_ID 0 +#define P_ID 1 + +/*-----------------------------------------------------------------------* +** Macros +**-----------------------------------------------------------------------*/ + +#define DIST(x,y,d) (abs(x) < d && abs(y) < d) +#define EquivMonst(m,t) ((m) >= (t) && (m) <= (t)+3) + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +// AnimStruct +// One per animation, e.g. Fat demon walk +typedef struct { + BYTE *CMem; + BYTE *Cels[8]; + int Frames; + int Rate; +} AnimStruct; + +typedef struct { + TSnd * effect[2]; +} SndEffectStruct; + +typedef struct { + long mAnimWidth; // width of monster + long mImgSize; // Size of graphics for monster + char *filename; // pattern used to denote this monster in file names + BOOL has_special; // has a special animation + char *sndfile; // Name of the sound file + BOOL snd_special; // has a special snd + BOOL transflag; // Does this monster need gfx translation + char *TransFile; // Name of the gfx translation file + int Frames[MAX_ANIMTYPE]; + int Rate[MAX_ANIMTYPE]; + char *mName; // name + char mMinDLvl; // Min dungeon level + char mMaxDLvl; // Max dungeon level + char mLevel; // monster ranking + long mMinHP; // base hitpoints + long mMaxHP; // random hitpoints + BYTE mAi; // AI type + DWORD mFlags; // ai related flags + BYTE mInt; // Intelligence (0-3) + BYTE mHit; // hit% + BYTE mAFNum; // Which frame to check for attack on + BYTE mMinDamage; // min damage + BYTE mMaxDamage; // max damage + BYTE mHit2; // hit% + BYTE mAFNum2; // Which frame to check for attack on + BYTE mMinDamage2; // min damage + BYTE mMaxDamage2; // max damage + char mArmorClass; // Armor class + char mMonstClass; // Monster class + WORD mMagicRes; // Magic resistance + WORD mMagicRes2; // Magic resistance (for nightmare & hell modes) + WORD mTreasure; // Treasure + char mSelFlag; // Which type of selection + WORD mExp; // base experience +} MonsterData; + +// CMonster +// One per monster class, e.g. Fat demon +typedef struct { + int mtype; + BYTE mPlaceFlags; // monster placement flags + AnimStruct Anims[6]; + SndEffectStruct Snds[4]; + long mAnimWidth; // width of monster + long mAnimWidth2; // (width - 64) / 2 of monster for drawing + long mMinHP; // base hitpoints + long mMaxHP; // random hitpoints + BOOL has_special; // has a special animation + BYTE mAFNum; // Which frame to check for attack on + char mdeadval; // Which val to put in flags when dead + MonsterData *MData; + byte *pTrans; // Pointer to gfx translation table +} CMonster; + +// MonsterStruct +// One per monster in the dungeon, e.g., Joe the Fat demon +typedef struct { + int _mMTidx; // Type index into Monsters[] array (*** NOT MT_whatever ***) + int _mmode; // monsters current mode + BYTE _mgoal; // higher-level mode, i.e., run away! + int _mgoalvar1; // goal scratch 1 + int _mgoalvar2; // goal scratch 2 + int _mgoalvar3; // goal scratch 3 + int _mgoalvar4; // goal scratch 4 + BYTE _pathcount; // + int _mx; // monster map x + int _my; // monster map y + int _mfutx; // monster future map x + int _mfuty; // monster future map y + int _moldx; // monster starting walk map x + int _moldy; // monster starting walk map y + long _mxoff; // offset x from left of map tile + long _myoff; // offset y from bottom of map tile + long _mxvel; // current x rate + long _myvel; // current y rate + int _mdir; // current facing direction + int _menemy; // Which player is my enemy + BYTE _menemyx; // x location of enemy in dungeon + BYTE _menemyy; // y " + BYTE *_mAnimData; // Data pointer to anim tables + int _mAnimDelay; // anim delay amount + int _mAnimCnt; // current anim delay value + int _mAnimLen; // number of anim frames + int _mAnimFrame; // current anim frame + int _meflag; // draw extra tile to left for walk fix (flag) + BOOL _mDelFlag; // Delete/Kill monster + long _mVar1; // scratch var 1 + long _mVar2; // scratch var 2 + long _mVar3; // scratch var 3 + long _mVar4; // scratch var 4 + long _mVar5; // scratch var 5 + long _mVar6; // scratch var 6 + long _mVar7; // scratch var 7 + long _mVar8; // scratch var 8 + long _mmaxhp; // Fully healed monster hit points + long _mhitpoints; // Monster hit points + BYTE _mAi; // AI type + BYTE _mint; // Monster intelligence + DWORD _mFlags; + BYTE _msquelch; // keeps monster active for a while after it's not visible + int _mAFNum; // Which frame to check for attack on + int _lastx; // Coordinates where player was last seen + int _lasty; + + int _mRndSeed; // Random seed for item generation + int _mAISeed; // Random seed for AI (multiplayer only) + + BOOL _Wandering; // Is this a wandering monster + + BYTE _uniqtype; // Type of unique (0==None) + BYTE _uniqtrans; // Pal translation index + char _udeadval; // If unique, it's dead val + + char mWhoHit; // Which players have hit me so I can divvy up experience + + char mLevel; // monster ranking + WORD mExp; // base experience + BYTE mHit; // hit% + BYTE mMinDamage; // min damage + BYTE mMaxDamage; // max damage + BYTE mHit2; // hit% + BYTE mMinDamage2; // min damage + BYTE mMaxDamage2; // max damage + char mArmorClass; // Armor class + WORD mMagicRes; // Magic resistance + int mtalkmsg; // talking monster message number + + BYTE leader; // monster # of pack leader + BYTE leaderflag; + BYTE packsize; // # of monsters in pack + + BYTE mlid; // light id + + // Anything below this will not be saved or sent during a sync + #define SAVE_MONSTER_SIZE offsetof(MonsterStruct,mName) + char *mName; + CMonster *MType; + MonsterData *MData; +} MonsterStruct; + + +typedef struct { + int mtype; // i.e. MT_SKELSD + char * mName; + char * mTFile; // Translation filename + BYTE mlevel; // level on which it appears + WORD mmaxhp; + BYTE mAi; // AI type + BYTE mint; // AI level + BYTE mMinDamage; // min damage + BYTE mMaxDamage; // max damage + WORD mMagicRes; // Magic resistance + WORD mUnqAttr; // Unique attributes, i.e., pack leader + BYTE mUnqVar1; // parameter to unique attribute + BYTE mUnqVar2; // " + int mtalkmsg; // talking monster message number +} UniqMonstStruct; + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern MonsterStruct monster[MAXMONSTERS]; +extern long nummonsters; +extern int monstactive[MAXMONSTERS]; + +extern long monstkills[MONSTERTYPES]; + +extern int offset_x[]; +extern int offset_y[]; +extern int left[]; +extern int right[]; +extern int opposite[]; + +extern int nummtypes; +extern CMonster Monsters[MAX_LVLMTYPES]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitLevelMonsters(); +void GetLevelMTypes(); +void InitMonsterGFX(int monst); +void InitMonsterSND(int monst); +void FreeMonsterGFX(); +void InitMonsters(); +void TalktoMonster(int i); +void SetMapMonsters(BYTE *, int, int); + +void ProcessMonsters(); + +void M_StartStand(int i, int md); +void M_StartKill(int, int); +void M_SyncStartKill(int, int, int, int); +void M_StartHit(int, int, int); +void M_GetKnockback(int i); +void M_WalkDir(int i, int md); +void MAI_Golum(int i); + +BOOL DirOK(int i, int mdir); + +void SyncMonsterAnim(int); + +void PrintMonstHistory(int); + +void MissToMonst(int i, int x, int y); +BOOL PosOkMonst(int i, int x, int y); +BOOL PosOkMissile(int x, int y); + +BOOL IsSkel(int mt); +BOOL SpawnSkeleton(int i, int x, int y); +int PreSpawnSkeleton(); +void SpawnGolum(int, int, int, int); +void DeleteMonsterList(); +void MonstStartKill(int, int, BOOL); + +void PlaceQuestMonsters(); + +int AddMonster(int x, int y, int dir, int mtype, BOOL InMap); + +BOOL IsGoat(int mt); + +BOOL CanTalkToMonst(int m); + +BOOL CheckMonsterHit(int m, BOOL &ret); +BOOL LineClear(int, int, int, int); +int encode_enemy(int m); +void decode_enemy(int m, int enemy); + +void Hose_NaKrul(); +void CloneMonster(int m); diff --git a/src/MONSTER.SAV b/src/MONSTER.SAV new file mode 100644 index 0000000..953cdc6 --- /dev/null +++ b/src/MONSTER.SAV @@ -0,0 +1,6618 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Monsters file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MONSTER.CPP 3 1/23/97 7:22p Rseis $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "debug.h" +#include "monster.h" +#include "monstdat.h" +#include "engine.h" +#include "gendung.h" +#include "lighting.h" +#include "items.h" +#include "itemdat.h" +#include "player.h" +#include "effects.h" +#include "dead.h" +#include "missiles.h" +#include "misdat.h" +#include "control.h" +#include "objects.h" +#include "objdat.h" +#include "path.h" +#include "quests.h" +#include "minitext.h" +#include "textdat.h" +#include "monstint.h" +#include "msg.h" +#include "inv.h" +#include "multi.h" +#include "trigs.h" +#include "themes.h" +#include "drlg_l4.h" +#include "towners.h" +#include "setmaps.h" +#include "palette.h" +#include "scrollrt.h" +#include "cursor.h" + + +/*-----------------------------------------------------------------------* +** Function Prototypes +**-----------------------------------------------------------------------*/ +BOOL LineClear(int x1, int y1, int x2, int y2); +int M_GetDir(int i); + +typedef BOOL (*CHECKFUNC)(int x, int y); +typedef BOOL (*CHECKFUNC1)(int arg1, int x, int y); +BOOL LineClearF(CHECKFUNC Clear, int x1, int y1, int x2, int y2); +BOOL LineClearF1(CHECKFUNC1 Clear, int arg, int x1, int y1, int x2, int y2); +BOOL CheckNoSolid(int x, int y); +BOOL PosOkMissile(int x, int y); +int M_SpawnSkel(int x, int y, int dir); +void M_Teleport(int i); +void PlaceGroup(int, int, BOOL, int); +void ClrAllMonsters(); +BOOL PosOkMonst2(int i, int x, int y); +BOOL PosOkMonst3(int i, int x, int y); +BOOL effect_is_playing(int nSFX); + +extern const TextDataStruct alltext[]; + +//void DaveMonstMap(BOOL initupdate, int pnum); + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +MonsterStruct monster[MAXMONSTERS]; +long nummonsters; +int totalmonsters; + +// monstactive -- indexes into monster[] +int monstactive[MAXMONSTERS]; // [0..nummonsters-1] -- active monsters + // [nummonsters..MAXMONSTERS-1] -- available monsters + +int nummtypes = 0; +long monstimgtot; +int gfxflags; +int uniquetrans; // index to next available unique monster palette translation + +BYTE mleveltypes[NUMLEVELS][MAX_LVLMTYPES]; + +long monstkills[MONSTERTYPES]; + +static char sgszInvalidMonstName[] = "Invalid Monster"; + +/*-----------------------------------------------------------------------* +** Defines +**-----------------------------------------------------------------------*/ +#define PACK_MEMBER 1 +#define PACK_NOMEMBER 2 + +#define INITMONSTRAD 15 // Initial vision radius for no monsters + +/*-----------------------------------------------------------------------* +** Macros +**-----------------------------------------------------------------------*/ +#define InBounds(x,y) (0 <= (y) && (y) < MAXDUNY && 0 <= (x) && (x) < MAXDUNX) +#define WALKMODE(m) ((m) == MM_WALK || (m) == MM_WALK2 || (m) == MM_WALK3) +#define Sign(x) ((x) < 0 ? -1 : (x) > 0 ? 1 : 0) +#define Mod(val, x) ((val) < 0 ? (val)+(x) : (val) >= (x) ? (val)-(x) : (val)) + +/*-----------------------------------------------------------------------* +** File Variables +**-----------------------------------------------------------------------*/ +// I had to add this variable, because _mVar2 seems like +// it must have been trashed, since sound never came on again -- pjw +static BYTE sgbSaveSoundOn; + + // 16 32 64 +int MWVel[24][3] = { {0x100,0x200,0x400}, // 1 frame + {0x80,0x100,0x200}, // 2 frame + {0x55,0xaa,0x155}, // 3 frame + {0x40,0x80,0x100}, // 4 frame + {0x33,0x66,0xcc}, // 5 frame + {0x2a,0x55,0xaa}, // 6 frame + {0x24,0x49,0x92}, // 7 frame + {0x20,0x40,0x80}, // 8 frame + {0x1c,0x38,0x71}, // 9 frame + {0x1a,0x33,0x66}, // 10 frame + {0x17,0x2e,0x5d}, // 11 frame + {0x15,0x2a,0x55}, // 12 frame + {0x13,0x27,0x4e}, // 13 frame + {0x12,0x24,0x49}, // 14 frame + {0x11,0x22,0x44}, // 15 frame + {0x10,0x20,0x40}, // 16 frame + {0x0f,0x1e,0x3c}, // 17 frame + {0x0e,0x1c,0x39}, // 18 frame + {0x0d,0x1a,0x36}, // 19 frame + {0x0c,0x19,0x33}, // 20 frame + {0x0c,0x18,0x30}, // 21 frame + {0x0b,0x17,0x2e}, // 22 frame + {0x0b,0x16,0x2c}, // 23 frame + {0x0a,0x15,0x2a} }; // 24 frame + +// Muli-player monster multiplier % +/*int MPMM[4] = { 100, // 1 player + 150, // 2 player + 175, // 3 player + 200 }; // 4 player*/ + +CMonster Monsters[MAX_LVLMTYPES]; + +char animletter[] = "nwahds"; +int left[] = {7,0,1,2,3,4,5,6}; +int right[] = {1,2,3,4,5,6,7,0}; +int opposite[] = {4,5,6,7,0,1,2,3}; +int offset_x[] = {1,0,-1,-1,-1,0,1,1}; +int offset_y[] = {1,1,1,0,-1,-1,-1,0}; +int rnd5[] = { 5, 10, 15, 20 }; +int rnd10[] = { 10, 15, 20, 30 }; +int rnd20[] = { 20, 30, 40, 50 }; +int rnd60[] = { 60, 70, 80, 90 }; + + +void MAI_Zombie(int); +void MAI_Fat(int); +void MAI_SkelSd(int); +void MAI_SkelBow(int); +void MAI_Scav(int); +void MAI_Rhino(int); +void MAI_GoatMc(int); +void MAI_GoatBow(int); +void MAI_Fallen(int); +void MAI_Magma(int); +void MAI_SkelKing(int); +void MAI_Bat(int); +void MAI_Garg(int); +void MAI_Cleaver(int); +void MAI_Succ(int); +void MAI_Sneak(int); +void MAI_Storm(int); +void MAI_Fireman(int i); +void MAI_Garbud(int); +void MAI_Acid(int); +void MAI_AcidUniq(int); +void MAI_Golum(int); +void MAI_Zhar(int); +void MAI_SnotSpil(int); +void MAI_Snake(int); +void MAI_Counselor(int); +void MAI_Mega(int); +void MAI_Diablo(int); +void MAI_Lazurus(int); +void MAI_Lazhelp(int); +void MAI_Lachdanan(int); +void MAI_Warlord(int); + +void (*AiProc[])(int) = +{ + MAI_Zombie, + MAI_Fat, + MAI_SkelSd, + MAI_SkelBow, + MAI_Scav, + MAI_Rhino, + MAI_GoatMc, + MAI_GoatBow, + MAI_Fallen, + MAI_Magma, + MAI_SkelKing, + MAI_Bat, + MAI_Garg, + MAI_Cleaver, + MAI_Succ, + MAI_Sneak, + MAI_Storm, + MAI_Fireman, + MAI_Garbud, + MAI_Acid, + MAI_AcidUniq, + MAI_Golum, + MAI_Zhar, + MAI_SnotSpil, + MAI_Snake, + MAI_Counselor, + MAI_Mega, + MAI_Diablo, + MAI_Lazurus, + MAI_Lazhelp, + MAI_Lachdanan, + MAI_Warlord, +}; + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void TranslateMonsterGFX(int monst, BOOL sp) +{ + app_assert((DWORD)monst < MAX_LVLMTYPES); + int i,j,nf; + BYTE * pData = Monsters[monst].pTrans; + + for (int n = 256; n--; pData++) { + if (*pData == 255) + *pData = 0; + } + nf = sp ? 6 : 5; + for (j = 0; j < nf; j++) { + if ((j == 1) && (Monsters[monst].mtype >= MT_COUNSLR) && (Monsters[monst].mtype <= MT_ADVOCATE)) continue; + for (i = 0; i < 8; i++) + TranslateCels(Monsters[monst].Anims[j].Cels[i], Monsters[monst].pTrans, Monsters[monst].Anims[j].Frames); + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL MonstTaken(int i) +{ + int lev; + BOOL found = FALSE; + int m; + int templvl; // JKE + +// Temp hack for monsters JKE 7/30 + templvl = currlevel; +// if (templvl > 20) templvl -= 8; +// else if (templvl > 16) templvl -= 4; + +// for(lev = 0; lev <= currlevel && !found; lev++) // JKE + for(lev = 0; lev <= templvl && !found; lev++) + { + for(m = 0; m < MAX_LVLMTYPES && mleveltypes[m] && !found; m++) + found = ((i < mleveltypes[lev][m]-1) + && + !strcmp(monsterdata[i].filename, monsterdata[mleveltypes[lev][m]-1].filename)); + } + return found; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitLevelMonsters() +{ + int i; + + nummtypes = 0; + monstimgtot = 0; + gfxflags = 0; + + for (i = 0; i < MAX_LVLMTYPES; i++) + Monsters[i].mPlaceFlags = 0; + + ClrAllMonsters(); + nummonsters = 0; + totalmonsters = MAXMONSTERS; // this value gets further restricted later on + + // active monsters list + for (i = 0; i < MAXMONSTERS; i++) { + monstactive[i] = i; + } + uniquetrans = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int AddMonsterType(int type, int placeflag) +{ + int i; + BOOL done = FALSE; + + // check if this type is already being loaded + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (i = 0; i < nummtypes && !done; i++) + done = Monsters[i].mtype == type; + i--; + + if (!done) + { + i = nummtypes++; + Monsters[i].mtype = type; + monstimgtot += monsterdata[type].mImgSize; + InitMonsterGFX(i); + InitMonsterSND(i); + } + + Monsters[i].mPlaceFlags |= placeflag; + + return i; +} + +/*-----------------------------------------------------------------------* + * GetLevelMTypes() + * + * Pick the monsters types to be placed in this level +**-----------------------------------------------------------------------*/ + +void GetLevelMTypes() +{ + int typelist[MONSTERTYPES]; + int nt, i; + int tidx, mt; + int minl,maxl; + char mamask; + int templvl; // temp hack JKE + + #if IS_VERSION(SHAREWARE) + mamask = MAT_SW; + #else + mamask = MAT_SW | MAT_YES; + #endif + + // Certain monsters are required for certain levels + + AddMonsterType(MT_GOLEM, MPFLAG_DONT); + + if (currlevel == 16) { + AddMonsterType(MT_ADVOCATE, MPFLAG_SCATTER); + AddMonsterType(MT_RBLACK, MPFLAG_SCATTER); + AddMonsterType(MT_DIABLO, MPFLAG_DONT); + return; + } + + // Set levels load their own monster types + if (!setlevel) + { + if (QuestStatus(Q_BUTCHER)) { + AddMonsterType(MT_CLEAVER, MPFLAG_DONT); + } + + if (QuestStatus(Q_GARBUD)) { + AddMonsterType(UniqMonst[MU_GARBUD].mtype, MPFLAG_UNIQ); + } + + if (QuestStatus(Q_ZHAR)) { + AddMonsterType(UniqMonst[MU_ZHAR].mtype, MPFLAG_UNIQ); + } + + if (QuestStatus(Q_LTBANNER)) { + AddMonsterType(UniqMonst[MU_SNOTSPIL].mtype, MPFLAG_UNIQ); + } + + if (QuestStatus(Q_VEIL)) { + AddMonsterType(UniqMonst[MU_LACHDA].mtype, MPFLAG_UNIQ); + } + + if (QuestStatus(Q_WARLORD)) { + AddMonsterType(UniqMonst[MU_WARLORD].mtype, MPFLAG_UNIQ); + } + + if (gbMaxPlayers != 1 && currlevel == quests[Q_SKELKING]._qlevel) { + AddMonsterType(MT_SKING, MPFLAG_UNIQ); + + // Skelking requires skeleton minions + int skeltypes[LASTMT]; + int numskeltypes = 0; + + for (i = MT_WSKELAX; i <= MT_XSKELSD; i++) + { + if (IsSkel(i)) + { + minl = ((monsterdata[i].mMinDLvl * 15) / 30) + 1; + maxl = ((monsterdata[i].mMaxDLvl * 15) / 30) + 1; + if ((currlevel >= minl) && (currlevel <= maxl) && (MonstAvailTbl[i] & mamask)) + skeltypes[numskeltypes++] = i; + } + } + AddMonsterType(skeltypes[random(88,numskeltypes)], MPFLAG_SCATTER); + } + + // Pick general monsters + + // Make list of available monster types for this level +// Temp hack monster JKE + templvl = currlevel; +// if (templvl > 20) templvl -=8; +// else if (templvl > 16) templvl -= 4; + + nt = 0; + for (i = 0; i < LASTMT; i++) { + minl = ((monsterdata[i].mMinDLvl * 15) / 30) + 1; + maxl = ((monsterdata[i].mMaxDLvl * 15) / 30) + 1; +// if ((currlevel >= minl) && (currlevel <= maxl) && (MonstAvailTbl[i] & mamask)) { +// typelist[nt] = i; +// nt++; +// } + // use templvl to patch over current level + if ((templvl >= minl) && (templvl <= maxl) && (MonstAvailTbl[i] & mamask)) { + typelist[nt] = i; + nt++; + } + } + + if (monstdebug) + { + for(i = 0; i < debugmonsttypes; i++) + AddMonsterType(DebugMonsters[i], MPFLAG_SCATTER); + } + else + { + while ((nt > 0) && (nummtypes < MAX_LVLMTYPES) && (monstimgtot < IMG_MAX)) { + // prune excessively large monsters + for (i = 0; i < nt; ) + { + if (monsterdata[typelist[i]].mImgSize > IMG_MAX - monstimgtot) + typelist[i] = typelist[--nt]; + else + i++; + } + + if (nt) + { + tidx = random(88, nt); + mt = typelist[tidx]; + AddMonsterType(mt, MPFLAG_SCATTER); + typelist[tidx] = typelist[--nt]; + } + } + } + } + else if (setlvlnum == SL_SKELKING) { + AddMonsterType(MT_SKING, MPFLAG_UNIQ); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitMonsterGFX (int monst) +{ + int anim; + long i; + char strBuff[256]; + int mtype; + BYTE *p; + + app_assert((DWORD)monst < MAX_LVLMTYPES); + mtype = Monsters[monst].mtype; + for(anim = 0; anim < MAX_ANIMTYPE; anim++) + { + if((!(animletter[anim] == 's' && !monsterdata[mtype].has_special)) && monsterdata[mtype].Frames[anim] > 0) + { + sprintf(strBuff, monsterdata[mtype].filename, animletter[anim]); + app_assert(! Monsters[monst].Anims[anim].CMem); + Monsters[monst].Anims[anim].CMem = LoadFileInMemSig(strBuff,NULL,'MONS'); + p = Monsters[monst].Anims[anim].CMem; + if (Monsters[monst].mtype == MT_GOLEM && (animletter[anim] == 's' || animletter[anim] == 'd')) { + for(i=0; i<8; i++) Monsters[monst].Anims[anim].Cels[i] = p; + } else { + for(i=0; i<8; i++) Monsters[monst].Anims[anim].Cels[i] = p + *(DWORD *)(p + (i<<2)); + } + } + Monsters[monst].Anims[anim].Frames = monsterdata[mtype].Frames[anim]; + Monsters[monst].Anims[anim].Rate = monsterdata[mtype].Rate[anim]; + } + Monsters[monst].mAnimWidth = monsterdata[mtype].mAnimWidth; + Monsters[monst].mAnimWidth2 = (monsterdata[mtype].mAnimWidth - 64) >> 1; + Monsters[monst].mMinHP = monsterdata[mtype].mMinHP; + Monsters[monst].mMaxHP = monsterdata[mtype].mMaxHP; + Monsters[monst].has_special = monsterdata[mtype].has_special; + Monsters[monst].mAFNum = monsterdata[mtype].mAFNum; + Monsters[monst].MData = &monsterdata[mtype]; + if (monsterdata[mtype].transflag) { + Monsters[monst].pTrans = LoadFileInMemSig(monsterdata[mtype].TransFile,NULL,'MONS'); + TranslateMonsterGFX(monst, monsterdata[mtype].has_special); + DiabloFreePtr(Monsters[monst].pTrans); + } + if (EquivMonst(mtype, MT_NMAGMA) && ((gfxflags & 0x0001) == 0)) { + gfxflags |= 0x0001; + ILoadMissileGFX(MF_MAGBALL); + } + + if (EquivMonst(mtype, MT_STORM) && ((gfxflags & 0x0002) == 0)) { + gfxflags |= 0x0002; + ILoadMissileGFX(MF_THINLIGHT); + } + + if ((mtype == MT_SUCCUBUS) && ((gfxflags & 0x0004) == 0)) { + gfxflags |= 0x0004; + ILoadMissileGFX(MF_FLARE); + ILoadMissileGFX(MF_FLAREXP); + } + if ((mtype == MT_SNOWWICH) && ((gfxflags & 0x0020) == 0)) { + gfxflags |= 0x0020; + ILoadMissileGFX(MF_BFLARE); + ILoadMissileGFX(MF_BFLAREXP); + } + if ((mtype == MT_HLSPWN) && ((gfxflags & 0x0040) == 0)) { + gfxflags |= 0x0040; + ILoadMissileGFX(MF_DFLARE); + ILoadMissileGFX(MF_DFLAREXP); + } + if ((mtype == MT_SOLBRNR) && ((gfxflags & 0x0080) == 0)) { + gfxflags |= 0x0080; + ILoadMissileGFX(MF_CFLARE); + ILoadMissileGFX(MF_CFLAREXP); + } + + if (EquivMonst(mtype, MT_INCIN) && ((gfxflags & 0x0008) == 0)) { + gfxflags |= 0x0008; + ILoadMissileGFX(MF_KRULL); + } + + if (EquivMonst(mtype, MT_NACID) && ((gfxflags & 0x0010) == 0)) { + gfxflags |= 0x0010; + ILoadMissileGFX(MF_ACID); + ILoadMissileGFX(MF_ACIDSPLAT); + ILoadMissileGFX(MF_ACIDPUD); + } + + if (mtype == MT_DIABLO) + ILoadMissileGFX(MF_FIREPLAR); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ClearMVars(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + monster[i]._mVar1 = 0; + monster[i]._mVar2 = 0; + monster[i]._mVar3 = 0; + monster[i]._mVar4 = 0; + monster[i]._mVar5 = 0; + monster[i]._mVar6 = 0; + monster[i]._mVar7 = 0; + monster[i]._mVar8 = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + + +void InitMonster(int i, int rd, int mtype, int x, int y) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert((DWORD)mtype < MAX_LVLMTYPES); + CMonster *monst = &Monsters[mtype]; + app_assert(monst->MData != NULL); + + monster[i]._mdir = rd; + monster[i]._mx = x; + monster[i]._my = y; + monster[i]._mfutx = x; + monster[i]._mfuty = y; + monster[i]._moldx = x; + monster[i]._moldy = y; + + monster[i]._mMTidx = mtype; + monster[i]._mmode = MM_STAND; + monster[i].mName = monst->MData->mName; + monster[i].MType = monst; + monster[i].MData = monst->MData; + monster[i]._mAnimData = monst->Anims[MA_STAND].Cels[rd]; + monster[i]._mAnimDelay = monst->Anims[MA_STAND].Rate; + monster[i]._mAnimCnt = random(88, monster[i]._mAnimDelay - 1); + monster[i]._mAnimLen = monst->Anims[MA_STAND].Frames; + monster[i]._mAnimFrame = random(88, monster[i]._mAnimLen - 1) + 1; + if (monst->mtype == MT_DIABLO) { + monster[i]._mmaxhp = (random(88, 1666 - 1666 + 1) + 1666) << HP_SHIFT; + } else { + monster[i]._mmaxhp = (random(88, monst->mMaxHP - monst->mMinHP + 1) + monst->mMinHP) << HP_SHIFT; + } +/* if (gbMaxPlayers != 1) + monster[i]._mmaxhp = (monster[i]._mmaxhp * MPMM[gbActivePlayers-1]) / 100; + else + monster[i]._mmaxhp = monster[i]._mmaxhp >> 1; + if (monster[i]._mmaxhp < (1 << HP_SHIFT)) monster[i]._mmaxhp = 1 << HP_SHIFT;*/ + if (gbMaxPlayers == 1) { + monster[i]._mmaxhp = monster[i]._mmaxhp >> 1; + if (monster[i]._mmaxhp < (1 << HP_SHIFT)) monster[i]._mmaxhp = 1 << HP_SHIFT; + } + monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i]._mAi = monst->MData->mAi; + monster[i]._mint = monst->MData->mInt; + monster[i]._mgoal = MG_ATTACK; + monster[i]._mgoalvar1 = 0; + monster[i]._mgoalvar2 = 0; + monster[i]._mgoalvar3 = 0; + monster[i]._mgoalvar4 = 0; + monster[i]._pathcount = 0; + monster[i]._mDelFlag = FALSE; + monster[i]._uniqtype = 0; + monster[i]._msquelch = 0; + + monster[i]._mRndSeed = GetRndSeed(); + monster[i]._mAISeed = GetRndSeed(); + + monster[i].mWhoHit = 0; + + monster[i].mLevel = monst->MData->mLevel; + monster[i].mExp = monst->MData->mExp; + monster[i].mHit = monst->MData->mHit; + monster[i].mMinDamage = monst->MData->mMinDamage; + monster[i].mMaxDamage = monst->MData->mMaxDamage; + monster[i].mHit2 = monst->MData->mHit2; + monster[i].mMinDamage2 = monst->MData->mMinDamage2; + monster[i].mMaxDamage2 = monst->MData->mMaxDamage2; + monster[i].mArmorClass = monst->MData->mArmorClass; + monster[i].mMagicRes = monst->MData->mMagicRes; + monster[i].leader = 0; + monster[i].leaderflag = 0; + monster[i]._mFlags = monst->MData->mFlags; + monster[i].mtalkmsg = 0; + + if (monster[i]._mAi == AI_GARG) + { + monster[i]._mAnimData = monst->Anims[MA_SPECIAL].Cels[rd]; + monster[i]._mAnimFrame = 1; + monster[i]._mFlags |= MFLAG_STILL; + monster[i]._mmode = MM_SATTACK; + } + + if (gnDifficulty == D_NIGHTMARE) { + monster[i]._mmaxhp = (monster[i]._mmaxhp * 3) + 100; + monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i].mLevel += 15; + monster[i].mExp = (monster[i].mExp << 1) + 2000; + monster[i].mHit += 85; + monster[i].mMinDamage = (monster[i].mMinDamage * 2) + 4; + monster[i].mMaxDamage = (monster[i].mMaxDamage * 2) + 4; + monster[i].mHit2 += 85; + monster[i].mMinDamage2 = (monster[i].mMinDamage2 * 2) + 4; + monster[i].mMaxDamage2 = (monster[i].mMaxDamage2 * 2) + 4; + monster[i].mArmorClass += 50; + } + if (gnDifficulty == D_HELL) { + monster[i]._mmaxhp = (monster[i]._mmaxhp * 4) + 200; + monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i].mLevel += 30; + monster[i].mExp = (monster[i].mExp << 2) + 4000; + monster[i].mHit += 120; + monster[i].mMinDamage = (monster[i].mMinDamage * 4) + 6; + monster[i].mMaxDamage = (monster[i].mMaxDamage * 4) + 6; + monster[i].mHit2 += 120; + monster[i].mMinDamage2 = (monster[i].mMinDamage2 * 4) + 6; + monster[i].mMaxDamage2 = (monster[i].mMaxDamage2 * 4) + 6; + monster[i].mArmorClass += 80; + monster[i].mMagicRes = monst->MData->mMagicRes2; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ClrAllMonsters() +{ + int i; + MonsterStruct *Monst; + + for (i = 0; i < MAXMONSTERS; i++) { + Monst = &monster[i]; + ClearMVars(i); + + //track down freeloaders from previous levels by making them obvious + Monst->mName = sgszInvalidMonstName; + + Monst->_mgoal = 0; + Monst->_mmode = MM_STAND; + Monst->_mVar1 = MM_STAND; + Monst->_mVar2 = 0; + Monst->_mx = 0; + Monst->_my = 0; + Monst->_mfutx = 0; + Monst->_mfuty = 0; + Monst->_moldx = 0; + Monst->_moldy = 0; + Monst->_mdir = random(89, 8); + Monst->_mxvel = 0; + Monst->_myvel = 0; + Monst->_mAnimData = NULL; + Monst->_mAnimDelay = 0; + Monst->_mAnimCnt = 0; + Monst->_mAnimLen = 0; + Monst->_mAnimFrame = 0; + Monst->_mFlags = 0; + Monst->_mDelFlag = FALSE; + Monst->_menemy = random(89, gbActivePlayers); + Monst->_menemyx = plr[Monst->_menemy]._pfutx; + Monst->_menemyy = plr[Monst->_menemy]._pfuty; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL MonstPlace(int xp, int yp) { + if (xp < 0 || xp >= DMAXX || yp < 0 || yp >= DMAXY) return FALSE; + if (dMonster[xp][yp] != 0) return FALSE; + if (dPlayer[xp][yp] != 0) return FALSE; + if (dFlags[xp][yp] & BFLAG_MONSTACTIVE) return FALSE; + if (dFlags[xp][yp] & BFLAG_SETPC) return FALSE; + if (SolidLoc(xp,yp)) return FALSE; + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PlaceMonster(int i, int mtype, int x, int y) +{ + int rd; + + dMonster[x][y] = i + 1; + rd = random(90, 8); + InitMonster(i, rd, mtype, x, y); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void LoadUniMonstTrans(int uid) +{ + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PlaceUniqueMonst(int uniqindex, int miniontype, int packsize) +{ + app_assert((DWORD)nummonsters < MAXMONSTERS); + UniqMonstStruct *Uniq = &UniqMonst[uniqindex]; + MonsterStruct *Monst = &monster[nummonsters]; + + int xp,yp; + int x,y; + BOOL done; + int count, count2; + char filestr[64]; + done = FALSE; + count2 = 0; + int uniqtype; + + // Check if too many uniques. Limit is unique palette translation table size + if((uniquetrans << 8) + 4864 >= LIGHTSIZE) + return; + + // find the index of the monster graphics + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (uniqtype = 0; uniqtype < nummtypes; uniqtype++) + if (Monsters[uniqtype].mtype == UniqMonst[uniqindex].mtype) break; + app_assert(uniqtype < nummtypes); + + do + { + xp = random(91, DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(91, DMAXY - DIRTEDGE) + (DIRTEDGED2); + count = 0; + for(x = xp-3; x < xp+3; x++) + for(y = yp-3; y < yp+3; y++) + if(InBounds(x,y) && MonstPlace(x,y)) + count++; + } while((count < 9 // try finding a clear spot + && ++count2 < 1000) // avoid infinite loop + || !MonstPlace(xp,yp)); // make sure there's at least + // a spot for the leader + + if(uniqindex == MU_SNOTSPIL) { + xp = (setpc_x << 1) + DIRTEDGED2 + 8; + yp = (setpc_y << 1) + DIRTEDGED2 + 12; + } + if(uniqindex == MU_WARLORD) { + xp = (setpc_x << 1) + DIRTEDGED2 + 6; + yp = (setpc_y << 1) + DIRTEDGED2 + 7; + } + if(uniqindex == MU_ZHAR) { + int i; + BOOL zharflag = TRUE; + for (i = 0; i < themeCount; i++) { + if ((i == zharlib) && (zharflag == TRUE)) { + zharflag = FALSE; + xp = ((themeLoc[i].x << 1) + DIRTEDGED2)+4; + yp = ((themeLoc[i].y << 1) + DIRTEDGED2)+4; + } + } + } + if (gbMaxPlayers == 1) { + if(uniqindex == MU_LAZARUS) { + xp = 32; + yp = 46; + } + if(uniqindex == MU_REDVEX) { + xp = 40; + yp = 45; + } + if(uniqindex == MU_BLKJADE) { + xp = 38; + yp = 49; + } + if(uniqindex == MU_SKELKING) { + xp = 35; + yp = 47; + } + } else { + if(uniqindex == MU_LAZARUS) { + xp = (setpc_x << 1) + DIRTEDGED2 + 3; + yp = (setpc_y << 1) + DIRTEDGED2 + 6; + } + if(uniqindex == MU_REDVEX) { + xp = (setpc_x << 1) + DIRTEDGED2 + 5; + yp = (setpc_y << 1) + DIRTEDGED2 + 3; + } + if(uniqindex == MU_BLKJADE) { + xp = (setpc_x << 1) + DIRTEDGED2 + 5; + yp = (setpc_y << 1) + DIRTEDGED2 + 9; + } + } + + if (uniqindex == MU_CLEAVER) { + done = FALSE; + // Find certain tile where Butcher goes + for (yp = 0; yp < DMAXY && !done; yp++) + for (xp = 0; xp < DMAXX && !done; xp++) + done = (dPiece[xp][yp] == 367); + // NOTE: xp and yp get incremented an extra time after done=TRUE, but + // coincidentally, that's where we want to place butcher + } + + PlaceMonster(nummonsters, uniqtype, xp, yp); + Monst->_uniqtype = uniqindex+1; + if (Uniq->mlevel != 0) Monst->mLevel = Uniq->mlevel*2; + else Monst->mLevel += 5; + Monst->mExp = (Monst->mExp*2); + Monst->mName = Uniq->mName; + Monst->_mmaxhp = Uniq->mmaxhp << HP_SHIFT; +/* if (gbMaxPlayers != 1) + Monst->_mmaxhp = (Monst->_mmaxhp * MPMM[gbActivePlayers-1]) / 100; + else + Monst->_mmaxhp = Monst->_mmaxhp >> 1; + if (Monst->_mmaxhp < (1 << HP_SHIFT)) Monst->_mmaxhp = 1 << HP_SHIFT;*/ + if (gbMaxPlayers == 1) { + Monst->_mmaxhp = Monst->_mmaxhp >> 1; + if (Monst->_mmaxhp < (1 << HP_SHIFT)) Monst->_mmaxhp = 1 << HP_SHIFT; + } + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->_mAi = Uniq->mAi; + Monst->_mint = Uniq->mint; + Monst->mMinDamage = Uniq->mMinDamage; + Monst->mMaxDamage = Uniq->mMaxDamage; + Monst->mMinDamage2 = Uniq->mMinDamage; + Monst->mMaxDamage2 = Uniq->mMaxDamage; + Monst->mMagicRes = Uniq->mMagicRes; + Monst->mtalkmsg = Uniq->mtalkmsg; + Monst->mlid = AddLight(Monst->_mx, Monst->_my, 3); + if ((gbMaxPlayers != 1) && (Monst->_mAi == AI_LAZHELP)) Monst->mtalkmsg = 0; + if (Monst->mtalkmsg != 0) Monst->_mgoal = MG_TALK; + if (gnDifficulty == D_NIGHTMARE) { + Monst->_mmaxhp = (Monst->_mmaxhp * 3) + 100; + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->mLevel += 15; + Monst->mExp = (Monst->mExp << 1) + 2000; + Monst->mMinDamage = (Monst->mMinDamage * 2) + 4; + Monst->mMaxDamage = (Monst->mMaxDamage * 2) + 4; + Monst->mMinDamage2 = (Monst->mMinDamage2 * 2) + 4; + Monst->mMaxDamage2 = (Monst->mMaxDamage2 * 2) + 4; + } + if (gnDifficulty == D_HELL) { + Monst->_mmaxhp = (Monst->_mmaxhp * 4) + 200; + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->mLevel += 30; + Monst->mExp = (Monst->mExp << 2) + 4000; + Monst->mMinDamage = (Monst->mMinDamage * 4) + 6; + Monst->mMaxDamage = (Monst->mMaxDamage * 4) + 6; + Monst->mMinDamage2 = (Monst->mMinDamage2 * 4) + 6; + Monst->mMaxDamage2 = (Monst->mMaxDamage2 * 4) + 6; + } + + // Load unique monster translations + sprintf(filestr, "Monsters\\Monsters\\%s.TRN", Uniq->mTFile); + app_assert((uniquetrans << 8) + 4864 < LIGHTSIZE); + LoadFileWithMem(filestr, pLightTbl + (uniquetrans << 8) + 4864); + Monst->_uniqtrans = uniquetrans; + uniquetrans++; + + if(Uniq->mUnqAttr & UN_H) + { + Monst->mHit = Uniq->mUnqVar1; + Monst->mHit2 = Uniq->mUnqVar1; + } + if(Uniq->mUnqAttr & UN_A) + { + Monst->mArmorClass = Uniq->mUnqVar1; + } + + nummonsters++; + + if(Uniq->mUnqAttr & UN_PACK) + { + PlaceGroup(miniontype, packsize, Uniq->mUnqAttr, nummonsters-1); + } + // quick fix for monsters that were gargoyles before they became unique + if (Monst->_mAi != AI_GARG) + { + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + Monst->_mAnimFrame = random(88, Monst->_mAnimLen - 1) + 1; + Monst->_mFlags &= ~MFLAG_STILL; + Monst->_mmode = MM_STAND; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static void PlaceUniques() +{ + int u; + int mt; + BOOL done; + + //uniquetrans = 0; + for(u = 0; UniqMonst[u].mtype != -1; u++) + { +#if CHEATS + if ((UniqMonst[u].mlevel == currlevel) + || (UniqMonst[u].mlevel && davedebug)) { +#else + if (UniqMonst[u].mlevel == currlevel) { +#endif + done = FALSE; + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for(mt = 0; mt < nummtypes && !done; mt++) + done = Monsters[mt].mtype == UniqMonst[u].mtype; + mt--; + if ((u == MU_GARBUD) && (quests[Q_GARBUD]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if ((u == MU_ZHAR) && (quests[Q_ZHAR]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if ((u == MU_SNOTSPIL) && (quests[Q_LTBANNER]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if ((u == MU_LACHDA) && (quests[Q_VEIL]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if ((u == MU_WARLORD) && (quests[Q_WARLORD]._qactive == QUEST_NOTAVAIL)) + done = FALSE; + if(done) + { + PlaceUniqueMonst(u, mt, 8); + } + } + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +void PlaceQuestMonsters() +{ + int skeltype; + byte *setp; + + if (!setlevel) { + if (QuestStatus(Q_BUTCHER)) + PlaceUniqueMonst(MU_CLEAVER, 0, 0); + + if ((currlevel == quests[Q_SKELKING]._qlevel) && (gbMaxPlayers != 1)) + { + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (skeltype = 0; skeltype < nummtypes; skeltype++) + if (IsSkel(Monsters[skeltype].mtype)) break; + app_assert(skeltype < nummtypes); + + PlaceUniqueMonst(MU_SKELKING, skeltype, 30); + } + + if (QuestStatus(Q_LTBANNER)) + { + setp = LoadFileInMemSig("Levels\\L1Data\\Banner1.DUN",NULL,'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + + if (QuestStatus(Q_BLOOD)) + { + setp = LoadFileInMemSig("Levels\\L2Data\\Blood2.DUN", NULL, 'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + + if (QuestStatus(Q_BLIND)) + { + setp = LoadFileInMemSig("Levels\\L2Data\\Blind2.DUN", NULL, 'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + + if (QuestStatus(Q_ANVIL)) + { + setp = LoadFileInMemSig("Levels\\L3Data\\Anvil.DUN",NULL,'MONS'); + SetMapMonsters(setp, ((setpc_x+1) << 1), ((setpc_y+1) << 1)); + DiabloFreePtr(setp); + } + + if (QuestStatus(Q_WARLORD)) + { + setp = LoadFileInMemSig("Levels\\L4Data\\Warlord.DUN",NULL,'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + AddMonsterType(UniqMonst[MU_WARLORD].mtype, MPFLAG_SCATTER); // to allow scatterable monst of mtype + } + + if (QuestStatus(Q_VEIL)) + { + AddMonsterType(UniqMonst[MU_LACHDA].mtype, MPFLAG_SCATTER); // to allow scatterable monst of mtype + } + + if (QuestStatus(Q_ZHAR)) { + if (zharlib == -1) + quests[Q_ZHAR]._qactive = QUEST_NOTAVAIL; + } + + if ((currlevel == quests[Q_BETRAYER]._qlevel) && (gbMaxPlayers != 1)) { + AddMonsterType(UniqMonst[MU_LAZARUS].mtype, MPFLAG_UNIQ); + AddMonsterType(UniqMonst[MU_REDVEX].mtype, MPFLAG_UNIQ); + PlaceUniqueMonst(MU_LAZARUS, 0, 0); + PlaceUniqueMonst(MU_REDVEX, 0, 0); + PlaceUniqueMonst(MU_BLKJADE, 0, 0); + setp = LoadFileInMemSig("Levels\\L4Data\\Vile1.DUN",NULL,'MONS'); + SetMapMonsters(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + + } + else if (setlvlnum == SL_SKELKING) { + PlaceUniqueMonst(MU_SKELKING, 0, 0); + } +} +#endif + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PlaceGroup(int mtype, int num, BOOL leaderf, int leader) +{ + int xp, yp; + int x1, y1; + int j; + int placed = 0; + int try1 = 0; + int try2; + int rd; + + app_assert((DWORD)leader < MAXMONSTERS); + do + { + // Clear out the subset placed last time through the loop + while(placed) + { + nummonsters--; + placed--; + app_assert((DWORD)nummonsters < MAXMONSTERS); + app_assert((DWORD)monster[nummonsters]._mx < MAXDUNX); + app_assert((DWORD)monster[nummonsters]._my < MAXDUNY); + dMonster[monster[nummonsters]._mx][monster[nummonsters]._my] = 0; + } + + if(leaderf & UN_PACK) + { + rd = random(92, 8); + x1 = xp = monster[leader]._mx + offset_x[rd]; + y1 = yp = monster[leader]._my + offset_y[rd]; + } + else + { + do + { + x1 = xp = random(93, DMAXX - DIRTEDGE) + (DIRTEDGED2); + y1 = yp = random(93, DMAXY - DIRTEDGE) + (DIRTEDGED2); + } while (!MonstPlace(xp, yp)); + } + + if ((nummonsters + num) > totalmonsters) num = totalmonsters - nummonsters; + j = 0; + try2 = 0; + while (j < num && try2 < 100) { + if (MonstPlace(xp, yp) && (dTransVal[xp][yp] == dTransVal[x1][y1]) + && !((leaderf & UN_STICK) && !DIST(xp-x1,yp-y1,4))) { + PlaceMonster(nummonsters, mtype, xp, yp); + if(leaderf & UN_PACK) + { + monster[nummonsters]._mmaxhp *= 2; + monster[nummonsters]._mhitpoints = monster[nummonsters]._mmaxhp; + monster[nummonsters]._mint = monster[leader]._mint; + if (leaderf & UN_STICK) + { + monster[nummonsters].leader = leader; + monster[nummonsters].leaderflag = PACK_MEMBER; + monster[nummonsters]._mAi = monster[leader]._mAi; + } + // quick fix for monsters that were gargoyles before they became unique + if (monster[nummonsters]._mAi != AI_GARG) + { + monster[nummonsters]._mAnimData = monster[nummonsters].MType->Anims[MA_STAND].Cels[monster[nummonsters]._mdir]; + monster[nummonsters]._mAnimFrame = random(88, monster[nummonsters]._mAnimLen - 1) + 1; + monster[nummonsters]._mFlags &= ~MFLAG_STILL; + monster[nummonsters]._mmode = MM_STAND; + } + } + + nummonsters++; + placed++; + j++; + } + else + try2++; + xp += offset_x[random(94, 8)]; + yp += offset_x[random(94, 8)]; + } + } while((placed < num) && (++try1 < 10)); + if(leaderf & UN_STICK) + monster[leader].packsize = placed; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +void LoadDiabMonsts() +{ + BYTE *pSetPiece; + int xx, yy; + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab1.DUN",NULL,'STPC'); + xx = (diabquad1x << 1); + yy = (diabquad1y << 1); + SetMapMonsters(pSetPiece, xx, yy); + DiabloFreePtr(pSetPiece); + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab2a.DUN",NULL,'STPC'); + xx = (diabquad2x << 1); + yy = (diabquad2y << 1); + SetMapMonsters(pSetPiece, xx, yy); + DiabloFreePtr(pSetPiece); + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab3a.DUN",NULL,'STPC'); + xx = (diabquad3x << 1); + yy = (diabquad3y << 1); + SetMapMonsters(pSetPiece, xx, yy); + DiabloFreePtr(pSetPiece); + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab4a.DUN",NULL,'STPC'); + xx = (diabquad4x << 1); + yy = (diabquad4y << 1); + SetMapMonsters(pSetPiece, xx, yy); + DiabloFreePtr(pSetPiece); +} +#endif + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitMonsters () +{ + int i, mtype; + int na, nt; + int scattertypes[LASTMT]; + int numscattypes = 0; + long fv,j; + int numplacemonsters; + int s,t; + +void DaveCheck2(); + if (gbMaxPlayers != 1) DaveCheck2(); + + // add 4 golem places first + // WARNING!! IF YOU CHANGE THIS YOU MUST TEST POSION WATER QUEST!!! + if (!setlevel) { + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + } + + // We will place the monsters seperately for 16 +#if !IS_VERSION(SHAREWARE) + if (!setlevel && currlevel == 16) { + LoadDiabMonsts(); + } +#endif + + // Monsters are not placed where bFlags[][] & BFLAG_MONSTACTIVE is set + // This prevents: 1) Monsters attacking players as they enter dungeon + // 2) Monsters setting off traps + + nt = numtrigs; + if (currlevel == 15) nt = 1; + for (i = 0; i < nt; i++) + { + for (s = -2; s < 2; s++) + for (t = -2; t < 2; t++) + DoVision(trigs[i]._tx + s, trigs[i]._ty + t, INITMONSTRAD, FALSE, FALSE); + } + +#if !IS_VERSION(SHAREWARE) + PlaceQuestMonsters(); +#endif + + if (!setlevel) + { +#if !IS_VERSION(SHAREWARE) + PlaceUniques(); // Place uniques before any other monsters +#endif + // Calc a volume of monsters + fv = 0; + for (i = DIRTEDGED2; i < (DMAXY - (DIRTEDGED2)); i++) { + for (j = DIRTEDGED2; j < (DMAXX - (DIRTEDGED2)); j++) { + if (!SolidLoc(i,j)) fv++; + } + } + numplacemonsters = fv / MONSTDENSITY; +#if 0 // Debugging = 1, normal = 0 + numplacemonsters = 1; +#else + if (gbMaxPlayers != 1) numplacemonsters += (numplacemonsters >> 1); +#endif + if (numplacemonsters + nummonsters > MAXMONSTERS - 10) + numplacemonsters = MAXMONSTERS - 10 - nummonsters; + + totalmonsters = nummonsters + numplacemonsters; + + +#ifndef PACKS_ONLY // switch for debugging pack AI + // Place scattered monsters + + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (i = 0; i < nummtypes; i++) + { + if (Monsters[i].mPlaceFlags & MPFLAG_SCATTER) + scattertypes[numscattypes++] = i; + } + + while (nummonsters < totalmonsters) { + mtype = scattertypes[random(95, numscattypes)]; + + if (currlevel != 1 // no groups on level 1 + && random(95, 2)) + { + if (currlevel == 2) // half-size groups on level 2 + na = random(95, 2) + 2; + else + na = random(95, 3) + 3; + } + else na = 1; + + PlaceGroup(mtype, na, FALSE, NULL); + } +#endif // PACKS_ONLY + } + + for (i = 0; i < nt; i++) + { + for (s = -2; s < 2; s++) + for (t = -2; t < 2; t++) + DoUnVision(trigs[i]._tx + s, trigs[i]._ty + t, INITMONSTRAD); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetMapMonsters(BYTE *pMap, int startx, int starty) +{ + int i,j; + WORD rw,rh; + WORD *lm; + int mt,mx,my; + int mtype; + + // add 4 golem places first + // WARNING! IF YOU CHANGE THIS YOU MUST TEST THE POISON WATER QUEST!!!! + AddMonsterType(MT_GOLEM, MPFLAG_DONT); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + AddMonster(1, 0, 0, 0, FALSE); + + if ((setlevel) && (setlvlnum == SL_VILEBETRAYER)) { + AddMonsterType(UniqMonst[MU_LAZARUS].mtype, MPFLAG_UNIQ); + AddMonsterType(UniqMonst[MU_REDVEX].mtype, MPFLAG_UNIQ); + AddMonsterType(UniqMonst[MU_BLKJADE].mtype, MPFLAG_UNIQ); + PlaceUniqueMonst(MU_LAZARUS, 0, 0); + PlaceUniqueMonst(MU_REDVEX, 0, 0); + PlaceUniqueMonst(MU_BLKJADE, 0, 0); + } + + + lm = (WORD *)pMap; + rw = *(lm++); + rh = *(lm++); + // Skip map + lm += rw * rh; + // Convert to index mini tile level instead of mega + rw = rw << 1; + rh = rh << 1; + // Skip treasure map + lm += rw * rh; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*lm != 0) { + mt = *lm; + mt = MonstConvTbl[mt-1]; + mtype = AddMonsterType(mt, MPFLAG_DONT); + mx = i + DIRTEDGED2 + startx; + my = j + DIRTEDGED2 + starty; + PlaceMonster(nummonsters++, mtype, mx, my); + } + lm++; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DeleteMonster(int i) +{ + int temp; + + app_assert((DWORD)(nummonsters-1) < MAXMONSTERS); + app_assert((DWORD)i < MAXMONSTERS); + temp = monstactive[--nummonsters]; + monstactive[nummonsters] = monstactive[i]; + monstactive[i] = temp; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int AddMonster(int x, int y, int dir, int mtype, BOOL InMap) +{ + int i; + + if (nummonsters < MAXMONSTERS) { + i = monstactive[nummonsters++]; + if (InMap) dMonster[x][y] = i + 1; + InitMonster(i, dir, mtype, x, y); + return i; + } else return -1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void NewMonsterAnim(int i, AnimStruct &anim, int md) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert((DWORD)md < 8); + MonsterStruct *Monst = &monster[i]; + + Monst->_mAnimData = anim.Cels[md]; + Monst->_mAnimLen = anim.Frames; + Monst->_mAnimFrame = 1; + Monst->_mAnimCnt = 0; + Monst->_mAnimDelay = anim.Rate; + Monst->_mdir = md; + Monst->_mFlags &= ~(MFLAG_BACKWARDS|MFLAG_STILL); +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL M_Ranged (int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + if (monster[i]._mAi == AI_SKELBOW || + monster[i]._mAi == AI_GOATBOW || + monster[i]._mAi == AI_SUCC || + monster[i]._mAi == AI_LAZHELP) return TRUE; + + return FALSE; +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL M_Talker (int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + if (monster[i]._mAi == AI_LAZURUS || + monster[i]._mAi == AI_WARLORD || + monster[i]._mAi == AI_GARBUD || + monster[i]._mAi == AI_ZHAR || + monster[i]._mAi == AI_SNOTSPIL || + monster[i]._mAi == AI_LACHDANAN || + monster[i]._mAi == AI_LAZHELP) return TRUE; + + return FALSE; +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_Enemy (int i) +{ + int j, mi; + int pnum, closest; + int dist, bestdist; + BOOL sameroom, bestsameroom; + + app_assert((DWORD)i < MAXMONSTERS); + MonsterStruct *Monst = &monster[i]; + BYTE enemyx,enemyy; + + closest = -1; + bestdist = -1; + bestsameroom = FALSE; + + if (!(Monst->_mFlags & MFLAG_MKILLER)) { + for(pnum = 0; pnum < MAX_PLRS; pnum++) { + if (!plr[pnum].plractive + || currlevel != plr[pnum].plrlevel + || plr[pnum]._pLvlChanging + || (plr[pnum]._pHitPoints == 0) && (gbMaxPlayers != 1)) + continue; + + sameroom = (dTransVal[Monst->_mx][Monst->_my] == dTransVal[plr[pnum]._px][plr[pnum]._py]); + dist = max(abs(Monst->_mx - plr[pnum]._px), abs(Monst->_my - plr[pnum]._py)); + + if ((sameroom && !bestsameroom) || ((sameroom || !bestsameroom) && dist < bestdist) || closest == -1) { + Monst->_mFlags &= ~MFLAG_MID; +// Monst->_mFlags &= ~MFLAG_MKILLER; + closest = pnum; + enemyx = plr[pnum]._pfutx; + enemyy = plr[pnum]._pfuty; + bestdist = dist; + bestsameroom = sameroom; + } + } + } + + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for (j = 0; j < nummonsters; j++) { + mi = monstactive[j]; + if ((mi != i) && + ((monster[mi]._mx != 1) || (monster[mi]._my != 0)) && // special confus-o-matic code for inactive golum + ((!M_Talker(mi)) || monster[mi].mtalkmsg == 0) && + /*(DIST((monster[mi]._mx - Monst->_mx),(monster[mi]._my - Monst->_my),2)) &&*/ + ((Monst->_mFlags & MFLAG_MKILLER) || + ((DIST((monster[mi]._mx - Monst->_mx),(monster[mi]._my - Monst->_my),2)) || (M_Ranged(i)))) && + (Monst->_mFlags & MFLAG_MKILLER || monster[mi]._mFlags & MFLAG_MKILLER)) { + sameroom = (dTransVal[Monst->_mx][Monst->_my] == dTransVal[monster[mi]._mx][monster[mi]._my]); + dist = max(abs(Monst->_mx - monster[mi]._mx), abs(Monst->_my - monster[mi]._my)); + if ((sameroom && !bestsameroom) || ((sameroom || !bestsameroom) && dist < bestdist) || closest == -1) { + Monst->_mFlags |= MFLAG_MID; + closest = mi; + enemyx = monster[mi]._mfutx; + enemyy = monster[mi]._mfuty; + bestdist = dist; + bestsameroom = sameroom; + } + } + } + + // everyone dead? + if (closest != -1) + { + Monst->_menemy = closest; + Monst->_menemyx = enemyx; + Monst->_menemyy = enemyy; + Monst->_mFlags &= ~MFLAG_NOENEMY; + } + else + Monst->_mFlags |= MFLAG_NOENEMY; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int M_GetDir(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + return GetDirection(monster[i]._mx, monster[i]._my, monster[i]._menemyx, monster[i]._menemyy); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_CheckEFlag(int i) +{ + int tx,ty,tv; + int t; + WORD *mt; + + app_assert((DWORD)i < MAXMONSTERS); + tx = monster[i]._mx - 1; + ty = monster[i]._my + 1; + tv = 0; + mt = &(dMT[tx][ty].mt[0]); + for(t = 2; t < 10; t++) + tv |= mt[t]; + tv |= dSpecial[tx][ty]; + if (tv != 0) monster[i]._meflag = 1; + else monster[i]._meflag = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartStand(int i, int md) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + ClearMVars(i); + if (monster[i].MType->mtype == MT_GOLEM) + NewMonsterAnim(i, monster[i].MType->Anims[MA_WALK], md); + else + NewMonsterAnim(i, monster[i].MType->Anims[MA_STAND], md); + + monster[i]._mVar1 = monster[i]._mmode; + monster[i]._mVar2 = 0; // count how long he's been standing + monster[i]._mmode = MM_STAND; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); + + // Pick nearest enemy + M_Enemy(i); +} + +/*-----------------------------------------------------------------------* + * M_StartDelay + * + * Keeps monster in Stand animation for len frames + * Monster must be in Stand mode before entering Delay mode +**-----------------------------------------------------------------------*/ + +void M_StartDelay(int i, int len) +{ + if(len > 0) + { + if (monster[i]._mAi == AI_LAZURUS) return; + app_assert((DWORD)i < MAXMONSTERS); + monster[i]._mVar2 = len; + monster[i]._mmode = MM_DELAY; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartSpStand(int i, int md) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + + monster[i]._mmode = MM_SPSTAND; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartWalk(int i, int xvel, int yvel, int xadd, int yadd, int EndDir) +{ + long fx,fy; + int pn; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + fx = monster[i]._mx + xadd; + fy = monster[i]._my + yadd; + app_assert((DWORD)fx < MAXDUNX); + app_assert((DWORD)fy < MAXDUNY); + pn = dPiece[fx][fy] - 1; + dMonster[fx][fy] = -1 - i; + monster[i]._mmode = MM_WALK; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mfutx = fx; + monster[i]._mfuty = fy; + monster[i]._mxvel = xvel; + monster[i]._myvel = yvel; + monster[i]._mVar1 = xadd; + monster[i]._mVar2 = yadd; + monster[i]._mVar3 = EndDir; + monster[i]._mdir = EndDir; + NewMonsterAnim(i, monster[i].MType->Anims[MA_WALK], EndDir); + monster[i]._mVar6 = 0; + monster[i]._mVar7 = 0; + monster[i]._mVar8 = 0; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartWalk2(int i, int xvel, int yvel, int xoff, int yoff, + int xadd, int yadd, int EndDir) +{ + long fx,fy; + int pn; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + fx = monster[i]._mx + xadd; + fy = monster[i]._my + yadd; + app_assert((DWORD)fx < MAXDUNX); + app_assert((DWORD)fy < MAXDUNY); + pn = dPiece[fx][fy] - 1; + app_assert((DWORD)monster[i]._mx < MAXDUNX); + app_assert((DWORD)monster[i]._my < MAXDUNY); + dMonster[monster[i]._mx][monster[i]._my] = -1 - i; + monster[i]._mVar1 = monster[i]._mx; + monster[i]._mVar2 = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mx = fx; + monster[i]._my = fy; + monster[i]._mfutx = fx; + monster[i]._mfuty = fy; + dMonster[fx][fy] = i + 1; + if(monster[i]._uniqtype) + ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my); + monster[i]._mxoff = xoff; + monster[i]._myoff = yoff; + monster[i]._mmode = MM_WALK2; + monster[i]._mxvel = xvel; + monster[i]._myvel = yvel; + monster[i]._mVar3 = EndDir; + monster[i]._mdir = EndDir; + NewMonsterAnim(i, monster[i].MType->Anims[MA_WALK], EndDir); + monster[i]._mVar6 = xoff << 4; + monster[i]._mVar7 = yoff << 4; + monster[i]._mVar8 = 0; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartWalk3(int i, int xvel, int yvel, int xoff, int yoff, + int xadd, int yadd, int txa, int tya, int EndDir) +{ + long fx,fy; + long tx,ty; + int pn, pn2; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + fx = monster[i]._mx + xadd; + fy = monster[i]._my + yadd; + tx = monster[i]._mx + txa; // Temp location for drawing + ty = monster[i]._my + tya; + if(monster[i]._uniqtype) + ChangeLightXY(monster[i].mlid, tx, ty); + app_assert((DWORD)fx < MAXDUNX); + app_assert((DWORD)fy < MAXDUNY); + pn = dPiece[fx][fy] - 1; + pn2 = dPiece[tx][ty] - 1; + app_assert((DWORD)monster[i]._mx < MAXDUNX); + app_assert((DWORD)monster[i]._my < MAXDUNY); + dMonster[monster[i]._mx][monster[i]._my] = -1 - i; + dMonster[fx][fy] = -1 - i; + monster[i]._mVar4 = tx; + monster[i]._mVar5 = ty; + dFlags[tx][ty] |= BFLAG_MONSTLR; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mfutx = fx; + monster[i]._mfuty = fy; + monster[i]._mxoff = xoff; + monster[i]._myoff = yoff; + monster[i]._mmode = MM_WALK3; + monster[i]._mxvel = xvel; + monster[i]._myvel = yvel; + monster[i]._mVar1 = fx; + monster[i]._mVar2 = fy; + monster[i]._mVar3 = EndDir; + monster[i]._mdir = EndDir; + NewMonsterAnim(i, monster[i].MType->Anims[MA_WALK], EndDir); + monster[i]._mVar6 = xoff << 4; + monster[i]._mVar7 = yoff << 4; + monster[i]._mVar8 = 0; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartAttack(int i) +{ + int md; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + md = M_GetDir(i); + NewMonsterAnim(i, monster[i].MType->Anims[MA_ATTACK], md); + + monster[i]._mmode = MM_ATTACK; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +** Ranged weapons +**-----------------------------------------------------------------------*/ + +void M_StartRAttack(int i, int missile_type, int dam) +{ + int md; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + md = M_GetDir(i); + NewMonsterAnim(i, monster[i].MType->Anims[MA_ATTACK], md); + + monster[i]._mmode = MM_RATTACK; + monster[i]._mVar1 = missile_type; + monster[i]._mVar2 = dam; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +** Ranged Special weapons +**-----------------------------------------------------------------------*/ + +void M_StartRSpAttack(int i, int missile_type, int dam) +{ + int md; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + md = M_GetDir(i); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + + monster[i]._mmode = MM_RSATTACK; + monster[i]._mVar1 = missile_type; + monster[i]._mVar2 = 0; + monster[i]._mVar3 = dam; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartSpAttack(int i) +{ + int md; + + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + md = M_GetDir(i); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + + monster[i]._mmode = MM_SATTACK; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mdir = md; + M_CheckEFlag(i); +} + +/*-----------------------------------------------------------------------* + * M_StartEat is the same as M_StartSpAttack except mdir isn't affected +**-----------------------------------------------------------------------*/ + +void M_StartEat(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], monster[i]._mdir); + + monster[i]._mmode = MM_SATTACK; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_ClearSquares(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + int mx = monster[i]._moldx; + int my = monster[i]._moldy; + int mt = -1 - i; + int mt2 = i + 1; + app_assert((DWORD)(mx+1) < MAXDUNX); + app_assert((DWORD)(my+1) < MAXDUNY); + for (int y = my-1; y <= my+1; y++) { + for (int x = mx-1; x <= mx+1; x++) { + if (dMonster[x][y] == mt || dMonster[x][y] == mt2) { + dMonster[x][y] = 0; + } + } + } + + dFlags[mx+1][my+0] &= BFMASK_MONSTLR; + dFlags[mx+0][my+1] &= BFMASK_MONSTLR; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_GetKnockback(int i) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + // knock back enemy if you can + int d = (monster[i]._mdir + 4) & 0x7; + if (DirOK(i, d)) { + M_ClearSquares(i); + monster[i]._moldx += offset_x[d]; + monster[i]._moldy += offset_y[d]; + NewMonsterAnim(i, monster[i].MType->Anims[MA_GOTHIT], monster[i]._mdir); + monster[i]._mmode = MM_GOTHIT; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mx = monster[i]._moldx; + monster[i]._my = monster[i]._moldy; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); + M_ClearSquares(i); + app_assert((DWORD)monster[i]._mx < MAXDUNX); + app_assert((DWORD)monster[i]._my < MAXDUNY); + dMonster[monster[i]._mx][monster[i]._my] = i + 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_StartHit(int i, int pnum, int dam) +{ + app_assert((DWORD)i < MAXMONSTERS); + app_assert(monster[i].MType != NULL); + if (pnum >= 0) monster[i].mWhoHit |= (1 << pnum); // Who damaged me + + if (pnum == myplr) { + extern void delta_monster_hp(int mi,long hp,BYTE bLevel); + delta_monster_hp(i,monster[i]._mhitpoints,currlevel); + NetSendCmdParam2(FALSE,CMD_MONSTDAMAGE,i,dam); + } + PlayEffect(i, MS_GOTHIT); + + // Sneaky demons always get hit + if (!EquivMonst(monster[i].MType->mtype, MT_SNEAK)) + // Other monsters only get hit if damage is severe + //if (((dam >> HP_SHIFT) < (monster[i].mLevel + 3)) && (!(plr[pnum]._pIFlags & IAF_KNOCKBACK))) + if ((dam >> HP_SHIFT) < (monster[i].mLevel + 3)) + return; + + // Set monster's enemy to be this player + if (pnum >= 0) { + monster[i]._menemy = pnum; + monster[i]._menemyx = plr[pnum]._pfutx; + monster[i]._menemyy = plr[pnum]._pfuty; + monster[i]._mFlags &= ~MFLAG_MID; + monster[i]._mdir = M_GetDir(i); + } + + // Check for special hits/teleports + if(monster[i].MType->mtype == MT_BLINK) { + M_Teleport(i); + } else { + if (EquivMonst(monster[i].MType->mtype, MT_NSCAV) || + monster[i].MType->mtype == MT_GRAVDG) { + // allow it to seek food again. + monster[i]._mgoal = MG_ATTACK; + monster[i]._mgoalvar1 = 0; + monster[i]._mgoalvar2 = 0; + } + } + if (monster[i]._mmode != MM_STONE) { + NewMonsterAnim(i, monster[i].MType->Anims[MA_GOTHIT], monster[i]._mdir); + monster[i]._mmode = MM_GOTHIT; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mx = monster[i]._moldx; + monster[i]._my = monster[i]._moldy; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); + M_ClearSquares(i); + dMonster[monster[i]._mx][monster[i]._my] = i + 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void M_DiabloDeath(int i, BOOL sendmsg) +{ + MonsterStruct *Monst = &monster[i]; + + // disable any other sounds from playing, for dramatic effect + #if !IS_VERSION(SHAREWARE) + PlaySFX(USFX_DIABLOD); + #endif + quests[Q_DIABLO]._qactive = QUEST_DONE; + if (sendmsg) NetSendCmdQuest(TRUE, Q_DIABLO); + sgbSaveSoundOn = gbSoundOn; + gbSoundOn = FALSE; + // disable player processing, so we can take over screen scrolling + gbProcessPlayers = FALSE; + // kill all other monsters on level + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for (int j = 0; j < nummonsters; j++) { + int k = monstactive[j]; + if (k != i && monster[i]._msquelch) { + NewMonsterAnim(k, monster[k].MType->Anims[MA_DEATH], monster[k]._mdir); + monster[k]._mmode = MM_DEATH; + monster[k]._mxoff = 0; + monster[k]._myoff = 0; + monster[k]._mVar1 = 0; + monster[k]._mx = monster[k]._moldx; + monster[k]._my = monster[k]._moldy; + monster[k]._mfutx = monster[k]._mx; + monster[k]._mfuty = monster[k]._my; + monster[k]._moldx = monster[k]._mx; + monster[k]._moldy = monster[k]._my; + M_CheckEFlag(k); + M_ClearSquares(k); + dMonster[monster[k]._mx][monster[k]._my] = k + 1; + } + } + AddLight(Monst->_mx, Monst->_my, 8); + DoVision(Monst->_mx, Monst->_my, 8, FALSE, TRUE); + // set up scrolling vars + int steps = max(abs(ViewX-Monst->_mx),abs(ViewY-Monst->_my)); + steps = min(20, steps); + + Monst->_mVar3 = ViewX << 16; // convert to fixed-point + Monst->_mVar4 = ViewY << 16; + // calculate scroll offsets + Monst->_mVar5 = (int)((double)(Monst->_mVar3 - (Monst->_mx << 16))/(double)steps); + Monst->_mVar6 = (int)((double)(Monst->_mVar4 - (Monst->_my << 16))/(double)steps); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M2MStartHit(int mid, int i, int dam) +{ + if ((DWORD)mid >= MAXMONSTERS) + app_fatal("Invalid monster %d getting hit by monster",mid); + if (monster[mid].MType == NULL) + app_fatal("Monster %d \"%s\" getting hit by monster: MType NULL",mid,monster[mid].mName); + + if (i >= 0) monster[i].mWhoHit |= (1 << i); // Who damaged me + + extern void delta_monster_hp(int mi,long hp, BYTE bLevel); + delta_monster_hp(mid, monster[mid]._mhitpoints, currlevel); + NetSendCmdParam2(FALSE, CMD_MONSTDAMAGE, mid, dam); + + PlayEffect(mid, MS_GOTHIT); + + // Sneaky demons always get hit + if (!EquivMonst(monster[mid].MType->mtype, MT_SNEAK)) + // Other monsters only get hit if damage is severe + if ((dam >> HP_SHIFT) < (monster[mid].mLevel + 3)) return; + + // face plr who hit me + if (i >= 0) monster[mid]._mdir = (monster[i]._mdir + 4) &0x07; + + // Check for special hits/teleports + if(monster[mid].MType->mtype == MT_BLINK) { + M_Teleport(mid); + } else { + if (EquivMonst(monster[mid].MType->mtype, MT_NSCAV) || + monster[mid].MType->mtype == MT_GRAVDG) { + // allow it to seek food again. + monster[mid]._mgoal = MG_ATTACK; + monster[mid]._mgoalvar1 = 0; + monster[mid]._mgoalvar2 = 0; + } + } + + if (monster[mid]._mmode != MM_STONE) { + if (monster[mid].MType->mtype != MT_GOLEM) { + NewMonsterAnim(mid, monster[mid].MType->Anims[MA_GOTHIT], monster[mid]._mdir); + monster[mid]._mmode = MM_GOTHIT; + } + + monster[mid]._mxoff = 0; + monster[mid]._myoff = 0; + monster[mid]._mx = monster[mid]._moldx; + monster[mid]._my = monster[mid]._moldy; + monster[mid]._mfutx = monster[mid]._mx; + monster[mid]._mfuty = monster[mid]._my; + monster[mid]._moldx = monster[mid]._mx; + monster[mid]._moldy = monster[mid]._my; + M_CheckEFlag(mid); + M_ClearSquares(mid); + dMonster[monster[mid]._mx][monster[mid]._my] = mid + 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MonstStartKill(int i, int pnum, BOOL sendmsg) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MonstStartKill: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("MonstStartKill: Monster %d \"%s\" MType NULL",i,monster[i].mName); + int md; + MonsterStruct *Monst = &monster[i]; + + // killer gets credit too, and divvy up exper + if (pnum >= 0) Monst->mWhoHit |= (1 << pnum); // Who killed me + + // rjs.patch1.start.1/23/97 - fixes golem giving exp when killed + //old. if (pnum < MAX_PLRS) AddPlrMonstExper(Monst->mLevel, Monst->mExp, Monst->mWhoHit); + if ((pnum < MAX_PLRS) && (i > MAX_PLRS)) AddPlrMonstExper(Monst->mLevel, Monst->mExp, Monst->mWhoHit); + // rjs.patch1.end.1/23/97 + + // Kill the monster (for myplr or other plr) + monstkills[Monst->MType->mtype]++; + Monst->_mhitpoints = 0; + SetRndSeed(Monst->_mRndSeed); + if (QuestStatus(Q_GARBUD) && (Monst->mName == UniqMonst[MU_GARBUD].mName)) + CreateTypeItem(Monst->_mx+1, Monst->_my+1, TRUE, IT_MACE, IMID_NONE, TRUE, FALSE); + else if (i > 3) SpawnItem(i, Monst->_mx, Monst->_my, sendmsg); + + if (Monst->MType->mtype == MT_DIABLO) { + M_DiabloDeath(i, TRUE); + } + else + PlayEffect(i, MS_DEATH); + + if (pnum >= 0) md = M_GetDir(i); + else md = Monst->_mdir; + Monst->_mdir = md; + NewMonsterAnim(i, Monst->MType->Anims[MA_DEATH], md); + Monst->_mmode = MM_DEATH; + Monst->_mxoff = 0; + Monst->_myoff = 0; + Monst->_mVar1 = 0; + Monst->_mx = Monst->_moldx; + Monst->_my = Monst->_moldy; + Monst->_mfutx = Monst->_mx; + Monst->_mfuty = Monst->_my; + Monst->_moldx = Monst->_mx; + Monst->_moldy = Monst->_my; + M_CheckEFlag(i); + M_ClearSquares(i); + dMonster[Monst->_mx][Monst->_my] = i + 1; + CheckQuestKill(i, sendmsg); + // Send Fallen Ones running in fear + M_FallenFear(Monst->_mx, Monst->_my); + // Acid demon emits acid pool + if(EquivMonst(Monst->MType->mtype, MT_NACID)) + AddMissile(Monst->_mx, Monst->_my, 0, 0, 0, MIT_ACIDPUD, MI_ENEMYPLR, i, Monst->_mint + 1, 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M2MStartKill(int i, int mid) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M2MStartKill: Invalid monster (attacker) %d",i); + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M2MStartKill: Invalid monster (killed) %d",mid); + if (monster[i].MType == NULL) + app_fatal("M2MStartKill: Monster %d \"%s\" MType NULL",mid,monster[mid].mName); + int md; + + void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel); + delta_kill_monster(mid, monster[mid]._mx, monster[mid]._my, currlevel); + NetSendCmdLocParam1(FALSE, CMD_MONSTDEATH, monster[mid]._mx, monster[mid]._my, mid); + + monster[mid].mWhoHit |= (1 << i); // Who killed me + if (i < MAX_PLRS) AddPlrMonstExper(monster[mid].mLevel, monster[mid].mExp, monster[mid].mWhoHit); + monstkills[monster[mid].MType->mtype]++; + monster[mid]._mhitpoints = 0; + SetRndSeed(monster[mid]._mRndSeed); + // @@@ needs to be fixed for multiplayer (death not synced, etc) + if (mid >= MAX_PLRS) SpawnItem(mid, monster[mid]._mx, monster[mid]._my, TRUE); + if (monster[mid].MType->mtype == MT_DIABLO) { + M_DiabloDeath(mid, TRUE); + } + else + PlayEffect(i, MS_DEATH); + PlayEffect(mid, MS_DEATH); + md = (monster[i]._mdir + 4) & 0x07; + if (monster[mid].MType->mtype == MT_GOLEM) md = 0; + monster[mid]._mdir = md; + NewMonsterAnim(mid, monster[mid].MType->Anims[MA_DEATH], md); + monster[mid]._mmode = MM_DEATH; + monster[mid]._mxoff = 0; + monster[mid]._myoff = 0; + monster[mid]._mx = monster[mid]._moldx; + monster[mid]._my = monster[mid]._moldy; + monster[mid]._mfutx = monster[mid]._mx; + monster[mid]._mfuty = monster[mid]._my; + monster[mid]._moldx = monster[mid]._mx; + monster[mid]._moldy = monster[mid]._my; + M_CheckEFlag(mid); + M_ClearSquares(mid); + dMonster[monster[mid]._mx][monster[mid]._my] = mid + 1; + CheckQuestKill(mid, TRUE); + + // Send Fallen Ones running in fear + M_FallenFear(monster[mid]._mx, monster[mid]._my); + // Acid demon emits acid pool + if(EquivMonst(monster[mid].MType->mtype, MT_NACID)) + AddMissile(monster[mid]._mx, monster[mid]._my, 0, 0, 0, MIT_ACIDPUD, MI_ENEMYPLR, mid, monster[mid]._mint + 1, 0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartKill(int i, int pnum) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_StartKill: Invalid monster %d",i); + // Send a message to everyone saying I killed the monster + if (myplr == pnum) { + void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel); + delta_kill_monster(i,monster[i]._mx,monster[i]._my,currlevel); + if (i != pnum) + NetSendCmdLocParam1(FALSE,CMD_MONSTDEATH,monster[i]._mx,monster[i]._my,i); + else + NetSendCmdLocParam1(FALSE,CMD_KILLGOLEM,monster[i]._mx,monster[i]._my,currlevel); + } + + MonstStartKill(i, pnum, TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_SyncStartKill(int i, int x, int y, int pnum) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_SyncStartKill: Invalid monster %d",i); + // Already dead? + if (monster[i]._mhitpoints == 0) return; + if (monster[i]._mmode == MM_DEATH) return; + + app_assert(pnum != myplr); + + if (!dMonster[x][y]) { + M_ClearSquares(i); + monster[i]._mx = x; + monster[i]._my = y; + monster[i]._moldx = x; + monster[i]._moldy = y; + } + MonstStartKill(i, pnum, FALSE); +// app_assert(dMonster[monster[i]._mx][monster[i]._my] == i+1 +// || dMonster[monster[i]._mx][monster[i]._my] == -(i+1)); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartFadein(int i, int md, BOOL backwards) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_StartFadein: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_StartFadein: Monster %d \"%s\" MType NULL",i,monster[i].mName); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + + monster[i]._mmode = MM_FADEIN; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); + monster[i]._mdir = md; + monster[i]._mFlags &= ~MFLAG_INVISIBLE; + if (backwards) + { + monster[i]._mFlags |= MFLAG_BACKWARDS; + monster[i]._mAnimFrame = monster[i]._mAnimLen; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartFadeout(int i, int md, BOOL backwards) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_StartFadeout: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_StartFadeout: Monster %d \"%s\" MType NULL",i,monster[i].mName); + NewMonsterAnim(i, monster[i].MType->Anims[MA_SPECIAL], md); + monster[i]._mmode = MM_FADEOUT; + monster[i]._mxoff = 0; + monster[i]._myoff = 0; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + M_CheckEFlag(i); + monster[i]._mdir = md; + if (backwards) + { + monster[i]._mFlags |= MFLAG_BACKWARDS; + monster[i]._mAnimFrame = monster[i]._mAnimLen; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_StartHeal(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_StartHeal: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_StartHeal: Monster %d \"%s\" MType NULL",i,monster[i].mName); + MonsterStruct *Monst = &monster[i]; + + Monst->_mAnimData = Monst->MType->Anims[MA_SPECIAL].Cels[Monst->_mdir]; + Monst->_mAnimFrame = Monst->MType->Anims[MA_SPECIAL].Frames; + Monst->_mFlags |= MFLAG_BACKWARDS; + Monst->_mmode = MM_HEAL; + Monst->_mVar1 = Monst->_mmaxhp / (16*(random(97, 5)+4)); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_ChangeLightOffset(int monst) +{ + if ((DWORD)monst >= MAXMONSTERS) + app_fatal("M_ChangeLightOffset: Invalid monster %d",monst); + int lx,ly; + int sign; + + lx = (monster[monst]._mxoff + (monster[monst]._myoff << 1)); + ly = ((monster[monst]._myoff << 1) - monster[monst]._mxoff); + + // Divide these values by 8, because lighting offsets have + // 8 subdivisions per tile. + if (lx < 0) + { + sign = -1; + lx = -lx; + } + else + sign = 1; + lx = lx >> 3; + lx *= sign; + + if (ly < 0) + { + sign = -1; + ly = -ly; + } + else + sign = 1; + ly = ly >> 3; + ly *= sign; + + ChangeLightOff(monster[monst].mlid, lx, ly); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoStand(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoStand: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoStand: Monster %d \"%s\" MType NULL",i,monster[i].mName); + MonsterStruct *Monst = &monster[i]; + + if (Monst->MType->mtype == MT_GOLEM) + Monst->_mAnimData = Monst->MType->Anims[MA_WALK].Cels[Monst->_mdir]; + else + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + if (Monst->_mAnimFrame == Monst->_mAnimLen) { + M_Enemy(i); + } + + Monst->_mVar2++; + return RUN_DONE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoWalk(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoWalk: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoWalk: Monster %d \"%s\" MType NULL",i,monster[i].mName); + int rv; + + if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) { + dMonster[monster[i]._mx][monster[i]._my] = 0; + monster[i]._mx += monster[i]._mVar1; + monster[i]._my += monster[i]._mVar2; + dMonster[monster[i]._mx][monster[i]._my] = i + 1; + if(monster[i]._uniqtype) + ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my); + M_StartStand(i, monster[i]._mdir); + rv = RUN_AGAIN; +// DaveMonstMap(FALSE, 0); + } else { + if (monster[i]._mAnimCnt == 0) { + monster[i]._mVar8++; + monster[i]._mVar6 += monster[i]._mxvel; + monster[i]._mVar7 += monster[i]._myvel; + monster[i]._mxoff = monster[i]._mVar6 >> 4; + monster[i]._myoff = monster[i]._mVar7 >> 4; + } + rv = RUN_DONE; + } + if(monster[i]._uniqtype) + M_ChangeLightOffset(i); + + return (rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoWalk2(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoWalk2: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoWalk2: Monster %d \"%s\" MType NULL",i,monster[i].mName); + int rv; + + if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) { + dMonster[monster[i]._mVar1][monster[i]._mVar2] = 0; + if(monster[i]._uniqtype) + ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my); + M_StartStand(i, monster[i]._mdir); + rv = RUN_AGAIN; +// DaveMonstMap(FALSE, 0); + } else { + if (monster[i]._mAnimCnt == 0) { + monster[i]._mVar8++; + monster[i]._mVar6 += monster[i]._mxvel; + monster[i]._mVar7 += monster[i]._myvel; + monster[i]._mxoff = monster[i]._mVar6 >> 4; + monster[i]._myoff = monster[i]._mVar7 >> 4; + } + rv = RUN_DONE; + } + if(monster[i]._uniqtype) + M_ChangeLightOffset(i); + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoWalk3(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoWalk3: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoWalk3: Monster %d \"%s\" MType NULL",i,monster[i].mName); + int rv; + + if (monster[i]._mVar8 == monster[i].MType->Anims[MA_WALK].Frames) { + dMonster[monster[i]._mx][monster[i]._my] = 0; + monster[i]._mx = monster[i]._mVar1; + monster[i]._my = monster[i]._mVar2; + dFlags[monster[i]._mVar4][monster[i]._mVar5] &= BFMASK_MONSTLR; + dMonster[monster[i]._mx][monster[i]._my] = i + 1; + if(monster[i]._uniqtype) + ChangeLightXY(monster[i].mlid, monster[i]._mx, monster[i]._my); + M_StartStand(i, monster[i]._mdir); + rv = RUN_AGAIN; +// DaveMonstMap(FALSE, 0); + } else { + if (monster[i]._mAnimCnt == 0) { + monster[i]._mVar8++; + monster[i]._mVar6 += monster[i]._mxvel; + monster[i]._mVar7 += monster[i]._myvel; + monster[i]._mxoff = monster[i]._mVar6 >> 4; + monster[i]._myoff = monster[i]._mVar7 >> 4; + } + rv = RUN_DONE; + } + if(monster[i]._uniqtype) + M_ChangeLightOffset(i); + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_TryM2MHit(int i, int mid, int hper, int mind, int maxd) +{ + int hit, dam; + BOOL ret; + + if ((DWORD)mid >= MAXMONSTERS) + app_fatal("M_TryM2MHit: Invalid monster %d",mid); + if (monster[mid].MType == NULL) + app_fatal("M_TryM2MHit: Monster %d \"%s\" MType NULL",mid,monster[mid].mName); + + if ((monster[mid]._mhitpoints >> HP_SHIFT) <= 0) return; + if (monster[mid].MType->mtype == MT_ILLWEAV && monster[mid]._mgoal == MG_RUN_AWAY) return; + + hit = random(4, 100); + if (monster[mid]._mmode == MM_STONE) hit = 0; + + if (CheckMonsterHit(mid, ret)) { + return; + } else { + if (hit < hper) { + dam = random(5, maxd - mind + 1) + mind; + dam = dam << HP_SHIFT; + + monster[mid]._mhitpoints -= dam; + //rjs - x2 stone dam fix - if (monster[mid]._mmode == MM_STONE) monster[mid]._mhitpoints -= dam; + if ((monster[mid]._mhitpoints >> HP_SHIFT) <= 0) { + if (monster[mid]._mmode == MM_STONE) { + M2MStartKill(i, mid); + monster[mid]._mmode = MM_STONE; + } else M2MStartKill(i, mid); + } else { + if (monster[mid]._mmode == MM_STONE) { + M2MStartHit(mid, i, dam); + monster[mid]._mmode = MM_STONE; + } else M2MStartHit(mid, i, dam); + } + } + } + return; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_TryH2HHit: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_TryH2HHit: Monster %d \"%s\" MType NULL",i,monster[i].mName); + + int hit, hper, tac; + long dam; + int dx, dy; + int blk, blkper, blkdir; + int mdam; + + if ((monster[i]._mFlags & MFLAG_MID) != 0) { + M_TryM2MHit(i, pnum, Hit, MinDam, MaxDam); + return; + } + + app_assert((DWORD)pnum < MAX_PLRS); + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) return; + if (plr[pnum]._pInvincible) return; + if ((plr[pnum]._pSpellFlags & SF_ETHER) != 0) return; + + dx = abs(monster[i]._mx - plr[pnum]._px); + dy = abs(monster[i]._my - plr[pnum]._py); + if ((dx < 2) && (dy < 2)) { + // Did I hit? + hit = random(98, 100); +#if CHEATS + if (simplecheat || cheatflag) hit = 1000; // TEMP! +#endif + //rjs tac = (byte)plr[pnum]._pArmorClass + plr[pnum]._pIAC + plr[pnum]._pIBonusAC; + tac = plr[pnum]._pIAC + plr[pnum]._pIBonusAC; + tac += (plr[pnum]._pDexterity / 5); + hper = 30 + Hit - tac + ((monster[i].mLevel - plr[pnum]._pLevel) << 1); + if (hper < 15) hper = 15; + if ((currlevel == 14) && (hper < 20)) hper = 20; + if ((currlevel == 15) && (hper < 25)) hper = 25; + if ((currlevel == 16) && (hper < 30)) hper = 30; + if (((plr[pnum]._pmode == PM_STAND) || (plr[pnum]._pmode == PM_ATTACK)) && (plr[pnum]._pBlockFlag)) blk = random(98, 100); + else blk = 100; + blkper = plr[pnum]._pBaseToBlk + plr[pnum]._pDexterity - ((monster[i].mLevel - plr[pnum]._pLevel) << 1); + if (blkper < 0) blkper = 0; + if (blkper > 100) blkper = 100; + if (hit < hper) { + if (blk < blkper) { + blkdir = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mx, monster[i]._my); + StartPlrBlock(pnum, blkdir); + } else { + + + if (monster[i].MType->mtype == MT_YZOMBIE && pnum == myplr) + { + + // find manashield + int k; + int mi; + int msi = -1; + for (k = 0; k < nummissiles; k++) { + mi = missileactive[k]; + if (missile[mi]._mitype == MIT_MANASHIELD && missile[mi]._misource == pnum) { + msi = mi; + } + } + + if(plr[pnum]._pMaxHP > 1 << HP_SHIFT ) + { + plr[pnum]._pMaxHP -= 1 << HP_SHIFT; + if(plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + if( msi >= 0 ) + missile[msi]._miVar1 = plr[pnum]._pHitPoints; + } + plr[pnum]._pMaxHPBase -= 1 << HP_SHIFT; + if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) { + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + if( msi >= 0 ) + missile[msi]._miVar2 = plr[pnum]._pHPBase; + } + } + + + } + + + + dam = (MaxDam - MinDam + 1) << HP_SHIFT; + dam = random(99, dam) + (MinDam << HP_SHIFT); + dam += (plr[pnum]._pIGetHit << HP_SHIFT); + if (dam < (1 << HP_SHIFT)) dam = (1 << HP_SHIFT); + if (pnum == myplr) { + plr[pnum]._pHitPoints -= dam; + plr[pnum]._pHPBase -= dam; + + if (plr[pnum]._pReflectCount > 0) + { + --plr[pnum]._pReflectCount; + // Reflect back with 20->30% of the damage. + mdam = static_cast(dam * (0.01 * (random(100, 10) + 20))); + monster[i]._mhitpoints -= mdam; + if (monster[i]._mhitpoints >> HP_SHIFT <= 0) { + M_StartKill (i, pnum); + } else { + M_StartHit(i, pnum, mdam); + } + } + } + + + + if (plr[pnum]._pIFlags & IAF_THORN) { + mdam = ((random (99, 3) + 1) << HP_SHIFT); + monster[i]._mhitpoints -= mdam; + if (monster[i]._mhitpoints >> HP_SHIFT <= 0) { + M_StartKill (i, pnum); + //(old) AddPlrExperience(pnum, monster[i].mLevel, monster[i].mExp); + //(new, but moved) AddPlrMonstExper(monster[i].mLevel, monster[i].mExp, monster[i].mWhoHit); + } else { + M_StartHit(i, pnum, mdam); + } + } + if (!(monster[i]._mFlags & IAF_MNOHEAL)) { + if (monster[i].MType->mtype == MT_SKING + && gbMaxPlayers != 1) + monster[i]._mhitpoints += dam; + } + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + } + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - plr[pnum]._pHitPoints = 0; + StartPlrKill(pnum, FALSE); + } else { + StartPlrHit(pnum, dam, FALSE); + + if (monster[i]._mFlags & MFLAG_KNOCKBACK) { + // make sure player is doing a hit animation + if (plr[pnum]._pmode != PM_GOTHIT) + StartPlrHit(pnum, 0, TRUE); + + // knock back enemy one square + int newx,newy,oldx,oldy; + + oldx = plr[pnum]._px; + oldy = plr[pnum]._py; + newx = oldx + offset_x[monster[i]._mdir]; + newy = oldy + offset_y[monster[i]._mdir]; + if(PosOkPlayer(pnum, newx, newy)) + { + plr[pnum]._px = newx; + plr[pnum]._py = newy; + FixPlayerLocation(pnum,plr[pnum]._pdir); + FixPlrWalkTags(pnum); + dPlayer[newx][newy] = pnum + 1; + SetPlayerOld(pnum); + } + } + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoAttack(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoAttack: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoAttack: Monster %d \"%s\" MType NULL",i,monster[i].mName); + if (monster[i].MType == NULL) + app_fatal("M_DoAttack: Monster %d \"%s\" MData NULL",i,monster[i].mName); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mAnimFrame == Monst->MData->mAFNum) { + M_TryH2HHit(i, Monst->_menemy, Monst->mHit, Monst->mMinDamage, Monst->mMaxDamage); + if (Monst->_mAi != AI_SNAKE) + PlayEffect(i, MS_ATTACK); + } + // Special code for Magma -- second punch + if (EquivMonst(Monst->MType->mtype, MT_NMAGMA) + && Monst->_mAnimFrame == 9) + { + M_TryH2HHit(i, Monst->_menemy, Monst->mHit+10, Monst->mMinDamage-2, Monst->mMaxDamage-2); + PlayEffect(i, MS_ATTACK); + } + // Special code for Storm -- second punch + if (EquivMonst(Monst->MType->mtype, MT_STORM) + && Monst->_mAnimFrame == 13) + { + M_TryH2HHit(i, Monst->_menemy, Monst->mHit-20, Monst->mMinDamage+4, Monst->mMaxDamage+4); + PlayEffect(i, MS_ATTACK); + } + // Special code for Snake -- play sound before attack frame + if (Monst->_mAi == AI_SNAKE && Monst->_mAnimFrame == 1) + PlayEffect(i, MS_ATTACK); + + if (Monst->_mAnimFrame == Monst->_mAnimLen) { + M_StartStand(i, Monst->_mdir); + return(RUN_AGAIN); + } else return (RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoRAttack(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoRAttack: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoRAttack: Monster %d \"%s\" MType NULL",i,monster[i].mName); + if (monster[i].MType == NULL) + app_fatal("M_DoRAttack: Monster %d \"%s\" MData NULL",i,monster[i].mName); + int multimissiles; + int mi; + + if (monster[i]._mAnimFrame == monster[i].MData->mAFNum) { + if (monster[i]._mVar1 != -1) + { + if (monster[i]._mVar1 == MIT_CBOLT) + multimissiles = 3; + else + multimissiles = 1; + for (mi = 0; mi < multimissiles; mi++) // special loop code to handle CBOLT, which must be cast 3 times + AddMissile(monster[i]._mx, monster[i]._my, monster[i]._menemyx, monster[i]._menemyy, monster[i]._mdir, monster[i]._mVar1, MI_ENEMYPLR, i, monster[i]._mVar2, 0); + } + PlayEffect(i, MS_ATTACK); + } + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return (RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoRSpAttack(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoRSpAttack: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoRSpAttack: Monster %d \"%s\" MType NULL",i,monster[i].mName); + if (monster[i].MType == NULL) + app_fatal("M_DoRSpAttack: Monster %d \"%s\" MData NULL",i,monster[i].mName); + if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2 && !monster[i]._mAnimCnt) { + AddMissile(monster[i]._mx, monster[i]._my, monster[i]._menemyx, monster[i]._menemyy, monster[i]._mdir, monster[i]._mVar1, MI_ENEMYPLR, i, monster[i]._mVar3, 0); + PlayEffect(i, MS_SATTACK); + } + + // special code for Mega demon -- hold attack animation frame + if (monster[i]._mAi == AI_MEGA && monster[i]._mAnimFrame == 3) + { + if (!monster[i]._mVar2++) + monster[i]._mFlags |= MFLAG_STILL; + else if (monster[i]._mVar2 == 15) + monster[i]._mFlags &= ~MFLAG_STILL; + } + + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return (RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoSAttack(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoSAttack: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoSAttack: Monster %d \"%s\" MType NULL",i,monster[i].mName); + if (monster[i].MType == NULL) + app_fatal("M_DoSAttack: Monster %d \"%s\" MData NULL",i,monster[i].mName); + if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2) + M_TryH2HHit(i, monster[i]._menemy, monster[i].mHit2, monster[i].mMinDamage2, monster[i].mMaxDamage2); + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoFadein(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoFadein: Invalid monster %d",i); + if ((monster[i]._mFlags & MFLAG_BACKWARDS && monster[i]._mAnimFrame == 1) + || (!(monster[i]._mFlags & MFLAG_BACKWARDS) && monster[i]._mAnimFrame == monster[i]._mAnimLen)) + { + M_StartStand(i, monster[i]._mdir); + monster[i]._mFlags &= ~MFLAG_BACKWARDS; + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoFadeout(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoFadeout: Invalid monster %d",i); + int mtype; + if ((monster[i]._mFlags & MFLAG_BACKWARDS && monster[i]._mAnimFrame == 1) + || (!(monster[i]._mFlags & MFLAG_BACKWARDS) && monster[i]._mAnimFrame == monster[i]._mAnimLen)) + { + app_assert(monster[i].MType != NULL); + mtype = monster[i].MType->mtype; + if (EquivMonst(mtype, MT_INCIN)) + monster[i]._mFlags &= ~MFLAG_BACKWARDS; + else + { + monster[i]._mFlags &= ~MFLAG_BACKWARDS; + monster[i]._mFlags |= MFLAG_INVISIBLE; + } + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoHeal(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoHeal: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (monster[i]._mFlags & MFLAG_NOHEAL) return RUN_DONE; + // Gargoyle turning back to stone + if(Monst->_mAnimFrame == 1) + { + Monst->_mFlags &= ~MFLAG_BACKWARDS; + Monst->_mFlags |= MFLAG_STILL; + if(Monst->_mhitpoints + Monst->_mVar1 < Monst->_mmaxhp) + Monst->_mhitpoints += Monst->_mVar1; + else + { + Monst->_mhitpoints = Monst->_mmaxhp; + Monst->_mFlags &= ~MFLAG_STILL; + Monst->_mmode = MM_SATTACK; + } + } + return RUN_DONE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +int M_DoTalk(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoTalk: Invalid monster %d",i); + int tren; + MonsterStruct *Monst = &monster[i]; + + M_StartStand(i, monster[i]._mdir); + Monst->_mgoal=MG_WAITTOTALK; + if (effect_is_playing(alltext[monster[i].mtalkmsg].sfxnr)) return RUN_DONE; + InitQTextMsg(monster[i].mtalkmsg); + if (monster[i].mName == UniqMonst[MU_GARBUD].mName) { + if (monster[i].mtalkmsg == TXT_GARB1) + quests[Q_GARBUD]._qactive = QUEST_NOTDONE; + quests[Q_GARBUD]._qlog = TRUE; + if (monster[i].mtalkmsg == TXT_GARB2) { + if(!(monster[i]._mFlags & MFLAG_DROP)) { + SpawnItem(i, monster[i]._mx+1, monster[i]._my+1, TRUE); + monster[i]._mFlags |= MFLAG_DROP; + } + } + } + if (monster[i].mName == UniqMonst[MU_ZHAR].mName) { + if (monster[i].mtalkmsg == TXT_ZHAR1) { + if(!(monster[i]._mFlags & MFLAG_DROP)) { + quests[Q_ZHAR]._qactive = QUEST_NOTDONE; + quests[Q_ZHAR]._qlog = TRUE; + CreateTypeItem(monster[i]._mx+1, monster[i]._my+1, FALSE, IT_MISC, IMID_BOOK, TRUE, FALSE); + monster[i]._mFlags |= MFLAG_DROP; + } + } + } + if (monster[i].mName == UniqMonst[MU_SNOTSPIL].mName) { + if ((monster[i].mtalkmsg == TXT_BOL1) && (!(monster[i]._mFlags & MFLAG_DROP))) { + app_assert(setpc_x != 0); + ObjChangeMap(setpc_x, setpc_y, setpc_x+(setpc_w>>1)+2, setpc_y+(setpc_h>>1)-2); + tren = TransVal; + TransVal = 9; + DRLG_MRectTrans(setpc_x, setpc_y, setpc_x+(setpc_w>>1)+4, setpc_y+(setpc_h>>1)); + TransVal = tren; + quests[Q_LTBANNER]._qvar1 = 2; + if (quests[Q_LTBANNER]._qactive == QUEST_NOTACTIVE) quests[Q_LTBANNER]._qactive = QUEST_NOTDONE; + monster[i]._mFlags |= MFLAG_DROP; + } + if (quests[Q_LTBANNER]._qvar1 < 2) { + sprintf(tempstr, "SS Talk = %i, Flags = %i", monster[i].mtalkmsg, monster[i]._mFlags); + app_fatal(tempstr); + } + } + if (monster[i].mName == UniqMonst[MU_LACHDA].mName) { + if (monster[i].mtalkmsg == TXT_VEIL1) { + quests[Q_VEIL]._qactive = QUEST_NOTDONE; + quests[Q_VEIL]._qlog = TRUE; + } + if ((monster[i].mtalkmsg == TXT_VEIL3) && (!(monster[i]._mFlags & MFLAG_DROP))) { + SpawnUnique(UID_STEELVEIL, monster[i]._mx+1, monster[i]._my+1); + monster[i]._mFlags |= MFLAG_DROP; + } + } + if (monster[i].mName == UniqMonst[MU_WARLORD].mName) { + app_assert(gbMaxPlayers == 1); + quests[Q_WARLORD]._qvar1 = 2; + } + if ((monster[i].mName == UniqMonst[MU_LAZARUS].mName) && (gbMaxPlayers != 1)) { + quests[Q_BETRAYER]._qvar1 = 6; + monster[i]._mgoal = MG_ATTACK; + monster[i]._msquelch = 255; + monster[i].mtalkmsg = 0; + } + return RUN_DONE; +} + +/*-----------------------------------------------------------------------* + * M_Teleport + * + * Teleports monster i to one of it's enemy's 8 adjacent squares. +**----------------------------------------------------------------------*/ + +void M_Teleport(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_Teleport: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + BOOL done = FALSE; + int mulx,muly; + int x,y; + int a,b; + int px,py; + + if (Monst->_mmode == MM_STONE) + return; + + px = Monst->_menemyx; + py = Monst->_menemyy; + + // randomize search direction + mulx = random(100,2)*2-1; + muly = random(100,2)*2-1; + for(a = -1; a <= 1 && !done; a++) + for(b = -1; b < 1 && !done; b++) + if(a || b) + { + x = px + a*mulx; + y = py + b*muly; + if(InBounds(x,y) + && x != Monst->_mx && y != Monst->_my) + if(PosOkMonst(i,x,y)) + done = TRUE; + } + if(done) + { + M_ClearSquares(i); + app_assert((DWORD)Monst->_mx < MAXDUNX); + app_assert((DWORD)Monst->_my < MAXDUNY); + dMonster[Monst->_mx][Monst->_my] = 0; + dMonster[x][y] = i+1; + // M_StartHit knocks monster back to oldx,oldy, so those are the members to set + Monst->_moldx = x; + Monst->_moldy = y; + Monst->_mdir = M_GetDir(i); + M_CheckEFlag(i); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoGotHit(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoGotHit: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoGotHit: Monster %d \"%s\" MType NULL",i,monster[i].mName); + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_UpdateLeader(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_UpdateLeader: Invalid monster %d",i); + int x,tmp; + + // check for pack leader + if(monster[i]._uniqtype && (UniqMonst[monster[i]._uniqtype-1].mUnqAttr & UN_STICK)) + // free the pack + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for(x = 0; x < nummonsters; x++) + { + if(monster[tmp=monstactive[x]].leaderflag == PACK_MEMBER + && monster[tmp].leader == i) + { + monster[tmp].leaderflag = 0; + } + } + // check for pack member + if(monster[i].leaderflag == PACK_MEMBER) + monster[monster[i].leader].packsize--; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void play_movie(const char * pszMovie,BOOL bAllowCancel); +extern BOOL gbRunGame; +extern BOOL deathflag; +extern BYTE gbDoEnding; + +void DoEnding() { + // tell other players to view victory + if (gbMaxPlayers > 1) SNetLeaveGame(SNET_EXIT_PLAYERWON); + + //SetCursor(NO_CURSOR); + //FullBlit(TRUE); + //PaletteFadeOut(FADE_FAST); + music_stop(); + + // give SNet some more time to field messages + if (gbMaxPlayers > 1) Sleep(1000); + + #if !IS_VERSION(SHAREWARE) + LONG lMusicVol; + BOOL bMusicOn; + if (plr[myplr]._pClass == CLASS_WARRIOR) play_movie("gendata\\DiabVic2.smk",FALSE); + else if (plr[myplr]._pClass == CLASS_SORCEROR) play_movie("gendata\\DiabVic1.smk",FALSE); + else play_movie("gendata\\DiabVic3.smk",FALSE); + play_movie("gendata\\Diabend.smk",FALSE); + + // turn music to full volume + bMusicOn = gbMusicOn; + gbMusicOn = TRUE; + lMusicVol = music_volume(VOLUME_READ); + music_volume(VOLUME_MAX); + music_start(MUSIC_L2); + + extern BOOL gbLoopMovie; + gbLoopMovie = TRUE; + play_movie("gendata\\loopdend.smk",TRUE); + gbLoopMovie = FALSE; + #endif + + //ClrDraw(); + //FullBlit(FALSE); + //PaletteFadeOut(FADE_FAST); + + // restore music volume + #if !IS_VERSION(SHAREWARE) + music_stop(); + music_volume(lMusicVol); + gbMusicOn = bMusicOn; + #endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PrepDoEnding() { + // enable sound again + gbSoundOn = sgbSaveSoundOn; + gbDoEnding = TRUE; + gbRunGame = FALSE; + deathflag = FALSE; + + app_assert((DWORD)myplr < MAX_PLRS); + plr[myplr].pDiabloKillLevel = max( + plr[myplr].pDiabloKillLevel, + (DWORD) gnDifficulty + 1 + ); + + for (int i = 0; i < MAX_PLRS; i++) { + plr[i]._pmode = PM_QUIT; + plr[i]._pInvincible = TRUE; + if (gbMaxPlayers > 1) { + if ((plr[i]._pHitPoints >> HP_SHIFT) == 0) + plr[i]._pHitPoints = 1 << HP_SHIFT; + if ((plr[i]._pMana >> MANA_SHIFT) == 0) + plr[i]._pMana = 1 << MANA_SHIFT; + } + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int M_DoDeath(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoDeath: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoDeath: Monster %d \"%s\" MType NULL",i,monster[i].mName); + monster[i]._mVar1++; + if (monster[i].MType->mtype == MT_DIABLO) { + ViewX += Sign(monster[i]._mx - ViewX); + ViewY += Sign(monster[i]._my - ViewY); + if (monster[i]._mVar1 == 140) { + PrepDoEnding(); + } + } else { + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + if (monster[i]._uniqtype == 0) + AddDead(monster[i]._mx, monster[i]._my, monster[i].MType->mdeadval, monster[i]._mdir); + else + AddDead(monster[i]._mx, monster[i]._my, monster[i]._udeadval, monster[i]._mdir); + app_assert(!(dFlags[monster[i]._mx+1][monster[i]._my] & BFLAG_MONSTLR) + && !(dFlags[monster[i]._mx][monster[i]._my+1] & BFLAG_MONSTLR)); + dMonster[monster[i]._mx][monster[i]._my] = 0; + monster[i]._mDelFlag = TRUE; + M_UpdateLeader(i); + } + } + return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoSpStand(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoSpStand: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoSpStand: Monster %d \"%s\" MType NULL",i,monster[i].mName); + if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2) { + PlayEffect(i, MS_SATTACK); + } + if (monster[i]._mAnimFrame == monster[i]._mAnimLen) { + M_StartStand(i, monster[i]._mdir); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +int M_DoDelay(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoDelay: Invalid monster %d",i); + if (monster[i].MType == NULL) + app_fatal("M_DoDelay: Monster %d \"%s\" MType NULL",i,monster[i].mName); + int md; + + md = M_GetDir(i); + monster[i]._mAnimData = monster[i].MType->Anims[MA_STAND].Cels[md]; + if (monster[i]._mAi == AI_LAZURUS) { + if ((monster[i]._mVar2 > 8) || (monster[i]._mVar2 < 0)) monster[i]._mVar2 = 8; + } + if(!monster[i]._mVar2--) + { + int tmp = monster[i]._mAnimFrame; + M_StartStand(i, monster[i]._mdir); // StartStand sets AnimFrame to 0 + monster[i]._mAnimFrame = tmp; // restore AnimFrame to avoid pop + // in case monster continues standing. + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_DoStone(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_DoStone: Invalid monster %d",i); + if (monster[i]._mhitpoints == 0) { + dMonster[monster[i]._mx][monster[i]._my] = 0; + monster[i]._mDelFlag = TRUE; + } + return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_WalkDir(int i, int md) +{ + int mwi; + + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_WalkDir: Invalid monster %d",i); + mwi = monster[i].MType->Anims[MA_WALK].Frames - 1; + + switch (md) { + case M_DIRU : + M_StartWalk(i, 0, -MWVel[mwi][1], -1, -1, M_DIRU); + break; + case M_DIRUR : + M_StartWalk(i, MWVel[mwi][1], -MWVel[mwi][0], 0, -1, M_DIRUR); + break; + case M_DIRR : + M_StartWalk3(i, MWVel[mwi][2], 0, -32, -16, 1, -1, 1, 0, M_DIRR); + break; + case M_DIRDR : + M_StartWalk2(i, MWVel[mwi][1], MWVel[mwi][0], -32, -16, 1, 0, M_DIRDR); + break; + case M_DIRD : + M_StartWalk2(i, 0, MWVel[mwi][1], 0, -32, 1, 1, M_DIRD); + break; + case M_DIRDL : + M_StartWalk2(i, -MWVel[mwi][1], MWVel[mwi][0], 32, -16, 0, 1, M_DIRDL); + break; + case M_DIRL : + M_StartWalk3(i, -MWVel[mwi][2], 0, 32, -16, -1, 1, 0, 1, M_DIRL); + break; + case M_DIRUL : + M_StartWalk(i, -MWVel[mwi][1], -MWVel[mwi][0], -1 ,0, M_DIRUL); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GroupUnity(int i) +{ + int leader; + int tmp; + int m; + + // + // IMPLEMENT GROUP COHESION + // + + if ((DWORD)i >= MAXMONSTERS) + app_fatal("GroupUnity: Invalid monster %d",i); + if(monster[i].leaderflag) + { + leader = monster[i].leader; + + // test if there's a wall between monst and pack leader + tmp = LineClearF(CheckNoSolid, monster[i]._mx, monster[i]._my, + monster[leader]._mfutx, monster[leader]._mfuty); + if(!tmp && monster[i].leaderflag == PACK_MEMBER) + { + // have to leave pack + monster[leader].packsize--; + monster[i].leaderflag = PACK_NOMEMBER; + } + else if(tmp && monster[i].leaderflag == PACK_NOMEMBER + && DIST(monster[i]._mx - monster[leader]._mfutx, + monster[i]._my - monster[leader]._mfuty, 4)) + { + // rejoin pack + monster[leader].packsize++; + monster[i].leaderflag = PACK_MEMBER; + } + } + + if(monster[i].leaderflag == PACK_MEMBER) + { + // make sure leader is active + if(monster[i]._msquelch > monster[leader]._msquelch) + { + monster[leader]._lastx = monster[i]._mx; + monster[leader]._lasty = monster[i]._my; + monster[leader]._msquelch = monster[i]._msquelch-1; + } + if (monster[leader]._mAi == AI_GARG && (monster[leader]._mFlags & MFLAG_STILL)) { + monster[leader]._mFlags &= ~MFLAG_STILL; + monster[leader]._mmode = MM_SATTACK; + } + } + else if(monster[i]._uniqtype && (UniqMonst[monster[i]._uniqtype-1].mUnqAttr & UN_STICK)) + { + // make sure all of pack is activated + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for(m = 0; m < nummonsters; m++) + { + if(monster[tmp=monstactive[m]].leaderflag == PACK_MEMBER + && monster[tmp].leader == i) + { + if(monster[i]._msquelch > monster[tmp]._msquelch) + { + monster[tmp]._lastx = monster[i]._mx; + monster[tmp]._lasty = monster[i]._my; + monster[tmp]._msquelch = monster[i]._msquelch-1; + } + if (monster[tmp]._mAi == AI_GARG && (monster[tmp]._mFlags & MFLAG_STILL)) { + monster[tmp]._mFlags &= ~MFLAG_STILL; + monster[tmp]._mmode = MM_SATTACK; + } + } + } + } + // END OF GROUP COHESION +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_CallWalk(int i, int md) +{ + int mdtemp = md; + BOOL ok = FALSE; + ok = DirOK(i,md); + + if(random(101,2)) + ok = ok || DirOK(i, md = left[mdtemp]) || DirOK(i, md = right[mdtemp]); + else + ok = ok || DirOK(i, md = right[mdtemp]) || DirOK(i, md = left[mdtemp]); + + if(random(102,2)) + ok = ok || DirOK(i, md = right[right[mdtemp]]) || DirOK(i, md = left[left[mdtemp]]); + else + ok = ok || DirOK(i, md = left[left[mdtemp]]) || DirOK(i, md = right[right[mdtemp]]); + + if(ok) + M_WalkDir(i, md); + + return ok; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_PathWalk(int i) +{ + char path[MAXPATHLEN]; + static const char plr2monst[] = { 0, 5, 3, 7, 1, 4, 6, 0, 2 }; + + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_PathWalk: Invalid monster %d",i); + CHECKFUNC1 Check = (monster[i]._mFlags & MFLAG_CHECKDOORS) ? PosOkMonst3:PosOkMonst; + + int pathlen = FindPath(Check, i, monster[i]._mx, monster[i]._my, + monster[i]._menemyx, monster[i]._menemyy, + path); + if(pathlen) { + M_CallWalk(i, plr2monst[path[0]]); + return TRUE; + } + else + return FALSE; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_CallWalk2(int i, int md) +{ + int mdtemp = md; + BOOL ok = FALSE; + ok = DirOK(i,md); + + if(random(101,2)) + ok = ok || DirOK(i, md = left[mdtemp]) || DirOK(i, md = right[mdtemp]); + else + ok = ok || DirOK(i, md = right[mdtemp]) || DirOK(i, md = left[mdtemp]); + + if(ok) + M_WalkDir(i, md); + + return ok; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_DumbWalk(int i, int md) +{ + BOOL ok; + + ok = DirOK(i,md); + + if(ok) + M_WalkDir(i, md); + return ok; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL M_RoundWalk(int i, int md, int &dir) +{ + int mdtemp; + BOOL ok = FALSE; + + if(dir) + md = left[left[md]]; + else + md = right[right[md]]; + mdtemp = md; + + ok = DirOK(i,md); + if(!ok) + { + // Note: The use of || below is a trick: the second condition is not evaluated + // (and therefore md is not re-set) if the first condition evaluates TRUE. + + if(dir) + ok = DirOK(i, md = right[mdtemp]) || DirOK(i, md = right[right[mdtemp]]); + else + ok = DirOK(i, md = left[mdtemp]) || DirOK(i, md = left[left[mdtemp]]); + } + + if(ok) + M_WalkDir(i,md); + else + { + // Note: The value of md here is set according to the second condition of the + // || operators above. Therefore, md is, by design, the direction towards + // the player. + dir = !dir; + ok = M_CallWalk(i,opposite[mdtemp]); + } + return ok; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void M_Face(int i) +{ + int md; + + if ((DWORD)i >= MAXMONSTERS) + app_fatal("M_Face: Invalid monster %d",i); + if (monster[i]._msquelch) { + md = M_GetDir(i); + monster[i]._mdir = md; + if (monster[i].MType == NULL) + app_fatal("M_Face: Monster %d \"%s\" MType NULL",i,monster[i].mName); + monster[i]._mAnimData = monster[i].MType->Anims[MA_STAND].Cels[md]; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Zombie(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Zombie: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int mx, my, md, v; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx -= Monst->_menemyx; + my -= Monst->_menemyy; + md = Monst->_mdir; + v = random(103,100); + + // Try attack + if (DIST(mx,my,2)) { + if (v < (10 + 2*Monst->_mint)) M_StartAttack(i); + } else { + // Try walk + if (v < (10 + 2*Monst->_mint)) { + // Check on distance from player + if(DIST(mx,my,4+2*Monst->_mint)) { + md = M_GetDir(i); + M_CallWalk(i, md); + } else { + if(random(104,100) < (20 + 2*Monst->_mint)) md = random(104,8); + M_DumbWalk(i, md); + } + } + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_SkelSd(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_SkelSd: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int mx, my, md; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + Monst->_mdir = md; + // Try attack + if (DIST(mx,my,2)) { + if (Monst->_mVar1 == MM_DELAY || random(105,100) < 20 + 2*Monst->_mint) + M_StartAttack(i); + else + M_StartDelay(i, random(105,10)+10 - 2*Monst->_mint); + } else { + // Try walk -- more likely to walk if already walking + if ((Monst->_mVar1 != MM_DELAY) && random(106,100) < 35 - 4*Monst->_mint) + M_StartDelay(i, random(106,10) + 15 - 2*Monst->_mint); + else + M_CallWalk(i, md); + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL MAI_Path(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Path: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if ((Monst->MType->mtype != MT_GOLEM) // golum always ready to walk + && ((!Monst->_msquelch) + || (Monst->_mmode != MM_STAND) + || !(Monst->_mgoal == MG_ATTACK + || Monst->_mgoal == MG_WALK_AROUND1 + || Monst->_mgoal == MG_ATTACK2) + || (Monst->_mx == 1 && Monst->_my == 0))) // inactive golum + return FALSE; + if (!LineClearF1(PosOkMonst2, i,Monst->_mx,Monst->_my,Monst->_menemyx,Monst->_menemyy) + || (Monst->_pathcount >= 5 && Monst->_pathcount < 8)) + { + // Try Opening Door + if (Monst->_mFlags & MFLAG_CHECKDOORS) + MonstCheckDoors(i); + + if (++Monst->_pathcount >= 5) + { + if (M_PathWalk(i)) + return TRUE; + } + else // don't want to zero pathcount + return FALSE; + } + + if (Monst->MType->mtype != MT_GOLEM) Monst->_pathcount = 0; //path count for golum handled in ai + return FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Snake(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Snake: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int fx, fy, mx, my, md, pnum; + char pattern[] = { +1, +1, 0, -1, -1 , 0}; + int tmp; + + pnum = Monst->_menemy; + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + Monst->_mdir = md; + // Try attack + if (DIST(mx,my,2)) { + if (Monst->_mVar1 == MM_DELAY + || Monst->_mVar1 == MM_MISSILE + || random(105,100) < 20 + 1*Monst->_mint) + M_StartAttack(i); + else + M_StartDelay(i, random(105,10)+10 - 1*Monst->_mint); + } + else if (DIST(mx,my,3) + && LineClearF1(PosOkMonst, i,Monst->_mx,Monst->_my,fx,fy) + && Monst->_mVar1 != MM_MISSILE) + { + // Launch snake + if (AddMissile(Monst->_mx, Monst->_my, fx,fy, md, MIT_RHINO, pnum, i, 0, 0) != -1) { + PlayEffect(i, MS_ATTACK); + dMonster[Monst->_mx][Monst->_my] = -(i+1); + Monst->_mmode = MM_MISSILE; + } + } else { + // Try walk -- more likely to walk if already walking + if ((Monst->_mVar1 != MM_DELAY) && random(106,100) < 35 - 2*Monst->_mint) + M_StartDelay(i, random(106,10) + 15 - 1*Monst->_mint); + else + { + md = Mod(md + pattern[Monst->_mgoalvar1], 8); + if (++Monst->_mgoalvar1 > 5) + Monst->_mgoalvar1 = 0; + tmp = Mod(md - Monst->_mgoalvar2, 8); + if (tmp > 0) + { + if (tmp < 4) + Monst->_mgoalvar2 = Mod(Monst->_mgoalvar2 + 1, 8); + else if (tmp == 4) + Monst->_mgoalvar2 = md; + else + Monst->_mgoalvar2 = Mod(Monst->_mgoalvar2 - 1, 8); + } + app_assert(Monst->_mgoalvar2 >= 0 && Monst->_mgoalvar2 < 8); + if (!M_DumbWalk(i, Monst->_mgoalvar2)) + M_CallWalk2(i, Monst->_mdir); + } + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Bat(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Bat: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int mx, my, md, v, pnum; + int fx, fy; + + pnum = Monst->_menemy; + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + Monst->_mdir = md; + v = random(107,100); + if(Monst->_mgoal == MG_RUN_AWAY) + { + if(!Monst->_mgoalvar1) + { + M_CallWalk(i, opposite[md]); + Monst->_mgoalvar1++; + } + else + { + if(random(108,2)) + M_CallWalk(i, left[md]); + else + M_CallWalk(i, right[md]); + Monst->_mgoal = MG_ATTACK; + } + } + else + { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + // Try attack + if ((Monst->MType->mtype == MT_GLOOM) + && (!DIST(mx,my,5) && v < 33 + 4*Monst->_mint) && + LineClearF1(PosOkMonst, i,Monst->_mx,Monst->_my,fx,fy)) + { + // Turn into missile + if (AddMissile(Monst->_mx, Monst->_my, fx, fy, md, MIT_RHINO, pnum, i, 0, 0) != -1) { + dMonster[Monst->_mx][Monst->_my] = -(i+1); + Monst->_mmode = MM_MISSILE; + } + } + else if (DIST(mx,my,2)) { + if (v < 8 + 4*Monst->_mint) + { + M_StartAttack(i); + + // After attacking, fly away + Monst->_mgoal = MG_RUN_AWAY; + Monst->_mgoalvar1 = 0; + + if(Monst->MType->mtype == MT_FAMILIAR) { + // Note: arg 5 is a signal to the lightning code. + // The code checks if this is != to arg 1, and if so, checks for + // collision. Normally, collision is only checked for when + // lightning moves, but in this case it won't move! + AddMissile(Monst->_menemyx, Monst->_menemyy, Monst->_menemyx+1, 0, -1, MIT_LIGHTNING, MI_ENEMYPLR, i, random(109,10)+1, 0); + } + } + } else { + // Try walk + if ((Monst->_mVar2 > 20 && v < (13 + Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (63 + Monst->_mint))) { + M_CallWalk(i, md); + } + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_SkelBow(int i) +{ + int mx, my, md, fx, fy; + BOOL walking = FALSE; + int v; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_SkelBow: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = M_GetDir(i); + Monst->_mdir = md; + + // Try walk + v = random(110,100); + if (DIST(mx,my,4) + && + ((Monst->_mVar2 > 20 + && v < 13 + 2*Monst->_mint) + || (WALKMODE(Monst->_mVar1) + && Monst->_mVar2 == 0 + && v < 63 + 2*Monst->_mint))) + { + walking = M_DumbWalk(i, opposite[md]); + } + fx = Monst->_menemyx; + fy = Monst->_menemyy; + if (!walking && (random(110,100) < 3+2*Monst->_mint) && + LineClear(Monst->_mx,Monst->_my,fx, fy)) + { + // Try attack + M_StartRAttack(i,MIT_ARROW,4); + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Fat(int i) +{ + int mx, my, md, v; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Fat: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = M_GetDir(i); + Monst->_mdir = md; + v = random(111,100); + // Try attack + if (DIST(mx,my,2)) { + if (v < (15 + 4*Monst->_mint)) M_StartAttack(i); + else if (v < (20 + 4*Monst->_mint)) M_StartSpAttack(i); + } else { + // Try walk + if ((Monst->_mVar2 > 20 && v < (20 + 4*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (70 + 4*Monst->_mint))) { + M_CallWalk(i, md); + } + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Sneak(int i) +{ + int mx, my, md, v; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Sneak: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int dist; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + if (dLight[mx][my] != lightmax) { + + mx -= Monst->_menemyx; + my -= Monst->_menemyy; + md = M_GetDir(i); + + dist = 5 - Monst->_mint; + + // If gothit, run away + if(Monst->_mVar1 == MM_GOTHIT) + { + Monst->_mgoal = MG_RUN_AWAY; + Monst->_mgoalvar1 = 0; // count run_away moves + } + // if far away enough, stop running away + else if(!DIST(mx,my,dist+3) || Monst->_mgoalvar1 > 8) + { + Monst->_mgoal = MG_ATTACK; + Monst->_mgoalvar1 = 0; + } + + if(Monst->_mgoal == MG_RUN_AWAY) + { + // Use special "owner location", i.e. the location of the player + // according to the computer which owns the player + // This is an attempt to reduce the amount of monster warping due to + // diverging paths on different computers + if (Monst->_mFlags & MFLAG_MID) + md = GetDirection(Monst->_mx, Monst->_my, + plr[Monst->_menemy]._pownerx, plr[Monst->_menemy]._pownery); + md = opposite[md]; + if(Monst->MType->mtype == MT_UNSEEN) + { + if(random(112,2)) + md = left[md]; + else + md = right[md]; + } + } + + Monst->_mdir = md; + + v = random(112,100); + // become visible + if(DIST(mx,my,dist) && (Monst->_mFlags & MFLAG_INVISIBLE)) + M_StartFadein(i,md,FALSE); + // become invisible + else if(!DIST(mx,my,dist+1) && !(Monst->_mFlags & MFLAG_INVISIBLE)) + M_StartFadeout(i,md,TRUE); + // Try attack + else if ((Monst->_mgoal == MG_RUN_AWAY) + || + ( !DIST(mx,my,2) + && + ((Monst->_mVar2 > 20 && v < (14 + 4*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (64 + 4*Monst->_mint))))) { + // Try walk + Monst->_mgoalvar1++; + M_CallWalk(i, md); + } + // face dir + if (Monst->_mmode == MM_STAND) + { + if (DIST(mx,my,2) && (v < (10 + 4*Monst->_mint))) { + M_StartAttack(i); + } + else + { + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Fireman(int i) +{ + int mx, my, md, v, pnum; + int fx, fy; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Fireman: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND && Monst->_msquelch) { + pnum = Monst->_menemy; + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = M_GetDir(i); + + if(Monst->_mgoal == MG_ATTACK) + { + if(LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Launch monster missile + if (AddMissile(Monst->_mx, Monst->_my, fx,fy, md, MIT_FIREMAN, pnum, i, 0, 0) != -1) { + Monst->_mmode = MM_MISSILE; + Monst->_mgoal = MG_ATTACK2; + Monst->_mgoalvar1 = 0; + } + } + } + else if(Monst->_mgoal == MG_ATTACK2) + { + if(Monst->_mgoalvar1 == 3) + { + Monst->_mgoal = MG_ATTACK; + M_StartFadeout(i,md,TRUE); + } + else if(LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Try attack + M_StartRAttack(i,MIT_KRULL,4); + Monst->_mgoalvar1++; + } + else + { + M_StartDelay(i, random(112,10) + 5); + Monst->_mgoalvar1++; + } + } + + else if(Monst->_mgoal == MG_RUN_AWAY) + { + M_StartFadein(i, md,FALSE); + Monst->_mgoal = MG_ATTACK2; + } + + Monst->_mdir = md; + + v = random(112,100); + + if(Monst->_mmode == MM_STAND) + { + if(DIST(mx,my,2) && Monst->_mgoal == MG_ATTACK) + { + M_TryH2HHit(i, monster[i]._menemy, monster[i].mHit, monster[i].mMinDamage, monster[i].mMaxDamage); + Monst->_mgoal = MG_RUN_AWAY; + if(!M_CallWalk(i, opposite[md])) + { + M_StartFadein(i, md,FALSE); + Monst->_mgoal = MG_ATTACK2; + } + } + else + { + if(!M_CallWalk(i, md)) + { + if(Monst->_mgoal == MG_ATTACK || Monst->_mgoal == MG_RUN_AWAY) + { + M_StartFadein(i, md, FALSE); + Monst->_mgoal = MG_ATTACK2; + } + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Fallen(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Fallen: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int x,y; + int xpos,ypos; + int m; + int rad; + int mx,my; + int aitype; + + if (Monst->_mgoal == MG_ATTACK2) + { + if(Monst->_mgoalvar1) + Monst->_mgoalvar1--; + else + Monst->_mgoal = MG_ATTACK; + } + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) + { + if (Monst->_mgoal == MG_RUN_AWAY && Monst->_mgoalvar1-- == 0) + { + Monst->_mgoal = MG_ATTACK; + M_StartStand(i, opposite[Monst->_mdir]); + } + if (Monst->_mAnimFrame == Monst->_mAnimLen) { + if (random(113,4) == 0) + { + // start 'dance' + if (!(monster[i]._mFlags & MFLAG_NOHEAL)) { + M_StartSpStand(i, Monst->_mdir); + if(Monst->_mmaxhp - (2*Monst->_mint+2) >= Monst->_mhitpoints) + Monst->_mhitpoints += 2*Monst->_mint+2; + else + Monst->_mhitpoints = Monst->_mmaxhp; + } + // set surrounding monsters into relentless attack + rad = 2*Monst->_mint+4; + for(y = -rad; y <= rad; y++) + { + for(x = -rad; x <= rad; x++) + { + xpos = Monst->_mx + x; + ypos = Monst->_my + y; + if(InBounds(x,y)) + { + m = dMonster[xpos][ypos]; + if(m > 0) + { + m--; + aitype = monster[m]._mAi; + if(aitype == AI_FALLEN) + { + monster[m]._mgoal = MG_ATTACK2; + // Set # frames for crazy attack mode + monster[m]._mgoalvar1 = (2*Monst->_mint+7)*15; + } + } + } + } + } + } + } + else if (Monst->_mgoal == MG_RUN_AWAY) + { + M_CallWalk(i,Monst->_mdir); + } + else if (Monst->_mgoal == MG_ATTACK2) + { + // attack relentlessly + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if(DIST(mx,my,2)) + M_StartAttack(i); + else + M_CallWalk(i, M_GetDir(i)); + } + else + MAI_SkelSd(i); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Cleaver(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Cleaver: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int mx, my, md; + + if (Monst->_mmode == MM_STAND && Monst->_msquelch) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + Monst->_mdir = md; + // If close, attack + if (DIST(mx,my,2)) { + M_StartAttack(i); + } else { + // Try walk + M_CallWalk(i, md); + } + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Round(int i, BOOL special) +{ + int mx, my, md, v; + int fx, fy, dist; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Round: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(114,100); + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,4) && !random(115,4))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(116,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if( (Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) + { + Monst->_mgoal = MG_ATTACK; + } + else if(!M_RoundWalk(i,md,Monst->_mgoalvar2)) + M_StartDelay(i, random(125,10)+10); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (DIST(mx,my,2)) { + if (v < 23 + 2*Monst->_mint) + { + Monst->_mdir = md; + if(special && Monst->_mhitpoints < (Monst->_mmaxhp >> 1) && random(117,2)) + M_StartSpAttack(i); + else + M_StartAttack(i); + } + } + else if ((Monst->_mVar2 > 20 && v < (28 + 2*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (78 + 2*Monst->_mint))) { + M_CallWalk(i, md); + } + } + + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +void MAI_GoatMc(int i) +{ + MAI_Round(i, TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Ranged(int i, int missile_type, BOOL special) +{ + int fx, fy, mx, my, md; + BOOL walking = FALSE; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Ranged: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + if (Monst->_msquelch == 255 + || monster[i]._mFlags & MFLAG_MID) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = M_GetDir(i); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + Monst->_mdir = md; + + if (Monst->_mVar1 == MM_RATTACK) + { + // pause after each arrow + M_StartDelay(i, random(118,20)); + } + else if (DIST(mx,my,4) && random(119,100) < 70 + 10*Monst->_mint) + { + // retreat + walking = M_CallWalk(i, opposite[md]); + } + if (Monst->_mmode == MM_STAND) + { + if (LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Try attack + if(special) + M_StartRSpAttack(i,missile_type,4); + else + M_StartRAttack(i,missile_type,4); + } + else + // face dir + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } + } + else if(Monst->_msquelch // 0 < msquelch < 255 + && !(monster[i]._mFlags & MFLAG_MID)) // temp. golum fix + { + mx = Monst->_lastx; + my = Monst->_lasty; + md = GetDirection(Monst->_mx, Monst->_my, mx, my); + + M_CallWalk(i, md); + } + } +} + +void MAI_GoatBow(int i) +{ + MAI_Ranged(i,MIT_ARROW, FALSE); +} + +void MAI_Succ(int i) +{ + MAI_Ranged(i,MIT_FLARE, FALSE); +} + +void MAI_AcidUniq(int i) +{ + MAI_Ranged(i,MIT_ACID, TRUE); +} + +/*-----------------------------------------------------------------------* + * MAI_Scav + * + * MG_EAT is the scavenger's eat goal. + * _mgoalvar1 : =0 ==> no goal dest + * >0 ==> _mgoalvar1-1 is x coord of food + * _mgoalvar2 : _mgoalvar2-1 is y coord of food + * +**-----------------------------------------------------------------------*/ + +void MAI_Scav(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Scav: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int x,y; + BOOL done = FALSE; + + if (Monst->_mmode == MM_STAND) { + if(Monst->_mhitpoints < (Monst->_mmaxhp >> 1) && Monst->_mgoal != MG_EAT) + { + if(monster[i].leaderflag) + { + // leave pack permanently + monster[monster[i].leader].packsize--; + monster[i].leaderflag = 0; + } + Monst->_mgoal = MG_EAT; + Monst->_mgoalvar3 = 10; + } + + if (Monst->_mgoal == MG_EAT && Monst->_mgoalvar3) + { + Monst->_mgoalvar3--; + + // Are we on top of food? + if (dDead[Monst->_mx][Monst->_my]) + { + M_StartEat(i); + if (!(monster[i]._mFlags & MFLAG_NOHEAL)) { + int maxhp = (Monst->MType->mMaxHP << HP_SHIFT); + if (gbMaxPlayers == 1) + maxhp >>= 1; + + int healamt = maxhp >> 3; + + sprintf(infostr, "Eating, hp = %d, amt = %d, max = %d", + Monst->_mhitpoints >> HP_SHIFT, + healamt >> HP_SHIFT, + maxhp >> HP_SHIFT); + ClearPanel(); + AddPanelString(infostr, TEXT_CENTER); + + Monst->_mhitpoints += healamt; + + // by eating, the monster can get to its species maximum + // in hit points... + if (Monst->_mhitpoints > maxhp) + Monst->_mhitpoints = maxhp; + if (Monst->_mmaxhp < Monst->_mhitpoints) + Monst->_mmaxhp = Monst->_mhitpoints; + + if (Monst->_mgoalvar3 <= 0 || // done eating + Monst->_mhitpoints == maxhp) + { + dDead[Monst->_mx][Monst->_my] = 0; // monster buried + } + } +// if ((Monst->_mhitpoints) >= (Monst->_mmaxhp >> 1) + (Monst->_mmaxhp >> 2)) + if ((Monst->_mhitpoints) == (Monst->_mmaxhp)) + { + Monst->_mgoal = MG_ATTACK; + Monst->_mgoalvar1 = 0; + Monst->_mgoalvar2 = 0; + } + } + else + { + if (!Monst->_mgoalvar1) + { + // Find food! + // Randomize search direction + if(random(120,2)) + { + for(y = -4; y <= 4 && !done; y++) + for(x = -4; x <= 4 && !done; x++) + if(InBounds(x,y)) + done = dDead[Monst->_mx + x][Monst->_my + y] + && LineClearF(CheckNoSolid, Monst->_mx,Monst->_my,Monst->_mx + x,Monst->_my + y); + x--; + y--; + } + else + { + for(y = 4; y >= -4 && !done; y--) + for(x = 4; x >= -4 && !done; x--) + if(InBounds(x,y)) + done = dDead[Monst->_mx + x][Monst->_my + y] + && LineClearF(CheckNoSolid,Monst->_mx,Monst->_my,Monst->_mx + x,Monst->_my + y); + x++; + y++; + } + if(done) + { + // Note: 1 is added to the following vars because + // 0 is reserved as a flag meaning undefined. + Monst->_mgoalvar1 = Monst->_mx + x +1; + Monst->_mgoalvar2 = Monst->_my + y +1; + } + } + if(Monst->_mgoalvar1) + { + x = Monst->_mgoalvar1 - 1; + y = Monst->_mgoalvar2 - 1; + Monst->_mdir = GetDirection(Monst->_mx, Monst->_my, x, y); + M_CallWalk(i, Monst->_mdir); + } + } + } + else +// if(Monst->_mmode == MM_STAND) + // none of the above cases applied, so resort to default behavior + MAI_SkelSd(i); + } +} + + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Garg(int i) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Garg: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int mx, my; + int md; + + mx = Monst->_mx - Monst->_lastx; + my = Monst->_my - Monst->_lasty; + md = M_GetDir(i); + if(Monst->_msquelch && (Monst->_mFlags & MFLAG_STILL)) + { + M_Enemy(i); + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + + if(DIST(mx,my,Monst->_mint+2)) + Monst->_mFlags &= ~MFLAG_STILL; + } + else if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) + { + if(Monst->_mhitpoints < (Monst->_mmaxhp >> 1)) + { + // run away to get healed. + Monst->_mgoal = MG_RUN_AWAY; + } + if(Monst->_mgoal == MG_RUN_AWAY) + { + if(DIST(mx,my,Monst->_mint+2)) + { + if(!M_CallWalk(i,opposite[md])) + Monst->_mgoal = MG_ATTACK; + } + else + { + Monst->_mgoal = MG_ATTACK; + M_StartHeal(i); + + } + } + MAI_Round(i, FALSE); + } +} + + +/*-----------------------------------------------------------------------* + * MAI_RoundRanged + * + * Similar to MAI_Round, but does ranged attacks (throws lava) + * +**-----------------------------------------------------------------------*/ + +void MAI_RoundRanged(int i, int missile_type, BOOL checkdoors, int dam, BOOL lessmissiles) +{ + int fx, fy, mx, my, md, v, pnum; + int dist; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_RoundRanged: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + pnum = Monst->_menemy; + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(checkdoors && Monst->_msquelch < 255) + MonstCheckDoors(i); + + // Using random(10000) instead of random(100) for increased precision + // for small numbers, e.g. random(100) < (5 >> 1) + v = random(121,10000); + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,3) && !random(122,4 << lessmissiles))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(123,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if(Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + { + Monst->_mgoal = MG_ATTACK; + } + else if(v < (500 + 500*Monst->_mint) >> lessmissiles + && + LineClear(Monst->_mx, Monst->_my, fx, fy)) + { + // Missile Attack + M_StartRSpAttack(i,missile_type,dam); + } + else + M_RoundWalk(i,md,Monst->_mgoalvar2); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (((!DIST(mx,my,3) && v < (1000 + 500*Monst->_mint) >> lessmissiles) + || + v < (500 + 500*Monst->_mint) >> lessmissiles) + && + LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Missile Attack + M_StartRSpAttack(i,missile_type,dam); + } + else if (DIST(mx,my,2)) + { + if (v < 6000 + 1000*Monst->_mint) + { + Monst->_mdir = md; + M_StartAttack(i); + } + } + else if (((v=random(124,100)) < (5000 + 1000*Monst->_mint)) + || + (WALKMODE(Monst->_mVar1) + && + Monst->_mVar2 == 0 && v < (8000 + 1000*Monst->_mint))) + { + M_CallWalk(i, md); + } + } + + // face dir + if (Monst->_mmode == MM_STAND) + M_StartDelay(i, random(125,10)+5); + } +} + +void MAI_Magma(int i) +{ + MAI_RoundRanged(i, MIT_MAGMABALL, TRUE,4, FALSE); +} + +void MAI_Storm(int i) +{ + MAI_RoundRanged(i, MIT_THINLIGHTCTRL, TRUE,4, FALSE); +} + +void MAI_Acid(int i) +{ + MAI_RoundRanged(i, MIT_ACID, FALSE,4, TRUE); +} + + +void MAI_Diablo(int i) +{ + MAI_RoundRanged(i, MIT_DIABAPOCA, FALSE, 40, FALSE); +} + +void MAI_RR2(int i, int mistype, int dam) +{ + int fx, fy, mx, my, md, v, pnum; + int dist; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_RR2: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if (!DIST(mx, my, 5)) + MAI_SkelSd(i); + else if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + pnum = Monst->_menemy; + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(121,100); + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || !DIST(mx,my,3)) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(123,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + Monst->_mgoalvar3 = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if(Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + { + Monst->_mgoal = MG_ATTACK; + } + else if (v < 80 + 5*Monst->_mint) + M_RoundWalk(i,md,Monst->_mgoalvar2); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (((!DIST(mx,my,3) && v < 10 + 5*Monst->_mint) + || + v < 5 + 5*Monst->_mint + || Monst->_mgoalvar3 == MG_WALK_AROUND1) + && + LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Missile Attack + M_StartRSpAttack(i,mistype,dam); + } + else if (DIST(mx,my,2)) + { + if (random(124,100) < 40 + 10*Monst->_mint) + { + Monst->_mdir = md; + if (random(124, 2)) + M_StartAttack(i); + else + // Missile Attack + M_StartRSpAttack(i,mistype,dam); + } + } + else if (((v=random(124,100)) < (50 + 10*Monst->_mint)) + || + (WALKMODE(Monst->_mVar1) + && + Monst->_mVar2 == 0 && v < (80 + 10*Monst->_mint))) + { + M_CallWalk(i, md); + } + Monst->_mgoalvar3 = MG_ATTACK; + } + + if (Monst->_mmode == MM_STAND) + M_StartDelay(i, random(125,10)+5); + } +} + +void MAI_Mega(int i) +{ + MAI_RR2(i, MIT_FLAMEC,0); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MAI_Golum(int i) +{ + int ok, j, k, mid; + int mx, my, md; + BOOL have_enemy; + + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Golum: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if ((Monst->_mx == 1) && (Monst->_my == 0)) return; + + if (Monst->_mmode == MM_DEATH) return; + if (Monst->_mmode == MM_SPSTAND) return; + if (Monst->_mmode >= MM_WALK && Monst->_mmode <= MM_WALK3) return; + + if (!(monster[i]._mFlags & MFLAG_MID)) M_Enemy(i); + + have_enemy = !(Monst->_mFlags & MFLAG_NOENEMY); + + if (Monst->_mmode != MM_ATTACK) { + mx = Monst->_mx - monster[Monst->_menemy]._mfutx; + my = Monst->_my - monster[Monst->_menemy]._mfuty; + md = GetDirection(Monst->_mx, Monst->_my, monster[Monst->_menemy]._mx, monster[Monst->_menemy]._my); + Monst->_mdir = md; + + if (DIST(mx,my,2) && have_enemy) { + Monst->_menemyx = monster[Monst->_menemy]._mx; + Monst->_menemyy = monster[Monst->_menemy]._my; + if(!monster[Monst->_menemy]._msquelch) { + monster[Monst->_menemy]._msquelch = 255; + monster[Monst->_menemy]._lastx = Monst->_mx; + monster[Monst->_menemy]._lasty = Monst->_my; + for (j = 0; j < 5; j++) { + for (k = 0; k < 5; k++) { + mid = dMonster[monster[i]._mx - 2 + k][monster[i]._my - 2 + j]; + if (mid > 0) monster[mid]._msquelch = 255; + } + } + } + M_StartAttack(i); + } else { + if (!have_enemy || + !MAI_Path(i)) { + Monst->_pathcount++; + if (Monst->_pathcount > 8) Monst->_pathcount = 5; + ok = M_CallWalk(i, plr[i]._pdir); + if (ok == FALSE) { + md = (md - 1) & 0x07; + for (j = 0; j < 8 && ok == FALSE; j++) { + md = (md + 1) & 0x07; + ok = DirOK(i, md); + } + if (ok) + M_WalkDir(i, md); + } + } + } + } + +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_SkelKing(int i) +{ + int fx, fy, mx, my, md, v; + int dist; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_SkelKing: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + int nx,ny; // location for new skel spawn + int skel; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(126,100); + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,3) && !random(127,4))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(128,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if( (Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) + { + Monst->_mgoal = MG_ATTACK; + } + else if(!M_RoundWalk(i,md,Monst->_mgoalvar2)) + M_StartDelay(i, random(125,10)+10); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (gbMaxPlayers == 1 // no spawning in multi-player + && ((!DIST(mx,my,3) && v < 35 + 4*Monst->_mint) + || v < 6) + && + LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Spawn new Skeleton + nx = Monst->_mx + offset_x[md]; + ny = Monst->_my + offset_y[md]; + if (PosOkMonst(i,nx,ny) && nummonsters < MAXMONSTERS) + { +// skel = AddMonster(nx, ny, md, 1, TRUE); +// M_StartSpStand(skel, md); + skel = M_SpawnSkel(nx, ny, md); + M_StartSpStand(i, md); + } + } + else if (DIST(mx,my,2)) { + if (v < 20 + Monst->_mint) + { + Monst->_mdir = md; + M_StartAttack(i); + } + } + else if (((v=random(129,100)) < (25 + Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (75 + Monst->_mint))) { + M_CallWalk(i, md); + } + else + M_StartDelay(i, random(130,10)+10); + } + + // face dir + if (Monst->_mmode == MM_STAND) + Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Rhino(int i) +{ + int fx, fy, mx, my, md, v; + int dist; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Rhino: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND && Monst->_msquelch) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(131,100); + if (DIST(mx,my,2)) { + Monst->_mgoal = MG_ATTACK; + } + else if(Monst->_mgoal == MG_WALK_AROUND1 + || (!DIST(mx,my,5) && random(132,4))) + { + if(Monst->_mgoal != MG_WALK_AROUND1) + { + Monst->_mgoalvar1 = 0; // reset counter + // Pick direction to walk around player + Monst->_mgoalvar2 = random(133,2); + } + + // MODE CHANGE: Walk Around player + + Monst->_mgoal = MG_WALK_AROUND1; + + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if( (Monst->_mgoalvar1++ >= (dist << 1)) + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) + { + Monst->_mgoal = MG_ATTACK; + } + else if(!M_RoundWalk(i,md,Monst->_mgoalvar2)) + M_StartDelay(i, random(125,10)+10); + } + if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if ((!DIST(mx,my,5) && v < 43 + 2*Monst->_mint) && + LineClearF1(PosOkMonst, i,Monst->_mx,Monst->_my,fx,fy)) + { + // Launch rhino + if (AddMissile(Monst->_mx, Monst->_my, fx,fy, md, MIT_RHINO, Monst->_menemy, i, 0, 0) != -1) { + if (Monst->MData->snd_special) PlayEffect(i, MS_SATTACK); + dMonster[Monst->_mx][Monst->_my] = -(i+1); + Monst->_mmode = MM_MISSILE; + } + } + else if (DIST(mx,my,2)) { + if (v < 28 + 2*Monst->_mint) + { + Monst->_mdir = md; + M_StartAttack(i); + } + } + else if (((v=random(134,100)) < (33 + 2*Monst->_mint)) || + (WALKMODE(Monst->_mVar1) && + Monst->_mVar2 == 0 && v < (83 + 2*Monst->_mint))) { + M_CallWalk(i, md); + } + else + M_StartDelay(i, random(135,10)+10); + } + + // face dir + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[Monst->_mdir]; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Counselor(int i) +{ + int fx, fy, mx, my, md, v; + int dist; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Counselor: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + static const BYTE counsmiss[] = { MIT_FIREBOLT, MIT_CBOLT, MIT_LIGHTCTRL, MIT_FIREBALL }; + + if ((Monst->_mmode == MM_STAND) && (Monst->_msquelch)) { + fx = Monst->_menemyx; + fy = Monst->_menemyy; + mx = Monst->_mx - fx; + my = Monst->_my - fy; + md = GetDirection(Monst->_mx, Monst->_my, Monst->_lastx, Monst->_lasty); + + if(Monst->_msquelch < 255) + MonstCheckDoors(i); + + v = random(121,100); + if (Monst->_mgoal == MG_RUN_AWAY) + { + if (Monst->_mgoalvar1++ > 3) + { + Monst->_mgoal = MG_ATTACK; + M_StartFadein(i, md, TRUE); + } + else + M_CallWalk(i, opposite[md]); + } + else if(Monst->_mgoal == MG_WALK_AROUND1) + { + // Calculate distance to player + dist = max(abs(mx),abs(my)); + + if (DIST(mx,my,2) + || Monst->_msquelch != 255 + || dTransVal[Monst->_mx][Monst->_my] + != dTransVal[fx][fy]) { + Monst->_mgoal = MG_ATTACK; + M_StartFadein(i, md, TRUE); + } + else if(Monst->_mgoalvar1++ >= (dist << 1) + && DirOK(i,md)) + { + Monst->_mgoal = MG_ATTACK; + M_StartFadein(i, md, TRUE); + } + else + M_RoundWalk(i,md,Monst->_mgoalvar2); + } + else if(Monst->_mgoal == MG_ATTACK) + { + // Try attack + if (DIST(mx,my,2)) + { + Monst->_mdir = md; + if (Monst->_mhitpoints < (Monst->_mmaxhp >> 1)) + { + // run away! + Monst->_mgoal = MG_RUN_AWAY; + Monst->_mgoalvar1 = 0; + M_StartFadeout(i, md, FALSE); + } + else if (Monst->_mVar1 == MM_DELAY || random(105,100) < 20 + 2*Monst->_mint) + { + M_StartRAttack(i,-1,0); + AddMissile(monster[i]._mx, monster[i]._my, 0, 0, monster[i]._mdir, MIT_FLASH, MI_ENEMYPLR, i, 4, 0); + AddMissile(monster[i]._mx, monster[i]._my, 0, 0, monster[i]._mdir, MIT_FLASH2, MI_ENEMYPLR, i, 4, 0); + } + else + M_StartDelay(i, random(105,10)+10 - 2*Monst->_mint); + } + else if (v < 50 + 5*Monst->_mint + && LineClear(Monst->_mx,Monst->_my,fx,fy)) + { + // Missile Attack + M_StartRAttack(i, counsmiss[Monst->_mint], random(77, Monst->mMaxDamage - Monst->mMinDamage + 1) + Monst->mMinDamage); + } + else if (random(124, 100) < 30) + { + Monst->_mgoal = MG_WALK_AROUND1; + Monst->_mgoalvar1 = 0; + M_StartFadeout(i, md, FALSE); + } + else + M_StartDelay(i, random(105,10)+10 - 2*Monst->_mint); + } + + // face dir + if (Monst->_mmode == MM_STAND) + M_StartDelay(i, random(125,10)+5); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Garbud(int i) +{ + int mx, my, md; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Garbud: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if ((Monst->mtalkmsg < TXT_GARB4) && (Monst->mtalkmsg > (TXT_GARB1-1)) && !(dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->mtalkmsg++; + Monst->_mgoal = MG_TALK; + } + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_GARB4) && !(effect_is_playing(USFX_GARBUD4)) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + } + if ((Monst->_mgoal == MG_ATTACK) || (Monst->_mgoal == MG_WALK_AROUND1)) { + MAI_Round(i, TRUE); + } + monster[i]._mdir = md; + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Zhar(int i) +{ + int mx, my, md, dist; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Zhar: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if ((Monst->mtalkmsg == TXT_ZHAR1) && !(dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->mtalkmsg++; + Monst->_mgoal = MG_TALK; + } + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + dist = max(abs(mx), abs(my)); + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_ZHAR2) && !(effect_is_playing(USFX_ZHAR2)) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + } + if ((Monst->_mgoal == MG_ATTACK) || (Monst->_mgoal == MG_RUN_AWAY) || (Monst->_mgoal == MG_WALK_AROUND1)) { + MAI_Counselor(i); + } + monster[i]._mdir = md; + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_SnotSpil(int i) +{ + int mx, my, md, pnum; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_SnotSpil: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + pnum = Monst->_menemy; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if ((Monst->mtalkmsg == TXT_BOL1) && !(dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->mtalkmsg = TXT_BOL2; + Monst->_mgoal = MG_TALK; + } + if ((Monst->mtalkmsg == TXT_BOL2) && (quests[Q_LTBANNER]._qvar1 == 3)) { + Monst->mtalkmsg = 0; + Monst->_mgoal = MG_ATTACK; + } + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_BOL3) && !(effect_is_playing(USFX_SNOT3)) && (Monst->_mgoal == MG_WAITTOTALK)) { + int i = plr[pnum]._pvid; + ObjChangeMap(setpc_x, setpc_y, setpc_x + setpc_w + 1, setpc_y + setpc_h + 1); + quests[Q_LTBANNER]._qvar1 = 3; + extern void RedoPlayerVision(); + RedoPlayerVision(); + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + if (quests[Q_LTBANNER]._qvar1 == 3) { + if ((Monst->_mgoal == MG_ATTACK) || (Monst->_mgoal == MG_ATTACK2)) { + MAI_Fallen(i); + } + } + + } + monster[i]._mdir = md; + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Lazurus(int i) +{ + int mx, my, md; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Lazurus: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if (gbMaxPlayers == 1) { + if ((Monst->mtalkmsg == TXT_VB1) && (Monst->_mgoal == MG_TALK) + && (plr[myplr]._px == 35) && (plr[myplr]._py == 46)) { + PlayInGameMovie("gendata\\fprst3.smk"); + Monst->_mmode = MM_TALK; + quests[Q_BETRAYER]._qvar1 = 5; + } + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_VB1) && !(effect_is_playing(USFX_LAZ1)) && (Monst->_mgoal == MG_WAITTOTALK)) { + ObjChangeMapResync(1, 18, 20, 24); + extern void RedoPlayerVision(); + RedoPlayerVision(); + quests[Q_BETRAYER]._qvar1 = 6; + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + } + if (gbMaxPlayers != 1) { + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_VB1) && (Monst->_mgoal == MG_TALK) && (quests[Q_BETRAYER]._qvar1 <= 3)) { + Monst->_mmode = MM_TALK; + } + #endif + } + + } + if ((Monst->_mgoal == MG_ATTACK) || (Monst->_mgoal == MG_RUN_AWAY) || (Monst->_mgoal == MG_WALK_AROUND1)) { + MAI_Counselor(i); + } + monster[i]._mdir = md; + if ((Monst->_mmode == MM_STAND) || (Monst->_mmode == MM_TALK)) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Lazhelp(int i) +{ + int mx, my, md; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Lazhelp: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if (gbMaxPlayers == 1) { + if (quests[Q_BETRAYER]._qvar1 <= 5) + Monst->_mgoal = MG_TALK; + else { + Monst->_mgoal = MG_ATTACK; + Monst->mtalkmsg = 0; + } + } else if (gbMaxPlayers != 1) { + Monst->_mgoal = MG_ATTACK; + } + } + if (Monst->_mgoal == MG_ATTACK) { + MAI_Succ(i); + } + monster[i]._mdir = md; + } if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Lachdanan(int i) +{ + int mx, my, md, pnum; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Lachdanan: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + pnum = Monst->_menemy; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_VEIL1) && !(dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->mtalkmsg++; + Monst->_mgoal = MG_TALK; + } + #endif + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + #if !IS_VERSION(SHAREWARE) + if ((Monst->mtalkmsg == TXT_VEIL3) && !(effect_is_playing(USFX_LACH3)) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->mtalkmsg = 0; + quests[Q_VEIL]._qactive = QUEST_DONE; + M_StartKill(i, -1); + } + #endif + } + monster[i]._mdir = md; + if (Monst->_mmode == MM_STAND) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MAI_Warlord(int i) +{ + int mx, my, md; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("MAI_Warlord: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + + if (Monst->_mmode == MM_STAND) { + mx = Monst->_mx; + my = Monst->_my; + md = M_GetDir(i); + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + mx = Monst->_mx - Monst->_menemyx; + my = Monst->_my - Monst->_menemyy; + if ((Monst->mtalkmsg == TXT_WARLRD1) && (Monst->_mgoal == MG_TALK)) { + Monst->_mmode = MM_TALK; + } + + #if !IS_VERSION(SHAREWARE) + BOOL effect_is_playing(int nSFX); + if ((Monst->mtalkmsg == TXT_WARLRD1) && !(effect_is_playing(USFX_WARLRD1)) && (Monst->_mgoal == MG_WAITTOTALK)) { + Monst->_mgoal = MG_ATTACK; + Monst->_msquelch = 255; + Monst->mtalkmsg = 0; + } + #endif + } + if (Monst->_mgoal == MG_ATTACK) { + MAI_SkelSd(i); + } + monster[i]._mdir = md; + if ((Monst->_mmode == MM_STAND) || (Monst->_mmode == MM_TALK)) Monst->_mAnimData = Monst->MType->Anims[MA_STAND].Cels[md]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DeleteMonsterList() +{ + int i, mi; + + // pseudo delete dead golems + for (i = 0; i < 4; i++) { + if (monster[i]._mDelFlag) { + monster[i]._mx = 1; + monster[i]._my = 0; + monster[i]._mfutx = 0; + monster[i]._mfuty = 0; + monster[i]._moldx = 0; + monster[i]._moldy = 0; + monster[i]._mDelFlag = FALSE; + } + } + + i = 4; // this is to skip the golems + app_assert((DWORD)nummonsters <= MAXMONSTERS); + while (i < nummonsters) { + mi = monstactive[i]; + if (monster[mi]._mDelFlag) { + DeleteMonster(i); + i = 0; + } else i++; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ProcessMonsters () +{ + int i, mi; + int raflag; + int mx, my; + MonsterStruct *Monst; + int oldmode; + + DeleteMonsterList(); + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for (i = 0; i < nummonsters; i++) { + mi = monstactive[i]; + Monst = &monster[mi]; + raflag = RUN_DONE; + + // Try and run same AI's as best as possible in multiplayer + if (gbMaxPlayers > 1) { + SetRndSeed(Monst->_mAISeed); + Monst->_mAISeed = GetRndSeed(); + } + + // Turn regen + if (!(monster[mi]._mFlags & MFLAG_NOHEAL)) { + if ((Monst->_mhitpoints < Monst->_mmaxhp) && ((Monst->_mhitpoints >> HP_SHIFT) > 0)) { + if (Monst->mLevel > 1) + Monst->_mhitpoints += Monst->mLevel >> 1; + else + Monst->_mhitpoints += Monst->mLevel; + } + } + // Check if just activating + mx = Monst->_mx; + my = Monst->_my; + if ((dFlags[mx][my] & BFLAG_MONSTACTIVE) && (Monst->_msquelch == 0)) { + #if !IS_VERSION(SHAREWARE) + if (Monst->MType->mtype == MT_CLEAVER) { + //if (gbMaxPlayers == 1) PlayInGameMovie("gendata\\fbutch3.smk"); + PlaySFX(USFX_CLEAVER); + } + #endif + } + + // Check if monster's enemy + if (Monst->_mFlags & MFLAG_MID) { + if ((DWORD)Monst->_menemy >= MAXMONSTERS) + app_fatal("Illegal enemy monster %d for monster \"%s\"",Monst->_menemy,Monst->mName); + Monst->_menemyx = Monst->_lastx = monster[Monst->_menemy]._mfutx; + Monst->_menemyy = Monst->_lasty = monster[Monst->_menemy]._mfuty; + } else { + // Deal with keeping a monster active for a while after its visibility flag + // goes off + if ((DWORD)Monst->_menemy >= MAX_PLRS) + app_fatal("Illegal enemy player %d for monster \"%s\"",Monst->_menemy,Monst->mName); + Monst->_menemyx = plr[Monst->_menemy]._pfutx; + Monst->_menemyy = plr[Monst->_menemy]._pfuty; + if (dFlags[mx][my] & BFLAG_MONSTACTIVE) { + Monst->_msquelch = 255; + Monst->_lastx = plr[Monst->_menemy]._pfutx; + Monst->_lasty = plr[Monst->_menemy]._pfuty; + } else if(Monst->_msquelch && (Monst->_mAi != MT_DIABLO)) Monst->_msquelch--; + } + + do { + // Run Monster's AI + + // Try Path Mode + if (Monst->_mFlags & MFLAG_PATH) + { + if (!MAI_Path(mi)) + AiProc[Monst->_mAi](mi); + } + else + AiProc[Monst->_mAi](mi); + + // Run Monster Mode + switch (oldmode = Monst->_mmode) { + case MM_STAND : + raflag = M_DoStand(mi); + break; + case MM_WALK : + raflag = M_DoWalk(mi); + break; + case MM_WALK2 : + raflag = M_DoWalk2(mi); + break; + case MM_WALK3: + raflag = M_DoWalk3(mi); + break; + case MM_ATTACK: + raflag = M_DoAttack(mi); + break; + case MM_RATTACK: + raflag = M_DoRAttack(mi); + break; + case MM_GOTHIT: + raflag = M_DoGotHit(mi); + break; + case MM_DEATH: + raflag = M_DoDeath(mi); + break; + case MM_SATTACK: + raflag = M_DoSAttack(mi); + break; + case MM_FADEIN: + raflag = M_DoFadein(mi); + break; + case MM_FADEOUT: + raflag = M_DoFadeout(mi); + break; + case MM_SPSTAND: + raflag = M_DoSpStand(mi); + break; + case MM_RSATTACK: + raflag = M_DoRSpAttack(mi); + break; + case MM_DELAY: + raflag = M_DoDelay(mi); + break; + case MM_MISSILE: + raflag = RUN_DONE; + break; + case MM_STONE: + raflag = M_DoStone(mi); + break; + case MM_HEAL: + raflag = M_DoHeal(mi); + break; + case MM_TALK: + raflag = M_DoTalk(mi); + break; + } + +/* for (int mm = 0; mm < nummonsters; mm++) { + int mmi = monstactive[mm]; + app_assert(monster[mmi]._mDelFlag + || monster[mmi]._mmode == MM_MISSILE + || !monster[mmi]._msquelch + || mmi < 4 + || dMonster[monster[mmi]._mx][monster[mmi]._my] == mmi+1 + || dMonster[monster[mmi]._mx][monster[mmi]._my] == -(mmi+1)); + }*/ + + if(raflag != RUN_DONE) + GroupUnity(mi); + +// if (Monst->_msquelch) DaveMonstMap(FALSE, 0); + + } while (raflag != RUN_DONE); + + // Animate Monster + if (Monst->_mmode != MM_STONE) { + Monst->_mAnimCnt++; + if (!(Monst->_mFlags & MFLAG_STILL)) + { + if (Monst->_mAnimCnt >= Monst->_mAnimDelay) { + Monst->_mAnimCnt = 0; + if(Monst->_mFlags & MFLAG_BACKWARDS) + { + Monst->_mAnimFrame--; + if (!Monst->_mAnimFrame) Monst->_mAnimFrame = Monst->_mAnimLen; + } + else + { + Monst->_mAnimFrame++; + if (Monst->_mAnimFrame > Monst->_mAnimLen) Monst->_mAnimFrame = 1; + } + } + } + } + } + DeleteMonsterList(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreeMonsterGFX() +{ + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (int monst = 0; monst < nummtypes; monst++) { + int mtype = Monsters[monst].mtype; + for (int anim = 0; anim < MAX_ANIMTYPE; anim++) { + if(!(animletter[anim] == 's' && !monsterdata[mtype].has_special)) { + DiabloFreePtr(Monsters[monst].Anims[anim].CMem); + } + } + } + + IFreeMissileGFX(); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL DirOK(int i, int mdir) +{ + long fx, fy; + int tmp; + + if ((DWORD)i >= MAXMONSTERS) + app_fatal("DirOK: Invalid monster %d",i); + fx = monster[i]._mx + offset_x[mdir]; + fy = monster[i]._my + offset_y[mdir]; + if(! InBounds(fx,fy)) + return FALSE; + + if (! PosOkMonst(i, fx, fy)) + return FALSE; + + if (mdir == M_DIRR) { + if (SolidLoc(fx+0,fy+1)) return FALSE; + if (dFlags[fx+0][fy+1] & BFLAG_MONSTLR) return FALSE; + } + else if(mdir == M_DIRL) { + if (SolidLoc(fx+1,fy+0)) return FALSE; + if (dFlags[fx+1][fy+0] & BFLAG_MONSTLR) return FALSE; + } + else if (mdir == M_DIRU) { + if (SolidLoc(fx+1,fy+0)) return FALSE; + if (SolidLoc(fx+0,fy+1)) return FALSE; + } + else if (mdir == M_DIRD) { + if (SolidLoc(fx-1,fy+0)) return FALSE; + if (SolidLoc(fx+0,fy-1)) return FALSE; + } + + // check for group cohesion + if(monster[i].leaderflag == PACK_MEMBER) { + // make sure monster is close to leader + return DIST( + fx-monster[monster[i].leader]._mfutx, + fy-monster[monster[i].leader]._mfuty, + 4 + ); + } + + if (monster[i]._uniqtype && (UniqMonst[monster[i]._uniqtype-1].mUnqAttr & UN_STICK)) + { + int mcount = 0; + for (int x = fx - 3; x <= fx + 3; x++) { + for (int y = fy - 3; y <= fy + 3; y++) { + if (! InBounds(x,y)) continue; + + if((tmp = dMonster[x][y]) < 0) tmp = -tmp; + if (tmp != 0) tmp--; + app_assert(tmp >= 0); + + if (monster[tmp].leaderflag == PACK_MEMBER && + monster[tmp].leader == i && + monster[tmp]._mfutx == x && + monster[tmp]._mfuty == y) mcount++; + } + } + + return (mcount == monster[i].packsize); + } + + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PosOkMissile(int x, int y) +{ + return !(nMissileTable[dPiece[x][y]] || (dFlags[x][y] & BFLAG_MONSTLR)); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL CheckNoSolid(int x, int y) +{ + return !nSolidTable[dPiece[x][y]]; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +BOOL LineClearF(CHECKFUNC Clear, int x1, int y1, int x2, int y2) +{ + int md; + BOOL done = FALSE; + + do + { + md = GetDirection(x1,y1,x2,y2); + x1 += offset_x[md]; + y1 += offset_y[md]; + done = !(*Clear)(x1, y1); + } while(!done && !(x1==x2 && y1==y2)); + return (x1 == x2) && (y1 == y2); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL LineClearF(CHECKFUNC Clear, int x1, int y1, int x2, int y2) +{ + // Bresenham line algorithm + // See Foley/van Dam, "Computer Graphics: Principles and Practice" + + int dx,dy; + int d; // test variable + int dincH; // Horizontal increment for d + int dincD; // Diagonal increment for d + int xincD,yincD; // Diagonal increments for minor axis + int xorg, yorg; + BOOL done = FALSE; + int tmp; + + xorg = x1; + yorg = y1; + + dx = x2 - x1; + dy = y2 - y1; + if(abs(dx) > abs(dy)) + { + // X is the major axis + if(dx < 0) + { + // swap endpoints + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + + dx = -dx; + dy = -dy; + } + if(dy > 0) + { + // pos. slope + d = 2*dy - dx; + dincH = 2*dy; + dincD = 2*(dy - dx); + yincD = 1; + } + else + { + // neg. slope + d = 2*dy + dx; + dincH = 2*dy; + dincD = 2*(dy + dx); + yincD = -1; + } + +// done = (x1 != xorg || y1 != yorg) && !(*Clear)(x1, y1); + + while(!done && !(x1 == x2 && y1 == y2)) + { + if((d <= 0) ^ (yincD < 0)) + { + d += dincH; + } + else + { + d += dincD; + y1 += yincD; + } + x1++; + done = (x1 != xorg || y1 != yorg) && !(*Clear)(x1, y1); + } + } + else + { + // Y is the major axis + if(dy < 0) + { + // swap endpoints + tmp = y1; + y1 = y2; + y2 = tmp; + tmp = x1; + x1 = x2; + x2 = tmp; + + dy = -dy; + dx = -dx; + } + if(dx > 0) + { + // pos. slope + d = 2*dx - dy; + dincH = 2*dx; + dincD = 2*(dx - dy); + xincD = 1; + } + else + { + // neg. slope + d = 2*dx + dy; + dincH = 2*dx; + dincD = 2*(dx + dy); + xincD = -1; + } + +// done = (y1 != yorg || x1 != xorg) && !(*Clear)(x1, y1); + + while(!done && !(y1 == y2 && x1 == x2)) + { + if((d <= 0) ^ (xincD < 0)) + { + d += dincH; + } + else + { + d += dincD; + x1 += xincD; + } + y1++; + done = (y1 != yorg || x1 != xorg) && !(*Clear)(x1, y1); + } + } + + return x1 == x2 && y1 == y2; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL LineClear(int x1, int y1, int x2, int y2) +{ + return LineClearF(PosOkMissile, x1, y1, x2, y2); +} + +/*-----------------------------------------------------------------------* + * LineClearF1 + * + * This is exactly the same routine as LineClearF, except its Check + * routine requires an extra argument +**-----------------------------------------------------------------------*/ + +BOOL LineClearF1(CHECKFUNC1 Clear, int monst, int x1, int y1, int x2, int y2) +{ + // Bresenham line algorithm + // See Foley/van Dam, "Computer Graphics: Principles and Practice" + + int dx,dy; + int d; // test variable + int dincH; // Horizontal increment for d + int dincD; // Diagonal increment for d + int xincD,yincD; // Diagonal increments for minor axis + int xorg, yorg; + BOOL done = FALSE; + int tmp; + + xorg = x1; + yorg = y1; + + dx = x2 - x1; + dy = y2 - y1; + if(abs(dx) > abs(dy)) + { + // X is the major axis + if(dx < 0) + { + // swap endpoints + tmp = x1; + x1 = x2; + x2 = tmp; + tmp = y1; + y1 = y2; + y2 = tmp; + + dx = -dx; + dy = -dy; + } + if(dy > 0) + { + // pos. slope + d = 2*dy - dx; + dincH = 2*dy; + dincD = 2*(dy - dx); + yincD = 1; + } + else + { + // neg. slope + d = 2*dy + dx; + dincH = 2*dy; + dincD = 2*(dy + dx); + yincD = -1; + } + + while(!done && !(x1 == x2 && y1 == y2)) + { + if((d <= 0) ^ (yincD < 0)) + { + d += dincH; + } + else + { + d += dincD; + y1 += yincD; + } + x1++; + done = (x1 != xorg || y1 != yorg) && !Clear(monst, x1, y1); + } + } + else + { + // Y is the major axis + if(dy < 0) + { + // swap endpoints + tmp = y1; + y1 = y2; + y2 = tmp; + tmp = x1; + x1 = x2; + x2 = tmp; + + dy = -dy; + dx = -dx; + } + if(dx > 0) + { + // pos. slope + d = 2*dx - dy; + dincH = 2*dx; + dincD = 2*(dx - dy); + xincD = 1; + } + else + { + // neg. slope + d = 2*dx + dy; + dincH = 2*dx; + dincD = 2*(dx + dy); + xincD = -1; + } + + while(!done && !(y1 == y2 && x1 == x2)) + { + if((d <= 0) ^ (xincD < 0)) + { + d += dincH; + } + else + { + d += dincD; + x1 += xincD; + } + y1++; + done = (y1 != yorg || x1 != xorg) && !Clear(monst, x1, y1); + } + } + + return x1 == x2 && y1 == y2; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncMonsterAnim(int m) +{ + int dir; + + if ((DWORD)m >= MAXMONSTERS) + app_fatal("SyncMonsterAnim: Invalid monster %d",m); + app_assert((DWORD)monster[m]._mMTidx < MAX_LVLMTYPES); + monster[m].MType = &Monsters[monster[m]._mMTidx]; + monster[m].MData = Monsters[monster[m]._mMTidx].MData; + if(monster[m]._uniqtype) + monster[m].mName = UniqMonst[monster[m]._uniqtype-1].mName; + else + monster[m].mName = monster[m].MData->mName; + + dir = monster[m]._mdir; + switch (monster[m]._mmode) { + case MM_STAND : + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + break; + case MM_WALK : + monster[m]._mAnimData = monster[m].MType->Anims[MA_WALK].Cels[dir]; + break; + case MM_WALK2 : + monster[m]._mAnimData = monster[m].MType->Anims[MA_WALK].Cels[dir]; + break; + case MM_WALK3: + monster[m]._mAnimData = monster[m].MType->Anims[MA_WALK].Cels[dir]; + break; + case MM_ATTACK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_ATTACK].Cels[dir]; + break; + case MM_RATTACK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_ATTACK].Cels[dir]; + break; + case MM_GOTHIT: + monster[m]._mAnimData = monster[m].MType->Anims[MA_GOTHIT].Cels[dir]; + break; + case MM_DEATH: + monster[m]._mAnimData = monster[m].MType->Anims[MA_DEATH].Cels[dir]; + break; + case MM_SATTACK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_FADEIN: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_FADEOUT: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_SPSTAND: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_RSATTACK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_DELAY: + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + break; + case MM_HEAL: + monster[m]._mAnimData = monster[m].MType->Anims[MA_SPECIAL].Cels[dir]; + break; + case MM_TALK: + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + break; + case MM_STONE: + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + monster[m]._mAnimFrame = 1; + monster[m]._mAnimLen = monster[m].MType->Anims[MA_STAND].Frames; + break; + case MM_MISSILE: + monster[m]._mAnimData = monster[m].MType->Anims[MA_ATTACK].Cels[dir]; + monster[m]._mAnimFrame = 1; + monster[m]._mAnimLen = monster[m].MType->Anims[MA_ATTACK].Frames; + break; + default: + monster[m]._mAnimData = monster[m].MType->Anims[MA_STAND].Cels[dir]; + monster[m]._mAnimFrame = 1; + monster[m]._mAnimLen = monster[m].MType->Anims[MA_STAND].Frames; + break; + } +} + + +/*-----------------------------------------------------------------------* +* When monster gets killed, make the fallen run in fear +**-----------------------------------------------------------------------*/ +void M_FallenFear(int x, int y) +{ + int i, mi; + int rundist; + int aitype; + + app_assert((DWORD)nummonsters <= MAXMONSTERS); + for (i = 0; i < nummonsters; i++) { + mi = monstactive[i]; + rundist = 0; + switch(monster[mi].MType->mtype) { + case MT_RFALLSD : + case MT_RFALLSP : + rundist = 7; + break; + case MT_DFALLSD : + case MT_DFALLSP : + rundist = 5; + break; + case MT_YFALLSD : + case MT_YFALLSP : + rundist = 3; + break; + case MT_BFALLSD : + case MT_BFALLSP : + rundist = 2; + break; + } + + aitype = monster[mi]._mAi; + if(aitype == AI_FALLEN) { + if (rundist + && DIST(x-monster[mi]._mx, y-monster[mi]._my, 5) + && ((monster[mi]._mhitpoints >> HP_SHIFT) > 0)) + { + monster[mi]._mgoal = MG_RUN_AWAY; + monster[mi]._mgoalvar1 = rundist; // run away for 'rundist' squares + // next direction will be away from monster that got hit + monster[mi]._mdir = GetDirection(x, y, monster[i]._mx, monster[i]._my); + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PrintMonstHistory(int mt) +{ + int res, minhp, maxhp; + + sprintf(tempstr, "Total kills : %i", monstkills[mt]); + AddPanelString(tempstr, TEXT_CENTER); + if (monstkills[mt] >= 30) { + minhp = monsterdata[mt].mMinHP; + maxhp = monsterdata[mt].mMaxHP; + if (gbMaxPlayers == 1) { + minhp = minhp >> 1; + maxhp = maxhp >> 1; + } + if (minhp < 1) minhp = 1; + if (maxhp < 1) maxhp = 1; + if (gnDifficulty == D_NIGHTMARE) { + minhp = (minhp * 3) + 100; + maxhp = (maxhp * 3) + 100; + } + if (gnDifficulty == D_HELL) { + minhp = (minhp * 4) + 200; + maxhp = (maxhp * 4) + 200; + } + sprintf(tempstr, "Hit Points : %i-%i", minhp, maxhp); + AddPanelString(tempstr, TEXT_CENTER); + } + /*minhp = monster[cursmonst]._mhitpoints >> HP_SHIFT; + maxhp = monster[cursmonst]._mmaxhp >> HP_SHIFT; + sprintf(tempstr, "Hit Points : %i of %i", minhp, maxhp); + AddPanelString(tempstr, TEXT_CENTER);*/ + if (monstkills[mt] >= 15) { + if (gnDifficulty != D_HELL) + res = monsterdata[mt].mMagicRes; + else + res = monsterdata[mt].mMagicRes2; + res &= (M_RM|M_RF|M_RL|M_IM|M_IF|M_IL); + if (res == M_NONE) { + strcpy(tempstr, "No magic resistance"); + AddPanelString(tempstr, TEXT_CENTER); + } else { + if (res & (M_RM|M_RF|M_RL)) { + strcpy(tempstr, "Resists : "); + if (res & M_RM) strcat(tempstr, "Magic "); + if (res & M_RF) strcat(tempstr, "Fire "); + if (res & M_RL) strcat(tempstr, "Lightning "); + tempstr[strlen(tempstr)-1] = 0; + AddPanelString(tempstr, TEXT_CENTER); + } + if (res & (M_IM|M_IF|M_IL)) { + strcpy(tempstr, "Immune : "); + if (res & M_IM) strcat(tempstr, "Magic "); + if (res & M_IF) strcat(tempstr, "Fire "); + if (res & M_IL) strcat(tempstr, "Lightning "); + tempstr[strlen(tempstr)-1] = 0; + AddPanelString(tempstr, TEXT_CENTER); + } + } + } + pinfoflag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PrintUniqueHistory() +{ + int res; + + /*int minhp = monster[cursmonst]._mhitpoints >> HP_SHIFT; + int maxhp = monster[cursmonst]._mmaxhp >> HP_SHIFT; + sprintf(tempstr, "Hit Points : %i of %i", minhp, maxhp); + AddPanelString(tempstr, TEXT_CENTER);*/ + res = monster[cursmonst].mMagicRes; + res &= (M_RM|M_RF|M_RL|M_IM|M_IF|M_IL); + if (res == M_NONE) { + strcpy(tempstr, "No resistances"); + AddPanelString(tempstr, TEXT_CENTER); + strcpy(tempstr, "No Immunities"); + AddPanelString(tempstr, TEXT_CENTER); + } else { + if (res & (M_RM|M_RF|M_RL)) + strcpy(tempstr, "Some Magic Resistances"); + else + strcpy(tempstr, "No resistances"); + AddPanelString(tempstr, TEXT_CENTER); + if (res & (M_IM|M_IF|M_IL)) + strcpy(tempstr, "Some Magic Immunities"); + else + strcpy(tempstr, "No Immunities"); + AddPanelString(tempstr, TEXT_CENTER); + } + pinfoflag = TRUE; +} + +/*-----------------------------------------------------------------------* + * MissToMonst + * + * Used when Rhino charges and collides into something. +**-----------------------------------------------------------------------*/ + +void MissToMonst(int i, int x, int y) +{ + int oldx,oldy; + int newx,newy; + if ((DWORD)i >= MAXMISSILES) + app_fatal("MissToMonst: Invalid missile %d",i); + MissileStruct *Miss = &missile[i]; + int m = Miss->_misource; + if ((DWORD)m >= MAXMONSTERS) + app_fatal("MissToMonst: Invalid monster %d",m); + MonsterStruct *Monst = &monster[m]; + int pnum; + + app_assert(Monst->_mmode == MM_MISSILE); + + oldx = Miss->_mix; + oldy = Miss->_miy; + + dMonster[x][y] = m+1; + + Monst->_mdir = Miss->_mimfnum; + Monst->_mx = x; + Monst->_my = y; + M_StartStand(m, Monst->_mdir); + + if(EquivMonst(Monst->MType->mtype, MT_INCIN)) + M_StartFadein(m, Monst->_mdir, FALSE); + else { + if ((Monst->_mFlags & MFLAG_MID) == 0) + M_StartHit(m,-1,0); + else + M2MStartHit(m,-1,0); + } + + if ((Monst->_mFlags & MFLAG_MID) == 0) { + pnum = dPlayer[oldx][oldy]-1; + if((dPlayer[oldx][oldy] > 0) + && (Monst->MType->mtype != MT_GLOOM) + && !EquivMonst(Monst->MType->mtype, MT_INCIN)) + { + M_TryH2HHit(m, dPlayer[oldx][oldy]-1, 500, Monst->mMinDamage2, Monst->mMaxDamage2); + + // make sure player didn't go change location during h2hhit + if (pnum == dPlayer[oldx][oldy]-1 + && !EquivMonst(Monst->MType->mtype, MT_NSNAKE)) + { + // make sure player is doing a hit animation + if (plr[pnum]._pmode != PM_GOTHIT && plr[pnum]._pmode != PM_DEATH) + StartPlrHit(pnum, 0, TRUE); + + // knock opponent back one square + newx = oldx + offset_x[Monst->_mdir]; + newy = oldy + offset_y[Monst->_mdir]; + if(PosOkPlayer(pnum, newx, newy)) + { + plr[pnum]._px = newx; + plr[pnum]._py = newy; + FixPlayerLocation(pnum,plr[pnum]._pdir); + FixPlrWalkTags(pnum); + dPlayer[newx][newy] = pnum + 1; + SetPlayerOld(pnum); + } + } + } + } else { + if((dMonster[oldx][oldy] > 0) + && (Monst->MType->mtype != MT_GLOOM) && !EquivMonst(Monst->MType->mtype, MT_INCIN)) + { + M_TryM2MHit(m, dMonster[oldx][oldy]-1, 500, Monst->mMinDamage2, Monst->mMaxDamage2); + if (!EquivMonst(Monst->MType->mtype, MT_NSNAKE)) + { + // knock opponent back one square + newx = oldx + offset_x[Monst->_mdir]; + newy = oldy + offset_y[Monst->_mdir]; + if(PosOkMonst(dMonster[oldx][oldy]-1, newx, newy)) + { + // This assumes that monster got hit (since we use a 500% hit above) + // so we don't have to clean up his area, and we assume pnum is positive + pnum = dMonster[newx][newy] = dMonster[oldx][oldy]; + dMonster[oldx][oldy] = 0; + pnum--; + monster[pnum]._mfutx = monster[pnum]._mx = newx; + monster[pnum]._mfuty = monster[pnum]._my = newy; + } + } + } + } +} + +/*-----------------------------------------------------------------------* + * PosOkMonst + * + * Map position (x,y) is ok for placement of a monster. +**-----------------------------------------------------------------------*/ + +BOOL PosOkMonst(int i, int x, int y) +{ + BOOL ret = TRUE; + int oi; + int mi; + BOOL fire = FALSE; + + ret = !SolidLoc(x, y) && !dPlayer[x][y] && !dMonster[x][y]; + + if(ret && dObject[x][y]) + { + if (dObject[x][y] > 0) oi = dObject[x][y] - 1; + else oi = -(dObject[x][y] + 1); + if (object[oi]._oSolidFlag) ret = FALSE; + } + if(ret && dMissile[x][y] && i >= 0) + { + if((mi = dMissile[x][y]) > 0) + if(missile[mi]._mitype == MIT_FIREWALL) + fire = TRUE; + else + { + for(mi = 0; mi < nummissiles; mi++) + if(missile[missileactive[mi]]._mitype == MIT_FIREWALL) + fire = TRUE; + } + if ((fire && !(monster[i].mMagicRes & M_IF)) || (fire && (monster[i].MType->mtype == MT_DIABLO))) + ret = FALSE; + } + + return ret; +} + +/*-----------------------------------------------------------------------* + * PosOkMonst2 + * + * Map position (x,y) is ok for placement of a monster. + * Same as PosOkMonst, except ignores other monsters and players +**-----------------------------------------------------------------------*/ + +BOOL PosOkMonst2(int i, int x, int y) +{ + BOOL ret = TRUE; + int oi; + int mi; + BOOL fire = FALSE; + + ret = !SolidLoc(x, y); + + if(ret && dObject[x][y]) + { + if (dObject[x][y] > 0) oi = dObject[x][y] - 1; + else oi = -(dObject[x][y] + 1); + if (object[oi]._oSolidFlag) ret = FALSE; + } + if(ret && dMissile[x][y] && i >= 0) + { + if((mi = dMissile[x][y]) > 0) + if(missile[mi]._mitype == MIT_FIREWALL) + fire = TRUE; + else + { + for(mi = 0; mi < nummissiles; mi++) + if(missile[missileactive[mi]]._mitype == MIT_FIREWALL) + fire = TRUE; + } + if ((fire && !(monster[i].mMagicRes & M_IF)) || (fire && (monster[i].MType->mtype == MT_DIABLO))) + ret = FALSE; + } + + return ret; +} + +/*-----------------------------------------------------------------------* + * PosOkMonst + * + * Map position (x,y) is ok for placement of a monster. + * Same as PosOkMonst3, except ignores doors +**-----------------------------------------------------------------------*/ + +BOOL PosOkMonst3(int i, int x, int y) +{ + BOOL ret = TRUE; + int oi, objtype; + int mi; + BOOL fire = FALSE; + BOOL isdoor = FALSE; + + if(dObject[x][y]) + { + if (dObject[x][y] > 0) oi = dObject[x][y] - 1; + else oi = -(dObject[x][y] + 1); + objtype = object[oi]._otype; + isdoor = (objtype == OBJ_L1DOORL + || objtype == OBJ_L1DOORR + || objtype == OBJ_L2DOORL + || objtype == OBJ_L2DOORR + || objtype == OBJ_L3DOORL + || objtype == OBJ_L3DOORR); + if (object[oi]._oSolidFlag && !isdoor) + ret = FALSE; + } + + if (ret) + ret = (!SolidLoc(x, y) || isdoor) && !dPlayer[x][y] && !dMonster[x][y]; + + if(ret && dMissile[x][y] && i >= 0) + { + if((mi = dMissile[x][y]) > 0) + if(missile[mi]._mitype == MIT_FIREWALL) + fire = TRUE; + else + { + for(mi = 0; mi < nummissiles; mi++) + if(missile[missileactive[mi]]._mitype == MIT_FIREWALL) + fire = TRUE; + } + if ((fire && !(monster[i].mMagicRes & M_IF)) || (fire && (monster[i].MType->mtype == MT_DIABLO))) + ret = FALSE; + } + + return ret; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL IsSkel(int mt) +{ + return EquivMonst(mt, MT_WSKELAX) + || EquivMonst(mt, MT_WSKELBW) + || EquivMonst(mt, MT_WSKELSD); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL IsGoat(int mt) +{ + return EquivMonst(mt, MT_NGOATMC) + || EquivMonst(mt, MT_NGOATBW); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int M_SpawnSkel(int x, int y, int dir) +{ + int i,j; + int skeltypes = 0; + int skel; + + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (i = 0; i < nummtypes; i++) + if (IsSkel(Monsters[i].mtype)) + skeltypes++; + + if (skeltypes) + { + j = random(136,skeltypes); + skeltypes = 0; + for (i = 0; i < nummtypes && skeltypes <= j; i++) + if(IsSkel(Monsters[i].mtype)) + skeltypes++; + i--; + skel = AddMonster(x, y, dir, i, TRUE); + if (skel != -1) M_StartSpStand(skel, dir); + return skel; + } + else + return -1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ActivateSpawn(int i, int x, int y, int dir) +{ + dMonster[x][y] = i + 1; + monster[i]._mx = x; + monster[i]._my = y; + monster[i]._mfutx = x; + monster[i]._mfuty = y; + monster[i]._moldx = x; + monster[i]._moldy = y; + M_StartSpStand(i, dir); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL SpawnSkeleton(int ii, int x, int y) +{ + int monstok[3][3]; + int i,j,xx,yy,rs; + BOOL savail; + + if (ii == -1) return FALSE; + // Try location first + if (PosOkMonst(-1, x, y)) { + ActivateSpawn(ii, x, y, GetDirection(x, y, x, y)); + } else { + // Try surrounding squares + savail = FALSE; + yy = 0; + for (j = (y-1); j <= (y+1); j++) { + xx = 0; + for (i = (x-1); i <= (x+1); i++) { + monstok[xx][yy] = PosOkMonst(-1, i,j); + savail |= monstok[xx][yy]; + xx++; + } + yy++; + } + + // No fit, no good + if (!savail) return(FALSE); + + // Place skeleton + rs = random(137,15) + 1; + xx = 0; + yy = 0; + while (rs > 0) { + if (monstok[xx][yy]) rs--; + if (rs > 0) { + xx++; + if (xx == 3) { + xx = 0; + yy++; + if (yy == 3) yy = 0; + } + } + } + xx = xx + x - 1; + yy = yy + y - 1; + ActivateSpawn(ii, xx, yy, GetDirection(xx, yy, x, y)); + } + return(TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PreSpawnSkeleton() +{ + int i,j; + int skeltypes = 0; + int skel; + + app_assert((DWORD)nummtypes <= MAX_LVLMTYPES); + for (i = 0; i < nummtypes; i++) + if (IsSkel(Monsters[i].mtype)) + skeltypes++; + + if (skeltypes) + { + j = random(136,skeltypes); + skeltypes = 0; + for (i = 0; i < nummtypes && skeltypes <= j; i++) + { + if(IsSkel(Monsters[i].mtype)) + skeltypes++; + } + i--; + skel = AddMonster(0, 0, 0, i, FALSE); + if (skel != -1) M_StartStand(skel, 0); + return skel; + } + else + return -1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void TalktoMonster(int i) +{ + int pnum, itm; + if ((DWORD)i >= MAXMONSTERS) + app_fatal("TalktoMonster: Invalid monster %d",i); + MonsterStruct *Monst = &monster[i]; + pnum = Monst->_menemy; + + Monst->_mmode = MM_TALK; + + if ((Monst->_mAi != AI_SNOTSPIL) && (Monst->_mAi != AI_LACHDANAN)) + return; + + if (QuestStatus(Q_LTBANNER)) { + if ((quests[Q_LTBANNER]._qvar1 == 2) && (PlrHasItem(pnum, IDI_BANNER, itm))) { + RemoveInvItem(pnum, itm); + quests[Q_LTBANNER]._qactive = QUEST_DONE; + Monst->mtalkmsg = TXT_BOL3; + Monst->_mgoal = MG_TALK; + } + } + if (QuestStatus(Q_VEIL)) { + if ((Monst->mtalkmsg >= TXT_VEIL1) && (PlrHasItem(pnum, IDI_GLDNELIX, itm))) { + RemoveInvItem(pnum, itm); + Monst->mtalkmsg = TXT_VEIL3; + Monst->_mgoal = MG_TALK; + } + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SpawnGolum(int i, int x, int y, int mi) +{ + if ((DWORD)i >= MAXMONSTERS) + app_fatal("SpawnGolum: Invalid monster %d",i); + dMonster[x][y] = i + 1; + monster[i]._mx = x; + monster[i]._my = y; + monster[i]._mfutx = x; + monster[i]._mfuty = y; + monster[i]._moldx = x; + monster[i]._moldy = y; + monster[i]._pathcount = 0; + + monster[i]._mmaxhp = ((plr[i]._pMaxMana/3)<<1) + (((missile[mi]._mispllvl << HP_SHIFT) << 3) + ((missile[mi]._mispllvl << HP_SHIFT) << 1)); + monster[i]._mhitpoints = monster[i]._mmaxhp; + monster[i].mArmorClass = 25; + monster[i].mHit = 40 + (plr[i]._pLevel << 1) + ((missile[mi]._mispllvl << 2) + (missile[mi]._mispllvl)); + monster[i].mMinDamage = 8 + (missile[mi]._mispllvl << 1); + monster[i].mMaxDamage = 16 + (missile[mi]._mispllvl << 1); + + monster[i]._mFlags |= MFLAG_MKILLER; + M_StartSpStand(i, 0); + M_Enemy(i); + + void NetSendCmdGolem(BYTE, BYTE, BYTE, BYTE, long, BYTE); + if (i == myplr) + NetSendCmdGolem(monster[i]._mx, monster[i]._my, monster[i]._mdir, monster[i]._menemy, monster[i]._mhitpoints, currlevel); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL CanTalkToMonst(int m) +{ + if ((DWORD)m >= MAXMONSTERS) + app_fatal("CanTalkToMonst: Invalid monster %d",m); + if (monster[m]._mgoal == MG_TALK) return(TRUE); + if (monster[m]._mgoal == MG_WAITTOTALK) return(TRUE); + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL CheckMonsterHit(int m, BOOL &ret) +{ + if ((DWORD)m >= MAXMONSTERS) + app_fatal("CheckMonsterHit: Invalid monster %d",m); + if (monster[m]._mAi == AI_GARG && (monster[m]._mFlags & MFLAG_STILL)) + { + monster[m]._mFlags &= ~MFLAG_STILL; + monster[m]._mmode = MM_SATTACK; + ret = TRUE; + return(TRUE); + } + else if(EquivMonst(monster[m].MType->mtype, MT_COUNSLR) + && (monster[m]._mgoal != MG_ATTACK)) + { + ret = FALSE; + return TRUE; + } + return FALSE; +} + +//****************************************************************** +//****************************************************************** +int encode_enemy(int m) +{ + if (monster[m]._mFlags & MFLAG_MID) + return monster[m]._menemy + MAX_PLRS; + else + // enemy is player, guaranteed < MAX_PLRS + return monster[m]._menemy; +} + +//****************************************************************** +//****************************************************************** +void decode_enemy(int m, int enemy) +{ + if (enemy < MAX_PLRS) { + monster[m]._mFlags &= ~MFLAG_MID; + monster[m]._menemy = enemy; + monster[m]._menemyx = plr[enemy]._pfutx; + monster[m]._menemyy = plr[enemy]._pfuty; + } + else { + monster[m]._mFlags |= MFLAG_MID; + enemy -= MAX_PLRS; + monster[m]._menemy = enemy; + monster[m]._menemyx = monster[enemy]._mfutx; + monster[m]._menemyy = monster[enemy]._mfuty; + } +} diff --git a/src/MONSTINT.H b/src/MONSTINT.H new file mode 100644 index 0000000..054d674 --- /dev/null +++ b/src/MONSTINT.H @@ -0,0 +1,71 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Monstint.h +** +** Definitions internal to Monster modules +** See Monster.h for definitions necessary outside monster modules +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/MONSTINT.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +// Monster Modes +#define MM_STAND 0 +#define MM_WALK 1 +#define MM_WALK2 2 +#define MM_WALK3 3 +#define MM_ATTACK 4 +#define MM_GOTHIT 5 +#define MM_DEATH 6 +#define MM_SATTACK 7 // Special Attack +#define MM_FADEIN 8 +#define MM_FADEOUT 9 +#define MM_RATTACK 10 // Ranged weapon attack +#define MM_SPSTAND 11 // Special Neutral +#define MM_RSATTACK 12 // Ranged Special attack +#define MM_DELAY 13 // Stand for a while +#define MM_MISSILE 14 // Do nothing while monster is a missile +#define MM_STONE 15 // Monster is Stone Cursed +#define MM_HEAL 16 // Gargoyle still while healing +#define MM_TALK 17 // Monster is in talk mode + +// Monster Goals +#define MG_ATTACK 1 +#define MG_RUN_AWAY 2 +#define MG_EAT 3 +#define MG_WALK_AROUND1 4 +#define MG_ATTACK2 5 +#define MG_TALK 6 +#define MG_WAITTOTALK 7 + +// Monster Anims +#define MA_STAND 0 +#define MA_WALK 1 +#define MA_ATTACK 2 +#define MA_GOTHIT 3 +#define MA_DEATH 4 +#define MA_SPECIAL 5 + +// Monster Direction +#define M_DIRU 4 +#define M_DIRUR 5 +#define M_DIRR 6 +#define M_DIRDR 7 +#define M_DIRD 0 +#define M_DIRDL 1 + +#define M_DIRL 2 +#define M_DIRUL 3 + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void M_FallenFear(int x, int y); +BOOL SolidLoc(int x, int y); diff --git a/src/MOVIE.CPP b/src/MOVIE.CPP new file mode 100644 index 0000000..2042dd2 --- /dev/null +++ b/src/MOVIE.CPP @@ -0,0 +1,114 @@ +//****************************************************************** +// movie.cpp +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "palette.h" +#include "engine.h" +#include "scrollrt.h" +#include "gendung.h" +#include "sound.h" + + +//****************************************************************** +// externs +//****************************************************************** +void CALLBACK menusnd_play(LPCSTR pszName); +WNDPROC my_SetWindowProc(WNDPROC wndProc); +void BlackPalette(); +void music_pause(BOOL bPause); +void stream_stop(); + + +//****************************************************************** +// private +//****************************************************************** +static BYTE sgbPlayMovie; + + +//****************************************************************** +//****************************************************************** +static LRESULT CALLBACK MovieWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { + switch (uMsg) { + case WM_SYSCOMMAND: + if (wParam == SC_CLOSE) { + sgbPlayMovie = FALSE; + return 0; + } + break; + + case WM_KEYDOWN: + sgbPlayMovie = FALSE; + break; + + case WM_CHAR: + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + sgbPlayMovie = FALSE; + break; + } + + return DiabloDefProc(hWnd,uMsg,wParam,lParam); +} + + +//****************************************************************** +//****************************************************************** +BOOL gbLoopMovie = FALSE; +void play_movie(const char * pszMovie,BOOL bAllowCancel) { + app_assert(pszMovie); + + // if we are not the frontmost window then don't play the movie + if (! bActive) return; + + app_assert(ghMainWnd); + WNDPROC saveProc = my_SetWindowProc(MovieWndProc); + InvalidateRect(ghMainWnd,NULL,0); + UpdateWindow(ghMainWnd); + + sgbPlayMovie = TRUE; + + // stop music and streaming SFX from playing so they + // don't interfere with the CD bandwidth during movie + music_pause(TRUE); + stream_stop(); + + // play "silence" because according to RAD software, it + // prevents a popping noise upon movie startup + menusnd_play("Sfx\\Misc\\blank.wav"); + HSVIDEO hVid; + SVidPlayBegin( + pszMovie, + NULL, + NULL, + NULL, + 0, + gbLoopMovie ? (SVID_AUTOCUTSCENE|SVID_FLAG_LOOP)&~SVID_FLAG_CLEARSCREEN : SVID_AUTOCUTSCENE, + &hVid + ); + + while (hVid && bActive) { + if (bAllowCancel && !sgbPlayMovie) break; + + MSG msg; + while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { + if (msg.message == WM_QUIT) continue; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if (!SVidPlayContinue()) + break; + } + + if (hVid) SVidPlayEnd(hVid); + + // restore window procedure + saveProc = my_SetWindowProc(saveProc); + app_assert(saveProc == MovieWndProc); + + music_pause(FALSE); +} diff --git a/src/MPQAPI.CPP b/src/MPQAPI.CPP new file mode 100644 index 0000000..25badeb --- /dev/null +++ b/src/MPQAPI.CPP @@ -0,0 +1,1006 @@ +//****************************************************************** +// MPQapi.cpp +// File pack API +// By Michael O'Brien (6/1/96) && Patrick Wyatt (6/24/96) +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "engine.h" +#include "mpqapi.h" + + +//****************************************************************** +// debugging +//****************************************************************** +#define DUMP_BLOCK 0 // 0 in final +#ifdef NDEBUG +#undef DUMP_BLOCK +#define DUMP_BLOCK 0 +#endif + + +//****************************************************************** +// extern +//****************************************************************** +extern BYTE gbMaxPlayers; + + +//****************************************************************** +// public +//****************************************************************** +char gszProgKey[] = "Hellfire"; + + +//****************************************************************** +// private +//****************************************************************** +#define MPQ_HIDE_ATTR (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM) + +static HANDLE sghArchive = INVALID_HANDLE_VALUE; +static BOOL sgbChanged; + +// extra header -- non-standard .MPQ stuff +#define FILE_EXHDR_SIZE 72 +#define FILE_EXHDR_OFFSET sizeof(FILEHEADER) + +// block table +#define BLOCK_ENTRIES 2048 +#define BLOCK_TBL_SIZE (BLOCK_ENTRIES * sizeof(BLOCKENTRY)) +#define BLOCK_TBL_OFFSET (FILE_EXHDR_OFFSET + FILE_EXHDR_SIZE) +static BLOCKENTRYPTR sgpBlockTbl; + +// hash table +#define HASH_ENTRIES 2048 // must be pow2 +#define HASH_TBL_SIZE (HASH_ENTRIES * sizeof(HASHENTRY)) +#define HASH_TBL_OFFSET (BLOCK_TBL_OFFSET + BLOCK_TBL_SIZE) +static HASHENTRYPTR sgpHashTbl; + +// offset past last file where next added file will start +#define FIRST_FILE_START (HASH_TBL_OFFSET + HASH_TBL_SIZE) +static DWORD sgdwNextFileStart; + +// minimum space we will allow as standalone "free" block in file +#define MIN_FREE_SIZE 1024 + +static BYTE sgbSaveCreationKey = FALSE; + +#if IS_VERSION(SHAREWARE) +static char sgszArchiveKey[] = "Audio Playback "; +#else +static char sgszArchiveKey[] = "Video Player "; +#endif + + +#define CREATION_TIME 0 +#define LASTWRITE_TIME 1 +#define NUM_TIMES 2 + +typedef struct EXFILEHEADER { + BYTE bData[FILE_EXHDR_SIZE]; +} EXFILEHEADER; + +typedef struct FULLHEADER { + FILEHEADER hdr; + EXFILEHEADER exhdr; +} FULLHEADER; + + +//****************************************************************** +// imported functions +//****************************************************************** +void InitializeHashSource(); +void Decrypt(LPDWORD data, DWORD bytes, DWORD key); +void Encrypt(LPDWORD data, DWORD bytes, DWORD key); +DWORD Hash(const char *filename, int hashtype); +DWORD Compress(LPBYTE data, DWORD bytes); + + +//****************************************************************** +//****************************************************************** +static void xor_timestamp(FILETIME * pTime) { + DWORD dwKey = 0xf0761ab; + LPBYTE lpStamp = (LPBYTE) pTime; + DWORD dwBytes = sizeof(FILETIME); + while (dwBytes--) { + *lpStamp++ ^= (BYTE) dwKey; + dwKey = _rotl(dwKey,1); + } +} + + +//****************************************************************** +//****************************************************************** +static BOOL reg_get_stamps(FILETIME * pft,DWORD dwSize) { + ZeroMemory(pft,dwSize); + DWORD dwBytes; + if (! SRegLoadData(gszProgKey,sgszArchiveKey,0,pft,dwSize,&dwBytes)) + return FALSE; + if (dwBytes != dwSize) + return FALSE; + + while (dwSize >= sizeof FILETIME) { + xor_timestamp(pft++); + dwSize -= sizeof FILETIME; + } + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static void reg_set_stamps(FILETIME * pft,DWORD dwSize) { + // only update registry stamps for multiplayer mode + app_assert(gbMaxPlayers != 1); + + FILETIME * pft2 = pft; + for (DWORD d = dwSize; d >= sizeof FILETIME; d -= sizeof FILETIME) + xor_timestamp(pft2++); + +// pjw.patch1.start +// SRegSaveData(gszProgKey,sgszArchiveKey,SREG_FLAG_FLUSHTODISK,pft,dwSize); + SRegSaveData(gszProgKey,sgszArchiveKey,0,pft,dwSize); +// pjw.patch1.end +} + + +//****************************************************************** +//****************************************************************** +/* pjw.patch1.start +static int stamp_compare(FILETIME * pf1,FILETIME * pf2) { + return ! memcmp(pf1,pf2,sizeof FILETIME); +} +pjw.patch1.end */ + + +//****************************************************************** +//****************************************************************** +BOOL MPQSetAttributes(const char * pszArchive,BOOL bHide) { + app_assert(pszArchive); + + // get the attributes for the file + DWORD dwAttr; + if (0xffffffff == (dwAttr = GetFileAttributes(pszArchive))) { + if (ERROR_FILE_NOT_FOUND == GetLastError()) + return TRUE; + return FALSE; + } + + DWORD dwWantAttr = bHide ? MPQ_HIDE_ATTR : 0; + if (dwAttr == dwWantAttr) return TRUE; + return SetFileAttributes(pszArchive,dwWantAttr); +} + + +//****************************************************************** +//****************************************************************** +BOOL MPQCompareTimeStamps(const char * pszArchive,DWORD dwChar) { +/* pjw.patch1.start + app_assert(pszArchive); + app_assert(dwChar < MAX_CHARACTERS); + + // get archive timestamps from registry + FILETIME ft[MAX_CHARACTERS][NUM_TIMES]; + if (! reg_get_stamps(&ft[0][0],sizeof ft)) return FALSE; + + // get archive file timestamps + WIN32_FIND_DATA finddata; + HANDLE findhandle = FindFirstFile(pszArchive,&finddata); + if (findhandle == INVALID_HANDLE_VALUE) return FALSE; + FindClose(findhandle); + + return + stamp_compare(&finddata.ftCreationTime,&ft[dwChar][CREATION_TIME]) + && + stamp_compare(&finddata.ftLastWriteTime,&ft[dwChar][LASTWRITE_TIME]); +pjw.patch1.end */ + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +void MPQMungeStamps(DWORD dwChar) { +/* pjw.patch1.start + // only update registry stamps for multiplayer mode + if (gbMaxPlayers == 1) return; + app_assert(dwChar < MAX_CHARACTERS); + + FILETIME ft[MAX_CHARACTERS][NUM_TIMES]; + reg_get_stamps(&ft[0][0],sizeof ft); + ft[dwChar][0].dwHighDateTime = 0x78341348; + reg_set_stamps(&ft[0][0],sizeof ft); +pjw.patch1.end */ +} + + +//****************************************************************** +//****************************************************************** +static void MPQUpdateLastWriteTimeStamp(const char * pszArchive,DWORD dwChar) { + // only update registry stamps for multiplayer mode + if (gbMaxPlayers == 1) return; + + app_assert(pszArchive); + app_assert(dwChar < MAX_CHARACTERS); + + // get archive timestamps from registry + FILETIME ft[MAX_CHARACTERS][NUM_TIMES]; + reg_get_stamps(&ft[0][0],sizeof ft); + + // get archive file timestamps + WIN32_FIND_DATA finddata; + HANDLE findhandle = FindFirstFile(pszArchive,&finddata); + if (findhandle == INVALID_HANDLE_VALUE) return; + FindClose(findhandle); + + // update timestamp + ft[dwChar][LASTWRITE_TIME] = finddata.ftLastWriteTime; + + // save back to registry + reg_set_stamps(&ft[0][0],sizeof ft); +} + + +//****************************************************************** +//****************************************************************** +void MPQUpdateCreationTimeStamp(const char * pszArchive,DWORD dwChar) { + // only update registry stamps for multiplayer mode + if (gbMaxPlayers == 1) return; + app_assert(pszArchive); + app_assert(dwChar < MAX_CHARACTERS); + + // get archive timestamps from registry + FILETIME ft[MAX_CHARACTERS][NUM_TIMES]; + reg_get_stamps(&ft[0][0],sizeof ft); + + // get archive file timestamps + WIN32_FIND_DATA finddata; + HANDLE findhandle = FindFirstFile(pszArchive,&finddata); + if (findhandle == INVALID_HANDLE_VALUE) return; + FindClose(findhandle); + + // update timestamp + ft[dwChar][CREATION_TIME] = finddata.ftCreationTime; + + reg_set_stamps(&ft[0][0],sizeof ft); +} + + +//****************************************************************** +//****************************************************************** +#if DUMP_BLOCK +static const char * fflags_2_str(DWORD dwFlags) { + if (dwFlags & MPQ_ADD_COMPRESSED) { + if (dwFlags & MPQ_ADD_ENCRYPTED) + return "ENCRYPT+COMPRESS"; + return "COMPRESS"; + } + + if (dwFlags & MPQ_ADD_ENCRYPTED) + return "ENCRYPT"; + return "NONE"; +} +#endif + + +//****************************************************************** +//****************************************************************** +#if DUMP_BLOCK +static void dump_blocktbl(void) { + + FILE * f = fopen("c:\\block.txt","wb"); + if (! f) return; + + fprintf(f," start + size = end\r\n"); + DWORD dwPosition = FIRST_FILE_START; + while (dwPosition != sgdwNextFileStart) { + BLOCKENTRY * pBlk = sgpBlockTbl; + for (DWORD i = BLOCK_ENTRIES; i--; pBlk++) { + if (pBlk->offset != dwPosition) continue; + fprintf(f,"%8d + %8d = %8d %s\r\n", + pBlk->offset, + pBlk->sizealloc, + pBlk->offset + pBlk->sizealloc, + fflags_2_str(pBlk->flags) + ); + dwPosition = pBlk->offset + pBlk->sizealloc; + break; + } + if (i == -1) { + fclose(f); + void myDebugBreak(); + myDebugBreak(); + app_fatal("Bad block table"); + } + } + + fprintf(f,"next file start: %d\r\n",sgdwNextFileStart); + fclose(f); +} +#endif + + +//****************************************************************** +//****************************************************************** +static BLOCKENTRY * get_free_block(DWORD * pdwBlockIndex) { + BLOCKENTRY * pBlk = sgpBlockTbl; + for (DWORD i = 0; i < BLOCK_ENTRIES; i++, pBlk++) { + if (pBlk->offset) continue; + if (pBlk->sizealloc) continue; + if (pBlk->flags) continue; + if (pBlk->sizefile) continue; + if (pdwBlockIndex) *pdwBlockIndex = i; + return pBlk; + } + + app_fatal("Out of free block entries"); + return NULL; +} + + +//****************************************************************** +//****************************************************************** +static void add_free_block(DWORD dwOffset,DWORD dwSize) { + // see if we can merge this block with an existing free block + BLOCKENTRY * pBlk = sgpBlockTbl; + for (DWORD i = BLOCK_ENTRIES; i--; pBlk++) { + // is this block unused? + if (pBlk->offset == 0) continue; + if (pBlk->flags != 0) continue; + if (pBlk->sizefile != 0) continue; + + if (pBlk->offset + pBlk->sizealloc == dwOffset) { + dwOffset = pBlk->offset; + dwSize += pBlk->sizealloc; + } + else if (dwOffset + dwSize == pBlk->offset) { + dwSize += pBlk->sizealloc; + } + else { + continue; + } + + // try adding the new larger block. + // NOTE: in the worst case, we free a block which is between + // two free blocks, which causes only one deep recursion + ZeroMemory(pBlk,sizeof(*pBlk)); + add_free_block(dwOffset,dwSize); + return; + } + + if (dwOffset + dwSize > sgdwNextFileStart) + app_fatal("MPQ free list error"); + + // is this block at the end of the file? + if (dwOffset + dwSize == sgdwNextFileStart) { + sgdwNextFileStart = dwOffset; + return; + } + + // create a new block entry + pBlk = get_free_block(NULL); + pBlk->offset = dwOffset; + pBlk->sizealloc = dwSize; + pBlk->sizefile = 0; + pBlk->flags = 0; +} + + +//****************************************************************** +//****************************************************************** +static DWORD get_free_space(DWORD dwSize,DWORD * pdwSizeAlloc) { + DWORD dwOffset; + + // see if there is a space large enough in an existing block + BLOCKENTRY * pBlk = sgpBlockTbl; + for (DWORD i = BLOCK_ENTRIES; i--; pBlk++) { + // is this block unused? + if (pBlk->offset == 0) continue; + if (pBlk->flags != 0) continue; + if (pBlk->sizefile != 0) continue; + if (pBlk->sizealloc < dwSize) continue; + + // use a portion of this block + dwOffset = pBlk->offset; + *pdwSizeAlloc = dwSize; + + // fixup this block + pBlk->offset += dwSize; + pBlk->sizealloc -= dwSize; + + // did we use the entire block? + if (! pBlk->sizealloc) ZeroMemory(pBlk,sizeof(BLOCKENTRY)); + + return dwOffset; + } + + // use free space at end of .MPQ file + *pdwSizeAlloc = dwSize; + dwOffset = sgdwNextFileStart; + sgdwNextFileStart += dwSize; + return dwOffset; +} + + +//****************************************************************** +//****************************************************************** +static DWORD SearchHashEntry( + DWORD hashindex, + DWORD hashcheck0, + DWORD hashcheck1, + LCID lcid +) { + DWORD dwCount = HASH_ENTRIES; + for ( + DWORD entry = hashindex & (HASH_ENTRIES - 1); + (sgpHashTbl+entry)->block != HASH_BLOCK_UNUSED; + entry = (entry + 1) & (HASH_ENTRIES - 1) + ) { + if (! dwCount--) break; + + if ((sgpHashTbl+entry)->hashcheck[0] != hashcheck0) + continue; + if ((sgpHashTbl+entry)->hashcheck[1] != hashcheck1) + continue; + if ((sgpHashTbl+entry)->lcid != lcid) + continue; + if ((sgpHashTbl+entry)->block == HASH_BLOCK_FREED) + continue; + + return entry; + } + + return HASH_ENTRY_UNUSED; +} + + +//****************************************************************** +//****************************************************************** +static BOOL WriteFileHeader() { + FULLHEADER fhdr; + + // initialize header + ZeroMemory(&fhdr,sizeof(fhdr)); + + // fill in .mpq header + fhdr.hdr.signature = SIGNATURE; + fhdr.hdr.headersize = sizeof(FILEHEADER); + fhdr.hdr.filesize = GetFileSize(sghArchive,NULL); + fhdr.hdr.version = VERSION; + fhdr.hdr.sectorsizeid = SECTORSIZEID; + fhdr.hdr.hashoffset = HASH_TBL_OFFSET; + fhdr.hdr.blockoffset = BLOCK_TBL_OFFSET; + fhdr.hdr.hashcount = HASH_ENTRIES; + fhdr.hdr.blockcount = BLOCK_ENTRIES; + + DWORD dwTemp; + if (0xffffffff == SetFilePointer(sghArchive,0,NULL,FILE_BEGIN)) + return FALSE; + if (! WriteFile(sghArchive,&fhdr.hdr,sizeof(fhdr),&dwTemp,NULL)) + return FALSE; + return sizeof(fhdr) == dwTemp; +} + + +//****************************************************************** +//****************************************************************** +static BOOL WriteBlockTable() { + #if DUMP_BLOCK + dump_blocktbl(); + #endif + + if (0xffffffff == SetFilePointer(sghArchive,BLOCK_TBL_OFFSET,NULL,FILE_BEGIN)) + return FALSE; + + DWORD dwTemp; + Encrypt((LPDWORD) sgpBlockTbl,BLOCK_TBL_SIZE,Hash("(block table)",HASH_ENCRYPTKEY)); + BOOL bResult = WriteFile(sghArchive,sgpBlockTbl,BLOCK_TBL_SIZE,&dwTemp,NULL); + Decrypt((LPDWORD) sgpBlockTbl,BLOCK_TBL_SIZE,Hash("(block table)",HASH_ENCRYPTKEY)); + + return bResult && BLOCK_TBL_SIZE == dwTemp; +} + + +//****************************************************************** +//****************************************************************** +static BOOL WriteHashTable() { + if (0xffffffff == SetFilePointer(sghArchive,HASH_TBL_OFFSET,NULL,FILE_BEGIN)) + return FALSE; + + DWORD dwTemp; + Encrypt((LPDWORD) sgpHashTbl,HASH_TBL_SIZE,Hash("(hash table)",HASH_ENCRYPTKEY)); + BOOL bResult = WriteFile(sghArchive,sgpHashTbl,HASH_TBL_SIZE,&dwTemp,NULL); + Decrypt((LPDWORD) sgpHashTbl,HASH_TBL_SIZE,Hash("(hash table)",HASH_ENCRYPTKEY)); + + return bResult && HASH_TBL_SIZE == dwTemp; +} + + +//****************************************************************** +//****************************************************************** +static BOOL SetEOF() { + if (0xffffffff == SetFilePointer(sghArchive,sgdwNextFileStart,NULL,FILE_BEGIN)) + return FALSE; + return SetEndOfFile(sghArchive); +} + + +//****************************************************************** +//****************************************************************** +static BOOL read_mpq_file_hdr(FULLHEADER * pHdr,DWORD * pdwNextFileStart) { + BOOL bError; + DWORD dwBytes; + app_assert(pHdr); + app_assert(pdwNextFileStart); + + // read file hdr + DWORD dwFileSize = GetFileSize(sghArchive,NULL); + *pdwNextFileStart = dwFileSize; + if (dwFileSize == 0xffffffff) + bError = TRUE; + else if (sizeof(*pHdr) > dwFileSize) + bError = TRUE; + else if (! ReadFile(sghArchive,pHdr,sizeof(*pHdr),&dwBytes,NULL)) + bError = TRUE; + else if (sizeof(*pHdr) != dwBytes) + bError = TRUE; + else if (pHdr->hdr.signature != SIGNATURE) + bError = TRUE; + else if (pHdr->hdr.headersize != sizeof(FILEHEADER)) + bError = TRUE; + else if (pHdr->hdr.version > VERSION) + bError = TRUE; + else if (pHdr->hdr.sectorsizeid != SECTORSIZEID) + bError = TRUE; + else if (pHdr->hdr.filesize != dwFileSize) + bError = TRUE; + else if (pHdr->hdr.hashoffset != HASH_TBL_OFFSET) + bError = TRUE; + else if (pHdr->hdr.blockoffset != BLOCK_TBL_OFFSET) + bError = TRUE; + else if (pHdr->hdr.hashcount != HASH_ENTRIES) + bError = TRUE; + else if (pHdr->hdr.blockcount != BLOCK_ENTRIES) + bError = TRUE; + else // NO ERROR (finally) + bError = FALSE; + + if (bError) { + // kill off any existing file hdr information + if (0xffffffff == SetFilePointer(sghArchive,0,NULL,FILE_BEGIN)) + return FALSE; + if (! SetEndOfFile(sghArchive)) + return FALSE; + + // initialize file header + ZeroMemory(pHdr,sizeof(*pHdr)); + + // fill in .mpq header + pHdr->hdr.signature = SIGNATURE; + pHdr->hdr.headersize = sizeof(FILEHEADER); + pHdr->hdr.sectorsizeid = SECTORSIZEID; + pHdr->hdr.version = VERSION; + + // set location of start of next file + *pdwNextFileStart = FIRST_FILE_START; + + // modified the file + sgbChanged = TRUE; + sgbSaveCreationKey = TRUE; + } + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static DWORD SearchHashName(const char * pszName) { + return SearchHashEntry( + Hash(pszName,HASH_INDEX), + Hash(pszName,HASH_CHECK0), + Hash(pszName,HASH_CHECK1), + MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT) + ); +} + + +//****************************************************************** +//****************************************************************** +static void mpq_delete_file(const char * pszName) { + DWORD dwEntry = SearchHashName(pszName); + if (dwEntry == HASH_ENTRY_UNUSED) + return; + + HASHENTRY * pHash = sgpHashTbl + dwEntry; + BLOCKENTRY * pBlk = sgpBlockTbl + pHash->block; + + // we can't set the hash block to HASH_BLOCK_UNUSED, because + // we use closed hashing. Another file may have hashed + // to the same spot, and so was added to the hash table + // after this hash entry. Therefore, just mark the hash + // entry as freed, but not unused + pHash->block = HASH_BLOCK_FREED; + + // free the block entry and give back the memory + DWORD dwOffset = pBlk->offset; + DWORD dwSize = pBlk->sizealloc; + ZeroMemory(pBlk,sizeof(*pBlk)); + add_free_block(dwOffset,dwSize); + + // modified the file + sgbChanged = TRUE; +} + + +//****************************************************************** +//****************************************************************** +void MPQDeleteFile(const char * pszName) { + app_assert(sghArchive != INVALID_HANDLE_VALUE); + app_assert(pszName); + + // if the specified file is not part of the archive, + // then consider the delete operation successful + mpq_delete_file(pszName); +} + + +//****************************************************************** +//****************************************************************** +void MPQDeleteFiles(TGetNameFcn fnGetName) { + app_assert(sghArchive != INVALID_HANDLE_VALUE); + app_assert(fnGetName); + + DWORD dwIndex = 0; + char szName[MAX_PATH]; + while (fnGetName(dwIndex++,szName)) + mpq_delete_file(szName); +} + + +//****************************************************************** +//****************************************************************** +static BLOCKENTRY * InsertIntoHash(const char * pszName,BLOCKENTRY * pBlk,DWORD dwBlock) { + DWORD hashindex = Hash(pszName,HASH_INDEX); + DWORD hashcheck0 = Hash(pszName,HASH_CHECK0); + DWORD hashcheck1 = Hash(pszName,HASH_CHECK1); + + if (HASH_ENTRY_UNUSED != SearchHashEntry( + hashindex, + hashcheck0, + hashcheck1, + MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT))) + app_fatal("Hash collision between \"%s\" and existing file\n",pszName); + + // find free slot in hash table + long lCount = HASH_ENTRIES; + DWORD entry = hashindex & (HASH_ENTRIES - 1); + while (lCount--) { + if ((sgpHashTbl+entry)->block == HASH_BLOCK_UNUSED) break; + if ((sgpHashTbl+entry)->block == HASH_BLOCK_FREED) break; + entry = (entry + 1) & (HASH_ENTRIES - 1); + } + if (lCount < 0) app_fatal("Out of hash space"); + + if (! pBlk) pBlk = get_free_block(&dwBlock); + (sgpHashTbl+entry)->hashcheck[0] = hashcheck0; + (sgpHashTbl+entry)->hashcheck[1] = hashcheck1; + (sgpHashTbl+entry)->lcid = MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT); + (sgpHashTbl+entry)->block = dwBlock; + return pBlk; +} + + +//****************************************************************** +//****************************************************************** +static BOOL WriteFileData( + const char * pszName, + const BYTE * pbData, + DWORD dwLen, + BLOCKENTRY * pBlk +) { + // DETERMINE THE FILE NAME PORTION OF THE PATH NAME + const char * pszTemp; + while (NULL != (pszTemp = strchr(pszName,':'))) + pszName = pszTemp + 1; + while (NULL != (pszTemp = strchr(pszName,'\\'))) + pszName = pszTemp + 1; + + // CREATE AN ENCRYPTION KEY BASED ON THE FILE NAME + DWORD key = Hash(pszName,HASH_ENCRYPTKEY); + DWORD sectors = (dwLen + SECTORSIZE - 1) / SECTORSIZE; + DWORD sectoroffsetsize = (sectors + 1) * sizeof(DWORD); + + // find free space for file + DWORD dwSizeAllocGuess = dwLen + sectoroffsetsize; + pBlk->offset = get_free_space(dwSizeAllocGuess,&pBlk->sizealloc); + pBlk->sizefile = dwLen; + pBlk->flags = MPQ_ADD_COMPRESSED | MPQ_ADD_ALLOCATED; + if (0xffffffff == SetFilePointer(sghArchive,pBlk->offset,NULL,FILE_BEGIN)) + return FALSE; + + DWORD sector = 0; + DWORD destsize = 0; + static BYTE buffer[SECTORSIZE]; + LPDWORD sectoroffsettable = NULL; + while (dwLen) { + for (int loop = 0; loop < SECTORSIZE; ++loop) + buffer[loop] += 0xAA; + + // PERFORM COMPRESSION + DWORD bytes = min(dwLen,SECTORSIZE); + CopyMemory(buffer,pbData,bytes); + pbData += bytes; + bytes = Compress(buffer,bytes); + + // LEAVE SPACE FOR THE SECTOR OFFSET TABLE. + if (! sector) { + sectoroffsetsize = (sectors+1)*sizeof(DWORD); + sectoroffsettable = (LPDWORD) DiabloAllocPtrSig(sectoroffsetsize,'MPQt'); + ZeroMemory(sectoroffsettable,sectoroffsetsize); + if (! WriteFile(sghArchive,sectoroffsettable,sectoroffsetsize,§oroffsetsize,NULL)) + goto error; + destsize += sectoroffsetsize; + } + + // SAVE THE SECTOR OFFSET + app_assert(sectoroffsettable); + *(sectoroffsettable+sector) = destsize; + + // PERFORM ENCRYPTION -- not encrypted for save files + // Encrypt((LPDWORD)buffer,bytes & 0xFFFFFFFC,key+sector); + + // WRITE THE SECTOR + if (! WriteFile(sghArchive,buffer,bytes,&bytes,NULL)) + goto error; + + ++sector; + if (dwLen > SECTORSIZE) + dwLen -= SECTORSIZE; + else + dwLen = 0; + destsize += bytes; + } + + app_assert(sectoroffsettable); + *(sectoroffsettable+sector) = destsize; + // bug in mopaq 1.91 -- fixed in 1.92 + // sector table is not supposed to be encrypted for unencrypted files + // Encrypt(sectoroffsettable,sectoroffsetsize,key+0xFFFFFFFF); + if (0xffffffff == SetFilePointer(sghArchive,-(LONG)destsize,NULL,FILE_CURRENT)) + goto error; + if (! WriteFile(sghArchive,sectoroffsettable,sectoroffsetsize,§oroffsetsize,NULL)) + goto error; + if (0xffffffff == SetFilePointer(sghArchive,destsize-sectoroffsetsize,NULL,FILE_CURRENT)) + goto error; + DiabloFreePtr(sectoroffsettable); + + // make sure the file fit into the hole we provided + app_assert(destsize <= pBlk->sizealloc); + + // give back any extra space we might have allocated + if (destsize < pBlk->sizealloc) { + DWORD dwLeftover = pBlk->sizealloc - destsize; + if (dwLeftover >= MIN_FREE_SIZE) { + pBlk->sizealloc = destsize; + add_free_block(pBlk->offset + destsize, dwLeftover); + } + } + + return TRUE; +error: + if (sectoroffsettable) DiabloFreePtr(sectoroffsettable); + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +BOOL MPQAddFile(const char * pszName,const BYTE * pbData,DWORD dwLen) { + app_assert(sghArchive != INVALID_HANDLE_VALUE); + app_assert(pszName); + app_assert(pbData); + app_assert(dwLen); + + // think positive + BOOL bResult = TRUE; + sgbChanged = TRUE; + + // delete any existing file with the same name + mpq_delete_file(pszName); + + // insert the new file data + BLOCKENTRY * pBlk = InsertIntoHash(pszName,NULL,0); + if (! WriteFileData(pszName,pbData,dwLen,pBlk)) { + mpq_delete_file(pszName); + return FALSE; + } + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +void MPQRenameFile(const char * pszOld,const char * pszNew) { + app_assert(sghArchive != INVALID_HANDLE_VALUE); + app_assert(pszOld); + app_assert(pszNew); + DWORD dwEntry = SearchHashName(pszOld); + if (dwEntry == HASH_ENTRY_UNUSED) + return; + + HASHENTRY * pHash = sgpHashTbl + dwEntry; + BLOCKENTRY * pBlk = sgpBlockTbl + pHash->block; + DWORD dwBlock = pHash->block; + + // we can't set the hash block to HASH_BLOCK_UNUSED, because + // we use closed hashing. Another file may have hashed + // to the same spot, and so was added to the hash table + // after this hash entry. Therefore, just mark the hash + // entry as freed, but not unused + pHash->block = HASH_BLOCK_FREED; + + // create a new hash entry which references the existing block + InsertIntoHash(pszNew,pBlk,dwBlock); + + // modified the file + sgbChanged = TRUE; +} + + +//****************************************************************** +//****************************************************************** +BOOL MPQFileExists(const char * pszName) { + app_assert(sghArchive != INVALID_HANDLE_VALUE); + app_assert(pszName); + return SearchHashName(pszName) != HASH_ENTRY_UNUSED; +} + + +//****************************************************************** +//****************************************************************** +static void CloseArchive(const char * pszArchive,BOOL bFree,DWORD dwChar) { + + if (bFree) { + DiabloFreePtr(sgpBlockTbl); + DiabloFreePtr(sgpHashTbl); + } + + if (sghArchive != INVALID_HANDLE_VALUE) { + CloseHandle(sghArchive); + sghArchive = INVALID_HANDLE_VALUE; + } + + if (sgbChanged) { + // since we wrote the file, update the last write timestamp + sgbChanged = FALSE; + MPQUpdateLastWriteTimeStamp(pszArchive,dwChar); + } + + if (sgbSaveCreationKey) { + // update the file creation timestamp if the archive was just created + sgbSaveCreationKey = FALSE; + MPQUpdateCreationTimeStamp(pszArchive,dwChar); + } +} + + +//****************************************************************** +//****************************************************************** +BOOL MPQOpenArchive(const char * pszArchive,BOOL bHide,DWORD dwChar) { + DWORD dwTemp; + app_assert(pszArchive); + app_assert(sghArchive == INVALID_HANDLE_VALUE); + InitializeHashSource(); + + if (! MPQSetAttributes(pszArchive,bHide)) + return FALSE; + + DWORD dwFlags = gbMaxPlayers > 1 ? FILE_FLAG_WRITE_THROUGH : 0; + + sgbSaveCreationKey = FALSE; + sghArchive = CreateFile( + pszArchive, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + dwFlags, + NULL + ); + + if (sghArchive == INVALID_HANDLE_VALUE) { + DWORD dwAttr = bHide ? MPQ_HIDE_ATTR : 0; + if (INVALID_HANDLE_VALUE == (sghArchive = CreateFile( + pszArchive, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + dwAttr | dwFlags, + NULL + ))) return FALSE; + sgbSaveCreationKey = TRUE; + sgbChanged = TRUE; + } + + // if the file is still loaded in memory, skip reading file + if (sgpBlockTbl && sgpHashTbl) + return TRUE; + + FULLHEADER fhdr; + ZeroMemory(&fhdr,sizeof(fhdr)); + if (! read_mpq_file_hdr(&fhdr,&sgdwNextFileStart)) + goto error; + + // allocate enough memory for all the blocks we might need + app_assert(! sgpBlockTbl); + sgpBlockTbl = (BLOCKENTRYPTR) DiabloAllocPtrSig(BLOCK_TBL_SIZE,'MPQt'); + ZeroMemory(sgpBlockTbl,BLOCK_TBL_SIZE); + + // read in block table + if (fhdr.hdr.blockcount) { + app_assert(fhdr.hdr.blockcount == BLOCK_ENTRIES); + app_assert(fhdr.hdr.blockoffset == BLOCK_TBL_OFFSET); + if (0xffffffff == SetFilePointer(sghArchive,BLOCK_TBL_OFFSET,NULL,FILE_BEGIN)) + goto error; + if (! ReadFile(sghArchive,sgpBlockTbl,BLOCK_TBL_SIZE,&dwTemp,NULL)) + goto error; + app_assert(BLOCK_TBL_SIZE == dwTemp); + Decrypt( + (LPDWORD) sgpBlockTbl, + BLOCK_TBL_SIZE, + Hash("(block table)", + HASH_ENCRYPTKEY) + ); + } + + // allocate enough memory for hash table + app_assert(! sgpHashTbl); + sgpHashTbl = (HASHENTRYPTR) DiabloAllocPtrSig(HASH_TBL_SIZE,'MPQt'); + FillMemory(sgpHashTbl,HASH_TBL_SIZE,0xff); + + // read in hash table + if (fhdr.hdr.hashcount) { + app_assert(fhdr.hdr.hashcount == HASH_ENTRIES); + app_assert(fhdr.hdr.hashoffset == HASH_TBL_OFFSET); + if (0xffffffff == SetFilePointer(sghArchive,HASH_TBL_OFFSET,NULL,FILE_BEGIN)) + goto error; + if (! ReadFile(sghArchive,sgpHashTbl,HASH_TBL_SIZE,&dwTemp,NULL)) + goto error; + app_assert(HASH_TBL_SIZE == dwTemp); + Decrypt( + (LPDWORD) sgpHashTbl, + HASH_TBL_SIZE, + Hash("(hash table)", + HASH_ENCRYPTKEY) + ); + } + + return TRUE; + +error: + CloseArchive(pszArchive,TRUE,dwChar); + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +BOOL MPQCloseArchive(const char * pszArchive,BOOL bFree,DWORD dwChar) { + // write archive data only if the file open & changed + BOOL bResult; + if (sghArchive == INVALID_HANDLE_VALUE) bResult = TRUE; + else if (! sgbChanged) bResult = TRUE; + else if (! SetEOF()) bResult = FALSE; + else if (! WriteFileHeader()) bResult = FALSE; + else if (! WriteBlockTable()) bResult = FALSE; + else if (! WriteHashTable()) bResult = FALSE; + else bResult = TRUE; + + CloseArchive(pszArchive,bFree,dwChar); + return bResult; +} diff --git a/src/MPQAPI.H b/src/MPQAPI.H new file mode 100644 index 0000000..4ad09c9 --- /dev/null +++ b/src/MPQAPI.H @@ -0,0 +1,85 @@ +//****************************************************************** +// MPQapi.H +// File pack API +// By Michael O'Brien (6/1/96) && Patrick Wyatt (6/24/96) && Dan Liebgold (9/26/96) +//****************************************************************** + + +#ifndef _MPQAPI +#define _MPQAPI + + +// diablo specific +#define MAX_CHARACTERS 10 // saved on disk + + +//****************************************************************** +// constants +//****************************************************************** + #define MPQ_ADD_COMPRESSED 0x00000100 + #define MPQ_ADD_ENCRYPTED 0x00010000 + #define MPQ_ADD_ALLOCATED 0x80000000 + + #define HASH_INDEX 0 + #define HASH_CHECK0 1 + #define HASH_CHECK1 2 + #define HASH_ENCRYPTKEY 3 + #define HASH_ENCRYPTDATA 4 + #define HASH_ENTRY_UNUSED 0xFFFFFFFF + + // possible values for HASHENTRY.block + #define HASH_BLOCK_FREED 0xFFFFFFFE + #define HASH_BLOCK_UNUSED 0xFFFFFFFF + + #define SIGNATURE 0x1A51504D + #define SIGNATURELENGTH 72 + #define VERSION 0 + #define SECTORSIZEID 3 + #define SECTORSIZE (512 << SECTORSIZEID) + + +//****************************************************************** +// structures used in output file +//****************************************************************** + typedef struct _FILEHEADER { + DWORD signature; + DWORD headersize; + DWORD filesize; + WORD version; + WORD sectorsizeid; + DWORD hashoffset; + DWORD blockoffset; + DWORD hashcount; + DWORD blockcount; + } FILEHEADER, *FILEHEADERPTR; + + typedef struct _HASHENTRY { + DWORD hashcheck[2]; + LCID lcid; + DWORD block; + } HASHENTRY, *HASHENTRYPTR; + + typedef struct _BLOCKENTRY { + DWORD offset; + DWORD sizealloc; + DWORD sizefile; + DWORD flags; + } BLOCKENTRY, *BLOCKENTRYPTR; + + + BOOL MPQOpenArchive(const char * pszArchive,BOOL bHide,DWORD dwChar); + BOOL MPQCloseArchive(const char * pszArchive,BOOL bFree,DWORD dwChar); + + typedef BOOL (CALLBACK * TGetNameFcn)(DWORD dwIndex,char szPath[MAX_PATH]); + void MPQDeleteFiles(TGetNameFcn fnGetName); + void MPQDeleteFile(const char * pszName); + BOOL MPQAddFile(const char * pszName,const BYTE * pbData,DWORD dwLen); + void MPQRenameFile(const char * pszOld,const char * pszNew); + BOOL MPQFileExists(const char * pszName); + + BOOL MPQCompareTimeStamps(const char * pszArchive,DWORD dwChar); + void MPQUpdateCreationTimeStamp(const char * pszArchive,DWORD dwChar); + void MPQMungeStamps(DWORD dwChar); + + +#endif diff --git a/src/MSG.CPP b/src/MSG.CPP new file mode 100644 index 0000000..2414dd5 --- /dev/null +++ b/src/MSG.CPP @@ -0,0 +1,4246 @@ +//****************************************************************** +// msg.cpp +//****************************************************************** + +/* dig.patch1.start.1/30/97 + Replaced all occurrences of "DObject" with "DObjectStr" + Replaced all occurrences of "DMonster" with "DMonsterStr" + This was done because of a debugger bug. The debugger was + not able to distinguish between the global variable dObject + and the structure name DObject. + The change should have no effect on the executable. + dig.patch1.end.1/30/97 +*/ + +/* PATCH1.JMM + Added extensive logging to the msg handlers. All droplogs do not + compile in non-_DEBUG compiles. +*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "msg.h" +#include "multi.h" +#include "engine.h" +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "monstdat.h" +#include "inv.h" +#include "lighting.h" +#include "objects.h" +#include "objdat.h" +#include "spells.h" +#include "spelldat.h" +#include "control.h" +#include "dead.h" +#include "storm.h" +#include "diabloui.h" +#include "cursor.h" +#include "automap.h" +#include "portal.h" +#include "quests.h" +#include "missiles.h" +#include "drlg_l1.h" +#include "trigs.h" +#include "effects.h" + +/*-----------------------------------------------------------------------** +** extern +**-----------------------------------------------------------------------*/ +DWORD Compress(LPBYTE data, DWORD bytes); +void Expand(LPBYTE data, DWORD bytes, DWORD dwMaxBytes); +void M_ClearSquares(int nMonster); +void Obj_Trap(int i); +void StartStand(int pnum, int dir); +void SyncPlrAnim(int p); +void SyncInitPlr(int pnum); +void SendLocalPlayerInfo(int pnum,BYTE bCmd); +void recv_plrinfo(int pnum,const TCmdPlrInfoHdr * p,BOOL bAck); +void dthread_SendPlayerInfoChunk(int pnum,BYTE bCmd,const BYTE * pbSrc,DWORD dwLen); +void plrmsg_add(int pnum,const char * pszStr); +void M_UpdateLeader(int i); +void gamemenu_off(); +void DeleteItem(int ii, int i); +void SyncPortal(int i, BOOL open, int x, int y, int level, int ltype); +void __cdecl sysmsg_add(const char * pszFmt,...); +void NextPlrLevel(int pnum); +void nthread_set_delta_request(); +void NewPlrAnim(int pnum, BYTE *pAnim, int numFrames, int Delay, long width); +void AddWarpMissile(int i, int x, int y); + +// JMM.PATCH1.2.22.97 +void sysmsg_add_string(const char * pszMsg); +// END.JMM.PATCH1.2.22.97 + +void OpenNaKrul(); +void OpenNest(); +void OpenCrypt(); + +/*-----------------------------------------------------------------------** +** public +**-----------------------------------------------------------------------*/ +BOOL deltaload = FALSE; +BYTE gbBufferMsgs = BUFFER_OFF; + + +/*-----------------------------------------------------------------------** +** private +**-----------------------------------------------------------------------*/ +#pragma pack(push,1) + +typedef struct TCmdLoc { + BYTE bCmd; + BYTE x; + BYTE y; +} TCmdLoc; + +typedef struct TCmdLocParam1 { + BYTE bCmd; + BYTE x; + BYTE y; + WORD wParam1; +} TCmdLocParam1; + +typedef struct TCmdLocParam2 { + BYTE bCmd; + BYTE x; + BYTE y; + WORD wParam1; + WORD wParam2; +} TCmdLocParam2; + +typedef struct TCmdLocParam3 { + BYTE bCmd; + BYTE x; + BYTE y; + WORD wParam1; + WORD wParam2; + WORD wParam3; +} TCmdLocParam3; + +typedef struct TCmdParam1 { + BYTE bCmd; + WORD wParam1; +} TCmdParam1; + +typedef struct TCmdParam2 { + BYTE bCmd; + WORD wParam1; + WORD wParam2; +} TCmdParam2; + +typedef struct TCmdParam3 { + BYTE bCmd; + WORD wParam1; + WORD wParam2; + WORD wParam3; +} TCmdParam3; + +typedef struct TCmdString { + BYTE bCmd; + char str[MAX_SEND_STR_LEN]; +} TCmdString; + +typedef struct TCmdGolem { + BYTE bCmd; + BYTE _mx; + BYTE _my; + BYTE _mdir; + BYTE _menemy; + long _mhitpoints; + BYTE _currlevel; +} TCmdGolem; + +typedef struct TCmdQuest { + BYTE bCmd; + BYTE q; + BYTE qstate; + BYTE qlog; + BYTE qvar1; +} TCmdQuest; + +typedef struct TCmdGItem { + BYTE bCmd; + BYTE bMaster; + BYTE bPnum; + BYTE bCursitem; + // drb.patch1.start.2/05/97 + BYTE bLevel; + // drb.patch1.end.2/05/97 + BYTE x; + BYTE y; + WORD wIndx; + WORD wCI; + DWORD dwSeed; + BYTE bId; + BYTE bDur; + BYTE bMDur; + BYTE bCh; + BYTE bMCh; + WORD wValue; + DWORD dwBuff; + DWORD dwTime; + WORD wPLToHit; + WORD wMaxDam; + BYTE bMinStr; + BYTE bMinMag; + BYTE bMinDex; + BYTE bAC; +} TCmdGItem; + +typedef struct TCmdPItem { + BYTE bCmd; + BYTE x; + BYTE y; + WORD wIndx; + WORD wCI; + DWORD dwSeed; + BYTE bId; + BYTE bDur; + BYTE bMDur; + BYTE bCh; + BYTE bMCh; + WORD wValue; + DWORD dwBuff; + WORD wPLToHit; + WORD wMaxDam; + BYTE bMinStr; + BYTE bMinMag; + BYTE bMinDex; + BYTE bAC; +} TCmdPItem; +typedef struct TCmdChItem { + BYTE bCmd; + BYTE bLoc; + WORD wIndx; + WORD wCI; + DWORD dwSeed; + // drb.patch1.start.02/10/97 + BYTE bId; + // drb.patch1.end.02/10/97 +} TCmdChItem; + +typedef struct TCmdDelItem { + BYTE bCmd; + BYTE bLoc; +} TCmdDelItem; + + +typedef struct TCmdDamage{ + BYTE bCmd; + BYTE bPlr; + DWORD dwDam; +} TCmdDamage; + +typedef struct TCmdMonstDamage{ + BYTE bCmd; + WORD wMonst; + DWORD dwDam; +} TCmdMonstDamage; + +typedef struct TFakeCmdPlr { + BYTE bCmd; + BYTE bPlr; +} TFakeCmdPlr; + +typedef struct TFakeDropPlr { + BYTE bCmd; + BYTE bPlr; + DWORD dwReason; +} TFakeDropPlr; +// stuff that is on every level + +typedef struct DMonsterStr { + BYTE _mx; + BYTE _my; + BYTE _mdir; + BYTE _menemy; + BYTE _msquelch; + long _mhitpoints; +} DMonsterStr; + +typedef struct DObjectStr { + BYTE bCmd; +} DObjectStr; + +typedef struct DLevel { + TCmdPItem item[MAXITEMS]; + DObjectStr object[MAXOBJECTS]; + DMonsterStr monster[MAXMONSTERS]; +} DLevel; + +typedef struct LocalLevel { + BYTE automapsv[AUTOMAPX][AUTOMAPY]; +} LocalLevel; + +// stuff which is dungeon global +typedef struct DPortal { + BYTE x; + BYTE y; + BYTE level; + BYTE ltype; + BYTE setlvl; +} DPortal; +typedef struct MultiQuests { + BYTE qstate; + BYTE qlog; + BYTE qvar1; +} MultiQuests; +typedef struct DJunk { + DPortal portal[MAXPORTAL]; + MultiQuests quests[MAXMULTIQUESTS + 1]; +} DJunk; + +#pragma pack(pop) + +#define INIT_VAL 0xff +static DJunk sgJunk; +static DLevel sgLevels[NUMLEVELS]; // sent to other players +static LocalLevel sgLocals[NUMLEVELS]; // not sent + +// number of chunks of info we must receive to get all delta info +// 16 levels + 1 town level = NUMLEVELS +// + 1 global "junk" chunk +// + 1 terminator +// + 1 startup +// + 1 "99%" complete +#define DELTA_CHUNKS (NUMLEVELS+1+1+1+1) + +// allocate extra space to account for flag byte +#define SEND_LEVEL_SIZE (max(sizeof(DLevel),sizeof(DJunk)) + 1) + +// buffer to receive level information +static BYTE sgbRecvLevel[SEND_LEVEL_SIZE]; +static BYTE sgbRecvCmd; +static DWORD sgdwRecvOffset; +static BYTE sgbDeltaChunks; +static BYTE sgbDeltaChanged; +static DWORD sgdwOwnerWait; + + +// item flags which go into sgLevel[].item[].bCmd + // item generated on floor of dungeon -- presently on floor + #define ITEM_GEN_FLOOR 0 + + // item generated on floor of dungeon -- presently not on floor + #define ITEM_GEN_TAKEN 1 + + // item was dropped -- presently on floor + #define ITEM_DROP_FLOOR 2 + + // we don't have to keep track of items which were not originally + // part of the dungeon and were dropped and then picked up + + // item slot not in use + #define ITEM_FREE INIT_VAL + + +//****************************************************************** +//****************************************************************** +// time to keep resending messages if they don't make sense yet +#define RESEND_TIME 5000 // milliseconds + + +//****************************************************************** +// delta buffering +//****************************************************************** +#pragma pack(push,1) + +// this structure contains a whole bunch of link packets +typedef struct TMegaPkt { + struct TMegaPkt * pNext; + DWORD dwSpaceLeft; + BYTE data[32000]; +} TMegaPkt; + +#pragma pack(pop) + +static TMegaPkt * sgpMegaPkt; +static TMegaPkt * sgpCurrPkt; +static int sgnCurrMegaPlayer; + +// PATCH1.JMM +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +DWORD dwRecCount = 0; + +#if _DEBUG +void __cdecl DROPLOG(const char * pszFmt,...) { + extern BOOL gbDumpDropLog; + if (! gbDumpDropLog) return; + static FILE * f = NULL; + if (! f) f = fopen("c:\\droplog.txt","wb"); + if (! f) return; + + va_list args; + va_start(args,pszFmt); + fprintf(f,"(%8.8x,%2.2d):",dwRecCount,numitems); + vfprintf(f,pszFmt,args); + fflush(f); + va_end(args); +} +#else +#define DROPLOG // +#endif +// ENDPATCH1.JMM + + + +//****************************************************************** +//****************************************************************** +static void mega_add_pkt() { + sgpCurrPkt = (TMegaPkt *) DiabloAllocPtrSig(sizeof(TMegaPkt),'MEGA'); + sgpCurrPkt->pNext = NULL; + sgpCurrPkt->dwSpaceLeft = sizeof(sgpCurrPkt->data); + + TMegaPkt ** ppCurr = &sgpMegaPkt; + while (*ppCurr) ppCurr = &(*ppCurr)->pNext; + *ppCurr = sgpCurrPkt; +} + + +//****************************************************************** +//****************************************************************** +static void mega_free_pkts() { + while (sgpMegaPkt) { + sgpCurrPkt = sgpMegaPkt->pNext; + DiabloFreePtr(sgpMegaPkt); + sgpMegaPkt = sgpCurrPkt; + } + + // NOTE: both sgpMegaPkt & sgpCurrPkt are NULL +} + + +//****************************************************************** +//****************************************************************** +static void mega_run_pkts() { + int nPlayer = -1; + for (TMegaPkt * pMega = sgpMegaPkt; pMega; pMega = pMega->pNext) { + const BYTE * pbData = pMega->data; + DWORD dwBytes = sizeof(pMega->data); + while (dwBytes != pMega->dwSpaceLeft) { + if (*pbData == FAKE_CMD_SETID) { + const TFakeCmdPlr * p = (const TFakeCmdPlr *) pbData; + pbData += sizeof(TFakeCmdPlr); + dwBytes -= sizeof(TFakeCmdPlr); + nPlayer = p->bPlr; + } + else if (*pbData == FAKE_CMD_DROPID) { + const TFakeDropPlr * p = (const TFakeDropPlr *) pbData; + pbData += sizeof(TFakeDropPlr); + dwBytes -= sizeof(TFakeDropPlr); + void unbuffer_remove_player(int pnum,DWORD dwReason); + unbuffer_remove_player(p->bPlr,p->dwReason); + } + else { + app_assert((DWORD) nPlayer < MAX_PLRS); + const TCmd * p = (const TCmd *) pbData; + DWORD dwTemp = ParseCmd(nPlayer,p); + pbData += dwTemp; + dwBytes -= dwTemp; + } + } + } +} + + +//****************************************************************** +//****************************************************************** +static void mega_add_data(int pnum,const void * pMsg,DWORD dwLen) { + app_assert((DWORD) pnum < MAX_PLRS); + app_assert(pMsg); + app_assert(dwLen <= gdwLargestMsgSize); + + if (pnum != sgnCurrMegaPlayer) { + // add a command to set the current player + TFakeCmdPlr cmd; + sgnCurrMegaPlayer = pnum; + cmd.bCmd = FAKE_CMD_SETID; + cmd.bPlr = (BYTE) pnum; + mega_add_data(pnum,&cmd,sizeof(cmd)); + } + + // if there isn't enough space in the current megapkt, add another + app_assert(sgpCurrPkt); + if (sgpCurrPkt->dwSpaceLeft < dwLen) + mega_add_pkt(); + app_assert(sgpCurrPkt->dwSpaceLeft >= dwLen); + + // add data to megapacket + CopyMemory( + sgpCurrPkt->data + sizeof(sgpCurrPkt->data) - sgpCurrPkt->dwSpaceLeft, + pMsg, + dwLen + ); + sgpCurrPkt->dwSpaceLeft -= dwLen; +} + + +//****************************************************************** +//****************************************************************** +void buffer_drop_player(int pnum,DWORD dwReason) { + TFakeDropPlr cmd; + cmd.bCmd = FAKE_CMD_DROPID; + cmd.bPlr = (BYTE) pnum; + cmd.dwReason = dwReason; + mega_add_data(pnum,&cmd,sizeof(cmd)); +} + + +//****************************************************************** +//****************************************************************** +// pjw.patch2.start +static int CALLBACK delta_progress() { + if (sgbDeltaChunks == 0) { + // wait until we receive master player's future + // turn before we process our first turn. This is + // designed so that we don't start several turns ahead + // of the master player and stay there forever. We are + // waiting for turn X from all players. We wait for + // turn (X+gdwTurnsInTransit) from the master player, which + // means that the master player processed turn X and has + // sent turns X+1 and X+2. When we process turn X, we will be + // synced with the master player less the one-way packet + // latency from the master player. + DWORD dwTurns; + nthread_fill_sync_queue(0,0); + if (! SNetGetOwnerTurnsWaiting(&dwTurns)) { + if (GetLastError() == SNET_ERROR_NOT_IN_GAME) + return 100; + } + + // wait a maximum of 2 seconds before we give + // up syncing and just try for whatever we can get + // if a turn got dropped by the owner, it is possible + // we could wait forever for the owner, while he waits + // forever for us to resend the dropped turn. + if (GetTickCount() - sgdwOwnerWait <= 2000) { + if (dwTurns < gdwTurnsInTransit) + return 0; + } + + sgbDeltaChunks++; + } + + // handle asynchronous messages + NetReceivePackets(); + + // handle synchronous messages + BOOL bSendAsync; + nthread_fill_sync_queue(0,0); + // pjw.patch2.start -- if we call nthread_msg_check() without + // protection against "overcalling" then the gameclock will get + // continually reset and other systems will drop into timeout mode + // nthread_msg_check(&bSendAsync); + if (nthread_run_gameloop(FALSE)) nthread_msg_check(&bSendAsync); + // pjw.patch2.end + + // if the game was destroyed, return "100% complete" to exit dialog + if (gbGameDestroyed) return 100; + + // if the person sending us delta info dropped out, + // then we need to re-request the delta information + if (gbDeltaSender >= MAX_PLRS) { + sgbRecvCmd = CMD_DLEVEL_END; + sgbDeltaChunks = 0; + gbDeltaSender = (BYTE) myplr; + nthread_set_delta_request(); + } + + // make bar "full" + if (sgbDeltaChunks == DELTA_CHUNKS - 1) { + sgbDeltaChunks++; + return 99; + } + + // return completion status + return (sgbDeltaChunks * 100) / DELTA_CHUNKS; +} +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +BOOL wait_delta_info() { + app_assert(ghMainWnd); + app_assert(! sgpMegaPkt); + app_assert(! sgpCurrPkt); + mega_add_pkt(); + + sgbRecvCmd = CMD_DLEVEL_END; + sgbDeltaChunks = 0; + gbBufferMsgs = BUFFER_ON; + sgnCurrMegaPlayer = -1; + sgdwOwnerWait = GetTickCount(); + + BOOL bResult = UiProgressDialog( + ghMainWnd, + "Waiting for game data...", + TRUE, // allow abort + delta_progress, + GAME_FRAMES_PER_SECOND // calls per second + ); + + // done buffering messages, but don't go into BUFFER_PROCESS + // mode until we've successfully loaded the level + gbBufferMsgs = BUFFER_OFF; + + if (! bResult) { + // no message -- user canceled + mega_free_pkts(); + return FALSE; + } + else if (gbGameDestroyed) { + app_warning("The game ended"); + mega_free_pkts(); + return FALSE; + } + else if (sgbDeltaChunks != DELTA_CHUNKS) { + app_warning("Unable to get level data"); + mega_free_pkts(); + return FALSE; + } + + // leave the delta information around + // until the game level has been loaded + // and then run all the accumulated packets + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +void run_delta_info() { + if (gbMaxPlayers == 1) return; + + app_assert(currlevel == 0); + app_assert(plr[myplr].plrlevel == 0); + + gbBufferMsgs = BUFFER_PROCESS; + mega_run_pkts(); + gbBufferMsgs = BUFFER_OFF; + + mega_free_pkts(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BYTE * dbuild_items(BYTE * pbData,const TCmdPItem * pItem) { + for (int i = 0; i < MAXITEMS; i++,pItem++) { + if (pItem->bCmd == INIT_VAL) { + *pbData++ = INIT_VAL; + } + else { + //CopyMemory(pbData,pItem,sizeof(TCmdPItem)); + *(reinterpret_cast(pbData)) = *pItem; + pbData += sizeof(TCmdPItem); + } + } + + return pbData; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static const BYTE * dparse_items(const BYTE * pbData,TCmdPItem * pItem) { + for (int i = 0; i < MAXITEMS; i++,pItem++) { + if (*pbData == INIT_VAL) { + FillMemory(pItem,sizeof(TCmdPItem),INIT_VAL); + pbData++; + } + else { + //CopyMemory(pItem,pbData,sizeof(TCmdPItem)); + *pItem = *(reinterpret_cast(pbData)); + pbData += sizeof(TCmdPItem); + } + } + + return pbData; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BYTE * dbuild_objects(BYTE * pbData,const DObjectStr * pObj) { + // the object structure is only one byte, so just + // rely upon data compression to make it smaller + CopyMemory(pbData,pObj,MAXOBJECTS * sizeof(DObjectStr)); + return pbData + MAXOBJECTS * sizeof(DObjectStr); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static const BYTE * dparse_objects(const BYTE * pbData,DObjectStr * pObj) { + // the object structure is only one byte, so just + // rely upon data compression to make it smaller + CopyMemory(pObj,pbData,MAXOBJECTS * sizeof(DObjectStr)); + return pbData + MAXOBJECTS * sizeof(DObjectStr); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BYTE * dbuild_monsters(BYTE * pbData,const DMonsterStr * pM) { + for (int m = 0; m < MAXMONSTERS; m++,pM++) { + if (pM->_mx == INIT_VAL) { + *pbData++ = INIT_VAL; + } + else { + //CopyMemory(pbData,pM,sizeof(DMonsterStr)); + *(reinterpret_cast(pbData)) = *pM; + pbData += sizeof(DMonsterStr); + } + } + + return pbData; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static const BYTE * dparse_monsters(const BYTE * pbData,DMonsterStr * pM) { + for (int m = 0; m < MAXMONSTERS; m++,pM++) { + if (*pbData == INIT_VAL) { + FillMemory(pM,sizeof(DMonsterStr),INIT_VAL); + pbData++; + } + else { + //CopyMemory(pM,pbData,sizeof(DMonsterStr)); + *pM = *(reinterpret_cast (pbData)); + pbData += sizeof(DMonsterStr); + } + } + + return pbData; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +extern QuestData questlist[]; + +static BYTE * dbuild_junk(BYTE * pbData) { + for (int i = 0; i < MAXPORTAL; i++) { + if (sgJunk.portal[i].x == INIT_VAL) { + *pbData++ = INIT_VAL; + } + else { + //CopyMemory(pbData,&sgJunk.portal[i],sizeof(DPortal)); + *(reinterpret_cast(pbData)) = sgJunk.portal[i]; + pbData += sizeof(DPortal); + } + } + i = 0; + for (int q = 0; q < MAXQUESTS; q++) { + if (questlist[q]._qflags & QFLAG_MULTI) { + sgJunk.quests[i].qlog = quests[q]._qlog; + sgJunk.quests[i].qstate = quests[q]._qactive; + sgJunk.quests[i].qvar1 = quests[q]._qvar1; + //CopyMemory(pbData,&sgJunk.quests[i],sizeof(MultiQuests)); + *(reinterpret_cast(pbData)) = sgJunk.quests[i]; + pbData += sizeof(MultiQuests); + i++; + } + } + + return pbData; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void dparse_junk(const BYTE * pbData) { + int i; + for (i = 0; i < MAXPORTAL; i++) { + if (*pbData == INIT_VAL) { + FillMemory(&sgJunk.portal[i],sizeof(DPortal),INIT_VAL); + pbData++; + SyncPortal(i, FALSE, 0, 0, 0, 0); + } + else { + //CopyMemory(&sgJunk.portal[i],pbData,sizeof(DPortal)); + sgJunk.portal[i] = *(reinterpret_cast(pbData)); + pbData += sizeof(DPortal); + SyncPortal(i, TRUE, sgJunk.portal[i].x, sgJunk.portal[i].y, sgJunk.portal[i].level, sgJunk.portal[i].ltype); + } + } + i = 0; + for (int q = 0; q < MAXQUESTS; q++) { + if (questlist[q]._qflags & QFLAG_MULTI) { + //CopyMemory(&sgJunk.quests[i],pbData,sizeof(MultiQuests)); + sgJunk.quests[i] = *(reinterpret_cast(pbData)); + pbData += sizeof(MultiQuests); + quests[q]._qlog = sgJunk.quests[i].qlog; + quests[q]._qactive = sgJunk.quests[i].qstate; + quests[q]._qvar1 = sgJunk.quests[i].qvar1; + i++; + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD compress_chunk(BYTE * pbStart,BYTE * pbEnd) { + // calculate length excluding leading byte + DWORD dwLen = pbEnd - pbStart - 1; + + // compress data excluding leading byte + DWORD dwBytes = Compress(pbStart + 1,dwLen); + + // set compress flag ==> TRUE = compressed + *pbStart = (dwLen != dwBytes); + + // add one extra byte for compress flag + return dwBytes + 1; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DeltaSendAllLevels(int pnum) { + // send all delta information to player pnum + if (sgbDeltaChanged) { + BYTE * pbData; + DWORD dwBytes; + BYTE * pbBase = (BYTE *) DiabloAllocPtrSig(SEND_LEVEL_SIZE,'DLTt'); + for (int bLevel = 0; bLevel < NUMLEVELS; bLevel++) { + // save 1 byte for compress/uncompress flag + pbData = pbBase + 1; + + // build level data + pbData = dbuild_items(pbData,&sgLevels[bLevel].item[0]); + pbData = dbuild_objects(pbData,&sgLevels[bLevel].object[0]); + pbData = dbuild_monsters(pbData,&sgLevels[bLevel].monster[0]); + dwBytes = compress_chunk(pbBase,pbData); + dthread_SendPlayerInfoChunk(pnum,CMD_DLEVEL_0 + bLevel,pbBase,dwBytes); + } + + // send junk chunk -- save one byte for compress/uncompress flag + pbData = dbuild_junk(pbBase + 1); + dwBytes = compress_chunk(pbBase,pbData); + dthread_SendPlayerInfoChunk(pnum,CMD_DLEVEL_JUNK,pbBase,dwBytes); + DiabloFreePtr(pbBase); + } + + // send 1 byte terminator chunk + BYTE c = 0; // mark as "uncompressed" + dthread_SendPlayerInfoChunk(pnum,CMD_DLEVEL_END,&c,1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void dparse_chunk(BYTE bMsg,DWORD dwLen) { + // first byte is a flag which indicates whether the data is compressed + if (sgbRecvLevel[0]) Expand(&sgbRecvLevel[1],dwLen,sizeof(sgbRecvLevel) - 1); + const BYTE * pbData = &sgbRecvLevel[1]; + + if (bMsg == CMD_DLEVEL_JUNK) { + dparse_junk(pbData); + } + else if (bMsg >= CMD_DLEVEL_0 && bMsg <= CMD_DLEVEL_24) { + BYTE bLevel = bMsg - CMD_DLEVEL_0; + pbData = dparse_items(pbData,&sgLevels[bLevel].item[0]); + pbData = dparse_objects(pbData,&sgLevels[bLevel].object[0]); + pbData = dparse_monsters(pbData,&sgLevels[bLevel].monster[0]); + } + else { + app_fatal("msg:1"); + } + + sgbDeltaChanged = TRUE; + sgbDeltaChunks++; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD dreceive_chunk(int pnum,const TCmdPlrInfoHdr * p) { + + if (gbDeltaSender != pnum) { + // we are unexpectedly receiving delta info from somebody + // if they aren't sending us the starting information, ignore it + // otherwise, make them the new delta source + if (p->bCmd == CMD_DLEVEL_END) { + // we're getting an end chunk without any intervening delta + // which means there is no delta information + } + else if (p->bCmd != CMD_DLEVEL_0 || p->wOffset != 0) { + return p->wBytes + sizeof(TCmdPlrInfoHdr); + } + gbDeltaSender = (BYTE) pnum; + sgbRecvCmd = CMD_DLEVEL_END; + } + + if (sgbRecvCmd == CMD_DLEVEL_END) { + if (p->bCmd == CMD_DLEVEL_END) { + // we received the end command immediately, which + // means there was no level delta info + sgbDeltaChunks = DELTA_CHUNKS - 1; // set 99% done + return p->wBytes + sizeof(TCmdPlrInfoHdr); + } + + if (p->bCmd != CMD_DLEVEL_0 || p->wOffset != 0) { + // someone is in the middle of sending us info + // but we don't have the beginning + // just ignore the message + return p->wBytes + sizeof(TCmdPlrInfoHdr); + } + + // we just started receiving new data from the player + sgdwRecvOffset = 0; + sgbRecvCmd = p->bCmd; + } + else if (sgbRecvCmd != p->bCmd) { + // since we are receiving a new delta chunk, + // we must have finished receiving the last delta chunk. + // process last chunk before handling next chunk. + // ???dparse_chunk(sgbRecvCmd,sgdwRecvOffset + p->wBytes); + dparse_chunk(sgbRecvCmd,sgdwRecvOffset); + + // what's the new command? + if (p->bCmd == CMD_DLEVEL_END) { + // set 99% done flag + sgbDeltaChunks = DELTA_CHUNKS - 1; + sgbRecvCmd = CMD_DLEVEL_END; + return p->wBytes + sizeof(TCmdPlrInfoHdr); + } + + sgdwRecvOffset = 0; + sgbRecvCmd = p->bCmd; + } + + app_assert(p->wOffset == sgdwRecvOffset); + CopyMemory( &sgbRecvLevel[p->wOffset], + ((BYTE *)p) + sizeof(TCmdPlrInfoHdr), + p->wBytes + ); + + sgdwRecvOffset += p->wBytes; + return p->wBytes + sizeof(TCmdPlrInfoHdr); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void delta_init() { + sgbDeltaChanged = FALSE; + FillMemory(&sgJunk,sizeof sgJunk,INIT_VAL); + FillMemory(&sgLevels[0],sizeof sgLevels,INIT_VAL); + ZeroMemory(sgLocals,sizeof sgLocals); + deltaload = FALSE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel) { + if (gbMaxPlayers == 1) return; + app_assert((DWORD)mi < MAXMONSTERS); + app_assert(x < DMAXX); + app_assert(y < DMAXY); + app_assert(bLevel < NUMLEVELS); + + sgbDeltaChanged = TRUE; + DMonsterStr * p = &sgLevels[bLevel].monster[mi]; + p->_mx = x; + p->_my = y; + p->_mdir = monster[mi]._mdir; + p->_mhitpoints = 0; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void delta_monster_hp(int mi,long hp,BYTE bLevel) { + if (gbMaxPlayers == 1) return; + app_assert((DWORD)mi < MAXMONSTERS); + app_assert(bLevel < NUMLEVELS); + + sgbDeltaChanged = TRUE; + DMonsterStr * p = &sgLevels[bLevel].monster[mi]; + if (p->_mhitpoints > hp) p->_mhitpoints = hp; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void delta_sync_monster(const TSyncMonster * pSync,BYTE bLevel) { + if (gbMaxPlayers == 1) return; + app_assert(pSync != NULL); + app_assert(bLevel < NUMLEVELS); + + sgbDeltaChanged = TRUE; + DMonsterStr * pD = &sgLevels[bLevel].monster[pSync->_mndx]; + + // is this monster already dead? + if (! pD->_mhitpoints) return; + + pD->_mx = pSync->_mx; + pD->_my = pSync->_my; + pD->_msquelch = 255; + + //app_assert((DWORD) pSync->_menemy < MAX_PLRS); @@@ Taken out becasue monster enemy could be a monster + pD->_menemy = pSync->_menemy; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void delta_sync_golem(const TCmdGolem * pG, int pnum, BYTE bLevel) { + if (gbMaxPlayers == 1) return; + + app_assert(bLevel < NUMLEVELS); + app_assert(bLevel != 0); + + sgbDeltaChanged = TRUE; + DMonsterStr * pD = &sgLevels[bLevel].monster[pnum]; + + pD->_mx = pG->_mx; + pD->_my = pG->_my; + pD->_msquelch = 255; + pD->_menemy = pG->_menemy; + pD->_mdir = pG->_mdir; + pD->_mhitpoints = pG->_mhitpoints; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void delta_leave_sync(BYTE bLevel) { + if (gbMaxPlayers == 1) return; + + // recycle town store seeds + if (currlevel == 0) glSeedTbl[0] = GetRndSeed(); + if (currlevel <= 0) return; + app_assert(bLevel < NUMLEVELS); + + for (int i = 0; i < nummonsters; i++) { + int ii = monstactive[i]; + if (monster[ii]._mhitpoints == 0) continue; + + sgbDeltaChanged = TRUE; + DMonsterStr * pD = &sgLevels[bLevel].monster[ii]; + pD->_mx = monster[ii]._mx; + pD->_my = monster[ii]._my; + pD->_mdir = monster[ii]._mdir; + pD->_menemy = encode_enemy(ii); + //app_assert((DWORD) pD->_menemy < MAX_PLRS); + pD->_mhitpoints = monster[ii]._mhitpoints; + pD->_msquelch = monster[ii]._msquelch; + } + + // copy automap + app_assert(sizeof(sgLocals[bLevel].automapsv) == sizeof(automapview)); + CopyMemory( + &sgLocals[bLevel].automapsv[0][0], + &automapview[0][0], + sizeof(sgLocals[bLevel].automapsv) + ); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void delta_sync_object(int oi,BYTE bCmd,BYTE bLevel) { + if (gbMaxPlayers == 1) return; + app_assert((DWORD)oi < MAXOBJECTS); + app_assert(bLevel < NUMLEVELS); + + sgbDeltaChanged = TRUE; + DObjectStr * p = &sgLevels[bLevel].object[oi]; + p->bCmd = bCmd; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL delta_get_item(const TCmdGItem * pI, BYTE bLevel) { + if (gbMaxPlayers == 1) return(TRUE); + app_assert(pI != NULL); + app_assert(bLevel < NUMLEVELS); + + TCmdPItem * pD = &sgLevels[bLevel].item[0]; + for (int i = 0; i < MAXITEMS; i++,pD++) { + + // find item + if (pD->bCmd == ITEM_FREE) continue; + if (pD->wIndx != pI->wIndx) continue; + if (pD->wCI != pI->wCI) continue; + if (pD->dwSeed != pI->dwSeed) continue; + + if (pD->bCmd == ITEM_GEN_TAKEN) { + // PATCH1.JMM + DROPLOG(" delta_get_item: item already picked up?!\n"); + // ENDPATCH1.JMM + // someone else already picked it up?! + return(TRUE); + } + else if (pD->bCmd == ITEM_GEN_FLOOR) { + // pick item up from floor, but keep track + // of the fact that it is a generated item + // PATCH1.JMM + DROPLOG(" delta_get_item: native item picked up from floor\n"); + // ENDPATCH1.JMM + + sgbDeltaChanged = TRUE; + pD->bCmd = ITEM_GEN_TAKEN; + return(TRUE); + } + else if (pD->bCmd == ITEM_DROP_FLOOR) { + // since the item was dropped on the floor but + // not part of the generated dungeon, as soon + // as it is picked up we can forget about it + // PATCH1.JMM + DROPLOG(" delta_get_item: foreign item picked up from floor\n"); + // ENDPATCH1.JMM + + sgbDeltaChanged = TRUE; + pD->bCmd = ITEM_FREE; + return(TRUE); + } + else { + app_fatal("delta:1"); + } + break; + } + + + // PATCH1.JMM + DROPLOG(" delta_get_item: item not found\n"); + // ENDPATCH1.JMM + // If we are trying to remove an item from the delta list and it is not a dungeon + // pregenerated item, then forget it. Chances are that it was a message sent and + // buffered before the level delta was passed to us. So the level delta has the + // change in it already and we are processing the buffered message which is just + // duplicating what is already there. + // The above is true, or it could be we are processing the pickup before the drop + // so, we will be resending this message to ourselves + if (!(pI->wCI & ICI_PREGEN)) + return(FALSE); + + //app_assert(bLevel > 0); + // If not found, then an item generated by a level that I have not been to yet + pD = &sgLevels[bLevel].item[0]; + for (i = 0; i < MAXITEMS; i++,pD++) { + + // Free slot? + if (pD->bCmd != ITEM_FREE) continue; + + // put the item into the delta table + // PATCH1.JMM + DROPLOG(" delta_get_item: added item to delta tbl"); + // ENDPATCH1.JMM + + sgbDeltaChanged = TRUE; + pD->bCmd = ITEM_GEN_TAKEN; + pD->x = pI->x; + pD->y = pI->y; + pD->wIndx = pI->wIndx; + pD->wCI = pI->wCI; + pD->dwSeed = pI->dwSeed; + pD->bId = pI->bId; + pD->bDur = pI->bDur; + pD->bMDur = pI->bMDur; + pD->bCh = pI->bCh; + pD->bMCh = pI->bMCh; + pD->wValue = pI->wValue; + pD->dwBuff = pI->dwBuff; + pD->wPLToHit = pI->wPLToHit; + pD->wMaxDam = pI->wMaxDam; + pD->bMinStr = pI->bMinStr; + pD->bMinMag = pI->bMinMag; + pD->bMinDex = pI->bMinDex; + pD->bAC = pI->bAC; + return(TRUE); + } + // PATCH1.JMM + DROPLOG(" delta_get_item: could not add item to delta tbl"); + // ENDPATCH1.JMM + return(TRUE); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void delta_put_item(const TCmdPItem * pI, int x, int y, BYTE bLevel) { + if (gbMaxPlayers == 1) return; + app_assert(pI != NULL); + app_assert(x < DMAXX); + app_assert(y < DMAXY); + app_assert(bLevel < NUMLEVELS); + + // see if the item was already part of the generated dungeon + TCmdPItem * pD = &sgLevels[bLevel].item[0]; + for (int i = 0; i < MAXITEMS; i++,pD++) { + if (pD->bCmd == ITEM_GEN_TAKEN) continue; + if (pD->bCmd == ITEM_FREE) continue; + if (pD->wIndx != pI->wIndx) continue; + if (pD->wCI != pI->wCI) continue; + if (pD->dwSeed != pI->dwSeed) continue; + + // Already placed? + if (pD->bCmd == ITEM_DROP_FLOOR) { + return; + } + + app_fatal("Trying to drop a floor item?"); + } + + // find a location to drop this item + pD = &sgLevels[bLevel].item[0]; + for (i = 0; i < MAXITEMS; i++,pD++) { + if (pD->bCmd != ITEM_FREE) continue; + + // put the item back onto the floor at its + // new location and with its new state + + sgbDeltaChanged = TRUE; + //CopyMemory(pD,pI,sizeof(TCmdPItem)); + *pD = *pI; // struct copy. + pD->bCmd = ITEM_DROP_FLOOR; + pD->x = x; + pD->y = y; + return; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL delta_portal_inited(int i) +{ + app_assert((DWORD)i < MAXPORTAL); + if (sgJunk.portal[i].x == INIT_VAL) return(TRUE); + else return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL delta_quest_inited(int i) +{ + app_assert((DWORD)i <= MAXMULTIQUESTS); + if (sgJunk.quests[i].qstate == INIT_VAL) return(FALSE); + else return(TRUE); +} + +/*-----------------------------------------------------------------------** +** Called when level creating +**-----------------------------------------------------------------------*/ +void DeltaAddItem(int ii) { + if (gbMaxPlayers == 1) return; + app_assert((DWORD)ii < MAXITEMS); + + // Already in delta? + TCmdPItem * pD = &sgLevels[currlevel].item[0]; + for (int i = 0; i < MAXITEMS; i++,pD++) { + if (pD->bCmd == ITEM_FREE) continue; + if (pD->wIndx != item[ii].IDidx) continue; + if (pD->wCI != item[ii]._iCreateInfo) continue; + if (pD->dwSeed != (DWORD)item[ii]._iSeed) continue; + + // taken? + if (pD->bCmd == ITEM_GEN_TAKEN) return; + // 2nd time down? + if (pD->bCmd == ITEM_GEN_FLOOR) return; + } + + + // find a location to drop this item + pD = &sgLevels[currlevel].item[0]; + for (i = 0; i < MAXITEMS; i++,pD++) { + if (pD->bCmd != ITEM_FREE) continue; + + // put the item back onto the floor at its + // new location and with its new state + + sgbDeltaChanged = TRUE; + pD->bCmd = ITEM_GEN_FLOOR; + pD->x = item[ii]._ix; + pD->y = item[ii]._iy; + pD->wIndx = item[ii].IDidx; + pD->wCI = item[ii]._iCreateInfo; + pD->dwSeed = item[ii]._iSeed; + pD->bId = item[ii]._iIdentified; + pD->bDur = item[ii]._iDurability; + pD->bMDur = item[ii]._iMaxDur; + pD->bCh = item[ii]._iCharges; + pD->bMCh = item[ii]._iMaxCharges; + pD->wValue = item[ii]._ivalue; + pD->wPLToHit = item[ii]._iPLToHit; + pD->wMaxDam = item[ii]._iMaxDam; + pD->bMinStr = item[ii]._iMinStr; + pD->bMinMag = item[ii]._iMinMag; + pD->bMinDex = item[ii]._iMinDex; + pD->bAC = item[ii]._iAC; + return; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DeltaSaveLevel() { + if (gbMaxPlayers == 1) return; + + // throw away everyone else's graphics, they + // are probably out of date anyway + for (int i = 0; i < MAX_PLRS; i++) + if (i != myplr) plr[i]._pGFXLoad = 0; + + app_assert((DWORD) currlevel < NUMLEVELS); + plr[myplr]._pLvlVisited[currlevel] = TRUE; + delta_leave_sync(currlevel); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +// PATCH1.JMM +BOOL CanPut(int i, int j); +// ENDPATCH1.JMM + + +void DeltaLoadLevel() { + if (gbMaxPlayers == 1) return; + + int i, ii; + + deltaload = TRUE; + + // don't do the monster stuff for level 0, that is the town! + if (currlevel != 0) { + for (i = 0; i < nummonsters; i++) { + if (sgLevels[currlevel].monster[i]._mx == INIT_VAL) continue; + M_ClearSquares(i); + monster[i]._mx = sgLevels[currlevel].monster[i]._mx; + monster[i]._my = sgLevels[currlevel].monster[i]._my; + monster[i]._moldx = monster[i]._mx; + monster[i]._moldy = monster[i]._my; + monster[i]._mfutx = monster[i]._mx; + monster[i]._mfuty = monster[i]._my; + if (sgLevels[currlevel].monster[i]._mhitpoints != -1) + monster[i]._mhitpoints = sgLevels[currlevel].monster[i]._mhitpoints; + // Is monster dead? + if (sgLevels[currlevel].monster[i]._mhitpoints == 0) { + monster[i]._moldx = sgLevels[currlevel].monster[i]._mx; + monster[i]._moldy = sgLevels[currlevel].monster[i]._my; + M_ClearSquares(i); + if (monster[i]._mAi != AI_DIABLO) { // Diablo has no death frame + if (monster[i]._uniqtype == 0) { + app_assert(monster[i].MType != NULL); + AddDead(monster[i]._mx, monster[i]._my, monster[i].MType->mdeadval, monster[i]._mdir); + } else { + AddDead(monster[i]._mx, monster[i]._my, monster[i]._udeadval, monster[i]._mdir); + } + } + monster[i]._mDelFlag = TRUE; + M_UpdateLeader(i); + } else { + int enemy = sgLevels[currlevel].monster[i]._menemy; + //app_assert((DWORD) enemy < MAX_PLRS); + decode_enemy(i, enemy); + if (((monster[i]._mx != 0) && (monster[i]._mx != 1)) || (monster[i]._my != 0)) dMonster[monster[i]._mx][monster[i]._my] = i + 1; + if (i < 4) { + MAI_Golum(i); + monster[i]._mFlags |= MFLAG_MID; + monster[i]._mFlags |= MFLAG_MKILLER; + } else M_StartStand(i, monster[i]._mdir); + monster[i]._msquelch = sgLevels[currlevel].monster[i]._msquelch; + } + } + + // copy automap + app_assert(sizeof(sgLocals[currlevel].automapsv) == sizeof(automapview)); + CopyMemory( + &automapview[0][0], + &sgLocals[currlevel].automapsv[0][0], + sizeof(automapview) + ); + } + + for (i = 0; i < MAXITEMS; i++) { + if (sgLevels[currlevel].item[i].bCmd == ITEM_FREE) continue; + if (sgLevels[currlevel].item[i].bCmd == ITEM_GEN_TAKEN) { + ii = FindGetItem(sgLevels[currlevel].item[i].wIndx, + sgLevels[currlevel].item[i].wCI, + sgLevels[currlevel].item[i].dwSeed); + if (ii != -1) { + if (dItem[item[ii]._ix][item[ii]._iy] == (ii+1)) dItem[item[ii]._ix][item[ii]._iy] = 0; + DeleteItem(ii, i); + } + } + if (sgLevels[currlevel].item[i].bCmd == ITEM_DROP_FLOOR) { + ii = itemavail[0]; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + if (sgLevels[currlevel].item[i].wIndx == IDI_EAR) { + RecreateEar(ii, + sgLevels[currlevel].item[i].wCI, + sgLevels[currlevel].item[i].dwSeed, + sgLevels[currlevel].item[i].bId, + sgLevels[currlevel].item[i].bDur, + sgLevels[currlevel].item[i].bMDur, + sgLevels[currlevel].item[i].bCh, + sgLevels[currlevel].item[i].bMCh, + sgLevels[currlevel].item[i].wValue, + sgLevels[currlevel].item[i].dwBuff); + } else { + RecreateItem(ii, + sgLevels[currlevel].item[i].wIndx, + sgLevels[currlevel].item[i].wCI, + sgLevels[currlevel].item[i].dwSeed, + sgLevels[currlevel].item[i].wValue); + if (sgLevels[currlevel].item[i].bId) item[ii]._iIdentified = TRUE; + item[ii]._iDurability = sgLevels[currlevel].item[i].bDur; + item[ii]._iMaxDur = sgLevels[currlevel].item[i].bMDur; + item[ii]._iCharges = sgLevels[currlevel].item[i].bCh; + item[ii]._iMaxCharges = sgLevels[currlevel].item[i].bMCh; + item[ii]._iPLToHit = sgLevels[currlevel].item[i].wPLToHit; + item[ii]._iMaxDam = sgLevels[currlevel].item[i].wMaxDam; + item[ii]._iMinStr = sgLevels[currlevel].item[i].bMinStr; + item[ii]._iMinMag = sgLevels[currlevel].item[i].bMinMag; + item[ii]._iMinDex = sgLevels[currlevel].item[i].bMinDex; + item[ii]._iAC = sgLevels[currlevel].item[i].bAC; + } + + int ox = sgLevels[currlevel].item[i].x; + int oy = sgLevels[currlevel].item[i].y; + + // PATCH1.JMM + if (!CanPut(ox,oy)) { + BOOL done = FALSE; + // radial search outward until a space is found + for (int l = 1; (l < 50) && !done; l++) { + for (int j = -l; (j <= l) && !done; j++) { + int yy = oy + j; + for (int i = -l; (i <= l) && !done; i++) { + int xx = ox + i; + if (!CanPut(xx,yy)) continue; + done = TRUE; + DROPLOG(" DeltaLoadLevel: moving object from (x,y)->(%2.2x,%2.2x) to (x,y)->(%2.2x,%2.2x)!\n",ox,oy,xx,yy); + ox = xx; + oy = yy; + } + } + } + + app_assert(done); + } + // ENDPATCH1.JMM + + + item[ii]._ix = ox; + item[ii]._iy = oy; + dItem[item[ii]._ix][item[ii]._iy] = ii+1; + // PATCH1.JMM + DROPLOG(" DeltaLoadLevel: respawning %d (%4.4x,%4.4x,%8.8x) @ (x,y)->(%2.2x,%2.2x)\n",ii,item[ii]._itype,item[ii]._iCreateInfo,item[ii]._iSeed,item[ii]._ix,item[ii]._iy); + // ENDPATCH1.JMM + RespawnItem(ii, FALSE); + numitems++; + } + } + + if (currlevel != 0) { + for (i = 0; i < MAXOBJECTS; i++) { + switch (sgLevels[currlevel].object[i].bCmd) { + case INIT_VAL: + // no object + break; + + case CMD_OPENDOOR: + case CMD_CLOSEDOOR: + case CMD_OPERATEOBJ: + case CMD_PLROPOBJ: + SyncOpObject(-1, sgLevels[currlevel].object[i].bCmd, i); + break; + + case CMD_BREAKOBJ: + SyncBreakObj(-1, i); + break; + } + } + for (i = 0; i < numobjects; i++) { + ii = objectactive[i]; + if ((object[ii]._otype == OBJ_TRAPL) || (object[ii]._otype == OBJ_TRAPR)) Obj_Trap(ii); + } + } + + deltaload = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmd(BOOL bHiPri,BYTE bCmd) { + TCmd cmd; + cmd.bCmd = bCmd; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdGolem(BYTE mx, BYTE my, BYTE dir, BYTE menemy, long hp, BYTE cl) { + app_assert(mx < DMAXX); + app_assert(my < DMAXY); + + TCmdGolem cmd; + + cmd.bCmd = CMD_AWAKEGOLEM; + cmd._mx = mx; + cmd._my = my; + cmd._mdir = dir; + cmd._menemy = menemy; + cmd._mhitpoints = hp; + cmd._currlevel = cl; + + NetSendLoPri((BYTE *) &cmd, sizeof(cmd)); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdLoc(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y) { + app_assert(x < DMAXX); + app_assert(y < DMAXY); + TCmdLoc cmd; + cmd.bCmd = bCmd; + cmd.x = x; + cmd.y = y; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdLocParam1(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1) { + app_assert(x < DMAXX); + app_assert(y < DMAXY); + TCmdLocParam1 cmd; + cmd.bCmd = bCmd; + cmd.x = x; + cmd.y = y; + cmd.wParam1 = wParam1; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdLocParam2(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1,WORD wParam2) { + app_assert(x < DMAXX); + app_assert(y < DMAXY); + TCmdLocParam2 cmd; + cmd.bCmd = bCmd; + cmd.x = x; + cmd.y = y; + cmd.wParam1 = wParam1; + cmd.wParam2 = wParam2; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdLocParam3(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1,WORD wParam2,WORD wParam3) { + app_assert(x < DMAXX); + app_assert(y < DMAXY); + TCmdLocParam3 cmd; + cmd.bCmd = bCmd; + cmd.x = x; + cmd.y = y; + cmd.wParam1 = wParam1; + cmd.wParam2 = wParam2; + cmd.wParam3 = wParam3; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdParam1(BOOL bHiPri,BYTE bCmd,WORD wParam1) { + TCmdParam1 cmd; + cmd.bCmd = bCmd; + cmd.wParam1 = wParam1; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdParam2(BOOL bHiPri,BYTE bCmd,WORD wParam1,WORD wParam2) { + TCmdParam2 cmd; + cmd.bCmd = bCmd; + cmd.wParam1 = wParam1; + cmd.wParam2 = wParam2; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdParam3(BOOL bHiPri,BYTE bCmd,WORD wParam1,WORD wParam2, WORD wParam3) { + TCmdParam3 cmd; + cmd.bCmd = bCmd; + cmd.wParam1 = wParam1; + cmd.wParam2 = wParam2; + cmd.wParam3 = wParam3; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdQuest(BOOL bHiPri,BYTE q) { + TCmdQuest cmd; + cmd.bCmd = CMD_SYNCQUEST; + cmd.q = q; + cmd.qstate = quests[q]._qactive; + cmd.qlog = quests[q]._qlog; + cmd.qvar1 = quests[q]._qvar1; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdGItem(BOOL bHiPri,BYTE bCmd,BYTE mast,BYTE pnum,BYTE ii) { + app_assert(ii < MAXITEMS); + app_assert(pnum < MAX_PLRS); + + TCmdGItem cmd; + cmd.bCmd = bCmd; + cmd.bPnum = pnum; + cmd.bMaster = mast; + cmd.dwTime = 0; + cmd.bLevel = currlevel; + cmd.bCursitem = ii; + cmd.x = item[ii]._ix; + cmd.y = item[ii]._iy; + cmd.wIndx = item[ii].IDidx; + if (item[ii].IDidx == IDI_EAR) { + cmd.wCI = (item[ii]._iName[7] << 8) | item[ii]._iName[8]; + cmd.dwSeed = (item[ii]._iName[9] << 24) | + (item[ii]._iName[10] << 16) | + (item[ii]._iName[11] << 8) | + item[ii]._iName[12]; + cmd.bId = item[ii]._iName[13]; + cmd.bDur = item[ii]._iName[14]; + cmd.bMDur = item[ii]._iName[15]; + cmd.bCh = item[ii]._iName[16]; + cmd.bMCh = item[ii]._iName[17]; + cmd.wValue = (item[ii]._iName[18] << 8) | ((item[ii]._iCurs - ITEM_EAR1) << 6) | item[ii]._ivalue; + cmd.dwBuff = (item[ii]._iName[19] << 24) | + (item[ii]._iName[20] << 16) | + (item[ii]._iName[21] << 8) | + item[ii]._iName[22]; + } else { + cmd.wCI = item[ii]._iCreateInfo; + cmd.dwSeed = item[ii]._iSeed; + cmd.bId = item[ii]._iIdentified; + cmd.bDur = item[ii]._iDurability; + cmd.bMDur = item[ii]._iMaxDur; + cmd.bCh = item[ii]._iCharges; + cmd.bMCh = item[ii]._iMaxCharges; + cmd.wValue = item[ii]._ivalue; + cmd.wPLToHit = item[ii]._iPLToHit; + cmd.wMaxDam = item[ii]._iMaxDam; + cmd.bMinStr = item[ii]._iMinStr; + cmd.bMinMag = item[ii]._iMinMag; + cmd.bMinDex = item[ii]._iMinDex; + cmd.bAC = item[ii]._iAC; + } + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void NetSendCmdGItem2(BOOL usonly,BYTE bCmd,BYTE mast,BYTE pnum,const TCmdGItem * p) { + app_assert(pnum < MAX_PLRS); + app_assert(p != NULL); + + TCmdGItem cmd; + //CopyMemory(&cmd,p,sizeof(TCmdGItem)); + cmd = *p; // struct copy. + cmd.bCmd = bCmd; + cmd.bPnum = pnum; + cmd.bMaster = mast; + + // Should I init the timer? + if (!usonly) { + cmd.dwTime = 0; + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + } + else { + // Have I been sending this back to myself for more than 5 seconds? + DWORD dwCurr = GetTickCount(); + if (cmd.dwTime == 0) + cmd.dwTime = dwCurr; + else if ((long) (dwCurr - cmd.dwTime) > RESEND_TIME) + return; + NetSendMyselfPri((BYTE *) &cmd,sizeof(cmd)); + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL NetSendCmdReq2(BYTE bCmd,BYTE mast,BYTE pnum,const TCmdGItem * p) { + app_assert(pnum < MAX_PLRS); + app_assert(p != NULL); + + TCmdGItem cmd; + //CopyMemory(&cmd,p,sizeof(TCmdGItem)); + cmd = *p; // struct copy. + cmd.bCmd = bCmd; + cmd.bPnum = pnum; + cmd.bMaster = mast; + + // Have I been sending this back to myself for more than 5 seconds? + DWORD dwCurr = GetTickCount(); + if (cmd.dwTime == 0) // Timer inited in original send + cmd.dwTime = dwCurr; + else if ((long) (dwCurr - cmd.dwTime) > RESEND_TIME) + return(FALSE); + NetSendMyselfPri((BYTE *) &cmd,sizeof(cmd)); + return(TRUE); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdExtra(const TCmdGItem * p) +{ + app_assert(p != NULL); + + TCmdGItem cmd; + //CopyMemory(&cmd,p,sizeof(TCmdGItem)); + cmd = *p; // struct copy + cmd.bCmd = CMD_ITEMEXTRA; + cmd.dwTime = 0; + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdPItem(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y) { + app_assert(x < DMAXX); + app_assert(y < DMAXY); + + TCmdPItem cmd; + cmd.bCmd = bCmd; + cmd.x = x; + cmd.y = y; + cmd.wIndx = plr[myplr].HoldItem.IDidx; + if (plr[myplr].HoldItem.IDidx == IDI_EAR) { + cmd.wCI = (plr[myplr].HoldItem._iName[7] << 8) | plr[myplr].HoldItem._iName[8]; + cmd.dwSeed = (plr[myplr].HoldItem._iName[9] << 24) | + (plr[myplr].HoldItem._iName[10] << 16) | + (plr[myplr].HoldItem._iName[11] << 8) | + plr[myplr].HoldItem._iName[12]; + cmd.bId = plr[myplr].HoldItem._iName[13]; + cmd.bDur = plr[myplr].HoldItem._iName[14]; + cmd.bMDur = plr[myplr].HoldItem._iName[15]; + cmd.bCh = plr[myplr].HoldItem._iName[16]; + cmd.bMCh = plr[myplr].HoldItem._iName[17]; + cmd.wValue = (plr[myplr].HoldItem._iName[18] << 8) | + ((plr[myplr].HoldItem._iCurs - ITEM_EAR1) << 6) | + plr[myplr].HoldItem._ivalue; + cmd.dwBuff = (plr[myplr].HoldItem._iName[19] << 24) | + (plr[myplr].HoldItem._iName[20] << 16) | + (plr[myplr].HoldItem._iName[21] << 8) | + plr[myplr].HoldItem._iName[22]; + } else { + cmd.wCI = plr[myplr].HoldItem._iCreateInfo; + cmd.dwSeed = plr[myplr].HoldItem._iSeed; + cmd.bId = plr[myplr].HoldItem._iIdentified; + cmd.bDur = plr[myplr].HoldItem._iDurability; + cmd.bMDur = plr[myplr].HoldItem._iMaxDur; + cmd.bCh = plr[myplr].HoldItem._iCharges; + cmd.bMCh = plr[myplr].HoldItem._iMaxCharges; + cmd.wValue = plr[myplr].HoldItem._ivalue; + cmd.wPLToHit = plr[myplr].HoldItem._iPLToHit; + cmd.wMaxDam = plr[myplr].HoldItem._iMaxDam; + cmd.bMinStr = plr[myplr].HoldItem._iMinStr; + cmd.bMinMag = plr[myplr].HoldItem._iMinMag; + cmd.bMinDex = plr[myplr].HoldItem._iMinDex; + cmd.bAC = plr[myplr].HoldItem._iAC; + } + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdChItem(BOOL bHiPri,BYTE bLoc) { + TCmdChItem cmd; + cmd.bCmd = CMD_CHANGEPLRITEMS; + cmd.bLoc = bLoc; + cmd.wIndx = plr[myplr].HoldItem.IDidx; + cmd.wCI = plr[myplr].HoldItem._iCreateInfo; + cmd.dwSeed = plr[myplr].HoldItem._iSeed; + // drb.patch1.start.02/10/97 + cmd.bId = plr[myplr].HoldItem._iIdentified; + // drb.patch1.end.02/10/97 + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdDelItem(BOOL bHiPri,BYTE bLoc) { + TCmdDelItem cmd; + cmd.bCmd = CMD_DELPLRITEMS; + cmd.bLoc = bLoc; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdDItem(BOOL bHiPri,int ii) { + app_assert((DWORD)ii < MAXITEMS); + + TCmdPItem cmd; + cmd.bCmd = CMD_DROPITEM; + cmd.x = item[ii]._ix; + cmd.y = item[ii]._iy; + cmd.wIndx = item[ii].IDidx; + if (item[ii].IDidx == IDI_EAR) { + cmd.wCI = (item[ii]._iName[7] << 8) | item[ii]._iName[8]; + cmd.dwSeed = (item[ii]._iName[9] << 24) | + (item[ii]._iName[10] << 16) | + (item[ii]._iName[11] << 8) | + item[ii]._iName[12]; + cmd.bId = item[ii]._iName[13]; + cmd.bDur = item[ii]._iName[14]; + cmd.bMDur = item[ii]._iName[15]; + cmd.bCh = item[ii]._iName[16]; + cmd.bMCh = item[ii]._iName[17]; + cmd.wValue = (item[ii]._iName[18] << 8) | + ((item[ii]._iCurs - ITEM_EAR1) << 6) | + item[ii]._ivalue; + cmd.dwBuff = (item[ii]._iName[19] << 24) | + (item[ii]._iName[20] << 16) | + (item[ii]._iName[21] << 8) | + item[ii]._iName[22]; + } else { + cmd.wCI = item[ii]._iCreateInfo; + cmd.dwSeed = item[ii]._iSeed; + cmd.bId = item[ii]._iIdentified; + cmd.bDur = item[ii]._iDurability; + cmd.bMDur = item[ii]._iMaxDur; + cmd.bCh = item[ii]._iCharges; + cmd.bMCh = item[ii]._iMaxCharges; + cmd.wValue = item[ii]._ivalue; + cmd.wPLToHit = item[ii]._iPLToHit; + cmd.wMaxDam = item[ii]._iMaxDam; + cmd.bMinStr = item[ii]._iMinStr; + cmd.bMinMag = item[ii]._iMinMag; + cmd.bMinDex = item[ii]._iMinDex; + cmd.bAC = item[ii]._iAC; + } + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL i_own_level(int nReqLevel) { + // the lowest numbered player on a level is + // responsible for arbitrating disputes. + for (int i = 0; i < MAX_PLRS; i++) { + if (! plr[i].plractive) continue; + if (plr[i]._pLvlChanging) continue; + if (plr[i].plrlevel != nReqLevel) continue; + if (i == myplr && gbBufferMsgs != BUFFER_OFF) continue; + break; + } + + return i == myplr; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdDamage(BOOL bHiPri,BYTE bPlr,DWORD dwDam) { + app_assert(bPlr < MAX_PLRS); + + TCmdDamage cmd; + cmd.bCmd = CMD_PLRDAMAGE; + cmd.bPlr = bPlr; + cmd.dwDam = dwDam; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendCmdMonstDamage(BOOL bHiPri,WORD wMonst,DWORD dwDam) { + app_assert(wMonst < MAXMONSTERS); + + TCmdMonstDamage cmd; + cmd.bCmd = CMD_MONSTDAMAGE; + cmd.wMonst = wMonst; + cmd.dwDam = dwDam; + + if (bHiPri) + NetSendHiPri((BYTE *) &cmd,sizeof(cmd)); + else + NetSendLoPri((BYTE *) &cmd,sizeof(cmd)); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void NetSendString(DWORD dwSendMask,const char * pszStr) { + app_assert(pszStr); + + TCmdString cmd; + DWORD dwStrLen = strlen(pszStr); + app_assert(dwStrLen < sizeof(cmd.str)); + + cmd.bCmd = CMD_STRING; + strcpy(cmd.str,pszStr); + NetSendMask( + dwSendMask, + (BYTE *) &cmd, + (BYTE) (sizeof(cmd) - sizeof(cmd.str) + dwStrLen + 1) + ); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD cmd_string(int pnum,const TCmdString * p) { + app_assert((DWORD)pnum < MAX_PLRS); + app_assert(p != NULL); + + DWORD dwStrLen = strlen(p->str); + + // don't display messages while buffering or processing + if (gbBufferMsgs == BUFFER_OFF) + plrmsg_add(pnum,p->str); + + return sizeof(*p) - sizeof(p->str) + dwStrLen + 1; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void delta_open_portal( + int pnum, + BYTE x, + BYTE y, + BYTE bLevel, + BYTE bLType, + BYTE bSetLvl +) { + app_assert((DWORD)pnum < MAX_PLRS); + app_assert(x < DMAXX); + app_assert(y < DMAXY); + app_assert(bLevel < NUMLEVELS); + + sgJunk.portal[pnum].x = x; + sgJunk.portal[pnum].y = y; + sgJunk.portal[pnum].level = bLevel; + sgJunk.portal[pnum].ltype = bLType; + sgJunk.portal[pnum].setlvl = bSetLvl; + sgbDeltaChanged = TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void delta_close_portal(int pnum) { + app_assert((DWORD)pnum < MAX_PLRS); + FillMemory(&sgJunk.portal[pnum],sizeof(sgJunk.portal[pnum]),INIT_VAL); + sgbDeltaChanged = TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void check_update_plr(int pnum) { + if (gbMaxPlayers == 1) return; + + app_assert((DWORD)pnum < MAX_PLRS); + if (pnum != myplr) return; + + void TimedUpdatePlayerFile(BOOL bForce); + TimedUpdatePlayerFile(TRUE); +} + +// PATCH2.JMM.3/5/97 +#define MAX_ADDSTAT 256 +#define MAX_LEVEL 51 +#define MAX_STAT 750 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define CHEATER_DISP_INTERVAL 5 +static DWORD sgdwLastCheaterTime = 0; + +static void __cdecl IdentifyCheater( LPCSTR szFormat, ... ) { + DWORD dwCurrTime; + char szOut[256]; + + dwCurrTime = GetTickCount( ); + + if((dwCurrTime - sgdwLastCheaterTime) < (CHEATER_DISP_INTERVAL*1000)) + return; + + sgdwLastCheaterTime = dwCurrTime; + + va_list args; + va_start(args,szFormat); + vsprintf(szOut,szFormat,args); + va_end(args); + + sysmsg_add_string( szOut ); + +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SYNCDATA( const TCmd* pCmd, int pnum ) { + // sync_update handles gbBufferMsgs + + DROPLOG( "CMD_SYNCDATA(%d)\n", pnum ); + return sync_update( pnum, (CONST BYTE *) pCmd ); +} + + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_WALKXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLoc * p = (const TCmdLoc *) pCmd; + + DROPLOG("CMD_WALKXY(%d):(%d,%d)\n",pnum,p->x,p->y); + + ClrPlrPath(pnum); + MakePlrPath(pnum, p->x, p->y, TRUE); + plr[pnum].destAction = PCMD_NOTHING; + } + return sizeof(TCmdLoc); +} + + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ADDSTR( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_ADDSTR(%d)\n",pnum); + + // PATCH2.JMM.3/5/97 + if(p->wParam1 < 0 || p->wParam1 > MAX_ADDSTAT) { + return sizeof(TCmdParam1); + } + // ENDPATCH2.JMM.3/5/97 + + ModifyPlrStr(pnum, p->wParam1); + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ADDMAG( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_ADDMAG(%d)\n",pnum); + + // PATCH2.JMM.3/5/97 + if(p->wParam1 < 0 || p->wParam1 > MAX_ADDSTAT) { + return sizeof(TCmdParam1); + } + // ENDPATCH2.JMM.3/5/97 + + ModifyPlrMag(pnum, p->wParam1); + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ADDDEX( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_ADDDEX(%d)\n",pnum); + + // PATCH2.JMM.3/5/97 + if(p->wParam1 < 0 || p->wParam1 > MAX_ADDSTAT) { + return sizeof(TCmdParam1); + } + // ENDPATCH2.JMM.3/5/97 + + ModifyPlrDex(pnum, p->wParam1); + } + + return sizeof(TCmdParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ADDVIT( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_ADDVIT(%d)\n",pnum); + + // PATCH2.JMM.3/5/97 + if(p->wParam1 < 0 || p->wParam1 > MAX_ADDSTAT) { + return sizeof(TCmdParam1); + } + // ENDPATCH2.JMM.3/5/97 + + ModifyPlrVit(pnum, p->wParam1); + } + + return sizeof(TCmdParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SBSPELL( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_SBSPELL(%d)\n",pnum); + + // PATCH2.JMM.3/5/97 + UINT nSplType = p->wParam1; + + if(currlevel == 0 && !spelldata[nSplType].sTownSpell) { + IdentifyCheater("%s has cast an illegal spell.",plr[pnum]._pName); + return sizeof(TCmdParam1); + } + // ENDPATCH2.JMM.3/5/97 + + plr[pnum]._pSpell = p->wParam1; + plr[pnum]._pSplType = plr[pnum]._pSBkSplType; + plr[pnum]._pSplFrom = SPL_FROMBK; + plr[pnum].destAction = PCMD_SPELL; + } + return sizeof(TCmdParam1); +} + + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_GOTOGETITEM( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLocParam1 * p = (const TCmdLocParam1 *) pCmd; + + DROPLOG("CMD_GOTOGETITEM(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + MakePlrPath(pnum, p->x, p->y, FALSE); + plr[pnum].destAction = PCMD_REQGETITEM; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdLocParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_REQUESTGITEM( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else { + const TCmdGItem * p = (const TCmdGItem *) pCmd; + + DROPLOG("CMD_REQUESTGETITEM(%d,%8.8x): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d)\n",pnum,p->dwTime,p->wIndx,p->wCI,p->dwSeed,p->x,p->y); + + if (i_own_level(plr[pnum].plrlevel)) { + app_assert(currlevel == plr[myplr].plrlevel); + + // make sure we don't start resending an item we just picked up. + if( !CheckGetRecord( p->dwSeed, p->wCI, p->wIndx ) ) + return sizeof(TCmdGItem); + + int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed); + if (ii != -1) { + DROPLOG(" Item found. FindGetItem returned %d and iDelFlag is FALSE.\n",ii); + NetSendCmdGItem2(FALSE, CMD_GETITEM, myplr, p->bPnum, p); + + if (p->bPnum != myplr) { + SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed); + } + else { + InvGetItem(myplr, ii); + } + + AddGetRecord( p->dwSeed, p->wCI, p->wIndx ); + } + else { + if (ii == -1) { + DROPLOG(" Item not found. Resending.\n"); + if (! NetSendCmdReq2(CMD_REQUESTGITEM, myplr, p->bPnum, p)) { + DROPLOG(" Resend expired. Extra Item.\n"); + NetSendCmdExtra(p); + } + } + } + } + } + + return sizeof(TCmdGItem); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_GETITEM( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdGItem)); + } + else { + const TCmdGItem * p = (const TCmdGItem *) pCmd; + + DROPLOG("CMD_GETITEM(%d,%8.8x,%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d)\n",pnum,p->dwTime,p->bPnum,p->wIndx,p->wCI,p->dwSeed,p->x,p->y); + DROPLOG(" Data: bCmd = %2.2x\n", p->bCmd); + DROPLOG(" Data: bMaster = %2.2x\n",p->bMaster); + DROPLOG(" Data: bPnum = %2.2x\n",p->bPnum); + DROPLOG(" Data: bCursitem = %2.2x\n",p->bCursitem); + DROPLOG(" Data: bLevel = %2.2x\n",p->bLevel); + DROPLOG(" Data: x = %2.2x\n",p->x); + DROPLOG(" Data: y = %2.2x\n",p->y); + DROPLOG(" Data: wIndx = %4.4x\n",p->wIndx); + DROPLOG(" Data: wCI = %4.4x\n",p->wCI); + DROPLOG(" Data: dwSeed = %8.8x\n",p->dwSeed); + DROPLOG(" Data: bID = %2.2x\n",p->bId); + DROPLOG(" Data: bDur = %2.2x\n",p->bDur); + DROPLOG(" Data: bMDur = %2.2x\n",p->bMDur); + DROPLOG(" Data: bCh = %2.2x\n",p->bCh); + DROPLOG(" Data: bMCh = %2.2x\n",p->bMCh); + DROPLOG(" Data: wValue = %4.4x\n",p->wValue); + DROPLOG(" Data: dwBuff = %8.8x\n",p->dwBuff); + DROPLOG(" Data: dwTime = %8.8x\n",p->dwTime); + + int nIndex = FindGetItem( p->wIndx, p->wCI, p->dwSeed ); + + // Check if in the delta table + DROPLOG(" Looking in delta tbl[%d]\n",p->bLevel); + + //if (delta_get_item(p, plr[pnum].plrlevel) && (nIndex != -1)) { + if (delta_get_item(p, p->bLevel)) { + // Found in delta + DROPLOG(" Found in delta tbl.\n"); + + //if (currlevel == plr[pnum].plrlevel) { + if ((currlevel == p->bLevel) || (p->bPnum == myplr)) { + if (p->bMaster == myplr) { + // item has already been picked up + DROPLOG(" Item already picked up.\n"); + } + else if (p->bPnum == myplr) { + if (currlevel != p->bLevel) { + int hitem = SyncPutItem(myplr, + plr[myplr]._px, + plr[myplr]._py, + p->wIndx, + p->wCI, + p->dwSeed, + p->bId, + p->bDur, + p->bMDur, + p->bCh, + p->bMCh, + p->wValue, + p->dwBuff, + p->wPLToHit, + p->wMaxDam, + p->bMinStr, + p->bMinMag, + p->bMinDex, + p->bAC ); + if (hitem != -1) InvGetItem(myplr, hitem); + } else + InvGetItem(myplr, nIndex); + DROPLOG(" Local player got item.\n"); + } + else { + SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed); + DROPLOG(" Remote player (%d) got item.\n",p->bPnum); + } + } + } + else { + // Not found, so let's send it to ourselves again + DROPLOG(" Not found in delta tbl. Resending...\n"); + NetSendCmdGItem2(TRUE, CMD_GETITEM, p->bMaster, p->bPnum, p); + } + } + + return sizeof(TCmdGItem); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_GOTOAGETITEM( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLocParam1 * p = (const TCmdLocParam1 *) pCmd; + DROPLOG("CMD_GOTOAUTOGETITEM(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + MakePlrPath(pnum, p->x, p->y, FALSE); + plr[pnum].destAction = PCMD_REQAGETITEM; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdLocParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_REQUESTAGITEM( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else { + const TCmdGItem * p = (const TCmdGItem *) pCmd; + DROPLOG("CMD_REQUESTAUTOGETITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d)\n",pnum,p->wIndx,p->wCI,p->dwSeed,p->x,p->y); + if (i_own_level(plr[pnum].plrlevel)) { + app_assert(currlevel == plr[myplr].plrlevel); + + // make sure we don't start resending an item we just picked up. + if( !CheckGetRecord( p->dwSeed, p->wCI, p->wIndx ) ) + return sizeof(TCmdGItem); + + int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed); + if (ii != -1) { + NetSendCmdGItem2(FALSE, CMD_AGETITEM, myplr, p->bPnum, p); + DROPLOG(" Item found.\n"); + if (p->bPnum != myplr) SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed); + else AutoGetItem(myplr, p->bCursitem); + // PATCH1.JMM + AddGetRecord( p->dwSeed, p->wCI, p->wIndx ); + // ENDPATCH1.JMM + } else { + if (ii == -1) { + DROPLOG(" Item not found. Resending.\n"); + if (! NetSendCmdReq2(CMD_REQUESTAGITEM, myplr, p->bPnum, p)) { + DROPLOG(" Resend expired. Extra Item.\n"); + NetSendCmdExtra(p); + } + } + } + } + } + return sizeof(TCmdGItem); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_AGETITEM( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdGItem)); + } + else { + const TCmdGItem * p = (const TCmdGItem *) pCmd; + + // PATCH1.JMM + DROPLOG("CMD_AUTOGETITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d)\n",pnum,p->wIndx,p->wCI,p->dwSeed,p->x,p->y); + DROPLOG(" Data: bCmd = %2.2x\n", p->bCmd); + DROPLOG(" Data: bMaster = %2.2x\n",p->bMaster); + DROPLOG(" Data: bPnum = %2.2x\n",p->bPnum); + DROPLOG(" Data: bCursitem = %2.2x\n",p->bCursitem); + DROPLOG(" Data: bLevel = %2.2x\n",p->bLevel); + DROPLOG(" Data: x = %2.2x\n",p->x); + DROPLOG(" Data: y = %2.2x\n",p->y); + DROPLOG(" Data: wIndx = %4.4x\n",p->wIndx); + DROPLOG(" Data: wCI = %4.4x\n",p->wCI); + DROPLOG(" Data: dwSeed = %8.8x\n",p->dwSeed); + DROPLOG(" Data: bID = %2.2x\n",p->bId); + DROPLOG(" Data: bDur = %2.2x\n",p->bDur); + DROPLOG(" Data: bMDur = %2.2x\n",p->bMDur); + DROPLOG(" Data: bCh = %2.2x\n",p->bCh); + DROPLOG(" Data: bMCh = %2.2x\n",p->bMCh); + DROPLOG(" Data: wValue = %4.4x\n",p->wValue); + DROPLOG(" Data: dwBuff = %8.8x\n",p->dwBuff); + DROPLOG(" Data: dwTime = %8.8x\n",p->dwTime); + + int nIndex = FindGetItem( p->wIndx, p->wCI, p->dwSeed ); + // ENDPATCH1.JMM + + // Check if in the delta table + // drb.patch1.start.2/05/97 + //if (delta_get_item(p, plr[pnum].plrlevel)) { + DROPLOG(" Looking in delta tbl[%d]\n",p->bLevel); + if (delta_get_item(p, p->bLevel)) { + // drb.patch1.end.2/05/97 + // Found in delta + DROPLOG(" Found in delta tbl.\n"); + // PATCH1.JMM + //if (currlevel == plr[pnum].plrlevel) { + if ((currlevel == p->bLevel) || (p->bPnum == myplr)) { + // ENDPATCH1.JMM + if (p->bMaster == myplr) { + // item already picked up + DROPLOG(" Item already picked up.\n"); + } + else if (p->bPnum == myplr) { + // drb.patch1.start.02/14/97 + // This is the biggest kludge I have ever written. + // I am so ashamed, but it will work + if (currlevel != p->bLevel) { + int hitem = SyncPutItem(myplr, + plr[myplr]._px, + plr[myplr]._py, + p->wIndx, + p->wCI, + p->dwSeed, + p->bId, + p->bDur, + p->bMDur, + p->bCh, + p->bMCh, + p->wValue, + p->dwBuff, + p->wPLToHit, + p->wMaxDam, + p->bMinStr, + p->bMinMag, + p->bMinDex, + p->bAC ); + if (hitem != -1) AutoGetItem(myplr, hitem); + } else + AutoGetItem(myplr, p->bCursitem); + // drb.patch1.end.02.14/97 + DROPLOG(" Local player got item.\n"); + } + else { + SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed); + DROPLOG(" Remote player (%d) got item.\n",p->bPnum); + } + } + } + else { + // Not found, so let's send it to ourselves again + NetSendCmdGItem2(TRUE, CMD_AGETITEM, p->bMaster, p->bPnum, p); + DROPLOG(" Not found in delta tbl. Resending...\n"); + } + } + + return sizeof(TCmdGItem); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ITEMEXTRA( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdGItem)); + } + else { + const TCmdGItem * p = (const TCmdGItem *) pCmd; + + DROPLOG("CMD_ITEMEXTRA(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d)\n",pnum,p->wIndx,p->wCI,p->dwSeed,p->x,p->y); + // Check if in the delta table + // drb.patch1.start.2/05/97 + //delta_get_item(p, plr[p->bPnum].plrlevel); + DROPLOG(" Looking in delta tbl[%d]\n",p->bLevel); + delta_get_item(p, p->bLevel); + if (currlevel == plr[pnum].plrlevel) { + //if (currlevel == p->bLevel) { + // drb.patch1.end.2/05/97 + SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed); + } + } + + return sizeof(TCmdGItem); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_PUTITEM( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdPItem)); + } + else { + const TCmdPItem * p = (const TCmdPItem *) pCmd; + + DROPLOG("CMD_PUTITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d)\n",pnum,p->wIndx,p->wCI,p->dwSeed,p->x,p->y); + + if (currlevel == plr[pnum].plrlevel) { + DROPLOG(" Item on my level.\n"); + int ii; + if (pnum == myplr) { + ii = InvPutItem(pnum, p->x, p->y); + } + else { + ii = SyncPutItem(pnum, + p->x, + p->y, + p->wIndx, + p->wCI, + p->dwSeed, + p->bId, + p->bDur, + p->bMDur, + p->bCh, + p->bMCh, + p->wValue, + p->dwBuff, + p->wPLToHit, + p->wMaxDam, + p->bMinStr, + p->bMinMag, + p->bMinDex, + p->bAC ); + } + + if (ii != -1) { + DROPLOG(" Put successful. Putting item into delta...\n"); + + RemoveGetRecord( p->dwSeed, p->wCI, p->wIndx ); + + DROPLOG(" Dropping into delta tbl[%d]\n",plr[pnum].plrlevel); + delta_put_item(p,item[ii]._ix,item[ii]._iy,plr[pnum].plrlevel); + check_update_plr(pnum); + } + else { + DROPLOG(" Put unsuccessful.\n"); + } + + return sizeof(TCmdPItem); + } + + RemoveGetRecord( p->dwSeed, p->wCI, p->wIndx ); + + DROPLOG(" Item not on my level. Adding to delta...\n"); + DROPLOG(" Dropping into delta tbl[%d]\n",plr[pnum].plrlevel); + delta_put_item(p, p->x, p->y, plr[pnum].plrlevel); + check_update_plr(pnum); + } + return sizeof(TCmdPItem); +} + + + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SYNCPUTITEM( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdPItem)); + } + else { + const TCmdPItem * p = (const TCmdPItem *) pCmd; + + DROPLOG("CMD_SYNCPUTITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d)\n",pnum,p->wIndx,p->wCI,p->dwSeed,p->x,p->y); + + if (currlevel == plr[pnum].plrlevel) { + DROPLOG(" Item on my level.\n"); + int ii = SyncPutItem(pnum, + p->x, + p->y, + p->wIndx, + p->wCI, + p->dwSeed, + p->bId, + p->bDur, + p->bMDur, + p->bCh, + p->bMCh, + p->wValue, + p->dwBuff, + p->wPLToHit, + p->wMaxDam, + p->bMinStr, + p->bMinMag, + p->bMinDex, + p->bAC ); + if (ii != -1) { + RemoveGetRecord( p->dwSeed, p->wCI, p->wIndx ); + + DROPLOG(" Put successful. Putting item into delta...\n"); + delta_put_item(p,item[ii]._ix,item[ii]._iy,plr[pnum].plrlevel); + DROPLOG(" Dropping into delta tbl[%d]\n",plr[pnum].plrlevel); + check_update_plr(pnum); + } + else { + DROPLOG(" Put unsuccessful.\n"); + } + + return sizeof(TCmdPItem); + } + + RemoveGetRecord( p->dwSeed, p->wCI, p->wIndx ); + + DROPLOG(" Item not on my level. Adding to delta...\n"); + delta_put_item(p, p->x, p->y, plr[pnum].plrlevel); + DROPLOG(" Dropping into delta tbl[%d]\n",plr[pnum].plrlevel); + check_update_plr(pnum); + } + + return sizeof(TCmdPItem); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_RESPAWNITEM( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdPItem)); + } + else { + const TCmdPItem * p = (const TCmdPItem *) pCmd; + + DROPLOG("CMD_RESPAWNITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d)\n",pnum,p->wIndx,p->wCI,p->dwSeed,p->x,p->y); + + if ((currlevel == plr[pnum].plrlevel) && (pnum != myplr)) { + DROPLOG(" SyncPutting into level.\n"); + int ii = SyncPutItem(pnum, + p->x, + p->y, + p->wIndx, + p->wCI, + p->dwSeed, + p->bId, + p->bDur, + p->bMDur, + p->bCh, + p->bMCh, + p->wValue, + p->dwBuff, + p->wPLToHit, + p->wMaxDam, + p->bMinStr, + p->bMinMag, + p->bMinDex, + p->bAC ); + } + + RemoveGetRecord( p->dwSeed, p->wCI, p->wIndx ); + + DROPLOG(" Adding to delta...\n"); + delta_put_item(p, p->x, p->y, plr[pnum].plrlevel); + DROPLOG(" Dropping into delta tbl[%d]\n",plr[pnum].plrlevel); + } + + return sizeof(TCmdPItem); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ATTACKXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLoc * p = (const TCmdLoc *) pCmd; + + DROPLOG("CMD_ATTACKXY(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + MakePlrPath(pnum, p->x, p->y, FALSE); + plr[pnum].destAction = PCMD_ATTACK; + plr[pnum].destParam1 = p->x; + plr[pnum].destParam2 = p->y; + } + + return sizeof(TCmdLoc); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SATTACKXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLoc * p = (const TCmdLoc *) pCmd; + + DROPLOG("CMD_SATTACKXY(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_ATTACK; + plr[pnum].destParam1 = p->x; + plr[pnum].destParam2 = p->y; + } + + return sizeof(TCmdLoc); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_RATTACKXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLoc * p = (const TCmdLoc *) pCmd; + + DROPLOG("CMD_RATTACKXY(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_RATTACK; + plr[pnum].destParam1 = p->x; + plr[pnum].destParam2 = p->y; + } + + return sizeof(TCmdLoc); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SPELLXYD( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLocParam3 * p = (const TCmdLocParam3 *) pCmd; + + DROPLOG("CMD_SPELLXYD(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + // PATCH2.JMM.3/5/97 + UINT nSplType = p->wParam1; + + if(currlevel == 0 && !spelldata[nSplType].sTownSpell) { + IdentifyCheater("%s has cast an illegal spell.",plr[pnum]._pName); + return sizeof(TCmdLocParam3); + } + // ENDPATCH2.JMM.3/5/97 + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_SPELLXYD; + plr[pnum].destParam1 = p->x; + plr[pnum].destParam2 = p->y; + plr[pnum].destParam3 = p->wParam2; + plr[pnum].destParam4 = p->wParam3; + plr[pnum]._pSpell = p->wParam1; + plr[pnum]._pSplType = plr[pnum]._pRSplType; + plr[pnum]._pSplFrom = SPL_FROMR; + } + + return sizeof(TCmdLocParam3); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SPELLXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLocParam2 * p = (const TCmdLocParam2 *) pCmd; + + DROPLOG("CMD_SPELLXY(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + // PATCH2.JMM.3/5/97 + UINT nSplType = p->wParam1; + + if(currlevel == 0 && !spelldata[nSplType].sTownSpell) { + IdentifyCheater("%s has cast an illegal spell.",plr[pnum]._pName); + return sizeof(TCmdLocParam2); + } + // ENDPATCH2.JMM.3/5/97 + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_SPELL; + plr[pnum].destParam1 = p->x; + plr[pnum].destParam2 = p->y; + plr[pnum].destParam3 = p->wParam2; + plr[pnum]._pSpell = p->wParam1; + plr[pnum]._pSplType = plr[pnum]._pRSplType; + plr[pnum]._pSplFrom = SPL_FROMR; + } + return sizeof(TCmdLocParam2); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_TSPELLXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLocParam2 * p = (const TCmdLocParam2 *) pCmd; + + DROPLOG("CMD_TSPELLXY(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + // PATCH2.JMM.3/5/97 + UINT nSplType = p->wParam1; + + if(currlevel == 0 && !spelldata[nSplType].sTownSpell) { + IdentifyCheater("%s has cast an illegal spell.",plr[pnum]._pName); + return sizeof(TCmdLocParam2); + } + // ENDPATCH2.JMM.3/5/97 + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_SPELL; + plr[pnum].destParam1 = p->x; + plr[pnum].destParam2 = p->y; + plr[pnum].destParam3 = p->wParam2; + plr[pnum]._pSpell = p->wParam1; + plr[pnum]._pSplType = plr[pnum]._pTSplType; + plr[pnum]._pSplFrom = SPL_FROMT; + } + + return sizeof(TCmdLocParam2); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_OPOBJXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLocParam1 * p = (const TCmdLocParam1 *) pCmd; + + DROPLOG("CMD_OPOBJXY(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + if (!object[p->wParam1]._oSolidFlag && !object[p->wParam1]._oDoorFlag) + MakePlrPath(pnum, p->x, p->y, TRUE); + else + MakePlrPath(pnum, p->x, p->y, FALSE); + plr[pnum].destAction = PCMD_OPOBJ; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdLocParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_DISARMXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLocParam1 * p = (const TCmdLocParam1 *) pCmd; + DROPLOG("CMD_DISARMXY(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + if (!object[p->wParam1]._oSolidFlag && !object[p->wParam1]._oDoorFlag) + MakePlrPath(pnum, p->x, p->y, TRUE); + else + MakePlrPath(pnum, p->x, p->y, FALSE); + + plr[pnum].destAction = PCMD_DISARM; + plr[pnum].destParam1 = p->wParam1; + } + return sizeof(TCmdLocParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_OPOBJT( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_OPOBJT(%d)\n",pnum); + + plr[pnum].destAction = PCMD_TELEK; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ATTACKID( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_ATTACKID(%d): id->%d\n",pnum,p->wParam1); + + int dx = abs(plr[pnum]._px - monster[p->wParam1]._mfutx); + int dy = abs(plr[pnum]._py - monster[p->wParam1]._mfuty); + if ((dx > 1) || (dy > 1)) + MakePlrPath(pnum, monster[p->wParam1]._mfutx, monster[p->wParam1]._mfuty, FALSE); + plr[pnum].destAction = PCMD_ATTACKID; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ATTACKPID( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_ATTACKPID(%d): id->%d\n",pnum,p->wParam1); + + MakePlrPath(pnum, plr[p->wParam1]._pfutx, plr[p->wParam1]._pfuty, FALSE); + plr[pnum].destAction = PCMD_ATTACKPID; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_RATTACKID( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_RATTACKID(%d): id->%d\n",pnum,p->wParam1); + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_RATTACKID; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_RATTACKPID( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_RATTACKPID(%d): id->%d\n",pnum,p->wParam1); + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_RATTACKPID; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SPELLID( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam3 * p = (const TCmdParam3 *) pCmd; + + DROPLOG("CMD_SPELLID(%d): id->%d\n",pnum,p->wParam1); + + // PATCH2.JMM.3/5/97 + UINT nSplType = p->wParam2; + + if(currlevel == 0 && !spelldata[nSplType].sTownSpell) { + IdentifyCheater("%s has cast an illegal spell.",plr[pnum]._pName); + return sizeof(TCmdParam3); + } + // ENDPATCH2.JMM.3/5/97 + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_SPELLID; + plr[pnum].destParam1 = p->wParam1; + plr[pnum].destParam2 = p->wParam3; + plr[pnum]._pSpell = p->wParam2; + plr[pnum]._pSplType = plr[pnum]._pRSplType; + plr[pnum]._pSplFrom = SPL_FROMR; + } + + return sizeof(TCmdParam3); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SPELLPID( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam3 * p = (const TCmdParam3 *) pCmd; + + DROPLOG("CMD_SPELLPID(%d): id->%d\n",pnum,p->wParam1); + + // PATCH2.JMM.3/5/97 + UINT nSplType = p->wParam2; + + if(currlevel == 0 && !spelldata[nSplType].sTownSpell) { + IdentifyCheater("%s has cast an illegal spell.",plr[pnum]._pName); + return sizeof(TCmdParam3); + } + // ENDPATCH2.JMM.3/5/97 + + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_SPELLPID; + plr[pnum].destParam1 = p->wParam1; + plr[pnum].destParam2 = p->wParam3; + plr[pnum]._pSpell = p->wParam2; + plr[pnum]._pSplType = plr[pnum]._pRSplType; + plr[pnum]._pSplFrom = SPL_FROMR; + } + + return sizeof(TCmdParam3); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_TSPELLID( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam3 * p = (const TCmdParam3 *) pCmd; + + DROPLOG("CMD_TSPELLID(%d): id->%d\n",pnum,p->wParam1); + + // PATCH2.JMM.3/5/97 + UINT nSplType = p->wParam2; + + if(currlevel == 0 && !spelldata[nSplType].sTownSpell) { + IdentifyCheater("%s has cast an illegal spell.",plr[pnum]._pName); + return sizeof(TCmdParam3); + } + // ENDPATCH2.JMM.3/5/97 + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_SPELLID; + plr[pnum].destParam1 = p->wParam1; + plr[pnum].destParam2 = p->wParam3; + plr[pnum]._pSpell = p->wParam2; + plr[pnum]._pSplType = plr[pnum]._pTSplType; + plr[pnum]._pSplFrom = SPL_FROMT; + } + + return sizeof(TCmdParam3); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_TSPELLPID( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam3 * p = (const TCmdParam3 *) pCmd; + + DROPLOG("CMD_TSPELLPID(%d): id->%d\n",pnum,p->wParam1); + + // PATCH2.JMM.3/5/97 + UINT nSplType = p->wParam2; + + if(currlevel == 0 && !spelldata[nSplType].sTownSpell) { + IdentifyCheater("%s has cast an illegal spell.",plr[pnum]._pName); + return sizeof(TCmdParam3); + } + // ENDPATCH2.JMM.3/5/97 + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_SPELLPID; + plr[pnum].destParam1 = p->wParam1; + plr[pnum].destParam2 = p->wParam3; + plr[pnum]._pSpell = p->wParam2; + plr[pnum]._pSplType = plr[pnum]._pTSplType; + plr[pnum]._pSplFrom = SPL_FROMT; + } + + return sizeof(TCmdParam3); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_KNOCKBACK( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_KNOCKBACK(%d): id->%d\n",pnum,p->wParam1); + + if (currlevel == plr[pnum].plrlevel) { + M_GetKnockback(p->wParam1); + M_StartHit(p->wParam1, pnum, 0); + } + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_RESURRECT( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_RESURRECT(%d): id->%d\n",pnum,p->wParam1); + + DoResurrect(pnum, p->wParam1); + + // update character file to prevent cheating + check_update_plr(pnum); + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_HEALOTHER( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_HEALOTHER(%d): id->%d\n",pnum,p->wParam1); + + DoHealOther(pnum, p->wParam1); + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_TALKXY( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else if (currlevel == plr[pnum].plrlevel) { + const TCmdLocParam1 * p = (const TCmdLocParam1 *) pCmd; + + DROPLOG("CMD_TALKXY(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + MakePlrPath(pnum, p->x, p->y, FALSE); + plr[pnum].destAction = PCMD_TALK; + plr[pnum].destParam1 = p->wParam1; + } + + return sizeof(TCmdLocParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_NEWLVL( const TCmd* pCmd, int pnum ) { + + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam2)); + } + else if (pnum != myplr) { + const TCmdParam2 * p = (const TCmdParam2 *) pCmd; + + DROPLOG("CMD_NEWLVL(%d)\n",pnum); + + StartNewLvl(pnum,p->wParam1,p->wParam2); + } + + return sizeof(TCmdParam2); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_WARP( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + + DROPLOG("CMD_WARP(%d)\n",pnum); + + StartWarpLvl(pnum, p->wParam1); + + // drb.patch1.start.02/15/97 + if ((pnum == myplr) && (curs >= ICSTART)) { + item[TEMPAVAIL] = plr[myplr].HoldItem; + AutoGetItem(myplr, TEMPAVAIL); + } + // drb.patch1.end.02/15/97 + + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_MONSTDEATH( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdLocParam1)); + } + else if (pnum != myplr) { + const TCmdLocParam1 * p = (const TCmdLocParam1 *) pCmd; + DROPLOG("CMD_MONSTDEATH(%d): id->%d xy->(%d,%d)\n",pnum,p->wParam1,p->x,p->y); + if (currlevel == plr[pnum].plrlevel) + M_SyncStartKill(p->wParam1, p->x, p->y, pnum); + delta_kill_monster(p->wParam1, p->x, p->y,plr[pnum].plrlevel); + } + + return sizeof(TCmdLocParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_KILLGOLEM( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdLocParam1)); + } + else if (pnum != myplr) { + const TCmdLocParam1 * p = (const TCmdLocParam1 *) pCmd; + DROPLOG("CMD_KILLGOLEM(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + if (currlevel == p->wParam1) + M_SyncStartKill(pnum, p->x, p->y, pnum); + delta_kill_monster(pnum, p->x, p->y, plr[pnum].plrlevel); + } + + return sizeof(TCmdLocParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_AWAKEGOLEM( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) + mega_add_data(pnum, pCmd, sizeof(TCmdGolem)); + else { + DROPLOG("CMD_AWAKENGOLEM(%d)\n",pnum); + if (currlevel != plr[pnum].plrlevel) + delta_sync_golem((const TCmdGolem *) pCmd, pnum, ((const TCmdGolem *) pCmd)->_currlevel); + else { + if (pnum != myplr) { + BOOL addok = TRUE; + for (int i = 0; i < nummissiles; i++) { + int mi = missileactive[i]; + if ((missile[mi]._mitype == MIT_GOLEM) && (missile[mi]._misource == pnum)) addok = FALSE; + } + const TCmdGolem * pG = (const TCmdGolem *) pCmd; + if (addok) AddMissile(plr[pnum]._px, plr[pnum]._py, pG->_mx, pG->_my, pG->_mdir, MIT_GOLEM, MI_ENEMYMONST, pnum, 0, 1); + } + } + } + + return sizeof(TCmdGolem); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_MONSTDAMAGE( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam2)); + } + else if (pnum != myplr) { + const TCmdMonstDamage * p = (const TCmdMonstDamage *) pCmd; + + DROPLOG("CMD_MONSTDAMAGE(%d): id->%d\n",pnum,p->wMonst); + + if (currlevel == plr[pnum].plrlevel) { + monster[p->wMonst].mWhoHit |= (1 << pnum); + if (monster[p->wMonst]._mhitpoints >= 0) { + monster[p->wMonst]._mhitpoints -= p->dwDam; + // take damage but don't kill him + if ((monster[p->wMonst]._mhitpoints >> HP_SHIFT) < 1) + monster[p->wMonst]._mhitpoints = 1 << HP_SHIFT; + delta_monster_hp(p->wMonst,monster[p->wMonst]._mhitpoints,plr[pnum].plrlevel); + } + } + else { + // @@@@ Dave -- need some way to calculate new monster hp + // since we don't have its info handy + } + } + + return sizeof(TCmdMonstDamage); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_PLRDEAD( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else if (pnum != myplr) { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_PLAYERDEAD(%d): id->%d\n",pnum,p->wParam1); + SyncPlrKill(pnum, p->wParam1); + } + else { + DROPLOG("CMD_PLAYERDEAD(I'm dead!!!)\n",pnum); + check_update_plr(pnum); + } + + return sizeof(TCmdParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_PLRDAMAGE( const TCmd* pCmd, int pnum ) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + const TCmdDamage * p = (const TCmdDamage *) pCmd; + DROPLOG("CMD_PLAYERDAMAGE(%d)\n",pnum); + + if (p->bPlr != myplr) { + // ignore message + } + // JMM.PATCH1 + else if (currlevel == 0) { + // illegal message! + } + // JMM.ENDPATCH1 + else if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered, because + // the player isn't active yet, so he + // can't be taking any damage + } + // PATCH2.JMM.3/5/97 + else if (currlevel != plr[pnum].plrlevel) { + // illegal message! (player must be on same level) + } + else if ( p->dwDam > (3000<%d\n",currlevel); + // If I am already dead, don't kill me again. + if ((plr[myplr]._pHitPoints >> HP_SHIFT) > 0) { + // not dead yet + drawhpflag = TRUE; + plr[myplr]._pHitPoints -= p->dwDam; + plr[myplr]._pHPBase -= p->dwDam; + if (plr[myplr]._pHitPoints > plr[myplr]._pMaxHP) { + plr[myplr]._pHitPoints = plr[myplr]._pMaxHP; + plr[myplr]._pHPBase = plr[myplr]._pMaxHPBase; + } + if ((plr[myplr]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - plr[myplr]._pHitPoints = 0; + StartPlrKill(myplr, TRUE); + } + } + } + + return sizeof(TCmdDamage); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_OPENDOOR( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_OPENDOOR(%d): id->%d\n",pnum,p->wParam1); + if (currlevel == plr[pnum].plrlevel) + SyncOpObject(pnum, CMD_OPENDOOR, p->wParam1); + delta_sync_object(p->wParam1,CMD_OPENDOOR,plr[pnum].plrlevel); + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**----------------------------------------------------------------------*/ +static DWORD On_CLOSEDOOR( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_CLOSEDOOR(%d): id->%d\n",pnum,p->wParam1); + if (currlevel == plr[pnum].plrlevel) + SyncOpObject(pnum, CMD_CLOSEDOOR, p->wParam1); + delta_sync_object(p->wParam1,CMD_CLOSEDOOR,plr[pnum].plrlevel); + } + + return sizeof(TCmdParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_OPERATEOBJ( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_OPERATEOBJ(%d): id->%d\n",pnum,p->wParam1); + if (currlevel == plr[pnum].plrlevel) + SyncOpObject(pnum, CMD_OPERATEOBJ, p->wParam1); + delta_sync_object(p->wParam1,CMD_OPERATEOBJ,plr[pnum].plrlevel); + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_PLROPOBJ( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam2)); + } + else { + const TCmdParam2 * p = (const TCmdParam2 *) pCmd; + DROPLOG("CMD_PLAYEROPOBJ(%d): plrid->%d objid->%d\n",pnum,p->wParam1,p->wParam2); + if (currlevel == plr[pnum].plrlevel) + SyncOpObject(p->wParam1, CMD_PLROPOBJ, p->wParam2); + delta_sync_object(p->wParam2,CMD_PLROPOBJ,plr[pnum].plrlevel); + } + + return sizeof(TCmdParam2); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_BREAKOBJ( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam2)); + } + else { + const TCmdParam2 * p = (const TCmdParam2 *) pCmd; + DROPLOG("CMD_BREAKOBJ(%d): id1->%d id2->%d\n",pnum,p->wParam1,p->wParam2); + if (currlevel == plr[pnum].plrlevel) + SyncBreakObj(p->wParam1, p->wParam2); + delta_sync_object(p->wParam2,CMD_BREAKOBJ,plr[pnum].plrlevel); + } + + return sizeof(TCmdParam2); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_CHANGEPLRITEMS( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdChItem)); + } + else { + const TCmdChItem * p = (const TCmdChItem *) pCmd; + DROPLOG("CMD_CHANGEPLAYERITEMS(%d): index->%8.8x ci->%8.8x seed->%8.8x\n",pnum,p->wIndx, p->wCI, p->dwSeed); + // drb.patch1.start.02/10/97 + // if (pnum != myplr) SyncInvPaste(pnum, p->bLoc, p->wIndx, p->wCI, p->dwSeed); + if (pnum != myplr) SyncInvPaste(pnum, p->bLoc, p->wIndx, p->wCI, p->dwSeed, p->bId); + // drb.patch1.end.02/10/97 + } + + return sizeof(TCmdChItem); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_DELPLRITEMS( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdDelItem)); + } + else { + const TCmdDelItem * p = (const TCmdDelItem *) pCmd; + DROPLOG("CMD_DELPLAYERITEMS(%d): loc->%d\n",pnum, p->bLoc); + if (pnum != myplr) SyncInvCut(pnum, p->bLoc); + } + + return sizeof(TCmdDelItem); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_PLRLEVEL( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_PLAYERLEVEL(%d)\n",pnum); + + if ((p->wParam1 <= MAX_LEVEL) && pnum != myplr) + plr[pnum]._pLevel = (char) p->wParam1; + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_DROPITEM( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdPItem)); + } + else { + // item dropped by a dead monster/chest/etc. + // doesn't have to do anything to level data + // only to delta info + const TCmdPItem * p = (const TCmdPItem *) pCmd; + DROPLOG("CMD_DROPITEM(%d): index->%8.8x ci->%8.8x seed->%8.8x xy->(%d,%d)\n",pnum,p->wIndx, p->wCI, p->dwSeed, p->x, p->y); + delta_put_item(p,p->x,p->y,plr[pnum].plrlevel); + } + + return sizeof(TCmdPItem); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SEND_PLRINFO( const TCmd* pCmd, int pnum ) { + const TCmdPlrInfoHdr * p = (const TCmdPlrInfoHdr *) pCmd; + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,p,p->wBytes + sizeof(TCmdPlrInfoHdr)); + } + else { + DROPLOG("CMD_ACK\\SENDPLRINFO(%d)\n",pnum); + recv_plrinfo(pnum,p,p->bCmd == CMD_ACK_PLRINFO); + } + + return p->wBytes + sizeof(TCmdPlrInfoHdr); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ACK_PLRINFO( const TCmd* pCmd, int pnum ) { + return On_SEND_PLRINFO( pCmd, pnum ); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_PLAYER_JOINLEVEL( const TCmd* pCmd, int pnum ) { + + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdLocParam1)); + } + else { + app_assert((DWORD)pnum < MAX_PLRS); + DROPLOG("CMD_PLAYERJOINLEVEL(%d)\n",pnum); + + plr[pnum]._pLvlChanging = FALSE; + + // joining game? + if (! plr[pnum]._pName[0]) { + // we are probably unbuffering messages, + // and we received this message before we + // received the message that tells us who + // this player is. Just ignore this message. + // Eventually we will get a PLRINFO message + // which will activate this player + #if TRACEOUT + TraceOut("(%d) received %d joinlevel before plrdata",myplr,pnum); + #endif + } + else if (! plr[pnum].plractive) { + plr[pnum].plractive = 1; + gbActivePlayers++; + sysmsg_add("Player '%s' (level %d) just joined the game",plr[pnum]._pName,plr[pnum]._pLevel); + #if TRACEOUT + TraceOut("(%d) activating %d on joinlevel",myplr,pnum); + #endif + } + + // activate player on this level + if (plr[pnum].plractive && myplr != pnum) { + const TCmdLocParam1 * p = (const TCmdLocParam1 *) pCmd; + plr[pnum]._px = p->x; + plr[pnum]._py = p->y; + plr[pnum].plrlevel = p->wParam1; + plr[pnum]._pGFXLoad = 0; + if (currlevel == plr[pnum].plrlevel) { + LoadPlrGFX(pnum,PGL_STAND); + SyncInitPlr(pnum); + if ((plr[pnum]._pHitPoints >> HP_SHIFT) > 0) { + StartStand(pnum,0); + } else { + plr[pnum]._pgfxnum = PGFX_NGUY; + LoadPlrGFX(pnum, PGL_DEAD); + plr[pnum]._pmode = PM_DEATH; + NewPlrAnim(pnum, plr[pnum]._pDAnim[DIR_D], plr[pnum]._pDFrames, 1, plr[pnum]._pDWidth); + plr[pnum]._pAnimFrame = plr[pnum]._pAnimLen - 1; + plr[pnum]._pVar8 = plr[pnum]._pAnimLen << 1; + dFlags[plr[pnum]._px][plr[pnum]._py] |= BFLAG_DEADPLR; + } + plr[pnum]._pvid = AddVision(plr[pnum]._px, plr[pnum]._py, + plr[pnum]._pLightRad, pnum==myplr); + plr[pnum]._plid = -1; + } + } + } + return sizeof(TCmdLocParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ACTIVATEPORTAL( const TCmd* pCmd, int pnum ) { + + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdLocParam3)); + } + else { + const TCmdLocParam3 * p = (const TCmdLocParam3 *) pCmd; + + DROPLOG("CMD_ACTIVATEPORTAL(%d): xy->(%d,%d)\n",pnum,p->x,p->y); + + ActivatePortal(pnum, p->x, p->y, p->wParam1, p->wParam2, p->wParam3); + if (pnum != myplr) { + if (currlevel == 0) { + AddInTownPortal(pnum); + } else { + if (currlevel == plr[pnum].plrlevel) { + // If on same level make sure portal appears + int i,mi; + BOOL addok = TRUE; + for (i = 0; i < nummissiles; i++) { + mi = missileactive[i]; + if ((missile[mi]._mitype == MIT_TOWN) && (missile[mi]._misource == pnum)) addok = FALSE; + } + if (addok) AddWarpMissile(pnum, p->x, p->y); + } else { + // Remove portal if it was on my level before + RemovePortalMissile(pnum); + } + } + } + delta_open_portal(pnum,p->x,p->y,(BYTE) p->wParam1,(BYTE) p->wParam2, (BYTE) p->wParam3); + } + + return sizeof(TCmdLocParam3); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_DEACTIVATEPORTAL( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmd)); + } + else { + DROPLOG("CMD_DEACTIVEPORTAL(%d)\n",pnum); + if (PortalOnLevel(pnum)) RemovePortalMissile(pnum); + DeactivatePortal(pnum); + delta_close_portal(pnum); + } + + return sizeof(TCmd); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_RETOWN( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmd)); + } + else { + DROPLOG("CMD_RETOWN(%d)\n",pnum); + if (pnum == myplr) { + deathflag = FALSE; + gamemenu_off(); + } + RestartTownLvl(pnum); + } + + return sizeof(TCmd); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SETSTR( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_SETSTR(%d)\n",pnum); + + if( p->wParam1 > MAX_STAT ) + return sizeof( TCmdParam1 ); + + if (pnum != myplr) { + SetPlrStr(pnum, p->wParam1); + } + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SETDEX( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_SETDEX(%d)\n",pnum); + + if( p->wParam1 > MAX_STAT ) + return sizeof( TCmdParam1 ); + + if (pnum != myplr) { + SetPlrDex(pnum, p->wParam1); + } + } + + return sizeof(TCmdParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SETMAG( const TCmd* pCmd, int pnum ) { + + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_SETMAG(%d)\n",pnum); + + if( p->wParam1 > MAX_STAT ) + return sizeof( TCmdParam1 ); + + + if (pnum != myplr) { + SetPlrMag(pnum, p->wParam1); + } + } + + return sizeof(TCmdParam1); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SETVIT( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdParam1)); + } + else { + const TCmdParam1 * p = (const TCmdParam1 *) pCmd; + DROPLOG("CMD_SETVIT(%d)\n",pnum); + + if( p->wParam1 > MAX_STAT ) + return sizeof( TCmdParam1 ); + + + if (pnum != myplr) { + SetPlrVit(pnum, p->wParam1); + } + } + + return sizeof(TCmdParam1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_STRING( const TCmd* pCmd, int pnum ) { + + DROPLOG("CMD_STRING(%d)\n",pnum); + // cmd_string handles gbBufferMsgs + return cmd_string(pnum,(const TCmdString *) pCmd); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_SYNCQUEST( const TCmd* pCmd, int pnum ) { + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmdQuest)); + } + else { + DROPLOG("CMD_SYNCQUEST(%d)\n",pnum); + if (pnum != myplr) { + const TCmdQuest * p = (const TCmdQuest *) pCmd; + SetMultiQuest(p->q, p->qstate, p->qlog, p->qvar1); + } + + sgbDeltaChanged = TRUE; + } + + return sizeof(TCmdQuest); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ENDSHIELD( const TCmd* pCmd, int pnum ) { + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else { + DROPLOG("CMD_ENDSHIELD(%d)\n",pnum); + if ((pnum != myplr) && (currlevel == plr[pnum].plrlevel)) { + void DeleteMissile(int, int); + for (int i = 0; i < nummissiles; i++) { + int mi = missileactive[i]; + if ((missile[mi]._mitype == MIT_MANASHIELD) && (missile[mi]._misource == pnum)) { + ClearMissileSpot(mi); + DeleteMissile(mi, i); + } + } + + } + } + + return sizeof(TCmd); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_ENDREFLECT( const TCmd* pCmd, int pnum ) { + + if (gbBufferMsgs == BUFFER_ON) { + // doesn't need to be buffered + } + else { + DROPLOG("CMD_ENDREFLECT(%d)\n",pnum); + if ((pnum != myplr) && (currlevel == plr[pnum].plrlevel)) { + void DeleteMissile(int, int); + for (int i = 0; i < nummissiles; i++) { + int mi = missileactive[i]; + if ((missile[mi]._mitype == MIT_REFLECT) && (missile[mi]._misource == pnum)) { + ClearMissileSpot(mi); + DeleteMissile(mi, i); + } + } + + } + } + + return sizeof(TCmd); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_CHEAT_EXPERIENCE( const TCmd* pCmd, int pnum ) { + +#if _DEBUG + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmd)); + } + else { + DROPLOG("CMD_CHEATEXPERIENCE(%d)\n",pnum); + if (plr[pnum]._pLevel < 50) { + plr[pnum]._pExperience = plr[pnum]._pNextExper; + NextPlrLevel(pnum); + } + } +#endif + + return sizeof(TCmd); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_CHEAT_SPELL_LEVEL( const TCmd* pCmd, int pnum ) { + +#if _DEBUG + if (gbBufferMsgs == BUFFER_ON) { + mega_add_data(pnum,pCmd,sizeof(TCmd)); + } + else { + DROPLOG("CMD_CHEATSPELLLEVEL(%d)\n",pnum); + plr[pnum]._pSplLvl[plr[pnum]._pRSpell]++; + } +#endif + + return sizeof(TCmd); +} +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_OPEN_NAKRUL(const TCmd* pCmd, int pnum) +{ + if (gbBufferMsgs == BUFFER_ON) + { + // doesn't need to be buffered + } + else + { + DROPLOG("CMD_OPEN_NAKRUL(%d)\n",pnum); + + OpenNaKrul(); + Na_Krul.Books = TRUE; + quests[Q_NA_KRUL]._qactive = QUEST_DONE; + Hose_NaKrul(); + + } + return sizeof(TCmd); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_OPEN_NEST(const TCmd * pCmd, int pnum) +{ + if (gbBufferMsgs == BUFFER_ON) + { + // doesn't need to be buffered + } + else + { + DROPLOG("CMD_OPEN_NEST(%d)\n",pnum); + const TCmdLocParam2 * p = (const TCmdLocParam2 *) pCmd; + + AddMissile (p->x, p->y, p->wParam1, p->wParam2, 0, MIT_OPENNEST, MI_PLR, pnum, 0, 0); + OpenNest(); + } + return sizeof(TCmdLocParam2); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_OPEN_CRYPT(const TCmd* pCmd, int pnum) +{ + if (gbBufferMsgs == BUFFER_ON) + { + // doesn't need to be buffered + } + else + { + DROPLOG("CMD_OPEN_CRYPT(%d)\n",pnum); + + OpenCrypt(); + InitTownTriggers(); + if (currlevel == TLVL_START) // In town + PlaySFX(IS_SARC); + + } + return sizeof(TCmd); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static DWORD On_DEBUG( const TCmd* pCmd, int pnum ) { + return sizeof(TCmd); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// PATCH3.JMM +extern WORD sgwPackPlrOffsetTbl[MAX_PLRS]; +// ENDPATCH3.JMM +#define HANDLE_CMD( c ) case CMD_##c : return On_##c( pCmd, pnum ) +DWORD ParseCmd(int pnum,const TCmd * pCmd) { + app_assert((DWORD)pnum < MAX_PLRS); + app_assert(pCmd != NULL); + + static BYTE sbLastCmd; + sbLastCmd = pCmd->bCmd; + + // patch3.jmm + if( sgwPackPlrOffsetTbl[pnum] && + sbLastCmd != CMD_ACK_PLRINFO && + sbLastCmd != CMD_SEND_PLRINFO ) + return 0; + // endpatch3.jmm + + switch(pCmd->bCmd) { + HANDLE_CMD( SYNCDATA ); + HANDLE_CMD( WALKXY ); + HANDLE_CMD( ADDSTR ); + HANDLE_CMD( ADDDEX ); + HANDLE_CMD( ADDMAG ); + HANDLE_CMD( ADDVIT ); + HANDLE_CMD( SBSPELL ); + HANDLE_CMD( GOTOGETITEM ); + HANDLE_CMD( REQUESTGITEM ); + HANDLE_CMD( GETITEM ); + HANDLE_CMD( GOTOAGETITEM ); + HANDLE_CMD( REQUESTAGITEM ); + HANDLE_CMD( AGETITEM ); + HANDLE_CMD( ITEMEXTRA ); + HANDLE_CMD( PUTITEM ); + HANDLE_CMD( SYNCPUTITEM ); + HANDLE_CMD( RESPAWNITEM ); + HANDLE_CMD( ATTACKXY ); + HANDLE_CMD( SATTACKXY ); + HANDLE_CMD( RATTACKXY ); + HANDLE_CMD( SPELLXYD ); + HANDLE_CMD( SPELLXY ); + HANDLE_CMD( TSPELLXY ); + HANDLE_CMD( OPOBJXY ); + HANDLE_CMD( DISARMXY ); + HANDLE_CMD( OPOBJT ); + HANDLE_CMD( ATTACKID ); + HANDLE_CMD( ATTACKPID ); + HANDLE_CMD( RATTACKID ); + HANDLE_CMD( RATTACKPID ); + HANDLE_CMD( SPELLID ); + HANDLE_CMD( SPELLPID ); + HANDLE_CMD( TSPELLID ); + HANDLE_CMD( TSPELLPID ); + HANDLE_CMD( KNOCKBACK ); + HANDLE_CMD( RESURRECT ); + HANDLE_CMD( HEALOTHER ); + HANDLE_CMD( TALKXY ); + HANDLE_CMD( DEBUG ); + HANDLE_CMD( NEWLVL ); + HANDLE_CMD( WARP ); + HANDLE_CMD( MONSTDEATH ); + HANDLE_CMD( KILLGOLEM ); + HANDLE_CMD( AWAKEGOLEM ); + HANDLE_CMD( MONSTDAMAGE ); + HANDLE_CMD( PLRDEAD ); + HANDLE_CMD( PLRDAMAGE ); + HANDLE_CMD( OPENDOOR ); + HANDLE_CMD( CLOSEDOOR ); + HANDLE_CMD( OPERATEOBJ ); + HANDLE_CMD( PLROPOBJ ); + HANDLE_CMD( BREAKOBJ ); + HANDLE_CMD( CHANGEPLRITEMS ); + HANDLE_CMD( DELPLRITEMS ); + HANDLE_CMD( PLRLEVEL ); + HANDLE_CMD( DROPITEM ); + HANDLE_CMD( ACK_PLRINFO ); + HANDLE_CMD( SEND_PLRINFO ); + HANDLE_CMD( PLAYER_JOINLEVEL ); + HANDLE_CMD( ACTIVATEPORTAL ); + HANDLE_CMD( DEACTIVATEPORTAL ); + HANDLE_CMD( RETOWN ); + HANDLE_CMD( SETSTR ); + HANDLE_CMD( SETMAG ); + HANDLE_CMD( SETDEX ); + HANDLE_CMD( SETVIT ); + HANDLE_CMD( STRING ); + HANDLE_CMD( SYNCQUEST ); + HANDLE_CMD( ENDSHIELD ); + HANDLE_CMD( CHEAT_EXPERIENCE ); + HANDLE_CMD( CHEAT_SPELL_LEVEL ); + HANDLE_CMD( ENDREFLECT ); + HANDLE_CMD( OPEN_NAKRUL ); + HANDLE_CMD( OPEN_NEST ); + HANDLE_CMD( OPEN_CRYPT ); + + default: + // dreceive_level handles gbBufferMsgs + if (pCmd->bCmd >= CMD_DLEVEL_0 && pCmd->bCmd <= CMD_DLEVEL_END) + return dreceive_chunk(pnum,(const TCmdPlrInfoHdr *) pCmd); +// PATCH3.JMM +// app_fatal("Unknown PCMD %d (last cmd %d)\n",pCmd->bCmd,sbLastCmd); + SNetDropPlayer( pnum, SNET_EXIT_NOTRESPONDING ); + return 0; // 0 is error condition: ditch rest of packet +// ENDPATCH3.JMM + } + + + // NO final return statement -- each case + // should have its own return statement +} +// ENDPATCH2.JMM.3/5/97 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* +int GetLDeltaItem(int itm) +{ + TCmdPItem * pD = &sgLevels[currlevel].item[0]; + for (int i = 0; i < MAXITEMS; i++,pD++) { + // find item + if (pD->bCmd == ITEM_FREE) continue; + if (pD->wIndx != item[itm].IDidx) continue; + if (pD->wCI != item[itm]._iCreateInfo) continue; + if (pD->dwSeed != (DWORD)item[itm]._iSeed) continue; + return(i); + } + return(-1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +/* +old old old +void test_delta() { + static DLevel lvl[NUMLEVELS]; + + // randomize the level delta data + sgbDeltaChanged = TRUE; + srand(time(NULL)); + WORD * p = (WORD *) &sgLevels[0]; + for (int i = sizeof(sgLevels)/2; i--; ) + *p++ = rand(); + + // save level data for later comparison + CopyMemory(&lvl[0],&sgLevels[0],sizeof lvl); + + // send level delta info to myself + DeltaSendAllLevels(myplr); + + // reinit level delta info + ZeroMemory(&sgLevels[0],sizeof sgLevels); + + // get level delta packets + NetReceivePackets(); + + // make sure everything comps ok + for (i = 0; i < NUMLEVELS; i++) { + for (int j = 0; j < MAXITEMS; j++) { + if (sgLevels[i].item[j].bCmd == INIT_VAL) { + if (lvl[i].item[j].bCmd != INIT_VAL) + DebugBreak(); + } + else if (memcmp(&sgLevels[i].item[j],&lvl[i].item[j],sizeof(TCmdPItem))) { + DebugBreak(); + } + } + for (j = 0; j < MAXOBJECTS; j++) { + if (memcmp(&sgLevels[i].object[j],&lvl[i].object[j],sizeof(DObjectStr))) + DebugBreak(); + } + for (j = 0; j < MAXMONSTERS; j++) { + if (sgLevels[i].monster[j]._mx == INIT_VAL) { + if (lvl[i].monster[j]._mx != INIT_VAL) + DebugBreak(); + } + else if (memcmp(&sgLevels[i].monster[j],&lvl[i].monster[j],sizeof(DMonsterStr))) { + DebugBreak(); + } + } + } + + // reinit delta info + delta_init(); +} +*/ diff --git a/src/MSG.H b/src/MSG.H new file mode 100644 index 0000000..1ceb8fc --- /dev/null +++ b/src/MSG.H @@ -0,0 +1,260 @@ +//****************************************************************** +// msg.h +//****************************************************************** + +enum { + CMD_STAND = 0, + CMD_WALKXY, + CMD_ACK_PLRINFO, + CMD_ADDSTR, + CMD_ADDMAG, + CMD_ADDDEX, + CMD_ADDVIT, + CMD_SBSPELL, + CMD_GETITEM, + CMD_AGETITEM, + CMD_PUTITEM, + CMD_RESPAWNITEM, + CMD_ATTACKXY, + CMD_RATTACKXY, + CMD_SPELLXY, + CMD_TSPELLXY, + CMD_OPOBJXY, + CMD_DISARMXY, + CMD_ATTACKID, + CMD_ATTACKPID, + CMD_RATTACKID, + CMD_RATTACKPID, + CMD_SPELLID, + CMD_SPELLPID, + CMD_TSPELLID, + CMD_TSPELLPID, + CMD_RESURRECT, + CMD_OPOBJT, + CMD_KNOCKBACK, + CMD_TALKXY, + CMD_NEWLVL, + CMD_WARP, + CMD_CHEAT_EXPERIENCE, + CMD_CHEAT_SPELL_LEVEL, + CMD_DEBUG, + CMD_SYNCDATA, + CMD_MONSTDEATH, + CMD_MONSTDAMAGE, + CMD_PLRDEAD, + CMD_REQUESTGITEM, + CMD_REQUESTAGITEM, + CMD_GOTOGETITEM, + CMD_GOTOAGETITEM, + CMD_OPENDOOR, + CMD_CLOSEDOOR, + CMD_OPERATEOBJ, + CMD_PLROPOBJ, + CMD_BREAKOBJ, + CMD_CHANGEPLRITEMS, + CMD_DELPLRITEMS, + CMD_PLRDAMAGE, + CMD_PLRLEVEL, + CMD_DROPITEM, + CMD_PLAYER_JOINLEVEL, + CMD_SEND_PLRINFO, + CMD_SATTACKXY, + CMD_ACTIVATEPORTAL, + CMD_DEACTIVATEPORTAL, + CMD_DLEVEL_0, + CMD_DLEVEL_1, + CMD_DLEVEL_2, + CMD_DLEVEL_3, + CMD_DLEVEL_4, + CMD_DLEVEL_5, + CMD_DLEVEL_6, + CMD_DLEVEL_7, + CMD_DLEVEL_8, + CMD_DLEVEL_9, + CMD_DLEVEL_10, + CMD_DLEVEL_11, + CMD_DLEVEL_12, + CMD_DLEVEL_13, + CMD_DLEVEL_14, + CMD_DLEVEL_15, + CMD_DLEVEL_16, + CMD_DLEVEL_17, + CMD_DLEVEL_18, + CMD_DLEVEL_19, + CMD_DLEVEL_20, + CMD_DLEVEL_21, + CMD_DLEVEL_22, + CMD_DLEVEL_23, + CMD_DLEVEL_24, + CMD_DLEVEL_JUNK, + CMD_DLEVEL_END, + CMD_HEALOTHER, + CMD_STRING, + CMD_SETSTR, + CMD_SETMAG, + CMD_SETDEX, + CMD_SETVIT, + CMD_RETOWN, + CMD_SPELLXYD, + CMD_ITEMEXTRA, + CMD_SYNCPUTITEM, + CMD_KILLGOLEM, + CMD_SYNCQUEST, + CMD_ENDSHIELD, + CMD_AWAKEGOLEM, + CMD_ENDREFLECT, + CMD_OPEN_NAKRUL, + CMD_OPEN_NEST, + CMD_OPEN_CRYPT, + + // thse are commands which are never sent + FAKE_CMD_SETID, + FAKE_CMD_DROPID, + NUM_CMDS +}; + + +//****************************************************************** +// net commands +//****************************************************************** +#pragma pack(push,1) +typedef struct TCmd { + BYTE bCmd; +} TCmd; +void NetSendCmd(BOOL bHiPri,BYTE bCmd); + +void NetSendCmdLoc(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y); +void NetSendCmdLocParam1(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1); +void NetSendCmdLocParam2(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1,WORD wParam2); +void NetSendCmdLocParam3(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1,WORD wParam2,WORD wParam3); + +void NetSendCmdParam1(BOOL bHiPri,BYTE bCmd,WORD wParam1); +void NetSendCmdParam2(BOOL bHiPri,BYTE bCmd,WORD wParam1,WORD wParam2); +void NetSendCmdParam3(BOOL bHiPri,BYTE bCmd,WORD wParam1,WORD wParam2, WORD wParam3 ); + +void NetSendCmdQuest(BOOL bHiPri,BYTE q); + +void NetSendCmdGItem(BOOL bHiPri,BYTE bCmd,BYTE mast,BYTE pnum,BYTE bCursitem); +void NetSendCmdPItem(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y); +void NetSendCmdDItem(BOOL bHiPri,int ii); +void NetSendCmdChItem(BOOL bHiPri,BYTE bLoc); +void NetSendCmdDelItem(BOOL bHiPri,BYTE bLoc); + +void NetSendCmdDamage(BOOL bHiPri,BYTE bPlr,DWORD dwDam); +void NetSendCmdMonstDamage(BOOL bHiPri,WORD bMonst,DWORD dwDam); + +typedef struct TCmdPlrInfoHdr { + BYTE bCmd; + WORD wOffset; + WORD wBytes; +} TCmdPlrInfoHdr; + +// better not be bigger than this, the net will choke +#define MAX_SEND_STR_LEN 80 +#define SEND_ALL_MASK 0xffffffff +void NetSendString(DWORD dwSendMask,const char * pszStr); + + +#pragma pack(pop) + + +//****************************************************************** +// net syncing +//****************************************************************** +#pragma pack(push,1) +typedef struct TSyncHeader { + BYTE bCmd; + BYTE bLevel; + WORD wLen; + BYTE bObjId; + BYTE bObjCmd; + BYTE bItemI; + BYTE bItemX; + BYTE bItemY; + WORD wItemIndx; + WORD wItemCI; + int dwItemSeed; + BYTE bItemId; + BYTE bItemDur; + BYTE bItemMDur; + BYTE bItemCh; + BYTE bItemMCh; + WORD wItemVal; + DWORD dwItemBuff; + BYTE bPInvLoc; + WORD wPInvIndx; + WORD wPInvCI; + int dwPInvSeed; + // drb.patch1.start.02/10/97 + BYTE bPInvId; + // drb.patch1.end.02/10/97 + WORD wPLToHit; + WORD wMaxDam; + BYTE bMinStr; + BYTE bMinMag; + BYTE bMinDex; + BYTE bAC; +} TSyncHeader; + +typedef struct TSyncMonster { + BYTE _mndx; + BYTE _mx; + BYTE _my; + BYTE _menemy; + BYTE _mdelta; +} TSyncMonster; +#pragma pack(pop) + + +//****************************************************************** +// msg sizes +//****************************************************************** +#define MIN_MSG_SIZE 128 +#define MAX_MSG_SIZE 512 +extern DWORD gdwNormalMsgSize; // MIN_MSG_SIZE..MAX_MSG_SIZE +extern DWORD gdwLargestMsgSize; // MIN_MSG_SIZE..MAX_MSG_SIZE + + +//****************************************************************** +// net packets (which hold net commands inside them) +//****************************************************************** +#pragma pack(push,1) +typedef struct TPktHdr { + BYTE px; + BYTE py; + BYTE targx; + BYTE targy; + DWORD php; + DWORD pmhp; + BYTE bstr; + BYTE bmag; + BYTE bdex; + WORD wCheck; // @@ debug -- delete this + WORD wLen; // @@ debug -- delete this +} TPktHdr; +typedef struct TPkt { + TPktHdr hdr; + BYTE body[MAX_MSG_SIZE - sizeof TPktHdr]; +} TPkt; +#pragma pack(pop) + + +//****************************************************************** +//****************************************************************** +extern BOOL deltaload; +void DeltaSaveLevel(); +void DeltaLoadLevel(); +void DeltaSendAllLevels(int pnum); +DWORD ParseCmd(int pnum, const TCmd * pCmd); +void DeltaAddItem(int ii); + +// PATCH1.JMM +#if _DEBUG +void __cdecl DROPLOG(const char * pszFmt,...); +void VerifyItemActiveList( void ); +#else +#define VerifyItemActiveList( ) +#define DROPLOG // +#endif +// ENDPATCH1 + diff --git a/src/MSSCCPRJ.SCC b/src/MSSCCPRJ.SCC new file mode 100644 index 0000000..e8c4a0b --- /dev/null +++ b/src/MSSCCPRJ.SCC @@ -0,0 +1,4 @@ +SCC = This is a Source Code Control file + +[Diablo.mak] +SCC_Project_Name = "$/MainSrc", BAAAAAAA diff --git a/src/MULTI.CPP b/src/MULTI.CPP new file mode 100644 index 0000000..0f72118 --- /dev/null +++ b/src/MULTI.CPP @@ -0,0 +1,1452 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Multi file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/MULTI.CPP 9 4/01/97 5:09p Pwyatt $ +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "storm.h" +#include "msg.h" +#include "multi.h" +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "spells.h" +#include "packplr.h" +#include "engine.h" +#include "diabloui.h" +#include "portal.h" + + +//****************************************************************** +// extern +//****************************************************************** +extern char gszHero[]; +extern BOOL gbRunGame; +extern char gszVersionNumber[]; +extern SNETVERSIONDATA gVersion; +extern int gnDifficulty; + + +void tmsg_init(); +void tmsg_free(); +void dthread_init(); +void dthread_free(); +void delta_init(); +void dthread_remove_player(int pnum); +void SetupLocalPlayer(); +void FixPlrWalkTags(int pnum); +void StartStand(int,int); +BOOL wait_delta_info(); +void plrmsg_init(); +void __cdecl sysmsg_add(const char * pszFmt,...); +void sysmsg_add_string(const char * pszMsg); +void game_2_ui_player(const PlayerStruct * p,TPUIHEROINFO heroinfo,BOOL bHasSaveFile); +void nthread_check_snet_error(const char * pszFcn); +DWORD tmsg_get(BYTE * pbMsg,DWORD dwMaxLen); +void tmsg_add(const BYTE * pbMsg,BYTE bLen); +void delta_close_portal(int pnum); +void NewPlrAnim(int pnum, BYTE *pAnim, int numFrames, int Delay, long width); + + +//****************************************************************** +// public +//****************************************************************** +BYTE gbMaxPlayers; +BYTE gbActivePlayers; +BYTE gbGameDestroyed; +BYTE gbSelectProvider; +BYTE gbDeltaSender; +BYTE gbSomebodyWonGameKludge; + +char gszGameName[128]; +char gszGamePass[128]; + + +//****************************************************************** +// private -- packets +//****************************************************************** +// network initialized +static BOOL sgbNetInited = FALSE; + +// did we send an async message in this messaging cycle? +static BOOL sgbSentThisCycle; + +// number of sync messages/game loops -- will be synchronized +// across all systems as new players asychronously join the game +static DWORD sgdwSyncMsgs; +static DWORD sgdwGameLoops; + +// buffers for player information which +// is too big to fit into one packet +// PATCH3.JMM +WORD sgwPackPlrOffsetTbl[MAX_PLRS]; +// ENDPATCH3.JMM +static PkPlayerStruct sgPackPlr[MAX_PLRS]; + +static BYTE sgbPlayerLeftGameTbl[MAX_PLRS]; +static DWORD sgdwPlayerLeftReasonTbl[MAX_PLRS]; +static BYTE sgbSendDeltaTbl[MAX_PLRS]; +static TGAMEDATA sgGameInitInfo; + +// pjw.patch2.start +static BYTE sgbGameJoiner[MAX_PLRS]; +// pjw.patch2.end + +static BYTE sgbTimeout; +static long sglTimeoutStart; + +// time to hang out in timeout state before dropping nonresponsive players +#define DROP_NOTRESPONDING_DELAY (10*1000) // milliseconds + +// time to hang out in timeout state if we're not the master +#define LEAVE_GAME_DELAY (20*1000) // milliseconds + + +//****************************************************************** +// private -- internal buffering +//****************************************************************** +#define MAX_BUF_DATA 4096 +typedef struct TBuffer { + DWORD dwNextWriteOffset; + BYTE bData[MAX_BUF_DATA]; +} TBuffer; +static TBuffer sgLoPriBuf; +static TBuffer sgHiPriBuf; + + +//****************************************************************** +//****************************************************************** +#if TRACEOUT +static DWORD sgdwTraceStartTime; +void __cdecl TraceOut(const char * pszFmt, ...) { + static FILE * f = NULL; + if (! f) f = fopen("c:\\dumphist.txt","wb"); + if (! f) return; + + va_list args; + va_start(args,pszFmt); + DWORD dwCurrTime = GetTickCount() - sgdwTraceStartTime; + fprintf(f,"%4u.%02u ",dwCurrTime / 1000, (dwCurrTime % 1000) / 10); + vfprintf(f,pszFmt,args); + fprintf( + f,"\r\n %x%c %x%c %x%c %x%c\r\n", + gdwMsgStatTbl[0] >> 16,plr[0].plractive ? 'A' : ' ', + gdwMsgStatTbl[1] >> 16,plr[1].plractive ? 'A' : ' ', + gdwMsgStatTbl[2] >> 16,plr[2].plractive ? 'A' : ' ', + gdwMsgStatTbl[3] >> 16,plr[3].plractive ? 'A' : ' ' + ); + va_end(args); + fflush(f); +} +#endif + + +//****************************************************************** +//****************************************************************** +static void buffer_init(TBuffer * pBuf) { + pBuf->dwNextWriteOffset = 0; + pBuf->bData[0] = 0; +} + + +//****************************************************************** +//****************************************************************** +static BOOL buffer_empty(TBuffer * pBuf) { + return pBuf->dwNextWriteOffset == 0; +} + + +//****************************************************************** +//****************************************************************** +static void buffer_add(TBuffer * pBuf,const BYTE * pbMsg,BYTE bLen) { + // is there enough space in the buffer for length byte + data + // plus one more byte for terminating NULL? + if (pBuf->dwNextWriteOffset + bLen + 2 > MAX_BUF_DATA) { + #ifndef NDEBUG + app_fatal("msg buffer failure"); + #endif + return; + } + + // get ptr to curr location, and setup next location + BYTE * pbData = &pBuf->bData[pBuf->dwNextWriteOffset]; + pBuf->dwNextWriteOffset += bLen + 1; + + // write length, data, terminating NULL + *pbData++ = bLen; + CopyMemory(pbData,pbMsg,bLen); + pbData += bLen; + *pbData = 0; +} + + +//****************************************************************** +//****************************************************************** +static BYTE * buffer_get(TBuffer * pBuf,BYTE * pbMsg,DWORD * pdwMaxLen) { + + // is there any data in the buffer? + if (! pBuf->dwNextWriteOffset) + return pbMsg; + + BYTE * pbData = pBuf->bData; + while (1) { + // is there enough space to copy the data from the buffer + BYTE bLen = *pbData; + if (! bLen) break; + if (bLen > *pdwMaxLen) break; + + // skip over the length byte, and copy the data + CopyMemory(pbMsg,++pbData,bLen); + pbData += bLen; + pbMsg += bLen; + *pdwMaxLen -= bLen; + } + + // fixup buffer + MoveMemory( + pBuf->bData, // start of buffer + pbData, // curr position in buffer + pBuf->dwNextWriteOffset - (pbData - pBuf->bData) + 1 + ); + + // fixup buffer write offset + pBuf->dwNextWriteOffset -= (pbData - pBuf->bData); + + return pbMsg; +} + + +//****************************************************************** +//****************************************************************** +static void build_pkt_hdr(TPkt * pkt) { + app_assert(pkt); + pkt->hdr.wCheck = 0x6970; + pkt->hdr.px = plr[myplr]._px; + pkt->hdr.py = plr[myplr]._py; + pkt->hdr.targx = plr[myplr]._ptargx; + pkt->hdr.targy = plr[myplr]._ptargy; + pkt->hdr.php = plr[myplr]._pHitPoints; + pkt->hdr.pmhp = plr[myplr]._pMaxHP; + pkt->hdr.bstr = plr[myplr]._pBaseStr; + pkt->hdr.bmag = plr[myplr]._pBaseMag; + pkt->hdr.bdex = plr[myplr]._pBaseDex; +} + + +//****************************************************************** +//****************************************************************** +void NetSendMyselfPri(const BYTE * pbMsg,BYTE bLen) { + app_assert(sgbNetInited); + if (! pbMsg) return; + if (! bLen) return; + app_assert(bLen <= gdwNormalMsgSize - sizeof(TPktHdr)); + tmsg_add(pbMsg,bLen); +} + + +//****************************************************************** +//****************************************************************** +static void NetSendLocal(const BYTE * pbMsg,BYTE bLen) { + app_assert(sgbNetInited); + app_assert(pbMsg); + app_assert(bLen); + app_assert(bLen <= gdwNormalMsgSize - sizeof(TPktHdr)); + + // build message + TPkt pkt; + build_pkt_hdr(&pkt); + pkt.hdr.wLen = sizeof(pkt.hdr) + bLen; + CopyMemory(pkt.body,pbMsg,bLen); + + // send it + TRACE_FCN("SNetSendMessage0"); + if (! SNetSendMessage(myplr,&pkt,pkt.hdr.wLen)) + nthread_check_snet_error("SNetSendMessage0"); + TRACE_FCN(NULL); + + #ifndef NDEBUG + extern DWORD gdwAsyncSendTbl[MAX_PLRS]; + gdwAsyncSendTbl[myplr]++; + #endif +} + + +//****************************************************************** +//****************************************************************** +void NetSendLoPri(const BYTE * pbMsg,BYTE bLen) { + app_assert(sgbNetInited); + if (! pbMsg) return; + if (! bLen) return; + app_assert(bLen <= gdwNormalMsgSize - sizeof(TPktHdr)); + + // message not sent out of deference to higher priority + // commands which might come later in this message cycle + buffer_add(&sgLoPriBuf,pbMsg,bLen); + NetSendLocal(pbMsg,bLen); +} + + +//****************************************************************** +//****************************************************************** +void NetSendHiPri(const BYTE * pbMsg,BYTE bLen) { + app_assert(sgbNetInited); + if (pbMsg && bLen) { + app_assert(bLen <= gdwNormalMsgSize - sizeof(TPktHdr)); + buffer_add(&sgHiPriBuf,pbMsg,bLen); + NetSendLocal(pbMsg,bLen); + } + + // if we have already sent a message this cycle, then + // we cannot send another until the next cycle. + if (sgbSentThisCycle) + return; + sgbSentThisCycle = TRUE; + + app_assert((DWORD) myplr < MAX_PLRS); + + // setup packet header + TPkt pkt; + build_pkt_hdr(&pkt); + + // fill in packet body + BYTE * pbBody = pkt.body; + DWORD dwBytesLeft = gdwNormalMsgSize - sizeof(pkt.hdr); + pbBody = buffer_get(&sgHiPriBuf,pbBody,&dwBytesLeft); + pbBody = buffer_get(&sgLoPriBuf,pbBody,&dwBytesLeft); + dwBytesLeft = sync_get(pbBody,dwBytesLeft); + DWORD dwSendBytes = gdwNormalMsgSize - dwBytesLeft; + pkt.hdr.wLen = (WORD) dwSendBytes; + + // send it + TRACE_FCN("SNetSendMessage"); + if (! SNetSendMessage(SNET_BROADCASTNONLOCALPLAYERID,&pkt,dwSendBytes)) + nthread_check_snet_error("SNetSendMessage"); + TRACE_FCN(NULL); + + #ifndef NDEBUG + extern DWORD gdwAsyncSendTbl[MAX_PLRS]; + if (myplr != 0) gdwAsyncSendTbl[0]++; + if (myplr != 1) gdwAsyncSendTbl[1]++; + if (myplr != 2) gdwAsyncSendTbl[2]++; + if (myplr != 3) gdwAsyncSendTbl[3]++; + #endif +} + + +//****************************************************************** +//****************************************************************** +void NetSendMask(DWORD dwSendMask,const BYTE * pbMsg,BYTE bLen) { + app_assert(sgbNetInited); + app_assert(pbMsg); + app_assert(bLen); + + // setup packet header + TPkt pkt; + build_pkt_hdr(&pkt); + + // fill in packet body + DWORD dwSendBytes = sizeof(pkt.hdr) + bLen; + app_assert(dwSendBytes < gdwNormalMsgSize); + pkt.hdr.wLen = (WORD) dwSendBytes; + CopyMemory(pkt.body,pbMsg,bLen); + + // send to each player listed in send mask + DWORD dwMaskFlag = 0x1; + for (DWORD dwID = 0; dwID < MAX_PLRS; dwID++,dwMaskFlag <<= 1) { + if (! (dwMaskFlag & dwSendMask)) continue; + + TRACE_FCN("SNetSendMessage"); + BOOL bSent = SNetSendMessage(dwID,&pkt,dwSendBytes); + TRACE_FCN(NULL); + if (bSent) { + #ifndef NDEBUG + extern DWORD gdwAsyncSendTbl[MAX_PLRS]; + gdwAsyncSendTbl[dwID]++; + #endif + continue; + } + + // we don't keep track of players, so we may have sent a + // message to somebody who isn't there anymore. + if (GetLastError() == SNET_ERROR_INVALID_PLAYER) continue; + + nthread_check_snet_error("SNetSendMessage"); + break; + } +} + + +//****************************************************************** +//****************************************************************** +static void NetResync() { + // resync all monster seeds based on current value of game loops + sgdwGameLoops++; + + // reinitialize monster AI seed so that + // all systems can try to resynchronize + DWORD dwSeed = _rotr(sgdwGameLoops,8); + for (int i = 0; i < MAXMONSTERS; i++) + monster[i]._mAISeed = i + dwSeed; + + +#if 0 + if (! lpDDSPrimary) return; + if (sgdwGameLoops % 10) return; + + #define ACCUM_ENTRIES 4 + static DWORD sgdwTime[ACCUM_ENTRIES]; + static DWORD sgdwCount[ACCUM_ENTRIES]; + + MoveMemory(&sgdwTime[0],&sgdwTime[1],sizeof(DWORD) * (ACCUM_ENTRIES-1)); + MoveMemory(&sgdwCount[0],&sgdwCount[1],sizeof(DWORD) * (ACCUM_ENTRIES-1)); + sgdwTime[ACCUM_ENTRIES - 1] = GetTickCount(); + sgdwCount[ACCUM_ENTRIES - 1] = sgdwGameLoops; + + DWORD dwRate = sgdwTime[ACCUM_ENTRIES - 1] - sgdwTime[0]; + if (! dwRate) return; + dwRate = (sgdwCount[ACCUM_ENTRIES - 1] - sgdwCount[0]) * 1000 / dwRate; + + HDC hDC; + char szRate[16]; + sprintf(szRate,"%d",dwRate); + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr != DD_OK) return; + SetTextColor(hDC,0x00ff0000); + TextOut(hDC,0,420,szRate,strlen(szRate)); + lpDDSPrimary->ReleaseDC(hDC); +#endif +} + + +//****************************************************************** +//****************************************************************** +static void check_DeltaSendAllLevels(int nReceiver) { + // the lowest numbered active player is + // responsible for sending the level delta + // information to the new player + for (int nSender = 0; nSender < MAX_PLRS; nSender++) { + // inactive non-player cannot send info + // pjw.patch2.start + if (! (gdwMsgStatTbl[nSender] & SNET_PSF_ACTIVE)) continue; + // pjw.patch2.end + + // player requesting info cannot send info + if (nSender == nReceiver) continue; + + // we found a player who is responsible + break; + } + + if (myplr == nSender) + sgbSendDeltaTbl[nReceiver] = TRUE; + else if (myplr == nReceiver) + gbDeltaSender = (BYTE) nSender; +} + + +//****************************************************************** +//****************************************************************** +static void check_sync(int pnum,DWORD dwSyncMsgs) { + if (dwSyncMsgs & TURN_REQUEST_DELTA_FLAG) { + // player has just joined and needs delta information + check_DeltaSendAllLevels(pnum); + } + + // remove flag bits + dwSyncMsgs &= TURN_COUNTER_MASK; + + // if the other player has sent more sync msgs than we have, + // then recompute the number of game loops which have occurred + // using his msg count to keep both systems synchronized + if (sgdwSyncMsgs < dwSyncMsgs + gdwTurnsInTransit) { + if (dwSyncMsgs >= TURN_COUNTER_MASK) + dwSyncMsgs &= TURN_COUNTER_RESET_MASK; + sgdwSyncMsgs = dwSyncMsgs + gdwTurnsInTransit; + dwSyncMsgs *= ASYNC_CYCLES_PER_SYNC; + dwSyncMsgs *= gbGameLoopsPerPacket; + sgdwGameLoops = dwSyncMsgs; + } +} + + +//****************************************************************** +//****************************************************************** +// pjw.patch2.start +void process_turn() { + for (int i = 0; i < MAX_PLRS; i++) { + if (gdwMsgStatTbl[i] & SNET_PSF_TURNAVAILABLE) { + // make sure we got a valid message + app_assert(glpMsgTbl[i]); + + // odds are we will eventually get a bad packet + if (gdwMsgLenTbl[i] != sizeof(DWORD)) continue; + + // process turn + check_sync(i,*(DWORD *)glpMsgTbl[i]); + } + } +} +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +static void remove_active_player(int i,BOOL bMsg) { + if (! plr[i].plractive) return; + + #if TRACEOUT + TraceOut("(%d) player %d --> inactive",myplr,i); + #endif + + // remove player from map + void RemovePlrFromMap(int pnum); + RemovePlrFromMap(i); + RemovePortalMissile(i); + DeactivatePortal(i); + delta_close_portal(i); + void RemovePlrMissiles(int pnum); + RemovePlrMissiles(i); + + if (bMsg) { + const char * pszMsg_s = "Player '%s' just left the game"; + switch (sgdwPlayerLeftReasonTbl[i]) { + case SNET_EXIT_NOTRESPONDING: + pszMsg_s = "Player '%s' dropped due to timeout"; + break; + case SNET_EXIT_PLAYERWON: + pszMsg_s = "Player '%s' killed Diablo and left the game!"; + gbSomebodyWonGameKludge = TRUE; + break; + } + sysmsg_add(pszMsg_s,plr[i]._pName); + } + + plr[i].plractive = 0; + plr[i]._pName[0] = 0; + gbActivePlayers--; +} + + +//****************************************************************** +//****************************************************************** +static void update_players() { + for (int i = 0; i < MAX_PLRS; i++) { + // did the player leave the game + if (! sgbPlayerLeftGameTbl[i]) continue; + + if (gbBufferMsgs == BUFFER_ON) { + #if TRACEOUT + TraceOut("(%d) buffering -- player %d left game due to 0x%x",myplr,i,sgdwPlayerLeftReasonTbl[i]); + #endif + void buffer_drop_player(int pnum,DWORD dwReason); + buffer_drop_player(i,sgdwPlayerLeftReasonTbl[i]); + } + else { + #if TRACEOUT + TraceOut("(%d) player %d left game due to 0x%x",myplr,i,sgdwPlayerLeftReasonTbl[i]); + #endif + remove_active_player(i,TRUE); + } + + sgbPlayerLeftGameTbl[i] = FALSE; + sgdwPlayerLeftReasonTbl[i] = 0; + } +} + + +//****************************************************************** +//****************************************************************** +void unbuffer_remove_player(int pnum,DWORD dwReason) { + sgbPlayerLeftGameTbl[pnum] = TRUE; + sgdwPlayerLeftReasonTbl[pnum] = dwReason; + update_players(); +} + + +//****************************************************************** +//****************************************************************** +void NetStartTimeout() { + sgbTimeout = TRUE; + sglTimeoutStart = (long) GetTickCount(); +} + + +//****************************************************************** +//****************************************************************** +// pjw.patch2.start +static void drop_players() { + // kill other players + for (int i = 0; i < MAX_PLRS; i++) { + if (gdwMsgStatTbl[i] & SNET_PSF_RESPONDING) continue; + if (! (gdwMsgStatTbl[i] & SNET_PSF_ACTIVE)) continue; + + #if TRACEOUT + TraceOut("(%d) dropping player %d state 0x%x",myplr,i,gdwMsgStatTbl[i]); + #endif + + // snet drop player will perform a callback to + // our event function to indicate that the player "left" + TRACE_FCN("SNetDropPlayer"); + SNetDropPlayer(i,SNET_EXIT_NOTRESPONDING); + TRACE_FCN(NULL); + } +} +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +// pjw.patch2.start +static void drop_inactive_players() { + // if we're not in a timeout state, don't drop players + if (! sgbTimeout) return; + + // debug mode + #if CHEATS + extern BOOL gbNoDropInactive; + if (gbNoDropInactive) return; + #endif + + // check delay since timeout started + long lCurrTime = (long) GetTickCount(); + lCurrTime -= sglTimeoutStart; + + // if we've been hanging out forever, just exit game + if (lCurrTime > LEAVE_GAME_DELAY) { + gbRunGame = FALSE; + return; + } + + // time to kill other players? + if (lCurrTime < DROP_NOTRESPONDING_DELAY) return; + +// if there are only two players in the game, then the high +// player bails out, and the low player keeps playing. If there +// are three or more players in the game, then the group that has +// the most players keeps playing and the other player(s) bail. + int nLowestActive = -1; + int nLowestPlayer = -1; + BYTE bGroupPlayers = 0; + BYTE bNonGroupPlayers = 0; + for (int i = 0; i < MAX_PLRS; i++) { + if (! (gdwMsgStatTbl[i] & SNET_PSF_ACTIVE)) continue; + + if (nLowestPlayer == -1) nLowestPlayer = i; + + // get player state + if (gdwMsgStatTbl[i] & SNET_PSF_RESPONDING) { + // one more player in our group + bGroupPlayers++; + if (nLowestActive == -1) nLowestActive = i; + } + else { + // one more player not in our group + bNonGroupPlayers++; + } + } + app_assert(bGroupPlayers); + app_assert(nLowestActive != -1); + app_assert(nLowestPlayer != -1); + + + #if 0 + TraceOut( + "(%d) grp:%d ngrp:%d lowp:%d lowa:%d", + myplr, + bGroupPlayers, + bNonGroupPlayers, + nLowestPlayer, + nLowestActive + ); + #endif + + if (bGroupPlayers < bNonGroupPlayers) { + // we're not part of the big group, give up + gbGameDestroyed = TRUE; + } + else if (bGroupPlayers == bNonGroupPlayers) { + if (nLowestPlayer != nLowestActive) + gbGameDestroyed = TRUE; + else if (nLowestActive == myplr) + drop_players(); + } + else if (nLowestActive == myplr) { + drop_players(); + } +} +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +BOOL NetEndSendCycle() { + app_assert(sgbNetInited); + + if (gbGameDestroyed) { + gbRunGame = FALSE; + return FALSE; + } + + // send delta information to other players + for (int i = 0; i < MAX_PLRS; i++) { + // are we supposed to send somebody delta information? + if (! sgbSendDeltaTbl[i]) continue; + sgbSendDeltaTbl[i] = FALSE; + DeltaSendAllLevels(i); + } + + // fill up the outgoing message queue + // send the number of sync messages we think have been + // sent to other players (and increment by 1 each msg) + BOOL bSendAsync; + sgdwSyncMsgs = nthread_fill_sync_queue(sgdwSyncMsgs,1); + if (! nthread_msg_check(&bSendAsync)) { + drop_inactive_players(); + return FALSE; + } + + // we got some data -- reset timeout mode + sgbTimeout = FALSE; + + if (! bSendAsync) { + // it's not time to send an async message yet + } + else if (! sgbSentThisCycle) { + // we haven't sent any async messages this cycle so + // send a blank message and reset for next cycle + NetSendHiPri(NULL,0); + sgbSentThisCycle = FALSE; + } + else { + // we already sent an async message this cycle + // if there is any high priority stuff + // still in the queue, send the next cycle's + // message immediately + sgbSentThisCycle = FALSE; + if (! buffer_empty(&sgHiPriBuf)) + NetSendHiPri(NULL,0); + } + + // update the monster random number seeds + NetResync(); + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static void process_msg_body(DWORD dwID,const BYTE * pbCmd,DWORD dwBytes) { + while (dwBytes) { + DWORD dwCmdLen = ParseCmd(dwID,(const TCmd *) pbCmd); + // patch3.jmm + // zero is an error condition: + // skip the rest of the packet + if( dwCmdLen == 0 ) { + return; + } + // endpatch3.jmm + + pbCmd += dwCmdLen; + dwBytes -= dwCmdLen; + } +} + + +//****************************************************************** +//****************************************************************** +static void handle_local_msgs() { + DWORD dwLen; + BYTE msg[MAX_MSG_SIZE]; + while (0 != (dwLen = tmsg_get(msg,sizeof(msg)))) + process_msg_body(myplr,msg,dwLen); +} + + +//****************************************************************** +//****************************************************************** +// patch1.jmm +extern DWORD dwRecCount; +// endpatch1.jmm + +void NetReceivePackets() { + DWORD dwID; + LPVOID lpMsg; + DWORD dwMsgSize; + + // make sure all players are dropped ASAP + update_players(); + handle_local_msgs(); + + app_assert(sgbNetInited); + TRACE_FCN("SNetReceiveMessage"); + while (SNetReceiveMessage(&dwID,&lpMsg,&dwMsgSize)) { + TRACE_FCN(NULL); + + // patch1.jmm + dwRecCount++; + // endpatch1.jmm + + // do not dispatch any messages until + // we've dropped players who left the game + update_players(); + + // odds are we will eventually get a bad packet so ignore bad ones + const TPkt * pkt = (const TPkt *) lpMsg; + if (dwMsgSize < sizeof(TPktHdr)) continue; + if (dwID >= MAX_PLRS) continue; + if (pkt->hdr.wCheck != 0x6970) continue; + if (pkt->hdr.wLen != dwMsgSize) continue; + + plr[dwID]._pownerx = pkt->hdr.px; + plr[dwID]._pownery = pkt->hdr.py; + + #ifndef NDEBUG + extern DWORD gdwAsyncRecvTbl[MAX_PLRS]; + gdwAsyncRecvTbl[dwID]++; + #endif + + // the header contains the last known location of the + // player at the time the message was sent. Try to get + // the player to walk to his correct location. Any other + // commands in the message will be executed later and so + // can overwrite the results of this MakePlrPath. + if (dwID != (DWORD) myplr) { + app_assert(gbBufferMsgs != BUFFER_PROCESS); + plr[dwID]._pHitPoints = pkt->hdr.php; + plr[dwID]._pMaxHP = pkt->hdr.pmhp; + plr[dwID]._pBaseStr = pkt->hdr.bstr; + plr[dwID]._pBaseMag = pkt->hdr.bmag; + plr[dwID]._pBaseDex = pkt->hdr.bdex; + if (gbBufferMsgs == BUFFER_ON) { + // do nothing + } + else if (! plr[dwID].plractive) { + // do nothing + } + else if (plr[dwID]._pHitPoints == 0) { + // do nothing + } + else if ((currlevel == plr[dwID].plrlevel) && (!plr[dwID]._pLvlChanging)) { + int dx = abs(plr[dwID]._px - pkt->hdr.px); + int dy = abs(plr[dwID]._py - pkt->hdr.py); + // Is player in "ok delta" dist of where he should be? + if (((dx > 3) || (dy > 3)) && (!dPlayer[pkt->hdr.px][pkt->hdr.py])) { + // Warp player to location + FixPlrWalkTags(dwID); + plr[dwID]._poldx = plr[dwID]._px; + plr[dwID]._poldy = plr[dwID]._py; + FixPlrWalkTags(dwID); + plr[dwID]._px = pkt->hdr.px; + plr[dwID]._py = pkt->hdr.py; + plr[dwID]._pfutx = pkt->hdr.px; + plr[dwID]._pfuty = pkt->hdr.py; + dPlayer[plr[dwID]._px][plr[dwID]._py] = 1 + (char)dwID; + } + dx = abs(plr[dwID]._pfutx - plr[dwID]._px); + dy = abs(plr[dwID]._pfuty - plr[dwID]._py); + if ((dx > 1) || (dy > 1)) { + plr[dwID]._pfutx = plr[dwID]._px; + plr[dwID]._pfuty = plr[dwID]._py; + } + MakePlrPath(dwID, pkt->hdr.targx, pkt->hdr.targy, TRUE); + // do not override destAction + } + else { + plr[dwID]._px = pkt->hdr.px; + plr[dwID]._py = pkt->hdr.py; + plr[dwID]._pfutx = pkt->hdr.px; + plr[dwID]._pfuty = pkt->hdr.py; + plr[dwID]._ptargx = pkt->hdr.targx; + plr[dwID]._ptargy = pkt->hdr.targy; + // do not override destAction + } + } + process_msg_body(dwID,pkt->body,dwMsgSize - sizeof(TPktHdr)); + } + TRACE_FCN(NULL); + + if (GetLastError() != SNET_ERROR_NO_MESSAGES_WAITING) + nthread_check_snet_error("SNetReceiveMsg"); +} + + +//****************************************************************** +// NOTE: this routine is called from multiple threads +// don't do anything that would be thread unsafe +//****************************************************************** +void SendPlayerInfoChunk(int pnum,BYTE bCmd,const BYTE * pbSrc,DWORD dwLen) { + app_assert(pnum != myplr); + + // write info piece by piece + app_assert(pbSrc); + app_assert(dwLen <= 0x0ffff); + DWORD dwOffset = 0; + while (dwLen) { + // setup packet header + TPkt pkt; + pkt.hdr.wCheck = 0x6970; + pkt.hdr.px = 0; + pkt.hdr.py = 0; + pkt.hdr.targx = 0; + pkt.hdr.targy = 0; + pkt.hdr.php = 0; + pkt.hdr.pmhp = 0; + pkt.hdr.bstr = 0; + pkt.hdr.bmag = 0; + pkt.hdr.bdex = 0; + + // setup cmd header + TCmdPlrInfoHdr * p = (TCmdPlrInfoHdr *) &pkt.body[0]; + p->bCmd = bCmd; + p->wOffset = (WORD) dwOffset; + + // calculate how much data we can send + DWORD dwBody = gdwLargestMsgSize - sizeof(pkt.hdr) - sizeof(TCmdPlrInfoHdr); + dwBody = min(dwLen,dwBody); + app_assert(dwBody <= 0x0ffff); + p->wBytes = (WORD) dwBody; + + // copy cmd data + CopyMemory(&pkt.body[sizeof TCmdPlrInfoHdr],pbSrc,p->wBytes); + + // send message to target + DWORD dwSendBytes = sizeof(pkt.hdr); + dwSendBytes += sizeof(TCmdPlrInfoHdr); + dwSendBytes += p->wBytes; + pkt.hdr.wLen = (WORD) dwSendBytes; + + TRACE_FCN("SnetSendMessage"); + if (! SNetSendMessage(pnum,&pkt,dwSendBytes)) { + TRACE_FCN(NULL); + nthread_check_snet_error("SNetSendMessage2"); + break; + } + TRACE_FCN(NULL); + + #ifndef NDEBUG + extern DWORD gdwAsyncSendTbl[MAX_PLRS]; + if ((DWORD) pnum < MAX_PLRS) { + gdwAsyncSendTbl[pnum]++; + } + else { + if (myplr != 0) gdwAsyncSendTbl[0]++; + if (myplr != 1) gdwAsyncSendTbl[1]++; + if (myplr != 2) gdwAsyncSendTbl[2]++; + if (myplr != 3) gdwAsyncSendTbl[3]++; + } + #endif + + + // next data section + pbSrc += p->wBytes; + dwLen -= p->wBytes; + dwOffset += p->wBytes; + } +} + + +//****************************************************************** +//****************************************************************** +// pjw.patch2.start -- for patch, changed SendPlayerInfoChunk to +// dthread_SendPlayerInfoChunk to more closely attempt to match the +// available bandwidth. A player with a slow modem joining +// a game with 3 players would have to broadcast ~3k of playerdata, +// clogging the modem and preventing turns from getting out. +void dthread_SendPlayerInfoChunk(int pnum,BYTE bCmd,const BYTE * pbSrc,DWORD dwLen); +static void SendLocalPlayerInfo(int pnum,BYTE bCmd) { + // get local player information and send it to the specified net addr + PkPlayerStruct pack; + PackPlayer(&pack,myplr); + dthread_SendPlayerInfoChunk(pnum,bCmd,(const BYTE *) &pack,sizeof(pack)); +} +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +static int InitLevelType(int l) { + if (l == 0) return(0); + if ((l >= 1) && (l <= 4)) return(1); + if ((l >= 5) && (l <= 8)) return(2); + if ((l >= 9) && (l <= 12)) return(3); + //return(4); JKE 7/29 + if ((l >=13) && (l <= 16)) return(4); // Original level types JKE + if ((l >= CRYPTSTART) && (l <= CRYPTEND)) return(1); // change this to crypt type later JKE 7/29 + if ((l >= HIVESTART) && (l <= HIVEEND)) return(3); // use this for hives JKE + return(1); +} + + +//****************************************************************** +//****************************************************************** +static void SetupLocalCoords() { + // set the current level to start at the town + if (! leveldebug || gbMaxPlayers > 1) { + currlevel = 0; + leveltype = 0; + setlevel = FALSE; + } + + // put character near house on town level + int x = STARTX; + int y = STARTY; + + #if CHEATS + if (cheatflag || davedebug) { + //x = 25; // Near church + //y = 31; + x = 49; // Near maus + y = 23; + } + #endif + + // adjust character position for character number + // so everyone doesn't start on the same location + extern int plrxoff[9]; + extern int plryoff[9]; + x += plrxoff[myplr]; + y += plryoff[myplr]; + + plr[myplr]._px = x; + plr[myplr]._py = y; + plr[myplr]._pfutx = x; + plr[myplr]._pfuty = y; + plr[myplr]._ptargx = x; + plr[myplr]._ptargy = y; + plr[myplr].plrlevel = currlevel; + plr[myplr]._pLvlChanging = TRUE; + plr[myplr].pLvlLoad = 0; + plr[myplr]._pmode = PM_NEWLVL; + plr[myplr].destAction = PCMD_NOTHING; +} + + +//****************************************************************** +//****************************************************************** +static BOOL handle_upgrade(BOOL * pfExitProgram) { + DWORD dwStatus; + SNetPerformUpgrade(&dwStatus); + switch (dwStatus) { + case SNET_UPGRADE_FAILED: + app_warning("Network upgrade failed"); + break; + + case SNET_UPGRADE_NOT_NEEDED: + // continue game + return TRUE; + + case SNET_UPGRADE_SUCCEEDED: + // continue game + return TRUE; + + case SNET_UPGRADING_TERMINATE: + *pfExitProgram = TRUE; + break; + } + + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +static void CALLBACK net_callback(SNETEVENTPTR pEvt) { + DWORD dwReason; + TGAMEDATA * pGameData; + +// NOTE: this function must be thread-safe since +// it can be called from either the main thread, or during +// the progress screen, called from nthread_*() + switch (pEvt->eventid) { + case SNET_EVENT_INITDATA: + app_assert(pEvt->data); + app_assert(pEvt->databytes >= sizeof(DWORD)); + pGameData = (TGAMEDATA *) pEvt->data; + sgGameInitInfo.dwSeed = pGameData->dwSeed; + sgGameInitInfo.bDiff = pGameData->bDiff; + + // if we get a callback containing init data + // then we cannot be the one who started the game + // pjw.patch2.start + sgbGameJoiner[pEvt->playerid] = TRUE; + //pjw.patch2.end + break; + + case SNET_EVENT_PLAYERLEAVE: + app_assert(pEvt->playerid >= 0 && pEvt->playerid < MAX_PLRS); + sgbPlayerLeftGameTbl[pEvt->playerid] = TRUE; + sgbGameJoiner[pEvt->playerid] = FALSE; + dwReason = 0; + if (pEvt->data && pEvt->databytes >= sizeof(DWORD)) + dwReason = * (DWORD *) pEvt->data; + sgdwPlayerLeftReasonTbl[pEvt->playerid] = dwReason; + + if (dwReason == SNET_EXIT_PLAYERWON) + gbSomebodyWonGameKludge = TRUE; + + // protected by critical section -- OK + sgbSendDeltaTbl[pEvt->playerid] = 0; + dthread_remove_player(pEvt->playerid); + + // was this the guy who was supposed to send us delta info? + if (gbDeltaSender == pEvt->playerid) + gbDeltaSender = MAX_PLRS; + + #if TRACEOUT + TraceOut("(%d) callback: player %d left game due to 0x%x",myplr,pEvt->playerid,dwReason); + #endif + break; + + case SNET_EVENT_SERVERMESSAGE: + app_assert(pEvt->data); + sysmsg_add_string((const char *) pEvt->data); + break; + } +} + + +//****************************************************************** +//****************************************************************** +static void RegisterEventHandler(BOOL bRegister) { + static const DWORD sdwEventTbl[] = { + SNET_EVENT_PLAYERLEAVE, + SNET_EVENT_INITDATA, + SNET_EVENT_SERVERMESSAGE, + }; + + BOOL (__stdcall * fnReg)(DWORD,SNETEVENTPROC) = + bRegister ? SNetRegisterEventHandler : SNetUnregisterEventHandler; + + for (int i = 0; i < sizeof(sdwEventTbl) / sizeof(sdwEventTbl[0]); i++) { + if (! fnReg(sdwEventTbl[i],net_callback) && bRegister) + app_fatal("SNetRegisterEventHandler:\n%s",strGetLastError()); + } +} + + +//****************************************************************** +//****************************************************************** +void NetClose() { + if (sgbNetInited) { + sgbNetInited = FALSE; + nthread_free(); + dthread_free(); + tmsg_free(); + RegisterEventHandler(FALSE); + TRACE_FCN("SNetLeaveGame"); + SNetLeaveGame(SNET_EXIT_AUTO_SHUTDOWN); + TRACE_FCN(NULL); + + #if TRACEOUT + TraceOut("(%d) NetClose",myplr); + #endif + + // give storm enough time to send leave pkt + if (gbMaxPlayers > 1) Sleep(2000); + } +} + + +//****************************************************************** +//****************************************************************** +// pjw.patch2.start +BOOL NetInit(BOOL bSinglePlayer,BOOL * pfExitProgram) { +top_of_routine: + + app_assert(pfExitProgram); + *pfExitProgram = FALSE; + + // get player description + char szPlayerDescript[UI_DESC_MAXLENGTH]; + ZeroMemory(szPlayerDescript,sizeof szPlayerDescript); + if (! bSinglePlayer) { + TUIHEROINFO heroinfo; + myplr = 0; + SetupLocalPlayer(); + game_2_ui_player(&plr[0],&heroinfo,gbValidSaveFile); + if (! UiCreatePlayerDescription(&heroinfo,PROGRAMID,szPlayerDescript)) + return FALSE; + } + + // initialize random seed for game + SetRndSeed(0); + sgGameInitInfo.dwSeed = (DWORD) time(NULL); + sgGameInitInfo.bDiff = (BYTE) gnDifficulty; + + // BUILD A PROGRAM DATA RECORD + SNETPROGRAMDATA progdata; + ZeroMemory(&progdata,sizeof(progdata)); + progdata.size = sizeof(progdata); + #if IS_VERSION(RETAIL) + //progdata.programname = TEXT("Diablo Retail"); + progdata.programname = TEXT("Hellfire Retail"); + #elif IS_VERSION(BETA) + progdata.programname = TEXT("Diablo"); + #elif IS_VERSION(SHAREWARE) + progdata.programname = TEXT("Diablo Shareware"); + #else + #error VERSION NOT DEFINED + #endif + progdata.programdescription = gszVersionNumber; + progdata.programid = PROGRAMID; + progdata.versionid = VERSIONID; + progdata.maxplayers = MAX_PLRS; + progdata.initdata = &sgGameInitInfo.dwSeed; + progdata.initdatabytes = sizeof(sgGameInitInfo); + progdata.optcategorybits = 0x0f; + + // BUILD A PLAYER DATA RECORD + SNETPLAYERDATA plrdata; + ZeroMemory(&plrdata,sizeof(plrdata)); + plrdata.size = sizeof(plrdata); + plrdata.playername = gszHero; + plrdata.playerdescription = szPlayerDescript; + + // BUILD AN INTERFACE DATA RECORD + SNETUIDATA uidata; + ZeroMemory(&uidata,sizeof(SNETUIDATA)); + uidata.size = sizeof(SNETUIDATA); + uidata.parentwindow = SDrawGetFrameWindow(); + uidata.artcallback = UiArtCallback; + uidata.createcallback = UiCreateGameCallback; + uidata.drawdesccallback = UiDrawDescCallback; + uidata.messageboxcallback = UiMessageBoxCallback; + uidata.soundcallback = UiSoundCallback; + uidata.authcallback = UiAuthCallback; + uidata.getdatacallback = UiGetDataCallback; + uidata.categorycallback = UiCategoryCallback; + + // pjw.patch2.start + ZeroMemory(sgbGameJoiner,sizeof(sgbGameJoiner)); + // pjw.patch2.end + gbGameDestroyed = FALSE; + ZeroMemory(sgbPlayerLeftGameTbl,sizeof(sgbPlayerLeftGameTbl)); + ZeroMemory(sgdwPlayerLeftReasonTbl,sizeof(sgdwPlayerLeftReasonTbl)); + ZeroMemory(sgbSendDeltaTbl,sizeof(sgbSendDeltaTbl)); + // pjw.patch1.start + ZeroMemory(plr,sizeof(PlayerStruct) * MAX_PLRS); + // pjw.patch1.end + ZeroMemory(sgwPackPlrOffsetTbl,sizeof(sgwPackPlrOffsetTbl)); + SNetSetBasePlayer(0); + + if (bSinglePlayer) { + if (! SNetInitializeProvider(NULL,&progdata,&plrdata,&uidata,&gVersion)) + app_fatal("SNetInitializeProvider:\n%s",strGetLastError()); + + DWORD dwID = 0; + if (! SNetCreateGame ( + "local", // gamename + "local", // password + "local", // gamedescription + 0, // game category bits + &sgGameInitInfo, // initdata + sizeof(sgGameInitInfo), // initdatabytes + 1, // maxplayers + "local", // playername + "local", // playerdescription + &dwID // playerid + )) app_fatal("SNetCreateGame1:\n%s",strGetLastError()); + app_assert(dwID == 0); + myplr = 0; + gbMaxPlayers = 1; + } + else { + + if (gbSelectProvider) { + BOOL bTryAgain = TRUE; + while (1) { + DWORD dwProviderID; + if (UiSelectProvider(NULL,&progdata,&plrdata,&uidata,&gVersion,&dwProviderID)) + break; + if (! bTryAgain) + return FALSE; + if (GetLastError() != SNET_ERROR_REQUIRES_UPGRADE) + return FALSE; + if (! handle_upgrade(pfExitProgram)) + return FALSE; + bTryAgain = FALSE; + } + } + + RegisterEventHandler(TRUE); + + DWORD dwID; + if (! UiSelectGame(SNET_SF_ALLOWCREATE,&progdata,&plrdata,&uidata,&gVersion,&dwID)) { + app_assert(! *pfExitProgram); + return FALSE; + } + // this happened once, so handle it... + if (dwID >= MAX_PLRS) return FALSE; + + myplr = dwID; + gbMaxPlayers = MAX_PLRS; + } + + #if TRACEOUT + sgdwTraceStartTime = GetTickCount(); + TraceOut("(%d) new game started",myplr); + #endif + + // do various network initializations + sgbNetInited = TRUE; + sgbTimeout = FALSE; + delta_init(); + plrmsg_init(); + buffer_init(&sgHiPriBuf); + buffer_init(&sgLoPriBuf); + sgbSentThisCycle = FALSE; + sync_init(); + // pjw.patch2.start + nthread_init(sgbGameJoiner[myplr]); + // pjw.patch2.end + dthread_init(); + tmsg_init(); + sgdwGameLoops = 0; + sgdwSyncMsgs = 0; + gbDeltaSender = (BYTE) myplr; + gbSomebodyWonGameKludge = FALSE; + + // request everyone's player info + SetupLocalPlayer(); + +// pjw.patch2.start -- added this code so that the first thing +// out of the modem is the turn, not tons of playerdata. If we send +// only playerdata, the modem queue gets filled up, and we don't respond +// fast enough to other players - sometimes causing a timeout + nthread_fill_sync_queue(0,0); +// pjw.patch2.end + + // broadcast our player info to everyone + SetupLocalCoords(); + SendLocalPlayerInfo(SNET_BROADCASTNONLOCALPLAYERID,CMD_SEND_PLRINFO); + + // i'm always active on my system + plr[myplr].plractive = 1; + gbActivePlayers = 1; + + // if we started the game, then we can proceed immediately. + // if we joined the game, we must wait until we receive + // all the level delta information before proceeding + // pjw.patch2.start + if (sgbGameJoiner[myplr] && !wait_delta_info()) { + NetClose(); + gbSelectProvider = FALSE; + goto top_of_routine; // sorry :( + } + // pjw.patch2.end + + // initialize map random number seeds + gnDifficulty = sgGameInitInfo.bDiff; + SetRndSeed(sgGameInitInfo.dwSeed); + for (int i = 0; i < NUMLEVELS; i++) { + glSeedTbl[i] = GetRndSeed(); + gnLevelTypeTbl[i] = InitLevelType(i); + } + + DWORD dwTemp; + if (! SNetGetGameInfo(SNET_INFO_GAMENAME,gszGameName,SNET_MAXNAMELENGTH,&dwTemp)) + nthread_check_snet_error("SNetGetGameInfo1"); + if (! SNetGetGameInfo(SNET_INFO_GAMEPASSWORD,gszGamePass,SNET_MAXNAMELENGTH,&dwTemp)) + nthread_check_snet_error("SNetGetGameInfo2"); + + return TRUE; +} +// pjw.patch2.end + + +//****************************************************************** +//****************************************************************** +void recv_plrinfo(int pnum,const TCmdPlrInfoHdr * p,BOOL bAck) { + // local player is always properly set up + // and doesn't need to be unpacked + if (myplr == pnum) + return; + + app_assert((DWORD)pnum < MAX_PLRS); + + // check for out of order packet + if (sgwPackPlrOffsetTbl[pnum] != p->wOffset) { + sgwPackPlrOffsetTbl[pnum] = 0; + if (p->wOffset != 0) return; + } + + // if this packet came to us unrequested + // and we haven't responded before, + // respond by sending back our plrinfo + if (! bAck && ! sgwPackPlrOffsetTbl[pnum]) + SendLocalPlayerInfo(pnum,CMD_ACK_PLRINFO); + + // copy the message information into a global structure + // until we have received the entire packed player + CopyMemory( + ((BYTE *)&sgPackPlr[pnum]) + p->wOffset, + ((BYTE *)p) + sizeof(TCmdPlrInfoHdr), + p->wBytes + ); + sgwPackPlrOffsetTbl[pnum] += p->wBytes; + + // did we get the entire pack structure yet? + if (sgwPackPlrOffsetTbl[pnum] != sizeof(PkPlayerStruct)) + return; + sgwPackPlrOffsetTbl[pnum] = 0; + + remove_active_player(pnum,FALSE); + plr[pnum]._pGFXLoad = 0; + UnPackPlayer(&sgPackPlr[pnum],pnum, TRUE); + + // if this packet was an acknowledgement to our request + // for character information, then this character must + // already be in the game, so activate him + // Otherwise, this packet was being broadcast by a newbie + // joining the game. Wait until he sends a joinlevel command + // before activating his character + if (bAck) { + plr[pnum].plractive = 1; + gbActivePlayers++; + + // pjw.patch2.start + sysmsg_add( + sgbGameJoiner[pnum] ? + "Player '%s' (level %d) just joined the game" : + "Player '%s' (level %d) is already in the game", + plr[pnum]._pName,plr[pnum]._pLevel + ); + // pjw.patch2.end + + LoadPlrGFX(pnum,PGL_STAND); + SyncInitPlr(pnum); + if (plr[pnum].plrlevel == currlevel) { + if ((plr[pnum]._pHitPoints >> HP_SHIFT) > 0) { + StartStand(pnum,0); + } else { + plr[pnum]._pgfxnum = PGFX_NGUY; + LoadPlrGFX(pnum, PGL_DEAD); + plr[pnum]._pmode = PM_DEATH; + NewPlrAnim(pnum, plr[pnum]._pDAnim[DIR_D], plr[pnum]._pDFrames, 1, plr[pnum]._pDWidth); + plr[pnum]._pAnimFrame = plr[pnum]._pAnimLen - 1; + plr[pnum]._pVar8 = plr[pnum]._pAnimLen << 1; + dFlags[plr[pnum]._px][plr[pnum]._py] |= BFLAG_DEADPLR; + } + } + + #if TRACEOUT + TraceOut("(%d) making %d active -- recv_plrinfo",myplr,pnum); + #endif + } + else { + #if TRACEOUT + TraceOut("(%d) received all %d plrinfo",myplr,pnum); + #endif + } +} diff --git a/src/MULTI.H b/src/MULTI.H new file mode 100644 index 0000000..2126851 --- /dev/null +++ b/src/MULTI.H @@ -0,0 +1,88 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/MULTI.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + + +//****************************************************************** +// constants +//****************************************************************** +// for every X async messages, we send X/8 sync messages +#define ASYNC_CYCLES_PER_SYNC 4 + +// Near house +#define STARTX 75 +#define STARTY 68 + +#define TURN_REQUEST_DELTA_FLAG 0x80000000 +#define TURN_COUNTER_MASK 0x7fffffff +#define TURN_COUNTER_RESET_MASK 0x0000ffff + + +//****************************************************************** +// variables +//****************************************************************** +extern BYTE gbMaxPlayers; +extern BYTE gbActivePlayers; +extern BYTE gbDropInactive; +extern BYTE gbGameDestroyed; +extern BYTE gbGameLoopsPerPacket; +extern DWORD gdwTurnsInTransit; +extern BYTE gbDeltaSender; +extern char gszGameName[128]; +extern char gszGamePass[128]; + + +enum { + // msg buffering off when program running in normal game mode + BUFFER_OFF = 0, + + // msg buffering on when program waiting for level delta info, + // because program cannot handle any other messages besides deltas + BUFFER_ON, + + // processing msgs which were stored in the message buffer + BUFFER_PROCESS +}; +extern BYTE gbBufferMsgs; + + +// results from receiving the last synchronous turn +extern DWORD gdwMsgLenTbl[MAX_PLRS]; +extern LPVOID glpMsgTbl[MAX_PLRS]; +extern DWORD gdwMsgStatTbl[MAX_PLRS]; + + +//****************************************************************** +// functions +//****************************************************************** +// multi.cpp +BOOL NetInit(BOOL bSinglePlayer,BOOL * pfExitProgram); +void NetClose(); +void NetReceivePackets(); +BOOL NetEndSendCycle(); +void NetDropInactive(); +void process_turn(); + +void NetSendLoPri(const BYTE * pbMsg,BYTE bLen); +void NetSendHiPri(const BYTE * pbMsg,BYTE bLen); +void NetSendMyselfPri(const BYTE * pbMsg,BYTE bLen); +void NetSendMask(DWORD dwSendMask,const BYTE * pbMsg,BYTE bLen); + +// sync.cpp +void sync_init(); +DWORD sync_get(BYTE * pbBuf,DWORD dwMaxLen); +DWORD sync_update(int pnum,const BYTE * pbBuf); + +// nthread.cpp +void nthread_init(BOOL bRequestDelta); +void nthread_free(); +BOOL nthread_run_gameloop(BOOL bReloop); +void nthread_perform_keepalive(BOOL bStart); +DWORD nthread_fill_sync_queue(DWORD dwCounter,DWORD dwIncrement); +BOOL nthread_msg_check(BOOL * pfSendAsync); diff --git a/src/NTHREAD.CPP b/src/NTHREAD.CPP new file mode 100644 index 0000000..1402699 --- /dev/null +++ b/src/NTHREAD.CPP @@ -0,0 +1,706 @@ +//****************************************************************** +// nthread.cpp +// contains network code which runs in either main thread +// or auxiliary "progress" thread +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include +#include "storm.h" +#include "msg.h" +#include "multi.h" +#include "gendung.h" +#include "sound.h" +#include "storm.h" +#include "items.h" +#include "player.h" + + +//****************************************************************** +// debugging +//****************************************************************** +#define PRINT_STATUS 1 // 0 in final +#define STATUS_LASTERR 0 // 0 in final +#define DUMP_STATUS 0 // 0 in final + +#ifdef NDEBUG +#undef PRINT_STATUS +#undef STATUS_LASTERR +#undef DUMP_STATUS +#define PRINT_STATUS 0 +#define STATUS_LASTERR 0 +#define DUMP_STATUS 0 +#endif + + +//****************************************************************** +// public +//****************************************************************** +BYTE gbGameLoopsPerPacket; +DWORD gdwTurnsInTransit; +DWORD gdwNormalMsgSize; // MIN_MSG_SIZE..MAX_MSG_SIZE +DWORD gdwLargestMsgSize; // MIN_MSG_SIZE..MAX_MSG_SIZE +DWORD gdwDeltaBytesSec; + + +// results from receiving the last synchronous turn +DWORD gdwMsgLenTbl[MAX_PLRS]; +DWORD gdwMsgStatTbl[MAX_PLRS]; +LPVOID glpMsgTbl[MAX_PLRS]; + +#ifndef NDEBUG +DWORD gdwAsyncRecvTbl[MAX_PLRS]; +DWORD gdwAsyncSendTbl[MAX_PLRS]; +#endif + + +//****************************************************************** +// private -- packets +//****************************************************************** +static DWORD sgdwRequestDeltaFlag; + +static BYTE sgbRunThread; +static BYTE sgbThreadIsRunning; +static CCritSect sgCrit; +static HANDLE sghThread = INVALID_HANDLE_VALUE; +static unsigned sgThreadID; + +// are we waiting for a packet? +static BYTE sgbGotPacketOK; + +// countdown timer to the next time we need to send an +// async packet and value to initialize countdown timer +static BYTE sgbPacketCountdown; + +// countdown timer for synchronous message +static BYTE sgbSyncCountdown; + +// timer which marches forward to match the real time clock +// used to determine when to run game loops +static long sglGameClock = 0; + +// if game clock and the real clock differ by more than CATCH_UP_DELTA +// then reset the game clock to be equal to the real clock. This ensures +// that the game will attempt to maintain a normal frame rate, but if it +// falls too far outside normal bounds, it will not struggle indefinitely. +#define CATCH_UP_DELTA 500 // milliseconds + + +#if PRINT_STATUS +static BYTE sgbPrintStatus; +static DWORD sgdwPrintTime; +#if STATUS_LASTERR +static DWORD sgdwPrintTbl[MAX_PLRS]; +#endif +#endif + +#if DUMP_STATUS +static BYTE sgbDumpStatus; +static BYTE sgbDumpStatusOK; +static BYTE sbDumpInit = TRUE; +#endif + +#if ALLOW_TRACE_FCN +static BYTE sgbTraceFcn; +static const char * sgpszLastTrace; +#endif + + +//****************************************************************** +//****************************************************************** +#if ALLOW_TRACE_FCN +void trace_fcn(const char * pszFcn) { + // don't write stuff if we're not the active application + if (! bActive) return; + if (! sgbTraceFcn) return; + if (! lpDDSPrimary) return; + if (sgpszLastTrace == pszFcn) return; + sgpszLastTrace = pszFcn; + + // ooh -- how cheesy... + if (! pszFcn) pszFcn = " "; + + HDC hDC; + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr != DD_OK) return; + TextOut(hDC,5,370,pszFcn,strlen(pszFcn)); + lpDDSPrimary->ReleaseDC(hDC); +} +#endif + + +//****************************************************************** +//****************************************************************** +void nthread_check_snet_error(const char * pszFcn) { + app_assert(pszFcn); + DWORD dwErr = GetLastError(); + // we don't keep track of players, so we may have sent a + // message to somebody who isn't there anymore. + if (dwErr == SNET_ERROR_INVALID_PLAYER) + NULL; + else if (dwErr == SNET_ERROR_GAME_TERMINATED) + gbGameDestroyed = TRUE; + else if (dwErr == SNET_ERROR_NOT_IN_GAME) + gbGameDestroyed = TRUE; + else + app_fatal("%s:\n%s",pszFcn,strGetLastError()); +} + + +//****************************************************************** +//****************************************************************** +#ifdef _DEBUG +BOOL is_pat_debug_cmd(WPARAM wKey) { + // only a debug key if the control key is down + if (! (GetKeyState(VK_CONTROL) & 0x8000)) + return FALSE; + + switch (wKey) { + + case 0x03: // ctrl - break; + // debugger + if (!fullscreen) { + void myDebugBreak(); + myDebugBreak(); + force_redraw = FULLDRAW; + } + break; + + case 0x13: // ctrl - S + // stall the network by sleeping + Sleep(50); + break; + + #if PRINT_STATUS && STATUS_LASTERR + case 0x12: // ctrl - R + ZeroMemory(sgdwPrintTbl,sizeof(sgdwPrintTbl)); + break; + #endif + + #if PRINT_STATUS + case 0x10: // ctrl - P + // toggle print status + sgbPrintStatus = !sgbPrintStatus; + sgdwPrintTime = GetTickCount(); + break; + #endif + + #if DUMP_STATUS + case 0x4: // ctrl - D + sgbDumpStatus = !sgbDumpStatus; + sgbDumpStatusOK = TRUE; + sbDumpInit = TRUE; + + #if PRINT_STATUS + sgbPrintStatus = sgbDumpStatus; + #endif + break; + #endif + + #if ALLOW_TRACE_FCN + case 0xa: // ctrl - J + sgbTraceFcn = !sgbTraceFcn; + sgpszLastTrace = NULL; + break; + #endif + + default: + return FALSE; + } + + return TRUE; +} +#endif + + +//****************************************************************** +//****************************************************************** +DWORD nthread_fill_sync_queue(DWORD dwCounter,DWORD dwIncrement) { + // MAKE SURE THERE ARE ALWAYS SEVERAL SYNC TURNS IN TRANSIT + DWORD turns; + + TRACE_FCN("SNetGetTurnsInTransit"); + if (! SNetGetTurnsInTransit(&turns)) { + TRACE_FCN(NULL); + nthread_check_snet_error("SNetGetTurnsInTransit"); + return 0; + } + TRACE_FCN(NULL); + + app_assert(gdwTurnsInTransit); + while (turns++ < gdwTurnsInTransit) { + + // counter = low 31 bits + // hi bit = request delta flag or zero + // reset flag after first use + DWORD dwTemp = dwCounter & TURN_COUNTER_MASK; + dwTemp |= sgdwRequestDeltaFlag; + sgdwRequestDeltaFlag = 0; + + // send turn + TRACE_FCN("SNetSendTurn"); + if (! SNetSendTurn(&dwTemp,sizeof dwTemp)) { + TRACE_FCN(NULL); + nthread_check_snet_error("SNetSendTurn"); + return 0; + } + TRACE_FCN(NULL); + + // increment counter and reset wraparound + dwCounter += dwIncrement; + if (dwCounter >= TURN_COUNTER_MASK) + dwCounter &= TURN_COUNTER_RESET_MASK; + } + + return dwCounter; +} + + +//****************************************************************** +//****************************************************************** +#if DUMP_STATUS +void __cdecl dump_string(const char * pszFmt,...) { + app_assert(pszFmt); + + // open dumpfile + FILE * f = fopen("c:\\netdump.txt",sbDumpInit ? "wb" : "ab"); + if (! f) return; + sbDumpInit = FALSE; + + va_list args; + va_start(args,pszFmt); + vfprintf(f,pszFmt,args); + va_end(args); + + fclose(f); +} +#endif + + +//****************************************************************** +//****************************************************************** +#if DUMP_STATUS +static void DumpStatus() { + // don't write stuff if we're not the active application + if (! bActive) return; + + for (int i = 0; i < MAX_PLRS; i++) { + if (! (gdwMsgStatTbl[i] & SNET_PSF_RESPONDING)) + break; + } + + if (i >= MAX_PLRS) { + if (sgbDumpStatusOK) return; + sgbDumpStatusOK = TRUE; + } + else { + sgbDumpStatusOK = FALSE; + } + + // create status string + char szBuf[64]; + char * pszBuf = szBuf; + for (i = 0; i < MAX_PLRS; i++) { + if (i == myplr) *pszBuf++ = '>'; + *pszBuf++ = (char) (gdwMsgStatTbl[i] >> 16) + '0'; + if (plr[i].plractive) *pszBuf++ = '*'; + *pszBuf++ = ' '; + } + pszBuf--; + *pszBuf++ = '\r'; + *pszBuf++ = '\n'; + *pszBuf = 0; + dump_string(szBuf); +} +#endif + + +//****************************************************************** +//****************************************************************** +#if PRINT_STATUS +static void print_status() { + + // don't write stuff if we're not the active application + if (! bActive) return; + + // create status string + char szBuf[128]; + char * pszBuf = szBuf; + for (int i = 0; i < MAX_PLRS; i++) { + *pszBuf++ = (i == myplr) ? '<' : ' '; + #if STATUS_LASTERR + *pszBuf++ = (char) (sgdwPrintTbl[i] >> 16) + '0'; + #else + *pszBuf++ = (char) (gdwMsgStatTbl[i] >> 16) + '0'; + #endif + *pszBuf++ = plr[i].plractive ? 'A' : 'I'; + *pszBuf++ = (i == myplr) ? '>' : ' '; + } + *pszBuf++ = ' '; + *pszBuf = 0; + + if (! lpDDSPrimary) return; + HDC hDC; + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr != DD_OK) return; + COLORREF oldTextColor = SetTextColor(hDC,RGB(0xff,0xff,0)); + COLORREF oldBkColor = SetBkColor(hDC,RGB(0,0,0)); + int oldBkMode = SetBkMode(hDC,OPAQUE); + TextOut(hDC,5,385,szBuf,strlen(szBuf)); + + #ifndef NDEBUG + sprintf(szBuf,"%02x %02x %02x %02x", + gdwAsyncRecvTbl[0] & 0xff, + gdwAsyncRecvTbl[1] & 0xff, + gdwAsyncRecvTbl[2] & 0xff, + gdwAsyncRecvTbl[3] & 0xff + ); + TextOut(hDC,5,400,szBuf,strlen(szBuf)); + sprintf(szBuf,"%02x %02x %02x %02x", + gdwAsyncSendTbl[0] & 0xff, + gdwAsyncSendTbl[1] & 0xff, + gdwAsyncSendTbl[2] & 0xff, + gdwAsyncSendTbl[3] & 0xff + ); + TextOut(hDC,5,415,szBuf,strlen(szBuf)); + #endif + + static DWORD foo = 0; + sprintf(szBuf,"%d",foo++); + TextOut(hDC,5,430,szBuf,strlen(szBuf)); +/* + DWORD dwCurrTime = GetTickCount(); + if (dwCurrTime - sgdwPrintTime >= 1000) { + sgdwPrintTime = dwCurrTime; + + DWORD dwTurn,dwBytes; + SNetGetPerformanceData(SNET_PERFID_TURN,&dwTurn,NULL,NULL,NULL,NULL); + sprintf(szBuf,"turn: 0x%08x ",dwTurn); + TextOut(hDC,5,400,szBuf,strlen(szBuf)); + + static DWORD sgdwLastBytes; + SNetGetPerformanceData(SNET_PERFID_BYTESSENTONWIRE,&dwBytes,NULL,NULL,NULL,NULL); + sprintf(szBuf,"bytes: %8d ",dwBytes - sgdwLastBytes); + sgdwLastBytes = dwBytes; + TextOut(hDC,5,415,szBuf,strlen(szBuf)); + + DWORD dwUser,dwTotal; + static DWORD sdwLastUser; + static DWORD sdwLastTotal; + SNetGetPerformanceData(SNET_PERFID_USERBYTESSENT,&dwUser,NULL,NULL,NULL,NULL); + SNetGetPerformanceData(SNET_PERFID_TOTALBYTESSENT,&dwTotal,NULL,NULL,NULL,NULL); + dwBytes = dwTotal - sdwLastTotal; + if (! dwBytes) dwBytes = 1; + dwBytes = ((dwUser - sdwLastUser) * 100) / dwBytes; + sdwLastUser = dwUser; + sdwLastTotal = dwTotal; + sprintf(szBuf,"user: %3d%% ",dwBytes); + TextOut(hDC,5,430,szBuf,strlen(szBuf)); + } +*/ + + SetTextColor(hDC,oldTextColor); + SetBkColor(hDC,oldBkColor); + SetBkMode(hDC,oldBkMode); + lpDDSPrimary->ReleaseDC(hDC); +} +#endif + + +//****************************************************************** +//****************************************************************** +BOOL nthread_msg_check(BOOL * pfSendAsync) { + app_assert(pfSendAsync); + *pfSendAsync = FALSE; + + #if PRINT_STATUS + if (sgbPrintStatus) print_status(); + #endif + + // count down until time to send async packet + app_assert(sgbPacketCountdown); + if (--sgbPacketCountdown) { + // advance the game clock to the next + // time we will need to run a game loop + sglGameClock += 1000 / GAME_FRAMES_PER_SECOND; + return TRUE; + } + + // reset async countdown timer + sgbPacketCountdown = gbGameLoopsPerPacket; + + // is it time to receive sync message? + app_assert(sgbSyncCountdown); + if (! --sgbSyncCountdown) { + TRACE_FCN("SNetReceiveTurns"); + if (! SNetReceiveTurns(0,MAX_PLRS,glpMsgTbl,gdwMsgLenTbl,gdwMsgStatTbl)) { + TRACE_FCN(NULL); + DWORD dwErr = GetLastError(); + if (dwErr != SNET_ERROR_NO_MESSAGES_WAITING) + nthread_check_snet_error("SNetReceiveTurns"); + + // we didn't successfully receive a turn, so go run some + // user stuff, and come back here to try again next time + sgbPacketCountdown = sgbSyncCountdown = 1; + + #if PRINT_STATUS && STATUS_LASTERR + // copy results of last bad status info to private table + CopyMemory(sgdwPrintTbl,gdwMsgStatTbl,sizeof(sgdwPrintTbl)); + #endif + + #if DUMP_STATUS + DumpStatus(); + #endif + + sgbGotPacketOK = 0; + return FALSE; + } + else if (! sgbGotPacketOK) { + TRACE_FCN(NULL); + // we were waiting for the packet. Since + // there should be a bunch of messages in the + // queue, we should never have to wait. + sgbGotPacketOK = 1; + sglGameClock = GetTickCount(); + + #if DUMP_STATUS + DumpStatus(); + #endif + } + else { + TRACE_FCN(NULL); + } + + // reset sync countdown timer + sgbSyncCountdown = ASYNC_CYCLES_PER_SYNC; + + // process synchronous turn + process_turn(); + } + + // it's time to send an async message + *pfSendAsync = TRUE; + + // advance the game clock to the next + // time we will need to run a game loop + sglGameClock += 1000 / GAME_FRAMES_PER_SECOND; + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static unsigned __stdcall net_thread_proc(void *) { + long lDelta; + + while (sgbRunThread) { + sgCrit.Enter(); + + // if nthread_free() was called, it may have released the + // critical section so that this thread could run. However, + // we're just supposed to get out of here... + if (! sgbRunThread) { + sgCrit.Leave(); + return 0; + } + + // fill queue with minimum number of synchronous + // messages before we attempt to read any + BOOL bSendAsync; + nthread_fill_sync_queue(0,0); + if (nthread_msg_check(&bSendAsync)) { + // sleep until it is approximately time + // to send the next synchronous turn + lDelta = sglGameClock - (long) GetTickCount(); + } + else { + // we are waiting for a message from one of the other players + // since it is not here yet, sleep for a longish while so + // that we don't do any busy waiting + lDelta = 1000 / GAME_FRAMES_PER_SECOND; + } + sgCrit.Leave(); + if (lDelta > 0) Sleep(lDelta); + + // pjw.patch2.start + #if CHEATS + static DWORD sdwSkips = 0; + sdwSkips++; + if (lpDDSPrimary) + { + HDC hDC; + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr == DD_OK) { + char szBuf[16]; + wsprintf(szBuf,"n:%u",sdwSkips); + TextOut(hDC,5,440,szBuf,strlen(szBuf)); + lpDDSPrimary->ReleaseDC(hDC); + } + } + #endif + // pjw.patch2.end + } + + return 0; +} + + +//****************************************************************** +//****************************************************************** +void nthread_set_delta_request() { + sgdwRequestDeltaFlag = TURN_REQUEST_DELTA_FLAG; +} + + +//****************************************************************** +//****************************************************************** +void nthread_init(BOOL bRequestDelta) { + // start game clock and countdown timers + sglGameClock = GetTickCount(); + sgbPacketCountdown = 1; + sgbSyncCountdown = 1; + sgbGotPacketOK = 1; + if (bRequestDelta) nthread_set_delta_request(); + else sgdwRequestDeltaFlag = 0; + + // calculate the number of packets we should send + // per game loop based on the provider latency + SNETCAPS caps; + caps.size = sizeof caps; + if (! SNetGetProviderCaps(&caps)) + app_fatal("SNetGetProviderCaps:\n%s",strGetLastError()); + + // find out how many messages we should put into the queue + if (caps.defaultturnsintransit) + gdwTurnsInTransit = caps.defaultturnsintransit; + else + gdwTurnsInTransit = 1; + + // calculate the number of game loops to run per packet + // based on the speed of the network connection + if (caps.defaultturnssec > GAME_FRAMES_PER_SECOND || ! caps.defaultturnssec) + gbGameLoopsPerPacket = 1; + else + gbGameLoopsPerPacket = (BYTE) (GAME_FRAMES_PER_SECOND / caps.defaultturnssec); + + // size of largest packet which can be sent over network + gdwLargestMsgSize = min(caps.maxmessagesize,MAX_MSG_SIZE); + app_assert(gdwLargestMsgSize >= MIN_MSG_SIZE); + + // calculate how big our messages can be based on the available + // bandwidth and the number of messages we'll be sending per turn + // (bytes/sec) * (frames/pkt) / (frames/sec) = (bytes/pkt) + gdwNormalMsgSize = caps.bytessec * gbGameLoopsPerPacket / GAME_FRAMES_PER_SECOND; + + // use 1/4 of the channel for sending delta info to other players + gdwDeltaBytesSec = caps.bytessec * 1 / 4; + + // use 3/4 of channel for player messages + gdwNormalMsgSize *= 3; + gdwNormalMsgSize /= 4; + + // Divide by the number of players since we have to send a msg to each + // NOTE: we could subtract out the local player, since we send no + // info over the wire to local system, but leave this entry in + // to allow for "overhead" + app_assert(caps.maxplayers); + if (caps.maxplayers > MAX_PLRS) caps.maxplayers = MAX_PLRS; + gdwNormalMsgSize /= caps.maxplayers; + + // if our packet is too small, send fewer messages per turn + while (gdwNormalMsgSize < MIN_MSG_SIZE) { + gdwNormalMsgSize *= 2; + gbGameLoopsPerPacket *= 2; + } + + // bounds check maximum value + if (gdwNormalMsgSize > gdwLargestMsgSize) + gdwNormalMsgSize = gdwLargestMsgSize; + + // create synchronization object for thread + if (gbMaxPlayers > 1) { + sgbThreadIsRunning = FALSE; + sgCrit.Enter(); + + // create loader thread + sgbRunThread = TRUE; + app_assert(sghThread == INVALID_HANDLE_VALUE); + sghThread = (HANDLE) _beginthreadex( + NULL, // no security info + 0, // stack size + net_thread_proc, // start address + NULL, // argument list + 0, // initial state + &sgThreadID // sgThreadID + ); + if (sghThread == INVALID_HANDLE_VALUE) + app_fatal(TEXT("nthread2:\n%s"),strGetLastError()); + + // make sure this thread runs at higher priority than + // SFile, and at the same priority as SNet + SetThreadPriority(sghThread,THREAD_PRIORITY_HIGHEST); + } +} + + +//****************************************************************** +//****************************************************************** +void nthread_free() { + // kill off the thread + sgbRunThread = FALSE; + + // set parameters to invalid values + gdwTurnsInTransit = 0; + gdwNormalMsgSize = 0; + gdwLargestMsgSize = 0; + + // wait until it finishes + if (sghThread != INVALID_HANDLE_VALUE) { + if (sgThreadID != GetCurrentThreadId()) { + if (! sgbThreadIsRunning) sgCrit.Leave(); + if (WAIT_FAILED == WaitForSingleObject(sghThread,INFINITE)) + app_fatal(TEXT("nthread3:\n(%s)"),strGetLastError()); + CloseHandle(sghThread); + sghThread = INVALID_HANDLE_VALUE; + } + } +} + + +//****************************************************************** +//****************************************************************** +void nthread_perform_keepalive(BOOL bStart) { + if (sghThread == INVALID_HANDLE_VALUE) + return; + app_assert(sgbThreadIsRunning != bStart); + + if (bStart) { + // allow thread to run + sgCrit.Leave(); + } + else { + // prevent thread from running + sgCrit.Enter(); + } + + sgbThreadIsRunning = bStart; +} + + +//****************************************************************** +//****************************************************************** +BOOL nthread_run_gameloop(BOOL bReloop) { + long lRealClock = (long) GetTickCount(); + long lDelta = lRealClock - sglGameClock; + + // if it has been too long since we last ran a game loop, + // then pretend we have caught up and are running normally + if (gbMaxPlayers == 1 && lDelta > CATCH_UP_DELTA) { + sglGameClock = lRealClock; + lDelta = 0; + } + + return (lDelta >= 0); +} diff --git a/src/Newstm/STORM.H b/src/Newstm/STORM.H new file mode 100644 index 0000000..42aa011 --- /dev/null +++ b/src/Newstm/STORM.H @@ -0,0 +1,3332 @@ +#ifndef _STORM_H_ +#define _STORM_H_ + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import on +#endif + + +//#########################################################################// +//#########################################################################// +// // +// // +// STANDARD PROGRAMMING INTERFACE // +// // +// // +//#########################################################################// +//#########################################################################// + + +#define DECLARE_STRICT_HANDLE(name) typedef struct name##__ { int unused; } *name +#define DECLARE_DERIVED_HANDLE(name,base) typedef struct name##__ : public base##__ { int unused; } *name + + +/**************************************************************************** +* +* Error codes +* (Error text is defined in Stormerr.mc) +* +***/ + +#define STORMFAC 0x510 +#define STORMERROR(code) (0x80000000 | (STORMFAC << 16) | ((code) & 0xFFFF)) + +#define STORM_ERROR_ASSERTION STORMERROR(0) +#define STORM_ERROR_BAD_ARGUMENT STORMERROR(101) +#define STORM_ERROR_GAME_ALREADY_STARTED STORMERROR(102) +#define STORM_ERROR_GAME_FULL STORMERROR(103) +#define STORM_ERROR_GAME_NOT_FOUND STORMERROR(104) +#define STORM_ERROR_GAME_TERMINATED STORMERROR(105) +#define STORM_ERROR_INVALID_PLAYER STORMERROR(106) +#define STORM_ERROR_NO_MESSAGES_WAITING STORMERROR(107) +#define STORM_ERROR_NOT_ARCHIVE STORMERROR(108) +#define STORM_ERROR_NOT_ENOUGH_ARGUMENTS STORMERROR(109) +#define STORM_ERROR_NOT_IMPLEMENTED STORMERROR(110) +#define STORM_ERROR_NOT_IN_ARCHIVE STORMERROR(111) +#define STORM_ERROR_NOT_IN_GAME STORMERROR(112) +#define STORM_ERROR_NOT_INITIALIZED STORMERROR(113) +#define STORM_ERROR_NOT_PLAYING STORMERROR(114) +#define STORM_ERROR_NOT_REGISTERED STORMERROR(115) +#define STORM_ERROR_REQUIRES_CODEC STORMERROR(116) +#define STORM_ERROR_REQUIRES_DDRAW STORMERROR(117) +#define STORM_ERROR_REQUIRES_DSOUND STORMERROR(118) +#define STORM_ERROR_REQUIRES_UPGRADE STORMERROR(119) +#define STORM_ERROR_STILL_ACTIVE STORMERROR(120) +#define STORM_ERROR_VERSION_MISMATCH STORMERROR(121) +#define STORM_ERROR_MEMORY_ALREADY_FREED STORMERROR(122) +#define STORM_ERROR_MEMORY_CORRUPT STORMERROR(123) +#define STORM_ERROR_MEMORY_INVALID_BLOCK STORMERROR(124) +#define STORM_ERROR_MEMORY_MANAGER_INACTIVE STORMERROR(125) +#define STORM_ERROR_MEMORY_NEVER_RELEASED STORMERROR(126) +#define STORM_ERROR_HANDLE_NEVER_RELEASED STORMERROR(127) +#define STORM_ERROR_ACCESS_OUT_OF_BOUNDS STORMERROR(128) +#define STORM_ERROR_MEMORY_NULL_POINTER STORMERROR(129) + + +/**************************************************************************** +* +* BitBlt functions +* +***/ + +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SBltDestroy (); +#endif +extern "C" BOOL APIENTRY SBltGetSCode (DWORD rop3, + LPSTR buffer, + DWORD buffersize, + BOOL optimize = 1); +extern "C" BOOL APIENTRY SBltROP3 (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Clipped (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Tiled (LPBYTE dest, + LPRECT destrect, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3); + + +/**************************************************************************** +* +* Bitmap functions +* +***/ + +#define SBMP_IMAGETYPE_AUTO 0 +#define SBMP_IMAGETYPE_BMP 1 +#define SBMP_IMAGETYPE_PCX 2 + +typedef LPVOID (APIENTRY *SBMPALLOCPROC)(DWORD); + +extern "C" BOOL APIENTRY SBmpAllocLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE *returnedbuffer, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL, + int requestedbitdepth = 0, + SBMPALLOCPROC allocproc = NULL); +extern "C" BOOL APIENTRY SBmpDecodeImage (DWORD imagetype, + LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpSaveImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height, + int bitdepth); + + +/**************************************************************************** +* +* Command line parsing functions +* +***/ + +#define SCMD_ARG_FLAGGED (0 << 24) +#define SCMD_ARG_OPTIONAL (1 << 24) +#define SCMD_ARG_REQUIRED (2 << 24) +#define SCMD_ARG_MASK (SCMD_ARG_FLAGGED | SCMD_ARG_OPTIONAL | SCMD_ARG_REQUIRED) + +#define SCMD_BOOL_SET 0 +#define SCMD_BOOL_CLEAR 1 +#define SCMD_BOOL_MASK (SCMD_BOOL_CLEAR | SCMD_BOOL_SET) + +#define SCMD_CASESENSITIVE (0x01 << 8) + +#define SCMD_NUM_UNSIGNED 0 +#define SCMD_NUM_SIGNED 1 +#define SCMD_NUM_MASK (SCMD_NUM_UNSIGNED | SCMD_NUM_SIGNED) + +#define SCMD_TYPE_BOOL (0 << 16) +#define SCMD_TYPE_NUMERIC (1 << 16) +#define SCMD_TYPE_STRING (2 << 16) +#define SCMD_TYPE_MASK (SCMD_TYPE_BOOL | SCMD_TYPE_NUMERIC | SCMD_TYPE_STRING) + +#define SCMD_ERROR_BAD_ARGUMENT STORM_ERROR_BAD_ARGUMENT +#define SCMD_ERROR_NOT_ENOUGH_ARGUMENTS STORM_ERROR_NOT_ENOUGH_ARGUMENTS +#define SCMD_ERROR_OPEN_FAILED ERROR_OPEN_FAILED + +typedef struct _CMDERROR { + DWORD errorcode; + LPCTSTR itemstr; + LPCTSTR errorstr; +} CMDERROR, *CMDERRORPTR; + +typedef struct _CMDPARAMS { + DWORD flags; + DWORD id; + LPCTSTR name; + LPVOID variable; + DWORD setvalue; + DWORD setmask; + union { + BOOL boolvalue; + LONG signedvalue; + DWORD unsignedvalue; + LPCTSTR stringvalue; + }; +} CMDPARAMS, *CMDPARAMSPTR; + +typedef BOOL (CALLBACK *SCMDCALLBACK)(CMDPARAMSPTR,LPCTSTR); +typedef void (CALLBACK *SCMDERRORCALLBACK)(CMDERRORPTR); +typedef BOOL (CALLBACK *SCMDEXTRACALLBACK)(LPCTSTR); + +typedef struct _ARGLIST { + DWORD flags; + DWORD id; + LPCTSTR name; + SCMDCALLBACK callback; +} ARGLIST, *ARGLISTPTR; + +extern "C" BOOL APIENTRY SCmdCheckId (DWORD id); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SCmdDestroy (); +#endif +extern "C" BOOL APIENTRY SCmdGetBool (DWORD id); +extern "C" DWORD APIENTRY SCmdGetNum (DWORD id); +extern "C" BOOL APIENTRY SCmdGetString (DWORD id, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SCmdProcess (LPCTSTR cmdline, + BOOL skipprogname, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback); +extern "C" BOOL APIENTRY SCmdRegisterArgList (const ARGLIST *listptr, + DWORD numargs); +extern "C" BOOL APIENTRY SCmdRegisterArgument (DWORD flags, + DWORD id, + LPCTSTR name, + LPVOID variableptr = NULL, + DWORD variablebytes = 0, + DWORD setvalue = TRUE, + DWORD setmask = 0xFFFFFFFF, + SCMDCALLBACK callback = NULL); + +#define SCmdProcessCommandLine(ext,err) SCmdProcess(GetCommandLine(),TRUE,(ext),(err)) + +#define ARGBOOL(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),TRUE,0xFFFFFFFF,callback) +#define ARGFLAG(flags,name,var,valuecallback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),value,value,callback) +#define ARGNUMBER(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_NUMERIC | (flags),0xFFFFFFFF,name,var,sizeof(var),0,0,callback) +#define ARGSTRING(flags,name,buffer,chars,callback) SCmdRegisterArgument(SCMD_TYPE_STRING | (flags),0xFFFFFFFF,name,buffer,(chars),0,0,callback) + + +/**************************************************************************** +* +* S-Code functions +* +***/ + +#define SCODE_CF_AUTOALIGNDWORD 0x00040000 +#define SCODE_CF_USESALTADJUSTS 0x04000000 + +DECLARE_STRICT_HANDLE(HSCODESTREAM); + +typedef struct _SCODEEXECUTEDATA { + DWORD size; + DWORD flags; + int xiterations; + int yiterations; + int adjustdest; + int adjustsource; + LPVOID dest; + LPVOID source; + LPVOID table; + DWORD a; + DWORD b; + DWORD c; + int adjustdestalt; + int adjustsourcealt; + DWORD reserved[2]; +} SCODEEXECUTEDATA, *SCODEEXECUTEDATAPTR; + +extern "C" BOOL APIENTRY SCodeCompile (LPCSTR prologstring, + LPCSTR loopstring, + LPCSTR *firsterror, + DWORD maxiterations, + DWORD flags, + HSCODESTREAM *handle); +extern "C" BOOL APIENTRY SCodeDelete (HSCODESTREAM handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SCodeDestroy (); +#endif +extern "C" BOOL APIENTRY SCodeExecute (HSCODESTREAM handle, + SCODEEXECUTEDATAPTR executedata); +extern "C" BOOL APIENTRY SCodeGetJumpTable (HSCODESTREAM handle, + LPBYTE **jumptableptr, + LPDWORD *prologpatchlocation, + LPDWORD *looppatchlocation, + LPDWORD *epilogpatchlocation); +extern "C" BOOL APIENTRY SCodeGetPseudocode (LPCSTR scodestring, + LPSTR buffer, + DWORD buffersize); + + +/**************************************************************************** +* +* Compression functions +* +***/ + +#define SCOMP_HINT_NONE 0 +#define SCOMP_HINT_BINARY 1 +#define SCOMP_HINT_TEXT 2 +#define SCOMP_HINT_EXECUTABLE 3 +#define SCOMP_HINT_ADPCM4 4 +#define SCOMP_HINT_ADPCM6 5 +#define SCOMP_HINTS 6 + +#define SCOMP_OPT_DEFAULT 0 +#define SCOMP_OPT_COMPRESSION 1 +#define SCOMP_OPT_SPEED 2 +#define SCOMP_OPT_QUALITY 3 + +#define SCOMP_TYPE_HUFFMAN 0x01 +#define SCOMP_TYPE_PKWARE 0x08 +#define SCOMP_TYPE_LOSSY_ADPCM_MONO 0x10 +#define SCOMP_TYPE_LOSSY_ADPCM_STEREO 0x20 + +extern "C" BOOL APIENTRY SCompCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD compressiontypes, + DWORD hint, + DWORD optimization); +extern "C" BOOL APIENTRY SCompDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize); + + +/**************************************************************************** +* +* Dialog box functions +* +***/ + +#define SDLG_ADJUST_NONE 0 +#define SDLG_ADJUST_VERTICAL 1 +#define SDLG_ADJUST_CONTROLPOS 2 + +#define SDLG_DBF_TILE 0x00000001 +#define SDLG_DBF_VCENTER 0x00000002 + +#define SDLG_STYLE_ANY 0xFFFFFFFF +#define SDLG_STYLE_ANYPUSHBUTTON 0x00010001 + +#define SDLG_USAGE_BACKGROUND 0x00000001 +#define SDLG_USAGE_NORMAL_UNFOCUSED 0x00000010 +#define SDLG_USAGE_NORMAL_FOCUSED 0x00000020 +#define SDLG_USAGE_NORMAL (SDLG_USAGE_NORMAL_UNFOCUSED | SDLG_USAGE_NORMAL_FOCUSED) +#define SDLG_USAGE_SELECTED_UNFOCUSED 0x00000040 +#define SDLG_USAGE_SELECTED_FOCUSED 0x00000080 +#define SDLG_USAGE_SELECTED (SDLG_USAGE_SELECTED_UNFOCUSED | SDLG_USAGE_SELECTED_FOCUSED) +#define SDLG_USAGE_NORMAL_GRAYED 0x00000100 +#define SDLG_USAGE_SELECTED_GRAYED 0x00000400 +#define SDLG_USAGE_GRAYED (SDLG_USAGE_NORMAL_GRAYED | SDLG_USAGE_SELECTED_GRAYED) +#define SDLG_USAGE_CURSORMASK 0x00001000 +#define SDLG_USAGE_CURSORIMAGE 0x00002000 + +extern "C" HDC APIENTRY SDlgBeginPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgBltToWindowE (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgBltToWindowI (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgCheckTimers (); +extern "C" HWND APIENTRY SDlgCreateDialogIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" HWND APIENTRY SDlgCreateDialogParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDefDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SDlgDestroy (); +#endif +extern "C" int APIENTRY SDlgDialogBoxIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" int APIENTRY SDlgDialogBoxParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDrawBitmap (HWND window, + DWORD usage, + HRGN region, + int offsetx = 0, + int offsety = 0, + LPRECT boundingoffset = NULL, + DWORD flags = 0); +extern "C" BOOL APIENTRY SDlgEndDialog (HWND window, + int result); +extern "C" BOOL APIENTRY SDlgEndPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgKillTimer (HWND window, + UINT event); +extern "C" BOOL APIENTRY SDlgSetBaseFont (int pointsize, + int weight, + DWORD flags, + DWORD family, + LPCTSTR face); +extern "C" BOOL APIENTRY SDlgSetBitmapE (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetBitmapI (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetControlBitmaps (HWND parentwindow, + LPINT controllist, + LPDWORD usagelist, + LPBYTE bitmapbits, + LPSIZE bitmapsize, + DWORD adjusttype, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetCursor (HWND window, + HCURSOR cursor, + DWORD id, + HCURSOR *oldcursor); +extern "C" BOOL APIENTRY SDlgSetSystemCursor (LPBYTE maskbitmap, + LPBYTE imagebitmap, + LPSIZE size, + DWORD id = 32512); +extern "C" BOOL APIENTRY SDlgSetTimer (HWND window, + UINT event, + UINT elapse, + TIMERPROC timerfunc); +extern "C" BOOL APIENTRY SDlgUpdateCursor (); + +#define SDlgCreateDialog(ins,tpl,wnd,prc) SDlgCreateDialogParam(ins,tpl,wnd,prc,0) +#define SDlgCreateDialogIndirect(ins,tpl,wnd,prc) SDlgCreateDialogIndirectParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBox(ins,tpl,wnd,prc) SDlgDialogBoxParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBoxIndirect(ins,tpl,wnd,prc) SDlgDialogBoxIndirectParam(ins,tpl,wnd,prc,0) + +#ifdef SDLG_USE_INCLUSIVE_RECTS +#define SDlgBltToWindow SDlgBltToWindowI +#define SDlgSetBitmap SDlgSetBitmapI +#else +#define SDlgBltToWindow SDlgBltToWindowE +#define SDlgSetBitmap SDlgSetBitmapE +#endif + +/**************************************************************************** +* +* DirectDraw functions +* +***/ + +#define SDRAW_SERVICE_BASIC 1 +#define SDRAW_SERVICE_PAGEFLIP 2 +#define SDRAW_SERVICE_DOUBLEBUFFER 3 +#define SDRAW_SERVICE_MAX 3 + +#define SDRAW_SURFACE_FRONT 0 +#define SDRAW_SURFACE_BACK 1 +#define SDRAW_SURFACE_SYSTEM 2 +#define SDRAW_SURFACE_TEMPORARY 3 + +#ifndef MAC +extern "C" BOOL APIENTRY SDrawAutoInitialize (HINSTANCE instance, + LPCTSTR classname, + LPCTSTR title, + WNDPROC wndproc = NULL, + int servicelevel = SDRAW_SERVICE_BASIC, + int width = 640, + int height = 480, + int bitdepth = 8); +extern "C" BOOL APIENTRY SDrawCaptureScreen (LPCTSTR filename = NULL); +#endif +extern "C" BOOL APIENTRY SDrawClearSurface (int surfacenumber); +extern "C" BOOL APIENTRY SDrawDestroy (); +extern "C" BOOL APIENTRY SDrawFlipPage (); +extern "C" HWND APIENTRY SDrawGetFrameWindow (HWND *window = NULL); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawGetObjects (LPDIRECTDRAW *directdraw, + LPDIRECTDRAWSURFACE *frontbuffer, + LPDIRECTDRAWSURFACE *backbuffer, + LPDIRECTDRAWSURFACE *systembuffer, + LPDIRECTDRAWSURFACE *temporarybuffer, + LPDIRECTDRAWPALETTE *palette, + HPALETTE *gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawGetScreenSize (int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SDrawGetServiceLevel (int *servicelevel = NULL); +extern "C" BOOL APIENTRY SDrawLockSurface (int surfacenumber, + LPCRECT rect, + LPBYTE *ptr, + int *pitch = NULL, + DWORD flags = 0); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawManualInitialize (HWND framewindow, + LPDIRECTDRAW directdraw, + LPDIRECTDRAWSURFACE frontbuffer, + LPDIRECTDRAWSURFACE backbuffer, + LPDIRECTDRAWSURFACE systembuffer, + LPDIRECTDRAWSURFACE temporarybuffer, + LPDIRECTDRAWPALETTE palette, + HPALETTE gdipalette); +#endif +extern "C" int APIENTRY SDrawMessageBox (LPCTSTR text, + LPCTSTR title, + UINT flags); +extern "C" BOOL APIENTRY SDrawPostClose (); +extern "C" BOOL APIENTRY SDrawRealizePalette (); +#ifndef MAC +extern "C" BOOL APIENTRY SDrawSelectGdiSurface (BOOL select, BOOL copy); +#endif +extern "C" BOOL APIENTRY SDrawUnlockSurface (int surfacenumber, + LPBYTE ptr, + DWORD numrects = 0, + LPCRECT rectarray = NULL); +extern "C" BOOL APIENTRY SDrawUpdatePalette (DWORD firstentry, + DWORD numentries, + LPPALETTEENTRY entries, + BOOL reservedentries = FALSE); +extern "C" BOOL APIENTRY SDrawUpdateScreen (LPCRECT rect); +#ifdef MAC +extern "C" BOOL APIENTRY SDrawVidDriverInitialize (HWND framewindow, + int servicelevel); +#endif + + +/**************************************************************************** +* +* Error handling functions +* +***/ + +#define SERR_LINECODE_FUNCTION -1 +#define SERR_LINECODE_OBJECT -2 +#define SERR_LINECODE_HANDLE -3 +#define SERR_LINECODE_FILE -4 + +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SErrDestroy (); +#endif +extern "C" BOOL APIENTRY SErrDisplayError (DWORD errorcode, + LPCTSTR filename, + int linenumber, + LPCTSTR description, + BOOL recoverable, + UINT exitcode = 1); +extern "C" BOOL APIENTRY SErrGetErrorStr (DWORD errorcode, + LPTSTR buffer, + DWORD bufferchars); +#define GetLastError SErrGetLastError +extern "C" DWORD APIENTRY SErrGetLastError (); +extern "C" BOOL APIENTRY SErrRegisterMessageSource (WORD facility, + HMODULE module, + LPVOID reserved = NULL); +extern "C" void APIENTRY SErrReportResourceLeak (LPCTSTR handlename); +extern "C" void APIENTRY SErrSetLastError (DWORD errorcode); +extern "C" void APIENTRY SErrSuppressErrors (BOOL suppress); + +#define SErrGetLastErrorStr(buf,len) SErrGetErrorStr(SErrGetLastError(),buf,len) +#define FATALRESULT(str) SErrDisplayError(SErrGetLastError(),str,SERR_LINECODE_FUNCTION,NULL,FALSE) +#define REPORTRESOURCELEAK(handle) SErrReportResourceLeak(#handle) + +#ifdef _DEBUG +#define ASSERT(a) if (!(a)) \ + SErrDisplayError(STORM_ERROR_ASSERTION, \ + __FILE__, \ + __LINE__, \ + #a, \ + FALSE) +#define VALIDATEBEGIN do { +#define VALIDATE(a) ASSERT(a) +#define VALIDATEANDBLANK(a) do { \ + ASSERT(a); \ + *(a) = 0; \ + } while (0) +#define VALIDATEEND } while (0) +#define VALIDATEENDVOID } while (0) +#else +#define ASSERT(a) +#define VALIDATEBEGIN do { \ + int intrn_valresult = -1 +#define VALIDATE(a) intrn_valresult &= (a) ? -1 : 0 +#define VALIDATEANDBLANK(a) if (a) \ + *a = 0; \ + else \ + intrn_valresult = 0 +#define VALIDATEEND if (!intrn_valresult) { \ + SErrSetLastError( \ + ERROR_INVALID_PARAMETER); \ + return 0; \ + } \ + } while (0) +#define VALIDATEENDVOID if (!intrn_valresult) { \ + SErrSetLastError( \ + ERROR_INVALID_PARAMETER); \ + return; \ + } \ + } while (0) +#endif + + +/**************************************************************************** +* +* Event dispatching functions +* +***/ + +typedef void (CALLBACK *SEVTHANDLER)(LPVOID); + +extern "C" BOOL APIENTRY SEvtBreakHandlerChain (LPVOID data); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SEvtDestroy (); +#endif +extern "C" BOOL APIENTRY SEvtDispatch (DWORD type, + DWORD subtype, + DWORD id, + LPVOID data); +extern "C" BOOL APIENTRY SEvtPopState (DWORD type, + DWORD subtype); +extern "C" BOOL APIENTRY SEvtPushState (DWORD type, + DWORD subtype); +extern "C" BOOL APIENTRY SEvtRegisterHandler (DWORD type, + DWORD subtype, + DWORD id, + DWORD flags, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterHandler (DWORD type, + DWORD subtype, + DWORD id, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterType (DWORD type, + DWORD subtype); + + +/**************************************************************************** +* +* File I/O functions +* +***/ + +#define SFILE_AUTH_UNABLETOAUTHENTICATE 0 +#define SFILE_AUTH_NOSIGNATURE 1 +#define SFILE_AUTH_BADSIGNATURE 2 +#define SFILE_AUTH_UNKNOWNSIGNATURE 3 +#define SFILE_AUTH_FIRSTAUTHENTIC 5 +#define SFILE_AUTH_AUTHENTICBLIZZARD 5 + +#define SFILE_DDA_LOOP 0x00040000 + +#define SFILE_ERROR_BAD_FORMAT ERROR_BAD_FORMAT +#define SFILE_ERROR_BAD_PATHNAME ERROR_BAD_PATHNAME +#define SFILE_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED +#define SFILE_ERROR_FILE_INVALID ERROR_FILE_INVALID +#define SFILE_ERROR_FILE_NOT_FOUND ERROR_FILE_NOT_FOUND +#define SFILE_ERROR_HANDLE_EOF ERROR_HANDLE_EOF +#define SFILE_ERROR_INVALID_DATA ERROR_INVALID_DATA +#define SFILE_ERROR_INVALID_DRIVE ERROR_INVALID_DRIVE +#define SFILE_ERROR_INVALID_HANDLE ERROR_INVALID_HANDLE +#define SFILE_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SFILE_ERROR_NOT_ARCHIVE STORM_ERROR_NOT_ARCHIVE +#define SFILE_ERROR_NOT_AUTHENTICATED ERROR_NOT_AUTHENTICATED +#define SFILE_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SFILE_ERROR_NOT_IN_ARCHIVE STORM_ERROR_NOT_IN_ARCHIVE +#define SFILE_ERROR_NOT_INITIALIZED STORM_ERROR_NOT_INITIALIZED +#define SFILE_ERROR_NOT_PLAYING STORM_ERROR_NOT_PLAYING + +#define SFILE_ERRORMODE_RETURNCODE 0 +#define SFILE_ERRORMODE_CUSTOM 1 +#define SFILE_ERRORMODE_FATAL 2 + +#define SFILE_FIND_FILES 0x00000001 +#define SFILE_FIND_DIRECTORIES 0x00000002 + +DECLARE_STRICT_HANDLE(HSARCHIVE); +DECLARE_STRICT_HANDLE(HSFILE); + +typedef BOOL (CALLBACK *SFILEERRORPROC)(LPCTSTR,DWORD); + +extern "C" BOOL APIENTRY SFileAuthenticateArchive (HSARCHIVE archive, + DWORD *extendedresult); +extern "C" BOOL APIENTRY SFileCloseArchive (HSARCHIVE handle); +extern "C" BOOL APIENTRY SFileCloseFile (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaBegin (HSFILE handle, + DWORD buffersize, + DWORD flags); +extern "C" BOOL APIENTRY SFileDdaBeginEx (HSFILE handle, + DWORD buffersize, + DWORD flags, + DWORD offset, + LONG volume, + LONG pan, + LPVOID reserved); +extern "C" BOOL APIENTRY SFileDdaDestroy (); +extern "C" BOOL APIENTRY SFileDdaEnd (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaGetPos (HSFILE handle, + DWORD *position, + DWORD *maxposition); +extern "C" BOOL APIENTRY SFileDdaGetVolume (HSFILE handle, + LONG *volume, + LONG *pan); +#ifdef __DSOUND_INCLUDED__ +extern "C" BOOL APIENTRY SFileDdaInitialize (LPDIRECTSOUND directsound); +#endif +extern "C" BOOL APIENTRY SFileDdaSetVolume (HSFILE handle, + LONG volume, + LONG pan); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SFileDestroy (); +#endif +extern "C" BOOL APIENTRY SFileEnableDirectAccess (BOOL enable); +extern "C" BOOL APIENTRY SFileGetArchiveInfo (HSARCHIVE archive, + int *priority, + BOOL *cdrom); +extern "C" BOOL APIENTRY SFileGetArchiveName (HSARCHIVE archive, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SFileGetBasePath (LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SFileGetFileArchive (HSFILE file, + HSARCHIVE *archive); +extern "C" BOOL APIENTRY SFileGetFileName (HSFILE file, + LPTSTR buffer, + DWORD bufferchars); +extern "C" DWORD APIENTRY SFileGetFileSize (HSFILE handle, + LPDWORD filesizehigh = NULL); +extern "C" BOOL APIENTRY SFileOpenArchive (LPCTSTR archivename, + int priority, + BOOL cdonly, + HSARCHIVE *handle); +extern "C" BOOL APIENTRY SFileOpenFile (LPCTSTR filename, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileEx (HSARCHIVE archivehandle, + LPCTSTR filename, + DWORD flags, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileReadFile (HSFILE handle, + LPVOID buffer, + DWORD bytestoread, + LPDWORD bytesread = NULL, + LPOVERLAPPED overlapped = NULL); +extern "C" BOOL APIENTRY SFileSetBasePath (LPCTSTR path); +extern "C" DWORD APIENTRY SFileSetFilePointer (HSFILE handle, + LONG distancetomove, + PLONG distancetomovehigh, + DWORD movemethod); +extern "C" BOOL APIENTRY SFileSetIoErrorMode (DWORD errormode, + SFILEERRORPROC errorproc = NULL); +extern "C" BOOL APIENTRY SFileSetLocale (LCID lcid); + + +/**************************************************************************** +* +* GDI functions +* +***/ + +#define ETO_TEXT_TRANSPARENT 0 +#define ETO_TEXT_COLOR 1 +#define ETO_TEXT_BLACK 2 +#define ETO_TEXT_WHITE 3 +#define ETO_BKG_TRANSPARENT 0 +#define ETO_BKG_COLOR 1 +#define ETO_BKG_BLACK 2 +#define ETO_BKG_WHITE 3 + +DECLARE_STRICT_HANDLE(HSGDIOBJ); +DECLARE_DERIVED_HANDLE(HSGDIFONT,HSGDIOBJ); + +extern "C" BOOL APIENTRY SGdiBitBlt (LPBYTE videobuffer, + int destx, + int desty, + LPBYTE sourcedata, + LPRECT sourcerect, + int sourcecx, + int sourcecy, + COLORREF color = 0, + DWORD rop = SRCCOPY); +extern "C" BOOL APIENTRY SGdiCreateFont (LPBYTE bits, + int width, + int height, + int bitdepth, + int filecharwidth, + int filecharheight, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiDeleteObject (HSGDIOBJ handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SGdiDestroy (); +#endif +extern "C" BOOL APIENTRY SGdiExtTextOut (LPBYTE videobuffer, + int x, + int y, + LPRECT rect, + COLORREF color, + int textcoloruse, + int bkgcoloruse, + LPCTSTR string, + int chars = -1); +extern "C" BOOL APIENTRY SGdiGetTextExtent (LPCTSTR string, + int chars, + LPSIZE size); +extern "C" BOOL APIENTRY SGdiImportFont (HFONT windowsfont, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiLoadFont (LPCTSTR filename, + int filecharwidth, + int filecharheight, + int basecharwidth, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiRectangle (LPBYTE videobuffer, + int left, + int top, + int right, + int bottom, + COLORREF color); +extern "C" BOOL APIENTRY SGdiSelectObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiSetPitch (int pitch); +extern "C" BOOL APIENTRY SGdiSetTargetDimensions (int width, + int height, + int bitdepth, + int pitch); +extern "C" BOOL APIENTRY SGdiTextOut (LPBYTE videobuffer, + int x, + int y, + COLORREF color, + LPCTSTR string, + int chars = -1); + + +/**************************************************************************** +* +* Logging functions +* +***/ + +DECLARE_STRICT_HANDLE(HSLOG); + +extern "C" void APIENTRY SLogClose (HSLOG log); +extern "C" BOOL APIENTRY SLogCreate (LPCTSTR filename, + DWORD flags, + HSLOG *log); +#ifdef STORMSTATIC +extern "C" void APIENTRY SLogDestroy (); +#endif +extern "C" void APIENTRY SLogDump (HSLOG log, + LPCVOID data, + DWORD bytes); +extern "C" void APIENTRY SLogFlush (HSLOG log); +extern "C" void APIENTRY SLogFlushAll (); +#ifdef STORMSTATIC +extern "C" void APIENTRY SLogInitialize (); +#endif +extern "C" void __cdecl SLogPend (HSLOG log, + LPCTSTR format, + ...); +extern "C" void __cdecl SLogWrite (HSLOG log, + LPCTSTR format, + ...); + + +/**************************************************************************** +* +* Memory allocation functions +* +***/ + +#define SMEM_FLAG_ZEROMEMORY 0x00000008 +#define SMEM_FLAG_PRESERVEONDESTROY 0x08000000 + +DECLARE_STRICT_HANDLE(HSHEAP); + +typedef struct _SMEMBLOCKDETAILS { + DWORD size; + LPVOID ptr; + BOOL allocated; + BOOL valid; + DWORD bytes; + DWORD overhead; +} SMEMBLOCKDETAILS, *LPSMEMBLOCKDETAILS; + +typedef struct _SMEMHEAPDETAILS { + DWORD size; + HSHEAP handle; + char filename[MAX_PATH]; + int linenumber; + DWORD regions; + DWORD committedbytes; + DWORD reservedbytes; + DWORD maximumsize; + DWORD allocatedblocks; +} SMEMHEAPDETAILS, *LPSMEMHEAPDETAILS; + +extern "C" LPVOID APIENTRY SMemAlloc (DWORD bytes, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SMemDestroy (); +#endif +extern "C" BOOL APIENTRY SMemFindNextBlock (HSHEAP heap, + LPVOID prevblock, + LPVOID *nextblock, + LPSMEMBLOCKDETAILS details); +extern "C" BOOL APIENTRY SMemFindNextHeap (HSHEAP prevheap, + HSHEAP *nextheap, + LPSMEMHEAPDETAILS details); +extern "C" BOOL APIENTRY SMemFree (LPVOID ptr, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" HSHEAP APIENTRY SMemGetHeapByCaller (LPCSTR filename, + int linenumber); +extern "C" HSHEAP APIENTRY SMemGetHeapByPtr (LPVOID ptr); +extern "C" LPVOID APIENTRY SMemHeapAlloc (HSHEAP handle, + DWORD flags, + DWORD bytes); +extern "C" HSHEAP APIENTRY SMemHeapCreate (DWORD options, + DWORD initialsize, + DWORD maximumsize); +extern "C" BOOL APIENTRY SMemHeapDestroy (HSHEAP handle); +extern "C" BOOL APIENTRY SMemHeapFree (HSHEAP handle, + DWORD flags, + LPVOID ptr); +#ifdef STORMSTATIC +extern "C" void APIENTRY SMemInitialize (); +#endif + +inline void __cdecl operator delete (void *ptr) { + if (ptr) + SMemFree(ptr,__FILE__,__LINE__,0); +} + +inline void * __cdecl operator new (size_t bytes) { + return SMemAlloc(bytes,__FILE__,__LINE__,0); +} + +#ifndef __ICL +#ifndef __MWERKS__ +inline void __cdecl operator delete[] (void *ptr) { + if (ptr) + SMemFree(ptr,__FILE__,__LINE__,0); +} + +inline void * __cdecl operator new[] (size_t bytes) { + return SMemAlloc(bytes,__FILE__,__LINE__,0); +} +#endif +#endif + +#ifndef __PLACEMENT_NEW_INLINE +#define __PLACEMENT_NEW_INLINE +inline void * __cdecl operator new (size_t, void *ptr) { + return (ptr); +} + +inline void * __cdecl operator new[] (size_t, void *ptr) { + return (ptr); +} +#endif + +#define ALLOC(bytes) SMemAlloc(bytes,__FILE__,__LINE__,0) +#define ALLOCZERO(bytes) SMemAlloc(bytes,__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) +#define DEL(ptr) delete(ptr) +#define DELIFUSED(ptr) delete(ptr) +#define FREE(ptr) SMemFree(ptr,__FILE__,__LINE__,0) +#define FREEIFUSED(ptr) do if (ptr) SMemFree(ptr,__FILE__,__LINE__,0); while (0) +#define NEW(struct) (new(SMemAlloc(sizeof(struct),__FILE__,__LINE__,0)) struct) +#define NEWZERO(struct) (new(SMemAlloc(sizeof(struct),__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY)) struct) + + +/**************************************************************************** +* +* Message functions +* +***/ + +typedef struct _PARAMS { + HWND window; + UINT message; + WPARAM wparam; + LPARAM lparam; + UINT notifycode; + LPVOID extra; + BOOL useresult; + LRESULT result; +} PARAMS, *PARAMSPTR, *LPPARAMS; + +typedef BOOL (CALLBACK *SMSGIDLEPROC)(DWORD); +typedef void (CALLBACK *SMSGHANDLER)(LPPARAMS); + +extern "C" BOOL APIENTRY SMsgBreakHandlerChain (LPPARAMS params); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SMsgDestroy (); +#endif +extern "C" BOOL APIENTRY SMsgDispatchMessage (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL *useresult, + LRESULT *result); +extern "C" BOOL APIENTRY SMsgDoMessageLoop (SMSGIDLEPROC idleproc = NULL, + BOOL cleanuponquit = TRUE); +extern "C" BOOL APIENTRY SMsgPopRegisterState (HWND window); +extern "C" BOOL APIENTRY SMsgPushRegisterState (HWND window); +extern "C" BOOL APIENTRY SMsgRegisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); + + +/**************************************************************************** +* +* Networking functions +* +***/ + +#define SNET_ART_BACKGROUND 0 +#define SNET_ART_BUTTONTEXTURE 1 +#define SNET_ART_JOINBACKGROUND 2 +#define SNET_ART_HELPBACKGROUND 3 +#define SNET_ART_POPUPBACKGROUND 4 +#define SNET_ART_BUTTON_XSML 5 +#define SNET_ART_BUTTON_SML 6 +#define SNET_ART_BUTTON_MED 7 +#define SNET_ART_BUTTON_LRG 8 +#define SNET_ART_APP_LOGO_SML 9 +#define SNET_ART_PROGRESS_BACKGROUND 10 +#define SNET_ART_PROGRESS_FILLER 11 +#define SNET_ART_POPUPBACKGROUND_SML 12 +#define SNET_ART_SCROLLBARARROWS 13 +#define SNET_ART_SCROLLTHUMB 14 +#define SNET_ART_SCROLLBAR 15 +#define SNET_ART_COMBOLEFT 16 +#define SNET_ART_COMBOMIDDLE 17 +#define SNET_ART_COMBORIGHT 18 + +#define SNET_AUTHTYPE_CHANNEL 1 +#define SNET_AUTHTYPE_GAME 2 + +#define SNET_BROADCASTNONLOCALPLAYERID 0xFFFFFFFE +#define SNET_BROADCASTPLAYERID 0xFFFFFFFF +#define SNET_INVALIDPLAYERID 0xFFFFFFFF + +#define SNET_CAPS_PAGELOCKEDBUFFERS 0x00000001 +#define SNET_CAPS_BASICINTERFACE 0x00000002 +#define SNET_CAPS_DEBUGONLY 0x10000000 +#define SNET_CAPS_RETAILONLY 0x20000000 + +#define SNET_CF_ALLOWPRIVATEGAMES 0x00000001 + +#define SNET_DATA_SYSCOLORS 1 +#define SNET_DATA_CURSORLINK 2 +#define SNET_DATA_CURSORARROW 3 +#define SNET_DATA_CURSORIBEAM 4 + +#define SNET_DDF_INCLUDENAME 0x00000001 +#define SNET_DDF_MULTILINE 0x00000002 + +#define SNET_DDPF_BLIZZARD 0x00000001 +#define SNET_DDPF_MODERATOR 0x00000002 +#define SNET_DDPF_SPEAKER 0x00000004 +#define SNET_DDPF_SYSOP 0x00000008 +#define SNET_DDPF_SQUELCHED 0x00000020 + +#define SNET_DRAWTYPE_GAME 1 +#define SNET_DRAWTYPE_PLAYER 2 + +#define SNET_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS +#define SNET_ERROR_BAD_PROVIDER ERROR_BAD_PROVIDER +#define SNET_ERROR_CANCELLED ERROR_CANCELLED +#define SNET_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SNET_ERROR_INVALID_PLAYER STORM_ERROR_INVALID_PLAYER +#define SNET_ERROR_GAME_ALREADY_STARTED STORM_ERROR_GAME_ALREADY_STARTED +#define SNET_ERROR_GAME_FULL STORM_ERROR_GAME_FULL +#define SNET_ERROR_GAME_NOT_FOUND STORM_ERROR_GAME_NOT_FOUND +#define SNET_ERROR_GAME_TERMINATED STORM_ERROR_GAME_TERMINATED +#define SNET_ERROR_HOST_UNREACHABLE ERROR_HOST_UNREACHABLE +#define SNET_ERROR_MAX_THRDS_REACHED ERROR_MAX_THRDS_REACHED +#define SNET_ERROR_NETWORK_BUSY ERROR_NETWORK_BUSY +#define SNET_ERROR_NO_MESSAGES_WAITING STORM_ERROR_NO_MESSAGES_WAITING +#define SNET_ERROR_NO_NETWORK ERROR_NO_NETWORK +#define SNET_ERROR_NOT_CONNECTED ERROR_NOT_CONNECTED +#define SNET_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SNET_ERROR_NOT_IMPLEMENTED STORM_ERROR_NOT_IMPLEMENTED +#define SNET_ERROR_NOT_IN_GAME STORM_ERROR_NOT_IN_GAME +#define SNET_ERROR_NOT_OWNER ERROR_NOT_OWNER +#define SNET_ERROR_NOT_REGISTERED STORM_ERROR_NOT_REGISTERED +#define SNET_ERROR_REQUIRES_UPGRADE STORM_ERROR_REQUIRES_UPGRADE +#define SNET_ERROR_STILL_ACTIVE STORM_ERROR_STILL_ACTIVE +#define SNET_ERROR_TOO_MANY_NAMES ERROR_TOO_MANY_NAMES +#define SNET_ERROR_VERSION_MISMATCH STORM_ERROR_VERSION_MISMATCH + +#define SNET_EVENT_INITDATA 1 +#define SNET_EVENT_PLAYERJOIN 2 +#define SNET_EVENT_PLAYERLEAVE 3 +#define SNET_EVENT_SERVERMESSAGE 4 + +#define SNET_EXIT_AUTO_JOINING 0x00000001 +#define SNET_EXIT_AUTO_NEWGAME 0x00000002 +#define SNET_EXIT_AUTO_SHUTDOWN 0x00000003 +#define SNET_EXIT_PLAYERQUIT 0x40000001 +#define SNET_EXIT_PLAYERKILLED 0x40000002 +#define SNET_EXIT_PLAYERWON 0x40000004 +#define SNET_EXIT_GAMEOVER 0x40000005 +#define SNET_EXIT_NOTRESPONDING 0x40000006 + +#define SNET_GM_PRIVATE 0x00000001 +#define SNET_GM_FULL 0x00000002 +#define SNET_GM_ADVERTISED 0x00000004 +#define SNET_GM_UNJOINABLE 0x00000008 +#define SNET_GM_UNLISTEDMASK (SNET_GM_PRIVATE | SNET_GM_FULL | SNET_GM_UNJOINABLE) + +#define SNET_INFO_GAMENAME 1 +#define SNET_INFO_GAMEPASSWORD 2 +#define SNET_INFO_GAMEDESCRIPTION 3 +#define SNET_INFO_GAMEMODE 4 +#define SNET_INFO_INITDATA 5 +#define SNET_INFO_MAXPLAYERS 6 + +#define SNET_LMT_EXPECTED 1 +#define SNET_LMT_CURRENT 2 +#define SNET_LMT_PEAK 4 + +#define SNET_PERFID_TURN 1 +#define SNET_PERFID_TURNSSENT 4 +#define SNET_PERFID_TURNSRECV 5 +#define SNET_PERFID_MSGSENT 6 +#define SNET_PERFID_MSGRECV 7 +#define SNET_PERFID_USERBYTESSENT 8 +#define SNET_PERFID_USERBYTESRECV 9 +#define SNET_PERFID_TOTALBYTESSENT 10 +#define SNET_PERFID_TOTALBYTESRECV 11 +#define SNET_PERFID_PKTSENTONWIRE 12 +#define SNET_PERFID_PKTRECVONWIRE 13 +#define SNET_PERFID_BYTESSENTONWIRE 14 +#define SNET_PERFID_BYTESRECVONWIRE 15 +#define SNET_PERFIDNUM 16 + +#define SNET_PERFTYPE_COUNTER 0x10410400 +#define SNET_PERFTYPE_RAWCOUNT 0x00010000 + +#define SNET_PSF_ACTIVE 0x00010000 +#define SNET_PSF_TURNAVAILABLE 0x00020000 +#define SNET_PSF_RESPONDING 0x00040000 + +#define SNET_SF_ALLOWCREATE 0x00000001 + +#define SNET_SND_CHANGEFOCUS 0 +#define SNET_SND_SELECTITEM 1 + +#define SNET_UPGRADE_FAILED -1 +#define SNET_UPGRADE_NOT_NEEDED 0 +#define SNET_UPGRADE_SUCCEEDED 1 +#define SNET_UPGRADING_TERMINATE 2 + +#define SNET_MAXNAMELENGTH 128 +#define SNET_MAXDESCLENGTH 128 + +typedef struct _SNETCAPS { + DWORD size; + DWORD flags; + DWORD maxmessagesize; + DWORD maxqueuesize; + DWORD maxplayers; + DWORD bytessec; + DWORD latencyms; + DWORD defaultturnssec; + DWORD defaultturnsintransit; +} SNETCAPS, *SNETCAPSPTR; + +typedef struct _SNETCREATEDATA { + DWORD size; + DWORD providerid; + DWORD maxplayers; + DWORD createflags; +} SNETCREATEDATA, *SNETCREATEDATAPTR; + +typedef struct _SNET_DATA_SYSCOLORTABLE { + DWORD syscolor; + COLORREF rgb; +} SNET_DATA_SYSCOLORTABLE, *SNET_DATA_SYSCOLORTABLEPTR; + +typedef struct _SNETEVENT { + DWORD eventid; + DWORD playerid; + LPVOID data; + DWORD databytes; +} SNETEVENT, *SNETEVENTPTR; + +typedef struct _SNETGAME { + DWORD size; + DWORD id; + LPCSTR gamename; + LPCSTR gamedescription; + DWORD categorybits; + DWORD numplayers; + DWORD maxplayers; +} SNETGAME, *SNETGAMEPTR; + +struct _SNETPROGRAMDATA; +struct _SNETPLAYERDATA; +struct _SNETUIDATA; +struct _SNETVERSIONDATA; + +typedef BOOL (CALLBACK *SNETABORTPROC )(); +typedef void (CALLBACK *SNETADDCATEGORYPROC )(LPCSTR,DWORD,DWORD); +typedef void (CALLBACK *SNETCATEGORYLISTPROC )(_SNETPLAYERDATA *,SNETADDCATEGORYPROC); +typedef BOOL (CALLBACK *SNETCATEGORYPROC )(BOOL,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *,DWORD *); +typedef BOOL (CALLBACK *SNETCHECKAUTHPROC )(DWORD,LPCSTR,LPCSTR,DWORD,LPCSTR,LPSTR,DWORD); +typedef BOOL (CALLBACK *SNETCREATEPROC )(SNETCREATEDATAPTR,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *); +typedef BOOL (CALLBACK *SNETDRAWDESCPROC )(DWORD,DWORD,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,LPDRAWITEMSTRUCT); +typedef BOOL (CALLBACK *SNETENUMDEVICESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMGAMESEXPROC )(SNETGAMEPTR); +typedef BOOL (CALLBACK *SNETENUMGAMESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMPROVIDERSPROC)(DWORD,LPCSTR,LPCSTR,SNETCAPSPTR); +typedef void (CALLBACK *SNETEVENTPROC )(SNETEVENTPTR); +typedef BOOL (CALLBACK *SNETGETARTPROC )(DWORD,DWORD,LPPALETTEENTRY,LPBYTE,DWORD,int *,int *,int *); +typedef BOOL (CALLBACK *SNETGETDATAPROC )(DWORD,DWORD,LPVOID,DWORD,DWORD *); +typedef int (CALLBACK *SNETMESSAGEBOXPROC )(HWND,LPCSTR,LPCSTR,UINT); +typedef BOOL (CALLBACK *SNETPLAYSOUNDPROC )(DWORD,DWORD,DWORD); +typedef BOOL (CALLBACK *SNETSELECTEDPROC )(DWORD,SNETCAPSPTR,_SNETUIDATA *,_SNETVERSIONDATA *); +typedef BOOL (CALLBACK *SNETSTATUSPROC )(LPCSTR,DWORD,DWORD,DWORD,SNETABORTPROC); +typedef BOOL (CALLBACK *SNETPROFILEPROC )(); // tbd -- include callback to save info +typedef BOOL (CALLBACK *SNETNEWACCOUNTPROC )(); // tbd -- include callback to try to create + +typedef struct _SNETPLAYERDATA { + DWORD size; + LPCSTR playername; + LPCSTR playerdescription; + // new for 1.05: + LPCSTR displayedfields; +} SNETPLAYERDATA, *SNETPLAYERDATAPTR; + +typedef struct _SNETPROGRAMDATA { + DWORD size; + LPCSTR programname; + LPCSTR programdescription; + DWORD programid; + DWORD versionid; + DWORD reserved1; + DWORD maxplayers; + LPVOID initdata; + DWORD initdatabytes; + LPVOID reserved2; + DWORD optcategorybits; +} SNETPROGRAMDATA, *SNETPROGRAMDATAPTR; + +typedef struct _SNETUIDATA { + DWORD size; + DWORD uiflags; + HWND parentwindow; + SNETGETARTPROC artcallback; + SNETCHECKAUTHPROC authcallback; + SNETCREATEPROC createcallback; + SNETDRAWDESCPROC drawdesccallback; + SNETSELECTEDPROC selectedcallback; + SNETMESSAGEBOXPROC messageboxcallback; + SNETPLAYSOUNDPROC soundcallback; + SNETSTATUSPROC statuscallback; + SNETGETDATAPROC getdatacallback; + SNETCATEGORYPROC categorycallback; + // new for 1.05: + SNETCATEGORYLISTPROC categorylistcallback; + SNETNEWACCOUNTPROC newaccountcallback; + SNETPROFILEPROC profilecallback; +} SNETUIDATA, *SNETUIDATAPTR; + +typedef struct _SNETVERSIONDATA { + DWORD size; + LPCSTR versionstring; + LPCSTR executablefile; + LPCSTR originalarchivefile; + LPCSTR patcharchivefile; +} SNETVERSIONDATA, *SNETVERSIONDATAPTR; + +extern "C" BOOL APIENTRY SNetCreateGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamecategorybits, + LPVOID initdata, + DWORD initdatabytes, + DWORD maxplayers, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetDestroy (); +extern "C" BOOL APIENTRY SNetDropPlayer (DWORD playerid, DWORD exitcode); +extern "C" BOOL APIENTRY SNetEnumDevices (SNETENUMDEVICESPROC callback); +extern "C" BOOL APIENTRY SNetEnumGames (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumGamesEx (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESEXPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumProviders (SNETCAPSPTR mincaps, + SNETENUMPROVIDERSPROC callback); +extern "C" BOOL APIENTRY SNetGetGameInfo (DWORD index, + LPVOID buffer, + DWORD buffersize, + DWORD *byteswritten); +extern "C" BOOL APIENTRY SNetGetNetworkLatency (DWORD measurementtype, + DWORD *result); +extern "C" BOOL APIENTRY SNetGetNumPlayers (DWORD *firstplayerid, + DWORD *lastplayerid, + DWORD *activeplayers); +extern "C" BOOL APIENTRY SNetGetOwnerId (DWORD *playerid); +extern "C" BOOL APIENTRY SNetGetOwnerTurnsWaiting (DWORD *turns); +extern "C" BOOL APIENTRY SNetGetPerformanceData (DWORD counterid, + DWORD *countervalue, + DWORD *countertype, + LONG *counterscale, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +extern "C" BOOL APIENTRY SNetGetPlayerCaps (DWORD playerid, + SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetPlayerName (DWORD playerid, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SNetGetProviderCaps (SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetTurnsInTransit (DWORD *turns); +extern "C" BOOL APIENTRY SNetInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetInitializeProvider (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetJoinGame (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetLeaveGame (DWORD exitcode); +extern "C" BOOL APIENTRY SNetPerformUpgrade (DWORD *upgradestatus); +extern "C" BOOL APIENTRY SNetReceiveMessage (DWORD *senderplayerid, + LPVOID *data, + DWORD *databytes); +extern "C" BOOL APIENTRY SNetReceiveTurns (DWORD firstplayerid, + DWORD arraysize, + LPVOID *arraydata, + LPDWORD arraydatabytes, + LPDWORD arrayplayerstatus); +extern "C" BOOL APIENTRY SNetRegisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); +extern "C" BOOL APIENTRY SNetResetLatencyMeasurements (); +extern "C" BOOL APIENTRY SNetSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY SNetSendMessage (DWORD targetplayerid, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSendServerChatCommand (LPCSTR command); +extern "C" BOOL APIENTRY SNetSendTurn (LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSetBasePlayer (DWORD playerid); +extern "C" BOOL APIENTRY SNetSetGameMode (DWORD modeflags); +extern "C" BOOL APIENTRY SNetUnregisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); + + +/**************************************************************************** +* +* Networking service provider interface +* +***/ + +#define SNETSPI_MAXCLIENTDATA 256 +#define SNETSPI_MAXSTRINGLENGTH 128 + +typedef struct _SNETADDR { + BYTE address[16]; +} SNETADDR, *SNETADDRPTR; + +typedef struct _SNETSPI_DEVICELIST { + DWORD deviceid; + SNETCAPS devicecaps; + char devicename[SNETSPI_MAXSTRINGLENGTH]; + char devicedescription[SNETSPI_MAXSTRINGLENGTH]; + DWORD reserved; + _SNETSPI_DEVICELIST *next; +} SNETSPI_DEVICELIST, *SNETSPI_DEVICELISTPTR; + +typedef struct _SNETSPI_GAMELIST { + DWORD gameid; + DWORD gamemode; + DWORD creationtime; + SNETADDR owner; + DWORD ownerlatency; + DWORD ownerlasttime; + DWORD gamecategorybits; + char gamename[SNETSPI_MAXSTRINGLENGTH]; + char gamedescription[SNETSPI_MAXSTRINGLENGTH]; + _SNETSPI_GAMELIST *next; + // new for 1.05: + LPVOID clientdata; + DWORD clientdatabytes; +} SNETSPI_GAMELIST, *SNETSPI_GAMELISTPTR; + +typedef struct _SNETSPI { + DWORD size; + BOOL (CALLBACK *CompareNetAddresses)(SNETADDRPTR,SNETADDRPTR,DWORD *); + BOOL (CALLBACK *Destroy)(); + BOOL (CALLBACK *Free)(SNETADDRPTR,LPVOID,DWORD); + BOOL (CALLBACK *FreeExternalMessage)(LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *GetGameInfo)(DWORD,LPCSTR,LPCSTR,SNETSPI_GAMELIST *); + BOOL (CALLBACK *GetPerformanceData)(DWORD,DWORD *,LARGE_INTEGER *,LARGE_INTEGER *); + BOOL (CALLBACK *Initialize)(SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,HANDLE); + BOOL (CALLBACK *InitializeDevice)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR); + BOOL (CALLBACK *LockDeviceList)(SNETSPI_DEVICELISTPTR *); + BOOL (CALLBACK *LockGameList)(DWORD,DWORD,SNETSPI_GAMELISTPTR *); + +/* note: this is the way that the Receive call should look... + + BOOL (CALLBACK *Receive)(SNETADDRPTR *,LPVOID *,DWORD *); + + below is the receive call with two parameters switched around + to make it incompatible with older .snp's during the beta... */ + + BOOL (CALLBACK *Receive)(LPVOID *,DWORD *,SNETADDRPTR *); + + BOOL (CALLBACK *ReceiveExternalMessage)(LPCSTR *,LPCSTR *,LPCSTR *); + BOOL (CALLBACK *SelectGame)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,DWORD *); + BOOL (CALLBACK *Send)(DWORD,SNETADDRPTR *,LPVOID,DWORD); + BOOL (CALLBACK *SendExternalMessage)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *StartAdvertisingGame)(LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,DWORD,LPCVOID,DWORD); + BOOL (CALLBACK *StopAdvertisingGame)(); + BOOL (CALLBACK *UnlockDeviceList)(SNETSPI_DEVICELISTPTR); + BOOL (CALLBACK *UnlockGameList)(SNETSPI_GAMELISTPTR,DWORD *); + // new for 1.05: + BOOL (CALLBACK *GetLocalPlayerName)(LPSTR,DWORD,LPSTR,DWORD); +} SNETSPI, *SNETSPIPTR; + +typedef BOOL (APIENTRY *SNETSPIBIND )(DWORD,SNETSPIPTR *); +typedef BOOL (APIENTRY *SNETSPIQUERY)(DWORD,DWORD *,LPCSTR *,LPCSTR *,SNETCAPSPTR *); + + +/**************************************************************************** +* +* Registry functions +* +***/ + +#define SREG_FLAG_USERSPECIFIC 0x00000001 +#define SREG_FLAG_BATTLENET 0x00000002 +#define SREG_FLAG_FLUSHTODISK 0x00000008 +#define SREG_FLAG_MULTISZ 0x00000080 + +extern "C" BOOL APIENTRY SRegGetBaseKey (DWORD flags, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SRegLoadData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID buffer, + DWORD buffersize, + DWORD *bytesread); +extern "C" BOOL APIENTRY SRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SRegLoadValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *value); +extern "C" BOOL APIENTRY SRegSaveData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SRegSaveString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPCTSTR string); +extern "C" BOOL APIENTRY SRegSaveValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD value); + + +/**************************************************************************** +* +* Region manager functions +* +***/ + +#define SRGN_AND RGN_AND +#define SRGN_COPY RGN_COPY +#define SRGN_DIFF RGN_DIFF +#define SRGN_OR RGN_OR +#define SRGN_XOR RGN_XOR +#define SRGN_PARAMONLY 6 +#define SRGN_MIN 1 +#define SRGN_MAX 6 + +DECLARE_STRICT_HANDLE(HSRGN); + +extern "C" void APIENTRY SRgnClear (HSRGN handle); +extern "C" void APIENTRY SRgnCombineRect (HSRGN handle, + LPCRECT rect, + LPVOID param, + int combinemode); +extern "C" void APIENTRY SRgnCreate (HSRGN *handle, + DWORD reserved = 0); +extern "C" void APIENTRY SRgnDelete (HSRGN handle); +#ifdef STORMSTATIC +extern "C" void APIENTRY SRgnDestroy (); +#endif +extern "C" void APIENTRY SRgnDuplicate (HSRGN orighandle, + HSRGN *handle, + DWORD reserved = 0); +extern "C" void APIENTRY SRgnGetBoundingRect (HSRGN handle, + LPRECT rect); +extern "C" void APIENTRY SRgnGetRectParams (HSRGN handle, + LPCRECT rect, + DWORD *numparams, + LPVOID *buffer); +extern "C" void APIENTRY SRgnGetRects (HSRGN handle, + DWORD *numrects, + LPRECT buffer); + +#define SRgnAddParam(handle,rect,param) SRgnCombineRect(handle,rect,param,SRGN_PARAMONLY); +#define SRgnAddRect(handle,rect,param) SRgnCombineRect(handle,rect,param,SRGN_OR) + + +/**************************************************************************** +* +* Run-time library functions +* +***/ + +#define ONCE ONCEEXPAND(__FILE__##__##__LINE__##__once) +#define ONCEEXPAND(a) BOOL a = TRUE; a; a = FALSE + +#define TRY goto trylabel; trylabel: +#define LEAVE goto finallylabel +#define FINALLY goto finallylabel; finallylabel: + + +/**************************************************************************** +* +* String functions +* +***/ + +#define SSTR_HASH_CASESENSITIVE 0x00000001 + +#define SSTR_UNBOUNDED 0x7FFFFFFF + +extern "C" LPTSTR APIENTRY SStrChr (LPCTSTR string, + char ch, + BOOL reverse = FALSE); +extern "C" DWORD APIENTRY SStrCopy (LPTSTR dest, + LPCTSTR source, + DWORD destsize = SSTR_UNBOUNDED); +extern "C" DWORD APIENTRY SStrHash (LPCTSTR string, + DWORD flags = 0, + DWORD seed = 0); +extern "C" DWORD APIENTRY SStrLen (LPCTSTR string); +extern "C" void APIENTRY SStrPack (LPTSTR dest, + LPCTSTR source, + DWORD destsize = SSTR_UNBOUNDED); +extern "C" void APIENTRY SStrTokenize (LPCTSTR *string, + LPTSTR buffer, + DWORD bufferchars, + LPCTSTR whitespace, + BOOL *quoted = NULL); + + +/**************************************************************************** +* +* Transparency functions +* +***/ + +#define STRANS_CF_INTERSECT 0x00000001 +#define STRANS_CF_INVERTSECOND 0x00000002 +#define STRANS_CF_SUBTRACT (STRANS_CF_INTERSECT | STRANS_CF_INVERTSECOND) + +DECLARE_STRICT_HANDLE(HSTRANS); +typedef HSTRANS HTRANS; + +extern "C" BOOL APIENTRY STransBlt (LPBYTE dest, + int destx, + int desty, + int destpitch, + HSTRANS transparency); +extern "C" BOOL APIENTRY STransBltUsingMask (LPBYTE dest, + LPBYTE source, + int destpitch, + int sourcepitch, + HSTRANS mask); +extern "C" BOOL APIENTRY STransCombineMasks (HSTRANS basemask, + HSTRANS secondmask, + int offsetx, + int offsety, + DWORD flags, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateMaskE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateMaskI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransDelete (HSTRANS handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY STransDestroy (); +#endif +extern "C" BOOL APIENTRY STransDuplicate (HSTRANS source, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIntersectDirtyArray (HSTRANS sourcemask, + LPBYTE dirtyarray, + BYTE dirtyarraymask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransInvertMask (HSTRANS sourcemask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIsPixelInMask (HSTRANS mask, + int offsetx, + int offsety); +extern "C" BOOL APIENTRY STransLoadE (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransLoadI (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransSetDirtyArrayInfo (int screencx, + int screency, + int cellcx, + int cellcy); +extern "C" BOOL APIENTRY STransUpdateDirtyArray (LPBYTE dirtyarray, + BYTE dirtyvalue, + int destx, + int desty, + HSTRANS transparency, + BOOL tracecontour); + +#ifdef STRANS_USE_INCLUSIVE_RECTS +#define STransCreate STransCreateI +#define STransCreateMask STransCreateMaskI +#define STransLoad STransLoadI +#else +#define STransCreate STransCreateE +#define STransCreateMask STransCreateMaskE +#define STransLoad STransLoadE +#endif + + +/**************************************************************************** +* +* Video functions +* +***/ + +#define SVID_FLAG_DOUBLESCANS 0x00000001 +#define SVID_FLAG_INTERPOLATE 0x00000002 +#define SVID_FLAG_INTERLACE 0x00000004 +#define SVID_FLAG_AUTOQUALITY 0x00000008 +#define SVID_FLAG_1XSIZE 0x00000100 +#define SVID_FLAG_2XSIZE 0x00000200 +#define SVID_FLAG_AUTOSIZE 0x00000800 +#define SVID_FLAG_FILEHANDLE 0x00010000 +#define SVID_FLAG_PRELOAD 0x00020000 +#define SVID_FLAG_LOOP 0x00040000 +#define SVID_FLAG_FULLSCREEN 0x00080000 +#define SVID_FLAG_USECURRENTPALETTE 0x00100000 +#define SVID_FLAG_CLEARSCREEN 0x00200000 +#define SVID_FLAG_NOSKIP 0x00400000 +#define SVID_FLAG_NEEDPAN 0x02000000 +#define SVID_FLAG_NEEDVOLUME 0x04000000 +#define SVID_FLAG_TOSCREEN 0x10000000 +#define SVID_FLAG_TOBUFFER 0x20000000 + +#define SVID_CUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_2XSIZE) +#define SVID_AUTOCUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_AUTOSIZE | SVID_FLAG_AUTOQUALITY) + +#define SVID_QUALITY_LOW_SKIPSCANS SVID_FLAG_2XSIZE +#define SVID_QUALITY_LOW (SVID_FLAG_2XSIZE | SVID_FLAG_DOUBLESCANS) +#define SVID_QUALITY_HIGH_SKIPSCANS (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE) +#define SVID_QUALITY_HIGH (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE | SVID_FLAG_DOUBLESCANS) + +DECLARE_STRICT_HANDLE(HSVIDEO); + +typedef struct _SVIDPALETTEUSE { + DWORD size; + DWORD firstentry; + DWORD numentries; +} SVIDPALETTEUSE, *SVIDPALETTEUSEPTR; + +extern "C" BOOL APIENTRY SVidDestroy (); +extern "C" BOOL APIENTRY SVidGetPerformanceData (HSVIDEO video, + BOOL averageframems, + DWORD *framems, + BOOL averagepalettems, + DWORD *palettems); +extern "C" BOOL APIENTRY SVidGetSize (HSVIDEO video, + int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SVidInitialize (LPVOID directsound); +extern "C" BOOL APIENTRY SVidPlayBegin (LPCTSTR filename, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayBeginFromMemory (LPVOID sourceptr, + DWORD sourcebytes, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayContinue (); +extern "C" BOOL APIENTRY SVidPlayContinueSingle (HSVIDEO video, + BOOL forceupdate, + BOOL *updated); +extern "C" BOOL APIENTRY SVidPlayEnd (HSVIDEO video); +extern "C" BOOL APIENTRY SVidSetVolume (HSVIDEO video, + LONG volume, + LONG pan, + DWORD track = 0); + + +/**************************************************************************** +* +* Storm global functions +* +***/ + +extern "C" BOOL APIENTRY StormDestroy (); + +#ifdef MAC +extern "C" void StormStartup(); +extern "C" void StormShutdown(); +#endif + + +//#########################################################################// +//#########################################################################// +// // +// // +// CLASS-BASED PROGRAMMING INTERFACE // +// (under construction) // +// // +// // +//#########################################################################// +//#########################################################################// + + +/**************************************************************************** +* +* CSLog +* +***/ + +class CSLog { + + private: + HSLOG m_handle; + + public: + + //======================================================================= + CSLog (LPCTSTR filename) { + SLogCreate(filename,0,&m_handle); + } + + //======================================================================= + CSLog (LPCTSTR keyname, + LPCTSTR valuename) { + char filename[MAX_PATH] = ""; + SRegLoadString(keyname,valuename,0,filename,MAX_PATH); +#ifdef _DEBUG + SRegSaveString(keyname,valuename,0,filename); +#endif + if (filename[0]) + SLogCreate(filename,0,&m_handle); + } + + //======================================================================= + ~CSLog () { + SLogClose(m_handle); + } + + //======================================================================= + void Dump (LPCVOID data, + DWORD bytes) { + SLogDump(m_handle, + data, + bytes); + } + + //======================================================================= + void Flush () { + SLogFlush(m_handle); + } + + //======================================================================= + HSLOG GetHandle () { + return m_handle; + } + + //======================================================================= + void Pend (LPCSTR string) { + SLogPend(m_handle, + string); + } + + //======================================================================= + void Write (LPCSTR string) { + SLogWrite(m_handle, + string); + } + +}; + + +/**************************************************************************** +* +* CSRgn +* +***/ + +class CSRgn { + + private: + HSRGN m_handle; + + //======================================================================= + void CopyConstructor (const CSRgn & source) { + SRgnDuplicate(source.m_handle, + &m_handle); + } + + public: + + //======================================================================= + CSRgn () { + SRgnCreate(&m_handle); + } + + //======================================================================= + CSRgn (const CSRgn & source) { + CopyConstructor(source); + } + + //======================================================================= + ~CSRgn () { + SRgnDelete(m_handle); + } + + //======================================================================= + CSRgn & operator= (const CSRgn &source) { + if (this != &source) { + this->~CSRgn(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + void AddParam (LPCRECT rect, + LPVOID param) { + SRgnAddParam(m_handle, + rect, + param); + } + + //======================================================================= + void AddRect (LPCRECT rect, + LPVOID param) { + SRgnAddRect(m_handle, + rect, + param); + } + + //======================================================================= + void Clear () { + SRgnClear(m_handle); + } + + //======================================================================= + void CombineRect (LPCRECT rect, + LPVOID param, + int combinemode) { + SRgnCombineRect(m_handle, + rect, + param, + combinemode); + } + + //======================================================================= + void GetBoundingRect (LPRECT rect) { + SRgnGetBoundingRect(m_handle, + rect); + } + + //======================================================================= + void GetRects (DWORD *numrects, + LPRECT buffer) { + SRgnGetRects(m_handle, + numrects, + buffer); + } + + //======================================================================= + void GetRectParams (LPCRECT rect, + DWORD *numparams, + LPVOID *buffer) { + SRgnGetRectParams(m_handle, + rect, + numparams, + buffer); + } + +}; + + +//#########################################################################// +//#########################################################################// +// // +// // +// UTILITY CLASSES AND TEMPLATES // +// // +// // +//#########################################################################// +//#########################################################################// + + +/**************************************************************************** +* +* CCritSect -- Critical section class +* +* Methods: +* +* void Enter () +* void Leave () +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void Enter () { EnterCriticalSection(&m_critsect); } + void Enter (BOOL) { EnterCriticalSection(&m_critsect); } + void Leave () { LeaveCriticalSection(&m_critsect); } + void Leave (BOOL) { LeaveCriticalSection(&m_critsect); } +}; + + +/**************************************************************************** +* +* CLock -- Reader/writer lock class +* +* Methods: +* +* void Enter (BOOL forwriting) +* void Leave (BOOL fromwriting) +* +***/ + +class CLock { + + private: + + HANDLE m_mutexevent; + HANDLE m_readerevent; + LONG m_readercount; + + public: + + //======================================================================= + CLock () { + m_mutexevent = CreateEvent(NULL,FALSE,TRUE,NULL); + m_readerevent = CreateEvent(NULL,TRUE,FALSE,NULL); + m_readercount = -1; + } + + //======================================================================= + ~CLock () { + CloseHandle(m_readerevent); + CloseHandle(m_mutexevent); + } + + //======================================================================= + void Enter (BOOL forwriting) { + if (forwriting) + WaitForSingleObject(m_mutexevent,INFINITE); + else if (!InterlockedIncrement(&m_readercount)) { + WaitForSingleObject(m_mutexevent,INFINITE); + SetEvent(m_readerevent); + } + else + WaitForSingleObject(m_readerevent,INFINITE); + } + + //======================================================================= + void Leave (BOOL fromwriting) { + if (fromwriting) + SetEvent(m_mutexevent); + else if (InterlockedDecrement(&m_readercount) < 0) { + ResetEvent(m_readerevent); + SetEvent(m_mutexevent); + } + } + +}; + + +/**************************************************************************** +* +* CNullSync -- Null synchronization class +* +* (used for templates that take a synchronization class as a parameter) +* +***/ + +class CNullSync { + public: + void Enter (BOOL) { } + void Leave (BOOL) { } +}; + + +/**************************************************************************** +* +* type_info +* +* (used by templates to obtain the name of an object) +* +***/ + +#ifdef _MSC_VER + #ifdef _INC_TYPEINFO + #define INTERNALRAWNAME raw_name + #else + #define INTERNALRAWNAME internal_raw_name + class type_info { + public: + virtual ~type_info (); + const char * internal_raw_name () const { return _m_d_name; }; + private: + void *_m_data; + char _m_d_name[1]; + type_info (const type_info& rhs); + type_info& operator= (const type_info& rhs); + }; + #endif +#else + #if defined(MAC) && !defined(__typeinfo__) + #include + #endif + #define INTERNALRAWNAME name +#endif + + +/**************************************************************************** +* +* ARRAY -- Dynamically allocated array template +* +* Types: +* +* ARRAY(structname) -- dynamically sized array of struct +* +* Pointers to types: +* +* ARRAYPTR(structname) +* +* Array methods: +* +* void AddDiscontiguousElements (DWORD count, +* int stride, +* const *newelements); +* void AddElement (const *newelement); +* void AddElements (DWORD count, +* const *newelements); +* DWORD NumElements (); +* * NewElement (); +* * Ptr (); +* void ReserveSpace (DWORD count); +* void SetNumElements (DWORD totalcount); +* +***/ + +template +class TSArray { + + private: + DWORD m_allocchunksize; + T *m_data; + DWORD m_elements; + DWORD m_elementsalloc; + + //======================================================================= + BOOL CheckSpace (DWORD count) { + return (m_elements+count <= m_elementsalloc); + } + + //======================================================================= + void Constructor () { + m_allocchunksize = max(16,256/sizeof(T)); + m_data = NULL; + m_elements = 0; + m_elementsalloc = 0; + } + + //======================================================================= + void CopyConstructor (const TSArray & source) { + Constructor(); + m_allocchunksize = source.m_allocchunksize; + ReserveSpace(source.m_elementsalloc); + AddElements(source.m_elements, + source.m_data); + } + + public: + + //======================================================================= + TSArray () { + Constructor(); + } + + //======================================================================= + TSArray (const TSArray & source) { + CopyConstructor(source); + } + + //======================================================================= + ~TSArray () { + if (m_data) { + while (m_elements) { + --m_elements; + m_data[m_elements].~T(); + } + SMemFree(m_data,__FILE__,__LINE__,0); + m_data = NULL; + } + } + + //======================================================================= + TSArray & operator= (const TSArray &source) { + if (this != &source) { + this->~TSArray(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + T & operator[] (DWORD num) { + if (num >= m_elements) + SErrDisplayError(STORM_ERROR_ACCESS_OUT_OF_BOUNDS, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + NULL, + TRUE); + return m_data[num]; + } + + //======================================================================= + void AddDiscontiguousElements (DWORD count, + int stride, + const T *newelements) { + if (!CheckSpace(count)) + ReserveSpace(count); + if (stride == sizeof(T)) + AddElements(count,newelements); + else + for (DWORD loop = 0; loop < count; ++loop) { + new(m_data+m_elements++) T(*newelements); + newelements = (const T *)((LPBYTE)newelements+stride); + } + } + + //======================================================================= + void AddElement (const T *newelement) { + if (!CheckSpace(1)) + ReserveSpace(1); + new(m_data+m_elements++) T(*newelement); + } + + //======================================================================= + void AddElements (DWORD count, + const T *newelements) { + if (!CheckSpace(count)) + ReserveSpace(count); + for (DWORD loop = 0; loop < count; ++loop) + new(m_data+m_elements++) T(newelements[loop]); + } + + //======================================================================= + DWORD NumElements () { + return m_elements; + } + + //======================================================================= + T * NewElement () { + if (!CheckSpace(1)) + ReserveSpace(1); + return new(m_data+m_elements++) T; + } + + //======================================================================= + T * Ptr () { + if (!m_data) + ReserveSpace(1); + return m_data; + } + + //======================================================================= + void ReserveSpace (DWORD count) { + if (CheckSpace(count)) + return; + + // DETERMINE THE NUMBER OF NEW ELEMENTS TO ALLOCATE + DWORD newelements = m_elements+count; + DWORD partialchunk = newelements & (m_allocchunksize-1); + if (partialchunk) + newelements += m_allocchunksize-partialchunk; + + // ALLOCATE THE NEW ARRAY AND COPY DATA FROM THE OLD ARRAY + T *newdata = (T *)ALLOC(newelements*sizeof(T)); + if (m_data) { + for (DWORD loop = 0; loop < m_elements; ++loop) + new(newdata+loop) T(m_data[loop]); + FREE(m_data); + } + m_data = newdata; + m_elementsalloc = newelements; + + } + + //======================================================================= + void SetNumElements (DWORD totalcount) { + if (totalcount > m_elements) { + ReserveSpace(totalcount-m_elements); + for (DWORD loop = m_elements; loop < totalcount; ++loop) + new(m_data+loop) T; + } + else if (totalcount < m_elements) { + for (DWORD loop = totalcount; loop < m_elements; ++loop) + m_data[loop].~T(); + } + m_elements = totalcount; + } + +}; + +#define ARRAY(structname) TSArray< structname > +#define ARRAYDECL(structname,varname) TSArray< structname > varname +#define ARRAYPTR(structname) TSArray< structname > * + + +/**************************************************************************** +* +* NODE/LIST -- Linked list template +* +* Types: +* +* LINKEX(structname) -- explicit link field +* LIST(structname) -- linked list of implicitly linked nodes +* LISTEX(structname,linkname) -- linked list of explicitly linked nodes +* LISTEXDYN(structname) -- linked list of explicitly linked nodes, +* where the link field to be used by +* this list is not known at compile time +* NODEDECL(structname) -- implicitly linked node +* NODEDECLEX(structname) -- explicitly linked node (must contain one +* or more LINKEX fields) +* +* Pointers to types: +* +* LISTPTR(structname) +* LISTPTREX(structname) +* +* Link methods: +* +* * Next (); +* * Prev (); +* void Unlink (); +* +* Explicitly linked node methods: +* +* None. Use link methods for the link you want to manipulate. +* +* Implicitly linked node methods: +* +* * Next (); +* * Prev (); +* void Unlink (); +* +* List methods: +* +* void Clear (); +* * DeleteNode ( *ptr); +* * Head () const; +* BOOL IsEmpty () const; +* void LinkNode ( *ptr, +* DWORD linktype = LIST_TAIL, +* *existingptr = NULL); +* * NewNode (DWORD location = LIST_TAIL, +* DWORD extrabytes = 0, +* DWORD flags = 0); +* * Next (const *ptr) const; +* * Prev (const *ptr) const; +* * Tail () const; +* void UnlinkAll (); +* void UnlinkNode ( *ptr); +* +* Constants for use with LinkNode() and NewNode(): +* +* LIST_UNLINKED +* LIST_LINK_AFTER +* LIST_LINK_BEFORE +* LIST_HEAD +* LIST_TAIL +* +* Macros: +* +* LISTEXSETLINK(structname,listname,linkname) +* ITERATELIST(structname,listname,ptrname) +* ITERATELISTPTR(structname,listname,ptrname) +* ITERATEPARTIALLIST(structname,listname,start,ptrname) +* ITERATEPARTIALLISTPTR(structname,listname,start,ptrname) +* ITERATELISTREVERSE(structname,listname,ptrname) +* ITERATELISTREVERSEPTR(structname,listname,ptrname) +* ITERATEPARTIALLISTREVERSE(structname,listname,start,ptrname) +* ITERATEPARTIALLISTREVERSEPTR(structname,listname,start,ptrname) +* ITERATE_DELETE +* ITERATE_DELETEANDBREAK +* +***/ + +#define LIST_UNLINKED 0 +#define LIST_LINK_AFTER 1 +#define LIST_LINK_BEFORE 2 +#define LIST_HEAD LIST_LINK_AFTER +#define LIST_TAIL LIST_LINK_BEFORE + +template +class TSList; + +template +class TSLink { + friend class TSList; + friend class TSList; + + private: + TSLink *m_prevlink; + T *m_next; + + //======================================================================= + void Constructor () { + m_prevlink = NULL; + m_next = NULL; + } + + //======================================================================= + void CopyConstructor (const TSLink &) { + Constructor(); + } + + //======================================================================= + TSLink *NextLink () const { + + // IF THE NEXT NODE IS A TERMINATOR, ITS LINK POINTER IS THE SAME AS + // ITS NODE POINTER. + if ((int)m_next < 0) + return (TSLink *)~(DWORD)m_next; + + // OTHERWISE, COMPUTE THE LINK ADDRESS BY USING THE OFFSET OF THIS + // NODE'S LINK AND POINTER ADDRESSES. (THIS NODE MUST NOT BE A + // TERMINATOR.) + else { + DWORD linkoffset = (DWORD)this-(DWORD)(m_prevlink->m_next); + return (TSLink *)(linkoffset+(DWORD)m_next); + } + + } + + protected: + + //======================================================================= + T *NextThroughTerminator () const { + return ((int)m_next > 0) ? m_next : (T *)~(DWORD)m_next; + } + + public: + + //======================================================================= + TSLink () { + Constructor(); + } + + //======================================================================= + TSLink (const TSLink & source) { + CopyConstructor(source); + } + + //======================================================================= + ~TSLink () { + Unlink(); + } + + //======================================================================= + TSLink & operator= (const TSLink &) { + // LEAVE THE DESTINATION NODE LINKED INTO ITS CURRENT LIST + return *this; + } + + //======================================================================= + T * Next () const { + return ((int)m_next > 0) ? m_next : NULL; + } + + //======================================================================= + T * Prev () const { + return m_prevlink->m_prevlink->Next(); + } + + //======================================================================= + void Unlink () { + if (!m_prevlink) + return; + NextLink()->m_prevlink = m_prevlink; + m_prevlink->m_next = m_next; + m_prevlink = NULL; + m_next = NULL; + } + +}; + +template +class TSBaseNode { + public: + + //======================================================================= + inline void * __cdecl operator new (size_t bytes, + size_t extra, + DWORD flags) { + void *ptr = SMemAlloc(bytes+extra, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + flags | SMEM_FLAG_ZEROMEMORY); + return ptr; + } + +}; + +template +class TSExplicitNode : public TSBaseNode { + friend class TSList; + + private: + + //======================================================================= + TSLink *Link (BOOL explicitlink, int linkoffset) const { + ASSERT(explicitlink); + explicitlink; + return (TSLink *)((LPBYTE)this+linkoffset); + } + +}; + +template +class TSLinkedNode : public TSBaseNode { + friend class TSList; + + private: + TSLink m_link; + + //======================================================================= + TSLink *Link (BOOL explicitlink, int linkoffset) const { + if (explicitlink) + return (TSLink *)((LPBYTE)this+linkoffset); + else + return (TSLink *)&m_link; + } + + public: + + //======================================================================= + ~TSLinkedNode () { + Unlink(); + } + + //======================================================================= + T * Next () const { + return m_link.Next(); + } + + //======================================================================= + T * Prev () const { + return m_link.Prev(); + } + + //======================================================================= + void Unlink () { + m_link.Unlink(); + } + +}; + +template +class TSList { + + private: + int m_linkoffset; + TSLink m_terminator; + + //======================================================================= + void Constructor () { + m_linkoffset = 0; + InitializeTerminator(); + } + + //======================================================================= + void CopyConstructor (const TSList & source) { + m_linkoffset = source.m_linkoffset; + InitializeTerminator(); + } + + //======================================================================= + void InitializeTerminator () { + m_terminator.m_prevlink = &m_terminator; + m_terminator.m_next = (T *)~(DWORD)&m_terminator; + } + + //======================================================================= + TSLink *Link (const T *ptr) const { + // THIS FUNCTION CALLS THE LINK METHOD IN EITHER THE NODE OR THE LINK + // TO WHICH THIS LIST REFERS. IF THIS FUNCTION WON'T COMPILE, IT'S + // BECAUSE A NODE WITH EXPLICIT LINKS WAS DEFINED WITH NODEDECL() + // INSTEAD OF NODEDECLEX(). + return ptr->Link(explicitlink,m_linkoffset); + } + + protected: + + //======================================================================= + void SetLinkOffset (int linkoffset) { + m_linkoffset = linkoffset; + InitializeTerminator(); + } + + public: + + //======================================================================= + TSList () { + Constructor(); + }; + + //======================================================================= + TSList (const TSList &source) { + CopyConstructor(source); + }; + + //======================================================================= + TSList (int linkoffset) { + m_linkoffset = linkoffset; + InitializeTerminator(); + }; + + //======================================================================= + ~TSList () { + UnlinkAll(); + } + + //======================================================================= + TSList & operator= (const TSList &source) { + if (this != &source) { + this->~TSList(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + void ChangeLinkOffset (int linkoffset) { + UnlinkAll(); + SetLinkOffset(linkoffset); + } + + //======================================================================= + void Clear () { + T *curr; + while ((curr = Head()) != NULL) + delete curr; + } + + //======================================================================= + T * DeleteNode (T *ptr) { + T *nextptr = Next(ptr); + delete ptr; + return nextptr; + } + + //======================================================================= + T * Head () const { + return m_terminator.Next(); + } + + //======================================================================= + BOOL IsEmpty () const { + return !m_terminator.Next(); + } + + //======================================================================= + T * Iterate_RawNext (const T *ptr) const { + return Link(ptr)->m_next; + } + + //======================================================================= + void LinkNode (T *ptr, + DWORD linktype = LIST_TAIL, + T *existingptr = NULL) { + TSLink *link = Link(ptr); + + // IF THIS NODE IS ALREADY LINKED INTO THE LIST, UNLINK IT + if (link->m_prevlink) + link->Unlink(); + + // FIND THE NODE THAT WE WILL LINK BEFORE OR AFTER. USE THE + // TERMINATOR NODE IF WE'RE LINKING ONTO THE HEAD OR TAIL. + TSLink *existinglink; + if (existingptr) + existinglink = Link(existingptr); + else + existinglink = &m_terminator; + + // LINK THIS NODE INTO THE LIST + switch (linktype) { + + case LIST_LINK_AFTER: + { + link->m_prevlink = existinglink; + link->m_next = existinglink->m_next; + Link(existinglink->NextThroughTerminator())->m_prevlink = link; + existinglink->m_next = ptr; + } + break; + + case LIST_LINK_BEFORE: + { + TSLink *prevlink = existinglink->m_prevlink; + link->m_prevlink = prevlink; + link->m_next = prevlink->m_next; + prevlink->m_next = ptr; + existinglink->m_prevlink = link; + } + break; + + } + } + + //======================================================================= + T * NewNode (DWORD location = LIST_TAIL, + DWORD extrabytes = 0, + DWORD flags = 0) { + T *ptr = new(extrabytes,flags) T; + if (location != LIST_UNLINKED) + LinkNode(ptr,location); + return ptr; + } + + //======================================================================= + T * Next (const T *ptr) const { + return Link(ptr)->Next(); + } + + //======================================================================= + T * Prev (const T *ptr) const { + return Link(ptr)->Prev(); + } + + //======================================================================= + T * Tail () const { + return m_terminator.Prev(); + } + + //======================================================================= + void UnlinkAll () { + T *curr; + while ((curr = Head()) != NULL) + UnlinkNode(curr); + } + + //======================================================================= + void UnlinkNode (T *ptr) { + Link(ptr)->Unlink(); + } + +}; + +template +class TSExplicitList : public TSList { + public: + + //======================================================================= + TSExplicitList () { + SetLinkOffset(linkoffset); + } + +}; + + +#define LINKEX(structname) TSLink< structname > +#define LINKDECLEX(structname,varname) TSLink< structname > varname +#define LIST(structname) TSList< structname ,FALSE> +#define LISTDECL(structname,varname) TSList< structname ,FALSE> varname +#define LISTPTR(structname) TSList< structname ,FALSE> * +#define LISTPTREX(structname) TSList< structname ,TRUE> * +#define NODEDECL(structname) typedef struct structname : public TSLinkedNode< structname > +#define NODEDECLEX(structname) typedef struct structname : public TSExplicitNode< structname > + +#define LISTEX(structname,linkname) \ + TSExplicitList< structname ,(int)&(((structname *)0)->linkname)> + +#define LISTEXDYN(structname) \ + TSExplicitList< structname ,(int)0xDDDDDDDD> + +#define LISTEXSETLINK(structname,listname,linkname) \ + listname.ChangeLinkOffset((int)&(((structname *)0)->linkname)); + +#define LISTDECLEX(structname,linkname,varname) \ + TSExplicitList< structname ,(int)&(((structname *)0)->linkname)> varname + +#define ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,op) \ + for (structname *ptrname = start, \ + *iterate_delete = NULL; \ + (int)ptrname > 0; \ + iterate_delete \ + ? (ptrname = (listname)##op##DeleteNode(ptrname), \ + ptrname = ((int)iterate_delete > 0) ? ptrname : NULL, \ + iterate_delete = NULL, \ + ptrname) \ + : ptrname = (listname)##op##Iterate_RawNext(ptrname)) + +#define ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,op) \ + for (structname *ptrname = start, \ + *iterate_delete = NULL, \ + *iterate_delete_temp = NULL; \ + ptrname; \ + iterate_delete \ + ? (iterate_delete_temp = ((int)iterate_delete > 0) \ + ? (listname)##op##Prev(ptrname) \ + : NULL, \ + (listname)##op##DeleteNode(ptrname), \ + iterate_delete = NULL, \ + ptrname = iterate_delete_temp) \ + : ptrname = (listname)##op##Prev(ptrname)) + +#define ITERATELIST(structname,listname,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,(listname).Head(),ptrname,.) + +#define ITERATELISTPTR(structname,listname,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,(listname)->Head(),ptrname,->) + +#define ITERATEPARTIALLIST(structname,listname,start,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,.) + +#define ITERATEPARTIALLISTPTR(structname,listname,start,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,->) + +#define ITERATELISTREVERSE(structname,listname,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,(listname).Tail(),ptrname,.) + +#define ITERATELISTREVERSEPTR(structname,listname,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,(listname)->Tail(),ptrname,->) + +#define ITERATEPARTIALLISTREVERSE(structname,listname,start,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,.) + +#define ITERATEPARTIALLISTREVERSEPTR(structname,listname,start,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,->) + +#define ITERATE_DELETE \ + { \ + ++iterate_delete; \ + continue; \ + } + +#define ITERATE_DELETEANDBREAK \ + { \ + --iterate_delete; \ + continue; \ + } + + +/**************************************************************************** +* +* EXPORTOBJECT/EXPORTTABLE -- Export manager template +* +* Types: +* +* DECLARE_STRICT_HANDLE(handle) -- handle to object +* DECLARE_STRICT_HANDLE(lockedhandle) -- handle to locked object +* EXPORTOBJECTDECL(structname) -- object to be exported +* EXPORTTABLE(structname,handlename,lockedhandlename,synctype) +* EXPORTTABLEREUSE(structname,handlename,lockedhandlename,synctype) +* +* Export table methods: +* +* void Delete ( handle); +* void DeleteUnlock ( *ptr, +* lockedhandle); +* void Destroy (); +* * Lock ( handle, +* *lockedhandle, +* BOOL forwriting = FALSE); +* void New ( *handle); +* * NewLock ( *handle, +* *lockedhandle); +* void Unlock ( lockedhandle); +* +* Synchronization types for use with EXPORTTABLE(): +* +* SYNC_NONE -- use no synchronization +* SYNC_READWRITE -- use a reader/writer lock +* SYNC_ALWAYS -- use a critical section +* +***/ + +template +class TSExportTableBase { + + protected: + + //======================================================================= + T * BaseFindByHandle (LISTPTREX(T) list, unsigned handle) { + ITERATELISTPTR(T,list,curr) + if (curr->m_handle == handle) + return curr; + return NULL; + } + + //======================================================================= + T * BaseFindByHandleEx (LISTPTREX(T) list, unsigned handle, unsigned *count) { + *count = 0; + ITERATELISTPTR(T,list,curr) + if (curr->m_handle == handle) + return curr; + else + ++*count; + return NULL; + } + + //======================================================================= + unsigned BaseGetHandle (const T *ptr) { + return ptr->m_handle; + } + + //======================================================================= + int BaseGetLinkOffset () { + return (int)&(((T *)0)->m_linktoslot); + } + + //======================================================================= + void BaseSetHandle (T *ptr, unsigned handle) { + ptr->m_handle = handle; + } + +}; + +template +class TSExportTable : public TSExportTableBase { + + private: + ARRAY(LISTEXDYN(T)) m_listarray; + LISTEXDYN(T) m_reuselist; + H m_sequence; + unsigned m_slotmask; + SYNC m_sync; + + //======================================================================= + unsigned ComputeSlot (H handle) { + return (unsigned)handle & m_slotmask; + } + + //======================================================================= + H GenerateUniqueHandle () { + unsigned count; + for (;;) { + m_sequence = (H)((unsigned)m_sequence+1); + if (!BaseFindByHandleEx(&m_listarray[ComputeSlot(m_sequence)], + (unsigned)m_sequence, + &count)) + break; + } + if (count >= 4) + GrowListArray(); + return m_sequence; + } + + //======================================================================= + void GrowListArray () { +return; // note: out for testing + if (m_slotmask >= 1023) + return; + + // DETERMINE THE NEW ARRAY SIZE + unsigned oldarraysize = m_slotmask+1; + unsigned newarraysize = oldarraysize*2; + + // GROW THE ARRAY + { + m_listarray.SetNumElements(newarraysize); + int linkoffset = BaseGetLinkOffset(); + for (unsigned slot = oldarraysize; slot < newarraysize; ++slot) + m_listarray[slot].ChangeLinkOffset(linkoffset); + } + + // MOVE ALL RECORDS FROM THE OLD LISTS TO THE NEW LISTS + m_slotmask = newarraysize-1; + { + for (unsigned slot = 0; slot < oldarraysize; ++slot) { + T *currptr = m_listarray[slot].Head(); + while (currptr) { + T *nextptr = m_listarray[slot].Next(currptr); + unsigned newslot = ComputeSlot((H)BaseGetHandle(currptr)); + if (newslot != slot) { + m_listarray[slot].UnlinkNode(currptr); + m_listarray[newslot].LinkNode(currptr); + } + currptr = nextptr; + } + } + } + + } + + //======================================================================= + BOOL IsForWriting (LH lockedhandle) { + return (lockedhandle == (LH)1); + } + + //======================================================================= + void SyncEnterLock (LH *lockedhandle, BOOL forwriting) { + m_sync.Enter(forwriting); + *lockedhandle = (LH)(forwriting ? 1 : -1); + } + + //======================================================================= + void SyncLeaveLock (LH lockedhandle) { + if (lockedhandle) + m_sync.Leave(IsForWriting(lockedhandle)); + } + + public: + + //======================================================================= + TSExportTable () { + m_sequence = (H)0; + m_slotmask = 3; + m_listarray.SetNumElements(m_slotmask+1); + int linkoffset = BaseGetLinkOffset(); + for (unsigned slot = 0; slot <= m_slotmask; ++slot) + m_listarray[slot].ChangeLinkOffset(linkoffset); + m_reuselist.ChangeLinkOffset(linkoffset); + } + + //======================================================================= + ~TSExportTable () { + Destroy(); + } + + //======================================================================= + void Delete (H handle) { + LH lockedhandle; + T *ptr = Lock(handle,&lockedhandle,TRUE); + DeleteUnlock(ptr,lockedhandle); + } + + //======================================================================= + void DeleteUnlock (T *ptr, + LH lockedhandle) { + if (ptr) + if (REUSE) + m_reuselist.LinkNode(ptr); + else + delete ptr; + Unlock(lockedhandle); + } + + //======================================================================= + void Destroy () { + LH lockedhandle; + SyncEnterLock(&lockedhandle,TRUE); + for (unsigned slot = 0; slot <= m_slotmask; ++slot) { + T *curr; + while ((curr = m_listarray[slot].Head()) != NULL) { + delete curr; + SErrReportResourceLeak(typeid(H).INTERNALRAWNAME()); + } + } + m_reuselist.Clear(); + SyncLeaveLock(lockedhandle); + } + + //======================================================================= + T * Lock (H handle, + LH *lockedhandle, + BOOL forwriting = FALSE) { + SyncEnterLock(lockedhandle,forwriting); + T *result = BaseFindByHandle(&m_listarray[ComputeSlot(handle)], + (unsigned)handle); + if (!result) { + SyncLeaveLock(*lockedhandle); + *lockedhandle = (LH)0; + } + return result; + } + + //======================================================================= + void New (H *handle) { + LH lockedhandle; + NewLock(handle,&lockedhandle); + Unlock(lockedhandle); + } + + //======================================================================= + T * NewLock (H *handle, LH *lockedhandle) { + SyncEnterLock(lockedhandle,TRUE); + H newhandle = GenerateUniqueHandle(); + T *ptr = NULL; + if (REUSE) { + ptr = m_reuselist.Head(); + if (ptr) + m_listarray[ComputeSlot(newhandle)].LinkNode(ptr); + } + if (!ptr) + ptr = m_listarray[ComputeSlot(newhandle)].NewNode(); + BaseSetHandle(ptr,(unsigned)newhandle); + *handle = newhandle; + return ptr; + } + + //======================================================================= + void Unlock (LH lockedhandle) { + SyncLeaveLock(lockedhandle); + } + +}; + +template +class TSExportObject : public TSExplicitNode { + friend class TSExportTableBase; + + private: + unsigned m_handle; + LINKEX(T) m_linktoslot; + + public: + + //======================================================================= + TSExportObject () { + } + + //======================================================================= + TSExportObject (const TSExportObject &source) { + } + + //======================================================================= + TSExportObject & operator= (const TSExportObject &source) { + // COPY THE OBJECT DATA, BUT DON'T OVERWRITE THE DESTINATION OBJECT'S + // HANDLE OR LINK + return *this; + } + +}; + +#define SYNC_NONE CNullSync +#define SYNC_READWRITE CLock +#define SYNC_ALWAYS CCritSect + +#define EXPORTOBJECTDECL(structname) \ + typedef struct structname : public TSExportObject< structname > + +#define EXPORTTABLE(structname,handlename,lockedhandlename,synctype) \ + TSExportTable + +#define EXPORTTABLEREUSE(structname,handlename,lockedhandlename,synctype) \ + TSExportTable + + +/**************************************************************************** +* +* SWAP -- Swap template +* +* Macros: +* +* SWAP(a,b) +* +***/ + +//=========================================================================== +template +void inline TSSwap (T &a, T &b) { + T temp = a; + a = b; + b = temp; +} +#define SWAP(a,b) TSSwap(a,b) + + +/**************************************************************************** +* +* Old TList Template -- Obsolete!! +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return FALSE; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return FALSE; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return TRUE; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return FALSE; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return FALSE; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return TRUE; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return FALSE; + + ptr->next = *head; + *head = ptr; + return TRUE; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return FALSE; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return TRUE; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return FALSE; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber,0); + *head = next; + } + return TRUE; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return FALSE; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber,0); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return FALSE; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import off +#endif + +#endif // ifndef _STORM_H_ diff --git a/src/OBJDAT.CPP b/src/OBJDAT.CPP new file mode 100644 index 0000000..937f11d --- /dev/null +++ b/src/OBJDAT.CPP @@ -0,0 +1,624 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Objects file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/OBJDAT.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "objects.h" +#include "objdat.h" +#include "quests.h" + +/*-----------------------------------------------------------------------*/ + +int ObjTypeConv[] = { + 0, + OBJ_LEVER, + OBJ_CRUX1, + OBJ_CRUX2, + OBJ_CRUX3, + OBJ_ANGEL, + OBJ_BANNERL, + OBJ_BANNERM, + OBJ_BANNERR, + OBJ_BLADEL, + OBJ_BLADER, + OBJ_BLOCK, + OBJ_BOOK1L, + OBJ_BOOK1R, + OBJ_BOOK2L, + OBJ_BOOK2R, + OBJ_BCROSS, + OBJ_CANBRA, + OBJ_CANDLE1, + OBJ_CANDLE2, + OBJ_CANDLEO, + OBJ_CAULDRON, + OBJ_CHAINEL, + OBJ_CHAINER, + OBJ_CHAING1L, + OBJ_CHAING1R, + OBJ_CHAING2L, + OBJ_CHAING2R, + OBJ_CHAINLL, + OBJ_CHAINLR, + OBJ_FLAMEHOLE, + OBJ_FTNROUND, + OBJ_FTNL, + OBJ_FTNR, + OBJ_GATEL, + OBJ_GATER, + OBJ_MCIRCLE1, + OBJ_MCIRCLE2, + OBJ_SKFIRE, + OBJ_SKPILE, + OBJ_SKSTICK1, + OBJ_SKSTICK2, + OBJ_SKSTICK3, + OBJ_SKSTICK4, + OBJ_SKSTICK5, + OBJ_SPKTRAP, + OBJ_STEAMTRAP, + OBJ_SWITCHML, + OBJ_SWITCHMR, + OBJ_SWITCHRL, + OBJ_SWITCHRR, + OBJ_SWITCHSKL, + OBJ_SWITCHSKR, + OBJ_TRAPL, + OBJ_TRAPR, + OBJ_TORTURE1, + OBJ_TORTURE2, + OBJ_TORTURE3, + OBJ_TORTURE4, + OBJ_TORTURE5, + OBJ_WATERJUG, + OBJ_TORTURE6R, + OBJ_NUDEW1L, + OBJ_NUDEW1R, + OBJ_NUDEW2L, + OBJ_NUDEW2R, + OBJ_NUDEW8, + OBJ_NUDEMAN1L, + OBJ_NUDEMAN1R, + OBJ_NUDEMAN3, + OBJ_TNUDEM1, + OBJ_TNUDEM2, + OBJ_TNUDEM3, + OBJ_TNUDEM4, + OBJ_TNUDEW1, + OBJ_TNUDEW2, + OBJ_TNUDEW3, + OBJ_CHEST1, + OBJ_CHEST1, + OBJ_CHEST1, + OBJ_CHEST2, + OBJ_CHEST2, + OBJ_CHEST2, + OBJ_CHEST3, + OBJ_CHEST3, + OBJ_CHEST3, + OBJ_DEADSKL, + OBJ_INVPLATE, + OBJ_WOODPLATE, + OBJ_MTLPLATE, + OBJ_STNPLATE, + OBJ_PEDISTAL, + OBJ_ANVIL, + OBJ_FORGE, + OBJ_BIGROCK, + OBJ_ROCK1, + OBJ_ROCK2, + OBJ_ROCK3, + OBJ_ROCK4, + OBJ_STALAG1, + OBJ_STALAG2, + OBJ_STALAG3, + OBJ_STALAG4, + OBJ_STALAG5, + OBJ_ALTGIRL, + OBJ_ALTBOY, + OBJ_TORCH, + OBJ_VILEPORT, + OBJ_WARARMOR, + OBJ_WARWEAP, + OBJ_TORCHR2, + OBJ_TORCHL2, + OBJ_MUSHPATCH, +}; + +/*-----------------------------------------------------------------------*/ + +// Random object, file list index, min level, max level, leveltype, theme number, quest number +// Animates, Anim Delay or Frame, Anim Length, Anim Width, Solid, Missile, Draw with Light, Breakable, Selectable, Trapable +ObjDataStruct AllObjects[] = { + { OBJMUST, 0, 1, 4, 1, -1, -1, // OBJ_L1LIGHT + TRUE, 1, 26, 64, TRUE, TRUE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 1, 1, 4, 1, -1, -1, // OBJ_L1DOORL + FALSE, 1, 0, 64, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, TRUE }, + + { OBJMUST, 1, 1, 4, 1, -1, -1, // OBJ_L1DOORR + FALSE, 2, 0, 64, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, TRUE }, + + { OBJTHEME, 7, 0, 0, 0, 3, -1, // OBJ_SKFIRE + TRUE, 2, 11, 96, TRUE, TRUE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 2, 1, 4, 1, -1, -1, // OBJ_LEVER + FALSE, 1, 1, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJMUST, 3, 1, 16, 0, -1, -1, // OBJ_CHEST1 + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJMUST, 4, 1, 16, 0, -1, -1, // OBJ_CHEST2 + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJMUST, 16, 1, 16, 0, -1, -1, // OBJ_CHEST3 + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJNO, 0, 0, 0, 0, -1, -1, // OBJ_CANDLE1 + FALSE, 0, 0, 0, FALSE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJTHEME, 18, 0, 0, 0, 1, -1, // OBJ_CANDLE2 + TRUE, 2, 4, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 0, 0, 0, 0, -1, -1, // OBJ_CANDLEO + FALSE, 0, 0, 0, FALSE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJTHEME, 5, 0, 0, 0, 3, -1, // OBJ_BANNERL + FALSE, 2, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJTHEME, 5, 0, 0, 0, 3, -1, // OBJ_BANNERM + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJTHEME, 5, 0, 0, 0, 3, -1, // OBJ_BANNERR + FALSE, 3, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 6, 1, 4, 0, -1, -1, // OBJ_SKPILE + FALSE, 0, 1, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 0, 0, 0, 0, -1, -1, // OBJ_SKSTICK1 + FALSE, 0, 0, 0, FALSE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 0, 0, 0, 0, -1, -1, // OBJ_SKSTICK2 + FALSE, 0, 0, 0, FALSE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 0, 0, 0, 0, -1, -1, // OBJ_SKSTICK3 + FALSE, 0, 0, 0, FALSE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 0, 0, 0, 0, -1, -1, // OBJ_SKSTICK4 + FALSE, 0, 0, 0, FALSE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 0, 0, 0, 0, -1, -1, // OBJ_SKSTICK5 + FALSE, 0, 0, 0, FALSE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 9, 0, 0, 0, -1, -1, // OBJ_CRUX1 + FALSE, 1, 15, 96, TRUE, FALSE, TRUE, OBJ_BREAKABLE, OSEL_ALL, FALSE }, + + { OBJNO, 10, 0, 0, 0, -1, -1, // OBJ_CRUX2 + FALSE, 1, 15, 96, TRUE, FALSE, TRUE, OBJ_BREAKABLE, OSEL_ALL, FALSE }, + + { OBJNO, 11, 0, 0, 0, -1, -1, // OBJ_CRUX3 + FALSE, 1, 15, 96, TRUE, FALSE, TRUE, OBJ_BREAKABLE, OSEL_ALL, FALSE }, + + { OBJMUST, 14, 5, 5, 0, -1, -1, // OBJ_STAND + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 15, 0, 0, 0, -1, -1, // OBJ_ANGEL + FALSE, 1, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 13, 0, 0, 0, -1, -1, // OBJ_BOOK2L + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJNO, 17, 0, 0, 0, -1, -1, // OBJ_BCROSS + TRUE, 0, 10, 160, TRUE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 19, 0, 0, 0, -1, -1, // OBJ_NUDEW2R + TRUE, 3, 6, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 20, 16, 16, 0, -1, -1, // OBJ_SWITCHSKL + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJMUST, 21, 13, 16, 0, -1, Q_BUTCHER, // OBJ_TNUDEM1 + FALSE, 1, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 21, 13, 16, 0, 6, Q_BUTCHER, // OBJ_TNUDEM2 + FALSE, 2, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 21, 13, 16, 0, 6, Q_BUTCHER, // OBJ_TNUDEM3 + FALSE, 3, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 21, 13, 16, 0, 6, Q_BUTCHER, // OBJ_TNUDEM4 + FALSE, 4, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 22, 13, 16, 0, 6, Q_BUTCHER, // OBJ_TNUDEW1 + FALSE, 1, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 22, 13, 16, 0, 6, Q_BUTCHER, // OBJ_TNUDEW2 + FALSE, 2, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 22, 13, 16, 0, 6, Q_BUTCHER, // OBJ_TNUDEW3 + FALSE, 3, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 23, 13, 16, 0, -1, Q_BUTCHER, // OBJ_TORTURE1 + FALSE, 1, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 23, 13, 16, 0, -1, Q_BUTCHER, // OBJ_TORTURE2 + FALSE, 2, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 23, 13, 16, 0, -1, Q_BUTCHER, // OBJ_TORTURE3 + FALSE, 3, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 23, 13, 16, 0, -1, Q_BUTCHER, // OBJ_TORTURE4 + FALSE, 4, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 23, 13, 16, 0, -1, Q_BUTCHER, // OBJ_TORTURE5 + FALSE, 5, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 13, 6, 6, 0, -1, -1, // OBJ_BOOK2R + FALSE, 4, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 24, 5, 8, 2, -1, -1, // OBJ_L2DOORL + FALSE, 1, 0, 64, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, TRUE }, + + { OBJMUST, 24, 5, 8, 2, -1, -1, // OBJ_L2DOORR + FALSE, 2, 0, 64, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, TRUE }, + + { OBJMUST, 25, 5, 8, 2, -1, -1, // OBJ_TORCHL + TRUE, 1, 9, 96, FALSE, TRUE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 26, 5, 8, 2, -1, -1, // OBJ_TORCHR + TRUE, 1, 9, 96, FALSE, TRUE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 33, 5, 8, 2, -1, -1, // OBJ_TORCHL2 + TRUE, 1, 9, 96, FALSE, TRUE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 32, 5, 8, 2, -1, -1, // OBJ_TORCHR2 + TRUE, 1, 9, 96, FALSE, TRUE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 27, 1, 4, 1, -1, -1, // OBJ_SARC + FALSE, 1, 5, 128, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, TRUE }, + + { OBJNO, 28, 1, 4, 1, -1, -1, // OBJ_FLAMEHOLE + FALSE, 1, 20, 96, FALSE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 2, 1, 4, 1, -1, -1, // OBJ_FLAMELVR + FALSE, 1, 2, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJNO, 31, 1, 4, 1, -1, -1, // OBJ_WATER + TRUE, 1, 10, 64, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 12, 3, 4, 1, -1, -1, // OBJ_BOOKLVR + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 30, 1, 16, 0, -1, -1, // OBJ_TRAPL + FALSE, 1, 0, 64, FALSE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 30, 1, 16, 0, -1, -1, // OBJ_TRAPR + FALSE, 2, 0, 64, FALSE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 34, 0, 0, 0, -1, -1, // OBJ_BOOKSHELF + FALSE, 1, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 36, 0, 0, 0, -1, -1, // OBJ_WEAPRACK + FALSE, 1, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 37, 1, 16, 0, -1, -1, // OBJ_BARREL + FALSE, 1, 9, 96, TRUE, TRUE, TRUE, OBJ_BREAKABLE, OSEL_ALL, FALSE }, + + { OBJMUST, 38, 1, 16, 0, -1, -1, // OBJ_BARRELEX + FALSE, 1, 10, 96, TRUE, TRUE, TRUE, OBJ_BREAKABLE, OSEL_ALL, FALSE }, + + { OBJTHEME, 39, 0, 0, 0, 1, -1, // OBJ_SHRINEL + FALSE, 1, 11, 128, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 40, 0, 0, 0, 1, -1, // OBJ_SHRINER + FALSE, 1, 11, 128, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 13, 0, 0, 0, 3, -1, // OBJ_SKELBOOK + FALSE, 4, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 34, 0, 0, 0, 5, -1, // OBJ_BOOKCASEL + FALSE, 3, 0, 96, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 34, 0, 0, 0, 5, -1, // OBJ_BOOKCASER + FALSE, 4, 0, 96, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 13, 0, 0, 0, 5, -1, // OBJ_BOOKSTAND + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 18, 0, 0, 0, 5, -1, // OBJ_BOOKCANDLE + TRUE, 2, 4, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJTHEME, 41, 0, 0, 0, 7, -1, // OBJ_BLOODFTN + TRUE, 2, 10, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 42, 13, 16, 0, 8, -1, // OBJ_DECAP + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, FALSE }, + + { OBJMUST, 3, 1, 16, 0, -1, -1, // OBJ_TCHEST1 + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJMUST, 4, 1, 16, 0, -1, -1, // OBJ_TCHEST2 + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJMUST, 16, 1, 16, 0, -1, -1, // OBJ_TCHEST3 + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + + { OBJMUST, 12, 7, 7, 2, -1, Q_BLIND, // OBJ_BLINDBOOK + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 12, 5, 5, 2, -1, Q_BLOOD, // OBJ_BLOODBOOK + FALSE, 4, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 43, 5, 5, 2, -1, Q_BLOOD, // OBJ_PEDISTAL + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 44, 9, 12, 3, -1, -1, // OBJ_L3DOORL + FALSE, 1, 0, 64, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, TRUE }, + + { OBJMUST, 44, 9, 12, 3, -1, -1, // OBJ_L3DOORR + FALSE, 2, 0, 64, FALSE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, TRUE }, + + { OBJTHEME, 45, 0, 0, 0, 9, -1, // OBJ_PURIFYINGFTN + TRUE, 2, 10, 128, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 46, 0, 0, 0, 10, -1, // OBJ_ARMORSTAND + FALSE, 1, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 46, 0, 0, 0, 10, -1, // OBJ_ARMORSTANDN + FALSE, 2, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJTHEME, 47, 0, 0, 0, 11, -1, // OBJ_GOATSHRINE + TRUE, 2, 10, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 48, 13, 16, 0, -1, -1, // OBJ_CAULDRON + FALSE, 1, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 49, 0, 0, 0, 13, -1, // OBJ_MURKYFTN + TRUE, 2, 10, 128, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJTHEME, 50, 0, 0, 0, 14, -1, // OBJ_TEARFTN + TRUE, 2, 4, 128, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 51, 0, 0, 1, -1, Q_BETRAYER, // OBJ_ALTBOY + FALSE, 1, 0, 128, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 52, 0, 0, 1, -1, Q_BETRAYER, // OBJ_MCIRCLE1 + FALSE, 1, 0, 96, FALSE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 52, 0, 0, 1, -1, Q_BETRAYER, // OBJ_MCIRCLE2 + FALSE, 1, 0, 96, FALSE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 53, 1, 24, 0, -1, -1, // OBJ_STORYBOOK + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, // change 24 back to 12 JKE + + { OBJMUST, 18, 2, 12, 0, -1, 15, // OBJ_STORYCANDLE + TRUE, 2, 4, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJMUST, 12, 13, 13, 4, -1, Q_WARLORD, // OBJ_STEELTOME + FALSE, 4, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 46, 13, 13, 0, -1, Q_WARLORD, // OBJ_WARARMOR + FALSE, 1, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJNO, 36, 13, 13, 0, -1, Q_WARLORD, // OBJ_WARWEAP + FALSE, 1, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJNO, 17, 0, 0, 0, 15, -1, // OBJ_TBCROSS + TRUE, 0, 10, 160, TRUE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 36, 0, 0, 0, 16, -1, // OBJ_WEAPONRACK + FALSE, 1, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJNO, 36, 0, 0, 0, 16, -1, // OBJ_WEAPONRACKN + FALSE, 2, 0, 96, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_NONE, FALSE }, + + { OBJNO, 54, 0, 0, 0, -1, 1, // OBJ_MUSHPATCH + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_ALL, TRUE }, + + { OBJNO, 55, 0, 0, 0, -1, 15, // OBJ_LAZSTAND + FALSE, 1, 0, 128, TRUE, FALSE, TRUE, OBJ_NOBREAK, OSEL_ALL, FALSE }, + + { OBJMUST, 42, 9, 9, 3, -1, -1, // OBJ_SLAINHERO + FALSE, 2, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, FALSE }, + + { OBJNO, 16, 0, 0, 0, -1, -1, // OBJ_SIGNCHEST + FALSE, 1, 0, 96, TRUE, TRUE, TRUE, OBJ_NOBREAK, OSEL_FLR, TRUE }, + +// Random object, file list index, min level, max level, leveltype, theme number, quest number +// Animates, Anim Delay or Frame, Anim Length, Anim Width, Solid, Missile, Draw with Light, Breakable, Selectable, Trapable + + // Stopper + { -1, 0, 0, 0, -1, -1, -1, FALSE, 0, 0, 0, FALSE, FALSE, FALSE, OBJ_NOBREAK, OSEL_NONE, FALSE } +}; + +/*-----------------------------------------------------------------------*/ + +char *ObjMasterFList[] = { + "L1Braz", // 0 + "L1Doors", // 1 + "Lever", // 2 + "Chest1", // 3 + "Chest2", // 4 + "Banner", // 5 + "SkulPile", // 6 + "SkulFire", // 7 + "SkulStik", // 8 + "CruxSk1", // 9 + "CruxSk2", // 10 + "CruxSk3", // 11 + "Book1", // 12 + "Book2", // 13 + "Rockstan", // 14 + "Angel", // 15 + "Chest3", // 16 + "Burncros", // 17 + "Candle2", // 18 + "Nude2", // 19 + "Switch4", // 20 + "TNudeM", // 21 + "TNudeW", // 22 + "TSoul", // 23 + "L2Doors", // 24 + "WTorch4", // 25 + "WTorch3", // 26 + "Sarc", // 27 + "Flame1", // 28 + "Prsrplt1", // 29 + "Traphole", // 30 + "MiniWatr", // 31 + "WTorch2", // 32 + "WTorch1", // 33 + "BCase", // 34 + "BShelf", // 35 + "WeapStnd", // 36 + "Barrel", // 37 + "Barrelex", // 38 + "LShrineG", // 39 + "RShrineG", // 40 + "Bloodfnt", // 41 + "Decap", // 42 + "Pedistl", // 43 + "L3Doors", // 44 + "PFountn", // 45 + "Armstand", // 46 + "Goatshrn", // 47 + "Cauldren", // 48 + "MFountn", // 49 + "TFountn", // 50 + "Altboy", // 51 + "Mcirl", // 52 + "Bkslbrnt", // 53 + "Mushptch", // 54 + "LzStand", // 55 +}; + +char *CObjMasterFList[] = { + "L1Braz", // 0 + "L5Door", // 1 + "L5Lever", // 2 + "Chest1", // 3 + "Chest2", // 4 + "Banner", // 5 + "SkulPile", // 6 + "SkulFire", // 7 + "SkulStik", // 8 + "CruxSk1", // 9 + "CruxSk2", // 10 + "CruxSk3", // 11 + "Book1", // 12 + "Book2", // 13 + "Rockstan", // 14 + "Angel", // 15 + "Chest3", // 16 + "Burncros", // 17 + "L5Light", // 18 + "Nude2", // 19 + "Switch4", // 20 + "TNudeM", // 21 + "TNudeW", // 22 + "TSoul", // 23 + "L2Doors", // 24 + "WTorch4", // 25 + "WTorch3", // 26 + "L5Sarco", // 27 + "Flame1", // 28 + "Prsrplt1", // 29 + "Traphole", // 30 + "MiniWatr", // 31 + "WTorch2", // 32 + "WTorch1", // 33 + "BCase", // 34 + "BShelf", // 35 + "WeapStnd", // 36 + "Urn", // 37 + "Urnexpld", // 38 + "LShrineG", // 39 + "RShrineG", // 40 + "Bloodfnt", // 41 + "Decap", // 42 + "Pedistl", // 43 + "L3Doors", // 44 + "PFountn", // 45 + "Armstand", // 46 + "Goatshrn", // 47 + "Cauldren", // 48 + "MFountn", // 49 + "TFountn", // 50 + "Altboy", // 51 + "Mcirl", // 52 + "L5Books", // 53 + "Mushptch", // 54 + "LzStand", // 55 +}; + +char *HObjMasterFList[] = { + "L1Braz", // 0 + "L1Doors", // 1 + "Lever", // 2 + "Chest1", // 3 + "Chest2", // 4 + "Banner", // 5 + "SkulPile", // 6 + "SkulFire", // 7 + "SkulStik", // 8 + "CruxSk1", // 9 + "CruxSk2", // 10 + "CruxSk3", // 11 + "Book1", // 12 + "Book2", // 13 + "Rockstan", // 14 + "Angel", // 15 + "Chest3", // 16 + "Burncros", // 17 + "Candle2", // 18 + "Nude2", // 19 + "Switch4", // 20 + "TNudeM", // 21 + "TNudeW", // 22 + "TSoul", // 23 + "L2Doors", // 24 + "WTorch4", // 25 + "WTorch3", // 26 + "Sarc", // 27 + "Flame1", // 28 + "Prsrplt1", // 29 + "Traphole", // 30 + "MiniWatr", // 31 + "WTorch2", // 32 + "WTorch1", // 33 + "BCase", // 34 + "BShelf", // 35 + "WeapStnd", // 36 + "L6Pod1", // 37 + "L6Pod2", // 38 + "LShrineG", // 39 + "RShrineG", // 40 + "Bloodfnt", // 41 + "Decap", // 42 + "Pedistl", // 43 + "L3Doors", // 44 + "PFountn", // 45 + "Armstand", // 46 + "Goatshrn", // 47 + "Cauldren", // 48 + "MFountn", // 49 + "TFountn", // 50 + "Altboy", // 51 + "Mcirl", // 52 + "Bkslbrnt", // 53 + "Mushptch", // 54 + "LzStand", // 55 +}; + + diff --git a/src/OBJDAT.H b/src/OBJDAT.H new file mode 100644 index 0000000..ead2ebb --- /dev/null +++ b/src/OBJDAT.H @@ -0,0 +1,183 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/OBJDAT.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXOBJFILES 56 + +#define OBJ_L1LIGHT 0 +#define OBJ_L1DOORL 1 +#define OBJ_L1DOORR 2 +#define OBJ_SKFIRE 3 +#define OBJ_LEVER 4 +#define OBJ_CHEST1 5 +#define OBJ_CHEST2 6 +#define OBJ_CHEST3 7 +#define OBJ_CANDLE1 8 +#define OBJ_CANDLE2 9 +#define OBJ_CANDLEO 10 +#define OBJ_BANNERL 11 +#define OBJ_BANNERM 12 +#define OBJ_BANNERR 13 +#define OBJ_SKPILE 14 +#define OBJ_SKSTICK1 15 +#define OBJ_SKSTICK2 16 +#define OBJ_SKSTICK3 17 +#define OBJ_SKSTICK4 18 +#define OBJ_SKSTICK5 19 +#define OBJ_CRUX1 20 +#define OBJ_CRUX2 21 +#define OBJ_CRUX3 22 +#define OBJ_STAND 23 +#define OBJ_ANGEL 24 +#define OBJ_BOOK2L 25 +#define OBJ_BCROSS 26 +#define OBJ_NUDEW2R 27 +#define OBJ_SWITCHSKL 28 +#define OBJ_TNUDEM1 29 +#define OBJ_TNUDEM2 30 +#define OBJ_TNUDEM3 31 +#define OBJ_TNUDEM4 32 +#define OBJ_TNUDEW1 33 +#define OBJ_TNUDEW2 34 +#define OBJ_TNUDEW3 35 +#define OBJ_TORTURE1 36 +#define OBJ_TORTURE2 37 +#define OBJ_TORTURE3 38 +#define OBJ_TORTURE4 39 +#define OBJ_TORTURE5 40 +#define OBJ_BOOK2R 41 +#define OBJ_L2DOORL 42 +#define OBJ_L2DOORR 43 +#define OBJ_TORCHL 44 +#define OBJ_TORCHR 45 +#define OBJ_TORCHL2 46 +#define OBJ_TORCHR2 47 +#define OBJ_SARC 48 +#define OBJ_FLAMEHOLE 49 +#define OBJ_FLAMELVR 50 +#define OBJ_WATER 51 +#define OBJ_BOOKLVR 52 +#define OBJ_TRAPL 53 +#define OBJ_TRAPR 54 +#define OBJ_BOOKSHELF 55 +#define OBJ_WEAPRACK 56 +#define OBJ_BARREL 57 +#define OBJ_BARRELEX 58 +#define OBJ_SHRINEL 59 +#define OBJ_SHRINER 60 +#define OBJ_SKELBOOK 61 +#define OBJ_BOOKCASEL 62 +#define OBJ_BOOKCASER 63 +#define OBJ_BOOKSTAND 64 +#define OBJ_BOOKCANDLE 65 +#define OBJ_BLOODFTN 66 +#define OBJ_DECAP 67 +#define OBJ_TCHEST1 68 +#define OBJ_TCHEST2 69 +#define OBJ_TCHEST3 70 +#define OBJ_BLINDBOOK 71 +#define OBJ_BLOODBOOK 72 +#define OBJ_PEDISTAL 73 +#define OBJ_L3DOORL 74 +#define OBJ_L3DOORR 75 +#define OBJ_PURIFYINGFTN 76 +#define OBJ_ARMORSTAND 77 +#define OBJ_ARMORSTANDN 78 +#define OBJ_GOATSHRINE 79 +#define OBJ_CAULDRON 80 +#define OBJ_MURKYFTN 81 +#define OBJ_TEARFTN 82 +#define OBJ_ALTBOY 83 +#define OBJ_MCIRCLE1 84 +#define OBJ_MCIRCLE2 85 +#define OBJ_STORYBOOK 86 +#define OBJ_STORYCANDLE 87 +#define OBJ_STEELTOME 88 +#define OBJ_WARARMOR 89 +#define OBJ_WARWEAP 90 +#define OBJ_TBCROSS 91 +#define OBJ_WEAPONRACK 92 +#define OBJ_WEAPONRACKN 93 +#define OBJ_MUSHPATCH 94 +#define OBJ_LAZSTAND 95 +#define OBJ_SLAINHERO 96 +#define OBJ_SIGNCHEST 97 + +// These are not used yet, so their numbers are not relevent +#define OBJ_BLADEL 0 +#define OBJ_BLADER 0 +#define OBJ_BLOCK 0 +#define OBJ_BOOK1L 0 +#define OBJ_BOOK1R 0 +#define OBJ_CANBRA 0 +#define OBJ_CHAINEL 0 +#define OBJ_CHAINER 0 +#define OBJ_CHAING1L 0 +#define OBJ_CHAING1R 0 +#define OBJ_CHAING2L 0 +#define OBJ_CHAING2R 0 +#define OBJ_CHAINLL 0 +#define OBJ_CHAINLR 0 +#define OBJ_FTNROUND 0 +#define OBJ_FTNL 0 +#define OBJ_FTNR 0 +#define OBJ_GATEL 0 +#define OBJ_GATER 0 +#define OBJ_SPKTRAP 0 +#define OBJ_STEAMTRAP 0 +#define OBJ_SWITCHML 0 +#define OBJ_SWITCHMR 0 +#define OBJ_SWITCHRL 0 +#define OBJ_SWITCHRR 0 +#define OBJ_SWITCHSKR 0 +#define OBJ_WATERJUG 0 +#define OBJ_TORTURE6R 0 +#define OBJ_NUDEW1L 0 +#define OBJ_NUDEW1R 0 +#define OBJ_NUDEW2L 0 +#define OBJ_NUDEW8 0 +#define OBJ_NUDEMAN1L 0 +#define OBJ_NUDEMAN1R 0 +#define OBJ_NUDEMAN3 0 +#define OBJ_VAPOR 0 +#define OBJ_DEADSKL 0 +#define OBJ_INVPLATE 0 +#define OBJ_WOODPLATE 0 +#define OBJ_MTLPLATE 0 +#define OBJ_STNPLATE 0 +#define OBJ_ANVIL 0 +#define OBJ_FORGE 0 +#define OBJ_BIGROCK 0 +#define OBJ_ROCK1 0 +#define OBJ_ROCK2 0 +#define OBJ_ROCK3 0 +#define OBJ_ROCK4 0 +#define OBJ_STALAG1 0 +#define OBJ_STALAG2 0 +#define OBJ_STALAG3 0 +#define OBJ_STALAG4 0 +#define OBJ_STALAG5 0 +#define OBJ_ALTGIRL 0 +#define OBJ_TORCH 0 +#define OBJ_VILEPORT 0 + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern int ObjTypeConv[]; +extern ObjDataStruct AllObjects[]; +extern ObjDataStruct QuestObjects[]; +extern char *ObjMasterFList[]; +extern char *HObjMasterFList[]; +extern char *CObjMasterFList[]; diff --git a/src/OBJECTS.CPP b/src/OBJECTS.CPP new file mode 100644 index 0000000..b11fc8e --- /dev/null +++ b/src/OBJECTS.CPP @@ -0,0 +1,5865 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Objects file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/OBJECTS.CPP 5 2/12/97 10:51a Dbrevik2 $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ +#include + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "objects.h" +#include "objdat.h" +#include "engine.h" +#include "gendung.h" +#include "lighting.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "monstint.h" +#include "control.h" +#include "cursor.h" +#include "spells.h" +#include "minitext.h" +#include "textdat.h" +#include "quests.h" +#include "drlg_l1.h" +#include "missiles.h" +#include "misdat.h" +#include "effects.h" +#include "themes.h" +#include "itemdat.h" +#include "stores.h" +#include "monstdat.h" +#include "error.h" +#include "msg.h" +#include "multi.h" +#include "automap.h" +#include "drlg_l4.h" +#include "towners.h" +#include "inv.h" +#include "setmaps.h" + +/*-----------------------------------------------------------------------* +** Externs +**-----------------------------------------------------------------------*/ +int ObjIndex(int x, int y); +static bool OperateFountains(int, int); + +/*-----------------------------------------------------------------------* +** Local Defines +**-----------------------------------------------------------------------*/ + +//#define NO_L5_DOORS // JKE just until I get doors. + +#define DOOR_CLOSED 0 +#define DOOR_OPEN 1 +#define DOOR_BLOCKED 2 + +#define TRAP_NODIR 0 +#define TRAP_HORIZ 1 +#define TRAP_VERT 2 + +#define TOTAL_FOUNTAINS 4 + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +ObjectStruct object[MAXOBJECTS]; +long numobjects; + +static char ObjFileList[MAXLVLOBJS]; +static int numobjfiles = 0; +static BYTE *pObjCels[MAXLVLOBJS]; + +int objectactive[MAXOBJECTS]; +int objectavail[MAXOBJECTS]; + +static int trapid; +static int trapdir; + +static int leverid; + +BOOL InitObjFlag; //True while initing, false otherwise + +static int const bxadd[] = { -1, 0, 1, -1, 1, -1, 0, 1 }; +static int const byadd[] = { -1, -1, -1, 0, 0, 1, 1, 1 }; + +int SpellProgress; + +#if CHEATS +extern BOOL itemcheat; +extern BOOL uniqcheat; +#endif + +/*-----------------------------------------------------------------------* +** Function Prototypes +**-----------------------------------------------------------------------*/ +void AddMushPatch(); +void AddSlainHero(); +void AddSkulkenObject(int, int, int, int); +static void AddNa_Krul_Stuff(); +void OpenNaKrul(); +static void AddNaKrulLeverObj(); +static bool HCheckSpell(int); + +/*-----------------------------------------------------------------------*/ +// Shrine Data + + +// Shrine names +static char const * const shrinestrs[] = { + "Mysterious", // 0 + "Hidden", // 1 + "Gloomy", // 2 + "Weird", // 3 + "Magical", // 4 + "Stone", // 5 + "Religious", // 6 + "Enchanted", // 7 + "Thaumaturgic", // 8 + "Fascinating", // 9 + "Cryptic", // 10 + "Magical", // 11 + "Eldritch", // 12 + "Eerie", // 13 + "Divine", // 14 + "Holy", // 15 + "Sacred", // 16 + "Spiritual", // 17 + "Spooky", // 18 + "Abandoned", // 19 + "Creepy", // 20 + "Quiet", // 21 + "Secluded", // 22 + "Ornate", // 23 + "Glimmering", // 24 + "Tainted", // 25 + "Oily", // 26 + "Glowing", // 27 + "Mendicant's", // 28 + "Sparkling", // 29 + "Town", // 30 + "Shimmering", // 31 + "Solar", // 33 + "Murphy's", // 34 +}; +#define NUMSHRINETYPES (sizeof(shrinestrs)/sizeof(char *)) + +// Shrine min level it can appear +static char const shrineminlvl[NUMSHRINETYPES] = { + 1, // 0 Mysterious + 1, // 1 Hidden + 1, // 2 Gloomy + 1, // 3 Weird + 1, // 4 Magical + 1, // 5 Stone + 1, // 6 Religious + 1, // 7 Enchanted + 1, // 8 Thaumaturgic + 1, // 9 Fascinating + 1, // 10 Cryptic + 1, // 11 Supernatural + 1, // 12 Eldritch + 1, // 13 Eerie + 1, // 14 Divine + 1, // 15 Holy + 1, // 16 Sacred + 1, // 17 Spiritual + 1, // 18 Spooky + 1, // 19 Abandoned + 1, // 20 Creepy + 1, // 21 Quiet + 1, // 22 Secluded + 1, // 23 Ornate + 1, // 24 Glimmering + 1, // 25 Tainted + 1, // 26 Oily + 1, // 27 Glowing + 1, // 28 Mendicants + 1, // 29 Edisons + 1, // 30 Town + 1, // 31 Energy + 1, // 32 Solar + 1, // 33 Murphy's +}; + +// Shrine max level it can appear +static char const shrinemaxlvl[NUMSHRINETYPES] = { + MAX_LEVELS, // 0 Mysterious + MAX_LEVELS, // 1 Hidden + MAX_LEVELS, // 2 Gloomy + MAX_LEVELS, // 3 Weird + MAX_LEVELS, // 4 Magical + MAX_LEVELS, // 5 Stone + MAX_LEVELS, // 6 Religious + 8, // 7 Enchanted + MAX_LEVELS, // 8 Thaumaturgic + MAX_LEVELS, // 9 Fascinating + MAX_LEVELS, // 10 Cryptic + MAX_LEVELS, // 11 Supernatural + MAX_LEVELS, // 12 Eldritch + MAX_LEVELS, // 13 Eerie + MAX_LEVELS, // 14 Divine + MAX_LEVELS, // 15 Holy + MAX_LEVELS, // 16 Sacred + MAX_LEVELS, // 17 Spiritual + MAX_LEVELS, // 18 Spooky + MAX_LEVELS, // 19 Abandoned + MAX_LEVELS, // 20 Creepy + MAX_LEVELS, // 21 Quiet + MAX_LEVELS, // 22 Secluded + MAX_LEVELS, // 23 Ornate + MAX_LEVELS, // 24 Glimmering + MAX_LEVELS, // 25 Tainted + MAX_LEVELS, // 26 Oily + MAX_LEVELS, // 27 Glowing + MAX_LEVELS, // 28 Mendicants + MAX_LEVELS, // 29 Edisons + MAX_LEVELS, // 30 Town + MAX_LEVELS, // 31 Energy + MAX_LEVELS, // 32 Solar + MAX_LEVELS, // 33 Murphy's +}; + +#define SHRINE_ALL 0 +#define SHRINE_SINGLE 1 +#define SHRINE_MULTI 2 + +// Shrine available for either, single, or multiplayer? +static char const shrineavail[NUMSHRINETYPES] = { + SHRINE_ALL, // 0 Mysterious + SHRINE_ALL, // 1 Hidden + SHRINE_SINGLE, // 2 Gloomy + SHRINE_SINGLE, // 3 Weird + SHRINE_ALL, // 4 Magical + SHRINE_ALL, // 5 Stone + SHRINE_ALL, // 6 Religious + SHRINE_ALL, // 7 Enchanted + SHRINE_SINGLE, // 8 Thaumaturgic + SHRINE_ALL, // 9 Fascinating + SHRINE_ALL, // 10 Cryptic + SHRINE_ALL, // 11 Supernatural + SHRINE_ALL, // 12 Eldritch + SHRINE_ALL, // 13 Eerie + SHRINE_ALL, // 14 Divine + SHRINE_ALL, // 15 Holy + SHRINE_ALL, // 16 Sacred + SHRINE_ALL, // 17 Spiritual + SHRINE_MULTI, // 18 Spooky + SHRINE_ALL, // 19 Abandoned + SHRINE_ALL, // 20 Creepy + SHRINE_ALL, // 21 Quiet + SHRINE_ALL, // 22 Secluded + SHRINE_ALL, // 23 Ornate + SHRINE_ALL, // 24 Glimmering + SHRINE_MULTI, // 25 Tainted + SHRINE_ALL, // 26 Oily + SHRINE_ALL, // 27 Glowing + SHRINE_ALL, // 28 Mendicants + SHRINE_ALL, // 29 Edisons + SHRINE_ALL, // 30 Town + SHRINE_ALL, // 31 Energy + SHRINE_SINGLE, // 32 Solar + SHRINE_ALL, // 33 Murphy's +}; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static char const * const StoryBookName[] = { +// The Librium of the Horadrim (White Books) + + "The Great Conflict", + "The Wages of Sin are War", + "The Tale of the Horadrim", + +// Grimoire of the Burning Hells (Red Books) + + "The Dark Exile", + "The Sin War", + "The Binding of the Three", + +// The Journals of Lazarus the Betrayer (Normal Book Color) + + "The Realms Beyond", + "Tale of the Three", + "The Black King", + +// The Journals of Skulken the Necromancer JKE + + "Journal: The Ensorcellment", + "Journal: The Meeting", + "Journal: The Tirade", + "Journal: His Power Grows", + "Journal: NA-KRUL", + "Journal: The End", + + "A Spellbook" +}; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitObjectGFX() { + BYTE fileload[MAXOBJFILES]; + int i,j,t; + int templevel; //JKE + + ZeroMemory(fileload,sizeof(fileload)); + +// temp hack to get object art to appear. JKE + templevel = currlevel; + if ((currlevel >= CRYPTSTART) && (currlevel <= CRYPTEND)) + templevel = templevel - CRYPTSTART + 1; // replace templevel with currlevel when done. + else if ((currlevel >= HIVESTART) && (currlevel <= HIVEEND)) + templevel = templevel - HIVESTART + 9; + + for (i = 0; AllObjects[i].oload != -1; ++i) { + if ((AllObjects[i].oload == OBJMUST) + && (templevel >= AllObjects[i].ominlvl) + && (templevel <= AllObjects[i].omaxlvl)) + fileload[AllObjects[i].ofindex] = TRUE; + + if (AllObjects[i].otheme != -1) { + for (t = 0; t < numthemes; ++t) { + if (theme[t].ttype == AllObjects[i].otheme) + fileload[AllObjects[i].ofindex] = TRUE; + } + } + + if (AllObjects[i].oquest != -1) { + j = AllObjects[i].oquest; + if (QuestStatus(j)) + fileload[AllObjects[i].ofindex] = TRUE; + } + } + + app_assert(numobjfiles == 0); + for (i = 0; i < MAXOBJFILES; ++i) { + if (fileload[i]) { + char filestr[32]; + ObjFileList[numobjfiles] = i; + sprintf(filestr, "Objects\\%s.CEL", ObjMasterFList[i]); + if ((currlevel >= HIVESTART) && (currlevel < CRYPTSTART)) //JKE OBJECTS + sprintf(filestr, "Objects\\%s.CEL", HObjMasterFList[i]); + else if (currlevel >= CRYPTSTART) + sprintf(filestr, "Objects\\%s.CEL", CObjMasterFList[i]); + + app_assert(! pObjCels[numobjfiles]); + pObjCels[numobjfiles] = LoadFileInMemSig(filestr,NULL,'OGFX'); + ++numobjfiles; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreeObjectGFX() { + for (int i = 0; i < numobjfiles; ++i) { + DiabloFreePtr(pObjCels[i]); + } + numobjfiles = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static bool RndLocOk(int xp, int yp) { + if (dMonster[xp][yp] != 0) return FALSE; + if (dPlayer[xp][yp] != 0) return FALSE; + if (dObject[xp][yp] != 0) return FALSE; + if (dFlags[xp][yp] & BFLAG_SETPC) return FALSE; + if (nSolidTable[dPiece[xp][yp]]) return FALSE; + if (leveltype == 1) { + if ((dPiece[xp][yp] > 126) && (dPiece[xp][yp] < 144)) + return false; + } + + return true; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static bool TrapLocOk(int xp, int yp) { + if (dFlags[xp][yp] & BFLAG_SETPC) return false; + if (nSolidTable[dPiece[xp][yp]]) return false; + return true; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static bool RoomLocOk(int xp, int yp) { + if (dPlayer[xp][yp] != 0) return false; + if (dObject[xp][yp] != 0) return false; + if (dFlags[xp][yp] & BFLAG_SETPC) return false; + if (nSolidTable[dPiece[xp][yp]]) return false; + return true; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitRndLocObj(int min, int max, int objtype) { + int xp, yp; + + int numobjs = random(139,max - min) + min; + for (int i = 0; i < numobjs; ++i) { + while (1) { + xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); + if (! RndLocOk(xp-1, yp-1)) continue; + if (! RndLocOk(xp+0, yp-1)) continue; + if (! RndLocOk(xp+1, yp-1)) continue; + if (! RndLocOk(xp-1, yp+0)) continue; + if (! RndLocOk(xp+0, yp+0)) continue; + if (! RndLocOk(xp+1, yp+0)) continue; + if (! RndLocOk(xp-1, yp+1)) continue; + if (! RndLocOk(xp+0, yp+1)) continue; + if (! RndLocOk(xp+1, yp+1)) continue; + break; + } + AddObject(objtype, xp, yp); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void InitRndLocBigObj(int min, int max, int objtype) { + int xp, yp; + int numobjs = random(140,max - min) + min; + for (int i = 0; i < numobjs; ++i) { + while (1) { + xp = random(140,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(140,DMAXY - DIRTEDGE) + (DIRTEDGED2); + if (! RndLocOk(xp-1, yp-2)) continue; + if (! RndLocOk(xp+0, yp-2)) continue; + if (! RndLocOk(xp+1, yp-2)) continue; + if (! RndLocOk(xp-1, yp-1)) continue; + if (! RndLocOk(xp+0, yp-1)) continue; + if (! RndLocOk(xp+1, yp-1)) continue; + if (! RndLocOk(xp-1, yp+0)) continue; + if (! RndLocOk(xp+0, yp+0)) continue; + if (! RndLocOk(xp+1, yp+0)) continue; + if (! RndLocOk(xp-1, yp+1)) continue; + if (! RndLocOk(xp+0, yp+1)) continue; + if (! RndLocOk(xp+1, yp+1)) continue; + break; + } + + AddObject(objtype, xp, yp); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void InitRndLocObj5x5(int min, int max, int objtype) { + int xp, yp, xx, yy, cnt; + bool done; + + int numobjs = random(139,max - min) + min; + for (int i = 0; i < numobjs; ++i) { + cnt = 0; + done = false; + while (! done) { + done = true; + xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); + for (yy = -2; yy <= 2; ++yy) { + for (xx = -2; xx <= 2; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; + } + if (!done) { + ++cnt; + if (cnt > 20000) return; + } + } + AddObject(objtype, xp, yp); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void ClrAllObjects () +{ + int i; + + #if 0 + for (i = 0; i < MAXOBJECTS; ++i) { + object[i]._ox = 0; + object[i]._oy = 0; + object[i]._oAnimData = NULL; + object[i]._oAnimDelay = 0; + object[i]._oAnimCnt = 0; + object[i]._oAnimLen = 0; + object[i]._oAnimFrame = 0; + object[i]._oDelFlag = FALSE; + object[i]._oVar1 = 0; + object[i]._oVar2 = 0; + object[i]._oVar3 = 0; + object[i]._oVar4 = 0; + } + #else + memset(object, 0, sizeof(object)); + #endif + + numobjects = 0; + + for (i = 0; i < MAXOBJECTS; ++i) { + objectavail[i] = i; + //objectactive[i] = 0; + } + memset(objectactive, 0, sizeof(objectactive)); + trapid = 1; + trapdir = TRAP_NODIR; + leverid = 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddTortures() +{ + int yp, xp; + + for (yp = 0; yp < DMAXY; ++yp) { + for (xp = 0; xp < DMAXX; ++xp) { + if (dPiece[xp][yp] == 367) { + AddObject(OBJ_TORTURE1, xp, yp+1); + AddObject(OBJ_TORTURE3, xp+2, yp-1); + AddObject(OBJ_TORTURE2, xp, yp+3); + AddObject(OBJ_TORTURE4, xp+4, yp-1); + AddObject(OBJ_TORTURE5, xp, yp+5); + AddObject(OBJ_TNUDEM1, xp+1, yp+3); + AddObject(OBJ_TNUDEM2, xp+4, yp+5); + AddObject(OBJ_TNUDEM3, xp+2, yp); + AddObject(OBJ_TNUDEM4, xp+3, yp+2); + AddObject(OBJ_TNUDEW1, xp+2, yp+4); + AddObject(OBJ_TNUDEW2, xp+2, yp+1); + AddObject(OBJ_TNUDEW3, xp+4, yp+2); + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddCandles() +{ + int const xp = quests[Q_PWATER]._qtx; + int const yp = quests[Q_PWATER]._qty; + + AddObject(OBJ_STORYCANDLE, xp-2, yp+1); + AddObject(OBJ_STORYCANDLE, xp+3, yp+1); + AddObject(OBJ_STORYCANDLE, xp-1, yp+2); + AddObject(OBJ_STORYCANDLE, xp+2, yp+2); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddTrapLine(int min, int max, int tobjtype, int lobjtype) +{ + int i, j, xp, yp, numobjs; + int sx, sy, xa, ya, t; + int lx1, ly1, lx2, ly2; + bool found; + + numobjs = random(0,max - min) + min; + for (i = 0; i < numobjs; ++i) { + found = false; + while (!found) { + found = true; + xp = random(0,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(0,DMAXY - DIRTEDGE) + (DIRTEDGED2); + if (random(0,2)) { + while (TrapLocOk(xp, yp-1)) --yp; // Go to bottom + sx = xp; + sy = yp; + xa = 0; + ya = 1; + t = 0; + while (TrapLocOk(xp, yp+1) && found) { + found = found && RndLocOk(xp-3, yp); + found = found && RndLocOk(xp-2, yp); + found = found && RndLocOk(xp-1, yp); + found = found && RndLocOk(xp, yp); + found = found && RndLocOk(xp+1, yp); + found = found && RndLocOk(xp+2, yp); + found = found && RndLocOk(xp+3, yp); + ++yp; + ++t; + } + lx1 = xp-2; + ly1 = random(0,t-1) + sy + 1; + lx2 = xp+2; + ly2 = random(0,t-1) + sy + 1; + trapdir = TRAP_VERT; + } else { + while (TrapLocOk(xp-1, yp)) --xp; // Go to left + sx = xp; + sy = yp; + xa = 1; + ya = 0; + t = 0; + while (TrapLocOk(xp+1, yp) && found) { + found = found && RndLocOk(xp, yp-3); + found = found && RndLocOk(xp, yp-2); + found = found && RndLocOk(xp, yp-1); + found = found && RndLocOk(xp, yp); + found = found && RndLocOk(xp, yp+1); + found = found && RndLocOk(xp, yp+2); + found = found && RndLocOk(xp, yp+3); + ++xp; + ++t; + } + lx1 = random(0,t-1) + sx + 1; + ly1 = yp-2; + lx2 = random(0,t-1) + sx + 1; + ly2 = yp+2; + trapdir = TRAP_HORIZ; + } + if ((t < 5) || (t > 12)) found = FALSE; + } + + // Place trap + xp = sx; + yp = sy; + for (j = 0; j <= t; ++j) { + AddObject(tobjtype, xp, yp); + xp += xa; + yp += ya; + } + + // Place levers + AddObject(lobjtype, lx1, ly1); + AddObject(lobjtype, lx2, ly2); + + ++trapid; // Next trap + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddLeverObj(int lx1, int ly1, int lx2, int ly2, int x1, int y1, int x2, int y2) +{ + int xp, yp; + while (1) { + xp = random(141,lx2 - lx1 + 1) + lx1; + yp = random(141,ly2 - ly1 + 1) + ly1; + if (! RndLocOk(xp-1, yp-1)) continue; + if (! RndLocOk(xp+0, yp-1)) continue; + if (! RndLocOk(xp+1, yp-1)) continue; + if (! RndLocOk(xp-1, yp+0)) continue; + if (! RndLocOk(xp+0, yp+0)) continue; + if (! RndLocOk(xp+1, yp+0)) continue; + if (! RndLocOk(xp-1, yp+1)) continue; + if (! RndLocOk(xp+0, yp+1)) continue; + if (! RndLocOk(xp+1, yp+1)) continue; + break; + } + + AddObject(OBJ_LEVER, xp, yp); + int i = dObject[xp][yp] - 1; + SetObjMapRange(i, x1, y1, x2, y2, leverid); + ++leverid; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddBookLever(int lx1, int ly1, int lx2, int ly2, int x1, int y1, int x2, int y2, int msg) +{ +/* int xp, yp; + while (1) { + xp = random(142,lx2 - lx1 + 1) + lx1; + yp = random(142,ly2 - ly1 + 1) + ly1; + if (! RndLocOk(xp-1, yp-1)) continue; + if (! RndLocOk(xp+0, yp-1)) continue; + if (! RndLocOk(xp+1, yp-1)) continue; + if (! RndLocOk(xp-1, yp+0)) continue; + if (! RndLocOk(xp+0, yp+0)) continue; + if (! RndLocOk(xp+1, yp+0)) continue; + if (! RndLocOk(xp-1, yp+1)) continue; + if (! RndLocOk(xp+0, yp+1)) continue; + if (! RndLocOk(xp+1, yp+1)) continue; + break; + } +*/ + int xp, yp, xx, yy, cnt; + bool done; + + cnt = 0; + done = false; + while (! done) { + done = true; + xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); + for (yy = -2; yy <= 2; ++yy) { + for (xx = -2; xx <= 2; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; + } + if (!done) { + ++cnt; + if (cnt > 20000) return; + } + } + if (QuestStatus(Q_BLIND)) AddObject(OBJ_BLINDBOOK, xp, yp); + if (QuestStatus(Q_WARLORD)) AddObject(OBJ_STEELTOME, xp, yp); + if (QuestStatus(Q_BLOOD)) { + xp = (setpc_x << 1) + DIRTEDGED2 + 9; + yp = (setpc_y << 1) + DIRTEDGED2 + 24; + AddObject(OBJ_BLOODBOOK, xp, yp); + } + app_assert((DWORD)xp < MAXDUNX); + app_assert((DWORD)yp < MAXDUNY); + int i = dObject[xp][yp] - 1; + app_assert((DWORD)i < MAXOBJECTS); + SetObjMapRange(i, x1, y1, x2, y2, leverid); + SetBookMsg(i, msg); + ++leverid; + object[i]._oVar6 = object[i]._oAnimFrame + 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void InitRndBarrels() +{ + int xp, yp, o, rv, c, t; + + int numobjs = random(143,5) + 3; + for (int i = 0; i < numobjs; ++i) { + while (1) { + xp = random(143,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(143,DMAXY - DIRTEDGE) + (DIRTEDGED2); + if (! RndLocOk(xp, yp)) continue; + break; + } + + // Add normal or exploding barrel + if (random(143,4)) o = OBJ_BARREL; + else o = OBJ_BARRELEX; + AddObject(o, xp, yp); + c = 1; + + bool found = true; + while ((random(143,c >> 1) == 0) && (found)) { + t = 0; + found = false; + while ((!found) && (t < 3)) { + rv = random(143,8); + xp += bxadd[rv]; + yp += byadd[rv]; + found = RndLocOk(xp, yp); + ++t; + } + if (found) { + if (random(143,5)) o = OBJ_BARREL; + else o = OBJ_BARRELEX; + AddObject(o, xp, yp); + ++c; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddL1Objs(int x1, int y1, int x2, int y2) +{ + int i,j,pn; + + for (j = y1; j < y2; ++j) { + for (i = x1; i < x2; ++i) { + // Add Light + pn = dPiece[i][j]; + if (pn == 270) AddObject(OBJ_L1LIGHT, i, j); + if ((pn == 44) || (pn == 51) || (pn == 214)) + AddObject(OBJ_L1DOORL, i, j); + if ((pn == 46) || (pn == 56)) AddObject(OBJ_L1DOORR, i, j); + } + } +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddL5Objs(int x1, int y1, int x2, int y2) +{ + int i,j,pn; + + for (j = y1; j < y2; ++j) { + for (i = x1; i < x2; ++i) { + // Add Light + pn = dPiece[i][j]; +// if (pn == 270) AddObject(OBJ_L1LIGHT, i, j); + if (pn == 77) + AddObject(OBJ_L1DOORL, i, j); + if (pn == 80) + AddObject(OBJ_L1DOORR, i, j); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddL2Objs(int x1, int y1, int x2, int y2) +{ + int i,j,pn; + + for (j = y1; j < y2; ++j) { + for (i = x1; i < x2; ++i) { + // Add Doors + pn = dPiece[i][j]; + if (pn == 13 || pn == 541) AddObject(OBJ_L2DOORL, i, j); + if (pn == 17 || pn == 542) AddObject(OBJ_L2DOORR, i, j); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddL3Objs(int x1, int y1, int x2, int y2) +{ + int i,j,pn; + + for (j = y1; j < y2; ++j) { + for (i = x1; i < x2; ++i) { + // Add Doors + pn = dPiece[i][j]; + if (pn == 531) AddObject(OBJ_L3DOORL, i, j); + if (pn == 534) AddObject(OBJ_L3DOORR, i, j); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static bool TorchLocOK(int xp, int yp) +{ + if (dFlags[xp][yp] & BFLAG_SETPC) return false; + return true; +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddL2Torches() +{ + int i,j,pn; + + for (j = 0; j < DMAXY; ++j) { + for (i = 0; i < DMAXX; ++i) { + // Add Torches + if(TorchLocOK(i,j)) { + pn = dPiece[i][j]; + if ((pn == 1) && (random(145,3) == 0)) AddObject(OBJ_TORCHL2, i, j); + if ((pn == 5) && (random(145,3) == 0)) AddObject(OBJ_TORCHR2, i, j); + if ((pn == 37) && (random(145,10) == 0) && (dObject[i-1][j] == 0)) AddObject(OBJ_TORCHL, i-1, j); + if ((pn == 41) && (random(145,10) == 0) && (dObject[i][j-1] == 0)) AddObject(OBJ_TORCHR, i, j-1); + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static bool WallTrapLocOk(int xp, int yp) +{ + if (dFlags[xp][yp] & BFLAG_SETPC) return false; + if (!nTrapTable[dPiece[xp][yp]]) return false; + return true; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddObjTraps() +{ + int i,j; + int x,y; + int rndv; + char oi, oi2; + + if (currlevel == 1) rndv = 10; + if (currlevel >= 2) rndv = 15; + if (currlevel >= 5) rndv = 20; + if (currlevel >= 7) rndv = 25; + for (j = 0; j < DMAXY; ++j) { + for (i = 0; i < DMAXX; ++i) { + if ((dObject[i][j] > 0) && (random(144,100) < rndv)) { + oi = dObject[i][j] - 1; + if (AllObjects[object[oi]._otype].oTrapFlag) { + x = i; + y = j; + if (random(144,2) == 0) { + --x; + while (!nSolidTable[dPiece[x][y]]) --x; + if (WallTrapLocOk(x, y) && ((i - x) > 1)) { + AddObject(OBJ_TRAPL, x, y); + oi2 = dObject[x][y] - 1; + object[oi2]._oVar1 = i; + object[oi2]._oVar2 = j; + object[oi]._oTrapFlag = TRUE; + } + } else { + --y; + while (!nSolidTable[dPiece[x][y]]) --y; + if (WallTrapLocOk(x, y) && ((j - y) > 1)) { + AddObject(OBJ_TRAPR, x, y); + oi2 = dObject[x][y] - 1; + object[oi2]._oVar1 = i; + object[oi2]._oVar2 = j; + object[oi]._oTrapFlag = TRUE; + } + } + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddChestTraps() +{ + int i,j; + char oi; + + for (j = 0; j < DMAXY; ++j) { + for (i = 0; i < DMAXX; ++i) { + if (dObject[i][j] > 0) { + oi = dObject[i][j] - 1; + if ((object[oi]._otype >= OBJ_CHEST1) && + (object[oi]._otype <= OBJ_CHEST3) && + (!object[oi]._oTrapFlag) && + (random(0, 100) < 10)) { + object[oi]._otype = (object[oi]._otype - OBJ_CHEST1) + OBJ_TCHEST1; + object[oi]._oTrapFlag = TRUE; + if (leveltype == 2) object[oi]._oVar4 = random(0, 2); // Type of trap +#if defined(HELLFIRE2) + else object[oi]._oVar4 = random(0, 7); +#else + else object[oi]._oVar4 = random(0, 6); +#endif + } + } + } + } +} + +/*-----------------------------------------------------------------------* +** Used by diablo level only!!!!! +**-----------------------------------------------------------------------*/ + +static void LoadMapObjects(BYTE *pMap, int startx, int starty, int x1, int y1, int w, int h, int leveridx) +{ + int i,j,rw,rh; + int ox,oy; + BYTE *lm; + long mapoff; + int ot, oi; + + InitObjFlag = TRUE; + + lm = pMap; + rw = *lm; + lm += 2; + rh = *lm; + // Skip map + height word + mapoff = ((rw * rh) << 1) + 2; + // Convert to index mini tile level instead of mega + rw = rw << 1; + rh = rh << 1; + // Skip treasure and monster map + mapoff += ((rw * rh) << 2); + lm += mapoff; + + for (j = 0; j < rh; ++j) { + for (i = 0; i < rw; ++i) { + if (*lm != 0) { + ot = *lm; + ox = i + DIRTEDGED2 + startx; + oy = j + DIRTEDGED2 + starty; + AddObject(ObjTypeConv[ot], ox, oy); + oi = ObjIndex(ox, oy); + SetObjMapRange(oi, x1, y1, x1+w, y1+h, leveridx); + } + lm+=2; + } + } + + InitObjFlag = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void LoadMapObjs(BYTE *pMap, int startx, int starty) +{ + int i,j,rw,rh; + int ox,oy; + BYTE *lm; + long mapoff; + int ot; + + InitObjFlag = TRUE; + + lm = pMap; + rw = *lm; + lm += 2; + rh = *lm; + // Skip map + height word + mapoff = ((rw * rh) << 1) + 2; + // Convert to index mini tile level instead of mega + rw = rw << 1; + rh = rh << 1; + // Skip treasure and monster map + mapoff += ((rw * rh) << 2); + lm += mapoff; + + for (j = 0; j < rh; ++j) { + for (i = 0; i < rw; ++i) { + if (*lm != 0) { + ot = *lm; + ox = i + DIRTEDGED2 + startx; + oy = j + DIRTEDGED2 + starty; + AddObject(ObjTypeConv[ot], ox, oy); + } + lm+=2; + } + } + + InitObjFlag = FALSE; +} + +/*-----------------------------------------------------------------------* +** Levers for diablo level +**-----------------------------------------------------------------------*/ + +static void AddDiabObjs() +{ + BYTE *pSetPiece; + int xx, yy; + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab1.DUN",NULL,'STPC'); + xx = (diabquad1x << 1); + yy = (diabquad1y << 1); + LoadMapObjects(pSetPiece, xx, yy, diabquad2x, diabquad2y, 11, 12, 1); + DiabloFreePtr(pSetPiece); + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab2a.DUN",NULL,'STPC'); + xx = (diabquad2x << 1); + yy = (diabquad2y << 1); + LoadMapObjects(pSetPiece, xx, yy, diabquad3x, diabquad3y, 11, 11, 2); + DiabloFreePtr(pSetPiece); + + pSetPiece = LoadFileInMemSig("Levels\\L4Data\\diab3a.DUN",NULL,'STPC'); + xx = (diabquad3x << 1); + yy = (diabquad3y << 1); + LoadMapObjects(pSetPiece, xx, yy, diabquad4x, diabquad4y, 9, 9, 3); + DiabloFreePtr(pSetPiece); +} + +static void AddSkulkenBooks(int number) // Journal entry books JKE +{ + int xp,yp,xx,yy,cnt; + bool done; + + cnt = 0; + done = false; + while (! done) { + done = true; + xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); + for (yy = -2; yy <= 2; ++yy) { + for (xx = -3; xx <= 3; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; + } + if (!done) { + ++cnt; + if (cnt > 20000) return; + } + } + AddSkulkenObject(OBJ_STORYBOOK, number, xp, yp); + +// AddObject(OBJ_STORYBOOK, xp, yp); + + AddObject(OBJ_STORYCANDLE, xp-2, yp+1); + AddObject(OBJ_STORYCANDLE, xp-2, yp); + AddObject(OBJ_STORYCANDLE, xp-1, yp-1); + AddObject(OBJ_STORYCANDLE, xp+1, yp-1); + AddObject(OBJ_STORYCANDLE, xp+2, yp); + AddObject(OBJ_STORYCANDLE, xp+2, yp+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddStoryBooks() +{ + int xp,yp,xx,yy,cnt; + bool done; + + cnt = 0; + done = false; + while (! done) { + done = true; + xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); + for (yy = -2; yy <= 2; ++yy) { + for (xx = -3; xx <= 3; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; + } + if (!done) { + ++cnt; + if (cnt > 20000) return; + } + } + AddObject(OBJ_STORYBOOK, xp, yp); + AddObject(OBJ_STORYCANDLE, xp-2, yp+1); + AddObject(OBJ_STORYCANDLE, xp-2, yp); + AddObject(OBJ_STORYCANDLE, xp-1, yp-1); + AddObject(OBJ_STORYCANDLE, xp+1, yp-1); + AddObject(OBJ_STORYCANDLE, xp+2, yp); + AddObject(OBJ_STORYCANDLE, xp+2, yp+1); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddHookedBodies(int freq) +{ + int i, j, ii, jj; + + //Add tortured bodies on hooks + for (j = 0; j < MDMAXY; ++j) { + for (i = 0; i < MDMAXX; ++i) { + if ((dungeon[i][j] == 1 || dungeon[i][j] == 2) && + ((!random(0, freq)) && (SkipThemeRoom(i, j)))) { + ii = (i << 1) + DIRTEDGED2; + jj = (j << 1) + DIRTEDGED2; + if ((dungeon[i][j] == 1) && (dungeon[i+1][j] == 6)) { + switch(random(0, 3)) { + case 0: + AddObject(OBJ_TORTURE1, ii+1, jj); + break; + case 1: + AddObject(OBJ_TORTURE2, ii+1, jj); + break; + case 2: + AddObject(OBJ_TORTURE5, ii+1, jj); + break; + } + } else if ((dungeon[i][j] == 2) && (dungeon[i][j+1] == 6)) { + switch(random(0, 2)) { + case 0: + AddObject(OBJ_TORTURE3, ii, jj); + break; + case 1: + AddObject(OBJ_TORTURE4, ii, jj); + break; + } + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void AddL4Goodies() +{ + AddHookedBodies(6); + InitRndLocObj(2, 6, OBJ_TNUDEM1); + InitRndLocObj(2, 6, OBJ_TNUDEM2); + InitRndLocObj(2, 6, OBJ_TNUDEM3); + InitRndLocObj(2, 6, OBJ_TNUDEM4); + InitRndLocObj(2, 6, OBJ_TNUDEW1); + InitRndLocObj(2, 6, OBJ_TNUDEW2); + InitRndLocObj(2, 6, OBJ_TNUDEW3); + InitRndLocObj(2, 6, OBJ_DECAP); + InitRndLocObj(1, 3, OBJ_CAULDRON); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void AddLazStand() +{ + int xp,yp,xx,yy,cnt; + bool done = false; + + cnt = 0; + while (! done) { + done = true; + xp = random(139,DMAXX - DIRTEDGE) + (DIRTEDGED2); + yp = random(139,DMAXY - DIRTEDGE) + (DIRTEDGED2); + for (yy = -3; yy <= 3; ++yy) { + for (xx = -2; xx <= 3; ++xx) if (! RndLocOk(xp+xx,yp+yy)) done = FALSE; + } + if (!done) { + ++cnt; + if (cnt > 10000) { + // If can't find big area put it anywhere + InitRndLocObj(1, 1, OBJ_LAZSTAND); + return; + } + } + } + AddObject(OBJ_LAZSTAND, xp, yp); + AddObject(OBJ_TNUDEM2, xp+0, yp+2); + AddObject(OBJ_STORYCANDLE, xp+1, yp+2); + AddObject(OBJ_TNUDEM3, xp+2, yp+2); + AddObject(OBJ_TNUDEW1, xp+0, yp-2); + AddObject(OBJ_STORYCANDLE, xp+1, yp-2); + AddObject(OBJ_TNUDEW2, xp+2, yp-2); + AddObject(OBJ_STORYCANDLE, xp-1, yp-1); + AddObject(OBJ_TNUDEW3, xp-1, yp+0); + AddObject(OBJ_STORYCANDLE, xp-1, yp+1); +} + +/*-----------------------------------------------------------------------* +** Does not get called for setlevels so no worries +**-----------------------------------------------------------------------*/ + +void InitObjects () +{ + int textdef; + byte *setp; + + ClrAllObjects(); + SpellProgress = 0; + + // No objects on DIABLO_LEVEL. Inited seperatly + if (currlevel == DIABLO_LEVEL) { + AddDiabObjs(); + return; + } + + InitObjFlag = TRUE; + + int rs = GetRndSeed(); + + if (currlevel == SLAIN_HERO_LEVEL && gbMaxPlayers == 1) { + AddSlainHero(); + } + + if (currlevel == quests[Q_BKMUSHRM]._qlevel + && quests[Q_BKMUSHRM]._qactive == QUEST_NOTACTIVE) { + AddMushPatch(); + } + + if (currlevel == STORY_BOOK1_LEVEL) AddStoryBooks(); + else if (currlevel == STORY_BOOK2_LEVEL) AddStoryBooks(); + else if (currlevel == STORY_BOOK3_LEVEL) AddStoryBooks(); + + if (currlevel == SKULKEN_BOOK1_LEVEL) + { +// AddSkulkenBooks(0); + AddSkulkenBooks(1); + +// AddStoryBooks(); +// AddStoryBooks(); + } + else if (currlevel == SKULKEN_BOOK2_LEVEL) + { + AddSkulkenBooks(2); + AddSkulkenBooks(3); + } + else if (currlevel == SKULKEN_BOOK3_LEVEL) + { + AddSkulkenBooks(4); + AddSkulkenBooks(5); + } + + if (currlevel == NA_KRUL_LEVEL) + { + AddNa_Krul_Stuff(); + + } + + if (leveltype == 1) { + if (QuestStatus(Q_BUTCHER)) AddTortures(); + if (QuestStatus(Q_PWATER)) AddCandles(); + if (QuestStatus(Q_LTBANNER)) AddObject(OBJ_SIGNCHEST,(setpc_x << 1) + DIRTEDGED2 + 10, (setpc_y << 1) + DIRTEDGED2 + 3); + + InitRndLocBigObj(10, 15, OBJ_SARC); + if (currlevel < CRYPTSTART) + AddL1Objs(0, 0, DMAXX, DMAXY); + else + AddL5Objs(0,0,DMAXX,DMAXY); + InitRndBarrels(); + } + if (leveltype == 2) { + if (QuestStatus(Q_ROCK)) + InitRndLocObj5x5(1, 1, OBJ_STAND); // Rock stand + if (QuestStatus(Q_SCHAMB)) + InitRndLocObj5x5(1, 1, OBJ_BOOK2R); // SCamb book + + AddL2Objs(0, 0, DMAXX, DMAXY); + AddL2Torches(); + if (QuestStatus(Q_BLIND)) { + if (plr[myplr]._pClass == CLASS_WARRIOR) textdef = TXT_WARBLIND; + else if (plr[myplr]._pClass == CLASS_ROGUE) textdef = TXT_ROGBLIND; + else if (plr[myplr]._pClass == CLASS_SORCEROR) textdef = TXT_SORBLIND; + else if (plr[myplr]._pClass == CLASS_MONK) textdef = TXT_MNKBLIND; + else if (plr[myplr]._pClass == CLASS_BARD) textdef = TXT_BRDBLIND; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) textdef = TXT_BARBLIND; + quests[Q_BLIND]._qmsg = textdef; + AddBookLever(0, 0, DMAXX, DMAXY, setpc_x, setpc_y, setpc_x+setpc_w+1, setpc_y+setpc_h+1, textdef); + setp = LoadFileInMemSig("Levels\\L2Data\\Blind2.DUN",NULL,'STPC'); + LoadMapObjs(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + if (QuestStatus(Q_BLOOD)) { + if (plr[myplr]._pClass == CLASS_WARRIOR) textdef = TXT_WARBLOOD; + else if (plr[myplr]._pClass == CLASS_ROGUE) textdef = TXT_ROGBLOOD; + else if (plr[myplr]._pClass == CLASS_SORCEROR) textdef = TXT_SORBLOOD; + else if (plr[myplr]._pClass == CLASS_MONK) textdef = TXT_MNKBLOOD; + else if (plr[myplr]._pClass == CLASS_BARD) textdef = TXT_BRDBLOOD; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) textdef = TXT_BARBLOOD; + quests[Q_BLOOD]._qmsg = textdef; + AddBookLever(0, 0, DMAXX, DMAXY, setpc_x, setpc_y + 3, setpc_x + 2, setpc_y + 7, textdef); + AddObject(OBJ_PEDISTAL, (setpc_x << 1) + DIRTEDGED2 + 9, (setpc_y << 1) +DIRTEDGED2 + 16); + } + InitRndBarrels(); + } + + if (leveltype == 3) { + AddL3Objs(0, 0, DMAXX, DMAXY); + InitRndBarrels(); + } + + if (leveltype == 4) { + if (QuestStatus(Q_WARLORD)) { + if (plr[myplr]._pClass == CLASS_WARRIOR) textdef = TXT_WARLORD; + else if (plr[myplr]._pClass == CLASS_ROGUE) textdef = TXT_ROGLORD; + else if (plr[myplr]._pClass == CLASS_SORCEROR) textdef = TXT_SORLORD; + else if (plr[myplr]._pClass == CLASS_MONK) textdef = TXT_MNKLORD; + else if (plr[myplr]._pClass == CLASS_BARD) textdef = TXT_BRDLORD; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) textdef = TXT_BARLORD; + quests[Q_WARLORD]._qmsg = textdef; + AddBookLever(0, 0, DMAXX, DMAXY, setpc_x, setpc_y, setpc_x+setpc_w, setpc_y+setpc_h, textdef); + setp = LoadFileInMemSig("Levels\\L4Data\\Warlord.DUN",NULL,'STPC'); + LoadMapObjs(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } + if (QuestStatus(Q_BETRAYER) && (gbMaxPlayers == 1)) { + AddLazStand(); + } + InitRndBarrels(); + AddL4Goodies(); + } + + InitRndLocObj(5, 10, OBJ_CHEST1); + InitRndLocObj(3, 6, OBJ_CHEST2); + InitRndLocObj(1, 5, OBJ_CHEST3); + if (leveltype != 4) AddObjTraps(); + if (leveltype > 1) AddChestTraps(); + + InitObjFlag = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetMapObjects(BYTE *pMap, int startx, int starty) +{ + int i,j,rw,rh; + int ox,oy; + BYTE *lm, *h; + long mapoff; + int ot; + bool fileload[MAXOBJFILES]; + char filestr[32]; + + ClrAllObjects(); + InitObjFlag = TRUE; + + for (i = 0; i < MAXOBJFILES; ++i) fileload[i] = FALSE; + + // Load all must obj gfx for leveltype + for (i = 0; AllObjects[i].oload != -1; ++i) { + if ((AllObjects[i].oload == OBJMUST) && (leveltype == AllObjects[i].olvltype)) + fileload[AllObjects[i].ofindex] = true; + } + + lm = pMap; + rw = *lm; + lm += 2; + rh = *lm; + // Skip map + height word + mapoff = ((rw * rh) << 1) + 2; + // Convert to index mini tile level instead of mega + rw = rw << 1; + rh = rh << 1; + // Skip treasure and monster map + mapoff += ((rw * rh) << 2); + lm += mapoff; + + h = lm; + for (j = 0; j < rh; ++j) { + for (i = 0; i < rw; ++i) { + if (*lm != 0) { + ot = *lm; + ot = ObjTypeConv[ot]; + fileload[AllObjects[ot].ofindex] = TRUE; + } + lm+=2; + } + } + + app_assert(numobjfiles == 0); + for (i = 0; i < MAXOBJFILES; ++i) { + if (fileload[i]) { + ObjFileList[numobjfiles] = i; + sprintf(filestr, "Objects\\%s.CEL", ObjMasterFList[i]); + app_assert(! pObjCels[numobjfiles]); + pObjCels[numobjfiles] = LoadFileInMemSig(filestr,NULL,'OGFX'); + ++numobjfiles; + } + } + + lm = h; + for (j = 0; j < rh; ++j) { + for (i = 0; i < rw; ++i) { + if (*lm != 0) { + ot = *lm; + ox = i + DIRTEDGED2 + startx; + oy = j + DIRTEDGED2 + starty; + AddObject(ObjTypeConv[ot], ox, oy); + } + lm+=2; + } + } + + InitObjFlag = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void DeleteObject(int oi, int i) +{ + int ox,oy; + + app_assert((DWORD)oi < MAXOBJECTS); + ox = object[oi]._ox; + oy = object[oi]._oy; + dObject[ox][oy] = 0; + + objectavail[MAXOBJECTS - numobjects] = oi; + --numobjects; + if ((numobjects > 0) && (i != numobjects)) { + objectactive[i] = objectactive[numobjects]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SetupObject(int i, int x, int y, int ot) +{ + int ai, j; + + app_assert((DWORD)i < MAXOBJECTS); + object[i]._otype = ot; + object[i]._ox = x; + object[i]._oy = y; + + ai = AllObjects[ot].ofindex; + for (j = 0; ObjFileList[j] != ai; ++j); + object[i]._oAnimData = pObjCels[j]; + + object[i]._oAnimFlag = AllObjects[ot].oAnimFlag; + if (object[i]._oAnimFlag) { + object[i]._oAnimDelay = AllObjects[ot].oAnimDelay; + object[i]._oAnimCnt = random(146,AllObjects[ot].oAnimDelay); + object[i]._oAnimLen = AllObjects[ot].oAnimLen; + object[i]._oAnimFrame = random(146,AllObjects[ot].oAnimLen-1) + 1; + } else { + object[i]._oAnimDelay = 1000; + object[i]._oAnimCnt = 0; + object[i]._oAnimLen = AllObjects[ot].oAnimLen; + object[i]._oAnimFrame = AllObjects[ot].oAnimDelay; + } + + object[i]._oAnimWidth = AllObjects[ot].oAnimWidth; + object[i]._oSolidFlag = AllObjects[ot].oSolidFlag; + object[i]._oMissFlag = AllObjects[ot].oMissFlag; + object[i]._oLight = AllObjects[ot].oLightFlag; + object[i]._oDelFlag = FALSE; + object[i]._oBreak = AllObjects[ot].oBreak; + object[i]._oSelFlag = AllObjects[ot].oSelFlag; + object[i]._oPreFlag = FALSE; + object[i]._oTrapFlag = FALSE; + object[i]._oDoorFlag = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetObjMapRange(int i, int x1, int y1, int x2, int y2, int v) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oVar1 = x1; + object[i]._oVar2 = y1; + object[i]._oVar3 = x2; + object[i]._oVar4 = y2; + object[i]._oVar8 = v; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SetBookMsg(int i, int msg) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oVar7 = msg; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddL1Door(int i, int x, int y, int ot) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oDoorFlag = TRUE; + if (ot == OBJ_L1DOORL) { + object[i]._oVar1 = dPiece[x][y]; + object[i]._oVar2 = dPiece[x][y-1]; + } else { + object[i]._oVar1 = dPiece[x][y]; + object[i]._oVar2 = dPiece[x-1][y]; + } + object[i]._oVar4 = DOOR_CLOSED; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddSCambBook(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); +// if (quests[Q_SCHAMB]._qactive != QUEST_NOTACTIVE) { +// object[i]._oSelFlag = OSEL_NONE; +// object[i]._oAnimFrame = 6; +// } + object[i]._oVar1 = setpc_x; + object[i]._oVar2 = setpc_y; + object[i]._oVar3 = setpc_x+setpc_w+1; + object[i]._oVar4 = setpc_y+setpc_h+1; + object[i]._oVar6 = object[i]._oAnimFrame + 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddChest(int i, int t) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (random(147,2) == 0) object[i]._oAnimFrame += 3; // Left or right + object[i]._oRndSeed = GetRndSeed(); + // Set # chest items. If a setlevel then so to max items. + switch(t) { + case OBJ_CHEST1: + case OBJ_TCHEST1: + if (setlevel) object[i]._oVar1 = 1; + else object[i]._oVar1 = random(147,2); + break; + case OBJ_CHEST2: + case OBJ_TCHEST2: + if (setlevel) object[i]._oVar1 = 2; + else object[i]._oVar1 = random(147,3); + break; + case OBJ_CHEST3: + case OBJ_TCHEST3: + if (setlevel) object[i]._oVar1 = 3; + else object[i]._oVar1 = random(147,4); + break; + } + object[i]._oVar2 = random(147,8); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddL2Door(int i, int x, int y, int ot) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oDoorFlag = TRUE; + if (ot == OBJ_L2DOORL) ObjSetMicro(x, y, 538); + else ObjSetMicro(x, y, 540); + object[i]._oVar4 = DOOR_CLOSED; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddL3Door(int i, int x, int y, int ot) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oDoorFlag = TRUE; + if (ot == OBJ_L3DOORL) ObjSetMicro(x, y, 531); + else ObjSetMicro(x, y, 534); + object[i]._oVar4 = DOOR_CLOSED; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddSarc(int i) +{ + int x,y; + + app_assert((DWORD)i < MAXOBJECTS); + x = object[i]._ox; + y = object[i]._oy - 1; + dObject[x][y] = -1 - (char)i; + object[i]._oVar1 = random(153,10); + object[i]._oRndSeed = GetRndSeed(); + if (object[i]._oVar1 >= 8) object[i]._oVar2 = PreSpawnSkeleton(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddFlameTrap(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oVar1 = trapid; // Set trap id + object[i]._oVar2 = 0; // Trap active + object[i]._oVar3 = trapdir; // Horizontal, Vertical, or none + object[i]._oVar4 = 0; // Init to off +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddFlameLvr(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oVar1 = trapid; // Set trap id + object[i]._oVar2 = OBJ_FLAMEHOLE; // Trap active +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddTrap(int i, int ot) +{ + int mt, tdiff; + + // Difficulty + tdiff = (currlevel / 3) + 1; +// Temp hack trap JKE 7/30 + if (currlevel > 16) tdiff = ((currlevel-4)/3) + 1; + if (currlevel > 20) tdiff = ((currlevel-8)/3) + 1; + + // Missile type + mt = random(148,tdiff); + app_assert((DWORD)i < MAXOBJECTS); + if (mt == 0) object[i]._oVar3 = MIT_ARROW; + if (mt == 1) object[i]._oVar3 = MIT_FIREBOLT; + if (mt == 2) object[i]._oVar3 = MIT_LIGHTCTRL; + object[i]._oVar4 = 0; // Trap active +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddObjLight(int i, int r) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (InitObjFlag) { + DoLighting(object[i]._ox, object[i]._oy, r, -1); + object[i]._oVar1 = -1; + } else object[i]._oVar1 = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddBarrel(int i, int ot) +{ + app_assert((DWORD)i < MAXOBJECTS); + //object[i]._oVar1 = random(149,5) + 5; // Barrel hit points + object[i]._oVar1 = 0; + object[i]._oRndSeed = GetRndSeed(); + object[i]._oVar2 = random(149,10); // What is inside + object[i]._oVar3 = random(149,3); // if item, useful or not + if (object[i]._oVar2 >= 8) + object[i]._oVar4 = PreSpawnSkeleton(); // Get monster index if one will pop out +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddShrine(int i) +{ + int st, j; + bool slist[NUMSHRINETYPES]; + + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oPreFlag = TRUE; + for (j = 0; j < NUMSHRINETYPES; ++j) { + if ((currlevel >= shrineminlvl[j]) && (currlevel <= shrinemaxlvl[j])) + slist[j] = true; + else + slist[j] = false; + if ((gbMaxPlayers != 1) && (shrineavail[j] == SHRINE_SINGLE)) slist[j] = false; + if ((gbMaxPlayers == 1) && (shrineavail[j] == SHRINE_MULTI)) slist[j] = false; + } + + // Choose shrine type + do { + st = random(150,NUMSHRINETYPES); + } while (!slist[st]); + + object[i]._oVar1 = st; + + if (random(150,2)) { + object[i]._oAnimFrame = 12; + object[i]._oAnimLen = 22; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddBookcase(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); + object[i]._oPreFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddBookstand(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddBloodFtn(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddPurifyingFountain(int i) +{ + int x, y; + + app_assert((DWORD)i < MAXOBJECTS); + x = object[i]._ox; + y = object[i]._oy; + dObject[x][y-1] = -1 - (char)i; + dObject[x-1][y] = -1 - (char)i; + dObject[x-1][y-1] = -1 - (char)i; + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddArmorStand(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (!armorFlag) { + //A functional armor stand has already been placed + //Only place non-functional empty stands + object[i]._oAnimFlag = 2; + object[i]._oSelFlag = OSEL_NONE; + } + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddGoatShrine(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddCauldron(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddMurkyFountain(int i) +{ + int x, y; + + app_assert((DWORD)i < MAXOBJECTS); + x = object[i]._ox; + y = object[i]._oy; + dObject[x][y-1] = -1 - (char)i; + dObject[x-1][y] = -1 - (char)i; + dObject[x-1][y-1] = -1 - (char)i; + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddTearFountain(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddDecap(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); + object[i]._oAnimFrame = random(151,8) + 1; + object[i]._oPreFlag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +const void AddVilebook(int i) +{ + if ((setlevel) && (setlvlnum == SL_VILEBETRAYER)) { + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oAnimFrame = 4; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +const void AddMagicCircle(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); + object[i]._oPreFlag = TRUE; + object[i]._oVar6 = OBJNOWARP; + object[i]._oVar5 = OBJWARP1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +const void AddBrnCross(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +const void AddPedistal(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oVar1 = setpc_x; + object[i]._oVar2 = setpc_y; + object[i]._oVar3 = setpc_x + setpc_w; + object[i]._oVar4 = setpc_y + setpc_h; +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int const StoryText[3][3] = { + { TXT_BOOK11, TXT_BOOK12, TXT_BOOK13 }, + { TXT_BOOK21, TXT_BOOK22, TXT_BOOK23 }, + { TXT_BOOK31, TXT_BOOK32, TXT_BOOK33 } }; + +static void AddStoryBook(int i) +{ + // Use the last level seed to determine book types (which of 3) + SetRndSeed(glSeedTbl[16]); + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oVar1 = random(0, 3); + if (currlevel == STORY_BOOK1_LEVEL) object[i]._oVar2 = StoryText[object[i]._oVar1][0]; + else if (currlevel == STORY_BOOK2_LEVEL) object[i]._oVar2 = StoryText[object[i]._oVar1][1]; + else if (currlevel == STORY_BOOK3_LEVEL) object[i]._oVar2 = StoryText[object[i]._oVar1][2]; + object[i]._oVar3 = (object[i]._oVar1 * 3) + (currlevel >> 2) - 1; + + object[i]._oAnimFrame = 5 - (object[i]._oVar1 << 1); + object[i]._oVar4 = object[i]._oAnimFrame + 1; +} + +static void addskulkenbook (int i, int number) // number is the text to associate JKE +{ + app_assert((DWORD)i < MAXOBJECTS); + if (number > 5) + { + object[i]._oVar8 = number; + switch (object[i]._oVar8) + { + case 6: +// object[i]._oVar2 = TXT_SPELL1; + + if (plr[myplr]._pClass == CLASS_WARRIOR) object[i]._oVar2 = TXT_SPELL1; + else if (plr[myplr]._pClass == CLASS_ROGUE) object[i]._oVar2 = TXT_R_SPELL1; + else if (plr[myplr]._pClass == CLASS_SORCEROR) object[i]._oVar2 = TXT_S_SPELL1; + else if (plr[myplr]._pClass == CLASS_MONK) object[i]._oVar2 = TXT_M_SPELL1; + else if (plr[myplr]._pClass == CLASS_BARD) object[i]._oVar2 = TXT_B_SPELL1; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) object[i]._oVar2 = TXT_C_SPELL1; + break; + + case 7: +// object[i]._oVar2 = TXT_SPELL2; + + if (plr[myplr]._pClass == CLASS_WARRIOR) object[i]._oVar2 = TXT_SPELL2; + else if (plr[myplr]._pClass == CLASS_ROGUE) object[i]._oVar2 = TXT_R_SPELL2; + else if (plr[myplr]._pClass == CLASS_SORCEROR) object[i]._oVar2 = TXT_S_SPELL2; + else if (plr[myplr]._pClass == CLASS_MONK) object[i]._oVar2 = TXT_M_SPELL2; + else if (plr[myplr]._pClass == CLASS_BARD) object[i]._oVar2 = TXT_B_SPELL2; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) object[i]._oVar2 = TXT_C_SPELL2; + break; + + case 8: +// object[i]._oVar2 = TXT_SPELL3; + + if (plr[myplr]._pClass == CLASS_WARRIOR) object[i]._oVar2 = TXT_SPELL3; + else if (plr[myplr]._pClass == CLASS_ROGUE) object[i]._oVar2 = TXT_R_SPELL3; + else if (plr[myplr]._pClass == CLASS_SORCEROR) object[i]._oVar2 = TXT_S_SPELL3; + else if (plr[myplr]._pClass == CLASS_MONK) object[i]._oVar2 = TXT_M_SPELL3; + else if (plr[myplr]._pClass == CLASS_BARD) object[i]._oVar2 = TXT_B_SPELL3; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) object[i]._oVar2 = TXT_C_SPELL3; + break; + } + + object[i]._oVar1 = 1; + object[i]._oVar3 = 15; + + object[i]._oAnimFrame = 5 - ((object[i]._oVar1) << 1); + object[i]._oVar4 = object[i]._oAnimFrame + 1; + } + else + { + object[i]._oVar1 = 1; + object[i]._oVar2 = TXT_SKULLJRNL1 + number; + + object[i]._oVar3 = 9 + number; + + object[i]._oAnimFrame = 5 - (object[i]._oVar1 << 1); + object[i]._oVar4 = object[i]._oAnimFrame + 1; + object[i]._oVar8 = 0; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddWeaponRack(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (!weaponFlag) { + //A functional weapon rack has already been placed + //Only place non-functional empty racks + object[i]._oAnimFlag = 2; + object[i]._oSelFlag = OSEL_NONE; + } + object[i]._oRndSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddTorturedBody(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oRndSeed = GetRndSeed(); + object[i]._oAnimFrame = random(0, 4) + 1; + object[i]._oPreFlag = TRUE; +} + +/*-----------------------------------------------------------------------* + * GetRndObjLoc + * + * Gets a x by y empty location for object placement +**-----------------------------------------------------------------------*/ + +static void GetRndObjLoc(int randarea, int &xx, int &yy) +{ + int i,j; + bool failed; + + if (randarea) { + int tries = 0; + do { + if (++tries > 1000 && randarea > 1) + --randarea; + xx = random(0, DMAXX); + yy = random(0, DMAXY); + failed = false; + for (i = 0; i < randarea && !failed; ++i) + for (j = 0; j < randarea && !failed; ++j) + failed = !RndLocOk(xx + i, yy + j); + } while (failed); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddMushPatch() +{ + int x,y; + if (numobjects < MAXOBJECTS) { + int i = objectavail[0]; + + GetRndObjLoc(5, x, y); + dObject[x+1][y+1] = -1 - (char)i; + dObject[x+2][y+1] = -1 - (char)i; + dObject[x+1][y+2] = -1 - (char)i; + AddObject(OBJ_MUSHPATCH, x+2, y+2); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void AddSlainHero() +{ + int x, y; + + GetRndObjLoc(5, x, y); + AddObject(OBJ_SLAINHERO, x+2, y+2); +} + + +void AddSkulkenObject(int ot, int number, int ox, int oy) +{ + int oi; // Standard setup JKE + + if (numobjects < MAXOBJECTS) { + oi = objectavail[0]; + objectavail[0] = objectavail[MAXOBJECTS - numobjects - 1]; + objectactive[numobjects] = oi; + dObject[ox][oy] = (char)oi + 1; + // Standard init + SetupObject(oi, ox, oy, ot); + + addskulkenbook(oi, number); + + app_assert((DWORD)oi < MAXOBJECTS); + object[oi]._oAnimWidth2 = (object[oi]._oAnimWidth - 64) >> 1; + ++numobjects; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddObject(int ot, int ox, int oy) +{ + int oi; + + if (numobjects < MAXOBJECTS) { + oi = objectavail[0]; + objectavail[0] = objectavail[MAXOBJECTS - numobjects - 1]; + objectactive[numobjects] = oi; + dObject[ox][oy] = (char)oi + 1; + // Standard init + SetupObject(oi, ox, oy, ot); + // Bonus inits + switch (ot) { + case OBJ_L1LIGHT : + //AddObjLight(oi, 10); + AddObjLight(oi, 5); + break; + case OBJ_CANDLE1 : + case OBJ_CANDLE2 : + case OBJ_SKFIRE : + case OBJ_BOOKCANDLE: + AddObjLight(oi, 5); + break; + case OBJ_STORYCANDLE: + AddObjLight(oi, 3); + break; + case OBJ_TORCHL: + case OBJ_TORCHR: + case OBJ_TORCHL2: + case OBJ_TORCHR2: + AddObjLight(oi, 8); + break; + case OBJ_L1DOORL : + case OBJ_L1DOORR : + AddL1Door(oi, ox, oy, ot); + break; + case OBJ_L2DOORL : + case OBJ_L2DOORR : + AddL2Door(oi, ox, oy, ot); + break; + case OBJ_L3DOORL : + case OBJ_L3DOORR : + AddL3Door(oi, ox, oy, ot); + break; + case OBJ_BOOK2R: + AddSCambBook(oi); + break; + case OBJ_CHEST1: + case OBJ_CHEST2: + case OBJ_CHEST3: + case OBJ_TCHEST1: + case OBJ_TCHEST2: + case OBJ_TCHEST3: + AddChest(oi, ot); + break; + case OBJ_SARC: + AddSarc(oi); + break; + case OBJ_FLAMEHOLE: + AddFlameTrap(oi); + break; + case OBJ_FLAMELVR: + AddFlameLvr(oi); + break; + case OBJ_WATER: + app_assert((DWORD)oi < MAXOBJECTS); + object[oi]._oAnimFrame = 1; + break; + case OBJ_TRAPL: + case OBJ_TRAPR: + AddTrap(oi, ot); + break; + case OBJ_BARREL: + case OBJ_BARRELEX: + AddBarrel(oi, ot); + break; + case OBJ_SHRINEL: + case OBJ_SHRINER: + AddShrine(oi); + break; + case OBJ_BOOKCASEL: + case OBJ_BOOKCASER: + AddBookcase(oi); + break; + case OBJ_SKELBOOK: + case OBJ_BOOKSTAND: + AddBookstand(oi); + break; + case OBJ_BLOODFTN: + AddBloodFtn(oi); + break; + case OBJ_DECAP: + AddDecap(oi); + break; + case OBJ_PURIFYINGFTN: + AddPurifyingFountain(oi); + break; + case OBJ_ARMORSTAND: + case OBJ_WARARMOR: + AddArmorStand(oi); + break; + case OBJ_GOATSHRINE: + AddGoatShrine(oi); + break; + case OBJ_CAULDRON: + AddCauldron(oi); + break; + case OBJ_MURKYFTN: + AddMurkyFountain(oi); + break; + case OBJ_TEARFTN: + AddTearFountain(oi); + break; + case OBJ_BOOK2L: + AddVilebook(oi); + break; + case OBJ_MCIRCLE1: + case OBJ_MCIRCLE2: + AddMagicCircle(oi); + break; + case OBJ_STORYBOOK: + AddStoryBook(oi); + break; + case OBJ_TBCROSS: + case OBJ_BCROSS: + AddBrnCross(oi); + AddObjLight(oi, 5); + break; + case OBJ_PEDISTAL: + AddPedistal(oi); + break; + case OBJ_WARWEAP: + case OBJ_WEAPONRACK: + AddWeaponRack(oi); + break; + case OBJ_TNUDEM2: + AddTorturedBody(oi); + break; + } + app_assert((DWORD)oi < MAXOBJECTS); + object[oi]._oAnimWidth2 = (object[oi]._oAnimWidth - 64) >> 1; + ++numobjects; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Obj_Light(int i, int lr) +{ + int ox, oy; + int dx, dy, p, tr; + bool turnon = false; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oVar1 == -1) return; + + ox = object[i]._ox; + oy = object[i]._oy; + tr = lr + PLRLRAD; + if (lightflag == 0) { + for (p = 0; (p < MAX_PLRS) && (!turnon); ++p) { + if (!plr[p].plractive) continue; + if (currlevel != plr[p].plrlevel) continue; + dx = abs(plr[p]._px - ox); + dy = abs(plr[p]._py - oy); + if ((dx < tr) && (dy < tr)) turnon = true; + } + } + if (turnon) { + if (object[i]._oVar1 == 0) object[i]._olid = AddLight (ox, oy, lr); + object[i]._oVar1 = 1; + } else { + if (object[i]._oVar1 == 1) AddUnLight(object[i]._olid); + object[i]._oVar1 = 0; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Obj_Circle(int i) +{ + int px, py, ox, oy; + int v1, v2, v3; + + app_assert((DWORD)i < MAXOBJECTS); + ox = object[i]._ox; + oy = object[i]._oy; + px = plr[myplr]._px; + py = plr[myplr]._py; + if ((px == ox) && (py == oy)) { + if (object[i]._otype == OBJ_MCIRCLE1) object[i]._oAnimFrame = 2; + if (object[i]._otype == OBJ_MCIRCLE2) object[i]._oAnimFrame = 4; + if ((ox == 45) && (oy == 47)) object[i]._oVar6 = OBJWARP2; + else if ((ox == 26) && (oy == 46)) object[i]._oVar6 = OBJWARP1; + else object[i]._oVar6 = OBJNOWARP; + if ((ox == 35) && (oy == 36) && object[i]._oVar5 == OBJWARP3) { + object[i]._oVar6 = OBJDONEWARP; + v1 = 35; + v2 = 46; + ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + if (quests[Q_BETRAYER]._qactive == QUEST_NOTDONE) + quests[Q_BETRAYER]._qvar1 = 4; + v3 = dPiece[v1][v2]; + //Cast phase + AddMissile(plr[myplr]._px, plr[myplr]._py, v1, v2, plr[myplr]._pdir, MIT_PHASE, MI_ENEMYMONST, myplr, 0, 0); + void TrackInit(BOOL bMouseDown); + TrackInit(FALSE); +// drb.patch1.start.1/24/97 +// static BYTE sgbMouseDown; + extern BYTE sgbMouseDown; +// drb.patch1.end.1/24/97 + sgbMouseDown = FALSE; + ReleaseCapture(); + ClrPlrPath(myplr); + void StartStand(int, int); + StartStand(myplr, 0); + } + } + else { + if (object[i]._otype == OBJ_MCIRCLE1) object[i]._oAnimFrame = 1; + if (object[i]._otype == OBJ_MCIRCLE2) object[i]._oAnimFrame = 3; + object[i]._oVar6 = OBJNOWARP; + } +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Obj_StopAnim(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oAnimFrame == object[i]._oAnimLen) { + object[i]._oAnimCnt = 0; + object[i]._oAnimDelay = 1000; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Obj_Door(int i) +{ + int dx, dy; + bool dok; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oVar4 == DOOR_CLOSED) { + object[i]._oSelFlag = OSEL_ALL; + object[i]._oMissFlag = FALSE; + } else { + dx = object[i]._ox; + dy = object[i]._oy; + dok = (dMonster[dx][dy] == 0); + dok = dok && (dItem[dx][dy] == 0); + dok = dok && (dDead[dx][dy] == 0); + dok = dok && (dPlayer[dx][dy] == 0); + object[i]._oSelFlag = OSEL_TOP; + if (dok) object[i]._oVar4 = DOOR_OPEN; + else object[i]._oVar4 = DOOR_BLOCKED; + object[i]._oMissFlag = TRUE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Obj_Sarc(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oAnimFrame == object[i]._oAnimLen) object[i]._oAnimFlag = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ActivateTrapLine(int ttype, int tid) +{ + int i, oi; + + for (i = 0; i < numobjects; ++i) { + oi = objectactive[i]; + if ((object[oi]._otype == ttype) && (object[oi]._oVar1 == tid)) { + object[oi]._oVar4 = 1; + object[oi]._oAnimFlag = TRUE; + object[oi]._oAnimDelay = 1; + object[oi]._olid = AddLight (object[oi]._ox, object[oi]._oy, 1); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Obj_FlameTrap(int i) +{ + int xp,yp; + int j; + + // Is trap active? + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oVar2 != 0) { + // Not active, try dying down + if (object[i]._oVar4 != 0) { + --object[i]._oAnimFrame; + if (object[i]._oAnimFrame == 1) { + object[i]._oVar4 = 0; + AddUnLight(object[i]._olid); + } else { + if (object[i]._oAnimFrame <= 4) ChangeLightRadius(object[i]._olid, object[i]._oAnimFrame); + } + } + } else { + // Active so continue + // Not on? + if (object[i]._oVar4 == 0) { + if (object[i]._oVar3 == TRAP_VERT) { + xp = object[i]._ox-2; + yp = object[i]._oy; + for (j = 0; j < 5; ++j) { + if ((dPlayer[xp][yp] != 0) || (dMonster[xp][yp] != 0)) + object[i]._oVar4 = 1; + ++xp; + } + } else { + xp = object[i]._ox; + yp = object[i]._oy-2; + for (j = 0; j < 5; ++j) { + if ((dPlayer[xp][yp] != 0) || (dMonster[xp][yp] != 0)) + object[i]._oVar4 = 1; + ++yp; + } + } + if (object[i]._oVar4 != 0) ActivateTrapLine(object[i]._otype, object[i]._oVar1); + } else { + if (object[i]._oAnimFrame == object[i]._oAnimLen) object[i]._oAnimFrame = 11; + if (object[i]._oAnimFrame <= 5) ChangeLightRadius(object[i]._olid, object[i]._oAnimFrame); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Obj_Trap(int i) +{ + int oti; + bool otrig = false; + int sx, sy, dx, dy; + int x, y; + int ax, ay; + int mdir; + + // Triggered? + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oVar4 == 0) { + oti = dObject[object[i]._oVar1][object[i]._oVar2] - 1; + switch (object[oti]._otype) { + case OBJ_CHEST1: + case OBJ_CHEST2: + case OBJ_CHEST3: + case OBJ_SWITCHSKL: + case OBJ_LEVER : + case OBJ_SARC: + if (object[oti]._oSelFlag == OSEL_NONE) otrig = true; + break; + case OBJ_L1DOORL : + case OBJ_L1DOORR : + case OBJ_L2DOORL : + case OBJ_L2DOORR : + case OBJ_L3DOORL : + case OBJ_L3DOORR : + if (object[oti]._oVar4 != DOOR_CLOSED) otrig = true; + break; + } + if (otrig) { + object[i]._oVar4 = 1; + sx = object[i]._ox; + sy = object[i]._oy; + dx = object[oti]._ox; + dy = object[oti]._oy; + ax = dx; + ay = dy; + for (y = ay-1; y <= ay+1; ++y) { + for (x = ax-1; x <= ax+1; ++x) { + if (dPlayer[x][y] != 0) { + dx = x; + dy = y; + } + } + } + if (!deltaload) { + mdir = GetDirection(sx, sy, dx, dy); + AddMissile(sx, sy, dx, dy, mdir, object[i]._oVar3, MI_ENEMYPLR, -1, 0, 0); + PlaySfxLoc(IS_TRAP, object[oti]._ox, object[oti]._oy); + } + object[oti]._oTrapFlag = FALSE; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void Obj_BCrossDamage(int i) +{ + int resist; + int damage[4] = { 6, 8, 10, 12 }; + + if (plr[myplr]._pmode != PM_DEATH) { + //Check for fire resistance. If resistance, adjust damage accordingly. + resist = plr[myplr]._pFireResist; + if (resist > 0) damage[leveltype-1] -= (damage[leveltype-1] * resist) / 100; + //Is the player in the fire? + app_assert((DWORD)i < MAXOBJECTS); + if ((plr[myplr]._px == object[i]._ox) && (plr[myplr]._py == object[i]._oy-1)) { + //Subtract damage + plr[myplr]._pHitPoints -= damage[leveltype-1]; + plr[myplr]._pHPBase -= damage[leveltype-1]; + //Check if player is dead + if ((plr[myplr]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - SetPlayerHitPoints(myplr, 0); + StartPlrKill(myplr, FALSE); + } else { + //Play pain sfx + if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR68, plr[myplr]._px, plr[myplr]._py); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE68, plr[myplr]._px, plr[myplr]._py); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE68, plr[myplr]._px, plr[myplr]._py); + else if (plr[myplr]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK68, plr[myplr]._px, plr[myplr]._py); + else if (plr[myplr]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD68, plr[myplr]._px, plr[myplr]._py); + else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySfxLoc(PS_BARBARIAN68, plr[myplr]._px, plr[myplr]._py); + #endif + } + drawhpflag = TRUE; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ProcessObjects () +{ + int i, oi; + + for (i = 0; i < numobjects; ++i) { + oi = objectactive[i]; + app_assert((DWORD)oi < MAXOBJECTS); + switch (object[oi]._otype) { + case OBJ_L1LIGHT : + Obj_Light(oi, 10); + break; + case OBJ_CANDLE2 : + case OBJ_SKFIRE : + case OBJ_BOOKCANDLE: + Obj_Light(oi, 5); + break; + case OBJ_STORYCANDLE: + Obj_Light(oi, 3); + break; + case OBJ_CRUX1 : + case OBJ_CRUX2 : + case OBJ_CRUX3 : + case OBJ_BARREL: + case OBJ_BARRELEX: + case OBJ_SHRINEL: + case OBJ_SHRINER: + Obj_StopAnim(oi); + break; + case OBJ_L1DOORL : + case OBJ_L1DOORR : + case OBJ_L2DOORL : + case OBJ_L2DOORR : + case OBJ_L3DOORL : + case OBJ_L3DOORR : + Obj_Door(oi); + break; + case OBJ_TORCHL: + case OBJ_TORCHR: + case OBJ_TORCHL2: + case OBJ_TORCHR2: + Obj_Light(oi, 8); + break; + case OBJ_SARC: + Obj_Sarc(oi); + break; + case OBJ_FLAMEHOLE: + Obj_FlameTrap(oi); + break; + case OBJ_TRAPL: + case OBJ_TRAPR: + Obj_Trap(oi); + break; + case OBJ_MCIRCLE1: + case OBJ_MCIRCLE2: + Obj_Circle(oi); + break; + case OBJ_TBCROSS: + case OBJ_BCROSS: + Obj_Light(oi, 10); + Obj_BCrossDamage(oi); + break; + } + + // Animate Objects + if (object[oi]._oAnimFlag) { + ++object[oi]._oAnimCnt; + if (object[oi]._oAnimCnt >= object[oi]._oAnimDelay) { + object[oi]._oAnimCnt = 0; + ++object[oi]._oAnimFrame; + if (object[oi]._oAnimFrame > object[oi]._oAnimLen) object[oi]._oAnimFrame = 1; + } + } + } + i = 0; + while (i < numobjects) { + oi = objectactive[i]; + if (object[oi]._oDelFlag) { + DeleteObject(oi, i); + i = 0; + } else ++i; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ObjSetMicro(int dx, int dy, int pn) +{ + WORD *mtsource; + int t; + WORD *mt; + + dPiece[dx][dy] = pn; + --pn; + mt = &(dMT2[CalcRot(dx,dy)].mt[0]); + if (leveltype != 4) { + mtsource = (WORD *)(pMiniTiles + 20*pn); + for(t = 0; t < 10; ++t) + // MiniTiles array uses opposite y direction + // hence wierd index on next line + mt[t] = mtsource[8-(t&0xe)+(t&1)]; + } else { + mtsource = (WORD *)(pMiniTiles + 32*pn); + for(t = 0; t < 16; ++t) + // MiniTiles array uses opposite y direction + // hence wierd index on next line + mt[t] = mtsource[14-(t&0xe)+(t&1)]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void ObjSetMicro12(int dx, int dy) +{ + long mt1,mt2; + int pn; + + pn = dPiece[dx][dy] - 1; + __asm { + mov esi,dword ptr [pMiniTiles] + xor eax,eax + mov ax,word ptr [pn] + mov ebx,20 + mul ebx + add esi,eax + add esi,16 + xor eax,eax + lodsw + mov word ptr [mt1],ax + lodsw + mov word ptr [mt2],ax + } + dMT2[CalcRot(dx,dy)].mt[0] = mt1 & 0xffff; + dMT2[CalcRot(dx,dy)].mt[1] = mt2 & 0xffff; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void ObjSetMini(int x, int y, int v) +{ + long v1,v2,v3,v4; + int xx, yy; + + __asm { + mov esi,dword ptr [pMegaTiles] + xor eax,eax + mov ax,word ptr [v]; + dec eax + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + } + xx = (x << 1) + DIRTEDGED2; + yy = (y << 1) + DIRTEDGED2; + ObjSetMicro(xx, yy, v1); + ObjSetMicro(xx+1, yy, v2); + ObjSetMicro(xx, yy+1, v3); + ObjSetMicro(xx+1, yy+1, v4); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void ObjL1Special(int x1, int y1, int x2, int y2) +{ + int i,j; + + for (j = y1; j <= y2; ++j) { + for (i = x1; i <= x2; ++i) { + dSpecial[i][j] = 0; + // Place tops of arches + if (dPiece[i][j] == 12) dSpecial[i][j] = 1; + if (dPiece[i][j] == 11) dSpecial[i][j] = 2; + if (dPiece[i][j] == 71) dSpecial[i][j] = 1; + if (dPiece[i][j] == 259) dSpecial[i][j] = 5; + if (dPiece[i][j] == 249) dSpecial[i][j] = 2; + if (dPiece[i][j] == 325) dSpecial[i][j] = 2; + if (dPiece[i][j] == 321) dSpecial[i][j] = 1; + if (dPiece[i][j] == 255) dSpecial[i][j] = 4; + if (dPiece[i][j] == 211) dSpecial[i][j] = 1; + if (dPiece[i][j] == 344) dSpecial[i][j] = 2; + if (dPiece[i][j] == 341) dSpecial[i][j] = 1; + if (dPiece[i][j] == 331) dSpecial[i][j] = 2; + if (dPiece[i][j] == 418) dSpecial[i][j] = 1; + if (dPiece[i][j] == 421) dSpecial[i][j] = 2; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void ObjL2Special(int x1, int y1, int x2, int y2) +{ + int i,j; + + for (j = y1; j <= y2; ++j) { + for (i = x1; i <= x2; ++i) { + dSpecial[i][j] = 0; + if (dPiece[i][j] == 541) dSpecial[i][j] = 5; + if (dPiece[i][j] == 178) dSpecial[i][j] = 5; + if (dPiece[i][j] == 551) dSpecial[i][j] = 5; + if (dPiece[i][j] == 542) dSpecial[i][j] = 6; + if (dPiece[i][j] == 553) dSpecial[i][j] = 6; + if (dPiece[i][j] == 13) dSpecial[i][j] = 5; + if (dPiece[i][j] == 17) dSpecial[i][j] = 6; + } + } + + for (j = y1; j <= y2; ++j) { + for (i = x1; i <= x2; ++i) { + if (dPiece[i][j] == 132) { + dSpecial[i][j+1] = 2; + dSpecial[i][j+2] = 1; + } + if ((dPiece[i][j] == 135) || (dPiece[i][j] == 139)) { + dSpecial[i+1][j] = 3; + dSpecial[i+2][j] = 4; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void DoorSet(int oi, int dx, int dy) +{ + int pn; + + app_assert((DWORD)oi < MAXOBJECTS); + pn = dPiece[dx][dy]; + if (currlevel < HIVESTART) + { + if (pn == 43) ObjSetMicro(dx,dy,392); + if (pn == 45) ObjSetMicro(dx,dy,394); + if ((pn == 50) && (object[oi]._otype == OBJ_L1DOORL)) ObjSetMicro(dx,dy,411); + if ((pn == 50) && (object[oi]._otype == OBJ_L1DOORR)) ObjSetMicro(dx,dy,412); + if (pn == 54) ObjSetMicro(dx,dy,397); + if (pn == 55) ObjSetMicro(dx,dy,398); + if (pn == 61) ObjSetMicro(dx,dy,399); + if (pn == 67) ObjSetMicro(dx,dy,400); + if (pn == 68) ObjSetMicro(dx,dy,401); + if (pn == 69) ObjSetMicro(dx,dy,403); + if (pn == 70) ObjSetMicro(dx,dy,404); + if (pn == 72) ObjSetMicro(dx,dy,406); + if (pn == 212) ObjSetMicro(dx,dy,407); // Blood + if (pn == 354) ObjSetMicro(dx,dy,409); // Plain L + if (pn == 355) ObjSetMicro(dx,dy,410); // Plain R + if (pn == 411) ObjSetMicro(dx,dy,396); // Double open + if (pn == 412) ObjSetMicro(dx,dy,396); // Double open + } + else + { + + if (pn == 75) ObjSetMicro(dx,dy,204); + if (pn == 79) ObjSetMicro(dx,dy,208); + if ((pn == 86) && (object[oi]._otype == OBJ_L1DOORL)) ObjSetMicro(dx,dy,232); + if ((pn == 86) && (object[oi]._otype == OBJ_L1DOORR)) ObjSetMicro(dx,dy,234); + if (pn == 91) ObjSetMicro(dx,dy,215); + if (pn == 93) ObjSetMicro(dx,dy,218); + if (pn == 99) ObjSetMicro(dx,dy,220); + if (pn == 111) ObjSetMicro(dx,dy,222); + if (pn == 113) ObjSetMicro(dx,dy,224); + if (pn == 115) ObjSetMicro(dx,dy,226); + if (pn == 117) ObjSetMicro(dx,dy,228); + if (pn == 119) ObjSetMicro(dx,dy,230); + if (pn == 232) ObjSetMicro(dx,dy,212); // Double open + if (pn == 234) ObjSetMicro(dx,dy,212); // Double open + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void RedoPlayerVision() +{ + int p; + + for (p = 0; p < MAX_PLRS; ++p) { + if (! plr[p].plractive) continue; + if (currlevel != plr[p].plrlevel) continue; + ChangeVisionXY(plr[p]._pvid, plr[p]._px, plr[p]._py); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateL1RDoor(int pnum, int oi, bool sendflag) +{ + int dx, dy; + bool dok; + + app_assert((DWORD)oi < MAXOBJECTS); + if (object[oi]._oVar4 == DOOR_BLOCKED) { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + return; + } + dx = object[oi]._ox; + dy = object[oi]._oy; + if (object[oi]._oVar4 == DOOR_CLOSED) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); + if (currlevel < CRYPTSTART) + { + if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); + } + else + { + if (!deltaload) PlaySfxLoc(CR_DOOROPEN, object[oi]._ox, object[oi]._oy); + } + if (currlevel < CRYPTSTART) + ObjSetMicro(dx,dy,395); + else + ObjSetMicro(dx,dy,209); + if (currlevel < HIVESTART) + dSpecial[dx][dy] = 8; + else + dSpecial[dx][dy] = 2; + ObjSetMicro12(dx,dy-1); + --dx; + object[oi]._oAnimFrame += 2; +#ifdef NO_L5_DOORS + if (currlevel > HIVESTART) + object[oi]._oAnimFrame = -1; +#endif + + object[oi]._oPreFlag = TRUE; + DoorSet(oi, dx, dy); + object[oi]._oVar4 = DOOR_OPEN; + object[oi]._oSelFlag = OSEL_TOP; + RedoPlayerVision(); + } else { + if (currlevel < CRYPTSTART) + { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + } + else + { + if (!deltaload) PlaySfxLoc(CR_DOORCLOS, object[oi]._ox, object[oi]._oy); + } + dok = (dMonster[dx][dy] == 0); + dok = dok && (dItem[dx][dy] == 0); + dok = dok && (dDead[dx][dy] == 0); + if (dok) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); + object[oi]._oVar4 = DOOR_CLOSED; + object[oi]._oSelFlag = OSEL_ALL; + ObjSetMicro(dx,dy,object[oi]._oVar1); + if (currlevel < HIVESTART) + { + if (object[oi]._oVar2 != 50) ObjSetMicro(dx-1,dy,object[oi]._oVar2); + else { + // Double door + if (dPiece[dx-1][dy] == 396) ObjSetMicro(dx-1,dy,411); + else ObjSetMicro(dx-1,dy,object[oi]._oVar2); + } + } + else + { + if (object[oi]._oVar2 != 86) ObjSetMicro(dx-1,dy,object[oi]._oVar2); + else { + // Double door + if (dPiece[dx-1][dy] == 210) ObjSetMicro(dx-1,dy,232); + else ObjSetMicro(dx-1,dy,object[oi]._oVar2); + } + } + object[oi]._oAnimFrame -= 2; + object[oi]._oPreFlag = FALSE; + RedoPlayerVision(); + } else object[oi]._oVar4 = DOOR_BLOCKED; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateL1LDoor(int pnum, int oi, bool sendflag) +{ + int dx, dy; + bool dok; + + app_assert((DWORD)oi < MAXOBJECTS); + if (object[oi]._oVar4 == DOOR_BLOCKED) { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + return; + } + dx = object[oi]._ox; + dy = object[oi]._oy; + if (object[oi]._oVar4 == DOOR_CLOSED) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); + if (currlevel < CRYPTSTART) + { + if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); + } + else + { + if (!deltaload) PlaySfxLoc(CR_DOOROPEN, object[oi]._ox, object[oi]._oy); + } + if (currlevel < CRYPTSTART) + { + if (object[oi]._oVar1 == 214) + ObjSetMicro(dx,dy,408); //Blood + else + ObjSetMicro(dx,dy,393); + } + else + ObjSetMicro(dx,dy,206); + if (currlevel < HIVESTART) + dSpecial[dx][dy] = 7; + else + dSpecial[dx][dy] = 1; + ObjSetMicro12(dx-1,dy); + --dy; + object[oi]._oAnimFrame += 2; +#ifdef NO_L5_DOORS + if (currlevel > HIVESTART) + object[oi]._oAnimFrame = -1; +#endif + object[oi]._oPreFlag = TRUE; + DoorSet(oi, dx, dy); + object[oi]._oVar4 = DOOR_OPEN; + object[oi]._oSelFlag = OSEL_TOP; + RedoPlayerVision(); + } else { + if (currlevel < CRYPTSTART) + { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + } + else + { + if (!deltaload) PlaySfxLoc(CR_DOORCLOS, object[oi]._ox, object[oi]._oy); + } + dok = (dMonster[dx][dy] == 0); + dok = dok && (dItem[dx][dy] == 0); + dok = dok && (dDead[dx][dy] == 0); + if (dok) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); + object[oi]._oVar4 = DOOR_CLOSED; + object[oi]._oSelFlag = OSEL_ALL; + ObjSetMicro(dx,dy,object[oi]._oVar1); + if (currlevel < HIVESTART) + { + if (object[oi]._oVar2 != 50) ObjSetMicro(dx,dy-1,object[oi]._oVar2); + else { + // Double door + if (dPiece[dx][dy-1] == 396) ObjSetMicro(dx,dy-1,412); + else ObjSetMicro(dx,dy-1,object[oi]._oVar2); + } + } + else + { + if (object[oi]._oVar2 != 86) ObjSetMicro(dx,dy-1,object[oi]._oVar2); + else { + // Double door + if (dPiece[dx][dy-1] == 210) ObjSetMicro(dx,dy-1,234); + else ObjSetMicro(dx,dy-1,object[oi]._oVar2); + } + } + + object[oi]._oAnimFrame -= 2; + object[oi]._oPreFlag = FALSE; + RedoPlayerVision(); + } else object[oi]._oVar4 = DOOR_BLOCKED; + } +} + +/*-----------------------------------------------------------------------*/ +// this is the stupidest fix I've ever seen an' I did it! JKE +/*-----------------------------------------------------------------------*/ +void OpenCloseAllDoors() +{ + int i; + BOOL odeltaload = deltaload; + + deltaload = TRUE; + for (i = 0; i < MAXOBJECTS; ++i) + { + if (object[i]._otype == OBJ_L1DOORL) + { + OperateL1LDoor(myplr, i, FALSE); + OperateL1LDoor(myplr, i, FALSE); + } + else + if (object[i]._otype == OBJ_L1DOORR) + { + OperateL1RDoor(myplr, i, FALSE); + OperateL1RDoor(myplr, i, FALSE); + } + } + deltaload = odeltaload; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateL2RDoor(int pnum, int oi, bool sendflag) +{ + int dx, dy; + bool dok; + + app_assert((DWORD)oi < MAXOBJECTS); + if (object[oi]._oVar4 == DOOR_BLOCKED) { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + return; + } + dx = object[oi]._ox; + dy = object[oi]._oy; + if (object[oi]._oVar4 == DOOR_CLOSED) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); + if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); + ObjSetMicro(dx,dy,17); + object[oi]._oAnimFrame += 2; + object[oi]._oPreFlag = TRUE; + object[oi]._oVar4 = DOOR_OPEN; + object[oi]._oSelFlag = OSEL_TOP; + RedoPlayerVision(); + } else { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + dok = (dMonster[dx][dy] == 0); + dok = dok && (dItem[dx][dy] == 0); + dok = dok && (dDead[dx][dy] == 0); + if (dok) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); + object[oi]._oVar4 = DOOR_CLOSED; + object[oi]._oSelFlag = OSEL_ALL; + ObjSetMicro(dx,dy,540); + object[oi]._oAnimFrame -= 2; + object[oi]._oPreFlag = FALSE; + RedoPlayerVision(); + } else object[oi]._oVar4 = DOOR_BLOCKED; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +const void OperateL2LDoor(int pnum, int oi, BOOL sendflag) +{ + int dx, dy; + bool dok; + + app_assert((DWORD)oi < MAXOBJECTS); + if (object[oi]._oVar4 == DOOR_BLOCKED) { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + return; + } + dx = object[oi]._ox; + dy = object[oi]._oy; + if (object[oi]._oVar4 == DOOR_CLOSED) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); + if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); + ObjSetMicro(dx,dy,13); + object[oi]._oAnimFrame += 2; + object[oi]._oPreFlag = TRUE; + object[oi]._oVar4 = DOOR_OPEN; + object[oi]._oSelFlag = OSEL_TOP; + RedoPlayerVision(); + } else { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + dok = (dMonster[dx][dy] == 0); + dok = dok && (dItem[dx][dy] == 0); + dok = dok && (dDead[dx][dy] == 0); + if (dok) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); + object[oi]._oVar4 = DOOR_CLOSED; + object[oi]._oSelFlag = OSEL_ALL; + ObjSetMicro(dx,dy,538); + object[oi]._oAnimFrame -= 2; + object[oi]._oPreFlag = FALSE; + RedoPlayerVision(); + } else object[oi]._oVar4 = DOOR_BLOCKED; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateL3RDoor(int pnum, int oi, bool sendflag) +{ + int dx, dy; + bool dok; + + app_assert((DWORD)oi < MAXOBJECTS); + if (object[oi]._oVar4 == DOOR_BLOCKED) { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + return; + } + dx = object[oi]._ox; + dy = object[oi]._oy; + if (object[oi]._oVar4 == DOOR_CLOSED) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); + if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); + ObjSetMicro(dx,dy,541); + object[oi]._oAnimFrame += 2; + object[oi]._oPreFlag = TRUE; + object[oi]._oVar4 = DOOR_OPEN; + object[oi]._oSelFlag = OSEL_TOP; + RedoPlayerVision(); + } else { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + dok = (dMonster[dx][dy] == 0); + dok = dok && (dItem[dx][dy] == 0); + dok = dok && (dDead[dx][dy] == 0); + if (dok) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); + object[oi]._oVar4 = DOOR_CLOSED; + object[oi]._oSelFlag = OSEL_ALL; + ObjSetMicro(dx,dy,534); + object[oi]._oAnimFrame -= 2; + object[oi]._oPreFlag = FALSE; + RedoPlayerVision(); + } else object[oi]._oVar4 = DOOR_BLOCKED; + } +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void OperateL3LDoor(int pnum, int oi, bool sendflag) +{ + int dx, dy; + bool dok; + + app_assert((DWORD)oi < MAXOBJECTS); + if (object[oi]._oVar4 == DOOR_BLOCKED) { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + return; + } + dx = object[oi]._ox; + dy = object[oi]._oy; + if (object[oi]._oVar4 == DOOR_CLOSED) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_OPENDOOR,oi); + if (!deltaload) PlaySfxLoc(IS_DOOROPEN, object[oi]._ox, object[oi]._oy); + ObjSetMicro(dx,dy,538); + object[oi]._oAnimFrame += 2; + object[oi]._oPreFlag = TRUE; + object[oi]._oVar4 = DOOR_OPEN; + object[oi]._oSelFlag = OSEL_TOP; + RedoPlayerVision(); + } else { + if (!deltaload) PlaySfxLoc(IS_DOORCLOS, object[oi]._ox, object[oi]._oy); + dok = (dMonster[dx][dy] == 0); + dok = dok && (dItem[dx][dy] == 0); + dok = dok && (dDead[dx][dy] == 0); + if (dok) { + if ((pnum == myplr) && sendflag) NetSendCmdParam1(TRUE,CMD_CLOSEDOOR,oi); + object[oi]._oVar4 = DOOR_CLOSED; + object[oi]._oSelFlag = OSEL_ALL; + ObjSetMicro(dx,dy,531); + object[oi]._oAnimFrame -= 2; + object[oi]._oPreFlag = FALSE; + RedoPlayerVision(); + } else object[oi]._oVar4 = DOOR_BLOCKED; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void MonstCheckDoors(int m) +{ + int i, oi, dpx, dpy; + int mx, my; + + mx = monster[m]._mx; + my = monster[m]._my; + if (!(dObject[mx-1][my-1] + || dObject[mx][my-1] + || dObject[mx+1][my-1] + || dObject[mx-1][my] + || dObject[mx+1][my] + || dObject[mx-1][my+1] + || dObject[mx][my+1] + || dObject[mx+1][my+1])) + return; + for (i = 0; i < numobjects; ++i) { + oi = objectactive[i]; + app_assert((DWORD)oi < MAXOBJECTS); + if ((object[oi]._otype == OBJ_L1DOORL) || (object[oi]._otype == OBJ_L1DOORR)) { + if (object[oi]._oVar4 == DOOR_CLOSED) { + dpx = abs(object[oi]._ox - mx); + dpy = abs(object[oi]._oy - my); + if ((dpx == 1) && (dpy <= 1) && (object[oi]._otype == OBJ_L1DOORL)) OperateL1LDoor(myplr, oi, true); + if ((dpx <= 1) && (dpy == 1) && (object[oi]._otype == OBJ_L1DOORR)) OperateL1RDoor(myplr, oi, true); + } + } + if ((object[oi]._otype == OBJ_L2DOORL) || (object[oi]._otype == OBJ_L2DOORR)) { + if (object[oi]._oVar4 == DOOR_CLOSED) { + dpx = abs(object[oi]._ox - mx); + dpy = abs(object[oi]._oy - my); + if ((dpx == 1) && (dpy <= 1) && (object[oi]._otype == OBJ_L2DOORL)) OperateL2LDoor(myplr, oi, true); + if ((dpx <= 1) && (dpy == 1) && (object[oi]._otype == OBJ_L2DOORR)) OperateL2RDoor(myplr, oi, true); + } + } + if ((object[oi]._otype == OBJ_L3DOORL) || (object[oi]._otype == OBJ_L3DOORR)) { + if (object[oi]._oVar4 == DOOR_CLOSED) { + dpx = abs(object[oi]._ox - mx); + dpy = abs(object[oi]._oy - my); + + if ((dpx == 1) && (dpy <= 1) && (object[oi]._otype == OBJ_L3DOORR)) OperateL3RDoor(myplr, oi, true); + if ((dpx <= 1) && (dpy == 1) && (object[oi]._otype == OBJ_L3DOORL)) OperateL3LDoor(myplr, oi, true); + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ObjChangeMap(int x1, int y1, int x2, int y2) +{ + int i,j; + + for (j = y1; j <= y2; ++j) { + for (i = x1; i <= x2; ++i) { + ObjSetMini(i, j, pdungeon[i][j]); + dungeon[i][j] = pdungeon[i][j]; // For automap + } + } + if ((leveltype == 1)&&(currlevel < HIVESTART)) { // JKE + ObjL1Special((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); + AddL1Objs((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); + } + if (leveltype == 2) { + ObjL2Special((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); + AddL2Objs((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ObjChangeMapResync(int x1, int y1, int x2, int y2) +{ + int i,j; + + for (j = y1; j <= y2; ++j) { + for (i = x1; i <= x2; ++i) { + ObjSetMini(i, j, pdungeon[i][j]); + dungeon[i][j] = pdungeon[i][j]; // For automap + } + } + + if ((leveltype == 1)&&(currlevel < HIVESTART)) + ObjL1Special((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); + + if (leveltype == 2) + ObjL2Special((x1 << 1) + DIRTEDGED2, (y1 << 1) + DIRTEDGED2, (x2 << 1) + DIRTEDGED2 + 1, (y2 << 1) + DIRTEDGED2 + 1); + +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateL1Door(int pnum, int i, bool sendflag) +{ + int dpx, dpy; + + app_assert((DWORD)i < MAXOBJECTS); + dpx = abs(object[i]._ox - plr[pnum]._px); + dpy = abs(object[i]._oy - plr[pnum]._py); + if ((dpx == 1) && (dpy <= 1) && (object[i]._otype == OBJ_L1DOORL)) OperateL1LDoor(pnum, i, sendflag); + if ((dpx <= 1) && (dpy == 1) && (object[i]._otype == OBJ_L1DOORR)) OperateL1RDoor(pnum, i, sendflag); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateLever(int pnum, int i) +{ + bool mapflag; + int j, oi, ot; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (!deltaload) PlaySfxLoc(IS_LEVER, object[i]._ox, object[i]._oy); + + // Toggle to on + object[i]._oSelFlag = OSEL_NONE; + ++object[i]._oAnimFrame; + + mapflag = true; + if (currlevel == DIABLO_LEVEL) { + for (j = 0; j < numobjects; ++j) { + oi = objectactive[j]; + ot = object[oi]._otype; + if (ot == OBJ_SWITCHSKL) { + if ((object[i]._oVar8 == object[oi]._oVar8) && (object[oi]._oSelFlag != OSEL_NONE)) + mapflag = FALSE; + } + } + } + if (currlevel == NA_KRUL_LEVEL) + { +// dPiece[Na_Krul.LeverX][Na_Krul.LeverY] = 316; + OpenNaKrul(); + Na_Krul.Lever_Thrown = TRUE; + mapflag = FALSE; + quests[Q_NA_KRUL]._qactive = QUEST_DONE; + } + if (mapflag) ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateBook(int pnum, int i) +{ + int v1, v2, v3; + int j, oi, ot, itm; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if ((setlevel) && (setlvlnum == SL_VILEBETRAYER)) { + bool found = false; + bool dowarp = false; + for (j = 0; j < numobjects; ++j) { + oi = objectactive[j]; + ot = object[oi]._otype; + if ((ot == OBJ_MCIRCLE2) && (object[oi]._oVar6 == OBJWARP1)) { + v1 = 27; + v2 = 29; +// rmw.patch1.start.1/23/97 +// object[oi]._oVar6 == OBJDONEWARP; + object[oi]._oVar6 = OBJDONEWARP; +// rmw.patch1.end.1/23/97 + dowarp = TRUE; + } + if ((ot == OBJ_MCIRCLE2) && (object[oi]._oVar6 == OBJWARP2)) { + v1 = 43; + v2 = 29; +// rmw.patch1.start.1/23/97 +// object[oi]._oVar6 == OBJDONEWARP; + object[oi]._oVar6 = OBJDONEWARP; +// rmw.patch1.end.1/23/97 + dowarp = TRUE; + } + if (dowarp) { + v3 = dPiece[v1][v2]; + ++object[dObject[35][36]-1]._oVar5; + AddMissile(plr[pnum]._px, plr[pnum]._py, v1, v2, plr[pnum]._pdir, MIT_PHASE, MI_ENEMYMONST, pnum, 0, 0); + found = TRUE; + dowarp = FALSE; + } + } + if (!found) return; + } + // Toggle open + object[i]._oSelFlag = OSEL_NONE; + ++object[i]._oAnimFrame; + if ((setlevel) && (setlvlnum == SL_BONECHAMB)) { + __int64 t = 1; + plr[myplr]._pMemSpells |= t << (SPL_GUARDIAN-1); + if (plr[pnum]._pSplLvl[SPL_GUARDIAN] < SPELLCAP) { + ++plr[myplr]._pSplLvl[SPL_GUARDIAN]; + } + quests[Q_SCHAMB]._qactive = QUEST_DONE; + if (!deltaload) PlaySfxLoc(IS_QUESTDN, object[i]._ox, object[i]._oy); + InitDiabloMsg(MSG_INBONE); + AddMissile(plr[myplr]._px, plr[myplr]._py, object[i]._ox - 2, object[i]._oy - 4, plr[myplr]._pdir, MIT_GUARDIAN, MI_ENEMYMONST, myplr, 0, 0); + } + if ((setlevel) && (setlvlnum == SL_VILEBETRAYER)) { + ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + for (itm = 0; itm < numobjects; ++itm) SyncObjectAnim(objectactive[itm]); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateBookLever(int pnum, int i) +{ + int x,y, tren; + + app_assert(gbMaxPlayers == 1); + x = (setpc_x << 1) + DIRTEDGED2; + y = (setpc_y << 1) + DIRTEDGED2; + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (qtextflag) return; + // Check quests + if ((object[i]._otype == OBJ_BLINDBOOK) && (quests[Q_BLIND]._qvar1 == 0)) { + quests[Q_BLIND]._qactive = QUEST_NOTDONE; + quests[Q_BLIND]._qlog = TRUE; + quests[Q_BLIND]._qvar1 = 1; + } + if ((object[i]._otype == OBJ_BLOODBOOK) && (quests[Q_BLOOD]._qvar1 == 0)) { + quests[Q_BLOOD]._qactive = QUEST_NOTDONE; + quests[Q_BLOOD]._qlog = TRUE; + quests[Q_BLOOD]._qvar1 = 1; + SpawnQuestItem(IDI_BLDSTONE, (setpc_x << 1) + 3 + DIRTEDGED2, (setpc_y << 1) + 10 + DIRTEDGED2, FALSE, ISEL_FLR); + SpawnQuestItem(IDI_BLDSTONE, (setpc_x << 1) + 15 + DIRTEDGED2, (setpc_y << 1) + 10 + DIRTEDGED2, FALSE, ISEL_FLR); + SpawnQuestItem(IDI_BLDSTONE, (setpc_x << 1) + 9 + DIRTEDGED2, (setpc_y << 1) + 17 + DIRTEDGED2, FALSE, ISEL_FLR); + } + if ((object[i]._otype == OBJ_STEELTOME) && (quests[Q_WARLORD]._qvar1 == 0)) { + quests[Q_WARLORD]._qactive = QUEST_NOTDONE; + quests[Q_WARLORD]._qlog = TRUE; + quests[Q_WARLORD]._qvar1 = 1; + } + // Change map + if (object[i]._oAnimFrame != object[i]._oVar6) { + if (object[i]._otype != OBJ_BLOODBOOK) ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + if (object[i]._otype == OBJ_BLINDBOOK) { + CreateItem(UID_OPTAMULET, x+5, y+5); + tren = TransVal; + TransVal = 9; + DRLG_MRectTrans(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + TransVal = tren; + } + } + // Toggle open + // object[i]._oSelFlag = OSEL_NONE; + object[i]._oAnimFrame = object[i]._oVar6; + // Display msg + InitQTextMsg(object[i]._oVar7); + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateSChambBk(int pnum, int i) +{ + int textdef,j; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (qtextflag) return; + // object[i]._oSelFlag = OSEL_NONE; + // Change map + if (object[i]._oAnimFrame != object[i]._oVar6) { + ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + for (j = 0; j < numobjects; ++j) SyncObjectAnim(objectactive[j]); + } + // Toggle open + object[i]._oAnimFrame = object[i]._oVar6; + if (quests[Q_SCHAMB]._qactive == QUEST_NOTACTIVE) { + quests[Q_SCHAMB]._qactive = QUEST_NOTDONE; + quests[Q_SCHAMB]._qlog = TRUE; + } + + if (plr[myplr]._pClass == CLASS_WARRIOR) textdef = TXT_WARBONE; + else if (plr[myplr]._pClass == CLASS_ROGUE) textdef = TXT_ROGBONE; + else if (plr[myplr]._pClass == CLASS_SORCEROR) textdef = TXT_SORBONE; + else if (plr[myplr]._pClass == CLASS_MONK) textdef = TXT_MNKBONE; + else if (plr[myplr]._pClass == CLASS_BARD) textdef = TXT_BRDBONE; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) textdef = TXT_BARBONE; + quests[Q_SCHAMB]._qmsg = textdef; + InitQTextMsg(textdef); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateChest(int pnum, int i, bool sendmsg) +{ + int j, mdir, mtype = MIT_ARROW; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (!deltaload) PlaySfxLoc(IS_CHEST, object[i]._ox, object[i]._oy); + object[i]._oSelFlag = OSEL_NONE; + object[i]._oAnimFrame += 2; + if (deltaload) return; + SetRndSeed(object[i]._oRndSeed); + + if (setlevel) { //Create only good items for set levels + for (j = 0; j < object[i]._oVar1; ++j) { + CreateRndItem(object[i]._ox, object[i]._oy, TRUE, sendmsg, FALSE); + } + } else { + for (j = 0; j < object[i]._oVar1; ++j) { + if (object[i]._oVar2) CreateRndItem(object[i]._ox, object[i]._oy, FALSE, sendmsg, FALSE); + else CreateRndUseful(pnum, object[i]._ox, object[i]._oy, sendmsg); + } + } + + if ((object[i]._oTrapFlag) && + (object[i]._otype >= OBJ_TCHEST1) && + (object[i]._otype <= OBJ_TCHEST3)) { + mdir = GetDirection(object[i]._ox, object[i]._oy, plr[pnum]._px, plr[pnum]._py); + switch(object[i]._oVar4) { + case 0: + mtype = MIT_ARROW; + break; + case 1: + mtype = MIT_FARROW; + break; + case 2: + mtype = MIT_NOVA; + break; + case 3: + mtype = MIT_FLAMEBOX; +// SpawnSkeleton(object[i]._oVar2, object[i]._ox, object[i]._oy); + break; + case 4: + mtype = MIT_DISENCHANT; + break; + case 5: + mtype = MIT_MANAREMOVE; + break; +#if defined(HELLFIRE2) + // GWP Another good trap might be acid splatted all around. + case 6: + mtype = MIT_LIGHTBOX; +// SpawnSkeleton(object[i]._oVar2, object[i]._ox, object[i]._oy); + break; +#endif + default: + mtype = MIT_ARROW; + break; + } + AddMissile(object[i]._ox, object[i]._oy, plr[pnum]._px, plr[pnum]._py, mdir, mtype, MI_ENEMYPLR, -1, 0, 0); + object[i]._oTrapFlag = FALSE; + } + if (pnum == myplr) NetSendCmdParam2(FALSE,CMD_PLROPOBJ,pnum,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateMushPatch(int pnum, int i) +{ + int x, y; + + if (!(quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE + && (quests[Q_BKMUSHRM]._qvar1 >= QS_TOMEGIVEN))) // FUNGALTM was given to Witch + { + if (!deltaload && pnum == myplr) { + if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR13); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE13); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE13); + else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK13); + else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD13); + else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN13); + #endif + } + return; + } + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) + return; + if (!deltaload) PlaySfxLoc(IS_CHEST, object[i]._ox, object[i]._oy); + object[i]._oSelFlag = OSEL_NONE; + object[i]._oAnimFrame += 1; + if (deltaload) return; + GetSuperItemLoc(object[i]._ox, object[i]._oy, x, y); + SpawnQuestItem(IDI_MUSHROOM, x,y,0, ISEL_NONE); + quests[Q_BKMUSHRM]._qvar1 = QS_MUSHSPAWNED; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateInnSignChest(int pnum, int i) +{ + int x, y; + + if (!(quests[Q_LTBANNER]._qvar1 == 2)) + { + if (!deltaload && pnum == myplr) { + if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR24); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE24); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE24); + else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK24); + else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD24); + else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN24); + #endif + } + return; + } + + if (object[i]._oSelFlag == OSEL_NONE) + return; + if (!deltaload) PlaySfxLoc(IS_CHEST, object[i]._ox, object[i]._oy); + object[i]._oSelFlag = OSEL_NONE; + object[i]._oAnimFrame += 2; + if (deltaload) return; + GetSuperItemLoc(object[i]._ox, object[i]._oy, x, y); + SpawnQuestItem(IDI_BANNER, x,y,0, ISEL_NONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateSlainHero(int pnum, int i, bool sendmsg) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + object[i]._oSelFlag = OSEL_NONE; + if (deltaload) return; + + if (plr[pnum]._pClass == CLASS_WARRIOR) { + //Create magic breast plate + CreateMagicArmor(object[i]._ox, object[i]._oy, IT_HARMOR, ITEM_BPLATE, FALSE, TRUE); + #if !IS_VERSION(SHAREWARE) + PlaySfxLoc(PS_WARR9, plr[myplr]._px, plr[myplr]._py); + #endif + } else if (plr[pnum]._pClass == CLASS_ROGUE) { + //Create magic long battle bow + CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_BOW, ITEM_STLLONGBOW, FALSE, TRUE); + #if !IS_VERSION(SHAREWARE) + PlaySfxLoc(PS_ROGUE9, plr[myplr]._px, plr[myplr]._py); + #endif + } else if (plr[pnum]._pClass == CLASS_SORCEROR) { + //Create book of lightning + CreateSpellBook(object[i]._ox, object[i]._oy, SPL_LIGHTNING, FALSE, TRUE); + #if !IS_VERSION(SHAREWARE) + PlaySfxLoc(PS_MAGE9, plr[myplr]._px, plr[myplr]._py); + #endif + } else if (plr[pnum]._pClass == CLASS_MONK) { + //Create magic staff + CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_STAFF, ITEM_STLSTAFF, FALSE, TRUE); + #if !IS_VERSION(SHAREWARE) + PlaySfxLoc(PS_MONK9, plr[myplr]._px, plr[myplr]._py); + #endif + } else if (plr[pnum]._pClass == CLASS_BARD) { + //Create special sword. + CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_SWORD, ITEM_BASTSRD, FALSE, TRUE); + #if !IS_VERSION(SHAREWARE) + PlaySfxLoc(PS_BARD9, plr[myplr]._px, plr[myplr]._py); + #endif + } else if (plr[pnum]._pClass == CLASS_BARBARIAN) { + //Create special sword. + CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_AXE, ITEM_BTLAXE, FALSE, TRUE); + #if !IS_VERSION(SHAREWARE) + PlaySfxLoc(PS_BARBARIAN9, plr[myplr]._px, plr[myplr]._py); + #endif + } + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateTrapLvr(int i) +{ + int j, oi; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oAnimFrame == 1) { + // Toggle to on + ++object[i]._oAnimFrame; + for (j = 0; j < numobjects; ++j) { + oi = objectactive[j]; + if ((object[oi]._otype == object[i]._oVar2) && (object[oi]._oVar1 == object[i]._oVar1)) { + object[oi]._oVar2 = 1; + object[oi]._oAnimFlag = FALSE; + } + } + } else { + // Toggle to off + --object[i]._oAnimFrame; + for (j = 0; j < numobjects; ++j) { + oi = objectactive[j]; + if ((object[oi]._otype == object[i]._oVar2) && (object[oi]._oVar1 == object[i]._oVar1)) { + object[oi]._oVar2 = 0; + if (object[oi]._oVar4 != 0) object[oi]._oAnimFlag = TRUE; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateSarc(int pnum, int i, bool sendmsg) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (!deltaload) PlaySfxLoc(IS_SARC, object[i]._ox, object[i]._oy); + object[i]._oSelFlag = OSEL_NONE; + if (deltaload) { + object[i]._oAnimFrame = object[i]._oAnimLen; + return; + } else { + object[i]._oAnimFlag = TRUE; + object[i]._oAnimDelay = 3; + } + SetRndSeed(object[i]._oRndSeed); + if (object[i]._oVar1 <= 2) CreateRndItem(object[i]._ox, object[i]._oy, FALSE, sendmsg, FALSE); + if (object[i]._oVar1 >= 8) SpawnSkeleton(object[i]._oVar2, object[i]._ox, object[i]._oy); + +#if CHEATS + if (itemcheat) + CreateMagicWeapon(object[i]._ox, object[i]._oy, IT_STAFF, ITEM_SHRTSTAFF, FALSE, TRUE); +#endif + + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateL2Door(int pnum, int i, bool sendflag) +{ + int dpx, dpy; + + app_assert((DWORD)i < MAXOBJECTS); + dpx = abs(object[i]._ox - plr[pnum]._px); + dpy = abs(object[i]._oy - plr[pnum]._py); + if ((dpx == 1) && (dpy <= 1) && (object[i]._otype == OBJ_L2DOORL)) OperateL2LDoor(pnum, i, sendflag); + if ((dpx <= 1) && (dpy == 1) && (object[i]._otype == OBJ_L2DOORR)) OperateL2RDoor(pnum, i, sendflag); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateL3Door(int pnum, int i, bool sendflag) +{ + int dpx, dpy; + + app_assert((DWORD)i < MAXOBJECTS); + dpx = abs(object[i]._ox - plr[pnum]._px); + dpy = abs(object[i]._oy - plr[pnum]._py); + if ((dpx == 1) && (dpy <= 1) && (object[i]._otype == OBJ_L3DOORR)) OperateL3RDoor(pnum, i, sendflag); + if ((dpx <= 1) && (dpy == 1) && (object[i]._otype == OBJ_L3DOORL)) OperateL3LDoor(pnum, i, sendflag); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperatePedistal(int pnum, int i) +{ + int jstn; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oVar6 != 3) { + if (PlrHasItem(pnum, IDI_BLDSTONE, jstn)) { + RemoveInvItem(pnum, jstn); + ++object[i]._oAnimFrame; + ++object[i]._oVar6; + } + if (object[i]._oVar6 == 1) { + if (!deltaload) PlaySfxLoc(LS_PUDDLE, object[i]._ox, object[i]._oy); + ObjChangeMap(setpc_x, setpc_y + 3, setpc_x + 2, setpc_y + 7); + } + if (object[i]._oVar6 == 2) { + if (!deltaload) PlaySfxLoc(LS_PUDDLE, object[i]._ox, object[i]._oy); + ObjChangeMap(setpc_x + 6, setpc_y + 3, setpc_x + setpc_w, setpc_y + 7); + } + if (object[i]._oVar6 == 3) { + if (!deltaload) PlaySfxLoc(LS_BLODSTAR, object[i]._ox, object[i]._oy); + ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + byte *setp; + setp = LoadFileInMemSig("Levels\\L2Data\\Blood2.DUN", NULL, 'STPC'); + LoadMapObjs(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + CreateItem(UID_ARMOFVAL, (setpc_x << 1) + 9 + DIRTEDGED2, (setpc_y << 1) + 3 + DIRTEDGED2); + object[i]._oSelFlag = OSEL_NONE; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void TryDisarm(int pnum, int i) +{ + int j, oi, oti; + int trapdisper; + bool checkflag; + + if (pnum == myplr) NewCursor(GLOVE_CURS); + + app_assert((DWORD)i < MAXOBJECTS); + if (!object[i]._oTrapFlag) return; + + trapdisper = (plr[pnum]._pDexterity << 1) - (currlevel * 5); + if (random(154,100) > trapdisper) return; + + for (j = 0; j < numobjects; ++j) { + oi = objectactive[j]; + checkflag = false; + if (object[oi]._otype == OBJ_TRAPL) checkflag = true; + if (object[oi]._otype == OBJ_TRAPR) checkflag = true; + if (checkflag) { + oti = dObject[object[oi]._oVar1][object[oi]._oVar2] - 1; + if (oti == i) { + object[oi]._oVar4 = 1; + object[i]._oTrapFlag = FALSE; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int ItemMiscIdIdx(int imiscid) +{ + int i = 0; + while ((AllItemsList[i].iRnd == IRND_NO) || (AllItemsList[i].iMiscId != imiscid)) ++i; + return(i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateShrine(int pnum, int i, int sType) +{ + int r, xx, yy, idata, sc; + int v1, v2, v3, v4; + __int64 lv, t; + bool done; + + //Fixes any gold cheats + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + SetRndSeed(object[i]._oRndSeed); + object[i]._oSelFlag = OSEL_NONE; + if (! deltaload) { + PlaySfxLoc(sType, object[i]._ox, object[i]._oy); + object[i]._oAnimFlag = TRUE; + object[i]._oAnimDelay = 1; + } else { + object[i]._oAnimFrame = object[i]._oAnimLen; + object[i]._oAnimFlag = FALSE; + } + switch (object[i]._oVar1) { + case 0 : // Mysterious + if (deltaload) return; + if (pnum != myplr) return; + //Subtract 1 from all attributes + ModifyPlrStr(pnum, -1); + ModifyPlrMag(pnum, -1); + ModifyPlrDex(pnum, -1); + ModifyPlrVit(pnum, -1); + //Add 6 to random attribute. We are actually adding 5 since we + //subtracted 1 above. + switch(random(0, 4)) { + case 0: + ModifyPlrStr(pnum, 6); + break; + case 1: + ModifyPlrMag(pnum, 6); + break; + case 2: + ModifyPlrDex(pnum, 6); + break; + case 3: + ModifyPlrVit(pnum, 6); + break; + } + CheckStats(pnum); + InitDiabloMsg(SHRINE_1); + break; + case 1 : // Hidden + v1 = 0; + if (deltaload) return; + if (pnum != myplr) return; + //Find out if player has any items equipped + for (r = 0; r < NUM_INVLOC; ++r) { + if (plr[pnum].InvBody[r]._itype != -1) ++v1; + } + //Add 10 to max and current durability of all equipped items. + if (v1 > 0) { + for (r = 0; r < NUM_INVLOC; ++r) { + if (plr[pnum].InvBody[r]._itype != -1) { + //Ignore any items which are indestructible. + if ((plr[pnum].InvBody[r]._iMaxDur != INFINITE_DUR) && + (plr[pnum].InvBody[r]._iMaxDur != 0)) { + plr[pnum].InvBody[r]._iDurability += 10; + plr[pnum].InvBody[r]._iMaxDur += 10; + if (plr[pnum].InvBody[r]._iDurability > plr[pnum].InvBody[r]._iMaxDur) + plr[pnum].InvBody[r]._iDurability = plr[pnum].InvBody[r]._iMaxDur; + } + } + } + done = false; + while (!done) { + + // JMM.PATCH3 + int numitems = 0; + for( r = 0; r < NUM_INVLOC; ++r ) { + if ( plr[pnum].InvBody[r]._itype != -1 ) + ++numitems; + } + if( !numitems ) { + done = true; + break; + } + // JMM.ENDPATCH3 + + r = random(0, NUM_INVLOC); + if (plr[pnum].InvBody[r]._itype != -1) { + //Ignore any items which are indestructible. + if ((plr[pnum].InvBody[r]._iMaxDur != INFINITE_DUR) && + (plr[pnum].InvBody[r]._iMaxDur != 0)) { + //Subtract 20 from random equipped item. We are actually + //subtracting 10 since we added 10 above. + plr[pnum].InvBody[r]._iDurability -= 20; + plr[pnum].InvBody[r]._iMaxDur -= 20; + if (plr[pnum].InvBody[r]._iDurability <= 0) plr[pnum].InvBody[r]._iDurability = 1; + if (plr[pnum].InvBody[r]._iMaxDur <= 0) plr[pnum].InvBody[r]._iMaxDur = 1; + done = true; + break; + } + } + } + } + InitDiabloMsg(SHRINE_2); + break; + case 2: // Gloomy (Single Player Only) + if (deltaload) return; + if (pnum == myplr) { + if (plr[pnum].HeadItem._itype != -1) plr[pnum].HeadItem._iAC += 2; + if (plr[pnum].BodyItem._itype != -1) plr[pnum].BodyItem._iAC += 2; + if (plr[pnum].Hand1Item._itype != -1) { + if (plr[pnum].Hand1Item._itype == IT_SHIELD) + plr[pnum].Hand1Item._iAC += 2; + else { + --plr[pnum].Hand1Item._iMaxDam; + if (plr[pnum].Hand1Item._iMaxDam < plr[pnum].Hand1Item._iMinDam) + plr[pnum].Hand1Item._iMaxDam = plr[pnum].Hand1Item._iMinDam; + } + } + if (plr[pnum].Hand2Item._itype != -1) { + if (plr[pnum].Hand2Item._itype == IT_SHIELD) + plr[pnum].Hand2Item._iAC += 2; + else { + --plr[pnum].Hand2Item._iMaxDam; + if (plr[pnum].Hand2Item._iMaxDam < plr[pnum].Hand2Item._iMinDam) + plr[pnum].Hand2Item._iMaxDam = plr[pnum].Hand2Item._iMinDam; + } + } + for (r = 0; r < plr[pnum]._pNumInv; ++r) { + switch(plr[pnum].InvList[r]._itype) { + case IT_SHIELD: + case IT_ARMOR: + case IT_MARMOR: + case IT_HARMOR: + case IT_HELM: + plr[pnum].InvList[r]._iAC += 2; + break; + case IT_SWORD: + case IT_AXE: + case IT_BOW: + case IT_MACE: + case IT_STAFF: + --plr[pnum].InvList[r]._iMaxDam; + if (plr[pnum].InvList[r]._iMaxDam < plr[pnum].InvList[r]._iMinDam) + plr[pnum].InvList[r]._iMaxDam = plr[pnum].InvList[r]._iMinDam; + break; + } + } + InitDiabloMsg(SHRINE_3); + } + break; + case 3: // Weird (Single Player Only) + if (deltaload) return; + if (pnum == myplr) { + if ((plr[pnum].Hand1Item._itype != -1) && (plr[pnum].Hand1Item._itype != IT_SHIELD)) + ++plr[pnum].Hand1Item._iMaxDam; + if ((plr[pnum].Hand2Item._itype != -1) && (plr[pnum].Hand2Item._itype != IT_SHIELD)) + ++plr[pnum].Hand2Item._iMaxDam; + for (r = 0; r < plr[pnum]._pNumInv; ++r) { + switch(plr[pnum].InvList[r]._itype) { + case IT_SWORD: + case IT_AXE: + case IT_BOW: + case IT_MACE: + case IT_STAFF: + ++plr[pnum].InvList[r]._iMaxDam; + break; + } + } + InitDiabloMsg(SHRINE_4); + } + break; + case 4: // Magical + case 11: // Supernatural + if (deltaload) return; + //Cast mana shield + AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._px, plr[pnum]._py, + plr[pnum]._pdir, MIT_MANASHIELD, -1, pnum, 0, + (leveltype << 1)); + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_5); + break; + case 5: // Stone + if (deltaload) return; + if (pnum == myplr) { + for (r = 0; r < NUM_INVLOC; ++r) { + if (plr[pnum].InvBody[r]._itype == IT_STAFF) + plr[pnum].InvBody[r]._iCharges = plr[pnum].InvBody[r]._iMaxCharges; + } + for (r = 0; r < plr[pnum]._pNumInv; ++r) { + if (plr[pnum].InvList[r]._itype == IT_STAFF) + plr[pnum].InvList[r]._iCharges = plr[pnum].InvList[r]._iMaxCharges; + } + for (r = 0; r < MAXSPD; ++r) { + if (plr[pnum].SpdList[r]._itype == IT_STAFF) + plr[pnum].SpdList[r]._iCharges = plr[pnum].SpdList[r]._iMaxCharges; + } + InitDiabloMsg(SHRINE_6); + } + break; + case 6: // Religious + if (deltaload) return; + if (pnum == myplr) { + for (r = 0; r < NUM_INVLOC; ++r) { + plr[pnum].InvBody[r]._iDurability = plr[pnum].InvBody[r]._iMaxDur; + } + for (r = 0; r < plr[pnum]._pNumInv; ++r) { + plr[pnum].InvList[r]._iDurability = plr[pnum].InvList[r]._iMaxDur; + } + for (r = 0; r < MAXSPD; ++r) { + plr[pnum].SpdList[r]._iDurability = plr[pnum].SpdList[r]._iMaxDur; + } + InitDiabloMsg(SHRINE_7); + } + break; + case 7: // Enchanted (Levels 1-8 Only) + if (deltaload) return; + if (pnum != myplr) return; + //Get memorized spell count + sc = 0; + lv = 1; + for (r = 1; r <= MAXSPELLS; ++r) { + if (plr[pnum]._pMemSpells & lv) ++sc; + lv = lv << 1; + } + //Only add and subtract if player has more than 1 spell memorized + if (sc > 1) { + //Add one to all memorized spell levels + lv = 1; + for (r = 1; r <= MAXSPELLS; ++r) { + if (plr[pnum]._pMemSpells & lv) { + if (plr[pnum]._pSplLvl[r] < SPELLCAP) { + ++plr[pnum]._pSplLvl[r]; + v1 = r; + } + } + lv = lv << 1; + } + //Subtract 2 from random memorized spell. We are actually subtracting + //1 since we added 1 above. + done = false; + while (!done) { + lv = 1; + r = random(0, MAXSPELLS); + lv = lv << r; + if (plr[pnum]._pMemSpells & lv) { + if (plr[pnum]._pSplLvl[r+1] >= 2) plr[pnum]._pSplLvl[r+1] -= 2; + else plr[pnum]._pSplLvl[r+1] = 0; + done = true; + break; + } + } + } + InitDiabloMsg(SHRINE_8); + break; + case 8: // Thaumaturgic (Single Player Only) + //All chests regenerate + for (r = 0; r < numobjects; ++r) { + v1 = objectactive[r]; + app_assert((DWORD)v1 < MAXOBJECTS); + if (((object[v1]._otype == OBJ_CHEST1) || + (object[v1]._otype == OBJ_CHEST2) || + (object[v1]._otype == OBJ_CHEST3)) && + (object[v1]._oSelFlag == OSEL_NONE)) { + object[v1]._oRndSeed = GetRndSeed(); + object[v1]._oSelFlag = OSEL_FLR; + object[v1]._oAnimFrame -= 2; + } + } + if (deltaload) return; + if (pnum == myplr) InitDiabloMsg(SHRINE_9); + break; + case 9: // Fascinating + if (deltaload) return; + if (pnum != myplr) return; + //Give player fire bolt level +2 + t = 1; + plr[pnum]._pMemSpells |= t << (SPL_FIREBOLT-1); + if (plr[pnum]._pSplLvl[SPL_FIREBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_FIREBOLT] ; + if (plr[pnum]._pSplLvl[SPL_FIREBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_FIREBOLT] ; + //Subtract 1/10 of mana + v1 = plr[pnum]._pMaxManaBase / 10; + v2 = plr[pnum]._pMana - plr[pnum]._pManaBase; + v3 = plr[pnum]._pMaxMana - plr[pnum]._pMaxManaBase; + plr[pnum]._pManaBase -= v1; + plr[pnum]._pMana -= v1; + plr[pnum]._pMaxMana -= v1; + plr[pnum]._pMaxManaBase -= v1; + if ((plr[pnum]._pMana >> MANA_SHIFT) <= 0) { + plr[pnum]._pMana = v2; + plr[pnum]._pManaBase = 0; + } + if ((plr[pnum]._pMaxMana >> MANA_SHIFT) <= 0) { + plr[pnum]._pMaxMana = v3; + plr[pnum]._pMaxManaBase = 0; + } + InitDiabloMsg(SHRINE_10); + break; + case 10: // Cryptic + if (deltaload) return; + //Cast nova + AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._px, plr[pnum]._py, + plr[pnum]._pdir, MIT_NOVA, -1, pnum, 0, (leveltype << 1)); + if (pnum != myplr) return; + //Give full mana + plr[pnum]._pMana = plr[pnum]._pMaxMana; + plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; + InitDiabloMsg(SHRINE_11); + break; + case 12: // Eldritch + if (deltaload) return; + if (pnum == myplr) { + //All health and mana potions become full rejuv. + for (r = 0; r < plr[pnum]._pNumInv; ++r) { + if (plr[pnum].InvList[r]._itype == IT_MISC) { + if ((plr[pnum].InvList[r]._iMiscId == IMID_PLHEAL) || + (plr[pnum].InvList[r]._iMiscId == IMID_PMANA)) { + idata = ItemMiscIdIdx(IMID_REJUV); + SetPlrHandItem(&plr[pnum].HoldItem, idata); + GetPlrHandSeed(&plr[pnum].HoldItem); + plr[pnum].HoldItem._iStatFlag = TRUE; + plr[pnum].InvList[r] = plr[pnum].HoldItem; + } + if ((plr[pnum].InvList[r]._iMiscId == IMID_PHEAL) || + (plr[pnum].InvList[r]._iMiscId == IMID_PFMANA)) { + idata = ItemMiscIdIdx(IMID_FREJUV); + SetPlrHandItem(&plr[pnum].HoldItem, idata); + GetPlrHandSeed(&plr[pnum].HoldItem); + plr[pnum].HoldItem._iStatFlag = TRUE; + plr[pnum].InvList[r] = plr[pnum].HoldItem; + } + } + } + for (r = 0; r < MAXSPD; ++r) { + if (plr[pnum].SpdList[r]._itype == IT_MISC) { + if ((plr[pnum].SpdList[r]._iMiscId == IMID_PLHEAL) || + (plr[pnum].SpdList[r]._iMiscId == IMID_PMANA)) { + idata = ItemMiscIdIdx(IMID_REJUV); + SetPlrHandItem(&plr[pnum].HoldItem, idata); + GetPlrHandSeed(&plr[pnum].HoldItem); + plr[pnum].HoldItem._iStatFlag = TRUE; + plr[pnum].SpdList[r] = plr[pnum].HoldItem; + } + if ((plr[pnum].SpdList[r]._iMiscId == IMID_PHEAL) || + (plr[pnum].SpdList[r]._iMiscId == IMID_PFMANA)) { + idata = ItemMiscIdIdx(IMID_FREJUV); + SetPlrHandItem(&plr[pnum].HoldItem, idata); + GetPlrHandSeed(&plr[pnum].HoldItem); + plr[pnum].HoldItem._iStatFlag = TRUE; + plr[pnum].SpdList[r] = plr[pnum].HoldItem; + } + } + } + InitDiabloMsg(SHRINE_13); + } + break; + case 13: // Eerie + if (deltaload) return; + if (pnum != myplr) return; + //Add 2 to magic + ModifyPlrMag(pnum, 2); + CheckStats(pnum); + InitDiabloMsg(SHRINE_14); + break; + case 14: // Divine + if (deltaload) return; + if (pnum != myplr) return; + //Put this in because full rejuvs are only available from level 7 on. + if ((currlevel << 1) < 7) { + //Create 1 full heal and 1 full mana + CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_PFMANA, FALSE, TRUE); + CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_PHEAL, FALSE, TRUE); + } else { + //Create 2 full rejuv + CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_FREJUV, FALSE, TRUE); + CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_FREJUV, FALSE, TRUE); + } + //Give full mana and life + plr[pnum]._pMana = plr[pnum]._pMaxMana; + plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + InitDiabloMsg(SHRINE_15); + break; + case 15: // Holy + if (deltaload) return; + v4 = 0; + do { + v1 = random(159,DMAXX); + v2 = random(159,DMAXY); + v3 = dPiece[v1][v2]; + ++v4; + if (v4 > (DMAXX*DMAXY)) break; + } while (nSolidTable[v3] != 0 || dObject[v1][v2] != 0 || dMonster[v1][v2] != 0); + //Cast phase + AddMissile(plr[pnum]._px, plr[pnum]._py, v1, v2, plr[pnum]._pdir, + MIT_PHASE, -1, pnum, 0, (leveltype << 1)); + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_16); + break; + case 16: // Sacred + if (deltaload) return; + if (pnum != myplr) return; + //Give player charged bolt level +2 + t = 1; + plr[pnum]._pMemSpells |= t << (SPL_CBOLT-1); + if (plr[pnum]._pSplLvl[SPL_CBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_CBOLT] ; + if (plr[pnum]._pSplLvl[SPL_CBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_CBOLT] ; + //Subtract 1/10 of mana + v1 = plr[pnum]._pMaxManaBase / 10; + v2 = plr[pnum]._pMana - plr[pnum]._pManaBase; + v3 = plr[pnum]._pMaxMana - plr[pnum]._pMaxManaBase; + plr[pnum]._pManaBase -= v1; + plr[pnum]._pMana -= v1; + plr[pnum]._pMaxMana -= v1; + plr[pnum]._pMaxManaBase -= v1; + if ((plr[pnum]._pMana >> MANA_SHIFT) <= 0) { + plr[pnum]._pMana = v2; + plr[pnum]._pManaBase = 0; + } + if ((plr[pnum]._pMaxMana >> MANA_SHIFT) <= 0) { + plr[pnum]._pMaxMana = v3; + plr[pnum]._pMaxManaBase = 0; + } + InitDiabloMsg(SHRINE_17); + break; + case 17: // Spiritual + if (deltaload) return; + if (pnum != myplr) return; + //Fill inventory with gold + for (r = 0; r < MAXINV; ++r) { + if (plr[pnum].InvGrid[r] == 0) { + v2 = (leveltype * 5) + random(160,leveltype * 10); + v1 = plr[pnum]._pNumInv; + plr[pnum].InvList[v1] = golditem; + plr[pnum].InvList[v1]._iSeed = GetRndSeed(); + ++plr[pnum]._pNumInv; + plr[pnum].InvGrid[r] = plr[pnum]._pNumInv; + plr[pnum].InvList[v1]._ivalue = v2; + plr[pnum]._pGold += v2; + SetGoldCurs(pnum, v1); + } + } + InitDiabloMsg(SHRINE_18); + break; + case 18: // Spooky (Multi Player Only) + if (deltaload) return; + if (pnum == myplr) InitDiabloMsg(SHRINE_19); + else { + //Full rejuv for other players + InitDiabloMsg(SHRINE_19B); + plr[myplr]._pHitPoints = plr[myplr]._pMaxHP; + plr[myplr]._pHPBase = plr[myplr]._pMaxHPBase; + plr[myplr]._pMana = plr[myplr]._pMaxMana; + plr[myplr]._pManaBase = plr[myplr]._pMaxManaBase; + } + break; + case 19: // Abandoned + if (deltaload) return; + if (pnum != myplr) return; + //Add 2 to dexterity + ModifyPlrDex(pnum, 2); + CheckStats(pnum); + if (pnum == myplr) InitDiabloMsg(SHRINE_20); + break; + case 20: // Creepy + if (deltaload) return; + if (pnum != myplr) return; + //Add 2 to strength + ModifyPlrStr(pnum, 2); + CheckStats(pnum); + if (pnum == myplr) InitDiabloMsg(SHRINE_21); + break; + case 21: // Quiet + if (deltaload) return; + if (pnum != myplr) return; + //Add 2 to vitality + ModifyPlrVit(pnum, 2); + CheckStats(pnum); + if (pnum == myplr) InitDiabloMsg(SHRINE_22); + break; + case 22: // Secluded + if (deltaload) return; + if (pnum == myplr) { + //Complete automap for current level + for (yy = 0; yy < AUTOMAPY; ++yy) { + for (xx = 0; xx < AUTOMAPX; ++xx) automapview[xx][yy] = TRUE; + } + InitDiabloMsg(SHRINE_23); + } + break; + case 23: // Ornate + if (deltaload) return; + if (pnum != myplr) return; + //Give player holy bolt level +2 + t = 1; + plr[pnum]._pMemSpells |= t << (SPL_HBOLT-1); + if (plr[pnum]._pSplLvl[SPL_HBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_HBOLT] ; + if (plr[pnum]._pSplLvl[SPL_HBOLT] < SPELLCAP) ++plr[pnum]._pSplLvl[SPL_HBOLT] ; + //Subtract 1/10 of mana + v1 = plr[pnum]._pMaxManaBase / 10; + v2 = plr[pnum]._pMana - plr[pnum]._pManaBase; + v3 = plr[pnum]._pMaxMana - plr[pnum]._pMaxManaBase; + plr[pnum]._pManaBase -= v1; + plr[pnum]._pMana -= v1; + plr[pnum]._pMaxMana -= v1; + plr[pnum]._pMaxManaBase -= v1; + if ((plr[pnum]._pMana >> MANA_SHIFT) <= 0) { + plr[pnum]._pMana = v2; + plr[pnum]._pManaBase = 0; + } + if ((plr[pnum]._pMaxMana >> MANA_SHIFT) <= 0) { + plr[pnum]._pMaxMana = v3; + plr[pnum]._pMaxManaBase = 0; + } + InitDiabloMsg(SHRINE_24); + break; + case 24: // Glimmering + if (deltaload) return; + if (pnum != myplr) return; + //All items are identified + for (r = 0; r < NUM_INVLOC; ++r) { + if ((plr[pnum].InvBody[r]._iMagical != IMAGIC_NONE) && !plr[pnum].InvBody[r]._iIdentified) + plr[pnum].InvBody[r]._iIdentified = TRUE; + } + for (r = 0; r < plr[pnum]._pNumInv; ++r) { + if ((plr[pnum].InvList[r]._iMagical != IMAGIC_NONE) && !plr[pnum].InvList[r]._iIdentified) + plr[pnum].InvList[r]._iIdentified = TRUE; + } + for (r = 0; r < MAXSPD; ++r) { + if ((plr[pnum].SpdList[r]._iMagical != IMAGIC_NONE) && !plr[pnum].SpdList[r]._iIdentified) + plr[pnum].SpdList[r]._iIdentified = TRUE; + } + InitDiabloMsg(SHRINE_25); + break; + case 25: // Tainted (Multi Player Only) + if (deltaload) return; + if (pnum == myplr) InitDiabloMsg(SHRINE_26); + else { + //All other players get +1 to 3 random stats and -1 to other + InitDiabloMsg(SHRINE_26B); + r = random(155,4); + if (r == 0) v1 = 1; + else v1 = -1; + if (r == 1) v2 = 1; + else v2 = -1; + if (r == 2) v3 = 1; + else v3 = -1; + if (r == 3) v4 = 1; + else v4 = -1; + ModifyPlrStr(myplr, v1); + ModifyPlrMag(myplr, v2); + ModifyPlrDex(myplr, v3); + ModifyPlrVit(myplr, v4); + CheckStats(myplr); + } + break; + case 26: // Oily + // Increase good stats by 1. + if (deltaload) return; + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_27); + switch(plr[myplr]._pClass) + { + case CLASS_SORCEROR: + ModifyPlrMag(myplr,2); + break; + case CLASS_ROGUE: + ModifyPlrDex(myplr,2); + break; + case CLASS_WARRIOR: + ModifyPlrStr(myplr,2); + break; + case CLASS_BARBARIAN: + ModifyPlrVit(myplr,2); + break; + case CLASS_MONK: + ModifyPlrStr(myplr,1); + ModifyPlrDex(myplr,1); + break; + case CLASS_BARD: + ModifyPlrDex(myplr,1); + ModifyPlrMag(myplr,1); + break; + } + CheckStats(pnum); + AddMissile(object[i]._ox, object[i]._oy, plr[myplr]._px, plr[myplr]._py, plr[myplr]._pdir, MIT_FIREWALL, MI_ENEMYPLR, 0, 2 + (2 * currlevel), 0); + break; + case 27: // Glowing + { + if (deltaload) return; + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_28); + long CurrentExp = plr[myplr]._pExperience; + long ModMagic; + + if (CurrentExp > 5000) + { + ModMagic = 5; + CurrentExp = (long)(CurrentExp * 0.95); + } + else + { + ModMagic = CurrentExp/1000; + CurrentExp = 0; + + } + + ModifyPlrMag(myplr, ModMagic); + plr[myplr]._pExperience = CurrentExp; + CheckStats(pnum); + + } + break; + case 28: // Mendicant's + { + if (deltaload) return; + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_29); + long const HalfCurrentGold = plr[myplr]._pGold / 2; + + AddPlrExperience(myplr, plr[myplr]._pLevel, HalfCurrentGold); + TakePlrsMoney(HalfCurrentGold); // uses global var myplr. + CheckStats(pnum); + } + break; + case 29: // Sparkling + if (deltaload) return; + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_30); + AddPlrExperience(myplr, plr[myplr]._pLevel, 1000 * currlevel); + AddMissile(object[i]._ox, object[i]._oy, plr[myplr]._px, plr[myplr]._py, plr[myplr]._pdir, MIT_FLASH, MI_ENEMYPLR, 0, 2 + (3 * currlevel), 0); + CheckStats(pnum); + break; + case 30: // Town + if (deltaload) return; + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_31); + AddMissile(object[i]._ox, object[i]._oy, plr[myplr]._px, plr[myplr]._py, plr[myplr]._pdir, MIT_TOWN, MI_ENEMYPLR, 0, 0, 0); + break; + case 31: // Shimmering + if (deltaload) return; + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_32); + plr[pnum]._pMana = plr[pnum]._pMaxMana; // restore to full mana. + plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; + break; + case 32: // Solar + { + if (deltaload) return; + if (pnum != myplr) return; + time_t time_of_day = time(0); + struct tm * const tmbuf = localtime(&time_of_day); + + if (tmbuf->tm_hour > 20 || tmbuf->tm_hour < 4) + { + InitDiabloMsg(SHRINE_33D); + ModifyPlrVit(myplr, 2); + } + else if (tmbuf->tm_hour > 18) + { + InitDiabloMsg(SHRINE_33C); + ModifyPlrMag(myplr, 2); + } + else if (tmbuf->tm_hour > 12) + { + InitDiabloMsg(SHRINE_33B); + ModifyPlrStr(myplr, 2); + } + else if (tmbuf->tm_hour > 4) + { + InitDiabloMsg(SHRINE_33A); + ModifyPlrDex(myplr, 2); + } + + CheckStats(pnum); + } + break; + case 33: // Murphy's + { + if (deltaload) return; + if (pnum != myplr) return; + InitDiabloMsg(SHRINE_34); + long i; + long broken = 0; + + for (i = 0; i < 7; ++i) + { + ItemStruct * const itm = &plr[myplr].InvBody[i]; + + if (itm->_itype == -1) continue; + + if (random(0,3) == 0 + && itm->_iDurability != INFINITE_DUR + && itm->_iDurability != 0) // There are two values for infinite durablity !!! + { + // Randomly break something. + itm->_iDurability /= 2; + broken = 1; + break; + } + } + + if (!broken) + { + long const ThirdCurrentGold = plr[myplr]._pGold / 3; + TakePlrsMoney(ThirdCurrentGold); // uses global var myplr. + } + } + break; + } + CalcPlrInv(pnum, TRUE); + force_redraw = FULLDRAW; + if (pnum == myplr) NetSendCmdParam2(FALSE,CMD_PLROPOBJ,pnum,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateSkelBook(int pnum, int i, bool sendmsg) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (!deltaload) PlaySfxLoc(IS_ISCROL, object[i]._ox, object[i]._oy); + object[i]._oSelFlag = OSEL_NONE; + object[i]._oAnimFrame += 2; + if (deltaload) return; + SetRndSeed(object[i]._oRndSeed); + if (random(161,5)) CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_SCROLL, sendmsg, FALSE); + else CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_BOOK, sendmsg, FALSE); + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateBookCase(int pnum, int i, bool sendmsg) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (!deltaload) PlaySfxLoc(IS_ISCROL, object[i]._ox, object[i]._oy); + object[i]._oSelFlag = OSEL_NONE; + object[i]._oAnimFrame -= 2; + if (deltaload) return; + SetRndSeed(object[i]._oRndSeed); + CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_MISC, IMID_BOOK, sendmsg, FALSE); + if (QuestStatus(Q_ZHAR)) { + if (monster[4].mName == UniqMonst[MU_ZHAR].mName) { + if ((monster[4]._msquelch == 255) && (monster[4]._mhitpoints != 0)) { + monster[4].mtalkmsg = TXT_ZHAR2; + M_StartStand(0, monster[4]._mdir); + monster[4]._mgoal = MG_ATTACK2; + monster[4]._mmode = MM_TALK; + } + } + } + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateDecap(int pnum, int i, bool sendmsg) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + object[i]._oSelFlag = OSEL_NONE; + if (deltaload) return; + SetRndSeed(object[i]._oRndSeed); + CreateRndItem(object[i]._ox, object[i]._oy, FALSE, sendmsg, FALSE); + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateArmorStand(int pnum, int i, bool sendmsg) +{ + int uniqueRnd; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + object[i]._oSelFlag = OSEL_NONE; + ++object[i]._oAnimFrame; + if (deltaload) return; + SetRndSeed(object[i]._oRndSeed); + + //Randomize uniqueness + uniqueRnd = random(0, 2); + //Create an appropriate armor for the current level + if (currlevel <= 5) { + //Create unique only IT_ARMOR + CreateTypeItem(object[i]._ox, object[i]._oy, TRUE, IT_ARMOR, IMID_NONE, sendmsg, FALSE); + } else if (currlevel >= 6 && currlevel <= 9) { + //Create random unique IT_MARMOR + CreateTypeItem(object[i]._ox, object[i]._oy, uniqueRnd, IT_MARMOR, IMID_NONE, sendmsg, FALSE); + } else if (currlevel >= 10 && currlevel <= 12) { + //Create non-unique IT_HARMOR + CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, IT_HARMOR, IMID_NONE, sendmsg, FALSE); + } else if (currlevel >= 13 && currlevel <= 16) { + //Create unique IT_HARMOR + CreateTypeItem(object[i]._ox, object[i]._oy, TRUE, IT_HARMOR, IMID_NONE, sendmsg, FALSE); + } else if (currlevel >= 17) { + //Use the uniques for now, but we will add our own specifics JKE 7/30 + CreateTypeItem(object[i]._ox, object[i]._oy, TRUE, IT_HARMOR, IMID_NONE, sendmsg, FALSE); + } + + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static int FindValidShrine(int i) +/*-----------------------------------------------------------------------* +** Description: Used by OperateGoatShrine and OperateCauldron to find a +** usable shrine function. +** Input: i = Object index +** Return: Shrine function index. +**-----------------------------------------------------------------------*/ +{ + int rv; + bool done = false; + + //Search until we find a valid shrine type. Ignore Thaumaturgic shrine + //because it could possibly screw up the animation. + do { + rv = random(0, NUMSHRINETYPES); + if ((currlevel >= shrineminlvl[rv]) && + (currlevel <= shrinemaxlvl[rv]) && + (rv != 8)) { + done = true; + } + if (done) { + if ((gbMaxPlayers != 1) && (shrineavail[rv] == SHRINE_SINGLE)) { + done = FALSE; + } else if ((gbMaxPlayers == 1) && (shrineavail[rv] == SHRINE_MULTI)) { + done = FALSE; + } else done = TRUE; //We found a shrine type we can use. + } + } while (!done); + + return rv; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateGoatShrine(int pnum, int i, int sType) +{ + app_assert((DWORD)i < MAXOBJECTS); + SetRndSeed(object[i]._oRndSeed); + object[i]._oVar1 = FindValidShrine(i); + OperateShrine(pnum, i, sType); + object[i]._oAnimDelay = 2; + force_redraw = FULLDRAW; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateCauldron(int pnum, int i, int sType) +{ + app_assert((DWORD)i < MAXOBJECTS); + SetRndSeed(object[i]._oRndSeed); + object[i]._oVar1 = FindValidShrine(i); + OperateShrine(pnum, i, sType); + object[i]._oAnimFrame = 3; + object[i]._oAnimFlag = FALSE; + force_redraw = FULLDRAW; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static bool OperateFountains(int pnum, int i) +{ + int ii; + bool rv = false; + + app_assert((DWORD)i < MAXOBJECTS); + SetRndSeed(object[i]._oRndSeed); + + switch(object[i]._otype) { + case OBJ_PURIFYINGFTN: + if (deltaload) return rv; + if (pnum != myplr) return rv; + if (plr[pnum]._pMana < plr[pnum]._pMaxMana) { + PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); + //Add 1 Mana point + plr[pnum]._pMana += (1 << MANA_SHIFT); + plr[pnum]._pManaBase += (1 << MANA_SHIFT); + if (plr[pnum]._pMana > plr[pnum]._pMaxMana) { + plr[pnum]._pMana = plr[pnum]._pMaxMana; + plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; + } + rv = true; + } else if (!deltaload) PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); + break; + case OBJ_BLOODFTN: + if (deltaload) return rv; + if (pnum != myplr) return rv; + if (plr[pnum]._pHitPoints < plr[pnum]._pMaxHP) { + PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); + //Add 1 HP point + plr[pnum]._pHitPoints += (1 << HP_SHIFT); + plr[pnum]._pHPBase += (1 << HP_SHIFT); + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) { + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + } + rv = true; + } else if (!deltaload) PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); + break; + case OBJ_MURKYFTN: + if (object[i]._oSelFlag != OSEL_NONE) { + if (!deltaload) PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); + object[i]._oSelFlag = OSEL_NONE; + if (deltaload) return rv; + //Casts infravision + AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._px, plr[pnum]._py, + plr[pnum]._pdir, MIT_INFRA, -1, pnum, 0, + (leveltype << 1)); + rv = true; + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); + } + break; + case OBJ_TEARFTN: + if (object[i]._oSelFlag != OSEL_NONE) { + int rndVal; + int statVal = -1; + int saveRnd = -1; + int status = FALSE; + ii = 0; + if (!deltaload) PlaySfxLoc(LS_FOUNTAIN, object[i]._ox, object[i]._oy); + object[i]._oSelFlag = OSEL_NONE; + if (deltaload) return rv; + if (pnum != myplr) return rv; + //-1 to random stat, +1 to another + do { + if ((rndVal = random(0, 4)) != saveRnd) { + switch(rndVal) { + case 0: + ModifyPlrStr(pnum, statVal); + break; + case 1: + ModifyPlrMag(pnum, statVal); + break; + case 2: + ModifyPlrDex(pnum, statVal); + break; + case 3: + ModifyPlrVit(pnum, statVal); + break; + } + saveRnd = rndVal; + statVal = 1; + ++ii; + } + if (ii > 1) status = TRUE; + } while(!status); + CheckStats(pnum); + rv = true; + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); + } + break; + } + force_redraw = FULLDRAW; + return rv; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateWeaponRack(int pnum, int i, bool sendmsg) +{ + int weaponType, sfxType; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + SetRndSeed(object[i]._oRndSeed); + + //Choose random weapon/sfx type + switch((random(0, 4)+1)) { + case 1: + weaponType = IT_SWORD; + sfxType = IS_FSWOR; + break; + case 2: + weaponType = IT_AXE; + sfxType = IS_FAXE; + break; + case 3: + weaponType = IT_BOW; + sfxType = IS_FBOW; + break; + case 4: + weaponType = IT_MACE; + sfxType = IS_FAXE; + break; + } + + object[i]._oSelFlag = OSEL_NONE; + ++object[i]._oAnimFrame; + if (deltaload) return; + + //Create a random weapon. Create unique weapons from level 4 down. + if (leveltype > 1) CreateTypeItem(object[i]._ox, object[i]._oy, TRUE, weaponType, IMID_NONE, sendmsg, FALSE); + else CreateTypeItem(object[i]._ox, object[i]._oy, FALSE, weaponType, IMID_NONE, sendmsg, FALSE); + + if (pnum == myplr) NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateStoryBook(int pnum, int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (deltaload) return; + if (qtextflag) return; + if (pnum != myplr) return; + object[i]._oAnimFrame = object[i]._oVar4; + PlaySfxLoc(IS_ISCROL, object[i]._ox, object[i]._oy); + + if ((object[i]._oVar8 != 0) && (currlevel == NA_KRUL_LEVEL)) + { + if ((Na_Krul.Lever_Thrown != TRUE) && (quests[Q_NA_KRUL]._qactive != QUEST_DONE)) + if(HCheckSpell(object[i]._oVar8)) + { + NetSendCmd(FALSE,CMD_OPEN_NAKRUL); + return; + } + } + else if (currlevel >= CRYPTSTART) + { + quests[Q_NA_KRUL]._qactive = QUEST_NOTDONE; + quests[Q_NA_KRUL]._qlog = TRUE; + quests[Q_NA_KRUL]._qmsg = object[i]._oVar2; + } + + InitQTextMsg(object[i]._oVar2); + NetSendCmdParam1(FALSE,CMD_OPERATEOBJ,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void OperateLazStand(int pnum, int i) +{ + int x, y; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; + if (deltaload) return; + if (qtextflag) return; + if (pnum != myplr) return; + ++object[i]._oAnimFrame; + object[i]._oSelFlag = OSEL_NONE; + GetSuperItemLoc(object[i]._ox, object[i]._oy, x, y); + SpawnQuestItem(IDI_LAZSTAFF, x, y, 0, ISEL_NONE); + //quests[Q_BKMUSHRM]._qvar1 = QS_MUSHSPAWNED; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void OperateObject(int pnum, int i, BOOL TeleFlag) +{ + bool senditemmsg; + + if (pnum == myplr) senditemmsg = true; + else senditemmsg = false; + + app_assert((DWORD)i < MAXOBJECTS); + switch (object[i]._otype) { + case OBJ_L1DOORL : + case OBJ_L1DOORR : + if (TeleFlag) { + if (object[i]._otype == OBJ_L1DOORL) OperateL1LDoor(pnum, i, true); + if (object[i]._otype == OBJ_L1DOORR) OperateL1RDoor(pnum, i, true); + } else { + if (pnum == myplr) OperateL1Door(pnum, i, TRUE); + } + break; + case OBJ_L2DOORL : + case OBJ_L2DOORR : + if (TeleFlag) { + if (object[i]._otype == OBJ_L2DOORL) OperateL2LDoor(pnum, i, true); + if (object[i]._otype == OBJ_L2DOORR) OperateL2RDoor(pnum, i, true); + } else { + if (pnum == myplr) OperateL2Door(pnum, i, TRUE); + } + break; + case OBJ_L3DOORL : + case OBJ_L3DOORR : + if (TeleFlag) { + if (object[i]._otype == OBJ_L3DOORL) OperateL3LDoor(pnum, i, true); + if (object[i]._otype == OBJ_L3DOORR) OperateL3RDoor(pnum, i, true); + } else { + if (pnum == myplr) OperateL3Door(pnum, i, TRUE); + } + break; + case OBJ_SWITCHSKL: + case OBJ_LEVER : + OperateLever(pnum, i); + break; + case OBJ_BOOK2L: + OperateBook(pnum, i); + break; + case OBJ_BOOK2R: + OperateSChambBk(pnum, i); + break; + case OBJ_CHEST1: + case OBJ_CHEST2: + case OBJ_CHEST3: + case OBJ_TCHEST1: + case OBJ_TCHEST2: + case OBJ_TCHEST3: + OperateChest(pnum, i, senditemmsg); + break; + case OBJ_SARC: + OperateSarc(pnum, i, senditemmsg); + break; + case OBJ_FLAMELVR: + OperateTrapLvr(i); + break; +// case OBJ_BOOKLVR: + case OBJ_BLINDBOOK: + case OBJ_BLOODBOOK: + case OBJ_STEELTOME: + OperateBookLever(pnum, i); + break; + case OBJ_SHRINEL: + case OBJ_SHRINER: + OperateShrine(pnum, i, IS_MAGIC); + break; + case OBJ_SKELBOOK: + case OBJ_BOOKSTAND: + OperateSkelBook(pnum, i, senditemmsg); + break; + case OBJ_BOOKCASEL: + case OBJ_BOOKCASER: + OperateBookCase(pnum, i, senditemmsg); + break; + case OBJ_DECAP: + OperateDecap(pnum, i, senditemmsg); + break; + case OBJ_ARMORSTAND: + case OBJ_WARARMOR: + OperateArmorStand(pnum, i, senditemmsg); + break; + case OBJ_GOATSHRINE: + OperateGoatShrine(pnum, i, LS_GSHRINE); + break; + case OBJ_CAULDRON: + OperateCauldron(pnum, i, LS_CALDRON); + break; + case OBJ_MURKYFTN: + case OBJ_TEARFTN: + case OBJ_BLOODFTN: + case OBJ_PURIFYINGFTN: + OperateFountains(pnum, i); + break; + case OBJ_STORYBOOK: + OperateStoryBook(pnum, i); + break; + case OBJ_PEDISTAL: + OperatePedistal(pnum, i); + break; + case OBJ_WARWEAP: + case OBJ_WEAPONRACK: + OperateWeaponRack(pnum, i, senditemmsg); + break; + case OBJ_MUSHPATCH: + OperateMushPatch(pnum, i); + break; + case OBJ_LAZSTAND: + OperateLazStand(pnum, i); + break; + case OBJ_SLAINHERO: + OperateSlainHero(pnum, i, senditemmsg); + break; + case OBJ_SIGNCHEST: + OperateInnSignChest(pnum, i); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncOpL1Door(int pnum, int cmd, int i) +{ + if (pnum == myplr) return; + bool opok = false; + app_assert((DWORD)i < MAXOBJECTS); + if ((cmd == CMD_OPENDOOR) && (object[i]._oVar4 == DOOR_CLOSED)) opok = TRUE; + if ((cmd == CMD_CLOSEDOOR) && (object[i]._oVar4 == DOOR_OPEN)) opok = TRUE; + if (opok) { + if (object[i]._otype == OBJ_L1DOORL) OperateL1LDoor(-1, i, false); + if (object[i]._otype == OBJ_L1DOORR) OperateL1RDoor(-1, i, false); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncOpL2Door(int pnum, int cmd, int i) +{ + if (pnum == myplr) return; + bool opok = false; + app_assert((DWORD)i < MAXOBJECTS); + if ((cmd == CMD_OPENDOOR) && (object[i]._oVar4 == DOOR_CLOSED)) opok = true; + if ((cmd == CMD_CLOSEDOOR) && (object[i]._oVar4 == DOOR_OPEN)) opok = true; + if (opok) { + if (object[i]._otype == OBJ_L2DOORL) OperateL2LDoor(-1, i, false); + if (object[i]._otype == OBJ_L2DOORR) OperateL2RDoor(-1, i, false); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncOpL3Door(int pnum, int cmd, int i) +{ + if (pnum == myplr) return; + bool opok = false; + app_assert((DWORD)i < MAXOBJECTS); + if ((cmd == CMD_OPENDOOR) && (object[i]._oVar4 == DOOR_CLOSED)) opok = true; + if ((cmd == CMD_CLOSEDOOR) && (object[i]._oVar4 == DOOR_OPEN)) opok = true; + if (opok) { + if (object[i]._otype == OBJ_L3DOORL) OperateL3LDoor(-1, i, false); + if (object[i]._otype == OBJ_L3DOORR) OperateL3RDoor(-1, i, false); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncOpObject(int pnum, int cmd, int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + switch (object[i]._otype) { + case OBJ_L1DOORL : + case OBJ_L1DOORR : + SyncOpL1Door(pnum, cmd, i); + break; + case OBJ_L2DOORL : + case OBJ_L2DOORR : + SyncOpL2Door(pnum, cmd, i); + break; + case OBJ_L3DOORL : + case OBJ_L3DOORR : + SyncOpL3Door(pnum, cmd, i); + break; + case OBJ_SWITCHSKL: + case OBJ_LEVER : + OperateLever(pnum, i); + break; + case OBJ_CHEST1: + case OBJ_CHEST2: + case OBJ_CHEST3: + case OBJ_TCHEST1: + case OBJ_TCHEST2: + case OBJ_TCHEST3: + OperateChest(pnum, i, FALSE); + break; + case OBJ_SARC: + OperateSarc(pnum, i, FALSE); + break; +// case OBJ_BOOKLVR: + case OBJ_BLINDBOOK: + case OBJ_BLOODBOOK: + case OBJ_STEELTOME: + OperateBookLever(pnum, i); + break; + case OBJ_SHRINEL: + case OBJ_SHRINER: + OperateShrine(pnum, i, IS_MAGIC); + break; + case OBJ_SKELBOOK: + case OBJ_BOOKSTAND: + OperateSkelBook(pnum, i, FALSE); + break; + case OBJ_BOOKCASEL: + case OBJ_BOOKCASER: + OperateBookCase(pnum, i, FALSE); + break; + case OBJ_DECAP: + OperateDecap(pnum, i, FALSE); + break; + case OBJ_ARMORSTAND: + case OBJ_WARARMOR: + OperateArmorStand(pnum, i, FALSE); + break; + case OBJ_GOATSHRINE: + OperateGoatShrine(pnum, i, LS_GSHRINE); + break; + case OBJ_CAULDRON: + OperateCauldron(pnum, i, LS_CALDRON); + break; + case OBJ_MURKYFTN: + case OBJ_TEARFTN: + OperateFountains(pnum, i); + break; + case OBJ_STORYBOOK: + OperateStoryBook(pnum, i); + break; + case OBJ_PEDISTAL: + OperatePedistal(pnum, i); + break; + case OBJ_WARWEAP: + case OBJ_WEAPONRACK: + OperateWeaponRack(pnum, i, FALSE); + break; + case OBJ_MUSHPATCH: + OperateMushPatch(pnum, i); + break; + case OBJ_SLAINHERO: + OperateSlainHero(pnum, i, FALSE); + break; + case OBJ_SIGNCHEST: + OperateInnSignChest(pnum, i); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void BreakCrux(int i) +{ + int j, ot, oi; + bool mapflag; + + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oAnimFlag = TRUE; + object[i]._oAnimFrame = 1; + object[i]._oAnimDelay = 1; + object[i]._oSolidFlag = TRUE; + object[i]._oMissFlag = TRUE; + object[i]._oBreak = OBJ_BROKEN; + object[i]._oSelFlag = OSEL_NONE; + + mapflag = true; + for (j = 0; j < numobjects; ++j) { + oi = objectactive[j]; + ot = object[oi]._otype; + if ((ot == OBJ_CRUX1) || (ot == OBJ_CRUX2) || (ot == OBJ_CRUX3)) { + if (object[i]._oVar8 == object[oi]._oVar8) { + if (object[oi]._oBreak != OBJ_BROKEN) mapflag = false; + } + } + } + + if (mapflag) { + if (!deltaload) PlaySfxLoc(IS_LEVER, object[i]._ox, object[i]._oy); + ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +// DKT971012: Gary has items.cpp checked out; this should go there + +void RndUnique(int x, int y, int level) +{ + int uil[MAXUITEMS]; + int i, numui = 0; + + for (i=UID_LGTFORGE+1; i < MAXUITEMS && UniqueItemList[i].UIItemId != -1; ++i) + { + if (level*2 >= UniqueItemList[i].UIMinLvl) + uil[numui++] = i; + } + + if (numui > 0) + { + int uitem = uil[random(0, numui)]; + SpawnUnique(uitem, x, y); + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void BreakBarrel(int pnum, int i, int dam, BOOL forcebreak, BOOL sendmsg) +{ + int x, y, oi; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) return; // already broken? + if (forcebreak) { + object[i]._oVar1 = 0; // force it to bust open + } else { + object[i]._oVar1 -= dam; // normal damage + // if someone else is breaking the object, and it wasn't a force break + // message, then it hasn't broken yet. + if ((pnum != myplr) && (object[i]._oVar1 <= 0)) object[i]._oVar1 = 1; + } + if (object[i]._oVar1 > 0) { + if (!deltaload) PlaySfxLoc(IS_IBOW, object[i]._ox, object[i]._oy); + return; + } + + object[i]._oVar1 = 0; // broken + object[i]._oAnimFlag = TRUE; + object[i]._oAnimFrame = 1; + object[i]._oAnimDelay = 1; + object[i]._oSolidFlag = FALSE; + object[i]._oMissFlag = TRUE; + object[i]._oBreak = OBJ_BROKEN; + object[i]._oSelFlag = OSEL_NONE; + object[i]._oPreFlag = TRUE; + if (deltaload) { + object[i]._oAnimFrame = object[i]._oAnimLen; + object[i]._oAnimCnt = 0; + object[i]._oAnimDelay = 1000; + return; + } + if (object[i]._otype == OBJ_BARRELEX) { + bool foo; + + if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND) + PlaySfxLoc(IS_URNFIRE, object[i]._ox, object[i]._oy); + else if (currlevel >= HIVESTART && currlevel <= HIVEEND) + PlaySfxLoc(IS_PODFIRE, object[i]._ox, object[i]._oy); + else + PlaySfxLoc(IS_BARLFIRE, object[i]._ox, object[i]._oy); + for (y = object[i]._oy-1; y <= object[i]._oy+1; ++y) { + for (x = object[i]._ox-1; x <= object[i]._ox+1; ++x) { + if (dMonster[x][y] > 0) MonsterTrapHit(dMonster[x][y]-1, 1, 4, 0, MIMT_FIRE, 0); + if (dPlayer[x][y] > 0) PlayerMHit(dPlayer[x][y]-1, -1, 0, 8, 16, MIMT_FIRE, 0, FALSE, &foo); + if (dObject[x][y] > 0) { + oi = dObject[x][y] - 1; + if ((object[oi]._otype == OBJ_BARRELEX) && (object[oi]._oBreak != OBJ_BROKEN)) + BreakBarrel(pnum, oi, dam, TRUE, sendmsg); + } + } + } + } else { + if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND) + PlaySfxLoc(IS_URN, object[i]._ox, object[i]._oy); + else if (currlevel >= HIVESTART && currlevel <= HIVEEND) + PlaySfxLoc(IS_POD, object[i]._ox, object[i]._oy); + else + PlaySfxLoc(IS_BARREL, object[i]._ox, object[i]._oy); + SetRndSeed(object[i]._oRndSeed); +#if CHEATS + if (uniqcheat) + RndUnique(object[i]._ox, object[i]._oy, currlevel); + else +#endif + if (object[i]._oVar2 <= 1) { + if (!object[i]._oVar3) CreateRndUseful(pnum, object[i]._ox, object[i]._oy, sendmsg); + else CreateRndItem(object[i]._ox, object[i]._oy, FALSE, sendmsg, FALSE); + } + if (object[i]._oVar2 >= 8) SpawnSkeleton(object[i]._oVar4, object[i]._ox, object[i]._oy); + } + + + if (pnum == myplr) NetSendCmdParam2(FALSE,CMD_BREAKOBJ,pnum,i); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void BreakObject(int pnum, int oi) +{ + int objdam, mind, maxd; + + if (pnum != -1) { + mind = plr[pnum]._pIMinDam; + maxd = plr[pnum]._pIMaxDam; + objdam = random(163,maxd - mind + 1) + mind; + objdam += (objdam * plr[pnum]._pIBonusDam) / 100; + objdam += plr[pnum]._pIBonusDamMod + plr[pnum]._pDamageMod; + } else objdam = 10; + + app_assert((DWORD)oi < MAXOBJECTS); + switch (object[oi]._otype) { + case OBJ_CRUX1 : + case OBJ_CRUX2 : + case OBJ_CRUX3 : + BreakCrux(oi); + break; + case OBJ_BARREL: + case OBJ_BARRELEX: + BreakBarrel(pnum, oi, objdam, FALSE, TRUE); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncBreakObj(int pnum, int oi) +{ + app_assert((DWORD)oi < MAXOBJECTS); + switch (object[oi]._otype) { + case OBJ_BARREL: + case OBJ_BARRELEX: + BreakBarrel(pnum, oi, 0, TRUE, FALSE); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncL1Doors(int i) +{ + int dx, dy; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oVar4 == DOOR_CLOSED) { + object[i]._oMissFlag = FALSE; + return; + } else object[i]._oMissFlag = TRUE; + dx = object[i]._ox; + dy = object[i]._oy; + object[i]._oSelFlag = OSEL_TOP; + if (currlevel < HIVESTART) + { + if (object[i]._otype == OBJ_L1DOORL) { + if (object[i]._oVar1 == 214) ObjSetMicro(dx,dy,408); //Blood + else ObjSetMicro(dx,dy,393); + dSpecial[dx][dy] = 7; + ObjSetMicro12(dx-1,dy); + --dy; + } else { + ObjSetMicro(dx,dy,395); + if (currlevel < HIVESTART) + dSpecial[dx][dy] = 8; + ObjSetMicro12(dx,dy-1); + --dx; + } + } + else + { + if (object[i]._otype == OBJ_L1DOORL) { + ObjSetMicro(dx,dy,206); + dSpecial[dx][dy] = 1; + ObjSetMicro12(dx-1,dy); + --dy; + } else { + ObjSetMicro(dx,dy,209); + dSpecial[dx][dy] = 2; + ObjSetMicro12(dx,dy-1); + --dx; + } + } + + DoorSet(i, dx, dy); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncCrux(int i) +{ + int j, ot, oi; + bool mapflag; + + mapflag = TRUE; + for (j = 0; j < numobjects; ++j) { + oi = objectactive[j]; + app_assert((DWORD)oi < MAXOBJECTS); + ot = object[oi]._otype; + if ((ot == OBJ_CRUX1) || (ot == OBJ_CRUX2) || (ot == OBJ_CRUX3)) { + if (object[i]._oVar8 == object[oi]._oVar8) { + if (object[oi]._oBreak != OBJ_BROKEN) mapflag = FALSE; + } + } + } + + if (mapflag) ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncLever(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oSelFlag == OSEL_NONE) { + ObjChangeMap(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncQSTLever(int i) +{ + int tren; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oAnimFrame == object[i]._oVar6) { + ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + if (object[i]._otype == OBJ_BLINDBOOK) { + tren = TransVal; + TransVal = 9; + DRLG_MRectTrans(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + TransVal = tren; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncPedistal(int i) +{ + byte *setp; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oVar6 == 1) { + ObjChangeMapResync(setpc_x, setpc_y + 3, setpc_x + 2, setpc_y + 7); + } + if (object[i]._oVar6 == 2) { + ObjChangeMapResync(setpc_x, setpc_y + 3, setpc_x + 2, setpc_y + 7); + ObjChangeMapResync(setpc_x + 6, setpc_y + 3, setpc_x + setpc_w, setpc_y + 7); + } + if (object[i]._oVar6 == 3) { + ObjChangeMapResync(object[i]._oVar1, object[i]._oVar2, object[i]._oVar3, object[i]._oVar4); + setp = LoadFileInMemSig("Levels\\L2Data\\Blood2.DUN", NULL, 'STPC'); + LoadMapObjs(setp, (setpc_x << 1), (setpc_y << 1)); + DiabloFreePtr(setp); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncL2Doors(int i) +{ + int dx, dy; + + app_assert((DWORD)i < MAXOBJECTS); + if (object[i]._oVar4 == DOOR_CLOSED) object[i]._oMissFlag = FALSE; + else object[i]._oMissFlag = TRUE; + dx = object[i]._ox; + dy = object[i]._oy; + object[i]._oSelFlag = OSEL_TOP; + + //Fix doors upon returning to level or loading level + if ((object[i]._otype == OBJ_L2DOORL) && + (object[i]._oVar4 == DOOR_CLOSED)) { + ObjSetMicro(dx,dy,538); + } else if ((object[i]._otype == OBJ_L2DOORL) && + ((object[i]._oVar4 == DOOR_OPEN) || + (object[i]._oVar4 == DOOR_BLOCKED))) { + ObjSetMicro(dx,dy,13); + } else if ((object[i]._otype == OBJ_L2DOORR) && + (object[i]._oVar4 == DOOR_CLOSED)) { + ObjSetMicro(dx,dy,540); + } else if ((object[i]._otype == OBJ_L2DOORR) && + ((object[i]._oVar4 == DOOR_OPEN) || + (object[i]._oVar4 == DOOR_BLOCKED))) { + ObjSetMicro(dx,dy,17); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +static void SyncL3Doors(int i) +{ + int dx, dy; + + app_assert((DWORD)i < MAXOBJECTS); + object[i]._oMissFlag = TRUE; + dx = object[i]._ox; + dy = object[i]._oy; + object[i]._oSelFlag = OSEL_TOP; + + //Fix doors upon returning to level or loading level + if ((object[i]._otype == OBJ_L3DOORL) && + (object[i]._oVar4 == DOOR_CLOSED)) { + ObjSetMicro(dx,dy,531); + } else if ((object[i]._otype == OBJ_L3DOORL) && + ((object[i]._oVar4 == DOOR_OPEN) || + (object[i]._oVar4 == DOOR_BLOCKED))) { + ObjSetMicro(dx,dy,538); + } else if ((object[i]._otype == OBJ_L3DOORR) && + (object[i]._oVar4 == DOOR_CLOSED)) { + ObjSetMicro(dx,dy,534); + } else if ((object[i]._otype == OBJ_L3DOORR) && + ((object[i]._oVar4 == DOOR_OPEN) || + (object[i]._oVar4 == DOOR_BLOCKED))) { + ObjSetMicro(dx,dy,541); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncObjectAnim(int o) +{ + int ai, ot, j; + + app_assert((DWORD)o < MAXOBJECTS); + ot = object[o]._otype; + ai = AllObjects[ot].ofindex; + for (j = 0; ObjFileList[j] != ai; ++j); + object[o]._oAnimData = pObjCels[j]; + + switch (object[o]._otype) { + case OBJ_L1DOORL : + case OBJ_L1DOORR : + SyncL1Doors(o); + break; + case OBJ_L2DOORL : + case OBJ_L2DOORR : + SyncL2Doors(o); + break; + case OBJ_L3DOORL : + case OBJ_L3DOORR : + SyncL3Doors(o); + break; + case OBJ_CRUX1 : + case OBJ_CRUX2 : + case OBJ_CRUX3 : + SyncCrux(o); + break; + case OBJ_SWITCHSKL: + case OBJ_LEVER : + case OBJ_BOOK2L: + SyncLever(o); + break; + case OBJ_BLINDBOOK: + case OBJ_STEELTOME: + case OBJ_BOOK2R: + SyncQSTLever(o); + break; + case OBJ_PEDISTAL: + SyncPedistal(o); + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetObjectStr(int i) +{ + app_assert((DWORD)i < MAXOBJECTS); + switch (object[i]._otype) { + case OBJ_CRUX1 : + case OBJ_CRUX2 : + case OBJ_CRUX3 : + strcpy(infostr, "Crucified Skeleton"); + break; + case OBJ_LEVER : + case OBJ_FLAMELVR: + strcpy(infostr, "Lever"); + break; + case OBJ_L1DOORL : + case OBJ_L1DOORR : + case OBJ_L2DOORL : + case OBJ_L2DOORR : + case OBJ_L3DOORL : + case OBJ_L3DOORR : + if (object[i]._oVar4 == DOOR_OPEN) strcpy(infostr, "Open Door"); + if (object[i]._oVar4 == DOOR_CLOSED) strcpy(infostr, "Closed Door"); + if (object[i]._oVar4 == DOOR_BLOCKED) strcpy(infostr, "Blocked Door"); + break; + case OBJ_BOOK2L: + if (setlevel) { + if (setlvlnum == SL_BONECHAMB) + strcpy(infostr, "Ancient Tome"); + else if (setlvlnum == SL_VILEBETRAYER) + strcpy(infostr, "Book of Vileness"); + } + break; + case OBJ_SWITCHSKL: + strcpy(infostr, "Skull Lever"); + break; +// case OBJ_BOOKLVR: +// strcpy(infostr, "Tome"); +// break; + case OBJ_BOOK2R: + strcpy(infostr, "Mythical Book"); + break; + case OBJ_CHEST1: + case OBJ_TCHEST1: + strcpy(infostr, "Small Chest"); + break; + case OBJ_CHEST2: + case OBJ_TCHEST2: + strcpy(infostr, "Chest"); + break; + case OBJ_CHEST3: + case OBJ_TCHEST3: + case OBJ_SIGNCHEST: + strcpy(infostr, "Large Chest"); + break; + case OBJ_SARC: + strcpy(infostr, "Sarcophagus"); + break; + case OBJ_BOOKSHELF: + strcpy(infostr, "Bookshelf"); + break; + case OBJ_BOOKCASEL: + case OBJ_BOOKCASER: + strcpy(infostr, "Bookcase"); + break; + case OBJ_BARREL: + case OBJ_BARRELEX: + if (currlevel >= HIVESTART && currlevel <= HIVEEND) + strcpy(infostr, "Pod"); + else if (currlevel >= CRYPTSTART && currlevel <= CRYPTEND) + strcpy(infostr, "Urn"); + else + strcpy(infostr, "Barrel"); + break; + case OBJ_SHRINEL: + case OBJ_SHRINER: + sprintf(tempstr, "%s Shrine", shrinestrs[object[i]._oVar1]); + strcpy(infostr, tempstr); + break; + case OBJ_SKELBOOK: + strcpy(infostr, "Skeleton Tome"); + break; + case OBJ_BOOKSTAND: + strcpy(infostr, "Library Book"); + break; + case OBJ_BLOODFTN: + strcpy(infostr, "Blood Fountain"); + break; + case OBJ_DECAP: + strcpy(infostr, "Decapitated Body"); + break; + case OBJ_BLINDBOOK: + strcpy(infostr, "Book of the Blind"); + break; + case OBJ_STEELTOME: + strcpy(infostr, "Steel Tome"); + break; + case OBJ_BLOODBOOK: + strcpy(infostr, "Book of Blood"); + break; + case OBJ_PURIFYINGFTN: + strcpy(infostr, "Purifying Spring"); + break; + case OBJ_ARMORSTAND: + case OBJ_WARARMOR: + strcpy(infostr, "Armor"); + break; + case OBJ_WARWEAP: + strcpy(infostr, "Weapon Rack"); + break; + case OBJ_GOATSHRINE: + strcpy(infostr, "Goat Shrine"); + break; + case OBJ_CAULDRON: + strcpy(infostr, "Cauldron"); + break; + case OBJ_MURKYFTN: + strcpy(infostr, "Murky Pool"); + break; + case OBJ_TEARFTN: + strcpy(infostr, "Fountain of Tears"); + break; + case OBJ_PEDISTAL: + strcpy(infostr, "Pedestal of Blood"); + break; + case OBJ_STORYBOOK: + strcpy(infostr, StoryBookName[object[i]._oVar3]); + break; + case OBJ_WEAPONRACK: + strcpy(infostr, "Weapon Rack"); + break; + case OBJ_MUSHPATCH: + strcpy(infostr, "Mushroom Patch"); + break; + case OBJ_LAZSTAND: + strcpy(infostr, "Vile Stand"); + break; + case OBJ_SLAINHERO: + strcpy(infostr, "Slain Hero"); + break; + } + if ((plr[myplr]._pClass == CLASS_ROGUE) && (object[i]._oTrapFlag)) { + sprintf(tempstr, "Trapped %s", infostr); + strcpy(infostr, tempstr); + infoclr = ICOLOR_RED; + } +} + +static void SpellBook (int number, int locx, int locy) +{ + AddSkulkenObject(OBJ_STORYBOOK, number, locx, locy); + + +} + +static void AddNa_Krul_Stuff() +{ + int spell; + + AddNaKrulLeverObj(); + + spell = random(0, 6); + switch (spell) + { + case 0: + SpellBook(6, Na_Krul.x + 3, Na_Krul.y); + SpellBook(7, Na_Krul.x + 2, Na_Krul.y - 3); + SpellBook(8, Na_Krul.x + 2, Na_Krul.y + 2); + break; + case 1: + SpellBook(6, Na_Krul.x + 3, Na_Krul.y); + SpellBook(8, Na_Krul.x + 2, Na_Krul.y - 3); + SpellBook(7, Na_Krul.x + 2, Na_Krul.y + 2); + break; + case 2: + SpellBook(7, Na_Krul.x + 3, Na_Krul.y); + SpellBook(6, Na_Krul.x + 2, Na_Krul.y - 3); + SpellBook(8, Na_Krul.x + 2, Na_Krul.y + 2); + break; + case 3: + SpellBook(7, Na_Krul.x + 3, Na_Krul.y); + SpellBook(8, Na_Krul.x + 2, Na_Krul.y - 3); + SpellBook(6, Na_Krul.x + 2, Na_Krul.y + 2); + break; + case 4: + SpellBook(8, Na_Krul.x + 3, Na_Krul.y); + SpellBook(7, Na_Krul.x + 2, Na_Krul.y - 3); + SpellBook(6, Na_Krul.x + 2, Na_Krul.y + 2); + break; + case 5: + SpellBook(8, Na_Krul.x + 3, Na_Krul.y); + SpellBook(6, Na_Krul.x + 2, Na_Krul.y - 3); + SpellBook(7, Na_Krul.x + 2, Na_Krul.y + 2); + break; + } + + +} + +static bool HCheckSpell(int number) +{ + + switch (number) + { + case 6: + SpellProgress = 1; + break; + case 7: + if (SpellProgress == 1) + SpellProgress = 2; + else + SpellProgress = 0; + break; + case 8: + if (SpellProgress == 2) + { +// qtextflag = FALSE; +// stream_stop(); + return true; + } + else + SpellProgress = 0; + } + return false; +} + + +void OpenNaKrul() +{ + if (currlevel == NA_KRUL_LEVEL) + { + PlaySfxLoc(CR_DOOROPEN, Na_Krul.x, Na_Krul.y); + dPiece[Na_Krul.x][Na_Krul.y] = 298; + dPiece[Na_Krul.x][Na_Krul.y - 1] = 301; + dPiece[Na_Krul.x][Na_Krul.y - 2] = 300; + dPiece[Na_Krul.x][Na_Krul.y + 1] = 299; + + SetDungeonMicros(); + } +} + +void OpenNaKrul2() +{ + dPiece[Na_Krul.x][Na_Krul.y] = 298; + dPiece[Na_Krul.x][Na_Krul.y - 1] = 301; + dPiece[Na_Krul.x][Na_Krul.y - 2] = 300; + dPiece[Na_Krul.x][Na_Krul.y + 1] = 299; + + SetDungeonMicros(); +} + +static void AddNaKrulLeverObj() +{ + int xp, yp; + while (1) { + xp = random(141,80) + DIRTEDGED2; + yp = random(141,80) + DIRTEDGED2; + if (! RndLocOk(xp-1, yp-1)) continue; + if (! RndLocOk(xp+0, yp-1)) continue; + if (! RndLocOk(xp+1, yp-1)) continue; + if (! RndLocOk(xp-1, yp+0)) continue; + if (! RndLocOk(xp+0, yp+0)) continue; + if (! RndLocOk(xp+1, yp+0)) continue; + if (! RndLocOk(xp-1, yp+1)) continue; + if (! RndLocOk(xp+0, yp+1)) continue; + if (! RndLocOk(xp+1, yp+1)) continue; + break; + } + + // temp test + xp = Na_Krul.x + 3; + yp = Na_Krul.y - 1; + + Na_Krul.LeverX = xp; + Na_Krul.LeverY = yp; + AddObject(OBJ_LEVER, xp, yp); +} + diff --git a/src/OBJECTS.H b/src/OBJECTS.H new file mode 100644 index 0000000..55bd8cb --- /dev/null +++ b/src/OBJECTS.H @@ -0,0 +1,152 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/OBJECTS.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXOBJECTS 127 + +#define MAXLVLOBJS 40 + +#define OBJ_NOBREAK 0 +#define OBJ_BREAKABLE 1 +#define OBJ_BROKEN -1 + +#define OSEL_NONE 0 +#define OSEL_FLR 1 +#define OSEL_TOP 2 +#define OSEL_ALL 3 + +#define OBJRND 0 +#define OBJMUST 1 +#define OBJNO 2 +#define OBJTHEME 3 + +#define OBJNOWARP 0 +#define OBJWARP1 1 +#define OBJWARP2 2 +#define OBJWARP3 3 +#define OBJDONEWARP 4 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + char oload; // Loading a must, rnd, or can't + char ofindex; // Filename index + char ominlvl; // Min level for object + char omaxlvl; // Max level for object + char olvltype; // Level type for set levels + char otheme; // Theme type + char oquest; // Quest related? + BOOL oAnimFlag; // Animates? + int oAnimDelay; // Anim Delay + int oAnimLen; // if Animates then Length of animation, else initial frame + long oAnimWidth; // Width of cels + BOOL oSolidFlag; // Can I stand on square with object? + BOOL oMissFlag; // Can I shoot missiles through this object? + BOOL oLightFlag; // Draw with lighting? + char oBreak; // Breakable + char oSelFlag; // Selectable object? + BOOL oTrapFlag; // Object trapable? +} ObjDataStruct; + +typedef struct { + int _otype; // object type + int _ox; // object map x + int _oy; // object map y + BOOL _oLight; // Light source drawn? + BOOL _oAnimFlag; // Animate at all? + BYTE *_oAnimData; // Data pointer to anim tables + int _oAnimDelay; // anim delay amount + int _oAnimCnt; // current anim delay value + int _oAnimLen; // number of anim frames + int _oAnimFrame; // current anim frame + long _oAnimWidth; // width of object + long _oAnimWidth2; // (width - 64) / 2 of object for drawing + BOOL _oDelFlag; // Delete this object? + char _oBreak; // Breakable + BOOL _oSolidFlag; // Can I stand on square with object? + BOOL _oMissFlag; // Can I shoot missiles through this object? + char _oSelFlag; // Selectable object? + BOOL _oPreFlag; // Draw behind player? + BOOL _oTrapFlag; // Am I trapped? + BOOL _oDoorFlag; // Am I a door? + int _olid; // Light id + int _oRndSeed; // random seed + long _oVar1; // scratch var 1 + long _oVar2; // scratch var 2 + long _oVar3; // scratch var 3 + long _oVar4; // scratch var 4 + long _oVar5; // scratch var 5 + long _oVar6; // scratch var 6 + long _oVar7; // scratch var 7 + long _oVar8; // scratch var 8 +} ObjectStruct; + +#define SAVE_OBJECT_SIZE sizeof(ObjectStruct) + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +extern ObjectStruct object[MAXOBJECTS]; +extern long numobjects; +extern int objectactive[MAXOBJECTS]; +extern int objectavail[MAXOBJECTS]; +extern BOOL InitObjFlag; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitObjectGFX(); +void FreeObjectGFX(); +void InitObjects(); +void SetMapObjects(BYTE *, int, int); +void ProcessObjects(); +void AddObject(int, int, int); + +void SyncObjectAnim(int); + +void BreakObject(int, int); +void SyncBreakObj(int, int); + +void MonstCheckDoors(int); + +void OperateObject(int, int, BOOL); +void SyncOpObject(int, int, int); +void TryDisarm(int, int); + +void ClrAllObjects (); + +void GetObjectStr(int); + +void ObjSetMicro(int, int, int); +void ObjSetMini(int, int, int); + +void AddL1Objs(int, int, int, int); +void AddL2Objs(int, int, int, int); + +void ObjL1Special(int, int, int, int); +void ObjL2Special(int, int, int, int); + +void AddLeverObj(int, int, int, int, int, int, int, int); +void AddBookLever(int, int, int, int, int, int, int, int, int); + +void SetObjMapRange(int, int, int, int, int, int); +void SetBookMsg(int, int); +void ObjChangeMap(int, int ,int, int); +void ObjChangeMapResync(int, int ,int, int); + +int ItemMiscIdIdx(int /* imiscid */); + diff --git a/src/Orgdll/STORM.DLL b/src/Orgdll/STORM.DLL new file mode 100644 index 0000000..b80dff6 Binary files /dev/null and b/src/Orgdll/STORM.DLL differ diff --git a/src/PACKPLR.CPP b/src/PACKPLR.CPP new file mode 100644 index 0000000..25d6330 --- /dev/null +++ b/src/PACKPLR.CPP @@ -0,0 +1,302 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/PACKPLR.CPP 3 2/13/97 5:00p Dbrevik2 $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "msg.h" +#include "multi.h" +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "spells.h" +#include "packplr.h" +#include "stores.h" +#include "engine.h" + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define INVALID_ITEM 0xffff + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void PackItem(PkItemStruct *id, const ItemStruct *is) { + if (is->_itype == -1) { + id->idx = INVALID_ITEM; + } + else { + id->idx = is->IDidx; + if (is->IDidx == IDI_EAR) { + id->iCreateInfo = (is->_iName[7] << 8) | is->_iName[8]; + id->iSeed = (is->_iName[9] << 24) | + (is->_iName[10] << 16) | + (is->_iName[11] << 8) | + is->_iName[12]; + id->bId = is->_iName[13]; + id->bDur = is->_iName[14]; + id->bMDur = is->_iName[15]; + id->bCh = is->_iName[16]; + id->bMCh = is->_iName[17]; + id->wValue = (is->_iName[18] << 8) | ((is->_iCurs - ITEM_EAR1) << 6) | is->_ivalue; + id->dwBuff = (is->_iName[19] << 24) | + (is->_iName[20] << 16) | + (is->_iName[21] << 8) | + is->_iName[22]; + } else { + id->iSeed = is->_iSeed; + id->iCreateInfo = is->_iCreateInfo; + id->bId = is->_iIdentified + (is->_iMagical << 1); + id->bDur = is->_iDurability; + id->bMDur = is->_iMaxDur; + id->bCh = is->_iCharges; + id->bMCh = is->_iMaxCharges; + if (is->IDidx == IDI_GOLD) id->wValue = is->_ivalue; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void PackPlayer(PkPlayerStruct * pPack, int pnum) { + ZeroMemory(pPack,sizeof PkPlayerStruct); + + int i; + PkItemStruct * pki; + const ItemStruct * pi; + const PlayerStruct * pPlayer = &plr[pnum]; + + pPack->destAction = pPlayer->destAction; + pPack->destParam1 = pPlayer->destParam1; + pPack->destParam2 = pPlayer->destParam2; + pPack->plrlevel = pPlayer->plrlevel; + pPack->px = pPlayer->_px; + pPack->py = pPlayer->_py; + pPack->targx = pPlayer->_ptargx; + pPack->targy = pPlayer->_ptargy; + + strcpy(pPack->pName,pPlayer->_pName); + pPack->pClass = pPlayer->_pClass; + + pPack->pBaseStr = pPlayer->_pBaseStr; + pPack->pBaseMag = pPlayer->_pBaseMag; + pPack->pBaseDex = pPlayer->_pBaseDex; + pPack->pBaseVit = pPlayer->_pBaseVit; + pPack->pLevel = pPlayer->_pLevel; + pPack->pStatPts = pPlayer->_pStatPts; + + pPack->pExperience = pPlayer->_pExperience; + pPack->pGold = pPlayer->_pGold; + + pPack->pHPBase = pPlayer->_pHPBase; + pPack->pMaxHPBase = pPlayer->_pMaxHPBase; + pPack->pManaBase = pPlayer->_pManaBase; + pPack->pMaxManaBase = pPlayer->_pMaxManaBase; + + pPack->pMemSpells = pPlayer->_pMemSpells; + +// hack hack hack; will have to fix later --donald + for (i = 0; i <= SPL_BONESPIRIT; i++) + pPack->pSplLvl[i] = pPlayer->_pSplLvl[i]; + unsigned char *p = (unsigned char *) ((void *) &(pPack->wReserved3)); + for (i = SPL_MANA; i < SPL_RUNEOFFIRE; i++) + { + p[i - SPL_MANA] = pPlayer->_pSplLvl[i]; + } + + pki = &pPack->InvBody[0]; + pi = &pPlayer->InvBody[0]; + for (i = NUM_INVLOC; i--; pki++,pi++) + PackItem(pki,pi); + + pki = &pPack->InvList[0]; + pi = &pPlayer->InvList[0]; + for (i = MAXINV; i--; pki++,pi++) + PackItem(pki,pi); + for (i = 0; i < MAXINV; i++) + pPack->InvGrid[i] = pPlayer->InvGrid[i]; + pPack->_pNumInv = pPlayer->_pNumInv; + + pki = &pPack->SpdList[0]; + pi = &pPlayer->SpdList[0]; + for (i = MAXSPD; i--; pki++,pi++) + PackItem(pki,pi); + + pPack->_pReflectCount = pPlayer->_pReflectCount; + pPack->pDiabloKillLevel = pPlayer->pDiabloKillLevel; + pPack->_gnDifficulty = pPlayer->_gnDifficulty; + pPack->_pIFlags2 = pPlayer->_pIFlags2; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void UnPackItem(const PkItemStruct *is, ItemStruct *id) { + if (is->idx == INVALID_ITEM) { + id->_itype = -1; + } + else { + if (is->idx == IDI_EAR) { + RecreateEar(TEMPAVAIL, + is->iCreateInfo, + is->iSeed, + is->bId, + is->bDur, + is->bMDur, + is->bCh, + is->bMCh, + is->wValue, + is->dwBuff); + } else { + RecreateItem(TEMPAVAIL, is->idx, is->iCreateInfo, is->iSeed, is->wValue); + item[TEMPAVAIL]._iMagical = is->bId >> 1; + item[TEMPAVAIL]._iIdentified = is->bId & 1; + item[TEMPAVAIL]._iDurability = is->bDur; + item[TEMPAVAIL]._iMaxDur = is->bMDur; + item[TEMPAVAIL]._iCharges = is->bCh; + item[TEMPAVAIL]._iMaxCharges = is->bMCh; + } + *id = item[TEMPAVAIL]; + } +} + +// drb.patch1.start.2/13/97 +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void VerifyGoldSeeds(PlayerStruct * pPlayer) +{ + int i, j; + + for (i = 0; i < pPlayer->_pNumInv; i++) { + if (pPlayer->InvList[i].IDidx == IDI_GOLD) { + for (j = 0; j < pPlayer->_pNumInv; j++) { + if ((i != j) && (pPlayer->InvList[j].IDidx == IDI_GOLD) && + (pPlayer->InvList[i]._iSeed == pPlayer->InvList[j]._iSeed)) { + + pPlayer->InvList[i]._iSeed = GetRndSeed(); + j = -1; + } + } + } + } +} +// drb.patch1.end.2/13/97 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void UnPackPlayer(const PkPlayerStruct *pPack, int pnum, BOOL killok) { + ItemStruct * pi; + const PkItemStruct * pki; + PlayerStruct * pPlayer = &plr[pnum]; + + void PlrInitReserved(PlayerStruct * p); + PlrInitReserved(pPlayer); + + // position player + pPlayer->_px = pPack->px; + pPlayer->_py = pPack->py; + pPlayer->_pfutx = pPack->px; + pPlayer->_pfuty = pPack->py; + pPlayer->_ptargx = pPack->targx; + pPlayer->_ptargy = pPack->targy; + pPlayer->plrlevel = pPack->plrlevel; + + // reset command to NOTHING + ClrPlrPath(pnum); + pPlayer->destAction = PCMD_NOTHING; + + strcpy(pPlayer->_pName,pPack->pName); + pPlayer->_pClass = pPack->pClass; + + InitPlayer(pnum,TRUE); + + pPlayer->_pBaseStr = pPack->pBaseStr; + pPlayer->_pStrength = pPack->pBaseStr; + pPlayer->_pBaseMag = pPack->pBaseMag; + pPlayer->_pMagic = pPack->pBaseMag; + pPlayer->_pBaseDex = pPack->pBaseDex; + pPlayer->_pDexterity = pPack->pBaseDex; + pPlayer->_pBaseVit = pPack->pBaseVit; + pPlayer->_pVitality = pPack->pBaseVit; + pPlayer->_pLevel = pPack->pLevel; + pPlayer->_pStatPts = pPack->pStatPts; + + pPlayer->_pExperience = pPack->pExperience; + pPlayer->_pGold = pPack->pGold; + + pPlayer->_pMaxHPBase = pPack->pMaxHPBase; + pPlayer->_pHPBase = pPack->pHPBase; + if (!killok && ((pPlayer->_pHPBase >> HP_SHIFT) < 1)) pPlayer->_pHPBase = 1 << HP_SHIFT; + pPlayer->_pMaxManaBase = pPack->pMaxManaBase; + pPlayer->_pManaBase = pPack->pManaBase; + + pPlayer->_pMemSpells = pPack->pMemSpells; + +// hack hack hack -- donald + + for (int i = 0; i <= SPL_BONESPIRIT; i++) + pPlayer->_pSplLvl[i] = pPack->pSplLvl[i]; + + unsigned char *p = (unsigned char *) ((void *)&(pPack->wReserved3)); + for (i = SPL_MANA; i < SPL_RUNEOFFIRE; i++) + { + pPlayer->_pSplLvl[i] = p[i - SPL_MANA]; + } + +// end hack -- donald + + pki = &pPack->InvBody[0]; + pi = &pPlayer->InvBody[0]; + for (i = NUM_INVLOC; i--; pki++,pi++) + UnPackItem(pki,pi); + + pki = &pPack->InvList[0]; + pi = &pPlayer->InvList[0]; + for (i = MAXINV; i--; pki++,pi++) + UnPackItem(pki,pi); + for (i = 0; i < MAXINV; i++) + pPlayer->InvGrid[i] = pPack->InvGrid[i]; + pPlayer->_pNumInv = pPack->_pNumInv; + // drb.patch1.start.2/13/97 + VerifyGoldSeeds(pPlayer); + // drb.patch1.end.2/13/97 + + pki = &pPack->SpdList[0]; + pi = &pPlayer->SpdList[0]; + for (i = MAXSPD; i--; pki++,pi++) + UnPackItem(pki,pi); + + // this is a fix below for witch store items - rjs + if (pnum == myplr) + for (i = 0; i < MAXWITCHITEMS; i++) witchitem[i]._itype = -1; + + CalcPlrInv(pnum, FALSE); + + pPlayer->_pReflectCount = pPack->_pReflectCount; + pPlayer->pTownWarps = 0; + pPlayer->pDungMsgs = 0; + pPlayer->pHellfireMsgs = 0; + pPlayer->pLvlLoad = 0; + pPlayer->pDiabloKillLevel = pPack->pDiabloKillLevel; + pPlayer->_gnDifficulty = pPack->_gnDifficulty; + pPlayer->_pIFlags2 = pPack->_pIFlags2; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void PackClearCheater(PkPlayerStruct *pPack) { + pPack->pGold = 0; + FillMemory(pPack->InvBody,sizeof pPack->InvBody,0xff); + FillMemory(pPack->InvList,sizeof pPack->InvList,0xff); + FillMemory(pPack->InvGrid,sizeof pPack->InvGrid,0); + pPack->_pNumInv = 0; + FillMemory(pPack->SpdList,sizeof pPack->SpdList,0xff); +} diff --git a/src/PACKPLR.H b/src/PACKPLR.H new file mode 100644 index 0000000..2378b10 --- /dev/null +++ b/src/PACKPLR.H @@ -0,0 +1,109 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1996 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/PACKPLR.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Packed structures +**-----------------------------------------------------------------------*/ + +#pragma pack(push,1) +typedef struct { + int iSeed; + WORD iCreateInfo; + WORD idx; + BYTE bId; + BYTE bDur; + BYTE bMDur; + BYTE bCh; + BYTE bMCh; + WORD wValue; + DWORD dwBuff; +} PkItemStruct; + +typedef struct { + FILETIME archiveTime; + BYTE destAction; + BYTE destParam1; + BYTE destParam2; + BYTE plrlevel; + BYTE px; + BYTE py; + BYTE targx; + BYTE targy; + + // Player attributes + char pName[PLR_NAME_LEN]; + BYTE pClass; + + BYTE pBaseStr; + BYTE pBaseMag; + BYTE pBaseDex; + BYTE pBaseVit; + BYTE pLevel; + BYTE pStatPts; + + long pExperience; + long pGold; + + long pHPBase; + long pMaxHPBase; + long pManaBase; + long pMaxManaBase; + + // hack hack hack --donald + BYTE pSplLvl[SPL_BONESPIRIT+1]; + __int64 pMemSpells; + + PkItemStruct InvBody[NUM_INVLOC]; + PkItemStruct InvList[MAXINV]; + char InvGrid[MAXINV]; + BYTE _pNumInv; + PkItemStruct SpdList[MAXSPD]; + + // these fields are to be used if more variables need to be added + // to the player structure so that the size won't change... + BYTE bReserved1; + BYTE bReserved2; + BYTE bReserved3; + BYTE bReserved4; + BYTE bReserved5; + BYTE bReserved6; + BYTE bReserved7; + BYTE bReserved8; + + WORD _pReflectCount; + WORD wReserved2; + WORD wReserved3; // + WORD wReserved4; // + WORD wReserved5; // wReserved3-8 are used for spell slots... + WORD wReserved6; // + WORD wReserved7; // + WORD wReserved8; // + + DWORD pDiabloKillLevel; // player killed Diablo at what level + DWORD _gnDifficulty; + DWORD _pIFlags2; + DWORD dwReserved4; + DWORD dwReserved5; + DWORD dwReserved6; + DWORD dwReserved7; + DWORD dwReserved8; + +} PkPlayerStruct; +#pragma pack(pop) + + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +void PackPlayer(PkPlayerStruct *p, int pnum); +void UnPackPlayer(const PkPlayerStruct *p, int pnum, BOOL killok); + +void PackItem(PkItemStruct *id, const ItemStruct *is); +void UnPackItem(const PkItemStruct *is, ItemStruct *id); diff --git a/src/PALETTE.CPP b/src/PALETTE.CPP new file mode 100644 index 0000000..dec407c --- /dev/null +++ b/src/PALETTE.CPP @@ -0,0 +1,424 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Palette file +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/PALETTE.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "palette.h" +#include "engine.h" +#include +#include "resource.h" + + +/*-----------------------------------------------------------------------** +** extern +**-----------------------------------------------------------------------*/ +extern char gszProgKey[]; +void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine); + + +/*-----------------------------------------------------------------------** +** File Variables +**-----------------------------------------------------------------------*/ +static LONG sglGamma = lGAMMA_MAX; +static int sgnStaticColors2 = 0; +static PALETTEENTRY sgLoad[256]; // original loaded palette -- used as reference + // for gamma conversion +static PALETTEENTRY sgBase[256]; // palettized version of sgLoad +static PALETTEENTRY sgCurr[256]; // palette to be displayed -- includes rotations + +static const char sgszGamma[] = "Gamma Correction"; +static BYTE sgbFadedIn = TRUE; + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void SetPaletteEntries() { + if (! lpDDPal) return; + + int nStart; + int nColors; + if (! fullscreen) { + nStart = sgnStaticColors2; + nColors = 256 - sgnStaticColors2*2; + } + else { + nStart = 0; + nColors = 256; + } + +// HRESULT ddrval = lpDDPal->SetEntries(0,nStart,nColors,&sgCurr[nStart]); +// ddraw_assert(ddrval); + SDrawUpdatePalette(nStart,nColors,&sgCurr[nStart]); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void GammaPalette(PALETTEENTRY * pDst, const PALETTEENTRY * pSrc, int nNum) { + double gamma = sglGamma / 100.0; + for(int i = 0; i < nNum; i++,pDst++,pSrc++) { + pDst->peRed = (BYTE)(256.0*pow(((double)pSrc->peRed)/256.0, gamma)); + pDst->peGreen = (BYTE)(256.0*pow(((double)pSrc->peGreen)/256.0, gamma)); + pDst->peBlue = (BYTE)(256.0*pow(((double)pSrc->peBlue)/256.0, gamma)); + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void SavePaletteSettings() { + SRegSaveValue(gszProgKey,sgszGamma,0,sglGamma); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void GetPaletteSettings() { + DWORD dwTemp = (DWORD) sglGamma; + if (! SRegLoadValue(gszProgKey,sgszGamma,0,&dwTemp)) + dwTemp = lGAMMA_MAX; + + sglGamma = (LONG) dwTemp; + if (sglGamma < lGAMMA_MIN) + sglGamma = lGAMMA_MIN; + else if (sglGamma > lGAMMA_MAX) + sglGamma = lGAMMA_MAX; + sglGamma -= sglGamma % lGAMMA_STEP; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void FixWindowsPal() { + int i; + + // reserve all colors so no mapping occurs + for (i = 0; i < 256; i++) + sgCurr[i].peFlags = PC_NOCOLLAPSE | PC_RESERVED; + + if (fullscreen) return; + + // get static color count + HDC hDC = GetDC(NULL); + sgnStaticColors2 = GetDeviceCaps(hDC, NUMRESERVED) / 2; + + // get the lower windows color set + GetSystemPaletteEntries(hDC, 0, sgnStaticColors2, &sgCurr[0]); + for (i = 0; i < sgnStaticColors2; i++) sgCurr[i].peFlags = 0; + + // get the upper windows color set + i = 256 - sgnStaticColors2; + GetSystemPaletteEntries(hDC, i, sgnStaticColors2, &sgCurr[i]); + for ( ; i < 256; i++) sgCurr[i].peFlags = 0; + + ReleaseDC(NULL, hDC); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void CreatePalette() { + GetPaletteSettings(); + CopyMemory(sgCurr,sgLoad,sizeof(sgCurr)); + FixWindowsPal(); + HRESULT ddrval = lpDD->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE,sgCurr,&lpDDPal,NULL); + if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_PAL_ERR,ddrval,__FILE__,__LINE__); + + ddrval = lpDDSPrimary->SetPalette(lpDDPal); + if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_PAL_ERR,ddrval,__FILE__,__LINE__); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void LoadPalette(const char * pszFileName) { + struct RGB { + BYTE red; + BYTE green; + BYTE blue; + } pal[256]; + + HSFILE hFile; + app_assert(pszFileName); + patSFileOpenFile(pszFileName,&hFile); + patSFileReadFile(hFile,&pal[0],sizeof(pal)); + patSFileCloseFile(hFile); + + for (int i = 0; i < 256; i++) { + sgLoad[i].peRed = pal[i].red; + sgLoad[i].peGreen = pal[i].green; + sgLoad[i].peBlue = pal[i].blue; + sgLoad[i].peFlags = 0; + } +// GammaPalette(sgBase, sgLoad, 256); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void LoadRndLvlPal(int l) { + + if (l == 0) { + LoadPalette("Levels\\TownData\\Town.pal"); + } + else { + char filestr[MAX_PATH]; + int palnum = random(0, 4) + 1; + sprintf(filestr, "Levels\\L%iData\\L%i_%i.PAL", l, l, palnum); + // JKE add our palettes here + if (l == 5) + sprintf(filestr, "NLevels\\L5Data\\L5Base.PAL"); + if (l == 6) + { + if (!gbOurNest) + ++palnum; + sprintf(filestr, "NLevels\\L%iData\\L%iBase%i.PAL", l, l, palnum); + } + LoadPalette(filestr); + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ResetPal() { + if (lpDDSPrimary && lpDDSPrimary->IsLost() == DDERR_SURFACELOST) + if (DD_OK != lpDDSPrimary->Restore()) return; + SDrawRealizePalette(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void GammaUp() { + if(sglGamma < lGAMMA_MAX) { + sglGamma += lGAMMA_STEP; + if (sglGamma > lGAMMA_MAX) + sglGamma = lGAMMA_MAX; + GammaPalette(sgCurr,sgBase,256); + SetPaletteEntries(); + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void GammaDown() { + if(sglGamma > lGAMMA_MIN) { + sglGamma -= lGAMMA_STEP; + if (sglGamma < lGAMMA_MIN) + sglGamma = lGAMMA_MIN; + GammaPalette(sgCurr,sgBase,256); + SetPaletteEntries(); + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +LONG GammaLevel(LONG lGamma) { + if (lGamma != lGAMMA_READ) { + // invert gamma hi/lo + sglGamma = lGAMMA_MAX - lGamma + lGAMMA_MIN; + GammaPalette(sgCurr,sgBase,256); + SetPaletteEntries(); + } + + // invert gamma hi/lo + return lGAMMA_MAX - sglGamma + lGAMMA_MIN; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void SetFadeLevel(int fadeval) { + if (! lpDD) return; + + for (int i = 0; i < 255; i++) { + DWORD pv; + pv = sgBase[i].peRed * fadeval; + sgCurr[i].peRed = (BYTE) (pv/256); + pv = sgBase[i].peGreen * fadeval; + sgCurr[i].peGreen = (BYTE) (pv/256); + pv = sgBase[i].peBlue * fadeval; + sgCurr[i].peBlue = (BYTE) (pv/256); + } + +// sgCurr[i].peRed = 0xff; +// sgCurr[i].peGreen = 0xff; +// sgCurr[i].peBlue = 0xff; + + Sleep(3); + lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL); + SetPaletteEntries(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void BlackPalette() { + SetFadeLevel(0); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void PaletteFadeIn(int faderate) { + GammaPalette(sgBase,sgLoad,256); + for (int i = 0; i < 256; i += faderate) + SetFadeLevel(i); + SetFadeLevel(256); + + // un-gamma-fy base palette + CopyMemory(sgBase,sgLoad,sizeof(sgBase)); + sgbFadedIn = TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void PaletteFadeOut(int faderate) { + if (! sgbFadedIn) return; + for (int i = 256; i > 0; i -= faderate) + SetFadeLevel(i); + SetFadeLevel(0); + sgbFadedIn = FALSE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void LavaCycle() { + PALETTEENTRY temp = sgCurr[1]; + for (int i = 1; i < 31; i++) { + sgCurr[i].peRed = sgCurr[i + 1].peRed; + sgCurr[i].peGreen = sgCurr[i + 1].peGreen; + sgCurr[i].peBlue = sgCurr[i + 1].peBlue; + // don't copy flags + } + + sgCurr[i].peRed = temp.peRed; + sgCurr[i].peGreen = temp.peGreen; + sgCurr[i].peBlue = temp.peBlue; + // don't copy flags + + SetPaletteEntries(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// JKE new cycle to do twin effects +void TwinCycleCrypt() { + int i; + static int toggle = 0; + static int toggle2 = 0; + PALETTEENTRY temp; + + if (toggle2 > 1) + { + temp = sgCurr[15]; + for (i = 15; i > 1; --i) { + sgCurr[i].peRed = sgCurr[i - 1].peRed; + sgCurr[i].peGreen = sgCurr[i - 1].peGreen; + sgCurr[i].peBlue = sgCurr[i - 1].peBlue; + // don't copy flags + } + sgCurr[i].peRed = temp.peRed; + sgCurr[i].peGreen = temp.peGreen; + sgCurr[i].peBlue = temp.peBlue; + // don't copy flags + toggle2 = 0; + } + else + ++toggle2; + + if (toggle > 0) + { + temp = sgCurr[31]; + for (i = 31; i > 16; --i) + { + sgCurr[i].peRed = sgCurr[i - 1].peRed; + sgCurr[i].peGreen = sgCurr[i - 1].peGreen; + sgCurr[i].peBlue = sgCurr[i - 1].peBlue; + } + sgCurr[i].peRed = temp.peRed; + sgCurr[i].peGreen = temp.peGreen; + sgCurr[i].peBlue = temp.peBlue; + + SetPaletteEntries(); + ++toggle; + } + else + toggle = 1; +} +void TwinCycleNest() { + int i; + static int toggle = 0; + static int toggle2 = 0; + PALETTEENTRY temp; + if (toggle2 == 2) + { + temp = sgCurr[8]; + for (i = 8; i > 1; --i) { + sgCurr[i].peRed = sgCurr[i - 1].peRed; + sgCurr[i].peGreen = sgCurr[i - 1].peGreen; + sgCurr[i].peBlue = sgCurr[i - 1].peBlue; + // don't copy flags + } + + sgCurr[i].peRed = temp.peRed; + sgCurr[i].peGreen = temp.peGreen; + sgCurr[i].peBlue = temp.peBlue; + // don't copy flags + toggle2 = 0; + } + else + ++toggle2; + + if (toggle == 2) + { + temp = sgCurr[15]; + for (i = 15; i > 9; --i) + { + sgCurr[i].peRed = sgCurr[i - 1].peRed; + sgCurr[i].peGreen = sgCurr[i - 1].peGreen; + sgCurr[i].peBlue = sgCurr[i - 1].peBlue; + } + sgCurr[i].peRed = temp.peRed; + sgCurr[i].peGreen = temp.peGreen; + sgCurr[i].peBlue = temp.peBlue; + + SetPaletteEntries(); + toggle = 0; + } + else + ++toggle; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void UpdateLavaPalette() { + for (int i = 0; i < 32; i++) + sgBase[i] = sgLoad[i]; + GammaPalette(sgCurr,sgBase,32); + SetPaletteEntries(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void MeshLavaPalette(int fadeval) { + int i; + + for (i = 32 - fadeval; i >= 0; i--) + sgBase[i] = sgLoad[i]; + GammaPalette(sgCurr, sgBase, 32); + SetPaletteEntries(); +} diff --git a/src/PALETTE.H b/src/PALETTE.H new file mode 100644 index 0000000..ab64ddb --- /dev/null +++ b/src/PALETTE.H @@ -0,0 +1,46 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/PALETTE.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ +#define FADE_SLOW 8 +#define FADE_MED 16 +//#define FADE_FAST 32 +#define FADE_FAST 8 +#define FADE_VFAST 128 + + + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +void CreatePalette(); +void LoadRndLvlPal(int); +void LoadPalette(const char * pszFileName); +void ResetPal(); +void SetPalette(); +void PaletteFadeIn(int faderate); +void PaletteFadeOut(int faderate); +void LavaCycle(); +void TwinCycleCrypt(); // JKE new cycle for dual effects +void TwinCycleNest(); // JKE new cycle for nest +void MeshLavaPalette(int fadeval); + + +#define lGAMMA_READ 0 +#define lGAMMA_MIN 30 +#define lGAMMA_MAX 100 +#define lGAMMA_STEP 5 +#define lGAMMA_TICKS (((lGAMMA_MAX - lGAMMA_MIN) / lGAMMA_STEP) + 1) +void GammaUp(); +void GammaDown(); +LONG GammaLevel(LONG lGamma); \ No newline at end of file diff --git a/src/PATCH.TXT b/src/PATCH.TXT new file mode 100644 index 0000000..afa168f --- /dev/null +++ b/src/PATCH.TXT @@ -0,0 +1,129 @@ +-------------------------------------------------------------------- +patch.txt +-------------------------------------------------------------------- + + + +-------------------------------------------------------------------- +PATCH 1 -- 1/13/97 +-------------------------------------------------------------------- + + +diabloui.dll (connect.cpp) +-------------------------------------------------------------------- +corrects crash bug when attempting to join game created with an +invalid time (year < 1970 or year > 2036) + +checks for characters with (level==0) and treats that as an invalid +diablo character (no portrait, can't create or join) + +mike.rc +-------------------------------------------------------------------- +Added version information + + +storm.dll (snet.cpp) +-------------------------------------------------------------------- +send relative time instead of absolute time to players joining game +(helps correct diabloui crash bug) + + +standard.snp (ipx.cpp) +-------------------------------------------------------------------- +run-time dynamically link to wsock32.dll to prevent errors when +that file does not exist. + + +battle.snp (chatchnl.cpp) +-------------------------------------------------------------------- +fixed deallocated pointer error which caused player to get locked out +after creating a channel + +joingame.cpp +-------------------------------------------------------------------- +added more descriptive messages for can't join if game is full or +game owner is not responding. + +games shown in the list of public games will not disappear anymore. +The list will be refreshed only if the user closes and opens the join +game dialog. + +scrollrt.cpp +engine.cpp +-------------------------------------------------------------------- +corrects the NULL cell buffer errors and other data corruption in draw code +now uses "GRACEFUL_EXIT" to prevent fatal exits on error conditions + + +diablo.rc +-------------------------------------------------------------------- +version number changed +changed IDESCAPE to IDCANCEL for IDD_CDROM_ERR dialog +now matches code in appfat.cpp + + +init.cpp +-------------------------------------------------------------------- +version number changed + + +dx.cpp -- init_backbuf() +-------------------------------------------------------------------- +potential bug -- never actually seen +commented out ddraw_assert on failure to unlock video surface. +In NT it is possible to lose a video surface while it is locked. + + +dx.cpp:170 -- init_directx() fail on SetDisplayMode +-------------------------------------------------------------------- +reported bug -- occurs on some notebook systems +if direct draw doesn't support switching screen resolutions, try +switching color depth and keep same screen resolution + + +wave.cpp -- patSFileReadFile() +-------------------------------------------------------------------- +reported bug -- can't recover from read failure +if read failure occurs, restart read from beginning, +not from where read error occurred + + +wave.cpp/appfat.cpp -- InsertCDDlg() +-------------------------------------------------------------------- +reported bug -- both OK and Exit buttons did the same thing (oops) + + +sound.cpp -- snd_restore_snd() +-------------------------------------------------------------------- +potential bug -- never actually seen +if sound buffer cannot be locked, no error occurs, sound skipped + + +sound.cpp:384 -- snd_set_format() +-------------------------------------------------------------------- +reported bug -- sound cards don't support SetFormat() +commented out assertion + + +diablo.cpp -- CommandLine() +-------------------------------------------------------------------- +fixed silly problem with special direct draw command line options so +they can now appear anywhere on the command line instead of at the end + + +init.cpp -- MainWndProc() +-------------------------------------------------------------------- +correct palette problems when other applications realize their +palettes in the background. + + +pfile.cpp +-------------------------------------------------------------------- +removed "retribution" code which deletes player inventory when +cheating dectected. + + +mpqapi.cpp +-------------------------------------------------------------------- +removed time-stamp save code which appears to damage registry on +some systems. Code was related to "retribution" code diff --git a/src/PATH.CPP b/src/PATH.CPP new file mode 100644 index 0000000..da2e756 --- /dev/null +++ b/src/PATH.CPP @@ -0,0 +1,399 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Path file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/PATH.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** A* Path Search Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "path.h" + +PATHNODE PNodePool[MAXPNODES]; +PATHNODE *OPEN; +PATHNODE *CLOSED; + +int tempath[MAXPATHLEN]; + +PATHNODE pathnodes[MAXPNODES]; // node cache +int numpnodes; // index to next pathnode + +PATHNODE *Stack[MAXPNODES]; // stack of nodes to process +int numstack; // index to next stack item + +static char DirCmd[] = + { PCMD_WALKU, PCMD_WALKUR, PCMD_WALKR, PCMD_WALKUL, 0, + PCMD_WALKDR, PCMD_WALKL, PCMD_WALKDL, PCMD_WALKD + }; + +int PATHDIST(int x1, int y1, int x2, int y2); +PATHNODE *GetPathNode(); +PATHNODE *ReturnBestNode(void); +BOOL GenerateSuccessors(CHECKFUNC1 PosOk, int PosOkArg, PATHNODE *BestNode,int dx,int dy); +BOOL GenerateSucc(PATHNODE *BestNode,int x, int y, int dx, int dy); +PATHNODE *CheckOPEN(int x, int y); +PATHNODE *CheckCLOSED(int x, int y); +void Insert(PATHNODE *Successor); +void PropagateDown(PATHNODE *Old); + +void Push(PATHNODE *Node); +PATHNODE *Pop(void); + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int FindPath(CHECKFUNC1 PosOk, int PosOkArg, int sx,int sy,int dx,int dy, char path[]) +{ + PATHNODE *Node, *BestNode; + int i,len; + + numpnodes = 0; // clear node chache + OPEN=GetPathNode(); + CLOSED=GetPathNode(); + numstack = 0; // clear stack + + Node=GetPathNode(); + Node->g=0; + Node->h=PATHDIST(sx,sy,dx,dy); + Node->f=Node->g+Node->h; + Node->x=sx; + Node->y=sy; + + OPEN->NextNode=Node; /* make Open List point to first node */ + for (;;) + { + BestNode=(PATHNODE *)ReturnBestNode(); + if(!BestNode) + return 0; + + if (BestNode->x == dx && BestNode->y == dy) /* if we've found the end, break and finish */ + break; + if(!GenerateSuccessors(PosOk, PosOkArg, BestNode,dx,dy)) + return 0; + } + + // generate list of moves + Node = BestNode; + + len = 0; + + while(Node->Parent && len < MAXPATHLEN) + { + tempath[len++] = DirCmd[(Node->x - Node->Parent->x + 1) + (Node->y - Node->Parent->y + 1)*3]; + Node = Node->Parent; + } + if(len == MAXPATHLEN) + return 0; + + for(i = 0; i < len; i++) + path[i] = tempath[len - i - 1]; + + return i; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PATHDIST(int x1, int y1, int x2, int y2) +{ + int dx,dy; + int mind,maxd; + + dx = abs(x1-x2); + dy = abs(y1-y2); + mind = min(dx,dy); + maxd = max(dx,dy); + + // Assign dist of 3 for diagonal, 2 for straight + // Therefore, 3*(mind) + 2*(maxd-mind) + // = mind + 2*maxd + return mind + maxd<<1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int PathVal(PATHNODE *Node, int x, int y) +{ + if(Node->x == x || Node->y == y) + return 2; + return 3; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +PATHNODE *ReturnBestNode(void) +{ + PATHNODE *tmp; + + if (OPEN->NextNode == NULL) + { + return NULL; + } + +/* Pick Node with lowest f, in this case it's the first node in list + because we sort the OPEN list wrt lowest f. Call it BESTNODE. */ + + tmp=OPEN->NextNode; // point to first node on OPEN + OPEN->NextNode=tmp->NextNode; // Make OPEN point to nextnode or NULL. + +/* Next take BESTNODE (or temp in this case) and put it on CLOSED */ + + tmp->NextNode=CLOSED->NextNode; + CLOSED->NextNode=tmp; + + return(tmp); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PathDirOk(PATHNODE *Node, int x, int y) +{ + BOOL ok = TRUE; + + switch(DirCmd[(x - Node->x + 1) + (y - Node->y + 1)*3]) + { + case PCMD_WALKU: + ok = !(nSolidTable[dPiece[x][y+1]] || nSolidTable[dPiece[x+1][y]]); + break; + case PCMD_WALKR: + ok = !(nSolidTable[dPiece[x][y+1]] || nSolidTable[dPiece[x-1][y]]); + break; + case PCMD_WALKD: + ok = !(nSolidTable[dPiece[x][y-1]] || nSolidTable[dPiece[x-1][y]]); + break; + case PCMD_WALKL: + ok = !(nSolidTable[dPiece[x+1][y]] || nSolidTable[dPiece[x][y-1]]); + break; + } + + return ok; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL GenerateSuccessors(CHECKFUNC1 PosOk, int PosOkArg, PATHNODE *BestNode,int dx,int dy) +{ + int x,y; + int i; + BOOL posok; + static const char nextx[] = { -1, -1, 1, 1, -1, 0, 1, 0 }; + static const char nexty[] = { -1, 1, -1, 1, 0, -1, 0, 1 }; + + for(i = 0; i < 8; i++) + { + x = BestNode->x + nextx[i]; + y = BestNode->y + nexty[i]; + + posok = PosOk(PosOkArg, x, y); + if((posok && PathDirOk(BestNode, x, y)) + || (!posok && x==dx && y==dy)) // allow user to click on walls + if(!GenerateSucc(BestNode,x,y,dx,dy)) + return FALSE; + } + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL GenerateSucc(PATHNODE *BestNode,int x, int y, int dx, int dy) +{ + int g,c=0; + PATHNODE *Old,*Successor; + + g=BestNode->g+PathVal(BestNode,x,y); /* g(Successor)=g(BestNode)+cost of getting from BestNode to Successor */ + + if ((Old=CheckOPEN(x, y)) != NULL) /* if equal to NULL then not in OPEN list, else it returns the Node in Old */ + { + for(c=0;c<8;c++) + if(BestNode->Child[c] == NULL) /* Add Old to the list of BestNode's Children (or Successors). */ + break; + BestNode->Child[c]=Old; + + if (g < Old->g && PathDirOk(BestNode, x, y)) /* if our new g value is < Old's then reset Old's parent to point to BestNode */ + { + Old->Parent=BestNode; + Old->g=g; + Old->f=g+Old->h; + } + } + else if ((Old=CheckCLOSED(x, y)) != NULL) /* if equal to NULL then not in OPEN list, else it returns the Node in Old */ + { + for(c=0;c<8;c++) + if (BestNode->Child[c] == NULL) /* Add Old to the list of BestNode's Children (or Successors). */ + break; + BestNode->Child[c]=Old; + + if (g < Old->g && PathDirOk(BestNode, x, y)) /* if our new g value is < Old's then reset Old's parent to point to BestNode */ + { + Old->Parent=BestNode; + Old->g=g; + Old->f=g+Old->h; + PropagateDown(Old); /* Since we changed the g value of Old, we need + to propagate this new value downwards, i.e. + do a Depth-First traversal of the tree! */ + } + } + else + { + if(!(Successor=GetPathNode())) + return FALSE; + else + { + Successor->Parent=BestNode; + Successor->g=g; + Successor->h=PATHDIST(x,y,dx,dy); + Successor->f=g+Successor->h; + Successor->x=x; + Successor->y=y; + Insert(Successor); /* Insert Successor on OPEN list wrt f */ + for(c=0;c<8;c++) + if (BestNode->Child[c] == NULL) /* Add Successor to the list of BestNode's Children (or Successors). */ + break; + BestNode->Child[c]=Successor; + } + } + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +PATHNODE *CheckOPEN(int x, int y) +{ + PATHNODE *tmp; + + tmp=OPEN->NextNode; + while (tmp != NULL) + { + if (tmp->x == x && tmp->y == y) + return (tmp); + else + tmp=tmp->NextNode; + } + return (NULL); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +PATHNODE *CheckCLOSED(int x, int y) +{ + PATHNODE *tmp; + + tmp=CLOSED->NextNode; + + while (tmp != NULL) + { + if (tmp->x == x && tmp->y == y) + return (tmp); + else + tmp=tmp->NextNode; + } + return (NULL); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Insert(PATHNODE *Successor) +{ + PATHNODE *tmp1,*tmp2; + int f; + + if (OPEN->NextNode == NULL) + { + OPEN->NextNode=Successor; + return; + } + + /* insert into OPEN successor wrt f */ + + f=Successor->f; + tmp1=OPEN; + tmp2=OPEN->NextNode; + + while ((tmp2 != NULL) && (tmp2->f < f)) + { + tmp1=tmp2; + tmp2=tmp2->NextNode; + } + Successor->NextNode=tmp2; + tmp1->NextNode=Successor; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PropagateDown(PATHNODE *Old) +{ + int c; + PATHNODE *Child, *Father; + + Push(Old); + while (numstack) + { + Father=Pop(); + for(c=0;c<8;c++) + { + if ((Child=Father->Child[c])==NULL) /* we may stop the propagation 2 ways: either */ + break; + if (Father->g+PathVal(Father, Child->x, Child->y) < Child->g && PathDirOk(Father, Child->x, Child->y)) /* there are no children, or that the g value of */ + { /* the child is equal or better than the cost we're propagating */ + Child->Parent=Father; + Child->g=Father->g+PathVal(Father, Child->x, Child->y); + Child->f=Child->g+Child->h; + Push(Child); + } + } + } +} + +/**************************************************************************/ +/* STACK FUNCTIONS */ +/**************************************************************************/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void Push(PATHNODE *Node) +{ + Stack[numstack++] = Node; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +PATHNODE *Pop() +{ + return Stack[--numstack]; +} + +PATHNODE *GetPathNode() +{ + PATHNODE *Node; + + if(numpnodes == MAXPNODES) + return NULL; + else + { + Node = &pathnodes[numpnodes++]; + + memset((void *)Node, 0, sizeof(PATHNODE)); + return Node; + } +} diff --git a/src/PATH.H b/src/PATH.H new file mode 100644 index 0000000..89d4f01 --- /dev/null +++ b/src/PATH.H @@ -0,0 +1,36 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Path Header File +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/PATH.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXPNODES 300 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct tagPATHNODE{ + char f,h; + char g; + int x,y; + struct tagPATHNODE *Parent; + struct tagPATHNODE *Child[8]; /* a node may have upto 8+(NULL) children. */ + struct tagPATHNODE *NextNode; /* for filing purposes */ +} PATHNODE; + +/*-----------------------------------------------------------------------** +** Function Prototypes +**-----------------------------------------------------------------------*/ + +typedef BOOL (*CHECKFUNC1)(int arg1, int x, int y); + +int FindPath(CHECKFUNC1 PosOk, int PosOkArg, int sx,int sy,int dx,int dy, char path[]); diff --git a/src/PFILE.CPP b/src/PFILE.CPP new file mode 100644 index 0000000..ad1f969 --- /dev/null +++ b/src/PFILE.CPP @@ -0,0 +1,933 @@ +//****************************************************************** +// $Header: /Diablo/PFILE.CPP 3 2/04/97 11:17a Pwyatt $ +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include +#include "storm.h" +#include "diabloui.h" +#include "items.h" +#include "gendung.h" +#include "player.h" +#include "engine.h" +#include "multi.h" +#include "spells.h" +#include "packplr.h" +#include "gamemenu.h" +#include "mpqapi.h" + + +//****************************************************************** +// compiler constants +//****************************************************************** +// pjw.patch1.start -- remove retribution code +#define PREVENT_CHEATING 0 // 0 in final +#ifdef NDEBUG +#undef PREVENT_CHEATING +#define PREVENT_CHEATING 0 +#endif +// pjw.patch1.end + + +#define ENCRYPT_WITH_NAME 1 // 1 in final +#ifdef NDEBUG +#undef ENCRYPT_WITH_NAME +#define ENCRYPT_WITH_NAME 1 +#endif + +#if !ENCRYPT_WITH_NAME +#define ENCRYPTNAME "BROPER" // replace name to debug specific file +#endif + + +//****************************************************************** +// extern +//****************************************************************** +extern char gszHero[]; +extern char gszProgKey[]; +extern char gszArchiveKey[]; +extern int StrengthTbl[NUM_CLASSES]; +extern int MagicTbl[NUM_CLASSES]; +extern int DexterityTbl[NUM_CLASSES]; +extern int VitalityTbl[NUM_CLASSES]; + +DWORD CalcEncodeDstBytes(DWORD dwSrcBytes); +void EncodeFile(BYTE * pbSrcDst,DWORD dwSrcBytes,DWORD dwDstBytes,const char * pszPassword); +DWORD DecodeFile(BYTE * pbSrcDst,DWORD dwDstBytes,const char * pszPassword); +void PackClearCheater(PkPlayerStruct *pPack); +void DiskFreeErrorDlg(const char * pszDir); + + +//****************************************************************** +// public +//****************************************************************** +BOOL gbValidSaveFile = FALSE; +BOOL gbSaveFileExists = FALSE; + + +//****************************************************************** +// private +//****************************************************************** +// signature name for machines with no network name +#ifndef ENCRYPTNAME +#define ENCRYPTNAME "xrgyrkj1" +#endif + +#define ARCHIVE_PRIORITY 0x7000 + +static char sgszCharNames[MAX_CHARACTERS+1][PLR_NAME_LEN]; + +static const char sgszSaveGame[] = "game"; +static const char sgszSaveChar[] = "hero"; +static const char sgszPermSaveLevel_d[] = "perml%02d"; +static const char sgszPermSaveSLevel_d[] = "perms%02d"; +static const char sgszTempSaveLevel_d[] = "templ%02d"; +static const char sgszTempSaveSLevel_d[] = "temps%02d"; + +typedef enum { + ARCHIVE_DIABLO, + ARCHIVE_HELLFIRE + } ARCHIVE_TYPE; + + +//****************************************************************** +//****************************************************************** +static void check_disk_space_priv(char * pszDir) { + app_assert(pszDir); + + // remove any trailing path from the drive name + char * pszTemp = pszDir; + while (*pszTemp) { + if (*pszTemp++ != '\\') continue; + *pszTemp = 0; + break; + } + + DWORD dwSectorsPerCluster; + DWORD dwBytesPerSector; + DWORD dwNumberOfFreeClusters; + DWORD dwTotalNumberOfClusters; + BOOL bResult = GetDiskFreeSpace( + pszDir, + &dwSectorsPerCluster, + &dwBytesPerSector, + &dwNumberOfFreeClusters, + &dwTotalNumberOfClusters + ); + + if (bResult) { + __int64 i64BytesFree = dwNumberOfFreeClusters; + i64BytesFree *= dwSectorsPerCluster; + i64BytesFree *= dwBytesPerSector; + if (i64BytesFree < 10 * 1024 * 1024) bResult = FALSE; + } + + if (! bResult) DiskFreeErrorDlg(pszDir); +} + + +//****************************************************************** +//****************************************************************** +void check_disk_space() { + char szDir[MAX_PATH]; + + #if IS_VERSION(BETA) + if (! GetSystemDirectory(szDir,MAX_PATH)) goto error; + #else + if (! GetWindowsDirectory(szDir,MAX_PATH)) goto error; + #endif + check_disk_space_priv(szDir); + + if (! GetModuleFileName(ghInst,szDir,MAX_PATH)) goto error; + check_disk_space_priv(szDir); + + return; +error: + app_fatal("Unable to initialize save directory"); +} + + +//****************************************************************** +//****************************************************************** +static void archive_name(char * pszBuf,DWORD dwBufSize,DWORD dwChar, ARCHIVE_TYPE arType) { + app_assert(pszBuf); + app_assert(dwBufSize >= MAX_PATH); + const char * pszSaveFile_d; + UINT uiResult; + + if (gbMaxPlayers > 1) { + #if IS_VERSION(SHAREWARE) + pszSaveFile_d = "\\slinfo_%d.drv"; + #else + if (arType == ARCHIVE_DIABLO) + pszSaveFile_d = "\\dlinfo_%d.drv"; + else + pszSaveFile_d = "\\hrinfo_%d.drv"; + #endif + + #if IS_VERSION(BETA) + uiResult = GetSystemDirectory(pszBuf,MAX_PATH); + #else + uiResult = GetWindowsDirectory(pszBuf,MAX_PATH); + #endif + } + else { + #if IS_VERSION(SHAREWARE) + pszSaveFile_d = "\\spawn_%d.sv"; + #else + if (arType == ARCHIVE_DIABLO) + pszSaveFile_d = "\\single_%d.sv"; + else + pszSaveFile_d = "\\single_%d.hsv"; + #endif + + uiResult = GetModuleFileName(ghInst,pszBuf,MAX_PATH); + char * pszExeName = strrchr(pszBuf,'\\'); + if (pszExeName) *pszExeName = 0; + } + + // make sure we were able to get the parent directory + if (! uiResult) app_fatal("Unable to get save directory"); + + char szTemp[MAX_PATH]; + sprintf(szTemp,pszSaveFile_d,dwChar); + strcat(pszBuf,szTemp); + _strlwr(pszBuf); +} + + +//****************************************************************** +//****************************************************************** +static DWORD name_2_file_index(const char * pszName) { + for (DWORD d = 0; d < MAX_CHARACTERS; d++) { + if (! _stricmp(sgszCharNames[d],pszName)) + break; + } + + return d; +} + + +//****************************************************************** +//****************************************************************** +static BOOL CALLBACK GetPlayerFileNames(DWORD dwIndex,char szPath[MAX_PATH]) { + const char * pszFmt; + + if (gbMaxPlayers > 1) { + if (dwIndex) return FALSE; + pszFmt = sgszSaveChar; + } + else if (dwIndex < NUMLEVELS) { + // level file + pszFmt = sgszPermSaveLevel_d; + } + else if (dwIndex < NUMLEVELS*2) { + // slevel file + dwIndex -= NUMLEVELS; + pszFmt = sgszPermSaveSLevel_d; + } + else if (dwIndex == NUMLEVELS*2) { + // game file + pszFmt = sgszSaveGame; + } + else if (dwIndex == NUMLEVELS*2+1) { + // character file + pszFmt = sgszSaveChar; + } + else { + return FALSE; + } + + sprintf(szPath,pszFmt,dwIndex); + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static BOOL LoadCharacter(HSARCHIVE hsArchive,PkPlayerStruct * pPack) { + app_assert(pPack); + + // open the character file + HSFILE hsFile; + if (! SFileOpenFileEx(hsArchive,sgszSaveChar,0,&hsFile)) + return FALSE; + + // setup everything in case of error + BYTE * pbFile = NULL; + BOOL bResult = FALSE; + + // get password + char computername[MAX_COMPUTERNAME_LENGTH+1] = ENCRYPTNAME; + DWORD size = MAX_COMPUTERNAME_LENGTH+1; + #if ENCRYPT_WITH_NAME + if (gbMaxPlayers > 1) GetComputerName(computername,&size); + #endif + + // read character data + DWORD dwSize = SFileGetFileSize(hsFile,NULL); + if (! dwSize) goto error; + pbFile = DiabloAllocPtrSig(dwSize,'SAVt'); + DWORD dwBytes; + if (! SFileReadFile(hsFile,pbFile,dwSize,&dwBytes,NULL)) + goto error; + app_assert(dwBytes == dwSize); + + // decode file using password + dwBytes = DecodeFile(pbFile,dwSize,computername); + if (dwBytes != sizeof(*pPack)) goto error; + + // success! + CopyMemory(pPack,pbFile,sizeof(*pPack)); + bResult = TRUE; + +error: // CLEANUP + if (pbFile) DiabloFreePtr(pbFile); + SFileCloseFile(hsFile); + return bResult; +} + + +//****************************************************************** +//****************************************************************** +static void SaveCharacter(const PkPlayerStruct * pPack) { + // get password + char computername[MAX_COMPUTERNAME_LENGTH+1] = ENCRYPTNAME; + DWORD size = MAX_COMPUTERNAME_LENGTH+1; + #if ENCRYPT_WITH_NAME + if (gbMaxPlayers > 1) GetComputerName(computername,&size); + #endif + + // encrypt character data + DWORD dwDstBytes = CalcEncodeDstBytes(sizeof(*pPack)); + BYTE * pbSrcDst = DiabloAllocPtrSig(dwDstBytes,'SAVt'); + CopyMemory(pbSrcDst,pPack,sizeof(*pPack)); + EncodeFile(pbSrcDst,sizeof(*pPack),dwDstBytes,computername); + + // add file to archive + MPQAddFile(sgszSaveChar,pbSrcDst,dwDstBytes); + + // cleanup + DiabloFreePtr(pbSrcDst); +} + + +//****************************************************************** +//****************************************************************** +#if PREVENT_CHEATING +static BOOL FixCheaters(BOOL * pbMsgBox,DWORD dwChar) { + app_assert(dwChar < MAX_CHARACTERS); + + // only perform cheat detection/correction for multiplayer chars + if (gbMaxPlayers == 1) return TRUE; + + // compare current state of archive time stamps to expected values + char szSaveArchive[MAX_PATH]; + archive_name(szSaveArchive,MAX_PATH,dwChar, ARCHIVE_HELLFIRE); + if (MPQCompareTimeStamps(szSaveArchive,dwChar)) + return TRUE; + + HSARCHIVE hsArchive = NULL; + if (! SFileOpenArchive(szSaveArchive,ARCHIVE_PRIORITY,0,&hsArchive)) + return TRUE; + + // load character + PkPlayerStruct pack; + if (! LoadCharacter(hsArchive,&pack)) + pack.pName[0] = 0; + else + PackClearCheater(&pack); + SFileCloseArchive(hsArchive); + hsArchive = NULL; + + // write all characters + if (pack.pName[0]) { + if (! MPQOpenArchive(szSaveArchive,TRUE,dwChar)) return FALSE; + SaveCharacter(&pack); + MPQCloseArchive(szSaveArchive,TRUE,dwChar); + MPQUpdateCreationTimeStamp(szSaveArchive,dwChar); + } + else { + BOOL MPQSetAttributes(const char * pszArchive,BOOL bHide); + MPQSetAttributes(szSaveArchive,FALSE); + DeleteFile(szSaveArchive); + } + + if (pbMsgBox && *pbMsgBox) { + *pbMsgBox = FALSE; + UiMessageBoxCallback( + ghMainWnd, + "A problem with your saved game file has been detected." + "The file has been fixed, but changes to it may have occurred.", + "Diablo", + MB_OK + ); + } + + return TRUE; +} +#endif + + +//****************************************************************** +//****************************************************************** +static BOOL open_archive_write(BOOL bMungeOnError,DWORD dwChar) { + // make sure nobody is screwing with our file + #if PREVENT_CHEATING + if (FixCheaters(NULL,dwChar)) + #endif + { + char szSaveArchive[MAX_PATH]; + archive_name(szSaveArchive,MAX_PATH,dwChar, ARCHIVE_HELLFIRE); + if (MPQOpenArchive(szSaveArchive,gbMaxPlayers > 1,dwChar)) + return TRUE; + } + + if (bMungeOnError && gbMaxPlayers > 1) + MPQMungeStamps(dwChar); + return FALSE; +} + + +//****************************************************************** +//****************************************************************** +static void close_archive_write(BOOL bFree,DWORD dwChar) { + char szSaveArchive[MAX_PATH]; + archive_name(szSaveArchive,MAX_PATH,dwChar, ARCHIVE_HELLFIRE); + MPQCloseArchive(szSaveArchive,bFree,dwChar); +} + + +//****************************************************************** +//****************************************************************** +static HSARCHIVE open_archive_read(BOOL * pbMsgBox,DWORD dwChar) { + // make sure nobody is screwing with our file + #if PREVENT_CHEATING + if (! FixCheaters(pbMsgBox,dwChar)) + return FALSE; + #endif + + // open the archive for reading + HSARCHIVE hsArchive; + char szSaveArchive[MAX_PATH]; + archive_name(szSaveArchive,MAX_PATH,dwChar, ARCHIVE_HELLFIRE); + if (! SFileOpenArchive(szSaveArchive,ARCHIVE_PRIORITY,0,&hsArchive)) + { + //archive_name(szSaveArchive,MAX_PATH,dwChar, ARCHIVE_DIABLO); + //if (! SFileOpenArchive(szSaveArchive,ARCHIVE_PRIORITY,0,&hsArchive)) + return NULL; + } + return hsArchive; +} + + +//****************************************************************** +//****************************************************************** +static void close_archive_read(HSARCHIVE hsArchive) { + app_assert(hsArchive); + SFileCloseArchive(hsArchive); +} + + +//****************************************************************** +//****************************************************************** +static BOOL check_valid_save(HSARCHIVE hsArchive,DWORD dwChar) { + app_assert(dwChar < MAX_CHARACTERS); + + BOOL Result = FALSE; + + gbSaveFileExists = FALSE; + + // only single player games can have save games + if (gbMaxPlayers != 1) + return Result; + + HSFILE hsFile; + if (! SFileOpenFileEx(hsArchive,sgszSaveGame,0,&hsFile)) + return Result; + + // allocate a buffer large enough for the file + DWORD dwLen = SFileGetFileSize(hsFile,NULL); + if (! dwLen) app_fatal("Invalid save file"); + BYTE * pbData = DiabloAllocPtrSig(dwLen + 8,'SAVt'); + + // decode overwrites the headers, so give it extra room + BYTE *pbHackData = 4 + pbData; + + DWORD dwBytes; + if (SFileReadFile(hsFile, pbHackData, dwLen, &dwBytes, NULL)) + { + if (dwBytes == dwLen) + { + char computername[MAX_COMPUTERNAME_LENGTH+1] = ENCRYPTNAME; + DWORD size = MAX_COMPUTERNAME_LENGTH+1; + #if ENCRYPT_WITH_NAME + if (gbMaxPlayers > 1) GetComputerName(computername,&size); + #endif + + gbSaveFileExists = TRUE; + + dwLen = DecodeFile(pbHackData,dwLen,computername); + if (dwLen) + { + long id; + id = *pbHackData << 24; + pbHackData++; + id |= *pbHackData << 16; + pbHackData++; + id |= *pbHackData << 8; + pbHackData++; + id |= *pbHackData; + + // Test first 4 bytes for our header. + if ('HELF' == id) + { + Result = TRUE; + } + } + } + } + + if (pbData) DiabloFreePtr(pbData); + SFileCloseFile(hsFile); + return Result; +} + + +//****************************************************************** +//****************************************************************** +void UpdatePlayerFile() { + app_assert(myplr >= 0 && myplr < MAX_PLRS); + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + if (! open_archive_write(TRUE,dwChar)) return; + + // pack and save player + PkPlayerStruct pack; + PackPlayer(&pack,myplr); + SaveCharacter(&pack); + + // close archive -- in single player mode, release + // the file memory. In multiplayer mode, leave the + // file info in memory so we don't have to reload + close_archive_write(gbMaxPlayers == 1,dwChar); +} + + +//****************************************************************** +//****************************************************************** +void ReleasePlayerFile() { + // free any memory associated with player file + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + close_archive_write(TRUE,dwChar); +} + + +//****************************************************************** +//****************************************************************** +static char ui_2_game_class(int heroclass) { + if (heroclass == UI_WARRIOR) + return CLASS_WARRIOR; + if (heroclass == UI_ROGUE) + return CLASS_ROGUE; + if (heroclass == UI_MONK) + return CLASS_MONK; + if (heroclass == UI_BARD) + return CLASS_BARD; + if (heroclass == UI_BARBARIAN) + return CLASS_BARBARIAN; + return CLASS_SORCEROR; +} + + +//****************************************************************** +//****************************************************************** +static BYTE game_2_ui_class(const PlayerStruct * p) { + if (p->_pClass == CLASS_WARRIOR) + return UI_WARRIOR; + if (p->_pClass == CLASS_ROGUE) + return UI_ROGUE; + if (p->_pClass == CLASS_MONK) + return UI_MONK; + if (p->_pClass == CLASS_BARD) + return UI_BARD; + if (p->_pClass == CLASS_BARBARIAN) + return UI_BARBARIAN; + return UI_SORCERER; +} + + +//****************************************************************** +//****************************************************************** +void game_2_ui_player(const PlayerStruct * p,TPUIHEROINFO heroinfo,BOOL bHasSaveFile) { + ZeroMemory(heroinfo,sizeof(TUIHEROINFO)); + strncpy(heroinfo->name,p->_pName,MAX_NAME_LEN-1); + heroinfo->name[MAX_NAME_LEN-1] = 0; + heroinfo->level = p->_pLevel; + heroinfo->heroclass = game_2_ui_class(p); + heroinfo->strength = p->_pStrength; + heroinfo->magic = p->_pMagic; + heroinfo->dexterity = p->_pDexterity; + heroinfo->vitality = p->_pVitality; + heroinfo->gold = p->_pGold; + heroinfo->hassaved = bHasSaveFile; + heroinfo->herorank = (BYTE) p->pDiabloKillLevel; + heroinfo->spawned = IS_VERSION(SHAREWARE); +} + + +//****************************************************************** +//****************************************************************** +BOOL CALLBACK UiEnumHeroes(ENUMHEROPROC enumproc) { + // assume there is no archive + ZeroMemory(sgszCharNames,sizeof(sgszCharNames)); + + // get the character name field and save into global + BOOL bMsgBox = TRUE; + for (DWORD dwChar = 0; dwChar < MAX_CHARACTERS; dwChar++) { + HSARCHIVE hsArchive; + if (NULL == (hsArchive = open_archive_read(&bMsgBox,dwChar))) + continue; + + PkPlayerStruct pack; + TUIHEROINFO heroinfo; + BOOL bResult = LoadCharacter(hsArchive,&pack); + if (bResult) { + app_assert(sizeof sgszCharNames[dwChar] == sizeof pack.pName); + strcpy(sgszCharNames[dwChar],pack.pName); + UnPackPlayer(&pack,0,FALSE); + game_2_ui_player(&plr[0],&heroinfo,check_valid_save(hsArchive,dwChar)); + enumproc(&heroinfo); + } + + // close archive + close_archive_read(hsArchive); + } + + return 1; +} + + +//****************************************************************** +//****************************************************************** +BOOL CALLBACK UiGetDefaultCharStats(int heroclass, TPUIDEFSTATS defaultstats) { + int nClass = ui_2_game_class(heroclass); + defaultstats->strength = StrengthTbl[nClass]; + defaultstats->magic = MagicTbl[nClass]; + defaultstats->dexterity = DexterityTbl[nClass]; + defaultstats->vitality = VitalityTbl[nClass]; + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +BOOL CALLBACK UiCreateHero(TPUIHEROINFO heroinfo) { + app_assert(heroinfo->name[0]); + + // find out if this guy already exists + // or find a free hero slot + DWORD dwChar = name_2_file_index(heroinfo->name); + if (dwChar >= MAX_CHARACTERS) { + for (dwChar = 0; dwChar < MAX_CHARACTERS; dwChar++) + if (! sgszCharNames[dwChar][0]) + break; + } + if (dwChar >= MAX_CHARACTERS) + return FALSE; + + // open archive to save character + if (! open_archive_write(FALSE,dwChar)) return FALSE; + + // we are going to overwrite a save slot. If the player + // has done any hacking, there may be invalid save files + // from a previous player in the slot. Remove those files + MPQDeleteFiles(GetPlayerFileNames); + + // fix up the name table + strncpy(sgszCharNames[dwChar],heroinfo->name,PLR_NAME_LEN); + sgszCharNames[dwChar][PLR_NAME_LEN - 1] = 0; + + // create character in player slot 0 + // heroinfo->heroclass = UI_BARD; + CreatePlayer(0,ui_2_game_class(heroinfo->heroclass)); + strncpy(plr[0]._pName,heroinfo->name,PLR_NAME_LEN); + plr[0]._pName[PLR_NAME_LEN - 1] = 0; + + // pack character and save + PkPlayerStruct pack; + PackPlayer(&pack,0); + SaveCharacter(&pack); + + // convert character into something the UI can use + + game_2_ui_player(&plr[0],heroinfo,FALSE); + + close_archive_write(TRUE,dwChar); + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +BOOL CALLBACK UiDeleteHero(TPUIHEROINFO heroinfo) { + DWORD dwChar = name_2_file_index(heroinfo->name); + if (dwChar >= MAX_CHARACTERS) return TRUE; + + // delete character + sgszCharNames[dwChar][0] = 0; + + // delete archive + char szSaveArchive[MAX_PATH]; + archive_name(szSaveArchive,MAX_PATH,dwChar, ARCHIVE_HELLFIRE); + DeleteFile(szSaveArchive); + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +void SetupLocalPlayer() { + // load the player information we want into our player slot + app_assert(myplr >= 0 && myplr < MAX_PLRS); + DWORD dwChar = name_2_file_index(gszHero); + app_assert(dwChar != MAX_CHARACTERS); + + // open the main archive + HSARCHIVE hsArchive; + PkPlayerStruct pack; + if (NULL == (hsArchive = open_archive_read(NULL,dwChar))) + app_fatal("Unable to open archive"); + if (! LoadCharacter(hsArchive,&pack)) + app_fatal("Unable to load character"); + UnPackPlayer(&pack,myplr,FALSE); + gbValidSaveFile = check_valid_save(hsArchive,dwChar); + close_archive_read(hsArchive); +} + + +//****************************************************************** +//****************************************************************** +void CreateSaveLevelName(char szName[MAX_PATH]) { + // make sure the character is currently valid + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + app_assert(dwChar < MAX_CHARACTERS); + app_assert(gbMaxPlayers == 1); + + // saving a level always saves it as a "temporary" save file + if (setlevel) sprintf(szName,sgszTempSaveSLevel_d,setlvlnum); + else sprintf(szName,sgszTempSaveLevel_d,currlevel); +} + + +//****************************************************************** +//****************************************************************** +void CreateLoadLevelName(char szName[MAX_PATH]) { + // make sure the character is currently valid + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + app_assert(dwChar < MAX_CHARACTERS); + app_assert(gbMaxPlayers == 1); + + // try "temporary" save file name + CreateSaveLevelName(szName); + + if (! open_archive_write(FALSE,dwChar)) + app_fatal("Unable to read to save file archive"); + BOOL bResult = MPQFileExists(szName); + close_archive_write(TRUE,dwChar); + if (bResult) return; + + // create "permanent" save file name + if (setlevel) sprintf(szName,sgszPermSaveSLevel_d,setlvlnum); + else sprintf(szName,sgszPermSaveLevel_d,currlevel); +} + + +//****************************************************************** +//****************************************************************** +void CreateSaveGameName(char szName[MAX_PATH]) { + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + app_assert(dwChar < MAX_CHARACTERS); + app_assert(gbMaxPlayers == 1); + strcpy(szName,sgszSaveGame); +} + + +//****************************************************************** +//****************************************************************** +static BOOL CALLBACK GetPermSaveNames(DWORD dwIndex,char szPath[MAX_PATH]) { + const char * pszFmt; + + app_assert(gbMaxPlayers == 1); + if (dwIndex < NUMLEVELS) { + // level file + pszFmt = sgszPermSaveLevel_d; + } + else if (dwIndex < NUMLEVELS*2) { + // slevel file + dwIndex -= NUMLEVELS; + pszFmt = sgszPermSaveSLevel_d; + } + else { + return FALSE; + } + + sprintf(szPath,pszFmt,dwIndex); + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static BOOL CALLBACK GetTempSaveNames(DWORD dwIndex,char szPath[MAX_PATH]) { + const char * pszFmt; + + app_assert(gbMaxPlayers == 1); + if (dwIndex < NUMLEVELS) { + // level file + pszFmt = sgszTempSaveLevel_d; + } + else if (dwIndex < NUMLEVELS*2) { + // slevel file + dwIndex -= NUMLEVELS; + pszFmt = sgszTempSaveSLevel_d; + } + else { + return FALSE; + } + + sprintf(szPath,pszFmt,dwIndex); + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +void DestroyTempSaves() { + if (gbMaxPlayers > 1) return; + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + app_assert(dwChar < MAX_CHARACTERS); + if (! open_archive_write(FALSE,dwChar)) + app_fatal("Unable to write to save file archive"); + MPQDeleteFiles(GetTempSaveNames); + close_archive_write(TRUE,dwChar); +} + + +//****************************************************************** +//****************************************************************** +void MoveTempSavesToPermanent() { + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + app_assert(dwChar < MAX_CHARACTERS); + app_assert(gbMaxPlayers == 1); + + if (! open_archive_write(FALSE,dwChar)) + app_fatal("Unable to write to save file archive"); + + DWORD dwIndex = 0; + char szTemp[MAX_PATH]; + char szPerm[MAX_PATH]; + while (GetTempSaveNames(dwIndex,szTemp)) { + BOOL bResult = GetPermSaveNames(dwIndex,szPerm); + app_assert(bResult); + dwIndex++; + + // is there a temp file? + if (! MPQFileExists(szTemp)) continue; + + // delete permanent file so we can rename temp file + if (MPQFileExists(szPerm)) MPQDeleteFile(szPerm); + + MPQRenameFile(szTemp,szPerm); + } + app_assert(! GetPermSaveNames(dwIndex,szPerm)); + + close_archive_write(TRUE,dwChar); +} + + +//****************************************************************** +//****************************************************************** +void WriteSaveFile(const char * pszName,BYTE * pbData,DWORD dwLen,DWORD dwDstBytes) { + app_assert(pszName); + app_assert(pbData); + app_assert(dwLen); + app_assert(gbMaxPlayers == 1); + + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + app_assert(dwChar < MAX_CHARACTERS); + + // encode file + char computername[MAX_COMPUTERNAME_LENGTH+1] = ENCRYPTNAME; + DWORD size = MAX_COMPUTERNAME_LENGTH+1; + #if ENCRYPT_WITH_NAME + if (gbMaxPlayers > 1) GetComputerName(computername,&size); + #endif + EncodeFile(pbData,dwLen,dwDstBytes,computername); + + if (! open_archive_write(FALSE,dwChar)) + app_fatal("Unable to write to save file archive"); + MPQAddFile(pszName,pbData,dwDstBytes); + close_archive_write(TRUE,dwChar); +} + + +//****************************************************************** +//****************************************************************** +BYTE * ReadSaveFile(const char * pszName,DWORD * pdwLen) { + app_assert(pszName); + app_assert(pdwLen); + app_assert(gbMaxPlayers == 1); + + DWORD dwChar = name_2_file_index(plr[myplr]._pName); + app_assert(dwChar < MAX_CHARACTERS); + + HSARCHIVE hsArchive; + if (NULL == (hsArchive = open_archive_read(NULL,dwChar))) + app_fatal("Unable to open save file archive"); + + HSFILE hsFile; + if (! SFileOpenFileEx(hsArchive,pszName,0,&hsFile)) + app_fatal("Unable to open save file"); + + // allocate a buffer large enough for the file + *pdwLen = SFileGetFileSize(hsFile,NULL); + if (! *pdwLen) app_fatal("Invalid save file"); + BYTE * pbData = DiabloAllocPtrSig(*pdwLen,'SAVt'); + + DWORD dwBytes; + if (! SFileReadFile(hsFile,pbData,*pdwLen,&dwBytes,NULL)) + app_fatal("Unable to read save file"); + app_assert(dwBytes == *pdwLen); + + SFileCloseFile(hsFile); + close_archive_read(hsArchive); + + char computername[MAX_COMPUTERNAME_LENGTH+1] = ENCRYPTNAME; + DWORD size = MAX_COMPUTERNAME_LENGTH+1; + #if ENCRYPT_WITH_NAME + if (gbMaxPlayers > 1) GetComputerName(computername,&size); + #endif + *pdwLen = DecodeFile(pbData,*pdwLen,computername); + if (! *pdwLen) app_fatal("Invalid save file"); + + return pbData; +} + + +//****************************************************************** +//****************************************************************** +void TimedUpdatePlayerFile(BOOL bForce) { + #define SAVE_TICKS (60*1000) // 60 seconds + static long slSaveTime = 0; + if (gbMaxPlayers == 1) return; + + long lCurrTime = (long) GetTickCount(); + if (bForce || lCurrTime - slSaveTime > SAVE_TICKS) { + slSaveTime = lCurrTime; + UpdatePlayerFile(); + } +} diff --git a/src/PLAYER.CPP b/src/PLAYER.CPP new file mode 100644 index 0000000..9365d2a --- /dev/null +++ b/src/PLAYER.CPP @@ -0,0 +1,4759 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Player file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/PLAYER.CPP 11 10-03-97 13:40 Jmcreynolds $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "msg.h" +#include "multi.h" +#include "debug.h" +#include "engine.h" +#include "gendung.h" +#include "palette.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "missiles.h" +#include "spells.h" +#include "inv.h" +#include "lighting.h" +#include "cursor.h" +#include "control.h" +#include "effects.h" +#include "objects.h" +#include "town.h" +#include "towners.h" +#include "monstint.h" +#include "monstdat.h" +#include "gamemenu.h" +#include "stores.h" +#include "spelldat.h" +#include "path.h" +#include "quests.h" +#include "minitext.h" +#include "textdat.h" +#include "portal.h" +#include "themes.h" +#include "objdat.h" + +void SetPlrHandItem(ItemStruct *h, int idata); +void GetPlrHandSeed(ItemStruct *h); +void GetGoldSeed(int pnum, ItemStruct *h); +void SetPrlHandSeed(ItemStruct *h, int iseed); +void FixPlrWalkTags(int pnum); +void RemovePlrFromMap(int pnum); +void SetPlrHandGoldCurs(ItemStruct *h); + +extern BOOL GoldAutoPlace(int pnum); +extern HSARCHIVE ghsHFBardArchive; +extern HSARCHIVE ghsHFBarbarianArchive; +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ +// pjw.patch1.start +// PlayerStruct plr[MAX_PLRS]; +PlayerStruct * plr = NULL; +// pjw.patch1.end +int myplr; +int deathdelay; +BOOL deathflag; + +/*-----------------------------------------------------------------------* +** File Variables +**-----------------------------------------------------------------------*/ +// Init View offsets +int plrxoff[9] = { 0, 2, 0, 2, 1, 0, 1, 2, 1 }; +int plryoff[9] = { 0, 2, 2, 0, 1, 1, 0, 1, 2 }; + +int plrxoff2[9] = { 0, 1, 0, 1, 2, 0, 1, 2, 2 }; +int plryoff2[9] = { 0, 0, 1, 1, 0, 2, 2, 1, 2 }; + + +/*-----------------------------------------------------------------------*/ +char PlrGFXAnimLens[NUM_CLASSES][11] = { + // Warrior + // AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame + { 10, 16, 8, 2, 20, 20, 6, 20, 8, 9, 14 }, + // Rogue + // AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame + { 8, 18, 8, 4, 20, 16, 7, 20, 8, 10, 12 }, + // Sorceror + // AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame + { 8, 16, 8, 6, 20, 12, 8, 20, 8, 12, 8 }, + // Monk + // AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame + { 8, 16, 8, 3, 20, 18, 6, 20, 8, 12, 13 }, +// Fix this when we get art. + // Bard + // AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame + { 8, 18, 8, 4, 20, 16, 7, 20, 8, 10, 12 }, + // Barbarian + // AS, AT, AW, BL, DT, Magic, HT, ST, WL, AFrame, SFrame + { 10, 16, 8, 2, 20, 20, 6, 20, 8, 9, 14 }, +}; + +/*-----------------------------------------------------------------------*/ + +// Different walk velocities for different classes +int PlrWalkTbl[NUM_CLASSES][3] = { + { 2048, 1024, 512 }, // Warrior (8 frames) + //{ 2730, 1365, 682 }, // Warrior (6 frames) + { 2048, 1024, 512 }, // Rogue (8 frames) + //{ 2340, 1170, 585 }, // Rogue (7 frames) + { 2048, 1024, 512 }, // Sorceror (8 frames) + { 2048, 1024, 512 }, // Monk (8 frames) + { 2048, 1024, 512 }, // Bard (8 frames) + { 2048, 1024, 512 } }; // Barbarian (8 frames) + +// Different walk lengths for different classes +//int PlrWalkLenTbl[3] = { 6, 7, 8 }; +int PlrWalkLenTbl[NUM_CLASSES] = { 8, 8, 8, 8, 8, 8 }; + +extern DWORD gbWalkOn; // double speed walk + +/*-----------------------------------------------------------------------*/ + +int StrengthTbl[NUM_CLASSES] = { 30, 20, 15, 25, 20, 40}; +int MagicTbl[NUM_CLASSES] = { 10, 15, 35, 15, 20, 0}; +int DexterityTbl[NUM_CLASSES] = { 20, 30, 15, 25, 25, 20}; +int VitalityTbl[NUM_CLASSES] = { 25, 20, 20, 20, 20, 25}; + +//int ToHitTbl[NUM_CLASSES] = { 50, 50, 50 }; +int ToBlkTbl[NUM_CLASSES] = { 30, 20, 10, 25, 25, 30}; + +char *ClassStrTbl[NUM_CLASSES] = { "Warrior", + "Rogue", + "Sorceror", + "Monk", + "Bard", + "Barbarian" }; + +/*-----------------------------------------------------------------------*/ + +int MaxStats[NUM_CLASSES][4] = { + // Str, Mag, Dex, Vit. + { 250, 50, 60, 100 }, // warrior + { 55, 70, 250, 80 }, // rogue + { 45, 250, 85, 80 }, // sorceror + { 150, 80, 150, 80 }, // monk + { 120, 120, 120, 100 }, // bard + { 255, 0, 55, 150 }, // barbarian + }; + +/*-----------------------------------------------------------------------*/ + +#define MAX_EXPLVLS 50 + +long ExpLvlsTbl[MAX_EXPLVLS+1] = { +/* 0, // 0 Changed 11/5 Dave + 1000, // 1 + 2400, // 2 + 4353, // 3 + 7070, // 4 + 10837, // 5 + 16044, // 6 + 23217, // 7 + 33065, // 8 + 46542, // 9 + 64925, // 10 + 89917, // 11 + 123782, // 12 + 169516, // 13*/ + + 0, // 0 + 2000, // 1 + 4620, // 2 + 8040, // 3 + 12489, // 4 + 18258, // 5 + 25712, // 6 + 35309, // 7 + 47622, // 8 + 63364, // 9 + 83419, // 10 + 108879, // 11 + 141086, // 12 + 181683, // 13 + 231075, // 14 + 313656, // 15 + 424067, // 16 + 571190, // 17 + 766569, // 18 + 1025154, // 19 + 1366227, // 10 + 1814568, // 21 + 2401895, // 22 + 3168651, // 23 + 4166200, // 24 + 5459523, // 25 + 7130496, // 26 + 9281874, // 27 + 12042092, // 28 + 15571031, // 29 + 20066900, // 30 + 25774405, // 31 + 32994399, // 32 + 42095202, // 33 + 53525811, // 34 + 67831218, // 35 + 85670061, // 36 + 107834823, // 37 + 135274799, // 38 + 169122009, // 39 + 210720231, // 40 + 261657253, // 41 + 323800420, // 42 + 399335440, // 43 + 490808349, // 44 + 601170414, // 45 + 733825617, // 46 + 892680222, // 47 + 1082908612, // 48 + 1310707109, // 49 + 1583495809 }; // 50 + + +/*-----------------------------------------------------------------------* +** player animation files +**-----------------------------------------------------------------------*/ +static const char plrgfxlmh[] = "LMH"; +static const char plrgfxweap[] = "NUSDBAMHT"; +static const char sgcCharClass[NUM_CLASSES] = { 'W', 'R', 'S', 'M', 'B', 'C' }; +static const char sgcAlterCharClass[NUM_CLASSES] = { 'W', 'R', 'S', 'M', 'R', 'W'}; +static const char * const sgpszCharDir[NUM_CLASSES] = { + "Warrior","Rogue","Sorceror","Monk","Bard","Barbarian" +}; +static const char * const sgpszAlterCharDir[NUM_CLASSES] = { + "Warrior","Rogue","Sorceror","Monk","Rogue","Warrior" +}; + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetAnimPtrs(BYTE *pData, BYTE *pAnim[]) { + for (int i = 0; i < 8; i++) + pAnim[i] = pData + ((DWORD*)pData)[i]; +} + + +/*-----------------------------------------------------------------------* +** loads player anims based on bit flags +**-----------------------------------------------------------------------*/ +void LoadPlrGFX(int pnum,DWORD dwLoad) { + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("LoadPlrGFX: illegal player %d",pnum); + // get a pointer to the player + PlayerStruct * pPlayer = &plr[pnum]; + + // calculate which player type, weapon and armor values to use + #if IS_VERSION(SHAREWARE) + app_assert(pPlayer->_pClass == CLASS_WARRIOR); + #else + app_assert((DWORD) pPlayer->_pClass <= NUM_CLASSES); + #endif + + char szPlrType[16]; + char const * pszPlrPath = ""; + if ((pPlayer->_pClass == CLASS_BARD && ghsHFBardArchive == NULL) + || (pPlayer->_pClass == CLASS_BARBARIAN && ghsHFBarbarianArchive == NULL)) + { + sprintf( + szPlrType, + "%c%c%c", + sgcAlterCharClass[pPlayer->_pClass], // player class + plrgfxlmh[pPlayer->_pgfxnum >> PGFX_CSHIFT], // armor class + plrgfxweap[pPlayer->_pgfxnum & PGFX_MASK] // weapon + ); + pszPlrPath = sgpszAlterCharDir[pPlayer->_pClass]; + } else { + sprintf( + szPlrType, + "%c%c%c", + sgcCharClass[pPlayer->_pClass], // player class + plrgfxlmh[pPlayer->_pgfxnum >> PGFX_CSHIFT], // armor class + plrgfxweap[pPlayer->_pgfxnum & PGFX_MASK] // weapon + ); + pszPlrPath = sgpszCharDir[pPlayer->_pClass]; + } + // get player directory + + // load file + BYTE * pData; + BYTE ** ppAnim; + const char * pszAnim; + for (DWORD dwBit = 1; dwBit <= PGL_ALL; dwBit <<= 1) { + // load this graphic set? + if (! (dwBit & dwLoad)) continue; + + switch (dwBit) { + + case PGL_STAND: + // load dungeon/town stand + pszAnim = leveltype ? "AS" : "ST"; + pData = pPlayer->_pNData; + ppAnim = pPlayer->_pNAnim; + break; + + case PGL_WALK: + // load dungeon/town walk + pszAnim = leveltype ? "AW" : "WL"; + pData = pPlayer->_pWData; + ppAnim = pPlayer->_pWAnim; + break; + + case PGL_DEAD: + // dead anim only valid for guy holding no weapons + if ((pPlayer->_pgfxnum & PGFX_MASK) != PGFX_NGUY) continue; + pszAnim = "DT"; + pData = pPlayer->_pDData; + ppAnim = pPlayer->_pDAnim; + break; + + case PGL_ATTACK: + if (! leveltype) continue; + pszAnim = "AT"; + pData = pPlayer->_pAData; + ppAnim = pPlayer->_pAAnim; + break; + + case PGL_HIT: + if (! leveltype) continue; + pszAnim = "HT"; + pData = pPlayer->_pHData; + ppAnim = pPlayer->_pHAnim; + break; + + case PGL_LMAG: + if (! leveltype) continue; + pszAnim = "LM"; + pData = pPlayer->_pLData; + ppAnim = pPlayer->_pLAnim; + break; + + case PGL_FMAG: + if (! leveltype) continue; + pszAnim = "FM"; + pData = pPlayer->_pFData; + ppAnim = pPlayer->_pFAnim; + break; + + case PGL_TMAG: + if (! leveltype) continue; + pszAnim = "QM"; + pData = pPlayer->_pTData; + ppAnim = pPlayer->_pTAnim; + break; + + case PGL_BLOCK: + if (! leveltype) continue; + if (! pPlayer->_pBlockFlag) continue; + pszAnim = "BL"; + pData = pPlayer->_pBData; + ppAnim = pPlayer->_pBAnim; + break; + + default: + app_fatal("PLR:2"); + break; + } + + char szBuf[256]; + sprintf( + szBuf, + #if RLE_DRAW + "PlrGFX\\%s\\%s\\%s%s.CL2", + #else + "PlrGFX\\%s\\%s\\%s%s.CEL", + #endif + pszPlrPath, + szPlrType, + szPlrType, + pszAnim + ); + + app_assert(pData); + LoadFileWithMem(szBuf,pData); + SetAnimPtrs(pData,ppAnim); + pPlayer->_pGFXLoad |= dwBit; + } +} + + +/*-----------------------------------------------------------------------* +** loads all player anims +**-----------------------------------------------------------------------*/ +void InitPlayerGFX(int pnum) { + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("InitPlayerGFX: illegal player %d",pnum); + if ((plr[pnum]._pHitPoints >> HP_SHIFT) == 0) { + plr[pnum]._pgfxnum = PGFX_NGUY; + LoadPlrGFX(pnum, PGL_DEAD); + } else { + LoadPlrGFX(pnum,PGL_ALL); + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static DWORD calc_plr_mem(const char * pszAnim) { + DWORD dwMax = 0; + + for (DWORD dwClass = 0; dwClass < NUM_CLASSES; dwClass++) { + #if IS_VERSION(SHAREWARE) + if (dwClass != CLASS_WARRIOR) continue; + #endif + + for (const char * pszArmor = plrgfxlmh; *pszArmor; pszArmor++) { + #if IS_VERSION(SHAREWARE) + if (pszArmor != plrgfxlmh) break; + #endif + + for (const char * pszWeap = plrgfxweap; *pszWeap; pszWeap++) { + char szPlrType[16]; + char szBuf[256]; + + if ((dwClass == CLASS_BARD && ghsHFBardArchive == NULL) + || (dwClass == CLASS_BARBARIAN && ghsHFBarbarianArchive == NULL)) + { + sprintf( szPlrType, "%c%c%c", + sgcAlterCharClass[dwClass], + *pszArmor, + *pszWeap ); + sprintf( szBuf, + #if RLE_DRAW + "PlrGFX\\%s\\%s\\%s%s.CL2", + #else + "PlrGFX\\%s\\%s\\%s%s.CEL", + #endif + sgpszAlterCharDir[dwClass], + szPlrType, + szPlrType, + pszAnim + ); //whew + } else { + sprintf( szPlrType, "%c%c%c", + sgcCharClass[dwClass], + *pszArmor, + *pszWeap ); + sprintf( szBuf, + #if RLE_DRAW + "PlrGFX\\%s\\%s\\%s%s.CL2", + #else + "PlrGFX\\%s\\%s\\%s%s.CEL", + #endif + sgpszCharDir[dwClass], + szPlrType, + szPlrType, + pszAnim + ); //whew + } + + HSFILE hsFile; + if (! patSFileOpenFile(szBuf,&hsFile,TRUE)) + continue; + + app_assert(hsFile); + DWORD dwSize = patSFileGetFileSize(hsFile); + patSFileCloseFile(hsFile); + dwMax = max(dwMax,dwSize); + } + } + } + + return dwMax; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +// remember to update these numbers if we ever add another set of +// player graphics + +void InitPlrGFXMem(int pnum) { + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("InitPlrGFXMem: illegal player %d",pnum); + app_assert(! plr[pnum]._pNData); + + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL ) + ? 0x35E28 : max(calc_plr_mem("AS"),calc_plr_mem("ST")); + plr[pnum]._pNData = DiabloAllocPtrSig(dwMem,'PGFN'); + } + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL) + ? 0x16EB9 : max(calc_plr_mem("AW"),calc_plr_mem("WL")); + plr[pnum]._pWData = DiabloAllocPtrSig(dwMem,'PGFW'); + } + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL) + ? 0x40047 : calc_plr_mem("AT"); + plr[pnum]._pAData = DiabloAllocPtrSig(dwMem,'PGFA'); + } + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL) + ? 0x16484 : calc_plr_mem("HT"); + plr[pnum]._pHData = DiabloAllocPtrSig(dwMem,'PGFH'); + } + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL) + ? 0x4AD88 : calc_plr_mem("LM"); + plr[pnum]._pLData = DiabloAllocPtrSig(dwMem,'PGFL'); + } + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL) + ? 0x67AED : calc_plr_mem("FM"); + plr[pnum]._pFData = DiabloAllocPtrSig(dwMem,'PGFF'); + } + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL) + ? 0x92F55 : calc_plr_mem("QM"); + plr[pnum]._pTData = DiabloAllocPtrSig(dwMem,'PGFT'); + } + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL) + ? 0x3A8A6 : calc_plr_mem("DT"); + plr[pnum]._pDData = DiabloAllocPtrSig(dwMem,'PGFD'); + } + { + static DWORD dwMem = (ghsHFBardArchive == NULL && ghsHFBarbarianArchive == NULL) + ? 0x10FE3 : calc_plr_mem("BL"); + plr[pnum]._pBData = DiabloAllocPtrSig(dwMem,'PGFB'); + } + + // no gfx loaded + plr[pnum]._pGFXLoad = 0; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreePlayerGFX(int pnum) { + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("FreePlayerGFX: illegal player %d",pnum); + DiabloFreePtr(plr[pnum]._pNData); + DiabloFreePtr(plr[pnum]._pWData); + DiabloFreePtr(plr[pnum]._pAData); + DiabloFreePtr(plr[pnum]._pHData); + DiabloFreePtr(plr[pnum]._pLData); + DiabloFreePtr(plr[pnum]._pFData); + DiabloFreePtr(plr[pnum]._pTData); + DiabloFreePtr(plr[pnum]._pDData); + DiabloFreePtr(plr[pnum]._pBData); + plr[pnum]._pGFXLoad = 0; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void NewPlrAnim(int pnum, BYTE *pAnim, int numFrames, int Delay, long width) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("NewPlrAnim: illegal player %d",pnum); + plr[pnum]._pAnimData = pAnim; + plr[pnum]._pAnimLen = numFrames; + plr[pnum]._pAnimFrame = 1; + plr[pnum]._pAnimCnt = 0; + plr[pnum]._pAnimDelay = Delay; + plr[pnum]._pAnimWidth = width; + plr[pnum]._pAnimWidth2 = (width - 64) >> 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ClearPlrPVars(int pnum) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("ClearPlrPVars: illegal player %d",pnum); + plr[pnum]._pVar1 = 0; + plr[pnum]._pVar2 = 0; + plr[pnum]._pVar3 = 0; + plr[pnum]._pVar4 = 0; + plr[pnum]._pVar5 = 0; + plr[pnum]._pVar6 = 0; + plr[pnum]._pVar7 = 0; + plr[pnum]._pVar8 = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPlrAnims(int pnum) +{ + int gn,pc; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("SetPlrAnims: illegal player %d",pnum); + plr[pnum]._pNWidth = 96; + plr[pnum]._pWWidth = 96; + plr[pnum]._pAWidth = 128; + plr[pnum]._pHWidth = 96; + plr[pnum]._pSWidth = 96; + plr[pnum]._pDWidth = 128; + plr[pnum]._pBWidth = 96; + + pc = plr[pnum]._pClass; + if (leveltype == 0) { + plr[pnum]._pNFrames = PlrGFXAnimLens[pc][7]; + plr[pnum]._pWFrames = PlrGFXAnimLens[pc][8]; + plr[pnum]._pDFrames = PlrGFXAnimLens[pc][4]; + plr[pnum]._pSFrames = PlrGFXAnimLens[pc][5]; + plr[pnum]._pSFNum = PlrGFXAnimLens[pc][10]; + } + else { + plr[pnum]._pNFrames = PlrGFXAnimLens[pc][0]; + plr[pnum]._pWFrames = PlrGFXAnimLens[pc][2]; + plr[pnum]._pAFrames = PlrGFXAnimLens[pc][1]; + plr[pnum]._pHFrames = PlrGFXAnimLens[pc][6]; + plr[pnum]._pSFrames = PlrGFXAnimLens[pc][5]; + plr[pnum]._pDFrames = PlrGFXAnimLens[pc][4]; + plr[pnum]._pBFrames = PlrGFXAnimLens[pc][3]; + plr[pnum]._pAFNum = PlrGFXAnimLens[pc][9]; + plr[pnum]._pSFNum = PlrGFXAnimLens[pc][10]; + } + + gn = plr[pnum]._pgfxnum & PGFX_MASK; + if (pc == CLASS_WARRIOR) { + if (gn == PGFX_BGUY) { // Bow + if (leveltype != 0) plr[pnum]._pNFrames = 8; + plr[pnum]._pAWidth = 96; + plr[pnum]._pAFNum = 11; + } + else if (gn == PGFX_FGUY) { // Axe + plr[pnum]._pAFrames = 20; + plr[pnum]._pAFNum = 10; + } + else if (gn == PGFX_TGUY) { // Staff + plr[pnum]._pAFrames = 16; + plr[pnum]._pAFNum = 11; + } + } +#if !IS_VERSION(SHAREWARE) + else if (pc == CLASS_ROGUE) { + if (gn == PGFX_FGUY) { // Axe + plr[pnum]._pAFrames = 22; + plr[pnum]._pAFNum = 13; + } + else if (gn == PGFX_BGUY) { // Bow + plr[pnum]._pAFrames = 12; + plr[pnum]._pAFNum = 7; + } + else if (gn == PGFX_TGUY) { // Staff + plr[pnum]._pAFrames = 16; + plr[pnum]._pAFNum = 11; + } + } + else if (pc == CLASS_SORCEROR) { + plr[pnum]._pSWidth = 128; + + if (gn == PGFX_NGUY) { // No weapon + plr[pnum]._pAFrames = 20; + } + else if (gn == PGFX_SGUY) { // Shield only + plr[pnum]._pAFNum = 9; + } + else if (gn == PGFX_BGUY) { // Bow + plr[pnum]._pAFrames = 20; + plr[pnum]._pAFNum = 16; + } + else if (gn == PGFX_FGUY) { // Axe + plr[pnum]._pAFrames = 24; + plr[pnum]._pAFNum = 16; + } + } + + else if (pc == CLASS_MONK) + { + plr[pnum]._pNWidth = 112; + plr[pnum]._pWWidth = 112; + plr[pnum]._pAWidth = 130; + plr[pnum]._pHWidth = 98; + plr[pnum]._pSWidth = 114; + plr[pnum]._pDWidth = 160; + plr[pnum]._pBWidth = 98; + + switch(gn) + { + case PGFX_NGUY: + case PGFX_SGUY: // may want to slow this down + plr[pnum]._pAFrames = 12; + plr[pnum]._pAFNum = 7; + break; + case PGFX_BGUY: + plr[pnum]._pAFrames = 20; + plr[pnum]._pAFNum = 14; + break; + case PGFX_FGUY: + plr[pnum]._pAFrames = 23; + plr[pnum]._pAFNum = 14; + break; + case PGFX_TGUY: + plr[pnum]._pAFrames = 13; + plr[pnum]._pAFNum = 8; + break; + default: + break; + } + } + + // + // + // Fix this when the art arrives. + // + // + else if (pc == CLASS_BARD) + { + if (gn == PGFX_FGUY) { // Axe + plr[pnum]._pAFrames = 22; + plr[pnum]._pAFNum = 13; + } + else if (gn == PGFX_BGUY) { // Bow + plr[pnum]._pAFrames = 12; + plr[pnum]._pAFNum = 11; + } + else if (gn == PGFX_TGUY) { // Staff + plr[pnum]._pAFrames = 16; + plr[pnum]._pAFNum = 11; + } + else if (gn == PGFX_GUY) { // Sword and shield + plr[pnum]._pAFNum = 10; + } + else if (gn == PGFX_XGUY) { // Sword + plr[pnum]._pAFNum = 10; + } + } + else if (pc == CLASS_BARBARIAN) + { + if (gn == PGFX_FGUY) { // Axe + plr[pnum]._pAFrames = 20; + plr[pnum]._pAFNum = 8; + } + else if (gn == PGFX_BGUY) { // Bow + if (leveltype != 0) plr[pnum]._pNFrames = 8; + plr[pnum]._pAWidth = 96; + plr[pnum]._pAFNum = 11; + } + else if (gn == PGFX_TGUY) { // Staff + plr[pnum]._pAFrames = 16; + plr[pnum]._pAFNum = 11; + } + else if (gn == PGFX_ZGUY) { // Mace + plr[pnum]._pAFNum = 8; + } + else if (gn == PGFX_CGUY) { // Mace with Shield + plr[pnum]._pAFNum = 8; + } + } +#endif +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void PlrInitReserved(PlayerStruct * p) { + app_assert(p != NULL); +// REMEMBER -- every time you remove a variable from this +// list to rename it, it MUST be initialized in CreatePlayer() +// or you will screw up the character with unitialized data!!!! +// ALSO -- you MUST initialize the variable in UnPackPlayer() +// in packplr.cpp!!! + p->bReserved5 = 0; + p->bReserved6 = 0; + p->bReserved7 = 0; + p->bReserved8 = 0; + + p->wReserved2 = 0; + p->wReserved3 = 0; + p->wReserved4 = 0; + p->wReserved5 = 0; + p->wReserved6 = 0; + p->wReserved7 = 0; + p->wReserved8 = 0; + + p->dwReserved4 = 0; + p->dwReserved5 = 0; + p->dwReserved6 = 0; + p->dwReserved7 = 0; + p->dwReserved8 = 0; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CreatePlayer(int pnum, char c) { + + // This isn't good C++ but it beats the lack of initialization currently done. + memset(&plr[pnum], 0, sizeof(PlayerStruct)); + PlrInitReserved(&plr[pnum]); + + int i; + char vc; + +// dig.patch1.start.2/4/97 + // time() returns -1 if clock is set far ahead, e.g., the year 2097. + // Many customers have broken clock, resulting in all games being the same. + +// SetRndSeed((int) time(NULL)); + SetRndSeed((int) GetTickCount()); +// dig.patch1.end.2/4/97 + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("CreatePlayer: illegal player %d",pnum); + plr[pnum]._pClass = c; + + vc = StrengthTbl[c]; + if (vc < 0) vc = 0; + plr[pnum]._pStrength = vc; + plr[pnum]._pBaseStr = vc; + vc = MagicTbl[c]; + if (vc < 0) vc = 0; + plr[pnum]._pMagic = vc; + plr[pnum]._pBaseMag = vc; + vc = DexterityTbl[c]; + if (vc < 0) vc = 0; + plr[pnum]._pDexterity = vc; + plr[pnum]._pBaseDex = vc; + vc = VitalityTbl[c]; + if (vc < 0) vc = 0; + plr[pnum]._pVitality = vc; + plr[pnum]._pBaseVit = vc; + + plr[pnum]._pStatPts = 0; + + plr[pnum].pTownWarps = 0; + plr[pnum].pDungMsgs = 0; + plr[pnum].pHellfireMsgs = 0; + plr[pnum].pLvlLoad = 0; + plr[pnum].pDiabloKillLevel = 0; + plr[pnum]._gnDifficulty = D_NORMAL; + + + if (plr[pnum]._pClass == CLASS_MONK) + plr[pnum]._pDamageMod = ((plr[pnum]._pStrength + plr[pnum]._pDexterity) * plr[pnum]._pLevel) / 150; + else if (plr[pnum]._pClass == CLASS_ROGUE || + plr[pnum]._pClass == CLASS_BARD) + plr[pnum]._pDamageMod = ((plr[pnum]._pStrength + plr[pnum]._pDexterity) * plr[pnum]._pLevel) / 200; + else // Warrior and Barbarian + plr[pnum]._pDamageMod = (plr[pnum]._pStrength * plr[pnum]._pLevel) / 100; + plr[pnum]._pBaseToBlk = ToBlkTbl[c]; + + plr[pnum]._pHitPoints = (plr[pnum]._pVitality + 10) << HP_SHIFT; + if (plr[pnum]._pClass == CLASS_WARRIOR + || plr[pnum]._pClass == CLASS_BARBARIAN ) plr[pnum]._pHitPoints = plr[pnum]._pHitPoints << 1; + else if (plr[pnum]._pClass == CLASS_ROGUE || + plr[pnum]._pClass == CLASS_MONK || + plr[pnum]._pClass == CLASS_BARD) plr[pnum]._pHitPoints += (plr[pnum]._pHitPoints >> 1); + plr[pnum]._pMaxHP = plr[pnum]._pHitPoints; + plr[pnum]._pHPBase = plr[pnum]._pHitPoints; + plr[pnum]._pMaxHPBase = plr[pnum]._pHitPoints; + + plr[pnum]._pMana = plr[pnum]._pMagic << MANA_SHIFT; + if (plr[pnum]._pClass == CLASS_SORCEROR) plr[pnum]._pMana = plr[pnum]._pMana << 1; // 2x + else if( plr[pnum]._pClass == CLASS_BARD) plr[pnum]._pMana += (plr[pnum]._pMana * 3)/4; // 1.75 + else if (plr[pnum]._pClass == CLASS_ROGUE || + plr[pnum]._pClass == CLASS_MONK ) plr[pnum]._pMana += (plr[pnum]._pMana >> 1); // 1.5x + plr[pnum]._pMaxMana = plr[pnum]._pMana; + plr[pnum]._pManaBase = plr[pnum]._pMana; + plr[pnum]._pMaxManaBase = plr[pnum]._pMana; + + plr[pnum]._pLevel = 1; + plr[pnum]._pMaxLvl = plr[pnum]._pLevel; + + plr[pnum]._pExperience = 0; + plr[pnum]._pMaxExp = plr[pnum]._pExperience; + plr[pnum]._pNextExper = ExpLvlsTbl[1]; + + plr[pnum]._pArmorClass = 0; + + if (plr[pnum]._pClass == CLASS_BARBARIAN) { + plr[pnum]._pMagResist = 1; + plr[pnum]._pFireResist = 1; + plr[pnum]._pLghtResist = 1; + } + else { + plr[pnum]._pMagResist = 0; + plr[pnum]._pFireResist = 0; + plr[pnum]._pLghtResist = 0; + } + + plr[pnum]._pLightRad = PLRLRAD; + + plr[pnum]._pInfraFlag = FALSE; + + if (c == CLASS_WARRIOR) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_REPAIR-1); + #if !IS_VERSION(SHAREWARE) + else if (c == CLASS_ROGUE) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_DISARM-1); + else if (c == CLASS_SORCEROR) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_RECHARGE-1); + else if (c == CLASS_MONK) plr[pnum]._pAblSpells = (__int64)(1) << (SPL_SHOWMAGITEMS-1); + else if (c == CLASS_BARD) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_IDENTIFY-1); + else if (c == CLASS_BARBARIAN) plr[pnum]._pAblSpells = (_int64)(1) << (SPL_RAGE-1); + #endif + + if (c == CLASS_SORCEROR) plr[pnum]._pMemSpells = (_int64)(1) << (SPL_FIREBOLT-1); + else plr[pnum]._pMemSpells = 0; + + for (i = 0; i < 64; i++) + plr[pnum]._pSplLvl[i] = 0; + plr[pnum]._pSpellFlags = 0; + if (plr[pnum]._pClass == CLASS_SORCEROR) + plr[pnum]._pSplLvl[SPL_FIREBOLT] = 2; + + for (i = 0; i < 3; i++) plr[pnum]._pSplHotKey[i] = -1; + + if (c == CLASS_WARRIOR) plr[pnum]._pgfxnum = PGFX_GUY; + #if !IS_VERSION(SHAREWARE) + else if (c == CLASS_ROGUE) plr[pnum]._pgfxnum = PGFX_BGUY; + else if (c == CLASS_SORCEROR) plr[pnum]._pgfxnum = PGFX_TGUY; + else if (c == CLASS_MONK) plr[pnum]._pgfxnum = PGFX_TGUY; + else if (c == CLASS_BARD) plr[pnum]._pgfxnum = PGFX_GUY; + else if (c == CLASS_BARBARIAN) plr[pnum]._pgfxnum = PGFX_GUY; + #endif + + for (i = 0; i < NUMLEVELS; i++) + plr[pnum]._pLvlVisited[i] = FALSE; + for (i = 0; i < NUMSLEVELS; i++) + plr[pnum]._pSLvlVisited[i] = FALSE; + + plr[pnum]._pLvlChanging = FALSE; + plr[pnum].pTownWarps = 0; + plr[pnum].pLvlLoad = 0; + plr[pnum]._pIFlags2 = 0; + + plr[pnum]._pReflectCount = 0; + + InitDungMsgs(pnum); + + CreatePlrItems(pnum); + + SetRndSeed(0); +} + +// drb.patch1.start.2/05/97 +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int CalcStatDiff(int pnum) +{ + int c = plr[pnum]._pClass; + int d = MaxStats[c][0] - plr[pnum]._pBaseStr; + d += MaxStats[c][1] - plr[pnum]._pBaseMag; + d += MaxStats[c][2] - plr[pnum]._pBaseDex; + d += MaxStats[c][3] - plr[pnum]._pBaseVit; + return(d); +} +// drb.patch1.end.2/05/97 + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void NextPlrLevel(int pnum) { + long l; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("NextPlrLevel: illegal player %d",pnum); + plr[pnum]._pLevel++; + plr[pnum]._pMaxLvl++; + CalcPlrInv(pnum,TRUE); // added by donald 8/26 + + // drb.patch1.start.2/05/97 + // plr[pnum]._pStatPts += 5; + if (CalcStatDiff(pnum) < 5) plr[pnum]._pStatPts = CalcStatDiff(pnum); + else plr[pnum]._pStatPts += 5; + // drb.patch1.end.2/05/97 + + plr[pnum]._pNextExper = ExpLvlsTbl[plr[pnum]._pLevel]; + + if (plr[pnum]._pClass == CLASS_SORCEROR) + { + l = 1 << HP_SHIFT; + } + else + { + l = 2 << HP_SHIFT; + } + + if (gbMaxPlayers == 1) l++; + plr[pnum]._pMaxHP += l; + plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pMaxHPBase += l; + plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + if (pnum == myplr) drawhpflag = TRUE; + + if (plr[pnum]._pClass == CLASS_WARRIOR) + { + l = 1 << MANA_SHIFT; + } + else if ( plr[pnum]._pClass == CLASS_BARBARIAN) + { + l = 0; + } + else + { + l = 2 << MANA_SHIFT; + } + if (gbMaxPlayers == 1) l++; + plr[pnum]._pMaxMana += l; + plr[pnum]._pMaxManaBase += l; + + if (!(plr[pnum]._pIFlags & IAF_LMANA )) { + plr[pnum]._pMana = plr[pnum]._pMaxMana; + plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; + } + if (pnum == myplr + && plr[pnum]._pMana > 0) drawmanaflag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddPlrExperience(int pnum, int lvl, long exp) +{ + if (pnum != myplr) return; + if ((DWORD)myplr >= MAX_PLRS) + app_fatal("AddPlrExperience: illegal player %d",myplr); + if (plr[myplr]._pHitPoints <= 0) return; + + double v = (1 + (((double)lvl - (double)plr[pnum]._pLevel) * 0.1)) * (double)exp; + long e = long(v); + if (e < 0) e = 0; + + // put limits on how fast you go up levels + if (gbMaxPlayers > 1) { + long lLevel = max(0,plr[pnum]._pLevel); + lLevel = min(lLevel,MAX_EXPLVLS); + long lMax = ExpLvlsTbl[lLevel] / 20; + e = min(e,lMax); + lMax = lLevel * 200; + e = min(e,lMax); + } + + // upgrade player + plr[pnum]._pExperience += e; + if ((DWORD) plr[pnum]._pExperience > 2000000000) + plr[pnum]._pExperience = 2000000000; + if (plr[pnum]._pExperience >= ExpLvlsTbl[MAX_EXPLVLS-1]) { + plr[pnum]._pLevel = MAX_EXPLVLS; + } + else { + for (int l = 0; plr[pnum]._pExperience >= ExpLvlsTbl[l]; l++); + if (l != plr[pnum]._pLevel) { + l -= plr[pnum]._pLevel; + for (int i = 0; i < l; i++) + NextPlrLevel(pnum); + } + NetSendCmdParam1(FALSE, CMD_PLRLEVEL, plr[myplr]._pLevel); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddPlrMonstExper(int lvl, long exp, char pmask) +{ + int totplrs = 0; + for (int i = 0; i < MAX_PLRS; i++) + if (pmask & (1 << i)) totplrs++; + + if (totplrs) { + long myexp = exp / totplrs; + if (pmask & (1 << myplr)) AddPlrExperience(myplr, lvl, myexp); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitPlayer(int pnum, BOOL FirstTime) +{ + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("InitPlayer: illegal player %d",pnum); + PlrInitReserved(&plr[pnum]); + + if (FirstTime) { + /*if (plr[pnum]._pClass == CLASS_WARRIOR) { + plr[pnum]._pRSpell = SPL_REPAIR; + plr[pnum]._pRSplType = SPT_ABILITY; + } + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) { + plr[pnum]._pRSpell = SPL_DISARM; + plr[pnum]._pRSplType = SPT_ABILITY; + } + else if (plr[pnum]._pClass == CLASS_SORCEROR) { + plr[pnum]._pRSpell = SPL_FIREBOLT; + plr[pnum]._pRSplType = SPT_MEMORIZED; + } + else if (plr[pnum]._pClass == CLASS_MONK) { + plr[pnum]._pRSpell = SPL_SHOWMAGITEMS; + plr[pnum]._pRSplType = SPT_ABILITY; + } + else if (plr[pnum]._pClass == CLASS_BARD) { + plr[pnum]._pRSpell = SPL_IDENTIFY; + plr[pnum]._pRSplType = SPT_ABILITY; + } + else if (plr[pnum]._pClass == CLASS_BARBARIAN) { + plr[pnum]._pRSpell = SPL_RAGE; + plr[pnum]._pRSplType = SPT_ABILITY; + } + #endif + */ + + plr[pnum]._pRSplType = SPT_NONE; + plr[pnum]._pRSpell = -1; + + plr[pnum]._pSBkSpell = -1; + plr[pnum]._pSpell = plr[pnum]._pRSpell; + plr[pnum]._pSplType = plr[pnum]._pRSplType; + + if ((plr[pnum]._pgfxnum & PGFX_MASK) == PGFX_BGUY) + plr[pnum]._pwtype = WEAP_RANGE; + else + plr[pnum]._pwtype = WEAP_H2H; + } + + if ((plr[pnum].plrlevel == currlevel) || (leveldebug)) { + SetPlrAnims(pnum); + plr[pnum]._pxoff = 0; + plr[pnum]._pyoff = 0; + plr[pnum]._pxvel = 0; + plr[pnum]._pyvel = 0; + ClearPlrPVars(pnum); + + if ((plr[pnum]._pHitPoints >> HP_SHIFT) > 0) { + plr[pnum]._pmode = PM_STAND; + NewPlrAnim(pnum, plr[pnum]._pNAnim[DIR_D], plr[pnum]._pNFrames, 3, plr[pnum]._pNWidth); + plr[pnum]._pAnimFrame = random(2, plr[pnum]._pNFrames - 1) + 1; + plr[pnum]._pAnimCnt = random(2, 3); + } else { + plr[pnum]._pmode = PM_DEATH; + NewPlrAnim(pnum, plr[pnum]._pDAnim[DIR_D], plr[pnum]._pDFrames, 1, plr[pnum]._pDWidth); + plr[pnum]._pAnimFrame = plr[pnum]._pAnimLen - 1; + plr[pnum]._pVar8 = plr[pnum]._pAnimLen << 1; + } + + plr[pnum]._pdir = DIR_D; + plr[pnum]._peflag = 0; + + if (pnum == myplr) { + // put me in my optimal space + if ((!FirstTime) || (currlevel != 0)) { + plr[pnum]._px = ViewX; + plr[pnum]._py = ViewY; + } + plr[pnum]._ptargx = plr[pnum]._px; + plr[pnum]._ptargy = plr[pnum]._py; + } + else { + // Make other players target position where he is now + plr[pnum]._ptargx = plr[pnum]._px; + plr[pnum]._ptargy = plr[pnum]._py; + + // Find space for player + for (int i = 0; i < sizeof(plrxoff2)/sizeof(plrxoff2[0]) - 1; i++) { + if (PosOkPlayer( + pnum, + plr[pnum]._px + plrxoff2[i], + plr[pnum]._py + plryoff2[i] + )) break; + } + plr[pnum]._px += plrxoff2[i]; + plr[pnum]._py += plryoff2[i]; + } + + plr[pnum]._pfutx = plr[pnum]._px; + plr[pnum]._pfuty = plr[pnum]._py; + plr[pnum].walkpath[0] = PCMD_NOTHING; // No buffered walking etc + plr[pnum].destAction = PCMD_NOTHING; + + if (pnum == myplr) + plr[pnum]._plid = AddLight(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pLightRad); + else + plr[pnum]._plid = -1; + plr[pnum]._pvid = AddVision(plr[pnum]._px, plr[pnum]._py, + plr[pnum]._pLightRad, pnum==myplr); + } + + if (plr[pnum]._pClass == CLASS_WARRIOR) + plr[pnum]._pAblSpells = (_int64)(1) << (SPL_REPAIR-1); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) + plr[pnum]._pAblSpells = (_int64)(1) << (SPL_DISARM-1); + else if (plr[pnum]._pClass == CLASS_SORCEROR) + plr[pnum]._pAblSpells = (_int64)(1) << (SPL_RECHARGE-1); + else if (plr[pnum]._pClass == CLASS_MONK) + plr[pnum]._pAblSpells = (__int64)(1) << (SPL_SHOWMAGITEMS-1); + else if (plr[pnum]._pClass == CLASS_BARD) + plr[pnum]._pAblSpells = (_int64)(1) << (SPL_IDENTIFY-1); + else if (plr[pnum]._pClass == CLASS_BARBARIAN) + plr[pnum]._pAblSpells = (_int64)(1) << (SPL_RAGE-1); + #endif + +#if CHEATS + if (simplecheat && FirstTime) { + plr[pnum]._pMemSpells |= (_int64)(1) << SPL_TELE; + if (! plr[myplr]._pSplLvl[SPL_TELE]) + plr[myplr]._pSplLvl[SPL_TELE] = 1; + } + if (cheatflag && FirstTime) { + //splhold = plr[pnum]._pMemSpells; + plr[pnum]._pMemSpells = 0x0fffffffffffffff; + //plr[pnum]._pMemSpells = 0x0000000000000000 | (((__int64)1) << (SPL_NOVA-1)); + //plr[pnum]._pMemSpells = plr[pnum]._pMemSpells | (((__int64)1) << (SPL_TELE-1)); + } +#endif + + plr[pnum]._pNextExper = ExpLvlsTbl[plr[pnum]._pLevel]; + plr[pnum]._pInvincible = FALSE; + + if (pnum == myplr) { + deathdelay = 0; + deathflag = FALSE; + ScrollInfo._sxoff = 0; + ScrollInfo._syoff = 0; + ScrollInfo._sdir = SCRL_NONE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitMultiView() +{ + if ((DWORD)myplr >= MAX_PLRS) + app_fatal("InitPlayer: illegal player %d",myplr); + ViewX = plr[myplr]._px; + ViewY = plr[myplr]._py; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckEFlag(int pnum, int flag2) +{ + int tx,ty,tv; + int t; + WORD *mt; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("InitPlayer: illegal player %d",pnum); + tx = plr[pnum]._px - 1; + ty = plr[pnum]._py + 1; + tv = 0; + mt = &dMT2[CalcRot(tx,ty)].mt[0]; + for(t = 2; t < 10; t++) + tv |= mt[t]; + tv |= dSpecial[tx][ty]; + tv |= nSolidTable[dPiece[tx][ty]]; + if (tv != 0) plr[pnum]._peflag = 1; + else plr[pnum]._peflag = 0; + + if ((flag2 == E_DOUBLE) && (plr[pnum]._peflag == 1)) { + tx = plr[pnum]._px; + ty = plr[pnum]._py + 2; + tv = 0; + mt = &dMT2[CalcRot(tx,ty)].mt[0]; + for(t = 2; t < 10; t++) + tv |= mt[t]; + tv |= dSpecial[tx][ty]; + if (tv == 0) { + tx = plr[pnum]._px - 2; + ty = plr[pnum]._py + 1; + tv = 0; + mt = &dMT2[CalcRot(tx,ty)].mt[0]; + for(t = 2; t < 10; t++) + tv |= mt[t]; + tv |= dSpecial[tx][ty]; + if (tv != 0) plr[pnum]._peflag = 2; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int PlrGetDir(int pnum, int i) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PlrGetDir: illegal player %d",pnum); + return GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mx, monster[i]._my); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PlrGetDirXY(int pnum, int xx, int yy) +{ + int d; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PlrGetDirXY: illegal player %d",pnum); + d = GetDirection(plr[pnum]._px, plr[pnum]._py, xx, yy); + if ((plr[pnum]._px == xx) && (plr[pnum]._py == yy)) d = plr[pnum]._pdir; + return (d); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL SolidLoc(int x, int y) { + return nSolidTable[dPiece[x][y]]; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL PlrDirOK(int i, int pdir) { + if ((DWORD)i >= MAX_PLRS) + app_fatal("PlrDirOK: illegal player %d",i); + long fx = plr[i]._px + offset_x[pdir]; + long fy = plr[i]._py + offset_y[pdir]; + if (fx < 0) return FALSE; // SKing fix Dave 4/3 + if (dPiece[fx][fy] == 0) return FALSE; + if (! PosOkPlayer(i, fx, fy)) return FALSE; + + BOOL ret = TRUE; + if(ret && pdir == DIR_R) ret = !SolidLoc(fx, fy+1) && !(dFlags[fx][fy+1] & BFLAG_PLRLR); + if(ret && pdir == DIR_L) ret = !SolidLoc(fx+1, fy) && !(dFlags[fx+1][fy] & BFLAG_PLRLR); +// if(ret && pdir == DIR_U) ret = !SolidLoc(fx+1, fy) && !SolidLoc(fx, fy+1); +// if(ret && pdir == DIR_D) ret = !SolidLoc(fx-1, fy) && !SolidLoc(fx, fy-1); + return ret; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PlrClrTrans(int x, int y) +{ + int i,j; + char v; + + for (j = y-1; j <= y+1; j++) { + for (i = x-1; i <= x+1; i++) { + v = dTransVal[i][j]; + TransList[v] = FALSE; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PlrDoTrans(int x, int y) +{ + int i,j; + char v; + + if ((leveltype == 1) || (leveltype == 2)) { + for (j = y-1; j <= y+1; j++) { + for (i = x-1; i <= x+1; i++) { + if (!nSolidTable[dPiece[i][j]]) { + v = dTransVal[i][j]; + if (v != 0) TransList[v] = TRUE; + } + } + } + } else TransList[1] = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPlayerOld(int pnum) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("SetPlayerOld: illegal player %d",pnum); + plr[pnum]._poldx = plr[pnum]._px; + plr[pnum]._poldy = plr[pnum]._py; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FixPlayerLocation(int pnum,int bDir) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("FixPlayerLocation: illegal player %d",pnum); + plr[pnum]._pfutx = plr[pnum]._px; + plr[pnum]._pfuty = plr[pnum]._py; + + plr[pnum]._ptargx = plr[pnum]._px; + plr[pnum]._ptargy = plr[pnum]._py; + + plr[pnum]._pxoff = 0; + plr[pnum]._pyoff = 0; + CheckEFlag(pnum, E_SINGLE); + plr[pnum]._pdir = bDir; + + if (pnum == myplr) { + ScrollInfo._sxoff = 0; + ScrollInfo._syoff = 0; + ScrollInfo._sdir = SCRL_NONE; + ViewX = plr[pnum]._px; + ViewY = plr[pnum]._py; + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void StartStand(int pnum, int dir) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartStand: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + if ((plr[pnum]._pGFXLoad & PGL_STAND) == 0) LoadPlrGFX(pnum, PGL_STAND); + NewPlrAnim(pnum, plr[pnum]._pNAnim[dir], plr[pnum]._pNFrames, 3, plr[pnum]._pNWidth); + plr[pnum]._pmode = PM_STAND; + FixPlayerLocation(pnum,dir); + FixPlrWalkTags(pnum); + dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum; + SetPlayerOld(pnum); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void StartWalkStand(int pnum) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartWalkStand: illegal player %d",pnum); + plr[pnum]._pmode = PM_STAND; + plr[pnum]._pfutx = plr[pnum]._px; + plr[pnum]._pfuty = plr[pnum]._py; + plr[pnum]._pxoff = 0; + plr[pnum]._pyoff = 0; + CheckEFlag(pnum, E_SINGLE); + if (pnum == myplr) { + ScrollInfo._sxoff = 0; + ScrollInfo._syoff = 0; + ScrollInfo._sdir = SCRL_NONE; + ViewX = plr[pnum]._px; + ViewY = plr[pnum]._py; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PM_ChangeLightOff(int pnum) +{ + int lx,ly; + int signx,signy; + static BYTE fix[] = {0,0,3,3,3,6,6,6,8}; + int totx, toty; + int oldtotx, oldtoty; + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_ChangeLightOff: illegal player %d",pnum); + LightListStruct * light = &LightList[plr[pnum]._plid]; + + // Convert from screen pixel offsets to dungeon coordinates + // i.e., 45 degree rotation + lx = (plr[pnum]._pxoff + (plr[pnum]._pyoff << 1)); + ly = ((plr[pnum]._pyoff << 1) - plr[pnum]._pxoff); + + // Divide these values by 8, because lighting offsets have + // 8 subdivisions per tile. + if (lx < 0) + { + signx = -1; + lx = -lx; + } + else + signx = 1; + + if (ly < 0) + { + signy = -1; + ly = -ly; + } + else + signy = 1; + + lx = lx >> 3; + ly = ly >> 3; + + // Then, fix the offset, because + // the player lighting looks bad with full lighting resolution. +// lx = fix[lx]; +// ly = fix[ly]; + + lx *= signx; + ly *= signy; + + totx = (light->_lx << 3) + lx; + toty = (light->_ly << 3) + ly; + + oldtotx = (light->_lx << 3) + light->_xoff; + oldtoty = (light->_ly << 3) + light->_yoff; + + if(abs(totx-oldtotx) >= 3 || abs(toty-oldtoty) >= 3) + ChangeLightOff(plr[pnum]._plid, lx, ly); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PM_ChangeOffset(int pnum) +{ + long xo, yo; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_ChangeOffset: illegal player %d",pnum); + plr[pnum]._pVar8++; + + xo = plr[pnum]._pVar6 >> 8; + yo = plr[pnum]._pVar7 >> 8; +#if 0 + plr[pnum]._pVar6 += plr[pnum]._pxvel; + plr[pnum]._pVar7 += plr[pnum]._pyvel; +#endif + + plr[pnum]._pVar6 += plr[pnum]._pxvel; + plr[pnum]._pVar7 += plr[pnum]._pyvel; + + if (currlevel == 0 && gbWalkOn) // double-speed walk + { + plr[pnum]._pVar6 += plr[pnum]._pxvel; + plr[pnum]._pVar7 += plr[pnum]._pyvel; + } + + plr[pnum]._pxoff = plr[pnum]._pVar6 >> 8; + plr[pnum]._pyoff = plr[pnum]._pVar7 >> 8; + xo -= (plr[pnum]._pVar6 >> 8); + yo -= (plr[pnum]._pVar7 >> 8); + if ((pnum == myplr) && (ScrollInfo._sdir != SCRL_NONE)) { + ScrollInfo._sxoff += xo; + ScrollInfo._syoff += yo; + } + PM_ChangeLightOff(pnum); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartWalk(int pnum, int xvel, int yvel, int xadd, int yadd, int EndDir, int scrldir) +{ + long fx,fy; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartWalk: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + SetPlayerOld(pnum); + fx = plr[pnum]._px + xadd; + fy = plr[pnum]._py + yadd; + if (PlrDirOK(pnum, EndDir)) { + //PlrClrTrans(plr[pnum]._px, plr[pnum]._py); + //PlrDoTrans(fx, fy); + plr[pnum]._pfutx = fx; + plr[pnum]._pfuty = fy; + if (pnum == myplr) { + ScrollInfo._sdx = plr[pnum]._px - ViewX; + ScrollInfo._sdy = plr[pnum]._py - ViewY; + } + dPlayer[fx][fy] = -1 - (char)pnum; + plr[pnum]._pmode = PM_WALK; + plr[pnum]._pxvel = xvel; + plr[pnum]._pyvel = yvel; + plr[pnum]._pxoff = 0; + plr[pnum]._pyoff = 0; + plr[pnum]._pVar1 = xadd; + plr[pnum]._pVar2 = yadd; + plr[pnum]._pVar3 = EndDir; + if ((plr[pnum]._pGFXLoad & PGL_WALK) == 0) LoadPlrGFX(pnum, PGL_WALK); + NewPlrAnim(pnum, plr[pnum]._pWAnim[EndDir], plr[pnum]._pWFrames, 0, plr[pnum]._pWWidth); + plr[pnum]._pdir = EndDir; + plr[pnum]._pVar6 = 0; + plr[pnum]._pVar7 = 0; + plr[pnum]._pVar8 = 0; + CheckEFlag(pnum, E_SINGLE); + if (pnum == myplr) { + if (svgamode) { + if ((abs(ScrollInfo._sdx) < 3) && (abs(ScrollInfo._sdy) < 3)) ScrollInfo._sdir = scrldir; + else ScrollInfo._sdir = SCRL_NONE; + } else { + if ((abs(ScrollInfo._sdx) < 2) && (abs(ScrollInfo._sdy) < 2)) ScrollInfo._sdir = scrldir; + else ScrollInfo._sdir = SCRL_NONE; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartWalk2(int pnum, int xvel, int yvel, int xoff, int yoff, + int xadd, int yadd, int EndDir, int scrldir) +{ + long fx,fy; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartWalk2: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + SetPlayerOld(pnum); + fx = plr[pnum]._px + xadd; + fy = plr[pnum]._py + yadd; + if (PlrDirOK(pnum, EndDir)) { + //PlrClrTrans(plr[pnum]._px, plr[pnum]._py); + //PlrDoTrans(fx, fy); + plr[pnum]._pfutx = fx; + plr[pnum]._pfuty = fy; + if (pnum == myplr) { + ScrollInfo._sdx = plr[pnum]._px - ViewX; + ScrollInfo._sdy = plr[pnum]._py - ViewY; + } + dPlayer[plr[pnum]._px][plr[pnum]._py] = -1 - (char)pnum; + plr[pnum]._pVar1 = plr[pnum]._px; + plr[pnum]._pVar2 = plr[pnum]._py; + plr[pnum]._px = fx; + plr[pnum]._py = fy; + dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum; + plr[pnum]._pxoff = xoff; + plr[pnum]._pyoff = yoff; + ChangeLightXY(plr[pnum]._plid, plr[pnum]._px, plr[pnum]._py); + PM_ChangeLightOff(pnum); + plr[pnum]._pmode = PM_WALK2; + plr[pnum]._pxvel = xvel; + plr[pnum]._pyvel = yvel; + plr[pnum]._pVar6 = xoff << 8; + plr[pnum]._pVar7 = yoff << 8; + plr[pnum]._pVar3 = EndDir; + if ((plr[pnum]._pGFXLoad & PGL_WALK) == 0) LoadPlrGFX(pnum, PGL_WALK); + NewPlrAnim(pnum, plr[pnum]._pWAnim[EndDir], plr[pnum]._pWFrames, 0, plr[pnum]._pWWidth); + plr[pnum]._pdir = EndDir; + plr[pnum]._pVar8 = 0; + if (EndDir == DIR_DR) CheckEFlag(pnum, E_DOUBLE); + else CheckEFlag(pnum, E_SINGLE); + if (pnum == myplr) { + if (svgamode) { + if ((abs(ScrollInfo._sdx) < 3) && (abs(ScrollInfo._sdy) < 3)) ScrollInfo._sdir = scrldir; + else ScrollInfo._sdir = SCRL_NONE; + } else { + if ((abs(ScrollInfo._sdx) < 2) && (abs(ScrollInfo._sdy) < 2)) ScrollInfo._sdir = scrldir; + else ScrollInfo._sdir = SCRL_NONE; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartWalk3(int pnum, int xvel, int yvel, int xoff, int yoff, + int xadd, int yadd, int txa, int tya, int EndDir, int scrldir) +{ + long fx,fy; + long tx,ty; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartWalk3: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + SetPlayerOld(pnum); + fx = plr[pnum]._px + xadd; + fy = plr[pnum]._py + yadd; + tx = plr[pnum]._px + txa; // Temp location for drawing + ty = plr[pnum]._py + tya; + if (PlrDirOK(pnum, EndDir)) { + //PlrClrTrans(plr[pnum]._px, plr[pnum]._py); + //PlrDoTrans(fx, fy); + plr[pnum]._pfutx = fx; + plr[pnum]._pfuty = fy; + if (pnum == myplr) { + ScrollInfo._sdx = plr[pnum]._px - ViewX; + ScrollInfo._sdy = plr[pnum]._py - ViewY; + } + dPlayer[plr[pnum]._px][plr[pnum]._py] = -1 - (char)pnum; + dPlayer[fx][fy] = -1 - (char)pnum; + plr[pnum]._pVar4 = tx; + plr[pnum]._pVar5 = ty; + dFlags[tx][ty] |= BFLAG_PLRLR; + plr[pnum]._pxoff = xoff; + plr[pnum]._pyoff = yoff; + if(leveltype) + { + ChangeLightXY(plr[pnum]._plid, tx, ty); + PM_ChangeLightOff(pnum); + } + plr[pnum]._pmode = PM_WALK3; + plr[pnum]._pxvel = xvel; + plr[pnum]._pyvel = yvel; + plr[pnum]._pVar1 = fx; + plr[pnum]._pVar2 = fy; + plr[pnum]._pVar6 = xoff << 8; + plr[pnum]._pVar7 = yoff << 8; + plr[pnum]._pVar3 = EndDir; + if ((plr[pnum]._pGFXLoad & PGL_WALK) == 0) LoadPlrGFX(pnum, PGL_WALK); + NewPlrAnim(pnum, plr[pnum]._pWAnim[EndDir], plr[pnum]._pWFrames, 0, plr[pnum]._pWWidth); + plr[pnum]._pdir = EndDir; + plr[pnum]._pVar8 = 0; + CheckEFlag(pnum, E_SINGLE); + if (pnum == myplr) { + if (svgamode) { + if ((abs(ScrollInfo._sdx) < 3) && (abs(ScrollInfo._sdy) < 3)) ScrollInfo._sdir = scrldir; + else ScrollInfo._sdir = SCRL_NONE; + } else { + if ((abs(ScrollInfo._sdx) < 2) && (abs(ScrollInfo._sdy) < 2)) ScrollInfo._sdir = scrldir; + else ScrollInfo._sdir = SCRL_NONE; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartAttack(int pnum, int d) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartAttack: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + if ((plr[pnum]._pGFXLoad & PGL_ATTACK) == 0) LoadPlrGFX(pnum, PGL_ATTACK); + NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth); + + plr[pnum]._pmode = PM_ATTACK; + FixPlayerLocation(pnum,d); + SetPlayerOld(pnum); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartRangeAttack(int pnum, int d, int dx, int dy) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartRangeAttack: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + if ((plr[pnum]._pGFXLoad & PGL_ATTACK) == 0) LoadPlrGFX(pnum, PGL_ATTACK); + NewPlrAnim(pnum, plr[pnum]._pAAnim[d], plr[pnum]._pAFrames, 0, plr[pnum]._pAWidth); + + plr[pnum]._pmode = PM_RATTACK; + FixPlayerLocation(pnum,d); + SetPlayerOld(pnum); + plr[pnum]._pVar1 = dx; + plr[pnum]._pVar2 = dy; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartPlrBlock(int pnum, int dir) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartPlrBlock: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + PlaySfxLoc(IS_ISWORD, plr[pnum]._px, plr[pnum]._py); + + if ((plr[pnum]._pGFXLoad & PGL_BLOCK) == 0) LoadPlrGFX(pnum, PGL_BLOCK); + NewPlrAnim(pnum, plr[pnum]._pBAnim[dir], plr[pnum]._pBFrames, 2, plr[pnum]._pBWidth); + plr[pnum]._pmode = PM_BLOCK; + FixPlayerLocation(pnum,dir); + SetPlayerOld(pnum); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartSpell(int pnum, int d, int cx, int cy) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartSpell: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + if (leveltype != 0) { + switch (spelldata[plr[pnum]._pSpell].sType) { + case ST_FIRE : + if ((plr[pnum]._pGFXLoad & PGL_FMAG) == 0) LoadPlrGFX(pnum, PGL_FMAG); + NewPlrAnim(pnum, plr[pnum]._pFAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth); + break; + case ST_LIGHT : + if ((plr[pnum]._pGFXLoad & PGL_LMAG) == 0) LoadPlrGFX(pnum, PGL_LMAG); + NewPlrAnim(pnum, plr[pnum]._pLAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth); + break; + case ST_MISC : + if ((plr[pnum]._pGFXLoad & PGL_TMAG) == 0) LoadPlrGFX(pnum, PGL_TMAG); + NewPlrAnim(pnum, plr[pnum]._pTAnim[d], plr[pnum]._pSFrames, 0, plr[pnum]._pSWidth); + break; + } + } + PlaySfxLoc(spelldata[plr[pnum]._pSpell].sSFX, plr[pnum]._px, plr[pnum]._py); + + plr[pnum]._pmode = PM_SPELL; + FixPlayerLocation(pnum,d); + SetPlayerOld(pnum); + + plr[pnum]._pVar1 = cx; + plr[pnum]._pVar2 = cy; + //if (((plr[pnum]._pSplFrom == SPL_FROMBK) || (plr[pnum]._pSplFrom == SPL_FROMR)) && (pnum == myplr)) + plr[pnum]._pVar4 = GetSpellLevel(pnum, plr[pnum]._pSpell); + //else + // plr[pnum]._pVar4 = 1; + plr[pnum]._pVar8 = 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FixPlrWalkTags(int pnum) { + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("FixPlrWalkTags: illegal player %d",pnum); + + int pp = pnum + 1; + int pn = -1 - pnum; + int px = plr[pnum]._poldx; + int py = plr[pnum]._poldy; + for (int y = py - 1; y <= py + 1; y++) { + for (int x = px - 1; x <= px + 1; x++) { + if (x < 0 || x >= DMAXX) continue; + if (y < 0 || y >= DMAXY) continue; + if (dPlayer[x][y] == pp || dPlayer[x][y] == pn) + dPlayer[x][y] = 0; + } + } + + if (px < 0 || px >= DMAXX-1) return; + if (py < 0 || py >= DMAXY-1) return; + dFlags[px+1][py+0] &= BFMASK_PLRLR; + dFlags[px+0][py+1] &= BFMASK_PLRLR; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RemovePlrFromMap(int pnum) +{ + int pp = pnum + 1; + int pn = -1 - pnum; + int x,y; + for (y = 1; y < DMAXY; y++) { + for (x = 1; x < DMAXX; x++) { + if (((dPlayer[x][y-1] == pn) || (dPlayer[x-1][y] == pn)) && (dFlags[x][y] & BFLAG_PLRLR)) + dFlags[x][y] &= BFMASK_PLRLR; + } + } + for (y = 0; y < DMAXY; y++) { + for (x = 0; x < DMAXX; x++) { + if (dPlayer[x][y] == pp || dPlayer[x][y] == pn) + dPlayer[x][y] = 0; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartPlrHit(int pnum, int dam, BOOL forcehit) +{ + int pd; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartPlrHit: illegal player %d",pnum); + if ((plr[pnum]._pInvincible) && (plr[pnum]._pHitPoints == 0) && (pnum == myplr)) { + StartPlrKill(pnum, KILL_UNKNOWN); + return; + } + + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_WARR69, plr[pnum]._px, plr[pnum]._py); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD69, plr[pnum]._px, plr[pnum]._py); + else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySfxLoc(PS_BARBARIAN69, plr[pnum]._px, plr[pnum]._py); + #endif + //PlaySfxLoc(PS_LGHIT, plr[pnum]._px, plr[pnum]._py); + + // Update hit bar + drawhpflag = TRUE; + + if (plr[pnum]._pClass == CLASS_BARBARIAN) + { + if ((dam >> HP_SHIFT) < (plr[pnum]._pLevel + (plr[pnum]._pLevel/4)) + && !forcehit) + { + return; + } + } + else if ((dam >> HP_SHIFT) < plr[pnum]._pLevel + && !forcehit) + return; + + pd = plr[pnum]._pdir; + if ((plr[pnum]._pGFXLoad & PGL_HIT) == 0) LoadPlrGFX(pnum, PGL_HIT); + NewPlrAnim(pnum, plr[pnum]._pHAnim[pd], plr[pnum]._pHFrames, 0, plr[pnum]._pHWidth); + plr[pnum]._pmode = PM_GOTHIT; + FixPlayerLocation(pnum,pd); + plr[pnum]._pVar8 = 1; + FixPlrWalkTags(pnum); + dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum; + SetPlayerOld(pnum); +} +// JMM.PATCH1.2/24/97 +void ShowDupString( LPCSTR lpszMessage ); +// END.PATCH1 +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RespawnDeadItem(ItemStruct *itm, int x, int y) +{ + int ii; + + if (numitems < MAXITEMS) { + // JMM.PATCH1.2/24/97 + if(FindGetItem(itm->IDidx, itm->_iCreateInfo, itm->_iSeed) >= 0) { + DROPLOG(" Duplicate item detected!\n"); + // JMM.PATCH1.2.22.97 + // NetSendString(1 << myplr, "A duplicate item has been detected. Unable to drop."); + ShowDupString("A duplicate item has been detected. Destroying duplicate..."); + SyncGetItem(x,y,itm->IDidx,itm->_iCreateInfo,itm->_iSeed); + // END.JMM.PATCH1.2.22.97 + } + // ENDPATCH1.2/24/97 + + ii = itemavail[0]; + dItem[x][y] = ii+1; + itemavail[0] = itemavail[MAXITEMS - numitems - 1]; + itemactive[numitems] = ii; + + item[ii] = *itm; + item[ii]._ix = x; + item[ii]._iy = y; + + RespawnItem(ii, TRUE); + numitems++; + + itm->_itype = -1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void PlrDeadItem(int pnum, ItemStruct *itm, int xx, int yy) { + + // no item to drop? + if (itm->_itype == -1) return; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PlrDeadItem: illegal player %d",pnum); + + // try optimal position first + int x = plr[pnum]._px + xx; + int y = plr[pnum]._py + yy; + + if ((xx != 0) || (yy != 0)) { + // Start placing + if (ItemSpaceOk(x, y)) { + RespawnDeadItem(itm, x, y); + plr[pnum].HoldItem = *itm; + NetSendCmdPItem(FALSE,CMD_RESPAWNITEM,x,y); + return; + } + } + + for (int l = 1; l < 50; l++) { + for (int j = -l; j <= l; j++) { + y = plr[pnum]._py + j; + for (int i = -l; i <= l; i++) { + x = plr[pnum]._px + i; + if (! ItemSpaceOk(x,y)) continue; + + // drop it + RespawnDeadItem(itm, x, y); + plr[pnum].HoldItem = *itm; + NetSendCmdPItem(FALSE,CMD_RESPAWNITEM,x,y); + return; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartPlayerKill(int pnum, BOOL earflag) +{ + ItemStruct * pi; + PlayerStruct * p = &plr[pnum]; + ItemStruct ear; + int i; + + // already dead? + if ((plr[pnum]._pHitPoints <= 0) && (plr[pnum]._pmode == PM_DEATH)) return; + + // if it's me, let everyone know + if (myplr == pnum) NetSendCmdParam1(TRUE,CMD_PLRDEAD,earflag); + + // dead players don't lose body items on diablo level + BOOL diablolevel = (gbMaxPlayers > 1) && (plr[pnum].plrlevel == 16); + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartPlayerKill: illegal player %d",pnum); + + if (plr[pnum]._pClass == CLASS_WARRIOR) PlaySfxLoc(PS_DEAD, p->_px, p->_py); + #if !IS_VERSION(SHAREWARE) + else if (plr[pnum]._pClass == CLASS_ROGUE) PlaySfxLoc(PS_ROGUE71, p->_px, p->_py); + else if (plr[pnum]._pClass == CLASS_SORCEROR) PlaySfxLoc(PS_MAGE71, p->_px, p->_py); + else if (plr[pnum]._pClass == CLASS_MONK) PlaySfxLoc(PS_MONK71, p->_px, p->_py); + else if (plr[pnum]._pClass == CLASS_BARD) PlaySfxLoc(PS_BARD71, p->_px, p->_py); + else if (plr[pnum]._pClass == CLASS_BARBARIAN) PlaySfxLoc(PS_BARBARIAN71, p->_px, p->_py); + #endif + + // Give the plr no items in hands gfx + if (p->_pgfxnum != PGFX_NGUY) { + p->_pgfxnum = PGFX_NGUY; + p->_pGFXLoad = 0; + SetPlrAnims(pnum); + } + + if ((p->_pGFXLoad & PGL_DEAD) == 0) LoadPlrGFX(pnum, PGL_DEAD); + NewPlrAnim(pnum, p->_pDAnim[p->_pdir], p->_pDFrames, 1, p->_pDWidth); + p->_pmode = PM_DEATH; + p->_pBlockFlag = FALSE; + p->_pInvincible = TRUE; + SetPlayerHitPoints(pnum, 0); + p->_pVar8 = 1; + if ((pnum != myplr) && (earflag == FALSE) && !diablolevel) { + pi = &p->InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) pi->_itype = -1; + CalcPlrInv(pnum, FALSE); + } + + if (plr[pnum].plrlevel != currlevel) return; + + // Clean up map and set up vars for death + FixPlayerLocation(pnum,p->_pdir); + RemovePlrFromMap(pnum); + dFlags[p->_px][p->_py] |= BFLAG_DEADPLR; + SetPlayerOld(pnum); + + // Bail out if this is not me + if (pnum != myplr) return; + + drawhpflag = TRUE; + deathdelay = 30; + + // Drop all item in hand + if (curs >= ICSTART) { + PlrDeadItem(pnum, &p->HoldItem, 0, 0); + NewCursor(GLOVE_CURS); + } + + if (diablolevel) + return; + + // Drop half of players gold + DropHalfPlayersGold(pnum); + + // Drop player ear if killed by player + if (earflag == KILL_UNKNOWN) return; + + if (earflag) { + SetPlrHandItem(&ear, IDI_EAR); + sprintf(ear._iName, "Ear of %s", plr[pnum]._pName); + if (plr[pnum]._pClass == CLASS_SORCEROR) ear._iCurs = ITEM_EAR1; + else if (plr[pnum]._pClass == CLASS_WARRIOR) ear._iCurs = ITEM_EAR2; + else if (plr[pnum]._pClass == CLASS_ROGUE) ear._iCurs = ITEM_EAR3; + // Fix this if necessary. + else if (plr[pnum]._pClass == CLASS_MONK) ear._iCurs = ITEM_EAR3; + else if (plr[pnum]._pClass == CLASS_BARD) ear._iCurs = ITEM_EAR3; + else if (plr[pnum]._pClass == CLASS_BARBARIAN) ear._iCurs = ITEM_EAR3; + + ear._iCreateInfo = (plr[pnum]._pName[0] << 8) | plr[pnum]._pName[1]; + ear._iSeed = (plr[pnum]._pName[2] << 24) | + (plr[pnum]._pName[3] << 16) | + (plr[pnum]._pName[4] << 8) | + plr[pnum]._pName[5]; + ear._ivalue = plr[pnum]._pLevel; + // my ear already on ground? + int ii = FindGetItem(IDI_EAR, ear._iCreateInfo, ear._iSeed); + if (ii == -1) PlrDeadItem(pnum, &ear, 0, 0); + } else { + // Drop body items if killed by monster + pi = &p->InvBody[0]; + for (i = NUM_INVLOC; i--; pi++) { + int pdd = (p->_pdir + i) & 0x07; + PlrDeadItem(pnum, pi, offset_x[pdd], offset_y[pdd]); + } + CalcPlrInv(pnum, FALSE); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DropHalfPlayersGold(int pnum) +{ + int i; + long hGold; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("DropHalfPlayersGold: illegal player %d",pnum); + + // Get half of players gold + hGold = plr[pnum]._pGold >> 1; + + // Remove gold from speed list first; if there is any + // Try non GOLD_VMAX first, then break into the GOLD_VMAX piles + for (i = 0; ((i < MAXSPD) && (hGold > 0)); i++) { + if ((plr[pnum].SpdList[i]._itype == IT_GOLD) && + (plr[pnum].SpdList[i]._ivalue != GOLD_VMAX)) { + if (hGold < plr[pnum].SpdList[i]._ivalue) { + // update gold items value + plr[pnum].SpdList[i]._ivalue -= hGold; + // update gold items cursor + SetSpdbarGoldCurs(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to hGold + plr[pnum].HoldItem._ivalue = hGold; + // drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + // initialize so we can exit the loop + hGold = 0; + } else { + // decrement hGold by SpdList items value + hGold -= plr[pnum].SpdList[i]._ivalue; + // remove gold item from SpdList + RemoveSpdBarItem(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to SpdList items value + plr[pnum].HoldItem._ivalue = plr[pnum].SpdList[i]._ivalue; + // drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + // restart looping + i = -1; + } + } + } + if (hGold > 0) { + // SpdList GOLD_VMAX piles + for (i = 0; ((i < MAXSPD) && (hGold > 0)); i++) { + if (plr[pnum].SpdList[i]._itype == IT_GOLD) { + if (hGold < plr[pnum].SpdList[i]._ivalue) { + // update gold items value + plr[pnum].SpdList[i]._ivalue -= hGold; + // update gold items cursor + SetSpdbarGoldCurs(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to hGold + plr[pnum].HoldItem._ivalue = hGold; + // drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + // initialize so we can exit the loop + hGold = 0; + } else { + // decrement hGold by SpdList items value + hGold -= plr[pnum].SpdList[i]._ivalue; + // remove gold item from SpdList + RemoveSpdBarItem(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to SpdList items value + plr[pnum].HoldItem._ivalue = plr[pnum].SpdList[i]._ivalue; + // drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + // restart looping + i = -1; + } + } + } + } + force_redraw = FULLDRAW; + + // Remove gold from inventory list if there was no gold in the speed list + // or all gold from the speed list was deplenished. + // Try non GOLD_VMAX first, then break into the GOLD_VMAX piles + if (hGold > 0) { + for (i = 0; ((i < plr[pnum]._pNumInv) && (hGold > 0)); i++) { + if ((plr[pnum].InvList[i]._itype == IT_GOLD) && + (plr[pnum].InvList[i]._ivalue != GOLD_VMAX)) { + if (hGold < plr[pnum].InvList[i]._ivalue) { + // update gold items value + plr[pnum].InvList[i]._ivalue -= hGold; + // update gold items cursor + SetGoldCurs(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to hGold + plr[pnum].HoldItem._ivalue = hGold; + // drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + hGold = 0; + } else { + // decrement hGold by InvList items value + hGold -= plr[pnum].InvList[i]._ivalue; + // remove gold item from InvList + RemoveInvItem(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to InvList items value + plr[pnum].HoldItem._ivalue = plr[pnum].InvList[i]._ivalue; + // drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + // restart looping + i = -1; + } + } + } + if (hGold > 0) { + // InvList GOLD_VMAX piles + for (i = 0; ((i < plr[pnum]._pNumInv) && (hGold > 0)); i++) { + if (plr[pnum].InvList[i]._itype == IT_GOLD) { + if (hGold < plr[pnum].InvList[i]._ivalue) { + // update gold items value + plr[pnum].InvList[i]._ivalue -= hGold; + // update gold items cursor + SetGoldCurs(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to hGold + plr[pnum].HoldItem._ivalue = hGold; + // drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + hGold = 0; + } else { + // decrement hGold by InvList items value + hGold -= plr[pnum].InvList[i]._ivalue; + // remove gold item from InvList + RemoveInvItem(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to InvList items value + plr[pnum].HoldItem._ivalue = plr[pnum].InvList[i]._ivalue; + // drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + // restart looping + i = -1; + } + } + } + } + } + // update players gold to account for losing half + plr[pnum]._pGold = CalculateGold(pnum); +} + + +void StripTopGold(int pnum) +{ + int i; + long hGold; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StripTopGold: illegal player %d",pnum); + + ItemStruct tmpHold = plr[pnum].HoldItem; + + // Remove gold from inventory list if there was no gold in the speed list + // or all gold from the speed list was deplenished. + // Try non GOLD_VMAX first, then break into the GOLD_VMAX piles + for (i = 0; i < plr[pnum]._pNumInv; i++) + { + if ((plr[pnum].InvList[i]._itype == IT_GOLD) && + (plr[pnum].InvList[i]._ivalue > GOLD_VMAX)) + { + + // first, remove the gold from the slot + hGold = plr[pnum].InvList[i]._ivalue - GOLD_VMAX; + plr[pnum].InvList[i]._ivalue = GOLD_VMAX; + + // update gold items cursor + SetGoldCurs(pnum, i); + // initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + SetPlrHandGoldCurs(&plr[pnum].HoldItem); + // set hold items value equal to hGold + plr[pnum].HoldItem._ivalue = hGold; + + hGold = 0; + // if it'll fit elsewhere, continue + if (!GoldAutoPlace(pnum)) // else drop the hold item + PlrDeadItem(pnum, &plr[pnum].HoldItem, 0, 0); + } + } + // update players gold + plr[pnum]._pGold = CalculateGold(pnum); + plr[pnum].HoldItem = tmpHold; +} +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartPlrKill(int pnum, BOOL earflag) +{ + int i, mx; + + // PATCH1.JMM + // no death on first level + if ((0 >= plr[pnum]._pHitPoints) && (0 == currlevel)) { + SetPlayerHitPoints(pnum,1<mdeadval, monster[myplr]._mdir); + dMonster[monster[myplr]._mx][monster[myplr]._my] = 0; + monster[myplr]._mDelFlag = TRUE; + DeleteMonsterList(); + } + + void DeleteMissile(int, int); + for (i = 0; i < nummissiles; i++) { + mx = missileactive[i]; + if ((missile[mx]._mitype == MIT_STONE) && (missile[mx]._misource == pnum)) + monster[(missile[mx]._miVar2)]._mmode = missile[mx]._miVar1; + if ((missile[mx]._mitype == MIT_MANASHIELD) && (missile[mx]._misource == pnum)) { + ClearMissileSpot(mx); + DeleteMissile(mx, i); + } + if ((missile[mx]._mitype == MIT_ETHER) && (missile[mx]._misource == pnum)) { + ClearMissileSpot(mx); + DeleteMissile(mx, i); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitLevelChange(int pnum) +{ + RemovePlrMissiles(pnum); + + if ((pnum == myplr) && (qtextflag)) { + qtextflag = FALSE; + stream_stop(); + } + // remove player from current level immediately + RemovePlrFromMap(pnum); + SetPlayerOld(pnum); + if (pnum == myplr) dPlayer[plr[myplr]._px][plr[myplr]._py] = 1 + myplr; + else plr[pnum]._pLvlVisited[plr[pnum].plrlevel] = TRUE; + + ClrPlrPath(pnum); + plr[pnum].destAction = PCMD_NOTHING; + plr[pnum]._pLvlChanging = TRUE; + if (pnum == myplr) plr[pnum].pLvlLoad = LVLCHANGE_TIME; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void StartNewLvl(int pnum, int fom, int lvl) +{ + InitLevelChange(pnum); + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("StartNewLvl: illegal player %d",pnum); + switch (fom) { + case WM_DIABNEXTLVL: + case WM_DIABPREVLVL: + case WM_DIABTOWNWARP: + //app_assert(plr[pnum].plrlevel != lvl); + plr[pnum].plrlevel = lvl; + break; + + case WM_DIABTWARPUP: + plr[myplr].pTownWarps |= 1 << (leveltype - 2); + plr[pnum].plrlevel = lvl; + break; + + case WM_DIABRETOWN: + // everything already set + break; + + case WM_DIABRTNLVL: + // can't do any validation on this + // one since it stuffs into global vars + app_assert(gbMaxPlayers == 1); + plr[pnum].plrlevel = lvl; + break; + + case WM_DIABSETLVL: + setlvlnum = lvl; + app_assert(gbMaxPlayers == 1); + break; + + default: + app_fatal("StartNewLvl"); + break; + } + + if (pnum == myplr) { + plr[pnum]._pmode = PM_NEWLVL; + plr[pnum]._pInvincible = TRUE; + PostMessage(ghMainWnd,fom,0,0); + if (gbMaxPlayers > 1) NetSendCmdParam2(TRUE,CMD_NEWLVL,fom,lvl); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void RestartTownLvl(int pnum) +{ + InitLevelChange(pnum); + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("RestartTownLvl: illegal player %d",pnum); + + //app_assert(plr[pnum].plrlevel != 0); + plr[pnum].plrlevel = 0; + + plr[pnum]._pInvincible = FALSE; + SetPlayerHitPoints(pnum, 1 << HP_SHIFT); + plr[pnum]._pMana = 0; + plr[pnum]._pManaBase = plr[pnum]._pMana - (plr[pnum]._pMaxMana - plr[pnum]._pMaxManaBase); + CalcPlrInv(pnum, FALSE); + + if (pnum == myplr) { + plr[pnum]._pmode = PM_NEWLVL; + plr[pnum]._pInvincible = TRUE; + PostMessage(ghMainWnd,WM_DIABRETOWN,0,0); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartWarpLvl(int pnum, int pidx) +{ + InitLevelChange(pnum); + + if (gbMaxPlayers != 1) { + if (plr[pnum].plrlevel != 0) plr[pnum].plrlevel = 0; + else plr[pnum].plrlevel = portal[pidx].level; + } + + if (pnum == myplr) { + SetCurrentPortal(pidx); + plr[pnum]._pmode = PM_NEWLVL; + plr[pnum]._pInvincible = TRUE; + PostMessage(ghMainWnd,WM_DIABWARPLVL,0,0); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoStand(int pnum) +{ + return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +********************************** TEMP ********************************* +**-----------------------------------------------------------------------* + +BOOL rfix1 = FALSE; +BOOL rfix2 = FALSE; + +void TempWalkFix(int pnum) +{ + if (currlevel == 0) return; + if ((plr[pnum]._pClass == CLASS_ROGUE) && (plr[pnum]._pAnimLen == 6)) { + if ((plr[pnum]._pAnimFrame == 2) && !rfix1) { + plr[pnum]._pAnimFrame = 1; + rfix1 = TRUE; + } else rfix1 = FALSE; + if ((plr[pnum]._pAnimFrame == 4) && !rfix2) { + plr[pnum]._pAnimFrame = 3; + rfix2 = TRUE; + } else rfix2 = FALSE; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoWalk(int pnum) +{ + int rv; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoWalk: illegal player %d",pnum); + +#if 0 + // changed _pAnimFrame == 2 to == 3 to prevent "extra" footstep == pat +// if ((plr[pnum]._pAnimFrame == 3) +// || (plr[pnum]._pWFrames == 8 && plr[pnum]._pAnimFrame == 7) +// || (plr[pnum]._pWFrames != 8 && plr[pnum]._pAnimFrame == 4)) +// PlaySfxLoc(PS_WALK1, plr[pnum]._px, plr[pnum]._py); + //TempWalkFix(pnum); +#endif + + if (currlevel == 0 && gbWalkOn) // double-speed walk in town + { + if (plr[pnum]._pAnimFrame%2 == 0) // should be even frames only + { + ++plr[pnum]._pAnimFrame; + ++plr[pnum]._pVar8; + } + if (plr[pnum]._pAnimFrame >= plr[pnum]._pWFrames) + plr[pnum]._pAnimFrame = 0; + } + + int l = 8; + + if (currlevel != 0) l = PlrWalkLenTbl[plr[pnum]._pClass]; + if (plr[pnum]._pVar8 >= l) { + dPlayer[plr[pnum]._px][plr[pnum]._py] = 0; + plr[pnum]._px += plr[pnum]._pVar1; + plr[pnum]._py += plr[pnum]._pVar2; + dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum; + if (leveltype != 0) { + ChangeLightXY(plr[pnum]._plid, plr[pnum]._px, plr[pnum]._py); + ChangeVisionXY(plr[pnum]._pvid, plr[pnum]._px, plr[pnum]._py); + } + if (pnum == myplr) { + if (ScrollInfo._sdir != SCRL_NONE) { + ViewX = plr[pnum]._px - ScrollInfo._sdx; + ViewY = plr[pnum]._py - ScrollInfo._sdy; + } + } + if (plr[pnum].walkpath[0] != PCMD_NOTHING) StartWalkStand(pnum); + else StartStand(pnum, plr[pnum]._pVar3); + ClearPlrPVars(pnum); + if (leveltype != 0) ChangeLightOff(plr[pnum]._plid, 0, 0); + rv = RUN_AGAIN; + } else { + PM_ChangeOffset(pnum); + rv = RUN_DONE; + } + + return (rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoWalk2(int pnum) +{ + int rv; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoWalk2: illegal player %d",pnum); + +#if 0 + // changed _pAnimFrame == 2 to == 3 to prevent "extra" footstep == pat + if ((plr[pnum]._pAnimFrame == 3) + || (plr[pnum]._pWFrames == 8 && plr[pnum]._pAnimFrame == 7) + || (plr[pnum]._pWFrames != 8 && plr[pnum]._pAnimFrame == 4)) + PlaySfxLoc(PS_WALK1, plr[pnum]._px, plr[pnum]._py); + //TempWalkFix(pnum); +#endif + if (currlevel == 0 && gbWalkOn) // double-speed walk in town + { + if (plr[pnum]._pAnimFrame%2 == 0) // should be even frames only + { + ++plr[pnum]._pAnimFrame; + ++plr[pnum]._pVar8; + } + if (plr[pnum]._pAnimFrame >= plr[pnum]._pWFrames) + plr[pnum]._pAnimFrame = 0; + } + + int l = 8; + + if (currlevel != 0) l = PlrWalkLenTbl[plr[pnum]._pClass]; + if (plr[pnum]._pVar8 >= l) { + dPlayer[plr[pnum]._pVar1][plr[pnum]._pVar2] = 0; + if (leveltype != 0) { + ChangeLightXY(plr[pnum]._plid, plr[pnum]._px, plr[pnum]._py); + ChangeVisionXY(plr[pnum]._pvid, plr[pnum]._px, plr[pnum]._py); + } + if (pnum == myplr) { + if (ScrollInfo._sdir != SCRL_NONE) { + ViewX = plr[pnum]._px - ScrollInfo._sdx; + ViewY = plr[pnum]._py - ScrollInfo._sdy; + } + } + if (plr[pnum].walkpath[0] != PCMD_NOTHING) StartWalkStand(pnum); + else StartStand(pnum, plr[pnum]._pVar3); + ClearPlrPVars(pnum); + if (leveltype != 0) ChangeLightOff(plr[pnum]._plid, 0, 0); + rv = RUN_AGAIN; + } else { + PM_ChangeOffset(pnum); + rv = RUN_DONE; + } + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoWalk3(int pnum) +{ + int rv; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoWalk3: illegal player %d",pnum); + +#if 0 + // changed _pAnimFrame == 2 to == 3 to prevent "extra" footstep == pat + if ((plr[pnum]._pAnimFrame == 3) + || (plr[pnum]._pWFrames == 8 && plr[pnum]._pAnimFrame == 7) + || (plr[pnum]._pWFrames != 8 && plr[pnum]._pAnimFrame == 4)) + PlaySfxLoc(PS_WALK1, plr[pnum]._px, plr[pnum]._py); + //TempWalkFix(pnum); +#endif + + if (currlevel == 0 && gbWalkOn) // double-speed walk in town + { + if (plr[pnum]._pAnimFrame%2 == 0) // should be even frames only + { + ++plr[pnum]._pAnimFrame; + ++plr[pnum]._pVar8; + } + if (plr[pnum]._pAnimFrame >= plr[pnum]._pWFrames) + plr[pnum]._pAnimFrame = 0; + } + + + int l = 8; + + if (currlevel != 0) l = PlrWalkLenTbl[plr[pnum]._pClass]; + if (plr[pnum]._pVar8 >= l) { + dPlayer[plr[pnum]._px][plr[pnum]._py] = 0; + dFlags[plr[pnum]._pVar4][plr[pnum]._pVar5] &= BFMASK_PLRLR; + plr[pnum]._px = plr[pnum]._pVar1; + plr[pnum]._py = plr[pnum]._pVar2; + dPlayer[plr[pnum]._px][plr[pnum]._py] = 1 + (char)pnum; + if (leveltype != 0) { + ChangeLightXY(plr[pnum]._plid, plr[pnum]._px, plr[pnum]._py); + ChangeVisionXY(plr[pnum]._pvid, plr[pnum]._px, plr[pnum]._py); + } + if (pnum == myplr) { + if (ScrollInfo._sdir != SCRL_NONE) { + ViewX = plr[pnum]._px - ScrollInfo._sdx; + ViewY = plr[pnum]._py - ScrollInfo._sdy; + } + } + if (plr[pnum].walkpath[0] != PCMD_NOTHING) StartWalkStand(pnum); + else StartStand(pnum, plr[pnum]._pVar3); + ClearPlrPVars(pnum); + if (leveltype != 0) ChangeLightOff(plr[pnum]._plid, 0, 0); + rv = RUN_AGAIN; + } else { + PM_ChangeOffset(pnum); + rv = RUN_DONE; + } + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL WeaponDur(int pnum, int durrnd) +{ + if (pnum != myplr) + return FALSE; + + if ((plr[pnum].Hand1Item._itype != -1) && (plr[pnum].Hand1Item._iClass == IC_WEAP)) { + if (plr[pnum].Hand1Item._iFlags2 & IAF2_DECAY) { + plr[pnum].Hand1Item._iPLDam -= 5; + if (plr[pnum].Hand1Item._iPLDam <= -100) { + NetSendCmdDelItem(TRUE, INVLOC_HAND1); + plr[pnum].Hand1Item._itype = -1; + CalcPlrInv(pnum,TRUE); + return(TRUE); + } + CalcPlrInv(pnum,TRUE); + } + } + if ((plr[pnum].Hand2Item._itype != -1) && (plr[pnum].Hand2Item._iClass == IC_WEAP)) { + if (plr[pnum].Hand2Item._iFlags2 & IAF2_DECAY) { + plr[pnum].Hand2Item._iPLDam -= 5; + if (plr[pnum].Hand2Item._iPLDam <= -100) { + NetSendCmdDelItem(TRUE, INVLOC_HAND1); + plr[pnum].Hand2Item._itype = -1; + CalcPlrInv(pnum,TRUE); + return(TRUE); + } + CalcPlrInv(pnum,TRUE); + } + } + + // Item used, so change durability + if (random(3, durrnd)) + return FALSE; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("WeaponDur: illegal player %d",pnum); + + if ((plr[pnum].Hand1Item._itype != -1) && (plr[pnum].Hand1Item._iClass == IC_WEAP)) { + if (plr[pnum].Hand1Item._iDurability == INFINITE_DUR) return(FALSE); + plr[pnum].Hand1Item._iDurability--; + if (plr[pnum].Hand1Item._iDurability <= 0) { + NetSendCmdDelItem(TRUE, INVLOC_HAND1); + plr[pnum].Hand1Item._itype = -1; + CalcPlrInv(pnum,TRUE); + return(TRUE); + } + } + if ((plr[pnum].Hand2Item._itype != -1) && (plr[pnum].Hand2Item._iClass == IC_WEAP)) { + if (plr[pnum].Hand2Item._iDurability == INFINITE_DUR) return(FALSE); + plr[pnum].Hand2Item._iDurability--; + if (plr[pnum].Hand2Item._iDurability == 0) { + NetSendCmdDelItem(TRUE, INVLOC_HAND2); + plr[pnum].Hand2Item._itype = -1; + CalcPlrInv(pnum,TRUE); + return(TRUE); + } + } + // Shield only guy + if ((plr[pnum].Hand1Item._itype == -1) && (plr[pnum].Hand2Item._itype == IT_SHIELD)) { + if (plr[pnum].Hand2Item._iDurability == INFINITE_DUR) return(FALSE); + plr[pnum].Hand2Item._iDurability--; + if (plr[pnum].Hand2Item._iDurability == 0) { + NetSendCmdDelItem(TRUE, INVLOC_HAND2); + plr[pnum].Hand2Item._itype = -1; + CalcPlrInv(pnum,TRUE); + return(TRUE); + } + } + if ((plr[pnum].Hand2Item._itype == -1) && (plr[pnum].Hand1Item._itype == IT_SHIELD)) { + if (plr[pnum].Hand1Item._iDurability == INFINITE_DUR) return(FALSE); + plr[pnum].Hand1Item._iDurability--; + if (plr[pnum].Hand1Item._iDurability == 0) { + NetSendCmdDelItem(TRUE, INVLOC_HAND1); + plr[pnum].Hand1Item._itype = -1; + CalcPlrInv(pnum,TRUE); + return(TRUE); + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PlrHitMonst(int pnum, int m) +{ + int hit, hper = 0, mind, maxd; + long dam, skdam; + int phanditype; + int tmac; + BOOL rv; + BOOL ret = FALSE; + BOOL quarterdamage = FALSE; + + if ((DWORD)m >= MAXMONSTERS) + app_fatal("PlrHitMonst: illegal monster %d",m); + + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) return(FALSE); + + if(monster[m].MType->mtype == MT_ILLWEAV && monster[m]._mgoal == MG_RUN_AWAY) + return FALSE; + + if (monster[m]._mmode == MM_MISSILE) return(FALSE); + + if (pnum < 0) + { + quarterdamage = TRUE; + pnum = -pnum; + if (plr[pnum]._pLevel > 20) + hper -= 30; + else + hper -= 2 * (35 - plr[pnum]._pLevel); + } + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PlrHitMonst: illegal player %d",pnum); + + rv = FALSE; + // Did I hit? + hit = random(4, 100); + if (monster[m]._mmode == MM_STONE) hit = 0; + tmac = monster[m].mArmorClass; + if (plr[pnum]._pIEnAc > 0) // like Damage Reduction in Hero --DKT + { + int i = plr[pnum]._pIEnAc - 1; + if (i > 0) + tmac >>= i; // halved (n-1) times + else + tmac -= tmac >> 2; // three quarters + + if (plr[pnum]._pClass == CLASS_BARBARIAN) + { + tmac -= (monster[m].mArmorClass)/8; // Barbarians have a slight advantage using these weapons. + } + + // limit it to a zero. + if (tmac < 0) + { + tmac = 0; + } + } + + // note: modified this to += so quarterdamage shots are at minus to hit + // by giving negative initial value to hper. + hper += BASE_TO_HIT + plr[pnum]._pLevel - tmac + (plr[pnum]._pDexterity >> 1); + if (plr[pnum]._pClass == CLASS_WARRIOR) + hper += 20; + hper += plr[pnum]._pIBonusToHit; + if (hper < 5) hper = 5; + if (hper > 95) hper = 95; + if (CheckMonsterHit(m, ret)) // ret passed by &reference!! + return(ret); +#if CHEATS + else if((hit < hper) || cheatflag || simplecheat) { +#else + else if (hit < hper) { +#endif + if ((plr[pnum]._pIFlags & IAF_FIREHIT && + plr[pnum]._pIFlags & IAF_LIGHTHIT)) + { + int dmg = plr[pnum]._pIFMinDam + random(3, (plr[pnum]._pIFMaxDam - plr[pnum]._pIFMinDam)); + AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pVar1, plr[pnum]._pVar2, plr[pnum]._pdir, MIT_SPECARROW, MI_ENEMYMONST, pnum, dmg, 0); + } + mind = plr[pnum]._pIMinDam; + maxd = plr[pnum]._pIMaxDam; + dam = random(5, maxd - mind + 1) + mind; + dam += (dam * plr[pnum]._pIBonusDam) / 100; + dam += plr[pnum]._pIBonusDamMod; + + int perildam = dam << HP_SHIFT; + + dam += plr[pnum]._pDamageMod; + if (plr[pnum]._pClass == CLASS_WARRIOR + || plr[pnum]._pClass == CLASS_BARBARIAN) { + //ddp = (plr[pnum]._pDexterity + plr[pnum]._pLevel) >> 3; + int ddp = plr[pnum]._pLevel; + int doubledam = random(6, 100); + if (doubledam < ddp) dam = dam << 1; + } + phanditype = -1; + if ((plr[pnum].Hand1Item._itype == IT_SWORD) || (plr[pnum].Hand2Item._itype == IT_SWORD)) phanditype = IT_SWORD; + if ((plr[pnum].Hand1Item._itype == IT_MACE) || (plr[pnum].Hand2Item._itype == IT_MACE)) phanditype = IT_MACE; + switch (monster[m].MData->mMonstClass) { + case MC_UNDEAD: + if (phanditype == IT_SWORD) dam -= (dam >> 1); + else if (phanditype == IT_MACE) dam += (dam >> 1); + break; + case MC_ANIMAL: + if (phanditype == IT_MACE) dam -= (dam >> 1); + else if (phanditype == IT_SWORD) dam += (dam >> 1); + break; + } + if ((plr[pnum]._pIFlags & IAF_DAMDEMON) && (monster[m].MData->mMonstClass == MC_DEMON)) dam += (dam << 1); + + if (plr[pnum]._pIFlags2 & IAF2_DEVASTATION) + { + int tdp = 5; + int tripledamage = random(6, 100); + if (tripledamage < tdp) dam += dam << 1; + } + + if (plr[pnum]._pIFlags2 & IAF2_CLONE) // doppelganger + { + if (monster[m].MType->mtype != MT_DIABLO) + { + if ((monster[m]._uniqtype == 0) && (random(6, 100) < 10)) + CloneMonster(m); + } + } + + dam = dam << HP_SHIFT; + + // after shift, to increase resolution + if (plr[pnum]._pIFlags2 & IAF2_JESTER) + { + int dammult = random(6, 201); + if (dammult >= 100) + dammult = 100 + (dammult-100) * 5; + dam = (dam * dammult) / 100; + } + + if (quarterdamage) + dam >>= 2; + + + // can only be damaged by me + if (pnum == myplr) { + if (plr[pnum]._pIFlags2 & IAF2_PERIL) + { + perildam += plr[pnum]._pIGetHit << HP_SHIFT; + if (perildam < 0) + { + // do nothing + } + else if (plr[pnum]._pHitPoints > perildam) + { + plr[pnum]._pHitPoints -= perildam; + plr[pnum]._pHPBase -= perildam; + } + else + { + plr[pnum]._pHPBase -= plr[pnum]._pHitPoints - (1 << HP_SHIFT); + plr[pnum]._pHitPoints = 1 << HP_SHIFT; + } + dam <<= 1; + } + monster[m]._mhitpoints -= dam; + } + if (plr[pnum]._pIFlags & IAF_SKING) { + skdam = random(7, dam >> 3); + plr[pnum]._pHitPoints += skdam; + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase += skdam; + if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + drawhpflag = TRUE; + } + if ((plr[pnum]._pIFlags & IAF_ALLBAT) && (!(plr[pnum]._pIFlags & IAF_LMANA))) { + if (plr[pnum]._pIFlags & IAF_BAT10) skdam = (dam * 3) / 100; + if (plr[pnum]._pIFlags & IAF_BAT20) skdam = (dam * 5) / 100; + plr[pnum]._pMana += skdam; + if (plr[pnum]._pMana > plr[pnum]._pMaxMana) plr[pnum]._pMana = plr[pnum]._pMaxMana; + plr[pnum]._pManaBase += skdam; + if (plr[pnum]._pManaBase > plr[pnum]._pMaxManaBase) plr[pnum]._pManaBase = plr[pnum]._pMaxManaBase; + drawmanaflag = TRUE; + } + if (plr[pnum]._pIFlags & IAF_ALLLEECH) { + if (plr[pnum]._pIFlags & IAF_LEECH10) skdam = (dam * 3) / 100; + if (plr[pnum]._pIFlags & IAF_LEECH20) skdam = (dam * 5) / 100; + plr[pnum]._pHitPoints += skdam; + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase += skdam; + if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + drawhpflag = TRUE; + } + if (plr[pnum]._pIFlags & IAF_NOHEAL) monster[m]._mFlags |= MFLAG_NOHEAL; +#if CHEATS + if (simplecheat || cheatflag) monster[m]._mhitpoints = 0; +// if (cheatflag) monster[m]._mhitpoints = 1 << HP_SHIFT; +#endif + //rjs - was doing double dam if stone - if (pnum == myplr && monster[m]._mmode == MM_STONE) monster[m]._mhitpoints -= dam; + if ((monster[m]._mhitpoints >> HP_SHIFT) <= 0) { + if (monster[m]._mmode == MM_STONE) { + M_StartKill(m, pnum); + monster[m]._mmode = MM_STONE; + } else M_StartKill(m, pnum); + } else { + if (monster[m]._mmode == MM_STONE) { + M_StartHit(m, pnum, dam); + monster[m]._mmode = MM_STONE; + } else { + if (plr[pnum]._pIFlags & IAF_KNOCKBACK) M_GetKnockback(m); + M_StartHit(m, pnum, dam); + } + } + rv = TRUE; + } + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PlrHitPlr(int pnum, char p) +{ + int hit, hper, mind, maxd; + int doubledam, ddp; + long dam, skdam; + int tac; + int blk, blkper, blkdir; + BOOL rv; + + if ((DWORD)p >= MAX_PLRS) + app_fatal("PlrHitPlr: illegal target player %d",p); + + rv = FALSE; + if (plr[p]._pInvincible) return(rv); + if ((plr[p]._pSpellFlags & SF_ETHER) != 0) return(rv); + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PlrHitPlr: illegal attacking player %d",pnum); + + // Did I hit? + hit = random(4, 100); + //rjs tac = (byte) plr[p]._pArmorClass + plr[p]._pIAC + plr[p]._pIBonusAC; + tac = plr[p]._pIAC + plr[p]._pIBonusAC; + tac += (plr[p]._pDexterity / 5); + hper = BASE_TO_HIT + plr[pnum]._pLevel - tac + (plr[pnum]._pDexterity >> 1); + if (plr[pnum]._pClass == CLASS_WARRIOR) + hper += 20; + hper += plr[pnum]._pIBonusToHit; + if (hper < 5) hper = 5; + if (hper > 95) hper = 95; + if (((plr[p]._pmode == PM_STAND) || (plr[p]._pmode == PM_ATTACK)) && (plr[p]._pBlockFlag)) blk = random(5, 100); + else blk = 100; + blkper = plr[p]._pBaseToBlk + plr[p]._pDexterity - ((plr[pnum]._pLevel - plr[p]._pLevel) << 1); + if (blkper < 0) blkper = 0; + if (blkper > 100) blkper = 100; + if (hit < hper) { + if (blk < blkper) { + blkdir = GetDirection(plr[p]._px, plr[p]._py, plr[pnum]._px, plr[pnum]._py); + StartPlrBlock(p, blkdir); + } else { + mind = plr[pnum]._pIMinDam; + maxd = plr[pnum]._pIMaxDam; + dam = random(5, maxd - mind + 1) + mind; + dam += (dam * plr[pnum]._pIBonusDam) / 100; + dam += plr[pnum]._pIBonusDamMod + plr[pnum]._pDamageMod; + if (plr[pnum]._pClass == CLASS_WARRIOR + || plr[pnum]._pClass == CLASS_BARBARIAN) { + //ddp = (plr[pnum]._pDexterity + plr[pnum]._pLevel) >> 3; + ddp = plr[pnum]._pLevel; + doubledam = random(6, 100); + if (doubledam < ddp) dam = dam << 1; + } + dam = dam << HP_SHIFT; + if (plr[pnum]._pIFlags & IAF_SKING) { + skdam = random(7, dam >> 3); + plr[pnum]._pHitPoints += skdam; + if (plr[pnum]._pHitPoints > plr[pnum]._pMaxHP) plr[pnum]._pHitPoints = plr[pnum]._pMaxHP; + plr[pnum]._pHPBase += skdam; + if (plr[pnum]._pHPBase > plr[pnum]._pMaxHPBase) plr[pnum]._pHPBase = plr[pnum]._pMaxHPBase; + drawhpflag = TRUE; + } + if (pnum == myplr) NetSendCmdDamage(TRUE, p, dam); + StartPlrHit(p, dam, FALSE); + } + rv = TRUE; + } + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PlrHitObj(int pnum, int mx, int my) +{ + int oi; + + if (dObject[mx][my] > 0) oi = dObject[mx][my] - 1; + else oi = -(dObject[mx][my] + 1); + if (object[oi]._oBreak == OBJ_BREAKABLE) { + BreakObject(pnum, oi); + return(TRUE); + } else return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoAttack(int pnum) +{ + int dx,dy,m; + char p; + BOOL didhit = FALSE; + int frame; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoAttack: illegal player %d",pnum); + + frame = plr[pnum]._pAnimFrame; + + if ((plr[pnum]._pIFlags & IAF_ATANIM1) && (frame == 1)) + plr[pnum]._pAnimFrame++; + + if ((plr[pnum]._pIFlags & IAF_ATANIM2) && (frame == 1 || frame == 3)) + plr[pnum]._pAnimFrame++; + + if ((plr[pnum]._pIFlags & IAF_ATANIM3) && (frame == 1 || frame == 3 || frame == 5)) + plr[pnum]._pAnimFrame++; + + if ((plr[pnum]._pIFlags & IAF_ATANIM4) && (frame == 1 || frame == 4)) + plr[pnum]._pAnimFrame += 2; + + if (plr[pnum]._pAnimFrame == (plr[pnum]._pAFNum-1)) + PlaySfxLoc(PS_SWING, plr[pnum]._px, plr[pnum]._py); + + if (plr[pnum]._pAnimFrame == plr[pnum]._pAFNum) { + dx = plr[pnum]._px + offset_x[plr[pnum]._pdir]; + dy = plr[pnum]._py + offset_y[plr[pnum]._pdir]; + + if (dMonster[dx][dy] != 0) { + if (dMonster[dx][dy] > 0) m = dMonster[dx][dy] - 1; + else m = -(dMonster[dx][dy] + 1); + if (CanTalkToMonst(m)) { + plr[pnum]._pVar1 = 0; + return(RUN_DONE); + } + } + + if ((plr[pnum]._pIFlags & IAF_FIREHIT && + plr[pnum]._pIFlags & IAF_LIGHTHIT)) + { + } + else if (plr[pnum]._pIFlags & IAF_FIREHIT) + AddMissile(dx, dy, 1, 0, 0, MIT_WEAPEXP, MI_ENEMYMONST, pnum, 0, 0); + else if (plr[pnum]._pIFlags & IAF_LIGHTHIT) + AddMissile(dx, dy, 2, 0, 0, MIT_WEAPEXP, MI_ENEMYMONST, pnum, 0, 0); + + if (dMonster[dx][dy] != 0) { + if (dMonster[dx][dy] > 0) + m = dMonster[dx][dy] - 1; + else + m = -(dMonster[dx][dy] + 1); + didhit = PlrHitMonst(pnum, m); + } else { + if ((dPlayer[dx][dy] != 0) && (!FriendlyMode)) { + if (dPlayer[dx][dy] > 0) p = dPlayer[dx][dy] - 1; + else p = -(dPlayer[dx][dy] + 1); + didhit = PlrHitPlr(pnum, p); + } else { + if (dObject[dx][dy] > 0) didhit = PlrHitObj(pnum,dx,dy); + } + } + + if ((plr[pnum]._pClass == CLASS_MONK && + (plr[pnum].Hand1Item._itype == IT_STAFF || + plr[pnum].Hand2Item._itype == IT_STAFF) + ) + || (plr[pnum]._pClass == CLASS_BARD && + (plr[pnum].Hand1Item._itype == IT_SWORD && + plr[pnum].Hand2Item._itype == IT_SWORD) + ) + // Axes, 2handed Maces or 2handed swords with no shield used. + || (plr[pnum]._pClass == CLASS_BARBARIAN && + (plr[pnum].Hand1Item._itype == IT_AXE || + plr[pnum].Hand2Item._itype == IT_AXE || + ((((plr[pnum].Hand1Item._itype == IT_MACE && plr[pnum].Hand1Item._iLoc == IL_2HAND) || + (plr[pnum].Hand2Item._itype == IT_MACE && plr[pnum].Hand2Item._iLoc == IL_2HAND) || + (plr[pnum].Hand1Item._itype == IT_SWORD && plr[pnum].Hand1Item._iLoc == IL_2HAND) || + (plr[pnum].Hand2Item._itype == IT_SWORD && plr[pnum].Hand2Item._iLoc == IL_2HAND) + ) + && !(plr[pnum].Hand1Item._itype == IT_SHIELD || plr[pnum].Hand2Item._itype == IT_SHIELD) + ) + ) + ) + ) + ) + { + // check right-hand opponent, then left + // note that we temporarily redeclare dx, dy, and m here + int dx = plr[pnum]._px + offset_x[(plr[pnum]._pdir+1)%8]; + int dy = plr[pnum]._py + offset_y[(plr[pnum]._pdir+1)%8]; + int m = ((dMonster[dx][dy] > 0) ? + dMonster[dx][dy] : -dMonster[dx][dy]) + - 1; + if (dMonster[dx][dy] != 0 && !CanTalkToMonst(m) && + monster[m]._moldx == dx && monster[m]._moldy == dy) + { + if (PlrHitMonst(-pnum, m)) + didhit = TRUE; + } + dx = plr[pnum]._px + offset_x[(plr[pnum]._pdir+7)%8]; + dy = plr[pnum]._py + offset_y[(plr[pnum]._pdir+7)%8]; + m = ((dMonster[dx][dy] > 0) ? + dMonster[dx][dy] : -dMonster[dx][dy]) + - 1; + if (dMonster[dx][dy] != 0 && !CanTalkToMonst(m) && + monster[m]._moldx == dx && monster[m]._moldy == dy) + { + if (PlrHitMonst(-pnum, m)) + didhit = TRUE; + } + } + if (didhit) { + if (WeaponDur(pnum, 30)) { // 1 in 30 dur hit if plr hit monst/obj + StartStand(pnum, plr[pnum]._pdir); + ClearPlrPVars(pnum); + return(RUN_AGAIN); + } + } + } + if (plr[pnum]._pAnimFrame == plr[pnum]._pAFrames) { + StartStand(pnum, plr[pnum]._pdir); + ClearPlrPVars(pnum); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoRangeAttack(int pnum) +{ + int mistype; + int numshots = 0; + int shottype = 0; + int deltaX = 0, deltaY = 0; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoRangeAttack: illegal player %d",pnum); + + if (plr[pnum]._pAnimFrame == plr[pnum]._pAFNum) + numshots = 1; + + if ((plr[pnum]._pIFlags & IAF_RABID) && + (plr[pnum]._pAnimFrame == plr[pnum]._pAFNum + 2)) + { + numshots = 2; + shottype = 1; // framing shots + } + + for (int shotnum = 0; shotnum < numshots; shotnum++) + { + switch(shottype) + { + case 0: break; + case 1: + { + int fanoffset = (shotnum == 0) ? -1 : 1; + int xoffset = plr[pnum]._pVar1 - plr[pnum]._px; + int yoffset = plr[pnum]._pVar2 - plr[pnum]._py; + if (xoffset < 0) + deltaY = fanoffset; + if (xoffset > 0) + deltaY = -fanoffset; + if (yoffset < 0) + deltaX = -fanoffset; + if (yoffset > 0) + deltaX = fanoffset; + } + break; + default: + break; + } + + mistype = MIT_ARROW; + if (plr[pnum]._pIFlags & IAF_FIREARROW) mistype = MIT_FARROW; + if (plr[pnum]._pIFlags & IAF_LARROW) mistype = MIT_LARROW; + + // both flags means a special arrow, doing (firedamage) damage. + // a bit of a hack. --donald + if ((plr[pnum]._pIFlags & IAF_FIREARROW) && + (plr[pnum]._pIFlags & IAF_LARROW)) + { + int dmg = plr[pnum]._pIFMinDam + random(3, (plr[pnum]._pIFMaxDam - plr[pnum]._pIFMinDam)); + mistype = MIT_SPECARROW; + + AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pVar1 + deltaX, plr[pnum]._pVar2 + deltaY, plr[pnum]._pdir, mistype, MI_ENEMYMONST, pnum, dmg, 0); + } + else + { + AddMissile(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pVar1 + deltaX, plr[pnum]._pVar2 + deltaY, plr[pnum]._pdir, mistype, MI_ENEMYMONST, pnum, 4, 0); + if (shotnum == 0) + { + if (shottype == 0) + PlaySfxLoc(PS_BFIRE, plr[pnum]._px, plr[pnum]._py); + else + PlaySfxLoc(PS_NEW_BFIRE, plr[pnum]._px, plr[pnum]._py); + } + } + + if (WeaponDur(pnum, 40)) { // 1 in 40 bow dur hit + StartStand(pnum, plr[pnum]._pdir); + ClearPlrPVars(pnum); + return(RUN_AGAIN); + } + } + if (plr[pnum]._pAnimFrame >= plr[pnum]._pAFrames) { + StartStand(pnum, plr[pnum]._pdir); + ClearPlrPVars(pnum); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ShieldDur(int pnum) +{ + if (pnum != myplr) return; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("ShieldDur: illegal player %d",pnum); + + // Item used, so change durability + if (plr[pnum].Hand1Item._itype == IT_SHIELD) { + if (plr[pnum].Hand1Item._iDurability == INFINITE_DUR) return; + plr[pnum].Hand1Item._iDurability--; + if (plr[pnum].Hand1Item._iDurability == 0) { + NetSendCmdDelItem(TRUE, INVLOC_HAND1); + plr[pnum].Hand1Item._itype = -1; + CalcPlrInv(pnum,TRUE); + } + } + if (plr[pnum].Hand2Item._itype == IT_SHIELD) { + if (plr[pnum].Hand2Item._iDurability == INFINITE_DUR) return; + plr[pnum].Hand2Item._iDurability--; + if (plr[pnum].Hand2Item._iDurability == 0) { + NetSendCmdDelItem(TRUE, INVLOC_HAND2); + plr[pnum].Hand2Item._itype = -1; + CalcPlrInv(pnum,TRUE); + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoBlock(int pnum) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoBlock: illegal player %d",pnum); + + if ((plr[pnum]._pIFlags & IAF_BLANIM) && (plr[pnum]._pAnimFrame != 1)) { + plr[pnum]._pAnimFrame = plr[pnum]._pBFrames; + } + if (plr[pnum]._pAnimFrame >= plr[pnum]._pBFrames) { + StartStand(pnum, plr[pnum]._pdir); + ClearPlrPVars(pnum); + if (random(3,10) == 0) ShieldDur(pnum); + return(RUN_AGAIN); + } else return(RUN_DONE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoSpell(int pnum) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoSpell: illegal player %d",pnum); + + if (plr[pnum]._pVar8 == plr[pnum]._pSFNum) { + CastSpell(pnum, plr[pnum]._pSpell, plr[pnum]._px, plr[pnum]._py, plr[pnum]._pVar1, plr[pnum]._pVar2, MI_PLR, plr[pnum]._pVar4); + if (plr[pnum]._pSplFrom == SPL_FROMR) { + if (plr[pnum]._pRSplType == SPT_SCROLL) { + if ((plr[pnum]._pScrlSpells & (((__int64)1) << (plr[pnum]._pRSpell-1))) == 0) { + plr[pnum]._pRSpell = -1; + plr[pnum]._pRSplType = SPT_NONE; + force_redraw = FULLDRAW; + } + } + if (plr[pnum]._pRSplType == SPT_ITEM) { + if (((plr[pnum]._pISpells & (((__int64)1) << (plr[pnum]._pRSpell-1)))) == 0) { + plr[pnum]._pRSpell = -1; + plr[pnum]._pRSplType = SPT_NONE; + force_redraw = FULLDRAW; + } + } + } + } + plr[pnum]._pVar8++; + if (leveltype == 0) { + if (plr[pnum]._pVar8 > plr[pnum]._pSFrames) { + StartWalkStand(pnum); + ClearPlrPVars(pnum); + return(RUN_AGAIN); + } else return(RUN_DONE); + } else { + if (plr[pnum]._pAnimFrame == plr[pnum]._pSFrames) { + StartStand(pnum, plr[pnum]._pdir); + ClearPlrPVars(pnum); + return(RUN_AGAIN); + } else return(RUN_DONE); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void ArmorDur(int pnum) { + if (pnum != myplr) return; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("ArmorDur: illegal player %d",pnum); + + PlayerStruct * p = &plr[pnum]; + if (p->BodyItem._itype == -1 && p->HeadItem._itype == -1) return; + + // Head or body hit? + int a = random(8, 3); + if (p->BodyItem._itype != -1 && p->HeadItem._itype == -1) a = 1; + if (p->BodyItem._itype == -1 && p->HeadItem._itype != -1) a = 0; + + ItemStruct * pi = a ? &p->BodyItem : &p->HeadItem; + if (pi->_iDurability == INFINITE_DUR) return; + + // lose some durability + pi->_iDurability--; + if (pi->_iDurability == 0) { + if (a) NetSendCmdDelItem(TRUE, INVLOC_BODY); + else NetSendCmdDelItem(TRUE, INVLOC_HEAD); + pi->_itype = -1; + CalcPlrInv(pnum,TRUE); + } +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +int PM_DoGotHit(int pnum) +{ + int rv; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoGotHit: illegal player %d",pnum); + + if (plr[pnum]._pIFlags & IAF_ALLHTANIM) + { + int htanimframes = 3; + if (plr[pnum]._pIFlags & IAF_HTANIM2) + htanimframes = 4; + if (plr[pnum]._pIFlags & IAF_HTANIM3) + htanimframes = 5; + + if (plr[pnum]._pVar8 > 1 && plr[pnum]._pVar8 < htanimframes) + plr[pnum]._pVar8 = htanimframes; + + // make sure we didn't go too far + if (plr[pnum]._pVar8 > plr[pnum]._pHFrames) + plr[pnum]._pVar8 = plr[pnum]._pHFrames; + } + if (plr[pnum]._pVar8 == plr[pnum]._pHFrames) { + StartStand(pnum, plr[pnum]._pdir); + ClearPlrPVars(pnum); + if (random(3,4)) ArmorDur(pnum); + rv = RUN_AGAIN; + } else { + plr[pnum]._pVar8++; + rv = RUN_DONE; + } + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoDeath(int pnum) +{ + int rv; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("PM_DoDeath: illegal player %d",pnum); + + // Hold last frame + if (plr[pnum]._pVar8 >= (plr[pnum]._pDFrames << 1)) { + if ((deathdelay > 1) && (pnum == myplr)) { + deathdelay--; + if (deathdelay == 1) { + deathflag = TRUE; + if (gbMaxPlayers == 1) gamemenu_on(); + } + } + plr[pnum]._pAnimDelay = 10000; + plr[pnum]._pAnimFrame = plr[pnum]._pAnimLen; + dFlags[plr[pnum]._px][plr[pnum]._py] |= BFLAG_DEADPLR; + } + if (plr[pnum]._pVar8 < 100) plr[pnum]._pVar8++; + rv = RUN_DONE; + + return(rv); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int PM_DoNewLvl(int pnum) +{ + return(RUN_DONE); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckNewPath(int pnum) +{ + int i, dx, dy, d, oi; + int v1,v2,v3; + + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("CheckNewPath: illegal player %d",pnum); + + if (plr[pnum].destAction == PCMD_ATTACKID) { + i = plr[pnum].destParam1; + MakePlrPath(pnum, monster[i]._mfutx, monster[i]._mfuty, FALSE); + } + if (plr[pnum].destAction == PCMD_ATTACKPID) { + i = plr[pnum].destParam1; + MakePlrPath(pnum, plr[i]._pfutx, plr[i]._pfuty, FALSE); + } + if (plr[pnum].walkpath[0] != PCMD_NOTHING) { + if (plr[pnum]._pmode == PM_STAND) { + // Special case for attack + if (pnum == myplr) { + if ((plr[pnum].destAction == PCMD_ATTACKID) || (plr[pnum].destAction == PCMD_ATTACKPID)) { + i = plr[pnum].destParam1; + if (plr[pnum].destAction == PCMD_ATTACKID) { + dx = abs(plr[pnum]._pfutx - monster[i]._mfutx); + dy = abs(plr[pnum]._pfuty - monster[i]._mfuty); + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, monster[i]._mfutx, monster[i]._mfuty); + } else { + dx = abs(plr[pnum]._pfutx - plr[i]._pfutx); + dy = abs(plr[pnum]._pfuty - plr[i]._pfuty); + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[i]._pfutx, plr[i]._pfuty); + } + if ((dx < 2) && (dy < 2)) { + ClrPlrPath(pnum); + if ((monster[i].mtalkmsg !=0) && (monster[i].mtalkmsg != TXT_VB2)) TalktoMonster(i); + else StartAttack(pnum, d); + plr[pnum].destAction = PCMD_NOTHING; + } + } + } + if (currlevel != 0) { + v1 = PlrWalkTbl[plr[pnum]._pClass][0]; + v2 = PlrWalkTbl[plr[pnum]._pClass][1]; + v3 = PlrWalkTbl[plr[pnum]._pClass][2]; + } else { + v1 = 2048; + v2 = 1024; + v3 = 512; + } + switch(plr[pnum].walkpath[0]) { + case PCMD_WALKU : + StartWalk(pnum, 0, -v2, -1, -1, DIR_U, SCRL_U); + break; + case PCMD_WALKUR : + StartWalk(pnum, v2, -v3, 0, -1, DIR_UR, SCRL_UR); + break; + case PCMD_WALKR : + StartWalk3(pnum, v1, 0, -32, -16, 1, -1, 1, 0, DIR_R, SCRL_R); + break; + case PCMD_WALKDR : + StartWalk2(pnum, v2, v3, -32, -16, 1, 0, DIR_DR, SCRL_DR); + break; + case PCMD_WALKD : + StartWalk2(pnum, 0, v2, 0, -32, 1, 1, DIR_D, SCRL_D); + break; + case PCMD_WALKDL : + StartWalk2(pnum, -v2, v3, 32, -16, 0, 1, DIR_DL, SCRL_DL); + break; + case PCMD_WALKL : + StartWalk3(pnum, -v1, 0, 32, -16, -1, 1, 0, 1, DIR_L, SCRL_L); + break; + case PCMD_WALKUL : + StartWalk(pnum, -v2, -v3, -1 ,0, DIR_UL, SCRL_UL); + break; + } + for (i = 1; i < MAXPATHLEN; i++) plr[pnum].walkpath[i-1] = plr[pnum].walkpath[i]; + plr[pnum].walkpath[MAXPATHLEN-1] = PCMD_NOTHING; + // if walk fails then start standing + if (plr[pnum]._pmode == PM_STAND) { + StartStand(pnum, plr[pnum]._pdir); + plr[pnum].destAction = PCMD_NOTHING; + } + } + } else { + if (plr[pnum].destAction != PCMD_NOTHING) { + if (plr[pnum]._pmode == PM_STAND) { + switch (plr[pnum].destAction) { + case PCMD_ATTACK : + d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2); + StartAttack(pnum, d); + break; + case PCMD_ATTACKID : + i = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - monster[i]._mfutx); + dy = abs(plr[pnum]._py - monster[i]._mfuty); + if ((dx <= 1) && (dy <= 1)) { + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, monster[i]._mfutx, monster[i]._mfuty); + if ((monster[i].mtalkmsg !=0) && (monster[i].mtalkmsg != TXT_VB2)) TalktoMonster(i); + else StartAttack(pnum, d); + } + break; + case PCMD_ATTACKPID: + i = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - plr[i]._pfutx); + dy = abs(plr[pnum]._py - plr[i]._pfuty); + if ((dx <= 1) && (dy <= 1)) { + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[i]._pfutx, plr[i]._pfuty); + StartAttack(pnum, d); + } + break; + case PCMD_RATTACK: + d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2); + StartRangeAttack(pnum, d, plr[pnum].destParam1, plr[pnum].destParam2); + break; + case PCMD_RATTACKID: + i = plr[pnum].destParam1; + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, monster[i]._mfutx, monster[i]._mfuty); + if ((monster[i].mtalkmsg !=0) && (monster[i].mtalkmsg != TXT_VB2)) TalktoMonster(i); + else StartRangeAttack(pnum, d, monster[i]._mfutx, monster[i]._mfuty); + break; + case PCMD_RATTACKPID: + i = plr[pnum].destParam1; + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[i]._pfutx, plr[i]._pfuty); + StartRangeAttack(pnum, d, plr[i]._pfutx, plr[i]._pfuty); + break; + case PCMD_SPELL: + d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2); + StartSpell(pnum, d, plr[pnum].destParam1, plr[pnum].destParam2); + plr[pnum]._pVar4 = plr[pnum].destParam3; + break; + case PCMD_SPELLXYD: + StartSpell(pnum, plr[pnum].destParam3, plr[pnum].destParam1, plr[pnum].destParam2); + plr[pnum]._pVar3 = plr[pnum].destParam3; + plr[pnum]._pVar4 = plr[pnum].destParam4; + break; + case PCMD_SPELLID: + i = plr[pnum].destParam1; + d = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mfutx, monster[i]._mfuty); + StartSpell(pnum, d, monster[i]._mfutx, monster[i]._mfuty); + plr[pnum]._pVar4 = plr[pnum].destParam2; + break; + case PCMD_SPELLPID: + i = plr[pnum].destParam1; + d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[i]._pfutx, plr[i]._pfuty); + StartSpell(pnum, d, plr[i]._pfutx, plr[i]._pfuty); + plr[pnum]._pVar4 = plr[pnum].destParam2; + break; + case PCMD_OPOBJ: + oi = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - object[oi]._ox); + dy = abs(plr[pnum]._py - object[oi]._oy); + if ((dy > 1) && (dObject[object[oi]._ox][object[oi]._oy-1] == (-1 - oi))) + dy = abs(plr[pnum]._py - object[oi]._oy + 1); + + if ((dx <= 1) && (dy <= 1)) { + if (object[oi]._oBreak == OBJ_BREAKABLE) { + d = GetDirection(plr[pnum]._px, plr[pnum]._py, object[oi]._ox, object[oi]._oy); + StartAttack(pnum, d); + } else OperateObject(pnum, oi, FALSE); + } + break; + case PCMD_DISARM: + oi = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - object[oi]._ox); + dy = abs(plr[pnum]._py - object[oi]._oy); + if ((dy > 1) && (dObject[object[oi]._ox][object[oi]._oy-1] == (-1 - oi))) + dy = abs(plr[pnum]._py - object[oi]._oy + 1); + if ((dx <= 1) && (dy <= 1)) { + if (object[oi]._oBreak == OBJ_BREAKABLE) { + d = GetDirection(plr[pnum]._px, plr[pnum]._py, object[oi]._ox, object[oi]._oy); + StartAttack(pnum, d); + } else { + TryDisarm(pnum, oi); + OperateObject(pnum, oi, FALSE); + } + } + break; + case PCMD_TELEK: + oi = plr[pnum].destParam1; + if (object[oi]._oBreak != OBJ_BREAKABLE) OperateObject(pnum, oi, TRUE); + break; + case PCMD_REQGETITEM : + if (pnum == myplr) { + i = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - item[i]._ix); + dy = abs(plr[pnum]._py - item[i]._iy); + // PATCH1.JMM + //if ((dx <= 1) && (dy <= 1) && (curs == GLOVE_CURS) && (!item[i]._iRequest) && (!item[i]._iDelFlag)) { + if ((dx <= 1) && (dy <= 1) && (curs == GLOVE_CURS) && (!item[i]._iRequest)) { + // ENDPATCH1.JMM + NetSendCmdGItem(TRUE, CMD_REQUESTGITEM, myplr, myplr, i); + item[i]._iRequest = TRUE; + } + } + break; + case PCMD_REQAGETITEM : + if (pnum == myplr) { + i = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - item[i]._ix); + dy = abs(plr[pnum]._py - item[i]._iy); + if ((dx <= 1) && (dy <= 1) && (curs == GLOVE_CURS)) + NetSendCmdGItem(TRUE, CMD_REQUESTAGITEM, myplr, myplr, i); + } + break; + case PCMD_TALK: + if (pnum == myplr) TalkToTowner(pnum, plr[pnum].destParam1); + break; + } + FixPlayerLocation(pnum,plr[pnum]._pdir); + plr[pnum].destAction = PCMD_NOTHING; + } else { + if ((plr[pnum]._pmode == PM_ATTACK) && (plr[pnum]._pAnimFrame > plr[myplr]._pAFNum)) { + if (plr[pnum].destAction == PCMD_ATTACK) { + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[pnum].destParam1, plr[pnum].destParam2); + StartAttack(pnum, d); + plr[pnum].destAction = PCMD_NOTHING; + } + else if (plr[pnum].destAction == PCMD_ATTACKID) { + i = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - monster[i]._mfutx); + dy = abs(plr[pnum]._py - monster[i]._mfuty); + if ((dx <= 1) && (dy <= 1)) { + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, monster[i]._mfutx, monster[i]._mfuty); + StartAttack(pnum, d); + } + plr[pnum].destAction = PCMD_NOTHING; + } + else if (plr[pnum].destAction == PCMD_ATTACKPID) { + i = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - plr[i]._pfutx); + dy = abs(plr[pnum]._py - plr[i]._pfuty); + if ((dx <= 1) && (dy <= 1)) { + d = GetDirection(plr[pnum]._pfutx, plr[pnum]._pfuty, plr[i]._pfutx, plr[i]._pfuty); + StartAttack(pnum, d); + } + plr[pnum].destAction = PCMD_NOTHING; + } + else if (plr[pnum].destAction == PCMD_OPOBJ) + { + oi = plr[pnum].destParam1; + dx = abs(plr[pnum]._px - object[oi]._ox); + dy = abs(plr[pnum]._py - object[oi]._oy); + if ((dy > 1) && (dObject[object[oi]._ox][object[oi]._oy-1] == (-1 - oi))) + dy = abs(plr[pnum]._py - object[oi]._oy + 1); + if ((dx <= 1) && (dy <= 1)) { + if (object[oi]._oBreak == OBJ_BREAKABLE) { + d = GetDirection(plr[pnum]._px, plr[pnum]._py, object[oi]._ox, object[oi]._oy); + StartAttack(pnum, d); + } else OperateObject(pnum, oi, FALSE); + } + } + } + if ((plr[pnum]._pmode == PM_RATTACK) && (plr[pnum]._pAnimFrame > plr[myplr]._pAFNum)) { + if (plr[pnum].destAction == PCMD_RATTACK) { + d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2); + StartRangeAttack(pnum, d, plr[pnum].destParam1, plr[pnum].destParam2); + plr[pnum].destAction = PCMD_NOTHING; + } + else if (plr[pnum].destAction == PCMD_RATTACKID) { + i = plr[pnum].destParam1; + d = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mfutx, monster[i]._mfuty); + StartRangeAttack(pnum, d, monster[i]._mfutx, monster[i]._mfuty); + plr[pnum].destAction = PCMD_NOTHING; + } + else if (plr[pnum].destAction == PCMD_RATTACKPID) { + i = plr[pnum].destParam1; + d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[i]._pfutx, plr[i]._pfuty); + StartRangeAttack(pnum, d, plr[i]._pfutx, plr[i]._pfuty); + plr[pnum].destAction = PCMD_NOTHING; + } + } + if ((plr[pnum]._pmode == PM_SPELL) && (plr[pnum]._pAnimFrame > plr[pnum]._pSFNum)) { + if (plr[pnum].destAction == PCMD_SPELL) { + d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[pnum].destParam1, plr[pnum].destParam2); + StartSpell(pnum, d, plr[pnum].destParam1, plr[pnum].destParam2); + plr[pnum].destAction = PCMD_NOTHING; + } + else if (plr[pnum].destAction == PCMD_SPELLID) { + i = plr[pnum].destParam1; + d = GetDirection(plr[pnum]._px, plr[pnum]._py, monster[i]._mfutx, monster[i]._mfuty); + StartSpell(pnum, d, monster[i]._mfutx, monster[i]._mfuty); + plr[pnum].destAction = PCMD_NOTHING; + } + else if (plr[pnum].destAction == PCMD_SPELLPID) { + i = plr[pnum].destParam1; + d = GetDirection(plr[pnum]._px, plr[pnum]._py, plr[i]._pfutx, plr[i]._pfuty); + StartSpell(pnum, d, plr[i]._pfutx, plr[i]._pfuty); + plr[pnum].destAction = PCMD_NOTHING; + } + } + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PlrDeathModeOK(int p) +{ + if (p != myplr) return(TRUE); + if ((DWORD)p >= MAX_PLRS) + app_fatal("PlrDeathModeOK: illegal player %d",p); + if (plr[p]._pmode == PM_DEATH) return(TRUE); + if (plr[p]._pmode == PM_QUIT) return(TRUE); + if (plr[p]._pmode == PM_NEWLVL) return(TRUE); + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ValidatePlayer() +{ + int i, gt, pc; + //jam.patch1.start.1/23/97 + //__int64 msk; + __int64 msk = 0; + //jam.patch1.end.1/23/97 + __int64 b = 1; + + if ((DWORD)myplr >= MAX_PLRS) + app_fatal("ValidatePlayer: illegal player %d",myplr); + if (plr[myplr]._pLevel > 50) plr[myplr]._pLevel = 50; + if (plr[myplr]._pExperience > plr[myplr]._pNextExper) + plr[myplr]._pExperience = plr[myplr]._pNextExper; + gt = 0; + for (i = 0; i < plr[myplr]._pNumInv; i++) { + if (plr[myplr].InvList[i]._itype == IT_GOLD) { + if (plr[myplr].InvList[i]._ivalue > GOLD_DOUBLE_VMAX) plr[myplr].InvList[i]._ivalue = GOLD_DOUBLE_VMAX; + gt += plr[myplr].InvList[i]._ivalue; + } + } + if (gt != plr[myplr]._pGold) plr[myplr]._pGold = gt; + pc = plr[myplr]._pClass; + if (plr[myplr]._pBaseStr > MaxStats[pc][0]) plr[myplr]._pBaseStr = MaxStats[pc][0]; + if (plr[myplr]._pBaseMag > MaxStats[pc][1]) plr[myplr]._pBaseMag = MaxStats[pc][1]; + if (plr[myplr]._pBaseDex > MaxStats[pc][2]) plr[myplr]._pBaseDex = MaxStats[pc][2]; + if (plr[myplr]._pBaseVit > MaxStats[pc][3]) plr[myplr]._pBaseVit = MaxStats[pc][3]; + + for (i = SPL_FIREBOLT; i < SPL_LAST; i++) { + if (spelldata[i].sBookLvl != -1) { + msk |= (b << (i-1)); + if (plr[myplr]._pSplLvl[i] > SPELLCAP) plr[myplr]._pSplLvl[i] = SPELLCAP; + } + } + plr[myplr]._pMemSpells &= msk; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +int pdoppely = DIRTEDGED2; + +void PlayerDoppel() +{ + int pdoppelx, pidx; + PlayerStruct *p; + BOOL forceclear; + + if (gbMaxPlayers == 1) return; + + for (pdoppelx = DIRTEDGED2; pdoppelx < (DIRTEDGED2+80); pdoppelx++) { + if (dPlayer[pdoppelx][pdoppely]) { + if (dPlayer[pdoppelx][pdoppely] > 0) + pidx = dPlayer[pdoppelx][pdoppely] - 1; + else + pidx = -(dPlayer[pdoppelx][pdoppely] + 1); + p = &plr[pidx]; + forceclear = FALSE; + if (p->plrlevel != currlevel) forceclear = TRUE; + if (!p->plractive) forceclear = TRUE; + if (!forceclear) { + if ((p->_pmode >= PM_WALK) && (p->_pmode <= PM_WALK3)) continue; + if (p->_pmode >= PM_NEWLVL) continue; + if ((p->_px == pdoppelx) && (p->_py == pdoppely)) continue; + forceclear = TRUE; + } + if (forceclear) { + dFlags[pdoppelx+1][pdoppely+0] &= BFMASK_PLRLR; + dFlags[pdoppelx+0][pdoppely+1] &= BFMASK_PLRLR; + dPlayer[pdoppelx][pdoppely] = 0; + } + } + } + pdoppely++; + if (pdoppely == DIRTEDGED2+80) pdoppely = DIRTEDGED2; +} +// PATCH2.JMM.3/5/97 +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#define MAX_STAT 750 +#define MAX_HP (2000< MAX_STAT ) + plr[pnum]._pStrength = MAX_STAT; + + if ( plr[pnum]._pDexterity > MAX_STAT ) + plr[pnum]._pDexterity = MAX_STAT; + + if ( plr[pnum]._pMagic > MAX_STAT ) + plr[pnum]._pMagic = MAX_STAT; + + if ( plr[pnum]._pVitality > MAX_STAT ) + plr[pnum]._pVitality = MAX_STAT; + + if ( plr[pnum]._pHitPoints > MAX_HP ) + plr[pnum]._pHitPoints = MAX_HP; + + if ( plr[pnum]._pMana > MAX_MANA ) + plr[pnum]._pMana = MAX_MANA; + +} +// ENDPATCH2 + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ProcessPlayers() +{ + int raflag; // Run again flag + int pnum; + + if ((DWORD)myplr >= MAX_PLRS) + app_fatal("ProcessPlayers: illegal player %d",myplr); + + // TEMP! debugging + for (int i = 0; i < MAXINV; i++) { + if (plr[myplr].InvGrid[i] > 0) + app_assert(plr[myplr].InvGrid[i] <= plr[myplr]._pNumInv); + } + + if (plr[myplr].pLvlLoad > 0) plr[myplr].pLvlLoad--; + + if (sfxdelay > 0) { + sfxdelay--; + if (sfxdelay == 0) + { + switch (sfxdnum) + { + case HSFX_DEFILER1: + InitQTextMsg(TXT_DEFILER1); + break; + case HSFX_DEFILER2: + InitQTextMsg(TXT_DEFILER2); + break; + case HSFX_DEFILER3: + InitQTextMsg(TXT_DEFILER3); + break; + case HSFX_DEFILER4: + InitQTextMsg(TXT_DEFILER4); + break; + default: + PlaySFX(sfxdnum); + } + } + } + + ValidatePlayer(); + + for (pnum = 0; pnum < MAX_PLRS; pnum++) { + if (!plr[pnum].plractive) continue; + if (currlevel != plr[pnum].plrlevel) continue; + if ((pnum != myplr) && (plr[pnum]._pLvlChanging)) continue; + + // PATCH2.JMM.3/5/97 + CheckCheatStats( pnum ); + // PATCH2.JMM.3/5/97 + + + + + if ((!PlrDeathModeOK(pnum)) && ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0)) { + // rjs - manashld fix? - SetPlayerHitPoints(pnum, 0); + StartPlrKill(pnum, KILL_UNKNOWN); + } + + if (pnum == myplr) { + // Constricting item + if ((plr[pnum]._pIFlags & IAF_CONSTRICT) && (currlevel != 0)) { + plr[pnum]._pHitPoints -= 4; + plr[pnum]._pHPBase -= 4; + if ((plr[pnum]._pHitPoints >> HP_SHIFT) <= 0) { + // rjs - manashld fix? - SetPlayerHitPoints(pnum, 0); + StartPlrKill(pnum, FALSE); + } + drawhpflag = TRUE; + } + + // lose mana item + if (plr[pnum]._pIFlags & IAF_LMANA) { + if (plr[pnum]._pManaBase > 0 ) { + plr[pnum]._pManaBase -= plr[pnum]._pMana; + plr[pnum]._pMana = 0; + drawmanaflag = TRUE; + } + } + } + + raflag = RUN_DONE; + do { + // Run Player Mode + switch (plr[pnum]._pmode) { + case PM_STAND : + raflag = PM_DoStand(pnum); + break; + case PM_WALK : + raflag = PM_DoWalk(pnum); + break; + case PM_WALK2 : + raflag = PM_DoWalk2(pnum); + break; + case PM_WALK3: + raflag = PM_DoWalk3(pnum); + break; + case PM_ATTACK: + raflag = PM_DoAttack(pnum); + break; + case PM_RATTACK: + raflag = PM_DoRangeAttack(pnum); + break; + case PM_BLOCK : + raflag = PM_DoBlock(pnum); + break; + case PM_SPELL: + raflag = PM_DoSpell(pnum); + break; + case PM_GOTHIT: + raflag = PM_DoGotHit(pnum); + break; + case PM_DEATH: + raflag = PM_DoDeath(pnum); + break; + case PM_NEWLVL: + raflag = PM_DoNewLvl(pnum); + break; + } + + // Check for new command + CheckNewPath(pnum); + + } while (raflag != RUN_DONE); + + // Animate Player + plr[pnum]._pAnimCnt++; + if (plr[pnum]._pAnimCnt > plr[pnum]._pAnimDelay) { + plr[pnum]._pAnimCnt = 0; + plr[pnum]._pAnimFrame++; + if (plr[pnum]._pAnimFrame > plr[pnum]._pAnimLen) plr[pnum]._pAnimFrame = 1; + } + } + + //PlayerDoppel(); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void ClrPlrPath(int pnum) { + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("ClrPlrPath: illegal player %d",pnum); + FillMemory(plr[pnum].walkpath,MAXPATHLEN,PCMD_NOTHING); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL PosOkPlayer(int pnum, int px, int py) +{ + int mi, p, pn; + char bv; + + if (dPiece[px][py] == 0) return FALSE; + pn = dPiece[px][py]; + if (SolidLoc(px, py)) return FALSE; + if (dPlayer[px][py]) { + if (dPlayer[px][py] > 0) p = dPlayer[px][py] - 1; + else p = -(dPlayer[px][py] + 1); + if ((p != pnum) && (plr[p]._pHitPoints != 0)) return FALSE; + } + if (dMonster[px][py]) { + if (currlevel == 0) return FALSE; + if (dMonster[px][py] > 0) { + mi = dMonster[px][py] - 1; + if ((monster[mi]._mhitpoints >> HP_SHIFT) > 0) return FALSE; + } else return FALSE; + } + if (dObject[px][py]) { + if (dObject[px][py] > 0) bv = dObject[px][py] - 1; + else bv = -(dObject[px][py] + 1); + if (object[bv]._oSolidFlag) return FALSE; + } + return TRUE; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void MakePlrPath(int pnum, int xx, int yy, BOOL endspace) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("MakePlrPath: illegal player %d",pnum); + + // set target position + plr[pnum]._ptargx = xx; + plr[pnum]._ptargy = yy; + + if (plr[pnum]._pfutx == xx && plr[pnum]._pfuty == yy) + return; + + int pathlen = FindPath(PosOkPlayer, pnum, plr[pnum]._pfutx, plr[pnum]._pfuty, xx, yy, plr[pnum].walkpath); + if(pathlen) { + if (!endspace) { + pathlen--; + switch (plr[pnum].walkpath[pathlen]) { + case PCMD_WALKUR: + yy++; + break; + case PCMD_WALKUL: + xx++; + break; + case PCMD_WALKDR: + xx--; + break; + case PCMD_WALKDL: + yy--; + break; + case PCMD_WALKU: + xx++; + yy++; + break; + case PCMD_WALKR: + xx--; + yy++; + break; + case PCMD_WALKD: + xx--; + yy--; + break; + case PCMD_WALKL: + xx++; + yy--; + break; + } + plr[pnum]._ptargx = xx; + plr[pnum]._ptargy = yy; + } + plr[pnum].walkpath[pathlen] = PCMD_NOTHING; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckPlrSpell() +{ + int sd; + BOOL addflag = FALSE; + + if ((DWORD)myplr >= MAX_PLRS) + app_fatal("CheckPlrSpell: illegal player %d",myplr); + + int rspell = plr[myplr]._pRSpell; + + if (rspell == -1) { + if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR34); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE34); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE34); + else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK34); + else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD34); + else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN34); + #endif + return; + } + + //rjs if (leveltype == 0) return; + if (leveltype == 0 && spelldata[plr[myplr]._pRSpell].sTownSpell == FALSE) { + if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR27); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE27); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE27); + else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK27); + else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD27); + else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN27); + #endif + return; + } + if (curs != GLOVE_CURS) return; + + // Check if cursor is in play area, allowing certain spells to be executed anywhere + if (!(((MouseY < 352) + && !(chrflag && MouseX < 320) + && !(invflag && MouseX > 320)) || + ((MouseY < 352) && (rspell == SPL_HEAL + || rspell == SPL_IDENTIFY + || rspell == SPL_REPAIR + || rspell == SPL_INFRA + || rspell == SPL_RECHARGE)))) + return; + + switch (plr[myplr]._pRSplType) { + case SPT_ABILITY : + case SPT_MEMORIZED : + addflag = CheckSpell(myplr, plr[myplr]._pRSpell, plr[myplr]._pRSplType, FALSE); + break; + case SPT_SCROLL : + addflag = UseScroll(); + break; + case SPT_ITEM: + addflag = UseStaff(); + break; + } + if (addflag) { + if (plr[myplr]._pRSpell == SPL_WALL + || plr[myplr]._pRSpell == SPL_LTWALL) { + sd = GetDirection(plr[myplr]._px, plr[myplr]._py, cursmx, cursmy); + NetSendCmdLocParam3(TRUE, CMD_SPELLXYD, cursmx, cursmy, plr[myplr]._pRSpell, sd, GetSpellLevel(myplr, plr[myplr]._pRSpell)); + } else { + if (cursmonst != -1) NetSendCmdParam3(TRUE, CMD_SPELLID, cursmonst, plr[myplr]._pRSpell,GetSpellLevel(myplr, plr[myplr]._pRSpell)); + else { + if (cursplr != -1) NetSendCmdParam3(TRUE, CMD_SPELLPID, cursplr, plr[myplr]._pRSpell,GetSpellLevel(myplr, plr[myplr]._pRSpell)); + else NetSendCmdLocParam2(TRUE, CMD_SPELLXY, cursmx, cursmy, plr[myplr]._pRSpell,GetSpellLevel(myplr, plr[myplr]._pRSpell)); + } + } + } else { + if (plr[myplr]._pRSplType == SPT_MEMORIZED) { + if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR35); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE35); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE35); + else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK35); + else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD35); + else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN35); + #endif + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SyncPlrAnim(int p) +{ + int dir, s; + + if ((DWORD)p >= MAX_PLRS) + app_fatal("SyncPlrAnim: illegal player %d",p); + + dir = plr[p]._pdir; + switch (plr[p]._pmode) { + case PM_STAND : + plr[p]._pAnimData = plr[p]._pNAnim[dir]; + break; + case PM_WALK : + plr[p]._pAnimData = plr[p]._pWAnim[dir]; + break; + case PM_WALK2 : + plr[p]._pAnimData = plr[p]._pWAnim[dir]; + break; + case PM_WALK3: + plr[p]._pAnimData = plr[p]._pWAnim[dir]; + break; + case PM_ATTACK: + plr[p]._pAnimData = plr[p]._pAAnim[dir]; + break; + case PM_RATTACK: + plr[p]._pAnimData = plr[p]._pAAnim[dir]; + break; + case PM_BLOCK: + plr[p]._pAnimData = plr[p]._pBAnim[dir]; + break; + case PM_SPELL: + if (p == myplr) s = spelldata[plr[p]._pSpell].sType; + //jam.patch1.start.1/23/97 + //else s == ST_FIRE; + else s = ST_FIRE; + //jam.patch1.end.1/23/97 + if (s == ST_FIRE) plr[p]._pAnimData = plr[p]._pFAnim[dir]; + if (s == ST_LIGHT) plr[p]._pAnimData = plr[p]._pLAnim[dir]; + if (s == ST_MISC) plr[p]._pAnimData = plr[p]._pTAnim[dir]; + break; + case PM_GOTHIT: + plr[p]._pAnimData = plr[p]._pHAnim[dir]; + break; + case PM_DEATH: + plr[p]._pAnimData = plr[p]._pDAnim[dir]; + break; + case PM_NEWLVL: + case PM_QUIT: + plr[p]._pAnimData = plr[p]._pNAnim[dir]; + break; + default: + app_fatal("SyncPlrAnim"); + break; + } + + app_assert(plr[p]._pAnimData); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SyncInitPlrPos(int pnum) +{ + // Force the player's target position to be where he wants it to be + plr[pnum]._ptargx = plr[pnum]._px; + plr[pnum]._ptargy = plr[pnum]._py; + + // Don't find a space for single player + if (gbMaxPlayers == 1) return; + + // Find a place to put him in the map + if (plr[pnum].plrlevel == currlevel) { + for (int i = 0; i < sizeof(plrxoff2)/sizeof(plrxoff2[0]) - 1; i++) { + if (PosOkPlayer( + pnum, + plr[pnum]._px + plrxoff2[i], + plr[pnum]._py + plryoff2[i] + )) break; + } + + // stuff player into the map + plr[pnum]._px += plrxoff2[i]; + plr[pnum]._py += plryoff2[i]; + dPlayer[plr[pnum]._px][plr[pnum]._py] = pnum + 1; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SyncInitPlr(int pnum) { + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("SyncInitPlr: illegal player %d",pnum); + + SetPlrAnims(pnum); + SyncInitPlrPos(pnum); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CheckStats(int p) +/*-----------------------------------------------------------------------* +** Description: Checks to see if specified characters base stat value +** is greater than the max base stat, or less than 0. +** If characters base stat > max. stat, then set characters base +** stat = max. stat. If characters base stat < 0, then set +** characters base stat = 0. +** Input: p = plr[?] index +** s = stat to check +** Return: None +**-----------------------------------------------------------------------*/ +{ + int c, i; + + if ((DWORD)p >= MAX_PLRS) + app_fatal("CheckStats: illegal player %d",p); + + //Find character class + if (plr[p]._pClass == CLASS_WARRIOR) c = 0; + else if (plr[p]._pClass == CLASS_ROGUE) c = 1; + else if (plr[p]._pClass == CLASS_SORCEROR) c = 2; + else if (plr[p]._pClass == CLASS_MONK) c = 3; + else if (plr[p]._pClass == CLASS_BARD) c = 4; + else if (plr[p]._pClass == CLASS_BARBARIAN) c = 5; + //Check stats + for (i = 0; i < 4; i++) { + switch(i) { + case 0: + //Strength + if (plr[p]._pBaseStr > MaxStats[c][0]) plr[p]._pBaseStr = MaxStats[c][0]; + else if (plr[p]._pBaseStr < 0) plr[p]._pBaseStr = 0; + break; + case 1: + //Magic + if (plr[p]._pBaseMag > MaxStats[c][1]) plr[p]._pBaseMag = MaxStats[c][1]; + else if (plr[p]._pBaseMag < 0) plr[p]._pBaseMag = 0; + break; + case 2: + //Dexterity + if (plr[p]._pBaseDex > MaxStats[c][2]) plr[p]._pBaseDex = MaxStats[c][2]; + else if (plr[p]._pBaseDex < 0) plr[p]._pBaseDex = 0; + break; + case 3: + //Vitality + if (plr[p]._pBaseVit > MaxStats[c][3]) plr[p]._pBaseVit = MaxStats[c][3]; + else if (plr[p]._pBaseVit < 0) plr[p]._pBaseVit = 0; + break; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ModifyPlrStr(int p, int l) +{ + if ((DWORD)p >= MAX_PLRS) + app_fatal("ModifyPlrStr: illegal player %d",p); + int ms = MaxStats[plr[p]._pClass][0]; + if ((plr[p]._pBaseStr + l) > ms) l = ms - plr[p]._pBaseStr; + plr[p]._pStrength += l; + plr[p]._pBaseStr += l; +// if (plr[p]._pClass == CLASS_ROGUE || +// plr[p]._pClass == CLASS_MONK || +// plr[p]._pClass == CLASS_BARD) +// plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200; +// else +// plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100; + CalcPlrInv(p,TRUE); + if (p == myplr) NetSendCmdParam1(FALSE, CMD_SETSTR, plr[p]._pBaseStr); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ModifyPlrMag(int p, int l) +{ + if ((DWORD)p >= MAX_PLRS) + app_fatal("ModifyPlrMag: illegal player %d",p); + int ms = MaxStats[plr[p]._pClass][1]; + if ((plr[p]._pBaseMag + l) > ms) l = ms - plr[p]._pBaseMag; + plr[p]._pMagic += l; + plr[p]._pBaseMag += l; + l = l << MANA_SHIFT; + if (plr[p]._pClass == CLASS_SORCEROR) l = l << 1; // 2x + else if (plr[p]._pClass == CLASS_BARD) l += l >> 1; // 1.5x + plr[p]._pMaxManaBase += l; + plr[p]._pMaxMana += l; + + if (!(plr[p]._pIFlags & IAF_LMANA)) { + plr[p]._pManaBase += l; + plr[p]._pMana += l; + } + CalcPlrInv(p,TRUE); + if (p == myplr) NetSendCmdParam1(FALSE, CMD_SETMAG, plr[p]._pBaseMag); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ModifyPlrDex(int p, int l) +{ + if ((DWORD)p >= MAX_PLRS) + app_fatal("ModifyPlrDex: illegal player %d",p); + int ms = MaxStats[plr[p]._pClass][2]; + if ((plr[p]._pBaseDex + l) > ms) l = ms - plr[p]._pBaseDex; + plr[p]._pDexterity += l; + plr[p]._pBaseDex += l; + CalcPlrInv(p,TRUE); +// if (plr[p]._pClass == CLASS_ROGUE || +// plr[p]._pClass == CLASS_MONK || +// plr[p]._pClass == CLASS_BARD) +// { +// plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200; +// } + if (p == myplr) NetSendCmdParam1(FALSE, CMD_SETDEX, plr[p]._pBaseDex); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ModifyPlrVit(int p, int l) +{ + if ((DWORD)p >= MAX_PLRS) + app_fatal("ModifyPlrVit: illegal player %d",p); + int ms = MaxStats[plr[p]._pClass][3]; + if ((plr[p]._pBaseVit + l) > ms) l = ms - plr[p]._pBaseVit; + plr[p]._pVitality += l; + plr[p]._pBaseVit += l; + l = l << HP_SHIFT; + if (plr[p]._pClass == CLASS_WARRIOR + || plr[p]._pClass == CLASS_BARBARIAN) l = l << 1; + plr[p]._pHPBase += l; + plr[p]._pMaxHPBase += l; + plr[p]._pHitPoints += l; + plr[p]._pMaxHP += l; + CalcPlrInv(p,TRUE); + if (p == myplr) NetSendCmdParam1(FALSE, CMD_SETVIT, plr[p]._pBaseVit); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetPlayerHitPoints(int pnum, int newhp) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("SetPlayerHitPoints: illegal player %d",pnum); + plr[pnum]._pHitPoints = newhp; + plr[pnum]._pHPBase = newhp - (plr[pnum]._pMaxHP - plr[pnum]._pMaxHPBase); + if (pnum == myplr) drawhpflag = TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetPlrStr(int p, int v) +{ + if ((DWORD)p >= MAX_PLRS) + app_fatal("SetPlrStr: illegal player %d",p); + plr[p]._pBaseStr = v; + CalcPlrInv(p,TRUE); +/* this stuff is done in CalcPlrInv */ +// if (plr[p]._pClass == CLASS_ROGUE || +// plr[p]._pClass == CLASS_MONK || +// plr[p]._pClass == CLASS_BARD) +// { +// plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200; +// } +// else +// plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetPlrMag(int p, int v) +{ + if ((DWORD)p >= MAX_PLRS) + app_fatal("SetPlrMag: illegal player %d",p); + plr[p]._pBaseMag = v; + v = v << MANA_SHIFT; + if (plr[p]._pClass == CLASS_SORCEROR) v = v << 1; // 2x + else if (plr[p]._pClass == CLASS_BARD) v += v >> 1; // 1.5x + plr[p]._pMaxManaBase = v; + plr[p]._pMaxMana = v; + CalcPlrInv(p,TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetPlrDex(int p, int v) +{ + if ((DWORD)p >= MAX_PLRS) + app_fatal("SetPlrDex: illegal player %d",p); + plr[p]._pBaseDex = v; + CalcPlrInv(p,TRUE); +/* this stuff is done in CalcPlrInv */ +// if (plr[p]._pClass == CLASS_ROGUE || +// plr[p]._pClass == CLASS_MONK || +// plr[p]._pClass == CLASS_BARD) +// { +// plr[p]._pDamageMod = ((plr[p]._pStrength + plr[p]._pDexterity) * plr[p]._pLevel) / 200; +// } +// else +// plr[p]._pDamageMod = (plr[p]._pStrength * plr[p]._pLevel) / 100; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetPlrVit(int p, int v) +{ + if ((DWORD)p >= MAX_PLRS) + app_fatal("SetPlrVit: illegal player %d",p); + plr[p]._pBaseVit = v; + v = v << HP_SHIFT; + if (plr[p]._pClass == CLASS_WARRIOR + || plr[p]._pClass == CLASS_BARBARIAN) v = v << 1; + plr[p]._pHPBase = v; + plr[p]._pMaxHPBase = v; + CalcPlrInv(p,TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitDungMsgs(int pnum) +{ + if ((DWORD)pnum >= MAX_PLRS) + app_fatal("InitDungMsgs: illegal player %d",pnum); + plr[pnum].pDungMsgs = 0; + plr[pnum].pHellfireMsgs = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void PlayDungMsgs() +{ + if ((DWORD)myplr >= MAX_PLRS) + app_fatal("PlayDungMsgs: illegal player %d",myplr); + if ((currlevel == 1) && (!plr[myplr]._pLvlVisited[1]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_1))) { + // play "The sancity of this place" speech + sfxdelay = 40; + #if !IS_VERSION(SHAREWARE) + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR97; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE97; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE97; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK97; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD97; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN97; + #else + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR97; + #endif + plr[myplr].pDungMsgs |= DUNGMSG_1; + } + + else if ((currlevel == 5) && (!plr[myplr]._pLvlVisited[5]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_2))) { + // play "smells of death" speech + sfxdelay = 40; + #if !IS_VERSION(SHAREWARE) + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR96B; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE96; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE96; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK96; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD96; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN96; + #else + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR96B; + #endif + plr[myplr].pDungMsgs |= DUNGMSG_2; + } + + else if ((currlevel == 9) && (!plr[myplr]._pLvlVisited[9]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_3))) { + // play "It's hot down here" speech + sfxdelay = 40; + #if !IS_VERSION(SHAREWARE) + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR98; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE98; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE98; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK98; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD98; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN98; + #else + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR98; + #endif + plr[myplr].pDungMsgs |= DUNGMSG_3; + } + + else if ((currlevel == 13) && (!plr[myplr]._pLvlVisited[13]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_4))) { + // play "I must be getting close" speech + sfxdelay = 40; + #if !IS_VERSION(SHAREWARE) + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR99; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE99; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE99; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK99; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD99; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN99; + #else + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR99; + #endif + plr[myplr].pDungMsgs |= DUNGMSG_4; + } + + else if ((currlevel == 16) && (!plr[myplr]._pLvlVisited[15]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_5))) { + // play "Diablo's Wrath" + sfxdelay = 40; + #if !IS_VERSION(SHAREWARE) + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_DIABLVLINT; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_DIABLVLINT; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_DIABLVLINT; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_DIABLVLINT; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_DIABLVLINT; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_DIABLVLINT; + #endif + plr[myplr].pDungMsgs |= DUNGMSG_5; + } + else if ((currlevel == HIVESTART) && (!plr[myplr]._pLvlVisited[HIVESTART]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_1))) + { + // play Defiler 1 JKE + sfxdelay = 10; + sfxdnum = HSFX_DEFILER1; + quests[Q_DEFILER]._qactive = QUEST_NOTDONE; + quests[Q_DEFILER]._qlog = TRUE; + quests[Q_DEFILER]._qmsg = TXT_DEFILER1; + plr[myplr].pHellfireMsgs |= DUNGMSG_1; + } +/* else if ((currlevel == (HIVESTART+1)) && (!plr[myplr]._pLvlVisited[(HIVESTART+1)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_2))) { + // play Defiler 2 JKE + sfxdelay = 10; + sfxdnum = HSFX_DEFILER2; + plr[myplr].pHellfireMsgs |= DUNGMSG_2; + } */ + else if ((currlevel == (HIVESTART+2)) && (!plr[myplr]._pLvlVisited[(HIVESTART+2)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_3))) { + // play Defiler 3 JKE + sfxdelay = 10; + sfxdnum = HSFX_DEFILER3; + plr[myplr].pHellfireMsgs |= DUNGMSG_3; + } +/* else if ((currlevel == (HIVESTART+3)) && (!plr[myplr]._pLvlVisited[(HIVESTART+3)]) && (gbMaxPlayers == 1) && (!(plr[myplr].pHellfireMsgs & DUNGMSG_4))) { + // play Defiler 4 JKE + sfxdelay = 10; + sfxdnum = HSFX_DEFILER4; + plr[myplr].pHellfireMsgs |= DUNGMSG_4; + } */ + else if ((currlevel == CRYPTSTART) && (!plr[myplr]._pLvlVisited[CRYPTSTART]) && (gbMaxPlayers == 1) && (!(plr[myplr].pDungMsgs & DUNGMSG_6))) { + // play "great power " JKE + sfxdelay = 30; + +// sfxdnum = HSFX_CORNERSTONE1; +/* quests[Q_CORNERSTONE]._qactive = QUEST_NOTDONE; + quests[Q_CORNERSTONE]._qlog = TRUE; + quests[Q_CORNERSTONE]._qmsg = TXT_CORNERSTONE1; + InitQTextMsg(TXT_CORNERSTONE1); */ + + #if !IS_VERSION(SHAREWARE) + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR92; + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE92; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE92; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK92; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD92; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN92; + #else + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR92; + #endif + + plr[myplr].pDungMsgs |= DUNGMSG_6; + } + + else sfxdelay = 0; +} + + +int GetMaxStr(int Plrclass) +{ + return MaxStats[Plrclass][0]; +} + +int GetMaxMag(int Plrclass) +{ + return MaxStats[Plrclass][1]; +} + +int GetMaxDex(int Plrclass) +{ + return MaxStats[Plrclass][2]; +} diff --git a/src/PLAYER.H b/src/PLAYER.H new file mode 100644 index 0000000..2e751da --- /dev/null +++ b/src/PLAYER.H @@ -0,0 +1,520 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/PLAYER.H 3 2/22/97 12:54p Pwyatt $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ +#define MAXPACKLEN 256 + +#define PM_STAND 0 +#define PM_WALK 1 +#define PM_WALK2 2 +#define PM_WALK3 3 +#define PM_ATTACK 4 +#define PM_RATTACK 5 +#define PM_BLOCK 6 +#define PM_GOTHIT 7 +#define PM_DEATH 8 +#define PM_SPELL 9 +#define PM_NEWLVL 10 +#define PM_QUIT 11 + +#define PCMD_NOTHING -1 +#define PCMD_STAND 0 +#define PCMD_WALKUR 1 +#define PCMD_WALKUL 2 +#define PCMD_WALKDR 3 +#define PCMD_WALKDL 4 +#define PCMD_WALKU 5 +#define PCMD_WALKR 6 +#define PCMD_WALKD 7 +#define PCMD_WALKL 8 +#define PCMD_ATTACK 9 +#define PCMD_RATTACK 10 +#define PCMD_BLOCK 11 +#define PCMD_SPELL 12 +#define PCMD_OPOBJ 13 +#define PCMD_DISARM 14 +#define PCMD_REQGETITEM 15 +#define PCMD_REQAGETITEM 16 +#define PCMD_TALK 17 +#define PCMD_TELEK 18 +// free space +#define PCMD_ATTACKID 20 +#define PCMD_ATTACKPID 21 +#define PCMD_RATTACKID 22 +#define PCMD_RATTACKPID 23 +#define PCMD_SPELLID 24 +#define PCMD_SPELLPID 25 +#define PCMD_SPELLXYD 26 + +#define DIR_U 4 +#define DIR_UR 5 +#define DIR_R 6 +#define DIR_DR 7 +#define DIR_D 0 +#define DIR_DL 1 +#define DIR_L 2 +#define DIR_UL 3 + +#define PGFX_MASK 0x0f +#define PGFX_CMASK 0xf0 +#define PGFX_CSHIFT 4 + +#define PGFX_NGUY 0 // Nothing in hands +#define PGFX_SGUY 1 // Shield only +#define PGFX_XGUY 2 // Sword only +#define PGFX_GUY 3 // Sword and shield +#define PGFX_BGUY 4 // Bow +#define PGFX_FGUY 5 // Axe +#define PGFX_ZGUY 6 // Mace +#define PGFX_CGUY 7 // Mace and shield +#define PGFX_TGUY 8 // Staff + +#define PGFX_NMGUY 16 // Same as above, medium armor = 0x10 + plain version +#define PGFX_SMGUY 17 +#define PGFX_XMGUY 18 +#define PGFX_MGUY 19 +#define PGFX_BMGUY 20 +#define PGFX_FMGUY 21 +#define PGFX_ZMGUY 22 +#define PGFX_CMGUY 23 +#define PGFX_TMGUY 24 + +#define PGFX_NHGUY 32 // Same as above, heavy armor = 0x20 + plain version +#define PGFX_SHGUY 33 +#define PGFX_XHGUY 34 +#define PGFX_HGUY 35 +#define PGFX_BHGUY 36 +#define PGFX_FHGUY 37 +#define PGFX_ZHGUY 38 +#define PGFX_CHGUY 39 +#define PGFX_THGUY 40 + +#define PGL_STAND 0x0001 // Player gfx load +#define PGL_WALK 0x0002 +#define PGL_ATTACK 0x0004 +#define PGL_HIT 0x0008 +#define PGL_LMAG 0x0010 +#define PGL_FMAG 0x0020 +#define PGL_TMAG 0x0040 +#define PGL_DEAD 0x0080 +#define PGL_BLOCK 0x0100 +#define PGL_ALL 0x017f + +#define E_SINGLE 0 +#define E_DOUBLE 1 + + +#define CLASS_WARRIOR 0 +#define CLASS_ROGUE 1 +#define CLASS_SORCEROR 2 +#define CLASS_MONK 3 +#define CLASS_BARD 4 +#define CLASS_BARBARIAN 5 + +#define NUM_CLASSES (1 + CLASS_BARBARIAN) + +#define HP_SHIFT 6 // number of fractional bits for hit points +#define MANA_SHIFT 6 // number of fractional bits for mana points + +#define WEAP_H2H 0 +#define WEAP_RANGE 1 + +#define MAXPATHLEN 25 + +#define MAXINV 40 // maximum inventory items per player +#define MAXSPD 8 // maximum invertory speed items per player + +#define SPL_FROMR 0 // Current spell from readied spell +#define SPL_FROMBK 1 // Current spell from spell book +#define SPL_FROMT 2 // Current spell from targeted spell +#define SPL_FROMSB 3 // Current spell from scroll in speed bar + +#define PLR_NAME_LEN 32 + +#define BASE_TO_HIT 50 + +#define SF_ETHER 0x01 // Etheralize spell on +#define SF_RAGE 0x02 // Rage spell on. +#define SF_LETHERGY 0x04 // Lethergy spell on. +#define SF_FLAG4 0x08 // +#define SF_FLAG5 0x10 // +#define SF_FLAG6 0x20 // +#define SF_FLAG7 0x40 // +#define SF_FLAG8 0x80 // + + +#define INVLOC_HEAD 0 +#define INVLOC_RING1 1 +#define INVLOC_RING2 2 +#define INVLOC_NECK 3 + +#define INVLOC_HAND1 4 +#define INVLOC_HAND2 5 +#define INVLOC_BODY 6 +#define NUM_INVLOC 7 + +#define DUNGMSG_1 0x01 +#define DUNGMSG_2 0x02 +#define DUNGMSG_3 0x04 +#define DUNGMSG_4 0x08 +#define DUNGMSG_5 0x10 +#define DUNGMSG_6 0x20 // JKE CRYPT +#define DUNGMSG_7 0x40 // JKE HIVE +#define DUNGMSG_8 0x80 // JKEQUEST HIVE2 + +#define STAT_STR 0 +#define STAT_MAG 1 +#define STAT_DEX 2 +#define STAT_VIT 3 + +#define LVLCHANGE_OFF 0 +#define LVLCHANGE_TIME 10 + +#define KILL_UNKNOWN -1 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ +typedef struct { + int _pmode; // players current mode + + char walkpath[MAXPATHLEN]; + BYTE plractive; + + int destAction; + int destParam1; + int destParam2; + int destParam3; + int destParam4; + int plrlevel; + + int _px; // plr map x + int _py; // plr map y + int _pfutx; // plr future map x + int _pfuty; // plr future map y + int _ptargx; // final target x + int _ptargy; // final target y + int _pownerx; // x coord from computer which owns this player + int _pownery; // x coord from computer which owns this player + int _poldx; // plr old x position + int _poldy; // plr old y position + + long _pxoff; // offset x from left of map tile + long _pyoff; // offset y from bottom of map tile + long _pxvel; // current x rate + long _pyvel; // current y rate + int _pdir; // current player direction + int _nextdir; // Next direction wanted + int _pgfxnum; // Graphic set player number + BYTE *_pAnimData; // Data pointer to anim tables + int _pAnimDelay; // anim delay amount + int _pAnimCnt; // current anim delay value + int _pAnimLen; // number of anim frames + int _pAnimFrame; // current anim frame + long _pAnimWidth; // current width of anim + long _pAnimWidth2; // (width - 64) / 2 + int _peflag; // draw extra tile to left for walk fix (flag) + + int _plid; // player light id + int _pvid; // player vision id + + int _pSpell; // Spell to cast (from book or readied) + char _pSplType; // Spell type of spell to cast + char _pSplFrom; // Spell from Readied, book, or speed bar + + int _pTSpell; // Targeted spell + char _pTSplType; // Targeted spell type + + int _pRSpell; // Readied spell + char _pRSplType; // Readied spell type (Memorized, ability, staff/item) + + int _pSBkSpell; // Current spell book spell + char _pSBkSplType; // Spell book spell type + + char _pSplLvl[64]; // Spell level corresponding to SplType bits + __int64 _pMemSpells; // Flags for which spell the char has from memorizing books + __int64 _pAblSpells; // Flags for which spell the char has class abilities + __int64 _pScrlSpells; // Flags for which spell the char has from scrolls + char _pSpellFlags; // Flags for spells, these can be used for anything, see defines above + + int _pSplHotKey[4]; // Spell hotkeys + char _pSplTHotKey[4]; // Spell type hotkeys + + int _pwtype; // Weapon type (ranged, h2h) + + BYTE _pBlockFlag; // Do I have a shield to block with? + BYTE _pInvincible; // Can I be hit? + char _pLightRad; // Player light radius + BYTE _pLvlChanging; // Am I in the process of changing levels? + + // Player attributes + char _pName[PLR_NAME_LEN]; + char _pClass; + + int _pStrength; + int _pBaseStr; + int _pMagic; + int _pBaseMag; + int _pDexterity; + int _pBaseDex; + int _pVitality; + int _pBaseVit; + + int _pStatPts; + + int _pDamageMod; // Damage modifier + int _pBaseToBlk; // Block % + + long _pHPBase; + long _pMaxHPBase; + long _pHitPoints; + long _pMaxHP; + int _pHPPer; + long _pManaBase; + long _pMaxManaBase; + long _pMana; + long _pMaxMana; + int _pManaPer; + + char _pLevel; + char _pMaxLvl; + long _pExperience; + long _pMaxExp; + long _pNextExper; + + char _pArmorClass; + + char _pMagResist; + char _pFireResist; + char _pLghtResist; + + long _pGold; + + BOOL _pInfraFlag; + + long _pVar1; // scratch var 1 + long _pVar2; // scratch var 2 + long _pVar3; // scratch var 3 + long _pVar4; // scratch var 4 + long _pVar5; // scratch var 5 + long _pVar6; // scratch var 6 + long _pVar7; // scratch var 7 + long _pVar8; // scratch var 8 + + BYTE _pLvlVisited[NUMLEVELS]; // Have I been on this level? + BYTE _pSLvlVisited[NUMLEVELS]; // Have I been on this set piece level? + + int _pGFXLoad; // Flag for which graphics are loaded + + BYTE *_pNAnim[8]; // Neutral anims + int _pNFrames; // Number of neutral frames + long _pNWidth; // Width of neutral frames + BYTE *_pWAnim[8]; // Walk anims + int _pWFrames; // Number of walk frames + long _pWWidth; // Width of walk frames + BYTE *_pAAnim[8]; // Attack anims + int _pAFrames; // Number of attack frames + long _pAWidth; // Width of attack frames + int _pAFNum; // Which frame to check for attack on + BYTE *_pLAnim[8]; // Lightning Spell anims + BYTE *_pFAnim[8]; // Fire Spell anims + BYTE *_pTAnim[8]; // Misc Spell anims + int _pSFrames; // Number of spell frames + long _pSWidth; // Width of spell frames + int _pSFNum; // Which frame to cast spell on + BYTE *_pHAnim[8]; // Got Hit anims + int _pHFrames; // Number of got hit frames + long _pHWidth; // Width of got hit frames + BYTE *_pDAnim[8]; // Death anims + int _pDFrames; // Number of death frames + long _pDWidth; // Width of death frames + BYTE *_pBAnim[8]; // Block anims + int _pBFrames; // Number of block frames + long _pBWidth; // Width of block frames + + ItemStruct InvBody[NUM_INVLOC]; + ItemStruct InvList[MAXINV]; + int _pNumInv; + char InvGrid[MAXINV]; + ItemStruct SpdList[MAXSPD]; + ItemStruct HoldItem; // Item in transit + + int _pIMinDam; // Min damage from all items + int _pIMaxDam; // Max damage from all items + int _pIAC; // AC bonus from all items + int _pIBonusDam; // Added to damage after calced (%) + int _pIBonusToHit; // Added to hit percent + int _pIBonusAC; // Added to AC + int _pIBonusDamMod; // Added to damage after calced (number) + __int64 _pISpells; // item activated spells + long _pIFlags; // tot item flags from all items + int _pIGetHit; // When I gen hit, added to or subtracted from damage + char _pISplLvlAdd; // What to add to each spell level + char _pISplCost; // % modifier to spell cost + int _pISplDur; // % modifier to spell duration + int _pIEnAc; + int _pIFMinDam; // Fire hit min damage + int _pIFMaxDam; // Fire hit min damage + int _pILMinDam; // Lightning hit min damage + int _pILMaxDam; // Lightning hit min damage + +/* BOOL _WarpActive; // If I am on the town level from a portal, this turns true. + int _WarpLevel; // Level Town portal was cast on + int _WarpLvlType; // Level type where warp occurred + BOOL _WarpSet; // Was it a set level? + int _WarpX; // Level X pos where warp occurred + int _WarpY; // Level Y pos where warp occurred */ + + int _pOilType; // Temp hold for oil creation + + + // these fields are to be used if more variables need to be added + // to the player structure so that the size won't change + BYTE pTownWarps; // Town warp flags for single player (drb 11/22) + BYTE pDungMsgs; // Dungeon phrases that the player says + BYTE pLvlLoad; + BYTE pHellfireMsgs; // Message slots for nest messages + BYTE bReserved5; + BYTE bReserved6; + BYTE bReserved7; + BYTE bReserved8; + + WORD _pReflectCount; // Number of reflected hits left. + WORD wReserved2; + WORD wReserved3; + WORD wReserved4; + WORD wReserved5; + WORD wReserved6; + WORD wReserved7; + WORD wReserved8; + + DWORD pDiabloKillLevel; // player killed Diablo at what level + DWORD _gnDifficulty; + DWORD _pIFlags2; + DWORD dwReserved4; + DWORD dwReserved5; + DWORD dwReserved6; + DWORD dwReserved7; + DWORD dwReserved8; + + // Anything below this will not be saved or sent during a sync + #define SAVE_PLAYER_SIZE offsetof(PlayerStruct,_pNData) + BYTE *_pNData; // Neutral anim memory + BYTE *_pWData; // Walk anim memory + BYTE *_pAData; // Attack anim memory + BYTE *_pLData; // Spell anim memory + BYTE *_pFData; // Spell anim memory + BYTE *_pTData; // Spell anim memory + BYTE *_pHData; // Got Hit anim memory + BYTE *_pDData; // Death anim memory + BYTE *_pBData; // Block anim memory +} PlayerStruct; + +// for compatiblity with existing code +#define HeadItem InvBody[INVLOC_HEAD] +#define BodyItem InvBody[INVLOC_BODY] +#define Ring1Item InvBody[INVLOC_RING1] +#define Ring2Item InvBody[INVLOC_RING2] +#define NeckItem InvBody[INVLOC_NECK] +#define Hand1Item InvBody[INVLOC_HAND1] +#define Hand2Item InvBody[INVLOC_HAND2] + + +extern DWORD glSeedTbl[NUMLEVELS]; +extern int gnLevelTypeTbl[NUMLEVELS]; +extern char *ClassStrTbl[NUM_CLASSES]; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +// pjw.patch1.start +// extern PlayerStruct plr[MAX_PLRS]; +extern PlayerStruct * plr; +// pjw.patch1.end + +extern int myplr; +extern int pholdx, pholdy; +extern int MaxStats[NUM_CLASSES][4]; + +extern int deathdelay; +extern BOOL deathflag; +extern BOOL gbValidSaveFile; +extern BOOL gbSaveFileExists; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitPlrGFXMem(int); +void LoadPlrGFX(int,DWORD); +void InitPlayerGFX(int); +void FreePlayerGFX(int); +void SetPlrAnims(int); + +void InitPlayer(int, BOOL); +void InitMultiView(); +void ProcessPlayers(); +int PlrGetDirXY(int, int, int); + +void StartSpell(int, int, int, int); +void StartPlrKill(int, BOOL); +void SyncPlrKill(int, BOOL); +void StartPlrHit(int, int, BOOL); +void StartPlrBlock(int, int); +void StartNewLvl(int, int, int); +void StartWarpLvl(int, int); +void RestartTownLvl(int); + +void CreatePlayer(int, char); + +void CreateMyPacket(); +void ProcessPackets(); + +void AddPlrExperience(int, int, long); +void AddPlrMonstExper(int, long, char); + +void SyncInitPlr(int); + +void ClrPlrPath(int); +BOOL PosOkPlayer(int, int, int); +void MakePlrPath(int, int, int, BOOL); +void CheckPlrSpell(); + +void PlrClrTrans(int, int); +void PlrDoTrans(int, int); + +void ModifyPlrStr(int, int); +void ModifyPlrMag(int, int); +void ModifyPlrDex(int, int); +void ModifyPlrVit(int, int); + +void SetPlayerHitPoints(int pnum, int newhp); +void SetPlrStr(int p, int v); +void SetPlrMag(int p, int v); +void SetPlrDex(int p, int v); +void SetPlrVit(int p, int v); + +void DropHalfPlayersGold(int pnum); +extern void StripTopGold(int pnum); + +void InitDungMsgs(int pnum); +void PlayDungMsgs(); + +void CheckStats(int p); + +void FixPlrWalkTags(int pnum); +void FixPlayerLocation(int pnum,int bDir); +void SetPlayerOld(int pnum); + +int GetMaxStr(int /* class */); +int GetMaxMag(int /* class */); +int GetMaxDex(int /* class */); diff --git a/src/PLRMSG.CPP b/src/PLRMSG.CPP new file mode 100644 index 0000000..eecbd76 --- /dev/null +++ b/src/PLRMSG.CPP @@ -0,0 +1,214 @@ +//****************************************************************** +// plrmsg.cpp +//****************************************************************** + +#include "diablo.h" +#pragma hdrstop +#include "msg.h" +#include "engine.h" +#include "scrollrt.h" +#include "control.h" +#include "inv.h" +#include "quests.h" +#include "gendung.h" +#include "items.h" +#include "player.h" + + +//****************************************************************** +// private +//****************************************************************** +typedef struct TMsg { + long lMsgTime; + BYTE bPlr; + // a little padding for "(level %d): " and stuff + char str[MAX_SEND_STR_LEN + PLR_NAME_LEN + 32]; +} TMsg; + + +#define MAX_MSGS 8 +#define MAX_MSGS_MASK (MAX_MSGS-1) +static TMsg sgMsgs[MAX_MSGS]; +static BYTE sgbNextMsg; + +#define MSG_TIME 10000 // milliseconds +#define MSG_XOFF 10 +#define MSG_YOFF 70 +#define MSG_YFONT 10 +#define MSG_YDELTA ((GAMEY - MSG_YOFF) / MAX_MSGS) +#define MAX_MSG_LINES 3 + + +//****************************************************************** +//****************************************************************** +void plrmsg_hold(BOOL bStart) { + static long slStartTime; + + // save starting time + if (bStart) { + slStartTime = - (long) GetTickCount(); + } + else { + // calculate hold interval + slStartTime += (long) GetTickCount(); + TMsg * pMsg = sgMsgs; + for (int i = MAX_MSGS; i--; pMsg++) + pMsg->lMsgTime += slStartTime; + } +} + + +//****************************************************************** +//****************************************************************** +void sysmsg_add_string(const char * pszMsg) { + app_assert(pszMsg); + TMsg * pMsg = &sgMsgs[sgbNextMsg++]; + sgbNextMsg &= MAX_MSGS_MASK; + + pMsg->bPlr = MAX_PLRS; + pMsg->lMsgTime = (long) GetTickCount(); + + strncpy(pMsg->str,pszMsg,sizeof(pMsg->str)); + pMsg->str[sizeof(pMsg->str) - 1] = 0; +} + + +//****************************************************************** +//****************************************************************** +void __cdecl sysmsg_add(const char * pszFmt,...) { + app_assert(pszFmt); + TMsg * pMsg = &sgMsgs[sgbNextMsg++]; + sgbNextMsg &= MAX_MSGS_MASK; + + pMsg->bPlr = MAX_PLRS; + pMsg->lMsgTime = (long) GetTickCount(); + + va_list args; + va_start(args,pszFmt); + vsprintf(pMsg->str,pszFmt,args); + va_end(args); + app_assert(strlen(pMsg->str) < sizeof(pMsg->str)); +} + + +//****************************************************************** +//****************************************************************** +void plrmsg_add(int pnum, const char * pszStr) { + app_assert((DWORD) pnum < MAX_PLRS); + app_assert(pszStr); + + TMsg * pMsg = &sgMsgs[sgbNextMsg++]; + sgbNextMsg &= MAX_MSGS_MASK; + + pMsg->bPlr = (BYTE) pnum; + pMsg->lMsgTime = (long) GetTickCount(); + + app_assert(strlen(plr[pnum]._pName) < PLR_NAME_LEN); + app_assert(strlen(pszStr) < MAX_SEND_STR_LEN); + sprintf(pMsg->str,"%s (lvl %d): %s",plr[pnum]._pName,plr[pnum]._pLevel,pszStr); +} + + +//****************************************************************** +//****************************************************************** +void plrmsg_update() { + +#if 0 + // debugging + static DWORD d = 0; + static long lTime = 0; + if ((long) GetTickCount() - lTime > 2000) { + plrmsg_add(myplr,strGetError(d++)); + lTime = (long) GetTickCount(); + } +#endif + + TMsg * pMsg = sgMsgs; + long lCurrTime = (long) GetTickCount(); + for (int i = MAX_MSGS; i--; pMsg++) { + if (lCurrTime - pMsg->lMsgTime > MSG_TIME) + pMsg->str[0] = 0; + } +} + + +//****************************************************************** +//****************************************************************** +void plrmsg_init() { + ZeroMemory(&sgMsgs[0],sizeof(sgMsgs)); + sgbNextMsg = 0; +} + + +//****************************************************************** +//****************************************************************** +static void draw_str(DWORD x,DWORD y,DWORD wdt,const char * pszStr,char cColor) { + + DWORD dwLines = 0; + while (*pszStr) { + // calc offset into draw buffer + DWORD dwOffset = nBuffWTbl[y] + x; + + // calculate maximum wrappable line + DWORD dwLineWdt = 0; + const char * pszLine = pszStr; + const char * pszEOL = pszStr; + while (1) { + if (! *pszLine) { + pszEOL = pszLine; + break; + } + BYTE c = char2print(*pszLine++); + c = fonttrans[c]; + dwLineWdt += fontkern[c] + 1; + if (! c) + pszEOL = pszLine; + else if (dwLineWdt >= wdt) + break; + } + + // draw line + while (pszStr < pszEOL) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + if (c) DrawPanelFont(dwOffset,c,cColor); + dwOffset += fontkern[c] + 1; + } + + // move down a line + y += MSG_YFONT; + + if (++dwLines == MAX_MSG_LINES) break; + } +} + + +//****************************************************************** +//****************************************************************** +void plrmsg_draw() { + static const char scColorTbl[MAX_PLRS + 1] = { + ICOLOR_WHITE, + ICOLOR_WHITE, + ICOLOR_WHITE, + ICOLOR_WHITE, + ICOLOR_GOLD + }; + + DWORD x = MSG_XOFF + (BUFFERX - TOTALX) /2 ; + DWORD y = MSG_YOFF + 160; + DWORD wdt = TOTALX - MSG_XOFF*2; + if (chrflag || questlog) { + if (invflag || sbookflag) return; + x += TOTALX / 2; + wdt -= TOTALX / 2; + } + else if (invflag || sbookflag) { + wdt -= TOTALX / 2; + } + + TMsg * pMsg = sgMsgs; + for (int i = MAX_MSGS; i--; pMsg++,y += MSG_YDELTA) { + if (! pMsg->str[0]) continue; + draw_str(x,y,wdt,pMsg->str,scColorTbl[pMsg->bPlr]); + } +} diff --git a/src/PORTAL.CPP b/src/PORTAL.CPP new file mode 100644 index 0000000..b3eb99c --- /dev/null +++ b/src/PORTAL.CPP @@ -0,0 +1,256 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Triggers file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "portal.h" +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "misdat.h" +#include "missiles.h" +#include "effects.h" +#include "msg.h" +#include "lighting.h" + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +PortalStruct portal[MAXPORTAL]; + +int WarpDropX[MAXPORTAL] = { 57, 59, 61, 63 }; +int WarpDropY[MAXPORTAL] = { 40, 40, 40, 40 }; + +int portalindex; // current portal in use for myplr + +/*-----------------------------------------------------------------------** +** externs +**-----------------------------------------------------------------------*/ +void SetMissDir(int mi, int dir); +void DeleteMissile(int mi, int i); +BOOL delta_portal_inited(int i); + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitPortals() +{ + for (int i = 0; i < MAXPORTAL; i++) { + // Check to see if needs initing or parsed from level delta + if (delta_portal_inited(i)) + portal[i].open = FALSE; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SyncPortal(int i, BOOL open, int x, int y, int level, int ltype) +{ + app_assert((DWORD)i < MAXPORTAL); + portal[i].open = open; + portal[i].x = x; + portal[i].y = y; + portal[i].level = level; + portal[i].ltype = ltype; + portal[i].setlvl = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void AddWarpMissile(int i, int x, int y) +{ + // Don't play sound when loading level + missiledata[MIT_TOWN].mlSFX = -1; + + // Fix because portal cant be drawn on top of each other + dMissile[x][y] = 0; + + // Put in map and activate + int mi = AddMissile(0, 0, x, y, 0, MIT_TOWN, MI_ENEMYMONST, i, 0, 0); + + //check if AddMissile unsuccessful + if (mi == -1) + return; //too many missiles already, so quit + + // Force open + SetMissDir(mi, 1); + + // Give it a lightsource +//DL - 11/9/97 +// This is a serious bug. Under certain situations, missile[i] will be +// uninitialized, causing coordinate (0, 0) to be passed to AddLight(). +// When the light is processed later, and the radius is subtracted from +// the (0, 0) coordinate, the light table will be written to with negative +// indicies, causing an array underwrite. This was causing a crash on the +// Mac because it was overwriting the memory block header, trashing the +// application's heap. I don't know what is getting overwritten on the PC +// version. An example of when this will happen is if player 1 creates a +// new game, and player 2 joins it. Both players go to level 1. Player 2 +// casts town portal (with cheats on). On player 1's machine, +// AddWarpMissile( will be called with i = 1 (player 2's player index). +// Since there are no missles yet, AddMissile() will use missle index 0, so +// mi wil be 0. But since i is 1, AddLight() will be passed the coordinates +// of missle[1], which doesn't exist, so its coordinates are undefined. In +// this case, they are uninitialized, so they are zero. + +// if (currlevel != 0) missile[i]._mlid = AddLight(missile[i]._mix, missile[i]._miy, 15); + if (currlevel != 0) missile[mi]._mlid = AddLight(missile[mi]._mix, missile[mi]._miy, 15); + + // play sound while in dungeon + missiledata[MIT_TOWN].mlSFX = LS_SENTINEL; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SyncPortals() +{ + // Add the warp fields + for (int i = 0; i < MAXPORTAL; i++) { + if (portal[i].open) { + if (currlevel == 0) { + AddWarpMissile(i, WarpDropX[i], WarpDropY[i]); + } else { + if (! setlevel) { + if (portal[i].level == currlevel) AddWarpMissile(i, portal[i].x, portal[i].y); + } else { + if (portal[i].level == setlvlnum) AddWarpMissile(i, portal[i].x, portal[i].y); + } + } + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AddInTownPortal(int i) +{ + AddWarpMissile(i, WarpDropX[i], WarpDropY[i]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ActivatePortal(int i, int x, int y, int lvl, int lvltype, BOOL sp) +{ + app_assert((DWORD)i < MAXPORTAL); + portal[i].open = TRUE; + if (lvl != 0) { + portal[i].x = x; + portal[i].y = y; + portal[i].level = lvl; + portal[i].ltype = lvltype; + portal[i].setlvl = sp; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DeactivatePortal(int i) +{ + app_assert((DWORD)i < MAXPORTAL); + portal[i].open = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL PortalOnLevel(int i) +{ + app_assert((DWORD)i < MAXPORTAL); + if (portal[i].level == currlevel) return(TRUE); + if (currlevel == 0) return(TRUE); + else return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void RemovePortalMissile(int id) +{ + int i, mi; + + // Remove current portal + for (i = 0; i < nummissiles; i++) { + mi = missileactive[i]; + if ((missile[mi]._mitype == MIT_TOWN) && (missile[mi]._misource == id)) { + dFlags[missile[mi]._mix][missile[mi]._miy] &= BFMASK_MISSILE; + dMissile[missile[mi]._mix][missile[mi]._miy] = 0; + if (portal[id].level != 0) AddUnLight(missile[mi]._mlid); + DeleteMissile(mi, i); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void SetCurrentPortal(int p) +{ + portalindex = p; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void GetPortalLevel() { + if (currlevel) { + setlevel = FALSE; + currlevel = 0; + plr[myplr].plrlevel = 0; + leveltype = 0; + return; + } + app_assert((DWORD)portalindex < MAXPORTAL); + if (portal[portalindex].setlvl) { + setlevel = TRUE; + setlvlnum = portal[portalindex].level; + currlevel = portal[portalindex].level; + plr[myplr].plrlevel = setlvlnum; + leveltype = portal[portalindex].ltype; + } + else { + setlevel = FALSE; + currlevel = portal[portalindex].level; + plr[myplr].plrlevel = currlevel; + leveltype = portal[portalindex].ltype; + } + if (portalindex == myplr) { + NetSendCmd(TRUE, CMD_DEACTIVATEPORTAL); + DeactivatePortal(portalindex); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void GetPortalLvlPos() +{ + app_assert((DWORD)portalindex < MAXPORTAL); + if (!currlevel) { + ViewX = WarpDropX[portalindex] + 1; + ViewY = WarpDropY[portalindex] + 1; + return; + } + ViewX = portal[portalindex].x; + ViewY = portal[portalindex].y; + if (portalindex != myplr) { + ViewX++; + ViewY++; + } +} + diff --git a/src/PORTAL.H b/src/PORTAL.H new file mode 100644 index 0000000..ad07b69 --- /dev/null +++ b/src/PORTAL.H @@ -0,0 +1,53 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXPORTAL 4 // Must be the same as MAX_PLRS! + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + BOOL open; + int x; + int y; + int level; + int ltype; + BOOL setlvl; +} PortalStruct; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern PortalStruct portal[MAXPORTAL]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitPortals(); +void SyncPortals(); +void AddInTownPortal(int i); + +void ActivatePortal(int i, int x, int y, int lvl, int lvltype, BOOL sp); +void DeactivatePortal(int i); + +void SetCurrentPortal(int p); + +void GetPortalLvlPos(); +void GetPortalLevel(); + +BOOL PortalOnLevel(int i); +void RemovePortalMissile(int i); diff --git a/src/QUESTS.CPP b/src/QUESTS.CPP new file mode 100644 index 0000000..741c8e2 --- /dev/null +++ b/src/QUESTS.CPP @@ -0,0 +1,1115 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Quests file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/QUESTS.CPP 3 1/23/97 4:51p Vdwel $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "quests.h" +#include "gendung.h" +#include "engine.h" +#include "control.h" +#include "items.h" +#include "objects.h" +#include "objdat.h" +#include "player.h" +#include "monster.h" +#include "monstdat.h" +#include "drlg_l1.h" +#include "stores.h" +#include "scrollrt.h" +#include "minitext.h" +#include "textdat.h" +#include "effects.h" +#include "cursor.h" +#include "palette.h" +#include "msg.h" +#include "multi.h" +#include "doom.h" +#include "missiles.h" +#include "trigs.h" +#include "towners.h" +#include "setmaps.h" + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL delta_quest_inited(int i); + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +QuestStruct quests[MAXQUESTS]; + +int ReturnLvlX, ReturnLvlY, ReturnLvl, ReturnLvlT; +BOOL rporttest; +BOOL questlog; +int qspin, qline, numqlines, qtopline; +int qlist[MAXQUESTS]; // index list of displayed quests in questlog +int qfade; + + +BYTE *pQLogCel; + +#if CHEATS +int questcheat = -1; // TEMP!!!!!! drb +#endif + +/*-----------------------------------------------------------------------* +** private +**-----------------------------------------------------------------------*/ +// level, multi lvl, lvl type, id, % chance, setlevel #, multi flag, qmsg, string +QuestData questlist[] = { + // Contained + { 5, -1, 255, Q_ROCK, 100, 0, 0, TXT_INFRABS1, "The Magic Rock" }, // 0 + { 9, -1, 255, Q_BKMUSHRM, 100, 0, 0, TXT_BLKMW1, "Black Mushroom" }, // 1 + { 4, -1, 255, Q_GARBUD, 100, 0, 0, TXT_GARB1, "Gharbad The Weak" }, // 2 + { 8, -1, 255, Q_ZHAR, 100, 0, 0, TXT_ZHAR1, "Zhar the Mad" }, // 3 + { 14, -1, 255, Q_VEIL, 100, 0, 0, TXT_VEIL1, "Lachdanan" }, // 4 + { 15, -1, 255, Q_DIABLO, 100, 0, QFLAG_MULTI, TXT_VBST3, "Diablo" }, // 5 + // Internal Set Pieces + { 2, 2, 255, Q_BUTCHER, 100, 0, QFLAG_MULTI, TXT_BUTCH1, "The Butcher" }, // 6 + { 4, -1, 255, Q_LTBANNER, 100, 0, 0, TXT_BOLTO1, "Ogden's Sign" }, // 7 + { 7, -1, 255, Q_BLIND, 100, 0, 0, TXT_WARBLIND, "Halls of the Blind" }, // 8 + { 5, -1, 255, Q_BLOOD, 100, 0, 0, TXT_WARBLOOD, "Valor" }, // 9 + { 10, -1, 255, Q_ANVIL, 100, 0, 0, TXT_ANVILBS1, "Anvil of Fury" }, // 10 + { 13, -1, 255, Q_WARLORD, 100, 0, 0, TXT_WARLORD, "Warlord of Blood" }, // 11 + // External Levels Maps + { 3, 3, 1, Q_SKELKING, 100, 1, QFLAG_MULTI, TXT_KINGTO1, "The Curse of King Leoric"},// 12 + { 2, -1, 3, Q_PWATER, 100, 4, 0, TXT_PWH1, "Poisoned Water Supply" }, // 13 + { 6, -1, 2, Q_SCHAMB, 100, 2, 0, TXT_WARBONE, "The Chamber of Bone" }, // 14 + { 15, 15, 1, Q_BETRAYER, 100, 5, QFLAG_MULTI, TXT_VBST1, "Archbishop Lazarus" }, // 15 + // New quests for Hellfire JKEQUEST + { 17, 17, 255, Q_CRYPTMAP, 100, 0, QFLAG_MULTI, TXT_CRYPTMAP7, "Grave Matters" }, // 16 + { 9, 9, 255, Q_FARMER, 100, 0, QFLAG_MULTI, TXT_FARMER1, "Farmer's Orchard" }, // 17 + { 17, -1, 255, Q_THEO, 100, 0, 0, TXT_THEO2, "Little Girl" }, // 18 + { 19, -1, 255, Q_TRADER, 100, 0, 0, TXT_TRADER1, "Wandering Trader" }, // 19 + { 17, 17, 255, Q_DEFILER, 100, 0, QFLAG_MULTI, TXT_DEFILER1, "The Defiler" }, // 20 + { 21, 21, 255, Q_NA_KRUL, 100, 0, QFLAG_MULTI, TXT_NA_KRUL1, "Na-Krul" }, // 21 + { 21, -1, 255, Q_CORNERSTONE, 100, 0, 0, TXT_CORNERSTONE1, "Cornerstone of the World"}, // 22 + { 9, 9, 255, Q_COWSUIT, 100, 0, QFLAG_MULTI, TXT_COWSUIT4, "The Jersey's Jersey" } // 23 +}; +#define ALLQUESTS (sizeof(questlist) / sizeof(questlist[0])) + +#define QUEST_OFFSETS 7 +static char questxoff[QUEST_OFFSETS] = { 0, -1, 0, -1, -2, -1, -2 }; +static char questyoff[QUEST_OFFSETS] = { 0, 0, -1, -1, -1, -2, -2 }; + +char *questtrigstr[] = { + "King Leoric's Tomb", + "The Chamber of Bone", + "Maze", + "A Dark Passage", + "Unholy Altar" +}; + +// Single player quest lists +int QuestGroup1[3] = { Q_BUTCHER, Q_LTBANNER, Q_GARBUD }; // 2 of 3 +int QuestGroup2[3] = { Q_BLIND, Q_ROCK, Q_BLOOD }; // 2 of 3 +int QuestGroup3[3] = { Q_BKMUSHRM, Q_ZHAR, Q_ANVIL }; // 2 of 3 +int QuestGroup4[2] = { Q_VEIL, Q_WARLORD }; // 1 of 2 + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitQuests() { + int i, gri, deltaq; + + if (gbMaxPlayers == 1) { + for (i = 0; i < MAXQUESTS; i++) + quests[i]._qactive = QUEST_NOTAVAIL; + } else { + for (i = 0; i < MAXQUESTS; i++) { + if (!(questlist[i]._qflags & QFLAG_MULTI)) + quests[i]._qactive = QUEST_NOTAVAIL; + } + } + + questlog = FALSE; + qspin = 1; + qfade = 0; + deltaq = 0; + for (i = 0; i < ALLQUESTS; i++) { + if (gbMaxPlayers > 1 && !(questlist[i]._qflags & QFLAG_MULTI)) continue; + + quests[i]._qtype = questlist[i]._qdtype; + if (gbMaxPlayers > 1) { + quests[i]._qlevel = questlist[i]._qdmultlvl; + if (! delta_quest_inited(deltaq)) { + quests[i]._qactive = QUEST_NOTACTIVE; + quests[i]._qvar1 = 0; + quests[i]._qlog = FALSE; + } + deltaq++; + } else { + quests[i]._qactive = QUEST_NOTACTIVE; + quests[i]._qlevel = questlist[i]._qdlvl; + quests[i]._qvar1 = 0; + quests[i]._qlog = FALSE; + } + quests[i]._qslvl = questlist[i]._qslvl; + quests[i]._qtx = 0; + quests[i]._qty = 0; + quests[i]._qidx = i; + quests[i]._qlvltype = questlist[i]._qlvlt; + quests[i]._qvar2 = 0; + quests[i]._qmsg = questlist[i]._qdmsg; + } + + // Random select quests + if (gbMaxPlayers == 1) { + SetRndSeed(glSeedTbl[15]); + if (random(0, 2)) quests[Q_PWATER]._qactive = QUEST_NOTAVAIL; + else quests[Q_SKELKING]._qactive = QUEST_NOTAVAIL; + gri = QuestGroup1[random(0, 3)]; + quests[gri]._qactive = QUEST_NOTAVAIL; + gri = QuestGroup2[random(0, 3)]; + quests[gri]._qactive = QUEST_NOTAVAIL; + gri = QuestGroup3[random(0, 3)]; + quests[gri]._qactive = QUEST_NOTAVAIL; + gri = QuestGroup4[random(0, 2)]; + quests[gri]._qactive = QUEST_NOTAVAIL; + } + +#if CHEATS + // New 12/01 drb + if (questcheat != -1) + quests[questcheat]._qactive = QUEST_NOTDONE; ///test area +#endif + + #if IS_VERSION(SHAREWARE) + for (i = 0; i < ALLQUESTS; i++) { + quests[i]._qactive = QUEST_NOTAVAIL; + } + #endif + +// additional inits for the quests (not to be messed with) + if (quests[Q_SKELKING]._qactive == QUEST_NOTAVAIL) quests[Q_SKELKING]._qvar2 = 2; + if (quests[Q_ROCK]._qactive == QUEST_NOTAVAIL) quests[Q_ROCK]._qvar2 = 2; + quests[Q_LTBANNER]._qvar1 = 1; // so the door is open to snotspil for the lame gamers (LAME!!!) + if (gbMaxPlayers != 1) quests[Q_BETRAYER]._qvar1 = 2; // so that betrayer is on level 15 +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CheckQuests() +{ +// no quests in shareware version +#if !IS_VERSION(SHAREWARE) + int i; + int rportx, rporty; + + if ((QuestStatus(Q_BETRAYER)) && (gbMaxPlayers != 1) && (quests[Q_BETRAYER]._qvar1 == 2)) { + AddObject(OBJ_ALTBOY, (setpc_x << 1) + DIRTEDGED2 + 4, (setpc_y << 1) + DIRTEDGED2 + 6); + quests[Q_BETRAYER]._qvar1 = 3; + NetSendCmdQuest(TRUE, Q_BETRAYER); + } + // If multiplayer return + if (gbMaxPlayers != 1) return; + + if ((currlevel == quests[Q_BETRAYER]._qlevel) && (!(setlevel)) && (quests[Q_BETRAYER]._qvar1 >= 2) + && ((quests[Q_BETRAYER]._qactive == QUEST_NOTDONE) || (quests[Q_BETRAYER]._qactive == QUEST_DONE))) { + if ((quests[Q_BETRAYER]._qvar2 == QS_VBRPOFF) || (quests[Q_BETRAYER]._qvar2 == QS_VBRP2)) { + rportx = (quests[Q_BETRAYER]._qtx<<1)+DIRTEDGED2; + rporty = (quests[Q_BETRAYER]._qty<<1)+DIRTEDGED2; + quests[Q_BETRAYER]._qtx = rportx; + quests[Q_BETRAYER]._qty = rporty; + AddMissile(rportx, rporty, rportx, rporty, 0, MIT_RPORTAL, MI_ENEMYMONST, myplr, 0, 0); + quests[Q_BETRAYER]._qvar2 = QS_VBRP1; + if (quests[Q_BETRAYER]._qactive == QUEST_NOTDONE) + quests[Q_BETRAYER]._qvar1 = 3; + } + } + if ((quests[Q_BETRAYER]._qactive == QUEST_DONE) && (setlevel && (setlvlnum == SL_VILEBETRAYER)) + && (quests[Q_BETRAYER]._qvar2 == QS_VBRP4)) { + AddMissile(35, 32, 35, 32, 0, MIT_RPORTAL, MI_ENEMYMONST, myplr, 0, 0); + quests[Q_BETRAYER]._qvar2 = QS_VBRP3; + } + if (setlevel) { + if ((setlvlnum == quests[Q_PWATER]._qslvl) && (quests[Q_PWATER]._qactive != QUEST_NOTACTIVE) && (leveltype == quests[Q_PWATER]._qlvltype)) { + if (nummonsters == 4 && quests[Q_PWATER]._qactive != QUEST_DONE) { + quests[Q_PWATER]._qactive = QUEST_DONE; + PlaySfxLoc(IS_QUESTDN, plr[myplr]._px, plr[myplr]._py); + LoadPalette("Levels\\L3Data\\L3pwater.pal"); + qfade = 32; + } + } + + if (qfade > 0) { + MeshLavaPalette(qfade); + qfade--; + } + + return; + } + + // only check quests in stand mode + if (plr[myplr]._pmode != PM_STAND) + return; + + for (i = 0; i < MAXQUESTS; i++) { + if ((currlevel == quests[i]._qlevel) && (quests[i]._qslvl != 0) && (quests[i]._qactive != QUEST_NOTAVAIL)) { + if ((plr[myplr]._px == quests[i]._qtx) && (plr[myplr]._py == quests[i]._qty)) { + if (quests[i]._qlvltype != 255) setlvltype = quests[i]._qlvltype; + StartNewLvl(myplr,WM_DIABSETLVL,quests[i]._qslvl); + } + } + } +#endif +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL ForceQuests() { +// no quests in shareware version +#if !IS_VERSION(SHAREWARE) + // If multiplayer return + if (gbMaxPlayers != 1) return(FALSE); + + for (int i = 0; i < MAXQUESTS; i++) { + if (i == Q_BETRAYER) continue; + if (currlevel != quests[i]._qlevel) continue; +// if (quests[i]._qactive != QUEST_NOTDONE) continue; + if (quests[i]._qslvl == 0) continue; + + int ql = quests[quests[i]._qidx]._qslvl - 1; + int qx = quests[i]._qtx; + int qy = quests[i]._qty; + for (int j = 0; j < QUEST_OFFSETS; j++) { + if (qx + questxoff[j] != cursmx) continue; + if (qy + questyoff[j] != cursmy) continue; + + sprintf(infostr, "To %s", questtrigstr[ql]); + cursmx = qx; + cursmy = qy; + return TRUE; + } + } +#endif + + return FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +BOOL QuestStatus(int i) { + if (setlevel) return FALSE; + app_assert((DWORD)i < MAXQUESTS); + if (currlevel != quests[i]._qlevel) return FALSE; + if (quests[i]._qactive == QUEST_NOTAVAIL) return FALSE; + if ((gbMaxPlayers != 1) && !(questlist[i]._qflags & QFLAG_MULTI)) return FALSE; + return TRUE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void CheckQuestKill(int m, BOOL sendmsg) +{ +// no quests in shareware version +#if !IS_VERSION(SHAREWARE) + + app_assert((DWORD)m < MAXMONSTERS); + + if (monster[m].MType->mtype == MT_SKING) { + quests[Q_SKELKING]._qactive = QUEST_DONE; + sfxdelay = 30; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR82; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE82; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE82; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK82; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD82; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN82; + #endif + if (sendmsg) NetSendCmdQuest(TRUE, Q_SKELKING); + } + else if (monster[m].MType->mtype == MT_CLEAVER) { + quests[Q_BUTCHER]._qactive = QUEST_DONE; + sfxdelay = 30; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR80; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE80; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE80; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK80; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD80; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN80; + #endif + if (sendmsg) NetSendCmdQuest(TRUE, Q_BUTCHER); + } + else if (monster[m].mName == UniqMonst[MU_GARBUD].mName) { + quests[Q_GARBUD]._qactive = QUEST_DONE; + sfxdelay = 30; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR61; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE61; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE61; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK61; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD61; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN61; + #endif + } + else if (monster[m].mName == UniqMonst[MU_ZHAR].mName) { + quests[Q_ZHAR]._qactive = QUEST_DONE; + sfxdelay = 30; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR62; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE62; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE62; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK62; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD62; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN62; + #endif + } + else if ((monster[m].mName == UniqMonst[MU_LAZARUS].mName ) && (gbMaxPlayers != 1)) { + int i,j; + quests[Q_BETRAYER]._qactive = QUEST_DONE; + quests[Q_BETRAYER]._qvar1 = 7; + sfxdelay = 30; + quests[Q_DIABLO]._qactive = QUEST_NOTDONE; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 370) { + if (quests[Q_BETRAYER]._qactive == QUEST_DONE) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; + } + } + } + } + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR83; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE83; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE83; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK83; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD83; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN83; + #endif + if (sendmsg) { + NetSendCmdQuest(TRUE, Q_BETRAYER); + NetSendCmdQuest(TRUE, Q_DIABLO); + } + } + else if ((monster[m].mName == UniqMonst[MU_LAZARUS].mName) && (gbMaxPlayers == 1)) { + quests[Q_BETRAYER]._qactive = QUEST_DONE; + sfxdelay = 30; + InitVPTriggers(); + quests[Q_BETRAYER]._qvar1 = 7; + quests[Q_BETRAYER]._qvar2 = QS_VBRP4; + quests[Q_DIABLO]._qactive = QUEST_NOTDONE; + AddMissile(35, 32, 35, 32, 0, MIT_RPORTAL, MI_ENEMYMONST, myplr, 0, 0); + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR83; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE83; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE83; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK83; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD83; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN83; + #endif + } + else if (monster[m].mName == UniqMonst[MU_WARLORD].mName) { + app_assert(gbMaxPlayers == 1); + quests[Q_WARLORD]._qactive = QUEST_DONE; + sfxdelay = 30; + if (plr[myplr]._pClass == CLASS_WARRIOR) sfxdnum = PS_WARR94; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) sfxdnum = PS_ROGUE94; + else if (plr[myplr]._pClass == CLASS_SORCEROR) sfxdnum = PS_MAGE94; + else if (plr[myplr]._pClass == CLASS_MONK) sfxdnum = PS_MONK94; + else if (plr[myplr]._pClass == CLASS_BARD) sfxdnum = PS_BARD94; + else if (plr[myplr]._pClass == CLASS_BARBARIAN) sfxdnum = PS_BARBARIAN94; + #endif + } +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void SetPostDungeon() +{ + int i,j; + + for (j = 0; j < MDMAXY; j++) { + for (i = 0; i < MDMAXX; i++) pdungeon[i][j] = dungeon[i][j]; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawButcher() +{ + int x, y; + + x = (setpc_x << 1) + DIRTEDGED2; + y = (setpc_y << 1) + DIRTEDGED2; + DRLG_RectTrans(x+3, y+3, x+10, y+10); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawSkelKing(int q, int x, int y) +{ + app_assert((DWORD)q < MAXQUESTS); + quests[q]._qtx = DIRTEDGED2 + (x << 1) + 12; + quests[q]._qty = DIRTEDGED2 + (y << 1) + 7; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawWarLord(int x, int y) +{ + int rw,rh; + int i,j; + byte *sp, *setp; + + setp = LoadFileInMemSig("Levels\\L4Data\\Warlord2.DUN",NULL,'QSTt'); + sp = setp; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_w = rw; + setpc_h = rh; + setpc_x = x; + setpc_y = y; + + app_assert((DWORD)(rw + x - 1) < MDMAXX); + app_assert((DWORD)(rh + y - 1) < MDMAXY); + for (j = y; j < (rh + y); j++) { + for (i = x; i < (rw + x); i++) { + dungeon[i][j] = *sp ? *sp : 6; + sp+=2; + } + } + DiabloFreePtr(setp); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawSChamber(int q, int x, int y) +{ + int i, j, rw, rh, xx, yy; + byte *sp, *setp; + + setp = LoadFileInMemSig("Levels\\L2Data\\Bonestr1.DUN",NULL,'QSTt'); + sp = setp; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_w = rw; + setpc_h = rh; + setpc_x = x; + setpc_y = y; + + app_assert((DWORD)(rw + x - 1) < MDMAXX); + app_assert((DWORD)(rh + y - 1) < MDMAXY); + for (j = y; j < (rh + y); j++) { + for (i = x; i < (rw + x); i++) { + dungeon[i][j] = *sp ? *sp : 3; + sp+=2; + } + } + + xx = DIRTEDGED2 + (x << 1) + 6; + yy = DIRTEDGED2 + (y << 1) + 7; + app_assert((DWORD)q < MAXQUESTS); + quests[q]._qtx = xx; + quests[q]._qty = yy; + DiabloFreePtr(setp); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawLTBanner(int x, int y) +{ + int rw,rh; + int i,j; + byte *sp, *setp; + + setp = LoadFileInMemSig("Levels\\L1Data\\Banner1.DUN",NULL,'QSTt'); + sp = setp; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_w = rw; + setpc_h = rh; + setpc_x = x; + setpc_y = y; + + app_assert((DWORD)(x+rw-1) < MDMAXX); + app_assert((DWORD)(y+rh-1) < MDMAXY); + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*sp) pdungeon[x+i][y+j] = *sp; + sp+=2; + } + } + DiabloFreePtr(setp); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawBlind(int x, int y) +{ + int rw,rh; + int i,j; + byte *sp, *setp; + + setp = LoadFileInMemSig("Levels\\L2Data\\Blind1.DUN",NULL,'QSTt'); + sp = setp; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_x = x; + setpc_y = y; + setpc_w = rw; + setpc_h = rh; + + app_assert((DWORD)(x+rw-1) < MDMAXX); + app_assert((DWORD)(y+rh-1) < MDMAXY); + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*sp) pdungeon[x+i][y+j] = *sp; + sp+=2; + } + } + DiabloFreePtr(setp); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawBlood(int x, int y) +{ + int rw,rh; + int i,j; + byte *sp, *setp; + + setp = LoadFileInMemSig("Levels\\L2Data\\Blood2.DUN",NULL,'QSTt'); + sp = setp; + rw = *sp; + sp+=2; + rh = *sp; + sp+=2; + + setpc_x = x; + setpc_y = y; + setpc_w = rw; + setpc_h = rh; + + app_assert((DWORD)(rw + x - 1) < MDMAXX); + app_assert((DWORD)(rh + y - 1) < MDMAXY); + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + if (*sp) dungeon[x+i][y+j] = *sp; + //else dungeon[x+i][x+j] = 3; + sp+=2; + } + } + + DiabloFreePtr(setp); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DRLG_CheckQuests(int x, int y) +{ + int i; + + for (i = 0; i < MAXQUESTS; i++) { + if (!QuestStatus(i)) + continue; + switch (quests[i]._qtype) { + case Q_BUTCHER: + DrawButcher(); + break; + case Q_SKELKING : + DrawSkelKing(i, x, y); + break; + case Q_SCHAMB : + DrawSChamber(i, x, y); + break; + case Q_BLIND : + DrawBlind(x, y); + break; + case Q_BLOOD : + DrawBlood(x,y); + break; + case Q_LTBANNER : + DrawLTBanner(x, y); + break; + case Q_WARLORD: + DrawWarLord(x, y); + break; + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetReturnLvlPos() +{ + switch (setlvlnum) { + case SL_SKELKING: // SKing + ReturnLvlX = quests[Q_SKELKING]._qtx + 1; + ReturnLvlY = quests[Q_SKELKING]._qty; + ReturnLvl = quests[Q_SKELKING]._qlevel; + ReturnLvlT = 1; + break; + case SL_BONECHAMB: // Bone chamber + ReturnLvlX = quests[Q_SCHAMB]._qtx + 1; + ReturnLvlY = quests[Q_SCHAMB]._qty; + ReturnLvl = quests[Q_SCHAMB]._qlevel; + ReturnLvlT = 2; + break; + case SL_POISONWATER: // Poison Water + ReturnLvlX = quests[Q_PWATER]._qtx; + ReturnLvlY = quests[Q_PWATER]._qty + 1; + ReturnLvl = quests[Q_PWATER]._qlevel; + ReturnLvlT = 1; + break; + case SL_VILEBETRAYER: // Vile Betrayer + ReturnLvlX = quests[Q_BETRAYER]._qtx + 1; + ReturnLvlY = quests[Q_BETRAYER]._qty - 1; + ReturnLvl = quests[Q_BETRAYER]._qlevel; + ReturnLvlT = 4; + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void GetReturnLvlPos() +{ + if (quests[Q_BETRAYER]._qactive == QUEST_DONE) quests[Q_BETRAYER]._qvar2 = QS_VBRP2; + ViewX = ReturnLvlX; + ViewY = ReturnLvlY; + currlevel = ReturnLvl; + leveltype = ReturnLvlT; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ResyncMPQuests() +{ +// no quests in shareware version +#if !IS_VERSION(SHAREWARE) + if (quests[Q_SKELKING]._qactive == QUEST_NOTACTIVE) { + if ((currlevel >= (quests[Q_SKELKING]._qlevel - 1)) && (currlevel <= (quests[Q_SKELKING]._qlevel + 1))) { + quests[Q_SKELKING]._qactive = QUEST_NOTDONE; + NetSendCmdQuest(TRUE, Q_SKELKING); + } + } + if (quests[Q_BUTCHER]._qactive == QUEST_NOTACTIVE) { + if ((currlevel >= (quests[Q_BUTCHER]._qlevel - 1)) && (currlevel <= (quests[Q_BUTCHER]._qlevel + 1))) { + quests[Q_BUTCHER]._qactive = QUEST_NOTDONE; + NetSendCmdQuest(TRUE, Q_BUTCHER); + } + } + if (quests[Q_BETRAYER]._qactive == QUEST_NOTACTIVE) { + if (currlevel == (quests[Q_BETRAYER]._qlevel - 1)) { + quests[Q_BETRAYER]._qactive = QUEST_NOTDONE; + NetSendCmdQuest(TRUE, Q_BETRAYER); + } + } + if (QuestStatus(Q_BETRAYER)) + AddObject(OBJ_ALTBOY, (setpc_x << 1) + DIRTEDGED2 + 4, (setpc_y << 1) + DIRTEDGED2 + 6); + + // Add Multi player Hellfire quests here + if (quests[Q_CRYPTMAP]._qactive == QUEST_NOTACTIVE) + if (currlevel == (quests[Q_CRYPTMAP]._qlevel - 1)) { + quests[Q_CRYPTMAP]._qactive = QUEST_NOTDONE; + NetSendCmdQuest(TRUE, Q_CRYPTMAP); + } + + if (quests[Q_DEFILER]._qactive == QUEST_NOTACTIVE) + if (currlevel == (quests[Q_DEFILER]._qlevel - 1)) { + quests[Q_DEFILER]._qactive = QUEST_NOTDONE; + NetSendCmdQuest(TRUE, Q_DEFILER); + } + + if (quests[Q_NA_KRUL]._qactive == QUEST_NOTACTIVE) + if (currlevel == (quests[Q_NA_KRUL]._qlevel - 1)) { + quests[Q_NA_KRUL]._qactive = QUEST_NOTDONE; + NetSendCmdQuest(TRUE, Q_NA_KRUL); + } + + if (quests[Q_COWSUIT]._qactive == QUEST_NOTACTIVE) + if (currlevel == (quests[Q_COWSUIT]._qlevel - 1)) { + quests[Q_COWSUIT]._qactive = QUEST_NOTDONE; + NetSendCmdQuest(TRUE, Q_COWSUIT); + } + +#endif + +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void ResyncQuests() +{ +// no quests in shareware version +#if !IS_VERSION(SHAREWARE) + + int i, tren; + + // for Poison Water quest only - inits the poison/not poison water pal + if (setlevel) { + if ((setlvlnum == quests[Q_PWATER]._qslvl) && (quests[Q_PWATER]._qactive != QUEST_NOTACTIVE) && (leveltype == quests[Q_PWATER]._qlvltype)) { + if (quests[Q_PWATER]._qactive == QUEST_DONE) LoadPalette("Levels\\L3Data\\L3pwater.pal"); + else LoadPalette("Levels\\L3Data\\L3pfoul.pal"); + for (i = 0; i <= 32; i++) { + MeshLavaPalette(i); + } + } + } + + if (QuestStatus(Q_LTBANNER)) { + if (quests[Q_LTBANNER]._qvar1 == 1) { + ObjChangeMapResync(setpc_x + setpc_w - 2, setpc_y + setpc_h - 2, setpc_x + setpc_w+1, setpc_y + setpc_h+1); + } + if (quests[Q_LTBANNER]._qvar1 == 2) { + ObjChangeMapResync(setpc_x + setpc_w - 2, setpc_y + setpc_h - 2, setpc_x + setpc_w+1, setpc_y + setpc_h+1); + ObjChangeMapResync(setpc_x, setpc_y, setpc_x+(setpc_w>>1)+2, setpc_y+(setpc_h>>1)-2); + for (i = 0; i < numobjects; i++) SyncObjectAnim(objectactive[i]); + tren = TransVal; + TransVal = 9; + DRLG_MRectTrans(setpc_x, setpc_y, setpc_x+(setpc_w>>1)+4, setpc_y+(setpc_h>>1)); + TransVal = tren; + } + if (quests[Q_LTBANNER]._qvar1 == 3) { + ObjChangeMapResync(setpc_x, setpc_y, setpc_x + setpc_w + 1, setpc_y + setpc_h + 1); + for (i = 0; i < numobjects; i++) SyncObjectAnim(objectactive[i]); + tren = TransVal; + TransVal = 9; + DRLG_MRectTrans(setpc_x, setpc_y, setpc_x+(setpc_w>>1)+4, setpc_y+(setpc_h>>1)); + TransVal = tren; + } + } + + if (currlevel == quests[Q_BKMUSHRM]._qlevel) { + if (quests[Q_BKMUSHRM]._qactive == QUEST_NOTACTIVE + && quests[Q_BKMUSHRM]._qvar1 == QS_INIT) + { + SpawnQuestItem(IDI_FUNGALTM, 0,0,5, ISEL_FLR); + quests[Q_BKMUSHRM]._qvar1 = QS_TOMESPAWNED; + } + else if (quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE) + { + if (quests[Q_BKMUSHRM]._qvar1 >= QS_MUSHGIVEN) // Mushroom was given to Witch + { + Qtalklist[TWN_HEALER][Q_BKMUSHRM] = TXT_BLKMH1; + Qtalklist[TWN_WITCH][Q_BKMUSHRM] = -1; + } + else if (quests[Q_BKMUSHRM]._qvar1 >= QS_BRAINGIVEN) // Brain was given to Healer + { + Qtalklist[TWN_HEALER][Q_BKMUSHRM] = -1; + } + } + } + if (currlevel == (quests[Q_VEIL]._qlevel + 1)) { + if ((quests[Q_VEIL]._qactive == QUEST_NOTDONE) && (quests[Q_VEIL]._qvar1 == 0)) { + quests[Q_VEIL]._qvar1 = 1; + SpawnQuestItem(IDI_GLDNELIX, 0,0,5, ISEL_FLR); + } + } + + if (setlevel && (setlvlnum == SL_VILEBETRAYER)) { + if (quests[Q_BETRAYER]._qvar1 >= 4) + ObjChangeMapResync(1, 11, 20, 18); + if (quests[Q_BETRAYER]._qvar1 >= 6) + ObjChangeMapResync(1, 18, 20, 24); + if (quests[Q_BETRAYER]._qvar1 >= 7) + InitVPTriggers(); + for (i = 0; i < numobjects; i++) SyncObjectAnim(objectactive[i]); + } + +// rmw.patch1.start.1/23/97 +// if ((currlevel == quests[Q_BETRAYER]._qlevel) && (quests[Q_BETRAYER]._qvar2 == QS_VBRP1) + if ((currlevel == quests[Q_BETRAYER]._qlevel) && !setlevel + && ((quests[Q_BETRAYER]._qvar2 == QS_VBRP1) || (quests[Q_BETRAYER]._qvar2 >= QS_VBRP3)) +// rmw.patch1.end.1/23/97 + && ((quests[Q_BETRAYER]._qactive == QUEST_NOTDONE) || (quests[Q_BETRAYER]._qactive == QUEST_DONE))) { + quests[Q_BETRAYER]._qvar2 = QS_VBRP2; + } + +#endif +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +void DrawQLBack() +{ + DrawCel(408, 487, pSTextBoxCels, 1, 271); + + __asm { + mov edi,dword ptr [pBuffer] + add edi,372123 + + xor eax,eax + mov edx,148 +_YLp: mov ecx,132 +_XLp1: stosb + inc edi + loop _XLp1 + stosb + sub edi,1033 + mov ecx,132 +_XLp2: inc edi + stosb + loop _XLp2 + sub edi,1032 + dec edx + jnz _YLp + mov ecx,132 +_XLp3: stosb + inc edi + loop _XLp3 + stosb + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PrintQLString(int x, int y, BOOL cjustflag, char str[], char col) +{ + long boffset; + int sl,i,w,tw,xx,yy; + + yy = SStringY[y]; + boffset = nBuffWTbl[yy + 204] + x + 96; + sl = strlen(str); + w = 0; + if (cjustflag) { + tw = 0; + for (i = 0; i < sl; i++) { + BYTE c = char2print(str[i]); + c = fonttrans[c]; + tw += fontkern[c]+1; + } + if (tw < 257) w = (257 - tw) >> 1; + boffset += w; + } + if (qline == y) { + if (cjustflag) xx = x + w + 76; + else xx = x + 76; + DrawCel(xx, yy + 205, pSTextSpinCels, qspin, 12); + } + for (i = 0; i < sl; i++) { + BYTE c = char2print(str[i]); + c = fonttrans[c]; + w += fontkern[c]+1; + if ((c != 0) && (w <= 257)) DrawPanelFont(boffset, c, col); + boffset += fontkern[c]+1; + } + if (qline == y) { + if (cjustflag) xx = x + w + 100; + else xx = 340 - x; + DrawCel(xx, yy + 205, pSTextSpinCels, qspin, 12); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* + +void DrawQLLine(int y) +{ + long doffset; + + doffset = nBuffWTbl[SStringY[y] + 198] + 410; + __asm { + mov esi,dword ptr [pBuffer] + mov edi,esi + add esi,142170 + add edi,dword ptr [doffset] + + mov ebx,502 + + mov edx,3 +_YLp: mov ecx,66 + rep movsd + movsw + add esi,ebx + add edi,ebx + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawQuestLog() +{ + int i, l, q; + + //DrawQLBack(); + PrintQLString(0, 2, TRUE, "Quest Log", ICOLOR_GOLD); + //DrawQLLine(5); + + DrawCel(64, 511, pQLogCel, 1, 320); + + l = qtopline; + for (i = 0; i < numqlines; i++) { + q = qlist[i]; + PrintQLString(0, l , TRUE, questlist[q]._qlstr, ICOLOR_WHITE); + l+=2; + } + PrintQLString(0, 22, TRUE, "Close Quest Log", ICOLOR_WHITE); + qspin = (qspin & 0x7) + 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void StartQuestlog() +{ + int i; + + numqlines = 0; + for (i = 0; i < ALLQUESTS; i++) { + if ((quests[i]._qactive == QUEST_NOTDONE) && (quests[i]._qlog)) { + qlist[numqlines] = i; + numqlines++; + } + } + if (numqlines > 5) qtopline = 5 - (numqlines >> 1); + else qtopline = 8; + if (numqlines == 0) qline = 22; + else qline = qtopline; + questlog = TRUE; + qspin = 1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void QuestlogUp() +{ + if (numqlines != 0) { + if (qline == qtopline) qline = 22; + else { + if (qline == 22) qline = ((numqlines-1) << 1) + qtopline; + else qline -= 2; + } + PlaySFX(IS_TITLEMOV); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void QuestlogDown() +{ + if (numqlines != 0) { + if (qline == 22) qline = qtopline; + else { + if (qline == (((numqlines-1) << 1) + qtopline)) qline = 22; + else qline += 2; + } + PlaySFX(IS_TITLEMOV); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void QuestlogEnter() +{ + int q; + + PlaySFX(IS_TITLSLCT); + if ((numqlines != 0) && (qline != 22)) { + q = qlist[(qline - qtopline) >> 1]; + InitQTextMsg(quests[q]._qmsg); + } + questlog = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CheckQLogBtn() +{ + int i, ql; + + ql = (MouseY - 32) / 12; + if (numqlines != 0) { + for (i = 0; i < numqlines; i++) { + if (ql == ((i << 1) + qtopline)) { + qline = ql; + QuestlogEnter(); + } + } + } + if (ql == 22) { + qline = 22; + QuestlogEnter(); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void QuestlogESC() +{ + questlog = FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetMultiQuest(int q, int s, BOOL l, int v1) +{ +#if !IS_VERSION(SHAREWARE) + app_assert((DWORD)q < MAXQUESTS); + app_assert(quests[q]._qactive != QUEST_NOTAVAIL); + + // Don't change if already done + if (quests[q]._qactive == QUEST_DONE) + return; + + // always next state + if (s > quests[q]._qactive) + quests[q]._qactive = s; + + // never change from TRUE to FALSE + quests[q]._qlog |= l; + + // always next state + if (v1 > quests[q]._qvar1) + quests[q]._qvar1 = v1; +#endif +} diff --git a/src/QUESTS.H b/src/QUESTS.H new file mode 100644 index 0000000..0805aa6 --- /dev/null +++ b/src/QUESTS.H @@ -0,0 +1,155 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/QUESTS.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ +#ifndef MAXQUESTS // only one copy in existsence JKE + + + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXQUESTS 24 // JKEQUEST add to this when adding new quests +#define MAXMULTIQUESTS 9 + +#define Q_ROCK 0 +#define Q_BKMUSHRM 1 +#define Q_GARBUD 2 +#define Q_ZHAR 3 +#define Q_VEIL 4 +#define Q_DIABLO 5 +#define Q_BUTCHER 6 +#define Q_LTBANNER 7 +#define Q_BLIND 8 +#define Q_BLOOD 9 +#define Q_ANVIL 10 +#define Q_WARLORD 11 +#define Q_SKELKING 12 +#define Q_PWATER 13 +#define Q_SCHAMB 14 +#define Q_BETRAYER 15 +#define Q_CRYPTMAP 16 // JKEQUEST +#define Q_FARMER 17 +#define Q_THEO 18 +#define Q_TRADER 19 +#define Q_DEFILER 20 +#define Q_NA_KRUL 21 +#define Q_CORNERSTONE 22 +#define Q_COWSUIT 23 + +#define QUEST_NOTAVAIL 0 +#define QUEST_NOTACTIVE 1 +#define QUEST_NOTDONE 2 +#define QUEST_DONE 3 +#define QUEST_TOOWEAK1 4 +#define QUEST_TOOWEAK2 5 +#define QUEST_TOOWEAK3 6 +#define QUEST_PASS1 7 +#define QUEST_PASS2 8 +#define QUEST_PASS3 9 +#define QUEST_REALLYDONE 10 + + +#define QFLAG_MULTI 1 + +// Vile Betrayer Red Portal +#define QS_VBRPOFF 0 // Red Portal not init +#define QS_VBRP1 1 // Red Portal lvl 15 on +#define QS_VBRP2 2 // Red Portal lvl 15 off +#define QS_VBRP3 3 // Red Portal set lvl on +#define QS_VBRP4 4 // Red Portal set lvl off + +// Mushroom Quest states +enum { + QS_INIT=0, + QS_TOMESPAWNED, + QS_TOMEGIVEN, + QS_MUSHSPAWNED, + QS_MUSHPICKED, + QS_MUSHGIVEN, + QS_BRAINSPAWNED, + QS_BRAINGIVEN, // == elixir spawned +}; + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + byte _qlevel; // Which level the quest will appear on + byte _qtype; // Which quest it is + byte _qactive; // Not avail, not active, not completed, done flag + byte _qlvltype; // Quest level type (255 is current) + int _qtx; // X trigger to level + int _qty; // Y trigger to level + byte _qslvl; // Which set level is it? + byte _qidx; // quest data index + int _qmsg; // current quest msg + BYTE _qvar1; // quest-dependent state variable + BYTE _qvar2; + BOOL _qlog; // display in quest log +} QuestStruct; +#define SAVE_QUEST_SIZE sizeof(QuestStruct) + +typedef struct { + byte _qdlvl; // level the quest will appear on + char _qdmultlvl; // Which level the quest will appear on in multiplayer + byte _qlvlt; // Level gfx type + byte _qdtype; // Which quest it is + byte _qdrnd; // Random percent of quest appearing + byte _qslvl; // Set level number + BOOL _qflags; // Quest flags + int _qdmsg; // initial quest message + char *_qlstr; // String description for log +} QuestData; + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern QuestStruct quests[MAXQUESTS]; + +extern BOOL questlog; + +extern BYTE *pQLogCel; + +extern int ReturnLvlX, ReturnLvlY, ReturnLvl, ReturnLvlT; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitQuests(); +void DRLG_CheckQuests(int, int); +void CheckQuests(); +void CheckQuestKill(int, BOOL); + +void SetReturnLvlPos(); +void GetReturnLvlPos(); + +void ResyncQuests(); +void ResyncMPQuests(); + +void DrawQuestLog(); + +void StartQuestlog(); +void QuestlogUp(); +void QuestlogDown(); +void QuestlogEnter(); +void QuestlogESC(); +void CheckQLogBtn(); + +BOOL ForceQuests(); +BOOL QuestStatus(int); + +void SetMultiQuest(int, int, BOOL, int); + + +#endif \ No newline at end of file diff --git a/src/REGCONST.H b/src/REGCONST.H new file mode 100644 index 0000000..da5a4fc --- /dev/null +++ b/src/REGCONST.H @@ -0,0 +1,20 @@ +//************************************** +// regconst.h +// written 9.17.94 +// written by Patrick Wyatt +//************************************** + + +//************************************** +// registration blocks +//************************************** + // length of registration block embedded in program + #define REG_LEN 128 + + // length of table of registration blocks embedded in program + #define TBL_LEN 128 + + // offset to registration block + typedef ULONG REG_OFF; + #define MAX_REGS 10 + diff --git a/src/RESOURCE.H b/src/RESOURCE.H new file mode 100644 index 0000000..07a8001 --- /dev/null +++ b/src/RESOURCE.H @@ -0,0 +1,28 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Diablo.rc +// +#define IDI_ICON1 101 +#define IDD_DDRAW_ERR 104 +#define IDD_MEM_ERR 105 +#define IDD_FILE_ERR 106 +#define IDD_DDRAW_DLL_ERR 107 +#define IDD_DSOUND_DLL_ERR 108 +#define IDD_CHIP_ERR 109 +#define IDD_DISKFREE_ERR 110 +#define IDI_ICON2 110 +#define IDD_DDRAW_PAL_ERR 111 +#define IDD_CDROM_ERR 112 +#define IDC_ERROR_TAG 1000 +#define IDESCAPE 1001 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 112 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1002 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/SCLASS.H b/src/SCLASS.H new file mode 100644 index 0000000..0e1c039 --- /dev/null +++ b/src/SCLASS.H @@ -0,0 +1,158 @@ +#ifndef _STORM_SCLASS_H_ +#define _STORM_SCLASS_H_ + +extern "C++" { + +/**************************************************************************** +* +* CCRITSECT -- Critical section class +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void inline Enter () { EnterCriticalSection(&m_critsect); } + void inline Leave () { LeaveCriticalSection(&m_critsect); } +}; + +/**************************************************************************** +* +* CLOCK -- Lock class +* +***/ + +class CLock { + private: + SSYNCLOCK m_lock; + public: + CLock () { SSyncInitializeLock(&m_lock); } + ~CLock () { SSyncDeleteLock(&m_lock); } + void inline Enter (BOOL forwriting) { SSyncEnterLock(&m_lock,forwriting); } + void inline Leave (BOOL fromwriting) { SSyncLeaveLock(&m_lock,fromwriting); } +}; + +/**************************************************************************** +* +* TLIST -- Linked list function templates +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return 1; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return 1; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = *head; + *head = ptr; + return 1; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return 1; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return 0; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber); + *head = next; + } + return 1; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + +} // extern "C++" +#endif // ifndef _STORM_SCLASS_H_ diff --git a/src/SCRLASM.CPP b/src/SCRLASM.CPP new file mode 100644 index 0000000..08030b0 --- /dev/null +++ b/src/SCRLASM.CPP @@ -0,0 +1,6946 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Scrolling file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/SCRLASM.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +** CheckForScroll +** DrawAndBlit +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "scrlasm.h" +#include "gendung.h" +#include "lighting.h" + + //************************************************************************* + // Externs from scrollrt.cpp + //************************************************************************* + extern long nLVal; + extern DWORD gdwPNum; + extern long ClipY; + extern int gnPieceNum; + extern BOOL nTrans; + extern char gbPartialTrans; + extern char lightmax; + + + //************************************************************************* + // Private + //************************************************************************* + static long sgLineVal, cm; + static byte wt; + static long *t; + static long sgRightMask[32] = { + 0xeaaaaaaa, // 1110 1010 1010 1010 1010 1010 1010 1010 + 0xf5555555, // 1111 0101 0101 0101 0101 0101 0101 0101 + 0xfeaaaaaa, // 1111 1110 1010 1010 1010 1010 1010 1010 + 0xff555555, // 1111 1111 0101 0101 0101 0101 0101 0101 + 0xffeaaaaa, // 1111 1111 1110 1010 1010 1010 1010 1010 + 0xfff55555, // 1111 1111 1111 0101 0101 0101 0101 0101 + 0xfffeaaaa, // 1111 1111 1111 1110 1010 1010 1010 1010 + 0xffff5555, // 1111 1111 1111 1111 0101 0101 0101 0101 + 0xffffeaaa, // 1111 1111 1111 1111 1110 1010 1010 1010 + 0xfffff555, // 1111 1111 1111 1111 1111 0101 0101 0101 + 0xfffffeaa, // 1111 1111 1111 1111 1111 1110 1010 1010 + 0xffffff55, // 1111 1111 1111 1111 1111 1111 0101 0101 + 0xffffffea, // 1111 1111 1111 1111 1111 1111 1110 1010 + 0xfffffff5, // 1111 1111 1111 1111 1111 1111 1111 0101 + 0xfffffffe, // 1111 1111 1111 1111 1111 1111 1111 1110 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff }; // 1111 1111 1111 1111 1111 1111 1111 1111 + + static long sgLeftMask[32] = { + 0xaaaaaaab, // 1010 1010 1010 1010 1010 1010 1010 1011 + 0x5555555f, // 0101 0101 0101 0101 0101 0101 0101 1111 + 0xaaaaaabf, // 1010 1010 1010 1010 1010 1010 1011 1111 + 0x555555ff, // 0101 0101 0101 0101 0101 0101 1111 1111 + 0xaaaaabff, // 1010 1010 1010 1010 1010 1011 1111 1111 + 0x55555fff, // 0101 0101 0101 0101 0101 1111 1111 1111 + 0xaaaabfff, // 1010 1010 1010 1010 1011 1111 1111 1111 + 0x5555ffff, // 0101 0101 0101 0101 1111 1111 1111 1111 + 0xaaabffff, // 1010 1010 1010 1011 1111 1111 1111 1111 + 0x555fffff, // 0101 0101 0101 1111 1111 1111 1111 1111 + 0xaabfffff, // 1010 1010 1011 1111 1111 1111 1111 1111 + 0x55ffffff, // 0101 0101 1111 1111 1111 1111 1111 1111 + 0xabffffff, // 1010 1011 1111 1111 1111 1111 1111 1111 + 0x5fffffff, // 0101 1111 1111 1111 1111 1111 1111 1111 + 0xbfffffff, // 1011 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff, // 1111 1111 1111 1111 1111 1111 1111 1111 + 0xffffffff }; // 1111 1111 1111 1111 1111 1111 1111 1111 + + static long sgFullMask[32] = { + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555, // 0101 0101 0101 0101 0101 0101 0101 0101 + 0xaaaaaaaa, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0x55555555 }; // 0101 0101 0101 0101 0101 0101 0101 0101 + + +/*-----------------------------------------------------------------------** +** Now with Y clipping (top clip) +**-----------------------------------------------------------------------*/ + +void TDecodeMicroTile (BYTE *pDecodeTo) +{ + t = µoffset[0][0]; + __asm { + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,dword ptr [nLVal] + or al,al + jz _NoLt + cmp al,byte ptr [lightmax] + jz _Black + + mov eax,dword ptr [gdwPNum] + and eax,08000h + jnz _Speed + + mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov ebx,dword ptr [nLVal]; // Light conversion table + shl ebx,8 + add ebx,dword ptr [pLightTbl]; + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz _Type0 // Solid 32x32 block + cmp ax,1 + jz _Type1 // 32x32 block with '0' holes + cmp ax,2 + jz _Type2 // Left Triangle + cmp ax,3 + jz _Type3 // Right Triangle + cmp ax,4 + jz _Type4 // Left Triangle to wall + jmp _Type5 // Right Triangle to wall + +_Speed: mov esi,dword ptr [t] + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [nLVal] + shl eax,2 + add esi,eax // Source + mov eax,dword ptr [esi] + mov esi,dword ptr [pSpeedCels] + add esi,eax + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +_SCmp: cmp ax,8 + jz _Type8 // PreTrans Solid 32x32 block + cmp ax,9 + jz _Type9 // PreTrans 32x32 block with '0' holes + cmp ax,10 + jz _TypeA // PreTrans Left Triangle + cmp ax,11 + jz _TypeB // PreTrans Right Triangle + cmp ax,12 + jz _TypeC // PreTrans Left Triangle to wall + jmp _TypeD // PreTrans Right Triangle to wall + +_NoLt: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RNoLt + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RNoLt: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp _SCmp + +_Black: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RBlk + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RBlk: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz _TypeG // Black Trans Solid 32x32 block + cmp ax,1 + jz _TypeH // Black Trans 32x32 block with '0' holes + cmp ax,2 + jz _TypeI // Black Trans Left Triangle + cmp ax,3 + jz _TypeJ // Black Trans Right Triangle + cmp ax,4 + jz _TypeK // Black Trans Left Triangle to wall + jmp _TypeL // Black Trans Right Triangle to wall + +/*-----------------------------------------------------------------------*/ + +_Type0: mov edx,16 +_T0Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquad2 + pop edx + + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquad1 + pop edx + + sub edi,NBUFFW32 + dec edx + jnz _T0Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type1: mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 + +_T1Lp1: push ecx + mov edx,32 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz _T1Od + + push edx + call xbyte1 + pop edx + jmp _T1x + +_T1Od: + push edx + call xbyte2 + pop edx + +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 + +_T1Nxt: pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz _T1Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type2: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_T2Lp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T2Od + + push edx + call xbyte1 + pop edx + jmp _T2x + +_T2Od: + push edx + call xbyte2 + pop edx + +_T2x: sub edi,NBUFFW32 + or edx,edx + jz _T2b + sub edx,2 + jmp _T2Lp1 + +_T2b: mov edx,2 +_T2Lp4: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T2Od2 + + push edx + call xbyte1 + pop edx + jmp _T2x2 + +_T2Od2: + push edx + call xbyte2 + pop edx + +_T2x2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _T2Lp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type3: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_T3Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T3Od + + push edx + call xbyte1 + pop edx + jmp _T3x + +_T3Od: + push edx + call xbyte2 + pop edx + +_T3x: sub edi,NBUFFW32 + or edx,edx + jz _T3b + add edi,edx + sub edx,2 + jmp _T3Lp1 + +_T3b: mov edx,2 +_T3Lp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T3Od2 + + push edx + call xbyte1 + pop edx + jmp _T3x2 + +_T3Od2: + push edx + call xbyte2 + pop edx + +_T3x2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _T3Lp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type4: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_T4Lp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T4Od + + push edx + call xbyte1 + pop edx + jmp _T4x + +_T4Od: + push edx + call xbyte2 + pop edx + +_T4x: sub edi,NBUFFW32 + or edx,edx + jz _T4b + sub edx,2 + jmp _T4Lp1 + +_T4b: mov edx,8 +_T4Lp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquad2 + pop edx + + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquad1 + pop edx + + sub edi,NBUFFW32 + dec edx + jnz _T4Lp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type5: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_T5Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T5Od + + push edx + call xbyte1 + pop edx + jmp _T5x + +_T5Od: + push edx + call xbyte2 + pop edx + +_T5x: sub edi,NBUFFW32 + or edx,edx + jz _T5b + add edi,edx + sub edx,2 + jmp _T5Lp1 + +_T5b: mov edx,8 +_T5Lp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquad2 + pop edx + + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquad1 + pop edx + + sub edi,NBUFFW32 + dec edx + jnz _T5Lp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type8: mov edx,16 +_T8Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_T8Lp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _T8Lp2 + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_T8Lp3: lodsd + stosb + inc edi + ror eax,16 + stosb + inc edi + loop _T8Lp3 + sub edi,NBUFFW32 + dec edx + jnz _T8Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type9: mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 + +_T9Lp1: push ecx + mov edx,32 + +_T9Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T9J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz _T9Od + shr ecx,1 + jnc _T9w + inc esi + inc edi + jecxz _T9x + jmp _T9w2 +_T9w: shr ecx,1 + jnc _T9Lp3 + inc esi + inc edi + movsb + jecxz _T9x +_T9Lp3: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _T9Lp3 + jmp _T9x + +_T9Od: shr ecx,1 + jnc _T9w2 + movsb + jecxz _T9x + jmp _T9w +_T9w2: shr ecx,1 + jnc _T9Lp4 + movsb + inc esi + inc edi + jecxz _T9x +_T9Lp4: lodsd + stosb + inc edi + ror eax,16 + stosb + inc edi + loop _T9Lp4 + +_T9x: or edx,edx + jz _T9Nxt + jmp _T9Lp2 + +_T9J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T9Lp2 + +_T9Nxt: pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz _T9Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeA: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TALp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TAOd + shr ecx,2 + jnc _TALp2 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TAx +_TALp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TALp2 + jmp _TAx + +_TAOd: shr ecx,2 + jnc _TALp3 + lodsw + stosb + inc edi + jecxz _TAx +_TALp3: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TALp3 + +_TAx: sub edi,NBUFFW32 + or edx,edx + jz _TAb + sub edx,2 + jmp _TALp1 + +_TAb: mov edx,2 +_TALp4: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TAOd2 + shr ecx,2 + jnc _TALp5 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TAx2 +_TALp5: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TALp5 + jmp _TAx2 + +_TAOd2: shr ecx,2 + jnc _TALp6 + lodsw + stosb + inc edi + jecxz _TAx2 +_TALp6: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TALp6 + +_TAx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TALp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeB: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TBLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TBOd + shr ecx,2 + jnc _TBLp2 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TBx +_TBLp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TBLp2 + jmp _TBx + +_TBOd: shr ecx,2 + jnc _TBLp3 + lodsw + stosb + inc edi + jecxz _TBx +_TBLp3: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TBLp3 + +_TBx: sub edi,NBUFFW32 + or edx,edx + jz _TBb + add edi,edx + sub edx,2 + jmp _TBLp1 + +_TBb: mov edx,2 +_TBLp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TBOd2 + shr ecx,2 + jnc _TBLp5 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TBx2 +_TBLp5: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TBLp5 + jmp _TBx2 + +_TBOd2: shr ecx,2 + jnc _TBLp6 + lodsw + stosb + inc edi + jecxz _TBx2 +_TBLp6: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TBLp6 + +_TBx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TBLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeC: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TCLp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TCOd + shr ecx,2 + jnc _TCLp2 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TCx +_TCLp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TCLp2 + jmp _TCx + +_TCOd: shr ecx,2 + jnc _TCLp3 + lodsw + stosb + inc edi + jecxz _TCx +_TCLp3: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TCLp3 + +_TCx: sub edi,NBUFFW32 + or edx,edx + jz _TCb + sub edx,2 + jmp _TCLp1 + +_TCb: mov edx,8 +_TCLp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TCLp5: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TCLp5 + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TCLp6: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TCLp6 + sub edi,NBUFFW32 + dec edx + jnz _TCLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeD: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TDLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TDOd + shr ecx,2 + jnc _TDLp2 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TDx +_TDLp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TDLp2 + jmp _TDx + +_TDOd: shr ecx,2 + jnc _TDLp3 + lodsw + stosb + inc edi + jecxz _TDx +_TDLp3: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TDLp3 + +_TDx: sub edi,NBUFFW32 + or edx,edx + jz _TDb + add edi,edx + sub edx,2 + jmp _TDLp1 + +_TDb: mov edx,8 +_TDLp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TDLp5: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TDLp5 + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TDLp6: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TDLp6 + sub edi,NBUFFW32 + dec edx + jnz _TDLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeG: mov edx,16 + xor eax,eax +_TGLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TGLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TGLp2 + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TGLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TGLp3 + sub edi,NBUFFW32 + dec edx + jnz _TGLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeH: mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 + +_THLp1: push ecx + mov edx,32 + +_THLp2: xor eax,eax // Load control byte + lodsb + or al,al + js _THJ + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + mov ecx,eax + add esi,ecx + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz _THOd + xor eax,eax + shr ecx,1 + jnc _THw + inc edi + jecxz _THx + jmp _THw2 +_THw: shr ecx,1 + jnc _THLp3 + inc edi + stosb + jecxz _THx +_THLp3: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _THLp3 + jmp _THx + +_THOd: xor eax,eax + shr ecx,1 + jnc _THw2 + stosb + jecxz _THx + jmp _THw +_THw2: shr ecx,1 + jnc _THLp4 + stosb + inc edi + jecxz _THx +_THLp4: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _THLp4 + +_THx: or edx,edx + jz _THNxt + jmp _THLp2 + +_THJ: neg al // Do jump + add edi,eax + sub edx,eax + jnz _THLp2 + +_THNxt: pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz _THLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeI: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TILp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TIOd + xor eax,eax + shr ecx,2 + jnc _TILp2 + inc edi + stosb + jecxz _TIx +_TILp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TILp2 + jmp _TIx + +_TIOd: xor eax,eax + shr ecx,2 + jnc _TILp3 + stosb + inc edi + jecxz _TIx +_TILp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TILp3 + +_TIx: sub edi,NBUFFW32 + or edx,edx + jz _TIb + sub edx,2 + jmp _TILp1 + +_TIb: mov edx,2 +_TILp4: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TIOd2 + xor eax,eax + shr ecx,2 + jnc _TILp5 + inc edi + stosb + jecxz _TIx2 +_TILp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TILp5 + jmp _TIx2 + +_TIOd2: xor eax,eax + shr ecx,2 + jnc _TILp6 + stosb + inc edi + jecxz _TIx2 +_TILp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TILp6 + +_TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TILp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeJ: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TJLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TJOd + xor eax,eax + shr ecx,2 + jnc _TJLp2 + inc edi + stosb + jecxz _TJx +_TJLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TJLp2 + jmp _TJx + +_TJOd: xor eax,eax + shr ecx,2 + jnc _TJLp3 + stosb + inc edi + jecxz _TJx +_TJLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TJLp3 + +_TJx: sub edi,NBUFFW32 + or edx,edx + jz _TJb + add edi,edx + sub edx,2 + jmp _TJLp1 + +_TJb: mov edx,2 +_TJLp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TJOd2 + xor eax,eax + shr ecx,2 + jnc _TJLp5 + inc edi + stosb + jecxz _TJx2 +_TJLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TJLp5 + jmp _TJx2 + +_TJOd2: xor eax,eax + shr ecx,2 + jnc _TJLp6 + stosb + inc edi + jecxz _TJx2 +_TJLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TJLp6 + +_TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TJLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeK: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TKLp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TKOd + xor eax,eax + shr ecx,2 + jnc _TKLp2 + inc edi + stosb + jecxz _TKx +_TKLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TKLp2 + jmp _TKx + +_TKOd: xor eax,eax + shr ecx,2 + jnc _TKLp3 + stosb + inc edi + jecxz _TKx +_TKLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TKLp3 + +_TKx: sub edi,NBUFFW32 + or edx,edx + jz _TKb + sub edx,2 + jmp _TKLp1 + +_TKb: mov edx,8 + xor eax,eax +_TKLp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TKLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TKLp5 + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TKLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TKLp6 + sub edi,NBUFFW32 + dec edx + jnz _TKLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeL: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TLLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TLOd + xor eax,eax + shr ecx,2 + jnc _TLLp2 + inc edi + stosb + jecxz _TLx +_TLLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TLLp2 + jmp _TLx + +_TLOd: xor eax,eax + shr ecx,2 + jnc _TLLp3 + stosb + inc edi + jecxz _TLx +_TLLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TLLp3 + +_TLx: sub edi,NBUFFW32 + or edx,edx + jz _TLb + add edi,edx + sub edx,2 + jmp _TLLp1 + +_TLb: mov edx,8 + xor eax,eax +_TLLp4: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TLLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TLLp5 + sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 +_TLLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TLLp6 + sub edi,NBUFFW32 + dec edx + jnz _TLLp4 + jmp _Done + +xbyte1: // blank first + + shr ecx,1 + jnc xword2 + inc esi + inc edi + +xword1: // xlat first + shr ecx,1 + jnc xquadt1 + mov dl,[esi] + mov dl,[ebx+edx] + add esi,2 + mov [edi],dl + add edi,2 + +xquadt1: + test cl,cl + jz xend + +xquad1: // xlat first +/* debug + shl ecx,2 + add esi,ecx + add edi,ecx + ret +*/ + + mov eax,[esi] + add esi,4 + mov dl,al + shr eax,16 + mov dl,[ebx+edx] + mov [edi],dl + mov dl,al + add edi,4 + mov dl,[ebx+edx] + dec ecx + mov [edi-2],dl + jnz xquad1 + + ret + + +xbyte2: // xlat first + + shr ecx,1 + jnc xword1 + mov dl,[esi] + mov dl,[ebx+edx] + inc esi + mov [edi],dl + inc edi + +xword2: // blank first + shr ecx,1 + jnc xquadt2 + mov dl,[esi+1] + mov dl,[ebx+edx] + add esi,2 + mov [edi+1],dl + add edi,2 + +xquadt2: + test cl,cl + jz xend + +xquad2: // blank first +/* debug + shl ecx,2 + add esi,ecx + add edi,ecx + ret +*/ + + + mov eax,[esi] + add esi,4 + mov dl,ah + shr eax,16 + mov dl,[ebx+edx] + mov [edi+1],dl + mov dl,ah + add edi,4 + mov dl,[ebx+edx] + dec ecx + mov [edi-1],dl + jnz xquad2 + +xend: + ret + +_PDone: pop eax +_Done: nop + + + } // end of asm block +} + +/*-----------------------------------------------------------------------** +** Now with Y clipping and Masking Transparency +**-----------------------------------------------------------------------*/ + +void TDecodeM12Tile (BYTE *pDecodeTo, long *mask) +{ + t = µoffset[0][0]; + __asm { + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,dword ptr [nLVal] + or al,al + jz _NoLt + cmp al,byte ptr [lightmax] + jz _Black + + mov eax,dword ptr [gdwPNum] + and eax,08000h + jnz _Speed + + mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov ebx,dword ptr [nLVal]; // Light conversion table + shl ebx,8 + add ebx,dword ptr [pLightTbl]; + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz _Type0 // Solid 32x32 block + cmp ax,1 + jz _Type1 // 32x32 block with '0' holes + cmp ax,2 + jz _Type2 // Left Triangle + cmp ax,3 + jz _Type3 // Right Triangle + cmp ax,4 + jz _Type4 // Left Triangle to wall + jmp _Type5 // Right Triangle to wall + +_Speed: mov esi,dword ptr [t] + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [nLVal] + shl eax,2 + add esi,eax // Source + mov eax,dword ptr [esi] + mov esi,dword ptr [pSpeedCels] + add esi,eax + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +_SCmp: cmp ax,8 + jz _Type8 // PreTrans Solid 32x32 block + cmp ax,9 + jz _Type9 // PreTrans 32x32 block with '0' holes + cmp ax,10 + jz _TypeA // PreTrans Left Triangle + cmp ax,11 + jz _TypeB // PreTrans Right Triangle + cmp ax,12 + jz _TypeC // PreTrans Left Triangle to wall + jmp _TypeD // PreTrans Right Triangle to wall + +_NoLt: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RNoLt + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RNoLt: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp _SCmp + +_Black: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RBlk + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RBlk: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz _TypeG // Black Trans Solid 32x32 block + cmp ax,1 + jz _TypeH // Black Trans 32x32 block with '0' holes + cmp ax,2 + jz _TypeI // Black Trans Left Triangle + cmp ax,3 + jz _TypeJ // Black Trans Right Triangle + cmp ax,4 + jz _TypeK // Black Trans Left Triangle to wall + jmp _TypeL // Black Trans Right Triangle to wall + +/*-----------------------------------------------------------------------*/ + +_Type0: mov edx,32 +_T0Lp1: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_T0Lp2: lodsb + shl edx,1 + jnc _T0S1 + xlatb + mov byte ptr [edi],al +_T0S1: inc edi + loop _T0Lp2 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _T0Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type1: mov ecx,32 + +_T1Lp1: push ecx + mov eax,dword ptr [mask] + mov eax,dword ptr [eax] + mov dword ptr [cm],eax + + mov edx,32 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + mov ecx,eax + push edx + mov edx,dword ptr [cm] +_T1Lp3: lodsb + shl edx,1 + jnc _T1S1 + xlatb + mov byte ptr [edi],al +_T1S1: inc edi + loop _T1Lp3 + mov dword ptr [cm],edx + pop edx + or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz _T1S2 + push eax + mov eax,dword ptr [cm] + shl eax,cl + mov dword ptr [cm],eax + pop eax +_T1S2: sub edx,eax + jnz _T1Lp2 +_T1Nxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec ecx + jnz _T1Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type2: mov edx,30 +_T2Lp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T2Lp2 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T2x +_T2Lp2: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T2Lp2 +_T2x: sub edi,NBUFFW32 + or edx,edx + jz _T2b + sub edx,2 + jmp _T2Lp1 + +_T2b: mov edx,2 +_T2Lp3: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T2Lp4 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T2x2 +_T2Lp4: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T2Lp4 +_T2x2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _T2Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type3: mov edx,30 +_T3Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T3Lp2 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T3x +_T3Lp2: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T3Lp2 +_T3x: sub edi,NBUFFW32 + or edx,edx + jz _T3b + add edi,edx + sub edx,2 + jmp _T3Lp1 + +_T3b: mov edx,2 +_T3Lp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T3Lp4 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T3x2 +_T3Lp4: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T3Lp4 +_T3x2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _T3Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type4: mov edx,30 +_T4Lp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T4Lp2 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T4x +_T4Lp2: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T4Lp2 +_T4x: sub edi,NBUFFW32 + or edx,edx + jz _T4b + sub edx,2 + jmp _T4Lp1 + +_T4b: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_T4Lp3: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_T4Lp4: lodsb + shl edx,1 + jnc _T4S1 + xlatb + mov byte ptr [edi],al +_T4S1: inc edi + loop _T4Lp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _T4Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type5: mov edx,30 +_T5Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T5Lp2 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T5x +_T5Lp2: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T5Lp2 +_T5x: sub edi,NBUFFW32 + or edx,edx + jz _T5b + add edi,edx + sub edx,2 + jmp _T5Lp1 + +_T5b: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_T5Lp3: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_T5Lp4: lodsb + shl edx,1 + jnc _T5S1 + xlatb + mov byte ptr [edi],al +_T5S1: inc edi + loop _T5Lp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _T5Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type8: mov edx,32 +_T8Lp1: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_T8Lp2: lodsb + shl edx,1 + jnc _T8S1 + mov byte ptr [edi],al +_T8S1: inc edi + loop _T8Lp2 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _T8Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type9: mov ecx,32 + +_T9Lp1: push ecx + mov eax,dword ptr [mask] + mov eax,dword ptr [eax] + mov dword ptr [cm],eax + + mov edx,32 + +_T9Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T9J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + push edx + mov edx,dword ptr [cm] + mov ecx,eax +_T9Lp3: lodsb + shl edx,1 + jnc _T9S1 + mov byte ptr [edi],al +_T9S1: inc edi + loop _T9Lp3 + mov dword ptr [cm],edx + pop edx + or edx,edx + jz _T9Nxt + jmp _T9Lp2 + +_T9J: neg al // Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz _T9S2 + mov ebx,dword ptr [cm] + shl ebx,cl + mov dword ptr [cm],ebx +_T9S2: sub edx,eax + jnz _T9Lp2 +_T9Nxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec ecx + jnz _T9Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeA: mov edx,30 +_TALp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TALp2 + movsw + jecxz _TAx +_TALp2: rep movsd +_TAx: sub edi,NBUFFW32 + or edx,edx + jz _TAb + sub edx,2 + jmp _TALp1 + +_TAb: mov edx,2 +_TALp3: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TALp4 + movsw + jecxz _TAx2 +_TALp4: rep movsd +_TAx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TALp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeB: mov edx,30 +_TBLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TBLp2 + movsw + jecxz _TBx +_TBLp2: rep movsd +_TBx: sub edi,NBUFFW32 + or edx,edx + jz _TBb + add edi,edx + sub edx,2 + jmp _TBLp1 + +_TBb: mov edx,2 +_TBLp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TBLp4 + movsw + jecxz _TBx2 +_TBLp4: rep movsd +_TBx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TBLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeC: mov edx,30 +_TCLp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TCLp2 + movsw + jecxz _TCx +_TCLp2: rep movsd +_TCx: sub edi,NBUFFW32 + or edx,edx + jz _TCb + sub edx,2 + jmp _TCLp1 + +_TCb: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_TCLp3: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_TCLp4: lodsb + shl edx,1 + jnc _TCS1 + mov byte ptr [edi],al +_TCS1: inc edi + loop _TCLp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TCLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeD: mov edx,30 +_TDLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TDLp2 + movsw + jecxz _TDx +_TDLp2: rep movsd +_TDx: sub edi,NBUFFW32 + or edx,edx + jz _TDb + add edi,edx + sub edx,2 + jmp _TDLp1 + +_TDb: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_TDLp3: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_TDLp4: lodsb + shl edx,1 + jnc _TDS1 + mov byte ptr [edi],al +_TDS1: inc edi + loop _TDLp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TDLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeG: mov edx,32 +_TGLp1: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +_TGLp2: shl edx,1 + jnc _TGS1 + mov byte ptr [edi],al +_TGS1: inc edi + loop _TGLp2 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TGLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeH: mov ecx,32 + +_THLp1: push ecx + mov eax,dword ptr [mask] + mov eax,dword ptr [eax] + mov dword ptr [cm],eax + + mov edx,32 + +_THLp2: xor eax,eax // Load control byte + lodsb + or al,al + js _THJ + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + push edx + mov edx,dword ptr [cm] + mov ecx,eax + add esi,ecx + xor eax,eax +_THLp3: shl edx,1 + jnc _THS1 + mov byte ptr [edi],al +_THS1: inc edi + loop _THLp3 + mov dword ptr [cm],edx + pop edx + or edx,edx + jz _THNxt + jmp _THLp2 + +_THJ: neg al // Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz _THS2 + mov ebx,dword ptr [cm] + shl ebx,cl + mov dword ptr [cm],ebx +_THS2: sub edx,eax + jnz _THLp2 +_THNxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec ecx + jnz _THLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeI: mov edx,30 + xor eax,eax +_TILp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TILp2 + stosw + jecxz _TIx +_TILp2: rep stosd +_TIx: sub edi,NBUFFW32 + or edx,edx + jz _TIb + sub edx,2 + jmp _TILp1 + +_TIb: mov edx,2 +_TILp3: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + + shr ecx,2 + jnc _TILp4 + stosw + jecxz _TIx2 +_TILp4: rep stosd +_TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TILp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeJ: mov edx,30 + xor eax,eax +_TJLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TJLp2 + stosw + jecxz _TJx +_TJLp2: rep stosd +_TJx: sub edi,NBUFFW32 + or edx,edx + jz _TJb + add edi,edx + sub edx,2 + jmp _TJLp1 + +_TJb: mov edx,2 +_TJLp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TJLp4 + stosw + jecxz _TJx2 +_TJLp4: rep stosd +_TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TJLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeK: mov edx,30 + xor eax,eax +_TKLp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TKLp2 + stosw + jecxz _TKx +_TKLp2: rep stosd +_TKx: sub edi,NBUFFW32 + or edx,edx + jz _TKb + sub edx,2 + jmp _TKLp1 + +_TKb: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_TKLp3: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +_TKLp4: shl edx,1 + jnc _TKS1 + mov byte ptr [edi],al +_TKS1: inc edi + loop _TKLp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TKLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeL: mov edx,30 + xor eax,eax +_TLLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TLLp2 + stosw + jecxz _TLx +_TLLp2: rep stosd +_TLx: sub edi,NBUFFW32 + or edx,edx + jz _TLb + add edi,edx + sub edx,2 + jmp _TLLp1 + +_TLb: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_TLLp3: cmp edi,dword ptr [ClipY] + jb _Done + push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +_TLLp4: shl edx,1 + jnc _TLS1 + mov byte ptr [edi],al +_TLS1: inc edi + loop _TLLp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TLLp3 + jmp _Done + +_PDone: pop eax +_Done: nop + + } // end of asm block +} + + +/*-----------------------------------------------------------------------** +** Now with Y clipping (top clip) +**-----------------------------------------------------------------------*/ + +void DecodeMicroTile (BYTE *pDecodeTo) +{ + if (nTrans) { + if (gbPartialTrans == PART_TRANS_NONE) { + TDecodeMicroTile(pDecodeTo); + return; + } else { + if (gbPartialTrans == PART_TRANS_LEFT) { + wt = nWTypeTable[gnPieceNum]; + if ((wt == WTYPE_LEFT) || (wt == WTYPE_ULC)) { + TDecodeM12Tile(pDecodeTo, &sgLeftMask[31]); + return; + } + if (wt == WTYPE_LRC) { + TDecodeM12Tile(pDecodeTo, &sgRightMask[31]); + return; + } + } + if (gbPartialTrans == PART_TRANS_RIGHT) { + wt = nWTypeTable[gnPieceNum]; + if ((wt == WTYPE_RIGHT) || (wt == WTYPE_ULC)) { + TDecodeM12Tile(pDecodeTo, &sgRightMask[31]); + return; + } + if (wt == WTYPE_LRC) { + TDecodeM12Tile(pDecodeTo, &sgLeftMask[31]); + return; + } + } + } + } + t = µoffset[0][0]; + __asm { + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,dword ptr [nLVal] + or al,al + jz _NoLt + cmp al,byte ptr [lightmax] + jz _Black + + mov eax,dword ptr [gdwPNum] + and eax,08000h + jnz _Speed + + mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov ebx,dword ptr [nLVal] // Light conversion table + shl ebx,8 + add ebx,dword ptr [pLightTbl] + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz _Type0 // Solid 32x32 block + cmp ax,1 + jz _Type1 // 32x32 block with '0' holes + cmp ax,2 + jz _Type2 // Left Triangle + cmp ax,3 + jz _Type3 // Right Triangle + cmp ax,4 + jz _Type4 // Left Triangle to wall + jmp _Type5 // Right Triangle to wall + +_Speed: mov esi,dword ptr [t] + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [nLVal] + shl eax,2 + add esi,eax // Source + mov eax,dword ptr [esi] + mov esi,dword ptr [pSpeedCels] + add esi,eax + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +_SCmp: cmp ax,8 + jz _Type8 // PreTrans Solid 32x32 block + cmp ax,9 + jz _Type9 // PreTrans 32x32 block with '0' holes + cmp ax,10 + jz _TypeA // PreTrans Left Triangle + cmp ax,11 + jz _TypeB // PreTrans Right Triangle + cmp ax,12 + jz _TypeC // PreTrans Left Triangle to wall + jmp _TypeD // PreTrans Right Triangle to wall + +_NoLt: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RNoLt + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RNoLt: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp _SCmp + +_Black: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RBlk + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RBlk: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz _TypeG // Black Trans Solid 32x32 block + cmp ax,1 + jz _TypeH // Black Trans 32x32 block with '0' holes + cmp ax,2 + jz _TypeI // Black Trans Left Triangle + cmp ax,3 + jz _TypeJ // Black Trans Right Triangle + cmp ax,4 + jz _TypeK // Black Trans Left Triangle to wall + jmp _TypeL // Black Trans Right Triangle to wall + +/*-----------------------------------------------------------------------*/ + +_Type0: mov edx,32 +_T0Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquads + pop edx + + sub edi,NBUFFW32 + dec edx + jnz _T0Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type1: mov ecx,32 + +_T1Lp1: push ecx + mov edx,32 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + mov ecx,eax + + push edx + call xbytes + pop edx + + or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: pop ecx + sub edi,NBUFFW32 + dec ecx + jnz _T1Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type2: mov edx,30 +_T2Lp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + + sub edi,NBUFFW32 + or edx,edx + jz _T2b + sub edx,2 + jmp _T2Lp1 + +_T2b: mov edx,2 +_T2Lp3: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + + sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _T2Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type3: mov edx,30 +_T3Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + + sub edi,NBUFFW32 + or edx,edx + jz _T3b + add edi,edx + sub edx,2 + jmp _T3Lp1 + +_T3b: mov edx,2 +_T3Lp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _T3Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type4: mov edx,30 +_T4Lp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + + sub edi,NBUFFW32 + or edx,edx + jz _T4b + sub edx,2 + jmp _T4Lp1 + +_T4b: mov edx,16 +_T4Lp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquads + pop edx + + sub edi,NBUFFW32 + dec edx + jnz _T4Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type5: mov edx,30 +_T5Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + + sub edi,NBUFFW32 + or edx,edx + jz _T5b + add edi,edx + sub edx,2 + jmp _T5Lp1 + +_T5b: mov edx,16 +_T5Lp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + + push edx + call xquads + pop edx + + sub edi,NBUFFW32 + dec edx + jnz _T5Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type8: mov edx,32 +_T8Lp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + rep movsd + sub edi,NBUFFW32 + dec edx + jnz _T8Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type9: mov ecx,32 + +_T9Lp1: push ecx + mov edx,32 + +_T9Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T9J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + mov ecx,eax + shr ecx,1 + jnc _T9w + movsb + jecxz _T9x +_T9w: shr ecx,1 + jnc _T9Lp3 + movsw + jecxz _T9x +_T9Lp3: rep movsd +_T9x: or edx,edx + jz _T9Nxt + jmp _T9Lp2 + +_T9J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T9Lp2 +_T9Nxt: pop ecx + sub edi,NBUFFW32 + loop _T9Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeA: mov edx,30 +_TALp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TALp2 + movsw + jecxz _TAx +_TALp2: rep movsd +_TAx: sub edi,NBUFFW32 + or edx,edx + jz _TAb + sub edx,2 + jmp _TALp1 + +_TAb: mov edx,2 +_TALp3: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TALp4 + movsw + jecxz _TAx2 +_TALp4: rep movsd +_TAx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TALp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeB: mov edx,30 +_TBLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TBLp2 + movsw + jecxz _TBx +_TBLp2: rep movsd +_TBx: sub edi,NBUFFW32 + or edx,edx + jz _TBb + add edi,edx + sub edx,2 + jmp _TBLp1 + +_TBb: mov edx,2 +_TBLp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TBLp4 + movsw + jecxz _TBx2 +_TBLp4: rep movsd +_TBx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TBLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeC: mov edx,30 +_TCLp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TCLp2 + movsw + jecxz _TCx +_TCLp2: rep movsd +_TCx: sub edi,NBUFFW32 + or edx,edx + jz _TCb + sub edx,2 + jmp _TCLp1 + +_TCb: mov edx,16 +_TCLp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + rep movsd + sub edi,NBUFFW32 + dec edx + jnz _TCLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeD: mov edx,30 +_TDLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TDLp2 + movsw + jecxz _TDx +_TDLp2: rep movsd +_TDx: sub edi,NBUFFW32 + or edx,edx + jz _TDb + add edi,edx + sub edx,2 + jmp _TDLp1 + +_TDb: mov edx,16 +_TDLp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + rep movsd + sub edi,NBUFFW32 + dec edx + jnz _TDLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeG: mov edx,32 + xor eax,eax +_TGLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + rep stosd + sub edi,NBUFFW32 + dec edx + jnz _TGLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeH: mov ecx,32 + +_THLp1: push ecx + mov edx,32 + +_THLp2: xor eax,eax // Load control byte + lodsb + or al,al + js _THJ + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _PDone + mov ecx,eax + add esi,ecx + xor eax,eax + shr ecx,1 + jnc _THw + stosb + jecxz _THx +_THw: shr ecx,1 + jnc _THLp3 + stosw + jecxz _THx +_THLp3: rep stosd +_THx: or edx,edx + jz _THNxt + jmp _THLp2 + +_THJ: neg al // Do jump + add edi,eax + sub edx,eax + jnz _THLp2 +_THNxt: pop ecx + sub edi,NBUFFW32 + loop _THLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeI: mov edx,30 + xor eax,eax +_TILp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TILp2 + stosw + jecxz _TIx +_TILp2: rep stosd +_TIx: sub edi,NBUFFW32 + or edx,edx + jz _TIb + sub edx,2 + jmp _TILp1 + +_TIb: mov edx,2 +_TILp3: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TILp4 + stosw + jecxz _TIx2 +_TILp4: rep stosd +_TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TILp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeJ: mov edx,30 + xor eax,eax +_TJLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TJLp2 + stosw + jecxz _TJx +_TJLp2: rep stosd +_TJx: sub edi,NBUFFW32 + or edx,edx + jz _TJb + add edi,edx + sub edx,2 + jmp _TJLp1 + +_TJb: mov edx,2 +_TJLp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TJLp4 + stosw + jecxz _TJx2 +_TJLp4: rep stosd +_TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TJLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeK: mov edx,30 + xor eax,eax +_TKLp1: cmp edi,dword ptr [ClipY] + jb _Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TKLp2 + stosw + jecxz _TKx +_TKLp2: rep stosd +_TKx: sub edi,NBUFFW32 + or edx,edx + jz _TKb + sub edx,2 + jmp _TKLp1 + +_TKb: mov edx,16 +_TKLp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + rep stosd + sub edi,NBUFFW32 + dec edx + jnz _TKLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeL: mov edx,30 + xor eax,eax +_TLLp1: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TLLp2 + stosw + jecxz _TLx +_TLLp2: rep stosd +_TLx: sub edi,NBUFFW32 + or edx,edx + jz _TLb + add edi,edx + sub edx,2 + jmp _TLLp1 + +_TLb: mov edx,16 +_TLLp3: cmp edi,dword ptr [ClipY] + jb _Done + mov ecx,8 + rep stosd + sub edi,NBUFFW32 + dec edx + jnz _TLLp3 + jmp _Done + +xbytes: + + shr cl,1 + jnc xwords + + mov dl, [esi] + mov dl, [ebx+edx] + mov [edi],dl + + add esi,1 + add edi,1 + +xwords: + shr cl,1 + jnc xquads + + mov dl, [esi] + mov ch, [ebx+edx] + + mov [edi],ch + mov dl, [esi+1] + + mov ch, [ebx+edx] + mov [edi+1],ch + + add esi,2 + add edi,2 + +xquads: + test cl,cl + jz xend + +xnext: + mov eax, [esi] + add esi,4 + + mov dl,al + mov ch,[ebx+edx] + + mov dl,ah + ror eax,16 + mov [edi],ch + + mov ch,[ebx+edx] + + mov dl,al + mov [edi+1],ch + + mov ch,[ebx+edx] + + mov dl,ah + mov [edi+2],ch + + mov ch,[ebx+edx] + mov [edi+3],ch + + add edi,4 + + dec cl + jnz xnext + +xend: + ret + +_PDone: pop eax +_Done: nop + + } // end of asm block +} + +/*-----------------------------------------------------------------------** +** Now with Y clipping +**-----------------------------------------------------------------------*/ + +void TCDecodeMicroTile (BYTE *pDecodeTo) +{ + t = µoffset[0][0]; + __asm { + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,dword ptr [nLVal] + or al,al + jz _NoLt + cmp al,byte ptr [lightmax] + jz _Black + + mov eax,dword ptr [gdwPNum] + and eax,08000h + jnz _Speed + + mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov ebx,dword ptr [nLVal]; // Light conversion table + shl ebx,8 + add ebx,dword ptr [pLightTbl]; + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz _Type0 // Solid 32x32 block + cmp ax,1 + jz _Type1 // 32x32 block with '0' holes + cmp ax,2 + jz _Type2 // Left Triangle + cmp ax,3 + jz _Type3 // Right Triangle + cmp ax,4 + jz _Type4 // Left Triangle to wall + jmp _Type5 // Right Triangle to wall + +_Speed: mov esi,dword ptr [t] + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [nLVal] + shl eax,2 + add esi,eax // Source + mov eax,dword ptr [esi] + mov esi,dword ptr [pSpeedCels] + add esi,eax + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +_SCmp: cmp ax,8 + jz _Type8 // PreTrans Solid 32x32 block + cmp ax,9 + jz _Type9 // PreTrans 32x32 block with '0' holes + cmp ax,10 + jz _TypeA // PreTrans Left Triangle + cmp ax,11 + jz _TypeB // PreTrans Right Triangle + cmp ax,12 + jz _TypeC // PreTrans Left Triangle to wall + jmp _TypeD // PreTrans Right Triangle to wall + +_NoLt: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RNoLt + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RNoLt: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp _SCmp + +_Black: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RBlk + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RBlk: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz _TypeG // Black Trans Solid 32x32 block + cmp ax,1 + jz _TypeH // Black Trans 32x32 block with '0' holes + cmp ax,2 + jz _TypeI // Black Trans Left Triangle + cmp ax,3 + jz _TypeJ // Black Trans Right Triangle + cmp ax,4 + jz _TypeK // Black Trans Left Triangle to wall + jmp _TypeL // Black Trans Right Triangle to wall + +/*-----------------------------------------------------------------------*/ + +_Type0: mov edx,16 +_T0Lp1: cmp edi,dword ptr [ClipY] + jb _T0C1 + add esi,32 + add edi,32 + jmp _T0C2 +_T0C1: mov ecx,8 + + push edx + call xquad2 + pop edx + +_T0C2: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _T0C3 + add esi,32 + add edi,32 + jmp _T0C4 +_T0C3: mov ecx,8 + + push edx + call xquad1 + pop edx + +_T0C4: sub edi,NBUFFW32 + dec edx + jnz _T0Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type1: mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 + +_T1Lp1: push ecx + mov edx,32 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _T1C1 + add esi,eax + add edi,eax + jmp _T1x +_T1C1: mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz _T1Od + + push edx + call xbyte1 + pop edx + jmp _T1x + +_T1Od: + push edx + call xbyte2 + pop edx + +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz _T1Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type2: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_T2Lp1: cmp edi,dword ptr [ClipY] + jb _T2C1 + add esi,32 + sub esi,edx + add edi,32 + jmp _T2x +_T2C1: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T2Od + + push edx + call xbyte1 + pop edx + jmp _T2x + +_T2Od: + push edx + call xbyte2 + pop edx + +_T2x: sub edi,NBUFFW32 + or edx,edx + jz _T2b + sub edx,2 + jmp _T2Lp1 + +_T2b: mov edx,2 +_T2Lp4: cmp edi,dword ptr [ClipY] + jb _T2C2 + add esi,32 + sub esi,edx + add edi,32 + jmp _T2x2 +_T2C2: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T2Od2 + + push edx + call xbyte1 + pop edx + jmp _T2x2 + +_T2Od2: + push edx + call xbyte2 + pop edx + +_T2x2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _T2Lp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type3: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_T3Lp1: cmp edi,dword ptr [ClipY] + jb _T3C1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T3x +_T3C1: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T3Od + + push edx + call xbyte1 + pop edx + jmp _T3x + +_T3Od: + push edx + call xbyte2 + pop edx + +_T3x: sub edi,NBUFFW32 + or edx,edx + jz _T3b + add edi,edx + sub edx,2 + jmp _T3Lp1 + +_T3b: mov edx,2 +_T3Lp4: cmp edi,dword ptr [ClipY] + jb _T3C2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T3x2 +_T3C2: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T3Od2 + + push edx + call xbyte1 + pop edx + jmp _T3x2 + +_T3Od2: + push edx + call xbyte2 + pop edx + +_T3x2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _T3Lp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type4: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_T4Lp1: cmp edi,dword ptr [ClipY] + jb _T4C1 + add esi,32 + sub esi,edx + add edi,32 + jmp _T4x +_T4C1: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T4Od + + push edx + call xbyte1 + pop edx + jmp _T4x + +_T4Od: + push edx + call xbyte2 + pop edx + +_T4x: sub edi,NBUFFW32 + or edx,edx + jz _T4b + sub edx,2 + jmp _T4Lp1 + +_T4b: mov edx,8 +_T4Lp4: cmp edi,dword ptr [ClipY] + jb _T4C2 + add esi,32 + add edi,32 + jmp _T4C3 +_T4C2: mov ecx,8 + + push edx + call xquad2 + pop edx + +_T4C3: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _T4C4 + add esi,32 + add edi,32 + jmp _T4C5 +_T4C4: mov ecx,8 + + push edx + call xquad1 + pop edx + +_T4C5: sub edi,NBUFFW32 + dec edx + jnz _T4Lp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type5: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_T5Lp1: cmp edi,dword ptr [ClipY] + jb _T5C1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T5x +_T5C1: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _T5Od + + push edx + call xbyte1 + pop edx + jmp _T5x + +_T5Od: + push edx + call xbyte2 + pop edx + +_T5x: sub edi,NBUFFW32 + or edx,edx + jz _T5b + add edi,edx + sub edx,2 + jmp _T5Lp1 + +_T5b: mov edx,8 +_T5Lp4: cmp edi,dword ptr [ClipY] + jb _T5C2 + add esi,32 + add edi,32 + jmp _T5C3 +_T5C2: mov ecx,8 + + push edx + call xquad2 + pop edx + +_T5C3: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _T5C4 + add esi,32 + add edi,32 + jmp _T5C5 +_T5C4: mov ecx,8 + + push edx + call xquad1 + pop edx + +_T5C5: sub edi,NBUFFW32 + dec edx + jnz _T5Lp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type8: mov edx,16 +_T8Lp1: cmp edi,dword ptr [ClipY] + jb _T8C1 + add esi,32 + add edi,32 + jmp _T8C2 +_T8C1: mov ecx,8 +_T8Lp2: lodsd + inc edi + ror eax,8 + stosb + inc edi + ror eax,16 + stosb + loop _T8Lp2 +_T8C2: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _T8C3 + add esi,32 + add edi,32 + jmp _T8C4 +_T8C3: mov ecx,8 +_T8Lp3: lodsd + stosb + inc edi + ror eax,16 + stosb + inc edi + loop _T8Lp3 +_T8C4: sub edi,NBUFFW32 + dec edx + jnz _T8Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type9: mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 + +_T9Lp1: push ecx + mov edx,32 + +_T9Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T9J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _T9C1 + add esi,eax + add edi,eax + jmp _T9x +_T9C1: mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz _T9Od + shr ecx,1 + jnc _T9w + inc esi + inc edi + jecxz _T9x + jmp _T9w2 +_T9w: shr ecx,1 + jnc _T9Lp3 + inc esi + inc edi + movsb + jecxz _T9x +_T9Lp3: lodsd + inc edi + ror eax,8 + stosb + inc edi + ror eax,16 + stosb + loop _T9Lp3 + jmp _T9x + +_T9Od: shr ecx,1 + jnc _T9w2 + movsb + jecxz _T9x + jmp _T9w +_T9w2: shr ecx,1 + jnc _T9Lp4 + movsb + inc esi + inc edi + jecxz _T9x +_T9Lp4: lodsd + stosb + inc edi + ror eax,16 + stosb + inc edi + loop _T9Lp4 + +_T9x: or edx,edx + jz _T9Nxt + jmp _T9Lp2 + +_T9J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T9Lp2 +_T9Nxt: pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz _T9Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeA: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TALp1: cmp edi,dword ptr [ClipY] + jb _TAC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TAx +_TAC1: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TAOd + shr ecx,2 + jnc _TALp2 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TAx +_TALp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TALp2 + jmp _TAx + +_TAOd: shr ecx,2 + jnc _TALp3 + lodsw + stosb + inc edi + jecxz _TAx +_TALp3: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TALp3 + +_TAx: sub edi,NBUFFW32 + or edx,edx + jz _TAb + sub edx,2 + jmp _TALp1 + +_TAb: mov edx,2 +_TALp4: cmp edi,dword ptr [ClipY] + jb _TAC2 + add esi,32 + sub esi,edx + add edi,32 + jmp _TAx2 +_TAC2: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TAOd2 + shr ecx,2 + jnc _TALp5 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TAx2 +_TALp5: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TALp5 + jmp _TAx2 + +_TAOd2: shr ecx,2 + jnc _TALp6 + lodsw + stosb + inc edi + jecxz _TAx2 +_TALp6: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TALp6 + +_TAx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TALp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeB: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TBLp1: cmp edi,dword ptr [ClipY] + jb _TBC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TBx +_TBC1: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TBOd + shr ecx,2 + jnc _TBLp2 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TBx +_TBLp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TBLp2 + jmp _TBx + +_TBOd: shr ecx,2 + jnc _TBLp3 + lodsw + stosb + inc edi + jecxz _TBx +_TBLp3: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TBLp3 + +_TBx: sub edi,NBUFFW32 + or edx,edx + jz _TBb + add edi,edx + sub edx,2 + jmp _TBLp1 + +_TBb: mov edx,2 +_TBLp4: cmp edi,dword ptr [ClipY] + jb _TBC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TBx2 +_TBC2: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TBOd2 + shr ecx,2 + jnc _TBLp5 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TBx2 +_TBLp5: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TBLp5 + jmp _TBx2 + +_TBOd2: shr ecx,2 + jnc _TBLp6 + lodsw + stosb + inc edi + jecxz _TBx2 +_TBLp6: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TBLp6 + +_TBx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TBLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeC: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TCLp1: cmp edi,dword ptr [ClipY] + jb _TCC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TCx +_TCC1: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TCOd + shr ecx,2 + jnc _TCLp2 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TCx +_TCLp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TCLp2 + jmp _TCx + +_TCOd: shr ecx,2 + jnc _TCLp3 + lodsw + stosb + inc edi + jecxz _TCx +_TCLp3: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TCLp3 + +_TCx: sub edi,NBUFFW32 + or edx,edx + jz _TCb + sub edx,2 + jmp _TCLp1 + +_TCb: mov edx,8 +_TCLp4: cmp edi,dword ptr [ClipY] + jb _TCC2 + add esi,32 + add edi,32 + jmp _TCC3 +_TCC2: mov ecx,8 +_TCLp5: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TCLp5 +_TCC3: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _TCC4 + add esi,32 + add edi,32 + jmp _TCC5 +_TCC4: mov ecx,8 +_TCLp6: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TCLp6 +_TCC5: sub edi,NBUFFW32 + dec edx + jnz _TCLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeD: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TDLp1: cmp edi,dword ptr [ClipY] + jb _TDC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TDx +_TDC1: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TDOd + shr ecx,2 + jnc _TDLp2 + lodsw + inc edi + ror eax,8 + stosb + jecxz _TDx +_TDLp2: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TDLp2 + jmp _TDx + +_TDOd: shr ecx,2 + jnc _TDLp3 + lodsw + stosb + inc edi + jecxz _TDx +_TDLp3: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TDLp3 + +_TDx: sub edi,NBUFFW32 + or edx,edx + jz _TDb + add edi,edx + sub edx,2 + jmp _TDLp1 + +_TDb: mov edx,8 +_TDLp4: cmp edi,dword ptr [ClipY] + jb _TDC2 + add esi,32 + add edi,32 + jmp _TDC3 +_TDC2: mov ecx,8 +_TDLp5: lodsd + inc edi + ror eax,8 + stosb + ror eax,16 + inc edi + stosb + loop _TDLp5 +_TDC3: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _TDC4 + add esi,32 + add edi,32 + jmp _TDC5 +_TDC4: mov ecx,8 +_TDLp6: lodsd + stosb + ror eax,16 + inc edi + stosb + inc edi + loop _TDLp6 +_TDC5: sub edi,NBUFFW32 + dec edx + jnz _TDLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeG: mov edx,16 + xor eax,eax +_TGLp1: cmp edi,dword ptr [ClipY] + jb _TGC1 + add esi,32 + add edi,32 + jmp _TGC2 +_TGC1: mov ecx,8 +_TGLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TGLp2 +_TGC2: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _TGC3 + add esi,32 + add edi,32 + jmp _TGC4 +_TGC3: mov ecx,8 +_TGLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TGLp3 +_TGC4: sub edi,NBUFFW32 + dec edx + jnz _TGLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeH: mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 + +_THLp1: push ecx + mov edx,32 + +_THLp2: xor eax,eax // Load control byte + lodsb + or al,al + js _THJ + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _THC1 + add esi,eax + add edi,eax + jmp _THx +_THC1: mov ecx,eax + add esi,ecx + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz _THOd + xor eax,eax + shr ecx,1 + jnc _THw + inc edi + jecxz _THx + jmp _THw2 +_THw: shr ecx,1 + jnc _THLp3 + inc edi + stosb + jecxz _THx +_THLp3: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _THLp3 + jmp _THx + +_THOd: xor eax,eax + shr ecx,1 + jnc _THw2 + stosb + jecxz _THx + jmp _THw +_THw2: shr ecx,1 + jnc _THLp4 + stosb + inc edi + jecxz _THx +_THLp4: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _THLp4 + +_THx: or edx,edx + jz _THNxt + jmp _THLp2 + +_THJ: neg al // Do jump + add edi,eax + sub edx,eax + jnz _THLp2 +_THNxt: pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz _THLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeI: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TILp1: cmp edi,dword ptr [ClipY] + jb _TIC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TIx +_TIC1: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TIOd + xor eax,eax + shr ecx,2 + jnc _TILp2 + inc edi + stosb + jecxz _TIx +_TILp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TILp2 + jmp _TIx + +_TIOd: xor eax,eax + shr ecx,2 + jnc _TILp3 + stosb + inc edi + jecxz _TIx +_TILp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TILp3 + +_TIx: sub edi,NBUFFW32 + or edx,edx + jz _TIb + sub edx,2 + jmp _TILp1 + +_TIb: mov edx,2 +_TILp4: cmp edi,dword ptr [ClipY] + jb _TIC2 + add esi,32 + sub esi,edx + add edi,32 + jmp _TIx2 +_TIC2: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TIOd2 + xor eax,eax + shr ecx,2 + jnc _TILp5 + inc edi + stosb + jecxz _TIx2 +_TILp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TILp5 + jmp _TIx2 + +_TIOd2: xor eax,eax + shr ecx,2 + jnc _TILp6 + stosb + inc edi + jecxz _TIx2 +_TILp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TILp6 + +_TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TILp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeJ: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TJLp1: cmp edi,dword ptr [ClipY] + jb _TJC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TJx +_TJC1: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TJOd + xor eax,eax + shr ecx,2 + jnc _TJLp2 + inc edi + stosb + jecxz _TJx +_TJLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TJLp2 + jmp _TJx + +_TJOd: xor eax,eax + shr ecx,2 + jnc _TJLp3 + stosb + inc edi + jecxz _TJx +_TJLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TJLp3 + +_TJx: sub edi,NBUFFW32 + or edx,edx + jz _TJb + add edi,edx + sub edx,2 + jmp _TJLp1 + +_TJb: mov edx,2 +_TJLp4: cmp edi,dword ptr [ClipY] + jb _TJC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TJx2 +_TJC2: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TJOd2 + xor eax,eax + shr ecx,2 + jnc _TJLp5 + inc edi + stosb + jecxz _TJx2 +_TJLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TJLp5 + jmp _TJx2 + +_TJOd2: xor eax,eax + shr ecx,2 + jnc _TJLp6 + stosb + inc edi + jecxz _TJx2 +_TJLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TJLp6 + +_TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TJLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeK: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TKLp1: cmp edi,dword ptr [ClipY] + jb _TKC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TKx +_TKC1: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TKOd + xor eax,eax + shr ecx,2 + jnc _TKLp2 + inc edi + stosb + jecxz _TKx +_TKLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TKLp2 + jmp _TKx + +_TKOd: xor eax,eax + shr ecx,2 + jnc _TKLp3 + stosb + inc edi + jecxz _TKx +_TKLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TKLp3 + +_TKx: sub edi,NBUFFW32 + or edx,edx + jz _TKb + sub edx,2 + jmp _TKLp1 + +_TKb: mov edx,8 +_TKLp4: cmp edi,dword ptr [ClipY] + jb _TKC2 + add esi,32 + add edi,32 + jmp _TKC3 +_TKC2: mov ecx,8 + xor eax,eax +_TKLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TKLp5 +_TKC3: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _TKC4 + add esi,32 + add edi,32 + jmp _TKC5 +_TKC4: mov ecx,8 + xor eax,eax +_TKLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TKLp6 +_TKC5: sub edi,NBUFFW32 + dec edx + jnz _TKLp4 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeL: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +_TLLp1: cmp edi,dword ptr [ClipY] + jb _TLC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TLx +_TLC1: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz _TLOd + xor eax,eax + shr ecx,2 + jnc _TLLp2 + inc edi + stosb + jecxz _TLx +_TLLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TLLp2 + jmp _TLx + +_TLOd: xor eax,eax + shr ecx,2 + jnc _TLLp3 + stosb + inc edi + jecxz _TLx +_TLLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TLLp3 + +_TLx: sub edi,NBUFFW32 + or edx,edx + jz _TLb + add edi,edx + sub edx,2 + jmp _TLLp1 + +_TLb: mov edx,8 +_TLLp4: cmp edi,dword ptr [ClipY] + jb _TLC2 + add esi,32 + add edi,32 + jmp _TLC3 +_TLC2: mov ecx,8 + xor eax,eax +_TLLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + loop _TLLp5 +_TLC3: sub edi,NBUFFW32 + + cmp edi,dword ptr [ClipY] + jb _TLC4 + add esi,32 + add edi,32 + jmp _TLC5 +_TLC4: mov ecx,8 + xor eax,eax +_TLLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + loop _TLLp6 +_TLC5: sub edi,NBUFFW32 + dec edx + jnz _TLLp4 + jmp _Done + +xbyte1: // blank first + + shr ecx,1 + jnc xword2 + inc esi + inc edi + +xword1: // xlat first + shr ecx,1 + jnc xquadt1 + mov dl,[esi] + mov dl,[ebx+edx] + add esi,2 + mov [edi],dl + add edi,2 + +xquadt1: + test cl,cl + jz xend + +xquad1: // xlat first +/* debug + shl ecx,2 + add esi,ecx + add edi,ecx + ret +*/ + + mov eax,[esi] + add esi,4 + mov dl,al + shr eax,16 + mov dl,[ebx+edx] + mov [edi],dl + mov dl,al + add edi,4 + mov dl,[ebx+edx] + dec ecx + mov [edi-2],dl + jnz xquad1 + + ret + + +xbyte2: // xlat first + + shr ecx,1 + jnc xword1 + mov dl,[esi] + mov dl,[ebx+edx] + inc esi + mov [edi],dl + inc edi + +xword2: // blank first + shr ecx,1 + jnc xquadt2 + mov dl,[esi+1] + mov dl,[ebx+edx] + add esi,2 + mov [edi+1],dl + add edi,2 + +xquadt2: + test cl,cl + jz xend + +xquad2: // blank first +/* debug + shl ecx,2 + add esi,ecx + add edi,ecx + ret +*/ + + + mov eax,[esi] + add esi,4 + mov dl,ah + shr eax,16 + mov dl,[ebx+edx] + mov [edi+1],dl + mov dl,ah + add edi,4 + mov dl,[ebx+edx] + dec ecx + mov [edi-1],dl + jnz xquad2 + +xend: + ret + +_Done: nop + + } // end of asm block +} + +/*-----------------------------------------------------------------------** +** Now with Y clipping and Masking Transparency +**-----------------------------------------------------------------------*/ + +void TCDecodeM12Tile (BYTE *pDecodeTo, long *mask) +{ + t = µoffset[0][0]; + __asm { + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,dword ptr [nLVal] + or al,al + jz _NoLt + cmp al,byte ptr [lightmax] + jz _Black + + mov eax,dword ptr [gdwPNum] + and eax,08000h + jnz _Speed + + mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov ebx,dword ptr [nLVal]; // Light conversion table + shl ebx,8 + add ebx,dword ptr [pLightTbl]; + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz _Type0 // Solid 32x32 block + cmp ax,1 + jz _Type1 // 32x32 block with '0' holes + cmp ax,2 + jz _Type2 // Left Triangle + cmp ax,3 + jz _Type3 // Right Triangle + cmp ax,4 + jz _Type4 // Left Triangle to wall + jmp _Type5 // Right Triangle to wall + +_Speed: mov esi,dword ptr [t] + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [nLVal] + shl eax,2 + add esi,eax // Source + mov eax,dword ptr [esi] + mov esi,dword ptr [pSpeedCels] + add esi,eax + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +_SCmp: cmp ax,8 + jz _Type8 // PreTrans Solid 32x32 block + cmp ax,9 + jz _Type9 // PreTrans 32x32 block with '0' holes + cmp ax,10 + jz _TypeA // PreTrans Left Triangle + cmp ax,11 + jz _TypeB // PreTrans Right Triangle + cmp ax,12 + jz _TypeC // PreTrans Left Triangle to wall + jmp _TypeD // PreTrans Right Triangle to wall + +_NoLt: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RNoLt + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RNoLt: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp _SCmp + +_Black: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RBlk + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RBlk: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz _TypeG // Black Trans Solid 32x32 block + cmp ax,1 + jz _TypeH // Black Trans 32x32 block with '0' holes + cmp ax,2 + jz _TypeI // Black Trans Left Triangle + cmp ax,3 + jz _TypeJ // Black Trans Right Triangle + cmp ax,4 + jz _TypeK // Black Trans Left Triangle to wall + jmp _TypeL // Black Trans Right Triangle to wall + +/*-----------------------------------------------------------------------*/ + +_Type0: mov edx,32 +_T0Lp1: cmp edi,dword ptr [ClipY] + jb _T0C1 + add esi,32 + add edi,32 + jmp _T0C2 +_T0C1: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_T0Lp2: lodsb + shl edx,1 + jnc _T0S1 + xlatb + mov byte ptr [edi],al +_T0S1: inc edi + loop _T0Lp2 + pop edx +_T0C2: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _T0Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type1: mov ecx,32 + +_T1Lp1: push ecx + mov eax,dword ptr [mask] + mov eax,dword ptr [eax] + mov dword ptr [cm],eax + + mov edx,32 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _T1C1 + add esi,eax + add edi,eax + jmp _T1x +_T1C1: mov ecx,eax + push edx + mov edx,dword ptr [cm] +_T1Lp3: lodsb + shl edx,1 + jnc _T1S1 + xlatb + mov byte ptr [edi],al +_T1S1: inc edi + loop _T1Lp3 + mov dword ptr [cm],edx + pop edx +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz _T1S2 + push eax + mov eax,dword ptr [cm] + shl eax,cl + mov dword ptr [cm],eax + pop eax +_T1S2: sub edx,eax + jnz _T1Lp2 +_T1Nxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec ecx + jnz _T1Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type2: mov edx,30 +_T2Lp1: cmp edi,dword ptr [ClipY] + jb _T2C1 + add esi,32 + sub esi,edx + add edi,32 + jmp _T2x +_T2C1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T2Lp2 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T2x +_T2Lp2: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T2Lp2 +_T2x: sub edi,NBUFFW32 + or edx,edx + jz _T2b + sub edx,2 + jmp _T2Lp1 + +_T2b: mov edx,2 +_T2Lp3: cmp edi,dword ptr [ClipY] + jb _T2C2 + add esi,32 + sub esi,edx + add edi,32 + jmp _T2x2 +_T2C2: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T2Lp4 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T2x2 +_T2Lp4: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T2Lp4 +_T2x2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _T2Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type3: mov edx,30 +_T3Lp1: cmp edi,dword ptr [ClipY] + jb _T3C1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T3x +_T3C1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T3Lp2 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T3x +_T3Lp2: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T3Lp2 +_T3x: sub edi,NBUFFW32 + or edx,edx + jz _T3b + add edi,edx + sub edx,2 + jmp _T3Lp1 + +_T3b: mov edx,2 +_T3Lp3: cmp edi,dword ptr [ClipY] + jb _T3C2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T3x2 +_T3C2: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T3Lp4 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T3x2 +_T3Lp4: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T3Lp4 +_T3x2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _T3Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type4: mov edx,30 +_T4Lp1: cmp edi,dword ptr [ClipY] + jb _T4C1 + add esi,32 + sub esi,edx + add edi,32 + jmp _T4x +_T4C1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T4Lp2 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T4x +_T4Lp2: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T4Lp2 +_T4x: sub edi,NBUFFW32 + or edx,edx + jz _T4b + sub edx,2 + jmp _T4Lp1 + +_T4b: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_T4Lp3: cmp edi,dword ptr [ClipY] + jb _T4C2 + add esi,32 + add edi,32 + jmp _T4C3 +_T4C2: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_T4Lp4: lodsb + shl edx,1 + jnc _T4S1 + xlatb + mov byte ptr [edi],al +_T4S1: inc edi + loop _T4Lp4 + pop edx +_T4C3: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _T4Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type5: mov edx,30 +_T5Lp1: cmp edi,dword ptr [ClipY] + jb _T5C1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T5x +_T5C1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _T5Lp2 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T5x +_T5Lp2: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T5Lp2 +_T5x: sub edi,NBUFFW32 + or edx,edx + jz _T5b + add edi,edx + sub edx,2 + jmp _T5Lp1 + +_T5b: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_T5Lp3: cmp edi,dword ptr [ClipY] + jb _T5C2 + add esi,32 + add edi,32 + jmp _T5C3 +_T5C2: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_T5Lp4: lodsb + shl edx,1 + jnc _T5S1 + xlatb + mov byte ptr [edi],al +_T5S1: inc edi + loop _T5Lp4 + pop edx +_T5C3: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _T5Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type8: mov edx,32 +_T8Lp1: cmp edi,dword ptr [ClipY] + jb _T8C1 + add esi,32 + add edi,32 + jmp _T8C2 +_T8C1: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_T8Lp2: lodsb + shl edx,1 + jnc _T8S1 + mov byte ptr [edi],al +_T8S1: inc edi + loop _T8Lp2 + pop edx +_T8C2: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _T8Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type9: mov ecx,32 + +_T9Lp1: push ecx + mov eax,dword ptr [mask] + mov eax,dword ptr [eax] + mov dword ptr [cm],eax + + mov edx,32 + +_T9Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T9J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _T9C1 + add esi,eax + add edi,eax + jmp _T9x +_T9C1: mov ecx,eax + push edx + mov edx,dword ptr [cm] +_T9Lp3: lodsb + shl edx,1 + jnc _T9S1 + mov byte ptr [edi],al +_T9S1: inc edi + loop _T9Lp3 + mov dword ptr [cm],edx + pop edx +_T9x: or edx,edx + jz _T9Nxt + jmp _T9Lp2 + +_T9J: neg al // Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz _T9S2 + mov ebx,dword ptr [cm] + shl ebx,cl + mov dword ptr [cm],ebx +_T9S2: sub edx,eax + jnz _T9Lp2 +_T9Nxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec ecx + jnz _T9Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeA: mov edx,30 +_TALp1: cmp edi,dword ptr [ClipY] + jb _TAC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TAx +_TAC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TALp2 + movsw + jecxz _TAx +_TALp2: rep movsd +_TAx: sub edi,NBUFFW32 + or edx,edx + jz _TAb + sub edx,2 + jmp _TALp1 + +_TAb: mov edx,2 +_TALp3: cmp edi,dword ptr [ClipY] + jb _TAC2 + add esi,32 + sub esi,edx + add edi,32 + jmp _TAx2 +_TAC2: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TALp4 + movsw + jecxz _TAx2 +_TALp4: rep movsd +_TAx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TALp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeB: mov edx,30 +_TBLp1: cmp edi,dword ptr [ClipY] + jb _TBC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TBx +_TBC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TBLp2 + movsw + jecxz _TBx +_TBLp2: rep movsd +_TBx: sub edi,NBUFFW32 + or edx,edx + jz _TBb + add edi,edx + sub edx,2 + jmp _TBLp1 + +_TBb: mov edx,2 +_TBLp3: cmp edi,dword ptr [ClipY] + jb _TBC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TBx2 +_TBC2: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TBLp4 + movsw + jecxz _TBx2 +_TBLp4: rep movsd +_TBx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TBLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeC: mov edx,30 +_TCLp1: cmp edi,dword ptr [ClipY] + jb _TCC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TCx +_TCC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TCLp2 + movsw + jecxz _TCx +_TCLp2: rep movsd +_TCx: sub edi,NBUFFW32 + or edx,edx + jz _TCb + sub edx,2 + jmp _TCLp1 + +_TCb: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_TCLp3: cmp edi,dword ptr [ClipY] + jb _TCC2 + add esi,32 + add edi,32 + jmp _TCC3 +_TCC2: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_TCLp4: lodsb + shl edx,1 + jnc _TCS1 + mov byte ptr [edi],al +_TCS1: inc edi + loop _TCLp4 + pop edx +_TCC3: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TCLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeD: mov edx,30 +_TDLp1: cmp edi,dword ptr [ClipY] + jb _TDC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TDx +_TDC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TDLp2 + movsw + jecxz _TDx +_TDLp2: rep movsd +_TDx: sub edi,NBUFFW32 + or edx,edx + jz _TDb + add edi,edx + sub edx,2 + jmp _TDLp1 + +_TDb: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_TDLp3: cmp edi,dword ptr [ClipY] + jb _TDC2 + add esi,32 + add edi,32 + jmp _TDC3 +_TDC2: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + mov ecx,32 +_TDLp4: lodsb + shl edx,1 + jnc _TDS1 + mov byte ptr [edi],al +_TDS1: inc edi + loop _TDLp4 + pop edx +_TDC3: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TDLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeG: mov edx,32 +_TGLp1: cmp edi,dword ptr [ClipY] + jb _TGC1 + add esi,32 + add edi,32 + jmp _TGC2 +_TGC1: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +_TGLp2: shl edx,1 + jnc _TGS1 + mov byte ptr [edi],al +_TGS1: inc edi + loop _TGLp2 + pop edx +_TGC2: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TGLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeH: mov ecx,32 + +_THLp1: push ecx + mov eax,dword ptr [mask] + mov eax,dword ptr [eax] + mov dword ptr [cm],eax + + mov edx,32 + +_THLp2: xor eax,eax // Load control byte + lodsb + or al,al + js _THJ + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _THC1 + add esi,eax + add edi,eax + jmp _THx +_THC1: mov ecx,eax + add esi,ecx + push edx + mov edx,dword ptr [cm] + xor eax,eax +_THLp3: shl edx,1 + jnc _THS1 + mov byte ptr [edi],al +_THS1: inc edi + loop _THLp3 + mov dword ptr [cm],edx + pop edx +_THx: or edx,edx + jz _THNxt + jmp _THLp2 + +_THJ: neg al // Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz _THS2 + mov ebx,dword ptr [cm] + shl ebx,cl + mov dword ptr [cm],ebx +_THS2: sub edx,eax + jnz _THLp2 +_THNxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec ecx + jnz _THLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeI: mov edx,30 + xor eax,eax +_TILp1: cmp edi,dword ptr [ClipY] + jb _TIC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TIx +_TIC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TILp2 + stosw + jecxz _TIx +_TILp2: rep stosd +_TIx: sub edi,NBUFFW32 + or edx,edx + jz _TIb + sub edx,2 + jmp _TILp1 + +_TIb: mov edx,2 +_TILp3: cmp edi,dword ptr [ClipY] + jb _TIC2 + add esi,32 + sub esi,edx + add edi,32 + jmp _TIx2 +_TIC2: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TILp4 + stosw + jecxz _TIx2 +_TILp4: rep stosd +_TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TILp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeJ: mov edx,30 + xor eax,eax +_TJLp1: cmp edi,dword ptr [ClipY] + jb _TJC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TJx +_TJC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TJLp2 + stosw + jecxz _TJx +_TJLp2: rep stosd +_TJx: sub edi,NBUFFW32 + or edx,edx + jz _TJb + add edi,edx + sub edx,2 + jmp _TJLp1 + +_TJb: mov edx,2 +_TJLp3: cmp edi,dword ptr [ClipY] + jb _TJC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TJx2 +_TJC2: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TJLp4 + stosw + jecxz _TJx2 +_TJLp4: rep stosd +_TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TJLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeK: mov edx,30 + xor eax,eax +_TKLp1: cmp edi,dword ptr [ClipY] + jb _TKC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TKx +_TKC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TKLp2 + stosw + jecxz _TKx +_TKLp2: rep stosd +_TKx: sub edi,NBUFFW32 + or edx,edx + jz _TKb + sub edx,2 + jmp _TKLp1 + +_TKb: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_TKLp3: cmp edi,dword ptr [ClipY] + jb _TKC2 + add esi,32 + add edi,32 + jmp _TKC3 +_TKC2: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +_TKLp4: shl edx,1 + jnc _TKS1 + mov byte ptr [edi],al +_TKS1: inc edi + loop _TKLp4 + pop edx +_TKC3: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TKLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeL: mov edx,30 + xor eax,eax +_TLLp1: cmp edi,dword ptr [ClipY] + jb _TLC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TLx +_TLC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TLLp2 + stosw + jecxz _TLx +_TLLp2: rep stosd +_TLx: sub edi,NBUFFW32 + or edx,edx + jz _TLb + add edi,edx + sub edx,2 + jmp _TLLp1 + +_TLb: mov eax,dword ptr [mask] + sub eax,64 + mov dword ptr [mask],eax + mov edx,16 +_TLLp3: cmp edi,dword ptr [ClipY] + jb _TLC2 + add esi,32 + add edi,32 + jmp _TLC3 +_TLC2: push edx + mov eax,dword ptr [mask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +_TLLp4: shl edx,1 + jnc _TLS1 + mov byte ptr [edi],al +_TLS1: inc edi + loop _TLLp4 + pop edx +_TLC3: sub edi,NBUFFW32 + mov eax,dword ptr [mask] + sub eax,4 + mov dword ptr [mask],eax + dec edx + jnz _TLLp3 + +_Done: nop + + } // end of asm block +} + + +/*-----------------------------------------------------------------------** +** Now with Y clipping +**-----------------------------------------------------------------------*/ + +void CDecodeMicroTile (BYTE *pDecodeTo) +{ + if (nTrans) { + switch (gbPartialTrans) { + case PART_TRANS_NONE: + TCDecodeMicroTile(pDecodeTo); + return; + case PART_TRANS_LEFT: + wt = nWTypeTable[gnPieceNum]; + if ((wt == WTYPE_LEFT) || (wt == WTYPE_ULC)) { + TCDecodeM12Tile(pDecodeTo, &sgLeftMask[31]); + return; + } + if (wt == WTYPE_LRC) { + TCDecodeM12Tile(pDecodeTo, &sgRightMask[31]); + return; + } + break; + case PART_TRANS_RIGHT: + wt = nWTypeTable[gnPieceNum]; + if ((wt == WTYPE_RIGHT) || (wt == WTYPE_ULC)) { + TCDecodeM12Tile(pDecodeTo, &sgRightMask[31]); + return; + } + if (wt == WTYPE_LRC) { + TCDecodeM12Tile(pDecodeTo, &sgLeftMask[31]); + return; + } + } + } + t = µoffset[0][0]; + __asm { + + mov edi,dword ptr [pDecodeTo] // Dest + + mov eax,dword ptr [nLVal] + or al,al + jz _NoLt + cmp al,byte ptr [lightmax] + jz _Black + + mov eax,dword ptr [gdwPNum] + and eax,08000h + jnz _Speed + + mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov ebx,dword ptr [nLVal]; // Light conversion table + shl ebx,8 + add ebx,dword ptr [pLightTbl]; + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz _Type0 // Solid 32x32 block + cmp ax,1 + jz _Type1 // 32x32 block with '0' holes + cmp ax,2 + jz _Type2 // Left Triangle + cmp ax,3 + jz _Type3 // Right Triangle + cmp ax,4 + jz _Type4 // Left Triangle to wall + jmp _Type5 // Right Triangle to wall + +_Speed: mov esi,dword ptr [t] + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [nLVal] + shl eax,2 + add esi,eax // Source + mov eax,dword ptr [esi] + mov esi,dword ptr [pSpeedCels] + add esi,eax + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +_SCmp: cmp ax,8 + jz _Type8 // PreTrans Solid 32x32 block + cmp ax,9 + jz _Type9 // PreTrans 32x32 block with '0' holes + cmp ax,10 + jz _TypeA // PreTrans Left Triangle + cmp ax,11 + jz _TypeB // PreTrans Right Triangle + cmp ax,12 + jz _TypeC // PreTrans Left Triangle to wall + jmp _TypeD // PreTrans Right Triangle to wall + +_NoLt: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RNoLt + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RNoLt: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp _SCmp + +_Black: mov eax,dword ptr [gdwPNum] + and eax,08000h + jz _RBlk + + mov esi,dword ptr [t] // Get old micro tile number + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [gdwPNum],eax + +_RBlk: mov ebx,dword ptr [pDungeonCels] + mov esi,ebx + mov eax,dword ptr [gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] // Source + + mov eax,dword ptr [gdwPNum] // Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz _TypeG // Black Trans Solid 32x32 block + cmp ax,1 + jz _TypeH // Black Trans 32x32 block with '0' holes + cmp ax,2 + jz _TypeI // Black Trans Left Triangle + cmp ax,3 + jz _TypeJ // Black Trans Right Triangle + cmp ax,4 + jz _TypeK // Black Trans Left Triangle to wall + jmp _TypeL // Black Trans Right Triangle to wall + +/*-----------------------------------------------------------------------*/ + +_Type0: mov edx,32 + push ebp +_T0Lp1: + push edx + cmp edi,dword ptr [ClipY] + jb _T0C1 + add esi,32 + add edi,32 + jmp _T0C2 +_T0C1: + xor edx,edx + mov ebp,8 +_T0Lp2: + mov eax,[esi] + add esi,4 + ror eax,16 + mov dl,al + mov cl,[ebx+edx] + mov dl,ah + mov ch,[ebx+edx] + ror eax,16 + shl ecx,16 + mov dl,al + mov cl,[ebx+edx] + mov dl,ah + mov ch,[ebx+edx] + mov [edi],ecx + add edi,4 + + dec ebp + jnz _T0Lp2 +_T0C2: + sub edi,NBUFFW32 + pop edx + dec edx + jnz _T0Lp1 + pop ebp + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type1: push ebp + mov ecx,32 +_T1Lp1: push ecx + mov ebp,32 +_T1Lp2: + xor eax,eax // Load control byte + mov al,[esi] + inc esi + + or al,al + jns _T1NoSkip + neg al + add edi,eax + sub ebp,eax + jmp _T1continue +_T1NoSkip: + sub ebp,eax + cmp edi,dword ptr [ClipY] + jb _T1NotCliped + add esi,eax + add edi,eax + jmp _T1continue +_T1NotCliped: + mov ecx,eax + call xbytes +_T1continue: + or ebp,ebp + jnz _T1Lp2 + + pop ecx + sub edi,NBUFFW32 + dec ecx + jnz _T1Lp1 + pop ebp + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type2: + push ebp + mov ebp,30 +_T2Lp1: + cmp edi,dword ptr [ClipY] + jb _T2NotClipped + add esi,32 + add edi,32 + sub esi,ebp + jmp _T2continue +_T2NotClipped: + add edi,ebp + mov ecx,32 + sub ecx,ebp + call xbytes +_T2continue: + sub edi,NBUFFW32 + sub ebp,2 + jge _T2Lp1 + + + mov ebp,2 +_T2Lp2: + cmp edi,dword ptr [ClipY] + jb _T2NotClipped2 + add esi,32 + add edi,32 + sub esi,ebp + jmp _T2continue2 +_T2NotClipped2: + add edi,ebp + mov ecx,32 + sub ecx,ebp + call xbytes +_T2continue2: + add ebp,2 + sub edi,NBUFFW32 + cmp ebp,32 + jnz _T2Lp2 + + pop ebp + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type3: mov edx,30 +_T3Lp1: cmp edi,dword ptr [ClipY] + jb _T3C1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T3x +_T3C1: mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + +_T3x: sub edi,NBUFFW32 + or edx,edx + jz _T3b + add edi,edx + sub edx,2 + jmp _T3Lp1 + +_T3b: mov edx,2 +_T3Lp3: cmp edi,dword ptr [ClipY] + jb _T3C2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T3x2 +_T3C2: mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + +_T3x2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _T3Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type4: mov edx,30 +_T4Lp1: cmp edi,dword ptr [ClipY] + jb _T4C1 + add esi,32 + sub esi,edx + add edi,32 + jmp _T4x +_T4C1: add edi,edx + mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + +_T4x: sub edi,NBUFFW32 + or edx,edx + jz _T4b + sub edx,2 + jmp _T4Lp1 + +_T4b: mov edx,16 +_T4Lp3: cmp edi,dword ptr [ClipY] + jb _T4C2 + add esi,32 + add edi,32 + jmp _T4C3 +_T4C2: mov ecx,8 + + push edx + call xquads + pop edx + +_T4C3: sub edi,NBUFFW32 + dec edx + jnz _T4Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type5: mov edx,30 +_T5Lp1: cmp edi,dword ptr [ClipY] + jb _T5C1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _T5x +_T5C1: mov ecx,32 + sub ecx,edx + + push edx + call xbytes + pop edx + +_T5x: sub edi,NBUFFW32 + or edx,edx + jz _T5b + add edi,edx + sub edx,2 + jmp _T5Lp1 + +_T5b: mov edx,16 +_T5Lp3: cmp edi,dword ptr [ClipY] + jb _T5C2 + add esi,32 + add edi,32 + jmp _T5C3 +_T5C2: mov ecx,8 + + push edx + call xquads + pop edx + +_T5C3: sub edi,NBUFFW32 + dec edx + jnz _T5Lp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type8: mov edx,32 +_T8Lp1: cmp edi,dword ptr [ClipY] + jb _T8C1 + add esi,32 + add edi,32 + jmp _T8C2 +_T8C1: mov ecx,8 + rep movsd +_T8C2: sub edi,NBUFFW32 + dec edx + jnz _T8Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_Type9: mov ecx,32 + +_T9Lp1: push ecx + mov edx,32 + +_T9Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T9J + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _T9C1 + add esi,eax + add edi,eax + jmp _T9x +_T9C1: mov ecx,eax + shr ecx,1 + jnc _T9w + movsb + jecxz _T9x +_T9w: shr ecx,1 + jnc _T9Lp3 + movsw + jecxz _T9x +_T9Lp3: rep movsd +_T9x: or edx,edx + jz _T9Nxt + jmp _T9Lp2 + +_T9J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T9Lp2 +_T9Nxt: pop ecx + sub edi,NBUFFW32 + loop _T9Lp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeA: mov edx,30 +_TALp1: cmp edi,dword ptr [ClipY] + jb _TAC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TAx +_TAC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TALp2 + movsw + jecxz _TAx +_TALp2: rep movsd +_TAx: sub edi,NBUFFW32 + or edx,edx + jz _TAb + sub edx,2 + jmp _TALp1 + +_TAb: mov edx,2 +_TALp3: cmp edi,dword ptr [ClipY] + jb _TAC2 + add esi,32 + sub esi,edx + add edi,32 + jmp _TAx2 +_TAC2: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TALp4 + movsw + jecxz _TAx2 +_TALp4: rep movsd +_TAx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TALp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeB: mov edx,30 +_TBLp1: cmp edi,dword ptr [ClipY] + jb _TBC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TBx +_TBC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TBLp2 + movsw + jecxz _TBx +_TBLp2: rep movsd +_TBx: sub edi,NBUFFW32 + or edx,edx + jz _TBb + add edi,edx + sub edx,2 + jmp _TBLp1 + +_TBb: mov edx,2 +_TBLp3: cmp edi,dword ptr [ClipY] + jb _TBC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TBx2 +_TBC2: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TBLp4 + movsw + jecxz _TBx2 +_TBLp4: rep movsd +_TBx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TBLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeC: mov edx,30 +_TCLp1: cmp edi,dword ptr [ClipY] + jb _TCC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TCx +_TCC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TCLp2 + movsw + jecxz _TCx +_TCLp2: rep movsd +_TCx: sub edi,NBUFFW32 + or edx,edx + jz _TCb + sub edx,2 + jmp _TCLp1 + +_TCb: mov edx,16 +_TCLp3: cmp edi,dword ptr [ClipY] + jb _TCC2 + add esi,32 + add edi,32 + jmp _TCC3 +_TCC2: mov ecx,8 + rep movsd +_TCC3: sub edi,NBUFFW32 + dec edx + jnz _TCLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeD: mov edx,30 +_TDLp1: cmp edi,dword ptr [ClipY] + jb _TDC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TDx +_TDC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TDLp2 + movsw + jecxz _TDx +_TDLp2: rep movsd +_TDx: sub edi,NBUFFW32 + or edx,edx + jz _TDb + add edi,edx + sub edx,2 + jmp _TDLp1 + +_TDb: mov edx,16 +_TDLp3: cmp edi,dword ptr [ClipY] + jb _TDC2 + add esi,32 + add edi,32 + jmp _TDC3 +_TDC2: mov ecx,8 + rep movsd +_TDC3: sub edi,NBUFFW32 + dec edx + jnz _TDLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeG: mov edx,32 + xor eax,eax +_TGLp1: cmp edi,dword ptr [ClipY] + jb _TGC1 + add esi,32 + add edi,32 + jmp _TGC2 +_TGC1: mov ecx,8 + rep stosd +_TGC2: sub edi,NBUFFW32 + dec edx + jnz _TGLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeH: mov ecx,32 + +_THLp1: push ecx + mov edx,32 + +_THLp2: xor eax,eax // Load control byte + lodsb + or al,al + js _THJ + + sub edx,eax + cmp edi,dword ptr [ClipY] + jb _THC1 + add esi,eax + add edi,eax + jmp _THx +_THC1: mov ecx,eax + add esi,ecx + xor eax,eax + shr ecx,1 + jnc _THw + stosb + jecxz _THx +_THw: shr ecx,1 + jnc _THLp3 + stosw + jecxz _THx +_THLp3: rep stosd +_THx: or edx,edx + jz _THNxt + jmp _THLp2 + +_THJ: neg al // Do jump + add edi,eax + sub edx,eax + jnz _THLp2 +_THNxt: pop ecx + sub edi,NBUFFW32 + loop _THLp1 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeI: mov edx,30 + xor eax,eax +_TILp1: cmp edi,dword ptr [ClipY] + jb _TIC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TIx +_TIC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TILp2 + stosw + jecxz _TIx +_TILp2: rep stosd +_TIx: sub edi,NBUFFW32 + or edx,edx + jz _TIb + sub edx,2 + jmp _TILp1 + +_TIb: mov edx,2 +_TILp3: cmp edi,dword ptr [ClipY] + jb _TIC2 + add esi,32 + sub esi,edx + add edi,32 + jmp _TIx2 +_TIC2: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TILp4 + stosw + jecxz _TIx2 +_TILp4: rep stosd +_TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz _TILp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeJ: mov edx,30 + xor eax,eax +_TJLp1: cmp edi,dword ptr [ClipY] + jb _TJC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TJx +_TJC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TJLp2 + stosw + jecxz _TJx +_TJLp2: rep stosd +_TJx: sub edi,NBUFFW32 + or edx,edx + jz _TJb + add edi,edx + sub edx,2 + jmp _TJLp1 + +_TJb: mov edx,2 +_TJLp3: cmp edi,dword ptr [ClipY] + jb _TJC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TJx2 +_TJC2: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TJLp4 + stosw + jecxz _TJx2 +_TJLp4: rep stosd +_TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz _TJLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeK: mov edx,30 + xor eax,eax +_TKLp1: cmp edi,dword ptr [ClipY] + jb _TKC1 + add esi,32 + sub esi,edx + add edi,32 + jmp _TKx +_TKC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TKLp2 + stosw + jecxz _TKx +_TKLp2: rep stosd +_TKx: sub edi,NBUFFW32 + or edx,edx + jz _TKb + sub edx,2 + jmp _TKLp1 + +_TKb: mov edx,16 +_TKLp3: cmp edi,dword ptr [ClipY] + jb _TKC2 + add esi,32 + add edi,32 + jmp _TKC3 +_TKC2: mov ecx,8 + rep stosd +_TKC3: sub edi,NBUFFW32 + dec edx + jnz _TKLp3 + jmp _Done + +/*-----------------------------------------------------------------------*/ + +_TypeL: mov edx,30 + xor eax,eax +_TLLp1: cmp edi,dword ptr [ClipY] + jb _TLC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp _TLx +_TLC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc _TLLp2 + stosw + jecxz _TLx +_TLLp2: rep stosd +_TLx: sub edi,NBUFFW32 + or edx,edx + jz _TLb + add edi,edx + sub edx,2 + jmp _TLLp1 + +_TLb: mov edx,16 +_TLLp3: cmp edi,dword ptr [ClipY] + jb _TLC2 + add esi,32 + add edi,32 + jmp _TLC3 +_TLC2: mov ecx,8 + rep stosd +_TLC3: sub edi,NBUFFW32 + dec edx + jnz _TLLp3 + + jmp _Done + +xbytes: + + shr cl,1 + jnc xwords + + mov dl, [esi] + mov dl, [ebx+edx] + mov [edi],dl + + add esi,1 + add edi,1 + +xwords: + shr cl,1 + jnc xquads + + mov dl, [esi] + mov ch, [ebx+edx] + + mov [edi],ch + mov dl, [esi+1] + + mov ch, [ebx+edx] + mov [edi+1],ch + + add esi,2 + add edi,2 + +xquads: + test cl,cl + jz xend + +xnext: + mov eax, [esi] + add esi,4 + + mov dl,al + mov ch,[ebx+edx] + + mov dl,ah + ror eax,16 + mov [edi],ch + + mov ch,[ebx+edx] + + mov dl,al + mov [edi+1],ch + + mov ch,[ebx+edx] + + mov dl,ah + mov [edi+2],ch + + mov ch,[ebx+edx] + mov [edi+3],ch + + add edi,4 + + dec cl + jnz xnext + +xend: + ret + +_Done: + + } // end of asm block +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawBlankMini(BYTE *pDecodeTo) +{ + __asm { + mov edi,dword ptr [pDecodeTo] // Dest + + mov edx,30 + mov ebx,1 + xor eax,eax + //mov eax,092929292h // yellow +_BLp1: add edi,edx + mov ecx,ebx + rep stosd + add edi,edx + sub edi,NBUFFW64 + or edx,edx + jz _Bb + sub edx,2 + inc ebx + jmp _BLp1 + +_Bb: mov edx,2 + mov ebx,15 +_BLp2: add edi,edx + mov ecx,ebx + rep stosd + add edi,edx + sub edi,NBUFFW64 + dec ebx + add edx,2 + cmp edx,32 + jnz _BLp2 + } +} + diff --git a/src/SCRLASM.H b/src/SCRLASM.H new file mode 100644 index 0000000..5796107 --- /dev/null +++ b/src/SCRLASM.H @@ -0,0 +1,38 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/SCRLASM.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +//************************************************************************* +// Flags for partial transparency (bottoms of trans walls, etc.) +//************************************************************************* +enum { + PART_TRANS_NONE, + PART_TRANS_LEFT, + PART_TRANS_RIGHT, +}; + + + +#define NBUFFW32 800 +#define NBUFFW64 832 + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +extern "C" void _fastcall DrawMTileClipTop(BYTE *pDecodeTo); +extern "C" void _fastcall DrawMTileClipBottom(BYTE *pDecodeTo); diff --git a/src/SCROLL.ASM b/src/SCROLL.ASM new file mode 100644 index 0000000..2c783c8 --- /dev/null +++ b/src/SCROLL.ASM @@ -0,0 +1,10181 @@ +;************************************************************** +;* scroll.asm +;* created 9.27.96 +;* written by Collin Murray +;************************************************************** +.386p +.model FLAT +LOCALS +JUMPS + +;include diablo.h +;include scrlasm.h +;include gendung.h +;include lighting.h + +WTYPE_NONE equ 0 +WTYPE_LEFT equ 1 +WTYPE_RIGHT equ 2 +WTYPE_ULC equ 3 +WTYPE_LRC equ 4 + +PART_TRANS_NONE equ 0 +PART_TRANS_LEFT equ 1 +PART_TRANS_RIGHT equ 2 +NBUFFW32 equ 800 +NBUFFW64 equ 832 + +;*********************************************************** +;* segment +;*********************************************************** +.DATA + + ;*********************************************************** + ;* Externs from scrollrt.cpp + ;*********************************************************** + extrn _nLVal :dword + extrn _glClipY :dword + extrn _gnPieceNum :dword + extrn _nTrans :dword + extrn _gdwPNum :dword + extrn _gbPartialTrans :byte + + ;*********************************************************** + ;* Externs from lighting.cpp + ;*********************************************************** + extrn _lightmax :byte + extrn _pLightTbl :dword + + ;*********************************************************** + ;* Externs from gendung.cpp + ;*********************************************************** + extrn _microoffset :dword + extrn _pDungeonCels :dword + extrn _pSpeedCels :dword + extrn _nWTypeTable :byte + + + ;************************************************************************* + ;* Private + ;************************************************************************* + sgLineVal dd ? + sgCM dd ? + sgWT db ? + sgT dd ? + sgMask dd ? + sgTimeLow dd ? + sgTimeHigh dd ? + sgLoopTime dd ? + sgUnrollTime dd ? + sgRightMask label dword + dd 0eaaaaaaah ; 1110 1010 1010 1010 1010 1010 1010 1010 + dd 0f5555555h ; 1111 0101 0101 0101 0101 0101 0101 0101 + dd 0feaaaaaah ; 1111 1110 1010 1010 1010 1010 1010 1010 + dd 0ff555555h ; 1111 1111 0101 0101 0101 0101 0101 0101 + dd 0ffeaaaaah ; 1111 1111 1110 1010 1010 1010 1010 1010 + dd 0fff55555h ; 1111 1111 1111 0101 0101 0101 0101 0101 + dd 0fffeaaaah ; 1111 1111 1111 1110 1010 1010 1010 1010 + dd 0ffff5555h ; 1111 1111 1111 1111 0101 0101 0101 0101 + dd 0ffffeaaah ; 1111 1111 1111 1111 1110 1010 1010 1010 + dd 0fffff555h ; 1111 1111 1111 1111 1111 0101 0101 0101 + dd 0fffffeaah ; 1111 1111 1111 1111 1111 1110 1010 1010 + dd 0ffffff55h ; 1111 1111 1111 1111 1111 1111 0101 0101 + dd 0ffffffeah ; 1111 1111 1111 1111 1111 1111 1110 1010 + dd 0fffffff5h ; 1111 1111 1111 1111 1111 1111 1111 0101 + dd 0fffffffeh ; 1111 1111 1111 1111 1111 1111 1111 1110 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + + sgLeftMask label dword + dd 0aaaaaaabh ; 1010 1010 1010 1010 1010 1010 1010 1011 + dd 05555555fh ; 0101 0101 0101 0101 0101 0101 0101 1111 + dd 0aaaaaabfh ; 1010 1010 1010 1010 1010 1010 1011 1111 + dd 0555555ffh ; 0101 0101 0101 0101 0101 0101 1111 1111 + dd 0aaaaabffh ; 1010 1010 1010 1010 1010 1011 1111 1111 + dd 055555fffh ; 0101 0101 0101 0101 0101 1111 1111 1111 + dd 0aaaabfffh ; 1010 1010 1010 1010 1011 1111 1111 1111 + dd 05555ffffh ; 0101 0101 0101 0101 1111 1111 1111 1111 + dd 0aaabffffh ; 1010 1010 1010 1011 1111 1111 1111 1111 + dd 0555fffffh ; 0101 0101 0101 1111 1111 1111 1111 1111 + dd 0aabfffffh ; 1010 1010 1011 1111 1111 1111 1111 1111 + dd 055ffffffh ; 0101 0101 1111 1111 1111 1111 1111 1111 + dd 0abffffffh ; 1010 1011 1111 1111 1111 1111 1111 1111 + dd 05fffffffh ; 0101 1111 1111 1111 1111 1111 1111 1111 + dd 0bfffffffh ; 1011 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + dd 0ffffffffh ; 1111 1111 1111 1111 1111 1111 1111 1111 + + sgFullMask label dword + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + dd 0aaaaaaaah ; 1010 1010 1010 1010 1010 1010 1010 1010 + dd 055555555h ; 0101 0101 0101 0101 0101 0101 0101 0101 + + sgDivBy3MulBy4 label dword + dd 0, 0, 0, 4, 4, 4, 8, 8, 8,12,12,12,16,16,16 + dd 20,20,20,24,24,24,28,28,28,32,32,32,36,36,36 + dd 40,40,40,44,44,44,48,48,48,52,52,52,56,56,56 + dd 60,60,60 + + TotalDataPerLineBottom label dword + dd 0, 4, 8, 16, 24, 36, 48, 64, 80 + dd 100,120,144,168,196,224,256,288 + + TotalDataPerLineTop label dword + dd 0, 32, 60, 88,112,136,156,176,192 + dd 208,220,232,240,248,252,256,288 + + +;*********************************************************** +;* segment +;*********************************************************** +.CODE + + +;*********************************************************** +;* CLIP_BOTTOM(LoopStart, Quit, SkipCountReg, fTopPiece) +;* Clips top of triangle piece +;* ESI - Source +;* EDI - Dest +;* EDX - # Pixels to skipped past +;* EAX,ECX - trashed +;*********************************************************** +CLIP_BOTTOM MACRO LoopStart, Quit, SkipCountReg, fTopPiece, fDither + LOCAL allClipped + + mov eax,edi + sub eax,dword ptr [_glClipY] + jb LoopStart + + ; divide eax by 256 to get 3x Lines to clip off + ; add 300h (768) to include the line at ClipY in the clipping + ; add 0ffh (255) so we always round up + add eax,3ffh + shr eax,8 + if fTopPiece + cmp eax,14*3 + else + cmp eax,15*3 + endif + jg allClipped + mov ecx,sgDivBy3MulBy4[eax*4] + + ;add esi,(data for lines skipped) + mov eax,ecx + if fTopPiece + add esi,TotalDataPerLineTop[ecx] + else + add esi,TotalDataPerLineBottom[ecx] + endif + + ;sub edi,768*(lines skipped) + shl eax,6 + lea eax,[eax+eax*2] + shr ecx,1 + sub edi,eax + if fTopPiece + add SkipCountReg,ecx + else + sub SkipCountReg,ecx + endif + if fDither + mov eax,[sgLineVal] + shr ecx,1 + add eax,ecx + mov [sgLineVal],eax + endif + jmp LoopStart +allClipped: + if fTopPiece + sub edi,768*15 + add esi,256 ;should match TotalDataPerLineTop[nLines+1] + else + sub edi,768*16 + add esi,288 ;should match TotalDataPerLineBottom[nLines+1] + endif + jmp Quit +ENDM + + +;*********************************************************** +;* X_DWORDS +;* draw ecx dwords with a given light intesity +;* ECX - number of dwords +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_DWORDS MACRO + LOCAL @@xnext,@@xend + +@@xnext: + mov eax,[esi] + add esi,4 + + mov dl,al + mov ch,[ebx+edx] + + mov dl,ah + ror eax,16 + mov [edi],ch + + mov ch,[ebx+edx] + + mov dl,al + mov [edi+1],ch + + mov ch,[ebx+edx] + + mov dl,ah + mov [edi+2],ch + + mov ch,[ebx+edx] + mov [edi+3],ch + + add edi,4 + + sub cl,4 + cmp cl,4 + jge @@xnext + +@@xend: +ENDM + + +;*********************************************************** +;* X_BYTES_PAD +;* draw ecx bytes with a given light intesity, accounting +;* for padding data out to dword boundaries +;* CL - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTES_PAD MACRO + LOCAL @@xwords,@@xbytes,@@xend + + cmp cl,4 + jl @@xwords + + X_DWORDS + +@@xwords: + cmp cl,2 + jl @@xbytes + + mov dl, [esi] + mov ch, [ebx+edx] + + mov [edi],ch + mov dl, [esi+1] + + mov ch, [ebx+edx] + mov [edi+1],ch + + add esi,2 + add edi,2 + +@@xbytes: +; and cl,1 +; jz @@xend + +; mov dl, [esi] +; inc esi +; mov dl, [ebx+edx] +; mov [edi],dl +; inc edi + +@@xend: + mov edx,esi + and edx,2 + add esi,edx +ENDM + + +;*********************************************************** +;* X_BYTES_PREPAD +;* draw ecx bytes with a given light intesity +;* CL - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTES_PREPAD MACRO + LOCAL @@xwords,@@xbytes,@@xend + + mov edx,ecx + and edx,2 + add esi,edx + + cmp cl,4 + jl @@xwords + + X_DWORDS + +@@xwords: + cmp cl,2 + jl @@xbytes + + mov dl, [esi] + mov ch, [ebx+edx] + + mov [edi],ch + mov dl, [esi+1] + + mov ch, [ebx+edx] + mov [edi+1],ch + + add esi,2 + add edi,2 + +@@xbytes: +; and cl,1 +; jz @@xend + +; mov dl, [esi] +; inc esi +; mov dl, [ebx+edx] +; mov [edi],dl +; inc edi + +@@xend: +ENDM + + +;*********************************************************** +;* X_BYTES +;* draw ecx bytes with a given light intesity +;* CL - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTES MACRO + LOCAL @@xwords,@@xbytes,@@xend + + cmp cl,4 + jl @@xwords + + X_DWORDS + +@@xwords: + cmp cl,2 + jl @@xbytes + + mov dl, [esi] + mov ch, [ebx+edx] + + mov [edi],ch + mov dl, [esi+1] + + mov ch, [ebx+edx] + mov [edi+1],ch + + add esi,2 + add edi,2 + +@@xbytes: + and cl,1 + jz @@xend + + mov dl, [esi] + inc esi + mov dl, [ebx+edx] + mov [edi],dl + inc edi + +@@xend: +ENDM + + +;*********************************************************** +;* X_DWORD2 +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_DWORD2 MACRO + LOCAL @@xquad2,@@xend +@@xquad2: ; blank first +; debug +; shl ecx,2 +; add esi,ecx +; add edi,ecx +; jmp @@xend + + mov eax,[esi] + add esi,4 + mov dl,ah + shr eax,16 + mov dl,[ebx+edx] + mov [edi+1],dl + mov dl,ah + add edi,4 + mov dl,[ebx+edx] + dec ecx + mov [edi-1],dl + jnz @@xquad2 +@@xend: +ENDM + + +;*********************************************************** +;* X_WORD2 +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_WORD2 MACRO + LOCAL @@xquadt2,@@xend + ; blank first + shr ecx,1 + jnc @@xquadt2 + mov dl,[esi+1] + mov dl,[ebx+edx] + add esi,2 + mov [edi+1],dl + add edi,2 + +@@xquadt2: + test cl,cl + jz @@xend + + X_DWORD2 + +@@xend: +ENDM + + +;*********************************************************** +;* X_DWORD1 +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_DWORD1 MACRO + LOCAL @@xquad1,@@xend +@@xquad1: ; xlat first +; debug +; shl ecx,2 +; add esi,ecx +; add edi,ecx +; jmp @@xend + + mov eax,[esi] + add esi,4 + mov dl,al + shr eax,16 + mov dl,[ebx+edx] + mov [edi],dl + mov dl,al + add edi,4 + mov dl,[ebx+edx] + dec ecx + mov [edi-2],dl + jnz @@xquad1 +@@xend: +ENDM + + +;*********************************************************** +;* X_WORD1 +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_WORD1 MACRO + LOCAL @@xquadt1,@@xend + ; xlat first + shr ecx,1 + jnc @@xquadt1 + mov dl,[esi] + mov dl,[ebx+edx] + add esi,2 + mov [edi],dl + add edi,2 + +@@xquadt1: + test cl,cl + jz @@xend + + X_DWORD1 + +@@xend: + +ENDM + + +;*********************************************************** +;* X_BYTE1 +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTE1 MACRO + LOCAL @@noxword2,@@xend + ; blank first + shr ecx,1 + jc @@noxword2 + X_WORD2 + jmp @@xend +@@noxword2: + inc esi + inc edi + + X_WORD1 +@@xend: +ENDM + + +;*********************************************************** +;* X_BYTE1_PREPAD +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTE1_PREPAD MACRO + LOCAL noxword2,xend + mov edx,ecx + and edx,2 + add esi,edx + ; blank first + shr ecx,1 + jc noxword2 + X_WORD2 + jmp xend +noxword2: + inc esi + inc edi + + X_WORD1 +xend: +ENDM + + +;*********************************************************** +;* X_BYTE1_PAD +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTE1_PAD MACRO + LOCAL noxword2,xend + ; blank first + shr ecx,1 + jc noxword2 + X_WORD2 + jmp xend +noxword2: + inc esi + inc edi + + X_WORD1 +xend: + mov edx,esi + and edx,2 + add esi,edx +ENDM + + +;*********************************************************** +;* X_BYTE2 +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTE2 MACRO + LOCAL @@no_xword1,@@xend + ; xlat first + shr ecx,1 + jc @@no_xword1 + X_WORD1 + jmp @@xend +@@no_xword1: + mov dl,[esi] + mov dl,[ebx+edx] + inc esi + mov [edi],dl + inc edi + + X_WORD2 +@@xend: +ENDM + + +;*********************************************************** +;* X_BYTE2_PREPAD +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTE2_PREPAD MACRO + LOCAL @@no_xword1,@@xend + mov edx,ecx + and edx,2 + add esi,edx + ; xlat first + shr ecx,1 + jc @@no_xword1 + X_WORD1 + jmp @@xend +@@no_xword1: + mov dl,[esi] + mov dl,[ebx+edx] + inc esi + mov [edi],dl + inc edi + + X_WORD2 +@@xend: +ENDM + + +;*********************************************************** +;* X_BYTE2_PAD +;* draw ecx bytes with a given light intesity +;* ECX - number of bytes +;* ESI - source +;* EDI - dest +;* EBX - light table pointer +;* EAX - trashed +;* EDX - trashed +;*********************************************************** +X_BYTE2_PAD MACRO + LOCAL @@no_xword1,@@xend + ; xlat first + shr ecx,1 + jc @@no_xword1 + X_WORD1 + jmp @@xend +@@no_xword1: + mov dl,[esi] + mov dl,[ebx+edx] + inc esi + mov [edi],dl + inc edi + + X_WORD2 +@@xend: + mov edx,esi + and edx,2 + add esi,edx +ENDM + + +;*********************************************************** +;*********************************************************** +RDTSC MACRO + db 0fh, 31h +ENDM + + +;*********************************************************** +;* static void DrawMTileDitherClipTop (BYTE *pDecodeTo) +;* ECX = pDecodeTo +;*********************************************************** +DrawMTileDitherClipTop proc + push ebx + push edx + push edi + push esi + + + ;sgT = &_microoffset[0][0]; + mov edi, offset _microoffset + mov dword ptr [sgT], edi + + mov edi, ecx ; Dest + + mov eax,dword ptr [_nLVal] + test al,al + jz @@NoLt + cmp al,byte ptr [_lightmax] + jz @@Black + + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jnz @@Speed + + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov ebx,dword ptr [_nLVal]; ; Light conversion table + shl ebx,8 + add ebx,dword ptr [_pLightTbl]; + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz @@Type0 ; Solid 32x32 block + cmp ax,1 + jz @@Type1 ; 32x32 block with '0' holes + cmp ax,2 + jz @@Type2 ; Left Triangle + cmp ax,3 + jz @@Type3 ; Right Triangle + cmp ax,4 + jz @@Type4 ; Left Triangle to wall + jmp @@Type5 ; Right Triangle to wall + +@@Speed: + mov esi,dword ptr [sgT] + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [_nLVal] + shl eax,2 + add esi,eax ; Source + mov eax,dword ptr [esi] + mov esi,dword ptr [_pSpeedCels] + add esi,eax + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +@@SCmp: + cmp ax,8 + jz @@Type8 ; PreTrans Solid 32x32 block + cmp ax,9 + jz @@Type9 ; PreTrans 32x32 block with '0' holes + cmp ax,10 + jz @@TypeA ; PreTrans Left Triangle + cmp ax,11 + jz @@TypeB ; PreTrans Right Triangle + cmp ax,12 + jz @@TypeC ; PreTrans Left Triangle to wall + jmp @@TypeD ; PreTrans Right Triangle to wall + +@@NoLt: + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RNoLt + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RNoLt: + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp @@SCmp + +@@Black: + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RBlk + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RBlk: + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz @@TypeG ; Black Trans Solid 32x32 block + cmp ax,1 + jz @@TypeH ; Black Trans 32x32 block with '0' holes + cmp ax,2 + jz @@TypeI ; Black Trans Left Triangle + cmp ax,3 + jz @@TypeJ ; Black Trans Right Triangle + cmp ax,4 + jz @@TypeK ; Black Trans Left Triangle to wall + jmp @@TypeL ; Black Trans Right Triangle to wall + +;*-----------------------------------------------------------------------* + +@@Type0: + push ebp + mov ebp,16 +@@T0Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T0Done + mov ecx,8 + X_DWORD2 + sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@T0Done + mov ecx,8 + X_DWORD1 + sub edi,NBUFFW32 + dec ebp + jnz @@T0Lp1 +@@T0Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@Type1: + push ebp + mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ebp,32 +@@T1Lp1: + mov edx,32 +@@T1Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T1J + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@T1Done + mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz @@T1Od + push edx + X_BYTE1 + pop edx + jmp @@T1x +@@T1Od: + push edx + X_BYTE2 + pop edx +@@T1x: + test edx,edx + jz @@T1Nxt + jmp @@T1Lp2 +@@T1J: + neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@T1Lp2 +@@T1Nxt: + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ebp + jnz @@T1Lp1 +@@T1Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@Type2: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov ebp,30 +@@T2Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T2End + add edi,ebp + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T2Od + X_BYTE1_PREPAD + jmp @@T2x +@@T2Od: + X_BYTE2_PREPAD +@@T2x: + sub edi,NBUFFW32 + sub ebp,2 + jge @@T2Lp1 + + +@@T2b: + mov ebp,2 +@@T2Lp4: + cmp edi,dword ptr [_glClipY] + jb @@T2End + add edi,ebp + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T2Od2 + X_BYTE1_PREPAD + jmp @@T2x2 +@@T2Od2: + X_BYTE2_PREPAD +@@T2x2: + sub edi,NBUFFW32 + add ebp,2 + cmp ebp,32 + jnz @@T2Lp4 +@@T2End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type3: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov ebp,30 +@@T3Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T3End + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T3Od + + X_BYTE1_PAD + jmp @@T3x +@@T3Od: + X_BYTE2_PAD +@@T3x: + sub edi,NBUFFW32 + add edi,ebp + sub ebp,2 + jge @@T3Lp1 + + +@@T3b: + mov ebp,2 +@@T3Lp4: + cmp edi,dword ptr [_glClipY] + jb @@T3End + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T3Od2 + + X_BYTE1_PAD + jmp @@T3x2 +@@T3Od2: + X_BYTE2_PAD +@@T3x2: + sub edi,NBUFFW32 + add edi,ebp + add ebp,2 + cmp ebp,32 + jnz @@T3Lp4 +@@T3End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type4: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov ebp,30 +@@T4Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T4End + add edi,ebp + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T4Od + X_BYTE1_PREPAD + jmp @@T4x +@@T4Od: + X_BYTE2_PREPAD +@@T4x: + sub edi,NBUFFW32 + sub ebp,2 + jge @@T4Lp1 + + mov ebp,8 +@@T4Lp4: + cmp edi,dword ptr [_glClipY] + jb @@T4End + mov ecx,8 + X_DWORD2 + sub edi,NBUFFW32 + cmp edi,dword ptr [_glClipY] + jb @@T4End + mov ecx,8 + X_DWORD1 + sub edi,NBUFFW32 + dec ebp + jnz @@T4Lp4 +@@T4End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@Type5: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov ebp,30 +@@T5Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T5End + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T5Od + X_BYTE1_PAD + jmp @@T5x +@@T5Od: + X_BYTE2_PAD +@@T5x: + sub edi,NBUFFW32 + add edi,ebp + sub ebp,2 + jge @@T5Lp1 + +@@T5b: + mov ebp,8 +@@T5Lp4: + cmp edi,dword ptr [_glClipY] + jb @@T5End + mov ecx,8 + X_DWORD2 + sub edi,NBUFFW32 + cmp edi,dword ptr [_glClipY] + jb @@T5End + mov ecx,8 + X_DWORD1 + sub edi,NBUFFW32 + dec ebp + jnz @@T5Lp4 +@@T5End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type8: + mov edx,16 +@@T8Lp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@T8Lp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@T8Lp2 + sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@T8Lp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@T8Lp3 + sub edi,NBUFFW32 + dec edx + jnz @@T8Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type9: + push ebp + mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ebp,32 +@@T9Lp1: + mov edx,32 +@@T9Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T9J + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@T9Done + mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz @@T9Od + shr ecx,1 + jnc @@T9w + inc esi + inc edi + test ecx,ecx + jz @@T9x + jmp @@T9w2 +@@T9w: + shr ecx,1 + jnc @@T9Lp3 + inc esi + inc edi + mov al,[esi] + inc esi + mov [edi],al + inc edi + test ecx,ecx + jz @@T9x +@@T9Lp3: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@T9Lp3 + jmp @@T9x +@@T9Od: + shr ecx,1 + jnc @@T9w2 + mov al,[esi] + inc esi + mov [edi],al + inc edi + test ecx,ecx + jz @@T9x + jmp @@T9w +@@T9w2: + shr ecx,1 + jnc @@T9Lp4 + mov al,[esi] + add esi,2 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@T9x +@@T9Lp4: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@T9Lp4 +@@T9x: + test edx,edx + jz @@T9Nxt + jmp @@T9Lp2 +@@T9J: + neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@T9Lp2 +@@T9Nxt: + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ebp + jnz @@T9Lp1 +@@T9Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeA: + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TALp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TAOd + shr ecx,2 + jnc @@TALp2 + mov ax,[esi+2] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + test ecx,ecx + jz @@TAx +@@TALp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TALp2 + jmp @@TAx +@@TAOd: + shr ecx,2 + jnc @@TALp3 + mov ax,[esi+2] + add esi,4 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TAx +@@TALp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TALp3 +@@TAx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TALp1 + + + mov edx,2 +@@TALp4: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TAOd2 + shr ecx,2 + jnc @@TALp5 + mov ax,[esi+2] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + test ecx,ecx + jz @@TAx2 +@@TALp5: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TALp5 + jmp @@TAx2 +@@TAOd2: + shr ecx,2 + jnc @@TALp6 + mov ax,[esi+2] + add esi,4 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TAx2 +@@TALp6: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TALp6 +@@TAx2: + sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TALp4 + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeB: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TBLp1: + cmp edi,dword ptr [_glClipY] + jb @@TBEnd + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov ebp,ecx + mov dword ptr [sgLineVal],eax + jz @@TBOd + shr ecx,2 + jz @@TBcontinue +@@TBLp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TBLp2 +@@TBcontinue: + and ebp,2 + jz @@TBx + mov ax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + jmp @@TBx +@@TBOd: + shr ecx,2 + jz @@TBcontinue2 +@@TBLp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TBLp3 +@@TBcontinue2: + and ebp,2 + jz @@TBx + mov ax,[esi] + add esi,4 + mov [edi],al + add edi,2 +@@TBx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TBLp1 + + + mov edx,2 +@@TBLp4: + cmp edi,dword ptr [_glClipY] + jb @@TBEnd + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TBOd2 + shr ecx,2 + jz @@TBcontinue3 +@@TBLp5: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TBLp5 +@@TBcontinue3: + and ebp,2 + jz @@TBx2 + mov ax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + jmp @@TBx2 +@@TBOd2: + shr ecx,2 + jz @@TBcontinue4 +@@TBLp6: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TBLp6 +@@TBcontinue4: + and ebp,2 + jz @@TBx2 + mov ax,[esi] + add esi,4 + mov [edi],al + add edi,2 +@@TBx2: + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TBLp4 +@@TBEnd: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeC: + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TCLp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TCOd + shr ecx,2 + jnc @@TCLp2 + mov ax,[esi+2] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + test ecx,ecx + jz @@TCx +@@TCLp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TCLp2 + jmp @@TCx +@@TCOd: + shr ecx,2 + jnc @@TCLp3 + mov ax,[esi+2] + add esi,4 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TCx +@@TCLp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TCLp3 +@@TCx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TCLp1 + + + mov edx,8 +@@TCLp4: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TCLp5: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TCLp5 + sub edi,NBUFFW32 + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TCLp6: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TCLp6 + sub edi,NBUFFW32 + dec edx + jnz @@TCLp4 + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeD: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TDLp1: + cmp edi,dword ptr [_glClipY] + jb @@TDEnd + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov ebp,ecx + mov dword ptr [sgLineVal],eax + jz @@TDOd + shr ecx,2 + jz @@TDcontinue +@@TDLp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TDLp2 +@@TDcontinue: + and ebp,2 + jz @@TDx + mov ax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + jmp @@TDx + +@@TDOd: + shr ecx,2 + jz @@TDcontinue2 +@@TDLp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TDLp3 +@@TDcontinue2: + and ebp,2 + jz @@TDx + mov ax,[esi] + add esi,4 + mov [edi],al + add edi,2 +@@TDx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TDLp1 + + + mov edx,8 +@@TDLp4: + cmp edi,dword ptr [_glClipY] + jb @@TDEnd + mov ecx,8 +@@TDLp5: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TDLp5 + sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@TDEnd + mov ecx,8 +@@TDLp6: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TDLp6 + sub edi,NBUFFW32 + dec edx + jnz @@TDLp4 +@@TDEnd: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeG: + mov edx,16 + xor eax,eax +@@TGLp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TGLp2: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TGLp2 + sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TGLp3: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TGLp3 + sub edi,NBUFFW32 + dec edx + jnz @@TGLp1 + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeH: + push ebp + mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ebp,32 + +@@THLp1: + mov edx,32 + +@@THLp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@THJ + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@THDone + mov ecx,eax + add esi,ecx + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz @@THOd + xor eax,eax + shr ecx,1 + jnc @@THw + inc edi + test ecx,ecx + jz @@THx + jmp @@THw2 +@@THw: + shr ecx,1 + jnc @@THLp3 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@THx +@@THLp3: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@THLp3 + jmp @@THx + +@@THOd: + xor eax,eax + shr ecx,1 + jnc @@THw2 + mov [edi],al + inc edi + test ecx,ecx + jz @@THx + jmp @@THw +@@THw2: + shr ecx,1 + jnc @@THLp4 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@THx +@@THLp4: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@THLp4 + +@@THx: + test edx,edx + jz @@THNxt + jmp @@THLp2 + +@@THJ: + neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@THLp2 + +@@THNxt: + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ebp + jnz @@THLp1 +@@THDone: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeI: + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TILp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TIOd + xor eax,eax + shr ecx,2 + jnc @@TILp2 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TIx +@@TILp2: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TILp2 + jmp @@TIx + +@@TIOd: + xor eax,eax + shr ecx,2 + jnc @@TILp3 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TIx +@@TILp3: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TILp3 + +@@TIx: + sub edi,NBUFFW32 + test edx,edx + jz @@TIb + sub edx,2 + jmp @@TILp1 + +@@TIb: + mov edx,2 +@@TILp4: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TIOd2 + xor eax,eax + shr ecx,2 + jnc @@TILp5 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TIx2 +@@TILp5: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TILp5 + jmp @@TIx2 + +@@TIOd2: + xor eax,eax + shr ecx,2 + jnc @@TILp6 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TIx2 +@@TILp6: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TILp6 + +@@TIx2: + sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TILp4 + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeJ: + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TJLp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TJOd + xor eax,eax + shr ecx,2 + jnc @@TJLp2 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TJx +@@TJLp2: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TJLp2 + jmp @@TJx + +@@TJOd: + xor eax,eax + shr ecx,2 + jnc @@TJLp3 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TJx +@@TJLp3: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TJLp3 + +@@TJx: + sub edi,NBUFFW32 + test edx,edx + jz @@TJb + add edi,edx + sub edx,2 + jmp @@TJLp1 + +@@TJb: + mov edx,2 +@@TJLp4: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TJOd2 + xor eax,eax + shr ecx,2 + jnc @@TJLp5 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TJx2 +@@TJLp5: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TJLp5 + jmp @@TJx2 + +@@TJOd2: + xor eax,eax + shr ecx,2 + jnc @@TJLp6 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TJx2 +@@TJLp6: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TJLp6 + +@@TJx2: + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TJLp4 + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeK: + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TKLp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TKOd + xor eax,eax + shr ecx,2 + jnc @@TKLp2 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TKx +@@TKLp2: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TKLp2 + jmp @@TKx + +@@TKOd: + xor eax,eax + shr ecx,2 + jnc @@TKLp3 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TKx +@@TKLp3: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TKLp3 + +@@TKx: + sub edi,NBUFFW32 + test edx,edx + jz @@TKb + sub edx,2 + jmp @@TKLp1 + +@@TKb: + mov edx,8 + xor eax,eax +@@TKLp4: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TKLp5: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TKLp5 + sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TKLp6: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TKLp6 + sub edi,NBUFFW32 + dec edx + jnz @@TKLp4 + jmp @@Done + +;*-----------------------------------------------------------------------* + +@@TypeL: + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TLLp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TLOd + xor eax,eax + shr ecx,2 + jnc @@TLLp2 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TLx +@@TLLp2: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TLLp2 + jmp @@TLx + +@@TLOd: + xor eax,eax + shr ecx,2 + jnc @@TLLp3 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TLx +@@TLLp3: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TLLp3 + +@@TLx: + sub edi,NBUFFW32 + test edx,edx + jz @@TLb + add edi,edx + sub edx,2 + jmp @@TLLp1 + +@@TLb: + mov edx,8 + xor eax,eax +@@TLLp4: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TLLp5: + mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TLLp5 + sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TLLp6: + mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TLLp6 + sub edi,NBUFFW32 + dec edx + jnz @@TLLp4 + jmp @@Done + +@@Done: + + pop esi + pop edi + pop edx + pop ebx + ret +DrawMTileDitherClipTop endp + + + +;*********************************************************** +;* static void DrawMTileHalfDitherClipTop (BYTE *pDecodeTo, long *sgMask) +;* ECX = pDecodeTo +;* EDX = sgMask +;*********************************************************** +DrawMTileHalfDitherClipTop proc + push ebx + push edi + push esi + + ;sgT = &_microoffset[0][0]; + mov edi, offset _microoffset + mov dword ptr [sgT], edi + + mov edi,ecx ; Dest + mov dword ptr [sgMask], edx + + mov eax,dword ptr [_nLVal] + test al,al + jz @@NoLt + cmp al,byte ptr [_lightmax] + jz @@Black + + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jnz @@Speed + + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov ebx,dword ptr [_nLVal]; ; Light conversion table + shl ebx,8 + add ebx,dword ptr [_pLightTbl]; + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz @@Type0 ; Solid 32x32 block + jz @@TypeG + cmp ax,1 + jz @@Type1 ; 32x32 block with '0' holes + cmp ax,2 + jz @@Type2 ; Left Triangle + cmp ax,3 + jz @@Type3 ; Right Triangle + cmp ax,4 + jz @@Type4 ; Left Triangle to wall + jmp @@Type5 ; Right Triangle to wall + +@@Speed: + mov esi,dword ptr [sgT] + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [_nLVal] + shl eax,2 + add esi,eax ; Source + mov eax,dword ptr [esi] + mov esi,dword ptr [_pSpeedCels] + add esi,eax + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +@@SCmp: + cmp ax,8 + jz @@Type8 ; PreTrans Solid 32x32 block + cmp ax,9 + jz @@Type9 ; PreTrans 32x32 block with '0' holes + cmp ax,10 + jz @@TypeA ; PreTrans Left Triangle + cmp ax,11 + jz @@TypeB ; PreTrans Right Triangle + cmp ax,12 + jz @@TypeC ; PreTrans Left Triangle to wall + jmp @@TypeD ; PreTrans Right Triangle to wall + +@@NoLt: + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RNoLt + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RNoLt: + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp @@SCmp + +@@Black: + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RBlk + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RBlk: + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz @@TypeG ; Black Trans Solid 32x32 block + cmp ax,1 + jz @@TypeH ; Black Trans 32x32 block with '0' holes + cmp ax,2 + jz @@TypeI ; Black Trans Left Triangle + cmp ax,3 + jz @@TypeJ ; Black Trans Right Triangle + cmp ax,4 + jz @@TypeK ; Black Trans Left Triangle to wall + jmp @@TypeL ; Black Trans Right Triangle to wall + +;*-----------------------------------------------------------------------*/ + +@@Type0: + mov edx,32 +@@T0Lp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@T0Lp2: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T0S1 + xlatb + mov byte ptr [edi],al +@@T0S1: + inc edi + dec ecx + jnz @@T0Lp2 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@T0Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type1: + mov ecx,32 + +@@T1Lp1: + push ecx + mov eax,dword ptr [sgMask] + mov eax,dword ptr [eax] + mov dword ptr [sgCM],eax + + mov edx,32 + +@@T1Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T1J + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@PDone + mov ecx,eax + push edx + mov edx,dword ptr [sgCM] +@@T1Lp3: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T1S1 + xlatb + mov byte ptr [edi],al +@@T1S1: inc edi + dec ecx + jnz @@T1Lp3 + mov dword ptr [sgCM],edx + pop edx + test edx,edx + jz @@T1Nxt + jmp @@T1Lp2 + +@@T1J: neg al ; Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz @@T1S2 + push eax + mov eax,dword ptr [sgCM] + shl eax,cl + mov dword ptr [sgCM],eax + pop eax +@@T1S2: sub edx,eax + jnz @@T1Lp2 +@@T1Nxt: + pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec ecx + jnz @@T1Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type2: + mov edx,30 +@@T2Lp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@T2Lp2 + mov ax,[esi+2] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@T2x +@@T2Lp2: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T2Lp2 +@@T2x: + sub edi,NBUFFW32 + sub edx,2 + jge @@T2Lp1 + + + mov edx,2 +@@T2Lp3: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@T2Lp4 + mov ax,[esi+2] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@T2x2 +@@T2Lp4: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T2Lp4 +@@T2x2: + sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@T2Lp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type3: + push ebp + mov edx,30 +@@T3Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T3End + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@T3continue +@@T3Lp2: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T3Lp2 +@@T3continue: + and ebp,2 + jz @@T3x + mov ax,[esi] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 +@@T3x: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@T3Lp1 + + mov edx,2 +@@T3Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T3End + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@T3continue2 +@@T3Lp4: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T3Lp4 +@@T3continue2: + and ebp,2 + jz @@T3x2 + mov ax,[esi] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 +@@T3x2: + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@T3Lp3 +@@T3End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type4: + mov edx,30 +@@T4Lp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@T4Lp2 + mov ax,[esi+2] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@T4x +@@T4Lp2: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T4Lp2 +@@T4x: + sub edi,NBUFFW32 + sub edx,2 + jge @@T4Lp1 + + mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@T4Lp3: + cmp edi,dword ptr [_glClipY] + jb @@Done + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 + mov eax,esi + and eax,2 + add esi,eax +@@T4Lp4: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T4S1 + xlatb + mov [edi],al +@@T4S1: + inc edi + dec ecx + jnz @@T4Lp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@T4Lp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type5: + push ebp + mov edx,30 +@@T5Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T5End + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@T5continue +@@T5Lp2: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T5Lp2 +@@T5continue: + and ebp,2 + jz @@T5x + mov ax,[esi] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 +@@T5x: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@T5Lp1 + + mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@T5Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T5End + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@T5Lp4: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T5S1 + xlatb + mov byte ptr [edi],al +@@T5S1: + inc edi + dec ecx + jnz @@T5Lp4 + mov ebp,esi + and ebp,2 + add esi,ebp + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@T5Lp3 +@@T5End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type8: mov edx,32 +@@T8Lp1: cmp edi,dword ptr [_glClipY] + jb @@Done + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@T8Lp2: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T8S1 + mov byte ptr [edi],al +@@T8S1: inc edi + dec ecx + jnz @@T8Lp2 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@T8Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type9: mov ecx,32 + +@@T9Lp1: push ecx + mov eax,dword ptr [sgMask] + mov eax,dword ptr [eax] + mov dword ptr [sgCM],eax + + mov edx,32 + +@@T9Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T9J + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@PDone + push edx + mov edx,dword ptr [sgCM] + mov ecx,eax +@@T9Lp3: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T9S1 + mov byte ptr [edi],al +@@T9S1: inc edi + dec ecx + jnz @@T9Lp3 + mov dword ptr [sgCM],edx + pop edx + test edx,edx + jz @@T9Nxt + jmp @@T9Lp2 + +@@T9J: neg al ; Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz @@T9S2 + mov ebx,dword ptr [sgCM] + shl ebx,cl + mov dword ptr [sgCM],ebx +@@T9S2: sub edx,eax + jnz @@T9Lp2 +@@T9Nxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec ecx + jnz @@T9Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeA: + mov edx,30 +@@TALp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TALp2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TAx +@@TALp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + dec ecx + lea edi,[edi+4] + jnz @@TALp2 +@@TAx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TALp1 + + mov edx,2 +@@TALp3: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TALp4 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + test ecx,ecx + lea edi,[edi+2] + jz @@TAx2 +@@TALp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TALp4 +@@TAx2: + sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TALp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeB: + push ebp + mov edx,30 +@@TBLp1: + cmp edi,dword ptr [_glClipY] + jb @@TBEnd + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TBcontinue +@@TBLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TBLp2 +@@TBcontinue: + and ebp,2 + jz @@TBx + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TBx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TBLp1 + +@@TBb: + mov edx,2 +@@TBLp3: + cmp edi,dword ptr [_glClipY] + jb @@TBEnd + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TBcontinue2 +@@TBLp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TBLp4 +@@TBcontinue2: + and ebp,2 + jz @@TBx2 + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TBx2: + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TBLp3 +@@TBEnd: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeC: + mov edx,30 +@@TCLp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TCLp2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TCx +@@TCLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TCLp2 +@@TCx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TCLp1 + +@@TCb: + mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@TCLp3: + cmp edi,dword ptr [_glClipY] + jb @@Done + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@TCLp4: + mov al,[esi] + inc esi + shl edx,1 + jnc @@TCS1 + mov byte ptr [edi],al +@@TCS1: + inc edi + dec ecx + jnz @@TCLp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TCLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeD: + push ebp + mov edx,30 +@@TDLp1: + cmp edi,dword ptr [_glClipY] + jb @@TDEnd + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TDcontinue +@@TDLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TDLp2 +@@TDcontinue: + and ebp,2 + jz @@TDx + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TDx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TDLp1 + + mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@TDLp3: + cmp edi,dword ptr [_glClipY] + jb @@TDEnd + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@TDLp4: + mov al,[esi] + inc esi + shl edx,1 + jnc @@TDS1 + mov byte ptr [edi],al +@@TDS1: + inc edi + dec ecx + jnz @@TDLp4 + mov ebp,esi + and ebp,2 + add esi,ebp + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TDLp3 +@@TDEnd: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeG: mov edx,32 +@@TGLp1: cmp edi,dword ptr [_glClipY] + jb @@Done + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +@@TGLp2: shl edx,1 + jnc @@TGS1 + mov byte ptr [edi],al +@@TGS1: inc edi + dec ecx + jnz @@TGLp2 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TGLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeH: mov ecx,32 + +@@THLp1: push ecx + mov eax,dword ptr [sgMask] + mov eax,dword ptr [eax] + mov dword ptr [sgCM],eax + + mov edx,32 + +@@THLp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@THJ + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@PDone + push edx + mov edx,dword ptr [sgCM] + mov ecx,eax + add esi,ecx + xor eax,eax +@@THLp3: shl edx,1 + jnc @@THS1 + mov byte ptr [edi],al +@@THS1: inc edi + dec ecx + jnz @@THLp3 + mov dword ptr [sgCM],edx + pop edx + test edx,edx + jz @@THNxt + jmp @@THLp2 + +@@THJ: neg al ; Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz @@THS2 + mov ebx,dword ptr [sgCM] + shl ebx,cl + mov dword ptr [sgCM],ebx +@@THS2: sub edx,eax + jnz @@THLp2 +@@THNxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec ecx + jnz @@THLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeI: mov edx,30 + xor eax,eax +@@TILp1: cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TILp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TIx +@@TILp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TILp2 +@@TIx: sub edi,NBUFFW32 + test edx,edx + jz @@TIb + sub edx,2 + jmp @@TILp1 + +@@TIb: mov edx,2 +@@TILp3: cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + + shr ecx,2 + jnc @@TILp4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TIx2 +@@TILp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TILp4 +@@TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TILp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeJ: mov edx,30 + xor eax,eax +@@TJLp1: cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TJLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TJx +@@TJLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TJLp2 +@@TJx: sub edi,NBUFFW32 + test edx,edx + jz @@TJb + add edi,edx + sub edx,2 + jmp @@TJLp1 + +@@TJb: mov edx,2 +@@TJLp3: cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TJLp4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TJx2 +@@TJLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TJLp4 +@@TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TJLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeK: mov edx,30 + xor eax,eax +@@TKLp1: cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TKLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TKx +@@TKLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TKLp2 +@@TKx: sub edi,NBUFFW32 + test edx,edx + jz @@TKb + sub edx,2 + jmp @@TKLp1 + +@@TKb: mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@TKLp3: cmp edi,dword ptr [_glClipY] + jb @@Done + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +@@TKLp4: shl edx,1 + jnc @@TKS1 + mov byte ptr [edi],al +@@TKS1: inc edi + dec ecx + jnz @@TKLp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TKLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeL: mov edx,30 + xor eax,eax +@@TLLp1: cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TLLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TLx +@@TLLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TLLp2 +@@TLx: sub edi,NBUFFW32 + test edx,edx + jz @@TLb + add edi,edx + sub edx,2 + jmp @@TLLp1 + +@@TLb: mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@TLLp3: cmp edi,dword ptr [_glClipY] + jb @@Done + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +@@TLLp4: shl edx,1 + jnc @@TLS1 + mov byte ptr [edi],al +@@TLS1: inc edi + dec ecx + jnz @@TLLp4 + pop edx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TLLp3 + jmp @@Done + +@@PDone: + pop eax +@@Done: + + pop esi + pop edi + pop ebx + ret +DrawMTileHalfDitherClipTop endp + + + +;*********************************************************** +;* void DrawMTileClipTop (BYTE *pDecodeTo) +;* ECX = pDecodeTo +;*********************************************************** +public @DrawMTileClipTop@4 +@DrawMTileClipTop@4 proc + push ebx + push edx + push edi + push esi + + mov edx, dword ptr [_nTrans] + test edx,edx + jz @@NoTrans + + ; if (gbPartialTrans == PART_TRANS_NONE) { + mov dl, byte ptr [_gbPartialTrans] + cmp dl, PART_TRANS_NONE + jne @@TransLeft + call DrawMTileDitherClipTop + jmp @@Done + +@@TransLeft: + ; if (gbPartialTrans == PART_TRANS_LEFT) { + cmp dl, PART_TRANS_LEFT + jne @@TransRight + + ;al = nWTypeTable[_gnPieceNum]; + mov ebx, dword ptr [_gnPieceNum] + mov al, _nWTypeTable[ebx] + + ; if ((al == WTYPE_LEFT) || (al == WTYPE_ULC)) { + cmp al, WTYPE_LEFT + je @@TLLeftMask + cmp al, WTYPE_ULC + je @@TLLeftMask + jmp @@TransRight + +@@TLLeftMask: + mov edx, offset sgLeftMask + add edx, 31*4 + call DrawMTileHalfDitherClipTop + jmp @@Done + + ; if (al == WTYPE_LRC) { + cmp al, WTYPE_LRC + jne @@TransRight + mov edx, offset sgRightMask + add edx, 31*4 + call DrawMTileHalfDitherClipTop + jmp @@Done + +@@TransRight: + ; if (gbPartialTrans == PART_TRANS_RIGHT) { + cmp dl, PART_TRANS_RIGHT + jne @@NoTrans + + ;al = nWTypeTable[_gnPieceNum]; + mov ebx, dword ptr [_gnPieceNum] + mov al, _nWTypeTable[ebx] + + ; if ((al == WTYPE_RIGHT) || (al == WTYPE_ULC)) { + cmp al, WTYPE_RIGHT + je @@TRRightMask + cmp al, WTYPE_ULC + je @@TRRightMask + jmp @@NoTrans +@@TRRightMask: + mov edx, offset sgRightMask + add edx, 31*4 + call DrawMTileHalfDitherClipTop + jmp @@Done + + ; if (al == WTYPE_LRC) { + cmp al, WTYPE_LRC + jne @@NoTrans + mov edx, offset sgLeftMask + add edx, 31*4 + call DrawMTileHalfDitherClipTop + jmp @@Done + +@@NoTrans: + ;sgT = &_microoffset[0][0]; + mov edi, offset _microoffset + mov dword ptr [sgT], edi + + mov edi,ecx ; Dest + + mov eax,dword ptr [_nLVal] + test al,al + jz @@NoLt + cmp al,byte ptr [_lightmax] + jz @@Black + + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jnz @@Speed + + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov ebx,dword ptr [_nLVal] ; Light conversion table + shl ebx,8 + add ebx,dword ptr [_pLightTbl] + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + shr eax,12 + and eax,0fh + jz @@Type0 ; Solid 32x32 block + cmp ax,1 + jz @@Type1 ; 32x32 block with '0' holes + cmp ax,2 + jz @@Type2 ; Left Triangle + cmp ax,3 + jz @@Type3 ; Right Triangle + cmp ax,4 + jz @@Type4 ; Left Triangle to wall + jmp @@Type5 ; Right Triangle to wall + +@@Speed: + mov esi,dword ptr [sgT] + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [_nLVal] + shl eax,2 + add esi,eax ; Source + mov eax,dword ptr [esi] + mov esi,dword ptr [_pSpeedCels] + add esi,eax + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + shr eax,12 + and eax,0fh +@@SCmp: cmp ax,8 + jz @@Type8 ; PreTrans Solid 32x32 block + cmp ax,9 + jz @@Type9 ; PreTrans 32x32 block with '0' holes + cmp ax,10 + jz @@TypeA ; PreTrans Left Triangle + cmp ax,11 + jz @@TypeB ; PreTrans Right Triangle + cmp ax,12 + jz @@TypeC ; PreTrans Left Triangle to wall + jmp @@TypeD ; PreTrans Right Triangle to wall + +@@NoLt: mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RNoLt + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RNoLt: mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp @@SCmp + +@@Black: mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RBlk + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RBlk: mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + shr eax,12 + and eax,07h + jz @@TypeG ; Black Trans Solid 32x32 block + cmp ax,1 + jz @@TypeH ; Black Trans 32x32 block with '0' holes + cmp ax,2 + jz @@TypeI ; Black Trans Left Triangle + cmp ax,3 + jz @@TypeJ ; Black Trans Right Triangle + cmp ax,4 + jz @@TypeK ; Black Trans Left Triangle to wall + jmp @@TypeL ; Black Trans Right Triangle to wall + +;*-----------------------------------------------------------------------*/ + +@@Type0: + mov edx,32 +@@T0Lp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8*4 + + push edx + X_DWORDS + pop edx + + sub edi,NBUFFW32 + dec edx + jnz @@T0Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type1: + push ebp + mov ebp,32 +@@T1Lp1: + mov edx,32 +@@T1Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T1J + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@T1Done + mov ecx,eax + + push edx + X_BYTES + pop edx + + test edx,edx + jz @@T1Nxt + jmp @@T1Lp2 + +@@T1J: neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@T1Lp2 +@@T1Nxt: + sub edi,NBUFFW32 + dec ebp + jnz @@T1Lp1 +@@T1Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type2: + push ebp + mov ebp,30 +@@T2Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T2End + add edi,ebp + mov ecx,32 + sub ecx,ebp + X_BYTES_PREPAD + sub edi,NBUFFW32 + sub ebp,2 + jge @@T2Lp1 + + mov ebp,2 +@@T2Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T2End + add edi,ebp + mov ecx,32 + sub ecx,ebp + X_BYTES_PREPAD + sub edi,NBUFFW32 + add ebp,2 + cmp ebp,32 + jnz @@T2Lp3 +@@T2End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type3: + push ebp + mov ebp,30 +@@T3Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T3End + mov ecx,32 + sub ecx,ebp + X_BYTES_PAD + sub edi,NBUFFW32 + add edi,ebp + sub ebp,2 + jge @@T3Lp1 + +@@T3b: + mov ebp,2 +@@T3Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T3End + mov ecx,32 + sub ecx,ebp + X_BYTES_PAD + sub edi,NBUFFW32 + add edi,ebp + add ebp,2 + cmp ebp,32 + jnz @@T3Lp3 +@@T3End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type4: + push ebp + mov ebp,30 +@@T4Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T4End + add edi,ebp + mov ecx,32 + sub ecx,ebp + X_BYTES_PREPAD + sub edi,NBUFFW32 + sub ebp,2 + jge @@T4Lp1 + +@@T4b: + mov ebp,16 +@@T4Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T4End + mov ecx,8*4 + X_DWORDS + sub edi,NBUFFW32 + dec ebp + jnz @@T4Lp3 +@@T4End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type5: + push ebp + mov ebp,30 +@@T5Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T5End + mov ecx,32 + sub ecx,ebp + X_BYTES_PAD + sub edi,NBUFFW32 + add edi,ebp + sub ebp,2 + jge @@T5Lp1 + +@@T5b: + mov ebp,16 +@@T5Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T5End + mov ecx,8*4 + X_DWORDS + sub edi,NBUFFW32 + dec ebp + jnz @@T5Lp3 +@@T5End: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type8: + mov edx,32 +@@T8Lp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@T8Lp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T8Lp2 + sub edi,NBUFFW32 + dec edx + jnz @@T8Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type9: + push ebp + mov ebp,32 +@@T9Lp1: + mov edx,32 +@@T9Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T9J + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@T9Done + mov ecx,eax + shr ecx,1 + jnc @@T9w + mov al,[esi] + inc esi + mov [edi],al + inc edi + test ecx,ecx + jz @@T9x +@@T9w: shr ecx,1 + jnc @@T9Lp3 + mov ax,[esi] + add esi,2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@T9x +@@T9Lp3: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T9Lp3 +@@T9x: test edx,edx + jz @@T9Nxt + jmp @@T9Lp2 + +@@T9J: neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@T9Lp2 +@@T9Nxt: + sub edi,NBUFFW32 + dec ebp + jnz @@T9Lp1 +@@T9Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeA: + mov edx,30 +@@TALp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TALp2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TAx +@@TALp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TALp2 +@@TAx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TALp1 + + mov edx,2 +@@TALp3: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TALp4 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TAx2 +@@TALp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TALp4 +@@TAx2: + sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TALp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeB: + push ebp + mov edx,30 +@@TBLp1: + cmp edi,dword ptr [_glClipY] + jb @@TBEnd + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TBcontinue +@@TBLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TBLp2 +@@TBcontinue: + and ebp,2 + jz @@TBx + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TBx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TBLp1 + + mov edx,2 +@@TBLp3: + cmp edi,dword ptr [_glClipY] + jb @@TBEnd + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TBcontinue2 +@@TBLp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TBLp4 +@@TBcontinue2: + and ebp,2 + jz @@TBx2 + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TBx2: + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TBLp3 +@@TBEnd: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeC: + mov edx,30 +@@TCLp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TCLp2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TCx +@@TCLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TCLp2 +@@TCx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TCLp1 + +@@TCb: + mov edx,16 +@@TCLp3: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TCLp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TCLp4 + sub edi,NBUFFW32 + dec edx + jnz @@TCLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeD: + push ebp + mov edx,30 +@@TDLp1: + cmp edi,dword ptr [_glClipY] + jb @@TDEnd + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TDcontinue +@@TDLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TDLp2 +@@TDcontinue: + and ebp,2 + jz @@TDx + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TDx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TDLp1 + + mov edx,16 +@@TDLp3: + cmp edi,dword ptr [_glClipY] + jb @@TDEnd + mov ecx,8 +@@TDLp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TDLp4 + sub edi,NBUFFW32 + dec edx + jnz @@TDLp3 +@@TDEnd: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeG: + mov edx,32 + xor eax,eax +@@TGLp1: + cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TGLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TGLp2 + sub edi,NBUFFW32 + dec edx + jnz @@TGLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeH: + push ebp + mov ebp,32 +@@THLp1: + mov edx,32 +@@THLp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@THJ + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@THDone + mov ecx,eax + add esi,ecx + xor eax,eax + shr ecx,1 + jnc @@THw + mov [edi],al + inc edi + test ecx,ecx + jz @@THx +@@THw: shr ecx,1 + jnc @@THLp3 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@THx +@@THLp3: + mov [edi],eax + add edi,4 + dec ecx + jnz @@THLp3 +@@THx: + test edx,edx + jz @@THNxt + jmp @@THLp2 +@@THJ: + neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@THLp2 +@@THNxt: + sub edi,NBUFFW32 + dec ebp + jnz @@THLp1 +@@THDone: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeI: mov edx,30 + xor eax,eax +@@TILp1: cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TILp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TIx +@@TILp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TILp2 +@@TIx: sub edi,NBUFFW32 + test edx,edx + jz @@TIb + sub edx,2 + jmp @@TILp1 + +@@TIb: mov edx,2 +@@TILp3: cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TILp4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TIx2 +@@TILp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TILp4 +@@TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TILp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeJ: mov edx,30 + xor eax,eax +@@TJLp1: cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TJLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TJx +@@TJLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TJLp2 +@@TJx: sub edi,NBUFFW32 + test edx,edx + jz @@TJb + add edi,edx + sub edx,2 + jmp @@TJLp1 + +@@TJb: mov edx,2 +@@TJLp3: cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TJLp4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TJx2 +@@TJLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TJLp4 +@@TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TJLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeK: mov edx,30 + xor eax,eax +@@TKLp1: cmp edi,dword ptr [_glClipY] + jb @@Done + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TKLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TKx +@@TKLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TKLp2 +@@TKx: sub edi,NBUFFW32 + test edx,edx + jz @@TKb + sub edx,2 + jmp @@TKLp1 + +@@TKb: mov edx,16 +@@TKLp3: cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TKLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TKLp4 + sub edi,NBUFFW32 + dec edx + jnz @@TKLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeL: mov edx,30 + xor eax,eax +@@TLLp1: cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TLLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TLx +@@TLLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TLLp2 +@@TLx: sub edi,NBUFFW32 + test edx,edx + jz @@TLb + add edi,edx + sub edx,2 + jmp @@TLLp1 + +@@TLb: mov edx,16 +@@TLLp3: cmp edi,dword ptr [_glClipY] + jb @@Done + mov ecx,8 +@@TLLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TLLp4 + sub edi,NBUFFW32 + dec edx + jnz @@TLLp3 + jmp @@Done + +@@PDone: + pop eax + +@@Done: + pop esi + pop edi + pop edx + pop ebx + ret +@DrawMTileClipTop@4 endp + + + +;*********************************************************** +;* static void DrawMTileDitherClipBottom (BYTE *pDecodeTo) +;* ECX = pDecodeTo +;*********************************************************** +DrawMTileDitherClipBottom proc + push ebx + push edx + push edi + push esi + + ;sgT = &_microoffset[0][0]; + mov edi, offset _microoffset + mov dword ptr [sgT], edi + + mov edi,ecx ; Dest + + mov eax,dword ptr [_nLVal] + test al,al + jz @@NoLt + cmp al,byte ptr [_lightmax] + jz @@Black + + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jnz @@Speed + + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov ebx,dword ptr [_nLVal]; ; Light conversion table + shl ebx,8 + add ebx,dword ptr [_pLightTbl]; + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz @@Type0 ; Solid 32x32 block + cmp ax,1 + jz @@Type1 ; 32x32 block with '0' holes + cmp ax,2 + jz @@Type2 ; Left Triangle + cmp ax,3 + jz @@Type3 ; Right Triangle + cmp ax,4 + jz @@Type4 ; Left Triangle to wall + jmp @@Type5 ; Right Triangle to wall + +@@Speed: + mov esi,dword ptr [sgT] + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [_nLVal] + shl eax,2 + add esi,eax ; Source + mov eax,dword ptr [esi] + mov esi,dword ptr [_pSpeedCels] + add esi,eax + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +@@SCmp: cmp ax,8 + jz @@Type8 ; PreTrans Solid 32x32 block + cmp ax,9 + jz @@Type9 ; PreTrans 32x32 block with '0' holes + cmp ax,10 + jz @@TypeA ; PreTrans Left Triangle + cmp ax,11 + jz @@TypeB ; PreTrans Right Triangle + cmp ax,12 + jz @@TypeC ; PreTrans Left Triangle to wall + jmp @@TypeD ; PreTrans Right Triangle to wall + +@@NoLt: mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RNoLt + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RNoLt: + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp @@SCmp + +@@Black: + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RBlk + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RBlk: + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz @@TypeG ; Black Trans Solid 32x32 block + cmp ax,1 + jz @@TypeH ; Black Trans 32x32 block with '0' holes + cmp ax,2 + jz @@TypeI ; Black Trans Left Triangle + cmp ax,3 + jz @@TypeJ ; Black Trans Right Triangle + cmp ax,4 + jz @@TypeK ; Black Trans Left Triangle to wall + jmp @@TypeL ; Black Trans Right Triangle to wall + +;*-----------------------------------------------------------------------*/ + +@@Type0: + push ebp + mov ebp,16 +@@T0Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T0C1 + add esi,32 + add edi,32 + jmp @@T0C2 +@@T0C1: + mov ecx,8 + X_DWORD2 +@@T0C2: + sub edi,NBUFFW32 + cmp edi,dword ptr [_glClipY] + jb @@T0C3 + add esi,32 + add edi,32 + jmp @@T0C4 +@@T0C3: + mov ecx,8 + X_DWORD1 +@@T0C4: + sub edi,NBUFFW32 + dec ebp + jnz @@T0Lp1 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type1: + push ebp + mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 +@@T1Lp1: + push ecx + mov ebp,32 +@@T1Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T1J + + sub ebp,eax + cmp edi,dword ptr [_glClipY] + jb @@T1C1 + add esi,eax + add edi,eax + jmp @@T1x +@@T1C1: + mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz @@T1Od + X_BYTE1 + jmp @@T1x +@@T1Od: + X_BYTE2 +@@T1x: + test ebp,ebp + jz @@T1Nxt + jmp @@T1Lp2 +@@T1J: + neg al ; Do jump + add edi,eax + sub ebp,eax + jnz @@T1Lp2 +@@T1Nxt: + pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz @@T1Lp1 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type2: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov ebp,30 + CLIP_BOTTOM @@T2Lp1 @@T2b ebp 0 1 +@@T2Lp1: + add edi,ebp + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T2Od + X_BYTE1_PREPAD + jmp @@T2x +@@T2Od: + X_BYTE2_PREPAD +@@T2x: + sub edi,NBUFFW32 + sub ebp,2 + jge @@T2Lp1 + +@@T2b: + mov ebp,2 + CLIP_BOTTOM @@T2Lp4 @@T2Done ebp 1 1 +@@T2Lp4: + add edi,ebp + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T2Od2 + X_BYTE1_PREPAD + jmp @@T2x2 +@@T2Od2: + X_BYTE2_PREPAD +@@T2x2: + sub edi,NBUFFW32 + add ebp,2 + cmp ebp,32 + jnz @@T2Lp4 +@@T2Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type3: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov ebp,30 + CLIP_BOTTOM @@T3Lp1 @@T3b ebp 0 1 +@@T3Lp1: + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T3Od + X_BYTE1_PAD + jmp @@T3x +@@T3Od: + X_BYTE2_PAD +@@T3x: + sub edi,NBUFFW32 + add edi,ebp + sub ebp,2 + jge @@T3Lp1 + +@@T3b: + mov ebp,2 + CLIP_BOTTOM @@T3Lp4 @@T3Done ebp 1 1 +@@T3Lp4: + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T3Od2 + X_BYTE1_PAD + jmp @@T3x2 +@@T3Od2: + X_BYTE2_PAD +@@T3x2: + sub edi,NBUFFW32 + add edi,ebp + add ebp,2 + cmp ebp,32 + jnz @@T3Lp4 +@@T3Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type4: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov ebp,30 + CLIP_BOTTOM @@T4Lp1 @@T4b ebp 0 1 +@@T4Lp1: + add edi,ebp + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T4Od + X_BYTE1_PREPAD + jmp @@T4x +@@T4Od: + X_BYTE2_PREPAD +@@T4x: + sub edi,NBUFFW32 + sub ebp,2 + jge @@T4Lp1 + +@@T4b: + mov ebp,8 +@@T4Lp4: + cmp edi,dword ptr [_glClipY] + jb @@T4C2 + add esi,32 + add edi,32 + jmp @@T4C3 +@@T4C2: + mov ecx,8 + X_DWORD2 +@@T4C3: + sub edi,NBUFFW32 + cmp edi,dword ptr [_glClipY] + jb @@T4C4 + add esi,32 + add edi,32 + jmp @@T4C5 +@@T4C4: + mov ecx,8 + X_DWORD1 +@@T4C5: + sub edi,NBUFFW32 + dec ebp + jnz @@T4Lp4 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type5: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov ebp,30 + CLIP_BOTTOM @@T5Lp1 @@T5b ebp 0 1 +@@T5Lp1: + mov ecx,32 + sub ecx,ebp + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@T5Od + X_BYTE1_PAD + jmp @@T5x +@@T5Od: + X_BYTE2_PAD +@@T5x: + sub edi,NBUFFW32 + add edi,ebp + sub ebp,2 + jge @@T5Lp1 + +@@T5b: + mov ebp,8 +@@T5Lp4: + cmp edi,dword ptr [_glClipY] + jb @@T5C2 + add esi,32 + add edi,32 + jmp @@T5C3 +@@T5C2: + mov ecx,8 + X_DWORD2 +@@T5C3: + sub edi,NBUFFW32 + cmp edi,dword ptr [_glClipY] + jb @@T5C4 + add esi,32 + add edi,32 + jmp @@T5C5 +@@T5C4: + mov ecx,8 + X_DWORD1 +@@T5C5: + sub edi,NBUFFW32 + dec ebp + jnz @@T5Lp4 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type8: mov edx,16 +@@T8Lp1: cmp edi,dword ptr [_glClipY] + jb @@T8C1 + add esi,32 + add edi,32 + jmp @@T8C2 +@@T8C1: mov ecx,8 +@@T8Lp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@T8Lp2 +@@T8C2: sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@T8C3 + add esi,32 + add edi,32 + jmp @@T8C4 +@@T8C3: mov ecx,8 +@@T8Lp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@T8Lp3 +@@T8C4: sub edi,NBUFFW32 + dec edx + jnz @@T8Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type9: + mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 +@@T9Lp1: + push ecx + mov edx,32 +@@T9Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T9J + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@T9C1 + add esi,eax + add edi,eax + jmp @@T9x +@@T9C1: + mov ecx,eax + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz @@T9Od + shr ecx,1 + jnc @@T9w + inc esi + inc edi + test ecx,ecx + jz @@T9x + jmp @@T9w2 +@@T9w: shr ecx,1 + jnc @@T9Lp3 + inc esi + inc edi + mov al,[esi] + inc esi + mov [edi],al + inc edi + test ecx,ecx + jz @@T9x +@@T9Lp3: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@T9Lp3 + jmp @@T9x + +@@T9Od: shr ecx,1 + jnc @@T9w2 + mov al,[esi] + inc esi + mov [edi],al + inc edi + test ecx,ecx + jz @@T9x + jmp @@T9w +@@T9w2: shr ecx,1 + jnc @@T9Lp4 + mov al,[esi] + add esi,2 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@T9x +@@T9Lp4: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@T9Lp4 + +@@T9x: test edx,edx + jz @@T9Nxt + jmp @@T9Lp2 + +@@T9J: neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@T9Lp2 +@@T9Nxt: + pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz @@T9Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeA: + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 + CLIP_BOTTOM @@TALp1 @@TAb edx 0 1 +@@TALp1: + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TAOd + shr ecx,2 + jnc @@TALp2 + mov ax,[esi+2] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + test ecx,ecx + jz @@TAx +@@TALp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TALp2 + jmp @@TAx +@@TAOd: + shr ecx,2 + jnc @@TALp3 + mov ax,[esi+2] + add esi,4 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TAx +@@TALp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TALp3 +@@TAx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TALp1 + +@@TAb: + mov edx,2 + CLIP_BOTTOM @@TALp4 @@Done edx 1 1 +@@TALp4: + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TAOd2 + shr ecx,2 + jnc @@TALp5 + mov ax,[esi+2] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + test ecx,ecx + jz @@TAx2 +@@TALp5: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TALp5 + jmp @@TAx2 +@@TAOd2: + shr ecx,2 + jnc @@TALp6 + mov ax,[esi+2] + add esi,4 + mov [edi],al + add edi,2 + dec ecx + jz @@TAx2 +@@TALp6: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TALp6 +@@TAx2: + sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TALp4 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeB: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 + CLIP_BOTTOM @@TBLp1 @@TBb edx 0 1 +@@TBLp1: + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov ebp,ecx + mov dword ptr [sgLineVal],eax + jz @@TBOd + shr ecx,2 + jz @@TBcontinue +@@TBLp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TBLp2 +@@TBcontinue: + and ebp,2 + jz @@TBx + mov ax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + jmp @@TBx +@@TBOd: + shr ecx,2 + jz @@TBcontinue2 +@@TBLp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TBLp3 +@@TBcontinue2: + and ebp,2 + jz @@TBx + mov ax,[esi] + add esi,4 + mov [edi],al + add edi,2 +@@TBx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TBLp1 + + +@@TBb: + mov edx,2 + CLIP_BOTTOM @@TBLp4 @@TBDone edx 1 1 +@@TBLp4: + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov ebp,ecx + mov dword ptr [sgLineVal],eax + jz @@TBOd2 + shr ecx,2 + jz @@TBcontinue3 +@@TBLp5: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TBLp5 +@@TBcontinue3: + and ebp,2 + jz @@TBx2 + mov ax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + jmp @@TBx2 +@@TBOd2: + shr ecx,2 + jz @@TBcontinue4 +@@TBLp6: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TBLp6 +@@TBcontinue4: + and ebp,2 + jz @@TBx2 + mov ax,[esi] + add esi,4 + mov [edi],al + add edi,2 +@@TBx2: + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TBLp4 +@@TBDone: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeC: + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 + CLIP_BOTTOM @@TCLp1 @@TCb edx 0 1 +@@TCLp1: + add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TCOd + shr ecx,2 + jnc @@TCLp2 + mov ax,[esi+2] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + test ecx,ecx + jz @@TCx +@@TCLp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TCLp2 + jmp @@TCx + +@@TCOd: shr ecx,2 + jnc @@TCLp3 + mov ax,[esi+2] + add esi,4 + mov [edi],al + test ecx,ecx + lea edi,[edi+2] + jz @@TCx +@@TCLp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + dec ecx + lea edi,[edi+2] + jnz @@TCLp3 + +@@TCx: sub edi,NBUFFW32 + sub edx,2 + jge @@TCLp1 + +@@TCb: + mov edx,8 +@@TCLp4: + cmp edi,dword ptr [_glClipY] + jb @@TCC2 + add esi,32 + add edi,32 + jmp @@TCC3 +@@TCC2: + mov ecx,8 +@@TCLp5: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TCLp5 +@@TCC3: + sub edi,NBUFFW32 + cmp edi,dword ptr [_glClipY] + jb @@TCC4 + add esi,32 + add edi,32 + jmp @@TCC5 +@@TCC4: + mov ecx,8 +@@TCLp6: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TCLp6 +@@TCC5: + sub edi,NBUFFW32 + dec edx + jnz @@TCLp4 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeD: + push ebp + xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 + CLIP_BOTTOM @@TDLp1 @@TDb edx 0 1 +@@TDLp1: + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov ebp,ecx + mov dword ptr [sgLineVal],eax + jz @@TDOd + shr ecx,2 + jz @@TDcontinue +@@TDLp2: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TDLp2 +@@TDcontinue: + and ebp,2 + jz @@TDx + mov ax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + inc edi + jmp @@TDx +@@TDOd: + shr ecx,2 + jz @@TDcontinue2 +@@TDLp3: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TDLp3 +@@TDcontinue2: + and ebp,2 + jz @@TDx + mov ax,[esi] + add esi,4 + mov [edi],al + add edi,2 +@@TDx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TDLp1 + + +@@TDb: + mov edx,8 +@@TDLp4: + cmp edi,dword ptr [_glClipY] + jb @@TDC2 + add esi,32 + add edi,32 + jmp @@TDC3 +@@TDC2: + mov ecx,8 +@@TDLp5: + mov eax,[esi] + add esi,4 + inc edi + ror eax,8 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + inc edi + dec ecx + jnz @@TDLp5 +@@TDC3: + sub edi,NBUFFW32 + cmp edi,dword ptr [_glClipY] + jb @@TDC4 + add esi,32 + add edi,32 + jmp @@TDC5 +@@TDC4: + mov ecx,8 +@@TDLp6: + mov eax,[esi] + add esi,4 + mov [edi],al + add edi,2 + ror eax,16 + mov [edi],al + add edi,2 + dec ecx + jnz @@TDLp6 +@@TDC5: + sub edi,NBUFFW32 + dec edx + jnz @@TDLp4 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeG: mov edx,16 + xor eax,eax +@@TGLp1: cmp edi,dword ptr [_glClipY] + jb @@TGC1 + add esi,32 + add edi,32 + jmp @@TGC2 +@@TGC1: mov ecx,8 +@@TGLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TGLp2 +@@TGC2: sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@TGC3 + add esi,32 + add edi,32 + jmp @@TGC4 +@@TGC3: mov ecx,8 +@@TGLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TGLp3 +@@TGC4: sub edi,NBUFFW32 + dec edx + jnz @@TGLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeH: mov eax,edi + and eax,1 + mov dword ptr [sgLineVal],eax + mov ecx,32 + +@@THLp1: push ecx + mov edx,32 + +@@THLp2: xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@THJ + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@THC1 + add esi,eax + add edi,eax + jmp @@THx +@@THC1: mov ecx,eax + add esi,ecx + mov eax,edi + and eax,1 + cmp eax,dword ptr [sgLineVal] + jnz @@THOd + xor eax,eax + shr ecx,1 + jnc @@THw + inc edi + test ecx,ecx + jz @@THx + jmp @@THw2 +@@THw: shr ecx,1 + jnc @@THLp3 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@THx +@@THLp3: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@THLp3 + jmp @@THx + +@@THOd: xor eax,eax + shr ecx,1 + jnc @@THw2 + mov [edi],al + inc edi + test ecx,ecx + jz @@THx + jmp @@THw +@@THw2: shr ecx,1 + jnc @@THLp4 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@THx +@@THLp4: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@THLp4 + +@@THx: test edx,edx + jz @@THNxt + jmp @@THLp2 + +@@THJ: neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@THLp2 +@@THNxt: pop ecx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + sub edi,NBUFFW32 + dec ecx + jnz @@THLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeI: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TILp1: cmp edi,dword ptr [_glClipY] + jb @@TIC1 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TIx +@@TIC1: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TIOd + xor eax,eax + shr ecx,2 + jnc @@TILp2 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TIx +@@TILp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TILp2 + jmp @@TIx + +@@TIOd: xor eax,eax + shr ecx,2 + jnc @@TILp3 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TIx +@@TILp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TILp3 + +@@TIx: sub edi,NBUFFW32 + test edx,edx + jz @@TIb + sub edx,2 + jmp @@TILp1 + +@@TIb: mov edx,2 +@@TILp4: cmp edi,dword ptr [_glClipY] + jb @@TIC2 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TIx2 +@@TIC2: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TIOd2 + xor eax,eax + shr ecx,2 + jnc @@TILp5 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TIx2 +@@TILp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TILp5 + jmp @@TIx2 + +@@TIOd2: xor eax,eax + shr ecx,2 + jnc @@TILp6 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TIx2 +@@TILp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TILp6 + +@@TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TILp4 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeJ: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TJLp1: cmp edi,dword ptr [_glClipY] + jb @@TJC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TJx +@@TJC1: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TJOd + xor eax,eax + shr ecx,2 + jnc @@TJLp2 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TJx +@@TJLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TJLp2 + jmp @@TJx + +@@TJOd: xor eax,eax + shr ecx,2 + jnc @@TJLp3 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TJx +@@TJLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TJLp3 + +@@TJx: sub edi,NBUFFW32 + test edx,edx + jz @@TJb + add edi,edx + sub edx,2 + jmp @@TJLp1 + +@@TJb: mov edx,2 +@@TJLp4: cmp edi,dword ptr [_glClipY] + jb @@TJC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TJx2 +@@TJC2: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TJOd2 + xor eax,eax + shr ecx,2 + jnc @@TJLp5 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TJx2 +@@TJLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TJLp5 + jmp @@TJx2 + +@@TJOd2: xor eax,eax + shr ecx,2 + jnc @@TJLp6 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TJx2 +@@TJLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TJLp6 + +@@TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TJLp4 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeK: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TKLp1: cmp edi,dword ptr [_glClipY] + jb @@TKC1 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TKx +@@TKC1: add edi,edx + mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TKOd + xor eax,eax + shr ecx,2 + jnc @@TKLp2 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TKx +@@TKLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TKLp2 + jmp @@TKx + +@@TKOd: xor eax,eax + shr ecx,2 + jnc @@TKLp3 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TKx +@@TKLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TKLp3 + +@@TKx: sub edi,NBUFFW32 + test edx,edx + jz @@TKb + sub edx,2 + jmp @@TKLp1 + +@@TKb: mov edx,8 +@@TKLp4: cmp edi,dword ptr [_glClipY] + jb @@TKC2 + add esi,32 + add edi,32 + jmp @@TKC3 +@@TKC2: mov ecx,8 + xor eax,eax +@@TKLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TKLp5 +@@TKC3: sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@TKC4 + add esi,32 + add edi,32 + jmp @@TKC5 +@@TKC4: mov ecx,8 + xor eax,eax +@@TKLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TKLp6 +@@TKC5: sub edi,NBUFFW32 + dec edx + jnz @@TKLp4 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeL: xor eax,eax + mov dword ptr [sgLineVal],eax + mov edx,30 +@@TLLp1: cmp edi,dword ptr [_glClipY] + jb @@TLC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TLx +@@TLC1: mov ecx,32 + sub ecx,edx + mov eax,dword ptr [sgLineVal] + inc eax + and eax,1 + mov dword ptr [sgLineVal],eax + jz @@TLOd + xor eax,eax + shr ecx,2 + jnc @@TLLp2 + inc edi + mov [edi],al + inc edi + test ecx,ecx + jz @@TLx +@@TLLp2: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TLLp2 + jmp @@TLx + +@@TLOd: xor eax,eax + shr ecx,2 + jnc @@TLLp3 + mov [edi],al + add edi,2 + test ecx,ecx + jz @@TLx +@@TLLp3: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TLLp3 + +@@TLx: sub edi,NBUFFW32 + test edx,edx + jz @@TLb + add edi,edx + sub edx,2 + jmp @@TLLp1 + +@@TLb: mov edx,8 +@@TLLp4: cmp edi,dword ptr [_glClipY] + jb @@TLC2 + add esi,32 + add edi,32 + jmp @@TLC3 +@@TLC2: mov ecx,8 + xor eax,eax +@@TLLp5: mov byte ptr [edi+1],al + mov byte ptr [edi+3],al + add edi,4 + dec ecx + jnz @@TLLp5 +@@TLC3: sub edi,NBUFFW32 + + cmp edi,dword ptr [_glClipY] + jb @@TLC4 + add esi,32 + add edi,32 + jmp @@TLC5 +@@TLC4: mov ecx,8 + xor eax,eax +@@TLLp6: mov byte ptr [edi],al + mov byte ptr [edi+2],al + add edi,4 + dec ecx + jnz @@TLLp6 +@@TLC5: sub edi,NBUFFW32 + dec edx + jnz @@TLLp4 + +@@Done: + pop esi + pop edi + pop edx + pop ebx + ret +DrawMTileDitherClipBottom endp + + + +;*********************************************************** +;* static void DrawMTileHalfDitherClipBottom (BYTE *pDecodeTo, long *mask) +;* ECX = pDecodeTo +;*********************************************************** +DrawMTileHalfDitherClipBottom proc + push ebx + push edi + push esi + + ;sgT = &_microoffset[0][0]; + mov edi, offset _microoffset + mov dword ptr [sgT], edi + + mov edi,ecx ; Dest + mov dword ptr [sgMask], edx + + mov eax,dword ptr [_nLVal] + test al,al + jz @@NoLt + cmp al,byte ptr [_lightmax] + jz @@Black + + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jnz @@Speed + + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov ebx,dword ptr [_nLVal]; ; Light conversion table + shl ebx,8 + add ebx,dword ptr [_pLightTbl]; + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,0fh + jz @@Type0 ; Solid 32x32 block + cmp ax,1 + jz @@Type1 ; 32x32 block with '0' holes + cmp ax,2 + jz @@Type2 ; Left Triangle + cmp ax,3 + jz @@Type3 ; Right Triangle + cmp ax,4 + jz @@Type4 ; Left Triangle to wall + jmp @@Type5 ; Right Triangle to wall +@@Speed: + mov esi,dword ptr [sgT] + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [_nLVal] + shl eax,2 + add esi,eax ; Source + mov eax,dword ptr [esi] + mov esi,dword ptr [_pSpeedCels] + add esi,eax + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,0fh +@@SCmp: cmp ax,8 + jz @@Type8 ; PreTrans Solid 32x32 block + cmp ax,9 + jz @@Type9 ; PreTrans 32x32 block with '0' holes + cmp ax,10 + jz @@TypeA ; PreTrans Left Triangle + cmp ax,11 + jz @@TypeB ; PreTrans Right Triangle + cmp ax,12 + jz @@TypeC ; PreTrans Left Triangle to wall + jmp @@TypeD ; PreTrans Right Triangle to wall + +@@NoLt: mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RNoLt + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RNoLt: mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + add eax,8 + jmp @@SCmp + +@@Black: mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RBlk + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RBlk: mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz @@TypeG ; Black Trans Solid 32x32 block + cmp ax,1 + jz @@TypeH ; Black Trans 32x32 block with '0' holes + cmp ax,2 + jz @@TypeI ; Black Trans Left Triangle + cmp ax,3 + jz @@TypeJ ; Black Trans Right Triangle + cmp ax,4 + jz @@TypeK ; Black Trans Left Triangle to wall + jmp @@TypeL ; Black Trans Right Triangle to wall + +;*-----------------------------------------------------------------------*/ + +@@Type0: + push ebp + mov ebp,32 +@@T0Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T0C1 + add esi,32 + add edi,32 + jmp @@T0C2 +@@T0C1: + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@T0Lp2: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T0S1 + xlatb + mov byte ptr [edi],al +@@T0S1: + inc edi + dec ecx + jnz @@T0Lp2 +@@T0C2: + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec ebp + jnz @@T0Lp1 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type1: + mov ecx,32 +@@T1Lp1: + push ecx + mov eax,dword ptr [sgMask] + mov eax,dword ptr [eax] + mov dword ptr [sgCM],eax + mov edx,32 +@@T1Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T1J + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@T1C1 + add esi,eax + add edi,eax + jmp @@T1x +@@T1C1: mov ecx,eax + push edx + mov edx,dword ptr [sgCM] +@@T1Lp3: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T1S1 + xlatb + mov byte ptr [edi],al +@@T1S1: inc edi + dec ecx + jnz @@T1Lp3 + mov dword ptr [sgCM],edx + pop edx +@@T1x: test edx,edx + jz @@T1Nxt + jmp @@T1Lp2 + +@@T1J: neg al ; Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz @@T1S2 + push eax + mov eax,dword ptr [sgCM] + shl eax,cl + mov dword ptr [sgCM],eax + pop eax +@@T1S2: sub edx,eax + jnz @@T1Lp2 +@@T1Nxt: + pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec ecx + jnz @@T1Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type2: + mov edx,30 + CLIP_BOTTOM @@T2Lp1 @@T2b edx 0 0 +@@T2Lp1: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@T2Lp2 + mov ax,[esi+2] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@T2x +@@T2Lp2: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T2Lp2 +@@T2x: + sub edi,NBUFFW32 + sub edx,2 + jge @@T2Lp1 + +@@T2b: + mov edx,2 + CLIP_BOTTOM @@T2Lp3 @@Done edx 1 0 +@@T2Lp3: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@T2Lp4 + mov ax,[esi+2] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@T2x2 +@@T2Lp4: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T2Lp4 +@@T2x2: + sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@T2Lp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type3: + push ebp + mov edx,30 + CLIP_BOTTOM @@T3Lp1 @@T3b edx 0 0 +@@T3Lp1: + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@T3continue +@@T3Lp2: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T3Lp2 +@@T3continue: + and ebp,2 + jz @@T3x + mov ax,[esi] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 +@@T3x: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@T3Lp1 + +@@T3b: + mov edx,2 + CLIP_BOTTOM @@T3Lp3 @@T3Done edx 1 0 +@@T3Lp3: + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@T3continue2 +@@T3Lp4: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T3Lp4 +@@T3continue2: + and ebp,2 + jz @@T3x2 + mov ax,[esi] + add esi,2 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 +@@T3x2: + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@T3Lp3 +@@T3Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type4: + mov edx,30 + CLIP_BOTTOM @@T4Lp1 @@T4b edx 0 0 +@@T4Lp1: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@T4Lp2 + mov ax,[esi+2] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@T4x +@@T4Lp2: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T4Lp2 +@@T4x: + sub edi,NBUFFW32 + sub edx,2 + jge @@T4Lp1 + + +@@T4b: + mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@T4Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T4C2 + add esi,32 + add edi,32 + jmp @@T4C3 +@@T4C2: + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@T4Lp4: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T4S1 + xlatb + mov [edi],al +@@T4S1: + inc edi + dec ecx + jnz @@T4Lp4 + pop edx +@@T4C3: + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@T4Lp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type5: + push ebp + mov edx,30 + CLIP_BOTTOM @@T5Lp1 @@T5b edx 0 0 +@@T5Lp1: + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@T5continue +@@T5Lp2: + mov eax,[esi] + add esi,4 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T5Lp2 +@@T5continue: + and ebp,2 + jz @@T5x + mov ax,[esi] + add esi,4 + xlatb + ror ax,8 + xlatb + ror ax,8 + mov [edi],ax + add edi,2 +@@T5x: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@T5Lp1 + + +@@T5b: + mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@T5Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T5C2 + add esi,32 + add edi,32 + jmp @@T5C3 +@@T5C2: + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@T5Lp4: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T5S1 + xlatb + mov byte ptr [edi],al +@@T5S1: + inc edi + dec ecx + jnz @@T5Lp4 + mov ebp,esi + and ebp,2 + add esi,ebp + pop edx +@@T5C3: + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@T5Lp3 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type8: mov edx,32 +@@T8Lp1: cmp edi,dword ptr [_glClipY] + jb @@T8C1 + add esi,32 + add edi,32 + jmp @@T8C2 +@@T8C1: push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@T8Lp2: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T8S1 + mov byte ptr [edi],al +@@T8S1: inc edi + dec ecx + jnz @@T8Lp2 + pop edx +@@T8C2: sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@T8Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type9: mov ecx,32 + +@@T9Lp1: push ecx + mov eax,dword ptr [sgMask] + mov eax,dword ptr [eax] + mov dword ptr [sgCM],eax + + mov edx,32 + +@@T9Lp2: xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T9J + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@T9C1 + add esi,eax + add edi,eax + jmp @@T9x +@@T9C1: mov ecx,eax + push edx + mov edx,dword ptr [sgCM] +@@T9Lp3: + mov al,[esi] + inc esi + shl edx,1 + jnc @@T9S1 + mov byte ptr [edi],al +@@T9S1: inc edi + dec ecx + jnz @@T9Lp3 + mov dword ptr [sgCM],edx + pop edx +@@T9x: test edx,edx + jz @@T9Nxt + jmp @@T9Lp2 + +@@T9J: neg al ; Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz @@T9S2 + mov ebx,dword ptr [sgCM] + shl ebx,cl + mov dword ptr [sgCM],ebx +@@T9S2: sub edx,eax + jnz @@T9Lp2 +@@T9Nxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec ecx + jnz @@T9Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeA: + mov edx,30 + CLIP_BOTTOM @@TALp1 @@TAb edx 0 0 +@@TALp1: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TALp2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TAx +@@TALp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TALp2 +@@TAx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TALp1 + +@@TAb: + mov edx,2 + CLIP_BOTTOM @@TALp3 @@Done edx 1 0 +@@TALp3: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TALp4 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TAx2 +@@TALp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TALp4 +@@TAx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TALp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeB: + push ebp + mov edx,30 + CLIP_BOTTOM @@TBLp1 @@TBb edx 0 0 +@@TBLp1: + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TBcontinue +@@TBLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TBLp2 +@@TBcontinue: + and ebp,2 + jz @@TBx + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TBx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TBLp1 + +@@TBb: + mov edx,2 + CLIP_BOTTOM @@TBLp3 @@TBDone edx 1 0 +@@TBLp3: + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TBcontinue2 +@@TBLp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TBLp4 +@@TBcontinue2: + and ebp,2 + jz @@TBx2 + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TBx2: + sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TBLp3 +@@TBDone: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeC: + mov edx,30 + CLIP_BOTTOM @@TCLp1 @@TCb edx 0 0 +@@TCLp1: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TCLp2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TCx +@@TCLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TCLp2 +@@TCx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TCLp1 + + +@@TCb: + mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@TCLp3: + cmp edi,dword ptr [_glClipY] + jb @@TCC2 + add esi,32 + add edi,32 + jmp @@TCC3 +@@TCC2: push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@TCLp4: + mov al,[esi] + inc esi + shl edx,1 + jnc @@TCS1 + mov [edi],al +@@TCS1: + inc edi + dec ecx + jnz @@TCLp4 + pop edx +@@TCC3: + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TCLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeD: + push ebp + mov edx,30 + CLIP_BOTTOM @@TDLp1 @@TDb edx 0 0 +@@TDLp1: + mov ecx,32 + sub ecx,edx + mov ebp,ecx + shr ecx,2 + jz @@TDcontinue +@@TDLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TDLp2 +@@TDcontinue: + and ebp,2 + jz @@TDx + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TDx: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TDLp1 + + +@@TDb: + mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@TDLp3: + cmp edi,dword ptr [_glClipY] + jb @@TDC2 + add esi,32 + add edi,32 + jmp @@TDC3 +@@TDC2: + push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + mov ecx,32 +@@TDLp4: + mov al,[esi] + inc esi + shl edx,1 + jnc @@TDS1 + mov byte ptr [edi],al +@@TDS1: + inc edi + dec ecx + jnz @@TDLp4 + mov ebp,esi + and ebp,2 + add esi,ebp + pop edx +@@TDC3: + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TDLp3 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeG: mov edx,32 +@@TGLp1: cmp edi,dword ptr [_glClipY] + jb @@TGC1 + add esi,32 + add edi,32 + jmp @@TGC2 +@@TGC1: push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +@@TGLp2: shl edx,1 + jnc @@TGS1 + mov byte ptr [edi],al +@@TGS1: inc edi + dec ecx + jnz @@TGLp2 + pop edx +@@TGC2: sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TGLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeH: mov ecx,32 + +@@THLp1: push ecx + mov eax,dword ptr [sgMask] + mov eax,dword ptr [eax] + mov dword ptr [sgCM],eax + + mov edx,32 + +@@THLp2: xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@THJ + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@THC1 + add esi,eax + add edi,eax + jmp @@THx +@@THC1: mov ecx,eax + add esi,ecx + push edx + mov edx,dword ptr [sgCM] + xor eax,eax +@@THLp3: shl edx,1 + jnc @@THS1 + mov byte ptr [edi],al +@@THS1: inc edi + dec ecx + jnz @@THLp3 + mov dword ptr [sgCM],edx + pop edx +@@THx: test edx,edx + jz @@THNxt + jmp @@THLp2 + +@@THJ: neg al ; Do jump + add edi,eax + mov ecx,eax + and ecx,01fh + jz @@THS2 + mov ebx,dword ptr [sgCM] + shl ebx,cl + mov dword ptr [sgCM],ebx +@@THS2: sub edx,eax + jnz @@THLp2 +@@THNxt: pop ecx + sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec ecx + jnz @@THLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeI: mov edx,30 + xor eax,eax +@@TILp1: cmp edi,dword ptr [_glClipY] + jb @@TIC1 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TIx +@@TIC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TILp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TIx +@@TILp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TILp2 +@@TIx: sub edi,NBUFFW32 + test edx,edx + jz @@TIb + sub edx,2 + jmp @@TILp1 + +@@TIb: mov edx,2 +@@TILp3: cmp edi,dword ptr [_glClipY] + jb @@TIC2 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TIx2 +@@TIC2: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TILp4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TIx2 +@@TILp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TILp4 +@@TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TILp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeJ: mov edx,30 + xor eax,eax +@@TJLp1: cmp edi,dword ptr [_glClipY] + jb @@TJC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TJx +@@TJC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TJLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TJx +@@TJLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TJLp2 +@@TJx: sub edi,NBUFFW32 + test edx,edx + jz @@TJb + add edi,edx + sub edx,2 + jmp @@TJLp1 + +@@TJb: mov edx,2 +@@TJLp3: cmp edi,dword ptr [_glClipY] + jb @@TJC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TJx2 +@@TJC2: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TJLp4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TJx2 +@@TJLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TJLp4 +@@TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TJLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeK: mov edx,30 + xor eax,eax +@@TKLp1: cmp edi,dword ptr [_glClipY] + jb @@TKC1 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TKx +@@TKC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TKLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TKx +@@TKLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TKLp2 +@@TKx: sub edi,NBUFFW32 + test edx,edx + jz @@TKb + sub edx,2 + jmp @@TKLp1 + +@@TKb: mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@TKLp3: cmp edi,dword ptr [_glClipY] + jb @@TKC2 + add esi,32 + add edi,32 + jmp @@TKC3 +@@TKC2: push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +@@TKLp4: shl edx,1 + jnc @@TKS1 + mov byte ptr [edi],al +@@TKS1: inc edi + dec ecx + jnz @@TKLp4 + pop edx +@@TKC3: sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TKLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeL: mov edx,30 + xor eax,eax +@@TLLp1: cmp edi,dword ptr [_glClipY] + jb @@TLC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TLx +@@TLC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TLLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TLx +@@TLLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TLLp2 +@@TLx: sub edi,NBUFFW32 + test edx,edx + jz @@TLb + add edi,edx + sub edx,2 + jmp @@TLLp1 + +@@TLb: mov eax,dword ptr [sgMask] + sub eax,64 + mov dword ptr [sgMask],eax + mov edx,16 +@@TLLp3: cmp edi,dword ptr [_glClipY] + jb @@TLC2 + add esi,32 + add edi,32 + jmp @@TLC3 +@@TLC2: push edx + mov eax,dword ptr [sgMask] + mov edx,dword ptr [eax] + xor eax,eax + mov ecx,32 +@@TLLp4: shl edx,1 + jnc @@TLS1 + mov byte ptr [edi],al +@@TLS1: inc edi + dec ecx + jnz @@TLLp4 + pop edx +@@TLC3: sub edi,NBUFFW32 + mov eax,dword ptr [sgMask] + sub eax,4 + mov dword ptr [sgMask],eax + dec edx + jnz @@TLLp3 + +@@Done: + pop esi + pop edi + pop ebx + ret +DrawMTileHalfDitherClipBottom endp + + +;*********************************************************** +;* CLIP_BOTTOM_UNROLL(Quit, fTopPiece) +;* Clips top of triangle piece +;* ESI - Source +;* EDI - Dest +;* EBX - set to 4*(lines to skip) +;* EAX - trashed +;* if fLeftPiece +;* ECX - trashed +;*********************************************************** +CLIP_BOTTOM_UNROLL MACRO Start, Quit, fTopPiece + mov eax,edi + sub eax,dword ptr [_glClipY] + jle Start + shr eax,8 + if fTopPiece + cmp eax,14*3 + else + cmp eax,15*3 + endif + jg Quit + mov ebx,sgDivBy3MulBy4[eax*4] + + ;add esi,(data for lines skipped) + mov eax,ebx + if fTopPiece + add esi,TotalDataPerLineTop[ebx] + else + add esi,TotalDataPerLineBottom[ebx] + endif + + ;sub edi,768*(lines skipped) + shl eax,6 + lea eax,[eax+eax*2] + sub edi,eax +ENDM + + +;*********************************************************** +;* UNROLLED_COPY_BOTTOM_RIGHT_TRIANGLE_CLIP +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* assumes segment is cs +;* ESI - Source +;* EDI - Dest +;* EAX - trashed +;* EBX - trashed +;*********************************************************** +UNROLLED_COPY_BOTTOM_RIGHT_TRIANGLE_CLIP MACRO + LOCAL l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,l15,allClipped,Done,CTRTclipping + + CLIP_BOTTOM_UNROLL l0 allClipped 0 + jmp CTRTclipping[ebx] + + CTRTclipping label dword + dd offset l0,offset l1 + dd offset l2,offset l3 + dd offset l4,offset l5 + dd offset l6,offset l7 + dd offset l8,offset l9 + dd offset l10,offset l11 + dd offset l12,offset l13 + dd offset l14,offset l15 + +l0: ;2 bytes + mov ax,[esi] + add esi,4 + mov [edi],ax + sub edi,NBUFFW32-32 +l1: ;4 bytes + mov eax,[esi] + add esi, 4 + mov [edi],eax + sub edi,NBUFFW32-32 +l2: ;6 bytes + mov bx,[esi+4] + mov eax,[esi] + mov [edi+4],bx + mov [edi],eax + add esi, 8 + sub edi,NBUFFW32-32 +l3: ;8 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 8 + sub edi,NBUFFW32-32 +l4: ;10 bytes + mov cx,[esi+8] + mov eax,[esi] + mov [edi+8],cx + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 12 + sub edi,NBUFFW32-32 +l5: ;12 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov eax,[esi+8] + add esi, 12 + mov [edi+8],eax + sub edi,NBUFFW32-32 +l6: ;14 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov cx,[esi+12] + mov eax,[esi+8] + mov [edi+12],cx + mov [edi+8],eax + add esi, 16 + sub edi,NBUFFW32-32 +l7: ;16 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 16 + sub edi,NBUFFW32-32 +l8: ;18 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+16] + add esi, 20 + mov [edi+16],cx + sub edi,NBUFFW32-32 +l9: ;20 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+16] + add esi, 20 + mov [edi+16],eax + sub edi,NBUFFW32-32 +l10: ;22 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+20] + mov eax,[esi+16] + mov [edi+20],cx + mov [edi+16],eax + add esi, 24 + sub edi,NBUFFW32-32 +l11: ;24 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 24 + sub edi,NBUFFW32-32 +l12: ;26 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+24] + add esi, 28 + mov [edi+24],cx + sub edi,NBUFFW32-32 +l13: ;28 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+24] + add esi, 28 + mov [edi+24],eax + sub edi,NBUFFW32-32 +l14: ;30 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+28] + mov eax,[esi+24] + mov [edi+28],cx + mov [edi+24],eax + add esi, 32 + sub edi,NBUFFW32-32 +l15: ;32 bytes + IRP bOffset,0,8,16,24 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 32 + sub edi,NBUFFW32-32 + jmp Done +allClipped: + sub edi,768*16 + add esi,288 ;TotalDataPerLine[15] +Done: +ENDM + + +;*********************************************************** +;* UNROLLED_COPY_BOTTOM_RIGHT_TRIANGLE +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* assumes segment is cs +;* ESI - Source +;* EDI - Dest +;* EAX - trashed +;* EBX - trashed +;*********************************************************** +UNROLLED_COPY_BOTTOM_RIGHT_TRIANGLE MACRO +;2 bytes + mov ax,[esi] + add esi,4 + mov [edi],ax + sub edi,NBUFFW32-32 +;4 bytes + mov eax,[esi] + add esi, 4 + mov [edi],eax + sub edi,NBUFFW32-32 +;6 bytes + mov bx,[esi+4] + mov eax,[esi] + mov [edi+4],bx + mov [edi],eax + add esi, 8 + sub edi,NBUFFW32-32 +;8 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 8 + sub edi,NBUFFW32-32 +;10 bytes + mov cx,[esi+8] + mov eax,[esi] + mov [edi+8],cx + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 12 + sub edi,NBUFFW32-32 +;12 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov eax,[esi+8] + add esi, 12 + mov [edi+8],eax + sub edi,NBUFFW32-32 +;14 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov cx,[esi+12] + mov eax,[esi+8] + mov [edi+12],cx + mov [edi+8],eax + add esi, 16 + sub edi,NBUFFW32-32 +;16 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 16 + sub edi,NBUFFW32-32 +;18 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+16] + add esi, 20 + mov [edi+16],cx + sub edi,NBUFFW32-32 +;20 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+16] + add esi, 20 + mov [edi+16],eax + sub edi,NBUFFW32-32 +;22 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+20] + mov eax,[esi+16] + mov [edi+20],cx + mov [edi+16],eax + add esi, 24 + sub edi,NBUFFW32-32 +;24 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 24 + sub edi,NBUFFW32-32 +;26 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+24] + add esi, 28 + mov [edi+24],cx + sub edi,NBUFFW32-32 +;28 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+24] + add esi, 28 + mov [edi+24],eax + sub edi,NBUFFW32-32 +;30 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+28] + mov eax,[esi+24] + mov [edi+28],cx + mov [edi+24],eax + add esi, 32 + sub edi,NBUFFW32-32 +;32 bytes + IRP bOffset,0,8,16,24 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 32 + sub edi,NBUFFW32-32 +ENDM + + +;*********************************************************** +;* COPY_BOTTOM_RIGHT_TRIANGLE +;* copies the bottom half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* ESI - Source +;* EDI - Dest +;* EAX,EBX,ECX,EDX - trashed +;*********************************************************** +COPY_BOTTOM_RIGHT_TRIANGLE_CLIP MACRO + LOCAL Loop1,Loop2,Continue,Skip,Done + + mov edx,30 + CLIP_BOTTOM Loop1 Done edx 0 0 +Loop1: + mov ecx,32 + sub ecx,edx + mov ebx,ecx + shr ecx,2 + jz Continue +Loop2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz Loop2 +Continue: + and ebx,2 + jz Skip + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +Skip: + add edi,edx + sub edi,NBUFFW32 + sub edx,2 + jge Loop1 +Done: +ENDM + + +;*********************************************************** +;* COPY_BOTTOM_RIGHT_TRIANGLE +;* copies the bottom half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* ESI - Source +;* EDI - Dest +;* EAX,EBX,ECX,EDX - trashed +;*********************************************************** +COPY_BOTTOM_RIGHT_TRIANGLE MACRO + LOCAL Loop1,Loop2,Continue,Skip,Done + + mov edx,30 +Loop1: + mov ecx,32 + sub ecx,edx + mov ebx,ecx + shr ecx,2 + jz Continue +Loop2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz Loop2 +Continue: + and ebx,2 + jz Skip + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +Skip: + add edi,edx + sub edi,NBUFFW32 + sub edx,2 + jge Loop1 +Done: +ENDM + + +;*********************************************************** +;* UNROLLED_COPY_TOP_RIGHT_TRIANGLE +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* assumes segment is cs +;* ESI - Source +;* EDI - Dest +;* EAX - trashed +;* EBX - trashed +;*********************************************************** +UNROLLED_COPY_TOP_RIGHT_TRIANGLE MACRO + LOCAL l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,allClipped,Done,CTRTclipping + + CLIP_BOTTOM_UNROLL l0 allClipped 1 + jmp CTRTclipping[ebx] + + CTRTclipping label dword + dd offset l0,offset l1 + dd offset l2,offset l3 + dd offset l4,offset l5 + dd offset l6,offset l7 + dd offset l8,offset l9 + dd offset l10,offset l11 + dd offset l12,offset l13 + dd offset l14 + +l0: ;30 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+28] + mov eax,[esi+24] + mov [edi+28],cx + mov [edi+24],eax + add esi, 32 + sub edi,NBUFFW32-32 +l1: ;28 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+24] + add esi, 28 + mov [edi+24],eax + sub edi,NBUFFW32-32 +l2: ;26 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+24] + add esi, 28 + mov [edi+24],cx + sub edi,NBUFFW32-32 +l3: ;24 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 24 + sub edi,NBUFFW32-32 +l4: ;22 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+20] + mov eax,[esi+16] + mov [edi+20],cx + mov [edi+16],eax + add esi, 24 + sub edi,NBUFFW32-32 +l5: ;20 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+16] + add esi, 20 + mov [edi+16],eax + sub edi,NBUFFW32-32 +l6: ;18 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+16] + add esi, 20 + mov [edi+16],cx + sub edi,NBUFFW32-32 +l7: ;16 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 16 + sub edi,NBUFFW32-32 +l8: ;14 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov cx,[esi+12] + mov eax,[esi+8] + mov [edi+12],cx + mov [edi+8],eax + add esi, 16 + sub edi,NBUFFW32-32 +l9: ;12 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov eax,[esi+8] + add esi, 12 + mov [edi+8],eax + sub edi,NBUFFW32-32 +l10: ;10 bytes + mov cx,[esi+8] + mov eax,[esi] + mov [edi+8],cx + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 12 + sub edi,NBUFFW32-32 +l11: ;8 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 8 + sub edi,NBUFFW32-32 +l12: ;6 bytes + mov bx,[esi+4] + mov eax,[esi] + mov [edi+4],bx + mov [edi],eax + add esi, 8 + sub edi,NBUFFW32-32 +l13: ;4 bytes + mov eax,[esi] + add esi, 4 + mov [edi],eax + sub edi,NBUFFW32-32 +l14: ;2 bytes + mov ax,[esi] + add esi,4 + mov [edi],ax + sub edi,NBUFFW32-32 + jmp Done +allClipped: + sub edi,768*15 + add esi,256 ;TotalDataPerLine[14] +Done: +ENDM + + +;*********************************************************** +;* UNROLLED_COPY_TOP_RIGHT_TRIANGLE_CLIP +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* assumes segment is cs +;* ESI - Source +;* EDI - Dest +;* EAX - trashed +;* EBX - trashed +;*********************************************************** +UNROLLED_COPY_TOP_RIGHT_TRIANGLE_CLIP MACRO +;30 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+28] + mov eax,[esi+24] + mov [edi+28],cx + mov [edi+24],eax + add esi, 32 + sub edi,NBUFFW32-32 +;28 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+24] + add esi, 28 + mov [edi+24],eax + sub edi,NBUFFW32-32 +;26 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+24] + add esi, 28 + mov [edi+24],cx + sub edi,NBUFFW32-32 +;24 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 24 + sub edi,NBUFFW32-32 +;22 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+20] + mov eax,[esi+16] + mov [edi+20],cx + mov [edi+16],eax + add esi, 24 + sub edi,NBUFFW32-32 +;20 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+16] + add esi, 20 + mov [edi+16],eax + sub edi,NBUFFW32-32 +;18 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+16] + add esi, 20 + mov [edi+16],cx + sub edi,NBUFFW32-32 +;16 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 16 + sub edi,NBUFFW32-32 +;14 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov cx,[esi+12] + mov eax,[esi+8] + mov [edi+12],cx + mov [edi+8],eax + add esi, 16 + sub edi,NBUFFW32-32 +;12 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov eax,[esi+8] + add esi, 12 + mov [edi+8],eax + sub edi,NBUFFW32-32 +;10 bytes + mov cx,[esi+8] + mov eax,[esi] + mov [edi+8],cx + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 12 + sub edi,NBUFFW32-32 +;8 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 8 + sub edi,NBUFFW32-32 +;6 bytes + mov bx,[esi+4] + mov eax,[esi] + mov [edi+4],bx + mov [edi],eax + add esi, 8 + sub edi,NBUFFW32-32 +;4 bytes + mov eax,[esi] + add esi, 4 + mov [edi],eax + sub edi,NBUFFW32-32 +;2 bytes + mov ax,[esi] + add esi,4 + mov [edi],ax + sub edi,NBUFFW32-32 +ENDM + + +;*********************************************************** +;* COPY_TOP_RIGHT_TRIANGLE_CLIP +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* ESI - Source +;* EDI - Dest +;* EAX,EBX,ECX,EDX - trashed +;*********************************************************** +COPY_TOP_RIGHT_TRIANGLE_CLIP MACRO + LOCAL Loop1,Loop2,Continue,Skip,Done + + mov edx,2 + CLIP_BOTTOM Loop1 Done edx 1 0 +Loop1: + mov ecx,32 + sub ecx,edx + mov ebx,ecx + shr ecx,2 + jz Continue +Loop2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz Loop2 +Continue: + and ebx,2 + jz Skip + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +Skip: + add edi,edx + add edx,2 + sub edi,NBUFFW32 + cmp edx,32 + jl Loop1 +Done: +ENDM + + +;*********************************************************** +;* COPY_TOP_RIGHT_TRIANGLE +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* ESI - Source +;* EDI - Dest +;* EAX,EBX,ECX,EDX - trashed +;*********************************************************** +COPY_TOP_RIGHT_TRIANGLE MACRO + LOCAL Loop1,Loop2,Continue,Skip,Done + + mov edx,2 +Loop1: + mov ecx,32 + sub ecx,edx + mov ebx,ecx + shr ecx,2 + jz Continue +Loop2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz Loop2 +Continue: + and ebx,2 + jz Skip + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +Skip: + add edi,edx + add edx,2 + sub edi,NBUFFW32 + cmp edx,32 + jl Loop1 +Done: +ENDM + + +;*********************************************************** +;* UNROLLED_COPY_BOTTOM_LEFT_TRIANGLE_CLIP +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* assumes segment is cs +;* ESI - Source +;* EDI - Dest +;* EAX - trashed +;* EBX - trashed +;*********************************************************** +UNROLLED_COPY_BOTTOM_LEFT_TRIANGLE_CLIP MACRO + LOCAL l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,l15,allClipped,Done,CTRTclipping + + CLIP_BOTTOM_UNROLL l0 allClipped 0 + jmp CTRTclipping[ebx] + + CTRTclipping label dword + dd offset l0,offset l1 + dd offset l2,offset l3 + dd offset l4,offset l5 + dd offset l6,offset l7 + dd offset l8,offset l9 + dd offset l10,offset l11 + dd offset l12,offset l13 + dd offset l14,offset l15 + +l0: ;2 bytes + add edi,30 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + sub edi,NBUFFW32-2 +l1: ;4 bytes + add edi,28 + mov eax,[esi] + add esi, 4 + mov [edi],eax + sub edi,NBUFFW32-4 +l2: ;6 bytes + add edi,26 + mov bx,[esi+2] + mov eax,[esi+4] + mov [edi],bx + mov [edi+2],eax + add esi, 8 + sub edi,NBUFFW32-6 +l3: ;8 bytes + add edi,24 + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 8 + sub edi,NBUFFW32-8 +l4: ;10 bytes + add edi,22 + mov cx,[esi+2] + mov eax,[esi+4] + mov [edi],cx + mov ebx,[esi+8] + mov [edi+2],eax + mov [edi+6],ebx + add esi, 12 + sub edi,NBUFFW32-10 +l5: ;12 bytes + add edi,20 + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov eax,[esi+8] + add esi, 12 + mov [edi+8],eax + sub edi,NBUFFW32-12 +l6: ;14 bytes + add edi,18 + mov eax,[esi+4] + mov ebx,[esi+8] + mov [edi+2],eax + mov [edi+6],ebx + mov cx,[esi+2] + mov eax,[esi+12] + mov [edi],cx + mov [edi+10],eax + add esi, 16 + sub edi,NBUFFW32-14 +l7: ;16 bytes + add edi,16 + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 16 + sub edi,NBUFFW32-16 +l8: ;18 bytes + add edi,14 + IRP bOffset,2,10 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + add esi, 20 + mov [edi],cx + sub edi,NBUFFW32-18 +l9: ;20 bytes + add edi,12 + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+16] + add esi, 20 + mov [edi+16],eax + sub edi,NBUFFW32-20 +l10: ;22 bytes + add edi,10 + IRP bOffset,2,10 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov eax,[esi+20] + mov [edi],cx + mov [edi+18],eax + add esi, 24 + sub edi,NBUFFW32-22 +l11: ;24 bytes + add edi,8 + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 24 + sub edi,NBUFFW32-24 +l12: ;26 bytes + add edi,6 + IRP bOffset,2,10,18 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + add esi, 28 + mov [edi],cx + sub edi,NBUFFW32-26 +l13: ;28 bytes + add edi,4 + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+24] + add esi, 28 + mov [edi+24],eax + sub edi,NBUFFW32-28 +l14: ;30 bytes + add edi,2 + IRP bOffset,2,10,18 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov eax,[esi+28] + mov [edi],cx + mov [edi+26],eax + add esi, 32 + sub edi,NBUFFW32-30 +l15: ;32 bytes + IRP bOffset,0,8,16,24 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 32 + sub edi,NBUFFW32-32 + jmp Done +allClipped: + sub edi,768*16 + add esi,288 ;TotalDataPerLine[15] +Done: +ENDM + + +;*********************************************************** +;* UNROLLED_COPY_BOTTOM_LEFT_TRIANGLE +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* assumes segment is cs +;* ESI - Source +;* EDI - Dest +;* EAX - trashed +;* EBX - trashed +;*********************************************************** +UNROLLED_COPY_BOTTOM_LEFT_TRIANGLE MACRO +;2 bytes + add edi,30 + mov ax,[esi+2] + add esi,4 + mov [edi],ax +;4 bytes + mov eax,[esi] + sub edi,NBUFFW32-30 + add esi, 4 + mov [edi],eax +;6 bytes + mov bx,[esi+2] + sub edi,NBUFFW32-30 + mov eax,[esi+4] + mov [edi],bx + mov [edi+2],eax + add esi, 8 +;8 bytes + sub edi,NBUFFW32-30 + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 8 +;10 bytes + sub edi,NBUFFW32-30 + mov cx,[esi+2] + mov eax,[esi+4] + mov [edi],cx + mov ebx,[esi+8] + mov [edi+2],eax + mov [edi+6],ebx + add esi, 12 +;12 bytes + sub edi,NBUFFW32-30 + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov eax,[esi+8] + add esi, 12 + mov [edi+8],eax +;14 bytes + mov eax,[esi+4] + sub edi,NBUFFW32-30 + mov ebx,[esi+8] + mov [edi+2],eax + mov [edi+6],ebx + mov cx,[esi+2] + mov eax,[esi+12] + mov [edi],cx + mov [edi+10],eax + add esi, 16 +;16 bytes + sub edi,NBUFFW32-30 + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 16 +;18 bytes + sub edi,NBUFFW32-30 + IRP bOffset,2,10 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov [edi],cx + add esi, 20 +;20 bytes + sub edi,NBUFFW32-30 + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+16] + mov [edi+16],eax + add esi, 20 +;22 bytes + sub edi,NBUFFW32-30 + IRP bOffset,2,10 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov eax,[esi+20] + mov [edi],cx + mov [edi+18],eax + add esi, 24 +;24 bytes + sub edi,NBUFFW32-30 + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 24 +;26 bytes + sub edi,NBUFFW32-30 + IRP bOffset,2,10,18 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + add esi, 28 + mov [edi],cx +;28 bytes + sub edi,NBUFFW32-30 + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+24] + add esi, 28 + mov [edi+24],eax +;30 bytes + sub edi,NBUFFW32-30 + IRP bOffset,2,10,18 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov eax,[esi+28] + mov [edi],cx + mov [edi+26],eax + add esi, 32 +;32 bytes + sub edi,NBUFFW32-30 + IRP bOffset,0,8,16,24 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 32 + sub edi,NBUFFW32-32 +ENDM + + +;*********************************************************** +;* COPY_BOTTOM_LEFT_TRIANGLE_CLIP +;* copies the bottom half of a 32x32 left-side triangle, +;* clips to y bounds using ClipY +;* ESI - Source +;* EDI - Dest +;* EAX,ECX,EDX - trashed +;*********************************************************** +COPY_BOTTOM_LEFT_TRIANGLE_CLIP MACRO + LOCAL Loop1,Loop2,Continue,Done + + mov edx,30 + CLIP_BOTTOM Loop1 Done edx 0 0 +Loop1: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc Loop2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz Continue +Loop2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz Loop2 +Continue: + sub edi,NBUFFW32 + sub edx,2 + jge Loop1 +Done: +ENDM + + +;*********************************************************** +;* COPY_BOTTOM_LEFT_TRIANGLE +;* copies the bottom half of a 32x32 left-side triangle, +;* clips to y bounds using ClipY +;* ESI - Source +;* EDI - Dest +;* EAX,ECX,EDX - trashed +;*********************************************************** +COPY_BOTTOM_LEFT_TRIANGLE MACRO + LOCAL Loop1,Loop2,Continue,Done + + mov edx,30 +Loop1: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc Loop2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz Continue +Loop2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz Loop2 +Continue: + sub edi,NBUFFW32 + sub edx,2 + jge Loop1 +Done: +ENDM + + +;*********************************************************** +;* UNROLLED_COPY_TOP_LEFT_TRIANGLE_CLIP +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* assumes segment is cs +;* ESI - Source +;* EDI - Dest +;* EAX - trashed +;* EBX - trashed +;*********************************************************** +UNROLLED_COPY_TOP_LEFT_TRIANGLE_CLIP MACRO + LOCAL l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,allClipped,Done,CTRTclipping + + CLIP_BOTTOM_UNROLL l0 allClipped 1 + jmp CTRTclipping[ebx] + + CTRTclipping label dword + dd offset l0,offset l1 + dd offset l2,offset l3 + dd offset l4,offset l5 + dd offset l6,offset l7 + dd offset l8,offset l9 + dd offset l10,offset l11 + dd offset l12,offset l13 + dd offset l14 + +l0: ;30 bytes + add edi,2 + IRP bOffset,2,10,18 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov eax,[esi+28] + mov [edi],cx + mov [edi+26],eax + add esi, 32 + sub edi,NBUFFW32-30 +l1: ;28 bytes + add edi,4 + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+24] + add esi, 28 + mov [edi+24],eax + sub edi,NBUFFW32-28 +l2: ;26 bytes + add edi,6 + IRP bOffset,2,10,18 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + add esi, 28 + mov [edi],cx + sub edi,NBUFFW32-26 +l3: ;24 bytes + add edi,8 + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 24 + sub edi,NBUFFW32-24 +l4: ;22 bytes + add edi,10 + IRP bOffset,2,10 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov eax,[esi+20] + mov [edi],cx + mov [edi+18],eax + add esi, 24 + sub edi,NBUFFW32-22 +l5: ;20 bytes + add edi,12 + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+16] + add esi, 20 + mov [edi+16],eax + sub edi,NBUFFW32-20 +l6: ;18 bytes + add edi,14 + IRP bOffset,2,10 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + add esi, 20 + mov [edi],cx + sub edi,NBUFFW32-18 +l7: ;16 bytes + add edi,16 + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 16 + sub edi,NBUFFW32-16 +l8: ;14 bytes + add edi,18 + mov eax,[esi+4] + mov ebx,[esi+8] + mov [edi+2],eax + mov [edi+6],ebx + mov cx,[esi+2] + mov eax,[esi+12] + mov [edi],cx + mov [edi+10],eax + add esi, 16 + sub edi,NBUFFW32-14 +l9: ;12 bytes + add edi,20 + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov eax,[esi+8] + add esi, 12 + mov [edi+8],eax + sub edi,NBUFFW32-12 +l10: ;10 bytes + add edi,22 + mov cx,[esi+2] + mov eax,[esi+4] + mov [edi],cx + mov ebx,[esi+8] + mov [edi+2],eax + mov [edi+6],ebx + add esi, 12 + sub edi,NBUFFW32-10 +l11: ;8 bytes + add edi,24 + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 8 + sub edi,NBUFFW32-8 +l12: ;6 bytes + add edi,26 + mov bx,[esi+2] + mov eax,[esi+4] + mov [edi],bx + mov [edi+2],eax + add esi, 8 + sub edi,NBUFFW32-6 +l13: ;4 bytes + add edi,28 + mov eax,[esi] + add esi, 4 + mov [edi],eax + sub edi,NBUFFW32-4 +l14: ;2 bytes + add edi,30 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + sub edi,NBUFFW32-2 + jmp Done +allClipped: + sub edi,768*15 + add esi,256 ;TotalDataPerLine[14] +Done: +ENDM + + +;*********************************************************** +;* UNROLLED_COPY_TOP_LEFT_TRIANGLE +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* assumes segment is cs +;* ESI - Source +;* EDI - Dest +;* EAX - trashed +;* EBX - trashed +;*********************************************************** +UNROLLED_COPY_TOP_LEFT_TRIANGLE MACRO +;30 bytes + add edi,2 + IRP bOffset,2,10,18 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov eax,[esi+28] + mov [edi],cx + mov [edi+26],eax + add esi, 32 + sub edi,NBUFFW32-34 +;28 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+24] + add esi, 28 + mov [edi+24],eax + sub edi,NBUFFW32-34 +;26 bytes + IRP bOffset,2,10,18 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + add esi, 28 + mov [edi],cx + sub edi,NBUFFW32-34 +;24 bytes + IRP bOffset,0,8,16 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 24 + sub edi,NBUFFW32-34 +;22 bytes + IRP bOffset,2,10 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + mov eax,[esi+20] + mov [edi],cx + mov [edi+18],eax + add esi, 24 + sub edi,NBUFFW32-34 +;20 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov eax,[esi+16] + add esi, 20 + mov [edi+16],eax + sub edi,NBUFFW32-34 +;18 bytes + IRP bOffset,2,10 + mov eax,[esi+bOffset+2] + mov ebx,[esi+bOffset+6] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + mov cx,[esi+2] + add esi, 20 + mov [edi],cx + sub edi,NBUFFW32-34 +;16 bytes + IRP bOffset,0,8 + mov eax,[esi+bOffset] + mov ebx,[esi+bOffset+4] + mov [edi+bOffset],eax + mov [edi+bOffset+4],ebx + ENDM + add esi, 16 + sub edi,NBUFFW32-34 +;14 bytes + mov eax,[esi+4] + mov ebx,[esi+8] + mov [edi+2],eax + mov [edi+6],ebx + mov cx,[esi+2] + mov eax,[esi+12] + mov [edi],cx + mov [edi+10],eax + add esi, 16 + sub edi,NBUFFW32-34 +;12 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + mov eax,[esi+8] + add esi, 12 + mov [edi+8],eax + sub edi,NBUFFW32-34 +;10 bytes + mov cx,[esi+2] + mov eax,[esi+4] + mov [edi],cx + mov ebx,[esi+8] + mov [edi+2],eax + mov [edi+6],ebx + add esi, 12 + sub edi,NBUFFW32-34 +;8 bytes + mov eax,[esi] + mov ebx,[esi+4] + mov [edi],eax + mov [edi+4],ebx + add esi, 8 + sub edi,NBUFFW32-34 +;6 bytes + mov bx,[esi+2] + mov eax,[esi+4] + mov [edi],bx + mov [edi+2],eax + add esi, 8 + sub edi,NBUFFW32-34 +;4 bytes + mov eax,[esi] + add esi, 4 + mov [edi],eax + sub edi,NBUFFW32-34 +;2 bytes + mov ax,[esi+2] + add esi,4 + mov [edi],ax + sub edi,NBUFFW32-2 +ENDM + + +;*********************************************************** +;* COPY_TOP_LEFT_TRIANGLE_CLIP +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* ESI - Source +;* EDI - Dest +;* EAX,ECX,EDX - trashed +;*********************************************************** +COPY_TOP_LEFT_TRIANGLE_CLIP MACRO + LOCAL Loop1,Loop2,Continue,Done + + mov edx,2 + CLIP_BOTTOM Loop1 Done edx 1 0 +Loop1: + mov ecx,32 + add edi,edx + sub ecx,edx + shr ecx,2 + jnc Loop2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz Continue +Loop2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz Loop2 +Continue: + add edx,2 + sub edi,NBUFFW32 + cmp edx,32 + jl Loop1 +Done: +ENDM + + +;*********************************************************** +;* COPY_TOP_LEFT_TRIANGLE +;* copies the top half of a 32x32 right-side triangle, +;* clips to y bounds using ClipY +;* ESI - Source +;* EDI - Dest +;* EAX,ECX,EDX - trashed +;*********************************************************** +COPY_TOP_LEFT_TRIANGLE MACRO + LOCAL Loop1,Loop2,Continue,Done + + mov edx,2 +Loop1: + mov ecx,32 + add edi,edx + sub ecx,edx + shr ecx,2 + jnc Loop2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz Continue +Loop2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz Loop2 +Continue: + add edx,2 + sub edi,NBUFFW32 + cmp edx,32 + jl Loop1 +Done: +ENDM + + +;*********************************************************** +;* void DrawMTileClipBottom (BYTE *pDecodeTo) +;* ECX = pDecodeTo +;*********************************************************** +public @DrawMTileClipBottom@4 +@DrawMTileClipBottom@4 proc + push ebx + push edx + push edi + push esi + + + mov edx, dword ptr [_nTrans] + test edx,edx + jz @@NoTrans + + ; if (gbPartialTrans == PART_TRANS_NONE) { + mov dl, byte ptr [_gbPartialTrans] + cmp dl, PART_TRANS_NONE + jne @@TransLeft + call DrawMTileDitherClipBottom + jmp @@Done + +@@TransLeft: + ; if (gbPartialTrans == PART_TRANS_LEFT) { + cmp dl, PART_TRANS_LEFT + jne @@TransRight + + ;al = nWTypeTable[_gnPieceNum]; + mov ebx, dword ptr [_gnPieceNum] + mov al, _nWTypeTable[ebx] + + ; if ((al == WTYPE_LEFT) || (al == WTYPE_ULC)) { + cmp al, WTYPE_LEFT + je @@TLLeftMask + cmp al, WTYPE_ULC + je @@TLLeftMask + jmp @@TransRight + +@@TLLeftMask: + mov edx, offset sgLeftMask + add edx, 31*4 + call DrawMTileHalfDitherClipBottom + jmp @@Done + + ; if (al == WTYPE_LRC) { + cmp al, WTYPE_LRC + jne @@TransRight + mov edx, offset sgRightMask + add edx, 31*4 + call DrawMTileHalfDitherClipBottom + jmp @@Done + +@@TransRight: + ; if (gbPartialTrans == PART_TRANS_RIGHT) { + cmp dl, PART_TRANS_RIGHT + jne @@NoTrans + + ;al = nWTypeTable[_gnPieceNum]; + mov ebx, dword ptr [_gnPieceNum] + mov al, _nWTypeTable[ebx] + + ; if ((al == WTYPE_RIGHT) || (al == WTYPE_ULC)) { + cmp al, WTYPE_RIGHT + je @@TRRightMask + cmp al, WTYPE_ULC + je @@TRRightMask + jmp @@NoTrans +@@TRRightMask: + mov edx, offset sgRightMask + add edx, 31*4 + call DrawMTileHalfDitherClipBottom + jmp @@Done + + ; if (al == WTYPE_LRC) { + cmp al, WTYPE_LRC + jne @@NoTrans + mov edx, offset sgLeftMask + add edx, 31*4 + call DrawMTileHalfDitherClipBottom + jmp @@Done + +@@NoTrans: + ;sgT = &_microoffset[0][0]; + mov edi, offset _microoffset + mov dword ptr [sgT], edi + + mov edi,ecx ; Dest + + mov eax,dword ptr [_nLVal] + test al,al + jz @@NoLt + cmp al,byte ptr [_lightmax] + jz @@Black + + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jnz @@Speed + + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov ebx,dword ptr [_nLVal]; ; Light conversion table + shl ebx,8 + add ebx,dword ptr [_pLightTbl]; + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + shr eax,12 + and eax,0fh + jz @@Type0 ; Solid 32x32 block + cmp ax,1 + jz @@Type1 ; 32x32 block with '0' holes + cmp ax,2 + jz @@Type2 ; Left Triangle + cmp ax,3 + jz @@Type3 ; Right Triangle + cmp ax,4 + jz @@Type4 ; Left Triangle to wall + jmp @@Type5 ; Right Triangle to wall + +@@Speed: + mov esi,dword ptr [sgT] + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,4 + add eax,dword ptr [_nLVal] + shl eax,2 + add esi,eax ; Source + mov eax,dword ptr [esi] + mov esi,dword ptr [_pSpeedCels] + add esi,eax + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + shr eax,12 + and eax,0fh +@@SCmp: + cmp ax,8 + jz @@Type8 ; PreTrans Solid 32x32 block + cmp ax,9 + jz @@Type9 ; PreTrans 32x32 block with '0' holes + cmp ax,10 + jz @@TypeA ; PreTrans Left Triangle + cmp ax,11 + jz @@TypeB ; PreTrans Right Triangle + cmp ax,12 + jz @@TypeC ; PreTrans Left Triangle to wall + jmp @@TypeD ; PreTrans Right Triangle to wall + +@@NoLt: + mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RNoLt + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RNoLt: + mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + shr eax,12 + and eax,07h + add eax,8 + jmp @@SCmp + +@@Black: mov eax,dword ptr [_gdwPNum] + and eax,08000h + jz @@RBlk + + mov esi,dword ptr [sgT] ; Get old micro tile number + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,6 + add esi,eax + mov eax,dword ptr [_gdwPNum] + and eax,0f000h + add eax,dword ptr [esi] + mov dword ptr [_gdwPNum],eax + +@@RBlk: mov ebx,dword ptr [_pDungeonCels] + mov esi,ebx + mov eax,dword ptr [_gdwPNum] + and eax,00fffh + shl eax,2 + add ebx,eax + add esi,dword ptr [ebx] ; Source + + mov eax,dword ptr [_gdwPNum] ; Determine draw type + mov al,ah + shr eax,4 + and eax,07h + jz @@TypeG ; Black Trans Solid 32x32 block + cmp ax,1 + jz @@TypeH ; Black Trans 32x32 block with '0' holes + cmp ax,2 + jz @@TypeI ; Black Trans Left Triangle + cmp ax,3 + jz @@TypeJ ; Black Trans Right Triangle + cmp ax,4 + jz @@TypeK ; Black Trans Left Triangle to wall + jmp @@TypeL ; Black Trans Right Triangle to wall + +;*-----------------------------------------------------------------------*/ + +@@Type0: + mov edx,32 + push ebp +@@T0Lp1: + push edx + cmp edi,dword ptr [_glClipY] + jb @@T0C1 + add esi,32 + add edi,32 + jmp @@T0C2 +@@T0C1: + xor edx,edx + mov ebp,8 +@@T0Lp2: + mov eax,[esi] + add esi,4 + ror eax,16 + mov dl,al + mov cl,[ebx+edx] + mov dl,ah + mov ch,[ebx+edx] + ror eax,16 + shl ecx,16 + mov dl,al + mov cl,[ebx+edx] + mov dl,ah + mov ch,[ebx+edx] + mov [edi],ecx + add edi,4 + + dec ebp + jnz @@T0Lp2 +@@T0C2: + sub edi,NBUFFW32 + pop edx + dec edx + jnz @@T0Lp1 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type1: + push ebp + mov ecx,32 +@@T1Lp1: + push ecx + mov ebp,32 +@@T1Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + + test al,al + jns @@T1NoSkip + neg al + add edi,eax + sub ebp,eax + jmp @@T1continue +@@T1NoSkip: + sub ebp,eax + cmp edi,dword ptr [_glClipY] + jb @@T1NotCliped + add esi,eax + add edi,eax + jmp @@T1continue +@@T1NotCliped: + mov ecx,eax + X_BYTES +@@T1continue: + test ebp,ebp + jnz @@T1Lp2 + + pop ecx + sub edi,NBUFFW32 + dec ecx + jnz @@T1Lp1 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type2: + push ebp + mov ebp,30 + CLIP_BOTTOM @@T2Lp1 @@T2b ebp 0 0 +@@T2Lp1: + add edi,ebp + mov ecx,32 + sub ecx,ebp +; X_BYTES_PREPAD + mov edx,ecx + and edx,2 + add esi,edx +@@T2PixLine: + mov dl,[esi] + inc esi + mov dl,[ebx+edx] + mov [edi],dl + inc edi + dec ecx + jnz @@T2PixLine +@@T2continue: + sub edi,NBUFFW32 + sub ebp,2 + jge @@T2Lp1 + + +@@T2b: + mov ebp,2 + CLIP_BOTTOM @@T2Lp2 @@T2Done ebp 1 0 +@@T2Lp2: + add edi,ebp + mov ecx,32 + sub ecx,ebp +; X_BYTES_PREPAD + mov edx,ecx + and edx,2 + add esi,edx +@@T2PixLine2: + mov dl,[esi] + inc esi + mov dl,[ebx+edx] + mov [edi],dl + inc edi + dec ecx + jnz @@T2PixLine2 +@@T2continue2: + add ebp,2 + sub edi,NBUFFW32 + cmp ebp,32 + jnz @@T2Lp2 +@@T2Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type3: + push ebp + mov ebp,30 + CLIP_BOTTOM @@T3Lp1 @@T3b ebp 0 0 +@@T3Lp1: + mov ecx,32 + sub ecx,ebp +; X_BYTES_PAD +@@T3PixLine: + mov dl,[esi] + inc esi + mov dl,[ebx+edx] + mov [edi],dl + inc edi + dec ecx + jnz @@T3PixLine + + mov edx,esi + and edx,2 + add esi,edx +@@T3x: + sub edi,NBUFFW32 + add edi,ebp + sub ebp,2 + jge @@T3Lp1 + + +@@T3b: + mov ebp,2 + CLIP_BOTTOM @@T3Lp3 @@T3Done ebp 1 0 +@@T3Lp3: + mov ecx,32 + sub ecx,ebp +; X_BYTES_PAD +@@T3PixLine2: + mov dl,[esi] + inc esi + mov dl,[ebx+edx] + mov [edi],dl + inc edi + dec ecx + jnz @@T3PixLine2 + + mov edx,esi + and edx,2 + add esi,edx +@@T3x2: + sub edi,NBUFFW32 + add edi,ebp + add ebp,2 + cmp ebp,32 + jnz @@T3Lp3 +@@T3Done: + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type4: + push ebp + mov ebp,30 + CLIP_BOTTOM @@T4Lp1 @@T4b ebp 0 0 +@@T4Lp1: + add edi,ebp + mov ecx,32 + sub ecx,ebp + X_BYTES_PREPAD +@@T4x: + sub edi,NBUFFW32 + sub ebp,2 + jge @@T4Lp1 + + +@@T4b: + mov ebp,16 +@@T4Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T4C2 + add esi,32 + add edi,32 + jmp @@T4C3 +@@T4C2: + mov ecx,8*4 + X_DWORDS +@@T4C3: + sub edi,NBUFFW32 + dec ebp + jnz @@T4Lp3 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type5: + push ebp + mov ebp,30 + CLIP_BOTTOM @@T5Lp1 @@T5b ebp 0 0 +@@T5Lp1: + mov ecx,32 + sub ecx,ebp + X_BYTES_PAD +@@T5x: + sub edi,NBUFFW32 + add edi,ebp + sub ebp,2 + jge @@T5Lp1 + + +@@T5b: + mov ebp,16 +@@T5Lp3: + cmp edi,dword ptr [_glClipY] + jb @@T5C2 + add esi,32 + add edi,32 + jmp @@T5C3 +@@T5C2: + mov ecx,8*4 + X_DWORDS +@@T5C3: + sub edi,NBUFFW32 + dec ebp + jnz @@T5Lp3 + pop ebp + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type8: + mov edx,32 +@@T8Lp1: + cmp edi,dword ptr [_glClipY] + jb @@T8C1 + add esi,32 + add edi,32 + jmp @@T8C2 +@@T8C1: + mov ecx,8 +@@T8Lp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T8Lp2 +@@T8C2: + sub edi,NBUFFW32 + dec edx + jnz @@T8Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@Type9: + mov ecx,32 +@@T9Lp1: + push ecx + mov edx,32 +@@T9Lp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@T9J + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@T9C1 + add esi,eax + add edi,eax + jmp @@T9x +@@T9C1: + mov ecx,eax + shr ecx,1 + jnc @@T9w + mov al,[esi] + inc esi + mov [edi],al + inc edi + test ecx,ecx + jz @@T9x +@@T9w: + shr ecx,1 + jnc @@T9Lp3 + mov ax,[esi] + add esi,2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@T9x +@@T9Lp3: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@T9Lp3 +@@T9x: + test edx,edx + jz @@T9Nxt + jmp @@T9Lp2 + +@@T9J: + neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@T9Lp2 +@@T9Nxt: + pop ecx + sub edi,NBUFFW32 + dec ecx + jnz @@T9Lp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeA: + COPY_BOTTOM_LEFT_TRIANGLE_CLIP + COPY_TOP_LEFT_TRIANGLE_CLIP + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeB: + COPY_BOTTOM_RIGHT_TRIANGLE_CLIP + COPY_TOP_RIGHT_TRIANGLE_CLIP + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeC: + mov edx,30 + CLIP_BOTTOM @@TCLp1 @@TCb edx 0 0 +@@TCLp1: + add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TCLp2 + mov ax,[esi+2] + add esi,4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TCx +@@TCLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TCLp2 +@@TCx: + sub edi,NBUFFW32 + sub edx,2 + jge @@TCLp1 + + +@@TCb: + mov edx,16 +@@TCLp3: + cmp edi,dword ptr [_glClipY] + jb @@TCC2 + add esi,32 + add edi,32 + jmp @@TCC3 +@@TCC2: + mov ecx,8 +@@TCLp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TCLp4 +@@TCC3: + sub edi,NBUFFW32 + dec edx + jnz @@TCLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeD: + mov edx,30 + CLIP_BOTTOM @@TDLp1 @@TDb edx 0 0 +@@TDLp1: + mov ecx,32 + sub ecx,edx + mov ebx,ecx + shr ecx,2 + jz @@TDx +@@TDLp2: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TDLp2 +@@TDx: + and ebx,2 + jz @@TDSkip + mov ax,[esi] + add esi,4 + mov [edi],ax + add edi,2 +@@TDSkip: + sub edi,NBUFFW32 + add edi,edx + sub edx,2 + jge @@TDLp1 + + +@@TDb: + mov edx,16 +@@TDLp3: + cmp edi,dword ptr [_glClipY] + jb @@TDC2 + add esi,32 + add edi,32 + jmp @@TDC3 +@@TDC2: + mov ecx,8 +@@TDLp4: + mov eax,[esi] + add esi,4 + mov [edi],eax + add edi,4 + dec ecx + jnz @@TDLp4 +@@TDC3: + sub edi,NBUFFW32 + dec edx + jnz @@TDLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeG: + mov edx,32 + xor eax,eax +@@TGLp1: + cmp edi,dword ptr [_glClipY] + jb @@TGC1 + add esi,32 + add edi,32 + jmp @@TGC2 +@@TGC1: + mov ecx,8 +@@TGLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TGLp2 +@@TGC2: + sub edi,NBUFFW32 + dec edx + jnz @@TGLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeH: mov ecx,32 + +@@THLp1: push ecx + mov edx,32 + +@@THLp2: + xor eax,eax ; Load control byte + mov al,[esi] + inc esi + test al,al + js @@THJ + + sub edx,eax + cmp edi,dword ptr [_glClipY] + jb @@THC1 + add esi,eax + add edi,eax + jmp @@THx +@@THC1: mov ecx,eax + add esi,ecx + xor eax,eax + shr ecx,1 + jnc @@THw + mov [edi],al + inc edi + test ecx,ecx + jz @@THx +@@THw: shr ecx,1 + jnc @@THLp3 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@THx +@@THLp3: + mov [edi],eax + add edi,4 + dec ecx + jnz @@THLp3 +@@THx: test edx,edx + jz @@THNxt + jmp @@THLp2 + +@@THJ: neg al ; Do jump + add edi,eax + sub edx,eax + jnz @@THLp2 +@@THNxt: pop ecx + sub edi,NBUFFW32 + dec ecx + jnz @@THLp1 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeI: mov edx,30 + xor eax,eax +@@TILp1: cmp edi,dword ptr [_glClipY] + jb @@TIC1 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TIx +@@TIC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TILp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TIx +@@TILp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TILp2 +@@TIx: sub edi,NBUFFW32 + test edx,edx + jz @@TIb + sub edx,2 + jmp @@TILp1 + +@@TIb: mov edx,2 +@@TILp3: cmp edi,dword ptr [_glClipY] + jb @@TIC2 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TIx2 +@@TIC2: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TILp4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TIx2 +@@TILp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TILp4 +@@TIx2: sub edi,NBUFFW32 + add edx,2 + cmp edx,32 + jnz @@TILp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeJ: mov edx,30 + xor eax,eax +@@TJLp1: cmp edi,dword ptr [_glClipY] + jb @@TJC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TJx +@@TJC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TJLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TJx +@@TJLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TJLp2 +@@TJx: sub edi,NBUFFW32 + test edx,edx + jz @@TJb + add edi,edx + sub edx,2 + jmp @@TJLp1 + +@@TJb: mov edx,2 +@@TJLp3: cmp edi,dword ptr [_glClipY] + jb @@TJC2 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TJx2 +@@TJC2: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TJLp4 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TJx2 +@@TJLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TJLp4 +@@TJx2: sub edi,NBUFFW32 + add edi,edx + add edx,2 + cmp edx,32 + jnz @@TJLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeK: mov edx,30 + xor eax,eax +@@TKLp1: cmp edi,dword ptr [_glClipY] + jb @@TKC1 + add esi,32 + sub esi,edx + add edi,32 + jmp @@TKx +@@TKC1: add edi,edx + mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TKLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TKx +@@TKLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TKLp2 +@@TKx: sub edi,NBUFFW32 + test edx,edx + jz @@TKb + sub edx,2 + jmp @@TKLp1 + +@@TKb: mov edx,16 +@@TKLp3: cmp edi,dword ptr [_glClipY] + jb @@TKC2 + add esi,32 + add edi,32 + jmp @@TKC3 +@@TKC2: + mov ecx,8 +@@TKLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TKLp4 +@@TKC3: sub edi,NBUFFW32 + dec edx + jnz @@TKLp3 + jmp @@Done + +;*-----------------------------------------------------------------------*/ + +@@TypeL: mov edx,30 + xor eax,eax +@@TLLp1: cmp edi,dword ptr [_glClipY] + jb @@TLC1 + add esi,32 + sub esi,edx + add edi,32 + sub edi,edx + jmp @@TLx +@@TLC1: mov ecx,32 + sub ecx,edx + shr ecx,2 + jnc @@TLLp2 + mov [edi],ax + add edi,2 + test ecx,ecx + jz @@TLx +@@TLLp2: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TLLp2 +@@TLx: sub edi,NBUFFW32 + test edx,edx + jz @@TLb + add edi,edx + sub edx,2 + jmp @@TLLp1 + +@@TLb: mov edx,16 +@@TLLp3: cmp edi,dword ptr [_glClipY] + jb @@TLC2 + add esi,32 + add edi,32 + jmp @@TLC3 +@@TLC2: + mov ecx,8 +@@TLLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@TLLp4 +@@TLC3: sub edi,NBUFFW32 + dec edx + jnz @@TLLp3 + +@@Done: + pop esi + pop edi + pop edx + pop ebx + ret +@DrawMTileClipBottom@4 endp + + +;*********************************************************** +;* void DrawBlankMTile (BYTE *pDecodeTo) +;* ECX = pDecodeTo +;*********************************************************** +public @DrawBlankMTile@4 +@DrawBlankMTile@4 proc + push ebx + push edx + push edi + push esi + + mov edi,ecx ; Dest + + mov edx,30 + mov ebx,1 + xor eax,eax + ;mov eax,092929292h ; yellow +@@BLp1: + add edi,edx + mov ecx,ebx +@@BLp3: + mov [edi],eax + add edi,4 + dec ecx + jnz @@BLp3 + add edi,edx + sub edi,NBUFFW64 + test edx,edx + jz @@Bb + sub edx,2 + inc ebx + jmp @@BLp1 + +@@Bb: + mov edx,2 + mov ebx,15 +@@BLp2: + add edi,edx + mov ecx,ebx +@@BLp4: + mov [edi],eax + add edi,4 + dec ecx + jnz @@BLp4 + add edi,edx + sub edi,NBUFFW64 + dec ebx + add edx,2 + cmp edx,32 + jnz @@BLp2 + + pop esi + pop edi + pop edx + pop ebx + ret +@DrawBlankMTile@4 endp + + +;**************************************************************************************** +;**************************************************************************************** +;**************************************************************************************** + END \ No newline at end of file diff --git a/src/SCROLLRT.CPP b/src/SCROLLRT.CPP new file mode 100644 index 0000000..99528c9 --- /dev/null +++ b/src/SCROLLRT.CPP @@ -0,0 +1,3819 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Scrolling file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/SCROLLRT.CPP 3 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +** CheckForScroll +** DrawAndBlit +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "engine.h" +#include "scrollrt.h" +#include "scrlasm.h" +#include "gendung.h" +#include "debug.h" +#include "inv.h" +#include "multi.h" +#include "lighting.h" +#include "control.h" +#include "gamemenu.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "monstint.h" +#include "dead.h" +#include "objects.h" +#include "missiles.h" +#include "misdat.h" +#include "spells.h" +#include "cursor.h" +#include "quests.h" +#include "town.h" +#include "minitext.h" +#include "automap.h" +#include "help.h" +#include "error.h" +#include "doom.h" + + +/*-----------------------------------------------------------------------** +** debugging +**-----------------------------------------------------------------------*/ +#define LOCK_WAIT 1 // 1 in final +#define LOCK_SLEEP 1 // 1 in final +#define MAX_FRAMES 50 // arbitrary limit to check for bogus numbers of frames +const char sgszUnknownAction[] = "unknown action"; +#define GRACEFUL_EXIT // this needs to be undefined later to get assert turned back on. JKE + +/*-----------------------------------------------------------------------** +** Registration info +**-----------------------------------------------------------------------*/ +#include "regconst.h" +char sgszRegSig6[REG_LEN] = "REGISTRATION_BLOCK"; + + +/*-----------------------------------------------------------------------** +** Function stubs +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +void DrawUnit(long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawUnitOutline(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +void DrawInfraUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff); +void DrawLitUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); + +void DrawUnitClipped(long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawUnitOutlineClipped(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +void DrawInfraUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff); +void DrawLitUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +#endif + +void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag); +void DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, int yp, BOOL chflag); +void DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, int yp, BOOL chflag); +void plrmsg_draw(); + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#define MOUTC 233 +#define IOUTC 181 //130 +#define OOUTC 194 //148 +#define POUTC 165 + +extern "C" { + BOOL nTrans; + long nLVal; + int gnPieceNum; + char gbPartialTrans; + DWORD gdwPNum; + long glClipY; +} +int gnMI; +long nBuffWTbl[1024]; + + +// frame counter +#ifndef NDEBUG +static DWORD sgnLastFrame; +static BYTE sgfFrameCounterEnabled = FALSE; +#endif + +bool HighLightAllItems = false; + +//****************************************************************** +// savecrsr variables +//****************************************************************** +static BYTE sgSaveBack[8*1024]; +static DWORD sgdwCursX,sgdwCursY,sgdwCursWdt,sgdwCursHgt; +static DWORD sgdwOldX,sgdwOldY,sgdwOldWdt,sgdwOldHgt; + + +//****************************************************************** +//****************************************************************** +void savecrsr_reset() { + // inhibit cursor redraw + sgdwCursWdt = 0; + sgdwOldWdt = 0; +} + + +//****************************************************************** +//****************************************************************** +static void savecrsr_hide() { + if (! sgdwCursWdt) return; + + // copy from save cursor buffer to draw buffer + app_assert(gpBuffer); + BYTE * pbDst = gpBuffer + (sgdwCursY + 160) * 768 + sgdwCursX + 64; + const BYTE * pbSrc = sgSaveBack; + for (DWORD hgt = sgdwCursHgt; hgt--; ) { + memcpy(pbDst,pbSrc,sgdwCursWdt); + pbSrc += sgdwCursWdt; + pbDst += 768; + } + + sgdwOldX = sgdwCursX; + sgdwOldY = sgdwCursY; + sgdwOldWdt = sgdwCursWdt; + sgdwOldHgt = sgdwCursHgt; + sgdwCursWdt = 0; +} + + +//****************************************************************** +//****************************************************************** +static void savecrsr_show() { + // make sure cursor was already erased before + app_assert(! sgdwCursWdt); + + if (curs <= 0) return; + if (! cursW || ! cursH) return; + + // add one pixel in each direction for outline drawn around cursor + int cursX = MouseX - 1; + if (cursX < 0) cursX = 0; + else if (cursX > 639) return; + int cursY = MouseY - 1; + if (cursY < 0) cursY = 0; + else if (cursY > 479) return; + + // calculate area behind cursor -- X/WDT rounded to DWORD boundary/size + sgdwCursX = cursX; // get X1 coord + sgdwCursWdt = cursX + cursW + 2 - 1; // get X2 coord + if (sgdwCursWdt > 639) sgdwCursWdt = 639; // clip X + sgdwCursX &= ~3; // X1 % 4 == 0 + sgdwCursWdt |= 3; // X2 % 4 == 3 + sgdwCursWdt += 1 - sgdwCursX; // WDT = X2 - X1 + 1 + + sgdwCursY = cursY; // get X1 coord + sgdwCursHgt = cursY + cursH + 2 - 1; // get X2 coord + if (sgdwCursHgt > 479) sgdwCursHgt = 479; // clip Y + sgdwCursHgt += 1 - sgdwCursY; // HGT = Y2 - Y1 + 1 + app_assert(sgdwCursWdt * sgdwCursHgt < sizeof sgSaveBack); + + // copy from draw buffer to save cursor buffer + app_assert(gpBuffer); + const BYTE * pbSrc = gpBuffer + (sgdwCursY + 160) * 768 + sgdwCursX + 64; + BYTE * pbDst = sgSaveBack; + for (DWORD hgt = sgdwCursHgt; hgt--; ) { + memcpy(pbDst,pbSrc,sgdwCursWdt); + pbDst += sgdwCursWdt; + pbSrc += 768; + } + + // remove one pixel in each direction for outline drawn around cursor + cursX += 1; + cursY += 1; + glClipY = (long) gpBuffer + nBuffWTbl[640] - (cursW + 2); + if (curs >= ICSTART) { + int oc = 197; + if (plr[myplr].HoldItem._iMagical) oc = 181; + if (!plr[myplr].HoldItem._iStatFlag) oc = 229; + if (curs <= ICLAST) + { + COutlineSlabCel(oc, cursX+64, cursY+160+cursH-1, pCursCels, curs, cursW, 0, 8); + if (oc != 229) CDrawSlabCel(cursX+64, cursY+160+cursH-1, pCursCels, curs, cursW, 0, 8); + else CDrawSlabCelI(cursX+64, cursY+160+cursH-1, pCursCels, curs, cursW, 0, 8, LIGHT_INFRA); + } + else + { + COutlineSlabCel(oc, cursX+64, cursY+160+cursH-1, pCursCels2, curs - ICLAST, cursW, 0, 8); + if (oc != 229) CDrawSlabCel(cursX+64, cursY+160+cursH-1, pCursCels2, curs - ICLAST, cursW, 0, 8); + else CDrawSlabCelI(cursX+64, cursY+160+cursH-1, pCursCels2, curs - ICLAST, cursW, 0, 8, LIGHT_INFRA); + } + } + else { + CDrawSlabCel(cursX+64, cursY+160+cursH-1, pCursCels, curs, cursW, 0, 8); + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +void DrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) +{ + int i, gnMI, mx, my; + + if (dMissile[sx][sy] != -1) { + gnMI = dMissile[sx][sy] - 1; + if(missile[gnMI]._miPreFlag == pre) { + mx = missile[gnMI]._mixoff + xp - missile[gnMI]._miAnimWidth2; + my = missile[gnMI]._miyoff + yp; + if (missile[gnMI]._miUniqTrans) { + DrawSlabCelI(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de, LIGHT_U + missile[gnMI]._miUniqTrans - 1); + } + else { + if (missile[gnMI]._miLightFlag) { + DrawSlabCelL(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de); + } + else { + app_assert(missile[gnMI]._miAnimData); + DrawSlabCel(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de); + } + } + } + } else { + for (i = 0; i < nummissiles; ++i) { + gnMI = missileactive[i]; + if ((missile[gnMI]._mix == sx) && (missile[gnMI]._miy == sy) + && (missile[gnMI]._miPreFlag == pre) && (missile[gnMI]._miDrawFlag == TRUE)) + { + mx = missile[gnMI]._mixoff + xp - missile[gnMI]._miAnimWidth2; + my = missile[gnMI]._miyoff + yp; + if (missile[gnMI]._miUniqTrans) { + DrawSlabCelI(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de, LIGHT_U + missile[gnMI]._miUniqTrans - 1); + } + else { + if (missile[gnMI]._miLightFlag) { + DrawSlabCelL(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de); + } + else { + app_assert(missile[gnMI]._miAnimData); + DrawSlabCel(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de); + } + } + } + } + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +void CDrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) +{ + int i, gnMI, mx, my; + + if (dMissile[sx][sy] != -1) { + gnMI = dMissile[sx][sy] - 1; + if (missile[gnMI]._miPreFlag == pre) { + mx = missile[gnMI]._mixoff + xp - missile[gnMI]._miAnimWidth2; + my = missile[gnMI]._miyoff + yp; + if (missile[gnMI]._miUniqTrans) + CDrawSlabCelI(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de, LIGHT_U + missile[gnMI]._miUniqTrans - 1); + else { + if (missile[gnMI]._miLightFlag) CDrawSlabCelL(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de); + else CDrawSlabCel(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de); + } + } + } else { + for (i = 0; i < nummissiles; ++i) { + gnMI = missileactive[i]; + if ((missile[gnMI]._mix == sx) && (missile[gnMI]._miy == sy) + && (missile[gnMI]._miPreFlag == pre) && (missile[gnMI]._miDrawFlag == TRUE)) + { + mx = missile[gnMI]._mixoff + xp - missile[gnMI]._miAnimWidth2; + my = missile[gnMI]._miyoff + yp; + if (missile[gnMI]._miUniqTrans) + CDrawSlabCelI(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de, LIGHT_U + missile[gnMI]._miUniqTrans - 1); + else { + if (missile[gnMI]._miLightFlag) CDrawSlabCelL(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de); + else CDrawSlabCel(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de); + } + } + } + } +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +void DrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) +{ + int i, mx, my; + MissileStruct * pMiss; + + if (dMissile[sx][sy] == -1) { + for (i = 0; i < nummissiles; ++i) { + app_assert(missileactive[i] < MAXMISSILES && missileactive[i] >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (missileactive[i] >= MAXMISSILES || missileactive[i] < 0 ) + return; + #endif + // jcm.patch1.end.1/14/97 + pMiss = &missile[missileactive[i]]; + if ((pMiss->_mix != sx) || (pMiss->_miy != sy) || (pMiss->_miPreFlag != pre) || !pMiss->_miDrawFlag) + continue; + if (pMiss->_miAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Missile type %d: NULL Cel Buffer",pMiss->_mitype); + #endif + // jcm.patch1.end.1/14/97 + if (pMiss->_miAnimFrame < 1 || *(DWORD*)pMiss->_miAnimData > MAX_FRAMES || + pMiss->_miAnimFrame > *(long*)pMiss->_miAnimData) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Draw Missile: frame %d of %d, missile type==%d", + pMiss->_miAnimFrame, + *(long*)pMiss->_miAnimData, + pMiss->_mitype + ); + #endif + // jcm.patch1.end.1/14/97 + } + mx = pMiss->_mixoff + xp - pMiss->_miAnimWidth2; + my = pMiss->_miyoff + yp; + if (pMiss->_miUniqTrans) { + DrawInfraUnit( + mx, my, + pMiss->_miAnimData, + pMiss->_miAnimFrame, + pMiss->_miAnimWidth, + ds, de, + LIGHT_U + pMiss->_miUniqTrans - 1 + ); + } else if (pMiss->_miLightFlag) { + DrawLitUnit(mx, my, pMiss->_miAnimData, pMiss->_miAnimFrame, pMiss->_miAnimWidth, ds, de); + } else { + DrawUnit(mx, my, pMiss->_miAnimData, pMiss->_miAnimFrame, pMiss->_miAnimWidth, ds, de); + } + } + return; + } + pMiss = &missile[dMissile[sx][sy] - 1]; + if (pMiss->_miPreFlag != pre) + return; + if (pMiss->_miAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Missile 2 type %d: NULL Cel Buffer",pMiss->_mitype); + #endif + // jcm.patch1.end.1/14/97 + if (pMiss->_miAnimFrame < 1 || *(DWORD*)pMiss->_miAnimData > MAX_FRAMES + || pMiss->_miAnimFrame > *(long*)pMiss->_miAnimData) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Draw Missile 2: frame %d of %d, missile type==%d", + pMiss->_miAnimFrame, + *(long*)pMiss->_miAnimData, + pMiss->_mitype + ); + #endif + // jcm.patch1.end.1/14/97 + } + mx = pMiss->_mixoff + xp - pMiss->_miAnimWidth2; + my = pMiss->_miyoff + yp; + if (pMiss->_miUniqTrans) { + DrawInfraUnit( + mx, my, + pMiss->_miAnimData, + pMiss->_miAnimFrame, + pMiss->_miAnimWidth, + ds, de, + LIGHT_U + pMiss->_miUniqTrans - 1 + ); + } else if (pMiss->_miLightFlag) { + DrawLitUnit(mx, my, pMiss->_miAnimData, pMiss->_miAnimFrame, pMiss->_miAnimWidth, ds, de); + } else { + DrawUnit(mx, my, pMiss->_miAnimData, pMiss->_miAnimFrame, pMiss->_miAnimWidth, ds, de); + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +void CDrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) +{ + int i, mx, my; + MissileStruct * pMiss; + + if (dMissile[sx][sy] == -1) { + for (i = 0; i < nummissiles; ++i) { + app_assert(missileactive[i] < MAXMISSILES && missileactive[i] >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (missileactive[i] >= MAXMISSILES || missileactive[i] < 0) + return; + #endif + // jcm.patch1.end.1/14/97 + pMiss = &missile[missileactive[i]]; + if ((pMiss->_mix != sx) || (pMiss->_miy != sy) || (pMiss->_miPreFlag != pre) || !pMiss->_miDrawFlag) + continue; + if (pMiss->_miAnimData == NULL) + // jcm.patch1.start.1/14/97 + //#ifdef GRACEFUL_EXIT + return; + //#else + //app_fatal("Draw Missile type %d Clipped: NULL Cel Buffer",pMiss->_mitype); + //#endif + // jcm.patch1.end.1/14/97 + if (pMiss->_miAnimFrame < 1 || *reinterpret_cast(pMiss->_miAnimData) > MAX_FRAMES + || pMiss->_miAnimFrame > *reinterpret_cast(pMiss->_miAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Draw Clipped Missile: frame %d of %d, missile type==%d", + pMiss->_miAnimFrame, + *reinterpret_cast(pMiss->_miAnimData), + pMiss->_mitype + ); + #endif + // jcm.patch1.end.1/14/97 + } + mx = pMiss->_mixoff + xp - pMiss->_miAnimWidth2; + my = pMiss->_miyoff + yp; + if (pMiss->_miUniqTrans) { + DrawInfraUnitClipped( + mx, my, + pMiss->_miAnimData, + pMiss->_miAnimFrame, + pMiss->_miAnimWidth, + ds, de, + LIGHT_U + pMiss->_miUniqTrans - 1 + ); + } else if (pMiss->_miLightFlag) { + DrawLitUnitClipped(mx,my,pMiss->_miAnimData,pMiss->_miAnimFrame,pMiss->_miAnimWidth,ds,de); + } else { + DrawUnitClipped(mx,my,pMiss->_miAnimData,pMiss->_miAnimFrame,pMiss->_miAnimWidth,ds,de); + } + } + return; + } + pMiss = &missile[dMissile[sx][sy] - 1]; + if (pMiss->_miPreFlag != pre) + return; + if (pMiss->_miAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Missile 2 type %d Clipped: NULL Cel Buffer",pMiss->_mitype); + #endif + // jcm.patch1.end.1/14/97 + if (pMiss->_miAnimFrame < 1 || *(DWORD*)pMiss->_miAnimData > MAX_FRAMES + || pMiss->_miAnimFrame > *(long*)pMiss->_miAnimData) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Draw Clipped Missile 2: frame %d of %d, missile type==%d", + pMiss->_miAnimFrame, + *reinterpret_cast(pMiss->_miAnimData), + pMiss->_mitype + ); + #endif + // jcm.patch1.end.1/14/97 + } + mx = pMiss->_mixoff + xp - pMiss->_miAnimWidth2; + my = pMiss->_miyoff + yp; + if (pMiss->_miUniqTrans) { + DrawInfraUnitClipped( + mx, my, + pMiss->_miAnimData, + pMiss->_miAnimFrame, + pMiss->_miAnimWidth, + ds, de, + LIGHT_U + pMiss->_miUniqTrans - 1 + ); + } else if (pMiss->_miLightFlag) { + DrawLitUnitClipped(mx,my,pMiss->_miAnimData,pMiss->_miAnimFrame,pMiss->_miAnimWidth,ds,de); + } else { + DrawUnitClipped(mx,my,pMiss->_miAnimData,pMiss->_miAnimFrame,pMiss->_miAnimWidth,ds,de); + } +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, int oend) +{ + char dinfra; + + if (!(dFlags[sx][sy] & BFLAG_VISIBLE)) + DrawSlabCelI(xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, LIGHT_INFRA); + else { + dinfra = LIGHT_NORM; + if (monster[gnMI]._uniqtype != 0) dinfra = LIGHT_U + monster[gnMI]._uniqtrans; + if (monster[gnMI]._mmode == MM_STONE) dinfra = LIGHT_STONE; + if ((plr[myplr]._pInfraFlag) && (nLVal > 8)) dinfra = LIGHT_INFRA; + if (dinfra != LIGHT_NORM) + DrawSlabCelI(xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, dinfra); + else + DrawSlabCelL(xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, monster[gnMI].MType->mAnimWidth, ostart, oend); + } +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +static void CDrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, int oend) +{ + char dinfra; + + if (!(dFlags[sx][sy] & BFLAG_VISIBLE)) + CDrawSlabCelI(xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, LIGHT_INFRA); + else { + dinfra = LIGHT_NORM; + if (monster[gnMI]._uniqtype != 0) dinfra = LIGHT_U + monster[gnMI]._uniqtrans; + if (monster[gnMI]._mmode == MM_STONE) dinfra = LIGHT_STONE; + if ((plr[myplr]._pInfraFlag) && (nLVal > 8)) dinfra = LIGHT_INFRA; + if (dinfra != LIGHT_NORM) + CDrawSlabCelI(xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, dinfra); + else + CDrawSlabCelL(xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, monster[gnMI].MType->mAnimWidth, ostart, oend); + } +} +#endif + + +//*************************************************************************** +//*************************************************************************** + // These strings should match the MM_xxx constants defined in monstint.h + const char * sgszMonsterAction[] = { + "standing", + "walking (1)", + "walking (2)", + "walking (3)", + "attacking", + "getting hit", + "dying", + "attacking (special)", + "fading in", + "fading out", + "attacking (ranged)", + "standing (special)", + "attacking (special ranged)", + "delaying", + "charging", + "stoned", + "healing", + "talking" + }; +inline const char * MonsterActionString(DWORD dwAction) { + if (dwAction <= MM_TALK) + return sgszMonsterAction[dwAction]; + return sgszUnknownAction; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, int oend) +{ + if ((DWORD)gnMI >= MAXMONSTERS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Monster: tried to draw illegal monster %d",gnMI); + #endif + // jcm.patch1.end.1/14/97 + if (monster[gnMI]._mAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Monster \"%s\": NULL Cel Buffer",monster[gnMI].mName); + #endif + // jcm.patch1.end.1/14/97 + if (monster[gnMI]._mAnimFrame < 1 || *reinterpret_cast(monster[gnMI]._mAnimData) > MAX_FRAMES + || monster[gnMI]._mAnimFrame > *reinterpret_cast(monster[gnMI]._mAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Draw Monster \"%s\" %s: facing %d, frame %d of %d", + monster[gnMI].mName, + MonsterActionString(monster[gnMI]._mmode), + monster[gnMI]._mdir, + monster[gnMI]._mAnimFrame, + *reinterpret_cast(monster[gnMI]._mAnimData) + ); + #endif + // jcm.patch1.end.1/14/97 + } + if (!(dFlags[sx][sy] & BFLAG_VISIBLE)) { + DrawInfraUnit( + xp, yp, + monster[gnMI]._mAnimData, + monster[gnMI]._mAnimFrame, + monster[gnMI].MType->mAnimWidth, + ostart, + oend, + LIGHT_INFRA + ); + return; + } + char dinfra = LIGHT_NORM; + if (monster[gnMI]._uniqtype) + dinfra = LIGHT_U + monster[gnMI]._uniqtrans; + if (monster[gnMI]._mmode == MM_STONE) + dinfra = LIGHT_STONE; + if (plr[myplr]._pInfraFlag && (nLVal > 8)) + dinfra = LIGHT_INFRA; + if (dinfra != LIGHT_NORM) + DrawInfraUnit( + xp, yp, + monster[gnMI]._mAnimData, + monster[gnMI]._mAnimFrame, + monster[gnMI].MType->mAnimWidth, + ostart, + oend, + dinfra + ); + else + DrawLitUnit( + xp, yp, + monster[gnMI]._mAnimData, + monster[gnMI]._mAnimFrame, + monster[gnMI].MType->mAnimWidth, + ostart, + oend + ); +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +static void CDrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, int oend) +{ + if ((DWORD)gnMI >= MAXMONSTERS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Monster Clipped: tried to draw illegal monster %d",gnMI); + #endif + // jcm.patch1.end.1/14/97 + if (monster[gnMI]._mAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Monster \"%s\" Clipped: NULL Cel Buffer",monster[gnMI].mName); + #endif + // jcm.patch1.end.1/14/97 + if (monster[gnMI]._mAnimFrame < 1 || *reinterpret_cast(monster[gnMI]._mAnimData) > MAX_FRAMES + || monster[gnMI]._mAnimFrame > *reinterpret_cast(monster[gnMI]._mAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Draw Monster \"%s\" %s Clipped: facing %d, frame %d of %d", + monster[gnMI].mName, + MonsterActionString(monster[gnMI]._mmode), + monster[gnMI]._mdir, + monster[gnMI]._mAnimFrame, + *reinterpret_cast(monster[gnMI]._mAnimData) + ); + #endif + // jcm.patch1.end.1/14/97 + } + if (!(dFlags[sx][sy] & BFLAG_VISIBLE)) { + DrawInfraUnitClipped( + xp, yp, + monster[gnMI]._mAnimData, + monster[gnMI]._mAnimFrame, + monster[gnMI].MType->mAnimWidth, + ostart, + oend, + LIGHT_INFRA + ); + return; + } + char dinfra = LIGHT_NORM; + if (monster[gnMI]._uniqtype) + dinfra = LIGHT_U + monster[gnMI]._uniqtrans; + if (monster[gnMI]._mmode == MM_STONE) + dinfra = LIGHT_STONE; + if (plr[myplr]._pInfraFlag && (nLVal > 8)) + dinfra = LIGHT_INFRA; + if (dinfra != LIGHT_NORM) + DrawInfraUnitClipped( + xp, yp, + monster[gnMI]._mAnimData, + monster[gnMI]._mAnimFrame, + monster[gnMI].MType->mAnimWidth, + ostart, + oend, + dinfra + ); + else + DrawLitUnitClipped( + xp, yp, + monster[gnMI]._mAnimData, + monster[gnMI]._mAnimFrame, + monster[gnMI].MType->mAnimWidth, + ostart, + oend + ); +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +static void DrawPSlabCelL (int gnPlayer, int sx, int sy, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + if (dFlags[sx][sy] & BFLAG_VISIBLE || plr[myplr]._pInfraFlag) { + if (gnPlayer == cursplr) { + OutlineSlabCel( + POUTC, + xp, yp, + pCelBuff, nCel, nCelW, + ostart, oend + ); + } + + if (gnPlayer == myplr) { + app_assert(pCelBuff); + DrawSlabCel(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + } + else if (!(dFlags[sx][sy] & BFLAG_VISIBLE) + || plr[myplr]._pInfraFlag && (nLVal > 8)) { + DrawSlabCelI(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, LIGHT_INFRA); + } + else { + // Draw other players slightly brighter than monsters + int templval = nLVal; + if (nLVal >= 5) + nLVal -= 5; + else + nLVal = 0; + DrawSlabCelL(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + nLVal = templval; + } + } +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if !RLE_DRAW +static void CDrawPSlabCelL (int gnPlayer, int sx, int sy, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + if (dFlags[sx][sy] & BFLAG_VISIBLE || plr[myplr]._pInfraFlag + || (!setlevel && currlevel == 0)) { + if (gnPlayer == cursplr) + COutlineSlabCel( + POUTC, + xp, yp, + pCelBuff, nCel, nCelW, + ostart, oend + ); + if (gnPlayer == myplr) + CDrawSlabCel(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + else if (!(dFlags[sx][sy] & BFLAG_VISIBLE) + || plr[myplr]._pInfraFlag && (nLVal > 8)) + CDrawSlabCelI(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, LIGHT_INFRA); + else + { + // Draw other players slightly brighter than monsters + int templval = nLVal; + if (nLVal >= 5) + nLVal -= 5; + else + nLVal = 0; + CDrawSlabCelL(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + nLVal = templval; + } + } +} +#endif + + +//*************************************************************************** +//*************************************************************************** + // These strings should match the PM_xxx constants defined in player.h + const char * sgszPlayerAction[] = { + "standing", + "walking (1)", + "walking (2)", + "walking (3)", + "attacking (melee)", + "attacking (ranged)", + "blocking", + "getting hit", + "dying", + "casting a spell", + "changing levels", + "quitting" + }; +inline const char * PlayerActionString(DWORD dwAction) { + if (dwAction <= PM_QUIT) + return sgszPlayerAction[dwAction]; + return sgszUnknownAction; +} + + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +static void DrawPSlabCelL ( + int nPlayer, int sx, int sy, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + if (!(dFlags[sx][sy] & BFLAG_VISIBLE) && !plr[myplr]._pInfraFlag && (setlevel || currlevel)) + return; + if (pCelBuff == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Drawing player %d \"%s\": NULL Cel Buffer",nPlayer,plr[nPlayer]._pName); + #endif + // jcm.patch1.end.1/14/97 + if (nCel < 1 || *(DWORD*)pCelBuff > MAX_FRAMES || nCel > *reinterpret_cast(pCelBuff)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Drawing player %d \"%s\" %s: facing %d, frame %d of %d", + nPlayer, + plr[nPlayer]._pName, + PlayerActionString(plr[nPlayer]._pmode), + plr[nPlayer]._pdir, + nCel, + *reinterpret_cast(pCelBuff) + ); + #endif + // jcm.patch1.end.1/14/97 + } + if (nPlayer == cursplr) + DrawUnitOutline(POUTC,xp,yp,pCelBuff,nCel,nCelW,ostart,oend); + + if (nPlayer == myplr) { + DrawUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + } + else if (!(dFlags[sx][sy] & BFLAG_VISIBLE) + || plr[myplr]._pInfraFlag && (nLVal > 8)) { + DrawInfraUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, LIGHT_INFRA); + } + else { + // Draw other players slightly brighter than monsters + int templval = nLVal; + nLVal = (nLVal < 5) ? 0 : nLVal - 5; + DrawLitUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + nLVal = templval; + } +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#if RLE_DRAW +static void CDrawPSlabCelL ( + int nPlayer, int sx, int sy, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + if (!(dFlags[sx][sy] & BFLAG_VISIBLE) && !plr[myplr]._pInfraFlag) + return; + if (pCelBuff == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Drawing player %d \"%s\" clipped: NULL Cel Buffer",nPlayer,plr[nPlayer]._pName); + #endif + // jcm.patch1.end.1/14/97 + if (nCel < 1 || *(DWORD*)pCelBuff > MAX_FRAMES || nCel > *reinterpret_cast(pCelBuff)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Drawing player %d \"%s\" %s clipped: facing %d, frame %d of %d", + nPlayer, + plr[nPlayer]._pName, + PlayerActionString(plr[nPlayer]._pmode), + plr[nPlayer]._pdir, + nCel, + *reinterpret_cast(pCelBuff) + ); + #endif + // jcm.patch1.end.1/14/97 + } + if (nPlayer == cursplr) + DrawUnitOutlineClipped(POUTC,xp,yp,pCelBuff,nCel,nCelW,ostart,oend); + if (nPlayer == myplr) { + DrawUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + } else if (!(dFlags[sx][sy] & BFLAG_VISIBLE) + || plr[myplr]._pInfraFlag && (nLVal > 8)) { + DrawInfraUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, LIGHT_INFRA); + } else { + // Draw other players slightly brighter than monsters + int templval = nLVal; + nLVal = (nLVal < 5) ? 0 : nLVal - 5; + DrawLitUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + nLVal = templval; + } +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawDeadPlr(int sx, int sy, int xp, int yp, int ostart, int oend, BOOL clip) +{ + int pnum; + static void (*PlayerDraw)(int, int, int, long, long, BYTE *, long, long, long, long); + PlayerStruct * pPlayer; + + PlayerDraw = clip ? CDrawPSlabCelL : DrawPSlabCelL; + + dFlags[sx][sy] &= ~BFLAG_DEADPLR; + for (pnum = 0; pnum < MAX_PLRS; ++pnum) + { + pPlayer = &plr[pnum]; + if (!pPlayer->plractive || pPlayer->_pHitPoints || pPlayer->plrlevel != currlevel + || pPlayer->_px != sx || pPlayer->_py != sy) + continue; + if (pPlayer->_pAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Drawing dead player %d \"%s\": NULL Cel Buffer", pnum, pPlayer->_pName); + #endif + // jcm.patch1.end.1/14/97 + if (pPlayer->_pAnimFrame < 1 || *reinterpret_cast(pPlayer->_pAnimData) > MAX_FRAMES + || pPlayer->_pAnimFrame > *reinterpret_cast(pPlayer->_pAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Drawing dead player %d \"%s\": facing %d, frame %d of %d", + pnum, + pPlayer->_pName, + pPlayer->_pdir, + pPlayer->_pAnimFrame, + *reinterpret_cast(pPlayer->_pAnimData) + ); + #endif + // jcm.patch1.end.1/14/97 + } + dFlags[sx][sy] |= BFLAG_DEADPLR; + PlayerDraw(pnum, sx, sy, + pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2, + pPlayer->_pyoff + yp, + pPlayer->_pAnimData, pPlayer->_pAnimFrame, pPlayer->_pAnimWidth, + ostart, oend); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawObjCel(int sx, int sy, int xp, int yp, BOOL pre, int ostart, int oend) +{ + char bv; + int pxp, pyp; + int odx, ody; + + if (dObject[sx][sy] > 0) { + bv = dObject[sx][sy] - 1; + if (object[bv]._oPreFlag != pre) return; + pxp = xp - object[bv]._oAnimWidth2; + pyp = yp; + } else { + bv = -(dObject[sx][sy]+1); + if (object[bv]._oPreFlag != pre) return; + odx = (object[bv]._ox - sx); + ody = (object[bv]._oy - sy); + pxp = xp - object[bv]._oAnimWidth2 + (odx << 5) - (ody << 5); + pyp = yp + (odx << 4) + (ody << 4); + ostart = 0; + oend = 8; + } + app_assert(bv < MAXOBJECTS && bv >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (bv >= MAXOBJECTS || bv < 0) + return; + #endif + // jcm.patch1.end.1/14/97 + if (object[bv]._oAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Object type %d: NULL Cel Buffer",object[bv]._otype); + #endif + // jcm.patch1.end.1/14/97 + if (object[bv]._oAnimFrame < 1 || *reinterpret_cast(object[bv]._oAnimData) > MAX_FRAMES + || object[bv]._oAnimFrame > *reinterpret_cast(object[bv]._oAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Draw Object: frame %d of %d, object type==%d", + object[bv]._oAnimFrame, + *reinterpret_cast(object[bv]._oAnimData), + object[bv]._otype + ); + #endif + // jcm.patch1.end.1/14/97 + } + if (bv == cursobj) OutlineSlabCel(OOUTC, pxp, pyp, object[bv]._oAnimData, object[bv]._oAnimFrame, object[bv]._oAnimWidth, ostart, oend); + if (object[bv]._oLight) { + DrawSlabCelL(pxp, pyp, object[bv]._oAnimData, object[bv]._oAnimFrame, object[bv]._oAnimWidth, ostart, oend); + } + else { + app_assert(object[bv]._oAnimData); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (object[bv]._oAnimData == NULL) + return; + #endif + // jcm.patch1.end.1/14/97 + DrawSlabCel(pxp, pyp, object[bv]._oAnimData, object[bv]._oAnimFrame, object[bv]._oAnimWidth, ostart, oend); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void CDrawObjCel(int sx, int sy, int xp, int yp, BOOL pre, int ostart, int oend) +{ + char bv; + int pxp, pyp; + int odx, ody; + + if (dObject[sx][sy] > 0) { + bv = dObject[sx][sy] - 1; + if (object[bv]._oPreFlag != pre) return; + pxp = xp - object[bv]._oAnimWidth2; + pyp = yp; + } else { + bv = -(dObject[sx][sy]+1); + if (object[bv]._oPreFlag != pre) return; + odx = (object[bv]._ox - sx); + ody = (object[bv]._oy - sy); + pxp = xp - object[bv]._oAnimWidth2 + (odx << 5) - (ody << 5); + pyp = yp + (odx << 4) + (ody << 4); + ostart = 0; + oend = 8; + } + app_assert(bv < MAXOBJECTS && bv >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (bv >= MAXOBJECTS) + return; + #endif + // jcm.patch1.end.1/14/97 + if (object[bv]._oAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal("Draw Object type %d Clipped: NULL Cel Buffer",object[bv]._otype); + #endif + // jcm.patch1.end.1/14/97 + if (object[bv]._oAnimFrame < 1 || *reinterpret_cast(object[bv]._oAnimData) > MAX_FRAMES + || object[bv]._oAnimFrame > *reinterpret_cast(object[bv]._oAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + return; + #else + app_fatal( + "Draw Clipped Object: frame %d of %d, object type==%d", + object[bv]._oAnimFrame, + *reinterpret_cast(object[bv]._oAnimData), + object[bv]._otype + ); + #endif + // jcm.patch1.end.1/14/97 + } + if (bv == cursobj) COutlineSlabCel(OOUTC, pxp, pyp, object[bv]._oAnimData, object[bv]._oAnimFrame, object[bv]._oAnimWidth, ostart, oend); + if (object[bv]._oLight) CDrawSlabCelL(pxp, pyp, object[bv]._oAnimData, object[bv]._oAnimFrame, object[bv]._oAnimWidth, ostart, oend); + else CDrawSlabCel(pxp, pyp, object[bv]._oAnimData, object[bv]._oAnimFrame, object[bv]._oAnimWidth, ostart, oend); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawEFlag1(BYTE *pTo2, int sx, int sy, int xp, int yp) +{ + BYTE *pTo; + long oldnLVal; + BOOL oldnTrans; + int oldPieceNum; + WORD *mt; + + oldnLVal = nLVal; + oldnTrans = nTrans; + oldPieceNum = gnPieceNum; + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + gbPartialTrans = PART_TRANS_LEFT; + if (gdwPNum = mt[0]) + DrawMTileClipBottom (pTo2); + gbPartialTrans = PART_TRANS_RIGHT; + if (gdwPNum = mt[1]) + DrawMTileClipBottom (pTo2+32); + gbPartialTrans = PART_TRANS_NONE; + pTo = pTo2; + for(int t = 2; t < MicroTileLen; t += 2) + { + pTo -= NBUFFWSL5; + if (gdwPNum = mt[t]) + DrawMTileClipBottom (pTo); + if (gdwPNum = mt[t+1]) + DrawMTileClipBottom (pTo+32); + } + + DrawHTLXsub (pTo2, sx, sy, xp, yp, FALSE); + + nLVal = oldnLVal; + nTrans = oldnTrans; + gnPieceNum = oldPieceNum; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag) +{ + char bFlags, bDead, bObject, bItem, bPlayer, bSpecial, bPlayerAbove, bTransVal; + int nMonster, nMonsterAbove; + int pxp,pyp; + + app_assert(sx < MAXDUNX); + app_assert(sy < MAXDUNY); + bFlags = dFlags[sx][sy]; + bDead = dDead[sx][sy]; + bObject = dObject[sx][sy]; + bItem = dItem[sx][sy]; + bPlayer = dPlayer[sx][sy]; + bSpecial = dSpecial[sx][sy]; + bTransVal = dTransVal[sx][sy]; + nMonster = dMonster[sx][sy]; + + app_assert((sy-1) < MAXDUNY); + bPlayerAbove = dPlayer[sx][sy-1]; + nMonsterAbove = dMonster[sx][sy-1]; + + if ((visiondebug) && (bFlags & BFLAG_VISIBLE)) + CDrawSlabCelP(pTo, pSquareCel, 1, 64, 0, 8); + if (MissilePreFlag && (bFlags & BFLAG_MISSILE)) + CDrawMissile(sx, sy, xp, yp, 0, 8, TRUE); + if (nLVal < lightmax) { + if (bDead) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + DeadStruct * pDeadGuy = &dead[(bDead & 0x1f) - 1]; + char dd = (bDead & 0xe0) >> 5; + pxp = xp - pDeadGuy->_deadWidth2; + app_assert(pDeadGuy->_deadData[dd] != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDeadGuy->_deadData[dd] == NULL) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pDeadGuy->_deadFrame < 1 || *reinterpret_cast(pDeadGuy->_deadData[dd]) > MAX_FRAMES + || pDeadGuy->_deadFrame > *reinterpret_cast(pDeadGuy->_deadData[dd])) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Clipped dead sub: frame %d of %d, deadnum==%d", + pDeadGuy->_deadFrame, + *reinterpret_cast(pDeadGuy->_deadData[dd]), + (bDead & 0x1f) - 1 + ); + #endif + // jcm.patch1.end.1/14/97 + } + #if RLE_DRAW + if (pDeadGuy->_deadtrans) + DrawInfraUnitClipped( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + 0, + 8, + pDeadGuy->_deadtrans + ); + else + DrawLitUnitClipped( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + 0, + 8 + ); + #else + if (pDeadGuy->_deadtrans) + CDrawSlabCelI( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + 0, + 8, + pDeadGuy->_deadtrans + ); + else + CDrawSlabCelL( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + 0, + 8 + ); + #endif + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bObject) + CDrawObjCel(sx, sy, xp, yp, TRUE, 0, 8); + } + if (bItem) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + ItemStruct * pItem = &item[bItem - 1]; + if (!pItem->_iPostDraw) { + app_assert(bItem <= MAXITEMS && bItem >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (bItem > MAXITEMS || bItem < 0) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Item \"%s\" Clipped 1: NULL Cel Buffer",pItem->_iIName); + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimFrame < 1 || *reinterpret_cast(pItem->_iAnimData) > MAX_FRAMES + || pItem->_iAnimFrame > *reinterpret_cast(pItem->_iAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Draw Clipped \"%s\" Item: frame %d of %d, item type==%d", + pItem->_iIName, + pItem->_iAnimFrame, + *reinterpret_cast(pItem->_iAnimData), + pItem->_itype + ); + #endif + // jcm.patch1.end.1/14/97 + } + pxp = xp - pItem->_iAnimWidth2; + if ((bItem - 1) == cursitem + || HighLightAllItems == true) + COutlineSlabCel( + IOUTC, + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + 0, + 8 + ); + CDrawSlabCelL( + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + 0, + 8 + ); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_PLRLR) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + int nPlayer = -(bPlayerAbove + 1); + if ((DWORD)nPlayer >= MAX_PLRS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("draw player clipped: tried to draw illegal player %d",nPlayer); + #endif + // jcm.patch1.end.1/14/97 + PlayerStruct * pPlayer = &plr[nPlayer]; + pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; + pyp = pPlayer->_pyoff + yp; + CDrawPSlabCelL( + -(bPlayerAbove + 1), + sx, sy-1, + pxp, + pyp, + pPlayer->_pAnimData, + pPlayer->_pAnimFrame, + pPlayer->_pAnimWidth, + 0, + 8 + ); + if (chflag && pPlayer->_peflag) { + if (pPlayer->_peflag == 2) + DrawEFlag1(pTo-(NBUFFWSL4+96), sx-2, sy+1, xp-96, yp-16); + DrawEFlag1(pTo-64, sx-1, sy+1, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while(0); + #endif + // jcm.patch1.end.1/14/97 + } + if ((bFlags & BFLAG_MONSTLR) && ((bFlags & BFLAG_VISIBLE) || plr[myplr]._pInfraFlag) && (nMonsterAbove < 0)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + gnMI = -(nMonsterAbove + 1); + if ((DWORD)gnMI >= MAXMONSTERS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster Clipped: tried to draw illegal monster %d",gnMI); + #endif + // jcm.patch1.end.1/14/97 + MonsterStruct * pMonster = &monster[gnMI]; + if (!(pMonster->_mFlags & MFLAG_INVISIBLE)) { + if (pMonster->MType == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster \"%s\" Clipped: uninitialized monster",pMonster->mName); + #endif + // jcm.patch1.end.1/14/97 + pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; + pyp = pMonster->_myoff + yp; + #if RLE_DRAW + if (gnMI == cursmonst) + DrawUnitOutlineClipped( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + 0, + 8 + ); + #else + if (gnMI == cursmonst) + COutlineSlabCel( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + 0, + 8 + ); + #endif + CDrawMSlabCelL(sx, sy, pxp, pyp, gnMI, 0, 8); + if (chflag && pMonster->_meflag) + DrawEFlag1(pTo-64, sx-1, sy+1, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_DEADPLR) + DrawDeadPlr(sx, sy, xp, yp, 0, 8, TRUE); + if (bPlayer > 0) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + int nPlayer = bPlayer - 1; + if ((DWORD)nPlayer >= MAX_PLRS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("draw player clipped: tried to draw illegal player %d",nPlayer); + #endif + // jcm.patch1.end.1/14/97 + PlayerStruct * pPlayer = &plr[nPlayer]; + pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; + pyp = pPlayer->_pyoff + yp; + CDrawPSlabCelL( + bPlayer - 1, + sx, sy, + pxp, + pyp, + pPlayer->_pAnimData, + pPlayer->_pAnimFrame, + pPlayer->_pAnimWidth, + 0, + 8 + ); + if (chflag && pPlayer->_peflag) { + if (pPlayer->_peflag == 2) + DrawEFlag1(pTo-(NBUFFWSL4+96), sx-2, sy+1, xp-96, yp-16); + DrawEFlag1(pTo-64, sx-1, sy+1, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if ((nMonster > 0) && ((bFlags & BFLAG_VISIBLE) || plr[myplr]._pInfraFlag)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + gnMI = nMonster - 1; + if ((DWORD)gnMI >= MAXMONSTERS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster Clipped: tried to draw illegal monster %d",gnMI); + #endif + // jcm.patch1.end.1/14/97 + MonsterStruct * pMonster = &monster[gnMI]; + if (!(pMonster->_mFlags & MFLAG_INVISIBLE)) { + if (pMonster->MType == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster \"%s\" Clipped: uninitialized monster",pMonster->mName); + #endif + // jcm.patch1.end.1/14/97 + pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; + pyp = pMonster->_myoff + yp; + #if RLE_DRAW + if (gnMI == cursmonst) + DrawUnitOutlineClipped( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + 0, + 8 + ); + #else + if (gnMI == cursmonst) + COutlineSlabCel( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + 0, + 8 + ); + #endif + CDrawMSlabCelL(sx, sy, pxp, pyp, gnMI, 0, 8); + if (chflag && pMonster->_meflag) + DrawEFlag1(pTo-64, sx-1, sy+1, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_MISSILE) + CDrawMissile(sx, sy, xp, yp, 0, 8, FALSE); + if (bObject && (nLVal < lightmax)) + CDrawObjCel(sx, sy, xp, yp, FALSE, 0, 8); + if (bItem) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + ItemStruct * pItem = &item[bItem - 1]; + if (pItem->_iPostDraw) { + app_assert(bItem <= MAXITEMS && bItem >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (bItem > MAXITEMS || bItem < 0) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Item \"%s\" Clipped 2: NULL Cel Buffer",pItem->_iIName); + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimFrame < 1 || *reinterpret_cast(pItem->_iAnimData) > MAX_FRAMES + || pItem->_iAnimFrame > *reinterpret_cast(pItem->_iAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Draw Clipped \"%s\" Item 2: frame %d of %d, item type==%d", + pItem->_iIName, + pItem->_iAnimFrame, + *reinterpret_cast(pItem->_iAnimData), + pItem->_itype + ); + #endif + // jcm.patch1.end.1/14/97 + } + pxp = xp - pItem->_iAnimWidth2; + if ((bItem - 1) == cursitem + || HighLightAllItems == true) + COutlineSlabCel( + IOUTC, + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + 0, + 8 + ); + CDrawSlabCelL( + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + 0, + 8 + ); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bSpecial) { + nTrans = TransList[bTransVal]; + TCDrawSlabCelPL(pTo, pSpecialCels, bSpecial, 64, 0, 8); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawHTileLineX (int sx, int sy, int xp, int yp, int nd, int halfflag) +{ + int i; + BYTE *pTo; + int t; + MICROS *pmt; + WORD *mt; + + app_assert(gpBuffer); + pmt = &dMT2[CalcRot(sx,sy)]; + if (halfflag) { + if (((unsigned)sy < DMAXY) && ((unsigned)sx < DMAXX)) { + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + if (gnPieceNum) { + pTo = gpBuffer + nBuffWTbl[yp] + xp + 32; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + + mt = &pmt->mt[0]; + + gbPartialTrans = PART_TRANS_RIGHT; + if (gdwPNum = mt[1]) + DrawMTileClipBottom (pTo); + gbPartialTrans = PART_TRANS_NONE; + + pTo -= NBUFFWSL5; + if (gdwPNum = mt[3]) + DrawMTileClipBottom (pTo); + + pTo -= NBUFFWSL5; + if (gdwPNum = mt[5]) + DrawMTileClipBottom (pTo); + + pTo -= NBUFFWSL5; + if (gdwPNum = mt[7]) + DrawMTileClipBottom (pTo); + + pTo -= NBUFFWSL5; + if (gdwPNum = mt[9]) + DrawMTileClipBottom (pTo); + + pTo -= NBUFFWSL5; + if ((gdwPNum = mt[11]) && (leveltype == 4)) + DrawMTileClipBottom (pTo); + + DrawHTLXsub (gpBuffer + nBuffWTbl[yp] + xp, sx, sy, xp, yp, FALSE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawBlankMTile(pTo); + } + } + ++sx; + --sy; + xp += 64; + ++pmt; + --nd; + } + + for (i = nd; i-- && sy >= 0 && sx < DMAXX; ++sx, --sy, xp += 64, ++pmt) { + if (sy >= DMAXY || sx < 0) + continue; + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + if (!gnPieceNum) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawBlankMTile(pTo); + continue; + } + pTo = gpBuffer + nBuffWTbl[yp] + xp; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + + mt = &pmt->mt[0]; + + gbPartialTrans = PART_TRANS_LEFT; + if (gdwPNum = mt[0]) DrawMTileClipBottom (pTo); + gbPartialTrans = PART_TRANS_RIGHT; + if (gdwPNum = mt[1]) DrawMTileClipBottom (pTo+32); + gbPartialTrans = PART_TRANS_NONE; + for(t = 2; t < MicroTileLen; t += 2) + { + pTo -= NBUFFWSL5; + if (gdwPNum = mt[t]) + DrawMTileClipBottom (pTo); + if (gdwPNum = mt[t+1]) + DrawMTileClipBottom (pTo+32); + } + + DrawHTLXsub (gpBuffer + nBuffWTbl[yp] + xp, sx, sy, xp, yp, TRUE); + } + + if (!halfflag || !((unsigned)sy < DMAXY && (unsigned)sx < DMAXX)) + return; + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + if (!gnPieceNum) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawBlankMTile(pTo); + return; + } + pTo = gpBuffer + nBuffWTbl[yp] + xp; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &pmt->mt[0]; + gbPartialTrans = PART_TRANS_LEFT; + if (gdwPNum = mt[0]) + DrawMTileClipBottom (pTo); + gbPartialTrans = PART_TRANS_NONE; + pTo -= NBUFFWSL5; + if (gdwPNum = mt[2]) + DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + if (gdwPNum = mt[4]) + DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + if (gdwPNum = mt[6]) + DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + if (gdwPNum = mt[8]) + DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + if ((gdwPNum = mt[10]) && (leveltype == 4)) + DrawMTileClipBottom (pTo); + DrawHTLXsub (gpBuffer + nBuffWTbl[yp] + xp, sx, sy, xp, yp, FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawEFlag2(BYTE *pTo2, int sx, int sy, int sv, int sv2, int xp, int yp) +{ + BYTE *pTo; + long oldnLVal; + BOOL oldnTrans; + int oldPieceNum; + WORD *mt; + + oldnLVal = nLVal; + oldnTrans = nTrans; + oldPieceNum = gnPieceNum; + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + pTo = pTo2 + (NBUFFWSL5 * sv); + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + switch (sv) { + case 0: + if (gdwPNum = mt[2]) DrawMTileClipBottom (pTo); + if (gdwPNum = mt[3]) DrawMTileClipBottom (pTo+32); + case 1: + pTo -= NBUFFWSL5; + if (gdwPNum = mt[4]) DrawMTileClipBottom (pTo); + if (gdwPNum = mt[5]) DrawMTileClipBottom (pTo+32); + case 2: + pTo -= NBUFFWSL5; + if (gdwPNum = mt[6]) DrawMTileClipBottom (pTo); + if (gdwPNum = mt[7]) DrawMTileClipBottom (pTo+32); + case 3: + pTo -= NBUFFWSL5; + if (gdwPNum = mt[8]) DrawMTileClipBottom (pTo); + if (gdwPNum = mt[9]) DrawMTileClipBottom (pTo+32); +// case 4: +// pTo -= NBUFFWSL5; +// if (leveltype == 4) { +// if (gdwPNum = mt[10]) DrawMTileClipBottom (pTo); +// if (gdwPNum = mt[11]) DrawMTileClipBottom (pTo+32); +// } + } + + if (sv2 < 8) + DrawHTLXsub2 (pTo2, sx, sy, sv, sv2, xp, yp, FALSE); + nLVal = oldnLVal; + nTrans = oldnTrans; + gnPieceNum = oldPieceNum; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, int yp, BOOL chflag) +{ + char bFlags, bDead, bObject, bItem, bPlayer, bSpecial, bPlayerAbove, bTransVal; + int nMonster, nMonsterAbove; + int pxp,pyp; + + app_assert(sx < MAXDUNX); + app_assert(sy < MAXDUNY); + bFlags = dFlags[sx][sy]; + bDead = dDead[sx][sy]; + bObject = dObject[sx][sy]; + bItem = dItem[sx][sy]; + bPlayer = dPlayer[sx][sy]; + bSpecial = dSpecial[sx][sy]; + bTransVal = dTransVal[sx][sy]; + nMonster = dMonster[sx][sy]; + + app_assert((sy-1) < MAXDUNY); + bPlayerAbove = dPlayer[sx][sy-1]; + nMonsterAbove = dMonster[sx][sy-1]; + + if (visiondebug && (bFlags & BFLAG_VISIBLE)) + CDrawSlabCelP(pTo, pSquareCel, 1, 64, sv2, 8); + if (MissilePreFlag && (bFlags & BFLAG_MISSILE)) + CDrawMissile(sx, sy, xp, yp, sv2, 8, TRUE); + if (nLVal < lightmax) { + if (bDead) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + DeadStruct * pDeadGuy = &dead[(bDead & 0x1f) - 1]; + char dd = (bDead & 0xe0) >> 5; + pxp = xp - pDeadGuy->_deadWidth2; + app_assert(pDeadGuy->_deadData[dd] != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDeadGuy->_deadData[dd] == NULL) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pDeadGuy->_deadFrame < 1 || *reinterpret_cast(pDeadGuy->_deadData[dd]) > MAX_FRAMES + || pDeadGuy->_deadFrame > *reinterpret_cast(pDeadGuy->_deadData[dd])) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Clipped dead sub2: frame %d of %d, deadnum==%d", + pDeadGuy->_deadFrame, + *reinterpret_cast(pDeadGuy->_deadData[dd]), + (bDead & 0x1f) - 1 + ); + #endif + // jcm.patch1.end.1/14/97 + } + #if RLE_DRAW + if (pDeadGuy->_deadtrans) + DrawInfraUnitClipped( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + sv2, + 8, + pDeadGuy->_deadtrans + ); + else + DrawLitUnitClipped( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + sv2, + 8 + ); + #else + if (pDeadGuy->_deadtrans) + CDrawSlabCelI( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + sv2, + 8, + pDeadGuy->_deadtrans + ); + else + CDrawSlabCelL( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + sv2, + 8 + ); + #endif + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bObject) + CDrawObjCel(sx, sy, xp, yp, TRUE, sv2, 8); + } + if (bItem) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + ItemStruct * pItem = &item[bItem - 1]; + if (!pItem->_iPostDraw) { + app_assert(bItem <= MAXITEMS && bItem >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (bItem > MAXITEMS || bItem < 0) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Item \"%s\" Clipped 3: NULL Cel Buffer",pItem->_iIName); + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimFrame < 1 || *reinterpret_cast(pItem->_iAnimData) > MAX_FRAMES + || pItem->_iAnimFrame > *reinterpret_cast(pItem->_iAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Draw Clipped \"%s\" Item 3: frame %d of %d, item type==%d", + pItem->_iIName, + pItem->_iAnimFrame, + *reinterpret_cast(pItem->_iAnimData), + pItem->_itype + ); + #endif + // jcm.patch1.end.1/14/97 + } + pxp = xp - pItem->_iAnimWidth2; + if ((bItem - 1) == cursitem + || HighLightAllItems == true) + COutlineSlabCel( + IOUTC, + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + sv2, + 8 + ); + CDrawSlabCelL( + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + sv2, + 8 + ); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_PLRLR) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + int nPlayer = -(bPlayerAbove + 1); + if (nPlayer >= MAX_PLRS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("draw player clipped: tried to draw illegal player %d",nPlayer); + #endif + // jcm.patch1.end.1/14/97 + PlayerStruct * pPlayer = &plr[nPlayer]; + pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; + pyp = pPlayer->_pyoff + yp; + CDrawPSlabCelL( + -(bPlayerAbove + 1), + sx, sy-1, + pxp, + pyp, + pPlayer->_pAnimData, + pPlayer->_pAnimFrame, + pPlayer->_pAnimWidth, + sv2, + 8 + ); + if (chflag && pPlayer->_peflag) { + if (pPlayer->_peflag == 2) + DrawEFlag2(pTo-(NBUFFWSL4+96), sx-2, sy+1, sv, sv2, xp-96, yp-16); + DrawEFlag2(pTo-64, sx-1, sy+1, sv, sv2, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if ((bFlags & BFLAG_MONSTLR) && ((bFlags & BFLAG_VISIBLE) || (plr[myplr]._pInfraFlag)) && (nMonsterAbove < 0)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + gnMI = -(nMonsterAbove + 1); + if (gnMI >= MAXMONSTERS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster Clipped: tried to draw illegal monster %d",gnMI); + #endif + // jcm.patch1.end.1/14/97 + MonsterStruct * pMonster = &monster[gnMI]; + if (!(pMonster->_mFlags & MFLAG_INVISIBLE)) { + if (pMonster->MType == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster \"%s\" Clipped: uninitialized monster",pMonster->mName); + #endif + // jcm.patch1.end.1/14/97 + pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; + pyp = pMonster->_myoff + yp; + #if RLE_DRAW + if (gnMI == cursmonst) + DrawUnitOutlineClipped( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + sv2, + 8 + ); + #else + if (gnMI == cursmonst) + COutlineSlabCel( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + sv2, + 8 + ); + #endif + CDrawMSlabCelL(sx, sy, pxp, pyp, gnMI, sv2, 8); + if (chflag && !pMonster->_meflag) + DrawEFlag2(pTo-64, sx-1, sy+1, sv, sv2, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_DEADPLR) + DrawDeadPlr(sx, sy, xp, yp, sv2, 8, TRUE); + if (bPlayer > 0) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + int nPlayer = bPlayer - 1; + if ((DWORD)nPlayer >= MAX_PLRS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("draw player clipped: tried to draw illegal player %d",nPlayer); + #endif + // jcm.patch1.end.1/14/97 + PlayerStruct * pPlayer = &plr[nPlayer]; + pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; + pyp = pPlayer->_pyoff + yp; + CDrawPSlabCelL( + bPlayer - 1, + sx, sy, + pxp, + pyp, + pPlayer->_pAnimData, + pPlayer->_pAnimFrame, + pPlayer->_pAnimWidth, + sv2, + 8 + ); + if (chflag && pPlayer->_peflag) { + if (pPlayer->_peflag == 2) + DrawEFlag2(pTo-(NBUFFWSL4+96), sx-2, sy+1, sv, sv2, xp-96, yp-16); + DrawEFlag2(pTo-64, sx-1, sy+1, sv, sv2, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if ((nMonster > 0) && ((bFlags & BFLAG_VISIBLE) || (plr[myplr]._pInfraFlag))) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + gnMI = nMonster - 1; + if ((DWORD)gnMI >= MAXMONSTERS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster Clipped: tried to draw illegal monster %d",gnMI); + #endif + // jcm.patch1.end.1/14/97 + MonsterStruct * pMonster = &monster[gnMI]; + if (!(pMonster->_mFlags & MFLAG_INVISIBLE)) { + if (pMonster->MType == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster \"%s\" Clipped: uninitialized monster",pMonster->mName); + #endif + // jcm.patch1.end.1/14/97 + pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; + pyp = pMonster->_myoff + yp; + #if RLE_DRAW + if (gnMI == cursmonst) + DrawUnitOutlineClipped( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + sv2, + 8 + ); + #else + if (gnMI == cursmonst) + COutlineSlabCel( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + sv2, + 8 + ); + #endif + CDrawMSlabCelL(sx, sy, pxp, pyp, gnMI, sv2, 8); + if (chflag && !pMonster->_meflag) + DrawEFlag2(pTo-64, sx-1, sy+1, sv, sv2, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_MISSILE) + CDrawMissile(sx, sy, xp, yp, sv2, 8, FALSE); + if (bObject && (nLVal < lightmax)) + CDrawObjCel(sx, sy, xp, yp, FALSE, sv2, 8); + if (bItem) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + ItemStruct * pItem = &item[bItem - 1]; + if (pItem->_iPostDraw) { + app_assert(bItem <= MAXITEMS && bItem >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (bItem > MAXITEMS || bItem < 0) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Item \"%s\" Clipped 4: NULL Cel Buffer",pItem->_iIName); + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimFrame < 1 || *reinterpret_cast(pItem->_iAnimData) > MAX_FRAMES + || pItem->_iAnimFrame > *reinterpret_cast(pItem->_iAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Draw Clipped \"%s\" Item 4: frame %d of %d, item type==%d", + pItem->_iIName, + pItem->_iAnimFrame, + *reinterpret_cast(pItem->_iAnimData), + pItem->_itype + ); + #endif + // jcm.patch1.end.1/14/97 + } + pxp = xp - pItem->_iAnimWidth2; + if ((bItem - 1) == cursitem + || HighLightAllItems == true) + COutlineSlabCel( + IOUTC, + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + sv2, + 8 + ); + CDrawSlabCelL( + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + sv2, + 8 + ); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bSpecial) { + nTrans = TransList[bTransVal]; + TCDrawSlabCelPL(pTo, pSpecialCels, bSpecial, 64, sv2, 8); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawHTLX2 (int sx, int sy, int xp, int yp, int nd, int sv, int halfflag) +{ + int i; + BYTE *pTo; + int sv2; + int t; + MICROS *pmt; + WORD *mt; + + app_assert(gpBuffer); + pmt = &dMT2[CalcRot(sx,sy)]; + sv2 = (sv + 1) << 1; + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + if (gnPieceNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5 + 32; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &pmt->mt[0]; + + for(t = 0; t < ((MicroTileLen>>1)-1); ++t) + { + if ((sv <= t) && (gdwPNum = mt[2*t+3])) DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + } + if (sv2 < 8) { + pTo = gpBuffer + nBuffWTbl[yp] + xp - (NBUFFWSL4 * sv2); + DrawHTLXsub2 (pTo, sx, sy, sv, sv2, xp, yp, FALSE); + } + } + } + ++sx; + --sy; + xp += 64; + --nd; + ++pmt; + } + + for (i = nd; i-- && sx < DMAXX && sy >= 0; ++sx, --sy, xp += 64, ++pmt) { + if (sy >= DMAXY || sx < 0) + continue; + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + if (!gnPieceNum) + continue; + pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &pmt->mt[0]; + for(t = 0; t < ((MicroTileLen>>1)-1); ++t, pTo -= NBUFFWSL5) + { + if (sv > t) + continue; + if (gdwPNum = mt[2*t + 2]) + DrawMTileClipBottom (pTo); + if (gdwPNum = mt[2*t + 3]) + DrawMTileClipBottom (pTo+32); + } + + if (sv2 >= 8) + continue; + pTo = gpBuffer + nBuffWTbl[yp] + xp - (NBUFFWSL5 * (sv + 1)); + DrawHTLXsub2 (pTo, sx, sy, sv, sv2, xp, yp, TRUE); + } + + if (!halfflag || !(static_cast(sy) < DMAXY && static_cast(sx) < DMAXX)) + return; + + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + + if (!gnPieceNum) + return; + pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &pmt->mt[0]; + + for(t = 0; t < ((MicroTileLen>>1)-1); ++t) + { + if ((sv <= t) && (gdwPNum = mt[2*t+2])) DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + } + + if (sv2 < 8) { + pTo = gpBuffer + nBuffWTbl[yp] + xp - (NBUFFWSL4 * sv2); + DrawHTLXsub2 (pTo, sx, sy, sv, sv2, xp, yp, FALSE); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawEFlag3(BYTE *pTo2, int sx, int sy, int ev, int ev2, int xp, int yp) +{ + BYTE *pTo; + long oldnLVal; + BOOL oldnTrans; + int oldPieceNum; + int t; + WORD *mt; + + oldnLVal = nLVal; + oldnTrans = nTrans; + oldPieceNum = gnPieceNum; + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + pTo = pTo2; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + gbPartialTrans = PART_TRANS_LEFT; + if (gdwPNum = mt[0]) DrawMTileClipTop (pTo); + gbPartialTrans = PART_TRANS_RIGHT; + if (gdwPNum = mt[1]) DrawMTileClipTop (pTo+32); + gbPartialTrans = PART_TRANS_NONE; + for(t = 1; t < ((MicroTileLen>>1)-1); ++t) + { + pTo -= NBUFFWSL5; + if (ev >= t) { + if (gdwPNum = mt[2*t]) DrawMTileClipTop (pTo); + if (gdwPNum = mt[2*t+1]) DrawMTileClipTop (pTo+32); + } + } + + DrawHTLXsub3 (pTo2, sx, sy, ev, ev2, xp, yp, FALSE); + + nLVal = oldnLVal; + nTrans = oldnTrans; + gnPieceNum = oldPieceNum; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, int yp, BOOL chflag) +{ + char bFlags, bDead, bObject, bItem, bPlayer, bSpecial, bPlayerAbove, bTransVal; + int nMonster, nMonsterAbove; + int pxp,pyp; + + app_assert(sx < MAXDUNX); + app_assert(sy < MAXDUNY); + bFlags = dFlags[sx][sy]; + bDead = dDead[sx][sy]; + bObject = dObject[sx][sy]; + bItem = dItem[sx][sy]; + bPlayer = dPlayer[sx][sy]; + bSpecial = dSpecial[sx][sy]; + bTransVal = dTransVal[sx][sy]; + nMonster = dMonster[sx][sy]; + + app_assert((sy-1) < MAXDUNY); + bPlayerAbove = dPlayer[sx][sy-1]; + nMonsterAbove = dMonster[sx][sy-1]; + + if (visiondebug && (bFlags & BFLAG_VISIBLE)) + DrawSlabCelP(pTo, pSquareCel, 1, 64, 0, ev2); + if (MissilePreFlag && (bFlags & BFLAG_MISSILE)) + DrawMissile(sx, sy, xp, yp, 0, ev2, TRUE); + if (nLVal < lightmax) { + if (bDead) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + DeadStruct * pDeadGuy = &dead[(bDead & 0x1f) - 1]; + char dd = (bDead & 0xe0) >> 5; + pxp = xp - pDeadGuy->_deadWidth2; + app_assert(pDeadGuy->_deadData[dd] != NULL); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (pDeadGuy->_deadData[dd] == NULL) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pDeadGuy->_deadFrame < 1 || *reinterpret_cast(pDeadGuy->_deadData[dd]) > MAX_FRAMES + || pDeadGuy->_deadFrame > *reinterpret_cast(pDeadGuy->_deadData[dd])) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Unclipped dead: frame %d of %d, deadnum==%d", + pDeadGuy->_deadFrame, + *reinterpret_cast(pDeadGuy->_deadData[dd]), + (bDead & 0x1f) - 1 + ); + #endif + // jcm.patch1.end.1/14/97 + } + #if RLE_DRAW + if (pDeadGuy->_deadtrans) + DrawInfraUnit( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + 0, + ev2,//diff + pDeadGuy->_deadtrans + ); + else + DrawLitUnit( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + 0, + ev2//diff + ); + #else + if (pDeadGuy->_deadtrans) + DrawSlabCelI( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + 0, + ev2,//diff + pDeadGuy->_deadtrans + ); + else + DrawSlabCelL( + pxp, + yp, + pDeadGuy->_deadData[dd], + pDeadGuy->_deadFrame, + pDeadGuy->_deadWidth, + 0, + ev2//diff + ); + #endif + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bObject) + DrawObjCel(sx, sy, xp, yp, TRUE, 0, ev2);//diff + } + if (bItem) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + ItemStruct * pItem = &item[bItem - 1]; + if (!pItem->_iPostDraw) { + app_assert(bItem <= MAXITEMS && bItem >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (bItem > MAXITEMS || bItem < 0) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Item \"%s\" 1: NULL Cel Buffer",pItem->_iIName); + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimFrame < 1 || *reinterpret_cast(pItem->_iAnimData) > MAX_FRAMES + || pItem->_iAnimFrame > *reinterpret_cast(pItem->_iAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Draw \"%s\" Item 1: frame %d of %d, item type==%d", + pItem->_iIName, + pItem->_iAnimFrame, + *reinterpret_cast(pItem->_iAnimData), + pItem->_itype + ); + #endif + // jcm.patch1.end.1/14/97 + } + pxp = xp - pItem->_iAnimWidth2; + if ((bItem - 1) == cursitem + || HighLightAllItems == true) + OutlineSlabCel( + IOUTC, + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + 0, + ev2//diff + ); + DrawSlabCelL( + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + 0, + ev2//diff + ); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_PLRLR) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + int nPlayer = -(bPlayerAbove + 1); + if (nPlayer >= MAX_PLRS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("draw player: tried to draw illegal player %d",nPlayer); + #endif + // jcm.patch1.end.1/14/97 + PlayerStruct * pPlayer = &plr[nPlayer]; + pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; + pyp = pPlayer->_pyoff + yp; + DrawPSlabCelL( + -(bPlayerAbove + 1), + sx, sy-1, + pxp, + pyp, + pPlayer->_pAnimData, + pPlayer->_pAnimFrame, + pPlayer->_pAnimWidth, + 0, + ev2//diff + ); + if (chflag && pPlayer->_peflag) { + if (pPlayer->_peflag == 2) + DrawEFlag3(pTo-(NBUFFWSL4+96), sx-2, sy+1, ev, ev2, xp-96, yp-16); + DrawEFlag3(pTo-64, sx-1, sy+1, ev, ev2, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if ((bFlags & BFLAG_MONSTLR) && ((bFlags & BFLAG_VISIBLE) || plr[myplr]._pInfraFlag) && (nMonsterAbove < 0)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + gnMI = -(nMonsterAbove + 1); + if (gnMI >= MAXMONSTERS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster: tried to draw illegal monster %d",gnMI); + #endif + // jcm.patch1.end.1/14/97 + MonsterStruct * pMonster = &monster[gnMI]; + if (!(pMonster->_mFlags & MFLAG_INVISIBLE)) { + if (pMonster->MType == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster \"%s\": uninitialized monster",pMonster->mName); + #endif + // jcm.patch1.end.1/14/97 + pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; + pyp = pMonster->_myoff + yp; + #if RLE_DRAW + if (gnMI == cursmonst) + DrawUnitOutline( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + 0, + ev2 + ); + #else + if (gnMI == cursmonst) + OutlineSlabCel( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + 0, + ev2 + ); + #endif + DrawMSlabCelL(sx, sy, pxp, pyp, gnMI, 0, ev2); + if (chflag && !pMonster->_meflag) + DrawEFlag3(pTo-64, sx-1, sy+1, ev, ev2, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_DEADPLR) + DrawDeadPlr(sx, sy, xp, yp, 0, ev2, FALSE); + if (bPlayer > 0) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + int nPlayer = bPlayer - 1; + if (nPlayer >= MAX_PLRS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("draw player: tried to draw illegal player %d",nPlayer); + #endif + // jcm.patch1.end.1/14/97 + PlayerStruct * pPlayer = &plr[nPlayer]; + pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; + pyp = pPlayer->_pyoff + yp; + DrawPSlabCelL( + bPlayer - 1, + sx, sy, + pxp, + pyp, + pPlayer->_pAnimData, + pPlayer->_pAnimFrame, + pPlayer->_pAnimWidth, + 0, + ev2 + ); + if (chflag && pPlayer->_peflag) { + if (pPlayer->_peflag == 2) + DrawEFlag3(pTo-(NBUFFWSL4+96), sx-2, sy+1, ev, ev2, xp-96, yp-16); + DrawEFlag3(pTo-64, sx-1, sy+1, ev, ev2, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if ((nMonster > 0) && ((bFlags & BFLAG_VISIBLE) || (plr[myplr]._pInfraFlag))) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + gnMI = nMonster - 1; + if ((DWORD)gnMI >= MAXMONSTERS) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster: tried to draw illegal monster %d",gnMI); + #endif + // jcm.patch1.end.1/14/97 + MonsterStruct * pMonster = &monster[gnMI]; + if (!(pMonster->_mFlags & MFLAG_INVISIBLE)) { + if (pMonster->MType == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Monster \"%s\": uninitialized monster",pMonster->mName); + #endif + // jcm.patch1.end.1/14/97 + pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; + pyp = pMonster->_myoff + yp; + #if RLE_DRAW + if (gnMI == cursmonst) + DrawUnitOutline( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + 0, + ev2 + ); + #else + if (gnMI == cursmonst) + OutlineSlabCel( + MOUTC, + pxp, + pyp, + pMonster->_mAnimData, + pMonster->_mAnimFrame, + pMonster->MType->mAnimWidth, + 0, + ev2 + ); + #endif + DrawMSlabCelL(sx, sy, pxp, pyp, gnMI, 0, ev2); + if (chflag && !pMonster->_meflag) + DrawEFlag3(pTo-64, sx-1, sy+1, ev, ev2, xp-64, yp); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bFlags & BFLAG_MISSILE) + DrawMissile(sx, sy, xp, yp, 0, ev2, FALSE); + if (bObject && (nLVal < lightmax)) + DrawObjCel(sx, sy, xp, yp, FALSE, 0, ev2); + if (bItem) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + do { + #endif + // jcm.patch1.end.1/14/97 + ItemStruct * pItem = &item[bItem - 1]; + if (pItem->_iPostDraw) { + app_assert(bItem <= MAXITEMS && bItem >= 0); + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + if (bItem > MAXITEMS || bItem < 0) + break; + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimData == NULL) + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal("Draw Item \"%s\" 2: NULL Cel Buffer",pItem->_iIName); + #endif + // jcm.patch1.end.1/14/97 + if (pItem->_iAnimFrame < 1 || *reinterpret_cast(pItem->_iAnimData) > MAX_FRAMES + || pItem->_iAnimFrame > *reinterpret_cast(pItem->_iAnimData)) { + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + break; + #else + app_fatal( + "Draw \"%s\" Item 2: frame %d of %d, item type==%d", + pItem->_iIName, + pItem->_iAnimFrame, + *reinterpret_cast(pItem->_iAnimData), + pItem->_itype + ); + #endif + // jcm.patch1.end.1/14/97 + } + pxp = xp - pItem->_iAnimWidth2; + if ((bItem - 1) == cursitem + || HighLightAllItems == true) + OutlineSlabCel( + IOUTC, + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + 0, + ev2 + ); + DrawSlabCelL( + pxp, + yp, + pItem->_iAnimData, + pItem->_iAnimFrame, + pItem->_iAnimWidth, + 0, + ev2 + ); + } + // jcm.patch1.start.1/14/97 + #ifdef GRACEFUL_EXIT + } while (0); + #endif + // jcm.patch1.end.1/14/97 + } + if (bSpecial) { + nTrans = TransList[bTransVal]; + TDrawSlabCelPL(pTo, pSpecialCels, bSpecial, 64, 0, ev2); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void DrawHTLX3 (int sx, int sy, int xp, int yp, int nd, int ev, int halfflag) +{ + int i; + BYTE *pTo; + int ev2; + int t; + MICROS *pmt; + WORD *mt; + + app_assert(gpBuffer); + pmt = &dMT2[CalcRot(sx,sy)]; + ev2 = (ev + 1) << 1; + if (ev2 > 8) ev2 = 8; + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + if (gnPieceNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp + 32; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &pmt->mt[0]; + if ((ev >= 0) && (gdwPNum = mt[1])) { + gbPartialTrans = PART_TRANS_RIGHT; + DrawMTileClipTop (pTo); + gbPartialTrans = PART_TRANS_NONE; + } + pTo -= NBUFFWSL5; + if ((ev >= 1) && (gdwPNum = mt[3])) + DrawMTileClipTop (pTo); + pTo -= NBUFFWSL5; + if ((ev >= 2) && (gdwPNum = mt[5])) + DrawMTileClipTop (pTo); + pTo -= NBUFFWSL5; + if ((ev >= 3) && (gdwPNum = mt[7])) + DrawMTileClipTop (pTo); + //pTo -= NBUFFWSL5; + //if ((ev >= 4) && (gdwPNum = mt[9]) && (leveltype == 4)) DrawMTileClipTop (pTo); + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawHTLXsub3 (pTo, sx, sy, ev, ev2, xp, yp, FALSE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawBlankMTile(pTo); + } + } + ++sx; + --sy; + xp += 64; + --nd; + ++pmt; + } + + for (i = 0; i < nd; ++i) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + if (gnPieceNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &pmt->mt[0]; + + gbPartialTrans = PART_TRANS_LEFT; + if (gdwPNum = mt[0]) DrawMTileClipTop (pTo); + gbPartialTrans = PART_TRANS_RIGHT; + if (gdwPNum = mt[1]) DrawMTileClipTop (pTo+32); + gbPartialTrans = PART_TRANS_NONE; + for(t = 1; t < ((MicroTileLen>>1)-1); ++t) + { + pTo -= NBUFFWSL5; + if (ev >= t) { + if (gdwPNum = mt[2*t]) DrawMTileClipTop (pTo); + if (gdwPNum = mt[2*t+1]) DrawMTileClipTop (pTo+32); + } + } + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawHTLXsub3 (pTo, sx, sy, ev, ev2, xp, yp, TRUE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawBlankMTile(pTo); + } + } + ++sx; + --sy; + xp += 64; + ++pmt; + } + + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gnPieceNum = dPiece[sx][sy]; + nLVal = dLight[sx][sy]; + if (gnPieceNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; + mt = &pmt->mt[0]; + + gbPartialTrans = PART_TRANS_LEFT; + if ((ev >= 0) && (gdwPNum = mt[0])) DrawMTileClipTop (pTo); + gbPartialTrans = PART_TRANS_NONE; + pTo -= NBUFFWSL5; + if ((ev >= 1) && (gdwPNum = mt[2])) DrawMTileClipTop (pTo); + pTo -= NBUFFWSL5; + if ((ev >= 2) && (gdwPNum = mt[4])) DrawMTileClipTop (pTo); + pTo -= NBUFFWSL5; + if ((ev >= 3) && (gdwPNum = mt[6])) DrawMTileClipTop (pTo); + //pTo -= NBUFFWSL5; + //if ((ev >= 4) && (gdwPNum = mt[8]) && (leveltype == 4)) DrawMTileClipTop (pTo); + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawHTLXsub3 (pTo, sx, sy, ev, ev2, xp, yp, FALSE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + DrawBlankMTile(pTo); + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void SVGADrawView(int StartX, int StartY) +{ + int xpos, ypos; + int i; + int width,height; + + ViewDX = 640; + ViewDY = 352; + ViewBX = 10; + ViewBY = 11; + + xpos = 64 + ScrollInfo._sxoff; + ypos = 175 + ScrollInfo._syoff; + StartX -= 10; + StartY -= 1; + width = 10; + height = 8; + + if (chrflag || questlog) { + StartX += 2; + StartY -= 2; + xpos += 288; + width = 6; + } + if (invflag || sbookflag) { + StartX += 2; + StartY -= 2; + xpos -= 32; + width = 6; + } + + switch (ScrollInfo._sdir) { + case SCRL_UR : + ++width; + case SCRL_U : + ypos -= 32; + --StartX; + --StartY; + height; + break; + case SCRL_DR : + ++height; + case SCRL_R : + ++width; + break; + case SCRL_D : + ++height; + break; + case SCRL_DL : + ++height; + case SCRL_L : + xpos -= 64; + --StartX; + ++StartY; + ++width; + break; + case SCRL_UL : + xpos -= 64; + ypos -= 32; + StartX -= 2; + ++width; + ++height; + break; +// case SCRL_NONE : + } + + app_assert(gpBuffer); + glClipY = (long)gpBuffer + nBuffWTbl[160]; + for (i = 0; i < 4; ++i) { + DrawHTLX3(StartX, StartY, xpos, ypos, width, i, 0); + ++StartY; + xpos -= 32; + ypos += 16; + DrawHTLX3(StartX, StartY, xpos, ypos, width, i, 1); + ++StartX; + xpos += 32; + ypos += 16; + } + app_assert(gpBuffer); + glClipY = (long)gpBuffer + nBuffWTbl[512]; + for (i = 0; i < height; ++i) { + DrawHTileLineX(StartX, StartY, xpos, ypos, width, 0); + ++StartY; + xpos -= 32; + ypos += 16; + DrawHTileLineX(StartX, StartY, xpos, ypos, width, 1); + ++StartX; + xpos += 32; + ypos += 16; + } + gbPartialTrans = PART_TRANS_NONE; + for (i = 0; i < 4; ++i) { + DrawHTLX2(StartX, StartY, xpos, ypos, width, i, 0); + ++StartY; + xpos -= 32; + ypos += 16; + DrawHTLX2(StartX, StartY, xpos, ypos, width, i, 1); + ++StartX; + xpos += 32; + ypos += 16; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void VGADrawView (int StartX, int StartY) +{ + int xpos, ypos; + int i; + int width,height; + long csrc, cdest, cw; + + ViewDX = 384; + ViewDY = 192; + ViewBX = 6; + ViewBY = 6; + + xpos = 64 + ScrollInfo._sxoff; + ypos = 143 + ScrollInfo._syoff; + StartX -= 6; + StartY -= 1; + width = 6; + height = 3; + + switch (ScrollInfo._sdir) { + case SCRL_UR : + ++width; + case SCRL_U : + ypos -= 32; + --StartX; + --StartY; + ++height; + break; + case SCRL_DR : + ++height; + case SCRL_R : + ++width; + break; + case SCRL_D : + ++height; + break; + case SCRL_DL : + ++height; + case SCRL_L : + xpos -= 64; + --StartX; + ++StartY; + ++width; + break; + case SCRL_UL : + xpos -= 64; + ypos -= 32; + StartX -= 2; + ++width; + ++height; +// case SCRL_NONE : + } + + app_assert(gpBuffer); + glClipY = (long)gpBuffer + nBuffWTbl[143]; + for (i = 0; i < 4; ++i) { + DrawHTLX3(StartX, StartY, xpos, ypos, width, i, 0); + ++StartY; + xpos -= 32; + ypos += 16; + DrawHTLX3(StartX, StartY, xpos, ypos, width, i, 1); + ++StartX; + xpos += 32; + ypos += 16; + } + app_assert(gpBuffer); + glClipY = (long)gpBuffer + nBuffWTbl[320]; + for (i = 0; i < height; ++i) { + DrawHTileLineX(StartX, StartY, xpos, ypos, width, 0); + ++StartY; + xpos -= 32; + ypos += 16; + DrawHTileLineX(StartX, StartY, xpos, ypos, width, 1); + ++StartX; + xpos += 32; + ypos += 16; + } + gbPartialTrans = PART_TRANS_NONE; + for (i = 0; i < 4; ++i) { + DrawHTLX2(StartX, StartY, xpos, ypos, width, i, 0); + ++StartY; + xpos -= 32; + ypos += 16; + DrawHTLX2(StartX, StartY, xpos, ypos, width, i, 1); + ++StartX; + xpos += 32; + ypos += 16; + } + + if (chrflag || questlog) { + csrc = 245168; + cdest = 392064; + cw = 160; + } else { + if (invflag || sbookflag) { + csrc = 245168; + cdest = 391744; + cw = 160; + } else { + csrc = 245088; + cdest = 391744; + cw = 320; + } + } + // Double res copy + app_assert(gpBuffer); + __asm { + mov esi,[gpBuffer] + mov edx,[cdest] + mov edi,esi + mov ecx,[csrc] + add edi,edx + add esi,ecx + mov ebx,edi + add ebx,768 + + mov edx,176 +_YLp: + mov ecx,[cw] +_XLp: + mov al,[esi] + inc esi + mov ah,al + mov [edi],ax + mov [ebx],ax + add edi,2 + add ebx,2 + dec ecx + jnz _XLp + mov eax,768 + add eax,[cw] + sub esi,eax + add eax,eax + sub ebx,eax + sub edi,eax + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawView(int StartX, int StartY) +{ + app_assert(gpBuffer); +/* __asm { + mov edi,dword ptr [gpBuffer] + add edi,122944 + + mov edx,352 + mov eax,092929292h // yellow + //xor eax,eax // black +_YLp: mov ecx,160 + rep stosd + add edi,128 + dec edx + jnz _YLp + }*/ + + if (svgamode) SVGADrawView (StartX, StartY); + else VGADrawView (StartX, StartY); + if (automapflag) DrawAutomap(); + + if (invflag) DrawInv(); + else if (sbookflag) DrawSpellBook(); + + DrawDurIcon(); + + if (chrflag) DrawChr(); + else if (questlog) DrawQuestLog(); + else if ((plr[myplr]._pStatPts != 0) && (!spselflag)) DrawLevelUpIcon(); + + if (uitemflag) DrawUniqueInfo(); + if (qtextflag) DrawQText(); + if (spselflag) DrawSpellList(); + if (dropGoldFlag) DrawGoldBox(dropGoldValue); + if (helpflag) DrawHelp(); + if (msgflag) DrawDiabloMsg(); + if (deathflag) RedBack(); + else if (PauseMode) DrawPause(); + + plrmsg_draw(); + + gmenu_draw(); + + DrawMapOfDoom(); + + DrawInfoBox(); + DrawHealthTop(); + DrawManaTop(); + + /* TEMP! ONLY ENABLE FOR TESTING + if (automapflag) { + if (leveltype == 1) + DrawDungMiniMap(22); + if (leveltype == 2) + DrawDungMiniMap(12); + if (leveltype == 3) + DrawDungMiniMap(8); + if (leveltype == 4) + DrawDungMiniMap(30); + } + TEMP! ONLY ENABLE FOR TESTING */ +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ClrDraw() +{ + // Clear drawing area with solid color to detect transparency problems + lock_buf(3); + app_assert(gpBuffer); + __asm { + mov edi,dword ptr [gpBuffer] + add edi,122944 + + mov edx,480 + xor eax,eax // black +_YLp: mov ecx,160 + rep stosd + add edi,128 + dec edx + jnz _YLp + } + unlock_buf(3); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckForScroll () +{ + if (curs >= ICSTART) return; + + BOOL bScrollUpdate = FALSE; + if (MouseX < 20) { + if ((ViewY < (dmaxy - 1)) && (ViewX > dminx)) { + ++ViewY; + --ViewX; + bScrollUpdate = TRUE; + } else { + if (ViewY < (dmaxy - 1)) { + ++ViewY; + bScrollUpdate = TRUE; + } + if (ViewX > dminx) { + --ViewX; + bScrollUpdate = TRUE; + } + } + } + + if (MouseX > 620) { + if ((ViewX < (dmaxx - 1)) && (ViewY > dminy)) { + --ViewY; + ++ViewX; + bScrollUpdate = TRUE; + } else { + if (ViewX < (dmaxx - 1)) { + ++ViewX; + bScrollUpdate = TRUE; + } + if (ViewY > dminy) { + ViewY--; + bScrollUpdate = TRUE; + } + } + } + + if (MouseY < 20) { + if ((ViewY > dminy) && (ViewX > dminx)) { + --ViewX; + --ViewY; + bScrollUpdate = TRUE; + } else { + if (ViewY > dminy) { + --ViewY; + bScrollUpdate = TRUE; + } + if (ViewX > dminx) { + --ViewX; + bScrollUpdate = TRUE; + } + } + } + + if (MouseY > 460) { + if ((ViewY < (dmaxy - 1)) && (ViewX < (dmaxx - 1))) { + ++ViewX; + ++ViewY; + bScrollUpdate = TRUE; + } else { + if (ViewY < (dmaxy - 1)) { + ++ViewY; + bScrollUpdate = TRUE; + } + if (ViewX < (dmaxx - 1)) { + ++ViewX; + bScrollUpdate = TRUE; + } + } + } + + if (bScrollUpdate) + ScrollInfo._sdir = SCRL_NONE; +} + + +//******************************************************************* +//******************************************************************* +#ifndef NDEBUG +void toggle_frame_counter() { + sgfFrameCounterEnabled = !sgfFrameCounterEnabled; + sgnLastFrame = GetTickCount(); +} +#endif + + +//******************************************************************* +//******************************************************************* +#ifndef NDEBUG +static void draw_frame_rate() { + if (!sgfFrameCounterEnabled) + return; + // don't write stuff if we're not the active application + if (! bActive) + return; + + static int snFrameCount = 0; + static int nFrameRate = 0; + int nTimeSpent; + char szFrameRate[10]; + DWORD nThisFrame; + HDC hDC; + + ++snFrameCount; + nThisFrame = GetTickCount(); + //give a 1 second average frame rate + if (nThisFrame - sgnLastFrame >= 1000) { + nTimeSpent = nThisFrame - sgnLastFrame; + sgnLastFrame = nThisFrame; + nFrameRate = (snFrameCount*1000)/nTimeSpent; + snFrameCount = 0; + } + + if (nFrameRate > 99) nFrameRate = 99; + wsprintf(szFrameRate, "%2d", nFrameRate); + HRESULT ddr = lpDDSPrimary->GetDC(&hDC); + if (ddr != DD_OK) return; + TextOut(hDC,0,400,szFrameRate,strlen(szFrameRate)); + lpDDSPrimary->ReleaseDC(hDC); +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define BUFFER_STARTX 64 +#define BUFFER_STARTY 160 +static DDSURFACEDESC sgDDSD; +extern LPDIRECTDRAWSURFACE lpDDSBackBuf; +static void DDBlit(DWORD dwX,DWORD dwY,DWORD dwWdt,DWORD dwHgt) { + + app_assert(! (dwX & 3)); + app_assert(! (dwWdt & 3)); + + // if we have a back buffer, it is because we cannot lock the + // primary surface. Use BltFast to avoid locking problem + if (lpDDSBackBuf) { + HRESULT ddrval; + RECT r; + r.left = dwX + BUFFER_STARTX; + r.top = dwY + BUFFER_STARTY; + r.right = r.left + dwWdt - 1; + r.bottom = r.top + dwHgt - 1; + + // make sure nobody is holding a lock on back surface + // because we wouldn't be able to BltFast + app_assert(! gpBuffer); + + DWORD dwStartTime = GetTickCount(); + while (1) { + // perform draw + #if LOCK_WAIT + ddrval = lpDDSPrimary->BltFast(dwX,dwY,lpDDSBackBuf,&r,DDBLTFAST_WAIT); + #else + ddrval = lpDDSPrimary->BltFast(dwX,dwY,lpDDSBackBuf,&r,0); + #endif + if (ddrval == DD_OK) break; + + // fatal if we've waited a long time for surface + if (dwStartTime - GetTickCount() > 5*1000) break; + + #if LOCK_SLEEP + Sleep(LOCK_SLEEP); + #endif + + // hey, we just checked a second ago, and we still + // had our surface -- try to get it next time + if (ddrval == DDERR_SURFACELOST) return; + + // handle errors related to another thread locking surface + if (ddrval == DDERR_WASSTILLDRAWING) continue; + if (ddrval == DDERR_SURFACEBUSY) continue; + + // other errors -- fatal + break; + } + + if (ddrval == DDERR_SURFACELOST) return; + if (ddrval == DDERR_WASSTILLDRAWING) return; + if (ddrval == DDERR_SURFACEBUSY) return; + ddraw_assert(ddrval); + return; + } + + LONG lSrcOff = (dwY + BUFFER_STARTY) * BUFFERX + dwX + BUFFER_STARTX; + LONG lDstOff = dwY * sgDDSD.lPitch + dwX; + LONG lSrcMod = BUFFERX - dwWdt; + LONG lDstMod = sgDDSD.lPitch - dwWdt; + dwWdt >>= 2; + lock_buf(6); + app_assert(gpBuffer); + __asm { + mov esi, [gpBuffer] + mov edi, [sgDDSD.lpSurface] + add esi, [lSrcOff] + add edi, [lDstOff] + mov eax, [lSrcMod] + mov ebx, [lDstMod] + mov edx, [dwHgt] + lpdword: + mov ecx, [dwWdt] + rep movsd + add esi, eax + add edi, ebx + dec edx + jnz lpdword + } + unlock_buf(6); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DirectDrawBlt( + long ysize, + BOOL tbox, + BOOL hp, + BOOL mana, + BOOL spdbar, + BOOL btns +) { + HRESULT ddrval; + + // don't redraw if we aren't the active application + if (! bActive) return; + + // don't redraw if we don't have a direct draw buffer + if (! lpDDSPrimary) return; + + // make sure primary surface is still in video memory + if (lpDDSPrimary->IsLost() == DDERR_SURFACELOST) { + ddrval = lpDDSPrimary->Restore(); + if (ddrval != DD_OK) return; + void ResetPal(); + ResetPal(); + + // force redraw of everything + ysize = TOTALY; + } + + // lock the surface if we have to manually blit + if (! lpDDSBackBuf) { + BOOL bReinit = TRUE; + DWORD dwStartTime = GetTickCount(); + while (1) { + // try to lock the surface + sgDDSD.dwSize = sizeof(sgDDSD); + #if LOCK_WAIT + ddrval = lpDDSPrimary->Lock(NULL,&sgDDSD,DDLOCK_WAIT | DDLOCK_WRITEONLY,NULL); + #else + ddrval = lpDDSPrimary->Lock(NULL,&sgDDSD,DDLOCK_WRITEONLY,NULL); + #endif + if (ddrval == DD_OK) break; + + // fatal if we've waited a long time for surface + if (dwStartTime - GetTickCount() > 5*1000) break; + + #if LOCK_SLEEP + Sleep(LOCK_SLEEP); + #endif + + // hey, we just checked a second ago, and we still + // had our surface -- try to get it next time + if (ddrval == DDERR_SURFACELOST) return; + + // handle errors related to another thread locking surface + if (ddrval == DDERR_WASSTILLDRAWING) continue; + if (ddrval == DDERR_SURFACEBUSY) continue; + + // this is to fix a bug when user switches to a different + // screen mode in another app. In windows NT, a DOS app + // switching to Mode 0x13 will cause a DDERR_GENERIC in + // this app when it is restored + if (bReinit && ddrval == DDERR_GENERIC) { + bReinit = FALSE; + void ddraw_reinit(); + ddraw_reinit(); + ysize = TOTALY; + dwStartTime = GetTickCount(); + continue; + } + + // other errors -- fatal + break; + } + + // handle errors related to another thread locking surface + if (ddrval == DDERR_SURFACELOST) return; + if (ddrval == DDERR_WASSTILLDRAWING) return; + if (ddrval == DDERR_SURFACEBUSY) return; + + ddraw_assert(ddrval); + } + + app_assert(ysize >= 0 && ysize <= 480); + + if (ysize > 0) { + // blit main game area + DDBlit(0,0,160*4,ysize); // X is divisible by 4 + } + + if (ysize < TOTALY) { + if (spdbar) { + // speed bar + // DDBlit(205,357,58*4,28); + DDBlit(204,357,58*4,28); // X is divisible by 4 + } + + if (tbox) { + // text box + // DDBlit(177,398,72*4,60); + DDBlit(176,398,72*4,60); // X is divisible by 4 + } + + if (mana) { + // mana bar + // DDBlit(461,352,22*4,72); + DDBlit(460,352,22*4,72); // X is divisible by 4 + + // spell icon + // DDBlit(565,416,14*4,56); + DDBlit(564,416,14*4,56); // X is divisible by 4 + } + + if (hp) { + // hitpoint bar + DDBlit(96,352,22*4,72); // X is divisible by 4 + } + + if (btns) { + // buttons on left side + // DDBlit(11,357,18*4,119); + DDBlit(8,357,18*4,119); // X is divisible by 4 + + // buttons on right side + // DDBlit(558,357,18*4,42); + DDBlit(556,357,18*4,48); // X is divisible by 4 + + if (gbMaxPlayers > 1) { + // "chat" button + // DDBlit(87,443,9*4,32); + DDBlit(84,443,9*4,32); // X is divisible by 4 + + // "friendly" button + // DDBlit(527,443,9*4,32); + DDBlit(524,443,9*4,32); // X is divisible by 4 + } + } + + if (sgdwOldWdt) { + DDBlit(sgdwOldX,sgdwOldY,sgdwOldWdt,sgdwOldHgt); + } + if (sgdwCursWdt) { + DDBlit(sgdwCursX,sgdwCursY,sgdwCursWdt,sgdwCursHgt); + } + + } + + if (! lpDDSBackBuf) { + // in NT, it is possible for us to lose the surface + // even when it is locked! + ddrval = lpDDSPrimary->Unlock(NULL); + if (ddrval != DDERR_SURFACELOST) + ddraw_assert(ddrval); + } + + #ifndef NDEBUG + draw_frame_rate(); + #endif +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void FullBlit(BOOL bArrow) { + int y; + if (force_redraw == FULLDRAW) { + force_redraw = NODRAW; + y = TOTALY; + } + else { + y = 0; + } + + if (bArrow) { + lock_buf(0); + savecrsr_show(); + unlock_buf(0); + } + + DirectDrawBlt(y, FALSE, FALSE, FALSE, FALSE, FALSE); + + if (bArrow) { + lock_buf(0); + savecrsr_hide(); + unlock_buf(0); + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +extern BOOL gbRunGame; + +void DrawAndBlit(void) { + BOOL tBox; + BOOL ctrlPan; + long ysize; + + if (! gbRunGame) return; + + if (force_redraw == FULLDRAW) { + drawhpflag = TRUE; + drawmanaflag = TRUE; + drawbtnflag = TRUE; + drawsbarflag = TRUE; + tBox = FALSE; + ctrlPan = TRUE; + ysize = TOTALY; + } + else if (force_redraw == VIEWDRAW) { + tBox = TRUE; + ctrlPan = FALSE; + ysize = GAMEY; + } + else { + return; + } + force_redraw = NODRAW; + + lock_buf(0); + if (leveltype) DrawView(ViewX, ViewY); + else T_DrawView(ViewX, ViewY); + if (ctrlPan) DrawCtrlPan(); + if (drawhpflag) DrawHealthBar(); + if (drawmanaflag) DrawManaBar(); + if (drawbtnflag) DrawButtons(); + if (drawsbarflag) DrawSpdBar(); + if (talkflag) { + DrawTalkBox(); + ysize = TOTALY; + } + savecrsr_show(); + unlock_buf(0); + + DirectDrawBlt(ysize, tBox, drawhpflag, drawmanaflag, drawsbarflag, drawbtnflag); + + lock_buf(0); + savecrsr_hide(); + unlock_buf(0); + + drawhpflag = FALSE; + drawmanaflag = FALSE; + drawbtnflag = FALSE; + drawsbarflag = FALSE; +} diff --git a/src/SCROLLRT.H b/src/SCROLLRT.H new file mode 100644 index 0000000..0097d03 --- /dev/null +++ b/src/SCROLLRT.H @@ -0,0 +1,45 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/SCROLLRT.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define NBUFFWSL4 12288 +#define NBUFFWSL5 24576 + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern "C" { + extern long nLVal; + extern DWORD gdwPNum; + extern BOOL nTrans; +} +extern long nBuffWTbl[1024]; +extern bool HighLightAllItems; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +extern "C" void _fastcall DrawBlankMTile(BYTE *); + +void DrawAndBlit (void); + +void FullBlit(BOOL); +void ClrDraw(); + +void CheckForScroll(); + +void DrawMissile(int, int, int, int, int, int, BOOL); +void CDrawMissile(int, int, int, int, int, int, BOOL); +void DrawDeadPlr(int sx, int sy, int xp, int yp, int ostart, int oend, BOOL clip); diff --git a/src/SETMAPS.CPP b/src/SETMAPS.CPP new file mode 100644 index 0000000..9aa10d4 --- /dev/null +++ b/src/SETMAPS.CPP @@ -0,0 +1,255 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Set Maps file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/SETMAPS.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "setmaps.h" +#include "gendung.h" +#include "palette.h" +#include "engine.h" + +#include "objects.h" +#include "quests.h" + +#include "drlg_l1.h" +#include "drlg_l2.h" +#include "drlg_l3.h" +#include "drlg_l4.h" + +#include "trigs.h" + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +static byte SkelKingTrans1[] = { + 19, 47, 26, 55, + 26, 49, 30, 53 }; + //18, 49, 18, 49 }; + +static byte SkelKingTrans2[] = { + 33, 19, 47, 29, + 37, 29, 43, 39 }; + +static byte SkelKingTrans3[] = { + 27, 53, 35, 61, + 27, 35, 34, 42, + 45, 35, 53, 43, + 45, 53, 53, 61, + 31, 39, 49, 57 }; + +static byte SkelKingTrans4[] = { + 49, 45, 58, 51, + 57, 31, 62, 37, + 63, 31, 69, 40, + 59, 41, 73, 55, + 63, 55, 69, 65, + 73, 45, 78, 51, + 79, 43, 89, 53 }; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static byte SkelChamTrans1[] = { + 43, 19, 50, 26, + 51, 19, 59, 26, + 35, 27, 42, 34, + 43, 27, 49, 34, + 50, 27, 59, 34}; + +static byte SkelChamTrans2[] = { + 19, 31, 34, 47, + 34, 35, 42, 42}; + +static byte SkelChamTrans3[] = { + 43, 35, 50, 42, + 51, 35, 62, 42, + 63, 31, 66, 46, + 67, 31, 78, 34, + 67, 35, 78, 42, + 67, 43, 78, 46, + 35, 43, 42, 51, + 43, 43, 49, 51, + 50, 43, 59, 51}; + +char *SetLevelName[] = { + "", + "Skeleton King's Lair", + "Bone Chamber", + "Maze", + "Poisoned Water Supply", + "Archbishop Lazarus' Lair", +}; + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int ObjIndex(int x, int y) +{ + int i, oi; + + for (i = 0; i < numobjects; i++) { + oi = objectactive[i]; + if ((object[oi]._ox == x) && (object[oi]._oy == y)) + return(oi); + } + app_fatal("ObjIndex: Active object not found at (%d,%d)",x,y); + return -1; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddSKingObjs() +{ + // Levers + SetObjMapRange(ObjIndex(64,34), 20, 7, 23, 10, 1); + SetObjMapRange(ObjIndex(64,59), 20, 14, 21, 16, 2); + + // Crux + SetObjMapRange(ObjIndex(27,37), 8, 1, 15, 11, 3); + SetObjMapRange(ObjIndex(46,35), 8, 1, 15, 11, 3); + SetObjMapRange(ObjIndex(49,53), 8, 1, 15, 11, 3); + SetObjMapRange(ObjIndex(27,53), 8, 1, 15, 11, 3); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddSChamObjs() +{ + // Levers + SetObjMapRange(ObjIndex(37,30), 17, 0, 21, 5, 1); + SetObjMapRange(ObjIndex(37,46), 13, 0, 16, 5, 2); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void AddVileObjs() +{ + // Books + SetObjMapRange(ObjIndex(26,45), 1, 1, 9, 10, 1); + SetObjMapRange(ObjIndex(45,46), 11, 1, 20, 10, 2); + + //Magic Circles + SetObjMapRange(ObjIndex(35,36), 7, 11, 13, 18, 3); + } + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DRLG_SetMapTrans(char sFileName[]) +{ + int i,j,rw,rh; + byte *pLevelMap,*lm; + long mapoff; + + //*** This data file seems to be stored as word values, but + //*** it is being accessed and stored in dTransVal as bytes. + //*** Is this correct? If so, the data is double sized. -Collin + + // Load map + pLevelMap = LoadFileInMemSig(sFileName,NULL,'LMPt'); + lm = pLevelMap; + + rw = *lm; + lm += 2; + rh = *lm; + // Skip map + height word + mapoff = ((rw * rh) << 1) + 2; + // Convert to index mini tile level instead of mega + rw = rw << 1; + rh = rh << 1; + // Skip treasure, monster, trap maps + mapoff += (((rw * rh) << 1) * 3); + lm += mapoff; + for (j = 0; j < rh; j++) { + for (i = 0; i < rw; i++) { + dTransVal[i+DIRTEDGED2][j+DIRTEDGED2] = *lm; + lm += 2; + } + } + + // Free map + DiabloFreePtr(pLevelMap); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +void LoadSetMap() +{ + switch (setlvlnum) { + case SL_SKELKING: + if (quests[Q_SKELKING]._qactive == QUEST_NOTACTIVE) { + quests[Q_SKELKING]._qactive = QUEST_NOTDONE; + quests[Q_SKELKING]._qvar1 = 1; + } + LoadPreL1Dungeon("Levels\\L1Data\\SklKng1.DUN", 83, 45); + LoadL1Dungeon("Levels\\L1Data\\SklKng2.DUN", 83, 45); + LoadPalette ("Levels\\L1Data\\L1_2.pal"); + DRLG_AreaTrans(2, &SkelKingTrans1[0]); + DRLG_ListTrans(2, &SkelKingTrans2[0]); + DRLG_AreaTrans(5, &SkelKingTrans3[0]); + DRLG_ListTrans(7, &SkelKingTrans4[0]); + AddL1Objs(0, 0, DMAXX, DMAXY); + AddSKingObjs(); + InitSKingTriggers(); + break; + + case SL_BONECHAMB: + LoadPreL2Dungeon("Levels\\L2Data\\Bonecha2.DUN", 69, 39); + LoadL2Dungeon("Levels\\L2Data\\Bonecha1.DUN", 69, 39); + LoadPalette ("Levels\\L2Data\\L2_2.pal"); + DRLG_ListTrans(5, &SkelChamTrans1[0]); + DRLG_AreaTrans(2, &SkelChamTrans2[0]); + DRLG_ListTrans(9, &SkelChamTrans3[0]); + AddL2Objs(0, 0, DMAXX, DMAXY); + AddSChamObjs(); + InitSChambTriggers(); + break; + + case SL_MAZE: + LoadPreL1Dungeon("Levels\\L1Data\\Lv1MazeA.DUN", 20, 50); + LoadL1Dungeon("Levels\\L1Data\\Lv1MazeB.DUN", 20, 50); + LoadPalette ("Levels\\L1Data\\L1_5.pal"); + AddL1Objs(0, 0, DMAXX, DMAXY); + DRLG_SetMapTrans("Levels\\L1Data\\Lv1MazeA.DUN"); + break; + + case SL_POISONWATER: + if (quests[Q_PWATER]._qactive == QUEST_NOTACTIVE) + quests[Q_PWATER]._qactive = QUEST_NOTDONE; + LoadPreL3Dungeon("Levels\\L3Data\\Foulwatr.DUN", 19, 50); + LoadL3Dungeon("Levels\\L3Data\\Foulwatr.DUN", 20, 50); + LoadPalette ("Levels\\L3Data\\L3pfoul.pal"); + InitPWaterTriggers(); + break; + + case SL_VILEBETRAYER: + if (quests[Q_BETRAYER]._qactive == QUEST_DONE) + quests[Q_BETRAYER]._qvar2 = QS_VBRP4; + else if (quests[Q_BETRAYER]._qactive == QUEST_NOTDONE) + quests[Q_BETRAYER]._qvar2 = QS_VBRP3; + LoadPreL1Dungeon("Levels\\L1Data\\Vile1.DUN", 35, 36); + LoadL1Dungeon("Levels\\L1Data\\Vile2.DUN", 35, 36); + LoadPalette ("Levels\\L1Data\\L1_2.pal"); + AddL1Objs(0, 0, DMAXX, DMAXY); + AddVileObjs(); + DRLG_SetMapTrans("Levels\\L1Data\\Vile1.DUN"); + InitNoTriggers(); + break; + } +} +#endif diff --git a/src/SETMAPS.H b/src/SETMAPS.H new file mode 100644 index 0000000..00b6636 --- /dev/null +++ b/src/SETMAPS.H @@ -0,0 +1,35 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/SETMAPS.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ +enum _setlevels { + SL_SKELKING=1, + SL_BONECHAMB, + SL_MAZE, + SL_POISONWATER, + SL_VILEBETRAYER, +}; + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern char *SetLevelName[]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void LoadSetMap(); diff --git a/src/SHA.CPP b/src/SHA.CPP new file mode 100644 index 0000000..8516800 --- /dev/null +++ b/src/SHA.CPP @@ -0,0 +1,189 @@ +/**************************************************************************** +* +* SHA.CPP +* Secure Hash Algorithm +* +* Implementation copyright (C) 1995, Michael O'Brien. All rights reserved. +* +* key size - N/A +* input block size - 512 bits +* output block size - 160 bits +* +***/ + + +#include "diablo.h" +#pragma hdrstop + + +//****************************************************************** +//****************************************************************** +#define SHA_BLOCKSIZE 64 +#define SHA_DIGESTSIZE 20 + +#define F1(x,y,z) ((x & y) | (~x & z)) +#define F2(x,y,z) (x ^ y ^ z) +#define F3(x,y,z) ((x & y) | (x & z) | (y & z)) +#define F4(x,y,z) (x ^ y ^ z) + +#define K1 0x5A827999 +#define K2 0x6ED9EBA1 +#define K3 0x8f1BBCDC +#define K4 0xCA62C1D6 + +#define H0INIT 0x67452301 +#define H1INIT 0xEFCDAB89 +#define H2INIT 0x98BADCFE +#define H3INIT 0x10325476 +#define H4INIT 0xC3D2E1F0 + +#define S(n,x) ((x << n) | (x >> (32 - n))) + +#define EXPAND(c) w[c] = w[c-3] ^ w[c-8] ^ w[c-14] ^ w[c-16] + +#define SUBROUND1(num) temp = S(5,a) + F1(b,c,d) + e + w[num] + K1 +#define SUBROUND2(num) temp = S(5,a) + F2(b,c,d) + e + w[num] + K2 +#define SUBROUND3(num) temp = S(5,a) + F3(b,c,d) + e + w[num] + K3 +#define SUBROUND4(num) temp = S(5,a) + F4(b,c,d) + e + w[num] + K4 + +typedef struct _shainfo { + int digest[5]; + int countlo; + int counthi; + int data[16]; +} shainfo, *shainfoptr; + + +//****************************************************************** +//****************************************************************** +static void InitializeHash (shainfoptr infoptr) { + infoptr->digest[0] = H0INIT; + infoptr->digest[1] = H1INIT; + infoptr->digest[2] = H2INIT; + infoptr->digest[3] = H3INIT; + infoptr->digest[4] = H4INIT; + infoptr->countlo = 0; + infoptr->counthi = 0; +} + + +//****************************************************************** +//****************************************************************** +static void TransformHash (shainfoptr infoptr) { + int w[80]; + int loop; + for (loop = 0; loop < 16; loop++) + w[loop] = infoptr->data[loop]; + for (loop = 16; loop < 80; loop++) + EXPAND(loop); + + int a = infoptr->digest[0]; + int b = infoptr->digest[1]; + int c = infoptr->digest[2]; + int d = infoptr->digest[3]; + int e = infoptr->digest[4]; + + int temp; + for (loop = 0; loop < 20; loop++) { + SUBROUND1(loop); + e = d; + d = c; + c = S(30,b); + b = a; + a = temp; + } + for (loop = 20; loop < 40; loop++) { + SUBROUND2(loop); + e = d; + d = c; + c = S(30,b); + b = a; + a = temp; + } + for (loop = 40; loop < 60; loop++) { + SUBROUND3(loop); + e = d; + d = c; + c = S(30,b); + b = a; + a = temp; + } + for (loop = 60; loop < 80; loop++) { + SUBROUND4(loop); + e = d; + d = c; + c = S(30,b); + b = a; + a = temp; + } + + infoptr->digest[0] += a; + infoptr->digest[1] += b; + infoptr->digest[2] += c; + infoptr->digest[3] += d; + infoptr->digest[4] += e; + + for (loop = 0; loop < 80; loop++) + w[loop] = 0; + a = b = c = d = e = 0; +} + + +//****************************************************************** +//****************************************************************** +static void UpdateHash (shainfoptr infoptr, const BYTE *buffer, int bytes) { + if ((infoptr->countlo + (bytes << 3)) < infoptr->countlo) + infoptr->counthi++; + infoptr->countlo += bytes << 3; + infoptr->counthi += bytes >> 29; + + while (bytes >= SHA_BLOCKSIZE) { + CopyMemory(infoptr->data,buffer,SHA_BLOCKSIZE); + TransformHash(infoptr); + buffer += SHA_BLOCKSIZE; + bytes -= SHA_BLOCKSIZE; + } +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +static shainfo currinfo[3]; + + +//****************************************************************** +//****************************************************************** +void ShaDestroy () { + ZeroMemory(&currinfo,3*sizeof(shainfo)); +} + + +//****************************************************************** +//****************************************************************** +void ShaGetLastHash (int streamnum, void *outptr) { + if (outptr) { + DWORD *outptr32 = (DWORD *)outptr; + int loop = 0; + while (loop < 5) + *(outptr32++) = currinfo[streamnum].digest[loop++]; + } +} + + +//****************************************************************** +//****************************************************************** +void ShaHash (int streamnum, const void *inptr, void *outptr) { + UpdateHash(&currinfo[streamnum],(const BYTE *)inptr,SHA_BLOCKSIZE); + if (outptr) + ShaGetLastHash(streamnum,outptr); +} + + +//****************************************************************** +//****************************************************************** +void ShaInitialize (int streamnum) { + InitializeHash(&currinfo[streamnum]); +} diff --git a/src/SOUND.CPP b/src/SOUND.CPP new file mode 100644 index 0000000..6ada0c1 --- /dev/null +++ b/src/SOUND.CPP @@ -0,0 +1,559 @@ +//****************************************************************** +// sound.cpp +// created 10.18.96 +// written by Patrick Wyatt +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "engine.h" +#include "resource.h" + + +//****************************************************************** +// debugging +//****************************************************************** +#define ALLOW_DUP_SOUNDS 1 // 1 in final + + +//****************************************************************** +// extern +//****************************************************************** +BOOL wave_read_header(HSFILE hsFile,WAVEFORMATEX * pwfx); +LPBYTE wave_load_file(HSFILE hsFile,WAVEFORMATEX * pwfx,CKINFO * pWaveInfo); +void wave_free_file(LPBYTE lpWave); +void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine); + + +//****************************************************************** +// public +//****************************************************************** +BYTE gbSndInited = FALSE; +BYTE gbMusicOn = TRUE; +BYTE gbSoundOn = TRUE; +BYTE gbDupSounds = TRUE; + + +//****************************************************************** +// private +//****************************************************************** +static LONG sglMusicVolume = VOLUME_MAX; +static LONG sglSoundVolume = VOLUME_MAX; +static int sgnMusicTrack = NUM_MUSIC; + +static HINSTANCE sghDSlib = NULL; +static LPDIRECTSOUND sglpDS; +static HSFILE sghMusic = NULL; +static const char * sgszMusicTracks[NUM_MUSIC] = { +#if IS_VERSION(SHAREWARE) + "Music\\sTowne.wav", + "Music\\sLvla.wav", + "Music\\sLvla.wav", + "Music\\sLvla.wav", + "Music\\sLvla.wav", + "Music\\sLvla.wav", + "Music\\sLvla.wav", + "Music\\sintro.wav", +#else + "Music\\DTowne.wav", + "Music\\DLvlA.wav", + "Music\\DLvlB.wav", + "Music\\DLvlC.wav", + "Music\\DLvlD.wav", + "Music\\DLvlE.wav", + "Music\\DLvlF.wav", + "Music\\Dintro.wav", +#endif +}; + +static const char sgszSoundVol[] = "Sound Volume"; +static const char sgszMusicVol[] = "Music Volume"; +extern char gszProgKey[]; + + +#if ALLOW_DUP_SOUNDS +#define MAX_DUP_DSB 8 +#define S1 0xf00ff00f +#define S2 0xe11ee11e +static int signpost1 = S1; +static LPDIRECTSOUNDBUFFER sgDupDSB[MAX_DUP_DSB]; +static int signpost2 = S2; +#endif + +// do not play the same sound effect more frequently than this value +#define MIN_REPLAY_THRESHOLD 80 // milliseconds + +//****************************************************************** +//****************************************************************** +void snd_update(BOOL bStopAll) { + +#if ALLOW_DUP_SOUNDS + for (DWORD d = 0; d < MAX_DUP_DSB; d++) { + if (! sgDupDSB[d]) continue; + if (! bStopAll) { + DWORD dwStatus; + HRESULT hr = sgDupDSB[d]->GetStatus(&dwStatus); + if (hr == DS_OK && dwStatus == DSBSTATUS_PLAYING) continue; + } + + sgDupDSB[d]->Stop(); + sgDupDSB[d]->Release(); + sgDupDSB[d] = NULL; + } +#endif +} + + +//****************************************************************** +//****************************************************************** +#if ALLOW_DUP_SOUNDS +static LPDIRECTSOUNDBUFFER snd_dup_snd(LPDIRECTSOUNDBUFFER pDSB) { + // did user disable duplicate sounds? + if (! gbDupSounds) return NULL; + + for (DWORD d = 0; d < MAX_DUP_DSB; d++) { + if (sgDupDSB[d]) continue; + if (DS_OK != sglpDS->DuplicateSoundBuffer(pDSB,&sgDupDSB[d])) + return NULL; + return sgDupDSB[d]; + } + + return NULL; +} +#endif + + +//****************************************************************** +//****************************************************************** +static void snd_get_volume(const char * pszKey,LONG * plVolume) { + DWORD dwTemp = (DWORD) *plVolume; + if (! SRegLoadValue(gszProgKey,pszKey,0,&dwTemp)) + dwTemp = VOLUME_MAX; + *plVolume = (LONG) dwTemp; + + if (*plVolume < VOLUME_MIN) + *plVolume = VOLUME_MIN; + else if (*plVolume > VOLUME_MAX) + *plVolume = VOLUME_MAX; + *plVolume -= *plVolume % VOLUME_STEP; +} + + +//****************************************************************** +//****************************************************************** +static void snd_set_volume(const char * pszKey,LONG lVolume) { + SRegSaveValue(gszProgKey,pszKey,0,lVolume); +} + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start.1/13/97 +static BOOL snd_restore_snd(TSnd * pSnd,LPDIRECTSOUNDBUFFER pDSB) { + app_assert(pSnd); + app_assert(pDSB); + + // restore sound memory + if (DS_OK != pDSB->Restore()) + return FALSE; + + // open file containing sound only if it isn't already open + HSFILE hsFile; + BOOL bResult = FALSE; + patSFileOpenFile(pSnd->pszName,&hsFile); + patSFileSetFilePointer(hsFile,pSnd->waveInfo.dwOffset,NULL,FILE_BEGIN); + + // lock sound buffer + BYTE * pbData; + BYTE * pbData2; + DWORD dwLen; + DWORD dwLen2; + HRESULT hr = pDSB->Lock(0,pSnd->waveInfo.dwSize,&pbData,&dwLen,&pbData2,&dwLen2,0); + // dsound_assert(hr); + if (DS_OK != hr) goto err; + + patSFileReadFile(hsFile,pbData,dwLen); + + // unlock sound buffer + hr = pDSB->Unlock(pbData,dwLen,pbData2,dwLen2); + // dsound_assert(hr); + if (DS_OK != hr) goto err; + + bResult = TRUE; +err: + patSFileCloseFile(hsFile); + return bResult; +} +// pjw.patch1.end.1/13/97 + + +//****************************************************************** +//****************************************************************** +void snd_stop_snd(TSnd * pSnd) { + if (! pSnd) return; + if (pSnd->pDSB == NULL) return; + pSnd->pDSB->Stop(); +} + + +//****************************************************************** +//****************************************************************** +BOOL snd_playing(TSnd * pSnd) { + if (! pSnd) return FALSE; + if (pSnd->pDSB == NULL) return FALSE; + + // get new status + DWORD dwStatus; + HRESULT hr = pSnd->pDSB->GetStatus(&dwStatus); + // pjw.patch1.start.1/13/97 + // dsound_assert(hr); + if (DS_OK != hr) return FALSE; + // pjw.patch1.end.1/13/97 + + // still playing? + return (dwStatus == DSBSTATUS_PLAYING); +} + + +//****************************************************************** +//****************************************************************** +void snd_play_snd(TSnd * pSnd,LONG lVolume,LONG lPan) { + HRESULT hr; + LPDIRECTSOUNDBUFFER pDSB; + + if (! pSnd) return; + if (! gbSoundOn) return; + if (NULL == (pDSB = pSnd->pDSB)) + return; + + // don't allow sounds to be replayed too frequently + DWORD dwCurrTime = GetTickCount(); + if (dwCurrTime - pSnd->dwLastPlayTime < MIN_REPLAY_THRESHOLD) { + dwCurrTime = GetTickCount(); + return; + } + + // if the sound is already playing, duplicate the sound + if (snd_playing(pSnd)) { + #if ALLOW_DUP_SOUNDS + if (NULL == (pDSB = snd_dup_snd(pSnd->pDSB))) return; + #else + return; + #endif + } + + // set parameters + lVolume += sglSoundVolume; + if (lVolume < VOLUME_MIN) lVolume = VOLUME_MIN; + else if (lVolume > VOLUME_MAX) lVolume = VOLUME_MAX; + + // pjw.patch1.start.1/13/97 + hr = pDSB->SetVolume(lVolume); + // dsound_assert(hr); + hr = pDSB->SetPan(lPan); + // dsound_assert(hr); + // pjw.patch1.end.1/13/97 + + if (DSERR_BUFFERLOST != (hr = pDSB->Play(0,0,0))) + dsound_assert(hr); + else if (snd_restore_snd(pSnd,pDSB)) + pDSB->Play(0,0,0); + + pSnd->dwLastPlayTime = dwCurrTime; +} + + +//****************************************************************** +//****************************************************************** +static void snd_alloc_buffer(TSnd * pSnd) { + app_assert(sglpDS); + + // set up the direct sound buffer. + DSBUFFERDESC dsbd; + ZeroMemory(&dsbd,sizeof(dsbd)); + dsbd.dwSize = sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME; + dsbd.dwBufferBytes = pSnd->waveInfo.dwSize; + dsbd.lpwfxFormat = &pSnd->wfx; + HRESULT hr = sglpDS->CreateSoundBuffer(&dsbd,&pSnd->pDSB,NULL); + dsound_assert(hr); +} + + +//****************************************************************** +//****************************************************************** +TSnd * snd_load_snd(const char * pszName) { + if (! sglpDS) return NULL; + + // open file containing sound + HSFILE hsFile; + patSFileOpenFile(pszName,&hsFile); + + // initialize sound record + TSnd * pSnd = (TSnd *) DiabloAllocPtrSig(sizeof(TSnd),'SND '); + ZeroMemory(pSnd,sizeof(TSnd)); + pSnd->pszName = pszName; + pSnd->dwLastPlayTime = GetTickCount() - MIN_REPLAY_THRESHOLD - 1; + + // get the sound format + LPBYTE lpWave = wave_load_file(hsFile,&pSnd->wfx,&pSnd->waveInfo); + if (! lpWave) app_fatal("Invalid sound format on file %s",pSnd->pszName); + + // allocate a buffer based on sound format + snd_alloc_buffer(pSnd); + + // lock sound buffer + BYTE * pbData; + BYTE * pbData2; + DWORD dwLen; + DWORD dwLen2; + HRESULT hr = pSnd->pDSB->Lock(0,pSnd->waveInfo.dwSize,&pbData,&dwLen,&pbData2,&dwLen2,0); + dsound_assert(hr); + + // read sound data + CopyMemory(pbData,lpWave + pSnd->waveInfo.dwOffset,dwLen); + + // unlock sound buffer + hr = pSnd->pDSB->Unlock(pbData,dwLen,pbData2,dwLen2); + dsound_assert(hr); + + #if DEBUG_MEM + mem_use_sig('DSND',pSnd->waveInfo.dwSize); + #endif + + // cleanup + wave_free_file(lpWave); + patSFileCloseFile(hsFile); + + return pSnd; +} + + +//****************************************************************** +//****************************************************************** +void snd_free_snd(TSnd * pSnd) { + if (pSnd) { + if (pSnd->pDSB) { + pSnd->pDSB->Stop(); + pSnd->pDSB->Release(); + pSnd->pDSB = NULL; + } + + #if DEBUG_MEM + mem_unuse_sig('DSND',pSnd->waveInfo.dwSize); + #endif + + DiabloFreePtr(pSnd); + } +} + + +//****************************************************************** +//****************************************************************** +static void snd_set_format(HSFILE hsFile) { + HRESULT hr; + app_assert(sglpDS); + + // Set up the primary direct sound buffer -- only try to + // do this the first time we're called (when hsFile == NULL). + // Don't worry about releasing the primary sound buffer, it + // will be done by directsound on application exit. + static LPDIRECTSOUNDBUFFER slpDSPrimary = NULL; + if (hsFile == NULL) { + DSBUFFERDESC dsbd; + ZeroMemory(&dsbd,sizeof(dsbd)); + dsbd.dwSize = sizeof(dsbd); + dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; + hr = sglpDS->CreateSoundBuffer(&dsbd,&slpDSPrimary,NULL); + dsound_assert(hr); + } + if (! slpDSPrimary) return; + + // get sound card capabilities + DSCAPS caps; + caps.dwSize = sizeof(DSCAPS); + hr = sglpDS->GetCaps(&caps); + dsound_assert(hr); + + // setup new format for primary buffer + WAVEFORMATEX fmt; + if (! hsFile || !wave_read_header(hsFile,&fmt)) { + ZeroMemory(&fmt,sizeof(fmt)); + fmt.wFormatTag = WAVE_FORMAT_PCM; + fmt.nSamplesPerSec = 22050; // 22k + fmt.wBitsPerSample = 16; // 16 bit + fmt.nChannels = 2; // stereo + fmt.cbSize = 0; + } + + // force stereo + fmt.nChannels = 2; + + // calculate sound buffer parameters + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample/8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + hr = slpDSPrimary->SetFormat(&fmt); + +// pjw.patch1.start.1/13/97 + // since sound cards may not implement this feature, or may not + // support certain formats, just ignore error codes... + // if (hr != DS_OK && hr != DSERR_BADFORMAT && hr != DSERR_PRIOLEVELNEEDED) + // dsound_assert(hr); +// pjw.patch1.end.1/13/97 +} + + +//****************************************************************** +//****************************************************************** +static HRESULT InDirectSoundCreate( + GUID * lpGUID, + LPDIRECTSOUND * lplpDS, + IUnknown * pUnkOuter +) { + // load direct sound library + if (! sghDSlib) sghDSlib = LoadLibrary(TEXT("dsound.dll")); + if (! sghDSlib) ErrorDlg(IDD_DSOUND_DLL_ERR,GetLastError(),__FILE__,__LINE__); + + // bind to DirectSoundCreate + typedef HRESULT (WINAPI * DSCREATETYPE)(GUID *,LPDIRECTSOUND *,IUnknown *); + DSCREATETYPE dscreatefunc = (DSCREATETYPE) GetProcAddress(sghDSlib,TEXT("DirectSoundCreate")); + if (! dscreatefunc) ErrorDlg(IDD_DSOUND_DLL_ERR,GetLastError(),__FILE__,__LINE__); + + // call DirectDrawCreate + return dscreatefunc(lpGUID,lplpDS,pUnkOuter); +} + + +//****************************************************************** +//****************************************************************** +void snd_init(HWND hWnd) { + snd_get_volume(sgszSoundVol,&sglSoundVolume); + gbSoundOn = (sglSoundVolume > VOLUME_MIN); + snd_get_volume(sgszMusicVol,&sglMusicVolume); + gbMusicOn = (sglMusicVolume > VOLUME_MIN); + + app_assert(! sglpDS); + HRESULT hr = InDirectSoundCreate(NULL,&sglpDS,NULL); + if (hr != DS_OK) sglpDS = NULL; + + if (sglpDS && DS_OK == sglpDS->SetCooperativeLevel(hWnd,DSSCL_EXCLUSIVE)) + snd_set_format(NULL); + + BOOL bSuccess = SVidInitialize(sglpDS); + app_assert(! sglpDS || bSuccess); + + bSuccess = SFileDdaInitialize(sglpDS); + app_assert(! sglpDS || bSuccess); + + // tell the world we can do sound + gbSndInited = (sglpDS != NULL); +} + + +//****************************************************************** +//****************************************************************** +void snd_exit() { + snd_update(TRUE); + + // shut down storm stuff before we release directsound + SVidDestroy(); + SFileDdaDestroy(); + + if (sglpDS) { + sglpDS->Release(); + sglpDS = NULL; + } + +// cannot free library now, still may be in use +// by directX window procedure... +/* + if (sghDSlib) { + FreeLibrary(sghDSlib); + sghDSlib = NULL; + } +*/ + + // turn off sound + if (gbSndInited) { + gbSndInited = FALSE; + snd_set_volume(sgszSoundVol,sglSoundVolume); + snd_set_volume(sgszMusicVol,sglMusicVolume); + } +} + + +//****************************************************************** +//****************************************************************** +void music_stop() { + if (sghMusic) { + SFileDdaEnd(sghMusic); + SFileCloseFile(sghMusic); + sghMusic = NULL; + sgnMusicTrack = NUM_MUSIC; + } +} + + +//****************************************************************** +//****************************************************************** +void music_start(int nTrack) { + app_assert((DWORD) nTrack < NUM_MUSIC); + music_stop(); + + if (! sglpDS) return; + if (! gbMusicOn) return; + + #ifndef NDEBUG + SFileEnableDirectAccess(0); + #endif + BOOL bResult = SFileOpenFile(sgszMusicTracks[nTrack],&sghMusic); + #ifndef NDEBUG + SFileEnableDirectAccess(1); + #endif + snd_set_format(sghMusic); + if (! bResult) { + sghMusic = NULL; + return; + } + + SFileDdaBeginEx(sghMusic,DDA_BUF_SIZE,SFILE_DDA_LOOP,0,sglMusicVolume,0,0); + sgnMusicTrack = nTrack; +} + + +//****************************************************************** +//****************************************************************** +void music_pause(BOOL bPause) { + if (bPause) + music_stop(); + else if (sgnMusicTrack != NUM_MUSIC) + music_start(sgnMusicTrack); +} + + +//****************************************************************** +//****************************************************************** +LONG music_volume(LONG lVolume) { + if (lVolume == VOLUME_READ) return sglMusicVolume; + app_assert(lVolume >= VOLUME_MIN); + app_assert(lVolume <= VOLUME_MAX); + sglMusicVolume = lVolume; + + if (sghMusic) SFileDdaSetVolume(sghMusic,sglMusicVolume,0); + + return sglMusicVolume; +} + + +//****************************************************************** +//****************************************************************** +LONG sound_volume(LONG lVolume) { + if (lVolume == VOLUME_READ) return sglSoundVolume; + app_assert(lVolume >= VOLUME_MIN); + app_assert(lVolume <= VOLUME_MAX); + sglSoundVolume = lVolume; + return sglSoundVolume; +} diff --git a/src/SOUND.H b/src/SOUND.H new file mode 100644 index 0000000..befde2e --- /dev/null +++ b/src/SOUND.H @@ -0,0 +1,78 @@ +//****************************************************************** +// sound.h +// created 10.18.96 +// written by Patrick Wyatt +//****************************************************************** + + +#ifndef H_SND +#define H_SND + + +//****************************************************************** +// public structures +//****************************************************************** +#define DDA_BUF_SIZE 0x40000 + +typedef struct CKINFO { + DWORD dwSize; + DWORD dwOffset; +} CKINFO; + + +typedef struct TSnd { + WAVEFORMATEX wfx; + CKINFO waveInfo; + const char * pszName; + LPDIRECTSOUNDBUFFER pDSB; + DWORD dwLastPlayTime; +} TSnd; + + +//****************************************************************** +// public vars +//****************************************************************** +extern BYTE gbMusicOn; +extern BYTE gbSoundOn; +extern BYTE gbSndInited; + + +//****************************************************************** +// public functions +//****************************************************************** +void snd_init(HWND hWnd); +void snd_exit(void); + +TSnd * snd_load_snd(const char * pszName); +void snd_free_snd(TSnd * pSnd); +void snd_play_snd(TSnd * pSnd,LONG lVolume,LONG lPan); +void snd_stop_snd(TSnd * pSnd); +BOOL snd_playing(TSnd * pSnd); + + +enum { + MUSIC_TOWN, + MUSIC_L1, + MUSIC_L2, + MUSIC_L3, + MUSIC_L4, + MUSIC_L5, + MUSIC_L6, + MUSIC_INTRO, + NUM_MUSIC +}; +void music_start(int nTrack); +void music_stop(); + + +#define VOLUME_READ 1 +#define VOLUME_MIN -1600 +#define VOLUME_MAX 0 +#define VOLUME_STEP 100 +#define VOLUME_TICKS (((VOLUME_MAX - VOLUME_MIN) / VOLUME_STEP) + 1) +LONG music_volume(LONG lVolume); +LONG sound_volume(LONG lVolume); + + + +#endif diff --git a/src/SPELL.SAV b/src/SPELL.SAV new file mode 100644 index 0000000..744350f --- /dev/null +++ b/src/SPELL.SAV @@ -0,0 +1,2819 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Control panel file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/CONTROL.CPP 2 2/05/97 10:41a Dbrevik2 $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "engine.h" +#include "control.h" +#include "gendung.h" +#include "scrollrt.h" +#include "msg.h" + +#include "items.h" +#include "itemdat.h" +#include "player.h" +#include "monster.h" +#include "objects.h" +#include "cursor.h" +#include "spells.h" +#include "missiles.h" + +#include "town.h" +#include "towners.h" +#include "trigs.h" +#include "gamemenu.h" +#include "inv.h" +#include "minitext.h" +#include "lighting.h" +#include "stores.h" +#include "automap.h" +#include "quests.h" + +#include "multi.h" + +#include "error.h" +#include "spelldat.h" + +/*-----------------------------------------------------------------------** +** Registration info +**-----------------------------------------------------------------------*/ +#include "regconst.h" +char sgszRegSig5[REG_LEN] = "REGISTRATION_BLOCK"; + +/*-----------------------------------------------------------------------** +** Local defines +**-----------------------------------------------------------------------*/ + +#define MANABUFFSIZE 7744 // 88x88 +#define LIFEBUFFSIZE 7744 + +#define STRN_GOLD 0 +#define STRN_BLUE 1 +#define STRN_RED 2 +#define STRN_ORANGE 3 +#define STRN_GREY 4 + +/*-----------------------------------------------------------------------** +** Global variables +**-----------------------------------------------------------------------*/ + +BYTE *pBtmBuff; // Offscreen control panel buffer +BYTE *pStatusPanel; +BYTE *pPanelButtons; +BYTE *pPanelText; +BYTE *pManaBuff; +BYTE *pLifeBuff; +BYTE *pChrPanel; +BYTE *pChrButtons; +BYTE *pSpellCels; +BYTE *pGBoxBuff; + +char panelstr[4][64]; +int pstrjust[4]; +BOOL pinfoflag; +int pnumlines; + +char infostr[256]; +char infoclr; + +char tempstr[256]; + +int pentaspin; +int dropGoldValue; +int initialDropGoldValue; +int initialDropGoldIndex; + +const BYTE fonttrans[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 0, 54, 44, 57, 58, 56, 55, 47, 40, 41, 59, 39, 50, 37, 51, 52, // 32-47 + 36, 27, 28, 29, 30, 31, 32, 33, 34, 35, 48, 49, 60, 38, 61, 53, // 48-63 + 62, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 64-79 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 63, 43, 64, 65, // 80-95 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 96-111 + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 40, 66, 41, 67, 0 }; // 112-127 + +const BYTE fontkern[68] = { 8, // Space/Invalid + 10, 7, 9, 8, 7, 6, 8, 8, 3, 3, 8, 6, 11, 9, 10, 6, // a-p + 9, 9, 6, 9, 11, 10, 13, 10, 11, 7, // q-z + 5, 7, 7, 8, 7, 7, 7, 7, 7, 10, // 1-0 + 4, 5, 6, 3, 3, 4, 3, 6, 6, 3, 3, 3, 3, 3, 2, 7, 6, 3, 10, 10, 6, // misc + 6, 7, 4, 4, 9, 6, 6, 12, 3, 7 }; // misc + +static const long fontofs[5][5] = { + { 456433, 24576, 24576, 24576, 24756 }, + { 447217, 465649, 24576, 24576, 24576 }, + { 442609, 456433, 470257, 24576, 24576 }, + { 439537, 451057, 461809, 473329, 24576 }, + { 438001, 447217, 456433, 465649, 474097 } }; + +BOOL drawhpflag; +BOOL drawmanaflag; +BOOL chrflag; + +/*-----------------------------------------------------------------------*/ + +BOOL spselflag = FALSE; +int pSpell, pSplType; +byte SpellTrans[256]; +static char SpellITbl[MAXSPELLS] = { + 1, // Invalid + 1, // SPL_FIREBOLT + 2, // SPL_HEAL + 3, // SPL_LIGHTNING + 4, // SPL_FLASH + 5, // SPL_IDENTIFY + 6, // SPL_WALL + 7, // SPL_TOWN + 8, // SPL_STONE + 9, // SPL_INFRA + 28, // SPL_PHASE + 13, // SPL_MANASHLD + 12, // SPL_FIREBALL + 18, // SPL_GUARDIAN + 16, // SPL_CHAIN + 14, // SPL_WAVE + 18, // SPL_DOOM + 19, // SPL_BLOODR + 11, // SPL_NOVA + 20, // SPL_INVIS + 15, // SPL_FLAME + 21, // SPL_GOLEM + 23, // SPL_BLOODB + 24, // SPL_TELE + 25, // SPL_APOCA + 22, // SPL_ETHER + 26, // SPL_REPAIR + 29, // SPL_RECHARGE + 37, // SPL_DISARM + 38, // SPL_ELEMENT + 39, // SPL_CBOLT + 42, // SPL_HBOLT + 41, // SPL_RESURRECT + 40, // SPL_TELEKINESIS + 10, // SPL_HEALOTHER + 36, // SPL_BSTAR + 30, // SPL_BONESPIRT + 26, // SPL_MANA + 29, // SPL_FMANA + 37, // SPL_RANDOM + 6, // SPL_LTWALL + 11, // SPL_IMMOLATION + 28, // SPL_TELESTAIRS + 26, // SPL_REFLECT + 4, // SPL_BERSERK + 6, // SPL_RINGOFFIRE + 6, // SPL_RINGOFLIGHT + 5, // SPL_SHOWMAGITEMS + }; + +/*-----------------------------------------------------------------------*/ + +#define NUMPBTNS 8 +#define SINGLE_PBTNS 6 +#define MULTI_PBTNS NUMPBTNS + +#define PBTN_CHR 0 +#define PBTN_TPLR1 0 +#define PBTN_QUEST 1 +#define PBTN_AMAP 2 +#define PBTN_TPLR2 2 +#define PBTN_MENU 3 +#define PBTN_INV 4 +#define PBTN_TPLR3 4 +#define PBTN_SBOOK 5 +#define PBTN_TALK 6 +#define PBTN_ATTACK 7 + +// x1, y1, width, height, talk pushable +int PanBtnPos[NUMPBTNS][5] = { + { 9, 361, 71, 19, TRUE }, + { 9, 387, 71, 19, FALSE }, + { 9, 427, 71, 19, TRUE }, + { 9, 453, 71, 19, FALSE }, + { 560, 361, 71, 19, TRUE }, + { 560, 387, 71, 19, FALSE }, + { 87, 443, 33, 32, TRUE }, + { 527, 443, 33, 32, TRUE }, +}; + +char *PanBtnHotKey[NUMPBTNS] = { + "'c'", + "'q'", + "Tab", + "Esc", + "'i'", + "'b'", + "Enter", + NULL }; + +char *PanBtnStr[NUMPBTNS] = { + "Character Information", + "Quests log", + "Automap", + "Main Menu", + "Inventory", + "Spell book", + "Send Message", + "Player Attack" }; + +BOOL panbtn[NUMPBTNS]; +BOOL drawbtnflag, panbtndown; +BOOL panelflag; // panel info draw +int numpanbtns; + +BYTE *pDurIcons; + +BOOL drawdurflag; +BOOL dropGoldFlag; + +/*-----------------------------------------------------------------------*/ + +#define NUMCBTNS 4 + +#define CBTN_STR 0 +#define CBTN_MAG 1 +#define CBTN_DEX 2 +#define CBTN_VIT 3 + +// x1, y1, width, height +int ChrBtnPos[NUMCBTNS][4] = { + { 137, 138, 41, 22 }, + { 137, 166, 41, 22 }, + { 137, 195, 41, 22 }, + { 137, 223, 41, 22 } }; + +BOOL chrbtn[NUMCBTNS]; +BOOL chrbtndown; + +/*-----------------------------------------------------------------------*/ + +BOOL lvlbtndown; + +/*-----------------------------------------------------------------------*/ + +BYTE *pSpellBkCel; +BYTE *pSBkBtnCel; +BYTE *pSBkIconCels; + +int sbooktab; +BOOL sbookflag; + +// The first entry will be filled during init with the player types skill +int SpellPages[6][7] = { + { 0, SPL_FIREBOLT, SPL_CBOLT, SPL_HBOLT, SPL_HEAL, SPL_HEALOTHER, SPL_FLAME }, + { SPL_RESURRECT, SPL_WALL, SPL_TELEKINESIS, SPL_LIGHTNING, SPL_TOWN, SPL_FLASH, SPL_STONE }, + { SPL_PHASE, SPL_MANASHLD, SPL_ELEMENT, SPL_FIREBALL, SPL_WAVE, SPL_CHAIN, SPL_GUARDIAN}, + { SPL_NOVA, SPL_GOLEM, SPL_TELE, SPL_APOCA, SPL_BONESPIRIT, SPL_BSTAR, SPL_ETHER }, + { SPL_LTWALL, SPL_IMMOLATION, SPL_TELESTAIRS, SPL_REFLECT, SPL_BERSERK, SPL_RINGOFFIRE, SPL_SHOWMAGITEMS }, + { -1, -1, -1, -1, -1, -1, -1 } +}; + +/*-----------------------------------------------------------------------*/ +#define MAX_TALK_SAVES 8 // must be pow2 +BOOL talkflag; +static int tspin; +static long talkofs; +static char sgszTalkMsg[MAX_SEND_STR_LEN]; +static BYTE sgbTalkSavePos; +static BYTE sgbNextTalkSave; +static char sgszTalkSaveMsg[MAX_TALK_SAVES][MAX_SEND_STR_LEN]; +static BYTE sgbPlrTalkTbl[MAX_PLRS]; +static BYTE *pTalkPanel; +static BYTE *pMultiBtns; +static BYTE *pTalkBtns; +static BOOL talkbtndown[3]; + +void TalkStart(); +void TalkEnd(); +void PlrStringXY(int x1, int y, int x2,const char * pszStr,char col); + + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ +void SetPlrHandItem(ItemStruct *h, int idata); +void GetPlrHandSeed(ItemStruct *h); +void GetGoldSeed(int pnum, ItemStruct *h); +void SetSpellTrans(char); + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawSpellCel(long xp, long yp, BYTE *pCels, long nCel, long w) +{ + BYTE *pTo; + byte *ttbl; + long RLELen; + + ttbl = &SpellTrans[0]; + app_assert(gpBuffer); + pTo = gpBuffer + nBuffWTbl[yp] + xp; + __asm { + mov ebx,dword ptr [pCels] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] + sub eax,dword ptr [ebx] + mov dword ptr [RLELen],eax + + mov esi,dword ptr [pCels] // Source + add esi,dword ptr [ebx] + + mov edi,dword ptr [pTo] // Dest + + mov eax,dword ptr [RLELen] + add eax,esi + mov dword ptr [RLELen],eax + + mov ebx,dword ptr [ttbl] + +_T1Lp1: mov edx,dword ptr [w] + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + mov ecx,eax + shr ecx,1 + jnc _T1w + lodsb + xlatb + stosb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + lodsw + xlatb + ror ax,8 + xlatb + ror ax,8 + stosw + jecxz _T1x +_T1Lp3: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop _T1Lp3 +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,768 + sub edi,dword ptr [w] + cmp esi,dword ptr [RLELen] + jnz _T1Lp1 + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetSpellTrans(char t) +{ + int i; + + if (t == STRN_GOLD) { + for (i = 0; i < 128; i++) SpellTrans[i] = i; + } + for (i = 128; i < 256; i++) SpellTrans[i] = i; + SpellTrans[255] = 0; + + switch (t) { + case STRN_BLUE : + SpellTrans[144] = 177; + SpellTrans[145] = 179; + SpellTrans[146] = 181; + for (i = 176; i < 192; i++) { + SpellTrans[i - 16] = i; // 160-175 + SpellTrans[i + 16] = i; // 192-207 + SpellTrans[i + 32] = i; // 208-223 + } + break; + case STRN_ORANGE : + SpellTrans[144] = 209; + SpellTrans[145] = 211; + SpellTrans[146] = 213; + for (i = 208; i < 224; i++) { + SpellTrans[i - 48] = i; // 160-175 + SpellTrans[i - 16] = i; // 192-207 + } + break; + case STRN_RED : + SpellTrans[144] = 161; + SpellTrans[145] = 163; + SpellTrans[146] = 165; + for (i = 160; i < 176; i++) { + SpellTrans[i + 32] = i; // 192-207 + SpellTrans[i + 48] = i; // 208-223 + } + break; + case STRN_GREY : + SpellTrans[144] = 241; + SpellTrans[145] = 243; + SpellTrans[146] = 245; + for (i = 240; i < 255; i++) { + SpellTrans[i - 80] = i; // 160-174 + SpellTrans[i - 48] = i; // 192-206 + SpellTrans[i - 32] = i; // 208-222 + } + SpellTrans[175] = 0; + SpellTrans[207] = 0; + SpellTrans[223] = 0; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawSpellIcon() { + char t, sn; + int sl; + + t = plr[myplr]._pRSplType; + sn = plr[myplr]._pRSpell; + sl = plr[myplr]._pSplLvl[sn] + plr[myplr]._pISplLvlAdd; + if ((t == SPT_MEMORIZED) && (sn != -1)) { + if (!CheckSpell(myplr, sn, t, TRUE)) t = STRN_GREY; + if (sl <= 0 ) t = STRN_GREY; + } + + if ((currlevel == 0) && (t != STRN_GREY) && (spelldata[sn].sTownSpell == FALSE)) t = STRN_GREY; + if (plr[myplr]._pRSpell < 0) t = STRN_GREY; + SetSpellTrans(t); + if (sn != -1) DrawSpellCel(629, 631, pSpellCels, SpellITbl[sn], 56); + else DrawSpellCel(629, 631, pSpellCels, 27, 56); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#define SPLICONSIZE 56 +#define SPLICONRIGHT 636 // (640 - (trunc(640 / 56) * 56)) / 2) + 640 + 64 - SPLICONSIZE +#define SPLICONLEFT 20 // SPLICONRIGHT - (trunc(640 / 56) * 56) - SPLICONSIZE + +void DrawSpellList() +{ + int mx,my,x,y,i,j,t; + __int64 mask,spl; + int s,c,hk; + int v, selbox; + + x = SPLICONRIGHT; + y = 495; + + pSpell = -1; + infostr[0] = 0; + ClearPanel(); + for (j = 0; j < 4; j++) { + switch(j) { + case 0: + SetSpellTrans(STRN_GOLD); + spl = plr[myplr]._pAblSpells; + selbox = 46; + break; + case 1: + spl = plr[myplr]._pMemSpells; + selbox = 47; + break; + case 2: + SetSpellTrans(STRN_RED); + spl = plr[myplr]._pScrlSpells; + selbox = 44; + break; + case 3: + SetSpellTrans(STRN_ORANGE); + spl = plr[myplr]._pISpells; + selbox = 45; + break; + } + mask = 1; + for (i = 1; i < SPL_LAST; i++) { + if ((spl & mask) != 0) { + if (j == 1) { + v = plr[myplr]._pSplLvl[i] + plr[myplr]._pISplLvlAdd; + if ( v < 0 ) v = 0; + if (v > 0) t = STRN_BLUE; + else t = STRN_GREY; + SetSpellTrans(t); + } + + if ((currlevel == 0) && (spelldata[i].sTownSpell == FALSE)) SetSpellTrans(STRN_GREY); + + DrawSpellCel(x, y, pSpellCels, SpellITbl[i], SPLICONSIZE); + mx = x - 64; + my = y - (160 + SPLICONSIZE); + if ((MouseX >= mx) && (MouseX < (mx+SPLICONSIZE)) && (MouseY >= my) && (MouseY < (my+SPLICONSIZE))) { + pSpell = i; + pSplType = j; + DrawSpellCel(x, y, pSpellCels, selbox, SPLICONSIZE); + switch (j) { + case 0: + sprintf(infostr, "%s Skill", spelldata[pSpell].sSkillText); + break; + case 1: + sprintf(infostr, "%s Spell", spelldata[pSpell].sNameText); + if (pSpell == SPL_HBOLT) { + sprintf(tempstr, "Damages undead only"); + AddPanelString(tempstr, TEXT_CENTER); + } + if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); + else sprintf(tempstr, "Spell Level %i", v); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 2: + sprintf(infostr, "Scroll of %s", spelldata[pSpell].sNameText); + c = 0; + for (s = 0; s < plr[myplr]._pNumInv; s++) { + if ((plr[myplr].InvList[s]._itype != -1) && + ((plr[myplr].InvList[s]._iMiscId == IMID_SCROLL) || + (plr[myplr].InvList[s]._iMiscId == IMID_TSCROLL))) { + if (plr[myplr].InvList[s]._iSpell == pSpell) c++; + } + } + for (s = 0; s < MAXSPD; s++) { + if ((plr[myplr].SpdList[s]._itype != -1) && + ((plr[myplr].SpdList[s]._iMiscId == IMID_SCROLL) || + (plr[myplr].SpdList[s]._iMiscId == IMID_TSCROLL))) { + if (plr[myplr].SpdList[s]._iSpell == pSpell) c++; + } + } + if (c == 1) strcpy(tempstr, "1 Scroll"); + else sprintf(tempstr, "%i Scrolls", c); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 3: + sprintf(infostr, "Staff of %s", spelldata[pSpell].sNameText); + if (plr[myplr].Hand1Item._iCharges == 1) strcpy(tempstr, "1 Charge"); + else sprintf(tempstr, "%i Charges", plr[myplr].Hand1Item._iCharges); + AddPanelString(tempstr, TEXT_CENTER); + break; + } + for (hk = 0; hk < 4; hk++) { + if ((plr[myplr]._pSplHotKey[hk] == pSpell) && (plr[myplr]._pSplTHotKey[hk] == pSplType)) { + DrawSpellCel(x, y, pSpellCels, 48+hk, SPLICONSIZE); + sprintf(tempstr, "Spell Hot Key #F%i", hk+5); + AddPanelString(tempstr, TEXT_CENTER); + } + } + } + x -= SPLICONSIZE; + if (x == SPLICONLEFT) { + x = SPLICONRIGHT; + y -= SPLICONSIZE; + } + } + mask = mask << 1; + } + if (spl && (x != SPLICONRIGHT)) x -= SPLICONSIZE; + if (x == SPLICONLEFT) { + x = SPLICONRIGHT; + y -= SPLICONSIZE; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void SetSpell() +{ + spselflag = FALSE; + if (pSpell != -1) { + ClearPanel(); + plr[myplr]._pRSpell = pSpell; + plr[myplr]._pRSplType = pSplType; + force_redraw = FULLDRAW; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetSpellHK(int hk) +{ + if (pSpell != -1) { + for (int i = 0; i < 4; i++) { + if ((plr[myplr]._pSplHotKey[i] == pSpell) && (plr[myplr]._pSplTHotKey[i] == pSplType)) + plr[myplr]._pSplHotKey[i] = -1; + } + plr[myplr]._pSplHotKey[hk] = pSpell; + plr[myplr]._pSplTHotKey[hk] = pSplType; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void GetSpellHK(int hk) +{ + __int64 spl; + + if (plr[myplr]._pSplHotKey[hk] == -1) return; + + switch(plr[myplr]._pSplTHotKey[hk]) { + case 0: + spl = plr[myplr]._pAblSpells; + break; + case 1: + spl = plr[myplr]._pMemSpells; + break; + case 2: + spl = plr[myplr]._pScrlSpells; + break; + case 3: + spl = plr[myplr]._pISpells; + break; + } + spl &= (((__int64)1) << (plr[myplr]._pSplHotKey[hk]-1)); + if (spl) { + plr[myplr]._pRSpell = plr[myplr]._pSplHotKey[hk]; + plr[myplr]._pRSplType = plr[myplr]._pSplTHotKey[hk]; + force_redraw = FULLDRAW; + } +} + +/*-----------------------------------------------------------------------** +** Draws a small font letter +**-----------------------------------------------------------------------*/ + +void DrawPanelFont (long poffset, long nCel, char clr) +{ + app_assert(gpBuffer); + __asm { + mov ebx,dword ptr [pPanelText] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + + mov edx,dword ptr [ebx+4] // Length + sub edx,dword ptr [ebx] + + mov esi,dword ptr [pPanelText] // Source + add esi,dword ptr [ebx] + + mov edi,dword ptr [gpBuffer] // Dest + add edi,dword ptr [poffset] + + mov ebx,edx + add ebx,esi + + xor edx,edx + mov dl,byte ptr [clr] + cmp edx,ICOLOR_WHITE + jz _T1Lp1 // Normal / White + cmp edx,ICOLOR_BLUE + jz _T2Lp1 // Blue + cmp edx,ICOLOR_RED + jz _T3Lp1 // Red + jmp _T4Lp1 // Gold + +/*- White ---------------------------------------------------------------*/ + +_T1Lp1: mov edx,13 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax // Draw + mov ecx,eax + shr ecx,1 + jnc _T1w + movsb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + movsw + jecxz _T1x +_T1Lp3: rep movsd +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,781 + cmp ebx,esi + jnz _T1Lp1 + jmp _Done + +/*- Blue ----------------------------------------------------------------*/ + +_T2Lp1: mov edx,13 + +_T2Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T2J + + sub edx,eax // Draw + mov ecx,eax +_T2Lp3: lodsb + cmp al,253 + ja _T2F + cmp al,240 + jb _T2Sv + sub al,62 + jmp _T2Sv +_T2F: mov al,191 +_T2Sv: stosb + loop _T2Lp3 + or edx,edx + jz _T2Nxt + jmp _T2Lp2 + +_T2J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T2Lp2 +_T2Nxt: sub edi,781 + cmp ebx,esi + jnz _T2Lp1 + jmp _Done + +/*- Red -----------------------------------------------------------------*/ + +_T3Lp1: mov edx,13 + +_T3Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T3J + + sub edx,eax // Draw + mov ecx,eax +_T3Lp3: lodsb + cmp al,240 + jb _T3Sv + sub al,16 +_T3Sv: stosb + loop _T3Lp3 + or edx,edx + jz _T3Nxt + jmp _T3Lp2 + +_T3J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T3Lp2 +_T3Nxt: sub edi,781 + cmp ebx,esi + jnz _T3Lp1 + jmp _Done + +/*- Gold ----------------------------------------------------------------*/ + +_T4Lp1: mov edx,13 + +_T4Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T4J + + sub edx,eax // Draw + mov ecx,eax +_T4Lp3: lodsb + cmp al,240 + jb _T4Sv + cmp al,254 + jae _T4val + sub al,46 + jmp _T4Sv +_T4val: mov al,207 +_T4Sv: stosb + loop _T4Lp3 + or edx,edx + jz _T4Nxt + jmp _T4Lp2 + +_T4J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T4Lp2 +_T4Nxt: sub edi,781 + cmp ebx,esi + jnz _T4Lp1 + +/*-----------------------------------------------------------------------*/ + +_Done: + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AddPanelString(const char * str, int just) +{ + strcpy(panelstr[pnumlines],str); + pstrjust[pnumlines] = just; + if (pnumlines < 4) pnumlines++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ClearPanel() +{ + pnumlines = 0; + pinfoflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CopyCtrlPan(int sx, int sy, int deltax, int deltay, int dx, int dy) +{ + long src, dest; + + app_assert(gpBuffer); + src = (sy * 640) + sx; + dest = (dy * 768) + dx; + __asm { + mov esi,dword ptr [pBtmBuff] + add esi,dword ptr [src] + mov edi,dword ptr [gpBuffer] + add edi,dword ptr [dest] + + xor ebx,ebx + mov bx,word ptr [deltax] + xor edx,edx + mov dx,word ptr [deltay] +_CLp: mov ecx,ebx + shr ecx,1 + jnc _Tw + movsb + jecxz _Tx +_Tw: shr ecx,1 + jnc _TLp + movsw + jecxz _Tx +_TLp: rep movsd +_Tx: add esi,640 + sub esi,ebx + add edi,768 + sub edi,ebx + dec edx + jnz _CLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitPanelStr() +{ + ClearPanel(); + //AddPanelString("Welcome to Diablo", TEXT_CENTER); // This was ok (pre Demo) now its not + //AddPanelString("Press F1 for help", TEXT_CENTER); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void BuffCopy(BYTE *pSrc, int y1, int y2, int dx, int dy) +{ + long srco, desto, deltay; + + app_assert(gpBuffer); + srco = y1 * 88; + desto = (dy * 768) + dx; + deltay = y2 - y1; + __asm { + mov esi,dword ptr [pSrc] + add esi,dword ptr [srco] + mov edi,dword ptr [gpBuffer] + add edi,dword ptr [desto] + + mov edx,dword ptr [deltay] +_YLp: mov ecx,22 + rep movsd + add edi,680 + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TransBuffCopy(BYTE *pSrc, long srcwidth, long srcoff, BYTE *pDest, long destoff, long dy) +{ + __asm { + mov esi,dword ptr [pSrc] + add esi,dword ptr [srcoff] + mov edi,dword ptr [pDest] + add edi,dword ptr [destoff] + + mov edx,dword ptr [dy] +_YLp: mov ecx,59 +_XLp: lodsb + or al,al + jz _Skip + mov byte ptr [edi],al +_Skip: inc edi + loop _XLp + add esi,dword ptr [srcwidth] + sub esi,59 + add edi,709 + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawHealthTop() +{ + double v; + int dv; + + if (plr[myplr]._pMaxHP <= 0) + v = 0.0; + else + v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; + dv = (int)v; + plr[myplr]._pHPPer = dv; + + + long dy; + + dy = 80 - plr[myplr]._pHPPer; + if (dy > 11) dy = 11; + dy += 2; + + app_assert(gpBuffer); + TransBuffCopy(pLifeBuff, 88, 277, gpBuffer, 383405, dy); + if (dy != 13) TransBuffCopy(pBtmBuff, 640, (dy * 640) + 2029, gpBuffer, (dy * 768) + 383405, 13 - dy); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawHealthBar() +{ + double v; + int dv; + + if (plr[myplr]._pMaxHP <= 0) + v = 0.0; + else + v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; + dv = (int)v; + plr[myplr]._pHPPer = dv; + + if (dv > 69) dv = 69; + if (dv != 69) BuffCopy(pLifeBuff, 16, 85-dv, 160, 512); + if (dv != 0) CopyCtrlPan(96, 85-dv, 88, dv, 160, 581-dv); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawManaTop() +{ + long dy; + + dy = 80 - plr[myplr]._pManaPer; + if (dy > 11) dy = 11; + dy += 2; + + app_assert(gpBuffer); + TransBuffCopy(pManaBuff, 88, 277, gpBuffer, 383771, dy); + if (dy != 13) TransBuffCopy(pBtmBuff, 640, (dy * 640) + 2395, gpBuffer, (dy * 768) + 383771, 13 - dy); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CalcInitBallPer() +{ + double v; + int dv; + long m,mm; + + mm = plr[myplr]._pMaxMana; + m = plr[myplr]._pMana; + if (mm < 0) mm = 0; + if (m < 0) m = 0; + if (mm == 0) dv = 0; + else { + v = ((double)m / (double)mm) * 80; + dv = (int)v; + } + plr[myplr]._pManaPer = dv; + v = ((double)plr[myplr]._pHitPoints / (double)plr[myplr]._pMaxHP) * 80; + dv = (int)v; + plr[myplr]._pHPPer = dv; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawManaBar() +{ + double v; + int dv; + long m,mm; + + mm = plr[myplr]._pMaxMana; + m = plr[myplr]._pMana; + if (mm < 0) mm = 0; + if (m < 0) m = 0; + if (mm == 0) dv = 0; + else { + v = ((double)m / (double)mm) * 80; + dv = (int)v; + } + plr[myplr]._pManaPer = dv; + + if (dv > 69) dv = 69; + if (dv != 69) BuffCopy(pManaBuff, 16, 85-dv, 528, 512); + if (dv != 0) CopyCtrlPan(464, 85-dv, 88, dv, 528, 581-dv); + + DrawSpellIcon(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitControlPan() +{ + int i; + + app_assert(! pBtmBuff); + if (gbMaxPlayers == 1) { + pBtmBuff = DiabloAllocPtrSig(BTMBUFFSIZE,'CTRL'); + ZeroMemory(pBtmBuff,BTMBUFFSIZE); + } else { + pBtmBuff = DiabloAllocPtrSig(BTMBUFFMULTISIZE,'CTRL'); + ZeroMemory(pBtmBuff,BTMBUFFMULTISIZE); + } + pManaBuff = DiabloAllocPtrSig(MANABUFFSIZE,'CTRL'); + ZeroMemory(pManaBuff,MANABUFFSIZE); + pLifeBuff = DiabloAllocPtrSig(LIFEBUFFSIZE,'CTRL'); + ZeroMemory(pLifeBuff,LIFEBUFFSIZE); + pPanelText = LoadFileInMemSig("CtrlPan\\SmalText.CEL",NULL,'CTRL'); + pChrPanel = LoadFileInMemSig("Data\\Char.CEL",NULL,'CTRL'); + pSpellCels = LoadFileInMemSig("CtrlPan\\SpelIcon.CEL",NULL,'CTRL'); + SetSpellTrans(STRN_GOLD); + + // Init Control panel offscreen buffer + pStatusPanel = LoadFileInMemSig("CtrlPan\\Panel8.CEL",NULL,'CTRL'); + DrawBuffCel(pBtmBuff, 0, 143, BTMBUFFX, pStatusPanel, 1, 640); + DiabloFreePtr (pStatusPanel); + pStatusPanel = LoadFileInMemSig("CtrlPan\\P8Bulbs.CEL",NULL,'CTRL'); + DrawBuffCel(pLifeBuff, 0, 87, 88, pStatusPanel, 1, 88); + DrawBuffCel(pManaBuff, 0, 87, 88, pStatusPanel, 2, 88); + DiabloFreePtr (pStatusPanel); + talkflag = FALSE; + if (gbMaxPlayers != 1) { + pTalkPanel = LoadFileInMemSig("CtrlPan\\TalkPanl.CEL",NULL,'CTRL'); + DrawBuffCel(pBtmBuff, 0, 287, BTMBUFFX, pTalkPanel, 1, 640); + DiabloFreePtr (pTalkPanel); + pMultiBtns = LoadFileInMemSig("CtrlPan\\P8But2.CEL",NULL,'CTRL'); + pTalkBtns = LoadFileInMemSig("CtrlPan\\TalkButt.CEL",NULL,'CTRL'); + talkofs = 0; + sgszTalkMsg[0] = 0; + for (i = 0; i < MAX_PLRS; i++) sgbPlrTalkTbl[i] = TRUE; + for (i = 0; i < 3; i++) talkbtndown[i] = FALSE; + } + panelflag = FALSE; + + lvlbtndown = FALSE; + + pPanelButtons = LoadFileInMemSig("CtrlPan\\Panel8bu.CEL",NULL,'CTRL'); + for (i = 0; i < NUMPBTNS; i++) panbtn[i] = FALSE; + panbtndown = FALSE; + if (gbMaxPlayers == 1) numpanbtns = SINGLE_PBTNS; + else numpanbtns = MULTI_PBTNS; + + pChrButtons = LoadFileInMemSig("Data\\CharBut.CEL",NULL,'CTRL'); + for (i = 0; i < NUMCBTNS; i++) chrbtn[i] = FALSE; + chrbtndown = FALSE; + + pDurIcons = LoadFileInMemSig("Items\\DurIcons.CEL",NULL,'CTRL'); + + strcpy(infostr,""); + InitPanelStr(); + drawhpflag = TRUE; + drawmanaflag = TRUE; + chrflag = FALSE; + spselflag = FALSE; + + pSpellBkCel = LoadFileInMemSig("Data\\SpellBk.CEL",NULL,'CTRL'); + pSBkBtnCel = LoadFileInMemSig("Data\\SpellBkB.CEL",NULL,'CTRL'); + pSBkIconCels = LoadFileInMemSig("Data\\SpellI2.CEL",NULL,'CTRL'); + sbooktab = 0; + sbookflag = FALSE; + if (plr[myplr]._pClass == CLASS_WARRIOR) SpellPages[0][0] = SPL_REPAIR; + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) SpellPages[0][0] = SPL_DISARM; + else if (plr[myplr]._pClass == CLASS_SORCEROR) SpellPages[0][0] = SPL_RECHARGE; + else if (plr[myplr]._pClass == CLASS_MONK) SpellPages[0][0] = SPL_HEALOTHER; + else if (plr[myplr]._pClass == CLASS_BARD) SpellPages[0][0] = SPL_IDENTIFY; + #endif + + pQLogCel = LoadFileInMemSig("Data\\Quest.CEL",NULL,'CTRL'); + + pGBoxBuff = LoadFileInMemSig("CtrlPan\\Golddrop.cel",NULL,'CTRL'); + // Initialize gold drop variables + dropGoldFlag = FALSE; + dropGoldValue = 0; + initialDropGoldValue = 0; + initialDropGoldIndex = 0; + pentaspin = 1; + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawCtrlPan() { + CopyCtrlPan(0, 16+talkofs, 640, 128, 64, 512); + DrawInfoBox(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawButtons() +{ + for (int i = 0; i < SINGLE_PBTNS; i++) { + if (!panbtn[i]) + CopyCtrlPan(PanBtnPos[i][0], PanBtnPos[i][1]-336, 71, 20, PanBtnPos[i][0] + 64, PanBtnPos[i][1] + 160); + else + DrawCel(PanBtnPos[i][0]+64, PanBtnPos[i][1]+178, pPanelButtons, i+1, 71); + } + + if (numpanbtns == MULTI_PBTNS) { + // Draw talk button + DrawCel(151, 634, pMultiBtns, 1+panbtn[PBTN_TALK], 33); + // Draw Friend or foe button + if (FriendlyMode) { + DrawCel(591, 634, pMultiBtns, 3+panbtn[PBTN_ATTACK], 33); + } else { + DrawCel(591, 634, pMultiBtns, 5+panbtn[PBTN_ATTACK], 33); + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetupSpellSel() +{ + int x,y,i,j; + __int64 mask,spl; + int cx, cy; + + spselflag = TRUE; + x = SPLICONRIGHT; + y = 495; + cx = x - (64 - (SPLICONSIZE >> 1)); + cy = y - (160 + (SPLICONSIZE >> 1)); + if (plr[myplr]._pRSpell != -1) { + for (j = 0; j < 4; j++) { + switch(j) { + case 0: + spl = plr[myplr]._pAblSpells; + break; + case 1: + spl = plr[myplr]._pMemSpells; + break; + case 2: + spl = plr[myplr]._pScrlSpells; + break; + case 3: + spl = plr[myplr]._pISpells; + break; + } + mask = 1; + for (i = 1; i < SPL_LAST; i++) { + if ((spl & mask) != 0) { + if ((i == plr[myplr]._pRSpell) && (j == plr[myplr]._pRSplType)) { + cx = x - (64 - (SPLICONSIZE >> 1)); + cy = y - (160 + (SPLICONSIZE >> 1)); + } + x -= SPLICONSIZE; + if (x == SPLICONLEFT) { + x = SPLICONRIGHT; + y -= SPLICONSIZE; + } + } + mask = mask << 1; + } + if (spl && (x != SPLICONRIGHT)) x -= SPLICONSIZE; + if (x == SPLICONLEFT) { + x = SPLICONRIGHT; + y -= SPLICONSIZE; + } + } + } + SetCursorPos(cx,cy); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckPanelBtns() +{ + for (int i = 0; i < numpanbtns; i++) { + int x2 = PanBtnPos[i][0] + PanBtnPos[i][2]; + int y2 = PanBtnPos[i][1] + PanBtnPos[i][3]; + if ((MouseX >= PanBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[i][1]) && (MouseY <= y2)) { + panbtn[i] = TRUE; + drawbtnflag = TRUE; + panbtndown = TRUE; + } + } + + if (!spselflag) { + if (MouseX >= 565 && MouseX < 621 && MouseY >= 416 && MouseY < 472) { + SetupSpellSel(); + gamemenu_off(); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ActivatePanelBtn(int i) +{ + panbtn[i] = TRUE; + drawbtnflag = TRUE; + panbtndown = TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckDeadButtons() +{ + int x2, y2; + + x2 = PanBtnPos[PBTN_MENU][0] + PanBtnPos[PBTN_MENU][2]; + y2 = PanBtnPos[PBTN_MENU][1] + PanBtnPos[PBTN_MENU][3]; + if ((MouseX >= PanBtnPos[PBTN_MENU][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[PBTN_MENU][1]) && (MouseY <= y2)) + ActivatePanelBtn(PBTN_MENU); + x2 = PanBtnPos[PBTN_TALK][0] + PanBtnPos[PBTN_TALK][2]; + y2 = PanBtnPos[PBTN_TALK][1] + PanBtnPos[PBTN_TALK][3]; + if ((MouseX >= PanBtnPos[PBTN_TALK][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[PBTN_TALK][1]) && (MouseY <= y2)) + ActivatePanelBtn(PBTN_TALK); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DoAutoMap() { + // if we are multiplayer on the town level, DO NOT display + // the error message. Instead, the automap will show the + // game name and password + if (currlevel == 0 && gbMaxPlayers == 1) { + InitDiabloMsg(MSG_AMAPTWN); + return; + } + + // toggle automap + if (!automapflag) StartAutomap(); + else automapflag = FALSE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckPanelInfo() +{ + int i; + int x2, y2; + int pSpell, c, s; + int v; + + panelflag = FALSE; + ClearPanel(); + + for (i = 0; i < numpanbtns; i++) { + x2 = PanBtnPos[i][0] + PanBtnPos[i][2]; + y2 = PanBtnPos[i][1] + PanBtnPos[i][3]; + if ((MouseX >= PanBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= PanBtnPos[i][1]) && (MouseY <= y2)) { + if (i != PBTN_ATTACK) + strcpy(infostr, PanBtnStr[i]); + else if (FriendlyMode) + strcpy(infostr, "Player friendly"); + else + strcpy(infostr, "Player attack"); + if (PanBtnHotKey[i] != NULL) { + sprintf(tempstr, "Hotkey : %s", PanBtnHotKey[i]); + AddPanelString(tempstr, TEXT_CENTER); + } + infoclr = ICOLOR_WHITE; + panelflag = TRUE; + pinfoflag = TRUE; + } + } + + if (!spselflag) { + if ((MouseX >= 565) && (MouseX < 621) && (MouseY >= 416) && (MouseY < 472)) { + strcpy(infostr, "Select current spell button"); + infoclr = ICOLOR_WHITE; + panelflag = TRUE; + pinfoflag = TRUE; + strcpy(tempstr, "Hotkey : 's'"); + AddPanelString(tempstr, TEXT_CENTER); + pSpell = plr[myplr]._pRSpell; + if (pSpell != -1) { + switch (plr[myplr]._pRSplType) { + case 0: + sprintf(tempstr, "%s Skill", spelldata[pSpell].sSkillText); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 1: + sprintf(tempstr, "%s Spell", spelldata[pSpell].sNameText); + AddPanelString(tempstr, TEXT_CENTER); + v = plr[myplr]._pSplLvl[pSpell]+plr[myplr]._pISplLvlAdd; + if ( v < 0 ) v = 0; + if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); + else sprintf(tempstr, "Spell Level %i", v); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 2: + sprintf(tempstr, "Scroll of %s", spelldata[pSpell].sNameText); + AddPanelString(tempstr, TEXT_CENTER); + c = 0; + for (s = 0; s < plr[myplr]._pNumInv; s++) { + if ((plr[myplr].InvList[s]._itype != -1) && + ((plr[myplr].InvList[s]._iMiscId == IMID_SCROLL) || + (plr[myplr].InvList[s]._iMiscId == IMID_TSCROLL))) { + if (plr[myplr].InvList[s]._iSpell == pSpell) c++; + } + } + for (s = 0; s < MAXSPD; s++) { + if ((plr[myplr].SpdList[s]._itype != -1) && + ((plr[myplr].SpdList[s]._iMiscId == IMID_SCROLL) || + (plr[myplr].SpdList[s]._iMiscId == IMID_TSCROLL))) { + if (plr[myplr].SpdList[s]._iSpell == pSpell) c++; + } + } + if (c == 1) strcpy(tempstr, "1 Scroll"); + else sprintf(tempstr, "%i Scrolls", c); + AddPanelString(tempstr, TEXT_CENTER); + break; + case 3: + sprintf(tempstr, "Staff of %s", spelldata[pSpell].sNameText); + AddPanelString(tempstr, TEXT_CENTER); + if (plr[myplr].Hand1Item._iCharges == 1) strcpy(tempstr, "1 Charge"); + else sprintf(tempstr, "%i Charges", plr[myplr].Hand1Item._iCharges); + AddPanelString(tempstr, TEXT_CENTER); + break; + } + } + } + } + + if ((MouseX > 190) && (MouseX < 437) && (MouseY > 356) && (MouseY < 385)) + cursinvitem = CheckInvHLight(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ReleasePanelBtn() { + BYTE bMenuOff = TRUE; + + drawbtnflag = TRUE; + panbtndown = FALSE; + for (int i = 0; i < NUMPBTNS; i++) { + if (! panbtn[i]) continue; + panbtn[i] = FALSE; + + // was the mouseup in this button? + if (MouseX < PanBtnPos[i][0]) continue; + if (MouseX > PanBtnPos[i][0] + PanBtnPos[i][2]) continue; + if (MouseY < PanBtnPos[i][1]) continue; + if (MouseY > PanBtnPos[i][1] + PanBtnPos[i][3]) continue; + + switch(i) { + case PBTN_CHR : + questlog = FALSE; + chrflag = !chrflag; + break; + case PBTN_QUEST: + chrflag = FALSE; + if (!questlog) StartQuestlog(); + else questlog = FALSE; + break; + case PBTN_AMAP : + DoAutoMap(); + break; + case PBTN_MENU : + qtextflag = FALSE; + gamemenu_toggle(); + bMenuOff = FALSE; + break; + case PBTN_INV : + sbookflag = FALSE; + invflag = !invflag; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + break; + case PBTN_SBOOK : + invflag = FALSE; + if (dropGoldFlag) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + } + sbookflag = !sbookflag; + break; + case PBTN_TALK: + if (talkflag) TalkEnd(); + else TalkStart(); + break; + case PBTN_ATTACK: + FriendlyMode = !FriendlyMode; + break; + } + } + + if (bMenuOff) gamemenu_off(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void FreeControlPan() +{ + DiabloFreePtr(pBtmBuff); + DiabloFreePtr(pManaBuff); + DiabloFreePtr(pLifeBuff); + DiabloFreePtr(pPanelText); + DiabloFreePtr(pChrPanel); + DiabloFreePtr(pSpellCels); + DiabloFreePtr(pPanelButtons); + DiabloFreePtr(pMultiBtns); + DiabloFreePtr(pTalkBtns); + DiabloFreePtr(pChrButtons); + DiabloFreePtr(pDurIcons); + DiabloFreePtr(pQLogCel); + DiabloFreePtr(pSpellBkCel); + DiabloFreePtr(pSBkBtnCel); + DiabloFreePtr(pSBkIconCels); + DiabloFreePtr(pGBoxBuff); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL InfoFit(const char * p) { + long tw = 0; + while (*p) { + BYTE c = char2print(*p++); + c = fonttrans[c]; + tw += fontkern[c]; + if (tw >= 125) return FALSE; + } + + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void CPrintString(int l,const char * pszStr, int just, int pnl) { + long boffset = fontofs[pnl][l]; + + int w = 0; + if (just == TEXT_CENTER) { + long tw = 0; + const char * pszTemp = pszStr; + while (*pszTemp) { + BYTE c = char2print(*pszTemp++); + c = fonttrans[c]; + tw += fontkern[c] + 2; + } + + if (tw < 288) w = (288 - tw) >> 1; + boffset += w; + } + + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + w += fontkern[c] + 2; + if (c && (w < 288)) DrawPanelFont(boffset, c, infoclr); + boffset += fontkern[c] + 2; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void PrintInfo() { + if (talkflag) return; + + int nOffset1 = 0; + int nOffset2 = 1; + if (infostr[0] != 0) { + CPrintString(0, infostr, TEXT_CENTER, pnumlines); + nOffset1 = 1; + nOffset2 = 0; + } + + for (int i = 0; i < pnumlines; i++) + CPrintString(i+nOffset1, panelstr[i], pstrjust[i], pnumlines-nOffset2); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawInfoBox() +{ + // Erase old box + CopyCtrlPan(177, 62, 288, 60, 241, 558); + + if ((!panelflag) && (!trigflag) && (cursinvitem == -1) && (!spselflag)) { + infostr[0] = 0; + infoclr = ICOLOR_WHITE; + ClearPanel(); + } + + if ((spselflag) || (trigflag)) { + infoclr = ICOLOR_WHITE; + } else { + if (curs >= ICSTART) { + if (plr[myplr].HoldItem._itype == IT_GOLD) { + int nGold = plr[myplr].HoldItem._ivalue; + const char * get_pieces_str(int nGold); + sprintf(infostr,"%i gold %s",nGold,get_pieces_str(nGold)); + } + else if (!plr[myplr].HoldItem._iStatFlag) { + ClearPanel(); + AddPanelString("Requirements not met", TEXT_CENTER); + pinfoflag = TRUE; + } + else { + if (plr[myplr].HoldItem._iIdentified) strcpy(infostr, plr[myplr].HoldItem._iIName); + else strcpy(infostr, plr[myplr].HoldItem._iName); + if (plr[myplr].HoldItem._iMagical == IMAGIC_MAGIC) infoclr = ICOLOR_BLUE; + if (plr[myplr].HoldItem._iMagical == IMAGIC_UNIQUE) infoclr = ICOLOR_GOLD; + } + } else { + // if cursinvitem != -1 then the string will already be in infostr + // if trigflag then the string will already be set as well + if (cursitem != -1) { + // @@@ drb debug +#if 0 + +int GetLDeltaItem(); + + ClearPanel(); + ItemStruct *pi = &item[cursitem]; + strcpy(infostr, pi->_iName); + sprintf(tempstr, "Delta # = %i", GetLDeltaItem()); + AddPanelString(tempstr, TEXT_CENTER); + //sprintf(tempstr, "seed = %i", pi->_iSeed); + //AddPanelString(tempstr, TEXT_CENTER); + // @@@ drb end debug +#else + GetItemStr(cursitem); +#endif + } + if (cursobj != -1) GetObjectStr(cursobj); + if (cursmonst != -1) { + if (leveltype != 0) { + infoclr = ICOLOR_WHITE; + strcpy(infostr, monster[cursmonst].mName); + ClearPanel(); + if (monster[cursmonst]._uniqtype != 0) { + infoclr = ICOLOR_GOLD; + void PrintUniqueHistory(); + PrintUniqueHistory(); + } else PrintMonstHistory(monster[cursmonst].MType->mtype); + } else strcpy(infostr, towner[cursmonst]._tName); + } + if (cursplr != -1) { + infoclr = ICOLOR_GOLD; + strcpy(infostr, plr[cursplr]._pName); + ClearPanel(); + sprintf(tempstr, "Level : %i", plr[cursplr]._pLevel); + AddPanelString(tempstr, TEXT_CENTER); + sprintf(tempstr, "Hit Points %i of %i", (plr[cursplr]._pHitPoints >> HP_SHIFT), (plr[cursplr]._pMaxHP >> HP_SHIFT)); + AddPanelString(tempstr, TEXT_CENTER); + } + } + } + //if ((pinfoflag) && (cursmonst == -1) && (cursinvitem == -1) && (curs < ICSTART)) ClearPanel(); + if ((infostr[0] != 0) || (pnumlines != 0)) PrintInfo(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void PlrStringXY(int x1, int y, int x2,const char * pszStr,char col) { + long boffset = nBuffWTbl[y + 160] + x1 + 64; + int aw = x2 - x1 + 1; + int w = 0; + + // calculate string width + int tw = 0; + const char * pszTemp = pszStr; + while (*pszTemp) { + BYTE c = char2print(*pszTemp++); + c = fonttrans[c]; + tw += fontkern[c] + 1; + } + + if (tw < aw) w = (aw - tw) >> 1; + boffset += w; + + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + w += fontkern[c] + 1; + if (c && w < aw) DrawPanelFont(boffset, c, col); + boffset += fontkern[c] + 1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PrintStringXY(int x, int y,const char * pszStr, char col) { + long boffset = nBuffWTbl[y + 160] + x + 64; + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + if (c) DrawPanelFont(boffset, c, col); + boffset += fontkern[c] + 1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void PlrStringXY2(int x1, int y, int x2,const char * pszStr,char col,int a) { + long boffset = nBuffWTbl[y + 160] + x1 + 64; + int aw = x2 - x1 + 1; + int w = 0; + + // calculate string width + int tw = 0; + const char * pszTemp = pszStr; + while (*pszTemp) { + BYTE c = char2print(*pszTemp++); + c = fonttrans[c]; + tw += fontkern[c] + a; + } + + if (tw < aw) w = (aw - tw) >> 1; + boffset += w; + + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + w += fontkern[c] + a; + if (c && w < aw) DrawPanelFont(boffset, c, col); + boffset += fontkern[c] + a; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawChr() +{ + char c; + char chrstr[64]; + int pc; + long mind, maxd; + int hper, ac; + + DrawCel(64, 511, pChrPanel, 1, 320); + + PlrStringXY(20, 32, 151, plr[myplr]._pName, ICOLOR_WHITE); + if (plr[myplr]._pClass == CLASS_WARRIOR) PlrStringXY(168, 32, 299, "Warrior", ICOLOR_WHITE); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlrStringXY(168, 32, 299, "Rogue", ICOLOR_WHITE); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlrStringXY(168, 32, 299, "Sorceror", ICOLOR_WHITE); + else if (plr[myplr]._pClass == CLASS_MONK) PlrStringXY(168, 32, 299, "Monk", ICOLOR_WHITE); + else if (plr[myplr]._pClass == CLASS_BARD) PlrStringXY(168, 32, 299, "Bard", ICOLOR_WHITE); + #endif + + sprintf(chrstr, "%i", plr[myplr]._pLevel); + PlrStringXY(66, 69, 109, chrstr, ICOLOR_WHITE); + + sprintf(chrstr, "%li", plr[myplr]._pExperience); + PlrStringXY(216, 69, 300, chrstr, ICOLOR_WHITE); + + if (plr[myplr]._pLevel == 50) { + strcpy(chrstr, "None"); + c = ICOLOR_GOLD; + } else { + sprintf(chrstr, "%li", plr[myplr]._pNextExper); + c = ICOLOR_WHITE; + } + PlrStringXY(216, 97, 300, chrstr, c); + + sprintf(chrstr, "%i", plr[myplr]._pGold); + PlrStringXY(216, 146, 300, chrstr, ICOLOR_WHITE); + + c = ICOLOR_WHITE; + if (plr[myplr]._pIBonusAC > 0) c = ICOLOR_BLUE; + if (plr[myplr]._pIBonusAC < 0) c = ICOLOR_RED; + // rjs ac = (byte)plr[myplr]._pArmorClass+plr[myplr]._pIAC+plr[myplr]._pIBonusAC; + ac = plr[myplr]._pIAC+plr[myplr]._pIBonusAC; + ac += (plr[myplr]._pDexterity / 5); + sprintf(chrstr, "%i", ac); + PlrStringXY(258, 183, 301, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pIBonusToHit > 0) c = ICOLOR_BLUE; + if (plr[myplr]._pIBonusToHit < 0) c = ICOLOR_RED; + hper = BASE_TO_HIT + (plr[myplr]._pDexterity >> 1) + plr[myplr]._pIBonusToHit; + sprintf(chrstr, "%i%%", hper); + PlrStringXY(258, 211, 301, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pIBonusDam > 0) c = ICOLOR_BLUE; + if (plr[myplr]._pIBonusDam < 0) c = ICOLOR_RED; + mind = plr[myplr]._pIMinDam; + mind += (mind * plr[myplr]._pIBonusDam) / 100; + mind += plr[myplr]._pIBonusDamMod; + if (plr[myplr].Hand1Item._itype == IT_BOW) { + if (plr[myplr]._pClass == CLASS_ROGUE) mind += plr[myplr]._pDamageMod; + else mind += (plr[myplr]._pDamageMod >> 1); + } else mind += plr[myplr]._pDamageMod; + maxd = plr[myplr]._pIMaxDam; + maxd += (maxd * plr[myplr]._pIBonusDam) / 100; + maxd += plr[myplr]._pIBonusDamMod; + if (plr[myplr].Hand1Item._itype == IT_BOW) { + if (plr[myplr]._pClass == CLASS_ROGUE) maxd += plr[myplr]._pDamageMod; + else maxd += (plr[myplr]._pDamageMod >> 1); + } else maxd += plr[myplr]._pDamageMod; + sprintf(chrstr, "%i-%i", mind, maxd); + if ((mind >= 100) || (maxd >= 100)) + PlrStringXY2(254, 239, 305, chrstr, c, -1); + else + PlrStringXY2(258, 239, 301, chrstr, c, 0); + + // Magic Resist + if (plr[myplr]._pMagResist == 0) c = ICOLOR_WHITE; + else c = ICOLOR_BLUE; + if (plr[myplr]._pMagResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pMagResist); + else { + c = ICOLOR_GOLD; + sprintf(chrstr, "MAX"); + } + PlrStringXY(257, 276, 300, chrstr, c); + + // Fire Resist + if (plr[myplr]._pFireResist == 0) c = ICOLOR_WHITE; + else c = ICOLOR_BLUE; + if (plr[myplr]._pFireResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pFireResist); + else { + c = ICOLOR_GOLD; + sprintf(chrstr, "MAX"); + } + PlrStringXY(257, 304, 300, chrstr, c); + + // Lightning Resist + if (plr[myplr]._pLghtResist == 0) c = ICOLOR_WHITE; + else c = ICOLOR_BLUE; + if (plr[myplr]._pLghtResist < RESIST_MAX) sprintf(chrstr, "%i%%", plr[myplr]._pLghtResist); + else { + c = ICOLOR_GOLD; + sprintf(chrstr, "MAX"); + } + PlrStringXY(257, 332, 300, chrstr, c); + + c = ICOLOR_WHITE; + sprintf(chrstr, "%i", plr[myplr]._pBaseStr); + if (MaxStats[plr[myplr]._pClass][0] == plr[myplr]._pBaseStr) c = ICOLOR_GOLD; + PlrStringXY( 95, 155, 126, chrstr, c); + + c = ICOLOR_WHITE; + sprintf(chrstr, "%i", plr[myplr]._pBaseMag); + if (MaxStats[plr[myplr]._pClass][1] == plr[myplr]._pBaseMag) c = ICOLOR_GOLD; + PlrStringXY( 95, 183, 126, chrstr, c); + + c = ICOLOR_WHITE; + sprintf(chrstr, "%i", plr[myplr]._pBaseDex); + if (MaxStats[plr[myplr]._pClass][2] == plr[myplr]._pBaseDex) c = ICOLOR_GOLD; + PlrStringXY( 95, 211, 126, chrstr, c); + + c = ICOLOR_WHITE; + sprintf(chrstr, "%i", plr[myplr]._pBaseVit); + if (MaxStats[plr[myplr]._pClass][3] == plr[myplr]._pBaseVit) c = ICOLOR_GOLD; + PlrStringXY( 95, 239, 126, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pStrength > plr[myplr]._pBaseStr) c = ICOLOR_BLUE; + if (plr[myplr]._pStrength < plr[myplr]._pBaseStr) c = ICOLOR_RED; + sprintf(chrstr, "%i", plr[myplr]._pStrength); + PlrStringXY(143, 155, 173, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pMagic > plr[myplr]._pBaseMag) c = ICOLOR_BLUE; + if (plr[myplr]._pMagic < plr[myplr]._pBaseMag) c = ICOLOR_RED; + sprintf(chrstr, "%i", plr[myplr]._pMagic); + PlrStringXY(143, 183, 173, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pDexterity > plr[myplr]._pBaseDex) c = ICOLOR_BLUE; + if (plr[myplr]._pDexterity < plr[myplr]._pBaseDex) c = ICOLOR_RED; + sprintf(chrstr, "%i", plr[myplr]._pDexterity); + PlrStringXY(143, 211, 173, chrstr, c); + + c = ICOLOR_WHITE; + if (plr[myplr]._pVitality > plr[myplr]._pBaseVit) c = ICOLOR_BLUE; + if (plr[myplr]._pVitality < plr[myplr]._pBaseVit) c = ICOLOR_RED; + sprintf(chrstr, "%i", plr[myplr]._pVitality); + PlrStringXY(143, 239, 173, chrstr, c); + + // drb.patch1.start.2/05/97 + if (plr[myplr]._pStatPts > 0) { + int CalcStatDiff(int); + if (CalcStatDiff(myplr) < plr[myplr]._pStatPts) plr[myplr]._pStatPts = CalcStatDiff(myplr); + } + // drb.patch1.end.2/05/97 + // Points to distibute + if (plr[myplr]._pStatPts > 0) { + sprintf(chrstr, "%i", plr[myplr]._pStatPts); + PlrStringXY(95, 266, 126, chrstr, ICOLOR_RED);// check x y + pc = plr[myplr]._pClass; + if (plr[myplr]._pBaseStr < MaxStats[pc][0]) DrawCel(201, 319, pChrButtons, 2+chrbtn[0], 41); + if (plr[myplr]._pBaseMag < MaxStats[pc][1]) DrawCel(201, 347, pChrButtons, 4+chrbtn[1], 41); + if (plr[myplr]._pBaseDex < MaxStats[pc][2]) DrawCel(201, 376, pChrButtons, 6+chrbtn[2], 41); + if (plr[myplr]._pBaseVit < MaxStats[pc][3]) DrawCel(201, 404, pChrButtons, 8+chrbtn[3], 41); + } + + if (plr[myplr]._pMaxHP > plr[myplr]._pMaxHPBase) c = ICOLOR_BLUE; + else c = ICOLOR_WHITE; + sprintf(chrstr, "%i", (plr[myplr]._pMaxHP >> HP_SHIFT)); + PlrStringXY( 95, 304, 126, chrstr, c); + if (plr[myplr]._pHitPoints != plr[myplr]._pMaxHP) c = ICOLOR_RED; + sprintf(chrstr, "%i", (plr[myplr]._pHitPoints >> HP_SHIFT)); + PlrStringXY(143, 304, 174, chrstr, c); + + if (plr[myplr]._pMaxMana > plr[myplr]._pMaxManaBase) c = ICOLOR_BLUE; + else c = ICOLOR_WHITE; + sprintf(chrstr, "%i", (plr[myplr]._pMaxMana >> MANA_SHIFT)); + PlrStringXY( 95, 332, 126, chrstr, c); + if (plr[myplr]._pMana != plr[myplr]._pMaxMana) c = ICOLOR_RED; + sprintf(chrstr, "%i", (plr[myplr]._pMana >> MANA_SHIFT)); + PlrStringXY(143, 332, 174, chrstr, c); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void CheckLvlBtn() { + if (lvlbtndown) return; + if ((MouseX >= 40) && (MouseX <= 81) && (MouseY >= 313) && (MouseY <= 335)) + lvlbtndown = TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ReleaseLvlBtn() { + if ((MouseX >= 40) && (MouseX <= 81) && (MouseY >= 313) && (MouseY <= 335)) + chrflag = TRUE; + lvlbtndown = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawLevelUpIcon() { + int c; + + if (stextflag != STORE_NONE) return; + if (lvlbtndown) c = 3; + else c = 2; + PlrStringXY(0, 303, 120, "Level Up", ICOLOR_WHITE); + DrawCel(104, 495, pChrButtons, c, 41); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void CheckChrBtns() { + if (chrbtndown) return; + if (! plr[myplr]._pStatPts) return; + + int pc = plr[myplr]._pClass; + for (int i = 0; i < NUMCBTNS; i++) { + switch(i) { + case 0: + if (plr[myplr]._pBaseStr >= MaxStats[pc][i]) + continue; + break; + + case 1: + if (plr[myplr]._pBaseMag >= MaxStats[pc][i]) + continue; + break; + + case 2: + if (plr[myplr]._pBaseDex >= MaxStats[pc][i]) + continue; + break; + + case 3: + if (plr[myplr]._pBaseVit >= MaxStats[pc][i]) + continue; + break; + + default: + continue; + } + + int x2 = ChrBtnPos[i][0] + ChrBtnPos[i][2]; + int y2 = ChrBtnPos[i][1] + ChrBtnPos[i][3]; + if ((MouseX >= ChrBtnPos[i][0]) && (MouseX <= x2) && (MouseY >= ChrBtnPos[i][1]) && (MouseY <= y2)) { + chrbtn[i] = TRUE; + chrbtndown = TRUE; + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ReleaseChrBtn() { + chrbtndown = FALSE; + for (int i = 0; i < NUMCBTNS; i++) { + if (! chrbtn[i]) continue; + chrbtn[i] = FALSE; + + // was mouseup inside button? + if (MouseX < ChrBtnPos[i][0]) continue; + if (MouseX > ChrBtnPos[i][0] + ChrBtnPos[i][2]) continue; + if (MouseY < ChrBtnPos[i][1]) continue; + if (MouseY > ChrBtnPos[i][1] + ChrBtnPos[i][3]) continue; + + switch(i) { + case CBTN_STR : + NetSendCmdParam1(TRUE,CMD_ADDSTR,1); + plr[myplr]._pStatPts--; + break; + case CBTN_MAG : + NetSendCmdParam1(TRUE,CMD_ADDMAG,1); + plr[myplr]._pStatPts--; + break; + case CBTN_DEX : + NetSendCmdParam1(TRUE,CMD_ADDDEX,1); + plr[myplr]._pStatPts--; + break; + case CBTN_VIT : + NetSendCmdParam1(TRUE,CMD_ADDVIT,1); + plr[myplr]._pStatPts--; + break; + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int DrawDurIcon4Item(const ItemStruct * pItem, int x, int c) { + + // don't need to draw icon if there is no item + if (pItem->_itype == -1) return x; + + // don't need to draw icon if durability is high + if (pItem->_iDurability > 5) return x; + + if (c == 0) { + if (pItem->_iClass == IC_WEAP) switch(pItem->_itype) { + case IT_SWORD: + c = 2; + break; + case IT_AXE: + c = 6; + break; + case IT_BOW: + c = 7; + break; + case IT_MACE: + c = 5; + break; + case IT_STAFF: + c = 8; + break; + } + else { + c = 1; + } + } + + // choose cel to draw based on durability + if (pItem->_iDurability > 2) c += 8; + + // draw it + DrawCel(x, 495, pDurIcons, c, 32); + + // adjust position for next durability icon + return x - 40; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawDurIcon() { + if ((chrflag || questlog) && (invflag || sbookflag)) return; + + int x = 656; + if (invflag || sbookflag) x -= 320; + const PlayerStruct * p = &plr[myplr]; + x = DrawDurIcon4Item(&p->InvBody[INVLOC_HEAD],x,4); + x = DrawDurIcon4Item(&p->InvBody[INVLOC_BODY],x,3); + x = DrawDurIcon4Item(&p->InvBody[INVLOC_HAND1],x,0); + x = DrawDurIcon4Item(&p->InvBody[INVLOC_HAND2],x,0); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void RedBack() { + long ltaboff; + + if (light4flag) ltaboff = 1536; + else ltaboff = 4608; + + app_assert(gpBuffer); + if (leveltype != 4) { + __asm { + mov edi,dword ptr [gpBuffer] + add edi,122944 + + mov ebx,dword ptr [pLightTbl] + add ebx,dword ptr [ltaboff] + + mov edx,352 +_YLp: mov ecx,640 +_XLp: mov al,byte ptr [edi] + xlatb + stosb + loop _XLp + add edi,128 + dec edx + jnz _YLp + } + } else { + __asm { + mov edi,dword ptr [gpBuffer] + add edi,122944 + + mov ebx,dword ptr [pLightTbl] + add ebx,dword ptr [ltaboff] + + mov edx,352 +_YLp2: mov ecx,640 +_XLp2: mov al,byte ptr [edi] + cmp al,32 + jb _Skip + xlatb +_Skip: stosb + loop _XLp2 + add edi,128 + dec edx + jnz _YLp2 + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void PrintSBookStr(int x, int y, BOOL cjustflag,const char * pszStr, char col) { + long boffset = nBuffWTbl[y] + x + 440; + int w = 0; + + if (cjustflag) { + int tw = 0; + const char * pszTemp = pszStr; + while (*pszTemp) { + BYTE c = char2print(*pszTemp++); + c = fonttrans[c]; + tw += fontkern[c] + 1; + } + + if (tw < 222) w = (222 - tw) >> 1; + boffset += w; + } + + while (*pszStr) { + BYTE c = char2print(*pszStr++); + c = fonttrans[c]; + w += fontkern[c] + 1; + if (c && w <= 222) DrawPanelFont(boffset, c, col); + boffset += fontkern[c] + 1; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +char GetSBookTrans(int ii, BOOL townok) { + char st, sl; + + st = STRN_BLUE; + if (plr[myplr]._pISpells & (((__int64)1) << (ii-1))) st = STRN_ORANGE; + if (plr[myplr]._pAblSpells & (1 << (ii-1))) st = STRN_GOLD; + if (st == STRN_BLUE) { + if (!CheckSpell(myplr, ii, SPT_MEMORIZED, TRUE)) st = STRN_GREY; + sl = plr[myplr]._pSplLvl[ii] + plr[myplr]._pISplLvlAdd; + if (sl <= 0 ) st = STRN_GREY; + } + if ((townok) && (currlevel == 0) && (st != STRN_GREY) && (spelldata[ii].sTownSpell == FALSE)) st = STRN_GREY; + return(st); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawSpellBook() +{ + int i, ii, x, y, mind, maxd; + __int64 tspls; + char st; + int v; + + // Drawbackground + DrawCel(384, 511, pSpellBkCel, 1, 320); + + // Draw tab + //x = (sbooktab * 51) + 391; + //DrawCel(x, 508, pSBkBtnCel, 1 + sbooktab, 51); + x = (sbooktab * 76) + 391; + DrawCel(x, 508, pSBkBtnCel, 1 + sbooktab, 76); + + // Draw Spell Icons + y = 215; + tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; + for (i = 1; i < 8; i++) { + ii = SpellPages[sbooktab][i-1]; + if (ii != -1) { + if (tspls & (((__int64) 1) << (ii-1))) { + st = GetSBookTrans(ii, TRUE); + SetSpellTrans(st); + DrawSpellCel(395, y, pSBkIconCels, SpellITbl[ii], 37); + if ((ii == plr[myplr]._pRSpell) && (st == plr[myplr]._pRSplType)) { + SetSpellTrans(STRN_GOLD); + DrawSpellCel(395, y, pSBkIconCels, 43, 37); + } + PrintSBookStr(10, y-23, FALSE, spelldata[ii].sNameText, ICOLOR_WHITE); + st = GetSBookTrans(ii, FALSE); + switch (st) { + case STRN_GOLD: + strcpy(tempstr, "Skill"); + break; + case STRN_ORANGE: + sprintf(tempstr, "Staff (%i charges)", plr[myplr].Hand1Item._iCharges); + break; + default: + v = GetManaAmount(myplr, ii) >> MANA_SHIFT; + GetDamageAmt(ii, &mind, &maxd); + if (mind != -1) sprintf(tempstr, "Mana: %i Dam: %i - %i", v, mind, maxd); + else sprintf(tempstr, "Mana: %i Dam: n/a", v); + if (ii == SPL_BONESPIRIT) sprintf(tempstr, "Mana: %i Dam: 1/3 tgt hp", v); + PrintSBookStr(10, y-1, FALSE, tempstr, ICOLOR_WHITE); + + v = plr[myplr]._pSplLvl[ii]+plr[myplr]._pISplLvlAdd; + if ( v < 0 ) v = 0; + if (v == 0) sprintf(tempstr, "Spell Level 0 - Unusable"); + else sprintf(tempstr, "Spell Level %i", v); + break; + } + PrintSBookStr(10, y-12, FALSE, tempstr, ICOLOR_WHITE); + } + } + y += 43; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckSBook() +{ + int spl; + __int64 tspls; + char st; + + // Check spell icon + if ((MouseX >= 331) && (MouseX < 368) && (MouseY >= 18) && (MouseY < 314)) { + spl = (MouseY - 18) / 43; + spl = SpellPages[sbooktab][spl]; + tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; + if (spl != -1) { + if (tspls & (((__int64)1) << (spl-1))) { + st = SPT_MEMORIZED; + if (plr[myplr]._pISpells & (((__int64)1) << (spl-1))) st = SPT_ITEM; + if (plr[myplr]._pAblSpells & (1 << (spl-1))) st = SPT_ABILITY; + + plr[myplr]._pRSpell = spl; + plr[myplr]._pRSplType = st; + force_redraw = FULLDRAW; + } + } + } + // Check spell tabs + if ((MouseX >= 327) && (MouseX < 633) && (MouseY >= 320) && (MouseY < 349)) { + sbooktab = (MouseX - 327) / 76; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------* + +BOOL CheckSBookCast() +{ + int spl; + __int64 tspls; + char st; + BOOL okflag; + + if (currlevel == 0) return(FALSE); + // Check spell icon + if ((MouseX >= 327) && (MouseX < 368) && (MouseY >= 29) && (MouseY < 346)) { + spl = (MouseY - 29) / 46; + spl = SpellPages[sbooktab][spl]; + tspls = plr[myplr]._pISpells | plr[myplr]._pMemSpells | plr[myplr]._pAblSpells; + if (spl != -1) { + if (tspls & (1 << (spl-1))) { + st = SPT_MEMORIZED; + if (plr[myplr]._pISpells & (((__int64)1) << (spl-1))) st = SPT_ITEM; + if (plr[myplr]._pAblSpells & (1 << (spl-1))) st = SPT_ABILITY; + okflag = FALSE; + switch (st) { + case SPT_ABILITY : + case SPT_MEMORIZED : + okflag = CheckSpell(myplr, spl, st, FALSE); + break; + case SPT_ITEM: + okflag = UseStaffSBook(spl); + break; + } + if (okflag) { + if (spelldata[spl].sTargeted) { + plr[myplr]._pTSpell = spl; + plr[myplr]._pTSplType = st; + NewCursor(TARGET_CURS); + } + else { + plr[myplr]._pSBkSpell = spl; + plr[myplr]._pSBkSplType = st; + NetSendCmdParam1(TRUE,CMD_SBSPELL,plr[myplr]._pSBkSpell); + } + return(TRUE); + } + } + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +const char * get_pieces_str(int nGold) { + if (nGold == 1) return "piece"; + return "pieces"; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void DrawGoldBox(int gold) +{ + int i; + long xOffset; + + // Initialize + xOffset = 0; + + // Draw the box + DrawCel(415, 338, pGBoxBuff, 1, 261); + // Output the strings + sprintf(tempstr, "You have %u gold",initialDropGoldValue); + PlrStringXY(366, 87, 600, tempstr, ICOLOR_GOLD); + sprintf(tempstr, "%s. How many do", get_pieces_str(initialDropGoldValue)); + PlrStringXY(366, 103, 600, tempstr, ICOLOR_GOLD); + PlrStringXY(366, 121, 600, "you want to remove?", ICOLOR_GOLD); + + if (gold > 0) { + sprintf(tempstr, "%u", gold); + PrintStringXY(388, 140, tempstr, ICOLOR_WHITE); + } + + // Get x offset for pentagram + if (gold > 0) { + for (i = 0; i < tempstr[i] != 0; i++) { + BYTE c = char2print(tempstr[i]); + c = fonttrans[c]; + xOffset += fontkern[c]+1; + } + xOffset += 452; + } else xOffset = 450; + + // Draw the pentagram + DrawCel(xOffset, 300, pSTextSpinCels, pentaspin, 12); + // Increment the pentagram spinner + pentaspin = (pentaspin & 0x7) + 1; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +// macro to convert char to int +#define ATON(c) (c - 0x30) +// keyboard constants +#define DG_CR 0x0d +#define DG_ESC 0x1b +#define DG_BACK 0x08 + +void DropGoldType(char c) //, int ivalue) +{ + char dGoldStr[6]; + + // Check if player is dead. This should prevent the multi player death frame + // gold cheat. + if ((plr[myplr]._pHitPoints >> HP_SHIFT) <= 0) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + return; + } + + // Clear the string + memset(dGoldStr, 0x00, sizeof(dGoldStr)); + // Convert number to string + _itoa(dropGoldValue, dGoldStr, 10); + + // Carriage Return was pressed so the player wants to drop some gold + if (c == DG_CR) { + if (dropGoldValue > 0) DropGold(myplr, initialDropGoldIndex); + dropGoldFlag = FALSE; + return; + } + // Escape was pressed so the player wants to quit w/out dropping gold + if (c == DG_ESC) { + dropGoldFlag = FALSE; + dropGoldValue = 0; + return; + } + // Backspace was pressed so clear the last char in the string + if (c == DG_BACK) { + dGoldStr[strlen(dGoldStr)-1] = NULL; + dropGoldValue = atoi(dGoldStr); + return; + } + // Check to see if the player typed a number and if so update the string + if ((ATON(c) >= 0) && (ATON(c) <= 9)) { + if ((dropGoldValue == 0) && (atoi(dGoldStr) > initialDropGoldValue)) + dGoldStr[0] = c; + else { + dGoldStr[strlen(dGoldStr)] = c; + if ((atoi(dGoldStr) > initialDropGoldValue) || (strlen(dGoldStr) > strlen(dGoldStr))) + return; + } + dropGoldValue = atoi(dGoldStr); + return; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DropGold(int pnum, int cii) +{ + int c; + + if (cii <= 46) { + // Item is in the InvList + c = cii - 7; + plr[pnum].InvList[c]._ivalue -= dropGoldValue; + // Modify item cursor in the InvList + if (plr[pnum].InvList[c]._ivalue > 0) SetGoldCurs(pnum, c); + else RemoveInvItem(pnum, c); + } else { + // Item is in the SpdList + c = cii - 47; + plr[pnum].SpdList[c]._ivalue -= dropGoldValue; + // Modify item cursor in the SpdList + if (plr[pnum].SpdList[c]._ivalue > 0) SetSpdbarGoldCurs(pnum, c); + else RemoveSpdBarItem(pnum, c); + } + + // Initialize hold item to gold type + SetPlrHandItem(&plr[pnum].HoldItem, IDI_GOLD); + GetGoldSeed(pnum, &plr[pnum].HoldItem); + // Set hold item values + plr[pnum].HoldItem._ivalue = dropGoldValue; + plr[pnum].HoldItem._iStatFlag = TRUE; + // Set cursor arrow to gold + SetDropGoldCursor(pnum); + + // Recalculate players gold + plr[pnum]._pGold = CalculateGold(pnum); + + dropGoldValue = 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetDropGoldCursor(int pnum) +{ + if (plr[pnum].HoldItem._ivalue >= GOLD_VT2) + plr[pnum].HoldItem._iCurs = ITEM_5GOLD; + else { + if (plr[pnum].HoldItem._ivalue <= GOLD_VT1) + plr[pnum].HoldItem._iCurs = ITEM_1GOLD; + else + plr[pnum].HoldItem._iCurs = ITEM_3GOLD; + } + + NewCursor(plr[pnum].HoldItem._iCurs + ICSTART); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +/* +void WhiteCtrlPan(int sx, int sy, int deltax, int deltay, int dx, int dy) +{ + long dest; + + dest = (dy * 768) + dx; + __asm { + mov edi,dword ptr [pBuffer] + add edi,dword ptr [dest] + + xor ebx,ebx + mov bx,word ptr [deltax] + xor edx,edx + mov dx,word ptr [deltay] + mov eax, 0ffffffffh +_CLp: mov ecx,ebx + shr ecx,1 + jnc _Tw + stosb + jecxz _Tx +_Tw: shr ecx,1 + jnc _TLp + stosw + jecxz _Tx +_TLp: rep stosd +_Tx: add edi,768 + sub edi,ebx + dec edx + jnz _CLp + } +} +*/ + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static char * print_talk_string( + char * pszStr, + int x, + int y, + long * plOffset, + int color +) { + // move to top left of talk box + x += 264; + //y += 546; + y += 534; + + int w = x; + *plOffset = nBuffWTbl[y] + x; + while (*pszStr) { + // can we fit the next character on this row? + BYTE c = char2print(*pszStr); + c = fonttrans[c]; + w += fontkern[c] + 1; + if (w > 250+264) return pszStr; + pszStr++; + + // draw char + if (c != 0) DrawPanelFont(*plOffset, c, color); + *plOffset += fontkern[c] + 1; + } + + return NULL; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define TALK_ROW_HGT 13 +void DrawTalkBox() { + + if (!talkflag) return; + app_assert(gpBuffer); + + // erase old box + CopyCtrlPan(175, 20+talkofs, 294, 5, 239, 516); + for (int i = 0; i < 10; i++) + CopyCtrlPan(175+(i>>1), 25+i+talkofs, 293-i, 1, 239+(i>>1), 521+i); + CopyCtrlPan(185, 35+talkofs, 274, 30, 249, 531); + CopyCtrlPan(180, 65+talkofs, 284, 5, 244, 561); + for (i = 0; i < 10; i++) + CopyCtrlPan(180, 70+i+talkofs, 284+i, 1, 244, 566+i); + CopyCtrlPan(170, 80+talkofs, 310, 55, 234, 576); + + // 200,373-450,456 (screen coords) + long lOffset; + char * pszStr = sgszTalkMsg; + for (int row = 0; row < 3; row++) { + pszStr = print_talk_string(pszStr,0,row * TALK_ROW_HGT,&lOffset,ICOLOR_WHITE); + if (! pszStr) break; + } + + // don't allow string to be too long + if (pszStr) *pszStr = 0; + + // draw spinnies on last row + DrawCelP(gpBuffer + lOffset, pSTextSpinCels, tspin, 12); + tspin = (tspin & 0x7) + 1; + + // draw player names + row = 0; + for (i = 0; i < MAX_PLRS; i++) { + if (i == myplr) continue; + + // are we "talking" to this player + int nColor, nCel; + if (sgbPlrTalkTbl[i]) { + nColor = ICOLOR_GOLD; + if (talkbtndown[row]) { + if (row == 0) nCel = 3; + else nCel = 4; + DrawCel(236, 596 + (row * 18), pTalkBtns, nCel, 61); + } + } else { + nColor = ICOLOR_RED; + if (row == 0) nCel = 1; + else nCel = 2; + if (talkbtndown[row]) nCel += 4; + DrawCel(236, 596 + (row * 18), pTalkBtns, nCel, 61); + } + + if (plr[i].plractive) + print_talk_string(plr[i]._pName,46,60 + (row * 18),&lOffset,nColor); + row++; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define TALK_NAME_TOP 421 +#define TALK_NAME_LEFT 172 +#define TALK_NAME_WDT 61 +#define TALK_NAME_HGT (18*(MAX_PLRS-1)) + +BOOL talk_click() { + if (! talkflag) return FALSE; + + if (MouseX < TALK_NAME_LEFT) return FALSE; + if (MouseY < TALK_NAME_TOP) return FALSE; + if (MouseX > TALK_NAME_LEFT + TALK_NAME_WDT) return FALSE; + if (MouseY > TALK_NAME_TOP + TALK_NAME_HGT) return FALSE; + + for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; + talkbtndown[(MouseY - TALK_NAME_TOP) / 18] = TRUE; + + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void talk_release() { + if (! talkflag) return; + + for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; + + if (MouseX < TALK_NAME_LEFT) return; + if (MouseY < TALK_NAME_TOP) return; + if (MouseX > TALK_NAME_LEFT + TALK_NAME_WDT) return; + if (MouseY > TALK_NAME_TOP + TALK_NAME_HGT) return; + + int pnum = (MouseY - TALK_NAME_TOP) / 18; + for (i = 0; (i < MAX_PLRS) && (pnum != -1); i++) + //if ((i != myplr) && plr[i].plractive) pnum--; + if (i != myplr) pnum--; + if (i <= MAX_PLRS) sgbPlrTalkTbl[i - 1] = !sgbPlrTalkTbl[i - 1]; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void TalkStart() { + if (gbMaxPlayers == 1) return; + talkflag = TRUE; + talkofs = 144; + sgszTalkMsg[0] = 0; + tspin = 1; + for (int i = 0; i < 3; i++) talkbtndown[i] = FALSE; + force_redraw = FULLDRAW; + + // reset history position + sgbTalkSavePos = sgbNextTalkSave; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void TalkEnd() { + talkflag = FALSE; + talkofs = 0; + force_redraw = FULLDRAW; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void TalkSendMsg() { + + if (sgszTalkMsg[0] != 0) { + // send message to all players who have flag set + DWORD sendmask = 0; + for (int i = 0; i < MAX_PLRS; i++) + if (sgbPlrTalkTbl[i]) sendmask |= 1 << i; + NetSendString(sendmask,sgszTalkMsg); + + // save msg in history buffer if it is unique + for (i = 0; i < MAX_TALK_SAVES; i++) { + if (! strcmp(sgszTalkSaveMsg[i],sgszTalkMsg)) + break; + } + if (i >= MAX_TALK_SAVES) { + // string is unique -- save in history buffer + strcpy(sgszTalkSaveMsg[sgbNextTalkSave],sgszTalkMsg); + sgbNextTalkSave++; + sgbNextTalkSave &= MAX_TALK_SAVES - 1; + } + else { + // string is not unique -- swap curr string with non-unique + BYTE bTemp = sgbNextTalkSave - 1; + bTemp &= MAX_TALK_SAVES - 1; + if (i != bTemp) { + strcpy(sgszTalkSaveMsg[i],sgszTalkSaveMsg[bTemp]); + strcpy(sgszTalkSaveMsg[bTemp],sgszTalkMsg); + } + } + + // reset history position + sgbTalkSavePos = sgbNextTalkSave; + + // reset talk string + sgszTalkMsg[0] = 0; + } + + TalkEnd(); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL Talk_wm_char(WPARAM wKey) { + if (gbMaxPlayers == 1) return FALSE; + if (! talkflag) return FALSE; + if (wKey < 32) return FALSE; + + int i = strlen(sgszTalkMsg); + if (i < (MAX_SEND_STR_LEN-2)) { + sgszTalkMsg[i] = (char) wKey; + sgszTalkMsg[i+1] = 0; + } + + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void talk_history(int nDelta) { + for (int i = 0; i < MAX_TALK_SAVES; i++) { + sgbTalkSavePos += nDelta; + sgbTalkSavePos &= MAX_TALK_SAVES - 1; + if (! sgszTalkSaveMsg[sgbTalkSavePos][0]) continue; + + // we found a string in the history + strcpy(sgszTalkMsg,sgszTalkSaveMsg[sgbTalkSavePos]); + break; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL Talk_wm_keydown(WPARAM wKey) { + // only in multiplayer + if (gbMaxPlayers == 1) return FALSE; + if (! talkflag) return FALSE; + + if (wKey == VK_SPACE) { + // grab keystroke so + // program doesn't get it + } + else if (wKey == VK_ESCAPE) { + TalkEnd(); + } + else if (wKey == VK_RETURN) { + TalkSendMsg(); + } + else if (wKey == VK_BACK) { + int i = strlen(sgszTalkMsg); + if (i > 0) sgszTalkMsg[i-1] = 0; + } + else if (wKey == VK_DOWN) { + talk_history(+1); + } + else if (wKey == VK_UP) { + talk_history(-1); + } + else { + return FALSE; + } + + return TRUE; +} + + +//****************************************************************** +// conversion table -- converts funky ANSI/OEM chars to ASCII +// NOTE: only '\0' is allowed to translate to zero +// map all other characters into range 32..127 +//****************************************************************** +const BYTE gbFontTransTbl[256] = { + // control characters + 0, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 0x07 + 1, 1, 1, 1, 1, 1, 1, 1, // 0x08 - 0x0f + 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 0x17 + 1, 1, 1, 1, 1, 1, 1, 1, // 0x18 - 0x1f + + // punctuation/digits + ' ', '!', '"', '#', '$', '%', '&', '\'',// 0x20 - 0x27 + '(', ')', '*', '+', ',', '-', '.', '/', // 0x28 - 0x2f + '0', '1', '2', '3', '4', '5', '6', '7', // 0x30 - 0x37 + '8', '9', ':', ';', '<', '=', '>', '?', // 0x38 - 0x3f + + // uppercase + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', // 0x40 - 0x47 + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', // 0x48 - 0x4f + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', // 0x50 - 0x57 + 'X', 'Y', 'Z', '[', '\\',']', '^', '_', // 0x58 - 0x5f + + // lowercase + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', // 0x60 - 0x67 + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // 0x68 - 0x6f + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', // 0x70 - 0x77 + 'x', 'y', 'z', '{', '|', '}', '~', 1, // 0x78 - 0x7f + + 'C', 'u', 'e', 'a', 'a', 'a', 'a', 'c', // 0x80 - 0x87 + 'e', 'e', 'e', 'i', 'i', 'i', 'A', 'A', // 0x88 - 0x8f + 'E', 'a', 'A', 'o', 'o', 'o', 'u', 'u', // 0x90 - 0x97 + 'y', 'O', 'U', 'c', 'L', 'Y', 'P', 'f', // 0x98 - 0x9f + + 'a', 'i', 'o', 'u', 'n', 'N', 'a', 'o', // 0xa0 - 0xa7 + '?', 1, 1, 1, 1, '!', '<', '>', // 0xa8 - 0xaf + 'o', '+', '2', '3', '\'','u', 'P', '.', // 0xb0 - 0xb7 + ',', '1', '0', '>', 1, 1, 1, '?', // 0xb8 - 0xbf + + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'C', // 0xc0 - 0xc7 + 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', // 0xc8 - 0xcf + 'D', 'N', 'O', 'O', 'O', 'O', 'O', 'X', // 0xd0 - 0xd7 + '0', 'U', 'U', 'U', 'U', 'Y', 'b', 'B', // 0xd8 - 0xdf + + 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', // 0xe0 - 0xe7 + 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', // 0xe8 - 0xef + 'o', 'n', 'o', 'o', 'o', 'o', 'o', '/', // 0xf0 - 0xf7 + '0', 'u', 'u', 'u', 'u', 'y', 'b', 'y', // 0xf8 - 0xff +}; diff --git a/src/SPELLDAT.CPP b/src/SPELLDAT.CPP new file mode 100644 index 0000000..12d982c --- /dev/null +++ b/src/SPELLDAT.CPP @@ -0,0 +1,1127 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Spells Data file +** +** (C)1996 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/SPELLDAT.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "effects.h" +#include "spelldat.h" +#include "spells.h" +#include "missiles.h" + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +SpellData spelldata[SPL_LAST] = +{ + { SPL_NONE, // #defines name of spell for ease of use + 0, // base cost in mana + NULL, // spell type (fire, light, misc) + NULL, // text name of spell + NULL, // text name of spell if it can be a skill + 0, // lvl book can be found + 0, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 0, // min intelligence to use + NULL, // sfx to use + { NULL, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 0, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + + { SPL_FIREBOLT, // #defines name of spell for ease of use + 6, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Firebolt", // text name of spell + "Firebolt", // text name of spell if it can be a skill + 1, // lvl book can be found + 1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 15, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_FIREBOLT, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 3, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 1000, // book cost + 50 }, // scroll cost + + { SPL_HEAL, // #defines name of spell for ease of use + 5, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Healing", // text name of spell + NULL, // text name of spell if it can be a skill + 1, // lvl book can be found + 1, // lvl staff can be found + FALSE, // Targeted spell? + TRUE, // Avail in town? + 17, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_HEAL, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 1, // min mana for use + 20, // min number of staff charges + 40, // max number of staff charges + 1000, // book cost + 50 }, // scroll cost + + { SPL_LIGHTNING, // #defines name of spell for ease of use + 10, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Lightning", // text name of spell + NULL, // text name of spell if it can be a skill + 4, // lvl book can be found + 3, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 20, // min intelligence to use + IS_CAST4, // sfx to use + { MIT_LIGHTCTRL, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 6, // min mana for use + 20, // min number of staff charges + 60, // max number of staff charges + 3000, // book cost + 150 }, // scroll cost + + { SPL_FLASH, // #defines name of spell for ease of use + 30, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Flash", // text name of spell + NULL, // text name of spell if it can be a skill + 5, // lvl book can be found + 4, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 33, // min intelligence to use + IS_CAST4, // sfx to use + { MIT_FLASH, MIT_FLASH2, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 16, // min mana for use + 20, // min number of staff charges + 40, // max number of staff charges + 7500, // book cost + 500 }, // scroll cost + + { SPL_IDENTIFY, // #defines name of spell for ease of use + 13, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Identify", // text name of spell + "Identify", // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + TRUE, // Avail in town? + 23, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_IDENTIFY, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 1, // min mana for use + 8, // min number of staff charges + 12, // max number of staff charges + 0, // book cost + 100 }, // scroll cost + + { SPL_WALL, // #defines name of spell for ease of use + 28, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Fire Wall", // text name of spell + NULL, // text name of spell if it can be a skill + 3, // lvl book can be found + 2, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 27, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_FIREWALLC, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 16, // min mana for use + 8, // min number of staff charges + 16, // max number of staff charges + 6000, // book cost + 400 }, // scroll cost + + { SPL_TOWN, // #defines name of spell for ease of use + 35, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Town Portal", // text name of spell + NULL, // text name of spell if it can be a skill + 3, // lvl book can be found + 3, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 20, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_TOWN, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 18, // min mana for use + 8, // min number of staff charges + 12, // max number of staff charges + 3000, // book cost + 200 }, // scroll cost + + { SPL_STONE, // #defines name of spell for ease of use + 60, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Stone Curse", // text name of spell + NULL, // text name of spell if it can be a skill +#if IS_VERSION(RETAIL) + 6, // lvl book can be found + 5, // lvl staff can be found +#else + -1,-1, +#endif + TRUE, // Targeted spell? + FALSE, // Avail in town? + 51, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_STONE, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 40, // min mana for use + 8, // min number of staff charges + 16, // max number of staff charges + 12000, // book cost + 800 }, // scroll cost + + { SPL_INFRA, // #defines name of spell for ease of use + 40, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Infravision", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 36, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_INFRA, NULL, NULL }, // missiles to launch per casting + 5, // mana adj per spell lvl + 20, // min mana for use + 0, // min number of staff charges + 0, // max number of staff charges + 0, // book cost + 600 }, // scroll cost + + { SPL_PHASE, // #defines name of spell for ease of use + 12, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Phasing", // text name of spell + NULL, // text name of spell if it can be a skill + 7, // lvl book can be found + 6, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 39, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_PHASE, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 4, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 3500, // book cost + 200 }, // scroll cost + + { SPL_MANASHLD, // #defines name of spell for ease of use + 33, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Mana Shield", // text name of spell + NULL, // text name of spell if it can be a skill + 6, // lvl book can be found + 5, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 25, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_MANASHIELD, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 33, // min mana for use + 4, // min number of staff charges + 10, // max number of staff charges + 16000, // book cost + 1200 }, // scroll cost + + { SPL_FIREBALL, // #defines name of spell for ease of use + 16, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Fireball", // text name of spell + NULL, // text name of spell if it can be a skill + 8, // lvl book can be found + 7, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 48, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_FIREBALL, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 10, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 8000, // book cost + 300 }, // scroll cost + + { SPL_GUARDIAN, // #defines name of spell for ease of use + 50, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Guardian", // text name of spell + NULL, // text name of spell if it can be a skill +#if IS_VERSION(RETAIL) + 9, // lvl book can be found + 8, // lvl staff can be found +#else + -1,-1, +#endif + TRUE, // Targeted spell? + FALSE, // Avail in town? + 61, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_GUARDIAN, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 30, // min mana for use + 16, // min number of staff charges + 32, // max number of staff charges + 14000, // book cost + 950 }, // scroll cost + + { SPL_CHAIN, // #defines name of spell for ease of use + 30, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Chain Lightning", // text name of spell + NULL, // text name of spell if it can be a skill + 8, // lvl book can be found + 7, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 54, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_CHAIN, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 18, // min mana for use + 20, // min number of staff charges + 60, // max number of staff charges + 11000, // book cost + 750 }, // scroll cost + + { SPL_WAVE, // #defines name of spell for ease of use + 35, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Flame Wave", // text name of spell + NULL, // text name of spell if it can be a skill + 9, // lvl book can be found + 8, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 54, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_WAVE, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 20, // min mana for use + 20, // min number of staff charges + 40, // max number of staff charges + 10000, // book cost + 650 }, // scroll cost + + { SPL_DOOM, // #defines name of spell for ease of use + 0, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Doom Serpents", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 0, // min intelligence to use + IS_CAST2, // sfx to use + { NULL, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 0, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + + { SPL_BLOODR, // #defines name of spell for ease of use + 0, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Blood Ritual", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 0, // min intelligence to use + IS_CAST2, // sfx to use + { NULL, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 0, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + + { SPL_NOVA, // #defines name of spell for ease of use + 60, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Nova", // text name of spell + NULL, // text name of spell if it can be a skill + 14, // lvl book can be found + 10, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 87, // min intelligence to use + IS_CAST4, // sfx to use + { MIT_NOVA, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 35, // min mana for use + 16, // min number of staff charges + 32, // max number of staff charges + 21000, // book cost + 1300 }, // scroll cost + + { SPL_INVIS, // #defines name of spell for ease of use + 0, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Invisibility", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 0, // min intelligence to use + IS_CAST2, // sfx to use + { NULL, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 0, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + + { SPL_FLAME, // #defines name of spell for ease of use + 11, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Inferno", // text name of spell + NULL, // text name of spell if it can be a skill + 3, // lvl book can be found + 2, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 20, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_FLAMEC, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 6, // min mana for use + 20, // min number of staff charges + 40, // max number of staff charges + 2000, // book cost + 100 }, // scroll cost + + { SPL_GOLEM, // #defines name of spell for ease of use + 100, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Golem", // text name of spell + NULL, // text name of spell if it can be a skill +#if IS_VERSION(RETAIL) + 11, // lvl book can be found + 9, // lvl staff can be found +#else + -1,-1, +#endif + FALSE, // Targeted spell? + FALSE, // Avail in town? + 81, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_GOLEM, NULL, NULL }, // missiles to launch per casting + 6, // mana adj per spell lvl + 60, // min mana for use + 16, // min number of staff charges + 32, // max number of staff charges + 18000, // book cost + 1100 }, // scroll cost + + #if 0 + { SPL_BLOODB, // #defines name of spell for ease of use + 0, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Blood Boil", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 0, // min intelligence to use + IS_CAST8, // sfx to use + { NULL, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 0, // min mana for use + 0, // min number of staff charges + 0, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + #else + { SPL_RAGE, // #defines name of spell for ease of use + 15, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Rage", // text name of spell + "Rage", // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 0, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_RAGE, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 1, // min mana for use + 0, // min number of staff charges + 0, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + #endif + + { SPL_TELE, // #defines name of spell for ease of use + 35, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Teleport", // text name of spell + NULL, // text name of spell if it can be a skill + 14, // lvl book can be found + 12, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 105, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_TELE, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 15, // min mana for use + 16, // min number of staff charges + 32, // max number of staff charges + 20000, // book cost + 1250 }, // scroll cost + + { SPL_APOCA, // #defines name of spell for ease of use + 150, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Apocalypse", // text name of spell + NULL, // text name of spell if it can be a skill +#if IS_VERSION(RETAIL) + 19, // lvl book can be found + 15, // lvl staff can be found +#else + -1,-1, +#endif + FALSE, // Targeted spell? + FALSE, // Avail in town? + 149, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_APOCA, NULL, NULL }, // missiles to launch per casting + 6, // mana adj per spell lvl + 90, // min mana for use + 8, // min number of staff charges + 12, // max number of staff charges + 30000, // book cost + 2000 }, // scroll cost + + { SPL_ETHER, // #defines name of spell for ease of use + 100, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Etherealize", // text name of spell + NULL, // text name of spell if it can be a skill +#if IS_VERSION(RETAIL) + -1, // lvl book can be found + -1, // lvl staff can be found +#else + -1,-1, +#endif + FALSE, // Targeted spell? + FALSE, // Avail in town? + 93, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_ETHER, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 100, // min mana for use + 2, // min number of staff charges + 6, // max number of staff charges + 26000, // book cost + 1600 }, // scroll cost + + { SPL_REPAIR, // #defines name of spell for ease of use + 0, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Item Repair", // text name of spell + "Item Repair", // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + TRUE, // Avail in town? + -1, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_REPAIR, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 0, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + + { SPL_RECHARGE, // #defines name of spell for ease of use + 0, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Staff Recharge", // text name of spell + "Staff Recharge", // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + TRUE, // Avail in town? + -1, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_RECHARGE, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 0, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + + { SPL_DISARM, // #defines name of spell for ease of use + 0, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Trap Disarm", // text name of spell + "Trap Disarm", // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + -1, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_DISARM, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 0, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 0, // book cost + 0 }, // scroll cost + + { SPL_ELEMENT, // #defines name of spell for ease of use + 35, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Elemental", // text name of spell + NULL, // text name of spell if it can be a skill +#if IS_VERSION(RETAIL) + 8, // lvl book can be found + 6, // lvl staff can be found +#else + -1,-1, +#endif + FALSE, // Targeted spell? + FALSE, // Avail in town? + 68, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_ELEMENT, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 20, // min mana for use + 20, // min number of staff charges + 60, // max number of staff charges + 10500, // book cost + 700 }, // scroll cost + + { SPL_CBOLT, // #defines name of spell for ease of use + 6, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Charged Bolt", // text name of spell + NULL, // text name of spell if it can be a skill + 1, // lvl book can be found + 1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 25, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_CBOLT, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 6, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 1000, // book cost + 50 }, // scroll cost + + { SPL_HBOLT, // #defines name of spell for ease of use + 7, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Holy Bolt", // text name of spell + NULL, // text name of spell if it can be a skill + 1, // lvl book can be found + 1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 20, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_HBOLT, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 3, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 1000, // book cost + 50 }, // scroll cost + + { SPL_RESURRECT, // #defines name of spell for ease of use + 20, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Resurrect", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + 5, // lvl staff can be found + FALSE, // Targeted spell? + TRUE, // Avail in town? + 30, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_RESURRECT, NULL, NULL }, // missiles to launch per casting + 0, // mana adj per spell lvl + 20, // min mana for use + 4, // min number of staff charges + 10, // max number of staff charges + 4000, // book cost + 250 }, // scroll cost + + { SPL_TELEKINESIS, // #defines name of spell for ease of use + 15, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Telekinesis", // text name of spell + NULL, // text name of spell if it can be a skill + 2, // lvl book can be found + 2, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 33, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_TELEKINESIS, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 8, // min mana for use + 20, // min number of staff charges + 40, // max number of staff charges + 2500, // book cost + 200 }, // scroll cost + + { SPL_HEALOTHER, // #defines name of spell for ease of use + 5, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Heal Other", // text name of spell + NULL, // text name of spell if it can be a skill + 1, // lvl book can be found + 1, // lvl staff can be found + FALSE, // Targeted spell? + TRUE, // Avail in town? + 17, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_HEALOTHER, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 1, // min mana for use + 20, // min number of staff charges + 40, // max number of staff charges + 1000, // book cost + 50 }, // scroll cost + + { SPL_BSTAR, // #defines name of spell for ease of use + 25, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Blood Star", // text name of spell + NULL, // text name of spell if it can be a skill +#if IS_VERSION(RETAIL) + 14, // lvl book can be found + 13, // lvl staff can be found +#else + -1,-1, +#endif + FALSE, // Targeted spell? + FALSE, // Avail in town? + 70, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_FLARE, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 14, // min mana for use + 20, // min number of staff charges + 60, // max number of staff charges + 27500, // book cost + 1800 }, // scroll cost + + { SPL_BONESPIRIT, // #defines name of spell for ease of use + 24, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Bone Spirit", // text name of spell + NULL, // text name of spell if it can be a skill +#if IS_VERSION(RETAIL) + 9, // lvl book can be found + 7, // lvl staff can be found +#else + -1,-1, +#endif + FALSE, // Targeted spell? + FALSE, // Avail in town? + 34, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_BONESPIRIT, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 12, // min mana for use + 20, // min number of staff charges + 60, // max number of staff charges + 11500, // book cost + 800 }, // scroll cost + + { SPL_MANA, // #defines name of spell for ease of use + 255, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Mana", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + 5, // lvl staff can be found + FALSE, // Targeted spell? + TRUE, // Avail in town? + 17, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_MANA, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 1, // min mana for use + 12, // min number of staff charges + 24, // max number of staff charges + 1000, // book cost + 50 }, // scroll cost + + { SPL_FMANA, // #defines name of spell for ease of use + 255, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "the Magi", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + 20, // lvl staff can be found + FALSE, // Targeted spell? + TRUE, // Avail in town? + 45, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_FMANA, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 1, // min mana for use + 15, // min number of staff charges + 30, // max number of staff charges + 100000, // book cost + 200 }, // scroll cost + + { SPL_RANDOM, // #defines name of spell for ease of use + 255, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "the Jester", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + 4, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 30, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_RANDOM, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 1, // min mana for use + 15, // min number of staff charges + 30, // max number of staff charges + 100000, // book cost + 200 }, // scroll cost + + { SPL_LTWALL, // #defines name of spell for ease of use + 28, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Lightning Wall", // text name of spell + NULL, // text name of spell if it can be a skill + 3, // lvl book can be found + 2, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 27, // min intelligence to use + IS_CAST4, // sfx to use + { MIT_LIGHTWALLC, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 16, // min mana for use + 8, // min number of staff charges + 16, // max number of staff charges + 6000, // book cost + 400 }, // scroll cost + + { SPL_IMMOLATION, // #defines name of spell for ease of use + 60, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Immolation", // text name of spell + NULL, // text name of spell if it can be a skill + 14, // lvl book can be found + 10, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 87, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_IMMOLATION, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 35, // min mana for use + 16, // min number of staff charges + 32, // max number of staff charges + 21000, // book cost + 1300 }, // scroll cost + + { SPL_TELESTAIRS, // #defines name of spell for ease of use + 35, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Warp", // text name of spell + NULL, // text name of spell if it can be a skill + 3, // lvl book can be found + 3, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 25, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_TELESTAIRS, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 18, // min mana for use + 8, // min number of staff charges + 12, // max number of staff charges + 3000, // book cost + 200 }, // scroll cost + + { SPL_REFLECT, // #defines name of spell for ease of use + 35, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Reflect", // text name of spell + NULL, // text name of spell if it can be a skill + 3, // lvl book can be found + 3, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 25, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_REFLECT, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 15, // min mana for use + 8, // min number of staff charges + 12, // max number of staff charges + 3000, // book cost + 200 }, // scroll cost + + { SPL_BERSERK, // #defines name of spell for ease of use + 35, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Berserk", // text name of spell + NULL, // text name of spell if it can be a skill + 3, // lvl book can be found + 3, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 35, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_BERSERK, NULL, NULL }, // missiles to launch per casting + 3, // mana adj per spell lvl + 15, // min mana for use + 8, // min number of staff charges + 12, // max number of staff charges + 3000, // book cost + 200 }, // scroll cost + + { SPL_RINGOFFIRE, // #defines name of spell for ease of use + 28, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Ring of Fire", // text name of spell + NULL, // text name of spell if it can be a skill + 5, // lvl book can be found + 5, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 27, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_FLAMEBOX, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 16, // min mana for use + 8, // min number of staff charges + 16, // max number of staff charges + 6000, // book cost + 400 }, // scroll cost + + { SPL_SHOWMAGITEMS, // #defines name of spell for ease of use + 15, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Search", // text name of spell + "Search", // text name of spell if it can be a skill + 1, // lvl book can be found + 3, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 25, // min intelligence to use + IS_CAST6, // sfx to use + { MIT_SHOWMAGITEMS, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 1, // min mana for use + 8, // min number of staff charges + 12, // max number of staff charges + 3000, // book cost + 200 }, // scroll cost + + { SPL_RUNEOFFIRE, // #defines name of spell for ease of use + 255, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Rune of Fire", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 48, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_RUNEOFFIRE, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 10, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 8000, // book cost + 300 }, // scroll cost + + { SPL_RUNEOFLIGHT, // #defines name of spell for ease of use + 255, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Rune of Light", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 48, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_RUNEOFLIGHT, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 10, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 8000, // book cost + 300 }, // scroll cost + + { SPL_RUNEOFNOVA, // #defines name of spell for ease of use + 255, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Rune of Nova", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 48, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_RUNEOFNOVA, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 10, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 8000, // book cost + 300 }, // scroll cost + + { SPL_RUNEOFIMMOLATION, // #defines name of spell for ease of use + 255, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Rune of Immolation", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 48, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_RUNEOFIMMOLATION, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 10, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 8000, // book cost + 300 }, // scroll cost + + { SPL_RUNEOFSTONE, // #defines name of spell for ease of use + 255, // base cost in mana + ST_MISC, // spell type (fire, light, misc) + "Rune of Stone", // text name of spell + NULL, // text name of spell if it can be a skill + -1, // lvl book can be found + -1, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 48, // min intelligence to use + IS_CAST8, // sfx to use + { MIT_RUNEOFSTONE, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 10, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 8000, // book cost + 300 }, // scroll cost + +#if defined (HELLFIRE2) + { SPL_RINGOFLIGHT, // #defines name of spell for ease of use + 28, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Ring of Light", // text name of spell + NULL, // text name of spell if it can be a skill + 6, // lvl book can be found + 6, // lvl staff can be found + TRUE, // Targeted spell? + FALSE, // Avail in town? + 23, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_LIGHTBOX, NULL, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 16, // min mana for use + 8, // min number of staff charges + 16, // max number of staff charges + 6000, // book cost + 400 }, // scroll cost + + { SPL_AURA, // #defines name of spell for ease of use + 30, // base cost in mana + ST_LIGHT, // spell type (fire, light, misc) + "Aura", // text name of spell + NULL, // text name of spell if it can be a skill + 1, // lvl book can be found + 1, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 33, // min intelligence to use + IS_CAST4, // sfx to use + { MIT_AURA, MIT_AURA2, NULL }, // missiles to launch per casting + 2, // mana adj per spell lvl + 16, // min mana for use + 20, // min number of staff charges + 40, // max number of staff charges + 7500, // book cost + 500 }, // scroll cost + + { SPL_SPIRALFIREBALL, // #defines name of spell for ease of use + 6, // base cost in mana + ST_FIRE, // spell type (fire, light, misc) + "Spiral Firebolt", // text name of spell + NULL, // text name of spell if it can be a skill + 1, // lvl book can be found + 1, // lvl staff can be found + FALSE, // Targeted spell? + FALSE, // Avail in town? + 15, // min intelligence to use + IS_CAST2, // sfx to use + { MIT_SPIRALFIREBALL, NULL, NULL }, // missiles to launch per casting + 1, // mana adj per spell lvl + 3, // min mana for use + 40, // min number of staff charges + 80, // max number of staff charges + 1000, // book cost + 50 }, // scroll cost +#endif // HELLFIRE2 +}; diff --git a/src/SPELLDAT.H b/src/SPELLDAT.H new file mode 100644 index 0000000..988b78d --- /dev/null +++ b/src/SPELLDAT.H @@ -0,0 +1,53 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/SPELLDAT.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define ST_FIRE 0 +#define ST_LIGHT 1 +#define ST_MISC 2 + +#define MA_MAX 255 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + BYTE sName; // #defines name of spell for ease of use + BYTE sManaCost; // base cost in mana + BYTE sType; // spell type (fire, light, misc) + char *sNameText; // text name of spell + char *sSkillText; // text name of spell if can be a skill + int sBookLvl; // lvl book can be found + int sStaffLvl; // lvl staff can be found + BOOL sTargeted; // Targeted spell? + BOOL sTownSpell; // Avail in town? + int sMinInt; // min intelligence to use + BYTE sSFX; // sfx to use + BYTE sMissiles[3]; // missiles to launch per casting + BYTE sManaAdj; // mana adj per spell lvl + BYTE sMinMana; // min mana for use + int sStaffMin; // min staff charges + int sStaffMax; // max staff charges + int sBookCost; // book cost + int sStaffCost; // staff cost +} SpellData; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern SpellData spelldata[]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ diff --git a/src/SPELLS.CPP b/src/SPELLS.CPP new file mode 100644 index 0000000..8bf608d --- /dev/null +++ b/src/SPELLS.CPP @@ -0,0 +1,255 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Spells file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/SPELLS.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "engine.h" +#include "sound.h" +#include "spells.h" +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "monster.h" +#include "cursor.h" +#include "missiles.h" +#include "control.h" +#include "inv.h" +#include "spelldat.h" +#include "gamemenu.h" + +extern void StartStand(int, int); + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +int GetManaAmount(int id, int sn) +{ + int i; + int sl, ma, adj; + + // get total mana adjustments + adj = 0; + sl = plr[id]._pSplLvl[sn] + plr[id]._pISplLvlAdd - 1; + if (sl < 0 ) sl = 0; + for (i = sl; i > 0; i--) adj += spelldata[sn].sManaAdj; + + // special cases for adjustments + //if (sn == SPL_CBOLT) adj = -adj; + if (sn == SPL_FIREBOLT) adj = adj >> 1; + if (sn == SPL_RESURRECT && sl > 0) { + adj = 0; + for (i = sl; i > 0; i--) adj += spelldata[sn].sManaCost >> 3; + } + + // calc mana cost with adj + if (spelldata[sn].sManaCost == MA_MAX) + ma = (((BYTE)plr[id]._pMaxManaBase) - adj) << MANA_SHIFT; + else + ma = (spelldata[sn].sManaCost - adj) << MANA_SHIFT; + + // special cases for mana cost + if (sn == SPL_HEAL) ma = ((plr[id]._pLevel << 1) + spelldata[SPL_HEAL].sManaCost - adj) << MANA_SHIFT; + if (sn == SPL_HEALOTHER) ma = ((plr[id]._pLevel << 1) + spelldata[SPL_HEAL].sManaCost - adj) << MANA_SHIFT; + if (sn == SPL_RESURRECT) { + adj = 0; + for (i = sl; i > 0; i--) adj += spelldata[sn].sManaCost; + } + + // calc mana cost with class adj + if (plr[id]._pClass == CLASS_SORCEROR) + { + ma >>= 1; + } + else if (plr[id]._pClass == CLASS_ROGUE || + plr[id]._pClass == CLASS_MONK || + plr[id]._pClass == CLASS_BARD) + { + ma -= (ma >> 2); + } + + // total final mana amount + if (spelldata[sn].sMinMana > (ma >> MANA_SHIFT)) ma = spelldata[sn].sMinMana << MANA_SHIFT; + //if (ma <= 0) ma = 1 << MANA_SHIFT; + ma = (ma * (100 - plr[id]._pISplCost)) / 100; + + return(ma); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void UseMana(int id, int sn) +{ + int ma; + + if (id != myplr) return; + // calc mana amounts seperated by the way spell was cast + switch (plr[id]._pSplType) { + case SPT_ABILITY: + case SPT_NONE: + break; + + case SPT_SCROLL: + RemoveScroll(id); + break; + + case SPT_ITEM: + UseStaffCharge(id); + break; + + case SPT_MEMORIZED: +#if CHEATS + if (!cheatflag) { + ma = GetManaAmount(id, sn); + plr[id]._pMana -= ma; + plr[id]._pManaBase -= ma; + drawmanaflag = TRUE; + } +#else + ma = GetManaAmount(id, sn); + plr[id]._pMana -= ma; + plr[id]._pManaBase -= ma; + drawmanaflag = TRUE; +#endif + break; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL CheckSpell(int id, int sn, char st, BOOL manaonly) +{ + int ma; + + // various checks to see if a player can cast a spell (assumes they + // already have casting available by some means, staff, scroll, etc.) +#if CHEATS + if (cheatflag) return(TRUE); +#endif + if ((!manaonly) && (curs != GLOVE_CURS)) return(FALSE); + if (st == SPT_ABILITY) return(TRUE); + + if ((GetSpellLevel(id, sn)) <= 0) return(FALSE); + + ma = GetManaAmount(id, sn); + if (plr[id]._pMana < ma) return(FALSE); + + return(TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void CastSpell(int id, int spl, int sx, int sy, int dx, int dy, int caster, int spllvl) +{ + int i; + int dir; + + switch (caster) { + case MI_PLR: + dir = plr[id]._pdir; + caster = MI_ENEMYMONST; // delete later + if (spl == SPL_WALL || spl == SPL_LTWALL) dir = plr[id]._pVar3; + break; + case MI_MONST: + dir = monster[id]._mdir; + break; + } + + for (i = 0; (spelldata[spl].sMissiles[i] != NULL) && (i < 3); i++) + AddMissile(sx, sy, dx, dy, dir, spelldata[spl].sMissiles[i], caster, id, 0, spllvl); + + if (spelldata[spl].sMissiles[0] == MIT_TOWN) UseMana(id, SPL_TOWN); + if (spelldata[spl].sMissiles[0] == MIT_CBOLT) { + UseMana(id, SPL_CBOLT); + for (i = (spllvl >> 1) + 3; i > 0; i--) + AddMissile(sx, sy, dx, dy, dir, MIT_CBOLT, caster, id, 0, spllvl); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoResurrect(int pnum, int rid) +{ + if ((char) rid != -1) + AddMissile(plr[rid]._px, plr[rid]._py, plr[rid]._px, plr[rid]._py, 0, MIT_RESURRECTBEAM, MI_PLR, pnum, 0, 0); + + if (pnum == myplr) { + NewCursor(GLOVE_CURS); + } + + if (((char) rid) != -1) { + // if I am casting on a live person bail out + if (plr[rid]._pHitPoints != 0) return; + if (rid == myplr) { + deathflag = FALSE; + gamemenu_off(); + drawhpflag = TRUE; + drawmanaflag = TRUE; + } + ClrPlrPath(rid); + plr[rid].destAction = PCMD_NOTHING; + plr[rid]._pInvincible = FALSE; + SetPlayerHitPoints(rid, 10 << HP_SHIFT); + plr[rid]._pHPBase = plr[rid]._pHitPoints - (plr[rid]._pMaxHP - plr[rid]._pMaxHPBase); + plr[rid]._pMana = 0; + plr[rid]._pManaBase = plr[rid]._pMana - (plr[rid]._pMaxMana - plr[rid]._pMaxManaBase); + CalcPlrInv(rid, TRUE); + if (plr[rid].plrlevel == currlevel) StartStand(rid, plr[rid]._pdir); + else plr[rid]._pmode = PM_STAND; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void DoHealOther(int pnum, int rid) +{ + int i; + long l; + + if (pnum == myplr) { + NewCursor(GLOVE_CURS); + } + + if (((char) rid) != -1) { + // if I am casting on a dead person bail out + if ((plr[rid]._pHitPoints >> HP_SHIFT) <= 0) return; + + l = (random(57, 10) + 1) << HP_SHIFT; + for (i = 0; i < plr[pnum]._pLevel; i++) l += ((random(57, 4) + 1) << HP_SHIFT); + for (i = 0; i < GetSpellLevel(pnum, SPL_HEALOTHER); i++) l += ((random(57, 6) + 1) << HP_SHIFT); + if (plr[pnum]._pClass == CLASS_WARRIOR + || plr[pnum]._pClass == CLASS_BARBARIAN) + { + l = l << 1; + } + else if (plr[pnum]._pClass == CLASS_ROGUE || + plr[pnum]._pClass == CLASS_BARD) + { + l += (l >> 1); + } + else if (plr[pnum]._pClass == CLASS_MONK) + { + l += (l << 1); + } + plr[rid]._pHitPoints += l; + if (plr[rid]._pHitPoints > plr[rid]._pMaxHP) plr[rid]._pHitPoints = plr[rid]._pMaxHP; + plr[rid]._pHPBase += l; + if (plr[rid]._pHPBase > plr[rid]._pMaxHPBase) plr[rid]._pHPBase = plr[rid]._pMaxHPBase; + drawhpflag = TRUE; + } +} diff --git a/src/SPELLS.H b/src/SPELLS.H new file mode 100644 index 0000000..1166882 --- /dev/null +++ b/src/SPELLS.H @@ -0,0 +1,149 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/SPELLS.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define PRE_BETA IS_VERSION(BETA) +#define PRE_NONE TRUE +#define PRE_FIREBOLT TRUE +#define PRE_HEAL TRUE +#define PRE_LIGHTNING TRUE +#define PRE_FLASH TRUE +#define PRE_IDENTIFY TRUE +#define PRE_WALL TRUE +#define PRE_TOWN TRUE +#define PRE_STONE TRUE +#define PRE_INFRA TRUE +#define PRE_PHASE TRUE +#define PRE_MANASHLD TRUE +#define PRE_FIREBALL TRUE +#define PRE_GUARDIAN FALSE +#define PRE_CHAIN TRUE +#define PRE_WAVE TRUE +#define PRE_DOOM FALSE +#define PRE_BLOODR FALSE +#define PRE_NOVA TRUE +#define PRE_INVIS FALSE +#define PRE_FLAME TRUE +#define PRE_GOLEM TRUE +#define PRE_BLOODB TRUE +#define PRE_TELE TRUE +#define PRE_APOCA FALSE +#define PRE_ETHER FALSE +#define PRE_REPAIR TRUE +#define PRE_RECHARGE TRUE +#define PRE_DISARM TRUE +#define PRE_ELEMENT TRUE +#define PRE_CBOLT TRUE +#define PRE_HBOLT TRUE +#define PRE_RESURRECT TRUE +#define PRE_TELEKINESIS TRUE +#define PRE_HEALOTHER TRUE +#define PRE_BSTAR FALSE +#define PRE_BONESPIRIT FALSE + +#define SPL_NONE 0 +#define SPL_FIREBOLT 1 +#define SPL_HEAL 2 +#define SPL_LIGHTNING 3 +#define SPL_FLASH 4 +#define SPL_IDENTIFY 5 +#define SPL_WALL 6 +#define SPL_TOWN 7 +#define SPL_STONE 8 +#define SPL_INFRA 9 +#define SPL_PHASE 10 +#define SPL_MANASHLD 11 +#define SPL_FIREBALL 12 +#define SPL_GUARDIAN 13 +#define SPL_CHAIN 14 +#define SPL_WAVE 15 +#define SPL_DOOM 16 +#define SPL_BLOODR 17 +#define SPL_NOVA 18 +#define SPL_INVIS 19 +#define SPL_FLAME 20 +#define SPL_GOLEM 21 +//#define SPL_BLOODB 22 +#define SPL_RAGE 22 +#define SPL_TELE 23 +#define SPL_APOCA 24 +#define SPL_ETHER 25 +#define SPL_REPAIR 26 +#define SPL_RECHARGE 27 +#define SPL_DISARM 28 +#define SPL_ELEMENT 29 +#define SPL_CBOLT 30 +#define SPL_HBOLT 31 +#define SPL_RESURRECT 32 +#define SPL_TELEKINESIS 33 +#define SPL_HEALOTHER 34 +#define SPL_BSTAR 35 +#define SPL_BONESPIRIT 36 + +// added 7/31 by donald +#define SPL_MANA 37 // staff versions of mana potions +#define SPL_FMANA 38 +#define SPL_RANDOM 39 +// Added 9/5/97 by Gary +#define SPL_LTWALL 40 +#define SPL_IMMOLATION 41 +#define SPL_TELESTAIRS 42 +#define SPL_REFLECT 43 +#define SPL_BERSERK 44 +#define SPL_RINGOFFIRE 45 +#define SPL_SHOWMAGITEMS 46 +#define SPL_RUNEOFFIRE 47 +#define SPL_RUNEOFLIGHT 48 +#define SPL_RUNEOFNOVA 49 +#define SPL_RUNEOFIMMOLATION 50 +#define SPL_RUNEOFSTONE 51 + + +#if defined(HELLFIRE2) +#define SPL_RINGOFLIGHT 46 +#define SPL_AURA 48 +#define SPL_SPIRALFIREBALL 49 +#endif // HELLFIRE2 + +#define SPL_LAST (SPL_RUNEOFSTONE + 1) + +#define MAXSPELLS SPL_LAST +#define SPELLCAP 15 + +#define SPT_ABILITY 0 +#define SPT_MEMORIZED 1 +#define SPT_SCROLL 2 +#define SPT_ITEM 3 +#define SPT_NONE 4 + +#define MI_PLR 0 +#define MI_MONST 1 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void CastSpell(int, int, int, int, int, int, int, int); +void DoResurrect(int, int); +void DoHealOther(int, int); +void UseMana(int, int); +int GetManaAmount(int, int); +BOOL CheckSpell(int, int, char, BOOL); diff --git a/src/STORES.CPP b/src/STORES.CPP new file mode 100644 index 0000000..be70fbf --- /dev/null +++ b/src/STORES.CPP @@ -0,0 +1,3035 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Control panel file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/STORES.CPP 6 3/19/97 11:19a Jmcreynolds $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "engine.h" +#include "control.h" +#include "scrollrt.h" +#include "gendung.h" +#include "items.h" +#include "itemdat.h" +#include "player.h" +#include "stores.h" +#include "minitext.h" +#include "cursor.h" +#include "inv.h" +#include "quests.h" +#include "effects.h" +#include "multi.h" +#include "towners.h" +#include "spelldat.h" +#include "textdat.h" +#include "spells.h" + +/*-----------------------------------------------------------------------** +** Local defines +**-----------------------------------------------------------------------*/ + +#define STEXT_SMALL 0 +#define STEXT_LARGE 1 + +#define MAXHOLDITEMS 48 + +/*-----------------------------------------------------------------------** +** Global variables +**-----------------------------------------------------------------------*/ + +BYTE *pSTextBoxCels; +BYTE *pSTextSpinCels; +BYTE *pSTextSlidCels; + +char stextflag, stextsize; +int stextspin, stextsel; +int stextlhold, stextshold, stextvhold; + +BOOL stextscrl; +int stextsval, stextsmax; +int stextup, stextdown; + +char stextscrlubtn, stextscrldbtn; + +int SStringY[24] = { + 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, + 156, 168, 180, 192, 204, 216, 228, 240, 252, 264, 276 }; + +STextStruct stext[NUMSTLINES]; + +ItemStruct smithitem[MAXSMITHITEMS]; + +ItemStruct premiumitem[MAXPREMIUM]; +int numpremium, premiumlevel; + +ItemStruct witchitem[MAXWITCHITEMS]; + +ItemStruct boyitem; +int boylevel; + +ItemStruct healitem[MAXHEALITEMS]; + +ItemStruct storehold[MAXHOLDITEMS]; +char storehidx[MAXHOLDITEMS]; + +ItemStruct golditem; + +int storenumh; + +int gossipstart, gossipend; + +/*-----------------------------------------------------------------------*/ + +char *talkname[] = { + "Griswold", + "Pepin", + "", + "Ogden", + "Cain", + "Farnham", + "Adria", + "Gillian", + "Wirt" +}; + +int talker; +extern QuestData questlist[]; + +/*-----------------------------------------------------------------------*/ + +void ClearSText(int, int); + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void InitStores() +{ + app_assert(! pSTextBoxCels); + pSTextBoxCels = LoadFileInMemSig("Data\\TextBox2.CEL",NULL,'STOR'); + pSTextSpinCels = LoadFileInMemSig("Data\\PentSpn2.CEL",NULL,'STOR'); + pSTextSlidCels = LoadFileInMemSig("Data\\TextSlid.CEL",NULL,'STOR'); + ClearSText(0, NUMSTLINES); + stextflag = STORE_NONE; + stextspin = 1; + stextsize = STEXT_SMALL; + stextscrl = FALSE; + numpremium = 0; + premiumlevel = 1; + for (int i = 0; i < MAXPREMIUM; i++) premiumitem[i]._itype = -1; + boyitem._itype = -1; + boylevel = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void SetupTownStores() +{ + int i, l; + + // PATCH2.JMM.3/10/97 + SetRndSeed( glSeedTbl[currlevel] * GetTickCount( ) ); + // ENDPATCh2.JMM.3/10/97 + + + // How deep have I gone? + if (gbMaxPlayers == 1) { + l = 0; + for (i = 0; i < NUMLEVELS; i++) + if (plr[myplr]._pLvlVisited[i]) l = i; + } else { + l = plr[myplr]._pLevel >> 1; + } + + // Make sure they carry relevant items all the time + l += 2; + if (l < 6) l = 6; + if (l > 16) l = 16; + + // Setup a gold item for transactions + SpawnStoreGold(); + // Setup blacksmith items + SpawnSmith(l); + // Setup witch items + SpawnWitch(l); + // Setup healer items + SpawnHealer(l); + + // Setup boy items can alter the random seed + SpawnBoy(plr[myplr]._pLevel); + // SpawnPremium can alter the random seed + SpawnPremium(myplr); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void FreeStoreMem() +{ + DiabloFreePtr(pSTextBoxCels); + DiabloFreePtr(pSTextSpinCels); + DiabloFreePtr(pSTextSlidCels); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +BOOL StoreQuestTalk(int t) +{ + int i; + for (i = 0; i < MAXQUESTS; i++) { + if ((quests[i]._qactive == QUEST_NOTDONE) && (Qtalklist[t][i] != -1)) return(TRUE); + } + return(FALSE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void DrawSTextBack() +{ + DrawCel(408, 487, pSTextBoxCels, 1, 271); + + app_assert(gpBuffer); + __asm { + mov edi,dword ptr [gpBuffer] + add edi,372123 + + xor eax,eax + mov edx,148 +_YLp: mov ecx,132 +_XLp1: stosb + inc edi + loop _XLp1 + stosb + sub edi,1033 + mov ecx,132 +_XLp2: inc edi + stosb + loop _XLp2 + sub edi,1032 + dec edx + jnz _YLp + mov ecx,132 +_XLp3: stosb + inc edi + loop _XLp3 + stosb + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PrintSString(int x, int y, BOOL cjustflag, char str[], char col, int val) +{ + long boffset; + int sl,i,w,tw,aw,xx,yy,xa; + char valstr[32]; + + yy = SStringY[y] + stext[y]._syoff; + if (stextsize == STEXT_SMALL) xa = 416; + else xa = 96; + boffset = nBuffWTbl[yy + 204] + x + xa; + sl = strlen(str); + if (stextsize == STEXT_SMALL) aw = 257; + else aw = 577; + w = 0; + if (cjustflag) { + tw = 0; + for (i = 0; i < sl; i++) { + BYTE c = char2print(str[i]); + c = fonttrans[c]; + tw += fontkern[c]+1; + } + if (tw < aw) w = (aw - tw) >> 1; + boffset += w; + } + if (stextsel == y) { + if (cjustflag) xx = x + w + xa - 20; + else xx = x + xa - 20; + DrawCel(xx, yy + 205, pSTextSpinCels, stextspin, 12); + } + for (i = 0; i < sl; i++) { + BYTE c = char2print(str[i]); + c = fonttrans[c]; + w += fontkern[c]+1; + if ((c != 0) && (w <= aw)) DrawPanelFont(boffset, c, col); + boffset += fontkern[c]+1; + } + if ((!cjustflag) && (val >= 0)) { + sprintf(valstr, "%i", val); + boffset = nBuffWTbl[yy + 204] + 656 - x; + sl = strlen(valstr); + for (i = sl-1; i >= 0; i--) { + BYTE c = char2print(valstr[i]); + c = fonttrans[c]; + boffset -= fontkern[c]+1; + if (c != 0) DrawPanelFont(boffset, c, col); + } + } + if (stextsel == y) { + if (cjustflag) xx = x + w + xa + 4; + else xx = 660 - x; + DrawCel(xx, yy + 205, pSTextSpinCels, stextspin, 12); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawSLine(int y) +{ + long soffset, doffset; + long width, wadd; + int yy; + + yy = SStringY[y]; + if (stextsize == STEXT_LARGE) { + soffset = 142170; + doffset = nBuffWTbl[yy + 198] + 90; + width = 146; + wadd = 182; + } else { + soffset = 142490; + doffset = nBuffWTbl[yy + 198] + 410; + width = 66; + wadd = 502; + } + + app_assert(gpBuffer); + __asm { + mov esi,dword ptr [gpBuffer] + mov edi,esi + add esi,dword ptr [soffset] + add edi,dword ptr [doffset] + + mov ebx,dword ptr [wadd] + + mov edx,3 +_YLp: mov ecx,dword ptr [width] + rep movsd + movsw + add esi,ebx + add edi,ebx + dec edx + jnz _YLp + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawScrlBar(int y1, int y2) +{ + int i, yy1, yy2, v, s; + + yy1 = SStringY[y1] + 204; + yy2 = SStringY[y2] + 204; + if (stextscrlubtn != -1) DrawCel(665, yy1, pSTextSlidCels, 12, 12); + else DrawCel(665, yy1, pSTextSlidCels, 10, 12); + if (stextscrldbtn != -1) DrawCel(665, yy2, pSTextSlidCels, 11, 12); + else DrawCel(665, yy2, pSTextSlidCels, 9, 12); + for (i = (yy1+12); i < yy2; i+=12) DrawCel(665, i, pSTextSlidCels, 14, 12); + + if (stextsel != 22) s = stextsel; + else s = stextlhold; + if (storenumh > 1) { + v = ((s - stextup) >> 2) + stextsval; + v = v * 1000; + v = v / (storenumh-1); + v = v * (SStringY[y2]-SStringY[y1]-24); + v = v / 1000; + } else v = 0; + v += SStringY[y1+1] + 204; + DrawCel(665, v, pSTextSlidCels, 13, 12); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetupSTextWin() +{ + stextsize = STEXT_SMALL; + stextsel = -1; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetupSTextLWin() +{ + stextsize = STEXT_LARGE; + stextsel = -1; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ClearSText(int s, int e) +{ + int i; + + for (i = s; i < e; i++) { + stext[i]._sx = 0; + stext[i]._syoff = 0; + stext[i]._sstr[0] = 0; + stext[i]._sjust = FALSE; + stext[i]._sclr = ICOLOR_WHITE; + stext[i]._sline = FALSE; + stext[i]._ssel = FALSE; + stext[i]._sval = -1; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AddSLine(int y) +{ + stext[y]._sx = 0; + stext[y]._syoff = 0; + stext[y]._sstr[0] = 0; + stext[y]._sline = TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AddSTextVal(int y, int val) +{ + stext[y]._sval = val; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void OffsetSTextY(int y, int yo) +{ + stext[y]._syoff = yo; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AddSText(int x, int y, BOOL j, char str[], char clr, BOOL sel) +{ + stext[y]._sx = x; + stext[y]._syoff = 0; + strcpy(stext[y]._sstr,str); + stext[y]._sjust = j; + stext[y]._sclr = clr; + stext[y]._sline = FALSE; + stext[y]._ssel = sel; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static void PrintStoreItem(const ItemStruct * x, int l, char iclr) +{ + char sstr[128]; + + sstr[0] = 0; + if (x->_iIdentified) { + if ((x->_iMagical != IMAGIC_UNIQUE) && (x->_iPrePower != -1)) { + PrintItemPower(x->_iPrePower, x); + strcat(sstr, tempstr); + } + if (x->_iSufPower != -1) { + PrintItemPower(x->_iSufPower, x); + if (sstr[0] != 0) strcat(sstr, ", "); + strcat(sstr, tempstr); + } + } + if ((x->_iMiscId == IMID_STAFF) && (x->_iMaxCharges != 0)) { + sprintf(tempstr, "Charges: %i/%i", x->_iCharges, x->_iMaxCharges); + if (sstr[0] != 0) strcat(sstr, ", "); + strcat(sstr, tempstr); + } + + if (sstr[0] != 0) { + AddSText(40, l, FALSE, sstr, iclr, FALSE); + l++; + } + + sstr[0] = 0; + if (x->_iClass == IC_WEAP) sprintf(sstr, "Damage: %i-%i ", x->_iMinDam, x->_iMaxDam); + if (x->_iClass == IC_ARMOR) sprintf(sstr, "Armor: %i ", x->_iAC); + + if ((x->_iMaxDur == INFINITE_DUR) || (x->_iMaxDur == 0)) strcat(sstr, "Indestructible, "); + else { + sprintf(tempstr, "Dur: %i/%i, ", x->_iDurability, x->_iMaxDur); + strcat(sstr, tempstr); + } + if (x->_itype == IT_MISC) sstr[0] = 0; + if ((x->_iMinStr + x->_iMinMag + x->_iMinDex) == 0) { + strcat(sstr, "No required attributes"); + } else { + strcpy(tempstr, "Required:"); + if (x->_iMinStr != 0) sprintf(tempstr, "%s %i Str", tempstr, x->_iMinStr); + if (x->_iMinMag != 0) sprintf(tempstr, "%s %i Mag", tempstr, (byte) x->_iMinMag); + if (x->_iMinDex != 0) sprintf(tempstr, "%s %i Dex", tempstr, x->_iMinDex); + strcat(sstr, tempstr); + } + AddSText(40, l++, FALSE, sstr, iclr, FALSE); + + if ((x->_iMagical == IMAGIC_UNIQUE) && (x->_iIdentified)) + AddSText(40, l++, FALSE, "Unique Item", iclr, FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +extern int AP2x2Tbl[10]; + +void StoreAutoPlace() +{ + int i, w, h, idx; + BOOL done; + + SetICursor(plr[myplr].HoldItem._iCurs + ICSTART); + // all items are either 1x1, 1x2, 1x3, 2x2, or 2x3 + // the inv is 10x4 + w = icursW28; + h = icursH28; + done = FALSE; + if ((w == 1) && (h == 1)) { + // Check to see if speed bar available first + idx = plr[myplr].HoldItem.IDidx; + if ((plr[myplr].HoldItem._iStatFlag) && (AllItemsList[idx].iUsable)) { + for (i = 0; (i < MAXSPD) && (!done); i++) { + if (plr[myplr].SpdList[i]._itype == -1) { + plr[myplr].SpdList[i] = plr[myplr].HoldItem; + done = TRUE; + } + } + } + // Start in lower left and continue trying right then up a line + for (i = 30; (i <= 39) && (!done); i++) done = AutoPlace(myplr, i, w, h, TRUE); + for (i = 20; (i <= 29) && (!done); i++) done = AutoPlace(myplr, i, w, h, TRUE); + for (i = 10; (i <= 19) && (!done); i++) done = AutoPlace(myplr, i, w, h, TRUE); + for (i = 0; (i <= 9) && (!done); i++) done = AutoPlace(myplr, i, w, h, TRUE); + } + if ((w == 1) && (h == 2)) { + // Try 3rd row, 1st row, and then 2nd row + for (i = 29; (i >= 20) && (!done); i--) done = AutoPlace(myplr, i, w, h, TRUE); + for (i = 9; (i >= 0) && (!done); i--) done = AutoPlace(myplr, i, w, h, TRUE); + for (i = 19; (i >= 10) && (!done); i--) done = AutoPlace(myplr, i, w, h, TRUE); + } + if ((w == 1) && (h == 3)) { + // Try 1st row then 2nd row + for (i = 0; (i < 20) && (!done); i++) done = AutoPlace(myplr, i, w, h, TRUE); + } + if ((w == 2) && (h == 2)) { + // Try 1st and 3rd row starting right and moving left + for (i = 0; (i < 10) && (!done); i++) done = AutoPlace(myplr, AP2x2Tbl[i], w, h, TRUE); + // Try 3rd row, 1st row, and then 2nd row + for (i = 21; (i < 29) && (!done); i+=2) done = AutoPlace(myplr, i, w, h, TRUE); + for (i = 1; (i < 9) && (!done); i+=2) done = AutoPlace(myplr, i, w, h, TRUE); + for (i = 10; (i < 19) && (!done); i++) done = AutoPlace(myplr, i, w, h, TRUE); + } + if ((w == 2) && (h == 3)) { + // Try 1st row then 2nd row + for (i = 0; (i < 9) && (!done); i++) done = AutoPlace(myplr, i, w, h, TRUE); + for (i = 10; (i < 19) && (!done); i++) done = AutoPlace(myplr, i, w, h, TRUE); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartSmith() +{ + stextsize = STEXT_SMALL; + stextscrl = FALSE; + AddSText(0, 1, TRUE, "Welcome to the", ICOLOR_GOLD, FALSE); + AddSText(0, 3, TRUE, "Blacksmith's shop", ICOLOR_GOLD, FALSE); + AddSText(0, 7, TRUE, "Would you like to:", ICOLOR_GOLD, FALSE); + AddSText(0, 10, TRUE, "Talk to Griswold", ICOLOR_BLUE, TRUE); + AddSText(0, 12, TRUE, "Buy basic items", ICOLOR_WHITE, TRUE); + AddSText(0, 14, TRUE, "Buy premium items", ICOLOR_WHITE, TRUE); + AddSText(0, 16, TRUE, "Sell items", ICOLOR_WHITE, TRUE); + AddSText(0, 18, TRUE, "Repair items", ICOLOR_WHITE, TRUE); + AddSText(0, 20, TRUE, "Leave the shop", ICOLOR_WHITE, TRUE); + AddSLine(5); + storenumh = 20; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_ScrollSBuy(int idx) +{ + int l, ls; + char iclr; + + ClearSText(5, 21); + stextup = 5; + for (l = 5; l < 20; l+=4) { + if (smithitem[idx]._itype != -1) { + ls = l; + iclr = ICOLOR_WHITE; + if (smithitem[idx]._iMagical) iclr = ICOLOR_BLUE; + if (!smithitem[idx]._iStatFlag) iclr = ICOLOR_RED; + if (smithitem[idx]._iMagical) AddSText(20, l, FALSE, smithitem[idx]._iIName, iclr, TRUE); + else AddSText(20, l, FALSE, smithitem[idx]._iName, iclr, TRUE); + AddSTextVal(l, smithitem[idx]._iIvalue); + PrintStoreItem(&smithitem[idx], l+1, iclr); + stextdown = ls; + idx++; + } + } + if ((!stext[stextsel]._ssel) && (stextsel != 22)) stextsel = stextdown; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartSBuy() +{ + int i; + + stextsize = STEXT_LARGE; + stextscrl = TRUE; + stextsval = 0; + sprintf(tempstr, "I have these items for sale : Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + S_ScrollSBuy(stextsval); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, FALSE); + OffsetSTextY(22, 6); + + storenumh = 0; + for (i = 0; smithitem[i]._itype != -1; i++) storenumh++; + stextsmax = storenumh - 4; + if (stextsmax < 0) stextsmax = 0; + //if (storenumh == 0) StartStore(STORE_SMITH); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_ScrollSPBuy(int idx) +{ + int l, ls; + char iclr; + int boughtitems; + + ClearSText(5, 21); + stextup = 5; + // Premium items don't get deleted from the list, so idx is not an index + // into premium array, but rather to the nth available item. + boughtitems = idx; + idx = 0; + while (boughtitems) { + if (premiumitem[idx]._itype != -1) + boughtitems--; + idx++; + } + for (l = 5; ((l < 20) && (idx < MAXPREMIUM)); l+=4) { + if (premiumitem[idx]._itype != -1) { + ls = l; + iclr = ICOLOR_WHITE; + if (premiumitem[idx]._iMagical) iclr = ICOLOR_BLUE; + if (!premiumitem[idx]._iStatFlag) iclr = ICOLOR_RED; + AddSText(20, l, FALSE, premiumitem[idx]._iIName, iclr, TRUE); + AddSTextVal(l, premiumitem[idx]._iIvalue); + PrintStoreItem(&premiumitem[idx], l+1, iclr); + stextdown = ls; + } else if (idx < MAXPREMIUM) l-=4; + idx++; + } + if ((!stext[stextsel]._ssel) && (stextsel != 22)) stextsel = stextdown; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL S_StartSPBuy() +{ + int i; + + storenumh = 0; + for (i = 0; i < MAXPREMIUM; i++) if (premiumitem[i]._itype != -1) storenumh++; + if (storenumh == 0) { + StartStore(STORE_SMITH); + stextsel = 14; + return(FALSE); + } else { + stextsize = STEXT_LARGE; + stextscrl = TRUE; + stextsval = 0; + sprintf(tempstr, "I have these premium items for sale : Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, FALSE); + OffsetSTextY(22, 6); + + stextsmax = storenumh - 4; + if (stextsmax < 0) stextsmax = 0; + + S_ScrollSPBuy(stextsval); + } + return(TRUE); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL SmithSellOk(int i) +{ + ItemStruct *pI; + + if (i >= 0) + pI = &plr[myplr].InvList[i]; + else + pI = &plr[myplr].SpdList[-(i+1)]; + + if (pI->_itype == -1) return FALSE; + + if (pI->_iMiscId > IMID_FIRSTOIL && + pI->_iMiscId < IMID_LASTOIL) + return TRUE; + + if (pI->_itype == IT_MISC) return FALSE; + if (pI->_itype == IT_GOLD) return FALSE; + if (pI->_itype == IT_FOOD) return FALSE; + if (pI->_itype == IT_STAFF && pI->_iSpell != SPL_NONE) return FALSE; + if (pI->_iClass == IC_SPECIAL) return FALSE; + if (pI->IDidx == IDI_LAZSTAFF) return FALSE; + +// if (plr[myplr].InvList[i]._iMagical && plr[myplr].InvList[i]._iIdentified) { +// if (plr[myplr].InvList[i]._iIvalue == 0) return FALSE; +// } + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_ScrollSSell(int idx) +{ + int l, ls, sidx, v; + char iclr; + + ClearSText(5, 21); + stextup = 5; + sidx = idx; + for (l = 5; l < 20 && idx < storenumh; l+=4) { + if (storehold[idx]._itype != -1) { + ls = l; + iclr = ICOLOR_WHITE; + if (storehold[idx]._iMagical) iclr = ICOLOR_BLUE; + if (!storehold[idx]._iStatFlag) iclr = ICOLOR_RED; + if (storehold[idx]._iMagical && storehold[idx]._iIdentified) { + AddSText(20, l, FALSE, storehold[idx]._iIName, iclr, TRUE); + v = storehold[idx]._iIvalue; + } else { + AddSText(20, l, FALSE, storehold[idx]._iName, iclr, TRUE); + v = storehold[idx]._ivalue; + } + AddSTextVal(l, v); + PrintStoreItem(&storehold[idx], l+1, iclr); + stextdown = ls; + } + idx++; + } + stextsmax = storenumh - 4; + if (stextsmax < 0) stextsmax = 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartSSell() +{ + int i; + BOOL sellok; + + stextsize = STEXT_LARGE; + sellok = FALSE; + storenumh = 0; + for (i = 0; i < MAXHOLDITEMS; i++) storehold[i]._itype = -1; + for (i = 0; i < plr[myplr]._pNumInv && storenumh < MAXHOLDITEMS; i++) { + if (SmithSellOk(i)) { + sellok = TRUE; + storehold[storenumh] = plr[myplr].InvList[i]; + if (storehold[storenumh]._iMagical && storehold[storenumh]._iIdentified) + storehold[storenumh]._ivalue = storehold[storenumh]._iIvalue; + storehold[storenumh]._ivalue = storehold[storenumh]._ivalue >> 2; + if (!storehold[storenumh]._ivalue) + storehold[storenumh]._ivalue = 1; + storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue; + storehidx[storenumh] = i; + storenumh++; + } + } + for (i = 0; i < MAXSPD && storenumh < MAXHOLDITEMS; i++) { + if (SmithSellOk(-(i+1))) { + sellok = TRUE; + storehold[storenumh] = plr[myplr].SpdList[i]; + if (storehold[storenumh]._iMagical && storehold[storenumh]._iIdentified) + storehold[storenumh]._ivalue = storehold[storenumh]._iIvalue; + storehold[storenumh]._ivalue = storehold[storenumh]._ivalue >> 2; + if (!storehold[storenumh]._ivalue) + storehold[storenumh]._ivalue = 1; + storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue; + storehidx[storenumh] = -(i+1); + storenumh++; + } + } + + if (!sellok) { + stextscrl = FALSE; + sprintf(tempstr, "You have nothing I want. Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } else { + stextscrl = TRUE; + stextsval = 0; + stextsmax = plr[myplr]._pNumInv; + sprintf(tempstr, "Which item is for sale? Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + S_ScrollSSell(stextsval); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL SmithRepairOk(int i) +{ + if (plr[myplr].InvList[i]._itype == -1) return FALSE; + if (plr[myplr].InvList[i]._itype == IT_MISC) return FALSE; + if (plr[myplr].InvList[i]._itype == IT_GOLD) return FALSE; + if (plr[myplr].InvList[i]._itype == IT_FOOD) return FALSE; + if (plr[myplr].InvList[i]._iDurability == plr[myplr].InvList[i]._iMaxDur) return FALSE; + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void AddStoreHoldRepair(ItemStruct * itm,int i) +{ + int v; + + app_assert(itm->_iMaxDur > 0); + + storehold[storenumh] = *itm; + itm = &storehold[storenumh]; + if (itm->_iMagical && itm->_iIdentified) + itm->_ivalue = (itm->_iIvalue * 30) / 100; + v = ((itm->_iMaxDur - itm->_iDurability) * 100) / itm->_iMaxDur; + v = (v * itm->_ivalue) / 100; + if (v == 0) { + if (itm->_iMagical && itm->_iIdentified) return; + else v = 1; + } + if (v > 1) v >>= 1; + itm->_ivalue = itm->_iIvalue = v; + storehidx[storenumh++] = i; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartSRepair() +{ + int i; + BOOL repairok; + + stextsize = STEXT_LARGE; + repairok = FALSE; + storenumh = 0; + for (i = 0; i < MAXHOLDITEMS; i++) storehold[i]._itype = -1; + if ((plr[myplr].HeadItem._itype != -1) && (plr[myplr].HeadItem._iDurability != plr[myplr].HeadItem._iMaxDur)) { + repairok = TRUE; + AddStoreHoldRepair(&plr[myplr].HeadItem, -1); + } + if ((plr[myplr].BodyItem._itype != -1) && (plr[myplr].BodyItem._iDurability != plr[myplr].BodyItem._iMaxDur)) { + repairok = TRUE; + AddStoreHoldRepair(&plr[myplr].BodyItem, -2); + } + if ((plr[myplr].Hand1Item._itype != -1) && (plr[myplr].Hand1Item._iDurability != plr[myplr].Hand1Item._iMaxDur)) { + repairok = TRUE; + AddStoreHoldRepair(&plr[myplr].Hand1Item, -3); + } + if ((plr[myplr].Hand2Item._itype != -1) && (plr[myplr].Hand2Item._iDurability != plr[myplr].Hand2Item._iMaxDur)) { + repairok = TRUE; + AddStoreHoldRepair(&plr[myplr].Hand2Item, -4); + } + for (i = 0; i < plr[myplr]._pNumInv && storenumh < MAXHOLDITEMS; i++) { + if (SmithRepairOk(i)) { + repairok = TRUE; + AddStoreHoldRepair(&plr[myplr].InvList[i], i); + } + } + if (!repairok) { + stextscrl = FALSE; + sprintf(tempstr, "You have nothing to repair. Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } else { + stextscrl = TRUE; + stextsval = 0; + stextsmax = plr[myplr]._pNumInv; + sprintf(tempstr, "Repair which item? Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + S_ScrollSSell(stextsval); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartWitch() +{ + stextsize = STEXT_SMALL; + stextscrl = FALSE; + AddSText(0, 2, TRUE, "Witch's shack", ICOLOR_GOLD, FALSE); + AddSText(0, 9, TRUE, "Would you like to:", ICOLOR_GOLD, FALSE); + AddSText(0, 12, TRUE, "Talk to Adria", ICOLOR_BLUE, TRUE); + AddSText(0, 14, TRUE, "Buy items", ICOLOR_WHITE, TRUE); + AddSText(0, 16, TRUE, "Sell items", ICOLOR_WHITE, TRUE); + AddSText(0, 18, TRUE, "Recharge staves", ICOLOR_WHITE, TRUE); + AddSText(0, 20, TRUE, "Leave the shack", ICOLOR_WHITE, TRUE); + AddSLine(5); + storenumh = 20; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_ScrollWBuy(int idx) +{ + int l, ls, sidx; + char iclr; + + ClearSText(5, 21); + stextup = 5; + sidx = idx; + for (l = 5; l < 20; l+=4) { + if (witchitem[idx]._itype != -1) { + ls = l; + iclr = ICOLOR_WHITE; + if (witchitem[idx]._iMagical) iclr = ICOLOR_BLUE; + if (!witchitem[idx]._iStatFlag) iclr = ICOLOR_RED; + if (witchitem[idx]._iMagical) AddSText(20, l, FALSE, witchitem[idx]._iIName, iclr, TRUE); + else AddSText(20, l, FALSE, witchitem[idx]._iName, iclr, TRUE); + AddSTextVal(l, witchitem[idx]._iIvalue); + PrintStoreItem(&witchitem[idx], l+1, iclr); + stextdown = ls; + idx++; + } + } + if ((!stext[stextsel]._ssel) && (stextsel != 22)) stextsel = stextdown; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartWBuy() +{ + int i; + + stextsize = STEXT_LARGE; + stextscrl = TRUE; + stextsval = 0; + stextsmax = 20; + sprintf(tempstr, "I have these items for sale : Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + S_ScrollWBuy(stextsval); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, FALSE); + OffsetSTextY(22, 6); + + storenumh = 0; + for (i = 0; witchitem[i]._itype != -1; i++) storenumh++; + stextsmax = storenumh - 4; + if (stextsmax < 0) stextsmax = 0; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL WitchSellOk(int i) +{ + BOOL rv; + ItemStruct *pI; + + rv = FALSE; + if (i >= 0) + pI = &plr[myplr].InvList[i]; + else + pI = &plr[myplr].SpdList[-(i+1)]; + + if (pI->_itype == IT_MISC) rv = TRUE; + if ((pI->_iMiscId > IMID_FIRSTOIL) && (pI->_iMiscId < IMID_LASTOIL)) + rv = FALSE; + if (pI->_iClass == IC_SPECIAL) + rv = FALSE; + + if (pI->_itype == IT_STAFF && pI->_iSpell != SPL_NONE) rv = TRUE; +// if (pI->_iMagical && pI->_iIdentified) { +// if (pI->_iIvalue == 0) rv = FALSE; +// } + if (pI->IDidx >= IDI_FIRSTQUEST + && pI->IDidx <= IDI_LASTQUEST) + rv = FALSE; + if (pI->IDidx == IDI_LAZSTAFF) rv = FALSE; + return(rv); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartWSell() +{ + int i; + BOOL sellok; + + stextsize = STEXT_LARGE; + sellok = FALSE; + storenumh = 0; + for (i = 0; i < MAXHOLDITEMS; i++) storehold[i]._itype = -1; + for (i = 0; i < plr[myplr]._pNumInv && storenumh < MAXHOLDITEMS; i++) { + if (WitchSellOk(i)) { + sellok = TRUE; + storehold[storenumh] = plr[myplr].InvList[i]; + if (storehold[storenumh]._iMagical && storehold[storenumh]._iIdentified) + storehold[storenumh]._ivalue = storehold[storenumh]._iIvalue; + storehold[storenumh]._ivalue = storehold[storenumh]._ivalue >> 2; + if (!storehold[storenumh]._ivalue) + storehold[storenumh]._ivalue = 1; + storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue; + storehidx[storenumh] = i; + storenumh++; + } + } + for (i = 0; i < MAXSPD && storenumh < MAXHOLDITEMS; i++) { + if ((plr[myplr].SpdList[i]._itype != -1) && (WitchSellOk(-(i+1)))) { + sellok = TRUE; + storehold[storenumh] = plr[myplr].SpdList[i]; + if (storehold[storenumh]._iMagical && storehold[storenumh]._iIdentified) + storehold[storenumh]._ivalue = storehold[storenumh]._iIvalue; + storehold[storenumh]._ivalue = storehold[storenumh]._ivalue >> 2; + if (!storehold[storenumh]._ivalue) + storehold[storenumh]._ivalue = 1; + storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue; + storehidx[storenumh] = -(i+1); + storenumh++; + } + } + if (!sellok) { + stextscrl = FALSE; + sprintf(tempstr, "You have nothing I want. Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } else { + stextscrl = TRUE; + stextsval = 0; + stextsmax = plr[myplr]._pNumInv; + sprintf(tempstr, "Which item is for sale? Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + S_ScrollSSell(stextsval); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL WitchRechargeOk(int i) +{ + BOOL rv; + + rv = FALSE; + if ((plr[myplr].InvList[i]._itype == IT_STAFF) && + (plr[myplr].InvList[i]._iCharges != plr[myplr].InvList[i]._iMaxCharges)) + { + rv = TRUE; + } + + // new: you can recharge unique items too. + if ((plr[myplr].InvList[i]._iMiscId == IMID_UNIQUE || + (plr[myplr].InvList[i]._iMiscId == IMID_STAFF)) && + (plr[myplr].InvList[i]._iCharges < plr[myplr].InvList[i]._iMaxCharges)) + { + rv = TRUE; + } + //***** + return(rv); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void AddStoreHoldRecharge(ItemStruct itm, int i) +{ + int v; + + storehold[storenumh] = itm; + storehold[storenumh]._ivalue += spelldata[itm._iSpell].sStaffCost; + v = ((storehold[storenumh]._iMaxCharges - storehold[storenumh]._iCharges) * 100) / storehold[storenumh]._iMaxCharges; + storehold[storenumh]._ivalue = ((v * storehold[storenumh]._ivalue) / 100) >> 1; + storehold[storenumh]._iIvalue = storehold[storenumh]._ivalue; + storehidx[storenumh] = i; + storenumh++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartWRecharge() +{ + int i; + BOOL rechargeok; + + stextsize = STEXT_LARGE; + rechargeok = FALSE; + storenumh = 0; + for (i = 0; i < MAXHOLDITEMS; i++) storehold[i]._itype = -1; + if (( (plr[myplr].Hand1Item._itype == IT_STAFF) + || (plr[myplr].Hand1Item._iMiscId == IMID_UNIQUE)) + && (plr[myplr].Hand1Item._iCharges != plr[myplr].Hand1Item._iMaxCharges)) + { + rechargeok = TRUE; + AddStoreHoldRecharge(plr[myplr].Hand1Item, -1); + } + for (i = 0; i < plr[myplr]._pNumInv && storenumh < MAXHOLDITEMS; i++) { + if (WitchRechargeOk(i)) { + rechargeok = TRUE; + AddStoreHoldRecharge(plr[myplr].InvList[i], i); + } + } + if (!rechargeok) { + stextscrl = FALSE; + sprintf(tempstr, "You have nothing to recharge. Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } else { + stextscrl = TRUE; + stextsval = 0; + stextsmax = plr[myplr]._pNumInv; + sprintf(tempstr, "Recharge which item? Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + S_ScrollSSell(stextsval); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartNoMoney() +{ + StartStore(stextshold); + stextsize = STEXT_LARGE; + stextscrl = FALSE; + ClearSText(5, 23); + AddSText(0, 14, TRUE, "You do not have enough gold", ICOLOR_WHITE, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartNoRoom() +{ + StartStore(stextshold); + stextscrl = FALSE; + ClearSText(5, 23); + AddSText(0, 14, TRUE, "You do not have enough room in inventory", ICOLOR_WHITE, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartConfirm() +{ + char iclr; + BOOL idprint; + + StartStore(stextshold); + stextscrl = FALSE; + ClearSText(5, 23); + iclr = ICOLOR_WHITE; + if (plr[myplr].HoldItem._iMagical) iclr = ICOLOR_BLUE; + if (!plr[myplr].HoldItem._iStatFlag) iclr = ICOLOR_RED; + + if (plr[myplr].HoldItem._iMagical) idprint = TRUE; + else idprint = FALSE; + + if (stextshold == STORE_STORYID) idprint = FALSE; + + if ((plr[myplr].HoldItem._iMagical) && (!plr[myplr].HoldItem._iIdentified)) { + if (stextshold == STORE_SSELL) idprint = FALSE; + if (stextshold == STORE_WSELL) idprint = FALSE; + if (stextshold == STORE_SREPAIR) idprint = FALSE; + if (stextshold == STORE_WRECHARGE) idprint = FALSE; + } + + if (idprint) + AddSText(20, 8, FALSE, plr[myplr].HoldItem._iIName, iclr, FALSE); + else + AddSText(20, 8, FALSE, plr[myplr].HoldItem._iName, iclr, FALSE); + + AddSTextVal(8, plr[myplr].HoldItem._iIvalue); + PrintStoreItem(&plr[myplr].HoldItem, 9, iclr); + switch(stextshold) { + case STORE_SBUY: + case STORE_WBUY: + case STORE_HBUY: + case STORE_SPBUY: + strcpy(tempstr, "Are you sure you want to buy this item?"); + break; + case STORE_SSELL: + case STORE_WSELL: + strcpy(tempstr, "Are you sure you want to sell this item?"); + break; + case STORE_SREPAIR: + strcpy(tempstr, "Are you sure you want to repair this item?"); + break; + case STORE_WRECHARGE: + strcpy(tempstr, "Are you sure you want to recharge this item?"); + break; + case STORE_BBUY: + strcpy(tempstr, "Do we have a deal?"); + break; + case STORE_STORYID: + strcpy(tempstr, "Are you sure you want to identify this item?"); + break; + } + AddSText(0, 15, TRUE, tempstr, ICOLOR_WHITE, FALSE); + AddSText(0, 18, TRUE, "Yes", ICOLOR_WHITE, TRUE); + AddSText(0, 20, TRUE, "No", ICOLOR_WHITE, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartBoy() +{ + stextsize = STEXT_SMALL; + stextscrl = FALSE; + AddSText(0, 2, TRUE, "Wirt the Peg-legged boy", ICOLOR_GOLD, FALSE); + AddSLine(5); + if (boyitem._itype != -1) { + AddSText(0, 8, TRUE, "Talk to Wirt", ICOLOR_BLUE, TRUE); + AddSText(0, 12, TRUE, "I have something for sale,", ICOLOR_GOLD, FALSE); + AddSText(0, 14, TRUE, "but it will cost 50 gold", ICOLOR_GOLD, FALSE); + AddSText(0, 16, TRUE, "just to take a look. ", ICOLOR_GOLD, FALSE); + AddSText(0, 18, TRUE, "What have you got?", ICOLOR_WHITE, TRUE); + AddSText(0, 20, TRUE, "Say goodbye", ICOLOR_WHITE, TRUE); + } + else { + AddSText(0, 12, TRUE, "Talk to Wirt", ICOLOR_BLUE, TRUE); + AddSText(0, 18, TRUE, "Say goodbye", ICOLOR_WHITE, TRUE); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartBBoy() +{ + int iclr; + + stextsize = STEXT_LARGE; + stextscrl = FALSE; + sprintf(tempstr, "I have this item for sale : Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + iclr = ICOLOR_WHITE; + if (boyitem._iMagical) iclr = ICOLOR_BLUE; + if (!boyitem._iStatFlag) iclr = ICOLOR_RED; + if (boyitem._iMagical) AddSText(20, 10, FALSE, boyitem._iIName, iclr, TRUE); + else AddSText(20, 10, FALSE, boyitem._iName, iclr, TRUE); +// PATCH2.JMM + // No actual change--just note that the value of the item = 75% value + AddSTextVal(10, boyitem._iIvalue - (boyitem._iIvalue >> 2)); +// ENDPATCH2.JMM + PrintStoreItem(&boyitem, 11, iclr); + AddSText(0, 22, TRUE, "Leave", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartHealer() +{ + // heal automatically + if (plr[myplr]._pHitPoints != plr[myplr]._pMaxHP) PlaySFX(IS_CAST8); + plr[myplr]._pHitPoints = plr[myplr]._pMaxHP; + plr[myplr]._pHPBase = plr[myplr]._pMaxHPBase; + drawhpflag = TRUE; + + stextsize = STEXT_SMALL; + stextscrl = FALSE; + AddSText(0, 1, TRUE, "Welcome to the", ICOLOR_GOLD, FALSE); + AddSText(0, 3, TRUE, "Healer's home", ICOLOR_GOLD, FALSE); + AddSText(0, 9, TRUE, "Would you like to:", ICOLOR_GOLD, FALSE); + AddSText(0, 12, TRUE, "Talk to Pepin", ICOLOR_BLUE, TRUE); +// AddSText(0, 14, TRUE, "Receive healing", ICOLOR_WHITE, TRUE); + AddSText(0, 14, TRUE, "Buy items", ICOLOR_WHITE, TRUE); + AddSText(0, 16, TRUE, "Leave Healer's home", ICOLOR_WHITE, TRUE); + AddSLine(5); + storenumh = 20; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_ScrollHBuy(int idx) +{ + int l, ls; + char iclr; + + ClearSText(5, 21); + stextup = 5; + for (l = 5; l < 20; l+=4) { + if (healitem[idx]._itype != -1) { + ls = l; + iclr = ICOLOR_WHITE; + if (!healitem[idx]._iStatFlag) iclr = ICOLOR_RED; + AddSText(20, l, FALSE, healitem[idx]._iName, iclr, TRUE); + AddSTextVal(l, healitem[idx]._iIvalue); + PrintStoreItem(&healitem[idx], l+1, iclr); + stextdown = ls; + idx++; + } + } + if ((!stext[stextsel]._ssel) && (stextsel != 22)) stextsel = stextdown; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartHBuy() +{ + int i; + + stextsize = STEXT_LARGE; + stextscrl = TRUE; + stextsval = 0; + sprintf(tempstr, "I have these items for sale : Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + S_ScrollHBuy(stextsval); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, FALSE); + OffsetSTextY(22, 6); + + storenumh = 0; + for (i = 0; healitem[i]._itype != -1; i++) storenumh++; + stextsmax = storenumh - 4; + if (stextsmax < 0) stextsmax = 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartStory() +{ + stextsize = STEXT_SMALL; + stextscrl = FALSE; + AddSText(0, 2, TRUE, "The Town Elder", ICOLOR_GOLD, FALSE); + AddSText(0, 9, TRUE, "Would you like to:", ICOLOR_GOLD, FALSE); + AddSText(0, 12, TRUE, "Talk to Cain", ICOLOR_BLUE, TRUE); + AddSText(0, 14, TRUE, "Identify an item", ICOLOR_WHITE, TRUE); + AddSText(0, 18, TRUE, "Say goodbye", ICOLOR_WHITE, TRUE); + AddSLine(5); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +BOOL IdItemOk(ItemStruct *i) +{ + if (i->_itype == -1) return(FALSE); + if (i->_iMagical == IMAGIC_NONE) return(FALSE); + if (i->_iIdentified) return(FALSE); + return(TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#define STOREIDCOST 100 + +void AddStoreHoldId(ItemStruct itm, int i) +{ + storehold[storenumh] = itm; + storehold[storenumh]._ivalue = STOREIDCOST; + storehold[storenumh]._iIvalue = STOREIDCOST; + storehidx[storenumh] = i; + storenumh++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartSIdentify() +{ + int i; + BOOL idok; + + stextsize = STEXT_LARGE; + idok = FALSE; + storenumh = 0; + for (i = 0; i < MAXHOLDITEMS; i++) storehold[i]._itype = -1; + if (IdItemOk(&plr[myplr].HeadItem)) { + idok = TRUE; + AddStoreHoldId(plr[myplr].HeadItem, -1); + } + if (IdItemOk(&plr[myplr].BodyItem)) { + idok = TRUE; + AddStoreHoldId(plr[myplr].BodyItem, -2); + } + if (IdItemOk(&plr[myplr].Hand1Item)) { + idok = TRUE; + AddStoreHoldId(plr[myplr].Hand1Item, -3); + } + if (IdItemOk(&plr[myplr].Hand2Item)) { + idok = TRUE; + AddStoreHoldId(plr[myplr].Hand2Item, -4); + } + if (IdItemOk(&plr[myplr].Ring1Item)) { + idok = TRUE; + AddStoreHoldId(plr[myplr].Ring1Item, -5); + } + if (IdItemOk(&plr[myplr].Ring2Item)) { + idok = TRUE; + AddStoreHoldId(plr[myplr].Ring2Item, -6); + } + if (IdItemOk(&plr[myplr].NeckItem)) { + idok = TRUE; + AddStoreHoldId(plr[myplr].NeckItem, -7); + } + for (i = 0; i < plr[myplr]._pNumInv && storenumh < MAXHOLDITEMS; i++) { + if (IdItemOk(&plr[myplr].InvList[i])) { + idok = TRUE; + AddStoreHoldId(plr[myplr].InvList[i], i); + } + } + if (!idok) { + stextscrl = FALSE; + sprintf(tempstr, "You have nothing to identify. Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } else { + stextscrl = TRUE; + stextsval = 0; + stextsmax = plr[myplr]._pNumInv; + sprintf(tempstr, "Identify which item? Your gold : %i", plr[myplr]._pGold); + AddSText(0, 1, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(3); + AddSLine(21); + S_ScrollSSell(stextsval); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); + OffsetSTextY(22, 6); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartIdShow() +{ + char iclr; + + StartStore(stextshold); + stextscrl = FALSE; + ClearSText(5, 23); + iclr = ICOLOR_WHITE; + if (plr[myplr].HoldItem._iMagical) iclr = ICOLOR_BLUE; + if (!plr[myplr].HoldItem._iStatFlag) iclr = ICOLOR_RED; + + AddSText(0, 7, TRUE, "This item is:", ICOLOR_WHITE, FALSE); + + AddSText(20, 11, FALSE, plr[myplr].HoldItem._iIName, iclr, FALSE); + PrintStoreItem(&plr[myplr].HoldItem, 12, iclr); + + AddSText(0, 18, TRUE, "Done", ICOLOR_WHITE, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#if !IS_VERSION(SHAREWARE) +void S_StartTalk() +{ + int i, tq, sn, la, gl; + + stextsize = STEXT_SMALL; + stextscrl = FALSE; + sprintf(tempstr, "Talk to %s", talkname[talker]); + AddSText(0, 2, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(5); + + tq = 0; + for (i = 0; i < MAXQUESTS; i++) { + if ((quests[i]._qactive == QUEST_NOTDONE) && (Qtalklist[talker][i] != -1) && quests[i]._qlog) tq++; + } + if (tq > 6) { + sn = 14 - (tq >> 1); + la = 1; + } else { + sn = 15 - tq; + la = 2; + } + gl = sn - 2; + for (i = 0; i < MAXQUESTS; i++) { + if ((quests[i]._qactive == QUEST_NOTDONE) && (Qtalklist[talker][i] != -1) && quests[i]._qlog) { + AddSText(0, sn, TRUE, questlist[i]._qlstr, ICOLOR_WHITE, TRUE); + sn += la; + } + } + + AddSText(0, gl, TRUE, "Gossip", ICOLOR_BLUE, TRUE); + + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); +} + +#else +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartShareTalk() +{ + stextsize = STEXT_SMALL; + stextscrl = FALSE; + sprintf(tempstr, "Talk to %s", talkname[talker]); + AddSText(0, 2, TRUE, tempstr, ICOLOR_GOLD, FALSE); + AddSLine(5); + + sprintf(tempstr, "Talking to %s", talkname[talker]); + AddSText(0, 10, TRUE, tempstr, ICOLOR_WHITE, FALSE); + AddSText(0, 12, TRUE, "is not available", ICOLOR_WHITE, FALSE); + AddSText(0, 14, TRUE, "in the shareware", ICOLOR_WHITE, FALSE); + AddSText(0, 16, TRUE, "version.", ICOLOR_WHITE, FALSE); + AddSText(0, 22, TRUE, "Back", ICOLOR_WHITE, TRUE); +} +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartTavern() +{ + stextsize = STEXT_SMALL; + stextscrl = FALSE; + AddSText(0, 1, TRUE, "Welcome to the", ICOLOR_GOLD, FALSE); + AddSText(0, 3, TRUE, "Rising Sun", ICOLOR_GOLD, FALSE); + AddSText(0, 9, TRUE, "Would you like to:", ICOLOR_GOLD, FALSE); + AddSText(0, 12, TRUE, "Talk to Ogden", ICOLOR_BLUE, TRUE); + AddSText(0, 18, TRUE, "Leave the tavern", ICOLOR_WHITE, TRUE); + AddSLine(5); + storenumh = 20; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartBarMaid() +{ + stextsize = STEXT_SMALL; + stextscrl = FALSE; + AddSText(0, 2, TRUE, "Gillian", ICOLOR_GOLD, FALSE); + AddSText(0, 9, TRUE, "Would you like to:", ICOLOR_GOLD, FALSE); + AddSText(0, 12, TRUE, "Talk to Gillian", ICOLOR_BLUE, TRUE); + AddSText(0, 18, TRUE, "Say goodbye", ICOLOR_WHITE, TRUE); + AddSLine(5); + storenumh = 20; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StartDrunk() +{ + stextsize = STEXT_SMALL; + stextscrl = FALSE; + AddSText(0, 2, TRUE, "Farnham the Drunk", ICOLOR_GOLD, FALSE); + AddSText(0, 9, TRUE, "Would you like to:", ICOLOR_GOLD, FALSE); + AddSText(0, 12, TRUE, "Talk to Farnham", ICOLOR_BLUE, TRUE); + AddSText(0, 18, TRUE, "Say Goodbye", ICOLOR_WHITE, TRUE); + AddSLine(5); + storenumh = 20; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void StartStore(char s) +{ + int i; + + sbookflag = FALSE; + invflag = FALSE; + chrflag = FALSE; + questlog = FALSE; + dropGoldFlag = FALSE; + ClearSText(0, NUMSTLINES); + ReleaseStoreBtn(); + switch(s) { + case STORE_SMITH: + S_StartSmith(); + break; + case STORE_SBUY: + if (storenumh > 0) S_StartSBuy(); + break; + case STORE_SSELL: + S_StartSSell(); + break; + case STORE_SREPAIR: + S_StartSRepair(); + break; + case STORE_WITCH: + S_StartWitch(); + break; + case STORE_WBUY: + if (storenumh > 0) S_StartWBuy(); + break; + case STORE_WSELL: + S_StartWSell(); + break; + case STORE_WRECHARGE: + S_StartWRecharge(); + break; + case STORE_NOMONEY: + S_StartNoMoney(); + break; + case STORE_NOROOM: + S_StartNoRoom(); + break; + case STORE_CONFIRM: + S_StartConfirm(); + break; + case STORE_BOY: + S_StartBoy(); + break; + case STORE_BBUY: + S_StartBBoy(); + break; + case STORE_HEALER: + S_StartHealer(); + break; + case STORE_STORYTLR: + S_StartStory(); + break; + case STORE_HBUY: + if (storenumh > 0) S_StartHBuy(); + break; + case STORE_STORYID: + S_StartSIdentify(); + break; + case STORE_SPBUY: + if (! S_StartSPBuy()) return; + break; + case STORE_TALK: + #if IS_VERSION(SHAREWARE) + S_StartShareTalk(); + #else + S_StartTalk(); + #endif + break; + case STORE_IDSHOW: + S_StartIdShow(); + break; + case STORE_TAVERN: + S_StartTavern(); + break; + case STORE_DRUNK: + S_StartDrunk(); + break; + case STORE_BARMAID: + S_StartBarMaid(); + break; + } + + for (i = 0; (i < NUMSTLINES) && (!stext[i]._ssel); i++) + NULL; + if (i == NUMSTLINES) stextsel = -1; + else stextsel = i; + stextflag = s; + if (s == STORE_SBUY && storenumh == 0) { + StartStore(STORE_SMITH); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void DrawSText() +{ + int i; + + // Draw background + if (stextsize == STEXT_SMALL) DrawSTextBack(); + else DrawQTextBack(); + + if (stextscrl) { + switch(stextflag) { + case STORE_SBUY: + S_ScrollSBuy(stextsval); + break; + case STORE_SPBUY: + S_ScrollSPBuy(stextsval); + break; + case STORE_SSELL: + case STORE_SREPAIR: + case STORE_WSELL: + case STORE_WRECHARGE: + case STORE_STORYID: + S_ScrollSSell(stextsval); + break; + case STORE_WBUY: + S_ScrollWBuy(stextsval); + break; + case STORE_HBUY: + S_ScrollHBuy(stextsval); + break; + } + } + + for (i = 0; i < NUMSTLINES; i++) { + if (stext[i]._sline) DrawSLine(i); + if (stext[i]._sstr[0] != 0) PrintSString(stext[i]._sx, i, stext[i]._sjust, stext[i]._sstr, stext[i]._sclr, stext[i]._sval); + } + + if (stextscrl) DrawScrlBar(4, 20); + + stextspin = (stextspin & 0x7) + 1; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void STextESC() +{ + if (qtextflag) { + qtextflag = FALSE; + if (leveltype == 0) stream_stop(); + return; + } + switch(stextflag) { + case STORE_SMITH: + case STORE_WITCH: + case STORE_BOY: + case STORE_BBUY: + case STORE_HEALER: + case STORE_STORYTLR: + case STORE_TAVERN: + case STORE_BARMAID: + case STORE_DRUNK: + stextflag = STORE_NONE; + break; + case STORE_TALK: + StartStore(stextshold); + stextsel = stextlhold; + break; + case STORE_SBUY: + StartStore(STORE_SMITH); + stextsel = 12; + break; + case STORE_SPBUY: + StartStore(STORE_SMITH); + stextsel = 14; + break; + case STORE_SSELL: + StartStore(STORE_SMITH); + stextsel = 16; + break; + case STORE_SREPAIR: + StartStore(STORE_SMITH); + stextsel = 18; + break; + case STORE_WBUY: + StartStore(STORE_WITCH); + stextsel = 14; + break; + case STORE_WSELL: + StartStore(STORE_WITCH); + stextsel = 16; + break; + case STORE_WRECHARGE: + StartStore(STORE_WITCH); + stextsel = 18; + break; + case STORE_HBUY: + StartStore(STORE_HEALER); + stextsel = 16; + break; + case STORE_STORYID: + StartStore(STORE_STORYTLR); + stextsel = 14; + break; + case STORE_IDSHOW: + StartStore(STORE_STORYID); + break; + case STORE_NOMONEY: + case STORE_NOROOM: + case STORE_CONFIRM: + StartStore(stextshold); + stextsel = stextlhold; + stextsval = stextvhold; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void STextUp() +{ + PlaySFX(IS_TITLEMOV); + if (stextsel != -1) { + if (stextscrl) { + if (stextsel == stextup) { + if (stextsval != 0) stextsval--; + } else { + stextsel--; + while (!stext[stextsel]._ssel) { + if (stextsel == 0) stextsel = NUMSTLINES-1; + else stextsel--; + } + } + } else { + if (stextsel == 0) stextsel = NUMSTLINES-1; + else stextsel--; + while (!stext[stextsel]._ssel) { + if (stextsel == 0) stextsel = NUMSTLINES-1; + else stextsel--; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void STextDown() +{ + PlaySFX(IS_TITLEMOV); + if (stextsel != -1) { + if (stextscrl) { + if (stextsel == stextdown) { + if (stextsval < stextsmax) stextsval++; + } else { + stextsel++; + while (!stext[stextsel]._ssel) { + if (stextsel == NUMSTLINES-1) stextsel = 0; + else stextsel++; + } + } + } else { + if (stextsel == NUMSTLINES-1) stextsel = 0; + else stextsel++; + while (!stext[stextsel]._ssel) { + if (stextsel == NUMSTLINES-1) stextsel = 0; + else stextsel++; + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void STextPgUp() +{ + PlaySFX(IS_TITLEMOV); + if ((stextsel != -1) && (stextscrl)) { + if (stextsel == stextup) { + if (stextsval != 0) stextsval-=4; + if (stextsval < 0) stextsval = 0; + } else { + stextsel = stextup; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void STextPgDown() +{ + PlaySFX(IS_TITLEMOV); + if ((stextsel != -1) && (stextscrl)) { + if (stextsel == stextdown) { + if (stextsval < stextsmax) stextsval+=4; + if (stextsval > stextsmax) stextsval = stextsmax; + } else { + stextsel = stextdown; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_SmithEnter() +{ + switch(stextsel) { + case 10: + talker = TWN_BLKSMITH; + stextshold = STORE_SMITH; + stextlhold = 10; + gossipstart = TXT_GRIS2; + gossipend = TXT_GRIS13; + StartStore(STORE_TALK); + break; + case 12: + StartStore(STORE_SBUY); + break; + case 14: + StartStore(STORE_SPBUY); + break; + case 16: + StartStore(STORE_SSELL); + break; + case 18: + StartStore(STORE_SREPAIR); + break; + case 20: + stextflag = STORE_NONE; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetGoldCurs(int pnum, int i) +{ + if (plr[pnum].InvList[i]._ivalue >= GOLD_VT2) { + plr[pnum].InvList[i]._iCurs = ITEM_5GOLD; + } else { + if (plr[pnum].InvList[i]._ivalue <= GOLD_VT1) plr[pnum].InvList[i]._iCurs = ITEM_1GOLD; + else plr[pnum].InvList[i]._iCurs = ITEM_3GOLD; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SetSpdbarGoldCurs(int pnum, int i) +{ + if (plr[pnum].SpdList[i]._ivalue >= GOLD_VT2) { + plr[pnum].SpdList[i]._iCurs = ITEM_5GOLD; + } else { + if (plr[pnum].SpdList[i]._ivalue <= GOLD_VT1) plr[pnum].SpdList[i]._iCurs = ITEM_1GOLD; + else plr[pnum].SpdList[i]._iCurs = ITEM_3GOLD; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TakePlrsMoney(long cost) +{ + int i; + + // Take players money + plr[myplr]._pGold = CalculateGold(myplr) - cost; + + // Remove gold from speed list first; if there is any + // Try non GOLD_VMAX first, then break into the GOLD_VMAX piles + for (i = 0; ((i < MAXSPD) && (cost > 0)); i++) { + if ((plr[myplr].SpdList[i]._itype == IT_GOLD) && + (plr[myplr].SpdList[i]._ivalue != GOLD_VMAX)) { + if (cost < plr[myplr].SpdList[i]._ivalue) { + plr[myplr].SpdList[i]._ivalue -= cost; + SetSpdbarGoldCurs(myplr, i); + cost = 0; + } else { + cost -= plr[myplr].SpdList[i]._ivalue; + RemoveSpdBarItem(myplr, i); + i = -1; // restart looping + } + } + } + if (cost > 0) { + // GOLD_VMAX piles + for (i = 0; ((i < MAXSPD) && (cost > 0)); i++) { + if (plr[myplr].SpdList[i]._itype == IT_GOLD) { + if (cost < plr[myplr].SpdList[i]._ivalue) { + plr[myplr].SpdList[i]._ivalue -= cost; + SetSpdbarGoldCurs(myplr, i); + cost = 0; + } else { + cost -= plr[myplr].SpdList[i]._ivalue; + RemoveSpdBarItem(myplr, i); + i = -1; // restart looping + } + } + } + } + force_redraw = FULLDRAW; + + // Remove gold from inventory list if there was no gold in the speed list + // or all gold from the speed list was deplenished. + // Try non GOLD_VMAX first, then break into the GOLD_VMAX piles + if (cost > 0) { + for (i = 0; ((i < plr[myplr]._pNumInv) && (cost > 0)); i++) { + if ((plr[myplr].InvList[i]._itype == IT_GOLD) && + (plr[myplr].InvList[i]._ivalue != GOLD_VMAX)) { + if (cost < plr[myplr].InvList[i]._ivalue) { + plr[myplr].InvList[i]._ivalue -= cost; + SetGoldCurs(myplr, i); + cost = 0; + } else { + cost -= plr[myplr].InvList[i]._ivalue; + RemoveInvItem(myplr, i); + i = -1; // restart looping + } + } + } + if (cost > 0) { + // GOLD_VMAX piles + for (i = 0; ((i < plr[myplr]._pNumInv) && (cost > 0)); i++) { + if (plr[myplr].InvList[i]._itype == IT_GOLD) { + if (cost < plr[myplr].InvList[i]._ivalue) { + plr[myplr].InvList[i]._ivalue -= cost; + SetGoldCurs(myplr, i); + cost = 0; + } else { + cost -= plr[myplr].InvList[i]._ivalue; + RemoveInvItem(myplr, i); + i = -1; // restart looping + } + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SmithBuyItem() +{ + int idx; + + // Take players money + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + + // Put in players inv + if (!plr[myplr].HoldItem._iMagical) plr[myplr].HoldItem._iIdentified = FALSE; + StoreAutoPlace(); + + // Remove from smithitems + idx = ((stextlhold - stextup) >> 2) + stextvhold; + if (idx == MAXSMITHITEMS-1) smithitem[idx]._itype = -1; + else { + while (smithitem[idx+1]._itype != -1) { + smithitem[idx] = smithitem[idx+1]; + idx++; + } + smithitem[idx]._itype = -1; + } + + CalcPlrInv(myplr, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_SBuyEnter() +{ + int idx, i; + BOOL done; + + if (stextsel == 22) { + StartStore(STORE_SMITH); + stextsel = 12; + } else { + stextshold = STORE_SBUY; + stextlhold = stextsel; + stextvhold = stextsval; + idx = ((stextsel - stextup) >> 2) + stextsval; + if (plr[myplr]._pGold < smithitem[idx]._iIvalue) { + StartStore(STORE_NOMONEY); + } else { + plr[myplr].HoldItem = smithitem[idx]; + SetCursor(plr[myplr].HoldItem._iCurs + ICSTART); + done = FALSE; + for (i = 0; (i < MAXINV) && (!done); i++) done = AutoPlace(myplr, i, cursW/28, cursH/28, FALSE); + if (done) StartStore(STORE_CONFIRM); + else StartStore(STORE_NOROOM); + SetCursor(GLOVE_CURS); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SmithBuyPItem() +{ + int idx, i; + + // Take players money + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + + // Put in players inv + if (!plr[myplr].HoldItem._iMagical) plr[myplr].HoldItem._iIdentified = FALSE; + StoreAutoPlace(); + + // Remove from premiumitems + int xx = ((stextlhold - stextup) >> 2) + stextvhold; + idx = 0; + for (i = 0; xx >= 0; i++) { + if (premiumitem[i]._itype != -1) { + xx--; + idx = i; + } + } + premiumitem[idx]._itype = -1; + numpremium--; + + // replenish premium list + SpawnPremium(myplr); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_SPBuyEnter() +{ + int idx, i; + BOOL done; + + if (stextsel == 22) { + StartStore(STORE_SMITH); + stextsel = 14; + } else { + stextshold = STORE_SPBUY; + stextlhold = stextsel; + stextvhold = stextsval; + int xx = ((stextsel - stextup) >> 2) + stextsval; + idx = 0; + for (i = 0; xx >= 0; i++) { + if (premiumitem[i]._itype != -1) { + xx--; + idx = i; + } + } + if (plr[myplr]._pGold < premiumitem[idx]._iIvalue) { + StartStore(STORE_NOMONEY); + } else { + plr[myplr].HoldItem = premiumitem[idx]; + SetCursor(plr[myplr].HoldItem._iCurs + ICSTART); + done = FALSE; + for (i = 0; (i < MAXINV) && (!done); i++) done = AutoPlace(myplr, i, cursW/28, cursH/28, FALSE); + if (done) StartStore(STORE_CONFIRM); + else StartStore(STORE_NOROOM); + SetCursor(GLOVE_CURS); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL StoreGoldFit(int idx) +{ + int sz, numsqrs, i; + long cost; + + // How many squares am I going to need? + cost = storehold[idx]._iIvalue; + numsqrs = cost / GOLD_VMAX; + if ((cost % GOLD_VMAX) != 0) numsqrs++; + SetCursor(storehold[idx]._iCurs + ICSTART); + sz = (cursW/28) * (cursH/28); + SetCursor(GLOVE_CURS); + if (sz >= numsqrs) return(TRUE); + for (i = 0; i < MAXINV; i++) { + if (plr[myplr].InvGrid[i] == 0) sz++; + } + for (i = 0; i < plr[myplr]._pNumInv; i++) { + if ((plr[myplr].InvList[i]._itype == IT_GOLD) && + (plr[myplr].InvList[i]._ivalue != GOLD_VMAX)) { + if ((cost + plr[myplr].InvList[i]._ivalue) <= GOLD_VMAX) cost = 0; + else cost -= (GOLD_VMAX - plr[myplr].InvList[i]._ivalue); + } + } + numsqrs = cost / GOLD_VMAX; + if ((cost % GOLD_VMAX) != 0) numsqrs++; + if (sz >= numsqrs) return(TRUE); + else return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PlaceStoreGold(long v) +{ + int i, ii, xx, yy; + BOOL done; + + done = FALSE; + for (ii = 0; (ii < MAXINV) && (!done); ii++) { + yy = (ii / 10) * 10; + xx = ii % 10; + if (plr[myplr].InvGrid[xx+yy] == 0) { + i = plr[myplr]._pNumInv; + // drb.patch1.start.02/13/97 + void GetGoldSeed(int pnum, ItemStruct *h); + GetGoldSeed(myplr, &golditem); + // drb.patch1.end.02/13/97 + plr[myplr].InvList[i] = golditem; + plr[myplr]._pNumInv++; + plr[myplr].InvGrid[xx+yy] = plr[myplr]._pNumInv; + plr[myplr].InvList[i]._ivalue = v; + SetGoldCurs(myplr, i); + done = TRUE; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void StoreSellItem() +{ + int idx, i; + long cost; + + // Remove item from inv + idx = ((stextlhold - stextup) >> 2) + stextvhold; + if (storehidx[idx] >= 0) RemoveInvItem(myplr, storehidx[idx]); + else RemoveSpdBarItem(myplr, -(storehidx[idx]+1)); + + // Get value + cost = storehold[idx]._iIvalue; + + // Remove from hold list + storenumh--; + if (idx != storenumh) { + while (idx < storenumh) { + storehold[idx] = storehold[idx+1]; + storehidx[idx] = storehidx[idx+1]; + idx++; + } + } + + // Add value to player + plr[myplr]._pGold += cost; + // Try placing with other gold first + for (i = 0; ((i < plr[myplr]._pNumInv) && (cost > 0)); i++) { + if ((plr[myplr].InvList[i]._itype == IT_GOLD) && + (plr[myplr].InvList[i]._ivalue != GOLD_VMAX)) { + if ((cost + plr[myplr].InvList[i]._ivalue) <= GOLD_VMAX) { + plr[myplr].InvList[i]._ivalue += cost; + SetGoldCurs(myplr, i); + cost = 0; + } else { + cost -= (GOLD_VMAX - plr[myplr].InvList[i]._ivalue); + plr[myplr].InvList[i]._ivalue = GOLD_VMAX; + SetGoldCurs(myplr, i); + } + } + } + // Place new gold slots + if (cost > 0) { + while (cost > GOLD_VMAX) { + PlaceStoreGold(GOLD_VMAX); + cost -= GOLD_VMAX; + } + PlaceStoreGold(cost); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_SSellEnter() +{ + int idx; + + if (stextsel == 22) { + StartStore(STORE_SMITH); + stextsel = 16; + } else { + stextshold = STORE_SSELL; + stextlhold = stextsel; + stextvhold = stextsval; + idx = ((stextsel - stextup) >> 2) + stextsval; + plr[myplr].HoldItem = storehold[idx]; + if (StoreGoldFit(idx)) StartStore(STORE_CONFIRM); + else StartStore(STORE_NOROOM); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SmithRepairItem() +{ + int i, idx; + + // Take players money + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + + idx = ((stextlhold - stextup) >> 2) + stextvhold; + storehold[idx]._iDurability = storehold[idx]._iMaxDur; + i = storehidx[idx]; + if (i < 0) { + if (i == -1) plr[myplr].HeadItem._iDurability = plr[myplr].HeadItem._iMaxDur; + if (i == -2) plr[myplr].BodyItem._iDurability = plr[myplr].BodyItem._iMaxDur; + if (i == -3) plr[myplr].Hand1Item._iDurability = plr[myplr].Hand1Item._iMaxDur; + if (i == -4) plr[myplr].Hand2Item._iDurability = plr[myplr].Hand2Item._iMaxDur; + } else plr[myplr].InvList[i]._iDurability = plr[myplr].InvList[i]._iMaxDur; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_SRepairEnter() +{ + int idx; + + if (stextsel == 22) { + StartStore(STORE_SMITH); + stextsel = 18; + } else { + stextshold = STORE_SREPAIR; + stextlhold = stextsel; + stextvhold = stextsval; + idx = ((stextsel - stextup) >> 2) + stextsval; + plr[myplr].HoldItem = storehold[idx]; + if (plr[myplr]._pGold < storehold[idx]._iIvalue) StartStore(STORE_NOMONEY); + else StartStore(STORE_CONFIRM); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_WitchEnter() +{ + switch(stextsel) { + case 12: + talker = TWN_WITCH; + stextshold = STORE_WITCH; + stextlhold = 12; + gossipstart = TXT_ADRIA2; + gossipend = TXT_ADRIA13; + StartStore(STORE_TALK); + break; + case 14: + StartStore(STORE_WBUY); + break; + case 16: + StartStore(STORE_WSELL); + break; + case 18: + StartStore(STORE_WRECHARGE); + break; + case 20: + stextflag = STORE_NONE; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void WitchBuyItem() +{ + int idx; + + // Check if mana, full mana, portal, at top of list. These need new seeds + idx = ((stextlhold - stextup) >> 2) + stextvhold; + if (idx < 3) plr[myplr].HoldItem._iSeed = GetRndSeed(); + + // Take players money + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + + // Put in players inv + StoreAutoPlace(); + + // Remove from witchitems + // If item index is mana, don't remove from her items list + if (idx < 3) { + CalcPlrInv(myplr, TRUE); + return; + } + if (idx == MAXWITCHITEMS-1) witchitem[idx]._itype = -1; + else { + while (witchitem[idx+1]._itype != -1) { + witchitem[idx] = witchitem[idx+1]; + idx++; + } + witchitem[idx]._itype = -1; + } + + CalcPlrInv(myplr, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_WBuyEnter() +{ + int idx, i; + BOOL done; + + if (stextsel == 22) { + StartStore(STORE_WITCH); + stextsel = 14; + } else { + stextshold = STORE_WBUY; + stextlhold = stextsel; + stextvhold = stextsval; + idx = ((stextsel - stextup) >> 2) + stextsval; + if (plr[myplr]._pGold < witchitem[idx]._iIvalue) { + StartStore(STORE_NOMONEY); + } else { + plr[myplr].HoldItem = witchitem[idx]; + SetCursor(plr[myplr].HoldItem._iCurs + ICSTART); + done = FALSE; + for (i = 0; (i < MAXINV) && (!done); i++) done = SpecialAutoPlace(myplr, i, cursW/28, cursH/28, FALSE); + if (done) StartStore(STORE_CONFIRM); + else StartStore(STORE_NOROOM); + SetCursor(GLOVE_CURS); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_WSellEnter() +{ + int idx; + + if (stextsel == 22) { + StartStore(STORE_WITCH); + stextsel = 16; + } else { + stextshold = STORE_WSELL; + stextlhold = stextsel; + stextvhold = stextsval; + idx = ((stextsel - stextup) >> 2) + stextsval; + plr[myplr].HoldItem = storehold[idx]; + if (StoreGoldFit(idx)) StartStore(STORE_CONFIRM); + else StartStore(STORE_NOROOM); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void WitchRechargeItem() +{ + int i, idx; + + // Take players money + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + + // Recharge staff + idx = ((stextlhold - stextup) >> 2) + stextvhold; + storehold[idx]._iCharges = storehold[idx]._iMaxCharges; + i = storehidx[idx]; + if (i < 0) plr[myplr].Hand1Item._iCharges = plr[myplr].Hand1Item._iMaxCharges; + else plr[myplr].InvList[i]._iCharges = plr[myplr].InvList[i]._iMaxCharges; + CalcPlrInv(myplr, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_WRechargeEnter() +{ + int idx; + + if (stextsel == 22) { + StartStore(STORE_WITCH); + stextsel = 18; + } else { + stextshold = STORE_WRECHARGE; + stextlhold = stextsel; + stextvhold = stextsval; + idx = ((stextsel - stextup) >> 2) + stextsval; + plr[myplr].HoldItem = storehold[idx]; + if (plr[myplr]._pGold < storehold[idx]._iIvalue) StartStore(STORE_NOMONEY); + else StartStore(STORE_CONFIRM); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_BoyEnter() +{ + if ((boyitem._itype != -1) && (stextsel == 18)) { + if (plr[myplr]._pGold < 50) { + stextshold = STORE_BOY; + stextlhold = stextsel; + stextvhold = stextsval; + StartStore(STORE_NOMONEY); + } else { + TakePlrsMoney(50); + StartStore(STORE_BBUY); + } + } else { + if ( ((stextsel == 8) && (boyitem._itype != -1)) || ((stextsel == 12) && (boyitem._itype == -1)) ) { + talker = TWN_BOY; + stextshold = STORE_BOY; + stextlhold = stextsel; + gossipstart = TXT_WIRT2; + gossipend = TXT_WIRT12; + StartStore(STORE_TALK); + } else stextflag = STORE_NONE; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void BoyBuyItem() +{ + // Take players money + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + + // Put in players inv + StoreAutoPlace(); + + // Remove from boyitem + boyitem._itype = -1; + stextshold = STORE_BOY; + + CalcPlrInv(myplr, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void HealerBuyItem() +{ + int idx; + + // Check if healing, full healing at top of list. These need new seeds + idx = ((stextlhold - stextup) >> 2) + stextvhold; + if (gbMaxPlayers == 1) { + if (idx < 2) plr[myplr].HoldItem._iSeed = GetRndSeed(); + } else { + if (idx < 3) plr[myplr].HoldItem._iSeed = GetRndSeed(); + } + + // Take players money + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + + // Put in players inv + if (!plr[myplr].HoldItem._iMagical) plr[myplr].HoldItem._iIdentified = FALSE; + StoreAutoPlace(); + + // Remove from healitems + // If item index is mana, don't remove from his items list + if (gbMaxPlayers == 1) { + if (idx < 2) return; + } else { + if (idx < 3) return; + } + idx = ((stextlhold - stextup) >> 2) + stextvhold; + if (idx == MAXHEALITEMS-1) healitem[idx]._itype = -1; + else { + while (healitem[idx+1]._itype != -1) { + healitem[idx] = healitem[idx+1]; + idx++; + } + healitem[idx]._itype = -1; + } + + CalcPlrInv(myplr, TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_BBuyEnter() +{ + int i; + BOOL done; + + if (stextsel == 10) { + stextshold = STORE_BBUY; + stextlhold = stextsel; + stextvhold = stextsval; + // PATCH2.JMM + //if (plr[myplr]._pGold < ( boyitem._iIvalue + ) StartStore(STORE_NOMONEY); + if (plr[myplr]._pGold < ( boyitem._iIvalue - (boyitem._iIvalue >> 2) ) ) StartStore(STORE_NOMONEY); + // ENDPATCH2.JMM + else { + plr[myplr].HoldItem = boyitem; + plr[myplr].HoldItem._iIvalue -= (plr[myplr].HoldItem._iIvalue >> 2); + SetCursor(plr[myplr].HoldItem._iCurs + ICSTART); + done = FALSE; + for (i = 0; (i < MAXINV) && (!done); i++) done = AutoPlace(myplr, i, cursW/28, cursH/28, FALSE); + if (done) StartStore(STORE_CONFIRM); + else StartStore(STORE_NOROOM); + SetCursor(GLOVE_CURS); + } + } else stextflag = STORE_NONE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void StoryIdItem() +{ + int i, idx; + + idx = ((stextlhold - stextup) >> 2) + stextvhold; + i = storehidx[idx]; + if (i < 0) { + if (i == -1) plr[myplr].HeadItem._iIdentified = TRUE; + if (i == -2) plr[myplr].BodyItem._iIdentified = TRUE; + if (i == -3) plr[myplr].Hand1Item._iIdentified = TRUE; + if (i == -4) plr[myplr].Hand2Item._iIdentified = TRUE; + if (i == -5) plr[myplr].Ring1Item._iIdentified = TRUE; + if (i == -6) plr[myplr].Ring2Item._iIdentified = TRUE; + if (i == -7) plr[myplr].NeckItem._iIdentified = TRUE; + } + else + plr[myplr].InvList[i]._iIdentified = TRUE; + + plr[myplr].HoldItem._iIdentified = TRUE; + + // Take players money + TakePlrsMoney(plr[myplr].HoldItem._iIvalue); + CalcPlrInv(myplr,TRUE); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_ConfirmEnter() +{ + if (stextsel == 18) { + switch(stextshold) { + case STORE_SBUY: + SmithBuyItem(); + break; + case STORE_SPBUY: + SmithBuyPItem(); + break; + case STORE_SSELL: + case STORE_WSELL: + StoreSellItem(); + break; + case STORE_SREPAIR: + SmithRepairItem(); + break; + case STORE_WBUY: + WitchBuyItem(); + break; + case STORE_WRECHARGE: + WitchRechargeItem(); + break; + case STORE_BBUY: + BoyBuyItem(); + break; + case STORE_HBUY: + HealerBuyItem(); + break; + case STORE_STORYID: + StoryIdItem(); + StartStore(STORE_IDSHOW); + return; + } + StartStore(stextshold); + } else { + StartStore(stextshold); + stextsel = stextlhold; + stextsval = stextvhold; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_HealerEnter() +{ + switch(stextsel) { + case 12: + talker = TWN_HEALER; + stextshold = STORE_HEALER; + stextlhold = 12; + gossipstart = TXT_PEPIN2; + gossipend = TXT_PEPIN11; + StartStore(STORE_TALK); + break; +// case 14: +// if (plr[myplr]._pHitPoints != plr[myplr]._pMaxHP) PlaySFX(IS_CAST8); +// plr[myplr]._pHitPoints = plr[myplr]._pMaxHP; +// plr[myplr]._pHPBase = plr[myplr]._pMaxHPBase; +// drawhpflag = TRUE; +// break; + case 14: + StartStore(STORE_HBUY); + break; + case 16: + stextflag = STORE_NONE; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_HBuyEnter() +{ + int idx, i; + BOOL done; + + if (stextsel == 22) { + StartStore(STORE_HEALER); + stextsel = 16; + } else { + stextshold = STORE_HBUY; + stextlhold = stextsel; + stextvhold = stextsval; + idx = ((stextsel - stextup) >> 2) + stextsval; + if (plr[myplr]._pGold < healitem[idx]._iIvalue) { + StartStore(STORE_NOMONEY); + } else { + plr[myplr].HoldItem = healitem[idx]; + SetCursor(plr[myplr].HoldItem._iCurs + ICSTART); + done = FALSE; + for (i = 0; (i < MAXINV) && (!done); i++) done = SpecialAutoPlace(myplr, i, cursW/28, cursH/28, FALSE); + if (done) StartStore(STORE_CONFIRM); + else StartStore(STORE_NOROOM); + SetCursor(GLOVE_CURS); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_StoryEnter() +{ + switch(stextsel) { + case 12: + talker = TWN_TELLER; + stextshold = STORE_STORYTLR; + stextlhold = 12; + gossipstart = TXT_STORY2; + gossipend = TXT_STORY11; + StartStore(STORE_TALK); + break; + case 14: + StartStore(STORE_STORYID); + break; + case 18: + stextflag = STORE_NONE; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_SIDEnter() +{ + int idx; + + if (stextsel == 22) { + StartStore(STORE_STORYTLR); + stextsel = 14; + } else { + stextshold = STORE_STORYID; + stextlhold = stextsel; + stextvhold = stextsval; + idx = ((stextsel - stextup) >> 2) + stextsval; + plr[myplr].HoldItem = storehold[idx]; + if (plr[myplr]._pGold < storehold[idx]._iIvalue) StartStore(STORE_NOMONEY); + else StartStore(STORE_CONFIRM); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_TalkEnter() +{ + int i, tq, sn, la; + + if (stextsel == 22) { + StartStore(stextshold); + stextsel = stextlhold; + } else { + tq = 0; + for (i = 0; i < MAXQUESTS; i++) { + if ((quests[i]._qactive == QUEST_NOTDONE) && (Qtalklist[talker][i] != -1) && quests[i]._qlog) tq++; + } + if (tq > 6) { + sn = 14 - (tq >> 1); + la = 1; + } else { + sn = 15 - tq; + la = 2; + } + if (stextsel == (sn - 2)) { + // Gossip + SetRndSeed(towner[talker]._tSeed); + int m = random(0, gossipend - gossipstart + 1) + gossipstart; + InitQTextMsg(m); + } else { + // Quest info + for (i = 0; i < MAXQUESTS; i++) { + if ((quests[i]._qactive == QUEST_NOTDONE) && (Qtalklist[talker][i] != -1) && quests[i]._qlog) { + if (sn == stextsel) InitQTextMsg(Qtalklist[talker][i]); + sn += la; + } + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_TavernEnter() +{ + switch(stextsel) { + case 12: + talker = TWN_BAROWNER; + stextshold = STORE_TAVERN; + stextlhold = 12; + gossipstart = TXT_OGDEN2; + gossipend = TXT_OGDEN10; + StartStore(STORE_TALK); + break; + case 18: + stextflag = STORE_NONE; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_BarmaidEnter() +{ + switch(stextsel) { + case 12: + talker = TWN_BARMAID; + stextshold = STORE_BARMAID; + stextlhold = 12; + gossipstart = TXT_GILIAN2; + gossipend = TXT_GILIAN10; + StartStore(STORE_TALK); + break; + case 18: + stextflag = STORE_NONE; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void S_DrunkEnter() +{ + switch(stextsel) { + case 12: + talker = TWN_DRUNK; + stextshold = STORE_DRUNK; + stextlhold = 12; + gossipstart = TXT_FARN2; + gossipend = TXT_FARN13; + StartStore(STORE_TALK); + break; + case 18: + stextflag = STORE_NONE; + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void STextEnter() +{ + if (qtextflag) { + qtextflag = FALSE; + if (leveltype == 0) stream_stop(); + return; + } + PlaySFX(IS_TITLSLCT); + switch(stextflag) { + case STORE_SMITH: + S_SmithEnter(); + break; + case STORE_SBUY: + S_SBuyEnter(); + break; + case STORE_SPBUY: + S_SPBuyEnter(); + break; + case STORE_SSELL: + S_SSellEnter(); + break; + case STORE_SREPAIR: + S_SRepairEnter(); + break; + case STORE_WITCH: + S_WitchEnter(); + break; + case STORE_WBUY: + S_WBuyEnter(); + break; + case STORE_WSELL: + S_WSellEnter(); + break; + case STORE_WRECHARGE: + S_WRechargeEnter(); + break; + case STORE_NOMONEY: + case STORE_NOROOM: + StartStore(stextshold); + stextsel = stextlhold; + stextsval = stextvhold; + break; + case STORE_CONFIRM: + S_ConfirmEnter(); + break; + case STORE_BOY: + S_BoyEnter(); + break; + case STORE_BBUY: + S_BBuyEnter(); + break; + case STORE_HEALER: + S_HealerEnter(); + break; + case STORE_STORYTLR: + S_StoryEnter(); + break; + case STORE_HBUY: + S_HBuyEnter(); + break; + case STORE_STORYID: + S_SIDEnter(); + break; + case STORE_TALK: + S_TalkEnter(); + break; + case STORE_IDSHOW: + StartStore(STORE_STORYID); + break; + case STORE_TAVERN: + S_TavernEnter(); + break; + case STORE_BARMAID: + S_BarmaidEnter(); + break; + case STORE_DRUNK: + S_DrunkEnter(); + break; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckStoreBtn() +{ + int y; + + if (qtextflag) { + qtextflag = FALSE; + if (leveltype == 0) stream_stop(); + return; + } + if (stextsel == -1) return; + if ((MouseY < 32) || (MouseY > 320)) return; + if (stextsize == STEXT_SMALL) { + if ((MouseX < 344) || (MouseX > 616)) return; + } else { + if ((MouseX < 24) || (MouseX > 616)) return; + } + y = (MouseY - 32) / 12; + if ((stextscrl) && (MouseX > 600)) { + if (y == 4) { + if (stextscrlubtn <= 0) { + STextUp(); + stextscrlubtn = 10; + } else stextscrlubtn--; + } + if (y == 20) { + if (stextscrldbtn <= 0) { + STextDown(); + stextscrldbtn = 10; + } else stextscrldbtn--; + } + } else { + if (y < 5) return; + if (y >= 23) y = 22; + if ((stextscrl) && (y < 21) && (!stext[y]._ssel)) { + if (stext[y-2]._ssel) y -= 2; + else if (stext[y-1]._ssel) y--; + } + if ((stext[y]._ssel) || (stextscrl && (y == 22))) { + stextsel = y; + STextEnter(); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void ReleaseStoreBtn() +{ + stextscrlubtn = -1; + stextscrldbtn = -1; +} + diff --git a/src/STORES.H b/src/STORES.H new file mode 100644 index 0000000..2dc1f50 --- /dev/null +++ b/src/STORES.H @@ -0,0 +1,115 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/STORES.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + + +#define MAXSMITHITEMS 25 +#define MAXWITCHITEMS 25 +#define MAXHEALITEMS 20 +#define MAXPREMIUM 15 + +#define NUMSTLINES ((MAXSMITHITEMS + 1) * 4) //24 + +#define STORE_NONE 0 +#define STORE_SMITH 1 +#define STORE_SBUY 2 +#define STORE_SSELL 3 +#define STORE_SREPAIR 4 +#define STORE_WITCH 5 +#define STORE_WBUY 6 +#define STORE_WSELL 7 +#define STORE_WRECHARGE 8 +#define STORE_NOMONEY 9 +#define STORE_NOROOM 10 +#define STORE_CONFIRM 11 +#define STORE_BOY 12 +#define STORE_BBUY 13 +#define STORE_HEALER 14 +#define STORE_STORYTLR 15 +#define STORE_HBUY 16 +#define STORE_STORYID 17 +#define STORE_SPBUY 18 +#define STORE_TALK 19 +#define STORE_IDSHOW 20 +#define STORE_TAVERN 21 +#define STORE_DRUNK 22 +#define STORE_BARMAID 23 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + int _sx; // X justify + int _syoff; // Y offset (usually 0) + char _sstr[128]; // string to print + BOOL _sjust; // Center, left, or right + char _sclr; // color + BOOL _sline; // just a line + BOOL _ssel; // selectable + //BOOL _shigh; // Highlighted + int _sval; // displayable value +} STextStruct; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern BYTE *pSTextBoxCels; +extern BYTE *pSTextSpinCels; +extern BYTE *pSTextSlidCels; + +extern int SStringY[]; + +extern char stextflag; +extern ItemStruct smithitem[]; +extern ItemStruct premiumitem[]; +extern int numpremium, premiumlevel; +extern ItemStruct witchitem[]; +extern ItemStruct boyitem; +extern int boylevel; +extern ItemStruct golditem; +extern ItemStruct healitem[]; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitStores(); +void SetupTownStores(); +void FreeStoreMem(); + +void DrawSText(); +void STextESC(); +void STextUp(); +void STextDown(); +void STextPgUp(); +void STextPgDown(); +void STextEnter(); + +void StartStore(char); + +void DrawSTextBack(); +void PrintSString(int x, int y, BOOL cjustflag, char str[], char col, int val); +void DrawSLine(int y); + +void SetupSTextWin(); +void SetupSTextLWin(); + +void CheckStoreBtn(); +void ReleaseStoreBtn(); + +void TakePlrsMoney(long); +void SetGoldCurs(int, int); + +void SetSpdbarGoldCurs(int pnum, int i); diff --git a/src/STORM.DLL b/src/STORM.DLL new file mode 100644 index 0000000..c8295c3 Binary files /dev/null and b/src/STORM.DLL differ diff --git a/src/STORM.H b/src/STORM.H new file mode 100644 index 0000000..2b4d22e --- /dev/null +++ b/src/STORM.H @@ -0,0 +1,1756 @@ +#ifndef _STORM_H_ +#define _STORM_H_ + +/**************************************************************************** +* +* Storm-specific error codes +* +***/ + +#define STORMFAC 0x510 +#define STORMERROR(code) (0x80000000 | (STORMFAC << 16) | ((code) & 0xFFFF)) + +#define STORM_ERROR_ASSERTION STORMERROR(0) +#define STORM_ERROR_BAD_ARGUMENT STORMERROR(101) +#define STORM_ERROR_GAME_ALREADY_STARTED STORMERROR(102) +#define STORM_ERROR_GAME_FULL STORMERROR(103) +#define STORM_ERROR_GAME_NOT_FOUND STORMERROR(104) +#define STORM_ERROR_GAME_TERMINATED STORMERROR(105) +#define STORM_ERROR_INVALID_PLAYER STORMERROR(106) +#define STORM_ERROR_NO_MESSAGES_WAITING STORMERROR(107) +#define STORM_ERROR_NOT_ARCHIVE STORMERROR(108) +#define STORM_ERROR_NOT_ENOUGH_ARGUMENTS STORMERROR(109) +#define STORM_ERROR_NOT_IMPLEMENTED STORMERROR(110) +#define STORM_ERROR_NOT_IN_ARCHIVE STORMERROR(111) +#define STORM_ERROR_NOT_IN_GAME STORMERROR(112) +#define STORM_ERROR_NOT_INITIALIZED STORMERROR(113) +#define STORM_ERROR_NOT_PLAYING STORMERROR(114) +#define STORM_ERROR_NOT_REGISTERED STORMERROR(115) +#define STORM_ERROR_REQUIRES_CODEC STORMERROR(116) +#define STORM_ERROR_REQUIRES_DDRAW STORMERROR(117) +#define STORM_ERROR_REQUIRES_DSOUND STORMERROR(118) +#define STORM_ERROR_REQUIRES_UPGRADE STORMERROR(119) +#define STORM_ERROR_STILL_ACTIVE STORMERROR(120) +#define STORM_ERROR_VERSION_MISMATCH STORMERROR(121) + +/**************************************************************************** +* +* BitBlt functions +* +***/ + +extern "C" BOOL APIENTRY SBltDestroy (); +extern "C" BOOL APIENTRY SBltGetSCode (DWORD rop3, + LPSTR buffer, + DWORD buffersize, + BOOL optimize = 1); +extern "C" BOOL APIENTRY SBltROP3 (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Clipped (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Tiled (LPBYTE dest, + LPRECT destrect, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3); + +/**************************************************************************** +* +* Bitmap functions +* +***/ + +#define SBMP_IMAGETYPE_BMP 1 +#define SBMP_IMAGETYPE_PCX 2 + +extern "C" BOOL APIENTRY SBmpDecodeImage (DWORD imagetype, + LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpDestroy (); +extern "C" BOOL APIENTRY SBmpLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpSaveImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height, + int bitdepth); + +/**************************************************************************** +* +* Command line parsing functions +* +***/ + +#define SCMD_ARG_FLAGGED (0 << 24) +#define SCMD_ARG_OPTIONAL (1 << 24) +#define SCMD_ARG_REQUIRED (2 << 24) +#define SCMD_ARG_MASK (SCMD_ARG_FLAGGED | SCMD_ARG_OPTIONAL | SCMD_ARG_REQUIRED) + +#define SCMD_BOOL_SET 0 +#define SCMD_BOOL_CLEAR 1 +#define SCMD_BOOL_MASK (SCMD_BOOL_CLEAR | SCMD_BOOL_SET) + +#define SCMD_CASESENSITIVE (0x01 << 8) + +#define SCMD_NUM_UNSIGNED 0 +#define SCMD_NUM_SIGNED 1 +#define SCMD_NUM_MASK (SCMD_NUM_UNSIGNED | SCMD_NUM_SIGNED) + +#define SCMD_TYPE_BOOL (0 << 16) +#define SCMD_TYPE_NUMERIC (1 << 16) +#define SCMD_TYPE_STRING (2 << 16) +#define SCMD_TYPE_MASK (SCMD_TYPE_BOOL | SCMD_TYPE_NUMERIC | SCMD_TYPE_STRING) + +#define SCMD_ERROR_BAD_ARGUMENT STORM_ERROR_BAD_ARGUMENT +#define SCMD_ERROR_NOT_ENOUGH_ARGUMENTS STORM_ERROR_NOT_ENOUGH_ARGUMENTS +#define SCMD_ERROR_OPEN_FAILED ERROR_OPEN_FAILED + +typedef struct _CMDERROR { + DWORD errorcode; + LPCTSTR itemstr; + LPCTSTR errorstr; +} CMDERROR, *CMDERRORPTR; + +typedef struct _CMDPARAMS { + DWORD flags; + DWORD id; + LPCTSTR name; + LPVOID variable; + DWORD setvalue; + DWORD setmask; + union { + BOOL boolvalue; + LONG signedvalue; + DWORD unsignedvalue; + LPCTSTR stringvalue; + }; +} CMDPARAMS, *CMDPARAMSPTR; + +typedef BOOL (CALLBACK *SCMDCALLBACK)(CMDPARAMSPTR,LPCTSTR); +typedef void (CALLBACK *SCMDERRORCALLBACK)(CMDERRORPTR); +typedef BOOL (CALLBACK *SCMDEXTRACALLBACK)(LPCTSTR); + +typedef struct _ARGLIST { + DWORD flags; + DWORD id; + LPCTSTR name; + SCMDCALLBACK callback; +} ARGLIST, *ARGLISTPTR; + +extern "C" BOOL APIENTRY SCmdDestroy (); +extern "C" BOOL APIENTRY SCmdGetBool (DWORD id); +extern "C" DWORD APIENTRY SCmdGetNum (DWORD id); +extern "C" BOOL APIENTRY SCmdGetString (DWORD id, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SCmdProcess (LPCTSTR cmdline, + BOOL skipprogname, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback); +extern "C" BOOL APIENTRY SCmdRegisterArgList (const ARGLIST *listptr, + DWORD numargs); +extern "C" BOOL APIENTRY SCmdRegisterArgument (DWORD flags, + DWORD id, + LPCTSTR name, + LPVOID variableptr = NULL, + DWORD variablebytes = 0, + DWORD setvalue = TRUE, + DWORD setmask = 0xFFFFFFFF, + SCMDCALLBACK callback = NULL); + +#define SCmdProcessCommandLine(ext,err) SCmdProcess(GetCommandLine(),TRUE,(ext),(err)) + +#define ARGBOOL(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),TRUE,0xFFFFFFFF,callback) +#define ARGFLAG(flags,name,var,valuecallback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),value,value,callback) +#define ARGNUMBER(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_NUMERIC | (flags),0xFFFFFFFF,name,var,sizeof(var),0,0,callback) +#define ARGSTRING(flags,name,buffer,chars,callback) SCmdRegisterArgument(SCMD_TYPE_STRING | (flags),0xFFFFFFFF,name,buffer,(chars)*sizeof(TCHAR),0,0,callback) + +/**************************************************************************** +* +* S-Code functions +* +***/ + +#define SCODE_CF_AUTOALIGNDWORD 0x00040000 +#define SCODE_CF_USESALTADJUSTS 0x04000000 + +typedef struct _HSCODESTREAM { int unused; } *HSCODESTREAM; + +typedef struct _SCODEEXECUTEDATA { + DWORD size; + DWORD flags; + int xiterations; + int yiterations; + int adjustdest; + int adjustsource; + LPVOID dest; + LPVOID source; + LPVOID table; + DWORD a; + DWORD b; + DWORD c; + int adjustdestalt; + int adjustsourcealt; + DWORD reserved[2]; +} SCODEEXECUTEDATA, *SCODEEXECUTEDATAPTR; + +extern "C" BOOL APIENTRY SCodeCompile (LPCSTR prologstring, + LPCSTR loopstring, + LPCSTR *firsterror, + DWORD maxiterations, + DWORD flags, + HSCODESTREAM *handle); +extern "C" BOOL APIENTRY SCodeDelete (HSCODESTREAM handle); +extern "C" BOOL APIENTRY SCodeDestroy (); +extern "C" BOOL APIENTRY SCodeExecute (HSCODESTREAM handle, + SCODEEXECUTEDATAPTR executedata); +extern "C" BOOL APIENTRY SCodeGetJumpTable (HSCODESTREAM handle, + LPBYTE **jumptableptr, + LPDWORD *prologpatchlocation, + LPDWORD *looppatchlocation, + LPDWORD *epilogpatchlocation); +extern "C" BOOL APIENTRY SCodeGetPseudocode (LPCSTR scodestring, + LPSTR buffer, + DWORD buffersize); + +/**************************************************************************** +* +* Dialog box functions +* +***/ + +#define SDLG_ADJUST_NONE 0 +#define SDLG_ADJUST_VERTICAL 1 +#define SDLG_ADJUST_CONTROLPOS 2 + +#define SDLG_DBF_TILE 0x00000001 +#define SDLG_DBF_VCENTER 0x00000002 + +#define SDLG_STYLE_ANY 0xFFFFFFFF +#define SDLG_STYLE_ANYPUSHBUTTON 0x00010001 + +#define SDLG_USAGE_BACKGROUND 0x00000001 +#define SDLG_USAGE_NORMAL_UNFOCUSED 0x00000010 +#define SDLG_USAGE_NORMAL_FOCUSED 0x00000020 +#define SDLG_USAGE_NORMAL (SDLG_USAGE_NORMAL_UNFOCUSED | SDLG_USAGE_NORMAL_FOCUSED) +#define SDLG_USAGE_SELECTED_UNFOCUSED 0x00000040 +#define SDLG_USAGE_SELECTED_FOCUSED 0x00000080 +#define SDLG_USAGE_SELECTED (SDLG_USAGE_SELECTED_UNFOCUSED | SDLG_USAGE_SELECTED_FOCUSED) +#define SDLG_USAGE_NORMAL_GRAYED 0x00000100 +#define SDLG_USAGE_SELECTED_GRAYED 0x00000400 +#define SDLG_USAGE_GRAYED (SDLG_USAGE_NORMAL_GRAYED | SDLG_USAGE_SELECTED_GRAYED) +#define SDLG_USAGE_CURSORMASK 0x00001000 +#define SDLG_USAGE_CURSORIMAGE 0x00002000 + +extern "C" HDC APIENTRY SDlgBeginPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgBltToWindow (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgCheckTimers (); +extern "C" HWND APIENTRY SDlgCreateDialogIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" HWND APIENTRY SDlgCreateDialogParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDefDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +extern "C" BOOL APIENTRY SDlgDestroy (); +extern "C" int APIENTRY SDlgDialogBoxIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" int APIENTRY SDlgDialogBoxParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDrawBitmap (HWND window, + DWORD usage, + HRGN region, + int offsetx = 0, + int offsety = 0, + LPRECT boundingoffset = NULL, + DWORD flags = 0); +extern "C" BOOL APIENTRY SDlgEndDialog (HWND window, + int result); +extern "C" BOOL APIENTRY SDlgEndPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgKillTimer (HWND window, + UINT event); +extern "C" BOOL APIENTRY SDlgSetBaseFont (int pointsize, + int weight, + DWORD flags, + DWORD family, + LPCTSTR face); +extern "C" BOOL APIENTRY SDlgSetBitmap (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetControlBitmaps (HWND parentwindow, + LPINT controllist, + LPDWORD usagelist, + LPBYTE bitmapbits, + LPSIZE bitmapsize, + DWORD adjusttype, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetCursor (HWND window, + HCURSOR cursor, + DWORD id, + HCURSOR *oldcursor); +extern "C" BOOL APIENTRY SDlgSetSystemCursor (LPBYTE maskbitmap, + LPBYTE imagebitmap, + LPSIZE size, + DWORD id = 32512); +extern "C" BOOL APIENTRY SDlgSetTimer (HWND window, + UINT event, + UINT elapse, + TIMERPROC timerfunc); +extern "C" BOOL APIENTRY SDlgUpdateCursor (); + +#define SDlgCreateDialog(ins,tpl,wnd,prc) SDlgCreateDialogParam(ins,tpl,wnd,prc,0) +#define SDlgCreateDialogIndirect(ins,tpl,wnd,prc) SDlgCreateDialogIndirectParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBox(ins,tpl,wnd,prc) SDlgDialogBoxParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBoxIndirect(ins,tpl,wnd,prc) SDlgDialogBoxIndirectParam(ins,tpl,wnd,prc,0) + +/**************************************************************************** +* +* DirectDraw functions +* +***/ + +#define SDRAW_SERVICE_BASIC 1 +#define SDRAW_SERVICE_PAGEFLIP 2 +#define SDRAW_SERVICE_DOUBLEBUFFER 3 +#define SDRAW_SERVICE_MAX 3 + +#define SDRAW_SURFACE_FRONT 0 +#define SDRAW_SURFACE_BACK 1 +#define SDRAW_SURFACE_SYSTEM 2 +#define SDRAW_SURFACE_TEMPORARY 3 + +extern "C" BOOL APIENTRY SDrawAutoInitialize (HINSTANCE instance, + LPCTSTR classname, + LPCTSTR title, + WNDPROC wndproc = NULL, + int servicelevel = SDRAW_SERVICE_BASIC, + int width = 640, + int height = 480, + int bitdepth = 8); +extern "C" BOOL APIENTRY SDrawCaptureScreen (LPCTSTR filename = NULL); +extern "C" BOOL APIENTRY SDrawClearSurface (int surfacenumber); +extern "C" BOOL APIENTRY SDrawDestroy (); +extern "C" BOOL APIENTRY SDrawFlipPage (); +extern "C" HWND APIENTRY SDrawGetFrameWindow (HWND *window = NULL); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawGetObjects (LPDIRECTDRAW *directdraw, + LPDIRECTDRAWSURFACE *frontbuffer, + LPDIRECTDRAWSURFACE *backbuffer, + LPDIRECTDRAWSURFACE *systembuffer, + LPDIRECTDRAWSURFACE *temporarybuffer, + LPDIRECTDRAWPALETTE *palette, + HPALETTE *gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawGetScreenSize (int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SDrawGetServiceLevel (int *servicelevel = NULL); +extern "C" BOOL APIENTRY SDrawLockSurface (int surfacenumber, + LPCRECT rect, + LPBYTE *ptr, + int *pitch = NULL, + DWORD flags = 0); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawManualInitialize (HWND framewindow, + LPDIRECTDRAW directdraw, + LPDIRECTDRAWSURFACE frontbuffer, + LPDIRECTDRAWSURFACE backbuffer, + LPDIRECTDRAWSURFACE systembuffer, + LPDIRECTDRAWSURFACE temporarybuffer, + LPDIRECTDRAWPALETTE palette, + HPALETTE gdipalette); +#endif +extern "C" int APIENTRY SDrawMessageBox (LPCTSTR text, + LPCTSTR title, + UINT flags); +extern "C" BOOL APIENTRY SDrawPostClose (); +extern "C" BOOL APIENTRY SDrawRealizePalette (); +extern "C" BOOL APIENTRY SDrawSelectGdiSurface (BOOL select, BOOL copy); +extern "C" BOOL APIENTRY SDrawUnlockSurface (int surfacenumber, + LPBYTE ptr, + DWORD numrects = 0, + LPCRECT rectarray = NULL); +extern "C" BOOL APIENTRY SDrawUpdatePalette (DWORD firstentry, + DWORD numentries, + LPPALETTEENTRY entries, + BOOL reservedentries = 0); +extern "C" BOOL APIENTRY SDrawUpdateScreen (LPCRECT rect); + +/**************************************************************************** +* +* Error handling functions +* +***/ + +#define SERR_LINECODE_FUNCTION -1 +#define SERR_LINECODE_OBJECT -2 + +extern "C" BOOL APIENTRY SErrDisplayError (DWORD errorcode, + LPCTSTR filename, + int linenumber, + LPCTSTR description, + BOOL recoverable, + UINT exitcode = 1); +extern "C" BOOL APIENTRY SErrGetErrorStr (DWORD errorcode, + LPTSTR buffer, + DWORD bufferchars); +extern "C" DWORD APIENTRY SErrGetLastError (); +extern "C" BOOL APIENTRY SErrRegisterMessageSource (WORD facility, + HMODULE module, + LPVOID reserved = NULL); +extern "C" void APIENTRY SErrSetLastError (DWORD errorcode); + +#define SErrGetLastErrorStr(buf,len) SErrGetErrorStr(SErrGetLastError(),buf,len) +#define FATALRESULT(str) SErrDisplayError(SErrGetLastError(),str,SERR_LINECODE_FUNCTION,NULL,FALSE) + +#ifdef _DEBUG +#define ASSERT(a) if (!(a)) \ + SErrDisplayError(STORM_ERROR_ASSERTION, \ + __FILE__, \ + __LINE__, \ + #a, \ + FALSE) +#define VALIDATEBEGIN do { +#define VALIDATE(a) ASSERT(a) +#define VALIDATEEND } while (0) +#define VALIDATEENDVOID } while (0) +#else +#define ASSERT(a) +#define VALIDATEBEGIN do { \ + int intrn_valresult = -1 +#define VALIDATE(a) intrn_valresult &= (a) ? -1 : 0 +#define VALIDATEEND if (!intrn_valresult) { \ + SErrSetLastError(ERROR_INVALID_PARAMETER); \ + return 0; \ + } \ + } while (0) +#define VALIDATEENDVOID if (!intrn_valresult) { \ + SErrSetLastError(ERROR_INVALID_PARAMETER); \ + return; \ + } \ + } while (0) +#endif + +/**************************************************************************** +* +* Event dispatching functions +* +***/ + +typedef void (CALLBACK *SEVTHANDLER)(LPVOID); + +extern "C" BOOL APIENTRY SEvtDestroy (); +extern "C" BOOL APIENTRY SEvtDispatch (DWORD type, + DWORD subtype, + DWORD id, + LPVOID data); +extern "C" BOOL APIENTRY SEvtRegisterHandler (DWORD type, + DWORD subtype, + DWORD id, + DWORD flags, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterHandler (DWORD type, + DWORD subtype, + DWORD id, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterType (DWORD type, + DWORD subtype); + +/**************************************************************************** +* +* File I/O functions +* +***/ + +#define SFILE_AUTH_UNABLETOAUTHENTICATE 0 +#define SFILE_AUTH_NOSIGNATURE 1 +#define SFILE_AUTH_BADSIGNATURE 2 +#define SFILE_AUTH_UNKNOWNSIGNATURE 3 +#define SFILE_AUTH_FIRSTAUTHENTIC 5 +#define SFILE_AUTH_AUTHENTICBLIZZARD 5 + +#define SFILE_DDA_LOOP 0x00040000 + +#define SFILE_ERROR_BAD_FORMAT ERROR_BAD_FORMAT +#define SFILE_ERROR_BAD_PATHNAME ERROR_BAD_PATHNAME +#define SFILE_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED +#define SFILE_ERROR_FILE_INVALID ERROR_FILE_INVALID +#define SFILE_ERROR_FILE_NOT_FOUND ERROR_FILE_NOT_FOUND +#define SFILE_ERROR_HANDLE_EOF ERROR_HANDLE_EOF +#define SFILE_ERROR_INVALID_DATA ERROR_INVALID_DATA +#define SFILE_ERROR_INVALID_DRIVE ERROR_INVALID_DRIVE +#define SFILE_ERROR_INVALID_HANDLE ERROR_INVALID_HANDLE +#define SFILE_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SFILE_ERROR_NOT_ARCHIVE STORM_ERROR_NOT_ARCHIVE +#define SFILE_ERROR_NOT_AUTHENTICATED ERROR_NOT_AUTHENTICATED +#define SFILE_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SFILE_ERROR_NOT_IN_ARCHIVE STORM_ERROR_NOT_IN_ARCHIVE +#define SFILE_ERROR_NOT_INITIALIZED STORM_ERROR_NOT_INITIALIZED +#define SFILE_ERROR_NOT_PLAYING STORM_ERROR_NOT_PLAYING + +#define SFILE_FIND_FILES 0x00000001 +#define SFILE_FIND_DIRECTORIES 0x00000002 + +typedef struct _HSARCHIVE { int unused; } *HSARCHIVE; +typedef struct _HSFILE { int unused; } *HSFILE; +typedef struct _HSFINDFILE { int unused; } *HSFINDFILE; + +extern "C" BOOL APIENTRY SFileAuthenticateArchive (HSARCHIVE archive, + DWORD *extendedresult); +extern "C" BOOL APIENTRY SFileCloseArchive (HSARCHIVE handle); +extern "C" BOOL APIENTRY SFileCloseFile (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaBegin (HSFILE handle, + DWORD buffersize, + DWORD flags); +extern "C" BOOL APIENTRY SFileDdaBeginEx (HSFILE handle, + DWORD buffersize, + DWORD flags, + DWORD offset, + LONG volume, + LONG pan, + LPVOID reserved); +extern "C" BOOL APIENTRY SFileDdaDestroy (); +extern "C" BOOL APIENTRY SFileDdaEnd (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaGetPos (HSFILE handle, + DWORD *position, + DWORD *maxposition); +extern "C" BOOL APIENTRY SFileDdaGetVolume (HSFILE handle, + LONG *volume, + LONG *pan); +#ifdef __DSOUND_INCLUDED__ +extern "C" BOOL APIENTRY SFileDdaInitialize (LPDIRECTSOUND directsound); +#endif +extern "C" BOOL APIENTRY SFileDdaSetVolume (HSFILE handle, + LONG volume, + LONG pan); +extern "C" BOOL APIENTRY SFileDestroy (); +extern "C" BOOL APIENTRY SFileEnableDirectAccess (BOOL enable); +extern "C" BOOL APIENTRY SFileGetFileArchive (HSFILE file, + HSARCHIVE *archive); +extern "C" DWORD APIENTRY SFileGetFileSize (HSFILE handle, + LPDWORD filesizehigh = NULL); +extern "C" BOOL APIENTRY SFileOpenArchive (LPCTSTR archivename, + int priority, + BOOL cdonly, + HSARCHIVE *handle); +extern "C" BOOL APIENTRY SFileOpenFile (LPCTSTR filename, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileEx (HSARCHIVE archivehandle, + LPCTSTR filename, + DWORD flags, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileWin32 (LPCTSTR filename, + HANDLE *handle); +extern "C" BOOL APIENTRY SFileReadFile (HSFILE handle, + LPVOID buffer, + DWORD bytestoread, + LPDWORD bytesread = NULL, + LPVOID reserved = NULL); +extern "C" BOOL APIENTRY SFileSetBasePath (LPCTSTR path); +extern "C" DWORD APIENTRY SFileSetFilePointer (HSFILE handle, + LONG distancetomove, + PLONG distancetomovehigh, + DWORD movemethod); +extern "C" BOOL APIENTRY SFileSetLocale (LCID lcid); + +/**************************************************************************** +* +* GDI functions +* +***/ + +#define ETO_TEXT_TRANSPARENT 0 +#define ETO_TEXT_COLOR 1 +#define ETO_TEXT_BLACK 2 +#define ETO_TEXT_WHITE 3 +#define ETO_BKG_TRANSPARENT 0 +#define ETO_BKG_COLOR 1 +#define ETO_BKG_BLACK 2 +#define ETO_BKG_WHITE 3 + +typedef struct _HSGDIOBJ { int unused; } *HSGDIOBJ; +typedef struct _HSGDIFONT : public _HSGDIOBJ { int unused; } *HSGDIFONT; + +extern "C" BOOL APIENTRY SGdiBitBlt (LPBYTE videobuffer, + int destx, + int desty, + LPBYTE sourcedata, + LPRECT sourcerect, + int sourcecx, + int sourcecy, + COLORREF color = 0, + DWORD rop = SRCCOPY); +extern "C" BOOL APIENTRY SGdiCreateFont (LPBYTE bits, + int width, + int height, + int bitdepth, + int filecharwidth, + int filecharheight, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiDeleteObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiDestroy (); +extern "C" BOOL APIENTRY SGdiExtTextOut (LPBYTE videobuffer, + int x, + int y, + LPRECT rect, + COLORREF color, + int textcoloruse, + int bkgcoloruse, + LPCTSTR string, + int chars = -1); +extern "C" BOOL APIENTRY SGdiImportFont (HFONT windowsfont, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiLoadFont (LPCTSTR filename, + int filecharwidth, + int filecharheight, + int basecharwidth, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiRectangle (LPBYTE videobuffer, + int left, + int top, + int right, + int bottom, + COLORREF color); +extern "C" BOOL APIENTRY SGdiSelectObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiSetPitch (int pitch); +extern "C" BOOL APIENTRY SGdiTextOut (LPBYTE videobuffer, + int x, + int y, + COLORREF color, + LPCTSTR string, + int chars = -1); + +/**************************************************************************** +* +* Memory allocation functions +* +***/ + +#define SMEM_FLAG_ZEROMEMORY 0x00000008 + +extern "C" LPVOID APIENTRY SMemAlloc (DWORD bytes, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" BOOL APIENTRY SMemDestroy (); +extern "C" BOOL APIENTRY SMemFree (LPVOID ptr, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" void APIENTRY SMemInitialize (); + +#define ALLOC(bytes) SMemAlloc(bytes,__FILE__,__LINE__,0) +#define ALLOCZERO(bytes) SMemAlloc(bytes,__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) +#define FREE(ptr) SMemFree(ptr,__FILE__,__LINE__,0) +#define NEW(struct) (struct *)SMemAlloc(sizeof(struct),__FILE__,__LINE__,0) +#define NEWZERO(struct) (struct *)SMemAlloc(sizeof(struct),__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) + +/**************************************************************************** +* +* Message functions +* +***/ + +typedef struct _PARAMS { + HWND window; + UINT message; + WPARAM wparam; + LPARAM lparam; + UINT notifycode; + LPVOID extra; + BOOL useresult; + LRESULT result; +} PARAMS, *PARAMSPTR, *LPPARAMS; + +typedef BOOL (CALLBACK *SMSGIDLEPROC)(DWORD); +typedef void (CALLBACK *SMSGHANDLER)(LPPARAMS); + +extern "C" BOOL APIENTRY SMsgDestroy (); +extern "C" BOOL APIENTRY SMsgDispatchMessage (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL *useresult, + LRESULT *result); +extern "C" BOOL APIENTRY SMsgDoMessageLoop (SMSGIDLEPROC idleproc = NULL, + BOOL cleanuponquit = 1); +extern "C" BOOL APIENTRY SMsgRegisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); + +/**************************************************************************** +* +* Networking functions +* +***/ + +#define SNET_ART_BACKGROUND 0 +#define SNET_ART_BUTTONTEXTURE 1 +#define SNET_ART_JOINBACKGROUND 2 +#define SNET_ART_HELPBACKGROUND 3 +#define SNET_ART_POPUPBACKGROUND 4 +#define SNET_ART_BUTTON_XSML 5 +#define SNET_ART_BUTTON_SML 6 +#define SNET_ART_BUTTON_MED 7 +#define SNET_ART_BUTTON_LRG 8 +#define SNET_ART_APP_LOGO_SML 9 +#define SNET_ART_PROGRESS_BACKGROUND 10 +#define SNET_ART_PROGRESS_FILLER 11 +#define SNET_ART_POPUPBACKGROUND_SML 12 +#define SNET_ART_SCROLLBARARROWS 13 +#define SNET_ART_SCROLLTHUMB 14 +#define SNET_ART_SCROLLBAR 15 + +#define SNET_AUTHTYPE_CHANNEL 1 +#define SNET_AUTHTYPE_GAME 2 + +#define SNET_BROADCASTNONLOCALPLAYERID 0xFFFFFFFE +#define SNET_BROADCASTPLAYERID 0xFFFFFFFF +#define SNET_INVALIDPLAYERID 0xFFFFFFFF + +#define SNET_CAPS_PAGELOCKEDBUFFERS 0x00000001 +#define SNET_CAPS_BASICINTERFACE 0x00000002 + +#define SNET_CF_ALLOWPRIVATEGAMES 0x00000001 + +#define SNET_DATA_SYSCOLORS 1 +#define SNET_DATA_CURSORLINK 2 +#define SNET_DATA_CURSORARROW 3 +#define SNET_DATA_CURSORIBEAM 4 + +#define SNET_DDF_INCLUDENAME 0x00000001 +#define SNET_DDF_MULTILINE 0x00000002 + +#define SNET_DDPF_BLIZZARD 0x00000001 +#define SNET_DDPF_MODERATOR 0x00000002 +#define SNET_DDPF_SPEAKER 0x00000004 +#define SNET_DDPF_SYSOP 0x00000008 +#define SNET_DDPF_SQUELCHED 0x00000020 + +#define SNET_DRAWTYPE_GAME 1 +#define SNET_DRAWTYPE_PLAYER 2 + +#define SNET_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS +#define SNET_ERROR_BAD_PROVIDER ERROR_BAD_PROVIDER +#define SNET_ERROR_CANCELLED ERROR_CANCELLED +#define SNET_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SNET_ERROR_INVALID_PLAYER STORM_ERROR_INVALID_PLAYER +#define SNET_ERROR_GAME_ALREADY_STARTED STORM_ERROR_GAME_ALREADY_STARTED +#define SNET_ERROR_GAME_FULL STORM_ERROR_GAME_FULL +#define SNET_ERROR_GAME_NOT_FOUND STORM_ERROR_GAME_NOT_FOUND +#define SNET_ERROR_GAME_TERMINATED STORM_ERROR_GAME_TERMINATED +#define SNET_ERROR_HOST_UNREACHABLE ERROR_HOST_UNREACHABLE +#define SNET_ERROR_MAX_THRDS_REACHED ERROR_MAX_THRDS_REACHED +#define SNET_ERROR_NETWORK_BUSY ERROR_NETWORK_BUSY +#define SNET_ERROR_NO_MESSAGES_WAITING STORM_ERROR_NO_MESSAGES_WAITING +#define SNET_ERROR_NO_NETWORK ERROR_NO_NETWORK +#define SNET_ERROR_NOT_CONNECTED ERROR_NOT_CONNECTED +#define SNET_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SNET_ERROR_NOT_IMPLEMENTED STORM_ERROR_NOT_IMPLEMENTED +#define SNET_ERROR_NOT_IN_GAME STORM_ERROR_NOT_IN_GAME +#define SNET_ERROR_NOT_OWNER ERROR_NOT_OWNER +#define SNET_ERROR_NOT_REGISTERED STORM_ERROR_NOT_REGISTERED +#define SNET_ERROR_REQUIRES_UPGRADE STORM_ERROR_REQUIRES_UPGRADE +#define SNET_ERROR_STILL_ACTIVE STORM_ERROR_STILL_ACTIVE +#define SNET_ERROR_TOO_MANY_NAMES ERROR_TOO_MANY_NAMES +#define SNET_ERROR_VERSION_MISMATCH STORM_ERROR_VERSION_MISMATCH + +#define SNET_EVENT_INITDATA 1 +#define SNET_EVENT_PLAYERJOIN 2 +#define SNET_EVENT_PLAYERLEAVE 3 +#define SNET_EVENT_SERVERMESSAGE 4 + +#define SNET_EXIT_AUTO_JOINING 0x00000001 +#define SNET_EXIT_AUTO_NEWGAME 0x00000002 +#define SNET_EXIT_AUTO_SHUTDOWN 0x00000003 +#define SNET_EXIT_PLAYERQUIT 0x40000001 +#define SNET_EXIT_PLAYERKILLED 0x40000002 +#define SNET_EXIT_PLAYERWON 0x40000004 +#define SNET_EXIT_GAMEOVER 0x40000005 +#define SNET_EXIT_NOTRESPONDING 0x40000006 + +#define SNET_GM_PRIVATE 0x00000001 +#define SNET_GM_FULL 0x00000002 +#define SNET_GM_ADVERTISED 0x00000004 + +#define SNET_INFO_GAMENAME 1 +#define SNET_INFO_GAMEPASSWORD 2 +#define SNET_INFO_GAMEDESCRIPTION 3 +#define SNET_INFO_GAMEMODE 4 +#define SNET_INFO_INITDATA 5 +#define SNET_INFO_MAXPLAYERS 6 + +#define SNET_LMT_EXPECTED 1 +#define SNET_LMT_CURRENT 2 +#define SNET_LMT_PEAK 4 + +#define SNET_PERFID_TURN 1 +#define SNET_PERFID_TURNSSENT 4 +#define SNET_PERFID_TURNSRECV 5 +#define SNET_PERFID_MSGSENT 6 +#define SNET_PERFID_MSGRECV 7 +#define SNET_PERFID_USERBYTESSENT 8 +#define SNET_PERFID_USERBYTESRECV 9 +#define SNET_PERFID_TOTALBYTESSENT 10 +#define SNET_PERFID_TOTALBYTESRECV 11 +#define SNET_PERFID_PKTSENTONWIRE 12 +#define SNET_PERFID_PKTRECVONWIRE 13 +#define SNET_PERFID_BYTESSENTONWIRE 14 +#define SNET_PERFID_BYTESRECVONWIRE 15 +#define SNET_PERFIDNUM 16 + +#define SNET_PERFTYPE_COUNTER 0x10410400 +#define SNET_PERFTYPE_RAWCOUNT 0x00010000 + +#define SNET_PSF_ACTIVE 0x00010000 +#define SNET_PSF_TURNAVAILABLE 0x00020000 +#define SNET_PSF_RESPONDING 0x00040000 + +#define SNET_SF_ALLOWCREATE 0x00000001 + +#define SNET_SND_CHANGEFOCUS 0 +#define SNET_SND_SELECTITEM 1 + +#define SNET_UPGRADE_FAILED -1 +#define SNET_UPGRADE_NOT_NEEDED 0 +#define SNET_UPGRADE_SUCCEEDED 1 +#define SNET_UPGRADING_TERMINATE 2 + +#define SNET_MAXNAMELENGTH 128 +#define SNET_MAXDESCLENGTH 128 + +typedef struct _SNETCAPS { + DWORD size; + DWORD flags; + DWORD maxmessagesize; + DWORD maxqueuesize; + DWORD maxplayers; + DWORD bytessec; + DWORD latencyms; + DWORD defaultturnssec; + DWORD defaultturnsintransit; +} SNETCAPS, *SNETCAPSPTR; + +typedef struct _SNETCREATEDATA { + DWORD size; + DWORD providerid; + DWORD maxplayers; + DWORD createflags; +} SNETCREATEDATA, *SNETCREATEDATAPTR; + +typedef struct _SNET_DATA_SYSCOLORTABLE { + DWORD syscolor; + COLORREF rgb; +} SNET_DATA_SYSCOLORTABLE, *SNET_DATA_SYSCOLORTABLEPTR; + +typedef struct _SNETEVENT { + DWORD eventid; + DWORD playerid; + LPVOID data; + DWORD databytes; +} SNETEVENT, *SNETEVENTPTR; + +struct _SNETPROGRAMDATA; +struct _SNETPLAYERDATA; +struct _SNETUIDATA; +struct _SNETVERSIONDATA; + +typedef BOOL (CALLBACK *SNETABORTPROC )(); +typedef BOOL (CALLBACK *SNETCATEGORYPROC )(BOOL,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *,DWORD *); +typedef BOOL (CALLBACK *SNETCHECKAUTHPROC )(DWORD,LPCSTR,LPCSTR,DWORD,LPCSTR,LPSTR,DWORD); +typedef BOOL (CALLBACK *SNETCREATEPROC )(SNETCREATEDATAPTR,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *); +typedef BOOL (CALLBACK *SNETDRAWDESCPROC )(DWORD,DWORD,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,LPDRAWITEMSTRUCT); +typedef BOOL (CALLBACK *SNETENUMDEVICESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMGAMESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMPROVIDERSPROC)(DWORD,LPCSTR,LPCSTR,SNETCAPSPTR); +typedef void (CALLBACK *SNETEVENTPROC )(SNETEVENTPTR); +typedef BOOL (CALLBACK *SNETGETARTPROC )(DWORD,DWORD,LPPALETTEENTRY,LPBYTE,DWORD,int *,int *,int *); +typedef BOOL (CALLBACK *SNETGETDATAPROC )(DWORD,DWORD,LPVOID,DWORD,DWORD *); +typedef int (CALLBACK *SNETMESSAGEBOXPROC )(HWND,LPCSTR,LPCSTR,UINT); +typedef BOOL (CALLBACK *SNETPLAYSOUNDPROC )(DWORD,DWORD,DWORD); +typedef BOOL (CALLBACK *SNETSELECTEDPROC )(DWORD,SNETCAPSPTR,_SNETUIDATA *,_SNETVERSIONDATA *); +typedef BOOL (CALLBACK *SNETSTATUSPROC )(LPCSTR,DWORD,DWORD,DWORD,SNETABORTPROC); + +typedef struct _SNETPLAYERDATA { + DWORD size; + LPCSTR playername; + LPCSTR playerdescription; +} SNETPLAYERDATA, *SNETPLAYERDATAPTR; + +typedef struct _SNETPROGRAMDATA { + DWORD size; + LPCSTR programname; + LPCSTR programdescription; + DWORD programid; + DWORD versionid; + DWORD reserved1; + DWORD maxplayers; + LPVOID initdata; + DWORD initdatabytes; + LPVOID reserved2; + DWORD optcategorybits; +} SNETPROGRAMDATA, *SNETPROGRAMDATAPTR; + +typedef struct _SNETUIDATA { + DWORD size; + DWORD uiflags; + HWND parentwindow; + SNETGETARTPROC artcallback; + SNETCHECKAUTHPROC authcallback; + SNETCREATEPROC createcallback; + SNETDRAWDESCPROC drawdesccallback; + SNETSELECTEDPROC selectedcallback; + SNETMESSAGEBOXPROC messageboxcallback; + SNETPLAYSOUNDPROC soundcallback; + SNETSTATUSPROC statuscallback; + SNETGETDATAPROC getdatacallback; + SNETCATEGORYPROC categorycallback; +} SNETUIDATA, *SNETUIDATAPTR; + +typedef struct _SNETVERSIONDATA { + DWORD size; + LPCSTR versionstring; + LPCSTR executablefile; + LPCSTR originalarchivefile; + LPCSTR patcharchivefile; +} SNETVERSIONDATA, *SNETVERSIONDATAPTR; + +extern "C" BOOL APIENTRY SNetCreateGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamecategorybits, + LPVOID initdata, + DWORD initdatabytes, + DWORD maxplayers, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetDestroy (); +extern "C" BOOL APIENTRY SNetDropPlayer (DWORD playerid, DWORD exitcode); +extern "C" BOOL APIENTRY SNetEnumDevices (SNETENUMDEVICESPROC callback); +extern "C" BOOL APIENTRY SNetEnumGames (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumProviders (SNETCAPSPTR mincaps, + SNETENUMPROVIDERSPROC callback); +extern "C" BOOL APIENTRY SNetGetGameInfo (DWORD index, + LPVOID buffer, + DWORD buffersize, + DWORD *byteswritten); +extern "C" BOOL APIENTRY SNetGetNetworkLatency (DWORD measurementtype, + DWORD *result); +extern "C" BOOL APIENTRY SNetGetNumPlayers (DWORD *firstplayerid, + DWORD *lastplayerid, + DWORD *activeplayers); +extern "C" BOOL APIENTRY SNetGetOwnerTurnsWaiting (DWORD *turns); +extern "C" BOOL APIENTRY SNetGetPerformanceData (DWORD counterid, + DWORD *countervalue, + DWORD *countertype, + LONG *counterscale, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +extern "C" BOOL APIENTRY SNetGetPlayerCaps (DWORD playerid, + SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetPlayerName (DWORD playerid, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SNetGetProviderCaps (SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetTurnsInTransit (DWORD *turns); +extern "C" BOOL APIENTRY SNetInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetInitializeProvider (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetJoinGame (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetLeaveGame (DWORD exitcode); +extern "C" BOOL APIENTRY SNetPerformUpgrade (DWORD *upgradestatus); +extern "C" BOOL APIENTRY SNetReceiveMessage (DWORD *senderplayerid, + LPVOID *data, + DWORD *databytes); +extern "C" BOOL APIENTRY SNetReceiveTurns (DWORD firstplayerid, + DWORD arraysize, + LPVOID *arraydata, + LPDWORD arraydatabytes, + LPDWORD arrayplayerstatus); +extern "C" BOOL APIENTRY SNetRegisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); +extern "C" BOOL APIENTRY SNetResetLatencyMeasurements (); +extern "C" BOOL APIENTRY SNetSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY SNetSendMessage (DWORD targetplayerid, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSendTurn (LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSetBasePlayer (DWORD playerid); +extern "C" BOOL APIENTRY SNetSetGameMode (DWORD modeflags); +extern "C" BOOL APIENTRY SNetUnregisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); + +/**************************************************************************** +* +* Networking service provider interface +* +***/ + +#define SNETSPI_MAXSTRINGLENGTH 128 + +typedef struct _SNETADDR { + BYTE address[16]; +} SNETADDR, *SNETADDRPTR; + +typedef struct _SNETSPI_DEVICELIST { + DWORD deviceid; + SNETCAPS devicecaps; + char devicename[SNETSPI_MAXSTRINGLENGTH]; + char devicedescription[SNETSPI_MAXSTRINGLENGTH]; + DWORD reserved; + _SNETSPI_DEVICELIST *next; +} SNETSPI_DEVICELIST, *SNETSPI_DEVICELISTPTR; + +typedef struct _SNETSPI_GAMELIST { + DWORD gameid; + DWORD gamemode; + DWORD creationtime; + SNETADDR owner; + DWORD ownerlatency; + DWORD ownerlasttime; + DWORD gamecategorybits; + char gamename[SNETSPI_MAXSTRINGLENGTH]; + char gamedescription[SNETSPI_MAXSTRINGLENGTH]; + _SNETSPI_GAMELIST *next; +} SNETSPI_GAMELIST, *SNETSPI_GAMELISTPTR; + +typedef struct _SNETSPI { + DWORD size; + BOOL (CALLBACK *CompareNetAddresses)(SNETADDRPTR,SNETADDRPTR,DWORD *); + BOOL (CALLBACK *Destroy)(); + BOOL (CALLBACK *Free)(SNETADDRPTR,LPVOID,DWORD); + BOOL (CALLBACK *FreeExternalMessage)(LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *GetGameInfo)(DWORD,LPCSTR,LPCSTR,SNETSPI_GAMELIST *); + BOOL (CALLBACK *GetPerformanceData)(DWORD,DWORD *,LARGE_INTEGER *,LARGE_INTEGER *); + BOOL (CALLBACK *Initialize)(SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,HANDLE); + BOOL (CALLBACK *InitializeDevice)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR); + BOOL (CALLBACK *LockDeviceList)(SNETSPI_DEVICELISTPTR *); + BOOL (CALLBACK *LockGameList)(DWORD,DWORD,SNETSPI_GAMELISTPTR *); + BOOL (CALLBACK *Receive)(SNETADDRPTR *,LPVOID *,DWORD *); + BOOL (CALLBACK *ReceiveExternalMessage)(LPCSTR *,LPCSTR *,LPCSTR *); + BOOL (CALLBACK *SelectGame)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,DWORD *); + BOOL (CALLBACK *Send)(DWORD,SNETADDRPTR *,LPVOID,DWORD); + BOOL (CALLBACK *SendExternalMessage)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *StartAdvertisingGame)(LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,DWORD); + BOOL (CALLBACK *StopAdvertisingGame)(); + BOOL (CALLBACK *UnlockDeviceList)(SNETSPI_DEVICELISTPTR); + BOOL (CALLBACK *UnlockGameList)(SNETSPI_GAMELISTPTR,DWORD *); +} SNETSPI, *SNETSPIPTR; + +typedef BOOL (APIENTRY *SNETSPIBIND )(DWORD,SNETSPIPTR *); +typedef BOOL (APIENTRY *SNETSPIQUERY)(DWORD,DWORD *,LPCSTR *,LPCSTR *,SNETCAPSPTR *); + +/**************************************************************************** +* +* Registry functions +* +***/ + +#define SREG_FLAG_USERSPECIFIC 0x00000001 +#define SREG_FLAG_BATTLENET 0x00000002 +#define SREG_FLAG_FLUSHTODISK 0x00000008 +#define SREG_FLAG_MULTISZ 0x00000080 + +extern "C" BOOL APIENTRY SRegLoadData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID buffer, + DWORD buffersize, + DWORD *bytesread); +extern "C" BOOL APIENTRY SRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SRegLoadValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *value); +extern "C" BOOL APIENTRY SRegSaveData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SRegSaveString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPCTSTR string); +extern "C" BOOL APIENTRY SRegSaveValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD value); + +/**************************************************************************** +* +* Run-time library functions +* +***/ + +#define TRY goto trylabel; trylabel: +#define LEAVE goto finallylabel +#define FINALLY goto finallylabel; finallylabel: + +/**************************************************************************** +* +* Transparency functions +* +***/ + +typedef struct _HSTRANS { int unused; } *HSTRANS; +typedef HSTRANS HTRANS; + +extern "C" BOOL APIENTRY STransBlt (LPBYTE dest, + int destx, + int desty, + int destpitch, + HSTRANS transparency); +extern "C" BOOL APIENTRY STransBltUsingMask (LPBYTE dest, + LPBYTE source, + int destpitch, + int sourcepitch, + HSTRANS mask); +extern "C" BOOL APIENTRY STransCreate (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransDelete (HSTRANS handle); +extern "C" BOOL APIENTRY STransDestroy (); +extern "C" BOOL APIENTRY STransDuplicate (HSTRANS source, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIntersectDirtyArray (HSTRANS sourcemask, + LPBYTE dirtyarray, + BYTE dirtyarraymask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransInvertMask (HSTRANS sourcemask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIsPixelInMask (HSTRANS mask, + int offsetx, + int offsety); +extern "C" BOOL APIENTRY STransLoad (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransSetDirtyArrayInfo (int screencx, + int screency, + int cellcx, + int cellcy); +extern "C" BOOL APIENTRY STransUpdateDirtyArray (LPBYTE dirtyarray, + BYTE dirtyvalue, + int destx, + int desty, + HSTRANS transparency, + BOOL tracecontour); + +/**************************************************************************** +* +* Video functions +* +***/ + +#define SVID_FLAG_DOUBLESCANS 0x00000001 +#define SVID_FLAG_INTERPOLATE 0x00000002 +#define SVID_FLAG_AUTOQUALITY 0x00000008 +#define SVID_FLAG_1XSIZE 0x00000100 +#define SVID_FLAG_2XSIZE 0x00000200 +#define SVID_FLAG_AUTOSIZE 0x00000800 +#define SVID_FLAG_FILEHANDLE 0x00010000 +#define SVID_FLAG_PRELOAD 0x00020000 +#define SVID_FLAG_LOOP 0x00040000 +#define SVID_FLAG_FULLSCREEN 0x00080000 +#define SVID_FLAG_USECURRENTPALETTE 0x00100000 +#define SVID_FLAG_CLEARSCREEN 0x00200000 +#define SVID_FLAG_NOSKIP 0x00400000 +#define SVID_FLAG_TOSCREEN 0x10000000 +#define SVID_FLAG_TOBUFFER 0x20000000 + +#define SVID_CUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_2XSIZE) +#define SVID_AUTOCUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_AUTOSIZE | SVID_FLAG_AUTOQUALITY) + +#define SVID_QUALITY_LOW_SKIPSCANS SVID_FLAG_2XSIZE +#define SVID_QUALITY_LOW (SVID_FLAG_2XSIZE | SVID_FLAG_DOUBLESCANS) +#define SVID_QUALITY_HIGH_SKIPSCANS (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE) +#define SVID_QUALITY_HIGH (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE | SVID_FLAG_DOUBLESCANS) + +typedef struct _HSVIDEO { int unused; } *HSVIDEO; + +typedef struct _SVIDPALETTEUSE { + DWORD size; + DWORD firstentry; + DWORD numentries; +} SVIDPALETTEUSE, *SVIDPALETTEUSEPTR; + +extern "C" BOOL APIENTRY SVidDestroy (); +extern "C" BOOL APIENTRY SVidGetPerformanceData (HSVIDEO video, + BOOL averageframems, + DWORD *framems, + BOOL averagepalettems, + DWORD *palettems); +extern "C" BOOL APIENTRY SVidGetSize (HSVIDEO video, + int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SVidInitialize (LPVOID directsound); +extern "C" BOOL APIENTRY SVidPlayBegin (LPCTSTR filename, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayBeginFromMemory (LPVOID sourceptr, + DWORD sourcebytes, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayContinue (); +extern "C" BOOL APIENTRY SVidPlayContinueSingle (HSVIDEO video, + BOOL forceupdate, + BOOL *updated); +extern "C" BOOL APIENTRY SVidPlayEnd (HSVIDEO video); + +/**************************************************************************** +* +* Storm global functions +* +***/ + +extern "C" BOOL APIENTRY StormDestroy (); + +/**************************************************************************** +* +* C++ Utility Classes and Templates +* +***/ + +#ifndef __cplusplus +extern "C++" +#endif + +/**************************************************************************** +* +* CCRITSECT -- Critical section class +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void inline Enter () { EnterCriticalSection(&m_critsect); } + void inline Leave () { LeaveCriticalSection(&m_critsect); } +}; + +/**************************************************************************** +* +* CLOCK -- Reader/writer lock class +* +***/ + +class CLock { + + private: + + HANDLE m_mutexevent; + HANDLE m_readerevent; + LONG m_readercount; + + public: + + //======================================================================= + CLock () { + m_mutexevent = CreateEvent(NULL,FALSE,TRUE,NULL); + m_readerevent = CreateEvent(NULL,TRUE,FALSE,NULL); + m_readercount = -1; + } + + //======================================================================= + ~CLock () { + CloseHandle(m_readerevent); + CloseHandle(m_mutexevent); + } + + //======================================================================= + void inline Enter (BOOL forwriting) { + if (forwriting) + WaitForSingleObject(m_mutexevent,INFINITE); + else if (!InterlockedIncrement(&m_readercount)) { + WaitForSingleObject(m_mutexevent,INFINITE); + SetEvent(m_readerevent); + } + else + WaitForSingleObject(m_readerevent,INFINITE); + } + + //======================================================================= + void inline Leave (BOOL fromwriting) { + if (fromwriting) + SetEvent(m_mutexevent); + else if (InterlockedDecrement(&m_readercount) < 0) { + ResetEvent(m_readerevent); + SetEvent(m_mutexevent); + } + } + +}; + +/**************************************************************************** +* +* TNODE/TLIST -- Linked list templates +* +***/ + +#ifdef _INC_TYPEINFO +#define INTERNALRAWNAME raw_name +#else +#define INTERNALRAWNAME internal_raw_name +class type_info { + public: + virtual ~type_info (); + inline const char * internal_raw_name () const { return _m_d_name; }; + private: + void *_m_data; + char _m_d_name[1]; + type_info (const type_info& rhs); + type_info& operator= (const type_info& rhs); +}; +#endif + +#define LIST_UNLINKED 0 +#define LIST_HEAD 1 +#define LIST_TAIL 2 + +#define LIST_LINK_AFTER LIST_HEAD +#define LIST_LINK_BEFORE LIST_TAIL + +#define LISTPTR(structname) TList * +#define LISTDECL(structname,varname) TList varname +#define NODEDECL(structname) typedef struct structname : public TNode + +template +class TList; + +template +class TNode { + friend class TList; + + private: + T *m_prev; + T *m_next; + + public: + + //======================================================================= + inline void __cdecl operator delete (void *ptr) { + SMemFree(ptr,typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + 0); + } + + //======================================================================= + inline void * __cdecl operator new (size_t bytes, size_t extra) { + void *ptr = SMemAlloc(bytes+extra, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + SMEM_FLAG_ZEROMEMORY); + return ptr; + } + + //======================================================================= + inline T * Next () { + return m_next; + } + + //======================================================================= + inline T * Prev () { + return m_prev; + } + +}; + +template +class TList { + + private: + T *m_head; + T *m_tail; + + //======================================================================= + inline void LinkToHead (T *ptr) { + // ptr->m_prev is assumed to be NULL + ptr->m_next = m_head; + if (IsEmpty()) + m_head = m_tail = ptr; + else { + m_head->m_prev = ptr; + m_head = ptr; + } + } + + //======================================================================= + inline void LinkToTail (T *ptr) { + // ptr->m_next is assumed to be NULL + ptr->m_prev = m_tail; + if (IsEmpty()) + m_head = m_tail = ptr; + else { + m_tail->m_next = ptr; + m_tail = ptr; + } + } + + public: + + //======================================================================= + inline TList () { + m_head = NULL; + m_tail = NULL; + }; + + //======================================================================= + inline void Clear () { + while (m_tail) { + T *prev = m_head->m_prev; + delete m_tail; + m_tail = prev; + } + m_head = NULL; + } + + //======================================================================= + inline T * DeleteNode (T *ptr) { + T *nextptr = ptr->m_next; + UnlinkNode(ptr); + delete ptr; + return nextptr; + } + + //======================================================================= + inline T * Head () { + return m_head; + } + + //======================================================================= + inline BOOL IsEmpty () { + return !m_head; + } + + //======================================================================= + void LinkNode (T *ptr, + DWORD linktype = LIST_LINK_AFTER, + T *existingptr = NULL) { + if (ptr->m_prev || ptr->m_next) + UnlinkNode(ptr); + switch (linktype) { + + case LIST_LINK_AFTER: + if (existingptr) { + ptr->m_prev = existingptr; + ptr->m_next = existingptr->m_next; + existingptr->m_next = ptr; + if (ptr->m_next) + ptr->m_next->m_prev = ptr; + else + m_tail = ptr; + } + else + LinkToHead(ptr); + break; + + case LIST_LINK_BEFORE: + if (existingptr) { + ptr->m_prev = existingptr->m_prev; + ptr->m_next = existingptr; + existingptr->m_prev = ptr; + if (ptr->m_prev) + ptr->m_prev->m_next = ptr; + else + m_head = ptr; + } + else + LinkToTail(ptr); + break; + + } + } + + //======================================================================= + inline T * NewNode (DWORD location = LIST_TAIL, + DWORD extrabytes = 0) { + T *ptr = new(extrabytes) T; + // new node is assumed to be initialized to zero + switch (location) { + + case LIST_HEAD: + LinkToHead(ptr); + break; + + case LIST_TAIL: + LinkToTail(ptr); + break; + + } + return ptr; + } + + //======================================================================= + inline void UnlinkNode (T *ptr) { + if (ptr->m_prev) + ptr->m_prev->m_next = ptr->m_next; + else if (m_head == ptr) + m_head = ptr->m_next; + if (ptr->m_next) + ptr->m_next->m_prev = ptr->m_prev; + else if (m_tail == ptr) + m_tail = ptr->m_prev; + ptr->m_prev = NULL; + ptr->m_next = NULL; + } + +}; + +/**************************************************************************** +* +* OLD TLIST TEMPLATE -- Obsolete!! +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return 1; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return 1; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = *head; + *head = ptr; + return 1; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return 1; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return 0; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber,0); + *head = next; + } + return 1; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber,0); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + +/**************************************************************************** +* +* TSWAP -- Swap function template +* +***/ + +//=========================================================================== +template +void inline TSwap (T *a, T *b) { + T temp = *a; + *a = *b; + *b = temp; +} +#define SWAP(a,b) TSwap(&a,&b) + +#ifndef __cplusplus +} // extern "C++" +#endif + +#endif // ifndef _STORM_H_ diff --git a/src/STORM.LIB b/src/STORM.LIB new file mode 100644 index 0000000..a2eefb2 Binary files /dev/null and b/src/STORM.LIB differ diff --git a/src/SYNC.CPP b/src/SYNC.CPP new file mode 100644 index 0000000..ad824f7 --- /dev/null +++ b/src/SYNC.CPP @@ -0,0 +1,470 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** sync.cpp +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/SYNC.CPP 3 2/10/97 6:23p Dbrevik2 $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "msg.h" +#include "multi.h" +#include "gendung.h" +#include "engine.h" +#include "items.h" +#include "player.h" +#include "error.h" +#include "debug.h" +#include "monster.h" +#include "monstint.h" +#include "inv.h" + +//****************************************************************** +// externs +//****************************************************************** +void M_ClearSquares(int nMonster); +void delta_sync_monster(const TSyncMonster * p,BYTE bLevel); + + +//****************************************************************** +// private +//****************************************************************** +static int sgnMonsters; +static WORD sgwDelta[MAXMONSTERS]; +static WORD sgwLRU[MAXMONSTERS]; +static int sgnLRUScan; + +#define LRU_NEVER 0xffff +#define LRU_REINIT 0xfffe +#define LRU_INIT 0xff + +static int sgnSyncItem = 0; +static int sgnSyncObj = 0; +static int sgnSyncPInv = 0; + +//****************************************************************** +//****************************************************************** +static void prep_monster_list(void) { + for (int i = 0; i < nummonsters; i++) { + int mi = monstactive[i]; + sgwDelta[mi] = abs(plr[myplr]._px - monster[mi]._mx) + + abs(plr[myplr]._py - monster[mi]._my); + + // make all the squelched monsters particularly unattractive + // make all the unsquelched monsters decrement their LRU + // counters so that they will get sent eventually + if (! monster[mi]._msquelch) + sgwDelta[mi] += 0x1000; + else if (sgwLRU[mi]) + sgwLRU[mi]--; + } +} + + +//****************************************************************** +//****************************************************************** +static void get_monster(TSyncMonster * p,int mi) { + // get the true monster number + // and save monster's parameters + p->_mndx = mi; + p->_mx = monster[mi]._mx; + p->_my = monster[mi]._my; + // encode player/monster enemy + p->_menemy = encode_enemy(mi); + p->_mdelta = sgwDelta[mi] > 0xff ? 0xff : sgwDelta[mi]; + // cant have this since menemy maybe a monster id + //app_assert((DWORD) p->_menemy < MAX_PLRS); + + // reset delta table so we don't find this monster again + sgwDelta[mi] = 0xffff; + + // reset LRU count so we don't resend this monster unnecessarily + sgwLRU[mi] = monster[mi]._msquelch ? LRU_REINIT : LRU_NEVER; +} + + +//****************************************************************** +//****************************************************************** +static BOOL get_best_monster(TSyncMonster * p) { + // search all the monsters for the one closest to the player + int nFound = -1; + DWORD dwMin = 0xffffffff; + for (int i = 0; i < nummonsters; i++) { + int mi = monstactive[i]; + + // is this monster close to the local player? + if (sgwDelta[mi] >= dwMin) continue; + + // is this a monster which has already been sent LRU? + if (sgwLRU[mi] >= LRU_REINIT) continue; + + // found better candidate + dwMin = sgwDelta[mi]; + nFound = mi; + } + if (nFound == -1) return FALSE; + get_monster(p,nFound); + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static BOOL get_lru_monster(TSyncMonster * p) { + // search all the monsters for the lowest LRU number + int nFound = -1; + DWORD dwMin = LRU_REINIT; + for (int i = 0; i < nummonsters; i++,sgnLRUScan++) { + if (sgnLRUScan >= nummonsters) sgnLRUScan = 0; + int mi = monstactive[sgnLRUScan]; + + // is this a monster which hasn't been sent in a while? + if (sgwLRU[mi] >= dwMin) continue; + + dwMin = sgwLRU[mi]; + nFound = mi; + } + if (nFound == -1) return FALSE; + get_monster(p,nFound); + return TRUE; +} + +//****************************************************************** +//****************************************************************** +static void FillHeaderSync(TSyncHeader * pHdr) +{ + // Fill one item + int ii; + if (numitems > 0) { + if (sgnSyncItem >= numitems) sgnSyncItem = 0; + ii = itemactive[sgnSyncItem++]; + pHdr->bItemI = ii; + pHdr->bItemX = item[ii]._ix; + pHdr->bItemY = item[ii]._iy; + pHdr->wItemIndx = item[ii].IDidx; + if (item[ii].IDidx == IDI_EAR) { + pHdr->wItemCI = (item[ii]._iName[7] << 8) | item[ii]._iName[8]; + pHdr->dwItemSeed = (item[ii]._iName[9] << 24) | + (item[ii]._iName[10] << 16) | + (item[ii]._iName[11] << 8) | + item[ii]._iName[12]; + pHdr->bItemId = item[ii]._iName[13]; + pHdr->bItemDur = item[ii]._iName[14]; + pHdr->bItemMDur = item[ii]._iName[15]; + pHdr->bItemCh = item[ii]._iName[16]; + pHdr->bItemMCh = item[ii]._iName[17]; + pHdr->wItemVal = (item[ii]._iName[18] << 8) | ((item[ii]._iCurs - ITEM_EAR1) << 6) | item[ii]._ivalue; + pHdr->dwItemBuff = (item[ii]._iName[19] << 24) | + (item[ii]._iName[20] << 16) | + (item[ii]._iName[21] << 8) | + item[ii]._iName[22]; + } else { + pHdr->wItemCI = item[ii]._iCreateInfo; + pHdr->dwItemSeed = item[ii]._iSeed; + pHdr->bItemId = item[ii]._iIdentified; + pHdr->bItemDur = item[ii]._iDurability; + pHdr->bItemMDur = item[ii]._iMaxDur; + pHdr->bItemCh = item[ii]._iCharges; + pHdr->bItemMCh = item[ii]._iMaxCharges; + if (item[ii].IDidx == IDI_GOLD) pHdr->wItemVal = item[ii]._ivalue; + } + } + else { + pHdr->bItemI = 0xff; + } + + // Fill with player inv info + app_assert((DWORD) sgnSyncPInv < NUM_INVLOC); + ItemStruct *itm = &plr[myplr].InvBody[sgnSyncPInv]; + if (itm->_itype != -1) { + pHdr->bPInvLoc = sgnSyncPInv; + pHdr->wPInvIndx = itm->IDidx; + pHdr->wPInvCI = itm->_iCreateInfo; + pHdr->dwPInvSeed = itm->_iSeed; + // drb.patch1.start.02/10/97 + pHdr->bPInvId = itm->_iIdentified; + // drb.patch1.end.02/10/97 + } + else { + pHdr->bPInvLoc = 0xff; + } + + // next item + sgnSyncPInv++; + if (sgnSyncPInv >= NUM_INVLOC) + sgnSyncPInv = 0; +} + + +//****************************************************************** +//****************************************************************** +DWORD sync_get(BYTE * pbBuf,DWORD dwMaxLen) { + // if there are no monsters to sync, exit + if (nummonsters < 1) return dwMaxLen; + + // is there enough space for at header + one monster sync + if (dwMaxLen < sizeof(TSyncMonster) + sizeof(TSyncHeader)) + return dwMaxLen; + + // setup header + TSyncHeader * pHdr = (TSyncHeader *) pbBuf; + pbBuf += sizeof(TSyncHeader); + dwMaxLen -= sizeof(TSyncHeader); + pHdr->bCmd = CMD_SYNCDATA; + pHdr->bLevel = currlevel; + pHdr->wLen = 0; + // Put one object, one item and one plr inv item into sync packets + FillHeaderSync(pHdr); + + // make sure we don't overrun header maximum length + app_assert(dwMaxLen <= 0xffff); + + prep_monster_list(); + for (int nMonsters = 0; nMonsters < nummonsters; nMonsters++) { + if (dwMaxLen < sizeof(TSyncMonster)) break; + + BOOL bGotOne = FALSE; + if (nMonsters < 2) bGotOne = get_lru_monster((TSyncMonster *) pbBuf); + if (! bGotOne) bGotOne = get_best_monster((TSyncMonster *) pbBuf); + if (! bGotOne) break; + + pbBuf += sizeof(TSyncMonster); + pHdr->wLen += sizeof(TSyncMonster); + dwMaxLen -= sizeof(TSyncMonster); + } + + // return bytes left in buffer + return dwMaxLen; +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------* + +byte monstupdate[MAXMONSTERS]; + +void DaveMonstMap(BOOL initupdate, int pnum) +{ + int i,j,m; + char tempstr[512], tempstr2[256]; + + if (initupdate) + for (i = 0; i < MAXMONSTERS; i++) monstupdate[i] = 0; + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dFlags[i][j] & BFLAG_MONSTLR) { + if (dMonster[i-1][j] != dMonster[i][j-1]) { + sprintf(tempstr, "Error in map @ %i,%i x-1,j = %i, x,j-1 = %i\n", i, j, dMonster[i-1][j], dMonster[i][j-1]); + if (dMonster[i-1][j] == 0) sprintf(tempstr2, "Null monster\n @ %i,%i", i-1, j); + else { + if (dMonster[i-1][j] > 0) m = dMonster[i-1][j] - 1; + else m = -(dMonster[i-1][j] + 1); + sprintf(tempstr2, "Monst %i xy = %i,%i oxy = %i,%i mode = %i Updated = %i\n", + m, monster[m]._mx, monster[m]._my, monster[m]._moldx, monster[m]._moldy, monster[m]._mmode, monstupdate[m]); + } + strcat(tempstr, tempstr2); + if (dMonster[i][j-1] == 0) sprintf(tempstr2, "Null monster @ %i,%i\n", i, j-1); + else { + if (dMonster[i][j-1] > 0) m = dMonster[i][j-1] - 1; + else m = -(dMonster[i][j-1] + 1); + sprintf(tempstr2, "Monst %i xy = %i,%i oxy = %i,%i mode = %i Updated = %i\n", + m, monster[m]._mx, monster[m]._my, monster[m]._moldx, monster[m]._moldy, monster[m]._mmode, monstupdate[m]); + } + strcat(tempstr, tempstr2); + sprintf(tempstr2, "Info from plr %i = %s", pnum, plr[pnum]._pName); + strcat(tempstr, tempstr2); + app_fatal(tempstr); + } + } + } + } +} +*/ +//****************************************************************** +//****************************************************************** +static void sync_monster(int pnum,const TSyncMonster * p) { + + // get monster index + int ndx = p->_mndx; + + // did I just kill this monster? + if (monster[ndx]._mhitpoints <= 0) return; + + // check for valid index + for (int i = 0; i < nummonsters && monstactive[i] != ndx; i++); + //app_assert(i < nummonsters); + + // calc distance I think he is from me + DWORD delta = + abs(plr[myplr]._px - monster[ndx]._mx) + + abs(plr[myplr]._py - monster[ndx]._my); + if (delta > 0xff) delta = 0xff; + + // if my delta is less than the other player's delta, use mine + if (delta < p->_mdelta) return; + // if the deltas are the same use the lowest player num + else if ((delta == p->_mdelta) && (pnum > myplr)) return; + + // if the monster is going to be there soon, don't do anything + if (monster[ndx]._mfutx == p->_mx && monster[ndx]._mfuty == p->_my) return; + + // Snake crash fix. Don't mess with missile monsters while they are warping + if (monster[ndx]._mmode == MM_MISSILE) return; + // Don't mess with stone cursed monsters + if (monster[ndx]._mmode == MM_STONE) return; + + // if the monster is far away, jump him into position + int mdx = abs(monster[ndx]._mx - p->_mx); + int mdy = abs(monster[ndx]._my - p->_my); + if (mdx > 2 || mdy > 2) { + if (! dMonster[p->_mx][p->_my]) { + // remove where monster is now + M_ClearSquares(ndx); + + // put him in new location + dMonster[p->_mx][p->_my] = ndx + 1; + monster[ndx]._mx = p->_mx; + monster[ndx]._my = p->_my; + decode_enemy(ndx, p->_menemy); + M_StartStand(ndx, GetDirection(p->_mx,p->_my, monster[ndx]._menemyx, monster[ndx]._menemyy)); + + // make sure he's awake + monster[ndx]._msquelch = 255; + } + } + else { + // if the monster is not already on the way to a nearby + // square, start him immediately on his way + if ((monster[ndx]._mmode < MM_WALK) || (monster[ndx]._mmode > MM_WALK3)) { + int md = GetDirection(monster[ndx]._mx, monster[ndx]._my, p->_mx, p->_my); + + if (DirOK(ndx, md)) { + // remove where monster is now + M_ClearSquares(ndx); + + // make monster walk into square where he should be + dMonster[monster[ndx]._mx][monster[ndx]._my] = ndx + 1; + M_WalkDir(ndx, md); + + // make sure he's awake + monster[ndx]._msquelch = 255; + } + } + } + + // sync enemy + // cant have this since menemy maybe a monster id + //app_assert((DWORD) p->_menemy < MAX_PLRS); + decode_enemy(ndx, p->_menemy); +} + + +//****************************************************************** +//****************************************************************** +static void UpdateHeaderSync(int pnum, const TSyncHeader * pHdr) +{ + // Fill one item + if (pHdr->bItemI != 0xff) { + int ii = pHdr->bItemI; + if ((pHdr->wItemIndx != item[ii].IDidx) || + (pHdr->wItemCI != item[ii]._iCreateInfo) || + (pHdr->dwItemSeed != item[ii]._iSeed)) { + ii = FindGetItem(pHdr->wItemIndx, pHdr->wItemCI, pHdr->dwItemSeed); + if (ii == -1) { + SyncPutItem(pnum, + pHdr->bItemX, + pHdr->bItemY, + pHdr->wItemIndx, + pHdr->wItemCI, + pHdr->dwItemSeed, + pHdr->bItemId, + pHdr->bItemDur, + pHdr->bItemMDur, + pHdr->bItemCh, + pHdr->bItemMCh, + pHdr->wItemVal, + pHdr->dwItemBuff, + pHdr->wPLToHit, + pHdr->wMaxDam, + pHdr->bMinStr, + pHdr->bMinMag, + pHdr->bMinDex, + pHdr->bAC + ); + } + } + } + // Fill with player inv info + if (pHdr->bPInvLoc != 0xff) { + ItemStruct *itm = &plr[myplr].InvBody[pHdr->bPInvLoc]; + if ((pHdr->wPInvIndx != itm->IDidx) || + (pHdr->wPInvCI != itm->_iCreateInfo) || + // drb.patch1.start.02/10/97 + // (pHdr->dwPInvSeed != itm->_iSeed)) { + (pHdr->dwPInvSeed != itm->_iSeed) || + (pHdr->bPInvId != itm->_iIdentified)) { + // SyncInvPaste(pnum, pHdr->bPInvLoc, pHdr->wPInvIndx, pHdr->wPInvCI, pHdr->dwPInvSeed,); + SyncInvPaste(pnum, pHdr->bPInvLoc, pHdr->wPInvIndx, pHdr->wPInvCI, pHdr->dwPInvSeed, pHdr->bPInvId); + // drb.patch1.end.02/10/97 + } + } +} + + +//****************************************************************** +//****************************************************************** +DWORD sync_update(int pnum,const BYTE * pbBuf) { + const TSyncHeader * pHdr = (const TSyncHeader *) pbBuf; + pbBuf += sizeof(TSyncHeader); + + // make sure we have a valid sync record + if (pHdr->bCmd != CMD_SYNCDATA) + app_fatal("bad sync command"); + + // don't resync while we're in buffer mode + app_assert(gbBufferMsgs != BUFFER_PROCESS); + if (gbBufferMsgs == BUFFER_ON) + return pHdr->wLen + sizeof(TSyncHeader); + + // we don't resync using our own information + if (pnum == myplr) return pHdr->wLen + sizeof(TSyncHeader); + + // Make sure we are in sync with others on the level + //if (currlevel == pHdr->bLevel) UpdateHeaderSync(pnum, pHdr); + + WORD wLen = pHdr->wLen; + while (wLen >= sizeof(TSyncMonster)) { + if (currlevel == pHdr->bLevel) + sync_monster(pnum,(const TSyncMonster *) pbBuf); + delta_sync_monster((const TSyncMonster *) pbBuf,pHdr->bLevel); + pbBuf += sizeof(TSyncMonster); + wLen -= sizeof(TSyncMonster); + } + + // make sure we used all the bytes + app_assert(wLen == 0); + + // return true number of bytes in our sync section + return pHdr->wLen + sizeof(TSyncHeader); +} + + +//****************************************************************** +//****************************************************************** +void sync_init() { + // don't let all the players start scanning in the same location. + // if each player is scanning from a different location, it is + // more likely that multiple monsters can be synced every turn + sgnLRUScan = myplr * 16; + FillMemory(sgwLRU,sizeof sgwLRU,LRU_INIT); +} diff --git a/src/SYSMON.EXE b/src/SYSMON.EXE new file mode 100644 index 0000000..d06854a Binary files /dev/null and b/src/SYSMON.EXE differ diff --git a/src/Savedll/STORM.DLL b/src/Savedll/STORM.DLL new file mode 100644 index 0000000..21f620d Binary files /dev/null and b/src/Savedll/STORM.DLL differ diff --git a/src/Storm/ARCHIVE.BAT b/src/Storm/ARCHIVE.BAT new file mode 100644 index 0000000..a177e11 --- /dev/null +++ b/src/Storm/ARCHIVE.BAT @@ -0,0 +1,13 @@ +@echo off +if "%1"=="" goto usage +if "%2"=="" goto usage +goto start +:usage +echo Usage: ARCHIVE filename password +goto done +:start +cmd /c clean +pkzip32 -add -dir -max %1.zip * -excl=*.smk -excl=*.cod -excl=*.dsp -excl=*.dsw -excl=*.mak -excl=*.map +rename %1.zip %1.zip.enc +encrypt %1.zip.enc %2 +:done diff --git a/src/Storm/BIN/BATTLE.SNP b/src/Storm/BIN/BATTLE.SNP new file mode 100644 index 0000000..853dddf Binary files /dev/null and b/src/Storm/BIN/BATTLE.SNP differ diff --git a/src/Storm/BIN/BATTLED.SNP b/src/Storm/BIN/BATTLED.SNP new file mode 100644 index 0000000..55ea508 Binary files /dev/null and b/src/Storm/BIN/BATTLED.SNP differ diff --git a/src/Storm/BIN/SMACKW32.DLL b/src/Storm/BIN/SMACKW32.DLL new file mode 100644 index 0000000..02c7940 Binary files /dev/null and b/src/Storm/BIN/SMACKW32.DLL differ diff --git a/src/Storm/BIN/STANDARD.SNP b/src/Storm/BIN/STANDARD.SNP new file mode 100644 index 0000000..8e4dafb Binary files /dev/null and b/src/Storm/BIN/STANDARD.SNP differ diff --git a/src/Storm/BIN/STANDA~1.SNP b/src/Storm/BIN/STANDA~1.SNP new file mode 100644 index 0000000..5c685a9 Binary files /dev/null and b/src/Storm/BIN/STANDA~1.SNP differ diff --git a/src/Storm/BIN/STORM.DLL b/src/Storm/BIN/STORM.DLL new file mode 100644 index 0000000..c8295c3 Binary files /dev/null and b/src/Storm/BIN/STORM.DLL differ diff --git a/src/Storm/BIN/STORMD.DLL b/src/Storm/BIN/STORMD.DLL new file mode 100644 index 0000000..443ad7d Binary files /dev/null and b/src/Storm/BIN/STORMD.DLL differ diff --git a/src/Storm/CLEAN.BAT b/src/Storm/CLEAN.BAT new file mode 100644 index 0000000..eff2ed0 --- /dev/null +++ b/src/Storm/CLEAN.BAT @@ -0,0 +1,8 @@ +@echo off +if not exist bin\storm.dll goto done +locate /d bin\*.bak +locate /d help\*.fts +locate /d samples\*.aps *.bak *.ilk *.exp *.obj *.pch *.pdb *.res *.tmp a.* dump.* +locate /d source\*.aps *.bak *.ilk *.exp *.obj *.pch *.pdb *.res *.tmp a.* dump.* *.lib *.dll *.snp +if exist *.bak del *.bak +:done diff --git a/src/Storm/DEBUG/STORM.EXP b/src/Storm/DEBUG/STORM.EXP new file mode 100644 index 0000000..30ad236 Binary files /dev/null and b/src/Storm/DEBUG/STORM.EXP differ diff --git a/src/Storm/DEBUG/STORM.LIB b/src/Storm/DEBUG/STORM.LIB new file mode 100644 index 0000000..4e594cc Binary files /dev/null and b/src/Storm/DEBUG/STORM.LIB differ diff --git a/src/Storm/DEBUG/STORMDLL.PCH b/src/Storm/DEBUG/STORMDLL.PCH new file mode 100644 index 0000000..5ca8119 Binary files /dev/null and b/src/Storm/DEBUG/STORMDLL.PCH differ diff --git a/src/Storm/DEBUG/VC50.IDB b/src/Storm/DEBUG/VC50.IDB new file mode 100644 index 0000000..a90330f Binary files /dev/null and b/src/Storm/DEBUG/VC50.IDB differ diff --git a/src/Storm/DOCS/C.BAT b/src/Storm/DOCS/C.BAT new file mode 100644 index 0000000..98f6497 --- /dev/null +++ b/src/Storm/DOCS/C.BAT @@ -0,0 +1,7 @@ +@echo off +if exist storm.hlp del storm.hlp +hc31 storm.hpj +if exist storm.ph del storm.ph +if exist *.bak del *.bak +if exist storm.hlp copy storm.hlp o:\help\storm.hlp /v +if exist storm.hlp start winhlp32 storm.hlp diff --git a/src/Storm/DOCS/CATEGO~1.RTF b/src/Storm/DOCS/CATEGO~1.RTF new file mode 100644 index 0000000..0ca6c98 --- /dev/null +++ b/src/Storm/DOCS/CATEGO~1.RTF @@ -0,0 +1,60 @@ +{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;} +{\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f19\froman\fcharset161\fprq2 Times New Roman Greek;}{\f20\froman\fcharset162\fprq2 Times New Roman Tur;} +{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f28\fmodern\fcharset238\fprq1 Courier New CE;}{\f29\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f31\fmodern\fcharset161\fprq1 Courier New Greek;}{\f32\fmodern\fcharset162\fprq1 Courier New Tur;} +{\f33\fmodern\fcharset186\fprq1 Courier New Baltic;}}{\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\widctlpar\adjustright \fs20 \snext0 Normal;} +{\*\cs10 \additive Default Paragraph Font;}{\s15\nowidctlpar\widctlpar\adjustright \b\fs40 \sbasedon0 \snext16 API Title;}{\s16\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 API Description;}{\s17\nowidctlpar\widctlpar\adjustright \f2\fs22 +\sbasedon0 \snext17 API Function;}{\s18\nowidctlpar\widctlpar\adjustright \b \sbasedon0 \snext16 API Section;}{\s19\li720\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 API Parameter Description;}{\s20\nowidctlpar\widctlpar\adjustright \i +\sbasedon0 \snext19 API Parameter Name;}{\s21\nowidctlpar\widctlpar\adjustright \fs20 \sbasedon0 \snext21 footnote text;}{\*\cs22 \additive \super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien} +{\creatim\yr1997\mo3\dy21\hr17\min1}{\revtim\yr1997\mo3\dy21\hr18\min23}{\version5}{\edmins17}{\nofpages2}{\nofwords261}{\nofchars1490}{\*\company Blizzard Entertainment}{\nofcharsws0}{\vern71}} +\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade\viewkind1\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 +\s15\keepn\nowidctlpar\widctlpar\adjustright \b\fs40 {\cs22\super ${\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super $}{ CategoryProc}}#{\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super #}{ +CategoryProc}}K{\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super K}{ CategoryProc}}}{ CategoryProc +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }{\b\i CategoryProc() is a placeholder for an application-defined function name.}{ +\par +\par This function is called by from SNetSelectGame() prior to enumerating games, and optionally in response to a user request, so that the application can prompt the user about which categories of games he would like to display. +\par +\par }\pard\plain \s17\nowidctlpar\widctlpar\adjustright \f2\fs22 {BOOL CALLBACK SelectCategoryProc ( +\par \tab BOOL\tab \tab \tab \tab userinitiated, +\par \tab SNETPROGRAMDATAPTR\tab programdata, +\par \tab SNETPLAYERDATAPTR\tab playerdata, +\par \tab SNETUIDATAPTR\tab \tab interfacedata, +\par \tab SNETVERSIONDATAPTR\tab versiondata, +\par \tab DWORD *\tab \tab \tab categorybits, +\par \tab DWORD *\tab \tab \tab categorymask +\par ); +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s18\nowidctlpar\widctlpar\adjustright \b {Parameters +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {userinitiated +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A boolean value spec +ifying why the callback function is being called. If this value is FALSE, the function is being called automatically prior to bringing up the list of games. If this value is TRUE, the function is being called in response to a user request. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {programdata +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A structure containing the program data that was passed to SNetSelectGame(). +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {playerdata +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A structure containing the player data that was passed to SNetSelectGame(). +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {interfacedata +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A structure containing the interface data that was passed to SNetSelectGame(), modified as necessary to ensure that the dialog that the create callback displays fits with the network provider +\rquote s interface. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {versiondata +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A structure containing the version data that was passed to SNetSelectGame(). +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {Categorybits +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A value returned by the callback function specifying which categories of games the user is interested in joining. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {categorymask +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A value returned by the callback function specifying which bits must match between the value of }{\i categorybits}{ and the game\rquote s category bits for a game to be enumerated. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par +\par }\pard\plain \s18\nowidctlpar\widctlpar\adjustright \b {Return Value +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par The application should return TRUE to cause game enumeration to begin, or FALSE to abort the call to SNetSelectGame(). +\par +\par }} \ No newline at end of file diff --git a/src/Storm/DOCS/CHECKA~1.RTF b/src/Storm/DOCS/CHECKA~1.RTF new file mode 100644 index 0000000..d68a1ed --- /dev/null +++ b/src/Storm/DOCS/CHECKA~1.RTF @@ -0,0 +1,62 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo11\dy28\hr2\min32}{\version3} +{\edmins34}{\nofpages2}{\nofwords249}{\nofchars1420}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} CheckAuthProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} CheckAuthProc}K{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} CheckAuthProc}} CheckAuthProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i CheckAuthProc() is a placeholder for an application-defined function name.} +\par +\par \pard \s16\widctlpar This function is called by the current network provider to determine whether the active user is authorized to join a game or chat channel. +\par \pard \s16\widctlpar +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK CheckAuthProc ( +\par \tab DWORD\tab \tab itemtype, +\par \tab LPCSTR\tab playername, +\par \tab LPCSTR\tab playerdescription, +\par \tab DWORD\tab \tab userflags, +\par \tab LPCSTR\tab itemdescription, +\par \tab LPSTR\tab \tab errorbuffer, +\par \tab DWORD\tab \tab errorsize +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 itemtype +\par \pard\plain \s19\li720\widctlpar \f4 An identifier which tells whether the name and description describe a game or a player. It can be one of the following values: +\par \pard\plain \s16\widctlpar \f4 +\par \trowd \trgaph108\trleft612 \cellx4140\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell \pard \s19\widctlpar\intbl {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4140\cellx7812 \pard\plain +\s19\widctlpar\intbl \f4 SNET_AUTHTYPE_GAME\cell \pard \s19\widctlpar\intbl Item is a game.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4140\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_AUTHTYPE_CHANNEL\cell +\pard \s19\widctlpar\intbl Item is a chat channel.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playername +\par \pard\plain \s19\li720\widctlpar \f4 The name of the player. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerdescription +\par \pard\plain \s19\li720\widctlpar \f4 An application defined string containing information about the player. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 userflags +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags for the player. The following flags are currently defined: +\par \pard\plain \s16\widctlpar \f4 \tab +\par \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNE +T_DDPF_BLIZZARD\cell Player is a Blizzard employee\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_DDPF_MODERATOR\cell Player is a channel moderator\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain +\s19\widctlpar\intbl \f4 SNET_DDPF_SPEAKER\cell Player is a speaker for a special event\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_DDPF_SYSOP\cell Player is a sysop of the selected gaming service\cell +\pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_DDPF_SQUELCHED\cell Player has been squelched by the local user\cell \pard\plain \widctlpar\intbl \f4\fs20 \row +\pard\plain \s16\widctlpar \f4 +\par +\par \pard\plain \s20\widctlpar \i\f4 itemdescription +\par \pard\plain \s19\li720\widctlpar \f4 If {\i itemtype} is SNET_AUTHTYPE_GAME, this field contains the game description. If {\i itemtype} is SNET_AUTHTYPE_CHANNEL, this field contains the channel name. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 errorbuffer +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a string buffer which the application fills in with an error message in the case that authorization is not granted. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 errorsize +\par \pard\plain \s19\li720\widctlpar \f4 The size, in characters, of the string buffer. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par \pard \s16\widctlpar This function should return TRUE if the user is authorized to join the game or channel, or FALSE if the function fails or the user is not authorized. +\par \pard \s16\widctlpar +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/CREATE~1.RTF b/src/Storm/DOCS/CREATE~1.RTF new file mode 100644 index 0000000..8c58d6f --- /dev/null +++ b/src/Storm/DOCS/CREATE~1.RTF @@ -0,0 +1,52 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy21\hr17\min2}{\version4} +{\edmins8}{\nofpages2}{\nofwords261}{\nofchars1490}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} CreateProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} CreateProc}K{\footnote \pard\plain +\s21\widctlpar \f4\fs20 {\cs22\super K} CreateProc}} CreateProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i CreateProc() is a placeholder for an application-defined function name.} +\par +\par This function is called by +from SNetSelectGame() if the user has decided to create a new game. The create callback is responsible for display a dialog to the user to request game information like the game name and difficulty, and then calling SNetCreateGame(). +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK CreateProc ( +\par \tab SNETCREATEDATAPTR\tab createdata, +\par \tab SNETPROGRAMDATAPTR\tab programdata, +\par \tab SNETPLAYERDATAPTR\tab playerdata, +\par \tab SNETUIDATAPTR\tab \tab interfacedata, +\par \tab SNETVERSIONDATAPTR\tab versiondata, +\par \tab DWORD\tab *\tab \tab \tab playerid +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 createdata +\par \pard\plain \s19\li720\widctlpar \f4 A structure provided by the service provider containing data that the application will need to create the game. When the data in this structure conflicts with the application\rquote +s own data, the application should use the data in the structure. For example, the maxplayers field may be set lower than the application\rquote s maximum number of players if the network provider does not support the application\rquote +s maximum number of players. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 programdata +\par \pard\plain \s19\li720\widctlpar \f4 A structure containing the program data that was passed to SNetSelectGame(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerdata +\par \pard\plain \s19\li720\widctlpar \f4 A structure containing the player data that was passed to SNetSelectGame(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 interfacedata +\par \pard\plain \s19\li720\widctlpar \f4 A structure containing the interface data that was passed to SNetSelectGame(), modified as necessary to ensure that the dialog that the create callback displays fits with the network provider\rquote s interface. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 versiondata +\par \pard\plain \s19\li720\widctlpar \f4 A structure containing the version data that was passed to SNetSelectGame(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerid +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a DWORD which the function should fill in with the player ID assigned in the call to SNetCreateGame(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par The application should return TRUE if it called SNetCreateGame() and the call was successful. It should return FALSE if the game was not created for any reason. +\par +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/DRAWDE~1.RTF b/src/Storm/DOCS/DRAWDE~1.RTF new file mode 100644 index 0000000..834d73b --- /dev/null +++ b/src/Storm/DOCS/DRAWDE~1.RTF @@ -0,0 +1,69 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo11\dy22\min44}{\version2} +{\edmins1}{\nofpages2}{\nofwords310}{\nofchars1768}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} DrawDescProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} DrawDescProc}K{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} DrawDescProc}} DrawDescProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i DrawDescProc() is a placeholder for an application-defined function name.} +\par +\par This function is called by Storm or the current network provider when it needs to draw a game or player description. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK DrawDescProc ( +\par \tab DWORD\tab \tab \tab \tab providerid, +\par \tab DWORD\tab \tab \tab \tab itemtype, +\par \tab LPCSTR\tab \tab \tab itemname, +\par \tab LPCSTR\tab \tab \tab itemdescription, +\par \tab DWORD\tab \tab \tab \tab itemflags, +\par \tab DWORD\tab \tab \tab \tab itemcreationtime, +\par \tab DWORD\tab \tab \tab \tab drawflags, +\par \tab LPDRAWITEMSTRUCT\tab drawdata +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 providerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the network provider which is making the request. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 itemtype +\par \pard\plain \s19\li720\widctlpar \f4 An identifier which tells whether the name and description describe a game or a player. It can be one of the following values: +\par \pard\plain \s16\widctlpar \f4 +\par \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_DRAWTYPE_GAME\cell Item is a game\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_DRAWTYPE_PLAYER\cell Item is a player\cell \pard\plain \widctlpar\intbl +\f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 itemname +\par \pard\plain \s19\li720\widctlpar \f4 The name of the game or player. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 itemdescription +\par \pard\plain \s19\li720\widctlpar \f4 The description of the game or player. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 itemflags +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags for the game or player. The following flags are currently defined for players: +\par \pard\plain \s16\widctlpar \f4 \tab +\par \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_DDPF_BLIZZARD\cell Player is a Blizzard employee\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_DDPF_MODERATOR\cell Player is a channel moderator\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain +\s19\widctlpar\intbl \f4 SNET_DDPF_SPEAKER\cell Player is a speaker for a special event\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_DDPF_SYSOP\cell Player is a sysop of the selected gaming service\cell +\pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_DDPF_SQUELCHED\cell Player has been squelched by the local user\cell \pard\plain \widctlpar\intbl \f4\fs20 \row +\pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 itemcreationtime +\par \pard\plain \s19\li720\widctlpar \f4 The creation time of the game, expressed as the number of seconds since midnight, January 1, 1970 UTC. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 drawflags +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags defining how the item should be drawn. The following flags are defined: +\par +\par \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard \s19\widctlpar\intbl {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_DDF_INCLUDENAME\cell The callback function should draw the game name as well as the description. If this flag is not specified then the game is already visible elsewhere on the screen, and only the description needs to be drawn.\cell \pard\plain +\widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_DDF_MULTILINE\cell The area for the description is large enough to include more than one line of text.\cell \pard\plain +\widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 drawdata +\par \pard\plain \s19\li720\widctlpar \f4 A structure containing information about the output device. This includes the device context, and the rectangle (in client coordinates) to which the application should bound its output. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function should return TRUE if the description was successfully drawn, or FALSE if an error occurred. +\par +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/ENUMGA~1.RTF b/src/Storm/DOCS/ENUMGA~1.RTF new file mode 100644 index 0000000..bfd5149 --- /dev/null +++ b/src/Storm/DOCS/ENUMGA~1.RTF @@ -0,0 +1,36 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr15\min4}{\version2} +{\edmins3}{\nofpages1}{\nofwords82}{\nofchars472}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} EnumGamesProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} EnumGamesProc}} {\cs22\super K +{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} EnumGamesProc}} EnumGamesProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i EnumGamesProc() is a placeholder for an application-defined function name.} +\par +\par This function is called by SNetEnumGames() once for each active game that matches the program and version IDs of the application. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK EnumGamesProc ( +\par \tab DWORD\tab \tab gameid, +\par \tab LPCSTR\tab gamename, +\par \tab LPCSTR\tab gamedescription +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 gameid +\par \pard\plain \s19\li720\widctlpar \f4 Unique identifier of the game. Pass this value to SNetJoinGame(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 gamename +\par \pard\plain \s19\li720\widctlpar \f4 The name of the game. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 gamedescription +\par \pard\plain \s19\li720\widctlpar \f4 A description of the game. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function should return TRUE to continue enumeration, or FALSE to stop. +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/ENUMPR~1.RTF b/src/Storm/DOCS/ENUMPR~1.RTF new file mode 100644 index 0000000..0d4ff29 --- /dev/null +++ b/src/Storm/DOCS/ENUMPR~1.RTF @@ -0,0 +1,40 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr15\min5}{\version3} +{\edmins1}{\nofpages1}{\nofwords105}{\nofchars602}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} EnumProvidersProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} EnumProvidersProc}K +{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} EnumProvidersProc}} EnumProvidersProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i EnumProvidersProc() is a placeholder for an application-defined function name.} +\par +\par This function is called by SNetEnumProviders() once for each network provider installed on the system. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK EnumProvidersProc ( +\par \tab DWORD\tab \tab \tab providerid, +\par \tab LPCSTR\tab \tab name, +\par \tab LPCSTR\tab \tab requirements, +\par \tab SNETCAPSPTR\tab caps +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 providerid +\par \pard\plain \s19\li720\widctlpar \f4 The unique ID of the provider. Pass this value to SNetInitializeProvider(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 name +\par \pard\plain \s19\li720\widctlpar \f4 The name of the provider. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 requirements +\par \pard\plain \s19\li720\widctlpar \f4 A string describing the requirements for using this provider, such as \ldblquote two computers connected by a serial cable and null-modem.\rdblquote +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 caps +\par \pard\plain \s19\li720\widctlpar \f4 The capabilities of this provider. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function should return TRUE to continue enumeration, or FALSE to stop. +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/EVENTP~1.RTF b/src/Storm/DOCS/EVENTP~1.RTF new file mode 100644 index 0000000..0720219 --- /dev/null +++ b/src/Storm/DOCS/EVENTP~1.RTF @@ -0,0 +1,28 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr15\min5}{\version2} +{\edmins0}{\nofpages1}{\nofwords77}{\nofchars439}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} EventProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} EventProc}K{\footnote \pard\plain +\s21\widctlpar \f4\fs20 {\cs22\super K} EventProc}} EventProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i EventProc() is a placeholder for an application-defined function name.} +\par +\par This function is called to notify the application of a network event. Network events are queued up, and only delivered to the application when it calls SNetReceiveMessage() or SNetReceiveTurns(). +\par +\par \pard\plain \s17\widctlpar \f11\fs22 void CALLBACK EventProc ( +\par \tab SNETEVENTPTR event +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 eventdata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure describing the event, and containing the ID of the player who caused the event to be generated. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function does not return a value. +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/GETART~1.RTF b/src/Storm/DOCS/GETART~1.RTF new file mode 100644 index 0000000..95481f8 --- /dev/null +++ b/src/Storm/DOCS/GETART~1.RTF @@ -0,0 +1,59 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr15\min5}{\version2} +{\edmins0}{\nofpages2}{\nofwords290}{\nofchars1656}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} GetArtProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} GetArtProc}K{\footnote \pard\plain +\s21\widctlpar \f4\fs20 {\cs22\super K} GetArtProc}} GetArtProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i GetArtProc() is a placeholder for an application-defined function name.} +\par +\par This function is called by Storm or the current network provider to get artwork necessary for displaying a user interface screen. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK GetArtProc ( +\par \tab DWORD\tab \tab \tab providerid, +\par \tab DWORD\tab \tab \tab artid, +\par \tab LPPALETTEENTRY\tab palette, +\par \tab LPBYTE\tab \tab buffer, +\par \tab DWORD\tab \tab \tab buffersize, +\par \tab int\tab \tab \tab *width, +\par \tab int\tab \tab \tab *height, +\par \tab int\tab \tab \tab *bitdepth +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 providerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the network provider which is requesting the artwork, or zero if the artwork is being requested for a screen which is not provider specific. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 artid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the artwork being requested. The standard artwork IDs are shown below. Network providers can define their own IDs, above 0x80000000, for artwork that is specific to the provider. +\par \pard\plain \s16\widctlpar \f4 +\par \trowd \trgaph108\trleft612 \cellx4230\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4230\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_ART_BACKGROUND\cell The background bitmap for the dialog.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4230\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_ART_BUTTONTEXTURE\cell +The texture which is tiled over buttons in the dialog.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 palette +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to an array of palette entries, to be filled in by the function. This parameter can be NULL if the provider doesn\rquote t need to load a palette. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 buffer +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a buffer where the function should copy the bitmap data. This parameter can be NULL if the provider doesn\rquote t need the bitmap data, or if it is only querying the bitmap dimensions. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 buffersize +\par \pard\plain \s19\li720\widctlpar \f4 The size of the buffer pointed to by {\i buffer}. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 width +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a variable which the function should fill in with the width of the bitmap. This parameter can be NULL if the provider doesn\rquote t need the bitmap width. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 height +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a variable which the function should fill in with the height of the bitmap. This parameter can be NULL if the provider doesn\rquote t need the bitmap height. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 bitdepth +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a variable which the function should fill in with the number of bits per pixel in the bitmap. This parameter can be NULL if the provider doesn\rquote t need the bitmap pixel depth. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function should return TRUE if the picture was successfully loaded, or FALSE if an error occurred. +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/GETDAT~1.RTF b/src/Storm/DOCS/GETDAT~1.RTF new file mode 100644 index 0000000..3600552 --- /dev/null +++ b/src/Storm/DOCS/GETDAT~1.RTF @@ -0,0 +1,44 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo11\dy22\hr18\min12}{\version3} +{\edmins6}{\nofpages1}{\nofwords172}{\nofchars981}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} GetDataProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} GetDataProc}K{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} GetDataProc}} GetDataProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i GetDataProc() is a placeholder for an application-defined function name.} +\par +\par This function can be called by a network provider to get data other than artwork from the current application. To get artwork, a network provider calls GetArtProc(). +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK GetDataProc ( +\par \tab DWORD\tab \tab \tab providerid, +\par \tab DWORD\tab \tab \tab dataid, +\par \tab LPVOID\tab \tab buffer, +\par \tab DWORD\tab \tab \tab buffersize, +\par \tab DWORD\tab \tab \tab *bytesused +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 providerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the network provider which is requesting the artwork. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 dataid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the data item being requested. There are no predefined IDs. Network providers can define their own IDs, above 0x80000000, for data that is specific to the provider. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 buffer +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a buffer where the function should copy the data. This parameter can be NULL if the provider is only querying the data size. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 buffersize +\par \pard\plain \s19\li720\widctlpar \f4 The size of the buffer pointed to by {\i buffer}. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 bytesused +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a variable which the function should fill in with the number of bytes written to the buffer. If the buffer is NULL, the function should fill in the total number of bytes in the data item. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function should return TRUE if the data ID is valid and can be provided, or FALSE otherwise. +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/MESSAG~1.RTF b/src/Storm/DOCS/MESSAG~1.RTF new file mode 100644 index 0000000..5dd52d2 --- /dev/null +++ b/src/Storm/DOCS/MESSAG~1.RTF @@ -0,0 +1,59 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy21\hr11\min40}{\version5} +{\edmins11}{\nofpages2}{\nofwords255}{\nofchars1458}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} MessageBoxProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} MessageBoxProc}K{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} MessageBoxProc}} MessageBoxProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i MessageBoxProc() is a placeholder for an application-defined function name.} +\par +\par \pard \s16\widctlpar This function is called by Storm or the current network provider when it needs to display a message box. +\par \pard \s16\widctlpar +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK MessageBoxProc ( +\par \tab HWND\tab \tab parentwindow, +\par \tab LPCSTR\tab text, +\par \tab LPCSTR\tab caption, +\par \tab UINT\tab \tab type +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 parentwindow +\par \pard\plain \s19\li720\widctlpar \f4 A handle to the window that the message box should use as its parent. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 text +\par \pard\plain \s19\li720\widctlpar \f4 The text of the message. The procedure should dynamically scale the message box in order to fit the entire text. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 caption +\par \pard\plain \s19\li720\widctlpar \f4 The caption, which should be used as the title of the message box window. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 type +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags which indicate the type of the message box. The following constants are allowed: +\par \pard\plain \s16\widctlpar \f4 +\par \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell \pard \s19\widctlpar\intbl {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain +\s19\widctlpar\intbl \f4 MB_OK\cell The message box contains one push button: OK. This is the default.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 MB_OKCANCEL\cell The message box contains tw +o push buttons: OK and Cancel.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 MB_RETRYCANCEL\cell The message box contains two push buttons: Retry and Cancel.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row +\pard\plain \s19\widctlpar\intbl \f4 MB_YESNO\cell The message box contains two push buttons: Yes and No.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 MB_YESNOCANCEL\cell +The message box contains three push buttons: Yes, No, and Cancel.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 MB_DEFBUTTON1\cell \pard \s19\widctlpar\intbl +The first button is the default button. This is the default.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 MB_DEFBUTTON2\cell The second button is the default button.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row +\trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 MB_DEFBUTTON3\cell \pard \s19\widctlpar\intbl The third button is the default button.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 + +\par \pard\plain \s20\widctlpar \i\f4 flags +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags specifying how the sound should be played. Use the SND_* constants defined in Windows.h. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par \pard \s16\widctlpar The return value is FALSE if the procedure is not able to display the message box. +\par +\par Otherwise, the return value is one of the following item values returned by the dialog box: +\par +\par \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 IDOK\cell The OK button was selected.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl +\f4 IDCANCEL\cell The Cancel button was selected.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 IDYES\cell The Yes button was selected.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain +\s19\widctlpar\intbl \f4 IDNO\cell The No button was selected.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 IDRETRY\cell \pard \s19\widctlpar\intbl +The Retry button was selected.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard \s16\widctlpar +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/PLAYSO~1.RTF b/src/Storm/DOCS/PLAYSO~1.RTF new file mode 100644 index 0000000..10aa335 --- /dev/null +++ b/src/Storm/DOCS/PLAYSO~1.RTF @@ -0,0 +1,40 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy21\hr11\min30}{\version3} +{\edmins5}{\nofpages1}{\nofwords145}{\nofchars829}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} PlaySoundProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} PlaySoundProc}K{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} PlaySoundProc}} PlaySoundProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i PlaySoundProc() is a placeholder for an application-defined function name.} +\par +\par This function is called by Storm or the current network provider when it needs to play a sound effect. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK PlaySoundProc ( +\par \tab DWORD\tab \tab providerid, +\par \tab DWORD\tab \tab soundid, +\par \tab DWORD\tab \tab flags +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 providerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the network provider which is making the request. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 soundid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the requested sound effect. The standard IDs are shown below. Network providers can define their own IDs, above 0x80000000, for sound effects that are specific to the provider. +\par \pard\plain \s16\widctlpar \f4 +\par \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_SND_CHANGEFOCUS\cell A sound to indicate that the user has changed to focus to a new menu or list-box item.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_SND_SELECTITEM\cell A sound to indicate that the user has selected the current item.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 flags +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags specifying how the sound should be played. Use the SND_* constants defined in Windows.h. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function should return TRUE if the sound was successfully played, or FALSE if an error occurred. +\par +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETCAPS.RTF b/src/Storm/DOCS/SNETCAPS.RTF new file mode 100644 index 0000000..6539a3f --- /dev/null +++ b/src/Storm/DOCS/SNETCAPS.RTF @@ -0,0 +1,54 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo11\dy13\hr23\min45}{\version2} +{\edmins1}{\nofpages2}{\nofwords185}{\nofchars1060}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNETCAPS}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNETCAPS}K{\footnote \pard\plain +\s21\widctlpar \f4\fs20 {\cs22\super K} SNETCAPS}} SNETCAPS +\par \pard\plain \s16\widctlpar \f4 +\par The SNETCAPS structure contains capabilities for a network provider or a player. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 typedef struct _SNETCAPS \{ +\par \tab DWORD\tab \tab size; +\par \tab DWORD\tab \tab flags; +\par \tab DWORD\tab \tab maxmessagesize; +\par \tab DWORD\tab \tab maxqueuesize; +\par \tab DWORD\tab \tab maxplayers; +\par \tab DWORD\tab \tab bytessec; +\par \tab DWORD\tab \tab latencyms; +\par \tab DWORD\tab \tab defaultturnssec; +\par \tab DWORD\tab \tab defaultturnsintransit; +\par \} SNETCAPS, *SNETCAPSPTR; +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Members +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 size +\par \pard\plain \s19\li720\widctlpar \f4 The size of the structure, in bytes. Must be filled in by the application. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 flags +\par \pard\plain \s19\li720\widctlpar \f4 Network capability flags. No flags are currently defined. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 maxmessagesize +\par \pard\plain \s19\li720\widctlpar \f4 The maximum size, in bytes, of a message or turn that can be sent using this network provider. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 maxqueuesize +\par \pard\plain \s19\li720\widctlpar \f4 The maximum size of the outgoing message queue. This field is only meaningful if the network provider makes use of Microsoft DirectPlay. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 maxplayers +\par \pard\plain \s19\li720\widctlpar \f4 The maximum number of players supported by this network provider. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 bytessec +\par \pard\plain \s19\li720\widctlpar \f4 The expected bandwidth of the communications medium, expressed in bytes per second. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 latencyms +\par \pard\plain \s19\li720\widctlpar \f4 The expected latency of the communications medium, expressed as the number of milliseconds for a round-trip transmission. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 defaultturnssec +\par \pard\plain \s19\li720\widctlpar \f4 The recommended number of turns per second for this network provider. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 defaultturnsintransit +\par \pard\plain \s19\li720\widctlpar \f4 The recommended number of turns that the application should maintain in transit when using this network provider. +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETCR~1.RTF b/src/Storm/DOCS/SNETCR~1.RTF new file mode 100644 index 0000000..e3e7bbe --- /dev/null +++ b/src/Storm/DOCS/SNETCR~1.RTF @@ -0,0 +1,37 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy21\hr16\min49}{\version2} +{\edmins0}{\nofpages1}{\nofwords126}{\nofchars719}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNETCREATEDATA}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNETCREATEDATA}K{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNETCREATEDATA}} SNETCREATEDATA +\par \pard\plain \s16\widctlpar \f4 +\par The SNETCREATEDATA structure is used in the create game callback function to communicate information about the current provider\rquote s abilities. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 typedef struct _SNETCREATEDATA \{ +\par \tab DWORD\tab \tab size; +\par \tab DWORD\tab \tab providerid; +\par \tab DWORD\tab \tab maxplayers; +\par \tab DWORD\tab \tab createflags; +\par \} SNETCREATEDATA, *SNETCREATEDATAPTR; +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Members +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 size +\par \pard\plain \s19\li720\widctlpar \f4 The size of the structure, in bytes. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 providerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the currently selected provider. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 maxplayers +\par \pard\plain \s19\li720\widctlpar \f4 The maximum number of players that can join the game. This value is the minimum of the maximum number of players the application supports and the maximum number of players the provider supports. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 createflags +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags specifying what creation options are available. The following flags are defined: +\par +\par \trowd \trgaph108\trleft612 \cellx4680\cellx7812 \pard \s19\widctlpar\intbl {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4680\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_CF_ALLOWPRIVATEGAMES\cell The creation callback function should allow the user the opportunity to create a private game.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETCR~2.RTF b/src/Storm/DOCS/SNETCR~2.RTF new file mode 100644 index 0000000..0463103 --- /dev/null +++ b/src/Storm/DOCS/SNETCR~2.RTF @@ -0,0 +1,85 @@ +{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;} +{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f19\froman\fcharset161\fprq2 Times New Roman Greek;} +{\f20\froman\fcharset162\fprq2 Times New Roman Tur;}{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f28\fmodern\fcharset238\fprq1 Courier New CE;}{\f29\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f31\fmodern\fcharset161\fprq1 Courier New Greek;} +{\f32\fmodern\fcharset162\fprq1 Courier New Tur;}{\f33\fmodern\fcharset186\fprq1 Courier New Baltic;}}{\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\widctlpar\adjustright \fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\nowidctlpar\widctlpar\adjustright \b\fs40 \sbasedon0 \snext16 API Title;}{\s16\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 +API Description;}{\s17\nowidctlpar\widctlpar\adjustright \f2\fs22 \sbasedon0 \snext17 API Function;}{\s18\nowidctlpar\widctlpar\adjustright \b \sbasedon0 \snext16 API Section;}{\s19\li720\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 +API Parameter Description;}{\s20\nowidctlpar\widctlpar\adjustright \i \sbasedon0 \snext19 API Parameter Name;}{\s21\nowidctlpar\widctlpar\adjustright \fs20 \sbasedon0 \snext21 footnote text;}{\*\cs22 \additive \super \sbasedon10 footnote reference;}} +{\*\listtable{\list\listtemplateid-1\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\'01*;}{\levelnumbers;}}{\listname ;}\listid-2}}{\*\listoverridetable{\listoverride\listid-2 +\listoverridecount1{\lfolevel\listoverrideformat{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelold\levelspace0\levelindent360{\leveltext\'01\u-3913 ?;}{\levelnumbers;}\f3\fbias0 \fi-360\li360 }}\ls1}}{\info{\title SNetCreateGame} +{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1997\mo3\dy21\hr16\min55}{\version3}{\edmins5}{\nofpages2}{\nofwords409}{\nofchars2332}{\*\company Blizzard Entertainment}{\nofcharsws0}{\vern71}} +\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade\viewkind1\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 +\s15\keepn\nowidctlpar\widctlpar\adjustright \b\fs40 {\cs22\super ${\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super $}{ SNetCreateGame}}#{\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super #}{ + SNetCreateGame}}K{\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super K}{ SNetCreateGame}}}{ SNetCreateGame +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par Creates a new network game using the currently selected network provider, and adds the local player as the game master. The game master is always player number one. +\par +\par Rather than calling this function manually, an application will generally call SNetSelectGame() to present the user with a list of games and allow him to join a game or create a new one. +\par +\par }\pard\plain \s17\nowidctlpar\widctlpar\adjustright \f2\fs22 {BOOL SNetCreateGame ( +\par \tab LPCSTR\tab gamename, +\par \tab LPCSTR\tab gamepassword, +\par \tab LPCSTR\tab gamedescription, +\par \tab DWORD\tab \tab gamecategorybits, +\par \tab LPVOID\tab initdata, +\par \tab DWORD\tab \tab initdatabytes, +\par \tab DWORD\tab \tab maxplayers, +\par \tab LPCSTR\tab playername, +\par \tab LPCSTR\tab playerdescription, +\par \tab DWORD\tab \tab *playerid +\par ); +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s18\nowidctlpar\widctlpar\adjustright \b {Parameters +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {gamename +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The name of the game being created, as specified by the player. For example, \ldblquote Bob\rquote s Game\rdblquote . +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {gamepassword +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A password for the game. If the password is not blank, then the game + is considered private. It does not show up on lists of games, and players cannot join the game without knowing the password. Passwords are not case sensitive. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {gamedescription +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A description of the game. This can be generated by the program, and cont +ain information about the game options. On joining systems, the options strings may be simply displayed as text, or may be decoded by the game into a graphical or iconic representation of game options, such as whether fog of war is in effect. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {gamecategorybits +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A set of bits describing the categories to which this game belongs. Other systems can either enumerate all games, or enumerate only games which belong to certain categories. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {initdata +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A +pointer to application-specific initialization data. This data is sent to all joining players. The application receives it on the joining side through the SNET_EVENT_INITDATA callback, which it is guaranteed to get on its first call to SNetReceiveMessag +e() or SNetReceiveTurns() after joining. The maximum size of the initialization data is equal to the maximum message size for the current network provider. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {initdatabytes +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The number of bytes in the application-specific initialization data. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {maxplayers +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The +maximum number of players which will be allowed to join this game. This number must be less than or equal to the maximum number of players that was set during the call to SNetInitializeProvider(). +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {playername +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The name of the local player. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {playerdescription +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A description of the local player. This can be generated by the program, and contain information such as the player\rquote +s character class or level. On joining systems, it may be decoded into a graphical or iconic representation of the player. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {playerid +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The ID that is assigned to the player, if creating the game is successful. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s18\nowidctlpar\widctlpar\adjustright \b {Return Value +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \s16\fi-360\li360\nowidctlpar\widctlpar{\*\pn \pnlvlblt\ilvl0\ls1\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls1\adjustright {No network provider has been initialized + +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}No game name or description is specified +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}The maximum number of players is out of range +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}No player name or description is specified +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}No variable is given to receive the player ID +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}The system is out of memory +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}The network provider uses a server, and the server is unable to process the request +\par }\pard\plain \nowidctlpar\widctlpar\adjustright \fs20 { +\par }} diff --git a/src/Storm/DOCS/SNETDE~1.RTF b/src/Storm/DOCS/SNETDE~1.RTF new file mode 100644 index 0000000..ddd09ca --- /dev/null +++ b/src/Storm/DOCS/SNETDE~1.RTF @@ -0,0 +1,25 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\widctlpar \f4\fs20 \sbasedon0\snext19 footnote text;}{\*\cs20 \additive\super \sbasedon10 +footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min19}{\revtim\yr1996\mo10\dy3\hr15\min6}{\version2}{\edmins0}{\nofpages1}{\nofwords53}{\nofchars307}{\*\company Blizzard Entertainment}{\vern57431}} +\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs20\super ${\footnote \pard\plain +\s19\widctlpar \f4\fs20 {\cs20\super $} SNetDestroy}#{\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super #} SNetDestroy}K{\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super K} SNetDestroy}} SNetDestroy +\par \pard\plain \s16\widctlpar \f4 +\par Closes all active games, uninitializes the network provider, and frees all memory used by this module. +\par +\par Normally, a program should call StormDestroy() once at the end of the program, rather than calling the individual destroy functions. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetDestroy (); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par None. +\par +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}This function returns TRUE for success or FALSE for failure. +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETEN~1.RTF b/src/Storm/DOCS/SNETEN~1.RTF new file mode 100644 index 0000000..94bba38 --- /dev/null +++ b/src/Storm/DOCS/SNETEN~1.RTF @@ -0,0 +1,60 @@ +{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;} +{\f3\froman\fcharset2\fprq2{\*\panose 05050102010706020507}Symbol;}{\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f19\froman\fcharset161\fprq2 Times New Roman Greek;} +{\f20\froman\fcharset162\fprq2 Times New Roman Tur;}{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f28\fmodern\fcharset238\fprq1 Courier New CE;}{\f29\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f31\fmodern\fcharset161\fprq1 Courier New Greek;} +{\f32\fmodern\fcharset162\fprq1 Courier New Tur;}{\f33\fmodern\fcharset186\fprq1 Courier New Baltic;}}{\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\widctlpar\adjustright \fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\nowidctlpar\widctlpar\adjustright \b\fs40 \sbasedon0 \snext16 API Title;}{\s16\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 +API Description;}{\s17\nowidctlpar\widctlpar\adjustright \f2\fs22 \sbasedon0 \snext17 API Function;}{\s18\nowidctlpar\widctlpar\adjustright \b \sbasedon0 \snext16 API Section;}{\s19\li720\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 +API Parameter Description;}{\s20\nowidctlpar\widctlpar\adjustright \i \sbasedon0 \snext19 API Parameter Name;}{\s21\li720\nowidctlpar\widctlpar\adjustright \f2 \sbasedon19 \snext21 API Callback;}{\s22\nowidctlpar\widctlpar\adjustright \fs20 +\sbasedon0 \snext22 footnote text;}{\*\cs23 \additive \super \sbasedon10 footnote reference;}}{\*\listtable{\list\listtemplateid-1\listsimple{\listlevel\levelnfc0\leveljc0\levelfollow0\levelstartat0\levelspace0\levelindent0{\leveltext\'01*;}{\levelnumbers +;}}{\listname ;}\listid-2}}{\*\listoverridetable{\listoverride\listid-2\listoverridecount1{\lfolevel\listoverrideformat{\listlevel\levelnfc23\leveljc0\levelfollow0\levelstartat1\levelold\levelspace0\levelindent360{\leveltext\'01\u-3913 ?;}{\levelnumbers;} +\f3\fbias0 \fi-360\li360 }}\ls1}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min19}{\revtim\yr1997\mo3\dy21\hr17}{\version3}{\edmins5}{\nofpages2}{\nofwords256}{\nofchars1462}{\*\company Blizzard Entertainment} +{\nofcharsws1795}{\vern71}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade\viewkind1\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 +\s15\keepn\nowidctlpar\widctlpar\adjustright \b\fs40 {\cs23\super ${\footnote \pard\plain \s22\nowidctlpar\widctlpar\adjustright \fs20 {\cs23\super $}{ SNetEnumGames}}#{\footnote \pard\plain \s22\nowidctlpar\widctlpar\adjustright \fs20 {\cs23\super #}{ + SNetEnumGames}}K{\footnote \pard\plain \s22\nowidctlpar\widctlpar\adjustright \fs20 {\cs23\super K}{ SNetEnumGames}}}{ SNetEnumGames +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par Enumerates all games available on the current network provider which match the program and version IDs. The callback function you provide is called once for each matching game. +\par +\par Some network providers can take a significant amount of time to find all active games (for example, one second). Instead of blocking for this duration, the function returns only the games it current +ly knows about, and then gives you a hint about when you should call it back to receive a more complete list. +\par +\par Rather than calling this function manually, an application will generally call SNetSelectGame() to present the user with a list of games and allow him to join a game or create a new one. +\par +\par }\pard\plain \s17\nowidctlpar\widctlpar\adjustright \f2\fs22 {BOOL SNetEnumGames ( +\par \tab DWORD\tab \tab \tab \tab categorybits, +\par \tab DWORD\tab \tab \tab \tab categorymask, +\par \tab SNETENUMGAMESPROC\tab callback, +\par \tab DWORD\tab \tab \tab \tab *hintnextcall +\par ); +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s18\nowidctlpar\widctlpar\adjustright \b {Parameters +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {categorybits +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A set of bits that specify which categories of games the application is interested in enumerating. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {categorymask +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A mask specifying which categories must match in order for a game to be enumerated. The following logical statement shows how }{\i categorybits}{ and }{\i categorymask}{ are used to select games: + +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard \s16\li1440\nowidctlpar\widctlpar\adjustright {if (categorybits AND categorymask) +\par equals (gamecategorybits AND categorymask) +\par then enumerate game +\par }\pard \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {callback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The application\rquote s callback function. See EnumGamesProc() for a description. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {hintnextcall +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The time that the application should wait before calling this function again, in milliseconds. If this number is zero, there is no need to call the function again. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s18\nowidctlpar\widctlpar\adjustright \b {Return Value +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}}\pard \s16\fi-360\li360\nowidctlpar\widctlpar{\*\pn \pnlvlblt\ilvl0\ls1\pnrnot0\pnf3\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\ls1\adjustright {No network provider has been initialized + +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}No callback function is provided +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}The system is out of memory +\par {\pntext\pard\plain\s16 \f3 \loch\af3\dbch\af0\hich\f3 \'b7\tab}The network provider is unable to retrieve a list of games +\par }\pard\plain \nowidctlpar\widctlpar\adjustright \fs20 { +\par }} \ No newline at end of file diff --git a/src/Storm/DOCS/SNETEN~2.RTF b/src/Storm/DOCS/SNETEN~2.RTF new file mode 100644 index 0000000..6bd2d7e --- /dev/null +++ b/src/Storm/DOCS/SNETEN~2.RTF @@ -0,0 +1,40 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\li720\widctlpar \f11 \sbasedon19\snext21 API Callback;}{\s22\widctlpar \f4\fs20 \sbasedon0\snext22 footnote text;}{\*\cs23 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien} +{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min19}{\revtim\yr1996\mo10\dy3\hr19\min16}{\version2}{\edmins1}{\nofpages1}{\nofwords178}{\nofchars1020}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade +\fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs23\super ${\footnote \pard\plain \s22\widctlpar +\f4\fs20 {\cs23\super $} SNetEnumProviders}#{\footnote \pard\plain \s22\widctlpar \f4\fs20 {\cs23\super #} SNetEnumProviders}K{\footnote \pard\plain \s22\widctlpar \f4\fs20 {\cs23\super K} SNetEnumProviders}} SNetEnumProviders +\par \pard\plain \s16\widctlpar \f4 +\par Enumerates all network providers installed on the system. The callback function you provide is called once for each provider. If desired, you can specify a minimum set of capabilities, and only providers which meet or exceed those capabilities will be r +eturned. +\par +\par Rather than calling this function manually, an application will generally call SNetSelectProvider() to present the user with a list of network providers and allow him to select and initialize one. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetEnumProviders ( +\par \tab SNETCAPSPTR\tab \tab \tab mincaps, +\par \tab SNETENUMPROVIDERSPROC\tab \tab callback +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 mincaps +\par \pard\plain \s19\li720\widctlpar \f4 +A pointer to an SNETCAPS structure specifying the minimum capabilities required of network providers. The size field must be filled in which the size of the structure. Any other field can contain a number to specify a minimum capability, or zero to spec +ify that the field should be ignored. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s19\li720\widctlpar \f4 If the mincaps parameter is NULL, all network providers are enumerated. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 callback +\par \pard\plain \s19\li720\widctlpar \f4 The application\rquote s callback function. See EnumProvidersProc() for a description. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No callback function is provided +\par {\pntext\pard\plain\f1 \'b7\tab}The size field of the SNETCAPS structure is invalid +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETGE~1.RTF b/src/Storm/DOCS/SNETGE~1.RTF new file mode 100644 index 0000000..bfb23ef --- /dev/null +++ b/src/Storm/DOCS/SNETGE~1.RTF @@ -0,0 +1,40 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min20} +{\revtim\yr1996\mo11\dy13\hr23\min45}{\version2}{\edmins0}{\nofpages2}{\nofwords202}{\nofchars1152}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetGetNetworkLatency}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetGetNetworkLatency}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetGetNetworkLatency}} SNetGetNetworkLatency +\par \pard\plain \s16\widctlpar \f4 +\par Returns the expected or measured round-trip latency. This is twice the approximate time, in milliseconds, that a message sent from one computer will take to reach another computer. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetGetNetworkLatency ( +\par \tab DWORD\tab \tab measurementtype, +\par \tab DWORD\tab \tab *result +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 measurementtype +\par \pard\plain \s19\li720\widctlpar \f4 An identifier specifying the way in which the latency should be measured. +\par \pard\plain \s16\widctlpar \f4 +\par \trowd \trgaph108\trleft612 \cellx3492\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3492\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_LMT_EXPECTED\cell The expected latency for this network provider. This value is always the same for any given network provider.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_LMT_CURRENT\cell +The current latency of the game. This computer must currently be joined in a game. The latency returned is the highest latency between this computer and any of the other players.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd +\trgaph108\trleft612 \cellx3492\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_LMT_PEAK\cell The peak latency of the game. This computer must currently be joined in a game. The latency returned is the highest measured latency between this computer + and any of the other players since the beginning of the game, or since the last call to SNetResetLatencyMeasurements().\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\li720\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 result +\par \pard\plain \s19\li720\widctlpar \f4 The returned latency. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}The measurement type identifier is invalid +\par {\pntext\pard\plain\f1 \'b7\tab}The measurement type calls for a measured rather than expected latency, and no game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}No variable is provided to receive the result +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETGE~2.RTF b/src/Storm/DOCS/SNETGE~2.RTF new file mode 100644 index 0000000..3ca1c40 --- /dev/null +++ b/src/Storm/DOCS/SNETGE~2.RTF @@ -0,0 +1,37 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min20} +{\revtim\yr1996\mo10\dy3\hr15\min7}{\version2}{\edmins0}{\nofpages1}{\nofwords98}{\nofchars559}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetGetNumPlayers}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetGetNumPlayers}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetGetNumPlayers}} SNetGetNumPlayers +\par \pard\plain \s16\widctlpar \f4 +\par Returns the number of active players in the game, and the range of active player IDs. The range of IDs may be larger than the number of active players if players have dropped out of the game. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetGetNumPlayers ( +\par \tab DWORD\tab \tab *firstplayerid, +\par \tab DWORD\tab \tab *lastplayerid, +\par \tab DWORD\tab \tab *activeplayers +\par \}; +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 firstplayerid +\par \pard\plain \s19\li720\widctlpar \f4 The lowest numbered ID of any active player. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 lastplayerid +\par \pard\plain \s19\li720\widctlpar \f4 The highest numbered ID of any active player. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 activeplayers +\par \pard\plain \s19\li720\widctlpar \f4 The total number of active players. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETGE~3.RTF b/src/Storm/DOCS/SNETGE~3.RTF new file mode 100644 index 0000000..3e3236e --- /dev/null +++ b/src/Storm/DOCS/SNETGE~3.RTF @@ -0,0 +1,35 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min20} +{\revtim\yr1996\mo10\dy3\hr15\min7}{\version2}{\edmins0}{\nofpages1}{\nofwords103}{\nofchars588}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetGetPlayerCaps}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetGetPlayerCaps}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetGetPlayerCaps}} SNetGetPlayerCaps +\par \pard\plain \s16\widctlpar \f4 +\par Returns the capabilities of an individual player. You can use this function to get the latency between this machine and any other player in the game. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetGetPlayerCaps ( +\par \tab DWORD\tab \tab \tab playerid, +\par \tab SNETCAPSPTR\tab caps +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the player for which capabilities will be returned. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 caps +\par \pard\plain \s19\li720\widctlpar \f4 An SNETCAPS structure. You must fill in the size field before passing this structure to SNetGetPlayerCaps(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}No active player exists with the given ID +\par {\pntext\pard\plain\f1 \'b7\tab}The size field of the SNETCAPS structure is invalid +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETGE~4.RTF b/src/Storm/DOCS/SNETGE~4.RTF new file mode 100644 index 0000000..32bf088 --- /dev/null +++ b/src/Storm/DOCS/SNETGE~4.RTF @@ -0,0 +1,40 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min21} +{\revtim\yr1996\mo10\dy3\hr15\min7}{\version2}{\edmins0}{\nofpages1}{\nofwords87}{\nofchars500}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetGetPlayerName}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetGetPlayerName}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetGetPlayerName}} SNetGetPlayerName +\par \pard\plain \s16\widctlpar \f4 +\par Returns the name of any player in the game. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetGetPlayerName ( +\par \tab DWORD\tab \tab playerid, +\par \tab LPSTR\tab \tab buffer, +\par \tab DWORD\tab \tab buffersize +\par ); +\par +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the player whose name is being requested. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 buffer +\par \pard\plain \s19\li720\widctlpar \f4 A string buffer into which the name will be copied. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 buffersize +\par \pard\plain \s19\li720\widctlpar \f4 The size, in characters, of the buffer. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}No active player exists with the given ID +\par {\pntext\pard\plain\f1 \'b7\tab}No buffer is given +\par {\pntext\pard\plain\f1 \'b7\tab}The size of the buffer is zero +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETGE~5.RTF b/src/Storm/DOCS/SNETGE~5.RTF new file mode 100644 index 0000000..89a4b34 --- /dev/null +++ b/src/Storm/DOCS/SNETGE~5.RTF @@ -0,0 +1,29 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min20} +{\revtim\yr1996\mo10\dy3\hr19\min18}{\version2}{\edmins0}{\nofpages1}{\nofwords67}{\nofchars387}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetGetProviderCaps}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetGetProviderCaps}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetGetProviderCaps}} SNetGetProviderCaps +\par \pard\plain \s16\widctlpar \f4 +\par Returns the capabilities of the currently selected network provider. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetGetProviderCaps ( +\par \tab SNETCAPSPTR\tab caps +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 caps +\par \pard\plain \s19\li720\widctlpar \f4 An SNETCAPS structure. You must fill in the size field before passing this structure to SNetGetProviderCaps(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}The size field of the SNETCAPS structure is invalid +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETGE~6.RTF b/src/Storm/DOCS/SNETGE~6.RTF new file mode 100644 index 0000000..cb372a4 --- /dev/null +++ b/src/Storm/DOCS/SNETGE~6.RTF @@ -0,0 +1,45 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min21} +{\revtim\yr1996\mo10\dy3\hr15\min8}{\version2}{\edmins1}{\nofpages2}{\nofwords292}{\nofchars1667}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetGetTurnsInTransit}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetGetTurnsInTransit}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetGetTurnsInTransit}} SNetGetTurnsInTransit +\par \pard\plain \s16\widctlpar \f4 +\par Returns the number of turns which have been from this machine with SNetSendTurn() but not yet received with SNetReceiveTurns(). It is generally a good idea to keep two or more turns in transit (on the wire) so that other machines can process turns withou +t having to wait for them to be transmitted. +\par +\par For example, if a game runs at the rate of two turns per second, and for each turn it simply sends its turn and then waits for turns from all other players to arrive, then the game speed may be cut in half when running on a high-latency network such as th +e Internet. This is because at least a quarter of a second will be wasted for every turn waiting for turns to arrive from other players. +\par +\par However, if the game is modified so that it always sends out turns two in advance of what it is processing (sending tu +rn 3 and then processing all turns for turn 1, sending turn 4 and then processing all turns for turn 2, etc.) then the turns will have plenty of time for transmission, so no game delay will be required. +\par +\par The two primary ways to compensate for latency in a turn-based game are: +\par {\pntext\pard\plain 1. \tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlbody\pndec\pnb0\pni0\pnf4\pnfs24\pnstart1\pnindent360\pnhang{\pntxta . }}Decrease the number of turns processed per second, or +\par {\pntext\pard\plain 2. \tab}Increase the number of turns in transit. +\par \pard \s16\widctlpar +\par Since decreasing the number of turns processed per second compensates not only for latency problems but also bandwidth problems, +it is probably best to fix the number of turns in transit at two and then adjust the number of turns per second. You can get a recommendation for the number of turns per second from the network provider\rquote +s capabilities, returned during SNetEnumerateProviders(). +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetGetTurnsInTransit ( +\par \tab DWORD\tab \tab *turns +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 turns +\par \pard\plain \s19\li720\widctlpar \f4 The number of turns that have been sent from this computer with SNetSendTurn() but not yet received with SNetReceiveTurns(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}No variable is provided to receive the result +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETIN~1.RTF b/src/Storm/DOCS/SNETIN~1.RTF new file mode 100644 index 0000000..cb5a126 --- /dev/null +++ b/src/Storm/DOCS/SNETIN~1.RTF @@ -0,0 +1,60 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min21} +{\revtim\yr1996\mo10\dy3\hr19\min16}{\version2}{\edmins0}{\nofpages2}{\nofwords438}{\nofchars2502}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetInitializeProvider}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetInitializeProvider}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetInitializeProvider}} SNetInitializeProvider +\par \pard\plain \s16\widctlpar \f4 +\par Initializes the given network provider, which will provide support for all further SNet calls. +\par +\par Some providers can take a second or more to initialize, especially if initialization involves connecting to a server. +\par +\par Rather than calling this function manually, an application will generally call SNetSelectProvider() to present the user with a list of network providers and allow him to select and initialize one. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetInitializeProvider ( +\par \tab DWORD\tab \tab \tab \tab providerid, +\par \tab SNETPROGRAMDATAPTR\tab programdata, +\par \tab SNETPLAYERDATAPTR\tab playerdata, +\par \tab SNETUIDATAPTR\tab \tab interfacedata, +\par \tab SNETVERSIONDATAPTR\tab versiondata +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 providerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the provider to be initialized. This is obtained from a call to SNetEnumerateProviders(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s19\li720\widctlpar \f4 You can also specify zero to use the null provider. The null provider is used just l +ike any other provider, but it does not make use of any communications medium. It is provided so that single player games can use the same code as multi-player games. To create a single player game using the null provider, first initialize the provider, + then create a game using SNetCreateGame(), then send messages and turns using the SNet functions as normal. At the end of the game, call SNetLeaveGame(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 programdata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing information about the program, such as the program name, version, and number of players supported. This is a mandatory parameter. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerdata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing the name and description of the current player. The provider may use this information if it performs a matchmaking process. This is a mandatory parameter. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 interfacedata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing information about how the network provider should display user interface screens if necessary. Most network providers will fail if this information is not given. For example, +the modem provider cannot query the user for a phone number to dial without the ability to display user interface screens. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 versiondata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing information about the application which is necessary for automatic version control. Some network providers are capable of performing over-the-wire version updates. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}The program data is missing or invalid. +\par {\pntext\pard\plain\f1 \'b7\tab}The player data is missing or invalid. +\par {\pntext\pard\plain\f1 \'b7\tab}The interface data is missing or invalid, and the provider needs to display user interface in order to initialize itself. +\par {\pntext\pard\plain\f1 \'b7\tab}The system is out of memory or resources +\par {\pntext\pard\plain\f1 \'b7\tab}The network provider was unable to initialize itself. For example, the IPX provider may fail if IPX support is not available, and the Battle.net provider may fail if it cannot contact any Battle.net servers. +\par {\pntext\pard\plain\f1 \'b7\tab}The application needs to be upgraded before it can connect to the server. +\par \pard \s16\widctlpar +\par If this function fails, the application should call GetLastError() to determine the reason for failure. If GetLastError() returns SNET_ERROR_REQUIRES_UPGRADE, the application should call SNetPerformUpgrade(). +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETJO~1.RTF b/src/Storm/DOCS/SNETJO~1.RTF new file mode 100644 index 0000000..2e91d01 --- /dev/null +++ b/src/Storm/DOCS/SNETJO~1.RTF @@ -0,0 +1,56 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min21} +{\revtim\yr1996\mo10\dy3\hr19\min14}{\version2}{\edmins0}{\nofpages2}{\nofwords232}{\nofchars1328}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetJoinGame}#{\footnote \pard\plain +\s21\widctlpar \f4\fs20 {\cs22\super #} SNetJoinGame}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetJoinGame}} SNetJoinGame +\par \pard\plain \s16\widctlpar \f4 +\par Joins an existing game. Rather than calling this function manually, an application will generally call SNetSelectGame() to present the user with a list of games and allow him to join a game or create a new one. +\par +\par To leave a game after joining, call SNetLeaveGame(). +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetJoinGame ( +\par \tab DWORD\tab \tab \tab gameid, +\par \tab LPCSTR\tab \tab gamename, +\par \tab LPCSTR\tab \tab gamepassword, +\par \tab LPCSTR\tab \tab playername, +\par \tab LPCSTR\tab \tab playerdescription, +\par \tab DWORD\tab \tab \tab *playerid +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 gameid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the game to be joined. You can discover IDs of active games using SNetEnumGames(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 gamename +\par \pard\plain \s19\li720\widctlpar \f4 The name of the game to be joined. By passing a name, you can join a game which was not enumerated, such as a private game. If {\i gameid} is not zero, this parameter is ignored. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 gamepassword +\par \pard\plain \s19\li720\widctlpar \f4 The password of the game to be joined. The function will fail if the password is incorrect. If the game to be joined is not password protected, simply pass a blank password. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playername +\par \pard\plain \s19\li720\widctlpar \f4 The name of the local player. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerdescription +\par \pard\plain \s19\li720\widctlpar \f4 A description of the local player. This can be generated by the program, and contain information such as the player\rquote s character class or level. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID that is assigned to the player, if joining is successful. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No player name or description is specified +\par {\pntext\pard\plain\f1 \'b7\tab}No variable is provided to receive the player ID +\par {\pntext\pard\plain\f1 \'b7\tab}The game owner cannot be contacted (possibly due to a firewall) +\par {\pntext\pard\plain\f1 \'b7\tab}The game password is incorrect +\par {\pntext\pard\plain\f1 \'b7\tab}The game is full or is closed to new players +\par {\pntext\pard\plain\f1 \'b7\tab}The system is out of memory +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETLE~1.RTF b/src/Storm/DOCS/SNETLE~1.RTF new file mode 100644 index 0000000..f84c8e7 --- /dev/null +++ b/src/Storm/DOCS/SNETLE~1.RTF @@ -0,0 +1,24 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\widctlpar \f4\fs20 \sbasedon0\snext19 footnote text;}{\*\cs20 \additive\super \sbasedon10 +footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min22}{\revtim\yr1996\mo10\dy3\hr15\min8}{\version2}{\edmins0}{\nofpages1}{\nofwords61}{\nofchars348}{\*\company Blizzard Entertainment}{\vern57431}} +\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs20\super ${\footnote \pard\plain +\s19\widctlpar \f4\fs20 {\cs20\super $} SNetLeaveGame}#{\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super #} SNetLeaveGame}K{\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super K} SNetLeaveGame}} SNetLeaveGame +\par \pard\plain \s16\widctlpar \f4 +\par Leaves the current game. If the local player created the game using SNetCreateGame(), and hasn\rquote t yet started the game, then leaving will destroy the game. Otherwise, the game will continue without the local player. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetLeaveGame(); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par None. +\par +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETPE~1.RTF b/src/Storm/DOCS/SNETPE~1.RTF new file mode 100644 index 0000000..408b84b --- /dev/null +++ b/src/Storm/DOCS/SNETPE~1.RTF @@ -0,0 +1,36 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien} +{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr19\min28}{\version2}{\edmins1}{\nofpages1}{\nofwords152}{\nofchars869}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd +\linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNet +PerformUpgrade}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetPerformUpgrade}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetPerformUpgrade}} SNetPerformUpgrade +\par \pard\plain \s16\widctlpar \f4 +\par Performs an automatic version update of the application. You should call this function is SNetSelectProvider() or SNetInitializeProvider() fails and GetLastError() returns SNET_ERROR_REQUIRES_UPGRADE. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetPerformUpgrade ( +\par \tab DWORD\tab \tab *upgradestatus +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 upgradestatus +\par \pard\plain \s19\li720\widctlpar \f4 Returns one of the following values, specifying whether the upgrade was successful: +\par +\par \trowd \trgaph108\trleft612 \cellx4500\cellx7812 \pard \s19\widctlpar\intbl {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4500\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_UPGRADE_FAILED\cell The upgrade failed or was canceled by the user.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_UPGRADE_NOT_NEEDED\cell No upgrade is needed.\cell \pard\plain \widctlpar\intbl \f4\fs20 +\row \pard\plain \s19\widctlpar\intbl \f4 SNET_UPGRADE_SUCCEEDED\cell The upgrade succeeded.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4500\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_UPGRADING_TERMINATE + +\par \pard\plain \s16\widctlpar\intbl \f4 \cell \pard\plain \s19\widctlpar\intbl \f4 The upgrade is currently in progress. The patch program needs the application to terminate so that it can modify the application\rquote +s EXE or DLL files. The patch program will restart the application after the upgrade is complete. \cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No variable was provided to receive the upgrade status +\par {\pntext\pard\plain\f1 \'b7\tab}The upgrade failed or was canceled by the user +\par {\pntext\pard\plain\f1 \'b7\tab}No upgrade was needed +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETPL~1.RTF b/src/Storm/DOCS/SNETPL~1.RTF new file mode 100644 index 0000000..4b350d6 --- /dev/null +++ b/src/Storm/DOCS/SNETPL~1.RTF @@ -0,0 +1,31 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr18\min2}{\version4} +{\edmins1}{\nofpages1}{\nofwords91}{\nofchars524}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNETPLAYERDATA}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNETPLAYERDATA}K{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNETPLAYERDATA}} SNETPLAYERDATA +\par \pard\plain \s16\widctlpar \f4 +\par The SNETPLAYERDATA function contains information about the local player. This information is required when initializing a provider, since the provider may provide a matchmaking service, and when creating or joining a game. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 typedef struct _SNETPLAYERDATA \{ +\par \tab DWORD\tab \tab size; +\par \tab DWORD\tab \tab playername; +\par \tab DWORD\tab \tab playerdescription; +\par \} SNETPLAYERDATA, *SNETPLAYERDATAPTR; +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Members +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 size +\par \pard\plain \s19\li720\widctlpar \f4 The size of the structure, in bytes. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playername +\par \pard\plain \s19\li720\widctlpar \f4 The name of the local player. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerdescription +\par \pard\plain \s19\li720\widctlpar \f4 A description of the local player. This can be generated by the program, and contain information such as the player\rquote s character class or level. +\par \pard\plain \s16\widctlpar \f4 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETPR~1.RTF b/src/Storm/DOCS/SNETPR~1.RTF new file mode 100644 index 0000000..0fb8ea8 --- /dev/null +++ b/src/Storm/DOCS/SNETPR~1.RTF @@ -0,0 +1,70 @@ +{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;} +{\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f19\froman\fcharset161\fprq2 Times New Roman Greek;}{\f20\froman\fcharset162\fprq2 Times New Roman Tur;} +{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f28\fmodern\fcharset238\fprq1 Courier New CE;}{\f29\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f31\fmodern\fcharset161\fprq1 Courier New Greek;}{\f32\fmodern\fcharset162\fprq1 Courier New Tur;} +{\f33\fmodern\fcharset186\fprq1 Courier New Baltic;}}{\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\widctlpar\adjustright \fs20 \snext0 Normal;} +{\*\cs10 \additive Default Paragraph Font;}{\s15\nowidctlpar\widctlpar\adjustright \b\fs40 \sbasedon0 \snext16 API Title;}{\s16\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 API Description;}{\s17\nowidctlpar\widctlpar\adjustright \f2\fs22 +\sbasedon0 \snext17 API Function;}{\s18\nowidctlpar\widctlpar\adjustright \b \sbasedon0 \snext16 API Section;}{\s19\li720\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 API Parameter Description;}{\s20\nowidctlpar\widctlpar\adjustright \i +\sbasedon0 \snext19 API Parameter Name;}{\s21\nowidctlpar\widctlpar\adjustright \fs20 \sbasedon0 \snext21 footnote text;}{\*\cs22 \additive \super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien} +{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1997\mo3\dy21\hr17\min47}{\version3}{\edmins5}{\nofpages2}{\nofwords224}{\nofchars1280}{\*\company Blizzard Entertainment}{\nofcharsws0}{\vern71}} +\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade\viewkind1\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 +\s15\keepn\nowidctlpar\widctlpar\adjustright \b\fs40 {\cs22\super ${\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super $}{ SNETPROGRAMDATA}}#{\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super #}{ + SNETPROGRAMDATA}}K{\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super K}{ SNETPROGRAMDATA}}}{ SNETPROGRAMDATA +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par The SNETPROGRAMDATA structure contains information about the application, such as the program name and version number. +\par +\par }\pard\plain \s17\nowidctlpar\widctlpar\adjustright \f2\fs22 {typedef struct _SNETPROGRAMDATA \{ +\par \tab DWORD\tab \tab size; +\par \tab LPCSTR\tab programname; +\par \tab LPCSTR\tab programdescription; +\par \tab DWORD\tab \tab programid; +\par \tab DWORD\tab \tab versionid; +\par \tab DWORD\tab \tab reserved1; +\par \tab DWORD\tab \tab maxplayers; +\par \tab LPVOID\tab initdata; +\par \tab DWORD\tab \tab initdatabytes; +\par \tab LPVOID\tab reserved2; +\par \tab DWORD\tab \tab optcategorybits; +\par \} SNETPROGRAMDATA, *SNETPROGRAMDATAPTR; +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s18\nowidctlpar\widctlpar\adjustright \b {Members +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {size +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The size of the structure, in bytes. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {programname +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The name of the program. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {programdescription +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The description of the progr +am. This usually includes a name and version number. It is displayed at the bottom of the standard connection screens. If this field is not provided, Storm will automatically generate it using the EXE file\rquote s product version information. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {programid +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A unique 32-bit identifier for the application. The use of this unique identifier allows multiple applications using Storm to create games on the same network without interfering with each other. + +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {versionid +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A unique 32-bit identifier for the network version of the application. This number should be incremented whenever a change in the application makes it incompatible with older versions. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {reserved1 +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {Reserved -- must be set to 0. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {maxplayers +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The maximum number of players per game supported by the application. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {initdata +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {Application-specific initialization data. This data is provided by the game creator, and is available to all joining computers through the SNET_EVENT_INITDATA callback. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {initdatabytes +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The size of the application-specific initialization data. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {reserved2 +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {Reserved \endash must be set to 0. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {optcategorybits +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {This value provides a hint to the network provider about which category bits will most often be used by users to narrow the list of joinable games. The network provider can us +e this hint to structure the way it stores its list of games. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }} \ No newline at end of file diff --git a/src/Storm/DOCS/SNETRE~1.RTF b/src/Storm/DOCS/SNETRE~1.RTF new file mode 100644 index 0000000..96d2750 --- /dev/null +++ b/src/Storm/DOCS/SNETRE~1.RTF @@ -0,0 +1,38 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min22} +{\revtim\yr1996\mo10\dy3\hr15\min9}{\version2}{\edmins0}{\nofpages1}{\nofwords112}{\nofchars640}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetReceiveMessage}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetReceiveMessage}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetReceiveMessage}} SNetReceiveMessage +\par \pard\plain \s16\widctlpar \f4 +\par This function receives the next unread message from any player. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetReceiveMessage ( +\par \tab DWORD\tab \tab *senderplayerid, +\par \tab LPVOID\tab *data, +\par \tab DWORD\tab \tab *databytes +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 senderplayerid +\par \pard\plain \s19\li720\widctlpar \f4 If a message is available, this parameter returns the ID of the player who sent the message. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 data +\par \pard\plain \s19\li720\widctlpar \f4 If a message is available, this parameter returns a pointer to the message data. The pointer remains valid until the next call to an SNet function or to StormDestroy(). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 databytes +\par \pard\plain \s19\li720\widctlpar \f4 If a message is available, this parameter returns the number of bytes in the message. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}No messages are available +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETRE~2.RTF b/src/Storm/DOCS/SNETRE~2.RTF new file mode 100644 index 0000000..23ed3d5 --- /dev/null +++ b/src/Storm/DOCS/SNETRE~2.RTF @@ -0,0 +1,54 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetReceiveTurns}{\author Mike O'Brien}{\operator Mike O'Brien} +{\creatim\yr1996\mo8\dy21\hr16\min22}{\revtim\yr1996\mo10\dy3\hr15\min9}{\version3}{\edmins0}{\nofpages2}{\nofwords269}{\nofchars1536}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd +\linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} + SNetReceiveTurns}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetReceiveTurns}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetReceiveTurns}} SNetReceiveTurns +\par \pard\plain \s16\widctlpar \f4 +\par This function receives the next set of turns from every active player, if all turns are available. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetReceiveTurns ( +\par \tab DWORD\tab \tab firstplayerid, +\par \tab DWORD\tab \tab arraysize, +\par \tab LPVOID\tab *arraydata, +\par \tab LPDWORD\tab arraydatabytes, +\par \tab LPDWORD\tab arrayplayerstatus +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 firstplayerid +\par \pard\plain \s19\li720\widctlpar \f4 The player ID of the first player for which a turn will be received. For example, if this parameter is one, then slot zero in the each array corresponds to player number one. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 arraysize +\par \pard\plain \s19\li720\widctlpar \f4 The number of slots in each array. This limits the number of players for which turns can be returned. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 arraydata +\par \pard\plain \s19\li720\widctlpar \f4 An array of pointers, which will be filled in with pointers to the message data for each player\rquote s turn. Each returned pointer will remain valid until the next call to an SNet function or to StormDestroy(). + +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 arraydatabytes +\par \pard\plain \s19\li720\widctlpar \f4 An array of DWORDs, which will be filled in with the size, in bytes, of the message data for each player\rquote s turn. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 arrayplayerstatus +\par \pard\plain \s19\li720\widctlpar \f4 An array of DWORDs, which will be filled in with the status of each player, whether or not the function successfully returns turns for each player. The following status codes can be returned: +\par \pard\plain \s16\widctlpar \f4 +\par \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_PS_UNUSED\cell There is no active player in this slot.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_PS_READY\cell The next turn for this player has been received.\cell \pard\plain \widctlpar\intbl +\f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_PS_WAITING\cell The next turn for this player has not yet been received.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3960\cellx7812 \pard\plain +\s19\widctlpar\intbl \f4 SNET_PS_NOTRESPONDING\cell The next turn for this player has not been received, and attempts to contact the computer for a resend have been unsuccessful. The player may have lost his network connection.\cell \pard\plain +\widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}An array size of zero is specified +\par {\pntext\pard\plain\f1 \'b7\tab}An array was not provided +\par {\pntext\pard\plain\f1 \'b7\tab}This machine has not yet received the next turn from at least one player +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETRE~3.RTF b/src/Storm/DOCS/SNETRE~3.RTF new file mode 100644 index 0000000..118eec7 --- /dev/null +++ b/src/Storm/DOCS/SNETRE~3.RTF @@ -0,0 +1,42 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\li720\widctlpar \f11 \sbasedon19\snext21 API Callback;}{\s22\widctlpar \f4\fs20 \sbasedon0\snext22 footnote text;}{\*\cs23 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien} +{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min22}{\revtim\yr1996\mo10\dy11\hr14\min19}{\version2}{\edmins1}{\nofpages2}{\nofwords197}{\nofchars1126}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade +\fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs23\super ${\footnote \pard\plain \s22\widctlpar +\f4\fs20 {\cs23\super $} SNetRegisterEventHandler}#{\footnote \pard\plain \s22\widctlpar \f4\fs20 {\cs23\super #} SNetRegisterEventHandler}K{\footnote \pard\plain \s22\widctlpar \f4\fs20 {\cs23\super K} SNetRegisterEventHandler}} SNetRegisterEventHandler + +\par \pard\plain \s16\widctlpar \f4 +\par Registers a callback function which will be called when the specified event occurs. Applications can use this functionality to receive notifications of players joining and leaving a game, among other things. +\par +\par Events can occur at any time, but Storm queues the events and only dispatches them to the appropriate event handler function during an application call to SNetReceiveMessage() or SNetReceiveTurns(). This protects the application from reentrancy issues. + +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetRegisterEventHandler ( +\par \tab DWORD\tab \tab \tab eventid, +\par \tab SNETEVENTPROC\tab callback +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 eventid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the event for which the callback function is being registered. The following events are defined: +\par \pard\plain \s16\widctlpar \f4 +\par \trowd \trgaph108\trleft612 \cellx4320\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4320\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_EVENT_INITDATA\cell Used to receive application-specific initialization data that the game creator specified in the call to SNetCreateGame().\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_EVENT_GAMEDESTROY +\cell The current game has been destroyed by the owner.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s19\widctlpar\intbl \f4 SNET_EVENT_GAMESTART\cell The current game has been started.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row +\pard\plain \s19\widctlpar\intbl \f4 SNET_EVENT_PLAYERJOIN\cell A player has joined the current game.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx4320\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 +SNET_EVENT_PLAYERLEAVE\cell A player has left the current game.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 callback +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to the callback function. See EventProc() for a description. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}An invalid event ID was specified +\par {\pntext\pard\plain\f1 \'b7\tab}No callback function was provided +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETRE~4.RTF b/src/Storm/DOCS/SNETRE~4.RTF new file mode 100644 index 0000000..af158ea --- /dev/null +++ b/src/Storm/DOCS/SNETRE~4.RTF @@ -0,0 +1,26 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\widctlpar \f4\fs20 \sbasedon0\snext19 footnote text;}{\*\cs20 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien} +{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min23}{\revtim\yr1996\mo10\dy3\hr15\min9}{\version2}{\edmins0}{\nofpages1}{\nofwords103}{\nofchars591}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0 +\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs20\super ${\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super $} + SNetResetLatencyMeasurements}#{\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super #} SNetResetLatencyMeasurements}K{\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super K} SNetResetLatencyMeasurements}} SNetResetLatencyMeasurements +\par \pard\plain \s16\widctlpar \f4 +\par This function has two effects. First, it clears the peak latency that has been measured since the beginning of the game, as returned by SNetGetNetworkLatency() with SNET_LMT_PEAK. Second, it causes all players in the game to be immediately polled for a +new current latency, as returned by SNetGetNetworkLatency() with SNET_LMT_CURRENT. +\par +\par It can be useful to call SNetResetLatencyMeasurements() after a player drops out of a game, especially if the game bases its speed or number of turns per second on the measured latency of the current players. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetResetLatencyMeasurements (); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par None. +\par +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETSE~1.RTF b/src/Storm/DOCS/SNETSE~1.RTF new file mode 100644 index 0000000..4a947a1 --- /dev/null +++ b/src/Storm/DOCS/SNETSE~1.RTF @@ -0,0 +1,59 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien} +{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr19\min9}{\version2}{\edmins1}{\nofpages2}{\nofwords317}{\nofchars1812}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd +\linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} + SNetSelectGame}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetSelectGame}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetSelectGame}} SNetSelectGame +\par \pard\plain \s16\widctlpar \f4 +\par Supplies user interface screens to allow the player to select from a list of games or create a new game, then creates or joins the game and returns the local user\rquote s game player ID. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetSelectGame ( +\par \tab DWORD\tab \tab \tab \tab flags, +\par \tab SNETPROGRAMDATAPTR\tab programdata, +\par \tab SNETPLAYERDATAPTR\tab playerdata, +\par \tab SNETUIDATAPTR\tab \tab interfacedata, +\par \tab SNETVERSIONDATAPTR\tab versiondata, +\par \tab DWORD\tab \tab \tab \tab *playerid +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 flags +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags specifying which options should be provided to the user. The following flags are defined: +\par +\par \trowd \trgaph108\trleft612 \cellx3780\cellx7812 \pard \s19\widctlpar\intbl {\b Value}\cell {\b Meaning}\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \trowd \trgaph108\trleft612 \cellx3780\cellx7812 \pard\plain \s19\widctlpar\intbl \f4 SNET_ +SF_ALLOWCREATE\cell The user is allowed to create new games. If this flag is not specified, the user is only allowed to join existing games.\cell \pard\plain \widctlpar\intbl \f4\fs20 \row \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 programdata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing information about the program, such as the program name, version, and number of players supported. This is a mandatory parameter. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerdata +\par \pard\plain \s19\li720\widctlpar \f4 +A pointer to a structure containing the name and description of the current player. The provider may use this information if it performs a matchmaking process. The provider also uses this information when creating or joining a game. This is a mandatory + parameter. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 interfacedata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing i +nformation about how the network provider should display user interface screens if necessary. Most network providers will fail if this information is not given. For example, the modem provider cannot query the user for a phone number to dial without the + ability to display user interface screens. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 versiondata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing information about the application which is necessary for automatic version control. Some network providers are capable of performing over-the-wire version updates. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID that is assigned to the player, if the function successfully creates or joins a game. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized. +\par {\pntext\pard\plain\f1 \'b7\tab}The program data is missing or invalid. +\par {\pntext\pard\plain\f1 \'b7\tab}The player data is missing or invalid. +\par {\pntext\pard\plain\f1 \'b7\tab}The interface data is missing or invalid +\par {\pntext\pard\plain\f1 \'b7\tab}No variable is provided to receive the player ID. +\par {\pntext\pard\plain\f1 \'b7\tab}The user canceled the creation or joining process. +\par {\pntext\pard\plain\f1 \'b7\tab}The system is out of memory. +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETSE~2.RTF b/src/Storm/DOCS/SNETSE~2.RTF new file mode 100644 index 0000000..f6ac105 --- /dev/null +++ b/src/Storm/DOCS/SNETSE~2.RTF @@ -0,0 +1,52 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien} +{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr19\min8}{\version5}{\edmins12}{\nofpages2}{\nofwords310}{\nofchars1770}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd +\linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNet +SelectProvider}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetSelectProvider}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetSelectProvider}} SNetSelectProvider +\par \pard\plain \s16\widctlpar \f4 +\par \pard \s16\widctlpar Supplies user interface screens to allow the user to select a network provider, then initializes that provider. +\par \pard \s16\widctlpar +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetSelectGame ( +\par \pard \s17\widctlpar \tab SNETCAPSPTR\tab \tab mincaps, +\par \tab SNETPROGRAMDATAPTR\tab programdata, +\par \tab SNETPLAYERDATAPTR\tab playerdata, +\par \tab SNETUIDATAPTR\tab \tab interfacedata, +\par \tab SNETVERSIONDATAPTR\tab versiondata, +\par \tab DWORD\tab \tab \tab \tab *providerid +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 programdata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing information about the program, such as the program name, version, and number of players supported. This is a mandatory parameter. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 playerdata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing the name and description of the current player. The provider may use this information if it performs a matchmaking process. This is a mandatory parameter. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 interfacedata +\par \pard\plain \s19\li720\widctlpar \f4 +A pointer to a structure containing information about how the network provider should display user interface screens if necessary. Most network providers will fail if this information is not given. For example, the modem provider cannot query the user f +or a phone number to dial without the ability to display user interface screens. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 versiondata +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a structure containing information about the application which is necessary for automatic version control. Some network providers are capable of performing over-the-wire version updates. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 providerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the provider that was selected. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}The program data is missing or invalid. +\par {\pntext\pard\plain\f1 \'b7\tab}The player data is missing or invalid. +\par {\pntext\pard\plain\f1 \'b7\tab}The interface data is missing or invalid, and the provider needs to display interface during the initialization process. +\par {\pntext\pard\plain\f1 \'b7\tab}The network provider was unable to initialize itself. For example, the IPX provider may fail if IPX support is not available, and the Battle.net provider may fail if it cannot contact any Battle.net servers. +\par {\pntext\pard\plain\f1 \'b7\tab}The application needs to be upgraded before it can connect to the server. +\par \pard \s16\widctlpar +\par If this function fails, the application should call GetLastError() to determine the reason for failure. If GetLastError() returns SNET_ERROR_REQUIRES_UPGRADE, the application should call SNetPerformUpgrade(). +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETSE~3.RTF b/src/Storm/DOCS/SNETSE~3.RTF new file mode 100644 index 0000000..2683a82 --- /dev/null +++ b/src/Storm/DOCS/SNETSE~3.RTF @@ -0,0 +1,44 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min23} +{\revtim\yr1996\mo10\dy21\hr11\min47}{\version2}{\edmins0}{\nofpages1}{\nofwords169}{\nofchars964}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetSendMessage}#{\footnote \pard\plain +\s21\widctlpar \f4\fs20 {\cs22\super #} SNetSendMessage}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetSendMessage}} SNetSendMessage +\par \pard\plain \s16\widctlpar \f4 +\par Sends a message to another player, or to all players. It must be received on the target computer using SNetReceiveMessage(). +\par +\par A message is different from a turn, in that messages can be sent between two individual players, and can be sent at any time, whereas turns are sent to all players at a specific interval. The choice of whether to use messages or turns depends on the netw +orking model of the game. Games can also mix and match, using messages for some purposes and turns for others. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetSendMessage ( +\par \tab DWORD\tab \tab targetplayerid, +\par \tab LPVOID\tab data, +\par \tab DWORD\tab \tab databytes +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 targetplayerid +\par \pard\plain \s19\li720\widctlpar \f4 The ID of the player to whom the message will be sent. Specify SNET_BROADCASTPLAYERID to broadcast the message to all players. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 data +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to the message data. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 databytes +\par \pard\plain \s19\li720\widctlpar \f4 The size of the message, in bytes. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}A player ID was given, and no active player exists with that ID +\par {\pntext\pard\plain\f1 \'b7\tab}No data pointer was provided +\par {\pntext\pard\plain\f1 \'b7\tab}The size of the message is zero +\par {\pntext\pard\plain\f1 \'b7\tab}The system is out of memory +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETSE~4.RTF b/src/Storm/DOCS/SNETSE~4.RTF new file mode 100644 index 0000000..cdce77e --- /dev/null +++ b/src/Storm/DOCS/SNETSE~4.RTF @@ -0,0 +1,41 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min23} +{\revtim\yr1996\mo10\dy3\hr15\min10}{\version2}{\edmins0}{\nofpages1}{\nofwords182}{\nofchars1042}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetSendTurn}#{\footnote \pard\plain +\s21\widctlpar \f4\fs20 {\cs22\super #} SNetSendTurn}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetSendTurn}} SNetSendTurn +\par \pard\plain \s16\widctlpar \f4 +\par Sends out the next turn for this computer. The turn must be received on the local machine and all other machines in the game using SNetReceiveTurns(). +\par +\par Typically, a game will send a turn as soon as it is generated (for example, as soon a +s the user performs an action), and then receive turns at a specific rate, such as two turns per second. By sending turns as soon as they are generated, rather than sending only two turns per second, the game ensures that turns are given as much time as +possible to travel over the wire. However, it is also important for the game to ensure that it has always sent more turns than it has processed, to ensure that there are always turns on the wire. The game can accomplish this by checking the number of tu +rns in transit, using SNetGetTurnsInTransit(), before calling SNetReceiveTurns(). +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetSendTurn ( +\par \tab LPVOID\tab data, +\par \tab DWORD\tab \tab databytes +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 data +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to the turn data. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 databytes +\par \pard\plain \s19\li720\widctlpar \f4 The size of the turn data, in bytes. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}No data pointer was provided +\par {\pntext\pard\plain\f1 \'b7\tab}The size of the turn is zero +\par {\pntext\pard\plain\f1 \'b7\tab}The system is out of memory +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETST~1.RTF b/src/Storm/DOCS/SNETST~1.RTF new file mode 100644 index 0000000..2d24635 --- /dev/null +++ b/src/Storm/DOCS/SNETST~1.RTF @@ -0,0 +1,31 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\widctlpar \f4\fs20 \sbasedon0\snext19 footnote text;}{\*\cs20 \additive\super \sbasedon10 +footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min23}{\revtim\yr1996\mo10\dy3\hr15\min10}{\version2}{\edmins0}{\nofpages1}{\nofwords157}{\nofchars898}{\*\company Blizzard Entertainment}{\vern57431}} +\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs20\super ${\footnote \pard\plain +\s19\widctlpar \f4\fs20 {\cs20\super $} SNetStartGame}#{\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super #} SNetStartGame}K{\footnote \pard\plain \s19\widctlpar \f4\fs20 {\cs20\super K} SNetStartGame}} SNetStartGame +\par \pard\plain \s16\widctlpar \f4 +\par Starts the current game. Only the game master can call this function. Once the game has been started, no new players can join, and the game will continue even if the game master has left. +\par +\par The SNetStartGame() function was designed around games like Warcraft, where all players sit in a chat room while waiting for the game to join, and then start playing the game at th +e same time. It makes less sense in a game like Quake where players can drop in and out of the game at any time. For this reason, it will probably be removed and replaced with a more comprehensive API that allows individual control over such game attrib +utes as whether new players can join, whether the game shows up in lists of games, and whether the game master is necessary to maintain the game. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetStartGame (); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par None. +\par +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}No network provider has been initialized +\par {\pntext\pard\plain\f1 \'b7\tab}No game has been created or joined +\par {\pntext\pard\plain\f1 \'b7\tab}The local player is not the master player +\par {\pntext\pard\plain\f1 \'b7\tab}The game has already been started +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETUI~1.RTF b/src/Storm/DOCS/SNETUI~1.RTF new file mode 100644 index 0000000..077d7e1 --- /dev/null +++ b/src/Storm/DOCS/SNETUI~1.RTF @@ -0,0 +1,80 @@ +{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;} +{\f16\froman\fcharset238\fprq2 Times New Roman CE;}{\f17\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f19\froman\fcharset161\fprq2 Times New Roman Greek;}{\f20\froman\fcharset162\fprq2 Times New Roman Tur;} +{\f21\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f28\fmodern\fcharset238\fprq1 Courier New CE;}{\f29\fmodern\fcharset204\fprq1 Courier New Cyr;}{\f31\fmodern\fcharset161\fprq1 Courier New Greek;}{\f32\fmodern\fcharset162\fprq1 Courier New Tur;} +{\f33\fmodern\fcharset186\fprq1 Courier New Baltic;}}{\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\widctlpar\adjustright \fs20 \snext0 Normal;} +{\*\cs10 \additive Default Paragraph Font;}{\s15\nowidctlpar\widctlpar\adjustright \b\fs40 \sbasedon0 \snext16 API Title;}{\s16\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 API Description;}{\s17\nowidctlpar\widctlpar\adjustright \f2\fs22 +\sbasedon0 \snext17 API Function;}{\s18\nowidctlpar\widctlpar\adjustright \b \sbasedon0 \snext16 API Section;}{\s19\li720\nowidctlpar\widctlpar\adjustright \sbasedon0 \snext16 API Parameter Description;}{\s20\nowidctlpar\widctlpar\adjustright \i +\sbasedon0 \snext19 API Parameter Name;}{\s21\nowidctlpar\widctlpar\adjustright \fs20 \sbasedon0 \snext21 footnote text;}{\*\cs22 \additive \super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien} +{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1997\mo3\dy21\hr17\min50}{\version4}{\edmins2}{\nofpages2}{\nofwords369}{\nofchars2106}{\*\company Blizzard Entertainment}{\nofcharsws0}{\vern71}} +\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade\viewkind1\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 +\s15\keepn\nowidctlpar\widctlpar\adjustright \b\fs40 {\cs22\super ${\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super $}{ SNETUIDATA}}#{\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super #}{ + SNETUIDATA}}K{\footnote \pard\plain \s21\nowidctlpar\widctlpar\adjustright \fs20 {\cs22\super K}{ SNETUIDATA}}}{ SNETUIDATA +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par The SNETUIDATA structure contains information which Storm and the network providers use to display user interface on behalf of the application program. +\par +\par }\pard\plain \s17\nowidctlpar\widctlpar\adjustright \f2\fs22 {typedef struct _SNETUIDATA \{ +\par \tab DWORD\tab \tab \tab \tab size; +\par \tab DWORD\tab \tab \tab \tab uiflags; +\par \tab HWND\tab \tab \tab \tab parentwindow; +\par \tab SNETGETARTPROC\tab \tab artcallback; +\par \tab SNETCHECKAUTHPROC\tab authcallback; +\par \tab SNETCREATEPROC\tab \tab createcallback; +\par \tab SNETDRAWDESCPROC\tab drawdesccallback; +\par \tab SNETSELECTEDPROC\tab selectedcallback; +\par \tab SNETMESSAGEBOXPROC\tab messageboxcallback; +\par \tab SNETPLAYSOUNDPROC\tab soundcallback; +\par \tab SNETSTATUSPROC\tab \tab statuscallback; +\par \tab SNETGETDATAPROC\tab \tab getdatacallback; +\par \tab SNETCATEGORYPROC\tab \tab categorycallback; +\par \} SNETUIDATA, *SNETUIDATAPTR; +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s18\nowidctlpar\widctlpar\adjustright \b {Members +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {size +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The size of the structure, in bytes. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {uiflags +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A set of flags specifying the desired behavior of the network provider\rquote s user interface. No flags are currently defined. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {parentwindow +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {The window handle of the active window. If Storm or a network provider creates a dialog box, it will use this handle for the parent window. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {artcallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A pointer to a function which Storm or a network provider can call to obtain artwork for the dialog background or controls. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {authcallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A pointer to a function which the network provider calls to determine whether the local player has access to a chat room. This only applies to network providers which provide chat functionality. + +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {createcallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright { +A pointer to a function which the network provider calls when the user has decided to create a game. This function is responsible for asking the user for the game name and options, and then calling SNetCreateGame(). +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {drawdesccallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright { +A pointer to a function which the network provider calls if it needs to draw a game or player description. This allows the application to perform its own drawing. For example, it could convert a cryptic description str +ing which only the application understands, like \ldblquote FOG LOW BATTLE.PUD\rdblquote into a group of icons which would represent the game options in a way players could easily understand. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {selectedcallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A pointer to a function which Storm calls when the user selects a network provider. This provides the application a chance to review the network provider\rquote +s ID and capabilities, and either accept the selection or present the user with an error message and reject the selection. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {messageboxcallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A pointer to a function which Storm and the network provider can use to display message boxes. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {soundcallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A pointer to a function which Storm and the network provider can use to play sound effects. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {statuscallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A pointer to a function that the network provider can use to provide feedback on the status of a long operation. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {getdatacallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A pointer to a function that the network provider can use to request provider-specific data from the application. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }\pard\plain \s20\nowidctlpar\widctlpar\adjustright \i {categorycallback +\par }\pard\plain \s19\li720\nowidctlpar\widctlpar\adjustright {A pointer to a function that the network provider can use to request information about which categories of games the user is interested in joining. +\par }\pard\plain \s16\nowidctlpar\widctlpar\adjustright { +\par }} \ No newline at end of file diff --git a/src/Storm/DOCS/SNETUN~1.RTF b/src/Storm/DOCS/SNETUN~1.RTF new file mode 100644 index 0000000..a9c3ccf --- /dev/null +++ b/src/Storm/DOCS/SNETUN~1.RTF @@ -0,0 +1,33 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f1\froman\fcharset2\fprq2 Symbol;}{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 +\sbasedon0\snext16 API Description;}{\s17\widctlpar \f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 +\sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 \sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min23} +{\revtim\yr1996\mo10\dy3\hr15\min10}{\version2}{\edmins0}{\nofpages1}{\nofwords77}{\nofchars443}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNetUnregisterEventHandler}#{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNetUnregisterEventHandler}K{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNetUnregisterEventHandler}} SNetUnregisterEventHandler +\par \pard\plain \s16\widctlpar \f4 +\par This removes a given function from the list of registered event handlers. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL SNetUnregisterEventHandler ( +\par \tab DWORD\tab \tab \tab eventid, +\par \tab SNETEVENTPROC\tab callback +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 eventid +\par \pard\plain \s19\li720\widctlpar \f4 The event ID for which the handler was registered. See SNetRegisterEventHandler() for a list of event IDs. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 callback +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to the event handler function. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par This function returns TRUE for success or FALSE for failure. The function can fail if: +\par {\pntext\pard\plain\f1 \'b7\tab}\pard \s16\fi-360\li360\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}An invalid event ID was specified +\par {\pntext\pard\plain\f1 \'b7\tab}No callback function was provided +\par \pard\plain \widctlpar \f4\fs20 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/SNETVE~1.RTF b/src/Storm/DOCS/SNETVE~1.RTF new file mode 100644 index 0000000..6a2b923 --- /dev/null +++ b/src/Storm/DOCS/SNETVE~1.RTF @@ -0,0 +1,39 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo10\dy3\hr18\min29}{\version2} +{\edmins2}{\nofpages1}{\nofwords135}{\nofchars771}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} SNETVERSIONDATA}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} SNETVERSIONDATA}K{\footnote +\pard\plain \s21\widctlpar \f4\fs20 {\cs22\super K} SNETVERSIONDATA}} SNETVERSIONDATA +\par \pard\plain \s16\widctlpar \f4 +\par The SNETVERSIONDATA structure contains information that is needed to perform an over-the-wire program upgrade. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 typedef struct _SNETVERSIONDATA \{ +\par \tab DWORD\tab \tab size; +\par \tab LPCSTR\tab versionstring; +\par \tab LPCSTR\tab executablefile; +\par \tab LPCSTR\tab originalarchivefile; +\par \tab LCPSTR\tab patcharchivefile; +\par \} SNETVERSIONDATA, *SNETVERSIONDATAPTR; +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Members +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 size +\par \pard\plain \s19\li720\widctlpar \f4 The size of the structure, in bytes. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 versionstring +\par \pard\plain \s19\li720\widctlpar \f4 A human-readable string representing the product version. If this string is provided, it overrides the product version string in the executable file\rquote s version information resource. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 executablefile +\par \pard\plain \s19\li720\widctlpar \f4 The full path name of the program\rquote s executable file. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 originalarchivename +\par \pard\plain \s19\li720\widctlpar \f4 The full path name to the archive file which contains all of the program\rquote s data. This file will typically be located on CD. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 patcharchivefile +\par \pard\plain \s19\li720\widctlpar \f4 The full path name to the archive file which contains patched program data. This file must be located on the user\rquote s hard drive. +\par \pard\plain \s16\widctlpar \f4 +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/STATUS~1.RTF b/src/Storm/DOCS/STATUS~1.RTF new file mode 100644 index 0000000..5b03c03 --- /dev/null +++ b/src/Storm/DOCS/STATUS~1.RTF @@ -0,0 +1,47 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18}{\revtim\yr1996\mo11\dy27\hr19\min45}{\version3} +{\edmins1}{\nofpages2}{\nofwords170}{\nofchars971}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 {\cs22\super ${\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super $} StatusProc}#{\footnote \pard\plain \s21\widctlpar \f4\fs20 {\cs22\super #} StatusProc}K{\footnote \pard\plain +\s21\widctlpar \f4\fs20 {\cs22\super K} StatusProc}} StatusProc +\par \pard\plain \s16\widctlpar \f4 +\par {\b\i StatusProc() is a placeholder for an application-defined function name.} +\par +\par This function is called by the network provider during a long operation to allow the program to provide visual feedback to the user. +\par +\par \pard\plain \s17\widctlpar \f11\fs22 BOOL CALLBACK StatusProc ( +\par \tab LPCSTR\tab \tab statustext, +\par \tab DWORD\tab \tab \tab workcompleted, +\par \tab DWORD\tab \tab \tab estimatedworkremaining, +\par \tab DWORD\tab \tab \tab flags, +\par \tab SNETABORTPROC\tab abortproc +\par ); +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Parameters +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 statustext +\par \pard\plain \s19\li720\widctlpar \f4 A human-readable description of the current status of the operation. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 workcompleted +\par \pard\plain \s19\li720\widctlpar \f4 A value representing the amount of work on this operation that the network provider has already completed. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 estimatedworkremaining +\par \pard\plain \s19\li720\widctlpar \f4 A value representing the network provider\rquote s best estimate for the amount of work remaining. If the application wants to display the progress as a percent, it can use the following equation: +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s19\fi720\li720\widctlpar \f4 percent = (completed*100)/(completed+remaining). +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 flags +\par \pard\plain \s19\li720\widctlpar \f4 A set of flags which specify the state of the service provider. There are no flags currently defined. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s20\widctlpar \i\f4 abortproc +\par \pard\plain \s19\li720\widctlpar \f4 A pointer to a function that the application can call to cancel the current operation. +\par \pard\plain \s16\widctlpar \f4 +\par \pard\plain \s18\widctlpar \b\f4 Return Value +\par \pard\plain \s16\widctlpar \f4 +\par If the application uses this information, it should return TRUE. Otherwise, it should return FALSE. +\par +\par } \ No newline at end of file diff --git a/src/Storm/DOCS/STORM.GID b/src/Storm/DOCS/STORM.GID new file mode 100644 index 0000000..5d647c2 Binary files /dev/null and b/src/Storm/DOCS/STORM.GID differ diff --git a/src/Storm/DOCS/STORM.HLP b/src/Storm/DOCS/STORM.HLP new file mode 100644 index 0000000..4905dcb Binary files /dev/null and b/src/Storm/DOCS/STORM.HLP differ diff --git a/src/Storm/DOCS/STORM.HPJ b/src/Storm/DOCS/STORM.HPJ new file mode 100644 index 0000000..32d5e65 --- /dev/null +++ b/src/Storm/DOCS/STORM.HPJ @@ -0,0 +1,49 @@ +[OPTIONS] +TITLE=Storm Reference +COMPRESS=on +WARNING=3 + +[FILES] +Title.rtf +SNetCreateGame.rtf +SNetDestroy.rtf +SNetEnumGames.rtf +SNetEnumProviders.rtf +SNetGetNetworkLatency.rtf +SNetGetNumPlayers.rtf +SNetGetPlayerCaps.rtf +SNetGetPlayerName.rtf +SNetGetProviderCaps.rtf +SNetGetTurnsInTransit.rtf +SNetInitializeProvider.rtf +SNetJoinGame.rtf +SNetLeaveGame.rtf +SNetPerformUpgrade.rtf +SNetReceiveMessage.rtf +SNetReceiveTurns.rtf +SNetRegisterEventHandler.rtf +SNetResetLatencyMeasurements.rtf +SNetSelectGame.rtf +SNetSelectProvider.rtf +SNetSendMessage.rtf +SNetSendTurn.rtf +SNetStartGame.rtf +SNetUnregisterEventHandler.rtf +CategoryProc.rtf +CheckAuthProc.rtf +CreateProc.rtf +DrawDescProc.rtf +EnumGamesProc.rtf +EnumProvidersProc.rtf +EventProc.rtf +GetArtProc.rtf +GetDataProc.rtf +MessageBoxProc.rtf +PlaySoundProc.rtf +StatusProc.rtf +SNETCAPS.rtf +SNETCREATEDATA.rtf +SNETPLAYERDATA.rtf +SNETPROGRAMDATA.rtf +SNETUIDATA.rtf +SNETVERSIONDATA.rtf diff --git a/src/Storm/DOCS/STORM.PH b/src/Storm/DOCS/STORM.PH new file mode 100644 index 0000000..7ad0786 --- /dev/null +++ b/src/Storm/DOCS/STORM.PH @@ -0,0 +1,652 @@ +*playerid +0x80000000, +32-bit +A description of the local player. This can be generated by the program, and contain information such as the player +A pointer to a structure containing information about how the network provider should display user interface screens if necessary. Most network providers will fail if this information is not given. For example, the modem provider cannot query the user +A pointer to a structure containing information about the application which is necessary for automatic version control. Some network providers are capable of performing over-the-wire version updates. +A pointer to a structure containing information about the program, such as the program name, version, and number of players supported. This is a mandatory parameter. +A set of flags specifying how the sound should be played. Use the SND_* constants defined in Windows.h. +A structure containing the interface data that was passed to SNetSelectGame(), modified as necessary to ensure that the dialog that the create callback displays fits with the network provider +A structure containing the player data that was passed to SNetSelectGame(). +A structure containing the program data that was passed to SNetSelectGame(). +A structure containing the version data that was passed to SNetSelectGame(). +A value returned by the callback function specifying which +An array +An identifier which tells whether the name and description describe a game or a player. It can be one of the following values: +An invalid event ID was specified +Any +Applications +BOOL SNetSelectGame ( +Battle.net +Blizzard +Cancel +Cancel. +CategoryProc +CheckAuthProc +Courier New; +CreateProc +DWORD +DWORD * +DWORDs, +DrawDescProc +EnumGamesProc +EnumProvidersProc +EventProc +FALSE +For +Functions +GetArtProc +GetDataProc +GetLastError() +IDs +IDs, +IDs. +If this function fails, the application should call GetLastError() to determine the reason for failure. If GetLastError() returns SNET_ERROR_REQUIRES_UPGRADE, the application should call SNetPerformUpgrade(). +LPCSTR +LPDWORD +LPVOID +Meaning +Members +MessageBoxProc +Most +New; +No active player exists with the given ID +No callback function is provided +No callback function was provided +No data pointer was provided +No game has been created or joined +No network provider has been initialized +No player name or description is specified +No variable is provided to receive the result +None. +Other +Otherwise, +Parameters +PlaySoundProc +Player has been squelched by the local user +Player is a Blizzard employee +Player is a channel moderator +Player is a speaker for a special event +Player is a sysop of the selected gaming service +Rather than calling this function manually, an application will generally call SNetSelectGame() to present the user with a list of games and allow him to join a game or create a new one. +Rather than calling this function manually, an application will generally call SNetSelectProvider() to present the user with a list of network providers and allow him to select and initialize one. +Return Value +SNETCAPS +SNETCAPSPTR +SNETCREATEDATA +SNETEVENTPROC +SNETPLAYERDATA +SNETPLAYERDATAPTR +SNETPROGRAMDATA +SNETPROGRAMDATAPTR +SNETUIDATA +SNETUIDATAPTR +SNETVERSIONDATA +SNETVERSIONDATAPTR +SNET_DDPF_BLIZZARD +SNET_DDPF_MODERATOR +SNET_DDPF_SPEAKER +SNET_DDPF_SQUELCHED +SNET_DDPF_SYSOP +SNET_ERROR_REQUIRES_UPGRADE, +SNET_EVENT_INITDATA +SNet +SNetCreateGame +SNetCreateGame() +SNetCreateGame(), +SNetCreateGame(). +SNetDestroy +SNetEnumGames +SNetEnumProviders +SNetEnumerateProviders(). +SNetGetNetworkLatency +SNetGetNetworkLatency() +SNetGetNumPlayers +SNetGetPlayerCaps +SNetGetPlayerName +SNetGetProviderCaps +SNetGetTurnsInTransit +SNetInitializeProvider +SNetInitializeProvider(). +SNetJoinGame +SNetLeaveGame +SNetLeaveGame(). +SNetPerformUpgrade +SNetPerformUpgrade(). +SNetReceiveMessage +SNetReceiveMessage() +SNetReceiveTurns +SNetReceiveTurns(). +SNetRegisterEventHandler +SNetResetLatencyMeasurements +SNetSelectGame +SNetSelectGame() +SNetSelectGame(), +SNetSelectGame(). +SNetSelectProvider +SNetSelectProvider() +SNetSendMessage +SNetSendTurn +SNetSendTurn() +SNetStartGame +SNetUnregisterEventHandler +Some +StatusProc +Storm +StormDestroy(). +Symbol; +TRUE +The ID of the network provider which is making the request. +The application +The application needs to be upgraded before it can connect to the server. +The name of the local player. +The network provider was unable to initialize itself. For example, the IPX provider may fail if IPX support is not available, and the Battle.net provider may fail if it cannot contact any Battle.net servers. +The player data is missing or invalid. +The program data is missing or invalid. +The size field of the SNETCAPS structure is invalid +The size of the buffer pointed to by +The size of the structure, in bytes. +The size of the turn +The system is out of memory +This function returns TRUE for success or FALSE for failure. The function can fail if: +This function should return TRUE to continue enumeration, or FALSE to stop. +Value +Windows.h. +ability +abortproc +about +above +active +after +all +allow +allowed +allows +already +also +always +amount +and +another +application +application-defined +application-specific +application. +archive +are +array +arrayplayerstatus +artwork +artwork, +assigned +authorized +automatic +automatically +available +available, +available. +background +bandwidth +been +before +beginning +being +below. +between +bitmap +bitmap. +bits +box +box. +buffer +buffer, +buffer. +buffersize +buffersize, +but +button +button. +buttons: +bytes +bytes, +bytes. +call +callback +callback, +called +calling +calls +can +canceled +cannot +capabilities +capabilities, +capable +caps +caption, +categories +category +categorybits +categorymask +categorymask) +channel +channel. +character +characters, +chat +class +communications +computer +computer. +computers +connect +constants +contact +contain +containing +contains +continue +control. +create +created +createdata +creates +creating +creation +current +currently +data +data, +data. +databytes +decided +decoded +default +default. +defaultturns +define +defined +defined. +defined: +describe +describing +description +description. +destroy +determine +dial +dialog +dialog. +display +displayed +displays +does +doesn +draw +drawdata +drawn. +during +each +effect. +effects. +either +employee +ensure +enumerate +enumerated. +enumeration, +error +especially +event +eventid +eventid, +events +example, +executable +existing +exists +expected +expressed +fail +failed +fails, +failure. +feedback +field +file +fill +filled +first +firstplayerid +flags +flags, +following +from +full +function +function. +game +game, +game. +gamedescription +gameid +gamename +gamename, +gamepassword +gamepassword, +games +games, +games. +gaming +generally +generated +get +given +given. +graphical +handle +handler +has +have +height +highest +him +hint +how +human-readable +iconic +identifier +if: +ignored. +includes +indicate +individual +information +initdata +initdatabytes +initialization +initialize +initialized +initialized. +installed +interested +interface +interface. +interfacedata +interfacedata, +into +invalid +invalid, +invalid. +item +item. +itemdescription +itemdescription, +itemtype +itemtype, +its +itself. +join +join, +joined +joined. +joining +joining. +latency +latency, +latency. +leaving +level. +like +list +local +located +machine +machines +maintain +makes +making +mandatory +manually, +master +match +matchmaking +maximum +maxplayers +maxplayers; +may +measured +measurement +medium, +memory +message +message. +messages +mincaps +mincaps, +minimum +missing +modem +moderator +modified +more +must +name +name, +name. +necessary +necessary. +need +needed +needs +network +new +next +not +null +number +number. +numbered +occurred. +once +one +one. +only +operation +operation. +options +options, +or a phone number to dial without the ability to display user interface screens. +order +out +over +over-the-wire +own +palette +parameter +parameter. +parentwindow +pass +passed +passing +password +password. +path +per +perform +performing +performs +phone +placeholder +played. +player +player, +player. +playerdata +playerdata, +playerdescription +playerdescription, +playerid +playerid, +playername +playername, +players +players. +pointed +pointer +pointers +present +private +probably +procedure +process +process. +processed +processing +product +program +program, +programdata +programdata, +provide +provided +provided, +provider +provider, +provider. +providerid +providerid, +providers +provides +push +query +querying +range +rather +reason +receive +received +received. +receives +recommended +registered. +represent +representing +request +request. +requested +requested. +requesting +required +requirements +response +responsible +result +return +returned +returned. +returns +round-trip +s character class or level. +s interface. +s maximum number of players +same +screens +screens. +second +second, +second. +select +selected +selected. +sending +sent +server +server. +servers. +service +set +should +simply +since +single +size +size, +size; +soon +sound +soundid +speaker +special +specific +specified +specify +specifying +squelched +standard +started +status +string +struct +structure +structure, +structure. +success +successful. +successfully +such +support +supported +supported. +supports +system +system. +systems, +take +than +that +the +their +then +there +this +through +time +time, +transit +turn +turns +two +type +unable +unique +updates. +upgrade +upgraded +use +used +user +user. +uses +using +valid +values: +variable +version +version, +versiondata +versiondata, +waiting +was +when +where +whether +which +will +window +window. +with +without +yet +you +zero diff --git a/src/Storm/DOCS/TITLE.BMP b/src/Storm/DOCS/TITLE.BMP new file mode 100644 index 0000000..638152a Binary files /dev/null and b/src/Storm/DOCS/TITLE.BMP differ diff --git a/src/Storm/DOCS/TITLE.RTF b/src/Storm/DOCS/TITLE.RTF new file mode 100644 index 0000000..044e363 --- /dev/null +++ b/src/Storm/DOCS/TITLE.RTF @@ -0,0 +1,62 @@ +{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f11\fmodern\fcharset0\fprq1 Courier New;}}{\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{\widctlpar \f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \b\f4\fs40 \sbasedon0\snext16 API Title;}{\s16\widctlpar \f4 \sbasedon0\snext16 API Description;}{\s17\widctlpar +\f11\fs22 \sbasedon0\snext17 API Function;}{\s18\widctlpar \b\f4 \sbasedon0\snext16 API Section;}{\s19\li720\widctlpar \f4 \sbasedon0\snext16 API Parameter Description;}{\s20\widctlpar \i\f4 \sbasedon0\snext19 API Parameter Name;}{\s21\widctlpar \f4\fs20 +\sbasedon0\snext21 footnote text;}{\*\cs22 \additive\super \sbasedon10 footnote reference;}{\s23\widctlpar\tqc\tx4320\tqr\tx8640 \f4\fs20 \sbasedon0\snext23 header;}{\s24\widctlpar\tqc\tx4320\tqr\tx8640 \f4\fs20 \sbasedon0\snext24 footer;}{\*\cs25 +\additive\uldb \sbasedon10 Link Text;}{\*\cs26 \additive\v \sbasedon10 Link Pointer;}{\*\cs27 \additive\sbasedon10 Default Font;}}{\info{\title SNetCreateGame}{\author Mike O'Brien}{\operator Mike O'Brien}{\creatim\yr1996\mo8\dy21\hr16\min18} +{\revtim\yr1996\mo11\dy28\hr2\min33}{\version2}{\edmins0}{\nofpages2}{\nofwords207}{\nofchars1184}{\*\company Blizzard Entertainment}{\vern57431}}\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade \fet0\sectd \linex0\endnhere {\*\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 \s15\keepn\widctlpar \b\f4\fs40 Storm Reference +\par \pard\plain \s16\widctlpar \f4 +\par {\b SNet API Functions} +\par +\par {\cs25\uldb SNetCreateGame()}{\cs26\v SNetCreateGame}{\cs27 +\par }{\cs25\uldb SNetDestroy()}{\cs26\v SNetDestroy}{\cs27 +\par }{\cs25\uldb SNetEnumGames()}{\cs26\v SNetEnumGames}{\cs27 +\par }{\cs25\uldb SNetEnumProviders()}{\cs26\v SNetEnumProviders}{\cs27 +\par }{\cs25\uldb SNetGetNetworkLatency()}{\cs26\v SNetGetNetworkLatency}{\cs27 +\par }{\cs25\uldb SNetGetNumPlayers()}{\cs26\v SNetGetNumPlayers}{\cs27 +\par }{\cs25\uldb SNetGetPlayerCaps()}{\cs26\v SNetGetPlayerCaps}{\cs27 +\par }{\cs25\uldb SNetGetPlayerName()}{\cs26\v SNetGetPlayerName}{\cs27 +\par }{\cs25\uldb SNetGetProviderCaps()}{\cs26\v SNetGetProviderCaps}{\cs27 +\par }{\cs25\uldb SNetGetTurnsInTransit()}{\cs26\v SNetGetTurnsInTransit}{\cs27 +\par }{\cs25\uldb SNetInitializeProvider()}{\cs26\v SNetInitializeProvider}{\cs27 +\par }{\cs25\uldb SNetJoinGame()}{\cs26\v SNetJoinGame}{\cs27 +\par }{\cs25\uldb SNetLeaveGame()}{\cs26\v SNetLeaveGame}{\cs27 +\par }{\cs25\uldb SNetPerformUpgrade()}{\cs26\v SNetPerformUpgrade}{\cs27 +\par }{\cs25\uldb SNetReceiveMessage()}{\cs26\v SNetReceiveMessage}{\cs27 +\par }{\cs25\uldb SNetReceiveTurns()}{\cs26\v SNetReceiveTurns}{\cs27 +\par }{\cs25\uldb SNetRegisterEventHandler()}{\cs26\v SNetRegisterEventHandler}{\cs27 +\par }{\cs25\uldb SNetResetLatencyMeasurements()}{\cs26\v SNetResetLatencyMeasurements}{\cs27 +\par }{\cs25\uldb SNetSelectGame()}{\cs26\v SNetSelectGame}{\cs27 +\par }{\cs25\uldb SNetSelectProvider()}{\cs26\v SNetSelectProvider}{\cs27 +\par }{\cs25\uldb SNetSendMessage()}{\cs26\v SNetSendMessage}{\cs27 +\par }{\cs25\uldb SNetSendTurn()}{\cs26\v SNetSendTurn}{\cs27 +\par }{\cs25\uldb SNetStartGame()}{\cs26\v SNetStartGame}{\cs27 +\par }{\cs25\uldb SNetUnregisterEventHandler()}{\cs26\v SNetUnregisterEventHandler}{\cs27 +\par } +\par {\b Callback Functions} +\par +\par {\cs25\uldb CheckAuthProc()}{\cs26\v CheckAuthProc} +\par {\cs25\uldb CreateProc()}{\cs26\v CreateProc} +\par {\cs25\uldb DrawDescProc()}{\cs26\v DrawDescProc}{\cs27 +\par }{\cs25\uldb EnumGamesProc()}{\cs26\v EnumGamesProc}{\cs27 +\par }{\cs25\uldb EnumProvidersProc()}{\cs26\v EnumProvidersProc}{\cs27 +\par }{\cs25\uldb EventProc()}{\cs26\v EventProc}{\cs27 +\par }{\cs25\uldb GetArtProc()}{\cs26\v GetArtProc}{\cs27 +\par }{\cs25\uldb GetDataProc()}{\cs26\v GetDataProc}{\cs27 +\par }{\cs25\uldb MessageBoxProc()}{\cs26\v MessageBoxProc}{\cs27 +\par }{\cs25\uldb PlaySoundProc()}{\cs26\v PlaySoundProc}{\cs27 +\par }{\cs25\uldb StatusProc()}{\cs26\v StatusProc}{\cs27 +\par +\par }{\cs27\b Data Structures +\par +\par }{\cs25\uldb SNETCAPS}{\cs26\v SNETCAPS}{\cs27 +\par }{\cs25\uldb SNETCREATEDATA}{\cs26\v SNETCREATEDATA}{\cs27 +\par }{\cs25\uldb SNETPLAYERDATA}{\cs26\v SNETPLAYERDATA}{\cs27 +\par }{\cs25\uldb SNETPROGRAMDATA}{\cs26\v SNETPROGRAMDATA}{\cs27 +\par }{\cs25\uldb SNETUIDATA}{\cs26\v SNETUIDATA}{\cs27 +\par }{\cs25\uldb SNETVERSIONDATA}{\cs26\v SNETVERSIONDATA}{\cs27 +\par } +\par } \ No newline at end of file diff --git a/src/Storm/H/BNETART.H b/src/Storm/H/BNETART.H new file mode 100644 index 0000000..6025781 --- /dev/null +++ b/src/Storm/H/BNETART.H @@ -0,0 +1,30 @@ +/**************************************************************************** +* +* bnetart.h +* +* This file should be included by an application that wants to provide +* battle.net-specific artwork in its art callback. +* +***/ + +enum _BATTLENET_ART { + SNET_ART_BATTLE_BTNS = 0x80000000, + SNET_ART_BATTLE_CHAT_BKG, + SNET_ART_BATTLE_GREENLAG, + SNET_ART_BATTLE_YELLOWLAG, + SNET_ART_BATTLE_REDLAG, + SNET_ART_BATTLE_CONNECT_BKG, + SNET_ART_BATTLE_SELECT_CHNL_BKG, + SNET_ART_BATTLE_LOGIN_BKG, + + SNET_ART_BATTLE_BADCONNECTION, + SNET_ART_BATTLE_WELCOME_AD, + + SNET_ART_BATTLE_LRG_EDIT_POPUP_BKG, +}; + + +enum _BATTLENET_DATA { + SNET_DATA_BATTLE_LOGODELAY = 0x80000000, // (DWORD) delay between frames +}; + diff --git a/src/Storm/H/STORM.BAK b/src/Storm/H/STORM.BAK new file mode 100644 index 0000000..0c5aebf --- /dev/null +++ b/src/Storm/H/STORM.BAK @@ -0,0 +1,3330 @@ +#ifndef _STORM_H_ +#define _STORM_H_ + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import on +#endif + + +//#########################################################################// +//#########################################################################// +// // +// // +// STANDARD PROGRAMMING INTERFACE // +// // +// // +//#########################################################################// +//#########################################################################// + + +#define DECLARE_STRICT_HANDLE(name) typedef struct name##__ { int unused; } *name +#define DECLARE_DERIVED_HANDLE(name,base) typedef struct name##__ : public base##__ { int unused; } *name + + +/**************************************************************************** +* +* Error codes +* (Error text is defined in Stormerr.mc) +* +***/ + +#define STORMFAC 0x510 +#define STORMERROR(code) (0x80000000 | (STORMFAC << 16) | ((code) & 0xFFFF)) + +#define STORM_ERROR_ASSERTION STORMERROR(0) +#define STORM_ERROR_BAD_ARGUMENT STORMERROR(101) +#define STORM_ERROR_GAME_ALREADY_STARTED STORMERROR(102) +#define STORM_ERROR_GAME_FULL STORMERROR(103) +#define STORM_ERROR_GAME_NOT_FOUND STORMERROR(104) +#define STORM_ERROR_GAME_TERMINATED STORMERROR(105) +#define STORM_ERROR_INVALID_PLAYER STORMERROR(106) +#define STORM_ERROR_NO_MESSAGES_WAITING STORMERROR(107) +#define STORM_ERROR_NOT_ARCHIVE STORMERROR(108) +#define STORM_ERROR_NOT_ENOUGH_ARGUMENTS STORMERROR(109) +#define STORM_ERROR_NOT_IMPLEMENTED STORMERROR(110) +#define STORM_ERROR_NOT_IN_ARCHIVE STORMERROR(111) +#define STORM_ERROR_NOT_IN_GAME STORMERROR(112) +#define STORM_ERROR_NOT_INITIALIZED STORMERROR(113) +#define STORM_ERROR_NOT_PLAYING STORMERROR(114) +#define STORM_ERROR_NOT_REGISTERED STORMERROR(115) +#define STORM_ERROR_REQUIRES_CODEC STORMERROR(116) +#define STORM_ERROR_REQUIRES_DDRAW STORMERROR(117) +#define STORM_ERROR_REQUIRES_DSOUND STORMERROR(118) +#define STORM_ERROR_REQUIRES_UPGRADE STORMERROR(119) +#define STORM_ERROR_STILL_ACTIVE STORMERROR(120) +#define STORM_ERROR_VERSION_MISMATCH STORMERROR(121) +#define STORM_ERROR_MEMORY_ALREADY_FREED STORMERROR(122) +#define STORM_ERROR_MEMORY_CORRUPT STORMERROR(123) +#define STORM_ERROR_MEMORY_INVALID_BLOCK STORMERROR(124) +#define STORM_ERROR_MEMORY_MANAGER_INACTIVE STORMERROR(125) +#define STORM_ERROR_MEMORY_NEVER_RELEASED STORMERROR(126) +#define STORM_ERROR_HANDLE_NEVER_RELEASED STORMERROR(127) +#define STORM_ERROR_ACCESS_OUT_OF_BOUNDS STORMERROR(128) + + +/**************************************************************************** +* +* BitBlt functions +* +***/ + +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SBltDestroy (); +#endif +extern "C" BOOL APIENTRY SBltGetSCode (DWORD rop3, + LPSTR buffer, + DWORD buffersize, + BOOL optimize = 1); +extern "C" BOOL APIENTRY SBltROP3 (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Clipped (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Tiled (LPBYTE dest, + LPRECT destrect, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3); + + +/**************************************************************************** +* +* Bitmap functions +* +***/ + +#define SBMP_IMAGETYPE_AUTO 0 +#define SBMP_IMAGETYPE_BMP 1 +#define SBMP_IMAGETYPE_PCX 2 + +typedef LPVOID (APIENTRY *SBMPALLOCPROC)(DWORD); + +extern "C" BOOL APIENTRY SBmpAllocLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE *returnedbuffer, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL, + int requestedbitdepth = 0, + SBMPALLOCPROC allocproc = NULL); +extern "C" BOOL APIENTRY SBmpDecodeImage (DWORD imagetype, + LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpSaveImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height, + int bitdepth); + + +/**************************************************************************** +* +* Command line parsing functions +* +***/ + +#define SCMD_ARG_FLAGGED (0 << 24) +#define SCMD_ARG_OPTIONAL (1 << 24) +#define SCMD_ARG_REQUIRED (2 << 24) +#define SCMD_ARG_MASK (SCMD_ARG_FLAGGED | SCMD_ARG_OPTIONAL | SCMD_ARG_REQUIRED) + +#define SCMD_BOOL_SET 0 +#define SCMD_BOOL_CLEAR 1 +#define SCMD_BOOL_MASK (SCMD_BOOL_CLEAR | SCMD_BOOL_SET) + +#define SCMD_CASESENSITIVE (0x01 << 8) + +#define SCMD_NUM_UNSIGNED 0 +#define SCMD_NUM_SIGNED 1 +#define SCMD_NUM_MASK (SCMD_NUM_UNSIGNED | SCMD_NUM_SIGNED) + +#define SCMD_TYPE_BOOL (0 << 16) +#define SCMD_TYPE_NUMERIC (1 << 16) +#define SCMD_TYPE_STRING (2 << 16) +#define SCMD_TYPE_MASK (SCMD_TYPE_BOOL | SCMD_TYPE_NUMERIC | SCMD_TYPE_STRING) + +#define SCMD_ERROR_BAD_ARGUMENT STORM_ERROR_BAD_ARGUMENT +#define SCMD_ERROR_NOT_ENOUGH_ARGUMENTS STORM_ERROR_NOT_ENOUGH_ARGUMENTS +#define SCMD_ERROR_OPEN_FAILED ERROR_OPEN_FAILED + +typedef struct _CMDERROR { + DWORD errorcode; + LPCTSTR itemstr; + LPCTSTR errorstr; +} CMDERROR, *CMDERRORPTR; + +typedef struct _CMDPARAMS { + DWORD flags; + DWORD id; + LPCTSTR name; + LPVOID variable; + DWORD setvalue; + DWORD setmask; + union { + BOOL boolvalue; + LONG signedvalue; + DWORD unsignedvalue; + LPCTSTR stringvalue; + }; +} CMDPARAMS, *CMDPARAMSPTR; + +typedef BOOL (CALLBACK *SCMDCALLBACK)(CMDPARAMSPTR,LPCTSTR); +typedef void (CALLBACK *SCMDERRORCALLBACK)(CMDERRORPTR); +typedef BOOL (CALLBACK *SCMDEXTRACALLBACK)(LPCTSTR); + +typedef struct _ARGLIST { + DWORD flags; + DWORD id; + LPCTSTR name; + SCMDCALLBACK callback; +} ARGLIST, *ARGLISTPTR; + +extern "C" BOOL APIENTRY SCmdCheckId (DWORD id); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SCmdDestroy (); +#endif +extern "C" BOOL APIENTRY SCmdGetBool (DWORD id); +extern "C" DWORD APIENTRY SCmdGetNum (DWORD id); +extern "C" BOOL APIENTRY SCmdGetString (DWORD id, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SCmdProcess (LPCTSTR cmdline, + BOOL skipprogname, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback); +extern "C" BOOL APIENTRY SCmdRegisterArgList (const ARGLIST *listptr, + DWORD numargs); +extern "C" BOOL APIENTRY SCmdRegisterArgument (DWORD flags, + DWORD id, + LPCTSTR name, + LPVOID variableptr = NULL, + DWORD variablebytes = 0, + DWORD setvalue = TRUE, + DWORD setmask = 0xFFFFFFFF, + SCMDCALLBACK callback = NULL); + +#define SCmdProcessCommandLine(ext,err) SCmdProcess(GetCommandLine(),TRUE,(ext),(err)) + +#define ARGBOOL(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),TRUE,0xFFFFFFFF,callback) +#define ARGFLAG(flags,name,var,valuecallback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),value,value,callback) +#define ARGNUMBER(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_NUMERIC | (flags),0xFFFFFFFF,name,var,sizeof(var),0,0,callback) +#define ARGSTRING(flags,name,buffer,chars,callback) SCmdRegisterArgument(SCMD_TYPE_STRING | (flags),0xFFFFFFFF,name,buffer,(chars),0,0,callback) + + +/**************************************************************************** +* +* S-Code functions +* +***/ + +#define SCODE_CF_AUTOALIGNDWORD 0x00040000 +#define SCODE_CF_USESALTADJUSTS 0x04000000 + +DECLARE_STRICT_HANDLE(HSCODESTREAM); + +typedef struct _SCODEEXECUTEDATA { + DWORD size; + DWORD flags; + int xiterations; + int yiterations; + int adjustdest; + int adjustsource; + LPVOID dest; + LPVOID source; + LPVOID table; + DWORD a; + DWORD b; + DWORD c; + int adjustdestalt; + int adjustsourcealt; + DWORD reserved[2]; +} SCODEEXECUTEDATA, *SCODEEXECUTEDATAPTR; + +extern "C" BOOL APIENTRY SCodeCompile (LPCSTR prologstring, + LPCSTR loopstring, + LPCSTR *firsterror, + DWORD maxiterations, + DWORD flags, + HSCODESTREAM *handle); +extern "C" BOOL APIENTRY SCodeDelete (HSCODESTREAM handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SCodeDestroy (); +#endif +extern "C" BOOL APIENTRY SCodeExecute (HSCODESTREAM handle, + SCODEEXECUTEDATAPTR executedata); +extern "C" BOOL APIENTRY SCodeGetJumpTable (HSCODESTREAM handle, + LPBYTE **jumptableptr, + LPDWORD *prologpatchlocation, + LPDWORD *looppatchlocation, + LPDWORD *epilogpatchlocation); +extern "C" BOOL APIENTRY SCodeGetPseudocode (LPCSTR scodestring, + LPSTR buffer, + DWORD buffersize); + + +/**************************************************************************** +* +* Compression functions +* +***/ + +#define SCOMP_HINT_NONE 0 +#define SCOMP_HINT_BINARY 1 +#define SCOMP_HINT_TEXT 2 +#define SCOMP_HINT_EXECUTABLE 3 +#define SCOMP_HINT_ADPCM4 4 +#define SCOMP_HINT_ADPCM6 5 +#define SCOMP_HINTS 6 + +#define SCOMP_OPT_DEFAULT 0 +#define SCOMP_OPT_COMPRESSION 1 +#define SCOMP_OPT_SPEED 2 +#define SCOMP_OPT_QUALITY 3 + +#define SCOMP_TYPE_HUFFMAN 0x01 +#define SCOMP_TYPE_PKWARE 0x08 +#define SCOMP_TYPE_LOSSY_ADPCM_MONO 0x10 +#define SCOMP_TYPE_LOSSY_ADPCM_STEREO 0x20 + +extern "C" BOOL APIENTRY SCompCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD compressiontypes, + DWORD hint, + DWORD optimization); +extern "C" BOOL APIENTRY SCompDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize); + + +/**************************************************************************** +* +* Dialog box functions +* +***/ + +#define SDLG_ADJUST_NONE 0 +#define SDLG_ADJUST_VERTICAL 1 +#define SDLG_ADJUST_CONTROLPOS 2 + +#define SDLG_DBF_TILE 0x00000001 +#define SDLG_DBF_VCENTER 0x00000002 + +#define SDLG_STYLE_ANY 0xFFFFFFFF +#define SDLG_STYLE_ANYPUSHBUTTON 0x00010001 + +#define SDLG_USAGE_BACKGROUND 0x00000001 +#define SDLG_USAGE_NORMAL_UNFOCUSED 0x00000010 +#define SDLG_USAGE_NORMAL_FOCUSED 0x00000020 +#define SDLG_USAGE_NORMAL (SDLG_USAGE_NORMAL_UNFOCUSED | SDLG_USAGE_NORMAL_FOCUSED) +#define SDLG_USAGE_SELECTED_UNFOCUSED 0x00000040 +#define SDLG_USAGE_SELECTED_FOCUSED 0x00000080 +#define SDLG_USAGE_SELECTED (SDLG_USAGE_SELECTED_UNFOCUSED | SDLG_USAGE_SELECTED_FOCUSED) +#define SDLG_USAGE_NORMAL_GRAYED 0x00000100 +#define SDLG_USAGE_SELECTED_GRAYED 0x00000400 +#define SDLG_USAGE_GRAYED (SDLG_USAGE_NORMAL_GRAYED | SDLG_USAGE_SELECTED_GRAYED) +#define SDLG_USAGE_CURSORMASK 0x00001000 +#define SDLG_USAGE_CURSORIMAGE 0x00002000 + +extern "C" HDC APIENTRY SDlgBeginPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgBltToWindowE (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgBltToWindowI (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgCheckTimers (); +extern "C" HWND APIENTRY SDlgCreateDialogIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" HWND APIENTRY SDlgCreateDialogParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDefDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SDlgDestroy (); +#endif +extern "C" int APIENTRY SDlgDialogBoxIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" int APIENTRY SDlgDialogBoxParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDrawBitmap (HWND window, + DWORD usage, + HRGN region, + int offsetx = 0, + int offsety = 0, + LPRECT boundingoffset = NULL, + DWORD flags = 0); +extern "C" BOOL APIENTRY SDlgEndDialog (HWND window, + int result); +extern "C" BOOL APIENTRY SDlgEndPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgKillTimer (HWND window, + UINT event); +extern "C" BOOL APIENTRY SDlgSetBaseFont (int pointsize, + int weight, + DWORD flags, + DWORD family, + LPCTSTR face); +extern "C" BOOL APIENTRY SDlgSetBitmapE (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetBitmapI (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetControlBitmaps (HWND parentwindow, + LPINT controllist, + LPDWORD usagelist, + LPBYTE bitmapbits, + LPSIZE bitmapsize, + DWORD adjusttype, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetCursor (HWND window, + HCURSOR cursor, + DWORD id, + HCURSOR *oldcursor); +extern "C" BOOL APIENTRY SDlgSetSystemCursor (LPBYTE maskbitmap, + LPBYTE imagebitmap, + LPSIZE size, + DWORD id = 32512); +extern "C" BOOL APIENTRY SDlgSetTimer (HWND window, + UINT event, + UINT elapse, + TIMERPROC timerfunc); +extern "C" BOOL APIENTRY SDlgUpdateCursor (); + +#define SDlgCreateDialog(ins,tpl,wnd,prc) SDlgCreateDialogParam(ins,tpl,wnd,prc,0) +#define SDlgCreateDialogIndirect(ins,tpl,wnd,prc) SDlgCreateDialogIndirectParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBox(ins,tpl,wnd,prc) SDlgDialogBoxParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBoxIndirect(ins,tpl,wnd,prc) SDlgDialogBoxIndirectParam(ins,tpl,wnd,prc,0) + +#ifdef SDLG_USE_INCLUSIVE_RECTS +#define SDlgBltToWindow SDlgBltToWindowI +#define SDlgSetBitmap SDlgSetBitmapI +#else +#define SDlgBltToWindow SDlgBltToWindowE +#define SDlgSetBitmap SDlgSetBitmapE +#endif + +/**************************************************************************** +* +* DirectDraw functions +* +***/ + +#define SDRAW_SERVICE_BASIC 1 +#define SDRAW_SERVICE_PAGEFLIP 2 +#define SDRAW_SERVICE_DOUBLEBUFFER 3 +#define SDRAW_SERVICE_MAX 3 + +#define SDRAW_SURFACE_FRONT 0 +#define SDRAW_SURFACE_BACK 1 +#define SDRAW_SURFACE_SYSTEM 2 +#define SDRAW_SURFACE_TEMPORARY 3 + +#ifndef MAC +extern "C" BOOL APIENTRY SDrawAutoInitialize (HINSTANCE instance, + LPCTSTR classname, + LPCTSTR title, + WNDPROC wndproc = NULL, + int servicelevel = SDRAW_SERVICE_BASIC, + int width = 640, + int height = 480, + int bitdepth = 8); +extern "C" BOOL APIENTRY SDrawCaptureScreen (LPCTSTR filename = NULL); +#endif +extern "C" BOOL APIENTRY SDrawClearSurface (int surfacenumber); +extern "C" BOOL APIENTRY SDrawDestroy (); +extern "C" BOOL APIENTRY SDrawFlipPage (); +extern "C" HWND APIENTRY SDrawGetFrameWindow (HWND *window = NULL); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawGetObjects (LPDIRECTDRAW *directdraw, + LPDIRECTDRAWSURFACE *frontbuffer, + LPDIRECTDRAWSURFACE *backbuffer, + LPDIRECTDRAWSURFACE *systembuffer, + LPDIRECTDRAWSURFACE *temporarybuffer, + LPDIRECTDRAWPALETTE *palette, + HPALETTE *gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawGetScreenSize (int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SDrawGetServiceLevel (int *servicelevel = NULL); +extern "C" BOOL APIENTRY SDrawLockSurface (int surfacenumber, + LPCRECT rect, + LPBYTE *ptr, + int *pitch = NULL, + DWORD flags = 0); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawManualInitialize (HWND framewindow, + LPDIRECTDRAW directdraw, + LPDIRECTDRAWSURFACE frontbuffer, + LPDIRECTDRAWSURFACE backbuffer, + LPDIRECTDRAWSURFACE systembuffer, + LPDIRECTDRAWSURFACE temporarybuffer, + LPDIRECTDRAWPALETTE palette, + HPALETTE gdipalette); +#endif +extern "C" int APIENTRY SDrawMessageBox (LPCTSTR text, + LPCTSTR title, + UINT flags); +extern "C" BOOL APIENTRY SDrawPostClose (); +extern "C" BOOL APIENTRY SDrawRealizePalette (); +#ifndef MAC +extern "C" BOOL APIENTRY SDrawSelectGdiSurface (BOOL select, BOOL copy); +#endif +extern "C" BOOL APIENTRY SDrawUnlockSurface (int surfacenumber, + LPBYTE ptr, + DWORD numrects = 0, + LPCRECT rectarray = NULL); +extern "C" BOOL APIENTRY SDrawUpdatePalette (DWORD firstentry, + DWORD numentries, + LPPALETTEENTRY entries, + BOOL reservedentries = FALSE); +extern "C" BOOL APIENTRY SDrawUpdateScreen (LPCRECT rect); +#ifdef MAC +extern "C" BOOL APIENTRY SDrawVidDriverInitialize (HWND framewindow, + int servicelevel); +#endif + + +/**************************************************************************** +* +* Error handling functions +* +***/ + +#define SERR_LINECODE_FUNCTION -1 +#define SERR_LINECODE_OBJECT -2 +#define SERR_LINECODE_HANDLE -3 +#define SERR_LINECODE_FILE -4 + +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SErrDestroy (); +#endif +extern "C" BOOL APIENTRY SErrDisplayError (DWORD errorcode, + LPCTSTR filename, + int linenumber, + LPCTSTR description, + BOOL recoverable, + UINT exitcode = 1); +extern "C" BOOL APIENTRY SErrGetErrorStr (DWORD errorcode, + LPTSTR buffer, + DWORD bufferchars); +extern "C" DWORD APIENTRY SErrGetLastError (); +extern "C" BOOL APIENTRY SErrRegisterMessageSource (WORD facility, + HMODULE module, + LPVOID reserved = NULL); +extern "C" void APIENTRY SErrReportResourceLeak (LPCTSTR handlename); +extern "C" void APIENTRY SErrSetLastError (DWORD errorcode); +extern "C" void APIENTRY SErrSuppressErrors (BOOL suppress); + +#define SErrGetLastErrorStr(buf,len) SErrGetErrorStr(SErrGetLastError(),buf,len) +#define FATALRESULT(str) SErrDisplayError(SErrGetLastError(),str,SERR_LINECODE_FUNCTION,NULL,FALSE) +#define REPORTRESOURCELEAK(handle) SErrReportResourceLeak(#handle) + +#ifdef _DEBUG +#define ASSERT(a) if (!(a)) \ + SErrDisplayError(STORM_ERROR_ASSERTION, \ + __FILE__, \ + __LINE__, \ + #a, \ + FALSE) +#define VALIDATEBEGIN do { +#define VALIDATE(a) ASSERT(a) +#define VALIDATEANDBLANK(a) do { \ + ASSERT(a); \ + *(a) = 0; \ + } while (0) +#define VALIDATEEND } while (0) +#define VALIDATEENDVOID } while (0) +#else +#define ASSERT(a) +#define VALIDATEBEGIN do { \ + int intrn_valresult = -1 +#define VALIDATE(a) intrn_valresult &= (a) ? -1 : 0 +#define VALIDATEANDBLANK(a) if (a) \ + *a = 0; \ + else \ + intrn_valresult = 0 +#define VALIDATEEND if (!intrn_valresult) { \ + SErrSetLastError( \ + ERROR_INVALID_PARAMETER); \ + return 0; \ + } \ + } while (0) +#define VALIDATEENDVOID if (!intrn_valresult) { \ + SErrSetLastError( \ + ERROR_INVALID_PARAMETER); \ + return; \ + } \ + } while (0) +#endif + + +/**************************************************************************** +* +* Event dispatching functions +* +***/ + +typedef void (CALLBACK *SEVTHANDLER)(LPVOID); + +extern "C" BOOL APIENTRY SEvtBreakHandlerChain (LPVOID data); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SEvtDestroy (); +#endif +extern "C" BOOL APIENTRY SEvtDispatch (DWORD type, + DWORD subtype, + DWORD id, + LPVOID data); +extern "C" BOOL APIENTRY SEvtPopState (DWORD type, + DWORD subtype); +extern "C" BOOL APIENTRY SEvtPushState (DWORD type, + DWORD subtype); +extern "C" BOOL APIENTRY SEvtRegisterHandler (DWORD type, + DWORD subtype, + DWORD id, + DWORD flags, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterHandler (DWORD type, + DWORD subtype, + DWORD id, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterType (DWORD type, + DWORD subtype); + + +/**************************************************************************** +* +* File I/O functions +* +***/ + +#define SFILE_AUTH_UNABLETOAUTHENTICATE 0 +#define SFILE_AUTH_NOSIGNATURE 1 +#define SFILE_AUTH_BADSIGNATURE 2 +#define SFILE_AUTH_UNKNOWNSIGNATURE 3 +#define SFILE_AUTH_FIRSTAUTHENTIC 5 +#define SFILE_AUTH_AUTHENTICBLIZZARD 5 + +#define SFILE_DDA_LOOP 0x00040000 + +#define SFILE_ERROR_BAD_FORMAT ERROR_BAD_FORMAT +#define SFILE_ERROR_BAD_PATHNAME ERROR_BAD_PATHNAME +#define SFILE_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED +#define SFILE_ERROR_FILE_INVALID ERROR_FILE_INVALID +#define SFILE_ERROR_FILE_NOT_FOUND ERROR_FILE_NOT_FOUND +#define SFILE_ERROR_HANDLE_EOF ERROR_HANDLE_EOF +#define SFILE_ERROR_INVALID_DATA ERROR_INVALID_DATA +#define SFILE_ERROR_INVALID_DRIVE ERROR_INVALID_DRIVE +#define SFILE_ERROR_INVALID_HANDLE ERROR_INVALID_HANDLE +#define SFILE_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SFILE_ERROR_NOT_ARCHIVE STORM_ERROR_NOT_ARCHIVE +#define SFILE_ERROR_NOT_AUTHENTICATED ERROR_NOT_AUTHENTICATED +#define SFILE_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SFILE_ERROR_NOT_IN_ARCHIVE STORM_ERROR_NOT_IN_ARCHIVE +#define SFILE_ERROR_NOT_INITIALIZED STORM_ERROR_NOT_INITIALIZED +#define SFILE_ERROR_NOT_PLAYING STORM_ERROR_NOT_PLAYING + +#define SFILE_ERRORMODE_RETURNCODE 0 +#define SFILE_ERRORMODE_CUSTOM 1 +#define SFILE_ERRORMODE_FATAL 2 + +#define SFILE_FIND_FILES 0x00000001 +#define SFILE_FIND_DIRECTORIES 0x00000002 + +DECLARE_STRICT_HANDLE(HSARCHIVE); +DECLARE_STRICT_HANDLE(HSFILE); + +typedef BOOL (CALLBACK *SFILEERRORPROC)(LPCTSTR,DWORD); + +extern "C" BOOL APIENTRY SFileAuthenticateArchive (HSARCHIVE archive, + DWORD *extendedresult); +extern "C" BOOL APIENTRY SFileCloseArchive (HSARCHIVE handle); +extern "C" BOOL APIENTRY SFileCloseFile (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaBegin (HSFILE handle, + DWORD buffersize, + DWORD flags); +extern "C" BOOL APIENTRY SFileDdaBeginEx (HSFILE handle, + DWORD buffersize, + DWORD flags, + DWORD offset, + LONG volume, + LONG pan, + LPVOID reserved); +extern "C" BOOL APIENTRY SFileDdaDestroy (); +extern "C" BOOL APIENTRY SFileDdaEnd (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaGetPos (HSFILE handle, + DWORD *position, + DWORD *maxposition); +extern "C" BOOL APIENTRY SFileDdaGetVolume (HSFILE handle, + LONG *volume, + LONG *pan); +#ifdef __DSOUND_INCLUDED__ +extern "C" BOOL APIENTRY SFileDdaInitialize (LPDIRECTSOUND directsound); +#endif +extern "C" BOOL APIENTRY SFileDdaSetVolume (HSFILE handle, + LONG volume, + LONG pan); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SFileDestroy (); +#endif +extern "C" BOOL APIENTRY SFileEnableDirectAccess (BOOL enable); +extern "C" BOOL APIENTRY SFileGetArchiveInfo (HSARCHIVE archive, + int *priority, + BOOL *cdrom); +extern "C" BOOL APIENTRY SFileGetArchiveName (HSARCHIVE archive, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SFileGetBasePath (LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SFileGetFileArchive (HSFILE file, + HSARCHIVE *archive); +extern "C" BOOL APIENTRY SFileGetFileName (HSFILE file, + LPTSTR buffer, + DWORD bufferchars); +extern "C" DWORD APIENTRY SFileGetFileSize (HSFILE handle, + LPDWORD filesizehigh = NULL); +extern "C" BOOL APIENTRY SFileOpenArchive (LPCTSTR archivename, + int priority, + BOOL cdonly, + HSARCHIVE *handle); +extern "C" BOOL APIENTRY SFileOpenFile (LPCTSTR filename, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileEx (HSARCHIVE archivehandle, + LPCTSTR filename, + DWORD flags, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileReadFile (HSFILE handle, + LPVOID buffer, + DWORD bytestoread, + LPDWORD bytesread = NULL, + LPOVERLAPPED overlapped = NULL); +extern "C" BOOL APIENTRY SFileSetBasePath (LPCTSTR path); +extern "C" DWORD APIENTRY SFileSetFilePointer (HSFILE handle, + LONG distancetomove, + PLONG distancetomovehigh, + DWORD movemethod); +extern "C" BOOL APIENTRY SFileSetIoErrorMode (DWORD errormode, + SFILEERRORPROC errorproc = NULL); +extern "C" BOOL APIENTRY SFileSetLocale (LCID lcid); + + +/**************************************************************************** +* +* GDI functions +* +***/ + +#define ETO_TEXT_TRANSPARENT 0 +#define ETO_TEXT_COLOR 1 +#define ETO_TEXT_BLACK 2 +#define ETO_TEXT_WHITE 3 +#define ETO_BKG_TRANSPARENT 0 +#define ETO_BKG_COLOR 1 +#define ETO_BKG_BLACK 2 +#define ETO_BKG_WHITE 3 + +DECLARE_STRICT_HANDLE(HSGDIOBJ); +DECLARE_DERIVED_HANDLE(HSGDIFONT,HSGDIOBJ); + +extern "C" BOOL APIENTRY SGdiBitBlt (LPBYTE videobuffer, + int destx, + int desty, + LPBYTE sourcedata, + LPRECT sourcerect, + int sourcecx, + int sourcecy, + COLORREF color = 0, + DWORD rop = SRCCOPY); +extern "C" BOOL APIENTRY SGdiCreateFont (LPBYTE bits, + int width, + int height, + int bitdepth, + int filecharwidth, + int filecharheight, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiDeleteObject (HSGDIOBJ handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SGdiDestroy (); +#endif +extern "C" BOOL APIENTRY SGdiExtTextOut (LPBYTE videobuffer, + int x, + int y, + LPRECT rect, + COLORREF color, + int textcoloruse, + int bkgcoloruse, + LPCTSTR string, + int chars = -1); +extern "C" BOOL APIENTRY SGdiGetTextExtent (LPCTSTR string, + int chars, + LPSIZE size); +extern "C" BOOL APIENTRY SGdiImportFont (HFONT windowsfont, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiLoadFont (LPCTSTR filename, + int filecharwidth, + int filecharheight, + int basecharwidth, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiRectangle (LPBYTE videobuffer, + int left, + int top, + int right, + int bottom, + COLORREF color); +extern "C" BOOL APIENTRY SGdiSelectObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiSetPitch (int pitch); +extern "C" BOOL APIENTRY SGdiSetTargetDimensions (int width, + int height, + int bitdepth, + int pitch); +extern "C" BOOL APIENTRY SGdiTextOut (LPBYTE videobuffer, + int x, + int y, + COLORREF color, + LPCTSTR string, + int chars = -1); + + +/**************************************************************************** +* +* Logging functions +* +***/ + +DECLARE_STRICT_HANDLE(HSLOG); + +extern "C" void APIENTRY SLogClose (HSLOG log); +extern "C" BOOL APIENTRY SLogCreate (LPCTSTR filename, + DWORD flags, + HSLOG *log); +#ifdef STORMSTATIC +extern "C" void APIENTRY SLogDestroy (); +#endif +extern "C" void APIENTRY SLogDump (HSLOG log, + LPCVOID data, + DWORD bytes); +extern "C" void APIENTRY SLogFlush (HSLOG log); +extern "C" void APIENTRY SLogFlushAll (); +#ifdef STORMSTATIC +extern "C" void APIENTRY SLogInitialize (); +#endif +extern "C" void __cdecl SLogPend (HSLOG log, + LPCTSTR format, + ...); +extern "C" void __cdecl SLogWrite (HSLOG log, + LPCTSTR format, + ...); + + +/**************************************************************************** +* +* Memory allocation functions +* +***/ + +#define SMEM_FLAG_ZEROMEMORY 0x00000008 +#define SMEM_FLAG_PRESERVEONDESTROY 0x08000000 + +DECLARE_STRICT_HANDLE(HSHEAP); + +typedef struct _SMEMBLOCKDETAILS { + DWORD size; + LPVOID ptr; + BOOL allocated; + BOOL valid; + DWORD bytes; + DWORD overhead; +} SMEMBLOCKDETAILS, *LPSMEMBLOCKDETAILS; + +typedef struct _SMEMHEAPDETAILS { + DWORD size; + HSHEAP handle; + char filename[MAX_PATH]; + int linenumber; + DWORD regions; + DWORD committedbytes; + DWORD reservedbytes; + DWORD maximumsize; + DWORD allocatedblocks; +} SMEMHEAPDETAILS, *LPSMEMHEAPDETAILS; + +extern "C" LPVOID APIENTRY SMemAlloc (DWORD bytes, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SMemDestroy (); +#endif +extern "C" BOOL APIENTRY SMemFindNextBlock (HSHEAP heap, + LPVOID prevblock, + LPVOID *nextblock, + LPSMEMBLOCKDETAILS details); +extern "C" BOOL APIENTRY SMemFindNextHeap (HSHEAP prevheap, + HSHEAP *nextheap, + LPSMEMHEAPDETAILS details); +extern "C" BOOL APIENTRY SMemFree (LPVOID ptr, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" HSHEAP APIENTRY SMemGetHeapByCaller (LPCSTR filename, + int linenumber); +extern "C" HSHEAP APIENTRY SMemGetHeapByPtr (LPVOID ptr); +extern "C" LPVOID APIENTRY SMemHeapAlloc (HSHEAP handle, + DWORD flags, + DWORD bytes); +extern "C" HSHEAP APIENTRY SMemHeapCreate (DWORD options, + DWORD initialsize, + DWORD maximumsize); +extern "C" BOOL APIENTRY SMemHeapDestroy (HSHEAP handle); +extern "C" BOOL APIENTRY SMemHeapFree (HSHEAP handle, + DWORD flags, + LPVOID ptr); +#ifdef STORMSTATIC +extern "C" void APIENTRY SMemInitialize (); +#endif + +inline void __cdecl operator delete (void *ptr) { + if (ptr) + SMemFree(ptr,__FILE__,__LINE__,0); +} + +inline void * __cdecl operator new (size_t bytes) { + return SMemAlloc(bytes,__FILE__,__LINE__,0); +} + +#ifndef __ICL +#ifndef __MWERKS__ +inline void __cdecl operator delete[] (void *ptr) { + if (ptr) + SMemFree(ptr,__FILE__,__LINE__,0); +} + +inline void * __cdecl operator new[] (size_t bytes) { + return SMemAlloc(bytes,__FILE__,__LINE__,0); +} +#endif +#endif + +#ifndef __PLACEMENT_NEW_INLINE +#define __PLACEMENT_NEW_INLINE +inline void * __cdecl operator new (size_t, void *ptr) { + return (ptr); +} + +inline void * __cdecl operator new[] (size_t, void *ptr) { + return (ptr); +} +#endif + +#define ALLOC(bytes) SMemAlloc(bytes,__FILE__,__LINE__,0) +#define ALLOCZERO(bytes) SMemAlloc(bytes,__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) +#define DEL(ptr) delete(ptr) +#define DELIFUSED(ptr) delete(ptr) +#define FREE(ptr) SMemFree(ptr,__FILE__,__LINE__,0) +#define FREEIFUSED(ptr) do if (ptr) SMemFree(ptr,__FILE__,__LINE__,0); while (0) +#define NEW(struct) (new(SMemAlloc(sizeof(struct),__FILE__,__LINE__,0)) struct) +#define NEWZERO(struct) (new(SMemAlloc(sizeof(struct),__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY)) struct) + + +/**************************************************************************** +* +* Message functions +* +***/ + +typedef struct _PARAMS { + HWND window; + UINT message; + WPARAM wparam; + LPARAM lparam; + UINT notifycode; + LPVOID extra; + BOOL useresult; + LRESULT result; +} PARAMS, *PARAMSPTR, *LPPARAMS; + +typedef BOOL (CALLBACK *SMSGIDLEPROC)(DWORD); +typedef void (CALLBACK *SMSGHANDLER)(LPPARAMS); + +extern "C" BOOL APIENTRY SMsgBreakHandlerChain (LPPARAMS params); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SMsgDestroy (); +#endif +extern "C" BOOL APIENTRY SMsgDispatchMessage (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL *useresult, + LRESULT *result); +extern "C" BOOL APIENTRY SMsgDoMessageLoop (SMSGIDLEPROC idleproc = NULL, + BOOL cleanuponquit = TRUE); +extern "C" BOOL APIENTRY SMsgPopRegisterState (HWND window); +extern "C" BOOL APIENTRY SMsgPushRegisterState (HWND window); +extern "C" BOOL APIENTRY SMsgRegisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); + + +/**************************************************************************** +* +* Networking functions +* +***/ + +#define SNET_ART_BACKGROUND 0 +#define SNET_ART_BUTTONTEXTURE 1 +#define SNET_ART_JOINBACKGROUND 2 +#define SNET_ART_HELPBACKGROUND 3 +#define SNET_ART_POPUPBACKGROUND 4 +#define SNET_ART_BUTTON_XSML 5 +#define SNET_ART_BUTTON_SML 6 +#define SNET_ART_BUTTON_MED 7 +#define SNET_ART_BUTTON_LRG 8 +#define SNET_ART_APP_LOGO_SML 9 +#define SNET_ART_PROGRESS_BACKGROUND 10 +#define SNET_ART_PROGRESS_FILLER 11 +#define SNET_ART_POPUPBACKGROUND_SML 12 +#define SNET_ART_SCROLLBARARROWS 13 +#define SNET_ART_SCROLLTHUMB 14 +#define SNET_ART_SCROLLBAR 15 +#define SNET_ART_COMBOLEFT 16 +#define SNET_ART_COMBOMIDDLE 17 +#define SNET_ART_COMBORIGHT 18 + +#define SNET_AUTHTYPE_CHANNEL 1 +#define SNET_AUTHTYPE_GAME 2 + +#define SNET_BROADCASTNONLOCALPLAYERID 0xFFFFFFFE +#define SNET_BROADCASTPLAYERID 0xFFFFFFFF +#define SNET_INVALIDPLAYERID 0xFFFFFFFF + +#define SNET_CAPS_PAGELOCKEDBUFFERS 0x00000001 +#define SNET_CAPS_BASICINTERFACE 0x00000002 +#define SNET_CAPS_DEBUGONLY 0x10000000 +#define SNET_CAPS_RETAILONLY 0x20000000 + +#define SNET_CF_ALLOWPRIVATEGAMES 0x00000001 + +#define SNET_DATA_SYSCOLORS 1 +#define SNET_DATA_CURSORLINK 2 +#define SNET_DATA_CURSORARROW 3 +#define SNET_DATA_CURSORIBEAM 4 + +#define SNET_DDF_INCLUDENAME 0x00000001 +#define SNET_DDF_MULTILINE 0x00000002 + +#define SNET_DDPF_BLIZZARD 0x00000001 +#define SNET_DDPF_MODERATOR 0x00000002 +#define SNET_DDPF_SPEAKER 0x00000004 +#define SNET_DDPF_SYSOP 0x00000008 +#define SNET_DDPF_SQUELCHED 0x00000020 + +#define SNET_DRAWTYPE_GAME 1 +#define SNET_DRAWTYPE_PLAYER 2 + +#define SNET_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS +#define SNET_ERROR_BAD_PROVIDER ERROR_BAD_PROVIDER +#define SNET_ERROR_CANCELLED ERROR_CANCELLED +#define SNET_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SNET_ERROR_INVALID_PLAYER STORM_ERROR_INVALID_PLAYER +#define SNET_ERROR_GAME_ALREADY_STARTED STORM_ERROR_GAME_ALREADY_STARTED +#define SNET_ERROR_GAME_FULL STORM_ERROR_GAME_FULL +#define SNET_ERROR_GAME_NOT_FOUND STORM_ERROR_GAME_NOT_FOUND +#define SNET_ERROR_GAME_TERMINATED STORM_ERROR_GAME_TERMINATED +#define SNET_ERROR_HOST_UNREACHABLE ERROR_HOST_UNREACHABLE +#define SNET_ERROR_MAX_THRDS_REACHED ERROR_MAX_THRDS_REACHED +#define SNET_ERROR_NETWORK_BUSY ERROR_NETWORK_BUSY +#define SNET_ERROR_NO_MESSAGES_WAITING STORM_ERROR_NO_MESSAGES_WAITING +#define SNET_ERROR_NO_NETWORK ERROR_NO_NETWORK +#define SNET_ERROR_NOT_CONNECTED ERROR_NOT_CONNECTED +#define SNET_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SNET_ERROR_NOT_IMPLEMENTED STORM_ERROR_NOT_IMPLEMENTED +#define SNET_ERROR_NOT_IN_GAME STORM_ERROR_NOT_IN_GAME +#define SNET_ERROR_NOT_OWNER ERROR_NOT_OWNER +#define SNET_ERROR_NOT_REGISTERED STORM_ERROR_NOT_REGISTERED +#define SNET_ERROR_REQUIRES_UPGRADE STORM_ERROR_REQUIRES_UPGRADE +#define SNET_ERROR_STILL_ACTIVE STORM_ERROR_STILL_ACTIVE +#define SNET_ERROR_TOO_MANY_NAMES ERROR_TOO_MANY_NAMES +#define SNET_ERROR_VERSION_MISMATCH STORM_ERROR_VERSION_MISMATCH + +#define SNET_EVENT_INITDATA 1 +#define SNET_EVENT_PLAYERJOIN 2 +#define SNET_EVENT_PLAYERLEAVE 3 +#define SNET_EVENT_SERVERMESSAGE 4 + +#define SNET_EXIT_AUTO_JOINING 0x00000001 +#define SNET_EXIT_AUTO_NEWGAME 0x00000002 +#define SNET_EXIT_AUTO_SHUTDOWN 0x00000003 +#define SNET_EXIT_PLAYERQUIT 0x40000001 +#define SNET_EXIT_PLAYERKILLED 0x40000002 +#define SNET_EXIT_PLAYERWON 0x40000004 +#define SNET_EXIT_GAMEOVER 0x40000005 +#define SNET_EXIT_NOTRESPONDING 0x40000006 + +#define SNET_GM_PRIVATE 0x00000001 +#define SNET_GM_FULL 0x00000002 +#define SNET_GM_ADVERTISED 0x00000004 +#define SNET_GM_UNJOINABLE 0x00000008 +#define SNET_GM_UNLISTEDMASK (SNET_GM_PRIVATE | SNET_GM_FULL | SNET_GM_UNJOINABLE) + +#define SNET_INFO_GAMENAME 1 +#define SNET_INFO_GAMEPASSWORD 2 +#define SNET_INFO_GAMEDESCRIPTION 3 +#define SNET_INFO_GAMEMODE 4 +#define SNET_INFO_INITDATA 5 +#define SNET_INFO_MAXPLAYERS 6 + +#define SNET_LMT_EXPECTED 1 +#define SNET_LMT_CURRENT 2 +#define SNET_LMT_PEAK 4 + +#define SNET_PERFID_TURN 1 +#define SNET_PERFID_TURNSSENT 4 +#define SNET_PERFID_TURNSRECV 5 +#define SNET_PERFID_MSGSENT 6 +#define SNET_PERFID_MSGRECV 7 +#define SNET_PERFID_USERBYTESSENT 8 +#define SNET_PERFID_USERBYTESRECV 9 +#define SNET_PERFID_TOTALBYTESSENT 10 +#define SNET_PERFID_TOTALBYTESRECV 11 +#define SNET_PERFID_PKTSENTONWIRE 12 +#define SNET_PERFID_PKTRECVONWIRE 13 +#define SNET_PERFID_BYTESSENTONWIRE 14 +#define SNET_PERFID_BYTESRECVONWIRE 15 +#define SNET_PERFIDNUM 16 + +#define SNET_PERFTYPE_COUNTER 0x10410400 +#define SNET_PERFTYPE_RAWCOUNT 0x00010000 + +#define SNET_PSF_ACTIVE 0x00010000 +#define SNET_PSF_TURNAVAILABLE 0x00020000 +#define SNET_PSF_RESPONDING 0x00040000 + +#define SNET_SF_ALLOWCREATE 0x00000001 + +#define SNET_SND_CHANGEFOCUS 0 +#define SNET_SND_SELECTITEM 1 + +#define SNET_UPGRADE_FAILED -1 +#define SNET_UPGRADE_NOT_NEEDED 0 +#define SNET_UPGRADE_SUCCEEDED 1 +#define SNET_UPGRADING_TERMINATE 2 + +#define SNET_MAXNAMELENGTH 128 +#define SNET_MAXDESCLENGTH 128 + +typedef struct _SNETCAPS { + DWORD size; + DWORD flags; + DWORD maxmessagesize; + DWORD maxqueuesize; + DWORD maxplayers; + DWORD bytessec; + DWORD latencyms; + DWORD defaultturnssec; + DWORD defaultturnsintransit; +} SNETCAPS, *SNETCAPSPTR; + +typedef struct _SNETCREATEDATA { + DWORD size; + DWORD providerid; + DWORD maxplayers; + DWORD createflags; +} SNETCREATEDATA, *SNETCREATEDATAPTR; + +typedef struct _SNET_DATA_SYSCOLORTABLE { + DWORD syscolor; + COLORREF rgb; +} SNET_DATA_SYSCOLORTABLE, *SNET_DATA_SYSCOLORTABLEPTR; + +typedef struct _SNETEVENT { + DWORD eventid; + DWORD playerid; + LPVOID data; + DWORD databytes; +} SNETEVENT, *SNETEVENTPTR; + +typedef struct _SNETGAME { + DWORD size; + DWORD id; + LPCSTR gamename; + LPCSTR gamedescription; + DWORD categorybits; + DWORD numplayers; + DWORD maxplayers; +} SNETGAME, *SNETGAMEPTR; + +struct _SNETPROGRAMDATA; +struct _SNETPLAYERDATA; +struct _SNETUIDATA; +struct _SNETVERSIONDATA; + +typedef BOOL (CALLBACK *SNETABORTPROC )(); +typedef void (CALLBACK *SNETADDCATEGORYPROC )(LPCSTR,DWORD,DWORD); +typedef void (CALLBACK *SNETCATEGORYLISTPROC )(_SNETPLAYERDATA *,SNETADDCATEGORYPROC); +typedef BOOL (CALLBACK *SNETCATEGORYPROC )(BOOL,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *,DWORD *); +typedef BOOL (CALLBACK *SNETCHECKAUTHPROC )(DWORD,LPCSTR,LPCSTR,DWORD,LPCSTR,LPSTR,DWORD); +typedef BOOL (CALLBACK *SNETCREATEPROC )(SNETCREATEDATAPTR,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *); +typedef BOOL (CALLBACK *SNETDRAWDESCPROC )(DWORD,DWORD,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,LPDRAWITEMSTRUCT); +typedef BOOL (CALLBACK *SNETENUMDEVICESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMGAMESEXPROC )(SNETGAMEPTR); +typedef BOOL (CALLBACK *SNETENUMGAMESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMPROVIDERSPROC)(DWORD,LPCSTR,LPCSTR,SNETCAPSPTR); +typedef void (CALLBACK *SNETEVENTPROC )(SNETEVENTPTR); +typedef BOOL (CALLBACK *SNETGETARTPROC )(DWORD,DWORD,LPPALETTEENTRY,LPBYTE,DWORD,int *,int *,int *); +typedef BOOL (CALLBACK *SNETGETDATAPROC )(DWORD,DWORD,LPVOID,DWORD,DWORD *); +typedef int (CALLBACK *SNETMESSAGEBOXPROC )(HWND,LPCSTR,LPCSTR,UINT); +typedef BOOL (CALLBACK *SNETPLAYSOUNDPROC )(DWORD,DWORD,DWORD); +typedef BOOL (CALLBACK *SNETSELECTEDPROC )(DWORD,SNETCAPSPTR,_SNETUIDATA *,_SNETVERSIONDATA *); +typedef BOOL (CALLBACK *SNETSTATUSPROC )(LPCSTR,DWORD,DWORD,DWORD,SNETABORTPROC); +typedef BOOL (CALLBACK *SNETPROFILEPROC )(); // tbd -- include callback to save info +typedef BOOL (CALLBACK *SNETNEWACCOUNTPROC )(); // tbd -- include callback to try to create + +typedef struct _SNETPLAYERDATA { + DWORD size; + LPCSTR playername; + LPCSTR playerdescription; + // new for 1.05: + LPCSTR displayedfields; +} SNETPLAYERDATA, *SNETPLAYERDATAPTR; + +typedef struct _SNETPROGRAMDATA { + DWORD size; + LPCSTR programname; + LPCSTR programdescription; + DWORD programid; + DWORD versionid; + DWORD reserved1; + DWORD maxplayers; + LPVOID initdata; + DWORD initdatabytes; + LPVOID reserved2; + DWORD optcategorybits; +} SNETPROGRAMDATA, *SNETPROGRAMDATAPTR; + +typedef struct _SNETUIDATA { + DWORD size; + DWORD uiflags; + HWND parentwindow; + SNETGETARTPROC artcallback; + SNETCHECKAUTHPROC authcallback; + SNETCREATEPROC createcallback; + SNETDRAWDESCPROC drawdesccallback; + SNETSELECTEDPROC selectedcallback; + SNETMESSAGEBOXPROC messageboxcallback; + SNETPLAYSOUNDPROC soundcallback; + SNETSTATUSPROC statuscallback; + SNETGETDATAPROC getdatacallback; + SNETCATEGORYPROC categorycallback; + // new for 1.05: + SNETCATEGORYLISTPROC categorylistcallback; + SNETNEWACCOUNTPROC newaccountcallback; + SNETPROFILEPROC profilecallback; +} SNETUIDATA, *SNETUIDATAPTR; + +typedef struct _SNETVERSIONDATA { + DWORD size; + LPCSTR versionstring; + LPCSTR executablefile; + LPCSTR originalarchivefile; + LPCSTR patcharchivefile; +} SNETVERSIONDATA, *SNETVERSIONDATAPTR; + +extern "C" BOOL APIENTRY SNetCreateGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamecategorybits, + LPVOID initdata, + DWORD initdatabytes, + DWORD maxplayers, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetDestroy (); +extern "C" BOOL APIENTRY SNetDropPlayer (DWORD playerid, DWORD exitcode); +extern "C" BOOL APIENTRY SNetEnumDevices (SNETENUMDEVICESPROC callback); +extern "C" BOOL APIENTRY SNetEnumGames (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumGamesEx (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESEXPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumProviders (SNETCAPSPTR mincaps, + SNETENUMPROVIDERSPROC callback); +extern "C" BOOL APIENTRY SNetGetGameInfo (DWORD index, + LPVOID buffer, + DWORD buffersize, + DWORD *byteswritten); +extern "C" BOOL APIENTRY SNetGetNetworkLatency (DWORD measurementtype, + DWORD *result); +extern "C" BOOL APIENTRY SNetGetNumPlayers (DWORD *firstplayerid, + DWORD *lastplayerid, + DWORD *activeplayers); +extern "C" BOOL APIENTRY SNetGetOwnerId (DWORD *playerid); +extern "C" BOOL APIENTRY SNetGetOwnerTurnsWaiting (DWORD *turns); +extern "C" BOOL APIENTRY SNetGetPerformanceData (DWORD counterid, + DWORD *countervalue, + DWORD *countertype, + LONG *counterscale, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +extern "C" BOOL APIENTRY SNetGetPlayerCaps (DWORD playerid, + SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetPlayerName (DWORD playerid, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SNetGetProviderCaps (SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetTurnsInTransit (DWORD *turns); +extern "C" BOOL APIENTRY SNetInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetInitializeProvider (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetJoinGame (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetLeaveGame (DWORD exitcode); +extern "C" BOOL APIENTRY SNetPerformUpgrade (DWORD *upgradestatus); +extern "C" BOOL APIENTRY SNetReceiveMessage (DWORD *senderplayerid, + LPVOID *data, + DWORD *databytes); +extern "C" BOOL APIENTRY SNetReceiveTurns (DWORD firstplayerid, + DWORD arraysize, + LPVOID *arraydata, + LPDWORD arraydatabytes, + LPDWORD arrayplayerstatus); +extern "C" BOOL APIENTRY SNetRegisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); +extern "C" BOOL APIENTRY SNetResetLatencyMeasurements (); +extern "C" BOOL APIENTRY SNetSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY SNetSendMessage (DWORD targetplayerid, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSendServerChatCommand (LPCSTR command); +extern "C" BOOL APIENTRY SNetSendTurn (LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSetBasePlayer (DWORD playerid); +extern "C" BOOL APIENTRY SNetSetGameMode (DWORD modeflags); +extern "C" BOOL APIENTRY SNetUnregisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); + + +/**************************************************************************** +* +* Networking service provider interface +* +***/ + +#define SNETSPI_MAXCLIENTDATA 256 +#define SNETSPI_MAXSTRINGLENGTH 128 + +typedef struct _SNETADDR { + BYTE address[16]; +} SNETADDR, *SNETADDRPTR; + +typedef struct _SNETSPI_DEVICELIST { + DWORD deviceid; + SNETCAPS devicecaps; + char devicename[SNETSPI_MAXSTRINGLENGTH]; + char devicedescription[SNETSPI_MAXSTRINGLENGTH]; + DWORD reserved; + _SNETSPI_DEVICELIST *next; +} SNETSPI_DEVICELIST, *SNETSPI_DEVICELISTPTR; + +typedef struct _SNETSPI_GAMELIST { + DWORD gameid; + DWORD gamemode; + DWORD creationtime; + SNETADDR owner; + DWORD ownerlatency; + DWORD ownerlasttime; + DWORD gamecategorybits; + char gamename[SNETSPI_MAXSTRINGLENGTH]; + char gamedescription[SNETSPI_MAXSTRINGLENGTH]; + _SNETSPI_GAMELIST *next; + // new for 1.05: + LPVOID clientdata; + DWORD clientdatabytes; +} SNETSPI_GAMELIST, *SNETSPI_GAMELISTPTR; + +typedef struct _SNETSPI { + DWORD size; + BOOL (CALLBACK *CompareNetAddresses)(SNETADDRPTR,SNETADDRPTR,DWORD *); + BOOL (CALLBACK *Destroy)(); + BOOL (CALLBACK *Free)(SNETADDRPTR,LPVOID,DWORD); + BOOL (CALLBACK *FreeExternalMessage)(LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *GetGameInfo)(DWORD,LPCSTR,LPCSTR,SNETSPI_GAMELIST *); + BOOL (CALLBACK *GetPerformanceData)(DWORD,DWORD *,LARGE_INTEGER *,LARGE_INTEGER *); + BOOL (CALLBACK *Initialize)(SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,HANDLE); + BOOL (CALLBACK *InitializeDevice)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR); + BOOL (CALLBACK *LockDeviceList)(SNETSPI_DEVICELISTPTR *); + BOOL (CALLBACK *LockGameList)(DWORD,DWORD,SNETSPI_GAMELISTPTR *); + +/* note: this is the way that the Receive call should look... + + BOOL (CALLBACK *Receive)(SNETADDRPTR *,LPVOID *,DWORD *); + + below is the receive call with two parameters switched around + to make it incompatible with older .snp's during the beta... */ + + BOOL (CALLBACK *Receive)(LPVOID *,DWORD *,SNETADDRPTR *); + + BOOL (CALLBACK *ReceiveExternalMessage)(LPCSTR *,LPCSTR *,LPCSTR *); + BOOL (CALLBACK *SelectGame)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,DWORD *); + BOOL (CALLBACK *Send)(DWORD,SNETADDRPTR *,LPVOID,DWORD); + BOOL (CALLBACK *SendExternalMessage)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *StartAdvertisingGame)(LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,DWORD,LPCVOID,DWORD); + BOOL (CALLBACK *StopAdvertisingGame)(); + BOOL (CALLBACK *UnlockDeviceList)(SNETSPI_DEVICELISTPTR); + BOOL (CALLBACK *UnlockGameList)(SNETSPI_GAMELISTPTR,DWORD *); + // new for 1.05: + BOOL (CALLBACK *GetLocalPlayerName)(LPSTR,DWORD,LPSTR,DWORD); +} SNETSPI, *SNETSPIPTR; + +typedef BOOL (APIENTRY *SNETSPIBIND )(DWORD,SNETSPIPTR *); +typedef BOOL (APIENTRY *SNETSPIQUERY)(DWORD,DWORD *,LPCSTR *,LPCSTR *,SNETCAPSPTR *); + + +/**************************************************************************** +* +* Registry functions +* +***/ + +#define SREG_FLAG_USERSPECIFIC 0x00000001 +#define SREG_FLAG_BATTLENET 0x00000002 +#define SREG_FLAG_FLUSHTODISK 0x00000008 +#define SREG_FLAG_MULTISZ 0x00000080 + +extern "C" BOOL APIENTRY SRegGetBaseKey (DWORD flags, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SRegLoadData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID buffer, + DWORD buffersize, + DWORD *bytesread); +extern "C" BOOL APIENTRY SRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SRegLoadValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *value); +extern "C" BOOL APIENTRY SRegSaveData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SRegSaveString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPCTSTR string); +extern "C" BOOL APIENTRY SRegSaveValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD value); + + +/**************************************************************************** +* +* Region manager functions +* +***/ + +#define SRGN_AND RGN_AND +#define SRGN_COPY RGN_COPY +#define SRGN_DIFF RGN_DIFF +#define SRGN_OR RGN_OR +#define SRGN_XOR RGN_XOR +#define SRGN_PARAMONLY 6 +#define SRGN_MIN 1 +#define SRGN_MAX 6 + +DECLARE_STRICT_HANDLE(HSRGN); + +extern "C" void APIENTRY SRgnClear (HSRGN handle); +extern "C" void APIENTRY SRgnCombineRect (HSRGN handle, + LPCRECT rect, + LPVOID param, + int combinemode); +extern "C" void APIENTRY SRgnCreate (HSRGN *handle, + DWORD reserved = 0); +extern "C" void APIENTRY SRgnDelete (HSRGN handle); +#ifdef STORMSTATIC +extern "C" void APIENTRY SRgnDestroy (); +#endif +extern "C" void APIENTRY SRgnDuplicate (HSRGN orighandle, + HSRGN *handle, + DWORD reserved = 0); +extern "C" void APIENTRY SRgnGetBoundingRect (HSRGN handle, + LPRECT rect); +extern "C" void APIENTRY SRgnGetRectParams (HSRGN handle, + LPCRECT rect, + DWORD *numparams, + LPVOID *buffer); +extern "C" void APIENTRY SRgnGetRects (HSRGN handle, + DWORD *numrects, + LPRECT buffer); + +#define SRgnAddParam(handle,rect,param) SRgnCombineRect(handle,rect,param,SRGN_PARAMONLY); +#define SRgnAddRect(handle,rect,param) SRgnCombineRect(handle,rect,param,SRGN_OR) + + +/**************************************************************************** +* +* Run-time library functions +* +***/ + +#define ONCE ONCEEXPAND(__FILE__##__##__LINE__##__once) +#define ONCEEXPAND(a) BOOL a = TRUE; a; a = FALSE + +#define TRY goto trylabel; trylabel: +#define LEAVE goto finallylabel +#define FINALLY goto finallylabel; finallylabel: + + +/**************************************************************************** +* +* String functions +* +***/ + +#define SSTR_HASH_CASESENSITIVE 0x00000001 + +#define SSTR_UNBOUNDED 0x7FFFFFFF + +extern "C" LPTSTR APIENTRY SStrChr (LPCTSTR string, + char ch, + BOOL reverse = FALSE); +extern "C" DWORD APIENTRY SStrCopy (LPTSTR dest, + LPCTSTR source, + DWORD destsize = SSTR_UNBOUNDED); +extern "C" DWORD APIENTRY SStrHash (LPCTSTR string, + DWORD flags = 0, + DWORD seed = 0); +extern "C" DWORD APIENTRY SStrLen (LPCTSTR string); +extern "C" void APIENTRY SStrPack (LPTSTR dest, + LPCTSTR source, + DWORD destsize = SSTR_UNBOUNDED); +extern "C" void APIENTRY SStrTokenize (LPCTSTR *string, + LPTSTR buffer, + DWORD bufferchars, + LPCTSTR whitespace, + BOOL *quoted = NULL); + + +/**************************************************************************** +* +* Transparency functions +* +***/ + +#define STRANS_CF_INTERSECT 0x00000001 +#define STRANS_CF_INVERTSECOND 0x00000002 +#define STRANS_CF_SUBTRACT (STRANS_CF_INTERSECT | STRANS_CF_INVERTSECOND) + +DECLARE_STRICT_HANDLE(HSTRANS); +typedef HSTRANS HTRANS; + +extern "C" BOOL APIENTRY STransBlt (LPBYTE dest, + int destx, + int desty, + int destpitch, + HSTRANS transparency); +extern "C" BOOL APIENTRY STransBltUsingMask (LPBYTE dest, + LPBYTE source, + int destpitch, + int sourcepitch, + HSTRANS mask); +extern "C" BOOL APIENTRY STransCombineMasks (HSTRANS basemask, + HSTRANS secondmask, + int offsetx, + int offsety, + DWORD flags, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateMaskE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateMaskI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransDelete (HSTRANS handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY STransDestroy (); +#endif +extern "C" BOOL APIENTRY STransDuplicate (HSTRANS source, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIntersectDirtyArray (HSTRANS sourcemask, + LPBYTE dirtyarray, + BYTE dirtyarraymask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransInvertMask (HSTRANS sourcemask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIsPixelInMask (HSTRANS mask, + int offsetx, + int offsety); +extern "C" BOOL APIENTRY STransLoadE (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransLoadI (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransSetDirtyArrayInfo (int screencx, + int screency, + int cellcx, + int cellcy); +extern "C" BOOL APIENTRY STransUpdateDirtyArray (LPBYTE dirtyarray, + BYTE dirtyvalue, + int destx, + int desty, + HSTRANS transparency, + BOOL tracecontour); + +#ifdef STRANS_USE_INCLUSIVE_RECTS +#define STransCreate STransCreateI +#define STransCreateMask STransCreateMaskI +#define STransLoad STransLoadI +#else +#define STransCreate STransCreateE +#define STransCreateMask STransCreateMaskE +#define STransLoad STransLoadE +#endif + + +/**************************************************************************** +* +* Video functions +* +***/ + +#define SVID_FLAG_DOUBLESCANS 0x00000001 +#define SVID_FLAG_INTERPOLATE 0x00000002 +#define SVID_FLAG_INTERLACE 0x00000004 +#define SVID_FLAG_AUTOQUALITY 0x00000008 +#define SVID_FLAG_1XSIZE 0x00000100 +#define SVID_FLAG_2XSIZE 0x00000200 +#define SVID_FLAG_AUTOSIZE 0x00000800 +#define SVID_FLAG_FILEHANDLE 0x00010000 +#define SVID_FLAG_PRELOAD 0x00020000 +#define SVID_FLAG_LOOP 0x00040000 +#define SVID_FLAG_FULLSCREEN 0x00080000 +#define SVID_FLAG_USECURRENTPALETTE 0x00100000 +#define SVID_FLAG_CLEARSCREEN 0x00200000 +#define SVID_FLAG_NOSKIP 0x00400000 +#define SVID_FLAG_NEEDPAN 0x02000000 +#define SVID_FLAG_NEEDVOLUME 0x04000000 +#define SVID_FLAG_TOSCREEN 0x10000000 +#define SVID_FLAG_TOBUFFER 0x20000000 + +#define SVID_CUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_2XSIZE) +#define SVID_AUTOCUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_AUTOSIZE | SVID_FLAG_AUTOQUALITY) + +#define SVID_QUALITY_LOW_SKIPSCANS SVID_FLAG_2XSIZE +#define SVID_QUALITY_LOW (SVID_FLAG_2XSIZE | SVID_FLAG_DOUBLESCANS) +#define SVID_QUALITY_HIGH_SKIPSCANS (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE) +#define SVID_QUALITY_HIGH (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE | SVID_FLAG_DOUBLESCANS) + +DECLARE_STRICT_HANDLE(HSVIDEO); + +typedef struct _SVIDPALETTEUSE { + DWORD size; + DWORD firstentry; + DWORD numentries; +} SVIDPALETTEUSE, *SVIDPALETTEUSEPTR; + +extern "C" BOOL APIENTRY SVidDestroy (); +extern "C" BOOL APIENTRY SVidGetPerformanceData (HSVIDEO video, + BOOL averageframems, + DWORD *framems, + BOOL averagepalettems, + DWORD *palettems); +extern "C" BOOL APIENTRY SVidGetSize (HSVIDEO video, + int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SVidInitialize (LPVOID directsound); +extern "C" BOOL APIENTRY SVidPlayBegin (LPCTSTR filename, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayBeginFromMemory (LPVOID sourceptr, + DWORD sourcebytes, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayContinue (); +extern "C" BOOL APIENTRY SVidPlayContinueSingle (HSVIDEO video, + BOOL forceupdate, + BOOL *updated); +extern "C" BOOL APIENTRY SVidPlayEnd (HSVIDEO video); +extern "C" BOOL APIENTRY SVidSetVolume (HSVIDEO video, + LONG volume, + LONG pan, + DWORD track = 0); + + +/**************************************************************************** +* +* Storm global functions +* +***/ + +extern "C" BOOL APIENTRY StormDestroy (); + +#ifdef MAC +extern "C" void StormStartup(); +extern "C" void StormShutdown(); +#endif + + +//#########################################################################// +//#########################################################################// +// // +// // +// CLASS-BASED PROGRAMMING INTERFACE // +// (under construction) // +// // +// // +//#########################################################################// +//#########################################################################// + + +/**************************************************************************** +* +* CSLog +* +***/ + +class CSLog { + + private: + HSLOG m_handle; + + public: + + //======================================================================= + CSLog (LPCTSTR filename) { + SLogCreate(filename,0,&m_handle); + } + + //======================================================================= + CSLog (LPCTSTR keyname, + LPCTSTR valuename) { + char filename[MAX_PATH] = ""; + SRegLoadString(keyname,valuename,0,filename,MAX_PATH); +#ifdef _DEBUG + SRegSaveString(keyname,valuename,0,filename); +#endif + if (filename[0]) + SLogCreate(filename,0,&m_handle); + } + + //======================================================================= + ~CSLog () { + SLogClose(m_handle); + } + + //======================================================================= + void Dump (LPCVOID data, + DWORD bytes) { + SLogDump(m_handle, + data, + bytes); + } + + //======================================================================= + void Flush () { + SLogFlush(m_handle); + } + + //======================================================================= + HSLOG GetHandle () { + return m_handle; + } + + //======================================================================= + void Pend (LPCSTR string) { + SLogPend(m_handle, + string); + } + + //======================================================================= + void Write (LPCSTR string) { + SLogWrite(m_handle, + string); + } + +}; + + +/**************************************************************************** +* +* CSRgn +* +***/ + +class CSRgn { + + private: + HSRGN m_handle; + + //======================================================================= + void CopyConstructor (const CSRgn & source) { + SRgnDuplicate(source.m_handle, + &m_handle); + } + + public: + + //======================================================================= + CSRgn () { + SRgnCreate(&m_handle); + } + + //======================================================================= + CSRgn (const CSRgn & source) { + CopyConstructor(source); + } + + //======================================================================= + ~CSRgn () { + SRgnDelete(m_handle); + } + + //======================================================================= + CSRgn & operator= (const CSRgn &source) { + if (this != &source) { + this->~CSRgn(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + void AddParam (LPCRECT rect, + LPVOID param) { + SRgnAddParam(m_handle, + rect, + param); + } + + //======================================================================= + void AddRect (LPCRECT rect, + LPVOID param) { + SRgnAddRect(m_handle, + rect, + param); + } + + //======================================================================= + void Clear () { + SRgnClear(m_handle); + } + + //======================================================================= + void CombineRect (LPCRECT rect, + LPVOID param, + int combinemode) { + SRgnCombineRect(m_handle, + rect, + param, + combinemode); + } + + //======================================================================= + void GetBoundingRect (LPRECT rect) { + SRgnGetBoundingRect(m_handle, + rect); + } + + //======================================================================= + void GetRects (DWORD *numrects, + LPRECT buffer) { + SRgnGetRects(m_handle, + numrects, + buffer); + } + + //======================================================================= + void GetRectParams (LPCRECT rect, + DWORD *numparams, + LPVOID *buffer) { + SRgnGetRectParams(m_handle, + rect, + numparams, + buffer); + } + +}; + + +//#########################################################################// +//#########################################################################// +// // +// // +// UTILITY CLASSES AND TEMPLATES // +// // +// // +//#########################################################################// +//#########################################################################// + + +/**************************************************************************** +* +* CCritSect -- Critical section class +* +* Methods: +* +* void Enter () +* void Leave () +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void Enter () { EnterCriticalSection(&m_critsect); } + void Enter (BOOL) { EnterCriticalSection(&m_critsect); } + void Leave () { LeaveCriticalSection(&m_critsect); } + void Leave (BOOL) { LeaveCriticalSection(&m_critsect); } +}; + + +/**************************************************************************** +* +* CLock -- Reader/writer lock class +* +* Methods: +* +* void Enter (BOOL forwriting) +* void Leave (BOOL fromwriting) +* +***/ + +class CLock { + + private: + + HANDLE m_mutexevent; + HANDLE m_readerevent; + LONG m_readercount; + + public: + + //======================================================================= + CLock () { + m_mutexevent = CreateEvent(NULL,FALSE,TRUE,NULL); + m_readerevent = CreateEvent(NULL,TRUE,FALSE,NULL); + m_readercount = -1; + } + + //======================================================================= + ~CLock () { + CloseHandle(m_readerevent); + CloseHandle(m_mutexevent); + } + + //======================================================================= + void Enter (BOOL forwriting) { + if (forwriting) + WaitForSingleObject(m_mutexevent,INFINITE); + else if (!InterlockedIncrement(&m_readercount)) { + WaitForSingleObject(m_mutexevent,INFINITE); + SetEvent(m_readerevent); + } + else + WaitForSingleObject(m_readerevent,INFINITE); + } + + //======================================================================= + void Leave (BOOL fromwriting) { + if (fromwriting) + SetEvent(m_mutexevent); + else if (InterlockedDecrement(&m_readercount) < 0) { + ResetEvent(m_readerevent); + SetEvent(m_mutexevent); + } + } + +}; + + +/**************************************************************************** +* +* CNullSync -- Null synchronization class +* +* (used for templates that take a synchronization class as a parameter) +* +***/ + +class CNullSync { + public: + void Enter (BOOL) { } + void Leave (BOOL) { } +}; + + +/**************************************************************************** +* +* type_info +* +* (used by templates to obtain the name of an object) +* +***/ + +#ifdef _MSC_VER + #ifdef _INC_TYPEINFO + #define INTERNALRAWNAME raw_name + #else + #define INTERNALRAWNAME internal_raw_name + class type_info { + public: + virtual ~type_info (); + const char * internal_raw_name () const { return _m_d_name; }; + private: + void *_m_data; + char _m_d_name[1]; + type_info (const type_info& rhs); + type_info& operator= (const type_info& rhs); + }; + #endif +#else + #if defined(MAC) && !defined(__typeinfo__) + #include + #endif + #define INTERNALRAWNAME name +#endif + + +/**************************************************************************** +* +* ARRAY -- Dynamically allocated array template +* +* Types: +* +* ARRAY(structname) -- dynamically sized array of struct +* +* Pointers to types: +* +* ARRAYPTR(structname) +* +* Array methods: +* +* void AddDiscontiguousElements (DWORD count, +* int stride, +* const *newelements); +* void AddElement (const *newelement); +* void AddElements (DWORD count, +* const *newelements); +* DWORD NumElements (); +* * NewElement (); +* * Ptr (); +* void ReserveSpace (DWORD count); +* void SetNumElements (DWORD totalcount); +* +***/ + +template +class TSArray { + + private: + DWORD m_allocchunksize; + T *m_data; + DWORD m_elements; + DWORD m_elementsalloc; + + //======================================================================= + BOOL CheckSpace (DWORD count) { + return (m_elements+count <= m_elementsalloc); + } + + //======================================================================= + void Constructor () { + m_allocchunksize = max(16,256/sizeof(T)); + m_data = NULL; + m_elements = 0; + m_elementsalloc = 0; + } + + //======================================================================= + void CopyConstructor (const TSArray & source) { + Constructor(); + m_allocchunksize = source.m_allocchunksize; + ReserveSpace(source.m_elementsalloc); + AddElements(source.m_elements, + source.m_data); + } + + public: + + //======================================================================= + TSArray () { + Constructor(); + } + + //======================================================================= + TSArray (const TSArray & source) { + CopyConstructor(source); + } + + //======================================================================= + ~TSArray () { + if (m_data) { + while (m_elements) { + --m_elements; + m_data[m_elements].~T(); + } + SMemFree(m_data,__FILE__,__LINE__,0); + m_data = NULL; + } + } + + //======================================================================= + TSArray & operator= (const TSArray &source) { + if (this != &source) { + this->~TSArray(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + T & operator[] (DWORD num) { + if (num >= m_elements) + SErrDisplayError(STORM_ERROR_ACCESS_OUT_OF_BOUNDS, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + NULL, + TRUE); + return m_data[num]; + } + + //======================================================================= + void AddDiscontiguousElements (DWORD count, + int stride, + const T *newelements) { + if (!CheckSpace(count)) + ReserveSpace(count); + if (stride == sizeof(T)) + AddElements(count,newelements); + else + for (DWORD loop = 0; loop < count; ++loop) { + new(m_data+m_elements++) T(*newelements); + newelements = (const T *)((LPBYTE)newelements+stride); + } + } + + //======================================================================= + void AddElement (const T *newelement) { + if (!CheckSpace(1)) + ReserveSpace(1); + new(m_data+m_elements++) T(*newelement); + } + + //======================================================================= + void AddElements (DWORD count, + const T *newelements) { + if (!CheckSpace(count)) + ReserveSpace(count); + for (DWORD loop = 0; loop < count; ++loop) + new(m_data+m_elements++) T(newelements[loop]); + } + + //======================================================================= + DWORD NumElements () { + return m_elements; + } + + //======================================================================= + T * NewElement () { + if (!CheckSpace(1)) + ReserveSpace(1); + return new(m_data+m_elements++) T; + } + + //======================================================================= + T * Ptr () { + if (!m_data) + ReserveSpace(1); + return m_data; + } + + //======================================================================= + void ReserveSpace (DWORD count) { + if (CheckSpace(count)) + return; + + // DETERMINE THE NUMBER OF NEW ELEMENTS TO ALLOCATE + DWORD newelements = m_elements+count; + DWORD partialchunk = newelements & (m_allocchunksize-1); + if (partialchunk) + newelements += m_allocchunksize-partialchunk; + + // ALLOCATE THE NEW ARRAY AND COPY DATA FROM THE OLD ARRAY + T *newdata = (T *)ALLOC(newelements*sizeof(T)); + if (m_data) { + for (DWORD loop = 0; loop < m_elements; ++loop) + new(newdata+loop) T(m_data[loop]); + FREE(m_data); + } + m_data = newdata; + m_elementsalloc = newelements; + + } + + //======================================================================= + void SetNumElements (DWORD totalcount) { + if (totalcount > m_elements) { + ReserveSpace(totalcount-m_elements); + for (DWORD loop = m_elements; loop < totalcount; ++loop) + new(m_data+loop) T; + } + else if (totalcount < m_elements) { + for (DWORD loop = totalcount; loop < m_elements; ++loop) + m_data[loop].~T(); + } + m_elements = totalcount; + } + +}; + +#define ARRAY(structname) TSArray< structname > +#define ARRAYDECL(structname,varname) TSArray< structname > varname +#define ARRAYPTR(structname) TSArray< structname > * + + +/**************************************************************************** +* +* NODE/LIST -- Linked list template +* +* Types: +* +* LINKEX(structname) -- explicit link field +* LIST(structname) -- linked list of implicitly linked nodes +* LISTEX(structname,linkname) -- linked list of explicitly linked nodes +* LISTEXDYN(structname) -- linked list of explicitly linked nodes, +* where the link field to be used by +* this list is not known at compile time +* NODEDECL(structname) -- implicitly linked node +* NODEDECLEX(structname) -- explicitly linked node (must contain one +* or more LINKEX fields) +* +* Pointers to types: +* +* LISTPTR(structname) +* LISTPTREX(structname) +* +* Link methods: +* +* * Next (); +* * Prev (); +* void Unlink (); +* +* Explicitly linked node methods: +* +* None. Use link methods for the link you want to manipulate. +* +* Implicitly linked node methods: +* +* * Next (); +* * Prev (); +* void Unlink (); +* +* List methods: +* +* void Clear (); +* * DeleteNode ( *ptr); +* * Head () const; +* BOOL IsEmpty () const; +* void LinkNode ( *ptr, +* DWORD linktype = LIST_TAIL, +* *existingptr = NULL); +* * NewNode (DWORD location = LIST_TAIL, +* DWORD extrabytes = 0, +* DWORD flags = 0); +* * Next (const *ptr) const; +* * Prev (const *ptr) const; +* * Tail () const; +* void UnlinkAll (); +* void UnlinkNode ( *ptr); +* +* Constants for use with LinkNode() and NewNode(): +* +* LIST_UNLINKED +* LIST_LINK_AFTER +* LIST_LINK_BEFORE +* LIST_HEAD +* LIST_TAIL +* +* Macros: +* +* LISTEXSETLINK(structname,listname,linkname) +* ITERATELIST(structname,listname,ptrname) +* ITERATELISTPTR(structname,listname,ptrname) +* ITERATEPARTIALLIST(structname,listname,start,ptrname) +* ITERATEPARTIALLISTPTR(structname,listname,start,ptrname) +* ITERATELISTREVERSE(structname,listname,ptrname) +* ITERATELISTREVERSEPTR(structname,listname,ptrname) +* ITERATEPARTIALLISTREVERSE(structname,listname,start,ptrname) +* ITERATEPARTIALLISTREVERSEPTR(structname,listname,start,ptrname) +* ITERATE_DELETE +* ITERATE_DELETEANDBREAK +* +***/ + +#define LIST_UNLINKED 0 +#define LIST_LINK_AFTER 1 +#define LIST_LINK_BEFORE 2 +#define LIST_HEAD LIST_LINK_AFTER +#define LIST_TAIL LIST_LINK_BEFORE + +template +class TSList; + +template +class TSLink { + friend class TSList; + friend class TSList; + + private: + TSLink *m_prevlink; + T *m_next; + + //======================================================================= + void Constructor () { + m_prevlink = NULL; + m_next = NULL; + } + + //======================================================================= + void CopyConstructor (const TSLink &) { + Constructor(); + } + + //======================================================================= + TSLink *NextLink () const { + + // IF THE NEXT NODE IS A TERMINATOR, ITS LINK POINTER IS THE SAME AS + // ITS NODE POINTER. + if ((int)m_next < 0) + return (TSLink *)~(DWORD)m_next; + + // OTHERWISE, COMPUTE THE LINK ADDRESS BY USING THE OFFSET OF THIS + // NODE'S LINK AND POINTER ADDRESSES. (THIS NODE MUST NOT BE A + // TERMINATOR.) + else { + DWORD linkoffset = (DWORD)this-(DWORD)(m_prevlink->m_next); + return (TSLink *)(linkoffset+(DWORD)m_next); + } + + } + + protected: + + //======================================================================= + T *NextThroughTerminator () const { + return ((int)m_next > 0) ? m_next : (T *)~(DWORD)m_next; + } + + public: + + //======================================================================= + TSLink () { + Constructor(); + } + + //======================================================================= + TSLink (const TSLink & source) { + CopyConstructor(source); + } + + //======================================================================= + ~TSLink () { + Unlink(); + } + + //======================================================================= + TSLink & operator= (const TSLink &) { + // LEAVE THE DESTINATION NODE LINKED INTO ITS CURRENT LIST + return *this; + } + + //======================================================================= + T * Next () const { + return ((int)m_next > 0) ? m_next : NULL; + } + + //======================================================================= + T * Prev () const { + return m_prevlink->m_prevlink->Next(); + } + + //======================================================================= + void Unlink () { + if (!m_prevlink) + return; + NextLink()->m_prevlink = m_prevlink; + m_prevlink->m_next = m_next; + m_prevlink = NULL; + m_next = NULL; + } + +}; + +template +class TSBaseNode { + public: + + //======================================================================= + inline void * __cdecl operator new (size_t bytes, + size_t extra, + DWORD flags) { + void *ptr = SMemAlloc(bytes+extra, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + flags | SMEM_FLAG_ZEROMEMORY); + return ptr; + } + +}; + +template +class TSExplicitNode : public TSBaseNode { + friend class TSList; + + private: + + //======================================================================= + TSLink *Link (BOOL explicitlink, int linkoffset) const { + ASSERT(explicitlink); + explicitlink; + return (TSLink *)((LPBYTE)this+linkoffset); + } + +}; + +template +class TSLinkedNode : public TSBaseNode { + friend class TSList; + + private: + TSLink m_link; + + //======================================================================= + TSLink *Link (BOOL explicitlink, int linkoffset) const { + if (explicitlink) + return (TSLink *)((LPBYTE)this+linkoffset); + else + return (TSLink *)&m_link; + } + + public: + + //======================================================================= + ~TSLinkedNode () { + Unlink(); + } + + //======================================================================= + T * Next () const { + return m_link.Next(); + } + + //======================================================================= + T * Prev () const { + return m_link.Prev(); + } + + //======================================================================= + void Unlink () { + m_link.Unlink(); + } + +}; + +template +class TSList { + + private: + int m_linkoffset; + TSLink m_terminator; + + //======================================================================= + void Constructor () { + m_linkoffset = 0; + InitializeTerminator(); + } + + //======================================================================= + void CopyConstructor (const TSList & source) { + m_linkoffset = source.m_linkoffset; + InitializeTerminator(); + } + + //======================================================================= + void InitializeTerminator () { + m_terminator.m_prevlink = &m_terminator; + m_terminator.m_next = (T *)~(DWORD)&m_terminator; + } + + //======================================================================= + TSLink *Link (const T *ptr) const { + // THIS FUNCTION CALLS THE LINK METHOD IN EITHER THE NODE OR THE LINK + // TO WHICH THIS LIST REFERS. IF THIS FUNCTION WON'T COMPILE, IT'S + // BECAUSE A NODE WITH EXPLICIT LINKS WAS DEFINED WITH NODEDECL() + // INSTEAD OF NODEDECLEX(). + return ptr->Link(explicitlink,m_linkoffset); + } + + protected: + + //======================================================================= + void SetLinkOffset (int linkoffset) { + m_linkoffset = linkoffset; + InitializeTerminator(); + } + + public: + + //======================================================================= + TSList () { + Constructor(); + }; + + //======================================================================= + TSList (const TSList &source) { + CopyConstructor(source); + }; + + //======================================================================= + TSList (int linkoffset) { + m_linkoffset = linkoffset; + InitializeTerminator(); + }; + + //======================================================================= + ~TSList () { + UnlinkAll(); + } + + //======================================================================= + TSList & operator= (const TSList &source) { + if (this != &source) { + this->~TSList(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + void ChangeLinkOffset (int linkoffset) { + UnlinkAll(); + SetLinkOffset(linkoffset); + } + + //======================================================================= + void Clear () { + T *curr; + while ((curr = Head()) != NULL) + delete curr; + } + + //======================================================================= + T * DeleteNode (T *ptr) { + T *nextptr = Next(ptr); + delete ptr; + return nextptr; + } + + //======================================================================= + T * Head () const { + return m_terminator.Next(); + } + + //======================================================================= + BOOL IsEmpty () const { + return !m_terminator.Next(); + } + + //======================================================================= + T * Iterate_RawNext (const T *ptr) const { + return Link(ptr)->m_next; + } + + //======================================================================= + void LinkNode (T *ptr, + DWORD linktype = LIST_TAIL, + T *existingptr = NULL) { + TSLink *link = Link(ptr); + + // IF THIS NODE IS ALREADY LINKED INTO THE LIST, UNLINK IT + if (link->m_prevlink) + link->Unlink(); + + // FIND THE NODE THAT WE WILL LINK BEFORE OR AFTER. USE THE + // TERMINATOR NODE IF WE'RE LINKING ONTO THE HEAD OR TAIL. + TSLink *existinglink; + if (existingptr) + existinglink = Link(existingptr); + else + existinglink = &m_terminator; + + // LINK THIS NODE INTO THE LIST + switch (linktype) { + + case LIST_LINK_AFTER: + { + link->m_prevlink = existinglink; + link->m_next = existinglink->m_next; + Link(existinglink->NextThroughTerminator())->m_prevlink = link; + existinglink->m_next = ptr; + } + break; + + case LIST_LINK_BEFORE: + { + TSLink *prevlink = existinglink->m_prevlink; + link->m_prevlink = prevlink; + link->m_next = prevlink->m_next; + prevlink->m_next = ptr; + existinglink->m_prevlink = link; + } + break; + + } + } + + //======================================================================= + T * NewNode (DWORD location = LIST_TAIL, + DWORD extrabytes = 0, + DWORD flags = 0) { + T *ptr = new(extrabytes,flags) T; + if (location != LIST_UNLINKED) + LinkNode(ptr,location); + return ptr; + } + + //======================================================================= + T * Next (const T *ptr) const { + return Link(ptr)->Next(); + } + + //======================================================================= + T * Prev (const T *ptr) const { + return Link(ptr)->Prev(); + } + + //======================================================================= + T * Tail () const { + return m_terminator.Prev(); + } + + //======================================================================= + void UnlinkAll () { + T *curr; + while ((curr = Head()) != NULL) + UnlinkNode(curr); + } + + //======================================================================= + void UnlinkNode (T *ptr) { + Link(ptr)->Unlink(); + } + +}; + +template +class TSExplicitList : public TSList { + public: + + //======================================================================= + TSExplicitList () { + SetLinkOffset(linkoffset); + } + +}; + + +#define LINKEX(structname) TSLink< structname > +#define LINKDECLEX(structname,varname) TSLink< structname > varname +#define LIST(structname) TSList< structname ,FALSE> +#define LISTDECL(structname,varname) TSList< structname ,FALSE> varname +#define LISTPTR(structname) TSList< structname ,FALSE> * +#define LISTPTREX(structname) TSList< structname ,TRUE> * +#define NODEDECL(structname) typedef struct structname : public TSLinkedNode< structname > +#define NODEDECLEX(structname) typedef struct structname : public TSExplicitNode< structname > + +#define LISTEX(structname,linkname) \ + TSExplicitList< structname ,(int)&(((structname *)0)->linkname)> + +#define LISTEXDYN(structname) \ + TSExplicitList< structname ,(int)0xDDDDDDDD> + +#define LISTEXSETLINK(structname,listname,linkname) \ + listname.ChangeLinkOffset((int)&(((structname *)0)->linkname)); + +#define LISTDECLEX(structname,linkname,varname) \ + TSExplicitList< structname ,(int)&(((structname *)0)->linkname)> varname + +#define ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,op) \ + for (structname *ptrname = start, \ + *iterate_delete = NULL; \ + (int)ptrname > 0; \ + iterate_delete \ + ? (ptrname = (listname)##op##DeleteNode(ptrname), \ + ptrname = ((int)iterate_delete > 0) ? ptrname : NULL, \ + iterate_delete = NULL, \ + ptrname) \ + : ptrname = (listname)##op##Iterate_RawNext(ptrname)) + +#define ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,op) \ + for (structname *ptrname = start, \ + *iterate_delete = NULL, \ + *iterate_delete_temp = NULL; \ + ptrname; \ + iterate_delete \ + ? (iterate_delete_temp = ((int)iterate_delete > 0) \ + ? (listname)##op##Prev(ptrname) \ + : NULL, \ + (listname)##op##DeleteNode(ptrname), \ + iterate_delete = NULL, \ + ptrname = iterate_delete_temp) \ + : ptrname = (listname)##op##Prev(ptrname)) + +#define ITERATELIST(structname,listname,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,(listname).Head(),ptrname,.) + +#define ITERATELISTPTR(structname,listname,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,(listname)->Head(),ptrname,->) + +#define ITERATEPARTIALLIST(structname,listname,start,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,.) + +#define ITERATEPARTIALLISTPTR(structname,listname,start,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,->) + +#define ITERATELISTREVERSE(structname,listname,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,(listname).Tail(),ptrname,.) + +#define ITERATELISTREVERSEPTR(structname,listname,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,(listname)->Tail(),ptrname,->) + +#define ITERATEPARTIALLISTREVERSE(structname,listname,start,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,.) + +#define ITERATEPARTIALLISTREVERSEPTR(structname,listname,start,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,->) + +#define ITERATE_DELETE \ + { \ + ++iterate_delete; \ + continue; \ + } + +#define ITERATE_DELETEANDBREAK \ + { \ + --iterate_delete; \ + continue; \ + } + + +/**************************************************************************** +* +* EXPORTOBJECT/EXPORTTABLE -- Export manager template +* +* Types: +* +* DECLARE_STRICT_HANDLE(handle) -- handle to object +* DECLARE_STRICT_HANDLE(lockedhandle) -- handle to locked object +* EXPORTOBJECTDECL(structname) -- object to be exported +* EXPORTTABLE(structname,handlename,lockedhandlename,synctype) +* EXPORTTABLEREUSE(structname,handlename,lockedhandlename,synctype) +* +* Export table methods: +* +* void Delete ( handle); +* void DeleteUnlock ( *ptr, +* lockedhandle); +* void Destroy (); +* * Lock ( handle, +* *lockedhandle, +* BOOL forwriting = FALSE); +* void New ( *handle); +* * NewLock ( *handle, +* *lockedhandle); +* void Unlock ( lockedhandle); +* +* Synchronization types for use with EXPORTTABLE(): +* +* SYNC_NONE -- use no synchronization +* SYNC_READWRITE -- use a reader/writer lock +* SYNC_ALWAYS -- use a critical section +* +***/ + +template +class TSExportTableBase { + + protected: + + //======================================================================= + T * BaseFindByHandle (LISTPTREX(T) list, unsigned handle) { + ITERATELISTPTR(T,list,curr) + if (curr->m_handle == handle) + return curr; + return NULL; + } + + //======================================================================= + T * BaseFindByHandleEx (LISTPTREX(T) list, unsigned handle, unsigned *count) { + *count = 0; + ITERATELISTPTR(T,list,curr) + if (curr->m_handle == handle) + return curr; + else + ++*count; + return NULL; + } + + //======================================================================= + unsigned BaseGetHandle (const T *ptr) { + return ptr->m_handle; + } + + //======================================================================= + int BaseGetLinkOffset () { + return (int)&(((T *)0)->m_linktoslot); + } + + //======================================================================= + void BaseSetHandle (T *ptr, unsigned handle) { + ptr->m_handle = handle; + } + +}; + +template +class TSExportTable : public TSExportTableBase { + + private: + ARRAY(LISTEXDYN(T)) m_listarray; + LISTEXDYN(T) m_reuselist; + H m_sequence; + unsigned m_slotmask; + SYNC m_sync; + + //======================================================================= + unsigned ComputeSlot (H handle) { + return (unsigned)handle & m_slotmask; + } + + //======================================================================= + H GenerateUniqueHandle () { + unsigned count; + for (;;) { + m_sequence = (H)((unsigned)m_sequence+1); + if (!BaseFindByHandleEx(&m_listarray[ComputeSlot(m_sequence)], + (unsigned)m_sequence, + &count)) + break; + } + if (count >= 4) + GrowListArray(); + return m_sequence; + } + + //======================================================================= + void GrowListArray () { +return; // note: out for testing + if (m_slotmask >= 1023) + return; + + // DETERMINE THE NEW ARRAY SIZE + unsigned oldarraysize = m_slotmask+1; + unsigned newarraysize = oldarraysize*2; + + // GROW THE ARRAY + { + m_listarray.SetNumElements(newarraysize); + int linkoffset = BaseGetLinkOffset(); + for (unsigned slot = oldarraysize; slot < newarraysize; ++slot) + m_listarray[slot].ChangeLinkOffset(linkoffset); + } + + // MOVE ALL RECORDS FROM THE OLD LISTS TO THE NEW LISTS + m_slotmask = newarraysize-1; + { + for (unsigned slot = 0; slot < oldarraysize; ++slot) { + T *currptr = m_listarray[slot].Head(); + while (currptr) { + T *nextptr = m_listarray[slot].Next(currptr); + unsigned newslot = ComputeSlot((H)BaseGetHandle(currptr)); + if (newslot != slot) { + m_listarray[slot].UnlinkNode(currptr); + m_listarray[newslot].LinkNode(currptr); + } + currptr = nextptr; + } + } + } + + } + + //======================================================================= + BOOL IsForWriting (LH lockedhandle) { + return (lockedhandle == (LH)1); + } + + //======================================================================= + void SyncEnterLock (LH *lockedhandle, BOOL forwriting) { + m_sync.Enter(forwriting); + *lockedhandle = (LH)(forwriting ? 1 : -1); + } + + //======================================================================= + void SyncLeaveLock (LH lockedhandle) { + if (lockedhandle) + m_sync.Leave(IsForWriting(lockedhandle)); + } + + public: + + //======================================================================= + TSExportTable () { + m_sequence = (H)0; + m_slotmask = 3; + m_listarray.SetNumElements(m_slotmask+1); + int linkoffset = BaseGetLinkOffset(); + for (unsigned slot = 0; slot <= m_slotmask; ++slot) + m_listarray[slot].ChangeLinkOffset(linkoffset); + m_reuselist.ChangeLinkOffset(linkoffset); + } + + //======================================================================= + ~TSExportTable () { + Destroy(); + } + + //======================================================================= + void Delete (H handle) { + LH lockedhandle; + T *ptr = Lock(handle,&lockedhandle,TRUE); + DeleteUnlock(ptr,lockedhandle); + } + + //======================================================================= + void DeleteUnlock (T *ptr, + LH lockedhandle) { + if (ptr) + if (REUSE) + m_reuselist.LinkNode(ptr); + else + delete ptr; + Unlock(lockedhandle); + } + + //======================================================================= + void Destroy () { + LH lockedhandle; + SyncEnterLock(&lockedhandle,TRUE); + for (unsigned slot = 0; slot <= m_slotmask; ++slot) { + T *curr; + while ((curr = m_listarray[slot].Head()) != NULL) { + delete curr; + SErrReportResourceLeak(typeid(H).INTERNALRAWNAME()); + } + } + m_reuselist.Clear(); + SyncLeaveLock(lockedhandle); + } + + //======================================================================= + T * Lock (H handle, + LH *lockedhandle, + BOOL forwriting = FALSE) { + SyncEnterLock(lockedhandle,forwriting); + T *result = BaseFindByHandle(&m_listarray[ComputeSlot(handle)], + (unsigned)handle); + if (!result) { + SyncLeaveLock(*lockedhandle); + *lockedhandle = (LH)0; + } + return result; + } + + //======================================================================= + void New (H *handle) { + LH lockedhandle; + NewLock(handle,&lockedhandle); + Unlock(lockedhandle); + } + + //======================================================================= + T * NewLock (H *handle, LH *lockedhandle) { + SyncEnterLock(lockedhandle,TRUE); + H newhandle = GenerateUniqueHandle(); + T *ptr = NULL; + if (REUSE) { + ptr = m_reuselist.Head(); + if (ptr) + m_listarray[ComputeSlot(newhandle)].LinkNode(ptr); + } + if (!ptr) + ptr = m_listarray[ComputeSlot(newhandle)].NewNode(); + BaseSetHandle(ptr,(unsigned)newhandle); + *handle = newhandle; + return ptr; + } + + //======================================================================= + void Unlock (LH lockedhandle) { + SyncLeaveLock(lockedhandle); + } + +}; + +template +class TSExportObject : public TSExplicitNode { + friend class TSExportTableBase; + + private: + unsigned m_handle; + LINKEX(T) m_linktoslot; + + public: + + //======================================================================= + TSExportObject () { + } + + //======================================================================= + TSExportObject (const TSExportObject &source) { + } + + //======================================================================= + TSExportObject & operator= (const TSExportObject &source) { + // COPY THE OBJECT DATA, BUT DON'T OVERWRITE THE DESTINATION OBJECT'S + // HANDLE OR LINK + return *this; + } + +}; + +#define SYNC_NONE CNullSync +#define SYNC_READWRITE CLock +#define SYNC_ALWAYS CCritSect + +#define EXPORTOBJECTDECL(structname) \ + typedef struct structname : public TSExportObject< structname > + +#define EXPORTTABLE(structname,handlename,lockedhandlename,synctype) \ + TSExportTable + +#define EXPORTTABLEREUSE(structname,handlename,lockedhandlename,synctype) \ + TSExportTable + + +/**************************************************************************** +* +* SWAP -- Swap template +* +* Macros: +* +* SWAP(a,b) +* +***/ + +//=========================================================================== +template +void inline TSSwap (T &a, T &b) { + T temp = a; + a = b; + b = temp; +} +#define SWAP(a,b) TSSwap(a,b) + + +/**************************************************************************** +* +* Old TList Template -- Obsolete!! +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return FALSE; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return FALSE; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return TRUE; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return FALSE; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return FALSE; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return TRUE; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return FALSE; + + ptr->next = *head; + *head = ptr; + return TRUE; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return FALSE; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return TRUE; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return FALSE; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber,0); + *head = next; + } + return TRUE; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return FALSE; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber,0); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return FALSE; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import off +#endif + +#endif // ifndef _STORM_H_ diff --git a/src/Storm/H/STORM.H b/src/Storm/H/STORM.H new file mode 100644 index 0000000..7916c00 --- /dev/null +++ b/src/Storm/H/STORM.H @@ -0,0 +1,3331 @@ +#ifndef _STORM_H_ +#define _STORM_H_ + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import on +#endif + + +//#########################################################################// +//#########################################################################// +// // +// // +// STANDARD PROGRAMMING INTERFACE // +// // +// // +//#########################################################################// +//#########################################################################// + + +#define DECLARE_STRICT_HANDLE(name) typedef struct name##__ { int unused; } *name +#define DECLARE_DERIVED_HANDLE(name,base) typedef struct name##__ : public base##__ { int unused; } *name + + +/**************************************************************************** +* +* Error codes +* (Error text is defined in Stormerr.mc) +* +***/ + +#define STORMFAC 0x510 +#define STORMERROR(code) (0x80000000 | (STORMFAC << 16) | ((code) & 0xFFFF)) + +#define STORM_ERROR_ASSERTION STORMERROR(0) +#define STORM_ERROR_BAD_ARGUMENT STORMERROR(101) +#define STORM_ERROR_GAME_ALREADY_STARTED STORMERROR(102) +#define STORM_ERROR_GAME_FULL STORMERROR(103) +#define STORM_ERROR_GAME_NOT_FOUND STORMERROR(104) +#define STORM_ERROR_GAME_TERMINATED STORMERROR(105) +#define STORM_ERROR_INVALID_PLAYER STORMERROR(106) +#define STORM_ERROR_NO_MESSAGES_WAITING STORMERROR(107) +#define STORM_ERROR_NOT_ARCHIVE STORMERROR(108) +#define STORM_ERROR_NOT_ENOUGH_ARGUMENTS STORMERROR(109) +#define STORM_ERROR_NOT_IMPLEMENTED STORMERROR(110) +#define STORM_ERROR_NOT_IN_ARCHIVE STORMERROR(111) +#define STORM_ERROR_NOT_IN_GAME STORMERROR(112) +#define STORM_ERROR_NOT_INITIALIZED STORMERROR(113) +#define STORM_ERROR_NOT_PLAYING STORMERROR(114) +#define STORM_ERROR_NOT_REGISTERED STORMERROR(115) +#define STORM_ERROR_REQUIRES_CODEC STORMERROR(116) +#define STORM_ERROR_REQUIRES_DDRAW STORMERROR(117) +#define STORM_ERROR_REQUIRES_DSOUND STORMERROR(118) +#define STORM_ERROR_REQUIRES_UPGRADE STORMERROR(119) +#define STORM_ERROR_STILL_ACTIVE STORMERROR(120) +#define STORM_ERROR_VERSION_MISMATCH STORMERROR(121) +#define STORM_ERROR_MEMORY_ALREADY_FREED STORMERROR(122) +#define STORM_ERROR_MEMORY_CORRUPT STORMERROR(123) +#define STORM_ERROR_MEMORY_INVALID_BLOCK STORMERROR(124) +#define STORM_ERROR_MEMORY_MANAGER_INACTIVE STORMERROR(125) +#define STORM_ERROR_MEMORY_NEVER_RELEASED STORMERROR(126) +#define STORM_ERROR_HANDLE_NEVER_RELEASED STORMERROR(127) +#define STORM_ERROR_ACCESS_OUT_OF_BOUNDS STORMERROR(128) +#define STORM_ERROR_MEMORY_NULL_POINTER STORMERROR(129) + + +/**************************************************************************** +* +* BitBlt functions +* +***/ + +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SBltDestroy (); +#endif +extern "C" BOOL APIENTRY SBltGetSCode (DWORD rop3, + LPSTR buffer, + DWORD buffersize, + BOOL optimize = 1); +extern "C" BOOL APIENTRY SBltROP3 (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Clipped (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Tiled (LPBYTE dest, + LPRECT destrect, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3); + + +/**************************************************************************** +* +* Bitmap functions +* +***/ + +#define SBMP_IMAGETYPE_AUTO 0 +#define SBMP_IMAGETYPE_BMP 1 +#define SBMP_IMAGETYPE_PCX 2 + +typedef LPVOID (APIENTRY *SBMPALLOCPROC)(DWORD); + +extern "C" BOOL APIENTRY SBmpAllocLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE *returnedbuffer, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL, + int requestedbitdepth = 0, + SBMPALLOCPROC allocproc = NULL); +extern "C" BOOL APIENTRY SBmpDecodeImage (DWORD imagetype, + LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpSaveImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height, + int bitdepth); + + +/**************************************************************************** +* +* Command line parsing functions +* +***/ + +#define SCMD_ARG_FLAGGED (0 << 24) +#define SCMD_ARG_OPTIONAL (1 << 24) +#define SCMD_ARG_REQUIRED (2 << 24) +#define SCMD_ARG_MASK (SCMD_ARG_FLAGGED | SCMD_ARG_OPTIONAL | SCMD_ARG_REQUIRED) + +#define SCMD_BOOL_SET 0 +#define SCMD_BOOL_CLEAR 1 +#define SCMD_BOOL_MASK (SCMD_BOOL_CLEAR | SCMD_BOOL_SET) + +#define SCMD_CASESENSITIVE (0x01 << 8) + +#define SCMD_NUM_UNSIGNED 0 +#define SCMD_NUM_SIGNED 1 +#define SCMD_NUM_MASK (SCMD_NUM_UNSIGNED | SCMD_NUM_SIGNED) + +#define SCMD_TYPE_BOOL (0 << 16) +#define SCMD_TYPE_NUMERIC (1 << 16) +#define SCMD_TYPE_STRING (2 << 16) +#define SCMD_TYPE_MASK (SCMD_TYPE_BOOL | SCMD_TYPE_NUMERIC | SCMD_TYPE_STRING) + +#define SCMD_ERROR_BAD_ARGUMENT STORM_ERROR_BAD_ARGUMENT +#define SCMD_ERROR_NOT_ENOUGH_ARGUMENTS STORM_ERROR_NOT_ENOUGH_ARGUMENTS +#define SCMD_ERROR_OPEN_FAILED ERROR_OPEN_FAILED + +typedef struct _CMDERROR { + DWORD errorcode; + LPCTSTR itemstr; + LPCTSTR errorstr; +} CMDERROR, *CMDERRORPTR; + +typedef struct _CMDPARAMS { + DWORD flags; + DWORD id; + LPCTSTR name; + LPVOID variable; + DWORD setvalue; + DWORD setmask; + union { + BOOL boolvalue; + LONG signedvalue; + DWORD unsignedvalue; + LPCTSTR stringvalue; + }; +} CMDPARAMS, *CMDPARAMSPTR; + +typedef BOOL (CALLBACK *SCMDCALLBACK)(CMDPARAMSPTR,LPCTSTR); +typedef void (CALLBACK *SCMDERRORCALLBACK)(CMDERRORPTR); +typedef BOOL (CALLBACK *SCMDEXTRACALLBACK)(LPCTSTR); + +typedef struct _ARGLIST { + DWORD flags; + DWORD id; + LPCTSTR name; + SCMDCALLBACK callback; +} ARGLIST, *ARGLISTPTR; + +extern "C" BOOL APIENTRY SCmdCheckId (DWORD id); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SCmdDestroy (); +#endif +extern "C" BOOL APIENTRY SCmdGetBool (DWORD id); +extern "C" DWORD APIENTRY SCmdGetNum (DWORD id); +extern "C" BOOL APIENTRY SCmdGetString (DWORD id, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SCmdProcess (LPCTSTR cmdline, + BOOL skipprogname, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback); +extern "C" BOOL APIENTRY SCmdRegisterArgList (const ARGLIST *listptr, + DWORD numargs); +extern "C" BOOL APIENTRY SCmdRegisterArgument (DWORD flags, + DWORD id, + LPCTSTR name, + LPVOID variableptr = NULL, + DWORD variablebytes = 0, + DWORD setvalue = TRUE, + DWORD setmask = 0xFFFFFFFF, + SCMDCALLBACK callback = NULL); + +#define SCmdProcessCommandLine(ext,err) SCmdProcess(GetCommandLine(),TRUE,(ext),(err)) + +#define ARGBOOL(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),TRUE,0xFFFFFFFF,callback) +#define ARGFLAG(flags,name,var,valuecallback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),value,value,callback) +#define ARGNUMBER(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_NUMERIC | (flags),0xFFFFFFFF,name,var,sizeof(var),0,0,callback) +#define ARGSTRING(flags,name,buffer,chars,callback) SCmdRegisterArgument(SCMD_TYPE_STRING | (flags),0xFFFFFFFF,name,buffer,(chars),0,0,callback) + + +/**************************************************************************** +* +* S-Code functions +* +***/ + +#define SCODE_CF_AUTOALIGNDWORD 0x00040000 +#define SCODE_CF_USESALTADJUSTS 0x04000000 + +DECLARE_STRICT_HANDLE(HSCODESTREAM); + +typedef struct _SCODEEXECUTEDATA { + DWORD size; + DWORD flags; + int xiterations; + int yiterations; + int adjustdest; + int adjustsource; + LPVOID dest; + LPVOID source; + LPVOID table; + DWORD a; + DWORD b; + DWORD c; + int adjustdestalt; + int adjustsourcealt; + DWORD reserved[2]; +} SCODEEXECUTEDATA, *SCODEEXECUTEDATAPTR; + +extern "C" BOOL APIENTRY SCodeCompile (LPCSTR prologstring, + LPCSTR loopstring, + LPCSTR *firsterror, + DWORD maxiterations, + DWORD flags, + HSCODESTREAM *handle); +extern "C" BOOL APIENTRY SCodeDelete (HSCODESTREAM handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SCodeDestroy (); +#endif +extern "C" BOOL APIENTRY SCodeExecute (HSCODESTREAM handle, + SCODEEXECUTEDATAPTR executedata); +extern "C" BOOL APIENTRY SCodeGetJumpTable (HSCODESTREAM handle, + LPBYTE **jumptableptr, + LPDWORD *prologpatchlocation, + LPDWORD *looppatchlocation, + LPDWORD *epilogpatchlocation); +extern "C" BOOL APIENTRY SCodeGetPseudocode (LPCSTR scodestring, + LPSTR buffer, + DWORD buffersize); + + +/**************************************************************************** +* +* Compression functions +* +***/ + +#define SCOMP_HINT_NONE 0 +#define SCOMP_HINT_BINARY 1 +#define SCOMP_HINT_TEXT 2 +#define SCOMP_HINT_EXECUTABLE 3 +#define SCOMP_HINT_ADPCM4 4 +#define SCOMP_HINT_ADPCM6 5 +#define SCOMP_HINTS 6 + +#define SCOMP_OPT_DEFAULT 0 +#define SCOMP_OPT_COMPRESSION 1 +#define SCOMP_OPT_SPEED 2 +#define SCOMP_OPT_QUALITY 3 + +#define SCOMP_TYPE_HUFFMAN 0x01 +#define SCOMP_TYPE_PKWARE 0x08 +#define SCOMP_TYPE_LOSSY_ADPCM_MONO 0x10 +#define SCOMP_TYPE_LOSSY_ADPCM_STEREO 0x20 + +extern "C" BOOL APIENTRY SCompCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD compressiontypes, + DWORD hint, + DWORD optimization); +extern "C" BOOL APIENTRY SCompDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize); + + +/**************************************************************************** +* +* Dialog box functions +* +***/ + +#define SDLG_ADJUST_NONE 0 +#define SDLG_ADJUST_VERTICAL 1 +#define SDLG_ADJUST_CONTROLPOS 2 + +#define SDLG_DBF_TILE 0x00000001 +#define SDLG_DBF_VCENTER 0x00000002 + +#define SDLG_STYLE_ANY 0xFFFFFFFF +#define SDLG_STYLE_ANYPUSHBUTTON 0x00010001 + +#define SDLG_USAGE_BACKGROUND 0x00000001 +#define SDLG_USAGE_NORMAL_UNFOCUSED 0x00000010 +#define SDLG_USAGE_NORMAL_FOCUSED 0x00000020 +#define SDLG_USAGE_NORMAL (SDLG_USAGE_NORMAL_UNFOCUSED | SDLG_USAGE_NORMAL_FOCUSED) +#define SDLG_USAGE_SELECTED_UNFOCUSED 0x00000040 +#define SDLG_USAGE_SELECTED_FOCUSED 0x00000080 +#define SDLG_USAGE_SELECTED (SDLG_USAGE_SELECTED_UNFOCUSED | SDLG_USAGE_SELECTED_FOCUSED) +#define SDLG_USAGE_NORMAL_GRAYED 0x00000100 +#define SDLG_USAGE_SELECTED_GRAYED 0x00000400 +#define SDLG_USAGE_GRAYED (SDLG_USAGE_NORMAL_GRAYED | SDLG_USAGE_SELECTED_GRAYED) +#define SDLG_USAGE_CURSORMASK 0x00001000 +#define SDLG_USAGE_CURSORIMAGE 0x00002000 + +extern "C" HDC APIENTRY SDlgBeginPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgBltToWindowE (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgBltToWindowI (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgCheckTimers (); +extern "C" HWND APIENTRY SDlgCreateDialogIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" HWND APIENTRY SDlgCreateDialogParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDefDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SDlgDestroy (); +#endif +extern "C" int APIENTRY SDlgDialogBoxIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" int APIENTRY SDlgDialogBoxParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDrawBitmap (HWND window, + DWORD usage, + HRGN region, + int offsetx = 0, + int offsety = 0, + LPRECT boundingoffset = NULL, + DWORD flags = 0); +extern "C" BOOL APIENTRY SDlgEndDialog (HWND window, + int result); +extern "C" BOOL APIENTRY SDlgEndPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgKillTimer (HWND window, + UINT event); +extern "C" BOOL APIENTRY SDlgSetBaseFont (int pointsize, + int weight, + DWORD flags, + DWORD family, + LPCTSTR face); +extern "C" BOOL APIENTRY SDlgSetBitmapE (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetBitmapI (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetControlBitmaps (HWND parentwindow, + LPINT controllist, + LPDWORD usagelist, + LPBYTE bitmapbits, + LPSIZE bitmapsize, + DWORD adjusttype, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetCursor (HWND window, + HCURSOR cursor, + DWORD id, + HCURSOR *oldcursor); +extern "C" BOOL APIENTRY SDlgSetSystemCursor (LPBYTE maskbitmap, + LPBYTE imagebitmap, + LPSIZE size, + DWORD id = 32512); +extern "C" BOOL APIENTRY SDlgSetTimer (HWND window, + UINT event, + UINT elapse, + TIMERPROC timerfunc); +extern "C" BOOL APIENTRY SDlgUpdateCursor (); + +#define SDlgCreateDialog(ins,tpl,wnd,prc) SDlgCreateDialogParam(ins,tpl,wnd,prc,0) +#define SDlgCreateDialogIndirect(ins,tpl,wnd,prc) SDlgCreateDialogIndirectParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBox(ins,tpl,wnd,prc) SDlgDialogBoxParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBoxIndirect(ins,tpl,wnd,prc) SDlgDialogBoxIndirectParam(ins,tpl,wnd,prc,0) + +#ifdef SDLG_USE_INCLUSIVE_RECTS +#define SDlgBltToWindow SDlgBltToWindowI +#define SDlgSetBitmap SDlgSetBitmapI +#else +#define SDlgBltToWindow SDlgBltToWindowE +#define SDlgSetBitmap SDlgSetBitmapE +#endif + +/**************************************************************************** +* +* DirectDraw functions +* +***/ + +#define SDRAW_SERVICE_BASIC 1 +#define SDRAW_SERVICE_PAGEFLIP 2 +#define SDRAW_SERVICE_DOUBLEBUFFER 3 +#define SDRAW_SERVICE_MAX 3 + +#define SDRAW_SURFACE_FRONT 0 +#define SDRAW_SURFACE_BACK 1 +#define SDRAW_SURFACE_SYSTEM 2 +#define SDRAW_SURFACE_TEMPORARY 3 + +#ifndef MAC +extern "C" BOOL APIENTRY SDrawAutoInitialize (HINSTANCE instance, + LPCTSTR classname, + LPCTSTR title, + WNDPROC wndproc = NULL, + int servicelevel = SDRAW_SERVICE_BASIC, + int width = 640, + int height = 480, + int bitdepth = 8); +extern "C" BOOL APIENTRY SDrawCaptureScreen (LPCTSTR filename = NULL); +#endif +extern "C" BOOL APIENTRY SDrawClearSurface (int surfacenumber); +extern "C" BOOL APIENTRY SDrawDestroy (); +extern "C" BOOL APIENTRY SDrawFlipPage (); +extern "C" HWND APIENTRY SDrawGetFrameWindow (HWND *window = NULL); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawGetObjects (LPDIRECTDRAW *directdraw, + LPDIRECTDRAWSURFACE *frontbuffer, + LPDIRECTDRAWSURFACE *backbuffer, + LPDIRECTDRAWSURFACE *systembuffer, + LPDIRECTDRAWSURFACE *temporarybuffer, + LPDIRECTDRAWPALETTE *palette, + HPALETTE *gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawGetScreenSize (int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SDrawGetServiceLevel (int *servicelevel = NULL); +extern "C" BOOL APIENTRY SDrawLockSurface (int surfacenumber, + LPCRECT rect, + LPBYTE *ptr, + int *pitch = NULL, + DWORD flags = 0); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawManualInitialize (HWND framewindow, + LPDIRECTDRAW directdraw, + LPDIRECTDRAWSURFACE frontbuffer, + LPDIRECTDRAWSURFACE backbuffer, + LPDIRECTDRAWSURFACE systembuffer, + LPDIRECTDRAWSURFACE temporarybuffer, + LPDIRECTDRAWPALETTE palette, + HPALETTE gdipalette); +#endif +extern "C" int APIENTRY SDrawMessageBox (LPCTSTR text, + LPCTSTR title, + UINT flags); +extern "C" BOOL APIENTRY SDrawPostClose (); +extern "C" BOOL APIENTRY SDrawRealizePalette (); +#ifndef MAC +extern "C" BOOL APIENTRY SDrawSelectGdiSurface (BOOL select, BOOL copy); +#endif +extern "C" BOOL APIENTRY SDrawUnlockSurface (int surfacenumber, + LPBYTE ptr, + DWORD numrects = 0, + LPCRECT rectarray = NULL); +extern "C" BOOL APIENTRY SDrawUpdatePalette (DWORD firstentry, + DWORD numentries, + LPPALETTEENTRY entries, + BOOL reservedentries = FALSE); +extern "C" BOOL APIENTRY SDrawUpdateScreen (LPCRECT rect); +#ifdef MAC +extern "C" BOOL APIENTRY SDrawVidDriverInitialize (HWND framewindow, + int servicelevel); +#endif + + +/**************************************************************************** +* +* Error handling functions +* +***/ + +#define SERR_LINECODE_FUNCTION -1 +#define SERR_LINECODE_OBJECT -2 +#define SERR_LINECODE_HANDLE -3 +#define SERR_LINECODE_FILE -4 + +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SErrDestroy (); +#endif +extern "C" BOOL APIENTRY SErrDisplayError (DWORD errorcode, + LPCTSTR filename, + int linenumber, + LPCTSTR description, + BOOL recoverable, + UINT exitcode = 1); +extern "C" BOOL APIENTRY SErrGetErrorStr (DWORD errorcode, + LPTSTR buffer, + DWORD bufferchars); +extern "C" DWORD APIENTRY SErrGetLastError (); +extern "C" BOOL APIENTRY SErrRegisterMessageSource (WORD facility, + HMODULE module, + LPVOID reserved = NULL); +extern "C" void APIENTRY SErrReportResourceLeak (LPCTSTR handlename); +extern "C" void APIENTRY SErrSetLastError (DWORD errorcode); +extern "C" void APIENTRY SErrSuppressErrors (BOOL suppress); + +#define SErrGetLastErrorStr(buf,len) SErrGetErrorStr(SErrGetLastError(),buf,len) +#define FATALRESULT(str) SErrDisplayError(SErrGetLastError(),str,SERR_LINECODE_FUNCTION,NULL,FALSE) +#define REPORTRESOURCELEAK(handle) SErrReportResourceLeak(#handle) + +#ifdef _DEBUG +#define ASSERT(a) if (!(a)) \ + SErrDisplayError(STORM_ERROR_ASSERTION, \ + __FILE__, \ + __LINE__, \ + #a, \ + FALSE) +#define VALIDATEBEGIN do { +#define VALIDATE(a) ASSERT(a) +#define VALIDATEANDBLANK(a) do { \ + ASSERT(a); \ + *(a) = 0; \ + } while (0) +#define VALIDATEEND } while (0) +#define VALIDATEENDVOID } while (0) +#else +#define ASSERT(a) +#define VALIDATEBEGIN do { \ + int intrn_valresult = -1 +#define VALIDATE(a) intrn_valresult &= (a) ? -1 : 0 +#define VALIDATEANDBLANK(a) if (a) \ + *a = 0; \ + else \ + intrn_valresult = 0 +#define VALIDATEEND if (!intrn_valresult) { \ + SErrSetLastError( \ + ERROR_INVALID_PARAMETER); \ + return 0; \ + } \ + } while (0) +#define VALIDATEENDVOID if (!intrn_valresult) { \ + SErrSetLastError( \ + ERROR_INVALID_PARAMETER); \ + return; \ + } \ + } while (0) +#endif + + +/**************************************************************************** +* +* Event dispatching functions +* +***/ + +typedef void (CALLBACK *SEVTHANDLER)(LPVOID); + +extern "C" BOOL APIENTRY SEvtBreakHandlerChain (LPVOID data); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SEvtDestroy (); +#endif +extern "C" BOOL APIENTRY SEvtDispatch (DWORD type, + DWORD subtype, + DWORD id, + LPVOID data); +extern "C" BOOL APIENTRY SEvtPopState (DWORD type, + DWORD subtype); +extern "C" BOOL APIENTRY SEvtPushState (DWORD type, + DWORD subtype); +extern "C" BOOL APIENTRY SEvtRegisterHandler (DWORD type, + DWORD subtype, + DWORD id, + DWORD flags, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterHandler (DWORD type, + DWORD subtype, + DWORD id, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterType (DWORD type, + DWORD subtype); + + +/**************************************************************************** +* +* File I/O functions +* +***/ + +#define SFILE_AUTH_UNABLETOAUTHENTICATE 0 +#define SFILE_AUTH_NOSIGNATURE 1 +#define SFILE_AUTH_BADSIGNATURE 2 +#define SFILE_AUTH_UNKNOWNSIGNATURE 3 +#define SFILE_AUTH_FIRSTAUTHENTIC 5 +#define SFILE_AUTH_AUTHENTICBLIZZARD 5 + +#define SFILE_DDA_LOOP 0x00040000 + +#define SFILE_ERROR_BAD_FORMAT ERROR_BAD_FORMAT +#define SFILE_ERROR_BAD_PATHNAME ERROR_BAD_PATHNAME +#define SFILE_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED +#define SFILE_ERROR_FILE_INVALID ERROR_FILE_INVALID +#define SFILE_ERROR_FILE_NOT_FOUND ERROR_FILE_NOT_FOUND +#define SFILE_ERROR_HANDLE_EOF ERROR_HANDLE_EOF +#define SFILE_ERROR_INVALID_DATA ERROR_INVALID_DATA +#define SFILE_ERROR_INVALID_DRIVE ERROR_INVALID_DRIVE +#define SFILE_ERROR_INVALID_HANDLE ERROR_INVALID_HANDLE +#define SFILE_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SFILE_ERROR_NOT_ARCHIVE STORM_ERROR_NOT_ARCHIVE +#define SFILE_ERROR_NOT_AUTHENTICATED ERROR_NOT_AUTHENTICATED +#define SFILE_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SFILE_ERROR_NOT_IN_ARCHIVE STORM_ERROR_NOT_IN_ARCHIVE +#define SFILE_ERROR_NOT_INITIALIZED STORM_ERROR_NOT_INITIALIZED +#define SFILE_ERROR_NOT_PLAYING STORM_ERROR_NOT_PLAYING + +#define SFILE_ERRORMODE_RETURNCODE 0 +#define SFILE_ERRORMODE_CUSTOM 1 +#define SFILE_ERRORMODE_FATAL 2 + +#define SFILE_FIND_FILES 0x00000001 +#define SFILE_FIND_DIRECTORIES 0x00000002 + +DECLARE_STRICT_HANDLE(HSARCHIVE); +DECLARE_STRICT_HANDLE(HSFILE); + +typedef BOOL (CALLBACK *SFILEERRORPROC)(LPCTSTR,DWORD); + +extern "C" BOOL APIENTRY SFileAuthenticateArchive (HSARCHIVE archive, + DWORD *extendedresult); +extern "C" BOOL APIENTRY SFileCloseArchive (HSARCHIVE handle); +extern "C" BOOL APIENTRY SFileCloseFile (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaBegin (HSFILE handle, + DWORD buffersize, + DWORD flags); +extern "C" BOOL APIENTRY SFileDdaBeginEx (HSFILE handle, + DWORD buffersize, + DWORD flags, + DWORD offset, + LONG volume, + LONG pan, + LPVOID reserved); +extern "C" BOOL APIENTRY SFileDdaDestroy (); +extern "C" BOOL APIENTRY SFileDdaEnd (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaGetPos (HSFILE handle, + DWORD *position, + DWORD *maxposition); +extern "C" BOOL APIENTRY SFileDdaGetVolume (HSFILE handle, + LONG *volume, + LONG *pan); +#ifdef __DSOUND_INCLUDED__ +extern "C" BOOL APIENTRY SFileDdaInitialize (LPDIRECTSOUND directsound); +#endif +extern "C" BOOL APIENTRY SFileDdaSetVolume (HSFILE handle, + LONG volume, + LONG pan); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SFileDestroy (); +#endif +extern "C" BOOL APIENTRY SFileEnableDirectAccess (BOOL enable); +extern "C" BOOL APIENTRY SFileGetArchiveInfo (HSARCHIVE archive, + int *priority, + BOOL *cdrom); +extern "C" BOOL APIENTRY SFileGetArchiveName (HSARCHIVE archive, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SFileGetBasePath (LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SFileGetFileArchive (HSFILE file, + HSARCHIVE *archive); +extern "C" BOOL APIENTRY SFileGetFileName (HSFILE file, + LPTSTR buffer, + DWORD bufferchars); +extern "C" DWORD APIENTRY SFileGetFileSize (HSFILE handle, + LPDWORD filesizehigh = NULL); +extern "C" BOOL APIENTRY SFileOpenArchive (LPCTSTR archivename, + int priority, + BOOL cdonly, + HSARCHIVE *handle); +extern "C" BOOL APIENTRY SFileOpenFile (LPCTSTR filename, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileEx (HSARCHIVE archivehandle, + LPCTSTR filename, + DWORD flags, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileReadFile (HSFILE handle, + LPVOID buffer, + DWORD bytestoread, + LPDWORD bytesread = NULL, + LPOVERLAPPED overlapped = NULL); +extern "C" BOOL APIENTRY SFileSetBasePath (LPCTSTR path); +extern "C" DWORD APIENTRY SFileSetFilePointer (HSFILE handle, + LONG distancetomove, + PLONG distancetomovehigh, + DWORD movemethod); +extern "C" BOOL APIENTRY SFileSetIoErrorMode (DWORD errormode, + SFILEERRORPROC errorproc = NULL); +extern "C" BOOL APIENTRY SFileSetLocale (LCID lcid); + + +/**************************************************************************** +* +* GDI functions +* +***/ + +#define ETO_TEXT_TRANSPARENT 0 +#define ETO_TEXT_COLOR 1 +#define ETO_TEXT_BLACK 2 +#define ETO_TEXT_WHITE 3 +#define ETO_BKG_TRANSPARENT 0 +#define ETO_BKG_COLOR 1 +#define ETO_BKG_BLACK 2 +#define ETO_BKG_WHITE 3 + +DECLARE_STRICT_HANDLE(HSGDIOBJ); +DECLARE_DERIVED_HANDLE(HSGDIFONT,HSGDIOBJ); + +extern "C" BOOL APIENTRY SGdiBitBlt (LPBYTE videobuffer, + int destx, + int desty, + LPBYTE sourcedata, + LPRECT sourcerect, + int sourcecx, + int sourcecy, + COLORREF color = 0, + DWORD rop = SRCCOPY); +extern "C" BOOL APIENTRY SGdiCreateFont (LPBYTE bits, + int width, + int height, + int bitdepth, + int filecharwidth, + int filecharheight, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiDeleteObject (HSGDIOBJ handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SGdiDestroy (); +#endif +extern "C" BOOL APIENTRY SGdiExtTextOut (LPBYTE videobuffer, + int x, + int y, + LPRECT rect, + COLORREF color, + int textcoloruse, + int bkgcoloruse, + LPCTSTR string, + int chars = -1); +extern "C" BOOL APIENTRY SGdiGetTextExtent (LPCTSTR string, + int chars, + LPSIZE size); +extern "C" BOOL APIENTRY SGdiImportFont (HFONT windowsfont, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiLoadFont (LPCTSTR filename, + int filecharwidth, + int filecharheight, + int basecharwidth, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiRectangle (LPBYTE videobuffer, + int left, + int top, + int right, + int bottom, + COLORREF color); +extern "C" BOOL APIENTRY SGdiSelectObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiSetPitch (int pitch); +extern "C" BOOL APIENTRY SGdiSetTargetDimensions (int width, + int height, + int bitdepth, + int pitch); +extern "C" BOOL APIENTRY SGdiTextOut (LPBYTE videobuffer, + int x, + int y, + COLORREF color, + LPCTSTR string, + int chars = -1); + + +/**************************************************************************** +* +* Logging functions +* +***/ + +DECLARE_STRICT_HANDLE(HSLOG); + +extern "C" void APIENTRY SLogClose (HSLOG log); +extern "C" BOOL APIENTRY SLogCreate (LPCTSTR filename, + DWORD flags, + HSLOG *log); +#ifdef STORMSTATIC +extern "C" void APIENTRY SLogDestroy (); +#endif +extern "C" void APIENTRY SLogDump (HSLOG log, + LPCVOID data, + DWORD bytes); +extern "C" void APIENTRY SLogFlush (HSLOG log); +extern "C" void APIENTRY SLogFlushAll (); +#ifdef STORMSTATIC +extern "C" void APIENTRY SLogInitialize (); +#endif +extern "C" void __cdecl SLogPend (HSLOG log, + LPCTSTR format, + ...); +extern "C" void __cdecl SLogWrite (HSLOG log, + LPCTSTR format, + ...); + + +/**************************************************************************** +* +* Memory allocation functions +* +***/ + +#define SMEM_FLAG_ZEROMEMORY 0x00000008 +#define SMEM_FLAG_PRESERVEONDESTROY 0x08000000 + +DECLARE_STRICT_HANDLE(HSHEAP); + +typedef struct _SMEMBLOCKDETAILS { + DWORD size; + LPVOID ptr; + BOOL allocated; + BOOL valid; + DWORD bytes; + DWORD overhead; +} SMEMBLOCKDETAILS, *LPSMEMBLOCKDETAILS; + +typedef struct _SMEMHEAPDETAILS { + DWORD size; + HSHEAP handle; + char filename[MAX_PATH]; + int linenumber; + DWORD regions; + DWORD committedbytes; + DWORD reservedbytes; + DWORD maximumsize; + DWORD allocatedblocks; +} SMEMHEAPDETAILS, *LPSMEMHEAPDETAILS; + +extern "C" LPVOID APIENTRY SMemAlloc (DWORD bytes, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SMemDestroy (); +#endif +extern "C" BOOL APIENTRY SMemFindNextBlock (HSHEAP heap, + LPVOID prevblock, + LPVOID *nextblock, + LPSMEMBLOCKDETAILS details); +extern "C" BOOL APIENTRY SMemFindNextHeap (HSHEAP prevheap, + HSHEAP *nextheap, + LPSMEMHEAPDETAILS details); +extern "C" BOOL APIENTRY SMemFree (LPVOID ptr, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" HSHEAP APIENTRY SMemGetHeapByCaller (LPCSTR filename, + int linenumber); +extern "C" HSHEAP APIENTRY SMemGetHeapByPtr (LPVOID ptr); +extern "C" LPVOID APIENTRY SMemHeapAlloc (HSHEAP handle, + DWORD flags, + DWORD bytes); +extern "C" HSHEAP APIENTRY SMemHeapCreate (DWORD options, + DWORD initialsize, + DWORD maximumsize); +extern "C" BOOL APIENTRY SMemHeapDestroy (HSHEAP handle); +extern "C" BOOL APIENTRY SMemHeapFree (HSHEAP handle, + DWORD flags, + LPVOID ptr); +#ifdef STORMSTATIC +extern "C" void APIENTRY SMemInitialize (); +#endif + +inline void __cdecl operator delete (void *ptr) { + if (ptr) + SMemFree(ptr,__FILE__,__LINE__,0); +} + +inline void * __cdecl operator new (size_t bytes) { + return SMemAlloc(bytes,__FILE__,__LINE__,0); +} + +#ifndef __ICL +#ifndef __MWERKS__ +inline void __cdecl operator delete[] (void *ptr) { + if (ptr) + SMemFree(ptr,__FILE__,__LINE__,0); +} + +inline void * __cdecl operator new[] (size_t bytes) { + return SMemAlloc(bytes,__FILE__,__LINE__,0); +} +#endif +#endif + +#ifndef __PLACEMENT_NEW_INLINE +#define __PLACEMENT_NEW_INLINE +inline void * __cdecl operator new (size_t, void *ptr) { + return (ptr); +} + +inline void * __cdecl operator new[] (size_t, void *ptr) { + return (ptr); +} +#endif + +#define ALLOC(bytes) SMemAlloc(bytes,__FILE__,__LINE__,0) +#define ALLOCZERO(bytes) SMemAlloc(bytes,__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) +#define DEL(ptr) delete(ptr) +#define DELIFUSED(ptr) delete(ptr) +#define FREE(ptr) SMemFree(ptr,__FILE__,__LINE__,0) +#define FREEIFUSED(ptr) do if (ptr) SMemFree(ptr,__FILE__,__LINE__,0); while (0) +#define NEW(struct) (new(SMemAlloc(sizeof(struct),__FILE__,__LINE__,0)) struct) +#define NEWZERO(struct) (new(SMemAlloc(sizeof(struct),__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY)) struct) + + +/**************************************************************************** +* +* Message functions +* +***/ + +typedef struct _PARAMS { + HWND window; + UINT message; + WPARAM wparam; + LPARAM lparam; + UINT notifycode; + LPVOID extra; + BOOL useresult; + LRESULT result; +} PARAMS, *PARAMSPTR, *LPPARAMS; + +typedef BOOL (CALLBACK *SMSGIDLEPROC)(DWORD); +typedef void (CALLBACK *SMSGHANDLER)(LPPARAMS); + +extern "C" BOOL APIENTRY SMsgBreakHandlerChain (LPPARAMS params); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SMsgDestroy (); +#endif +extern "C" BOOL APIENTRY SMsgDispatchMessage (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL *useresult, + LRESULT *result); +extern "C" BOOL APIENTRY SMsgDoMessageLoop (SMSGIDLEPROC idleproc = NULL, + BOOL cleanuponquit = TRUE); +extern "C" BOOL APIENTRY SMsgPopRegisterState (HWND window); +extern "C" BOOL APIENTRY SMsgPushRegisterState (HWND window); +extern "C" BOOL APIENTRY SMsgRegisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); + + +/**************************************************************************** +* +* Networking functions +* +***/ + +#define SNET_ART_BACKGROUND 0 +#define SNET_ART_BUTTONTEXTURE 1 +#define SNET_ART_JOINBACKGROUND 2 +#define SNET_ART_HELPBACKGROUND 3 +#define SNET_ART_POPUPBACKGROUND 4 +#define SNET_ART_BUTTON_XSML 5 +#define SNET_ART_BUTTON_SML 6 +#define SNET_ART_BUTTON_MED 7 +#define SNET_ART_BUTTON_LRG 8 +#define SNET_ART_APP_LOGO_SML 9 +#define SNET_ART_PROGRESS_BACKGROUND 10 +#define SNET_ART_PROGRESS_FILLER 11 +#define SNET_ART_POPUPBACKGROUND_SML 12 +#define SNET_ART_SCROLLBARARROWS 13 +#define SNET_ART_SCROLLTHUMB 14 +#define SNET_ART_SCROLLBAR 15 +#define SNET_ART_COMBOLEFT 16 +#define SNET_ART_COMBOMIDDLE 17 +#define SNET_ART_COMBORIGHT 18 + +#define SNET_AUTHTYPE_CHANNEL 1 +#define SNET_AUTHTYPE_GAME 2 + +#define SNET_BROADCASTNONLOCALPLAYERID 0xFFFFFFFE +#define SNET_BROADCASTPLAYERID 0xFFFFFFFF +#define SNET_INVALIDPLAYERID 0xFFFFFFFF + +#define SNET_CAPS_PAGELOCKEDBUFFERS 0x00000001 +#define SNET_CAPS_BASICINTERFACE 0x00000002 +#define SNET_CAPS_DEBUGONLY 0x10000000 +#define SNET_CAPS_RETAILONLY 0x20000000 + +#define SNET_CF_ALLOWPRIVATEGAMES 0x00000001 + +#define SNET_DATA_SYSCOLORS 1 +#define SNET_DATA_CURSORLINK 2 +#define SNET_DATA_CURSORARROW 3 +#define SNET_DATA_CURSORIBEAM 4 + +#define SNET_DDF_INCLUDENAME 0x00000001 +#define SNET_DDF_MULTILINE 0x00000002 + +#define SNET_DDPF_BLIZZARD 0x00000001 +#define SNET_DDPF_MODERATOR 0x00000002 +#define SNET_DDPF_SPEAKER 0x00000004 +#define SNET_DDPF_SYSOP 0x00000008 +#define SNET_DDPF_SQUELCHED 0x00000020 + +#define SNET_DRAWTYPE_GAME 1 +#define SNET_DRAWTYPE_PLAYER 2 + +#define SNET_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS +#define SNET_ERROR_BAD_PROVIDER ERROR_BAD_PROVIDER +#define SNET_ERROR_CANCELLED ERROR_CANCELLED +#define SNET_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SNET_ERROR_INVALID_PLAYER STORM_ERROR_INVALID_PLAYER +#define SNET_ERROR_GAME_ALREADY_STARTED STORM_ERROR_GAME_ALREADY_STARTED +#define SNET_ERROR_GAME_FULL STORM_ERROR_GAME_FULL +#define SNET_ERROR_GAME_NOT_FOUND STORM_ERROR_GAME_NOT_FOUND +#define SNET_ERROR_GAME_TERMINATED STORM_ERROR_GAME_TERMINATED +#define SNET_ERROR_HOST_UNREACHABLE ERROR_HOST_UNREACHABLE +#define SNET_ERROR_MAX_THRDS_REACHED ERROR_MAX_THRDS_REACHED +#define SNET_ERROR_NETWORK_BUSY ERROR_NETWORK_BUSY +#define SNET_ERROR_NO_MESSAGES_WAITING STORM_ERROR_NO_MESSAGES_WAITING +#define SNET_ERROR_NO_NETWORK ERROR_NO_NETWORK +#define SNET_ERROR_NOT_CONNECTED ERROR_NOT_CONNECTED +#define SNET_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SNET_ERROR_NOT_IMPLEMENTED STORM_ERROR_NOT_IMPLEMENTED +#define SNET_ERROR_NOT_IN_GAME STORM_ERROR_NOT_IN_GAME +#define SNET_ERROR_NOT_OWNER ERROR_NOT_OWNER +#define SNET_ERROR_NOT_REGISTERED STORM_ERROR_NOT_REGISTERED +#define SNET_ERROR_REQUIRES_UPGRADE STORM_ERROR_REQUIRES_UPGRADE +#define SNET_ERROR_STILL_ACTIVE STORM_ERROR_STILL_ACTIVE +#define SNET_ERROR_TOO_MANY_NAMES ERROR_TOO_MANY_NAMES +#define SNET_ERROR_VERSION_MISMATCH STORM_ERROR_VERSION_MISMATCH + +#define SNET_EVENT_INITDATA 1 +#define SNET_EVENT_PLAYERJOIN 2 +#define SNET_EVENT_PLAYERLEAVE 3 +#define SNET_EVENT_SERVERMESSAGE 4 + +#define SNET_EXIT_AUTO_JOINING 0x00000001 +#define SNET_EXIT_AUTO_NEWGAME 0x00000002 +#define SNET_EXIT_AUTO_SHUTDOWN 0x00000003 +#define SNET_EXIT_PLAYERQUIT 0x40000001 +#define SNET_EXIT_PLAYERKILLED 0x40000002 +#define SNET_EXIT_PLAYERWON 0x40000004 +#define SNET_EXIT_GAMEOVER 0x40000005 +#define SNET_EXIT_NOTRESPONDING 0x40000006 + +#define SNET_GM_PRIVATE 0x00000001 +#define SNET_GM_FULL 0x00000002 +#define SNET_GM_ADVERTISED 0x00000004 +#define SNET_GM_UNJOINABLE 0x00000008 +#define SNET_GM_UNLISTEDMASK (SNET_GM_PRIVATE | SNET_GM_FULL | SNET_GM_UNJOINABLE) + +#define SNET_INFO_GAMENAME 1 +#define SNET_INFO_GAMEPASSWORD 2 +#define SNET_INFO_GAMEDESCRIPTION 3 +#define SNET_INFO_GAMEMODE 4 +#define SNET_INFO_INITDATA 5 +#define SNET_INFO_MAXPLAYERS 6 + +#define SNET_LMT_EXPECTED 1 +#define SNET_LMT_CURRENT 2 +#define SNET_LMT_PEAK 4 + +#define SNET_PERFID_TURN 1 +#define SNET_PERFID_TURNSSENT 4 +#define SNET_PERFID_TURNSRECV 5 +#define SNET_PERFID_MSGSENT 6 +#define SNET_PERFID_MSGRECV 7 +#define SNET_PERFID_USERBYTESSENT 8 +#define SNET_PERFID_USERBYTESRECV 9 +#define SNET_PERFID_TOTALBYTESSENT 10 +#define SNET_PERFID_TOTALBYTESRECV 11 +#define SNET_PERFID_PKTSENTONWIRE 12 +#define SNET_PERFID_PKTRECVONWIRE 13 +#define SNET_PERFID_BYTESSENTONWIRE 14 +#define SNET_PERFID_BYTESRECVONWIRE 15 +#define SNET_PERFIDNUM 16 + +#define SNET_PERFTYPE_COUNTER 0x10410400 +#define SNET_PERFTYPE_RAWCOUNT 0x00010000 + +#define SNET_PSF_ACTIVE 0x00010000 +#define SNET_PSF_TURNAVAILABLE 0x00020000 +#define SNET_PSF_RESPONDING 0x00040000 + +#define SNET_SF_ALLOWCREATE 0x00000001 + +#define SNET_SND_CHANGEFOCUS 0 +#define SNET_SND_SELECTITEM 1 + +#define SNET_UPGRADE_FAILED -1 +#define SNET_UPGRADE_NOT_NEEDED 0 +#define SNET_UPGRADE_SUCCEEDED 1 +#define SNET_UPGRADING_TERMINATE 2 + +#define SNET_MAXNAMELENGTH 128 +#define SNET_MAXDESCLENGTH 128 + +typedef struct _SNETCAPS { + DWORD size; + DWORD flags; + DWORD maxmessagesize; + DWORD maxqueuesize; + DWORD maxplayers; + DWORD bytessec; + DWORD latencyms; + DWORD defaultturnssec; + DWORD defaultturnsintransit; +} SNETCAPS, *SNETCAPSPTR; + +typedef struct _SNETCREATEDATA { + DWORD size; + DWORD providerid; + DWORD maxplayers; + DWORD createflags; +} SNETCREATEDATA, *SNETCREATEDATAPTR; + +typedef struct _SNET_DATA_SYSCOLORTABLE { + DWORD syscolor; + COLORREF rgb; +} SNET_DATA_SYSCOLORTABLE, *SNET_DATA_SYSCOLORTABLEPTR; + +typedef struct _SNETEVENT { + DWORD eventid; + DWORD playerid; + LPVOID data; + DWORD databytes; +} SNETEVENT, *SNETEVENTPTR; + +typedef struct _SNETGAME { + DWORD size; + DWORD id; + LPCSTR gamename; + LPCSTR gamedescription; + DWORD categorybits; + DWORD numplayers; + DWORD maxplayers; +} SNETGAME, *SNETGAMEPTR; + +struct _SNETPROGRAMDATA; +struct _SNETPLAYERDATA; +struct _SNETUIDATA; +struct _SNETVERSIONDATA; + +typedef BOOL (CALLBACK *SNETABORTPROC )(); +typedef void (CALLBACK *SNETADDCATEGORYPROC )(LPCSTR,DWORD,DWORD); +typedef void (CALLBACK *SNETCATEGORYLISTPROC )(_SNETPLAYERDATA *,SNETADDCATEGORYPROC); +typedef BOOL (CALLBACK *SNETCATEGORYPROC )(BOOL,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *,DWORD *); +typedef BOOL (CALLBACK *SNETCHECKAUTHPROC )(DWORD,LPCSTR,LPCSTR,DWORD,LPCSTR,LPSTR,DWORD); +typedef BOOL (CALLBACK *SNETCREATEPROC )(SNETCREATEDATAPTR,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *); +typedef BOOL (CALLBACK *SNETDRAWDESCPROC )(DWORD,DWORD,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,LPDRAWITEMSTRUCT); +typedef BOOL (CALLBACK *SNETENUMDEVICESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMGAMESEXPROC )(SNETGAMEPTR); +typedef BOOL (CALLBACK *SNETENUMGAMESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMPROVIDERSPROC)(DWORD,LPCSTR,LPCSTR,SNETCAPSPTR); +typedef void (CALLBACK *SNETEVENTPROC )(SNETEVENTPTR); +typedef BOOL (CALLBACK *SNETGETARTPROC )(DWORD,DWORD,LPPALETTEENTRY,LPBYTE,DWORD,int *,int *,int *); +typedef BOOL (CALLBACK *SNETGETDATAPROC )(DWORD,DWORD,LPVOID,DWORD,DWORD *); +typedef int (CALLBACK *SNETMESSAGEBOXPROC )(HWND,LPCSTR,LPCSTR,UINT); +typedef BOOL (CALLBACK *SNETPLAYSOUNDPROC )(DWORD,DWORD,DWORD); +typedef BOOL (CALLBACK *SNETSELECTEDPROC )(DWORD,SNETCAPSPTR,_SNETUIDATA *,_SNETVERSIONDATA *); +typedef BOOL (CALLBACK *SNETSTATUSPROC )(LPCSTR,DWORD,DWORD,DWORD,SNETABORTPROC); +typedef BOOL (CALLBACK *SNETPROFILEPROC )(); // tbd -- include callback to save info +typedef BOOL (CALLBACK *SNETNEWACCOUNTPROC )(); // tbd -- include callback to try to create + +typedef struct _SNETPLAYERDATA { + DWORD size; + LPCSTR playername; + LPCSTR playerdescription; + // new for 1.05: + LPCSTR displayedfields; +} SNETPLAYERDATA, *SNETPLAYERDATAPTR; + +typedef struct _SNETPROGRAMDATA { + DWORD size; + LPCSTR programname; + LPCSTR programdescription; + DWORD programid; + DWORD versionid; + DWORD reserved1; + DWORD maxplayers; + LPVOID initdata; + DWORD initdatabytes; + LPVOID reserved2; + DWORD optcategorybits; +} SNETPROGRAMDATA, *SNETPROGRAMDATAPTR; + +typedef struct _SNETUIDATA { + DWORD size; + DWORD uiflags; + HWND parentwindow; + SNETGETARTPROC artcallback; + SNETCHECKAUTHPROC authcallback; + SNETCREATEPROC createcallback; + SNETDRAWDESCPROC drawdesccallback; + SNETSELECTEDPROC selectedcallback; + SNETMESSAGEBOXPROC messageboxcallback; + SNETPLAYSOUNDPROC soundcallback; + SNETSTATUSPROC statuscallback; + SNETGETDATAPROC getdatacallback; + SNETCATEGORYPROC categorycallback; + // new for 1.05: + SNETCATEGORYLISTPROC categorylistcallback; + SNETNEWACCOUNTPROC newaccountcallback; + SNETPROFILEPROC profilecallback; +} SNETUIDATA, *SNETUIDATAPTR; + +typedef struct _SNETVERSIONDATA { + DWORD size; + LPCSTR versionstring; + LPCSTR executablefile; + LPCSTR originalarchivefile; + LPCSTR patcharchivefile; +} SNETVERSIONDATA, *SNETVERSIONDATAPTR; + +extern "C" BOOL APIENTRY SNetCreateGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamecategorybits, + LPVOID initdata, + DWORD initdatabytes, + DWORD maxplayers, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetDestroy (); +extern "C" BOOL APIENTRY SNetDropPlayer (DWORD playerid, DWORD exitcode); +extern "C" BOOL APIENTRY SNetEnumDevices (SNETENUMDEVICESPROC callback); +extern "C" BOOL APIENTRY SNetEnumGames (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumGamesEx (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESEXPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumProviders (SNETCAPSPTR mincaps, + SNETENUMPROVIDERSPROC callback); +extern "C" BOOL APIENTRY SNetGetGameInfo (DWORD index, + LPVOID buffer, + DWORD buffersize, + DWORD *byteswritten); +extern "C" BOOL APIENTRY SNetGetNetworkLatency (DWORD measurementtype, + DWORD *result); +extern "C" BOOL APIENTRY SNetGetNumPlayers (DWORD *firstplayerid, + DWORD *lastplayerid, + DWORD *activeplayers); +extern "C" BOOL APIENTRY SNetGetOwnerId (DWORD *playerid); +extern "C" BOOL APIENTRY SNetGetOwnerTurnsWaiting (DWORD *turns); +extern "C" BOOL APIENTRY SNetGetPerformanceData (DWORD counterid, + DWORD *countervalue, + DWORD *countertype, + LONG *counterscale, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +extern "C" BOOL APIENTRY SNetGetPlayerCaps (DWORD playerid, + SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetPlayerName (DWORD playerid, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SNetGetProviderCaps (SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetTurnsInTransit (DWORD *turns); +extern "C" BOOL APIENTRY SNetInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetInitializeProvider (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetJoinGame (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetLeaveGame (DWORD exitcode); +extern "C" BOOL APIENTRY SNetPerformUpgrade (DWORD *upgradestatus); +extern "C" BOOL APIENTRY SNetReceiveMessage (DWORD *senderplayerid, + LPVOID *data, + DWORD *databytes); +extern "C" BOOL APIENTRY SNetReceiveTurns (DWORD firstplayerid, + DWORD arraysize, + LPVOID *arraydata, + LPDWORD arraydatabytes, + LPDWORD arrayplayerstatus); +extern "C" BOOL APIENTRY SNetRegisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); +extern "C" BOOL APIENTRY SNetResetLatencyMeasurements (); +extern "C" BOOL APIENTRY SNetSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY SNetSendMessage (DWORD targetplayerid, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSendServerChatCommand (LPCSTR command); +extern "C" BOOL APIENTRY SNetSendTurn (LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSetBasePlayer (DWORD playerid); +extern "C" BOOL APIENTRY SNetSetGameMode (DWORD modeflags); +extern "C" BOOL APIENTRY SNetUnregisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); + + +/**************************************************************************** +* +* Networking service provider interface +* +***/ + +#define SNETSPI_MAXCLIENTDATA 256 +#define SNETSPI_MAXSTRINGLENGTH 128 + +typedef struct _SNETADDR { + BYTE address[16]; +} SNETADDR, *SNETADDRPTR; + +typedef struct _SNETSPI_DEVICELIST { + DWORD deviceid; + SNETCAPS devicecaps; + char devicename[SNETSPI_MAXSTRINGLENGTH]; + char devicedescription[SNETSPI_MAXSTRINGLENGTH]; + DWORD reserved; + _SNETSPI_DEVICELIST *next; +} SNETSPI_DEVICELIST, *SNETSPI_DEVICELISTPTR; + +typedef struct _SNETSPI_GAMELIST { + DWORD gameid; + DWORD gamemode; + DWORD creationtime; + SNETADDR owner; + DWORD ownerlatency; + DWORD ownerlasttime; + DWORD gamecategorybits; + char gamename[SNETSPI_MAXSTRINGLENGTH]; + char gamedescription[SNETSPI_MAXSTRINGLENGTH]; + _SNETSPI_GAMELIST *next; + // new for 1.05: + LPVOID clientdata; + DWORD clientdatabytes; +} SNETSPI_GAMELIST, *SNETSPI_GAMELISTPTR; + +typedef struct _SNETSPI { + DWORD size; + BOOL (CALLBACK *CompareNetAddresses)(SNETADDRPTR,SNETADDRPTR,DWORD *); + BOOL (CALLBACK *Destroy)(); + BOOL (CALLBACK *Free)(SNETADDRPTR,LPVOID,DWORD); + BOOL (CALLBACK *FreeExternalMessage)(LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *GetGameInfo)(DWORD,LPCSTR,LPCSTR,SNETSPI_GAMELIST *); + BOOL (CALLBACK *GetPerformanceData)(DWORD,DWORD *,LARGE_INTEGER *,LARGE_INTEGER *); + BOOL (CALLBACK *Initialize)(SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,HANDLE); + BOOL (CALLBACK *InitializeDevice)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR); + BOOL (CALLBACK *LockDeviceList)(SNETSPI_DEVICELISTPTR *); + BOOL (CALLBACK *LockGameList)(DWORD,DWORD,SNETSPI_GAMELISTPTR *); + +/* note: this is the way that the Receive call should look... + + BOOL (CALLBACK *Receive)(SNETADDRPTR *,LPVOID *,DWORD *); + + below is the receive call with two parameters switched around + to make it incompatible with older .snp's during the beta... */ + + BOOL (CALLBACK *Receive)(LPVOID *,DWORD *,SNETADDRPTR *); + + BOOL (CALLBACK *ReceiveExternalMessage)(LPCSTR *,LPCSTR *,LPCSTR *); + BOOL (CALLBACK *SelectGame)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,DWORD *); + BOOL (CALLBACK *Send)(DWORD,SNETADDRPTR *,LPVOID,DWORD); + BOOL (CALLBACK *SendExternalMessage)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *StartAdvertisingGame)(LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,DWORD,LPCVOID,DWORD); + BOOL (CALLBACK *StopAdvertisingGame)(); + BOOL (CALLBACK *UnlockDeviceList)(SNETSPI_DEVICELISTPTR); + BOOL (CALLBACK *UnlockGameList)(SNETSPI_GAMELISTPTR,DWORD *); + // new for 1.05: + BOOL (CALLBACK *GetLocalPlayerName)(LPSTR,DWORD,LPSTR,DWORD); +} SNETSPI, *SNETSPIPTR; + +typedef BOOL (APIENTRY *SNETSPIBIND )(DWORD,SNETSPIPTR *); +typedef BOOL (APIENTRY *SNETSPIQUERY)(DWORD,DWORD *,LPCSTR *,LPCSTR *,SNETCAPSPTR *); + + +/**************************************************************************** +* +* Registry functions +* +***/ + +#define SREG_FLAG_USERSPECIFIC 0x00000001 +#define SREG_FLAG_BATTLENET 0x00000002 +#define SREG_FLAG_FLUSHTODISK 0x00000008 +#define SREG_FLAG_MULTISZ 0x00000080 + +extern "C" BOOL APIENTRY SRegGetBaseKey (DWORD flags, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SRegLoadData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID buffer, + DWORD buffersize, + DWORD *bytesread); +extern "C" BOOL APIENTRY SRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SRegLoadValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *value); +extern "C" BOOL APIENTRY SRegSaveData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SRegSaveString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPCTSTR string); +extern "C" BOOL APIENTRY SRegSaveValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD value); + + +/**************************************************************************** +* +* Region manager functions +* +***/ + +#define SRGN_AND RGN_AND +#define SRGN_COPY RGN_COPY +#define SRGN_DIFF RGN_DIFF +#define SRGN_OR RGN_OR +#define SRGN_XOR RGN_XOR +#define SRGN_PARAMONLY 6 +#define SRGN_MIN 1 +#define SRGN_MAX 6 + +DECLARE_STRICT_HANDLE(HSRGN); + +extern "C" void APIENTRY SRgnClear (HSRGN handle); +extern "C" void APIENTRY SRgnCombineRect (HSRGN handle, + LPCRECT rect, + LPVOID param, + int combinemode); +extern "C" void APIENTRY SRgnCreate (HSRGN *handle, + DWORD reserved = 0); +extern "C" void APIENTRY SRgnDelete (HSRGN handle); +#ifdef STORMSTATIC +extern "C" void APIENTRY SRgnDestroy (); +#endif +extern "C" void APIENTRY SRgnDuplicate (HSRGN orighandle, + HSRGN *handle, + DWORD reserved = 0); +extern "C" void APIENTRY SRgnGetBoundingRect (HSRGN handle, + LPRECT rect); +extern "C" void APIENTRY SRgnGetRectParams (HSRGN handle, + LPCRECT rect, + DWORD *numparams, + LPVOID *buffer); +extern "C" void APIENTRY SRgnGetRects (HSRGN handle, + DWORD *numrects, + LPRECT buffer); + +#define SRgnAddParam(handle,rect,param) SRgnCombineRect(handle,rect,param,SRGN_PARAMONLY); +#define SRgnAddRect(handle,rect,param) SRgnCombineRect(handle,rect,param,SRGN_OR) + + +/**************************************************************************** +* +* Run-time library functions +* +***/ + +#define ONCE ONCEEXPAND(__FILE__##__##__LINE__##__once) +#define ONCEEXPAND(a) BOOL a = TRUE; a; a = FALSE + +#define TRY goto trylabel; trylabel: +#define LEAVE goto finallylabel +#define FINALLY goto finallylabel; finallylabel: + + +/**************************************************************************** +* +* String functions +* +***/ + +#define SSTR_HASH_CASESENSITIVE 0x00000001 + +#define SSTR_UNBOUNDED 0x7FFFFFFF + +extern "C" LPTSTR APIENTRY SStrChr (LPCTSTR string, + char ch, + BOOL reverse = FALSE); +extern "C" DWORD APIENTRY SStrCopy (LPTSTR dest, + LPCTSTR source, + DWORD destsize = SSTR_UNBOUNDED); +extern "C" DWORD APIENTRY SStrHash (LPCTSTR string, + DWORD flags = 0, + DWORD seed = 0); +extern "C" DWORD APIENTRY SStrLen (LPCTSTR string); +extern "C" void APIENTRY SStrPack (LPTSTR dest, + LPCTSTR source, + DWORD destsize = SSTR_UNBOUNDED); +extern "C" void APIENTRY SStrTokenize (LPCTSTR *string, + LPTSTR buffer, + DWORD bufferchars, + LPCTSTR whitespace, + BOOL *quoted = NULL); + + +/**************************************************************************** +* +* Transparency functions +* +***/ + +#define STRANS_CF_INTERSECT 0x00000001 +#define STRANS_CF_INVERTSECOND 0x00000002 +#define STRANS_CF_SUBTRACT (STRANS_CF_INTERSECT | STRANS_CF_INVERTSECOND) + +DECLARE_STRICT_HANDLE(HSTRANS); +typedef HSTRANS HTRANS; + +extern "C" BOOL APIENTRY STransBlt (LPBYTE dest, + int destx, + int desty, + int destpitch, + HSTRANS transparency); +extern "C" BOOL APIENTRY STransBltUsingMask (LPBYTE dest, + LPBYTE source, + int destpitch, + int sourcepitch, + HSTRANS mask); +extern "C" BOOL APIENTRY STransCombineMasks (HSTRANS basemask, + HSTRANS secondmask, + int offsetx, + int offsety, + DWORD flags, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateMaskE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateMaskI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransDelete (HSTRANS handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY STransDestroy (); +#endif +extern "C" BOOL APIENTRY STransDuplicate (HSTRANS source, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIntersectDirtyArray (HSTRANS sourcemask, + LPBYTE dirtyarray, + BYTE dirtyarraymask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransInvertMask (HSTRANS sourcemask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIsPixelInMask (HSTRANS mask, + int offsetx, + int offsety); +extern "C" BOOL APIENTRY STransLoadE (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransLoadI (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransSetDirtyArrayInfo (int screencx, + int screency, + int cellcx, + int cellcy); +extern "C" BOOL APIENTRY STransUpdateDirtyArray (LPBYTE dirtyarray, + BYTE dirtyvalue, + int destx, + int desty, + HSTRANS transparency, + BOOL tracecontour); + +#ifdef STRANS_USE_INCLUSIVE_RECTS +#define STransCreate STransCreateI +#define STransCreateMask STransCreateMaskI +#define STransLoad STransLoadI +#else +#define STransCreate STransCreateE +#define STransCreateMask STransCreateMaskE +#define STransLoad STransLoadE +#endif + + +/**************************************************************************** +* +* Video functions +* +***/ + +#define SVID_FLAG_DOUBLESCANS 0x00000001 +#define SVID_FLAG_INTERPOLATE 0x00000002 +#define SVID_FLAG_INTERLACE 0x00000004 +#define SVID_FLAG_AUTOQUALITY 0x00000008 +#define SVID_FLAG_1XSIZE 0x00000100 +#define SVID_FLAG_2XSIZE 0x00000200 +#define SVID_FLAG_AUTOSIZE 0x00000800 +#define SVID_FLAG_FILEHANDLE 0x00010000 +#define SVID_FLAG_PRELOAD 0x00020000 +#define SVID_FLAG_LOOP 0x00040000 +#define SVID_FLAG_FULLSCREEN 0x00080000 +#define SVID_FLAG_USECURRENTPALETTE 0x00100000 +#define SVID_FLAG_CLEARSCREEN 0x00200000 +#define SVID_FLAG_NOSKIP 0x00400000 +#define SVID_FLAG_NEEDPAN 0x02000000 +#define SVID_FLAG_NEEDVOLUME 0x04000000 +#define SVID_FLAG_TOSCREEN 0x10000000 +#define SVID_FLAG_TOBUFFER 0x20000000 + +#define SVID_CUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_2XSIZE) +#define SVID_AUTOCUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_AUTOSIZE | SVID_FLAG_AUTOQUALITY) + +#define SVID_QUALITY_LOW_SKIPSCANS SVID_FLAG_2XSIZE +#define SVID_QUALITY_LOW (SVID_FLAG_2XSIZE | SVID_FLAG_DOUBLESCANS) +#define SVID_QUALITY_HIGH_SKIPSCANS (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE) +#define SVID_QUALITY_HIGH (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE | SVID_FLAG_DOUBLESCANS) + +DECLARE_STRICT_HANDLE(HSVIDEO); + +typedef struct _SVIDPALETTEUSE { + DWORD size; + DWORD firstentry; + DWORD numentries; +} SVIDPALETTEUSE, *SVIDPALETTEUSEPTR; + +extern "C" BOOL APIENTRY SVidDestroy (); +extern "C" BOOL APIENTRY SVidGetPerformanceData (HSVIDEO video, + BOOL averageframems, + DWORD *framems, + BOOL averagepalettems, + DWORD *palettems); +extern "C" BOOL APIENTRY SVidGetSize (HSVIDEO video, + int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SVidInitialize (LPVOID directsound); +extern "C" BOOL APIENTRY SVidPlayBegin (LPCTSTR filename, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayBeginFromMemory (LPVOID sourceptr, + DWORD sourcebytes, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayContinue (); +extern "C" BOOL APIENTRY SVidPlayContinueSingle (HSVIDEO video, + BOOL forceupdate, + BOOL *updated); +extern "C" BOOL APIENTRY SVidPlayEnd (HSVIDEO video); +extern "C" BOOL APIENTRY SVidSetVolume (HSVIDEO video, + LONG volume, + LONG pan, + DWORD track = 0); + + +/**************************************************************************** +* +* Storm global functions +* +***/ + +extern "C" BOOL APIENTRY StormDestroy (); + +#ifdef MAC +extern "C" void StormStartup(); +extern "C" void StormShutdown(); +#endif + + +//#########################################################################// +//#########################################################################// +// // +// // +// CLASS-BASED PROGRAMMING INTERFACE // +// (under construction) // +// // +// // +//#########################################################################// +//#########################################################################// + + +/**************************************************************************** +* +* CSLog +* +***/ + +class CSLog { + + private: + HSLOG m_handle; + + public: + + //======================================================================= + CSLog (LPCTSTR filename) { + SLogCreate(filename,0,&m_handle); + } + + //======================================================================= + CSLog (LPCTSTR keyname, + LPCTSTR valuename) { + char filename[MAX_PATH] = ""; + SRegLoadString(keyname,valuename,0,filename,MAX_PATH); +#ifdef _DEBUG + SRegSaveString(keyname,valuename,0,filename); +#endif + if (filename[0]) + SLogCreate(filename,0,&m_handle); + } + + //======================================================================= + ~CSLog () { + SLogClose(m_handle); + } + + //======================================================================= + void Dump (LPCVOID data, + DWORD bytes) { + SLogDump(m_handle, + data, + bytes); + } + + //======================================================================= + void Flush () { + SLogFlush(m_handle); + } + + //======================================================================= + HSLOG GetHandle () { + return m_handle; + } + + //======================================================================= + void Pend (LPCSTR string) { + SLogPend(m_handle, + string); + } + + //======================================================================= + void Write (LPCSTR string) { + SLogWrite(m_handle, + string); + } + +}; + + +/**************************************************************************** +* +* CSRgn +* +***/ + +class CSRgn { + + private: + HSRGN m_handle; + + //======================================================================= + void CopyConstructor (const CSRgn & source) { + SRgnDuplicate(source.m_handle, + &m_handle); + } + + public: + + //======================================================================= + CSRgn () { + SRgnCreate(&m_handle); + } + + //======================================================================= + CSRgn (const CSRgn & source) { + CopyConstructor(source); + } + + //======================================================================= + ~CSRgn () { + SRgnDelete(m_handle); + } + + //======================================================================= + CSRgn & operator= (const CSRgn &source) { + if (this != &source) { + this->~CSRgn(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + void AddParam (LPCRECT rect, + LPVOID param) { + SRgnAddParam(m_handle, + rect, + param); + } + + //======================================================================= + void AddRect (LPCRECT rect, + LPVOID param) { + SRgnAddRect(m_handle, + rect, + param); + } + + //======================================================================= + void Clear () { + SRgnClear(m_handle); + } + + //======================================================================= + void CombineRect (LPCRECT rect, + LPVOID param, + int combinemode) { + SRgnCombineRect(m_handle, + rect, + param, + combinemode); + } + + //======================================================================= + void GetBoundingRect (LPRECT rect) { + SRgnGetBoundingRect(m_handle, + rect); + } + + //======================================================================= + void GetRects (DWORD *numrects, + LPRECT buffer) { + SRgnGetRects(m_handle, + numrects, + buffer); + } + + //======================================================================= + void GetRectParams (LPCRECT rect, + DWORD *numparams, + LPVOID *buffer) { + SRgnGetRectParams(m_handle, + rect, + numparams, + buffer); + } + +}; + + +//#########################################################################// +//#########################################################################// +// // +// // +// UTILITY CLASSES AND TEMPLATES // +// // +// // +//#########################################################################// +//#########################################################################// + + +/**************************************************************************** +* +* CCritSect -- Critical section class +* +* Methods: +* +* void Enter () +* void Leave () +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void Enter () { EnterCriticalSection(&m_critsect); } + void Enter (BOOL) { EnterCriticalSection(&m_critsect); } + void Leave () { LeaveCriticalSection(&m_critsect); } + void Leave (BOOL) { LeaveCriticalSection(&m_critsect); } +}; + + +/**************************************************************************** +* +* CLock -- Reader/writer lock class +* +* Methods: +* +* void Enter (BOOL forwriting) +* void Leave (BOOL fromwriting) +* +***/ + +class CLock { + + private: + + HANDLE m_mutexevent; + HANDLE m_readerevent; + LONG m_readercount; + + public: + + //======================================================================= + CLock () { + m_mutexevent = CreateEvent(NULL,FALSE,TRUE,NULL); + m_readerevent = CreateEvent(NULL,TRUE,FALSE,NULL); + m_readercount = -1; + } + + //======================================================================= + ~CLock () { + CloseHandle(m_readerevent); + CloseHandle(m_mutexevent); + } + + //======================================================================= + void Enter (BOOL forwriting) { + if (forwriting) + WaitForSingleObject(m_mutexevent,INFINITE); + else if (!InterlockedIncrement(&m_readercount)) { + WaitForSingleObject(m_mutexevent,INFINITE); + SetEvent(m_readerevent); + } + else + WaitForSingleObject(m_readerevent,INFINITE); + } + + //======================================================================= + void Leave (BOOL fromwriting) { + if (fromwriting) + SetEvent(m_mutexevent); + else if (InterlockedDecrement(&m_readercount) < 0) { + ResetEvent(m_readerevent); + SetEvent(m_mutexevent); + } + } + +}; + + +/**************************************************************************** +* +* CNullSync -- Null synchronization class +* +* (used for templates that take a synchronization class as a parameter) +* +***/ + +class CNullSync { + public: + void Enter (BOOL) { } + void Leave (BOOL) { } +}; + + +/**************************************************************************** +* +* type_info +* +* (used by templates to obtain the name of an object) +* +***/ + +#ifdef _MSC_VER + #ifdef _INC_TYPEINFO + #define INTERNALRAWNAME raw_name + #else + #define INTERNALRAWNAME internal_raw_name + class type_info { + public: + virtual ~type_info (); + const char * internal_raw_name () const { return _m_d_name; }; + private: + void *_m_data; + char _m_d_name[1]; + type_info (const type_info& rhs); + type_info& operator= (const type_info& rhs); + }; + #endif +#else + #if defined(MAC) && !defined(__typeinfo__) + #include + #endif + #define INTERNALRAWNAME name +#endif + + +/**************************************************************************** +* +* ARRAY -- Dynamically allocated array template +* +* Types: +* +* ARRAY(structname) -- dynamically sized array of struct +* +* Pointers to types: +* +* ARRAYPTR(structname) +* +* Array methods: +* +* void AddDiscontiguousElements (DWORD count, +* int stride, +* const *newelements); +* void AddElement (const *newelement); +* void AddElements (DWORD count, +* const *newelements); +* DWORD NumElements (); +* * NewElement (); +* * Ptr (); +* void ReserveSpace (DWORD count); +* void SetNumElements (DWORD totalcount); +* +***/ + +template +class TSArray { + + private: + DWORD m_allocchunksize; + T *m_data; + DWORD m_elements; + DWORD m_elementsalloc; + + //======================================================================= + BOOL CheckSpace (DWORD count) { + return (m_elements+count <= m_elementsalloc); + } + + //======================================================================= + void Constructor () { + m_allocchunksize = max(16,256/sizeof(T)); + m_data = NULL; + m_elements = 0; + m_elementsalloc = 0; + } + + //======================================================================= + void CopyConstructor (const TSArray & source) { + Constructor(); + m_allocchunksize = source.m_allocchunksize; + ReserveSpace(source.m_elementsalloc); + AddElements(source.m_elements, + source.m_data); + } + + public: + + //======================================================================= + TSArray () { + Constructor(); + } + + //======================================================================= + TSArray (const TSArray & source) { + CopyConstructor(source); + } + + //======================================================================= + ~TSArray () { + if (m_data) { + while (m_elements) { + --m_elements; + m_data[m_elements].~T(); + } + SMemFree(m_data,__FILE__,__LINE__,0); + m_data = NULL; + } + } + + //======================================================================= + TSArray & operator= (const TSArray &source) { + if (this != &source) { + this->~TSArray(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + T & operator[] (DWORD num) { + if (num >= m_elements) + SErrDisplayError(STORM_ERROR_ACCESS_OUT_OF_BOUNDS, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + NULL, + TRUE); + return m_data[num]; + } + + //======================================================================= + void AddDiscontiguousElements (DWORD count, + int stride, + const T *newelements) { + if (!CheckSpace(count)) + ReserveSpace(count); + if (stride == sizeof(T)) + AddElements(count,newelements); + else + for (DWORD loop = 0; loop < count; ++loop) { + new(m_data+m_elements++) T(*newelements); + newelements = (const T *)((LPBYTE)newelements+stride); + } + } + + //======================================================================= + void AddElement (const T *newelement) { + if (!CheckSpace(1)) + ReserveSpace(1); + new(m_data+m_elements++) T(*newelement); + } + + //======================================================================= + void AddElements (DWORD count, + const T *newelements) { + if (!CheckSpace(count)) + ReserveSpace(count); + for (DWORD loop = 0; loop < count; ++loop) + new(m_data+m_elements++) T(newelements[loop]); + } + + //======================================================================= + DWORD NumElements () { + return m_elements; + } + + //======================================================================= + T * NewElement () { + if (!CheckSpace(1)) + ReserveSpace(1); + return new(m_data+m_elements++) T; + } + + //======================================================================= + T * Ptr () { + if (!m_data) + ReserveSpace(1); + return m_data; + } + + //======================================================================= + void ReserveSpace (DWORD count) { + if (CheckSpace(count)) + return; + + // DETERMINE THE NUMBER OF NEW ELEMENTS TO ALLOCATE + DWORD newelements = m_elements+count; + DWORD partialchunk = newelements & (m_allocchunksize-1); + if (partialchunk) + newelements += m_allocchunksize-partialchunk; + + // ALLOCATE THE NEW ARRAY AND COPY DATA FROM THE OLD ARRAY + T *newdata = (T *)ALLOC(newelements*sizeof(T)); + if (m_data) { + for (DWORD loop = 0; loop < m_elements; ++loop) + new(newdata+loop) T(m_data[loop]); + FREE(m_data); + } + m_data = newdata; + m_elementsalloc = newelements; + + } + + //======================================================================= + void SetNumElements (DWORD totalcount) { + if (totalcount > m_elements) { + ReserveSpace(totalcount-m_elements); + for (DWORD loop = m_elements; loop < totalcount; ++loop) + new(m_data+loop) T; + } + else if (totalcount < m_elements) { + for (DWORD loop = totalcount; loop < m_elements; ++loop) + m_data[loop].~T(); + } + m_elements = totalcount; + } + +}; + +#define ARRAY(structname) TSArray< structname > +#define ARRAYDECL(structname,varname) TSArray< structname > varname +#define ARRAYPTR(structname) TSArray< structname > * + + +/**************************************************************************** +* +* NODE/LIST -- Linked list template +* +* Types: +* +* LINKEX(structname) -- explicit link field +* LIST(structname) -- linked list of implicitly linked nodes +* LISTEX(structname,linkname) -- linked list of explicitly linked nodes +* LISTEXDYN(structname) -- linked list of explicitly linked nodes, +* where the link field to be used by +* this list is not known at compile time +* NODEDECL(structname) -- implicitly linked node +* NODEDECLEX(structname) -- explicitly linked node (must contain one +* or more LINKEX fields) +* +* Pointers to types: +* +* LISTPTR(structname) +* LISTPTREX(structname) +* +* Link methods: +* +* * Next (); +* * Prev (); +* void Unlink (); +* +* Explicitly linked node methods: +* +* None. Use link methods for the link you want to manipulate. +* +* Implicitly linked node methods: +* +* * Next (); +* * Prev (); +* void Unlink (); +* +* List methods: +* +* void Clear (); +* * DeleteNode ( *ptr); +* * Head () const; +* BOOL IsEmpty () const; +* void LinkNode ( *ptr, +* DWORD linktype = LIST_TAIL, +* *existingptr = NULL); +* * NewNode (DWORD location = LIST_TAIL, +* DWORD extrabytes = 0, +* DWORD flags = 0); +* * Next (const *ptr) const; +* * Prev (const *ptr) const; +* * Tail () const; +* void UnlinkAll (); +* void UnlinkNode ( *ptr); +* +* Constants for use with LinkNode() and NewNode(): +* +* LIST_UNLINKED +* LIST_LINK_AFTER +* LIST_LINK_BEFORE +* LIST_HEAD +* LIST_TAIL +* +* Macros: +* +* LISTEXSETLINK(structname,listname,linkname) +* ITERATELIST(structname,listname,ptrname) +* ITERATELISTPTR(structname,listname,ptrname) +* ITERATEPARTIALLIST(structname,listname,start,ptrname) +* ITERATEPARTIALLISTPTR(structname,listname,start,ptrname) +* ITERATELISTREVERSE(structname,listname,ptrname) +* ITERATELISTREVERSEPTR(structname,listname,ptrname) +* ITERATEPARTIALLISTREVERSE(structname,listname,start,ptrname) +* ITERATEPARTIALLISTREVERSEPTR(structname,listname,start,ptrname) +* ITERATE_DELETE +* ITERATE_DELETEANDBREAK +* +***/ + +#define LIST_UNLINKED 0 +#define LIST_LINK_AFTER 1 +#define LIST_LINK_BEFORE 2 +#define LIST_HEAD LIST_LINK_AFTER +#define LIST_TAIL LIST_LINK_BEFORE + +template +class TSList; + +template +class TSLink { + friend class TSList; + friend class TSList; + + private: + TSLink *m_prevlink; + T *m_next; + + //======================================================================= + void Constructor () { + m_prevlink = NULL; + m_next = NULL; + } + + //======================================================================= + void CopyConstructor (const TSLink &) { + Constructor(); + } + + //======================================================================= + TSLink *NextLink () const { + + // IF THE NEXT NODE IS A TERMINATOR, ITS LINK POINTER IS THE SAME AS + // ITS NODE POINTER. + if ((int)m_next < 0) + return (TSLink *)~(DWORD)m_next; + + // OTHERWISE, COMPUTE THE LINK ADDRESS BY USING THE OFFSET OF THIS + // NODE'S LINK AND POINTER ADDRESSES. (THIS NODE MUST NOT BE A + // TERMINATOR.) + else { + DWORD linkoffset = (DWORD)this-(DWORD)(m_prevlink->m_next); + return (TSLink *)(linkoffset+(DWORD)m_next); + } + + } + + protected: + + //======================================================================= + T *NextThroughTerminator () const { + return ((int)m_next > 0) ? m_next : (T *)~(DWORD)m_next; + } + + public: + + //======================================================================= + TSLink () { + Constructor(); + } + + //======================================================================= + TSLink (const TSLink & source) { + CopyConstructor(source); + } + + //======================================================================= + ~TSLink () { + Unlink(); + } + + //======================================================================= + TSLink & operator= (const TSLink &) { + // LEAVE THE DESTINATION NODE LINKED INTO ITS CURRENT LIST + return *this; + } + + //======================================================================= + T * Next () const { + return ((int)m_next > 0) ? m_next : NULL; + } + + //======================================================================= + T * Prev () const { + return m_prevlink->m_prevlink->Next(); + } + + //======================================================================= + void Unlink () { + if (!m_prevlink) + return; + NextLink()->m_prevlink = m_prevlink; + m_prevlink->m_next = m_next; + m_prevlink = NULL; + m_next = NULL; + } + +}; + +template +class TSBaseNode { + public: + + //======================================================================= + inline void * __cdecl operator new (size_t bytes, + size_t extra, + DWORD flags) { + void *ptr = SMemAlloc(bytes+extra, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + flags | SMEM_FLAG_ZEROMEMORY); + return ptr; + } + +}; + +template +class TSExplicitNode : public TSBaseNode { + friend class TSList; + + private: + + //======================================================================= + TSLink *Link (BOOL explicitlink, int linkoffset) const { + ASSERT(explicitlink); + explicitlink; + return (TSLink *)((LPBYTE)this+linkoffset); + } + +}; + +template +class TSLinkedNode : public TSBaseNode { + friend class TSList; + + private: + TSLink m_link; + + //======================================================================= + TSLink *Link (BOOL explicitlink, int linkoffset) const { + if (explicitlink) + return (TSLink *)((LPBYTE)this+linkoffset); + else + return (TSLink *)&m_link; + } + + public: + + //======================================================================= + ~TSLinkedNode () { + Unlink(); + } + + //======================================================================= + T * Next () const { + return m_link.Next(); + } + + //======================================================================= + T * Prev () const { + return m_link.Prev(); + } + + //======================================================================= + void Unlink () { + m_link.Unlink(); + } + +}; + +template +class TSList { + + private: + int m_linkoffset; + TSLink m_terminator; + + //======================================================================= + void Constructor () { + m_linkoffset = 0; + InitializeTerminator(); + } + + //======================================================================= + void CopyConstructor (const TSList & source) { + m_linkoffset = source.m_linkoffset; + InitializeTerminator(); + } + + //======================================================================= + void InitializeTerminator () { + m_terminator.m_prevlink = &m_terminator; + m_terminator.m_next = (T *)~(DWORD)&m_terminator; + } + + //======================================================================= + TSLink *Link (const T *ptr) const { + // THIS FUNCTION CALLS THE LINK METHOD IN EITHER THE NODE OR THE LINK + // TO WHICH THIS LIST REFERS. IF THIS FUNCTION WON'T COMPILE, IT'S + // BECAUSE A NODE WITH EXPLICIT LINKS WAS DEFINED WITH NODEDECL() + // INSTEAD OF NODEDECLEX(). + return ptr->Link(explicitlink,m_linkoffset); + } + + protected: + + //======================================================================= + void SetLinkOffset (int linkoffset) { + m_linkoffset = linkoffset; + InitializeTerminator(); + } + + public: + + //======================================================================= + TSList () { + Constructor(); + }; + + //======================================================================= + TSList (const TSList &source) { + CopyConstructor(source); + }; + + //======================================================================= + TSList (int linkoffset) { + m_linkoffset = linkoffset; + InitializeTerminator(); + }; + + //======================================================================= + ~TSList () { + UnlinkAll(); + } + + //======================================================================= + TSList & operator= (const TSList &source) { + if (this != &source) { + this->~TSList(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + void ChangeLinkOffset (int linkoffset) { + UnlinkAll(); + SetLinkOffset(linkoffset); + } + + //======================================================================= + void Clear () { + T *curr; + while ((curr = Head()) != NULL) + delete curr; + } + + //======================================================================= + T * DeleteNode (T *ptr) { + T *nextptr = Next(ptr); + delete ptr; + return nextptr; + } + + //======================================================================= + T * Head () const { + return m_terminator.Next(); + } + + //======================================================================= + BOOL IsEmpty () const { + return !m_terminator.Next(); + } + + //======================================================================= + T * Iterate_RawNext (const T *ptr) const { + return Link(ptr)->m_next; + } + + //======================================================================= + void LinkNode (T *ptr, + DWORD linktype = LIST_TAIL, + T *existingptr = NULL) { + TSLink *link = Link(ptr); + + // IF THIS NODE IS ALREADY LINKED INTO THE LIST, UNLINK IT + if (link->m_prevlink) + link->Unlink(); + + // FIND THE NODE THAT WE WILL LINK BEFORE OR AFTER. USE THE + // TERMINATOR NODE IF WE'RE LINKING ONTO THE HEAD OR TAIL. + TSLink *existinglink; + if (existingptr) + existinglink = Link(existingptr); + else + existinglink = &m_terminator; + + // LINK THIS NODE INTO THE LIST + switch (linktype) { + + case LIST_LINK_AFTER: + { + link->m_prevlink = existinglink; + link->m_next = existinglink->m_next; + Link(existinglink->NextThroughTerminator())->m_prevlink = link; + existinglink->m_next = ptr; + } + break; + + case LIST_LINK_BEFORE: + { + TSLink *prevlink = existinglink->m_prevlink; + link->m_prevlink = prevlink; + link->m_next = prevlink->m_next; + prevlink->m_next = ptr; + existinglink->m_prevlink = link; + } + break; + + } + } + + //======================================================================= + T * NewNode (DWORD location = LIST_TAIL, + DWORD extrabytes = 0, + DWORD flags = 0) { + T *ptr = new(extrabytes,flags) T; + if (location != LIST_UNLINKED) + LinkNode(ptr,location); + return ptr; + } + + //======================================================================= + T * Next (const T *ptr) const { + return Link(ptr)->Next(); + } + + //======================================================================= + T * Prev (const T *ptr) const { + return Link(ptr)->Prev(); + } + + //======================================================================= + T * Tail () const { + return m_terminator.Prev(); + } + + //======================================================================= + void UnlinkAll () { + T *curr; + while ((curr = Head()) != NULL) + UnlinkNode(curr); + } + + //======================================================================= + void UnlinkNode (T *ptr) { + Link(ptr)->Unlink(); + } + +}; + +template +class TSExplicitList : public TSList { + public: + + //======================================================================= + TSExplicitList () { + SetLinkOffset(linkoffset); + } + +}; + + +#define LINKEX(structname) TSLink< structname > +#define LINKDECLEX(structname,varname) TSLink< structname > varname +#define LIST(structname) TSList< structname ,FALSE> +#define LISTDECL(structname,varname) TSList< structname ,FALSE> varname +#define LISTPTR(structname) TSList< structname ,FALSE> * +#define LISTPTREX(structname) TSList< structname ,TRUE> * +#define NODEDECL(structname) typedef struct structname : public TSLinkedNode< structname > +#define NODEDECLEX(structname) typedef struct structname : public TSExplicitNode< structname > + +#define LISTEX(structname,linkname) \ + TSExplicitList< structname ,(int)&(((structname *)0)->linkname)> + +#define LISTEXDYN(structname) \ + TSExplicitList< structname ,(int)0xDDDDDDDD> + +#define LISTEXSETLINK(structname,listname,linkname) \ + listname.ChangeLinkOffset((int)&(((structname *)0)->linkname)); + +#define LISTDECLEX(structname,linkname,varname) \ + TSExplicitList< structname ,(int)&(((structname *)0)->linkname)> varname + +#define ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,op) \ + for (structname *ptrname = start, \ + *iterate_delete = NULL; \ + (int)ptrname > 0; \ + iterate_delete \ + ? (ptrname = (listname)##op##DeleteNode(ptrname), \ + ptrname = ((int)iterate_delete > 0) ? ptrname : NULL, \ + iterate_delete = NULL, \ + ptrname) \ + : ptrname = (listname)##op##Iterate_RawNext(ptrname)) + +#define ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,op) \ + for (structname *ptrname = start, \ + *iterate_delete = NULL, \ + *iterate_delete_temp = NULL; \ + ptrname; \ + iterate_delete \ + ? (iterate_delete_temp = ((int)iterate_delete > 0) \ + ? (listname)##op##Prev(ptrname) \ + : NULL, \ + (listname)##op##DeleteNode(ptrname), \ + iterate_delete = NULL, \ + ptrname = iterate_delete_temp) \ + : ptrname = (listname)##op##Prev(ptrname)) + +#define ITERATELIST(structname,listname,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,(listname).Head(),ptrname,.) + +#define ITERATELISTPTR(structname,listname,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,(listname)->Head(),ptrname,->) + +#define ITERATEPARTIALLIST(structname,listname,start,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,.) + +#define ITERATEPARTIALLISTPTR(structname,listname,start,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,->) + +#define ITERATELISTREVERSE(structname,listname,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,(listname).Tail(),ptrname,.) + +#define ITERATELISTREVERSEPTR(structname,listname,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,(listname)->Tail(),ptrname,->) + +#define ITERATEPARTIALLISTREVERSE(structname,listname,start,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,.) + +#define ITERATEPARTIALLISTREVERSEPTR(structname,listname,start,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,->) + +#define ITERATE_DELETE \ + { \ + ++iterate_delete; \ + continue; \ + } + +#define ITERATE_DELETEANDBREAK \ + { \ + --iterate_delete; \ + continue; \ + } + + +/**************************************************************************** +* +* EXPORTOBJECT/EXPORTTABLE -- Export manager template +* +* Types: +* +* DECLARE_STRICT_HANDLE(handle) -- handle to object +* DECLARE_STRICT_HANDLE(lockedhandle) -- handle to locked object +* EXPORTOBJECTDECL(structname) -- object to be exported +* EXPORTTABLE(structname,handlename,lockedhandlename,synctype) +* EXPORTTABLEREUSE(structname,handlename,lockedhandlename,synctype) +* +* Export table methods: +* +* void Delete ( handle); +* void DeleteUnlock ( *ptr, +* lockedhandle); +* void Destroy (); +* * Lock ( handle, +* *lockedhandle, +* BOOL forwriting = FALSE); +* void New ( *handle); +* * NewLock ( *handle, +* *lockedhandle); +* void Unlock ( lockedhandle); +* +* Synchronization types for use with EXPORTTABLE(): +* +* SYNC_NONE -- use no synchronization +* SYNC_READWRITE -- use a reader/writer lock +* SYNC_ALWAYS -- use a critical section +* +***/ + +template +class TSExportTableBase { + + protected: + + //======================================================================= + T * BaseFindByHandle (LISTPTREX(T) list, unsigned handle) { + ITERATELISTPTR(T,list,curr) + if (curr->m_handle == handle) + return curr; + return NULL; + } + + //======================================================================= + T * BaseFindByHandleEx (LISTPTREX(T) list, unsigned handle, unsigned *count) { + *count = 0; + ITERATELISTPTR(T,list,curr) + if (curr->m_handle == handle) + return curr; + else + ++*count; + return NULL; + } + + //======================================================================= + unsigned BaseGetHandle (const T *ptr) { + return ptr->m_handle; + } + + //======================================================================= + int BaseGetLinkOffset () { + return (int)&(((T *)0)->m_linktoslot); + } + + //======================================================================= + void BaseSetHandle (T *ptr, unsigned handle) { + ptr->m_handle = handle; + } + +}; + +template +class TSExportTable : public TSExportTableBase { + + private: + ARRAY(LISTEXDYN(T)) m_listarray; + LISTEXDYN(T) m_reuselist; + H m_sequence; + unsigned m_slotmask; + SYNC m_sync; + + //======================================================================= + unsigned ComputeSlot (H handle) { + return (unsigned)handle & m_slotmask; + } + + //======================================================================= + H GenerateUniqueHandle () { + unsigned count; + for (;;) { + m_sequence = (H)((unsigned)m_sequence+1); + if (!BaseFindByHandleEx(&m_listarray[ComputeSlot(m_sequence)], + (unsigned)m_sequence, + &count)) + break; + } + if (count >= 4) + GrowListArray(); + return m_sequence; + } + + //======================================================================= + void GrowListArray () { +return; // note: out for testing + if (m_slotmask >= 1023) + return; + + // DETERMINE THE NEW ARRAY SIZE + unsigned oldarraysize = m_slotmask+1; + unsigned newarraysize = oldarraysize*2; + + // GROW THE ARRAY + { + m_listarray.SetNumElements(newarraysize); + int linkoffset = BaseGetLinkOffset(); + for (unsigned slot = oldarraysize; slot < newarraysize; ++slot) + m_listarray[slot].ChangeLinkOffset(linkoffset); + } + + // MOVE ALL RECORDS FROM THE OLD LISTS TO THE NEW LISTS + m_slotmask = newarraysize-1; + { + for (unsigned slot = 0; slot < oldarraysize; ++slot) { + T *currptr = m_listarray[slot].Head(); + while (currptr) { + T *nextptr = m_listarray[slot].Next(currptr); + unsigned newslot = ComputeSlot((H)BaseGetHandle(currptr)); + if (newslot != slot) { + m_listarray[slot].UnlinkNode(currptr); + m_listarray[newslot].LinkNode(currptr); + } + currptr = nextptr; + } + } + } + + } + + //======================================================================= + BOOL IsForWriting (LH lockedhandle) { + return (lockedhandle == (LH)1); + } + + //======================================================================= + void SyncEnterLock (LH *lockedhandle, BOOL forwriting) { + m_sync.Enter(forwriting); + *lockedhandle = (LH)(forwriting ? 1 : -1); + } + + //======================================================================= + void SyncLeaveLock (LH lockedhandle) { + if (lockedhandle) + m_sync.Leave(IsForWriting(lockedhandle)); + } + + public: + + //======================================================================= + TSExportTable () { + m_sequence = (H)0; + m_slotmask = 3; + m_listarray.SetNumElements(m_slotmask+1); + int linkoffset = BaseGetLinkOffset(); + for (unsigned slot = 0; slot <= m_slotmask; ++slot) + m_listarray[slot].ChangeLinkOffset(linkoffset); + m_reuselist.ChangeLinkOffset(linkoffset); + } + + //======================================================================= + ~TSExportTable () { + Destroy(); + } + + //======================================================================= + void Delete (H handle) { + LH lockedhandle; + T *ptr = Lock(handle,&lockedhandle,TRUE); + DeleteUnlock(ptr,lockedhandle); + } + + //======================================================================= + void DeleteUnlock (T *ptr, + LH lockedhandle) { + if (ptr) + if (REUSE) + m_reuselist.LinkNode(ptr); + else + delete ptr; + Unlock(lockedhandle); + } + + //======================================================================= + void Destroy () { + LH lockedhandle; + SyncEnterLock(&lockedhandle,TRUE); + for (unsigned slot = 0; slot <= m_slotmask; ++slot) { + T *curr; + while ((curr = m_listarray[slot].Head()) != NULL) { + delete curr; + SErrReportResourceLeak(typeid(H).INTERNALRAWNAME()); + } + } + m_reuselist.Clear(); + SyncLeaveLock(lockedhandle); + } + + //======================================================================= + T * Lock (H handle, + LH *lockedhandle, + BOOL forwriting = FALSE) { + SyncEnterLock(lockedhandle,forwriting); + T *result = BaseFindByHandle(&m_listarray[ComputeSlot(handle)], + (unsigned)handle); + if (!result) { + SyncLeaveLock(*lockedhandle); + *lockedhandle = (LH)0; + } + return result; + } + + //======================================================================= + void New (H *handle) { + LH lockedhandle; + NewLock(handle,&lockedhandle); + Unlock(lockedhandle); + } + + //======================================================================= + T * NewLock (H *handle, LH *lockedhandle) { + SyncEnterLock(lockedhandle,TRUE); + H newhandle = GenerateUniqueHandle(); + T *ptr = NULL; + if (REUSE) { + ptr = m_reuselist.Head(); + if (ptr) + m_listarray[ComputeSlot(newhandle)].LinkNode(ptr); + } + if (!ptr) + ptr = m_listarray[ComputeSlot(newhandle)].NewNode(); + BaseSetHandle(ptr,(unsigned)newhandle); + *handle = newhandle; + return ptr; + } + + //======================================================================= + void Unlock (LH lockedhandle) { + SyncLeaveLock(lockedhandle); + } + +}; + +template +class TSExportObject : public TSExplicitNode { + friend class TSExportTableBase; + + private: + unsigned m_handle; + LINKEX(T) m_linktoslot; + + public: + + //======================================================================= + TSExportObject () { + } + + //======================================================================= + TSExportObject (const TSExportObject &source) { + } + + //======================================================================= + TSExportObject & operator= (const TSExportObject &source) { + // COPY THE OBJECT DATA, BUT DON'T OVERWRITE THE DESTINATION OBJECT'S + // HANDLE OR LINK + return *this; + } + +}; + +#define SYNC_NONE CNullSync +#define SYNC_READWRITE CLock +#define SYNC_ALWAYS CCritSect + +#define EXPORTOBJECTDECL(structname) \ + typedef struct structname : public TSExportObject< structname > + +#define EXPORTTABLE(structname,handlename,lockedhandlename,synctype) \ + TSExportTable + +#define EXPORTTABLEREUSE(structname,handlename,lockedhandlename,synctype) \ + TSExportTable + + +/**************************************************************************** +* +* SWAP -- Swap template +* +* Macros: +* +* SWAP(a,b) +* +***/ + +//=========================================================================== +template +void inline TSSwap (T &a, T &b) { + T temp = a; + a = b; + b = temp; +} +#define SWAP(a,b) TSSwap(a,b) + + +/**************************************************************************** +* +* Old TList Template -- Obsolete!! +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return FALSE; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return FALSE; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return TRUE; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return FALSE; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return FALSE; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return TRUE; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return FALSE; + + ptr->next = *head; + *head = ptr; + return TRUE; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return FALSE; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return TRUE; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return FALSE; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber,0); + *head = next; + } + return TRUE; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return FALSE; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber,0); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return FALSE; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import off +#endif + +#endif // ifndef _STORM_H_ diff --git a/src/Storm/HELP/STORM.HLP b/src/Storm/HELP/STORM.HLP new file mode 100644 index 0000000..3a09005 Binary files /dev/null and b/src/Storm/HELP/STORM.HLP differ diff --git a/src/Storm/LIB/STORM.LIB b/src/Storm/LIB/STORM.LIB new file mode 100644 index 0000000..986e26a Binary files /dev/null and b/src/Storm/LIB/STORM.LIB differ diff --git a/src/Storm/LIB/STORMD.LIB b/src/Storm/LIB/STORMD.LIB new file mode 100644 index 0000000..649bed1 Binary files /dev/null and b/src/Storm/LIB/STORMD.LIB differ diff --git a/src/Storm/LIB/STORMST.LIB b/src/Storm/LIB/STORMST.LIB new file mode 100644 index 0000000..988a57d Binary files /dev/null and b/src/Storm/LIB/STORMST.LIB differ diff --git a/src/Storm/LIB/STORMST.RES b/src/Storm/LIB/STORMST.RES new file mode 100644 index 0000000..2433693 Binary files /dev/null and b/src/Storm/LIB/STORMST.RES differ diff --git a/src/Storm/PKWARE/BIN/IMPBORL.DLL b/src/Storm/PKWARE/BIN/IMPBORL.DLL new file mode 100644 index 0000000..badd2a1 Binary files /dev/null and b/src/Storm/PKWARE/BIN/IMPBORL.DLL differ diff --git a/src/Storm/PKWARE/BIN/IMPLODE.DLL b/src/Storm/PKWARE/BIN/IMPLODE.DLL new file mode 100644 index 0000000..3fd5aca Binary files /dev/null and b/src/Storm/PKWARE/BIN/IMPLODE.DLL differ diff --git a/src/Storm/PKWARE/EXAMPLES.TXT b/src/Storm/PKWARE/EXAMPLES.TXT new file mode 100644 index 0000000..18f8ad8 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES.TXT @@ -0,0 +1,142 @@ +******************************************************************* +*** Important information for use with the *** +*** PKWARE Data Compression Library (R) for Win32 *** +*** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** +*** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** +******************************************************************* + +* The examples provided show how the PKWARE Data Compression Library is + implemented. These examples show how to do "file-to-file" compression, + "memory-to-memory" compression, and disk spanning. We recommend that + you run the examples with a debugger, and set breakpoints in the I/O + callback functions. These functions handle the data I/O, and can be + modified to compress or extract data from any device, not just from a file. + + +* Visual C++ users + + * To build a Visual C++ project, load the Visual Workbench, and open + the .MAK file through the "Open" menu item under "Project." This + will automatically update the makefile to the path of where the + examples are installed. + + * To make a VC++ .MAK file, add all the files in the example directory + with the extensions: *.c*, *.rc, *.def, *.lib + +* Borland C++ 4.x users + + * Borland .IDE files are provided for each example on the distribution + disk. You must set your include and library directories by going into + the OPTIONS | PROJECT | DIRECTORIES window. + + * If you are making your own .IDE file, add all the files in the current + directory to the project with the extensions: *.c*, *.rc, *.def, *.lib. + + +* DLL examples + + If you will be using the DLL examples, make sure that IMPLODE.DLL and/or + IMPBORL.DLL is in your user path. + + +Directory Structure for the examples: + + ÀÄÄÄEXAMPLES + ÃÄÄÄCMDLINE + ³ ÃÄÄÄFIL2FIL + ³ ÃÄÄÄMEM2MEM + ³ ÀÄÄÄMULTFILE + ÃÄÄÄGUI + ³ ÃÄÄÄFIL2FIL + ³ ÀÄÄÄMEM2MEM + ÃÄÄÄMFC + ³ ÃÄÄÄFIL2FIL + ³ ³ ÀÄÄÄRES + ³ ÃÄÄÄMEM2MEM + ³ ³ ÀÄÄÄRES + ³ ÃÄÄÄMULTFILE + ³ ³ ÀÄÄÄRES + ³ ÀÄÄÄSPAN + ³ ÀÄÄÄRES + ÀÄÄÄOWL + ÃÄÄÄMEM2MEM + ÀÄÄÄSPAN + + +CMDLINE Examples +---------------- + +FIL2FIL => This example shows how to compress and uncompress from one + file to another. Requires the TEST.IN file in the executable + directory to run. + +MEM2MEM => This example shows how to compress and uncompress from one + memory buffer to another. TEST.IN must be less than 62K bytes. + +MULTFILE => This example shows how to compress multiple files into one file, + then uncompress the file. The multiple files must be specified + on the command line. + + +GUI Examples +------------ + +FIL2FIL => SDK Windows example. Requires the TEST.IN file in the executable + directory to run. + +MEM2MEM => SDK Windows example. Requires the TEST.IN file in the executable + directory to run. This example shows how to compress and + uncompress from one memory buffer to another. + + +MFC Examples +------------ + +FIL2FIL => Written using Visual C++ with MFC and the static link library. + Requires the TEST.IN file in the executable directory to run. + This example also contains debugging statements to help display + how the PKWARE Data Compression Library calls the read and write + routines repeatedly. + +MEM2MEM => This example shows how to compress and uncompress from one + memory buffer to another. Written using Visual C++ with MFC + (also uses MFC DLL). Prompts for file to load, which must be + less than 62K bytes. + +MULTFILE => This example shows how to compress multiple files into one file, + then uncompress the file. Written using Visual C++ with MFC + (also uses MFC DLL). + +SPAN => Written using Visual C++ with MFC (also uses MFC DLL). This + example uses MULTFILE as a base, but includes disk spanning. + All files are extracted to a temporary directory, C:\TEMP\. + To change the extract directory, modify the global variable + "UncompressDir" in MAINFRM.CPP. + + +OWL Examples +------------ + +MEM2MEM => This example shows how to compress and uncompress from one + memory buffer to another. Written using Borland C++ 4.5 with OWL. + Prompts for file to load, which must be less than 62K bytes. + + +SPAN => Written using Borland C++ 4.5 with OWL. This example compresses + multiple files and includes disk spanning. All files are + extracted to a temporary directory, C:\TEMP\. To change the + extract directory, modify the global variable "UncompressDir" + in SPANAPP.CPP. + + +Directions on Using MULTFILE and SPAN Programs: + + To compress multiple files: Select Compress Files from the File + menu, and use the Shift and Ctrl keys with the mouse to + highlight multiple files. Select OK after selecting the files. + Enter the path and name of file to compress the selected files + to. + + To uncompress a file: Select Uncompress Files from the File menu, + and enter or select the file to uncompress, then select the OK + button. The files will be uncompressed in the same directory. diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/BORLDLL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/BORLDLL.BAT new file mode 100644 index 0000000..6900790 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/BORLDLL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using Borland compiler and DLL +: + +bcc32 example.c ..\..\..\impborli.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/EXAMPLE.C b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/EXAMPLE.C new file mode 100644 index 0000000..589d5b4 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/EXAMPLE.C @@ -0,0 +1,132 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#include +#include + +#include "implode.h" + +/* Define a structure containing data to be passed to the callback + functions through the user defined parameter. +*/ + +struct PassedParam +{ + unsigned int CmpPhase; + FILE *InFile; + FILE *OutFile; + unsigned long CRC; +}; + +/*------------------------------------------------------------------- + Routine to supply data to the implode() or explode() routines. + When this routine returns 0 bytes read, the implode() or explode() + routines will terminate. Also calculate the CRC-32 on the original + uncompressed data during the implode() call. +*/ + +unsigned int ReadData(char *Buff, unsigned int *Size, void *Param) +{ + size_t Read; + struct PassedParam *Par = (struct PassedParam *)Param; + + Read = fread(Buff, 1, *Size, Par->InFile); + if (Par->CmpPhase) + Par->CRC = crc32(Buff, (unsigned int *)&Read, &Par->CRC); + + return (unsigned int)Read; +} + +/*------------------------------------------------------------------- + Routine to write compressed data output from implode() or + uncompressed data from explode(). Also calculate the CRC on + the uncompressed data during the explode() call. +*/ + +void WriteData(char *Buff, unsigned int *Size, void *Param) +{ + struct PassedParam *Par = (struct PassedParam *)Param; + + fwrite(Buff, 1, *Size, Par->OutFile); + if (!Par->CmpPhase) + Par->CRC = crc32(Buff, Size, &Par->CRC); +} + +int cdecl main(void) +{ + char *WorkBuff; /* buffer for compression tables */ + unsigned int Error; + unsigned int type; /* ASCII or Binary compression */ + unsigned int dsize; /* Dictionary Size. 1,2 or 4K */ + unsigned long OrgCRC; /* CRC of original input file */ + struct PassedParam Param; /* Parameters passed to callback functions */ + + /* Open the input file */ + Param.InFile = fopen("test.in","rb"); + if (Param.InFile == NULL) + { + puts("Unable to open input file"); + return 1; + } + + /* Create the output compressed file */ + Param.OutFile = fopen("test.cmp","wb"); + + /* Allocate memory for implode work buffer */ + WorkBuff = (char *)malloc(CMP_BUFFER_SIZE); + if (WorkBuff == NULL) + { + puts("Unable to allocate work buffer"); + return 1; + } + + /* Initialize CRC */ + Param.CmpPhase = 1; + Param.CRC = (unsigned long) -1; + + type = CMP_ASCII; /* Use ASCII compression */ + dsize = 4096; /* Use 4K dictionary */ + + puts("Calling Implode"); + implode(ReadData, WriteData, WorkBuff, &Param, &type, &dsize); + puts("Done Compressing"); + + OrgCRC = ~Param.CRC; + free(WorkBuff); + + fclose(Param.InFile); + fclose(Param.OutFile); + + /* Compression done, now try extracting the compressed file */ + + WorkBuff = (char *)malloc(EXP_BUFFER_SIZE); + if (WorkBuff == NULL) + { + puts("Unable to allocate work buffer"); + return 1; + } + + Param.InFile = fopen("test.cmp","rb"); /* Compressed file */ + Param.OutFile = fopen("test.ext","wb"); /* File to extract to */ + + /* Initialize CRC */ + Param.CmpPhase = 0; + Param.CRC = (unsigned long) -1; + + puts("Calling Explode"); + Error = explode(ReadData, WriteData, WorkBuff, &Param); + + Param.CRC = ~Param.CRC; + free(WorkBuff); + fclose(Param.InFile); + fclose(Param.OutFile); + + printf("Uncompression completed - Error %d\n", Error); + printf("Original CRC=%08lx Uncompressed CRC=%08lx\n",OrgCRC,Param.CRC); + + return 0; +} + diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKE.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKE.BAT new file mode 100644 index 0000000..0eae9b5 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKE.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program +: + +cl example.c ..\..\..\implode.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKEBORL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKEBORL.BAT new file mode 100644 index 0000000..b47bbcc --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKEBORL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using Borland compiler +: + +bcc32 example.c ..\..\..\impborl.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKEDLL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKEDLL.BAT new file mode 100644 index 0000000..3810184 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/FIL2FIL/MAKEDLL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using DLL +: + +cl example.c ..\..\..\implodei.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/BORLDLL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/BORLDLL.BAT new file mode 100644 index 0000000..0fd6b68 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/BORLDLL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using Borland compiler and DLL +: + +bcc32 mem2mem.c ..\..\..\impborli.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKE.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKE.BAT new file mode 100644 index 0000000..6f5fab1 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKE.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program +: + +cl mem2mem.c ..\..\..\implode.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKEBORL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKEBORL.BAT new file mode 100644 index 0000000..742ce25 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKEBORL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using Borland compiler +: + +bcc32 mem2mem.c ..\..\..\impborl.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKEDLL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKEDLL.BAT new file mode 100644 index 0000000..6eae367 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MAKEDLL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using DLL +: + +cl mem2mem.c ..\..\..\implodei.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MEM2MEM.C b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MEM2MEM.C new file mode 100644 index 0000000..6cceb3a --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MEM2MEM/MEM2MEM.C @@ -0,0 +1,286 @@ +/************************************************************************* + Example to interface the PKWARE Data Compression Library (R) + Copyright 1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off + Version 1.11 + + This example takes a file from the disk (file must be <= 62K), + compresses the file to memory, and then expands the compressed + data back into another memory buffer. This data is then written + to a file called test.ext, that can be compared to the original file. +*************************************************************************/ + +#include +#include +#include + +#include "implode.h" + +#define BUFFERSIZE ((long)(62 * 1024)) /* File size limit */ +#define FALSE 0 +#define TRUE (!FALSE) + +typedef struct PassedParam +{ + char *pSource; /* Pointer to source buffer */ + char *pDestination; /* Pointer to destination buffer */ + unsigned long SourceOffset; /* Offset into the source buffer */ + unsigned long DestinationOffset; /* Offset into the destination buffer */ + unsigned long CompressedSize; /* Need this for extracting! */ + unsigned long UnCompressedSize; /* Size of uncompressed data file */ + unsigned long BufferSize; + unsigned long Crc; /* Calculated CRC value */ + unsigned long OrigCrc; /* Original CRC value of data */ +} PARAM; + + +/* +** BufferSize defines the maximum size allowed for output of compressed +** data from implode(), or uncompressed data from explode(). Notice that +** if you are compressing files that compress to a size greater than +** BufferSize, an error message will result. You can modify the value of +** BufferSize if you need a bigger buffer. If you know your maximum file +** size, you can adjust BUFFERSIZE. This will allow for larger, or smaller +** maximum values of BufferSize. +*/ + +/* Routine to read uncompressed data. Used only by implode(). +** This routine reads the data that is to be compressed. +*/ + +unsigned int +ReadUnCompressed(char *buff, unsigned int *size, void *Param) +{ + PARAM *Ptr = (PARAM *) Param; + + if (Ptr->UnCompressedSize == 0L) + { + /* This will terminate the compression or extraction process */ + return(0); + } + + if (Ptr->UnCompressedSize < (unsigned long)*size) + { + *size = (unsigned int)Ptr->UnCompressedSize; + } + + memcpy(buff, Ptr->pSource + Ptr->SourceOffset, *size); + Ptr->SourceOffset += (unsigned long)*size; + Ptr->UnCompressedSize -= (unsigned long)*size; + Ptr->Crc = crc32(buff, size, &Ptr->Crc); + + return(*size); +} + +/* Routine to read compressed data. Used only by explode(). +** This routine reads the compressed data that is to be uncompressed. +*/ + +unsigned int +ReadCompressed(char *buff, unsigned int *size, void *Param) +{ + PARAM *Ptr = (PARAM *) Param; + + if (Ptr->CompressedSize == 0L) + { + /* This will terminate the compression or extraction process */ + return(0); + } + + if (Ptr->CompressedSize < (unsigned long)*size) + { + *size = (unsigned int)Ptr->CompressedSize; + } + + memcpy(buff, Ptr->pSource + Ptr->SourceOffset, *size); + Ptr->SourceOffset += (unsigned long)*size; + Ptr->CompressedSize -= (unsigned long)*size; + + return(*size); +} + +/* Routime to write compressed data. Used only by implode(). +** This routine writes the compressed data to a memory buffer. +*/ + +void +WriteCompressed(char *buff, unsigned int *size, void *Param) +{ + PARAM *Ptr = (PARAM *) Param; + + if (Ptr->CompressedSize + (unsigned long)*size > Ptr->BufferSize) + { + puts("Compressed data will overflow buffer. Increase size of buffer!"); + exit(1); + } + memcpy(Ptr->pDestination + Ptr->DestinationOffset, buff, *size); + Ptr->DestinationOffset += (unsigned long)*size; + Ptr->CompressedSize += (unsigned long)*size; +} + +/* Routine to write uncompressed data. Used only by explode(). +** This routine writes the uncompressed data to a memory buffer. +*/ + +void +WriteUnCompressed(char *buff, unsigned int *size, void *Param) +{ + PARAM *Ptr = (PARAM *) Param; + + if (Ptr->CompressedSize + (unsigned long)*size > Ptr->BufferSize) + { + puts("Compressed data will overflow buffer. Increase size of buffer!"); + exit(1); + } + memcpy(Ptr->pDestination + Ptr->DestinationOffset, buff, *size); + Ptr->DestinationOffset += (unsigned long)*size; + Ptr->UnCompressedSize += (unsigned long)*size; + Ptr->Crc = crc32(buff, size, &Ptr->Crc); +} + +void +main(int argc, char *argv[]) +{ + char *WorkBuff; /* Buffer for compression tables */ + char *InFileName; + char *temp; + unsigned int error; + unsigned int bytes_read; + unsigned int type; + unsigned int dsize; + unsigned int written; + PARAM Param; + FILE *InFile; + FILE *OutFile; + + /* Use the first command line argument as the name of the file + ** to read as the data source. If no filename is given, default + ** to use "test.in" + */ + if (argc > 1) + { + InFileName = argv[1]; + } + else + { + InFileName = "test.in"; + } + + /* Open the file so it's contents can be read into memory. */ + if ((InFile = fopen(InFileName, "rb")) == NULL) + { + puts("Unable to open input file."); + exit(1); + } + + /* Determine the size of the file, and rewind to beginning of file. */ + if (fseek(InFile, 0L, SEEK_END)) + { + puts("Unable to determine input file size."); + exit(1); + } + Param.UnCompressedSize = ftell(InFile); + fseek(InFile, 0L, SEEK_SET); + + if (Param.UnCompressedSize > BUFFERSIZE) + { + fclose(InFile); + printf("Cannot compress files larger than %d.\n",BUFFERSIZE); + exit(1); + } + Param.BufferSize = Param.UnCompressedSize; + Param.CompressedSize = 0L; + + /* Allocate memory buffers to hold the compressed and uncompressed + ** contents of the data file. + */ + Param.pSource = (char *)malloc(Param.BufferSize); + Param.pDestination = (char *)malloc(Param.BufferSize); + + /* We make the destination buffer the same size as the source buffer. + ** You should determine what compression ratios you achieve with your + ** specific data. You may only need a destination buffer about one half + ** the size of the source buffer (assuming 50% compression). + */ + + if (Param.pSource == NULL || Param.pDestination == NULL) + { + puts("Unable to allocate source & destination buffers."); + exit(1); + } + + /* Read the contents of the file into the uncompressed data buffer. */ + fread((void *)Param.pSource, 1, Param.UnCompressedSize, InFile); + fclose(InFile); + + /* Allocate the buffer used by implode() for compression tables. */ + WorkBuff = (char *)malloc(CMP_BUFFER_SIZE); + if (WorkBuff == NULL) + { + puts("Unable to allocate work buffer."); + return; + } + + puts("Calling Implode"); + type = CMP_ASCII; + dsize = 1024; + + Param.SourceOffset = 0L; + Param.DestinationOffset = 0L; + Param.Crc = (unsigned long) -1; + implode(ReadUnCompressed,WriteCompressed,WorkBuff,&Param,&type,&dsize); + Param.OrigCrc = ~Param.Crc; + free(WorkBuff); + + /* Since the imploding is done, the data in the compressed buffer + ** will be used as the source for the exploding process. + */ + temp = Param.pSource; + Param.pSource = Param.pDestination; + Param.pDestination = temp; + + /* Clear buffer containing original uncompressed data */ + memset(Param.pDestination, 0, Param.UnCompressedSize); + + /* Allocate the buffer used by explode() for compression tables. */ + WorkBuff = (char *)malloc(EXP_BUFFER_SIZE); + if (WorkBuff == NULL) + { + puts("Unable to allocate work buffer."); + return; + } + Param.SourceOffset = 0L; + Param.DestinationOffset = 0L; + Param.UnCompressedSize = 0L; + Param.Crc = (unsigned long) -1; + + /* Now try extracting the compressed file data */ + puts("Calling Explode"); + error = explode(ReadCompressed,WriteUnCompressed,WorkBuff,&Param); + Param.Crc = ~Param.Crc; + + if (error || (Param.Crc != Param.OrigCrc)) + { + puts("Error in compressed data!"); + } + printf("Original CRC=%lx Uncompressed CRC=%lx\n",Param.OrigCrc, Param.Crc); + + /* The uncompressed data is now in pDestination. Lets write this to a file + ** called test.ext. We can compare this buffer to the original input file. + */ + + if ((OutFile = fopen("test.ext", "wb+")) == NULL) + { + puts("Unable to open output file."); + } + else + { + fwrite((void *)Param.pDestination, 1, Param.UnCompressedSize, OutFile); + fclose(OutFile); + } + + /* Free buffers */ + free(WorkBuff); + free(Param.pSource); + free(Param.pDestination); +} diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/BORLDLL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/BORLDLL.BAT new file mode 100644 index 0000000..4df5376 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/BORLDLL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using Borland compiler and DLL +: + +bcc32 multfile.c ..\..\..\impborli.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKE.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKE.BAT new file mode 100644 index 0000000..4db430f --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKE.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program +: + +cl multfile.c ..\..\..\implode.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKEBORL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKEBORL.BAT new file mode 100644 index 0000000..d04c870 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKEBORL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using Borland compiler +: + +bcc32 multfile.c ..\..\..\impborl.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKEDLL.BAT b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKEDLL.BAT new file mode 100644 index 0000000..9b433a5 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MAKEDLL.BAT @@ -0,0 +1,5 @@ +: +: Make file for example program using DLL +: + +cl multfile.c ..\..\..\implodei.lib diff --git a/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MULTFILE.C b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MULTFILE.C new file mode 100644 index 0000000..2bcabd4 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/CMDLINE/MULTFILE/MULTFILE.C @@ -0,0 +1,479 @@ +/************************************************************************* + Example to interface the PKWARE Data Compression Library (R) + Copyright 1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off + Version 1.11 + + This example compresses a set of one or more files into a single + output file. The set of files is taken from the command line. Each + file is compressed, and written to the output file. A record + holding information for each file is written to the output file along + with the compressed data. The name of the compressed output file + created by this program is PKWDCL.CMP. +**************************************************************************/ + +#include +#include +#include +#include + +#include "implode.h" + +#define BUFSIZE 2048 /* Work buffer */ +#define TEMPNAME "PKWDCL.TMP" /* Temporary file */ +#define COMPRESSED_FILE_NAME "PKWDCL.CMP" /* Name of compressed output file */ +#define FALSE 0 +#define TRUE (!FALSE) + + +/* +** Structure definitions +*/ + +typedef struct FileHeader +{ + char signature[4]; /* Signature in case of errors */ + char filename[13]; /* File name */ + unsigned long CompSize; /* Compressed size of file */ + unsigned long UnCompSize; /* Original size of file */ + unsigned long Crc; /* Crc value for file */ +} HEADER; +/* +** This structure will be written to the compressed output file and +** will record information for each input file that is compressed +** into the output file. +*/ + +typedef struct PassedParam +{ + FILE *InFile; /* Pointer to file for reading data */ + FILE *OutFile; /* Pointer to file for writing data */ + FILE *Destination; /* Pointer to compressed output file */ + int Imploding; /* Flag indicating compression or */ + /* uncompression is in progress. */ + unsigned long Crc; /* CRC value for current file. */ + unsigned long OrigCrc; /* Original CRC for a file */ + unsigned long CompressedFileSize; /* Size of compressed file */ + unsigned long UnCompressedFileSize;/* Original file size */ +} PARAM; +/* +** This structure is used to pass values shared between the main +** application and the callback functions called by implode() and +** explode(). +*/ + + +/* +** Function Prototypes +*/ +unsigned long FileSize(FILE *); +void ReadHeader(FILE *, HEADER *); +void SkipFile(FILE *, unsigned long); +void Expand(char *,int); +void CompressFile(char *, char *, PARAM *); +void AppendFile(FILE *,unsigned long); +void WriteHeader(char *, PARAM *); +void Compress(char *,int, char **); + + +/* The ReadBuff function is used by the implode() and explode() +** functions to read a stream of data that will be either +** compressed, or uncompressed. +*/ + +unsigned int +ReadBuff(char *buff, unsigned int *size, void *Param) +{ + PARAM *Ptr = (PARAM *) Param; + unsigned int Read = 0; + + /* This function may ask for up to 4K of data at a time. If your archive + ** file contains several compressed files, you may read too much. For + ** example, your first compressed file in the archive may be 100 bytes. + ** So you do not want to read more than 100 bytes or you'll be unable to + ** uncompress the second file, since you will not be located at the + ** beginning of the file any longer. We will use the variable + ** "CompressedFileSize" to check for this condition. + */ + + if (Ptr->Imploding == FALSE) + { + /* If we are exploding data, and the number of bytes left in the + ** compressed file is less than the number of bytes requested, then + ** set the number of bytes requested to the bytes remaining in the + ** compressed file. + */ + + /* Set size to bytes left */ + + if ((unsigned long)*size > Ptr->CompressedFileSize) + { + *size = (unsigned)Ptr->CompressedFileSize; + } + + /* Subtract the number of bytes read from the total size of the + ** compressed file. + */ + + Ptr->CompressedFileSize -= (unsigned long)*size; + } + + /* Read 'size' bytes from input source */ + Read = fread(buff, 1, *size, Ptr->InFile); + + if (Ptr->Imploding == FALSE) + { + /* Check the CRC value of data as it's uncompressed. */ + Ptr->Crc = crc32(buff, &Read, &Ptr->Crc); + } + + /* Return the number of bytes read from the input source */ + return(Read); +} + +/* The WriteBuff function is used by the implode() and explode() +** functions to write a stream of data that has been either +** compressed, or uncompressed. +*/ + +void +WriteBuff(char *buff, unsigned int *size, void *Param) +{ + /* If compressing data, add the number of bytes to 'CompressedFileSize'. + ** We need to keep track of the size of the compressed file. + */ + + PARAM *Ptr = (PARAM *) Param; + int Written; + + if (Ptr->Imploding) + { + Ptr->CompressedFileSize += (unsigned long)*size; + } + + /* Write the data to the file. If we are Imploding, this is compressed + ** data. Otherwise it is uncompressed data. + */ + + Written = fwrite((void *)buff, 1, *size, Ptr->OutFile); + if (Written != *size) + { + puts("Failed to write compressed data"); + } + if (Ptr->Imploding == TRUE) + { + /* Calculate the CRC value of data as it's compressed. */ + Ptr->Crc = crc32(buff, size, &Ptr->Crc); + } +} + +/* The ReadHeader function is used to read a HEADER data structure +** from the compressed output file. This HEADER record contains the +** information about the compressed file. +*/ +void +ReadHeader(FILE *pFile, HEADER *header) +{ + fread(header, 1, sizeof(HEADER), pFile); +} + +/* The SkipFile function is used to skip over a file that is in +** the compressed output file if that file is not to be uncompressed. +*/ +void +SkipFile(FILE *pFile, unsigned long Size) +{ + fseek(pFile, Size, SEEK_CUR); +} + +/* The FileSize function is used to determine the number of +** bytes in a file that is to be compressed. +*/ +unsigned long +FileSize(FILE *pFile) +{ + unsigned long Size; + + if (fseek(pFile, 0L, SEEK_END)) + { + puts("Unable to determine input file size."); + } + Size = ftell(pFile); + fseek(pFile, 0L, SEEK_SET); + + return(Size); +} + +/* The Expand function is used to uncompress the files that were +** written to the compressed output file. A prompt is displayed +** for each file allowing the user to skip the file if it is not +** to be uncompressed. +*/ +void +Expand(char *WorkBuff, int Files) +{ + HEADER header; + PARAM Param; + int error; + int i; + int FileCount; + char ch; + char s[80]; + + memset( &Param, 0, sizeof(Param) ); + + Param.InFile = fopen(COMPRESSED_FILE_NAME, "rb"); + if (Param.InFile == NULL) + { + printf("Unable to open compressed output file %s\n",COMPRESSED_FILE_NAME); + } + + for (FileCount = 1; FileCount < Files; FileCount++) + { + Param.CompressedFileSize = 0L; + ReadHeader(Param.InFile,&header); + + /* Display a message and ask if you wish to extract this file */ + sprintf(s,"Extract file %s ? File is %lu bytes. (Y/N)", + header.filename, header.UnCompSize); + puts(s); + + /* We need to remember how many bytes are in this compressed data + ** stream. We don't want to read too many bytes. + */ + Param.CompressedFileSize = header.CompSize; + Param.OrigCrc = header.Crc; + Param.Imploding = FALSE; + + do + { + ch = toupper(getchar()); + } + while(ch != 'Y' && ch != 'N'); + if (ch == 'Y') + { + /* If the file is to be uncompressed, create new, empty file + ** of the same name where the uncompressed contents of the + ** file will be written. + */ + Param.OutFile = fopen(header.filename, "wb+"); + if (Param.OutFile == NULL) + { + printf("Unable to open output data file %s\n",header.filename); + /* Skip past this file and go on to the next one. */ + SkipFile(Param.InFile,Param.CompressedFileSize); + } + else + { + /* Call explode to uncompress the file. */ + Param.Crc = (unsigned long) -1; + error = explode(ReadBuff,WriteBuff,WorkBuff,&Param); + Param.Crc = ~Param.Crc; + if (error || (Param.OrigCrc != Param.Crc)) + { + printf("Error in compressed file %s!\n",header.filename); + } + printf("Expanding file %s Original CRC = %lx Uncompressed CRC = %lx\n",header.filename,Param.OrigCrc,Param.Crc); + /* Close the file we just created */ + fclose(Param.OutFile); + } + } + else + { + /* Skip past this file and go on to the next one. */ + SkipFile(Param.InFile,Param.CompressedFileSize); + } + } + fclose(Param.InFile); +} + +/* The CompressFile function is used to compress a file into a +** temporary file. +*/ +void +CompressFile(char *file, char *WorkBuff, PARAM *Param) +{ + unsigned int type; /* Compression type */ + unsigned int dsize; /* Dictionary size */ + + /* Set the compression type to BINARY compression */ + type = CMP_BINARY; + + /* Set the compression dictionary size to 4K */ + dsize = 4096; + + /* Open the file to be compressed. */ + Param->InFile = fopen(file, "rb"); + if (Param->InFile == NULL) + { + puts("Unable to open input file"); + return; + } + + /* Open the temporary file where the compressed data will be written. */ + Param->OutFile = fopen(TEMPNAME, "wb+"); + if (Param->OutFile == NULL) + { + printf("Unable to open temporary output file %s\n",Param->OutFile); + } + else + { + Param->Crc = (unsigned long) -1; + Param->UnCompressedFileSize = FileSize(Param->InFile); + + /* Call implode() to compress the file. */ + implode(ReadBuff,WriteBuff,WorkBuff,Param,&type,&dsize); + printf("Compressing file %s", file); + printf(" File size = %ld bytes Compressed size = %ld bytes\n", + Param->UnCompressedFileSize,Param->CompressedFileSize); + + /* Close the temp file and the file being compressed */ + Param->OrigCrc = ~Param->Crc; + fclose(Param->InFile); + fclose(Param->OutFile); + } +} + +/* The AppendFile function is used to copy the compressed data from +** the temporary file to the compressed output file after the +** header record for the file has been written. +*/ + +void +AppendFile(FILE *pDest,unsigned long Size) +{ + char buf[BUFSIZE]; + unsigned long left; + unsigned int Read; + unsigned int written; + FILE *pFile; + + /* Keep track of the number of bytes that need to be appended */ + left = Size; + + /* Open the temporary file containing the compressed input file + ** data. The contents of this file are then written to the + ** final output file. + */ + if ((pFile = fopen(TEMPNAME, "rb")) != NULL) + { + do + { + Read = fread(buf, 1, BUFSIZE, pFile); + written = fwrite(buf, 1, Read, pDest); + left -= (unsigned long)written; + } + while (left && written); + fclose(pFile); + } + else + { + printf("Unable to open temporary file %s\n",TEMPNAME); + } +} + +/* The WriteHeader function is used to format and write the +** record header for each file compressed into the compressed +** output file. +*/ +void +WriteHeader(char *filename, PARAM *Param) +{ + HEADER header; + int Written; + + /* Save the filename and compressed file size in the structure */ + strcpy(header.filename, filename); + header.CompSize = Param->CompressedFileSize; + header.UnCompSize = Param->UnCompressedFileSize; + header.Crc = Param->OrigCrc; + + /* Save a signature, can be used to help rebuild a damaged file */ + header.signature[0] = 'D'; + header.signature[1] = 'H'; + header.signature[2] = 9; + header.signature[3] = 2; + + /* Write the data to the compressed archive file */ + Written = fwrite(&header, 1, sizeof(HEADER), Param->Destination); + if (Written != sizeof(HEADER)) + { + puts("Failed to write compressed file header record."); + } +} + +/* The Compress function is used to compress each file specified +** on the command line. +*/ +void +Compress(char *WorkBuff, int Files, char** FileList) +{ + PARAM Param; + int FileCount; + + memset( &Param, 0, sizeof(Param) ); + + /* Open the file that will be the final output file for all + ** of the compressed input files. + */ + Param.Destination = fopen(COMPRESSED_FILE_NAME, "wb+"); + if (Param.Destination == NULL) + { + printf("Unable to open compressed output file %s\n",COMPRESSED_FILE_NAME); + } + else + { + /* For each file specified on the command line, compress the file, + ** write a header record for the file, then write the compressed + ** file data to the output file. + */ + for (FileCount = 1; FileCount < Files; FileCount++) + { + Param.Imploding = TRUE; + Param.CompressedFileSize = 0L; + Param.OrigCrc = 0L; + CompressFile(FileList[FileCount], WorkBuff,&Param); + WriteHeader(FileList[FileCount], &Param); + AppendFile(Param.Destination,Param.CompressedFileSize); + } + + if( Param.InFile ) + fclose(Param.InFile); + fclose(Param.Destination); + unlink(TEMPNAME); + } +} + +/* The main function simply allocates a work buffer needed for +** calling the implode() and explode() functions, and then +** calls the functions will compress and uncompress the +** files specified on the commandline. +*/ +int +main(int argc, char *argv[]) +{ + char *WorkBuff; /* Buffer for compression tables */ + + if( argc < 2 ) + { + printf( "Usage: multfile filename(s)\n" ); + return 0; + } + + /* Allocate the memory needed for implode(). The explode() routine + ** will use this same buffer, although it can generally use a + ** smaller sized buffer. + */ + WorkBuff = (char *)malloc(CMP_BUFFER_SIZE); + + if (WorkBuff == NULL) + { + puts("Unable to allocate work buffer"); + return 1; + } + Compress(WorkBuff,argc,argv); /* Call Compress, pass the allocated memory */ + Expand(WorkBuff,argc); /* Call Expand, pass the allocated memory. */ + free(WorkBuff); /* Free the allocated memory */ + + return 0; +} diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKE.BAT b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKE.BAT new file mode 100644 index 0000000..0d9465f --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKE.BAT @@ -0,0 +1 @@ +nmake makefile.msc diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEDLL.BAT b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEDLL.BAT new file mode 100644 index 0000000..543a8b9 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEDLL.BAT @@ -0,0 +1 @@ +nmake makefdll.msc diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEFDLL.MSC b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEFDLL.MSC new file mode 100644 index 0000000..2ea09e4 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEFDLL.MSC @@ -0,0 +1,18 @@ +ALL : WinDCL.exe + +WinDCL.res : WinDCL.rc resource.h + rc -r WinDCL.rc + +WinDCL.obj : WinDCL.c WinDCL.h + cl -c /D "_X86_" /D "WIN32" WinDCL.c + +# rc WinDCL.res + +LINK32_OBJS= \ + WINDCL.res \ + WINDCL.OBJ \ + +WinDcl.exe : WinDCL.res WinDCL.obj + link /SUBSYSTEM:windows /INCREMENTAL:no /MACHINE:I386 /OUT:"windcl.exe" \ + $(LINK32_OBJS) ..\..\..\IMPLODEI.LIB + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEFILE.MSC b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEFILE.MSC new file mode 100644 index 0000000..08347b6 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/MAKEFILE.MSC @@ -0,0 +1,18 @@ +ALL : WinDCL.exe + +WinDCL.res : WinDCL.rc resource.h + rc -r WinDCL.rc + +WinDCL.obj : WinDCL.c WinDCL.h + cl -c /D "_X86_" /D "WIN32" WinDCL.c + +# rc WinDCL.res + +LINK32_OBJS= \ + WINDCL.res \ + WINDCL.OBJ \ + +WinDcl.exe : WinDCL.res WinDCL.obj + link /SUBSYSTEM:windows /INCREMENTAL:no /MACHINE:I386 /OUT:"windcl.exe" \ + $(LINK32_OBJS) ..\..\..\IMPLODE.LIB + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/RESOURCE.H b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/RESOURCE.H new file mode 100644 index 0000000..fce9635 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/RESOURCE.H @@ -0,0 +1,2 @@ +#define IDM_TEST_DCL 1000 + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WDCLDLL.IDE b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WDCLDLL.IDE new file mode 100644 index 0000000..dda887e Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WDCLDLL.IDE differ diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.C b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.C new file mode 100644 index 0000000..7d0a3f7 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.C @@ -0,0 +1,247 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#include + +#include +#include +#include + +#include "resource.h" +#include "WinDCL.h" +#include "implode.h" + +void TestDLL(void); + +#ifndef _MSC_VER + #pragma argsused +#endif + +int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) +{ + WNDCLASS wndclass; + MSG msg; + + // Get rid of any compiler warnings + lpszCmdLine = lpszCmdLine; + + hInst = hInstance; + + // Register the DCL Test window Class + if(!hPrevInstance) + { + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = WndProc; + + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = LoadIcon(hInst, "WinDCL"); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wndclass.lpszMenuName = "WinDCL"; + wndclass.lpszClassName = "WinDCL"; + + if (!RegisterClass(&wndclass)) + return FALSE; + } + + // create Main window + hWndMain = CreateWindow( + "WinDCL", + "DCL Example", // no title + WS_CAPTION | // Title and Min/Max + WS_SYSMENU | // Add system menu box + WS_MINIMIZEBOX | // Add minimize box + WS_MAXIMIZEBOX | // Add maximize box + WS_THICKFRAME | // thick sizeable frame + WS_CLIPCHILDREN | // don't draw in child windows areas + WS_VISIBLE | // window created visible + WS_OVERLAPPED, + CW_USEDEFAULT, 0, // Use default X, Y + CW_USEDEFAULT, 0, // Use default X, Y + NULL, // Parent window's handle + NULL, // Default to Class Menu + hInst, // Instance of window + NULL); // Create struct for WM_CREATE + + // Did the Create Work?? + if(hWndMain == NULL) + return 0; + + ShowWindow(hWndMain, nCmdShow); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return msg.wParam; +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + switch (Message) + { + case WM_COMMAND: + if (wParam == IDM_TEST_DCL) + TestDLL(); + break; + case WM_CLOSE: + DestroyWindow(hWnd); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, Message, wParam, lParam); + } + return 0L; +} + +UINT ProcessInBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + LPIOFILEBLOCK lpFileIOBlock; + unsigned int iRead; + + lpFileIOBlock = (LPIOFILEBLOCK) pParam; + + iRead = fread(buffer, 1, *iSize, lpFileIOBlock->InFile ); + + if( iRead > 0 && lpFileIOBlock->bDoCRC == DO_CRC_INSTREAM ) + lpFileIOBlock->dwCRC = crc32(buffer, &iRead, &lpFileIOBlock->dwCRC); + + return iRead; +} + +void ProcessOutBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + LPIOFILEBLOCK lpFileIOBlock; + unsigned int iWrite; + + lpFileIOBlock = (LPIOFILEBLOCK) pParam; + + iWrite = fwrite( buffer, 1, *iSize, lpFileIOBlock->OutFile ); + + if( lpFileIOBlock->bDoCRC == DO_CRC_OUTSTREAM ) + lpFileIOBlock->dwCRC = crc32(buffer, &iWrite, &lpFileIOBlock->dwCRC); +} + +void TestDLL() +{ + int iStatus; + char szVerbose[128]; + IOFILEBLOCK FileIOBlock; + HGLOBAL hWorkBuff; + PCHAR pWorkBuff; + unsigned int type; /* ASCII or Binary compression */ + unsigned int dsize; /* Dictionary Size. 1,2 or 4K */ + + type = CMP_ASCII; /* Use ASCII compression */ + dsize = 4096; /* Use 4K dictionary */ + + // allocate the memory block for the scratch pad + if( (hWorkBuff = GlobalAlloc(GHND, CMP_BUFFER_SIZE)) == NULL ) + { + return; + } + + if ((pWorkBuff = (LPSTR) GlobalLock(hWorkBuff)) == NULL) + { + GlobalFree(hWorkBuff); + return; + } + + // setup structure used by ProcessReadBuffer() and ProcessWriteBuffer() + FileIOBlock.InFile = fopen( "Test.in", "rb" ); + FileIOBlock.OutFile = fopen( "Test.cmp", "wb" ); + FileIOBlock.bDoCRC = DO_CRC_INSTREAM; + FileIOBlock.dwCRC = ~((DWORD)0); // Pre-condition CRC + + if( (FileIOBlock.InFile != NULL) && (FileIOBlock.OutFile != NULL) ) + { + MessageBox(NULL, "Ready to implode", "Notice", MB_OK); + + iStatus = implode(ProcessInBuffer, + ProcessOutBuffer, + pWorkBuff, + &FileIOBlock, + &type, &dsize ); + + if( iStatus != 0 ) + { + wsprintf(szVerbose, "Implode Error: %d", iStatus ); + MessageBox(NULL, szVerbose, "Error", MB_OK); + } + else + { + // Post-condition CRC + if (FileIOBlock.bDoCRC == DO_CRC_INSTREAM) + { + FileIOBlock.dwCRC = ~FileIOBlock.dwCRC; + wsprintf(szVerbose, "CRC of input file: %lX", FileIOBlock.dwCRC); + MessageBox(NULL, szVerbose, "Notice", MB_OK); + } + } + + fclose(FileIOBlock.OutFile); + fclose(FileIOBlock.InFile); + + if( iStatus == 0 ) + { + // setup structure used by ProcessReadBuffer() and ProcessWriteBuffer() + FileIOBlock.InFile = fopen( "Test.cmp", "rb" ); + FileIOBlock.OutFile = fopen( "Test.ext", "wb" ); + FileIOBlock.bDoCRC = DO_CRC_OUTSTREAM; + FileIOBlock.dwCRC = ~((DWORD)0); // Pre-condition CRC + + MessageBox(NULL, "Ready to explode", "Notice", MB_OK); + iStatus = explode(ProcessInBuffer, + ProcessOutBuffer, + pWorkBuff, + &FileIOBlock ); + + if( iStatus != 0 ) + { + wsprintf(szVerbose, "Explode Error: %d", iStatus ); + MessageBox(NULL, szVerbose, "Error", MB_OK); + } + else + { + // Post-condition CRC + if (FileIOBlock.bDoCRC == DO_CRC_OUTSTREAM) + { + FileIOBlock.dwCRC = ~FileIOBlock.dwCRC; + wsprintf(szVerbose, "CRC of exploded file: %lX", FileIOBlock.dwCRC); + MessageBox(NULL, szVerbose, "Notice", MB_OK); + } + } + + fclose(FileIOBlock.OutFile); + fclose(FileIOBlock.InFile); + } + } + else + { + if( FileIOBlock.InFile != NULL ) + { + fclose( FileIOBlock.InFile ); + } + + if( FileIOBlock.OutFile != NULL ) + { + fclose( FileIOBlock.OutFile ); + } + + MessageBox(NULL, "The file TEST.IN must be in the current directory", "Error", MB_OK); + } + + GlobalUnlock(hWorkBuff); + GlobalFree(hWorkBuff); +} + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.H b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.H new file mode 100644 index 0000000..7389311 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.H @@ -0,0 +1,26 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#define DO_CRC_INSTREAM 1 +#define DO_CRC_OUTSTREAM 2 + +#define WM_FAILEDVALIDATE (WM_USER + 1) + +typedef struct IOFILEBLOCK { + FILE *InFile; + FILE *OutFile; + BOOL bDoCRC; + DWORD dwCRC; +}IOFILEBLOCK, *LPIOFILEBLOCK; + +HWND hInst; +HWND hWndMain; + +LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam); + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.ICO b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.ICO new file mode 100644 index 0000000..aaffe20 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.ICO differ diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.IDE b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.IDE new file mode 100644 index 0000000..f836d70 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.IDE differ diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.RC b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.RC new file mode 100644 index 0000000..4c07061 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/FIL2FIL/WINDCL.RC @@ -0,0 +1,9 @@ +#include "resource.h" + +WinDcl ICON "WinDcl.ico" + +WinDCL MENU + BEGIN + MENUITEM "&Test DCL", IDM_TEST_DCL + END + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/DCL.C b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/DCL.C new file mode 100644 index 0000000..5fb9eb0 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/DCL.C @@ -0,0 +1,497 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#include + +#include +#include +#include + +#include "implode.h" + +typedef enum +{ + COMPRESSING = 1, + UNCOMPRESSING +} FILEMODE; + +typedef struct +{ + PBYTE Buffer; // POINTER TO BUFFER + UINT CurPos; // CURRENT POSITION IN BUFFER + UINT BuffSize; // SIZE OF THE BUFFER +} BUFFER_BLOCK, *PBUFFER_BLOCK; + +// STRUCT TO PASS TO THE FILE IO FUNCTIONS +typedef struct +{ + BUFFER_BLOCK FileBuff; // FILE BUFFER + BUFFER_BLOCK cmpBuff; // COMPRESSION BUFFER + BUFFER_BLOCK uncmpBuff; // UNCOMPRESSION BUFFER + FILEMODE mode; + ULONG ulCrc; // CRC + UINT nCompressSize; + BOOL ErrorOccurred; // ERROR FLAG +} DATABLOCK, *PDATABLOCK; + +UINT DataType = CMP_ASCII; // GLOBAL FOR DATA TYPE FOR COMPRESSION +UINT DictSize = 4096; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + +static int iLineCnt; // CURRENT LINE TO OUTPUT STRING + +/********************************************************************* + * + * Function: ReadBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * read requests. If compressing, then the data read is + * in uncompressed form. If compressing, then the data + * read is data that was previously compressed. This + * function is called until zero is returned. + * + * Parameters: buffer -> Address of buffer to read the data into + * iSize -> Number of bytes to read into buffer + * dwParam -> User-defined parameter, in this case a + * pointer to the DATABLOCK + * + * Returns: Number of bytes actually read, or zero on EOF + * + *********************************************************************/ +UINT ReadBuffer( PCHAR buffer, UINT *iSize, void *pParam ) +{ + PDATABLOCK pDataBlock; + PBUFFER_BLOCK pBufferBlock; + UINT iRead; + UINT Num2Read = *iSize; + + pDataBlock = (PDATABLOCK) pParam; + + // IF AN ERROR OCCURRED + if( pDataBlock->ErrorOccurred == TRUE ) + { + return 0; + } + + if( pDataBlock->mode == COMPRESSING ) + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE COMPRESSION BUFFER + pBufferBlock = &pDataBlock->FileBuff; + } + else + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE UNCOMPRESSION BUFFER + pBufferBlock = &pDataBlock->cmpBuff; + } + + if( pBufferBlock->CurPos < pBufferBlock->BuffSize ) + { + UINT BytesLeft = pBufferBlock->BuffSize - pBufferBlock->CurPos; + + // IF REQUESTING MORE BYTES THAN ARE LEFT + if( BytesLeft < Num2Read ) + { + // SET NUMBER OF BYTES TO COPY TO WHAT IS LEFT + Num2Read = BytesLeft; + } + + // COPY BYTES AND UPDATE COUNTER + memcpy( buffer, (pBufferBlock->Buffer + pBufferBlock->CurPos), Num2Read ); + pBufferBlock->CurPos += Num2Read; + + iRead = Num2Read; + } + else // ELSE - NOTHING LEFT IN BUFFER SO RETURN 0 + { + iRead = 0; + } + + // IF COMPRESSING, THEN CALCULATE THE CRC + if( pDataBlock->mode == COMPRESSING ) + { + pDataBlock->ulCrc = crc32( buffer, &iRead, &pDataBlock->ulCrc ); + } + + return iRead; +} + +/********************************************************************* + * + * Function: WriteBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * write requests. + * + * Parameters: buffer -> Address of buffer to write data from + * iSize -> Number of bytes to write + * dwParam -> User-defined parameter, in this case a + * pointer to the DATABLOCK + * + * Returns: Zero, the return value is not used by the Data + * Compression Library + * + *********************************************************************/ +void WriteBuffer( PCHAR buffer, UINT *iSize, void *pParam ) +{ + PDATABLOCK pDataBlock; + PBUFFER_BLOCK pBufferBlock; + UINT Num2Write; + + Num2Write = *iSize; + + pDataBlock = (PDATABLOCK) pParam; + + // IF AN ERROR OCCURRED + if( pDataBlock->ErrorOccurred == TRUE ) + { + return; + } + + if( pDataBlock->mode == COMPRESSING ) + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE COMPRESSION BUFFER + pBufferBlock = &pDataBlock->cmpBuff; + + // SINCE COMPRESSING, KEEP A TOTAL OF THE COMPRESSED FILE SIZE + pDataBlock->nCompressSize += Num2Write; + } + else + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE UNCOMPRESSION BUFFER + pBufferBlock = &pDataBlock->uncmpBuff; + } + + // IF NOT OUT OF BUFFER SPACE + if( pBufferBlock->CurPos < pBufferBlock->BuffSize ) + { + // IF WRITING MORE BYTES THAN ARE LEFT + if( (pBufferBlock->BuffSize - pBufferBlock->CurPos) < Num2Write ) + { + MessageBox( NULL, "Out of buffer space - #1", "Compression Error", MB_OK ); + pDataBlock->ErrorOccurred = TRUE; + return; + } + + // COPY BYTES AND UPDATE COUNTER + memcpy( (pBufferBlock->Buffer + pBufferBlock->CurPos), + buffer, Num2Write ); + pBufferBlock->CurPos += Num2Write; + } + else // ELSE - NOTHING LEFT IN BUFFER SO RETURN 0 + { + MessageBox( NULL, "Out of buffer space - #2", "Compression Error", MB_OK ); + pDataBlock->ErrorOccurred = TRUE; + return; + } + + // IF COMPRESSING, THEN CALCULATE THE CRC + if (pDataBlock->mode == UNCOMPRESSING ) + { + pDataBlock->ulCrc = crc32( buffer, &Num2Write, &pDataBlock->ulCrc ); + } + + return; +} + +/********************************************************************* + * + * Function: CompressMemToMem() + * + * Purpose: To compress a buffer to another buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pulCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * pnCompressedSize -> Number of bytes in the compressed + * buffer + * pFileBuffer -> Pointer to buffer to compress + * pCompressedBuffer -> Pointer to buffer to place + * compressed data + * BuffSize -> Size of the buffers (both are allocated + * for same number of bytes) + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressMemToMem( HWND hWnd, HDC hDC, ULONG *pulCrc, + UINT *pnCompressedSize, PBYTE pFileBuffer, + PBYTE pCompressedBuffer, UINT BuffSize ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + DATABLOCK DataBlock; + HGLOBAL hWorkBuff; + PCHAR pWorkBuff; + + // allocate the memory block for the scratch pad + if( (hWorkBuff = GlobalAlloc(GHND, CMP_BUFFER_SIZE)) == NULL ) + { + return 0; + } + + if ((pWorkBuff = (LPSTR) GlobalLock(hWorkBuff)) == NULL) + { + GlobalFree(hWorkBuff); + return 0; + } + + memset( &DataBlock, 0, sizeof(DataBlock) ); + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + DataBlock.mode = COMPRESSING; + DataBlock.ulCrc = ~((DWORD)0); // Pre-condition CRC + + // SETUP BUFFER BLOCK FOR FILE BUFFER + DataBlock.FileBuff.Buffer = pFileBuffer; + DataBlock.FileBuff.BuffSize = BuffSize; + + // SETUP BUFFER BLOCK FOR COMPRESSION BUFFER + DataBlock.cmpBuff.Buffer = pCompressedBuffer; + DataBlock.cmpBuff.BuffSize = BuffSize; + + wsprintf( szVerbose, "Compressing %u byte buffer to memory ", BuffSize ); + TextOut( hDC, 10, (iLineCnt++ * 20) + 5, szVerbose, strlen(szVerbose) ); + + // COMPRESS THE FILE + iStatus = implode( ReadBuffer, WriteBuffer, + pWorkBuff, &DataBlock, &DataType, &DictSize ); + + // IF THERE WAS AN ERROR COMPRESSING FILE + if( iStatus || DataBlock.ErrorOccurred ) + { + wsprintf( szVerbose, "Error occurred while imploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else // ELSE - COMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + DataBlock.ulCrc = ~DataBlock.ulCrc; + + // RETURN CRC + *pulCrc = DataBlock.ulCrc; + + // RETURN COMPRESSED BUFFER SIZE + *pnCompressedSize = DataBlock.nCompressSize; + + wsprintf( szVerbose, "Compressed file to memory -> CRC = %08lX ", + DataBlock.ulCrc ); + TextOut( hDC, 10, (iLineCnt++ * 20) + 5, szVerbose, strlen(szVerbose) ); + } + + GlobalUnlock(hWorkBuff); + GlobalFree(hWorkBuff); + + return rc; +} + + +/********************************************************************* + * + * Function: ExpandMemToMem() + * + * Purpose: To expand a compressed buffer to a buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pulCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file after uncompression + * pCompressedBuffer -> Pointer to buffer to place + * compressed data + * nCompressedSize -> Number of bytes in the compressed + * buffer + * pUncompressedBuffer -> Pointer to buffer to place + * uncompressed data + * BuffSize -> Size of the uncompressed buffer + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int ExpandMemToMem( HWND hWnd, HDC hDC, ULONG *pulCrc, + PBYTE pCompressedBuffer, UINT nCompressedSize, + PBYTE pUncompressedBuffer, UINT BuffSize ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + DATABLOCK DataBlock; + HGLOBAL hWorkBuff; + PCHAR pWorkBuff; + + // allocate the memory block for the scratch pad + if( (hWorkBuff = GlobalAlloc(GHND, CMP_BUFFER_SIZE)) == NULL ) + { + return 0; + } + + if ((pWorkBuff = (LPSTR) GlobalLock(hWorkBuff)) == NULL) + { + GlobalFree(hWorkBuff); + return 0; + } + + memset( &DataBlock, 0, sizeof(DataBlock) ); + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + DataBlock.mode = UNCOMPRESSING; + DataBlock.ulCrc = ~((DWORD)0); // Pre-condition CRC + + // SETUP BUFFER BLOCK FOR COMPRESSION BUFFER + DataBlock.cmpBuff.Buffer = pCompressedBuffer; + DataBlock.cmpBuff.BuffSize = nCompressedSize; + + // SETUP BUFFER BLOCK FOR UNCOMPRESSION BUFFER + DataBlock.uncmpBuff.Buffer = pUncompressedBuffer; + DataBlock.uncmpBuff.BuffSize = BuffSize; + + wsprintf( szVerbose, "Compressed buffer size = %u ", nCompressedSize ); + TextOut( hDC, 10, (iLineCnt++ * 20) + 5, szVerbose, strlen(szVerbose) ); + + TextOut( hDC, 10, (iLineCnt++ * 20) + 5, "Uncompressing buffer to memory ", 32 ); + + // UNCOMPRESS THE FILE + iStatus = explode( ReadBuffer, WriteBuffer, pWorkBuff, &DataBlock ); + + // IF THERE WAS AN ERROR UNCOMPRESSING FILE + if( iStatus || DataBlock.ErrorOccurred ) + { + wsprintf( szVerbose, "Error occurred while exploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else // ELSE - UNCOMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + DataBlock.ulCrc = ~DataBlock.ulCrc; + + // RETURN CRC + *pulCrc = DataBlock.ulCrc; + + wsprintf( szVerbose, "Uncompressed file to memory -> CRC = %08lX ", + DataBlock.ulCrc ); + TextOut( hDC, 10, (iLineCnt++ * 20) + 5, szVerbose, strlen(szVerbose) ); + } + + GlobalUnlock(hWorkBuff); + GlobalFree(hWorkBuff); + + return rc; +} + + +/********************************************************************* + * + * Function: MemToMemExample() + * + * Purpose: To load a file into memory. Then compress and uncompress + * the buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszFilename -> Name of file to load + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int MemToMemExample( HWND hWnd, HDC hDC, PCHAR pszFilename ) +{ + FILE *InFile; + int rc=1; // RETURN CODE + UINT BufferSize; + UINT cmpSize; + PBYTE pFileBuffer; // BUFFER FOR FILE DATA + PBYTE pCompressedBuffer; // BUFFER FOR THE COMPRESSED DATA + PBYTE pUncompressedBuffer; // BUFFER FOR THE UNCOMPRESSED DATA + DWORD cmpCrc; // CRC OF FILE BEFORE COMPRESSION + DWORD uncmpCrc; // CRC OF FILE AFTER UNCOMPRESSION + fpos_t FileSize; + + + iLineCnt = 0; + + // OPEN THE FILE + InFile = fopen( pszFilename, "rb" ); + if( InFile == NULL ) + { + MessageBox( hWnd, "Error opening file for compression", "Error", MB_OK ); + return 0; + } + + fseek( InFile, 0, SEEK_END ); + + // CHECK IF FILE IS TOO LARGE + if( fgetpos( InFile, &FileSize ) || FileSize > 64000U ) + { + MessageBox( hWnd, "File is too large to compress to memory", "Error", MB_OK ); + return 0; + } + + fseek( InFile, 0, SEEK_SET ); + + BufferSize = (UINT) FileSize; + + // ALLOCATE BUFFER MEMORY + pFileBuffer = (PBYTE) malloc(BufferSize); + pCompressedBuffer = (PBYTE) malloc(BufferSize); + pUncompressedBuffer = (PBYTE) malloc(BufferSize); + + // IF SUCCESSFULLY ALLOCATED MEMORY + if( (pFileBuffer != NULL) && + (pCompressedBuffer != NULL) && + (pUncompressedBuffer != NULL) ) + { + // READ FILE + fread( pFileBuffer, 1, BufferSize, InFile ); + + // IF COMPRESSED OK + if( CompressMemToMem( hWnd, hDC, &cmpCrc, &cmpSize, + pFileBuffer, pCompressedBuffer, BufferSize ) ) + { + // IF ERROR UNCOMPRESSING + if( !ExpandMemToMem( hWnd, hDC, &uncmpCrc, + pCompressedBuffer, cmpSize, + pUncompressedBuffer, BufferSize ) ) + { + MessageBox( hWnd, "Error uncompressing to memory", "Error", MB_OK ); + rc = 0; + } + } + else + { + MessageBox( hWnd, "Error compressing to memory", "Error", MB_OK ); + rc = 0; + } + } + + + if( pFileBuffer != NULL ) + { + free(pFileBuffer); + } + + if( pCompressedBuffer != NULL ) + { + free(pCompressedBuffer); + } + + if( pUncompressedBuffer != NULL ) + { + free(pUncompressedBuffer); + } + + return rc; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/DCL.H b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/DCL.H new file mode 100644 index 0000000..fa65195 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/DCL.H @@ -0,0 +1,2 @@ + +int MemToMemExample( HWND hWnd, CDC *pDC, LPSTR lpszFilename ); diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKE.BAT b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKE.BAT new file mode 100644 index 0000000..0d9465f --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKE.BAT @@ -0,0 +1 @@ +nmake makefile.msc diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEDLL.BAT b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEDLL.BAT new file mode 100644 index 0000000..543a8b9 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEDLL.BAT @@ -0,0 +1 @@ +nmake makefdll.msc diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEFDLL.MSC b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEFDLL.MSC new file mode 100644 index 0000000..f5c876a --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEFDLL.MSC @@ -0,0 +1,22 @@ +ALL : WINDCL.EXE + +WINDCL.RES : WINDCL.RC RESOURCE.H + rc -r WinDCL.rc + +WINDCL.OBJ : WINDCL.C WINDCL.H + cl -c /D "_X86_" /D "WIN32" WinDCL.c + +DCL.OBJ : DCL.C DCL.H + cl -c /D "_X86_" /D "WIN32" DCL.C + +# rc WinDCL.res + +LINK32_OBJS= \ + WINDCL.res \ + WINDCL.OBJ \ + DCL.OBJ + +WINDCL.EXE : WINDCL.RES WINDCL.OBJ DCL.OBJ + link /SUBSYSTEM:windows /INCREMENTAL:no /MACHINE:I386 /OUT:"windcl.exe" \ + $(LINK32_OBJS) ..\..\..\IMPLODEI.LIB GDI32.LIB + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEFILE.MSC b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEFILE.MSC new file mode 100644 index 0000000..8ffa35e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/MAKEFILE.MSC @@ -0,0 +1,22 @@ +ALL : WINDCL.EXE + +WINDCL.RES : WINDCL.RC RESOURCE.H + rc -r WinDCL.rc + +WINDCL.OBJ : WINDCL.C WINDCL.H + cl -c /D "_X86_" /D "WIN32" WinDCL.c + +DCL.OBJ : DCL.C DCL.H + cl -c /D "_X86_" /D "WIN32" DCL.C + +# rc WinDCL.res + +LINK32_OBJS= \ + WINDCL.res \ + WINDCL.OBJ \ + DCL.OBJ + +WINDCL.EXE : WINDCL.RES WINDCL.OBJ DCL.OBJ + link /SUBSYSTEM:windows /INCREMENTAL:no /MACHINE:I386 /OUT:"windcl.exe" \ + $(LINK32_OBJS) ..\..\..\IMPLODE.LIB GDI32.LIB + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/RESOURCE.H b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/RESOURCE.H new file mode 100644 index 0000000..fce9635 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/RESOURCE.H @@ -0,0 +1,2 @@ +#define IDM_TEST_DCL 1000 + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WDCLDLL.IDE b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WDCLDLL.IDE new file mode 100644 index 0000000..bffbfb5 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WDCLDLL.IDE differ diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.C b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.C new file mode 100644 index 0000000..89bb97d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.C @@ -0,0 +1,114 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#include + +#include +#include +#include + +#include "resource.h" +#include "WinDCL.h" +#include "implode.h" + +void TestDLL(void); + +#ifndef _MSC_VER + #pragma argsused +#endif + +int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) +{ + WNDCLASS wndclass; + MSG msg; + + // Get rid of any compiler warnings + lpszCmdLine = lpszCmdLine; + + hInst = hInstance; + + // Register the DCL Test window Class + if(!hPrevInstance) + { + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = WndProc; + + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = LoadIcon(hInst, "WinDCL"); + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wndclass.lpszMenuName = "WinDCL"; + wndclass.lpszClassName = "WinDCL"; + + if (!RegisterClass(&wndclass)) + return FALSE; + } + + // create Main window + hWndMain = CreateWindow( + "WinDCL", + "DCL Example", // no title + WS_CAPTION | // Title and Min/Max + WS_SYSMENU | // Add system menu box + WS_MINIMIZEBOX | // Add minimize box + WS_MAXIMIZEBOX | // Add maximize box + WS_THICKFRAME | // thick sizeable frame + WS_CLIPCHILDREN | // don't draw in child windows areas + WS_VISIBLE | // window created visible + WS_OVERLAPPED, + CW_USEDEFAULT, 0, // Use default X, Y + CW_USEDEFAULT, 0, // Use default X, Y + NULL, // Parent window's handle + NULL, // Default to Class Menu + hInst, // Instance of window + NULL); // Create struct for WM_CREATE + + // Did the Create Work?? + if(hWndMain == NULL) + return 0; + + ShowWindow(hWndMain, nCmdShow); + + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return msg.wParam; +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + switch (Message) + { + case WM_COMMAND: + if (wParam == IDM_TEST_DCL) + { + HDC hDC; + + hDC = GetDC( hWnd ); + SetBkMode( hDC, TRANSPARENT ); + MemToMemExample( hWnd, hDC, "TEST.IN" ); + ReleaseDC( hWnd, hDC ); + } + break; + case WM_CLOSE: + DestroyWindow(hWnd); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, Message, wParam, lParam); + } + return 0L; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.H b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.H new file mode 100644 index 0000000..c29d9ec --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.H @@ -0,0 +1,15 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +HWND hInst; +HWND hWndMain; + +LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam); +int MemToMemExample( HWND hWnd, HDC hDC, PCHAR pszFilename ); + diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.ICO b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.ICO new file mode 100644 index 0000000..aaffe20 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.ICO differ diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.IDE b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.IDE new file mode 100644 index 0000000..6b813f8 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.IDE differ diff --git a/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.RC b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.RC new file mode 100644 index 0000000..4c07061 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/GUI/MEM2MEM/WINDCL.RC @@ -0,0 +1,9 @@ +#include "resource.h" + +WinDcl ICON "WinDcl.ico" + +WinDCL MENU + BEGIN + MENUITEM "&Test DCL", IDM_TEST_DCL + END + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/COMPDLG.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/COMPDLG.CPP new file mode 100644 index 0000000..d8e32b7 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/COMPDLG.CPP @@ -0,0 +1,424 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// compdlg.cpp : implementation file +// + + +#include "stdafx.h" +#include +#include "dcl.h" + +// Start, Added by PKWARE +#include "implode.h" +#include "PKstruct.h" +#include "compdlg.h" + +static char CancelCompression[] = "Cancel Compression"; + +#define DO_CRC_INSTREAM 1 +#define DO_CRC_OUTSTREAM 2 + +void ProcessOutBuffer(PCHAR buffer, UINT *iSize, void *Param); +UINT ProcessInBuffer(PCHAR buffer, UINT *iSize, void *pParam); + +void PKCompressFile(void); +// End, added by PKWARE + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CCompDlg dialog + + +CCompDlg::CCompDlg(CWnd* pParent /*=NULL*/) + : CDialog(CCompDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCompDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +void CCompDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCompDlg) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CCompDlg, CDialog) + //{{AFX_MSG_MAP(CCompDlg) + ON_BN_CLICKED(IDC_BUTTON1, OnCompressButton) + ON_BN_CLICKED(IDC_BUTTON2, OnTestButton) + ON_BN_CLICKED(IDC_BUTTON3, OnClearButton) + ON_BN_CLICKED(IDC_BUTTON4, OnDebugButton) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CCompDlg message handlers +BOOL CCompDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + SetDlgItemText(IDC_EDIT1, "TEST.IN"); + SetDlgItemText(IDC_EDIT9, "?"); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON2), FALSE); // Disable the Extract button + DebugMessages = FALSE; + return TRUE; // return TRUE unless you set the focus to a control +} + +// Function to add an item to the listbox. The listbox is then scrolled to display this item +void CCompDlg::PKLBMessage(char *message) +{ + SendDlgItemMessage(IDC_LIST1, LB_ADDSTRING, 0, (LONG)(PCHAR)(const char *)message); + int Items = (int)SendDlgItemMessage(IDC_LIST1, LB_GETCOUNT, 0,0); + SendDlgItemMessage(IDC_LIST1, LB_SETCURSEL, Items-1, 0); // Show this item +} + +void CCompDlg::OnCompressButton() +{ + // TODO: Add your control notification handler code here + ClearMessages(); // Clear listbox and filesizes + PKCompressFile(); // Start compression +} + +void CCompDlg::OnTestButton() +{ + // TODO: Add your control notification handler code here + SendDlgItemMessage(IDC_LIST1, LB_RESETCONTENT, 0, 0L); // Clear the listbox + PKLBMessage("Extracting file..."); + PKExtractFile(); // Start extraction +} + +void CCompDlg::OnClearButton() +{ + // TODO: Add your control notification handler code here + ClearMessages(); +} + +void CCompDlg::OnCancel() +{ + // TODO: Add extra cleanup here + CDialog::OnCancel(); +} + +// Function to calculate the percentage of compression without using floating point math +int GetPercent(unsigned long top, unsigned long bottom) +{ + int percent; + unsigned long bot; + + if (top == 0L) + return(0); + + bot = bottom ? bottom : 1L; + + if (top > 400000000L) // 400,000,000 + percent = (int)(top / (bot / 100L)); + else if (top > 40000000L) // 40,000,000 + percent = int((top * 10L) / (bot / 10L)); + else + percent = int((top * 100L) / bot); + + return(percent > 100 ? 100 : percent); +} + +void CCompDlg::ClearMessages() +{ + SendDlgItemMessage(IDC_LIST1, LB_RESETCONTENT, 0, 0L); // Clear the listbox + SetDlgItemText(IDC_EDIT2, (PCHAR)""); // Clear all the edit boxes + SetDlgItemText(IDC_EDIT3, (PCHAR)""); + SetDlgItemText(IDC_EDIT4, (PCHAR)""); + SetDlgItemText(IDC_EDIT5, (PCHAR)""); + SetDlgItemText(IDC_EDIT6, (PCHAR)""); + SetDlgItemText(IDC_EDIT7, (PCHAR)""); + SetDlgItemText(IDC_EDIT8, (PCHAR)""); +} + +// This function is called by the implode and explode functions. +UINT ProcessInBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + PIOFILEBLOCK pFileIOBlock; + unsigned int iRead; + + pFileIOBlock = (PIOFILEBLOCK) pParam; + + if (pFileIOBlock->PKAbortOperation) // Set this variable to abort compression or extraction + return 0; + + iRead = fread( buffer, 1, *iSize, pFileIOBlock->InFile ); // Read data from disk + + if (pFileIOBlock->DebugMessages) // Debugging messages on ? + { + char s[80]; + wsprintf(s, "Asked to read %u bytes, actually read %u bytes", *iSize, iRead); + SendDlgItemMessage(pFileIOBlock->hWindow, IDC_LIST1, LB_ADDSTRING, 0, (LONG)(PCHAR)(const char *)s); + int Items = (int)SendDlgItemMessage(pFileIOBlock->hWindow, IDC_LIST1, LB_GETCOUNT, 0, 0); + SendDlgItemMessage(pFileIOBlock->hWindow, IDC_LIST1, LB_SETCURSEL, Items-1, 0); + } + + if( iRead > 0 && pFileIOBlock->bDoCRC == DO_CRC_INSTREAM) + pFileIOBlock->dwCRC = crc32(buffer, &iRead, &pFileIOBlock->dwCRC); + + return iRead; +} + +// This function is called by the implode and explode functions. +void ProcessOutBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + PIOFILEBLOCK pFileIOBlock; + unsigned int iWrite; + + pFileIOBlock = (PIOFILEBLOCK) pParam; + + if (pFileIOBlock->PKAbortOperation) // Set this variable to abort compression or extraction + return; + + iWrite = fwrite( buffer, 1, *iSize, pFileIOBlock->OutFile ); // Write the data to disk + + if (pFileIOBlock->DebugMessages) // Debugging messages on ? + { + char s[80]; + wsprintf(s, "Asked to write %u bytes, actually wrote %u bytes", iSize, iWrite); + SendDlgItemMessage(pFileIOBlock->hWindow, IDC_LIST1, LB_ADDSTRING, 0, (LONG)(PCHAR)(const char *)s); + int Items = (int)SendDlgItemMessage(pFileIOBlock->hWindow, IDC_LIST1, LB_GETCOUNT, 0, 0); + SendDlgItemMessage(pFileIOBlock->hWindow, IDC_LIST1, LB_SETCURSEL, Items-1, 0); + } + + if( iWrite > 0 && pFileIOBlock->bDoCRC == DO_CRC_OUTSTREAM) + pFileIOBlock->dwCRC = crc32(buffer, &iWrite, &pFileIOBlock->dwCRC); + + return; +} + +void CCompDlg::PKCompressFile() +{ + int iStatus; + UINT CompType = CMP_ASCII, DictSize; + char szVerbose[128], FileName[80]; + fpos_t FileSize = 0, CompressedFileSize; + static char *Comp[] = { "Binary", "ASCII" }; + + FileIOBlock.hWindow = m_hWnd; // Used in the read and write routines + FileIOBlock.DebugMessages = DebugMessages; + FileIOBlock.PKAbortOperation = FALSE; + + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON1), FALSE); // Disable buttons + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON2), FALSE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON3), FALSE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON4), FALSE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDCANCEL), FALSE); + + HANDLE hScratchPad; + PCHAR pScratchPad; + + // allocate the memory block for the scratch pad + if( (hScratchPad = GlobalAlloc(GHND, CMP_BUFFER_SIZE)) == NULL ) + { + return; + } + + if( (pScratchPad = (PCHAR) GlobalLock(hScratchPad)) == NULL ) + { + GlobalFree(hScratchPad); + return; + } + + int LoopCnt; + + for( LoopCnt=0, CompType = CMP_ASCII; LoopCnt < 2; LoopCnt++, CompType = CMP_BINARY ) + { + for (DictSize = 1024; DictSize <= 4096; DictSize *= 2) // Dictionary size + { + FileIOBlock.InFile = FileIOBlock.OutFile = NULL; // Initialize + + GetDlgItemText(IDC_EDIT1, FileName, 80); + FileIOBlock.InFile = fopen(FileName, "rb" ); // Open the source file + + if( FileIOBlock.InFile == NULL ) // Error opening file + { + char s[80]; + wsprintf(s, "Error opening file %s.", (PCHAR)FileName); + PKLBMessage(s); + break; + } + + if( FileSize == 0 ) + { + fseek(FileIOBlock.InFile, 0L, SEEK_END); // Get the filesize + fgetpos(FileIOBlock.InFile, &FileSize ); // Get the filesize + fseek(FileIOBlock.InFile, 0L, SEEK_SET); // Rewind the file + wsprintf(szVerbose, "%ld", (PCHAR)FileSize); // Uncompressed size + SetDlgItemText(IDC_EDIT9, szVerbose); + } + + FileIOBlock.OutFile = fopen( "Test.cmp", "wb" ); + FileIOBlock.bDoCRC = DO_CRC_INSTREAM; + FileIOBlock.dwCRC = ~((DWORD)0); // Pre-condition CRC + + if( (FileIOBlock.InFile != NULL) && (FileIOBlock.OutFile != NULL)) + { + iStatus = implode( ProcessInBuffer, ProcessOutBuffer, pScratchPad, + &FileIOBlock, &CompType, &DictSize ); + + // Check the value of iStatus for errors + + // Post-condition CRC + if (FileIOBlock.bDoCRC == DO_CRC_INSTREAM) + { + CString CRCvalue; + FileIOBlock.dwCRC = ~FileIOBlock.dwCRC; + InputCRC = FileIOBlock.dwCRC; + wsprintf(szVerbose, "%lX", FileIOBlock.dwCRC); + SetDlgItemText(IDC_EDIT8, szVerbose); // Display CRC + } + + fgetpos(FileIOBlock.OutFile, &CompressedFileSize ); // Get the filesize + + fclose(FileIOBlock.OutFile); // Close the files + fclose(FileIOBlock.InFile); + + wsprintf(szVerbose, "%ld", CompressedFileSize); + + if (CompType == CMP_ASCII) + { + if (DictSize == 1024) + SetDlgItemText(IDC_EDIT2, szVerbose); + else if (DictSize == 2048) + SetDlgItemText(IDC_EDIT3, szVerbose); + else + SetDlgItemText(IDC_EDIT4, szVerbose); + } + else // Binary + { + if (DictSize == 1024) + SetDlgItemText(IDC_EDIT5, szVerbose); + else if (DictSize == 2048) + SetDlgItemText(IDC_EDIT6, szVerbose); + else + SetDlgItemText(IDC_EDIT7, szVerbose); + } + wsprintf(szVerbose, "Using %d dictionary, %s compression. File Compressed %d%%.", + DictSize, (PCHAR)Comp[CompType], 100 - GetPercent(CompressedFileSize, FileSize)); + PKLBMessage(szVerbose); + } + } + } + + GlobalUnlock(hScratchPad); + GlobalFree(hScratchPad); + + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON1), TRUE); // Reset the buttons + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON2), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON3), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON4), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDCANCEL), TRUE); +} + +void CCompDlg::PKExtractFile() +{ + int iStatus; + + FileIOBlock.hWindow = m_hWnd; // Used in the read and write routines + FileIOBlock.DebugMessages = DebugMessages; + FileIOBlock.PKAbortOperation = FALSE; + + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON1), FALSE); // Disable the buttons + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON2), FALSE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON3), FALSE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON4), FALSE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDCANCEL), FALSE); + + HANDLE hScratchPad; + PCHAR pScratchPad; + + // allocate the memory block for the scratch pad + if( (hScratchPad = GlobalAlloc(GHND, EXP_BUFFER_SIZE)) == NULL ) + { + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON1), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON2), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON3), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON4), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDCANCEL), TRUE); + return; + } + + if( (pScratchPad = (PCHAR) GlobalLock(hScratchPad)) == NULL ) + { + GlobalFree(hScratchPad); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON1), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON2), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON3), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON4), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDCANCEL), TRUE); + return; + } + + FileIOBlock.InFile = FileIOBlock.OutFile = NULL; + + // setup structure used by ProcessReadBuffer() and ProcessWriteBuffer() + FileIOBlock.InFile = fopen( "Test.cmp", "rb" ); + + if( FileIOBlock.InFile == NULL ) + { + int Items = (int)SendDlgItemMessage(IDC_LIST1, LB_GETCOUNT, 0,0); + SendDlgItemMessage(IDC_LIST1, LB_INSERTSTRING, Items, (LONG)(PCHAR)(const char *)"The file TEST.CMP was not found, you must compress a file first."); + } + else + { + FileIOBlock.OutFile = fopen( "Test.ext", "wb" ); + FileIOBlock.bDoCRC = DO_CRC_OUTSTREAM; + FileIOBlock.dwCRC = ~((DWORD)0); // Pre-condition CRC + + iStatus = explode( ProcessInBuffer, ProcessOutBuffer, pScratchPad, &FileIOBlock ); + + // Check the value of iStatus for errors + + // Post-condition CRC + if (FileIOBlock.bDoCRC == DO_CRC_OUTSTREAM) + { + FileIOBlock.dwCRC = ~FileIOBlock.dwCRC; + if (InputCRC != FileIOBlock.dwCRC) + PKLBMessage("File fails the CRC check!"); + else + PKLBMessage("File tests OK."); + } + + if( FileIOBlock.OutFile != NULL ) + fclose(FileIOBlock.OutFile); + if( FileIOBlock.InFile != NULL ) + fclose(FileIOBlock.InFile); + + PKLBMessage("Done extracting."); + } + + GlobalUnlock(hScratchPad); + GlobalFree(hScratchPad); + + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON1), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON2), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON3), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDC_BUTTON4), TRUE); + ::EnableWindow(::GetDlgItem(m_hWnd, IDCANCEL), TRUE); +} + +void CCompDlg::OnDebugButton() +{ + // TODO: Add your control notification handler code here + + DebugMessages = !DebugMessages; + ::SetWindowText(::GetDlgItem(m_hWnd, IDC_BUTTON4), DebugMessages ? (PCHAR)"Debug Messages = On" : (PCHAR)"Debug Messages = Off"); +} + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/COMPDLG.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/COMPDLG.H new file mode 100644 index 0000000..f1d68a4 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/COMPDLG.H @@ -0,0 +1,50 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// compdlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCompDlg dialog + +#include "pkstruct.h" + +class CCompDlg : public CDialog +{ +// Construction +public: + CCompDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CCompDlg) + enum { IDD = IDD_DIALOG1 }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + +// Implementation +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + // Generated message map functions + //{{AFX_MSG(CCompDlg) + afx_msg void OnCompressButton(); + afx_msg void OnTestButton(); + afx_msg void OnClearButton(); + virtual void OnCancel(); + virtual void PKCompressFile(); // Added by PKWARE + virtual void PKExtractFile(); // Added by PKWARE + virtual void ClearMessages(); // Added by PKWARE + virtual void PKLBMessage(char *); // Added by PKWARE + afx_msg void OnDebugButton(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + BOOL DebugMessages; // Added by PKWARE + unsigned long InputCRC; // Added by PKWARE + IOFILEBLOCK FileIOBlock; // Added by PKWARE +}; diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.CPP new file mode 100644 index 0000000..fe22c9d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.CPP @@ -0,0 +1,137 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// dcl.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "dcl.h" + +#include "mainfrm.h" +#include "dcldoc.h" +#include "dclview.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDclApp + +BEGIN_MESSAGE_MAP(CDclApp, CWinApp) + //{{AFX_MSG_MAP(CDclApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDclApp construction + +CDclApp::CDclApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CDclApp object + +CDclApp NEAR theApp; + +///////////////////////////////////////////////////////////////////////////// +// CDclApp initialization + +BOOL CDclApp::InitInstance() +{ + // 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. + + SetDialogBkColor(); // Set dialog background color to gray + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(CDclDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CDclView)); + AddDocTemplate(pDocTemplate); + + // create a new (empty) document + OnFileNew(); + + if (m_lpCmdLine[0] != '\0') + { + // TODO: add command line processing here + } + + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + +// Implementation +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CDclApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CDclApp commands diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.H new file mode 100644 index 0000000..a475f44 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.H @@ -0,0 +1,42 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// dcl.h : main header file for the DCL application +// + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CDclApp: +// See dcl.cpp for the implementation of this class +// + +class CDclApp : public CWinApp +{ +public: + CDclApp(); + +// Overrides + virtual BOOL InitInstance(); + +// Implementation + + //{{AFX_MSG(CDclApp) + afx_msg void OnAppAbout(); + // 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() +}; + + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.MAK b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.MAK new file mode 100644 index 0000000..68ddab8 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.MAK @@ -0,0 +1,264 @@ +# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE No configuration specified. Defaulting to Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "DCL.MAK" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Win32 Debug" +MTL=MkTypLib.exe +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win32 Release" + +# PROP BASE Use_MFC 1 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 1 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : $(OUTDIR)/DCL.exe $(OUTDIR)/DCL.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE CPP /nologo /MT /W3 /GX /YX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FR /c +# ADD CPP /nologo /MT /W3 /GX /YX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MT /W3 /GX /YX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ + "_MBCS" /Fp$(OUTDIR)/"DCL.pch" /Fo$(INTDIR)/ /c +CPP_OBJS=.\WinRel/ +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"DCL.res" /d "NDEBUG" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"DCL.bsc" + +$(OUTDIR)/DCL.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 oldnames.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /MACHINE:IX86 +# ADD LINK32 oldnames.lib implode.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /MACHINE:IX86 +# SUBTRACT LINK32 /INCREMENTAL:yes +LINK32_FLAGS=oldnames.lib implode.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows\ + /INCREMENTAL:no /PDB:$(OUTDIR)/"DCL.pdb" /MACHINE:IX86 /OUT:$(OUTDIR)/"DCL.exe"\ + +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/DCL.res \ + $(INTDIR)/STDAFX.OBJ \ + $(INTDIR)/DCL.OBJ \ + $(INTDIR)/MAINFRM.OBJ \ + $(INTDIR)/DCLDOC.OBJ \ + $(INTDIR)/DCLVIEW.OBJ \ + $(INTDIR)/COMPDLG.OBJ + +$(OUTDIR)/DCL.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# PROP BASE Use_MFC 1 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 1 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : $(OUTDIR)/DCL.exe $(OUTDIR)/DCL.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE CPP /nologo /MT /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FR /c +# ADD CPP /nologo /MT /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MT /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /D "_MBCS" /Fp$(OUTDIR)/"DCL.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"DCL.pdb" /c +CPP_OBJS=.\WinDebug/ +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"DCL.res" /d "_DEBUG" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"DCL.bsc" + +$(OUTDIR)/DCL.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 oldnames.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /DEBUG /MACHINE:IX86 +# ADD LINK32 oldnames.lib implode.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /INCREMENTAL:no /DEBUG /MACHINE:IX86 +LINK32_FLAGS=oldnames.lib implode.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows\ + /INCREMENTAL:no /PDB:$(OUTDIR)/"DCL.pdb" /DEBUG /MACHINE:IX86\ + /OUT:$(OUTDIR)/"DCL.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/DCL.res \ + $(INTDIR)/STDAFX.OBJ \ + $(INTDIR)/DCL.OBJ \ + $(INTDIR)/MAINFRM.OBJ \ + $(INTDIR)/DCLDOC.OBJ \ + $(INTDIR)/DCLVIEW.OBJ \ + $(INTDIR)/COMPDLG.OBJ + +$(OUTDIR)/DCL.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Group "Source Files" + +################################################################################ +# Begin Source File + +SOURCE=.\DCL.RC +DEP_DCL_R=\ + .\RES\DCL.ICO\ + .\RES\TOOLBAR.BMP\ + .\RESOURCE.H\ + .\RES\DCL.RC2 + +$(INTDIR)/DCL.res : $(SOURCE) $(DEP_DCL_R) $(INTDIR) + $(RSC) $(RSC_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STDAFX.CPP +DEP_STDAF=\ + .\STDAFX.H + +$(INTDIR)/STDAFX.OBJ : $(SOURCE) $(DEP_STDAF) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DCL.CPP +DEP_DCL_C=\ + .\STDAFX.H\ + .\DCL.H\ + .\MAINFRM.H\ + .\DCLDOC.H\ + .\DCLVIEW.H\ + .\RESOURCE.H + +$(INTDIR)/DCL.OBJ : $(SOURCE) $(DEP_DCL_C) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MAINFRM.CPP +DEP_MAINF=\ + .\STDAFX.H\ + .\DCL.H\ + .\MAINFRM.H\ + .\RESOURCE.H + +$(INTDIR)/MAINFRM.OBJ : $(SOURCE) $(DEP_MAINF) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DCLDOC.CPP +DEP_DCLDO=\ + .\STDAFX.H\ + .\DCL.H\ + .\DCLDOC.H\ + .\RESOURCE.H + +$(INTDIR)/DCLDOC.OBJ : $(SOURCE) $(DEP_DCLDO) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DCLVIEW.CPP +DEP_DCLVI=\ + .\STDAFX.H\ + .\DCL.H\ + .\DCLDOC.H\ + .\DCLVIEW.H\ + .\COMPDLG.H\ + .\RESOURCE.H\ + .\PKSTRUCT.H + +$(INTDIR)/DCLVIEW.OBJ : $(SOURCE) $(DEP_DCLVI) $(INTDIR) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\COMPDLG.CPP +DEP_COMPD=\ + .\STDAFX.H\ + .\DCL.H\ + .\implode.h\ + .\PKSTRUCT.H\ + .\COMPDLG.H\ + .\RESOURCE.H + +$(INTDIR)/COMPDLG.OBJ : $(SOURCE) $(DEP_COMPD) $(INTDIR) + +# End Source File +# End Group +# End Project +################################################################################ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.RC b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.RC new file mode 100644 index 0000000..92c04d4 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCL.RC @@ -0,0 +1,255 @@ +//Microsoft App Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#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 + "#include ""res\\dcl.rc2"" // non-App Studio edited resources\r\n" + "\r\n" + "#include ""afxres.rc"" \011// Standard components\r\n" + "\0" +END + +///////////////////////////////////////////////////////////////////////////////////// +#endif // APSTUDIO_INVOKED + + +////////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +IDR_MAINFRAME ICON DISCARDABLE "RES\\DCL.ICO" + +////////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP MOVEABLE PURE "RES\\TOOLBAR.BMP" + +////////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "Compress...", COMP_DIALOG + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About Dcl...", ID_APP_ABOUT + END +END + + +////////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE PURE +BEGIN + "N", ID_FILE_NEW, VIRTKEY,CONTROL + "O", ID_FILE_OPEN, VIRTKEY,CONTROL + "S", ID_FILE_SAVE, VIRTKEY,CONTROL + "Z", ID_EDIT_UNDO, VIRTKEY,CONTROL + "X", ID_EDIT_CUT, VIRTKEY,CONTROL + "C", ID_EDIT_COPY, VIRTKEY,CONTROL + "V", ID_EDIT_PASTE, VIRTKEY,CONTROL + VK_BACK, ID_EDIT_UNDO, VIRTKEY,ALT + VK_DELETE, ID_EDIT_CUT, VIRTKEY,SHIFT + VK_INSERT, ID_EDIT_COPY, VIRTKEY,CONTROL + VK_INSERT, ID_EDIT_PASTE, VIRTKEY,SHIFT + VK_F6, ID_NEXT_PANE, VIRTKEY + VK_F6, ID_PREV_PANE, VIRTKEY,SHIFT +END + + +////////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 34, 22, 217, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Dcl" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "Dcl Application Version 1.0",IDC_STATIC,40,10,119,8 + LTEXT "Copyright \251 1994,1995",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,176,6,32,14,WS_GROUP +END + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 248, 258 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "PKWARE Data Compression Library for Win32" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "Exit",IDCANCEL,153,237,87,13 + LISTBOX IDC_LIST1,2,121,238,67,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | + WS_TABSTOP + DEFPUSHBUTTON "Compress",IDC_BUTTON1,3,194,94,28 + PUSHBUTTON "Extract Compressed file",IDC_BUTTON2,3,226,94,28 + EDITTEXT IDC_EDIT1,7,16,115,12,ES_AUTOHSCROLL + LTEXT "ASCII",IDC_STATIC,52,42,20,10 + LTEXT "Binary",IDC_STATIC,99,42,20,10 + EDITTEXT IDC_EDIT2,52,55,42,13,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT3,52,70,42,13,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT4,52,85,42,13,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT5,99,55,42,13,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT6,99,70,42,13,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_EDIT7,99,85,42,13,ES_AUTOHSCROLL | ES_READONLY + LTEXT "1K Dictionary",IDC_STATIC,5,58,44,9 + LTEXT "2K Dictionary",IDC_STATIC,5,73,43,9 + LTEXT "4K Dictionary",IDC_STATIC,5,87,43,9 + LTEXT "Messages",IDC_STATIC,2,108,58,9 + PUSHBUTTON "Clear Messages",IDC_BUTTON3,153,194,87,13 + LTEXT "CRC32",IDC_STATIC,150,43,30,10 + EDITTEXT IDC_EDIT8,150,55,45,13,ES_AUTOHSCROLL | ES_READONLY + LTEXT "Input File",IDC_STATIC,7,4,59,9 + PUSHBUTTON "Debug Messages = Off",IDC_BUTTON4,153,210,87,13 + LTEXT "File Size",IDC_STATIC,150,4,30,8 + EDITTEXT IDC_EDIT9,150,16,45,12,ES_AUTOHSCROLL | ES_READONLY +END + + +////////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + IDR_MAINFRAME "Dcl Win32 Application\nDcl\nDcl Document\n\n\nDcl.Document\nDcl Document" +END + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + AFX_IDS_APP_TITLE "Dcl Win32 Application" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_NEW "Create a new document" + ID_FILE_OPEN "Open an existing document" + ID_FILE_CLOSE "Close the active document" + ID_FILE_SAVE "Save the active document" + ID_FILE_SAVE_AS "Save the active document with a new name" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright" + ID_APP_EXIT "Quit the application; prompts to save documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_MRU_FILE1 "Open this document" + ID_FILE_MRU_FILE2 "Open this document" + ID_FILE_MRU_FILE3 "Open this document" + ID_FILE_MRU_FILE4 "Open this document" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane" + ID_PREV_PANE "Switch back to the previous window pane" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection" + ID_EDIT_CLEAR_ALL "Erase everything" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard" + ID_EDIT_FIND "Find the specified text" + ID_EDIT_PASTE "Insert Clipboard contents" + ID_EDIT_REPEAT "Repeat the last action" + ID_EDIT_REPLACE "Replace specific text with different text" + ID_EDIT_SELECT_ALL "Select the entire document" + ID_EDIT_UNDO "Undo the last action" + ID_EDIT_REDO "Redo the previously undone action" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar" + ID_VIEW_STATUS_BAR "Show or hide the status bar" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" +END + + +#ifndef APSTUDIO_INVOKED +//////////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "res\dcl.rc2" // non-App Studio edited resources + +#include "afxres.rc" // Standard components + +///////////////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLDOC.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLDOC.CPP new file mode 100644 index 0000000..18d1089 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLDOC.CPP @@ -0,0 +1,88 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// dcldoc.cpp : implementation of the CDclDoc class +// + +#include "stdafx.h" +#include "dcl.h" + +#include "dcldoc.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDclDoc + +IMPLEMENT_DYNCREATE(CDclDoc, CDocument) + +BEGIN_MESSAGE_MAP(CDclDoc, CDocument) + //{{AFX_MSG_MAP(CDclDoc) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDclDoc construction/destruction + +CDclDoc::CDclDoc() +{ + // TODO: add one-time construction code here +} + +CDclDoc::~CDclDoc() +{ +} + +BOOL CDclDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CDclDoc serialization + +void CDclDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CDclDoc diagnostics + +#ifdef _DEBUG +void CDclDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CDclDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CDclDoc commands diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLDOC.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLDOC.H new file mode 100644 index 0000000..e6df009 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLDOC.H @@ -0,0 +1,45 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// dcldoc.h : interface of the CDclDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class CDclDoc : public CDocument +{ +protected: // create from serialization only + CDclDoc(); + DECLARE_DYNCREATE(CDclDoc) + +// Attributes +public: +// Operations +public: + +// Implementation +public: + virtual ~CDclDoc(); + virtual void Serialize(CArchive& ar); // overridden for document i/o +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + virtual BOOL OnNewDocument(); + +// Generated message map functions +protected: + //{{AFX_MSG(CDclDoc) + // 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() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLVIEW.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLVIEW.CPP new file mode 100644 index 0000000..2181616 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLVIEW.CPP @@ -0,0 +1,87 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// dclview.cpp : implementation of the CDclView class +// + +#include "stdafx.h" +#include "dcl.h" + +#include "dcldoc.h" +#include "dclview.h" +#include "compdlg.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDclView + +IMPLEMENT_DYNCREATE(CDclView, CView) + +BEGIN_MESSAGE_MAP(CDclView, CView) + //{{AFX_MSG_MAP(CDclView) + ON_COMMAND(COMP_DIALOG, OnDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDclView construction/destruction + +CDclView::CDclView() +{ + // TODO: add construction code here +} + +CDclView::~CDclView() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// CDclView drawing + +void CDclView::OnDraw(CDC* pDC) +{ + CDclDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + // TODO: add draw code for native data here +} + +///////////////////////////////////////////////////////////////////////////// +// CDclView diagnostics + +#ifdef _DEBUG +void CDclView::AssertValid() const +{ + CView::AssertValid(); +} + +void CDclView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CDclDoc* CDclView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDclDoc))); + return (CDclDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CDclView message handlers + +void CDclView::OnDialog() +{ + // TODO: Add your command handler code here + CCompDlg dlg; + dlg.DoModal(); +} diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLVIEW.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLVIEW.H new file mode 100644 index 0000000..4e004b5 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/DCLVIEW.H @@ -0,0 +1,50 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// dclview.h : interface of the CDclView class +// +///////////////////////////////////////////////////////////////////////////// + +class CDclView : public CView +{ +protected: // create from serialization only + CDclView(); + DECLARE_DYNCREATE(CDclView) + +// Attributes +public: + CDclDoc* GetDocument(); + +// Operations +public: + +// Implementation +public: + virtual ~CDclView(); + virtual void OnDraw(CDC* pDC); // overridden to draw this view +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CDclView) + afx_msg void OnDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#ifndef _DEBUG // debug version in dclview.cpp +inline CDclDoc* CDclView::GetDocument() + { return (CDclDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/IMPLODE.LIB b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/IMPLODE.LIB new file mode 100644 index 0000000..4cc55e1 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/IMPLODE.LIB differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/MAINFRM.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/MAINFRM.CPP new file mode 100644 index 0000000..086a4ab --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/MAINFRM.CPP @@ -0,0 +1,114 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mainfrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "dcl.h" + +#include "mainfrm.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code ! + ON_WM_CREATE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// arrays of IDs used to initialize control bars + +// toolbar buttons - IDs are command buttons +static UINT BASED_CODE buttons[] = +{ + // same order as in the bitmap 'toolbar.bmp' + ID_FILE_NEW, + ID_FILE_OPEN, + ID_FILE_SAVE, + ID_SEPARATOR, + ID_EDIT_PASTE, + ID_SEPARATOR, + ID_FILE_PRINT, + ID_APP_ABOUT, +}; + +static UINT BASED_CODE indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here +} + +CMainFrame::~CMainFrame() +{ +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndToolBar.Create(this) || + !m_wndToolBar.LoadBitmap(IDR_MAINFRAME) || + !m_wndToolBar.SetButtons(buttons, + sizeof(buttons)/sizeof(UINT))) + { + TRACE("Failed to create toolbar\n"); + return -1; // fail to create + } + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE("Failed to create status bar\n"); + return -1; // fail to create + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/MAINFRM.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/MAINFRM.H new file mode 100644 index 0000000..1e000cc --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/MAINFRM.H @@ -0,0 +1,47 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mainfrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +class CMainFrame : public CFrameWnd +{ +protected: // create from serialization only + CMainFrame(); + DECLARE_DYNCREATE(CMainFrame) + +// Attributes +public: + +// Operations +public: + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + // 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() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/PKSTRUCT.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/PKSTRUCT.H new file mode 100644 index 0000000..bfdee74 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/PKSTRUCT.H @@ -0,0 +1,24 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#ifndef __PKSTRUCT__ +#define __PKSTRUCT__ 1 + +typedef struct IOFILEBLOCK +{ + FILE *InFile; + FILE *OutFile; + BOOL bDoCRC; + DWORD dwCRC; + BOOL DebugMessages; + HWND hWindow; + BOOL PKAbortOperation; +} +*PIOFILEBLOCK; + +#endif diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/DCL.ICO b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/DCL.ICO new file mode 100644 index 0000000..b718392 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/DCL.ICO differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/DCL.RC2 b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/DCL.RC2 new file mode 100644 index 0000000..f138e1f --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/DCL.RC2 @@ -0,0 +1,52 @@ +// +// DCL.RC2 - resources App Studio does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by App Studio +#endif //APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// Version stamp for this .EXE + +#include "ver.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG|VS_FF_PRIVATEBUILD|VS_FF_PRERELEASE +#else + FILEFLAGS 0 // final version +#endif + FILEOS VOS_DOS_WINDOWS16 + FILETYPE VFT_APP + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "DCL MFC Application\0" + VALUE "FileVersion", "1.0.001\0" + VALUE "InternalName", "DCL\0" + VALUE "LegalCopyright", "\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename","DCL.EXE\0" + VALUE "ProductName", "DCL\0" + VALUE "ProductVersion", "1.0.001\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + // English language (0x409) and the Windows ANSI codepage (1252) + END +END + +///////////////////////////////////////////////////////////////////////////// +// Add additional manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/TOOLBAR.BMP b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/TOOLBAR.BMP new file mode 100644 index 0000000..eaf5db2 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RES/TOOLBAR.BMP differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RESOURCE.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RESOURCE.H new file mode 100644 index 0000000..81a1161 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/RESOURCE.H @@ -0,0 +1,42 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +//{{NO_DEPENDENCIES}} +// App Studio generated include file. +// Used by DCL.RC +// +#define IDR_MAINFRAME 2 +#define IDD_ABOUTBOX 100 +#define IDD_DIALOG1 102 +#define IDC_LIST1 1000 +#define IDC_BUTTON1 1001 +#define IDC_BUTTON2 1002 +#define IDC_EDIT1 1003 +#define IDC_EDIT2 1004 +#define IDC_EDIT3 1005 +#define IDC_EDIT4 1006 +#define IDC_EDIT5 1007 +#define IDC_EDIT6 1008 +#define IDC_EDIT7 1009 +#define IDC_BUTTON3 1010 +#define IDC_EDIT8 1011 +#define IDC_BUTTON4 1012 +#define IDC_EDIT9 1013 +#define COMP_DIALOG 32771 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 32772 +#define _APS_NEXT_CONTROL_VALUE 1014 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/STDAFX.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/STDAFX.CPP new file mode 100644 index 0000000..07f7b46 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/STDAFX.CPP @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// stdafx.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/STDAFX.H b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/STDAFX.H new file mode 100644 index 0000000..6179a32 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/FIL2FIL/STDAFX.H @@ -0,0 +1,7 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#include // MFC core and standard components +#include // MFC extensions (including VB) diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/DCL.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/DCL.CPP new file mode 100644 index 0000000..52967dd --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/DCL.CPP @@ -0,0 +1,479 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +/* + * DCL.cpp - File to call various DCL DLL functions + */ + +#include "stdafx.h" + +#include +#include +#include + +#include "implode.h" + +typedef enum +{ + COMPRESSING = 1, + UNCOMPRESSING +} FILEMODE; + +typedef struct +{ + PBYTE Buffer; // POINTER TO BUFFER + UINT CurPos; // CURRENT POSITION IN BUFFER + UINT BuffSize; // SIZE OF THE BUFFER +} BUFFER_BLOCK, *PBUFFER_BLOCK; + +// STRUCT TO PASS TO THE FILE IO FUNCTIONS +typedef struct +{ + BUFFER_BLOCK FileBuff; // FILE BUFFER + BUFFER_BLOCK cmpBuff; // COMPRESSION BUFFER + BUFFER_BLOCK uncmpBuff; // UNCOMPRESSION BUFFER + FILEMODE mode; + DWORD dwCrc; // CRC + UINT nCompressSize; + BOOL ErrorOccurred; // ERROR FLAG +} DATABLOCK, *PDATABLOCK; + +UINT DataType = CMP_ASCII; // GLOBAL FOR DATA TYPE FOR COMPRESSION +UINT DictSize = 4096; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + +static int iLineCnt; // CURRENT LINE TO OUTPUT STRING + +/********************************************************************* + * + * Function: ReadBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * read requests. If compressing, then the data read is + * in uncompressed form. If compressing, then the data + * read is data that was previously compressed. This + * function is called until zero is returned. + * + * Parameters: buffer -> Address of buffer to read the data into + * iSize -> Number of bytes to read into buffer + * dwParam -> User-defined parameter, in this case a + * pointer to the DATABLOCK + * + * Returns: Number of bytes actually read, or zero on EOF + * + *********************************************************************/ +UINT ReadBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + PDATABLOCK pDataBlock; + PBUFFER_BLOCK pBufferBlock; + UINT iRead; + + pDataBlock = (PDATABLOCK) pParam; + + // IF AN ERROR OCCURRED + if( pDataBlock->ErrorOccurred == TRUE ) + { + return 0; + } + + if( pDataBlock->mode == COMPRESSING ) + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE COMPRESSION BUFFER + pBufferBlock = &pDataBlock->FileBuff; + } + else + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE UNCOMPRESSION BUFFER + pBufferBlock = &pDataBlock->cmpBuff; + } + + if( pBufferBlock->CurPos < pBufferBlock->BuffSize ) + { + UINT BytesLeft = pBufferBlock->BuffSize - pBufferBlock->CurPos; + + // IF REQUESTING MORE BYTES THAN ARE LEFT + if( BytesLeft < *iSize ) + { + // SET NUMBER OF BYTES TO COPY TO WHAT IS LEFT + *iSize = BytesLeft; + } + + // COPY BYTES AND UPDATE COUNTER + memcpy( buffer, (pBufferBlock->Buffer + pBufferBlock->CurPos), *iSize ); + pBufferBlock->CurPos += *iSize; + + iRead = *iSize; + } + else // ELSE - NOTHING LEFT IN BUFFER SO RETURN 0 + { + iRead = 0; + } + + // IF COMPRESSING, THEN CALCULATE THE CRC + if( pDataBlock->mode == COMPRESSING ) + { + pDataBlock->dwCrc = crc32( buffer, &iRead, &pDataBlock->dwCrc ); + } + + return iRead; +} + +/********************************************************************* + * + * Function: WriteBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * write requests. + * + * Parameters: buffer -> Address of buffer to write data from + * iSize -> Number of bytes to write + * dwParam -> User-defined parameter, in this case a + * pointer to the DATABLOCK + * + * Returns: Zero, the return value is not used by the Data + * Compression Library + * + *********************************************************************/ +void WriteBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + PDATABLOCK pDataBlock; + PBUFFER_BLOCK pBufferBlock; + + pDataBlock = (PDATABLOCK) pParam; + + // IF AN ERROR OCCURRED + if( pDataBlock->ErrorOccurred == TRUE ) + { + return; + } + + if( pDataBlock->mode == COMPRESSING ) + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE COMPRESSION BUFFER + pBufferBlock = &pDataBlock->cmpBuff; + + // SINCE COMPRESSING, KEEP A TOTAL OF THE COMPRESSED FILE SIZE + pDataBlock->nCompressSize += *iSize; + } + else + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE UNCOMPRESSION BUFFER + pBufferBlock = &pDataBlock->uncmpBuff; + } + + // IF NOT OUT OF BUFFER SPACE + if( pBufferBlock->CurPos < pBufferBlock->BuffSize ) + { + // IF WRITING MORE BYTES THAN ARE LEFT + if( (pBufferBlock->BuffSize - pBufferBlock->CurPos) < *iSize ) + { + MessageBox( NULL, "Out of buffer space - #1", "Compression Error", MB_OK ); + pDataBlock->ErrorOccurred = TRUE; + return; + } + + // COPY BYTES AND UPDATE COUNTER + memcpy( (pBufferBlock->Buffer + pBufferBlock->CurPos), + buffer, *iSize ); + pBufferBlock->CurPos += *iSize; + } + else // ELSE - NOTHING LEFT IN BUFFER SO RETURN 0 + { + MessageBox( NULL, "Out of buffer space - #2", "Compression Error", MB_OK ); + pDataBlock->ErrorOccurred = TRUE; + return; + } + + // IF COMPRESSING, THEN CALCULATE THE CRC + if (pDataBlock->mode == UNCOMPRESSING ) + { + pDataBlock->dwCrc = crc32( buffer, iSize, &pDataBlock->dwCrc ); + } + + return; +} + +/********************************************************************* + * + * Function: CompressMemToMem() + * + * Purpose: To compress a buffer to another buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * pnCompressedSize -> Number of bytes in the compressed + * buffer + * pFileBuffer -> Pointer to buffer to compress + * pCompressedBuffer -> Pointer to buffer to place + * compressed data + * BuffSize -> Size of the buffers (both are allocated + * for same number of bytes) + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressMemToMem( HWND hWnd, CDC *pDC, DWORD *pdwCrc, + UINT *pnCompressedSize, PBYTE pFileBuffer, + PBYTE pCompressedBuffer, UINT BuffSize ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + DATABLOCK DataBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + memset( &DataBlock, 0, sizeof(DataBlock) ); + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + DataBlock.mode = COMPRESSING; + DataBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + // SETUP BUFFER BLOCK FOR FILE BUFFER + DataBlock.FileBuff.Buffer = pFileBuffer; + DataBlock.FileBuff.BuffSize = BuffSize; + + // SETUP BUFFER BLOCK FOR COMPRESSION BUFFER + DataBlock.cmpBuff.Buffer = pCompressedBuffer; + DataBlock.cmpBuff.BuffSize = BuffSize; + + wsprintf( szVerbose, "Compressing %u byte buffer to memory ", BuffSize ); + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, szVerbose ); + + // COMPRESS THE FILE + iStatus = implode( ReadBuffer, WriteBuffer, + pScratchPad, &DataBlock, &DataType, &DictSize ); + + // IF THERE WAS AN ERROR COMPRESSING FILE + if( iStatus || DataBlock.ErrorOccurred ) + { + // DISPLAY ERROR STRING IF ERROR OCCURRED IN IMPLODE + wsprintf( szVerbose, "Error occurred while imploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else // ELSE - COMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + DataBlock.dwCrc = ~DataBlock.dwCrc; + + // RETURN CRC + *pdwCrc = DataBlock.dwCrc; + + // RETURN COMPRESSED BUFFER SIZE + *pnCompressedSize = DataBlock.nCompressSize; + + wsprintf( szVerbose, "Compressed file to memory -> CRC = %08lX ", + DataBlock.dwCrc ); + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, szVerbose ); + } + + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: ExpandMemToMem() + * + * Purpose: To expand a compressed buffer to a buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file after uncompression + * pCompressedBuffer -> Pointer to buffer to place + * compressed data + * nCompressedSize -> Number of bytes in the compressed + * buffer + * pUncompressedBuffer -> Pointer to buffer to place + * uncompressed data + * BuffSize -> Size of the uncompressed buffer + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int ExpandMemToMem( HWND hWnd, CDC *pDC, DWORD *pdwCrc, + PBYTE pCompressedBuffer, UINT nCompressedSize, + PBYTE pUncompressedBuffer, UINT BuffSize ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + DATABLOCK DataBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + memset( &DataBlock, 0, sizeof(DataBlock) ); + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + DataBlock.mode = UNCOMPRESSING; + DataBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + // SETUP BUFFER BLOCK FOR COMPRESSION BUFFER + DataBlock.cmpBuff.Buffer = pCompressedBuffer; + DataBlock.cmpBuff.BuffSize = nCompressedSize; + + // SETUP BUFFER BLOCK FOR UNCOMPRESSION BUFFER + DataBlock.uncmpBuff.Buffer = pUncompressedBuffer; + DataBlock.uncmpBuff.BuffSize = BuffSize; + + wsprintf( szVerbose, "Compressed buffer size = %u ", nCompressedSize ); + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, szVerbose ); + + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, "Uncompressing buffer to memory " ); + + // UNCOMPRESS THE FILE + iStatus = explode( ReadBuffer, WriteBuffer, pScratchPad, &DataBlock ); + + // IF THERE WAS AN ERROR UNCOMPRESSING FILE + if( iStatus || DataBlock.ErrorOccurred ) + { + wsprintf( szVerbose, "Error occurred while exploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else // ELSE - UNCOMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + DataBlock.dwCrc = ~DataBlock.dwCrc; + + // RETURN CRC + *pdwCrc = DataBlock.dwCrc; + + wsprintf( szVerbose, "Uncompressed file to memory -> CRC = %08lX ", + DataBlock.dwCrc ); + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, szVerbose ); + } + + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: MemToMemExample() + * + * Purpose: To load a file into memory. Then compress and uncompress + * the buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszFilename -> Name of file to load + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int MemToMemExample( HWND hWnd, CDC *pDC, PCHAR pszFilename ) +{ + ASSERT( hWnd ); + ASSERT_VALID( pDC ); + + CFile InFile; + int rc=1; // RETURN CODE + UINT BufferSize; + UINT cmpSize; + PBYTE pFileBuffer; // BUFFER FOR FILE DATA + PBYTE pCompressedBuffer; // BUFFER FOR THE COMPRESSED DATA + PBYTE pUncompressedBuffer; // BUFFER FOR THE UNCOMPRESSED DATA + DWORD cmpCrc; // CRC OF FILE BEFORE COMPRESSION + DWORD uncmpCrc; // CRC OF FILE AFTER UNCOMPRESSION + + + iLineCnt = 0; + + // OPEN THE FILE + if( !InFile.Open( pszFilename, + CFile::modeRead | CFile::shareExclusive | CFile::typeBinary ) ) + { + MessageBox( hWnd, "Error opening file for compression", "Error", MB_OK ); + return 0; + } + + // CHECK IF FILE IS TOO LARGE + if( InFile.GetLength() > 64000U ) + { + MessageBox( hWnd, "File is too large to compress to memory", "Error", MB_OK ); + return 0; + } + + BufferSize = (UINT) InFile.GetLength(); + + // ALLOCATE BUFFER MEMORY + pFileBuffer = (PBYTE) new char[BufferSize]; + pCompressedBuffer = (PBYTE) new char[BufferSize]; + pUncompressedBuffer = (PBYTE) new char[BufferSize]; + + // IF SUCCESSFULLY ALLOCATED MEMORY + if( (pFileBuffer != NULL) && + (pCompressedBuffer != NULL) && + (pUncompressedBuffer != NULL) ) + { + // READ FILE + InFile.Read( pFileBuffer, BufferSize ); + + // IF COMPRESSED OK + if( CompressMemToMem( hWnd, pDC, &cmpCrc, &cmpSize, + pFileBuffer, pCompressedBuffer, BufferSize ) ) + { + // IF ERROR UNCOMPRESSING + if( !ExpandMemToMem( hWnd, pDC, &uncmpCrc, + pCompressedBuffer, cmpSize, + pUncompressedBuffer, BufferSize ) ) + { + MessageBox( hWnd, "Error uncompressing to memory", "Error", MB_OK ); + rc = 0; + } + } + else + { + MessageBox( hWnd, "Error compressing to memory", "Error", MB_OK ); + rc = 0; + } + } + + + if( pFileBuffer != NULL ) + { + delete pFileBuffer; + } + + if( pCompressedBuffer != NULL ) + { + delete pCompressedBuffer; + } + + if( pUncompressedBuffer != NULL ) + { + delete pUncompressedBuffer; + } + + return rc; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/DCL.H b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/DCL.H new file mode 100644 index 0000000..c70ef42 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/DCL.H @@ -0,0 +1,10 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1994,1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +int MemToMemExample( HWND hWnd, CDC *pDC, PCHAR lpszFilename ); diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/IMPLODEI.LIB b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/IMPLODEI.LIB new file mode 100644 index 0000000..ca0b4df Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/IMPLODEI.LIB differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MAINFRM.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MAINFRM.CPP new file mode 100644 index 0000000..47fb798 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MAINFRM.CPP @@ -0,0 +1,126 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mainfrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "mem2mem.h" + +#include "mainfrm.h" +#include "DCL.H" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CREATE() + ON_COMMAND(IDM_TEST, OnTest) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// arrays of IDs used to initialize control bars + +// toolbar buttons - IDs are command buttons +static UINT BASED_CODE buttons[] = +{ + // same order as in the bitmap 'toolbar.bmp' + ID_FILE_NEW, + ID_FILE_OPEN, + ID_FILE_SAVE, + ID_SEPARATOR, + ID_EDIT_CUT, + ID_EDIT_COPY, + ID_EDIT_PASTE, + ID_SEPARATOR, + ID_FILE_PRINT, + ID_APP_ABOUT, +}; + +static UINT BASED_CODE indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here +} + +CMainFrame::~CMainFrame() +{ +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE("Failed to create status bar\n"); + return -1; // fail to create + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + +void CMainFrame::OnTest() +{ + CFileDialog FileDlg( TRUE, NULL, "*.*" ); + + if( FileDlg.DoModal() == IDOK ) + { + HWND hWnd; + + // GET DC AND SET THE TEXT BACKGROUND COLOR TO WINDOW BACKGROUND COLOR + CClientDC dc(this); + COLORREF bkGroundColor = dc.GetPixel( 0, 0 ); + dc.SetBkColor( bkGroundColor ); + + hWnd = CWnd::GetSafeHwnd(); + + MemToMemExample( hWnd, &dc, (LPSTR)(const char *)FileDlg.GetPathName() ); + } +} diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MAINFRM.H b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MAINFRM.H new file mode 100644 index 0000000..78e8804 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MAINFRM.H @@ -0,0 +1,46 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mainfrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +class CMainFrame : public CFrameWnd +{ +protected: // create from serialization only + CMainFrame(); + DECLARE_DYNCREATE(CMainFrame) + +// Attributes +public: + +// Operations +public: + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnTest(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MDOC.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MDOC.CPP new file mode 100644 index 0000000..e2c5e90 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MDOC.CPP @@ -0,0 +1,88 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mem2mdoc.cpp : implementation of the CMem2memDoc class +// + +#include "stdafx.h" +#include "mem2mem.h" + +#include "mem2mdoc.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMem2memDoc + +IMPLEMENT_DYNCREATE(CMem2memDoc, CDocument) + +BEGIN_MESSAGE_MAP(CMem2memDoc, CDocument) + //{{AFX_MSG_MAP(CMem2memDoc) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMem2memDoc construction/destruction + +CMem2memDoc::CMem2memDoc() +{ + // TODO: add one-time construction code here +} + +CMem2memDoc::~CMem2memDoc() +{ +} + +BOOL CMem2memDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMem2memDoc serialization + +void CMem2memDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CMem2memDoc diagnostics + +#ifdef _DEBUG +void CMem2memDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CMem2memDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMem2memDoc commands diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MDOC.H b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MDOC.H new file mode 100644 index 0000000..13745b9 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MDOC.H @@ -0,0 +1,45 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mem2mdoc.h : interface of the CMem2memDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class CMem2memDoc : public CDocument +{ +protected: // create from serialization only + CMem2memDoc(); + DECLARE_DYNCREATE(CMem2memDoc) + +// Attributes +public: +// Operations +public: + +// Implementation +public: + virtual ~CMem2memDoc(); + virtual void Serialize(CArchive& ar); // overridden for document i/o +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + virtual BOOL OnNewDocument(); + +// Generated message map functions +protected: + //{{AFX_MSG(CMem2memDoc) + // 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() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.CPP new file mode 100644 index 0000000..1c49951 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.CPP @@ -0,0 +1,137 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mem2mem.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "mem2mem.h" + +#include "mainfrm.h" +#include "mem2mdoc.h" +#include "mem2mvw.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMem2memApp + +BEGIN_MESSAGE_MAP(CMem2memApp, CWinApp) + //{{AFX_MSG_MAP(CMem2memApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMem2memApp construction + +CMem2memApp::CMem2memApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CMem2memApp object + +CMem2memApp NEAR theApp; + +///////////////////////////////////////////////////////////////////////////// +// CMem2memApp initialization + +BOOL CMem2memApp::InitInstance() +{ + // 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. + + SetDialogBkColor(); // Set dialog background color to gray + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(CMem2memDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CMem2memView)); + AddDocTemplate(pDocTemplate); + + // create a new (empty) document + OnFileNew(); + + if (m_lpCmdLine[0] != '\0') + { + // TODO: add command line processing here + } + + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + +// Implementation +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CMem2memApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CMem2memApp commands diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.H b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.H new file mode 100644 index 0000000..58899ff --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.H @@ -0,0 +1,42 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mem2mem.h : main header file for the MEM2MEM application +// + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CMem2memApp: +// See mem2mem.cpp for the implementation of this class +// + +class CMem2memApp : public CWinApp +{ +public: + CMem2memApp(); + +// Overrides + virtual BOOL InitInstance(); + +// Implementation + + //{{AFX_MSG(CMem2memApp) + afx_msg void OnAppAbout(); + // 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() +}; + + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.MAK b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.MAK new file mode 100644 index 0000000..8a78592 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.MAK @@ -0,0 +1,283 @@ +# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE No configuration specified. Defaulting to Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "MEM2MEM.MAK" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Win32 Debug" +MTL=MkTypLib.exe +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win32 Release" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : $(OUTDIR)/MEM2MEM.exe $(OUTDIR)/MEM2MEM.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE CPP /nologo /MD /W3 /GX /YX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /FR /c +# ADD CPP /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"STDAFX.H" /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"MEM2MEM.pch" /Yu"STDAFX.H" /Fo$(INTDIR)/ /c +CPP_OBJS=.\WinRel/ +# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"MEM2MEM.res" /d "NDEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"MEM2MEM.bsc" + +$(OUTDIR)/MEM2MEM.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 oldnames.lib pkwdcl.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /MACHINE:IX86 +# ADD LINK32 oldnames.lib implodei.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /MACHINE:IX86 +# SUBTRACT LINK32 /INCREMENTAL:yes +LINK32_FLAGS=oldnames.lib implodei.lib /NOLOGO /STACK:0x10240\ + /SUBSYSTEM:windows /INCREMENTAL:no /PDB:$(OUTDIR)/"MEM2MEM.pdb" /MACHINE:IX86\ + /OUT:$(OUTDIR)/"MEM2MEM.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/MEM2MEM.res \ + $(INTDIR)/STDAFX.OBJ \ + $(INTDIR)/MEM2MEM.OBJ \ + $(INTDIR)/MAINFRM.OBJ \ + $(INTDIR)/MEM2MDOC.OBJ \ + $(INTDIR)/MEM2MVW.OBJ \ + $(INTDIR)/DCL.OBJ + +$(OUTDIR)/MEM2MEM.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : $(OUTDIR)/MEM2MEM.exe $(OUTDIR)/MEM2MEM.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE CPP /nologo /MD /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /FR /c +# ADD CPP /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"STDAFX.H" /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"MEM2MEM.pch" /Yu"STDAFX.H" /Fo$(INTDIR)/\ + /Fd$(OUTDIR)/"MEM2MEM.pdb" /c +CPP_OBJS=.\WinDebug/ +# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"MEM2MEM.res" /d "_DEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"MEM2MEM.bsc" + +$(OUTDIR)/MEM2MEM.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 oldnames.lib pkwdcl.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /DEBUG /MACHINE:IX86 +# ADD LINK32 oldnames.lib implodei.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /INCREMENTAL:no /DEBUG /MACHINE:IX86 +LINK32_FLAGS=oldnames.lib implodei.lib /NOLOGO /STACK:0x10240\ + /SUBSYSTEM:windows /INCREMENTAL:no /PDB:$(OUTDIR)/"MEM2MEM.pdb" /DEBUG\ + /MACHINE:IX86 /OUT:$(OUTDIR)/"MEM2MEM.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/MEM2MEM.res \ + $(INTDIR)/STDAFX.OBJ \ + $(INTDIR)/MEM2MEM.OBJ \ + $(INTDIR)/MAINFRM.OBJ \ + $(INTDIR)/MEM2MDOC.OBJ \ + $(INTDIR)/MEM2MVW.OBJ \ + $(INTDIR)/DCL.OBJ + +$(OUTDIR)/MEM2MEM.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Group "Source Files" + +################################################################################ +# Begin Source File + +SOURCE=.\MEM2MEM.RC +DEP_MEM2M=\ + .\RES\MEM2MEM.ICO\ + .\RES\TOOLBAR.BMP\ + .\RESOURCE.H\ + .\RES\MEM2MEM.RC2 + +$(INTDIR)/MEM2MEM.res : $(SOURCE) $(DEP_MEM2M) $(INTDIR) + $(RSC) $(RSC_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STDAFX.CPP +DEP_STDAF=\ + .\STDAFX.H + +!IF "$(CFG)" == "Win32 Release" + +# ADD BASE CPP /Yc"STDAFX.H" +# ADD CPP /Yc"STDAFX.H" + +$(INTDIR)/STDAFX.OBJ : $(SOURCE) $(DEP_STDAF) $(INTDIR) + $(CPP) /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"MEM2MEM.pch" /Yc"STDAFX.H" /Fo$(INTDIR)/ /c\ + $(SOURCE) + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# ADD BASE CPP /Yc"STDAFX.H" +# ADD CPP /Yc"STDAFX.H" + +$(INTDIR)/STDAFX.OBJ : $(SOURCE) $(DEP_STDAF) $(INTDIR) + $(CPP) /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"MEM2MEM.pch" /Yc"STDAFX.H" /Fo$(INTDIR)/\ + /Fd$(OUTDIR)/"MEM2MEM.pdb" /c $(SOURCE) + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MEM2MEM.CPP +DEP_MEM2ME=\ + .\STDAFX.H\ + .\MEM2MEM.H\ + .\MAINFRM.H\ + .\MEM2MDOC.H\ + .\MEM2MVW.H\ + .\RESOURCE.H + +$(INTDIR)/MEM2MEM.OBJ : $(SOURCE) $(DEP_MEM2ME) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MAINFRM.CPP +DEP_MAINF=\ + .\STDAFX.H\ + .\MEM2MEM.H\ + .\MAINFRM.H\ + .\DCL.H\ + .\RESOURCE.H + +$(INTDIR)/MAINFRM.OBJ : $(SOURCE) $(DEP_MAINF) $(INTDIR) $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MEM2MDOC.CPP +DEP_MEM2MD=\ + .\STDAFX.H\ + .\MEM2MEM.H\ + .\MEM2MDOC.H\ + .\RESOURCE.H + +$(INTDIR)/MEM2MDOC.OBJ : $(SOURCE) $(DEP_MEM2MD) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MEM2MVW.CPP +DEP_MEM2MV=\ + .\STDAFX.H\ + .\MEM2MEM.H\ + .\MEM2MDOC.H\ + .\MEM2MVW.H\ + .\RESOURCE.H + +$(INTDIR)/MEM2MVW.OBJ : $(SOURCE) $(DEP_MEM2MV) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DCL.CPP +DEP_DCL_C=\ + .\STDAFX.H\ + .\PKWDCL.H + +$(INTDIR)/DCL.OBJ : $(SOURCE) $(DEP_DCL_C) $(INTDIR) $(INTDIR)/STDAFX.OBJ + +# End Source File +# End Group +# End Project +################################################################################ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.RC b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.RC new file mode 100644 index 0000000..d125235 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MEM.RC @@ -0,0 +1,209 @@ +//Microsoft App Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#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 + "#include ""res\\mem2mem.rc2"" // non-App Studio edited resources\r\n" + "\r\n" + "#include ""afxres.rc"" \011// Standard components\r\n" + "\0" +END + +///////////////////////////////////////////////////////////////////////////////////// +#endif // APSTUDIO_INVOKED + + +////////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +IDR_MAINFRAME ICON DISCARDABLE "RES\\MEM2MEM.ICO" + +////////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP MOVEABLE PURE "RES\\TOOLBAR.BMP" + +////////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Test", IDM_TEST + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&View" + BEGIN + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Help" + BEGIN + MENUITEM "&About Mem2mem...", ID_APP_ABOUT + END +END + + +////////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 34, 22, 217, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Mem2mem" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "Mem2mem Application Version 1.0",IDC_STATIC,40,10,119,8 + LTEXT "Copyright \251 1995",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,176,6,32,14,WS_GROUP +END + + +////////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + IDR_MAINFRAME "Mem2mem Windows Application\n\nMem2me Document\n\n\nMem2me.Document\nMem2me Document" +END + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + AFX_IDS_APP_TITLE "Mem2mem Windows Application" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_NEW "Create a new document" + ID_FILE_OPEN "Open an existing document" + ID_FILE_CLOSE "Close the active document" + ID_FILE_SAVE "Save the active document" + ID_FILE_SAVE_AS "Save the active document with a new name" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright" + ID_APP_EXIT "Quit the application; prompts to save documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_MRU_FILE1 "Open this document" + ID_FILE_MRU_FILE2 "Open this document" + ID_FILE_MRU_FILE3 "Open this document" + ID_FILE_MRU_FILE4 "Open this document" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane" + ID_PREV_PANE "Switch back to the previous window pane" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection" + ID_EDIT_CLEAR_ALL "Erase everything" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard" + ID_EDIT_FIND "Find the specified text" + ID_EDIT_PASTE "Insert Clipboard contents" + ID_EDIT_REPEAT "Repeat the last action" + ID_EDIT_REPLACE "Replace specific text with different text" + ID_EDIT_SELECT_ALL "Select the entire document" + ID_EDIT_UNDO "Undo the last action" + ID_EDIT_REDO "Redo the previously undone action" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar" + ID_VIEW_STATUS_BAR "Show or hide the status bar" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDM_TEST "Test compression to and from memory" +END + + +#ifndef APSTUDIO_INVOKED +//////////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "res\mem2mem.rc2" // non-App Studio edited resources + +#include "afxres.rc" // Standard components + +///////////////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MVW.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MVW.CPP new file mode 100644 index 0000000..22cf6a1 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MVW.CPP @@ -0,0 +1,80 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mem2mvw.cpp : implementation of the CMem2memView class +// + +#include "stdafx.h" +#include "mem2mem.h" + +#include "mem2mdoc.h" +#include "mem2mvw.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMem2memView + +IMPLEMENT_DYNCREATE(CMem2memView, CView) + +BEGIN_MESSAGE_MAP(CMem2memView, CView) + //{{AFX_MSG_MAP(CMem2memView) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMem2memView construction/destruction + +CMem2memView::CMem2memView() +{ + // TODO: add construction code here +} + +CMem2memView::~CMem2memView() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// CMem2memView drawing + +void CMem2memView::OnDraw(CDC* pDC) +{ + CMem2memDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + // TODO: add draw code for native data here +} + +///////////////////////////////////////////////////////////////////////////// +// CMem2memView diagnostics + +#ifdef _DEBUG +void CMem2memView::AssertValid() const +{ + CView::AssertValid(); +} + +void CMem2memView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CMem2memDoc* CMem2memView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMem2memDoc))); + return (CMem2memDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMem2memView message handlers diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MVW.H b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MVW.H new file mode 100644 index 0000000..402a082 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/MEM2MVW.H @@ -0,0 +1,51 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mem2mvw.h : interface of the CMem2memView class +// +///////////////////////////////////////////////////////////////////////////// + +class CMem2memView : public CView +{ +protected: // create from serialization only + CMem2memView(); + DECLARE_DYNCREATE(CMem2memView) + +// Attributes +public: + CMem2memDoc* GetDocument(); + +// Operations +public: + +// Implementation +public: + virtual ~CMem2memView(); + virtual void OnDraw(CDC* pDC); // overridden to draw this view +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CMem2memView) + // 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() +}; + +#ifndef _DEBUG // debug version in mem2mvw.cpp +inline CMem2memDoc* CMem2memView::GetDocument() + { return (CMem2memDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/MEM2MEM.ICO b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/MEM2MEM.ICO new file mode 100644 index 0000000..b718392 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/MEM2MEM.ICO differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/MEM2MEM.RC2 b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/MEM2MEM.RC2 new file mode 100644 index 0000000..a579bf3 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/MEM2MEM.RC2 @@ -0,0 +1,52 @@ +// +// MEM2MEM.RC2 - resources App Studio does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by App Studio +#endif //APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// Version stamp for this .EXE + +#include "ver.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG|VS_FF_PRIVATEBUILD|VS_FF_PRERELEASE +#else + FILEFLAGS 0 // final version +#endif + FILEOS VOS_DOS_WINDOWS16 + FILETYPE VFT_APP + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "MEM2MEM MFC Application\0" + VALUE "FileVersion", "1.0.001\0" + VALUE "InternalName", "MEM2MEM\0" + VALUE "LegalCopyright", "\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename","MEM2MEM.EXE\0" + VALUE "ProductName", "MEM2MEM\0" + VALUE "ProductVersion", "1.0.001\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + // English language (0x409) and the Windows ANSI codepage (1252) + END +END + +///////////////////////////////////////////////////////////////////////////// +// Add additional manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/TOOLBAR.BMP b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/TOOLBAR.BMP new file mode 100644 index 0000000..49695e2 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RES/TOOLBAR.BMP differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RESOURCE.H b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RESOURCE.H new file mode 100644 index 0000000..45c5b88 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/RESOURCE.H @@ -0,0 +1,27 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +//{{NO_DEPENDENCIES}} +// App Studio generated include file. +// Used by MEM2MEM.RC +// +#define IDR_MAINFRAME 2 +#define IDD_ABOUTBOX 100 +#define IDM_TEST 32771 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 32772 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/STDAFX.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/STDAFX.CPP new file mode 100644 index 0000000..07f7b46 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/STDAFX.CPP @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// stdafx.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/STDAFX.H b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/STDAFX.H new file mode 100644 index 0000000..6179a32 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MEM2MEM/STDAFX.H @@ -0,0 +1,7 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#include // MFC core and standard components +#include // MFC extensions (including VB) diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/DCL.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/DCL.CPP new file mode 100644 index 0000000..dc292aa --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/DCL.CPP @@ -0,0 +1,705 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +/* + * DCL.cpp - File to call various DCL DLL functions + */ + +#include "stdafx.h" + +#include +#include +#include + +#include "implode.h" + +#define TEMPFILENAME "~~~.$$$" // TEMPORARY FILENAME TO CREATE +#define APPENDBUFSIZE 32000 // SIZE OF BUFFER TO ALLOCATE FOR APPENDING + // A COMPRESSED FILE TO .MCF FILE + +typedef enum +{ + COMPRESSING = 1, + UNCOMPRESSING +} FILEMODE; + + +// STRUCT TO PASS TO THE FILE IO FUNCTIONS +typedef struct +{ + CFile *InFile; + CFile *OutFile; + CDC *pDC; + BYTE nPrevNdx; + BYTE nCnt; + DWORD dwCompressSize; + FILEMODE mode; + DWORD dwCrc; +}IOFILEBLOCK, *PIOFILEBLOCK; + +// FOUR LETTER IDENTIFIER TO IDENTIFY A FILE AS +// A .MCF (MULTIPLE COMPRESSED FILES) FILE +char MCF_FILEHEADER[] = { "MCFX" }; + +#pragma pack(2) + +// HEADER FOR EACH FILE COMPRESSED INTO THE .MCF FILE +typedef struct +{ + DWORD dwCompressSize; // SIZE OF FILE COMPRESSED + DWORD dwCrc; // THE CRC OF THE FILE BEFORE COMPRESSION + char filename[13]; // NAME OF THE FILE +}CMP_FILEHEADER, *PCMP_FILEHEADER; + +#pragma pack(8) + +/* + * FORMAT OF .MCF FILE: + * + * .MCF FILEHEADER => MCFX + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * AND SO ON + * + */ + +static char *pszActiveString[] = { "|", "/", "-", "\\" }; + +UINT DataType = CMP_ASCII; // GLOBAL FOR DATA TYPE FOR COMPRESSION +UINT DictSize = 4096; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + + +/********************************************************************* + * + * Function: ProcessMessages() + * + * Purpose: To allow Windows to process window messages which + * allows the user to multitask will compressing and + * uncompressing files. + * + * Returns: Nothing + * + *********************************************************************/ +void ProcessMessages(void) +{ + MSG msg; + + while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) + { + if (msg.message == WM_QUIT) + return; + + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +/********************************************************************* + * + * Function: ProcessInBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * read requests. If compressing, then the data read is + * in uncompressed form. If compressing, then the data + * read is data that was previously compressed. This + * function is called until zero is returned. + * + * Parameters: buffer -> Address of buffer to read the data into + * iSize -> Number of bytes to read into buffer + * dwParam -> User-defined parameter, in this case a + * pointer to the IOFILEBLOCK + * + * Returns: Number of bytes actually read, or zero on EOF + * + *********************************************************************/ +UINT ProcessInBuffer( PCHAR buffer, UINT *iSize, void *pParam) +{ + PIOFILEBLOCK pFileIOBlock; + UINT iRead; + UINT ndx; + + pFileIOBlock = (PIOFILEBLOCK) pParam; + + // DISPLAY ROTATING LINE + ndx = (pFileIOBlock->nCnt >> 4) & 3; + if( ndx != pFileIOBlock->nPrevNdx ) + { + pFileIOBlock->pDC->TextOut( 10,2, pszActiveString[ndx] ); + pFileIOBlock->nPrevNdx = ndx; + } + pFileIOBlock->nCnt++; + + // THIS FUNCTION MAY ASK FOR UP TO 4K OF DATA AT A TIME. IF YOUR + // ARCHIVE FILE CONTAINS SEVERAL COMPRESSED FILES, YOU MAY READ TOO + // MUCH. FOR EXAMPLE, YOUR FIRST COMPRESSED FILE IN THE ARCHIVE MAY + // BE 100 BYTES. SO YOU DO NOT WANT TO READ MORE THAN 100 BYTES OR + // YOU WILL BE UNABLE TO UNCOMPRESS THE SECOND FILE, SINCE YOU WILL + // NOT BE LOCATED AT THE BEGINNING OF THE FILE ANY LONGER. + // WE WILL USE THE VARIABLE "dwCompressSize" TO CHECK FOR THIS + // CONDITION. + if( pFileIOBlock->mode == UNCOMPRESSING ) + { + // IF DCL REQUESTED MORE BYTES THAN ARE LEFT IN COMPRESSED FILE, THEN + // SET THE NUMBER OF BYTES TO READ TO THE AMOUNT LEFT IN THE BUFFER + if( (DWORD) *iSize > pFileIOBlock->dwCompressSize ) + *iSize = (UINT) pFileIOBlock->dwCompressSize; + + pFileIOBlock->dwCompressSize -= (DWORD) *iSize; + } + + // READ BUFFER FROM DISK + iRead = (UINT)pFileIOBlock->InFile->Read( buffer, *iSize ); + + // IF COMPRESSING, THEN CALCULATE THE CRC + if( pFileIOBlock->mode == COMPRESSING ) + { + pFileIOBlock->dwCrc = crc32( buffer, &iRead, &pFileIOBlock->dwCrc ); + } + + // ENTER MESSAGE LOOP TO PROCESS BACKGROUND MESSAGES + // AND SIMULATE MULTITASKING + ProcessMessages(); + + return iRead; +} + +/********************************************************************* + * + * Function: ProcessOutBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * write requests. + * + * Parameters: buffer -> Address of buffer to write data from + * iSize -> Number of bytes to write + * dwParam -> User-defined parameter, in this case a + * pointer to the IOFILEBLOCK + * + * Returns: Zero, the return value is not used by the Data + * Compression Library + * + *********************************************************************/ +void ProcessOutBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + PIOFILEBLOCK pFileIOBlock; + UINT ndx; + + pFileIOBlock = (PIOFILEBLOCK) pParam; + + // DISPLAY ROTATING LINE PACIFIER + ndx = (pFileIOBlock->nCnt >> 4) & 3; + if( ndx != pFileIOBlock->nPrevNdx ) + { + pFileIOBlock->pDC->TextOut( 10,2, pszActiveString[ndx] ); + pFileIOBlock->nPrevNdx = ndx; + } + pFileIOBlock->nCnt++; + + // WRITE BUFFER TO DISK + pFileIOBlock->OutFile->Write(buffer, *iSize); + + // IF COMPRESSING, THEN KEEP A TOTAL OF THE COMPRESSED FILE SIZE + if (pFileIOBlock->mode == COMPRESSING ) + { + pFileIOBlock->dwCompressSize += (DWORD) *iSize; + } + else // ELSE UNCOMPRESSING, SO CALCULATE CRC ON THE UNCOMPRESSED DATA + { + pFileIOBlock->dwCrc = crc32(buffer, iSize, &pFileIOBlock->dwCrc); + } + + // ENTER MESSAGE LOOP TO PROCESS BACKGROUND MESSAGES + // AND SIMULATE MULTITASKING + ProcessMessages(); + + return; +} + +/********************************************************************* + * + * Function: CompressFile() + * + * Purpose: To compress file to a separate temporary file. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * pdwCompFileSize -> Pointer to DWORD buffer to return + * the size of the compressed file + * pszFileToCompress -> Name of file to compress + * OutputFile -> Name of file to write compressed data to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressFile( HWND hWnd, CDC *pDC, DWORD *pdwCrc, + DWORD *pdwCompFileSize, PCHAR pszFileToCompress, + PCHAR OutputFile ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + IOFILEBLOCK FileIOBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + // OPEN THE INPUT AND OUTPUT FILES + FileIOBlock.InFile = new CFile; + FileIOBlock.OutFile = new CFile; + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + FileIOBlock.mode = COMPRESSING; + FileIOBlock.dwCompressSize = 0; + FileIOBlock.pDC = pDC; + FileIOBlock.nCnt = 0; + FileIOBlock.nPrevNdx = 0; + FileIOBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + pDC->TextOut( 10,2, " " ); + + // OPEN THE FILES + if (FileIOBlock.InFile->Open( pszFileToCompress, CFile::modeRead | CFile::shareExclusive | CFile::typeBinary) && + FileIOBlock.OutFile->Open( OutputFile, CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary)) + { + wsprintf( szVerbose, "Compressing file: %s ", pszFileToCompress ); + pDC->TextOut( 10,40, szVerbose ); + + // ONLY COMPRESS IF FILE IS NOT A ZERO LENGTH FILE + if( FileIOBlock.InFile->GetLength() ) + { + // COMPRESS THE FILE + iStatus = implode( ProcessInBuffer, ProcessOutBuffer, pScratchPad, + &FileIOBlock, &DataType, &DictSize ); + } + else + { + // SINCE THIS IS A ZERO LENGTH FILE, THERE IS NOTHING TO COMPRESS + // SET STATUS TO NO ERROR + iStatus = 0; + } + + // IF THERE WAS AN ERROR COMPRESSING FILE + if( iStatus ) + { + // DISPLAY ERROR STRING FROM DLL + wsprintf( szVerbose, "Error occurred while imploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else // ELSE - COMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + FileIOBlock.dwCrc = ~FileIOBlock.dwCrc; + + // RETURN CRC + *pdwCrc = FileIOBlock.dwCrc; + + // RETURN COMPRESSED FILE SIZE + *pdwCompFileSize = FileIOBlock.dwCompressSize; + } + + FileIOBlock.OutFile->Close(); + FileIOBlock.InFile->Close(); + } + else // ELSE - ERROR OPENING FILES + { + MessageBox( hWnd, "Error opening files for compression", "Error", MB_OK ); + rc = 0; + } + + // CLEAN-UP + delete FileIOBlock.InFile; + delete FileIOBlock.OutFile; + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: ExpandFile() + * + * Purpose: To uncompress file from a .MCF file. The .MCF file will + * have been read upto the compressed data stream. + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * dwCompFileSize -> Size of the compressed file + * pMcfFile -> Pointer to already opened .MCF file + * OutputFile -> Name of file to write uncompressed data to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int ExpandFile( HWND hWnd, CDC *pDC, DWORD *pdwCrc, + DWORD dwCompFileSize, CFile *pMcfFile, PCHAR OutputFile ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + IOFILEBLOCK FileIOBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + FileIOBlock.InFile = pMcfFile; + FileIOBlock.OutFile = new CFile; + + // SETUP STRUCTURE USED BY ProcessReadBuffer() and ProcessWriteBuffer() + FileIOBlock.mode = UNCOMPRESSING; + FileIOBlock.dwCompressSize = dwCompFileSize; + FileIOBlock.pDC = pDC; + FileIOBlock.nCnt = 0; + FileIOBlock.nPrevNdx = 0; + FileIOBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + pDC->TextOut( 10,2, " " ); + + if( FileIOBlock.OutFile->Open(OutputFile, CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary) ) + { + // ONLY UNCOMPRESS IF FILE IS NOT A ZERO LENGTH FILE + if( FileIOBlock.dwCompressSize ) + { + iStatus = explode( ProcessInBuffer, ProcessOutBuffer, pScratchPad, &FileIOBlock ); + } + else + { + // SINCE THIS IS A ZERO LENGTH FILE, THERE IS NOTHING TO UNCOMPRESS + // SET STATUS TO NO ERROR + iStatus = 0; + } + + if( iStatus ) + { + wsprintf( szVerbose, "Error occurred while exploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else + { + FileIOBlock.dwCrc = ~FileIOBlock.dwCrc; + *pdwCrc = FileIOBlock.dwCrc; + + if( FileIOBlock.dwCompressSize != 0 ) + { + wsprintf( szVerbose, "Error uncompressing file: %s", OutputFile ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + } + + FileIOBlock.OutFile->Close(); + } + else + { + MessageBox( hWnd, "Error opening files for uncompression", "Error", MB_OK ); + rc = 0; + } + + delete FileIOBlock.OutFile; + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: AddFileToMcfFile() + * + * Purpose: To add a compressed file with header to a .MCF file. + * The file header is written followed by the compressed + * file data + * + * Parameters: pFileHeader -> File header for the compressed file + * pszInput -> Filename of the compressed file's data + * pszOutput -> Filename of .MCF file + * CompressedFileSize -> Size of the compressed file + * NewMcfFile -> Flag used to create a new .MCF file + * TRUE - A new .MCF file will be created + * FALSE - The .MCF file will appended to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int AddFileToMcfFile( PCMP_FILEHEADER pFileHeader, PCHAR pszInput, + PCHAR pszOutput, DWORD CompressedFileSize, + BOOL NewMcfFile ) +{ + PCHAR buf; + UINT read; + CFile InFile; + CFile OutFile; + + // ALLOCATE I/O BUFFER + if( (buf = new char[APPENDBUFSIZE]) == NULL ) + { + return 0; + } + + TRY + { + // OPEN THE FILES + InFile.Open( pszInput, CFile::modeRead | CFile::shareExclusive | CFile::typeBinary); + + // IF NEW FILE, THEN CREATE MULTIPLE COMPRESSED FILES FILE + if( NewMcfFile ) + { + // CREATE NEW .MCF FILE + OutFile.Open( pszOutput, CFile::modeCreate | CFile::modeWrite | CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary); + + // WRITE .MCF FILE HEADER + OutFile.Write( MCF_FILEHEADER, 4 ); + } + else + { + // OPEN OLD .MCF FILE + OutFile.Open( pszOutput, CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary); + + // GO TO END OF FILE + OutFile.SeekToEnd(); + } + + // WRITE THE COMPRESSED FILE'S FILEHEADER + OutFile.Write( pFileHeader, sizeof(CMP_FILEHEADER) ); + + do + { + // READ FROM COMPRESSED FILE + read = InFile.Read( buf, APPENDBUFSIZE ); + + // WRITE DATA TO .MCF FILE + OutFile.Write( buf, read ); + + // IF ERROR OCCURRED + if( CompressedFileSize < (DWORD) read ) + { + delete buf; + return 0; + } + + CompressedFileSize -= (DWORD) read; + } + while( CompressedFileSize > 0 ); + } + CATCH( CFileException, theException ) + { + // IF ERROR OCCURRED WHILE APPENDING FILE + if( theException->m_cause != CFileException::none ) + { + delete buf; + return 0; + } + } + END_CATCH + + delete buf; + + return 1; +} + +/********************************************************************* + * + * Function: CompressFileToMCF() + * + * Purpose: To compress a file then add it to a .MCF file + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszMcfFile -> Filename of .MCF file + * pszFileToCompress -> Filename of file with full path + * pszFilenameOnly -> Filename of file without any path + * This is the filename that is stored + * in the compressed file's file header + * NewMcfFile -> Flag used to create a new .MCF file + * TRUE - A new .MCF file will be created + * FALSE - The .MCF file will appended to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressFileToMCF( HWND hWnd, CDC *pDC, + PCHAR pszMcfFile, PCHAR pszFileToCompress, + PCHAR pszFilenameOnly, BOOL NewMcfFile ) +{ + ASSERT( hWnd ); + ASSERT_VALID( pDC ); + + CMP_FILEHEADER FileHeader; + + memset( &FileHeader, 0, sizeof(FileHeader) ); + + // ATTEMPT TO COMPRESS THE FILE + if( !CompressFile( hWnd, pDC, &FileHeader.dwCrc, + &FileHeader.dwCompressSize, pszFileToCompress, + TEMPFILENAME ) ) + { + remove( TEMPFILENAME ); + MessageBox( hWnd, "Compress File Failed", "Error", MB_OK ); + return 0; + } + + strcpy( FileHeader.filename, pszFilenameOnly ); + + if( !AddFileToMcfFile( &FileHeader, TEMPFILENAME, pszMcfFile, + FileHeader.dwCompressSize, NewMcfFile ) ) + { + remove( TEMPFILENAME ); + MessageBox( hWnd, "Compress File Failed", "Error", MB_OK ); + return 0; + } + + remove( TEMPFILENAME ); + + return 1; +} + +/********************************************************************* + * + * Function: UncompressFileToMCF() + * + * Purpose: To uncompress a .MCF file + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszMcfFilename -> Filename of .MCF file + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int UncompressMcfFile( HWND hWnd, CDC *pDC, PCHAR pszMcfFilename ) +{ + ASSERT( hWnd ); + ASSERT_VALID( pDC ); + + CMP_FILEHEADER FileHeader; + char szSaveDir[80]; + char McfFileheader[5]; + char szOutMsg[128]; + char szOutputFilename[100]; + UINT nNumFiles = 0; + PCHAR pszTemp; + DWORD dwCrc; // CRC OF FILE BEFORE COMPRESSION + UINT read; + CFile McfFile; + + // MAKE A COPY OF BUFFER SO THAT IT CAN BE MODIFIED + strcpy( szSaveDir, pszMcfFilename ); + + // SET BUFFER WITH NAME OF FILE WITHOUT A PATH OR EXTENSION + if( !(pszTemp = (PCHAR) strrchr( szSaveDir, '\\' )) ) + { + MessageBox( hWnd, "Error getting directory name", "Error", MB_OK ); + return 0; + } + + // POINT TO FIRST CHAR AFTER BACKSLASH + *(++pszTemp) = '\0'; + + TRY + { + // OPEN THE FILES + McfFile.Open( pszMcfFilename, CFile::modeRead | CFile::shareExclusive | CFile::typeBinary); + + memset( McfFileheader, 0, sizeof(McfFileheader) ); + + // MAKE SURE FILE IS A MULTIPLE COMPRESSED FILE + if( (McfFile.Read( McfFileheader, 4 ) != 4) || + (strcmp( McfFileheader, MCF_FILEHEADER ) != 0) ) + { + MessageBox( hWnd, "Invalid file format", "Error", MB_OK ); + return 0; + } + + do + { + // READ COMPRESSED FILE FILEHEADER + read = McfFile.Read( &FileHeader, sizeof(FileHeader) ); + + // IF SUCCESSFULLY READ COMPRESSED FILE FILEHEADER + if( read == sizeof(FileHeader) ) + { + // CREATE OUTPUT FILENAME + strcpy( szOutputFilename, szSaveDir ); + strcat( szOutputFilename, FileHeader.filename ); + + wsprintf( szOutMsg, "Uncompressing file: %s ", FileHeader.filename ); + pDC->TextOut( 10,60, szOutMsg ); + + // ATTEMPT TO EXPAND THE FILE + if( !ExpandFile( hWnd, pDC, &dwCrc, FileHeader.dwCompressSize, + &McfFile, szOutputFilename ) ) + { + wsprintf( szOutMsg, "Error Uncompressing file: %s", + szOutputFilename ); + MessageBox( hWnd, szOutMsg, "Error", MB_OK ); + return 0; + } + + // CHECK THE CRC OF THE FILE + if( dwCrc != FileHeader.dwCrc ) + { + wsprintf( szOutMsg, "There is an error in the CRC of %s", + szOutputFilename ); + MessageBox( hWnd, szOutMsg, "Error", MB_OK ); + } + + nNumFiles++; + } + } + while( read == sizeof(FileHeader) ); + + if( read != 0 ) + { + MessageBox( hWnd, "Invalid file format", "Error", MB_OK ); + return 0; + } + else + { + wsprintf( szOutMsg, "Uncompressed %u file(s)", nNumFiles ); + MessageBox( hWnd, szOutMsg, "MultFile", MB_OK ); + } + } + CATCH( CFileException, theException ) + { + if( theException->m_cause != CFileException::none ) + { + MessageBox( hWnd, "File Error", "Error", MB_OK ); + return 0; + } + } + END_CATCH + + return 1; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/DCL.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/DCL.H new file mode 100644 index 0000000..087d28b --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/DCL.H @@ -0,0 +1,13 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +int CompressFileToMCF( HWND hWnd, CDC *pDC, + LPSTR lpszMcfFile, LPSTR lpszFileToCompress, + LPSTR lpszFilenameOnly, BOOL NewMcfFile ); +int UncompressMcfFile( HWND hWnd, CDC *pDC, LPSTR lpszMcfFile ); diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/IMPLODEI.LIB b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/IMPLODEI.LIB new file mode 100644 index 0000000..ca0b4df Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/IMPLODEI.LIB differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MAINFRM.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MAINFRM.CPP new file mode 100644 index 0000000..547fe5d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MAINFRM.CPP @@ -0,0 +1,421 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +// mainfrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include +#include "multfile.h" + +#include "mainfrm.h" +#include "dcl.h" +#include "multfdlg.h" +#include "implode.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +extern UINT DataType; // GLOBAL FOR DATA TYPE FOR COMPRESSION +extern UINT DictSize; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CREATE() + ON_WM_QUERYENDSESSION() + ON_WM_CLOSE() + ON_COMMAND(IDM_COMPRESS_FILES, OnCompressFiles) + ON_COMMAND(IDM_UNCOMPRESS_FILES, OnUncompressFiles) + ON_UPDATE_COMMAND_UI(IDM_COMPRESS_FILES, OnUpdateCompressFiles) + ON_UPDATE_COMMAND_UI(IDM_UNCOMPRESS_FILES, OnUpdateUncompressFiles) + ON_COMMAND(IDM_CMP_ASCII, OnCmpAscii) + ON_COMMAND(IDM_CMP_BINARY, OnCmpBinary) + ON_COMMAND(IDM_DICT_SIZE_1024, OnDictSize1024) + ON_COMMAND(IDM_DICT_SIZE_2048, OnDictSize2048) + ON_COMMAND(IDM_DICT_SIZE_4096, OnDictSize4096) + ON_UPDATE_COMMAND_UI(IDM_CMP_ASCII, OnUpdateCmpAscii) + ON_UPDATE_COMMAND_UI(IDM_CMP_BINARY, OnUpdateCmpBinary) + ON_UPDATE_COMMAND_UI(IDM_DICT_SIZE_1024, OnUpdateDictSize1024) + ON_UPDATE_COMMAND_UI(IDM_DICT_SIZE_2048, OnUpdateDictSize2048) + ON_UPDATE_COMMAND_UI(IDM_DICT_SIZE_4096, OnUpdateDictSize4096) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// arrays of IDs used to initialize control bars + +// toolbar buttons - IDs are command buttons +static UINT BASED_CODE buttons[] = +{ + // same order as in the bitmap 'toolbar.bmp' + ID_FILE_NEW, + ID_FILE_OPEN, + ID_FILE_SAVE, + ID_SEPARATOR, + ID_EDIT_CUT, + ID_EDIT_COPY, + ID_EDIT_PASTE, + ID_SEPARATOR, + ID_FILE_PRINT, + ID_APP_ABOUT, +}; + +static UINT BASED_CODE indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here +} + +CMainFrame::~CMainFrame() +{ +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE("Failed to create status bar\n"); + return -1; // fail to create + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + +void CMainFrame::OnCompressFiles() +{ + int rc; + HWND hWnd; + + // GET HANDLE TO WINDOW AND INSTANCE HANDLE + hWnd = CWnd::GetSafeHwnd(); + + // TURN OFF HELP MESSAGE SCREEN AND CLEAR SCREEN + SendMessageToDescendants( WM_TURN_OFF_HELP ); + + // CREATE FILE DIALOG THAT CAN USE CAN SELECT MULTIPLE FILES + CMultiSelFileDialog *FileDlg = new CMultiSelFileDialog( this ); + + // IF USER PRESSED OK BUTTON + if( (rc = FileDlg->DoModal()) == IDOK ) + { + // CREATE SAVE AS FILE DIALOG + CFileDialog SaveFileDlg( FALSE, "MCF", "*.MCF", + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, + "Mult. Compressed Files (*.MCF) |*.MCF ||", this ); + + // GET FILENAME OF FILE TO PUT COMPRESSED FILES IN + if( (SaveFileDlg.DoModal()) == IDOK ) + { + BOOL GotFilenameOk, + bError = FALSE, + CreateMcfFile; + UINT nNumCmpFiles = 0; + char szFilename[13]; // BUFFER FOR FILENAME ONLY + char szFullPathname[128]; // BUFFER FOR FULL PATH FOR FILE + char szOutBuff[64]; // TEMP OUTPUT BUFFER + + // SET FLAG TO PREVENT EXITING IN THE MIDDLE OF THE COMPRESSION + ((CMultfileApp *) AfxGetApp())->OkToExit = FALSE; + + // GET DC AND SET THE TEXT BACKGROUND COLOR TO WINDOW BACKGROUND COLOR + CClientDC dc(this); + COLORREF bkGroundColor = dc.GetPixel( 0, 0 ); + dc.SetBkColor( bkGroundColor ); + + wsprintf( szOutBuff, "Compressing to: %s ", + (LPSTR) (const char *) SaveFileDlg.GetPathName() ); + dc.TextOut( 10,20, szOutBuff ); + + // SET CREATE .MCF FILE FLAG TO TRUE, SO THAT THE FIRST TIME + // CompressFileToMCF IS CALLED THE .MCF WILL BE CREATED INSTEAD + // OF APPENDED TO + CreateMcfFile = TRUE; + + // GET THE FIRST FILENAME IN THE LIST + GotFilenameOk = FileDlg->GetFirstFilename( szFullPathname, + sizeof(szFullPathname), + szFilename ); + // WHILE GOT A FILENAME FROM THE LIST + while( GotFilenameOk ) + { + // COMPRESS THE FILE AND ADD IT TO THE .MCF FILE + if( !CompressFileToMCF( hWnd, &dc, + (LPSTR) (const char *) SaveFileDlg.GetPathName(), + szFullPathname, szFilename, CreateMcfFile ) ) + { + // ERROR OCCURRED SO DELETE THE .MCF FILE + remove( (const char *) SaveFileDlg.GetPathName() ); + bError = TRUE; + break; + } + // INCREMENT TOTAL + nNumCmpFiles++; + + // RESET .MCF FILE FLAG SO THAT .MCF FILE WILL NOT BE CREATED + CreateMcfFile = FALSE; + + // GET THE FIRST FILENAME IN THE LIST + GotFilenameOk = FileDlg->GetNextFilename( szFullPathname, + sizeof(szFullPathname), + szFilename ); + } + + // IF THERE WAS NOT ERROR, THEN DISPLAY MESSAGE + if( !bError ) + { + wsprintf( szOutBuff, "Compressed %u file(s)", nNumCmpFiles ); + MessageBox( szOutBuff ); + } + + // DONE WITH COMPRESION SO ALLOW THE USER TO EXIT + ((CMultfileApp *) AfxGetApp())->OkToExit = TRUE; + } + } + + // CLEAN-UP + delete FileDlg; + + // TURN ON HELP MESSAGE AND CLEAR SCREEN + SendMessageToDescendants( WM_TURN_ON_HELP ); +} + +void CMainFrame::OnUncompressFiles() +{ + HWND hWnd; + + hWnd = CWnd::GetSafeHwnd(); + + // TURN OFF HELP MESSAGE AND CLEAR SCREEN + SendMessageToDescendants( WM_TURN_OFF_HELP ); + + // OPENFILENAME + CFileDialog OpenFileDlg( TRUE, "MCF", "*.MCF", + OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + "Mult. Compressed Files (*.MCF) |*.MCF ||", this ); + + // GET FILENAME OF FILE TO PUT COMPRESSED FILES IN + if( (OpenFileDlg.DoModal()) == IDOK ) + { + char szOutBuff[64]; // TEMP OUTPUT BUFFER + + // SET FLAG TO PREVENT EXITING IN THE MIDDLE OF THE UNCOMPRESSION + ((CMultfileApp *) AfxGetApp())->OkToExit = FALSE; + + // GET DC AND SET THE TEXT BACKGROUND COLOR TO WINDOW BACKGROUND COLOR + CClientDC dc(this); + COLORREF bkGroundColor = dc.GetPixel( 0, 0 ); + dc.SetBkColor( bkGroundColor ); + + wsprintf( szOutBuff, "Uncompressing: %s ", + (LPSTR) (const char *) OpenFileDlg.GetPathName() ); + dc.TextOut( 10,20, szOutBuff ); + + // UNCOMPRESS THE FILE + UncompressMcfFile( hWnd, &dc, (LPSTR) (const char *) OpenFileDlg.GetPathName() ); + + // DONE WITH UNCOMPRESION SO ALLOW THE USER TO EXIT + ((CMultfileApp *) AfxGetApp())->OkToExit = TRUE; + } + + // TURN ON HELP MESSAGE AND CLEAR SCREEN + SendMessageToDescendants( WM_TURN_ON_HELP ); +} + +BOOL CMainFrame::OnQueryEndSession() +{ + if (!CFrameWnd::OnQueryEndSession()) + return FALSE; + + // RETURN FALSE IF CANNOT EXIT RIGHT NOW + if( !((CMultfileApp *) AfxGetApp())->OkToExit ) + return FALSE; + + return TRUE; +} + +void CMainFrame::OnClose() +{ + // RETURN IF CANNOT EXIT RIGHT NOW + if( !((CMultfileApp *) AfxGetApp())->OkToExit ) + return; + + CFrameWnd::OnClose(); +} + +void CMainFrame::OnUpdateCompressFiles(CCmdUI* pCmdUI) +{ + pCmdUI->Enable( ((CMultfileApp *) AfxGetApp())->OkToExit ); +} + +void CMainFrame::OnUpdateUncompressFiles(CCmdUI* pCmdUI) +{ + pCmdUI->Enable( ((CMultfileApp *) AfxGetApp())->OkToExit ); +} + + +void CMainFrame::OnCmpAscii() +{ + DataType = CMP_ASCII; +} + +void CMainFrame::OnCmpBinary() +{ + DataType = CMP_BINARY; +} + +void CMainFrame::OnDictSize1024() +{ + DictSize = 1024; +} + +void CMainFrame::OnDictSize2048() +{ + DictSize = 2048; +} + +void CMainFrame::OnDictSize4096() +{ + DictSize = 4096; +} + +void CMainFrame::OnUpdateCmpAscii(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CMultfileApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DataType == CMP_ASCII ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + +void CMainFrame::OnUpdateCmpBinary(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CMultfileApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DataType == CMP_BINARY ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + +void CMainFrame::OnUpdateDictSize1024(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CMultfileApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DictSize == 1024 ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + +void CMainFrame::OnUpdateDictSize2048(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CMultfileApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DictSize == 2048 ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + +void CMainFrame::OnUpdateDictSize4096(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CMultfileApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DictSize == 4096 ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MAINFRM.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MAINFRM.H new file mode 100644 index 0000000..297fb13 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MAINFRM.H @@ -0,0 +1,61 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mainfrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +class CMainFrame : public CFrameWnd +{ +protected: // create from serialization only + CMainFrame(); + DECLARE_DYNCREATE(CMainFrame) + +// Attributes +public: + +// Operations +public: + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnCompressFiles(); + afx_msg void OnUncompressFiles(); + afx_msg BOOL OnQueryEndSession(); + afx_msg void OnClose(); + afx_msg void OnUpdateCompressFiles(CCmdUI* pCmdUI); + afx_msg void OnUpdateUncompressFiles(CCmdUI* pCmdUI); + afx_msg void OnCmpAscii(); + afx_msg void OnCmpBinary(); + afx_msg void OnDictSize1024(); + afx_msg void OnDictSize2048(); + afx_msg void OnDictSize4096(); + afx_msg void OnUpdateCmpAscii(CCmdUI* pCmdUI); + afx_msg void OnUpdateCmpBinary(CCmdUI* pCmdUI); + afx_msg void OnUpdateDictSize1024(CCmdUI* pCmdUI); + afx_msg void OnUpdateDictSize2048(CCmdUI* pCmdUI); + afx_msg void OnUpdateDictSize4096(CCmdUI* pCmdUI); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDLG.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDLG.CPP new file mode 100644 index 0000000..aff5eb3 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDLG.CPP @@ -0,0 +1,158 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include "stdafx.h" +#include + +#include "multfdlg.h" + +#define FILELIST_BUFFSIZE 4096 // AMOUNT OF MEMORY TO ALLOCATE FOR FILE LIST + + +CMultiSelFileDialog::CMultiSelFileDialog( CWnd *pParentWnd ) + :CFileDialog( TRUE, NULL, "*.*", + OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_NOCHANGEDIR, + "All Files (*.*) |*.* ||", pParentWnd ) +{ + // ALLOCATE MEMORY FOR FILE LIST + pszFileList = (PCHAR) new char[FILELIST_BUFFSIZE]; + + // SET ALLOCATED BUFFER AS FILENAME BUFER IN OPENFILENAME STRUCT + // AND REPLACE IT IN THE OPENFILENAME STRUCT + pszOldPtr = m_ofn.lpstrFile; + m_ofn.lpstrFile = pszFileList; + m_ofn.nMaxFile = FILELIST_BUFFSIZE; + + // DO SOME INITIALIZATION + memset( pszFileList, 0, FILELIST_BUFFSIZE ); + strcpy( pszFileList, "*.*" ); + memset( szPath, 0, sizeof(szPath) ); + nPathLen = 0; + Done = TRUE; +} + + +CMultiSelFileDialog::~CMultiSelFileDialog() +{ + // REPLACE OLD POINTER AND FREE MEMORY + m_ofn.lpstrFile = pszOldPtr; + delete pszFileList; +} + + +BOOL CMultiSelFileDialog::GetFirstFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ) +{ + PCHAR pszToken; + + nPathLen = 0; + Done = FALSE; + + // GET THE FIRST TOKEN WHICH SHOULD BE THE PATH + if( strchr( pszFileList, ' ' ) == NULL ) + { + // COULD NOT FIND TOKEN SO MUST BE PATH AND FILENAME + + Done = TRUE; + + memset( szPath, 0, sizeof(szPath) ); + nPathLen = 0; + + // MAKE SURE THE FILENAME + PATH WILL FIT + if( strlen( pszFileList ) > nPathBuffSize ) + { + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // CREATE FILENAME ONLY + strcpy( pszFilenameBuff, GetFileName() ); + strcat( pszFilenameBuff, "." ); + strcat( pszFilenameBuff, GetFileExt() ); + + // COPY PATH AND FILENAME TO BUFFER + strcpy( pszFullPathBuff, pszFileList ); + + return TRUE; + } + + // GET THE FIRST TOKEN WHICH SHOULD BE THE PATH + if( (pszToken = strtok( pszFileList, " " )) == NULL ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + memset( szPath, 0, sizeof(szPath) ); + strcpy( szPath, pszToken ); + strcat( szPath, "\\" ); + + nPathLen = strlen( szPath ); + + return GetNextFilename( pszFullPathBuff, nPathBuffSize, pszFilenameBuff ); +} + + +// pszFilenameBuff MUST BE AT LEAST 13 BYTES +BOOL CMultiSelFileDialog::GetNextFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ) +{ + PCHAR pszToken; + + if( Done ) + { + return FALSE; + } + + // GET THE NEXT TOKEN WHICH SHOULD BE A FILENAME + if( (pszToken = strtok( NULL, " " )) == NULL ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // MAKE SURE THE FILENAME + PATH WILL FIT + if( (strlen( pszToken ) + nPathLen) > nPathBuffSize ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // COPY PATH AND FILENAME TO BUFFER + strcpy( pszFullPathBuff, szPath ); + strcat( pszFullPathBuff, pszToken ); + + PCHAR pszNameOnly = strrchr( pszFullPathBuff, '\\' ); + + if( (pszNameOnly == NULL) || (strlen(pszNameOnly) > 13) ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + strcpy( pszFilenameBuff, ++pszNameOnly ); + + return TRUE; +} + + + + + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDLG.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDLG.H new file mode 100644 index 0000000..d9729e3 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDLG.H @@ -0,0 +1,30 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include + +class CMultiSelFileDialog : public CFileDialog +{ + private: + PCHAR pszFileList; + PCHAR pszOldPtr; + int nPathLen; + char szPath[80]; + BOOL Done; + + public: + CMultiSelFileDialog( CWnd *pParentWnd ); + ~CMultiSelFileDialog(); + BOOL GetFirstFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ); + BOOL GetNextFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ); +}; diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDOC.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDOC.CPP new file mode 100644 index 0000000..f4fdf2b --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDOC.CPP @@ -0,0 +1,89 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +// multfdoc.cpp : implementation of the CMultfileDoc class +// + +#include "stdafx.h" +#include "multfile.h" + +#include "multfdoc.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMultfileDoc + +IMPLEMENT_DYNCREATE(CMultfileDoc, CDocument) + +BEGIN_MESSAGE_MAP(CMultfileDoc, CDocument) + //{{AFX_MSG_MAP(CMultfileDoc) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMultfileDoc construction/destruction + +CMultfileDoc::CMultfileDoc() +{ + // TODO: add one-time construction code here +} + +CMultfileDoc::~CMultfileDoc() +{ +} + +BOOL CMultfileDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CMultfileDoc serialization + +void CMultfileDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CMultfileDoc diagnostics + +#ifdef _DEBUG +void CMultfileDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CMultfileDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMultfileDoc commands diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDOC.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDOC.H new file mode 100644 index 0000000..9fabd25 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFDOC.H @@ -0,0 +1,46 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +// multfdoc.h : interface of the CMultfileDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class CMultfileDoc : public CDocument +{ +protected: // create from serialization only + CMultfileDoc(); + DECLARE_DYNCREATE(CMultfileDoc) + +// Attributes +public: +// Operations +public: + +// Implementation +public: + virtual ~CMultfileDoc(); + virtual void Serialize(CArchive& ar); // overridden for document i/o +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + virtual BOOL OnNewDocument(); + +// Generated message map functions +protected: + //{{AFX_MSG(CMultfileDoc) + // 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() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.CPP new file mode 100644 index 0000000..201a332 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.CPP @@ -0,0 +1,140 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +// multfile.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "multfile.h" + +#include "mainfrm.h" +#include "multfdoc.h" +#include "multfvw.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMultfileApp + +BEGIN_MESSAGE_MAP(CMultfileApp, CWinApp) + //{{AFX_MSG_MAP(CMultfileApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMultfileApp construction + +CMultfileApp::CMultfileApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CMultfileApp object + +CMultfileApp NEAR theApp; + +///////////////////////////////////////////////////////////////////////////// +// CMultfileApp initialization + +BOOL CMultfileApp::InitInstance() +{ + // 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. + + OkToExit = TRUE; + + SetDialogBkColor(); // Set dialog background color to gray + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(CMultfileDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CMultfileView)); + AddDocTemplate(pDocTemplate); + + // create a new (empty) document + OnFileNew(); + + if (m_lpCmdLine[0] != '\0') + { + // TODO: add command line processing here + } + + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + +// Implementation +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CMultfileApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CMultfileApp commands diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.H new file mode 100644 index 0000000..aaf884d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.H @@ -0,0 +1,49 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +// multfile.h : main header file for the MULTFILE application +// + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +#define WM_TURN_OFF_HELP WM_USER+1 +#define WM_TURN_ON_HELP WM_USER+2 + +///////////////////////////////////////////////////////////////////////////// +// CMultfileApp: +// See multfile.cpp for the implementation of this class +// + +class CMultfileApp : public CWinApp +{ +public: + CMultfileApp(); + + BOOL OkToExit; + + +// Overrides + virtual BOOL InitInstance(); + +// Implementation + + //{{AFX_MSG(CMultfileApp) + afx_msg void OnAppAbout(); + // 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() +}; + + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.MAK b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.MAK new file mode 100644 index 0000000..651b52d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.MAK @@ -0,0 +1,300 @@ +# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE No configuration specified. Defaulting to Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "MULTFILE.MAK" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Win32 Debug" +MTL=MkTypLib.exe +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win32 Release" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : $(OUTDIR)/MULTFILE.exe $(OUTDIR)/MULTFILE.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE CPP /nologo /MD /W3 /GX /YX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /FR /c +# ADD CPP /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"STDAFX.H" /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"MULTFILE.pch" /Yu"STDAFX.H" /Fo$(INTDIR)/ /c\ + +CPP_OBJS=.\WinRel/ +# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"MULTFILE.res" /d "NDEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"MULTFILE.bsc" + +$(OUTDIR)/MULTFILE.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 oldnames.lib pkwdcl.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /MACHINE:IX86 +# ADD LINK32 oldnames.lib implodei.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /INCREMENTAL:yes /MACHINE:IX86 +LINK32_FLAGS=oldnames.lib implodei.lib /NOLOGO /STACK:0x10240\ + /SUBSYSTEM:windows /INCREMENTAL:yes /PDB:$(OUTDIR)/"MULTFILE.pdb" /MACHINE:IX86\ + /OUT:$(OUTDIR)/"MULTFILE.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/MULTFILE.res \ + $(INTDIR)/STDAFX.OBJ \ + $(INTDIR)/MULTFILE.OBJ \ + $(INTDIR)/MAINFRM.OBJ \ + $(INTDIR)/MULTFDOC.OBJ \ + $(INTDIR)/MULTFVW.OBJ \ + $(INTDIR)/DCL.OBJ \ + $(INTDIR)/MULTFDLG.OBJ + +$(OUTDIR)/MULTFILE.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : $(OUTDIR)/MULTFILE.exe $(OUTDIR)/MULTFILE.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE CPP /nologo /MD /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /FR /c +# ADD CPP /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"STDAFX.H" /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"MULTFILE.pch" /Yu"STDAFX.H" /Fo$(INTDIR)/\ + /Fd$(OUTDIR)/"MULTFILE.pdb" /c +CPP_OBJS=.\WinDebug/ +# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"MULTFILE.res" /d "_DEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"MULTFILE.bsc" + +$(OUTDIR)/MULTFILE.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 oldnames.lib pkwdcl.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /DEBUG /MACHINE:IX86 +# ADD LINK32 oldnames.lib implodei.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /DEBUG /MACHINE:IX86 +# SUBTRACT LINK32 /INCREMENTAL:no +LINK32_FLAGS=oldnames.lib implodei.lib /NOLOGO /STACK:0x10240\ + /SUBSYSTEM:windows /INCREMENTAL:yes /PDB:$(OUTDIR)/"MULTFILE.pdb" /DEBUG\ + /MACHINE:IX86 /OUT:$(OUTDIR)/"MULTFILE.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/MULTFILE.res \ + $(INTDIR)/STDAFX.OBJ \ + $(INTDIR)/MULTFILE.OBJ \ + $(INTDIR)/MAINFRM.OBJ \ + $(INTDIR)/MULTFDOC.OBJ \ + $(INTDIR)/MULTFVW.OBJ \ + $(INTDIR)/DCL.OBJ \ + $(INTDIR)/MULTFDLG.OBJ + +$(OUTDIR)/MULTFILE.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Group "Source Files" + +################################################################################ +# Begin Source File + +SOURCE=.\MULTFILE.RC +DEP_MULTF=\ + .\RES\MULTFILE.ICO\ + .\RES\TOOLBAR.BMP\ + .\resource.h\ + .\res\multfile.rc2 + +$(INTDIR)/MULTFILE.res : $(SOURCE) $(DEP_MULTF) $(INTDIR) + $(RSC) $(RSC_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STDAFX.CPP +DEP_STDAF=\ + .\stdafx.h + +!IF "$(CFG)" == "Win32 Release" + +# ADD BASE CPP /Yc"STDAFX.H" +# ADD CPP /Yc"STDAFX.H" + +$(INTDIR)/STDAFX.OBJ : $(SOURCE) $(DEP_STDAF) $(INTDIR) + $(CPP) /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"MULTFILE.pch" /Yc"STDAFX.H" /Fo$(INTDIR)/ /c\ + $(SOURCE) + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# ADD BASE CPP /Yc"STDAFX.H" +# ADD CPP /Yc"STDAFX.H" + +$(INTDIR)/STDAFX.OBJ : $(SOURCE) $(DEP_STDAF) $(INTDIR) + $(CPP) /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"MULTFILE.pch" /Yc"STDAFX.H" /Fo$(INTDIR)/\ + /Fd$(OUTDIR)/"MULTFILE.pdb" /c $(SOURCE) + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MULTFILE.CPP +DEP_MULTFI=\ + .\stdafx.h\ + .\multfile.h\ + .\mainfrm.h\ + .\multfdoc.h\ + .\multfvw.h\ + .\resource.h + +$(INTDIR)/MULTFILE.OBJ : $(SOURCE) $(DEP_MULTFI) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MAINFRM.CPP +DEP_MAINF=\ + .\stdafx.h\ + .\multfile.h\ + .\mainfrm.h\ + .\dcl.h\ + .\multfdlg.h\ + .\implode.h\ + .\resource.h + +$(INTDIR)/MAINFRM.OBJ : $(SOURCE) $(DEP_MAINF) $(INTDIR) $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MULTFDOC.CPP +DEP_MULTFD=\ + .\stdafx.h\ + .\multfile.h\ + .\multfdoc.h\ + .\resource.h + +$(INTDIR)/MULTFDOC.OBJ : $(SOURCE) $(DEP_MULTFD) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MULTFVW.CPP +DEP_MULTFV=\ + .\stdafx.h\ + .\multfile.h\ + .\multfdoc.h\ + .\multfvw.h\ + .\resource.h + +$(INTDIR)/MULTFVW.OBJ : $(SOURCE) $(DEP_MULTFV) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DCL.CPP +DEP_DCL_C=\ + .\stdafx.h\ + .\implode.h + +$(INTDIR)/DCL.OBJ : $(SOURCE) $(DEP_DCL_C) $(INTDIR) $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MULTFDLG.CPP +DEP_MULTFDL=\ + .\stdafx.h\ + .\multfdlg.h + +$(INTDIR)/MULTFDLG.OBJ : $(SOURCE) $(DEP_MULTFDL) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +# End Group +# End Project +################################################################################ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.RC b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.RC new file mode 100644 index 0000000..9d63d34 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFILE.RC @@ -0,0 +1,195 @@ +//Microsoft App Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#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 + "#include ""res\\multfile.rc2"" // non-App Studio edited resources\r\n" + "\r\n" + "#include ""afxres.rc"" \011// Standard components\r\n" + "\0" +END + +///////////////////////////////////////////////////////////////////////////////////// +#endif // APSTUDIO_INVOKED + + +////////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +IDR_MAINFRAME ICON DISCARDABLE "RES\\MULTFILE.ICO" + +////////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP MOVEABLE PURE "RES\\TOOLBAR.BMP" + +////////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Compress Files", IDM_COMPRESS_FILES + MENUITEM "&Uncompress Files", IDM_UNCOMPRESS_FILES + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Options" + BEGIN + MENUITEM "&ASCII", IDM_CMP_ASCII + MENUITEM "&Binary", IDM_CMP_BINARY + MENUITEM SEPARATOR + MENUITEM "&1024", IDM_DICT_SIZE_1024 + MENUITEM "&2048", IDM_DICT_SIZE_2048 + MENUITEM "&4096", IDM_DICT_SIZE_4096 + END + POPUP "&View" + BEGIN + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Help" + BEGIN + MENUITEM "&About Multfile...", ID_APP_ABOUT + END +END + + +////////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 34, 22, 217, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Multfile" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "Multfile Application Version 1.0",IDC_STATIC,40,10,119, + 8 + LTEXT "Copyright \251 1995",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,176,6,32,14,WS_GROUP +END + + +////////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + IDR_MAINFRAME "Multfile (DLL Version)\n\nMultfile Document\n\n\nMultfile.Document\nMultfile Document" +END + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + AFX_IDS_APP_TITLE "Multfile Windows Application" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright" + ID_APP_EXIT "Quit the application; prompts to save documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane" + ID_PREV_PANE "Switch back to the previous window pane" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar" + ID_VIEW_STATUS_BAR "Show or hide the status bar" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDM_CHOOSE_FILES "Select files to test Data Compression Library" + IDM_COMPRESS_FILES "Demo of compressing one or more files" + IDM_UNCOMPRESS_FILES "Demo of uncompressing a file created by 'Compress Files'" + IDM_CMP_BINARY "Set data type as binary" + IDM_CMP_ASCII "Set data type as text" + IDM_DICT_SIZE_1024 "Set dictionary size to 1024 bytes" + IDM_DICT_SIZE_2048 "Set dictionary size to 2048 bytes" + IDM_DICT_SIZE_4096 "Set dictionary size to 4096 bytes" +END + + +#ifndef APSTUDIO_INVOKED +//////////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "res\multfile.rc2" // non-App Studio edited resources + +#include "afxres.rc" // Standard components + +///////////////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFVW.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFVW.CPP new file mode 100644 index 0000000..8f290ec --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFVW.CPP @@ -0,0 +1,121 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +// multfvw.cpp : implementation of the CMultfileView class +// + +#include "stdafx.h" +#include "multfile.h" + +#include "multfdoc.h" +#include "multfvw.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + + +char szHelpMsg[] = { + "To compress multiple files: Select Compress Files from the File " + "menu, and use the shift and control keys with the mouse to " + "highlight multiple files. Press Ok after selecting the files. " + "Enter the path and name of file to compress the selected files " + "to.\n\n" + "To uncompress a file: Select Uncompress Files from the File menu, " + "and enter or select the file to uncompress, then press the Ok " + "button. The files will be uncompressed in the same directory." }; + + +///////////////////////////////////////////////////////////////////////////// +// CMultfileView + +IMPLEMENT_DYNCREATE(CMultfileView, CView) + +BEGIN_MESSAGE_MAP(CMultfileView, CView) + //{{AFX_MSG_MAP(CMultfileView) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + ON_MESSAGE( WM_TURN_OFF_HELP, OnTurnOffHelp ) + ON_MESSAGE( WM_TURN_ON_HELP, OnTurnOnHelp ) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMultfileView construction/destruction + +CMultfileView::CMultfileView() +{ + bDisplayHelp = TRUE; +} + +CMultfileView::~CMultfileView() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// CMultfileView drawing + +void CMultfileView::OnDraw(CDC* pDC) +{ + CMultfileDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + // TODO: add draw code for native data here + if( bDisplayHelp ) + { + RECT rect; + + pDC->SetBkMode( TRANSPARENT ); + GetClientRect( &rect ); + pDC->DrawText( szHelpMsg, -1, &rect, DT_LEFT | DT_WORDBREAK ); + } +} + +///////////////////////////////////////////////////////////////////////////// +// CMultfileView diagnostics + +#ifdef _DEBUG +void CMultfileView::AssertValid() const +{ + CView::AssertValid(); +} + +void CMultfileView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CMultfileDoc* CMultfileView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMultfileDoc))); + return (CMultfileDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMultfileView message handlers + +LRESULT CMultfileView::OnTurnOffHelp( WPARAM wParam, LPARAM lParam ) +{ + bDisplayHelp = FALSE; + InvalidateRect( NULL, TRUE ); + + return 0; +} + +LRESULT CMultfileView::OnTurnOnHelp( WPARAM wParam, LPARAM lParam ) +{ + bDisplayHelp = TRUE; + InvalidateRect( NULL, TRUE ); + + return 0; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFVW.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFVW.H new file mode 100644 index 0000000..374c3b7 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/MULTFVW.H @@ -0,0 +1,57 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +// multfvw.h : interface of the CMultfileView class +// +///////////////////////////////////////////////////////////////////////////// + +class CMultfileView : public CView +{ +private: + BOOL bDisplayHelp; + +protected: // create from serialization only + CMultfileView(); + DECLARE_DYNCREATE(CMultfileView) + +// Attributes +public: + CMultfileDoc* GetDocument(); + +// Operations +public: + +// Implementation +public: + virtual ~CMultfileView(); + virtual void OnDraw(CDC* pDC); // overridden to draw this view + afx_msg LRESULT OnTurnOffHelp( WPARAM wParam, LPARAM lParam ); + afx_msg LRESULT OnTurnOnHelp( WPARAM wParam, LPARAM lParam ); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CMultfileView) + // 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() +}; + +#ifndef _DEBUG // debug version in multfvw.cpp +inline CMultfileDoc* CMultfileView::GetDocument() + { return (CMultfileDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/MULTFILE.ICO b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/MULTFILE.ICO new file mode 100644 index 0000000..b718392 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/MULTFILE.ICO differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/MULTFILE.RC2 b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/MULTFILE.RC2 new file mode 100644 index 0000000..169e748 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/MULTFILE.RC2 @@ -0,0 +1,52 @@ +// +// MULTFILE.RC2 - resources App Studio does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by App Studio +#endif //APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// Version stamp for this .EXE + +#include "ver.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG|VS_FF_PRIVATEBUILD|VS_FF_PRERELEASE +#else + FILEFLAGS 0 // final version +#endif + FILEOS VOS_DOS_WINDOWS16 + FILETYPE VFT_APP + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "MULTFILE MFC Application\0" + VALUE "FileVersion", "1.0.001\0" + VALUE "InternalName", "MULTFILE\0" + VALUE "LegalCopyright", "\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename","MULTFILE.EXE\0" + VALUE "ProductName", "MULTFILE\0" + VALUE "ProductVersion", "1.0.001\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + // English language (0x409) and the Windows ANSI codepage (1252) + END +END + +///////////////////////////////////////////////////////////////////////////// +// Add additional manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/TOOLBAR.BMP b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/TOOLBAR.BMP new file mode 100644 index 0000000..49695e2 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RES/TOOLBAR.BMP differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RESOURCE.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RESOURCE.H new file mode 100644 index 0000000..7ddf0f9 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/RESOURCE.H @@ -0,0 +1,34 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +//{{NO_DEPENDENCIES}} +// App Studio generated include file. +// Used by MULTFILE.RC +// +#define IDR_MAINFRAME 2 +#define IDD_ABOUTBOX 100 +#define IDM_CHOOSE_FILES 32771 +#define IDM_COMPRESS_FILES 32772 +#define IDM_UNCOMPRESS_FILES 32773 +#define IDM_CMP_BINARY 32774 +#define IDM_CMP_ASCII 32775 +#define IDM_DICT_SIZE_1024 32777 +#define IDM_DICT_SIZE_2048 32778 +#define IDM_DICT_SIZE_4096 32779 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 32780 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/STDAFX.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/STDAFX.CPP new file mode 100644 index 0000000..07f7b46 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/STDAFX.CPP @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// stdafx.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/STDAFX.H b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/STDAFX.H new file mode 100644 index 0000000..6179a32 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/MULTFILE/STDAFX.H @@ -0,0 +1,7 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#include // MFC core and standard components +#include // MFC extensions (including VB) diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/DCL.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/DCL.CPP new file mode 100644 index 0000000..fff2f7f --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/DCL.CPP @@ -0,0 +1,889 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +/* + * DCL.cpp - File to call various DCL DLL functions + */ + +#include "stdafx.h" + +#include + +#include +#include +#include + +#include "implode.h" + +#define TEMPFILENAME "~~~.$$$" // TEMPORARY FILENAME TO CREATE +#define APPENDBUFSIZE 32000 // SIZE OF BUFFER TO ALLOCATE FOR APPENDING + // A COMPRESSED FILE TO .MCF FILE + +typedef enum +{ + COMPRESSING = 1, + UNCOMPRESSING +} FILEMODE; + + +// STRUCT TO PASS TO THE FILE IO FUNCTIONS +typedef struct +{ + CFile *InFile; + CFile *OutFile; + CDC *pDC; + BYTE nPrevNdx; + BYTE nCnt; + DWORD dwCompressSize; + FILEMODE mode; + DWORD dwCrc; +} IOFILEBLOCK, *PIOFILEBLOCK; + +// FOUR LETTER IDENTIFIER TO IDENTIFY A FILE AS +// A .MCF (MULTIPLE COMPRESSED FILES) FILE +char MCF_FILEHEADER[] = { "MCFX" }; + +#pragma pack(2) +// HEADER FOR EACH FILE COMPRESSED INTO THE .MCF FILE +typedef struct +{ + DWORD dwCompressSize; // SIZE OF FILE COMPRESSED + DWORD dwCrc; // THE CRC OF THE FILE BEFORE COMPRESSION + char filename[13]; // NAME OF THE FILE +}CMP_FILEHEADER, *PCMP_FILEHEADER; +#pragma pack(8) + +/* + * FORMAT OF .MCF FILE: + * + * .MCF FILEHEADER => MCFX + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * AND SO ON + * + */ + +static char *pszActiveString[] = { "|", "/", "-", "\\" }; + +UINT DataType = CMP_ASCII; // GLOBAL FOR DATA TYPE FOR COMPRESSION +UINT DictSize = 4096; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + +static PCHAR pszFilename; // NAME OF THE .MCF FILE + +/********************************************************************* + * + * Function: ProcessMessages() + * + * Purpose: To allow Windows to process window messages which + * allows the user to multitask will compressing and + * uncompressing files. + * + * Returns: Nothing + * + *********************************************************************/ +void ProcessMessages(void) +{ + MSG msg; + + while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) + { + if (msg.message == WM_QUIT) + return; + + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + + +/********************************************************************* + * + * Function: ReadFromDisk() + * + * Purpose: To read data from disk, and prompt user for another + * disk when needed. This function makes a large assumption + * that if when reading a header zero bytes are read, then + * EOF has been reached. + * + * Parameters: Infile -> Pointer to already opened .MCF file + * pBuffer -> input buffer + * nSize -> number of bytes to read + * numread -> pointer to return actual number of bytes read + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred (A FileException is thrown) + * + *********************************************************************/ +int ReadFromDisk( CFile *InFile, PCHAR pBuffer, UINT nSize, UINT *numread, + BOOL ReadingHeader ) +{ + UINT bytesread; + + // READ DATA FROM DISK + *numread = bytesread = InFile->Read( pBuffer, nSize ); + + // IF READING A HEADER AND READ 0 BYTES, THEN ASSUME THIS IS THE END + if( bytesread == 0 && ReadingHeader ) + { + return 1; + } + + // IF COULD NOT READ ALL BYTES + if( bytesread < nSize ) + { + // CALCULATE NUMBER OF BYTES TO READ + nSize -= bytesread; + + // CLOSE THE FILE + InFile->Close(); + + // PROMPT USER FOR ANOTHER DISK + MessageBox( NULL, "Insert Next Disk", "Uncompress", MB_OK ); + + // OPEN .MCF FILE ON NEW DISK + if( !InFile->Open( pszFilename, + CFile::modeRead | CFile::shareExclusive | CFile::typeBinary ) ) + { + AfxThrowFileException( CFileException::fileNotFound ); + return 0; + } + + // READ DATA FROM DISK + bytesread = InFile->Read( (pBuffer + bytesread), nSize ); + + *numread += bytesread; + } + + return 1; +} + + +/********************************************************************* + * + * Function: ProcessInBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * read requests. If compressing, then the data read is + * in uncompressed form. If compressing, then the data + * read is data that was previously compressed. This + * function is called until zero is returned. + * + * Parameters: buffer -> Address of buffer to read the data into + * iSize -> Number of bytes to read into buffer + * dwParam -> User-defined parameter, in this case a + * pointer to the IOFILEBLOCK + * + * Returns: Number of bytes actually read, or zero on EOF + * + *********************************************************************/ +UINT ProcessInBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + PIOFILEBLOCK pFileIOBlock; + UINT iRead; + UINT ndx; + + pFileIOBlock = (PIOFILEBLOCK) pParam; + + // DISPLAY ROTATING LINE + ndx = (pFileIOBlock->nCnt >> 4) & 3; + if( ndx != pFileIOBlock->nPrevNdx ) + { + pFileIOBlock->pDC->TextOut( 10,2, pszActiveString[ndx] ); + pFileIOBlock->nPrevNdx = ndx; + } + pFileIOBlock->nCnt++; + + // THIS FUNCTION MAY ASK FOR UP TO 4K OF DATA AT A TIME. IF YOUR + // ARCHIVE FILE CONTAINS SEVERAL COMPRESSED FILES, YOU MAY READ TOO + // MUCH. FOR EXAMPLE, YOUR FIRST COMPRESSED FILE IN THE ARCHIVE MAY + // BE 100 BYTES. SO YOU DO NOT WANT TO READ MORE THAN 100 BYTES OR + // YOU WILL BE UNABLE TO UNCOMPRESS THE SECOND FILE, SINCE YOU WILL + // NOT BE LOCATED AT THE BEGINNING OF THE FILE ANY LONGER. + // WE WILL USE THE VARIABLE "dwCompressSize" TO CHECK FOR THIS + // CONDITION. + if( pFileIOBlock->mode == UNCOMPRESSING ) + { + // IF DCL REQUESTED MORE BYTES THAN ARE LEFT IN COMPRESSED FILE, THEN + // SET THE NUMBER OF BYTES TO READ TO THE AMOUNT LEFT IN THE BUFFER + if( (DWORD)*iSize > pFileIOBlock->dwCompressSize ) + *iSize = (UINT) pFileIOBlock->dwCompressSize; + + pFileIOBlock->dwCompressSize -= (DWORD) *iSize; + + // READ COMPRESSED FILE FILEHEADER + if( !ReadFromDisk( pFileIOBlock->InFile, buffer, *iSize, &iRead, FALSE ) ) + { + return 0; + } + } + else + { + // READ BUFFER FROM DISK + iRead = (UINT)pFileIOBlock->InFile->Read( buffer, *iSize ); + } + + // IF COMPRESSING, THEN CALCULATE THE CRC + if( pFileIOBlock->mode == COMPRESSING ) + { + pFileIOBlock->dwCrc = crc32( buffer, &iRead, &pFileIOBlock->dwCrc ); + } + + // ENTER MESSAGE LOOP TO PROCESS BACKGROUND MESSAGES + // AND SIMULATE MULTITASKING + ProcessMessages(); + + return iRead; +} + +/********************************************************************* + * + * Function: ProcessOutBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * write requests. + * + * Parameters: buffer -> Address of buffer to write data from + * iSize -> Number of bytes to write + * dwParam -> User-defined parameter, in this case a + * pointer to the IOFILEBLOCK + * + * Returns: Zero, the return value is not used by the Data + * Compression Library + * + *********************************************************************/ +void ProcessOutBuffer(PCHAR buffer, UINT *iSize, void *pParam) +{ + PIOFILEBLOCK pFileIOBlock; + UINT ndx; + + pFileIOBlock = (PIOFILEBLOCK) pParam; + + // DISPLAY ROTATING LINE PACIFIER + ndx = (pFileIOBlock->nCnt >> 4) & 3; + if( ndx != pFileIOBlock->nPrevNdx ) + { + pFileIOBlock->pDC->TextOut( 10,2, pszActiveString[ndx] ); + pFileIOBlock->nPrevNdx = ndx; + } + pFileIOBlock->nCnt++; + + // WRITE BUFFER TO DISK + pFileIOBlock->OutFile->Write(buffer, *iSize); + + // IF COMPRESSING, THEN KEEP A TOTAL OF THE COMPRESSED FILE SIZE + if (pFileIOBlock->mode == COMPRESSING ) + { + pFileIOBlock->dwCompressSize += (DWORD) *iSize; + } + else // ELSE UNCOMPRESSING, SO CALCULATE CRC ON THE UNCOMPRESSED DATA + { + pFileIOBlock->dwCrc = crc32(buffer, iSize, &pFileIOBlock->dwCrc); + } + + // ENTER MESSAGE LOOP TO PROCESS BACKGROUND MESSAGES + // AND SIMULATE MULTITASKING + ProcessMessages(); + + return; +} + +/********************************************************************* + * + * Function: CompressFile() + * + * Purpose: To compress file to a separate temporary file. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * pdwCompFileSize -> Pointer to DWORD buffer to return + * the size of the compressed file + * pszFileToCompress -> Name of file to compress + * OutputFile -> Name of file to write compressed data to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressFile( HWND hWnd, CDC *pDC, DWORD *pdwCrc, DWORD *pdwCompFileSize, + PCHAR pszFileToCompress, PCHAR OutputFile ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + IOFILEBLOCK FileIOBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + // OPEN THE INPUT AND OUTPUT FILES + FileIOBlock.InFile = new CFile; + FileIOBlock.OutFile = new CFile; + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + FileIOBlock.mode = COMPRESSING; + FileIOBlock.dwCompressSize = 0; + FileIOBlock.pDC = pDC; + FileIOBlock.nCnt = 0; + FileIOBlock.nPrevNdx = 0; + FileIOBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + pDC->TextOut( 10,2, " " ); + + // OPEN THE FILES + if (FileIOBlock.InFile->Open( pszFileToCompress, CFile::modeRead | CFile::shareExclusive | CFile::typeBinary) && + FileIOBlock.OutFile->Open( OutputFile, CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary)) + { + wsprintf( szVerbose, "Compressing file: %s ", pszFileToCompress ); + pDC->TextOut( 10,40, szVerbose ); + + // ONLY COMPRESS IF FILE IS NOT A ZERO LENGTH FILE + if( FileIOBlock.InFile->GetLength() ) + { + // COMPRESS THE FILE + iStatus = implode( ProcessInBuffer, ProcessOutBuffer, pScratchPad, &FileIOBlock, + &DataType, &DictSize ); + } + else + { + // SINCE THIS IS A ZERO LENGTH FILE, THERE IS NOTHING TO COMPRESS + // SET STATUS TO NO ERROR + iStatus = 0; + } + + // IF THERE WAS AN ERROR COMPRESSING FILE + if( iStatus ) + { + // DISPLAY ERROR STRING FROM DLL + wsprintf( szVerbose, "Error occurred while imploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else // ELSE - COMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + FileIOBlock.dwCrc = ~FileIOBlock.dwCrc; + + // RETURN CRC + *pdwCrc = FileIOBlock.dwCrc; + + // RETURN COMPRESSED FILE SIZE + *pdwCompFileSize = FileIOBlock.dwCompressSize; + } + + FileIOBlock.OutFile->Close(); + FileIOBlock.InFile->Close(); + } + else // ELSE - ERROR OPENING FILES + { + MessageBox( hWnd, "Error opening files for compression", "Error", MB_OK ); + rc = 0; + } + + // CLEAN-UP + delete FileIOBlock.InFile; + delete FileIOBlock.OutFile; + + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: ExpandFile() + * + * Purpose: To uncompress file from a .MCF file. The .MCF file will + * have been read upto the compressed data stream. + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * dwCompFileSize -> Size of the compressed file + * pMcfFile -> Pointer to already opened .MCF file + * OutputFile -> Name of file to write uncompressed data to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int ExpandFile( HWND hWnd, CDC *pDC, DWORD *pdwCrc, DWORD dwCompFileSize, + CFile *pMcfFile, PCHAR OutputFile ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + IOFILEBLOCK FileIOBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + FileIOBlock.InFile = pMcfFile; + FileIOBlock.OutFile = new CFile; + + // SETUP STRUCTURE USED BY ProcessReadBuffer() and ProcessWriteBuffer() + FileIOBlock.mode = UNCOMPRESSING; + FileIOBlock.dwCompressSize = dwCompFileSize; + FileIOBlock.pDC = pDC; + FileIOBlock.nCnt = 0; + FileIOBlock.nPrevNdx = 0; + FileIOBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + pDC->TextOut( 10,2, " " ); + + if( FileIOBlock.OutFile->Open(OutputFile, CFile::modeCreate | CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary) ) + { + // ONLY UNCOMPRESS IF FILE IS NOT A ZERO LENGTH FILE + if( FileIOBlock.dwCompressSize ) + { + // UNCOMPRESS FILE + iStatus = explode( ProcessInBuffer, ProcessOutBuffer, pScratchPad, &FileIOBlock ); + } + else + { + // SINCE THIS IS A ZERO LENGTH FILE, THERE IS NOTHING TO UNCOMPRESS + // SET STATUS TO NO ERROR + iStatus = 0; + } + + if( iStatus ) + { + wsprintf( szVerbose, "Error occurred while exploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else + { + FileIOBlock.dwCrc = ~FileIOBlock.dwCrc; + *pdwCrc = FileIOBlock.dwCrc; + + if( FileIOBlock.dwCompressSize != 0 ) + { + wsprintf( szVerbose, "Error uncompressing file: %s", OutputFile ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + } + + FileIOBlock.OutFile->Close(); + } + else + { + MessageBox( hWnd, "Error opening files for uncompression", "Error", MB_OK ); + rc = 0; + } + + delete FileIOBlock.OutFile; + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: AmountDriveSpaceFree() + * + * Purpose: To calculate the number of bytes free on drive + * + * Parameters: drivenum -> Drive to check (A=1, B=2, ...) + * pdwBytesFree -> DWORD to return number of bytes free + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int AmountDriveSpaceFree( UINT drivenum, DWORD *pdwBytesFree ) +{ + static char RootStr[] = { "?:\\" }; + DWORD SectorsPerCluster, + BytesPerSector, + FreeClusters, + Clusters; + + *RootStr = 'A' + drivenum - 1; + + if( GetDiskFreeSpace( RootStr, &SectorsPerCluster, &BytesPerSector, + &FreeClusters, &Clusters ) == FALSE ) + { + return 0; + } + + *pdwBytesFree = SectorsPerCluster * BytesPerSector * FreeClusters; + + return 1; +} + + +/********************************************************************* + * + * Function: WriteToDisk() + * + * Purpose: To write data to disk, and prompt user for another + * disk when full. + * + * Parameters: OutFile -> Pointer to already opened file + * pBuffer -> output buffer + * nSize -> number of bytes to write + * pdwBytesFree -> number of bytes left on disk + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred (A FileException is thrown) + * + *********************************************************************/ +int WriteToDisk( CFile *OutFile, PCHAR pBuffer, UINT nSize, DWORD *pdwBytesFree ) +{ + UINT drivenum; + + // IF THERE IS SPACE TO WRITE FILE + if( (ULONG)nSize <= (ULONG)*pdwBytesFree ) + { + OutFile->Write( pBuffer, nSize ); + *pdwBytesFree -= nSize; + } + else // ELSE - NOT ENOUGH SPACE TO WRITE FILE + { + // FILL UP REMAINING DISKSPACE IF ANY + if( *pdwBytesFree > 0 ) + { + OutFile->Write( pBuffer, (UINT) *pdwBytesFree ); + nSize -= (UINT) *pdwBytesFree; + OutFile->Close(); + } + + drivenum = *pszFilename - 'A' + 1; + + // IF ON A FIXED DRIVE, THEN GIVE DISKFULL ERROR + if( drivenum > 2 ) + { + AfxThrowFileException( CFileException::diskFull ); + return 0; + } + + UINT nBytesRead = (UINT) *pdwBytesFree; + + // PROMPT USER FOR ANOTHER DISK + MessageBox( NULL, "Insert Another Disk", "Compress", MB_OK ); + + // GET NUMBER OF BYTES FREE ON DISK + if( !AmountDriveSpaceFree( drivenum, pdwBytesFree ) ) + { + AfxThrowFileException( CFileException::diskFull ); + return 0; + } + + // CREATE NEW .MCF FILE + OutFile->Open( pszFilename, CFile::modeCreate | CFile::modeWrite | CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary ); + + // WRITE REMAINING BYTES + OutFile->Write( (pBuffer + nBytesRead), nSize ); + *pdwBytesFree -= nSize; + } + + return 1; +} + + +/********************************************************************* + * + * Function: AddFileToMcfFile() + * + * Purpose: To add a compressed file with header to a .MCF file. + * The file header is written followed by the compressed + * file data + * + * Parameters: pFileHeader -> File header for the compressed file + * pszInput -> Filename of the compressed file's data + * pszOutput -> Filename of .MCF file + * CompressedFileSize -> Size of the compressed file + * NewMcfFile -> Flag used to create a new .MCF file + * TRUE - A new .MCF file will be created + * FALSE - The .MCF file will appended to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int AddFileToMcfFile( PCMP_FILEHEADER pFileHeader, PCHAR pszInput, + DWORD CompressedFileSize, BOOL NewMcfFile ) +{ + PCHAR buf; + UINT read; + CFile InFile; + CFile OutFile; + UINT drivenum; + DWORD BytesFree; + + // ALLOCATE I/O BUFFER + if( (buf = new char[APPENDBUFSIZE]) == NULL ) + { + return 0; + } + + drivenum = *pszFilename - 'A' + 1; + + // GET NUMBER OF BYTES FREE ON DISK + if( !AmountDriveSpaceFree( drivenum, &BytesFree ) ) + { + delete buf; + return 0; + } + + TRY + { + // OPEN THE FILES + InFile.Open( pszInput, CFile::modeRead | CFile::shareExclusive | CFile::typeBinary); + + // IF NEW FILE, THEN CREATE MULTIPLE COMPRESSED FILES FILE + if( NewMcfFile ) + { + // CREATE NEW .MCF FILE + OutFile.Open( pszFilename, CFile::modeCreate | CFile::modeWrite | CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary); + + // WRITE .MCF FILE HEADER + WriteToDisk( &OutFile, MCF_FILEHEADER, 4, &BytesFree ); + } + else + { + // OPEN OLD .MCF FILE + OutFile.Open( pszFilename, CFile::modeWrite | CFile::shareExclusive | CFile::typeBinary); + + // GO TO END OF FILE + OutFile.SeekToEnd(); + } + + // WRITE THE COMPRESSED FILE'S FILEHEADER + OutFile.Write( pFileHeader, sizeof(CMP_FILEHEADER) ); + + do + { + // READ FROM COMPRESSED FILE + read = InFile.Read( buf, APPENDBUFSIZE ); + + // WRITE DATA TO .MCF FILE + WriteToDisk( &OutFile, buf, read, &BytesFree ); + + // IF ERROR OCCURRED + if( CompressedFileSize < (DWORD) read ) + { + delete buf; + return 0; + } + + CompressedFileSize -= (DWORD) read; + } + while( CompressedFileSize > 0 ); + } + CATCH( CFileException, theException ) + { + // IF ERROR OCCURRED WHILE APPENDING FILE + if( theException->m_cause != CFileException::none ) + { + delete buf; + return 0; + } + } + END_CATCH + + delete buf; + + return 1; +} + +/********************************************************************* + * + * Function: CompressFileToMCF() + * + * Purpose: To compress a file then add it to a .MCF file + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszMcfFile -> Filename of .MCF file + * pszFileToCompress -> Filename of file with full path + * pszFilenameOnly -> Filename of file without any path + * This is the filename that is stored + * in the compressed file's file header + * NewMcfFile -> Flag used to create a new .MCF file + * TRUE - A new .MCF file will be created + * FALSE - The .MCF file will appended to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressFileToMCF( HWND hWnd, CDC *pDC, PCHAR pszMcfFile, PCHAR pszFileToCompress, + PCHAR pszFilenameOnly, BOOL NewMcfFile ) +{ + ASSERT( hWnd ); + ASSERT_VALID( pDC ); + + CMP_FILEHEADER FileHeader; + + pszFilename = pszMcfFile; + + memset( &FileHeader, 0, sizeof(FileHeader) ); + + // ATTEMPT TO COMPRESS THE FILE + if( !CompressFile( hWnd, pDC, &FileHeader.dwCrc, + &FileHeader.dwCompressSize, pszFileToCompress, + TEMPFILENAME ) ) + { + remove( TEMPFILENAME ); + MessageBox( hWnd, "Compress File Failed", "Error", MB_OK ); + return 0; + } + + strcpy( FileHeader.filename, pszFilenameOnly ); + + if( !AddFileToMcfFile( &FileHeader, TEMPFILENAME, FileHeader.dwCompressSize, NewMcfFile ) ) + { + remove( TEMPFILENAME ); + MessageBox( hWnd, "Compress File Failed", "Error", MB_OK ); + return 0; + } + + remove( TEMPFILENAME ); + + return 1; +} + +/********************************************************************* + * + * Function: UncompressFileToMCF() + * + * Purpose: To uncompress a .MCF file + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszMcfFilename -> Filename of .MCF file + * pszSaveDir -> Directory to save uncompressed files + * a backslash must be the last character + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int UncompressMcfFile( HWND hWnd, CDC *pDC, PCHAR pszMcfFilename, PCHAR pszSaveDir ) +{ + ASSERT( hWnd ); + ASSERT_VALID( pDC ); + + CMP_FILEHEADER FileHeader; + char McfFileheader[5]; + char szOutMsg[128]; + char szOutputFilename[100]; + UINT nNumFiles = 0; + DWORD dwCrc; // CRC OF FILE BEFORE COMPRESSION + UINT read; + CFile McfFile; + + pszFilename = pszMcfFilename; + + TRY + { + // OPEN THE FILES + McfFile.Open( pszFilename, CFile::modeRead | CFile::shareExclusive | CFile::typeBinary); + + memset( McfFileheader, 0, sizeof(McfFileheader) ); + + // MAKE SURE FILE IS A MULTIPLE COMPRESSED FILE + if( (!ReadFromDisk( &McfFile, McfFileheader, 4, &read, FALSE )) || + (read != 4) || + (strcmp( McfFileheader, MCF_FILEHEADER ) != 0) ) + { + MessageBox( hWnd, "Invalid file format", "Error", MB_OK ); + return 0; + } + + do + { + // READ COMPRESSED FILE FILEHEADER + if( !ReadFromDisk( &McfFile, (PCHAR)&FileHeader, sizeof(FileHeader), + &read, TRUE ) ) + { + MessageBox( hWnd, "Error Uncompressing file", "Error", MB_OK ); + return 0; + } + + // IF SUCCESSFULLY READ COMPRESSED FILE FILEHEADER + if( read == sizeof(FileHeader) ) + { + // CREATE OUTPUT FILENAME + strcpy( szOutputFilename, pszSaveDir ); + strcat( szOutputFilename, FileHeader.filename ); + + wsprintf( szOutMsg, "Uncompressing file: %s ", + FileHeader.filename ); + pDC->TextOut( 10,60, szOutMsg ); + + // ATTEMPT TO EXPAND THE FILE + if( !ExpandFile( hWnd, pDC, &dwCrc, + FileHeader.dwCompressSize, + &McfFile, szOutputFilename ) ) + { + wsprintf( szOutMsg, "Error Uncompressing file: %s", + szOutputFilename ); + MessageBox( hWnd, szOutMsg, "Error", MB_OK ); + return 0; + } + + // CHECK THE CRC OF THE FILE + if( dwCrc != FileHeader.dwCrc ) + { + wsprintf( szOutMsg, "There is an error in the CRC of %s", + szOutputFilename ); + MessageBox( hWnd, szOutMsg, "Error", MB_OK ); + } + + nNumFiles++; + } + } + while( read == sizeof(FileHeader) ); + + if( read != 0 ) + { + MessageBox( hWnd, "Invalid file format", "Error", MB_OK ); + return 0; + } + else + { + wsprintf( szOutMsg, "Uncompressed %u file(s)", nNumFiles ); + MessageBox( hWnd, szOutMsg, "Span", MB_OK ); + } + } + CATCH( CFileException, theException ) + { + if( theException->m_cause != CFileException::none ) + { + MessageBox( hWnd, "File Error", "Error", MB_OK ); + return 0; + } + } + END_CATCH + + return 1; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/DCL.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/DCL.H new file mode 100644 index 0000000..9a0de62 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/DCL.H @@ -0,0 +1,13 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +int CompressFileToMCF( HWND hWnd, CDC *pDC, + LPSTR lpszMcfFile, LPSTR lpszFileToCompress, + LPSTR lpszFilenameOnly, BOOL NewMcfFile ); +int UncompressMcfFile( HWND hWnd, CDC *pDC, LPSTR lpszMcfFile, LPSTR lpszSaveDir ); diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/IMPLODEI.LIB b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/IMPLODEI.LIB new file mode 100644 index 0000000..ca0b4df Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/IMPLODEI.LIB differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MAINFRM.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MAINFRM.CPP new file mode 100644 index 0000000..7ba6b50 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MAINFRM.CPP @@ -0,0 +1,427 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mainfrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "span.h" + +#include "mainfrm.h" +#include "implode.h" +#include "dcl.h" +#include "multfdlg.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +extern UINT DataType; // GLOBAL FOR DATA TYPE FOR COMPRESSION +extern UINT DictSize; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + +// THE UNCOMPRESS DIRECTORY MUST END WITH A BACKSLASH +char far *UncompressDir = "C:\\TEMP\\"; + + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame + +IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CREATE() + ON_COMMAND(IDM_CMP_ASCII, OnCmpAscii) + ON_UPDATE_COMMAND_UI(IDM_CMP_ASCII, OnUpdateCmpAscii) + ON_COMMAND(IDM_CMP_BINARY, OnCmpBinary) + ON_UPDATE_COMMAND_UI(IDM_CMP_BINARY, OnUpdateCmpBinary) + ON_COMMAND(IDM_COMPRESS_FILES, OnCompressFiles) + ON_UPDATE_COMMAND_UI(IDM_COMPRESS_FILES, OnUpdateCompressFiles) + ON_COMMAND(IDM_DICT_SIZE_1024, OnDictSize1024) + ON_UPDATE_COMMAND_UI(IDM_DICT_SIZE_1024, OnUpdateDictSize1024) + ON_COMMAND(IDM_DICT_SIZE_2048, OnDictSize2048) + ON_UPDATE_COMMAND_UI(IDM_DICT_SIZE_2048, OnUpdateDictSize2048) + ON_COMMAND(IDM_DICT_SIZE_4096, OnDictSize4096) + ON_UPDATE_COMMAND_UI(IDM_DICT_SIZE_4096, OnUpdateDictSize4096) + ON_COMMAND(IDM_UNCOMPRESS_FILES, OnUncompressFiles) + ON_UPDATE_COMMAND_UI(IDM_UNCOMPRESS_FILES, OnUpdateUncompressFiles) + ON_WM_CLOSE() + ON_WM_QUERYENDSESSION() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// arrays of IDs used to initialize control bars + +// toolbar buttons - IDs are command buttons +static UINT BASED_CODE buttons[] = +{ + // same order as in the bitmap 'toolbar.bmp' + ID_FILE_NEW, + ID_FILE_OPEN, + ID_FILE_SAVE, + ID_SEPARATOR, + ID_EDIT_CUT, + ID_EDIT_COPY, + ID_EDIT_PASTE, + ID_SEPARATOR, + ID_FILE_PRINT, + ID_APP_ABOUT, +}; + +static UINT BASED_CODE indicators[] = +{ + ID_SEPARATOR, // status line indicator + ID_INDICATOR_CAPS, + ID_INDICATOR_NUM, + ID_INDICATOR_SCRL, +}; + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() +{ + // TODO: add member initialization code here +} + +CMainFrame::~CMainFrame() +{ +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE("Failed to create status bar\n"); + return -1; // fail to create + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + + +void CMainFrame::OnCompressFiles() +{ + int rc; + HWND hWnd; + + // GET HANDLE TO WINDOW AND INSTANCE HANDLE + hWnd = CWnd::GetSafeHwnd(); + + // TURN OFF HELP MESSAGE SCREEN AND CLEAR SCREEN + SendMessageToDescendants( WM_TURN_OFF_HELP ); + + // CREATE FILE DIALOG THAT CAN USE CAN SELECT MULTIPLE FILES + CMultiSelFileDialog *FileDlg = new CMultiSelFileDialog( this ); + + // IF USER PRESSED OK BUTTON + if( (rc = FileDlg->DoModal()) == IDOK ) + { + // CREATE SAVE AS FILE DIALOG + CFileDialog SaveFileDlg( FALSE, "MCF", "*.MCF", + OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, + "Mult. Compressed Files (*.MCF) |*.MCF ||", this ); + + // GET FILENAME OF FILE TO PUT COMPRESSED FILES IN + if( (SaveFileDlg.DoModal()) == IDOK ) + { + BOOL GotFilenameOk, + bError = FALSE, + CreateMcfFile; + UINT nNumCmpFiles = 0; + char szFilename[13]; // BUFFER FOR FILENAME ONLY + char szFullPathname[128]; // BUFFER FOR FULL PATH FOR FILE + char szOutBuff[64]; // TEMP OUTPUT BUFFER + + // SET FLAG TO PREVENT EXITING IN THE MIDDLE OF THE COMPRESSION + ((CSpanApp *) AfxGetApp())->OkToExit = FALSE; + + // GET DC AND SET THE TEXT BACKGROUND COLOR TO WINDOW BACKGROUND COLOR + CClientDC dc(this); + COLORREF bkGroundColor = dc.GetPixel( 0, 0 ); + dc.SetBkColor( bkGroundColor ); + + wsprintf( szOutBuff, "Compressing to: %s ", + (LPSTR) (const char *) SaveFileDlg.GetPathName() ); + dc.TextOut( 10,20, szOutBuff ); + + // SET CREATE .MCF FILE FLAG TO TRUE, SO THAT THE FIRST TIME + // CompressFileToMCF IS CALLED THE .MCF WILL BE CREATED INSTEAD + // OF APPENDED TO + CreateMcfFile = TRUE; + + // GET THE FIRST FILENAME IN THE LIST + GotFilenameOk = FileDlg->GetFirstFilename( szFullPathname, + sizeof(szFullPathname), + szFilename ); + // WHILE GOT A FILENAME FROM THE LIST + while( GotFilenameOk ) + { + // COMPRESS THE FILE AND ADD IT TO THE .MCF FILE + if( !CompressFileToMCF( hWnd, &dc, + (LPSTR) (const char *) SaveFileDlg.GetPathName(), + szFullPathname, szFilename, CreateMcfFile ) ) + { + // ERROR OCCURRED SO DELETE THE .MCF FILE + remove( (const char *) SaveFileDlg.GetPathName() ); + bError = TRUE; + break; + } + // INCREMENT TOTAL + nNumCmpFiles++; + + // RESET .MCF FILE FLAG SO THAT .MCF FILE WILL NOT BE CREATED + CreateMcfFile = FALSE; + + // GET THE FIRST FILENAME IN THE LIST + GotFilenameOk = FileDlg->GetNextFilename( szFullPathname, + sizeof(szFullPathname), + szFilename ); + } + + // IF THERE WAS NOT ERROR, THEN DISPLAY MESSAGE + if( !bError ) + { + wsprintf( szOutBuff, "Compressed %u file(s)", nNumCmpFiles ); + MessageBox( szOutBuff ); + } + + // DONE WITH COMPRESION SO ALLOW THE USER TO EXIT + ((CSpanApp *) AfxGetApp())->OkToExit = TRUE; + } + } + + // CLEAN-UP + delete FileDlg; + + // TURN ON HELP MESSAGE AND CLEAR SCREEN + SendMessageToDescendants( WM_TURN_ON_HELP ); +} + +void CMainFrame::OnUncompressFiles() +{ + HWND hWnd; + + hWnd = CWnd::GetSafeHwnd(); + + // TURN OFF HELP MESSAGE AND CLEAR SCREEN + SendMessageToDescendants( WM_TURN_OFF_HELP ); + + // OPENFILENAME + CFileDialog OpenFileDlg( TRUE, "MCF", "*.MCF", + OFN_HIDEREADONLY | OFN_NOCHANGEDIR, + "Mult. Compressed Files (*.MCF) |*.MCF ||", this ); + + // GET FILENAME OF FILE TO PUT COMPRESSED FILES IN + if( (OpenFileDlg.DoModal()) == IDOK ) + { + char szOutBuff[64]; // TEMP OUTPUT BUFFER + + // SET FLAG TO PREVENT EXITING IN THE MIDDLE OF THE UNCOMPRESSION + ((CSpanApp *) AfxGetApp())->OkToExit = FALSE; + + // GET DC AND SET THE TEXT BACKGROUND COLOR TO WINDOW BACKGROUND COLOR + CClientDC dc(this); + COLORREF bkGroundColor = dc.GetPixel( 0, 0 ); + dc.SetBkColor( bkGroundColor ); + + wsprintf( szOutBuff, "Uncompressing: %s ", + (LPSTR) (const char *) OpenFileDlg.GetPathName() ); + dc.TextOut( 10,20, szOutBuff ); + + // UNCOMPRESS THE FILE + UncompressMcfFile( hWnd, &dc, + (LPSTR) (const char *) OpenFileDlg.GetPathName(), + UncompressDir ); + + // DONE WITH UNCOMPRESION SO ALLOW THE USER TO EXIT + ((CSpanApp *) AfxGetApp())->OkToExit = TRUE; + } + + // TURN ON HELP MESSAGE AND CLEAR SCREEN + SendMessageToDescendants( WM_TURN_ON_HELP ); +} + +BOOL CMainFrame::OnQueryEndSession() +{ + if (!CFrameWnd::OnQueryEndSession()) + return FALSE; + + // RETURN FALSE IF CANNOT EXIT RIGHT NOW + if( !((CSpanApp *) AfxGetApp())->OkToExit ) + return FALSE; + + return TRUE; +} + +void CMainFrame::OnClose() +{ + // RETURN IF CANNOT EXIT RIGHT NOW + if( !((CSpanApp *) AfxGetApp())->OkToExit ) + return; + + CFrameWnd::OnClose(); +} + +void CMainFrame::OnUpdateCompressFiles(CCmdUI* pCmdUI) +{ + pCmdUI->Enable( ((CSpanApp *) AfxGetApp())->OkToExit ); +} + +void CMainFrame::OnUpdateUncompressFiles(CCmdUI* pCmdUI) +{ + pCmdUI->Enable( ((CSpanApp *) AfxGetApp())->OkToExit ); +} + + +void CMainFrame::OnCmpAscii() +{ + DataType = CMP_ASCII; +} + +void CMainFrame::OnCmpBinary() +{ + DataType = CMP_BINARY; +} + +void CMainFrame::OnDictSize1024() +{ + DictSize = 1024; +} + +void CMainFrame::OnDictSize2048() +{ + DictSize = 2048; +} + +void CMainFrame::OnDictSize4096() +{ + DictSize = 4096; +} + +void CMainFrame::OnUpdateCmpAscii(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CSpanApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DataType == CMP_ASCII ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + +void CMainFrame::OnUpdateCmpBinary(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CSpanApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DataType == CMP_BINARY ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + +void CMainFrame::OnUpdateDictSize1024(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CSpanApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DictSize == 1024 ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + +void CMainFrame::OnUpdateDictSize2048(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CSpanApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DictSize == 2048 ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + +void CMainFrame::OnUpdateDictSize4096(CCmdUI* pCmdUI) +{ + // IF PROGRAM IS COMPRESSING OR UNCOMPRESSING RIGHT NOW + if( !((CSpanApp *) AfxGetApp())->OkToExit ) + { + pCmdUI->Enable( FALSE ); + return; + } + + if( DictSize == 4096 ) + { + pCmdUI->SetCheck( 1 ); + } + else + { + pCmdUI->SetCheck( 0 ); + } +} + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MAINFRM.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MAINFRM.H new file mode 100644 index 0000000..da293e9 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MAINFRM.H @@ -0,0 +1,61 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// mainfrm.h : interface of the CMainFrame class +// +///////////////////////////////////////////////////////////////////////////// + +class CMainFrame : public CFrameWnd +{ +protected: // create from serialization only + CMainFrame(); + DECLARE_DYNCREATE(CMainFrame) + +// Attributes +public: + +// Operations +public: + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + +// Generated message map functions +protected: + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnCmpAscii(); + afx_msg void OnUpdateCmpAscii(CCmdUI* pCmdUI); + afx_msg void OnCmpBinary(); + afx_msg void OnUpdateCmpBinary(CCmdUI* pCmdUI); + afx_msg void OnCompressFiles(); + afx_msg void OnUpdateCompressFiles(CCmdUI* pCmdUI); + afx_msg void OnDictSize1024(); + afx_msg void OnUpdateDictSize1024(CCmdUI* pCmdUI); + afx_msg void OnDictSize2048(); + afx_msg void OnUpdateDictSize2048(CCmdUI* pCmdUI); + afx_msg void OnDictSize4096(); + afx_msg void OnUpdateDictSize4096(CCmdUI* pCmdUI); + afx_msg void OnUncompressFiles(); + afx_msg void OnUpdateUncompressFiles(CCmdUI* pCmdUI); + afx_msg void OnClose(); + afx_msg BOOL OnQueryEndSession(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MULTFDLG.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MULTFDLG.CPP new file mode 100644 index 0000000..aff5eb3 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MULTFDLG.CPP @@ -0,0 +1,158 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include "stdafx.h" +#include + +#include "multfdlg.h" + +#define FILELIST_BUFFSIZE 4096 // AMOUNT OF MEMORY TO ALLOCATE FOR FILE LIST + + +CMultiSelFileDialog::CMultiSelFileDialog( CWnd *pParentWnd ) + :CFileDialog( TRUE, NULL, "*.*", + OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT | OFN_NOCHANGEDIR, + "All Files (*.*) |*.* ||", pParentWnd ) +{ + // ALLOCATE MEMORY FOR FILE LIST + pszFileList = (PCHAR) new char[FILELIST_BUFFSIZE]; + + // SET ALLOCATED BUFFER AS FILENAME BUFER IN OPENFILENAME STRUCT + // AND REPLACE IT IN THE OPENFILENAME STRUCT + pszOldPtr = m_ofn.lpstrFile; + m_ofn.lpstrFile = pszFileList; + m_ofn.nMaxFile = FILELIST_BUFFSIZE; + + // DO SOME INITIALIZATION + memset( pszFileList, 0, FILELIST_BUFFSIZE ); + strcpy( pszFileList, "*.*" ); + memset( szPath, 0, sizeof(szPath) ); + nPathLen = 0; + Done = TRUE; +} + + +CMultiSelFileDialog::~CMultiSelFileDialog() +{ + // REPLACE OLD POINTER AND FREE MEMORY + m_ofn.lpstrFile = pszOldPtr; + delete pszFileList; +} + + +BOOL CMultiSelFileDialog::GetFirstFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ) +{ + PCHAR pszToken; + + nPathLen = 0; + Done = FALSE; + + // GET THE FIRST TOKEN WHICH SHOULD BE THE PATH + if( strchr( pszFileList, ' ' ) == NULL ) + { + // COULD NOT FIND TOKEN SO MUST BE PATH AND FILENAME + + Done = TRUE; + + memset( szPath, 0, sizeof(szPath) ); + nPathLen = 0; + + // MAKE SURE THE FILENAME + PATH WILL FIT + if( strlen( pszFileList ) > nPathBuffSize ) + { + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // CREATE FILENAME ONLY + strcpy( pszFilenameBuff, GetFileName() ); + strcat( pszFilenameBuff, "." ); + strcat( pszFilenameBuff, GetFileExt() ); + + // COPY PATH AND FILENAME TO BUFFER + strcpy( pszFullPathBuff, pszFileList ); + + return TRUE; + } + + // GET THE FIRST TOKEN WHICH SHOULD BE THE PATH + if( (pszToken = strtok( pszFileList, " " )) == NULL ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + memset( szPath, 0, sizeof(szPath) ); + strcpy( szPath, pszToken ); + strcat( szPath, "\\" ); + + nPathLen = strlen( szPath ); + + return GetNextFilename( pszFullPathBuff, nPathBuffSize, pszFilenameBuff ); +} + + +// pszFilenameBuff MUST BE AT LEAST 13 BYTES +BOOL CMultiSelFileDialog::GetNextFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ) +{ + PCHAR pszToken; + + if( Done ) + { + return FALSE; + } + + // GET THE NEXT TOKEN WHICH SHOULD BE A FILENAME + if( (pszToken = strtok( NULL, " " )) == NULL ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // MAKE SURE THE FILENAME + PATH WILL FIT + if( (strlen( pszToken ) + nPathLen) > nPathBuffSize ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // COPY PATH AND FILENAME TO BUFFER + strcpy( pszFullPathBuff, szPath ); + strcat( pszFullPathBuff, pszToken ); + + PCHAR pszNameOnly = strrchr( pszFullPathBuff, '\\' ); + + if( (pszNameOnly == NULL) || (strlen(pszNameOnly) > 13) ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + strcpy( pszFilenameBuff, ++pszNameOnly ); + + return TRUE; +} + + + + + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MULTFDLG.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MULTFDLG.H new file mode 100644 index 0000000..d9729e3 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/MULTFDLG.H @@ -0,0 +1,30 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include + +class CMultiSelFileDialog : public CFileDialog +{ + private: + PCHAR pszFileList; + PCHAR pszOldPtr; + int nPathLen; + char szPath[80]; + BOOL Done; + + public: + CMultiSelFileDialog( CWnd *pParentWnd ); + ~CMultiSelFileDialog(); + BOOL GetFirstFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ); + BOOL GetNextFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ); +}; diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/SPAN.ICO b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/SPAN.ICO new file mode 100644 index 0000000..b718392 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/SPAN.ICO differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/SPAN.RC2 b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/SPAN.RC2 new file mode 100644 index 0000000..1dd2e43 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/SPAN.RC2 @@ -0,0 +1,52 @@ +// +// SPAN.RC2 - resources App Studio does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by App Studio +#endif //APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// Version stamp for this .EXE + +#include "ver.h" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG|VS_FF_PRIVATEBUILD|VS_FF_PRERELEASE +#else + FILEFLAGS 0 // final version +#endif + FILEOS VOS_DOS_WINDOWS16 + FILETYPE VFT_APP + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "SPAN MFC Application\0" + VALUE "FileVersion", "1.0.001\0" + VALUE "InternalName", "SPAN\0" + VALUE "LegalCopyright", "\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename","SPAN.EXE\0" + VALUE "ProductName", "SPAN\0" + VALUE "ProductVersion", "1.0.001\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + // English language (0x409) and the Windows ANSI codepage (1252) + END +END + +///////////////////////////////////////////////////////////////////////////// +// Add additional manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/TOOLBAR.BMP b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/TOOLBAR.BMP new file mode 100644 index 0000000..49695e2 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RES/TOOLBAR.BMP differ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RESOURCE.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RESOURCE.H new file mode 100644 index 0000000..2438033 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/RESOURCE.H @@ -0,0 +1,33 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +//{{NO_DEPENDENCIES}} +// App Studio generated include file. +// Used by SPAN.RC +// +#define IDR_MAINFRAME 2 +#define IDD_ABOUTBOX 100 +#define IDM_COMPRESS_FILES 32772 +#define IDM_UNCOMPRESS_FILES 32773 +#define IDM_CMP_BINARY 32774 +#define IDM_CMP_ASCII 32775 +#define IDM_DICT_SIZE_1024 32777 +#define IDM_DICT_SIZE_2048 32778 +#define IDM_DICT_SIZE_4096 32779 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.CPP new file mode 100644 index 0000000..bf25012 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.CPP @@ -0,0 +1,139 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// span.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "span.h" + +#include "mainfrm.h" +#include "spandoc.h" +#include "spanview.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSpanApp + +BEGIN_MESSAGE_MAP(CSpanApp, CWinApp) + //{{AFX_MSG_MAP(CSpanApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSpanApp construction + +CSpanApp::CSpanApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CSpanApp object + +CSpanApp NEAR theApp; + +///////////////////////////////////////////////////////////////////////////// +// CSpanApp initialization + +BOOL CSpanApp::InitInstance() +{ + // 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. + + OkToExit = TRUE; + + SetDialogBkColor(); // Set dialog background color to gray + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(CSpanDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CSpanView)); + AddDocTemplate(pDocTemplate); + + // create a new (empty) document + OnFileNew(); + + if (m_lpCmdLine[0] != '\0') + { + // TODO: add command line processing here + } + + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + +// Implementation +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CSpanApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CSpanApp commands diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.H new file mode 100644 index 0000000..e5335e5 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.H @@ -0,0 +1,47 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// span.h : main header file for the SPAN application +// + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +#define WM_TURN_OFF_HELP WM_USER+1 +#define WM_TURN_ON_HELP WM_USER+2 + +///////////////////////////////////////////////////////////////////////////// +// CSpanApp: +// See span.cpp for the implementation of this class +// + +class CSpanApp : public CWinApp +{ +public: + CSpanApp(); + + BOOL OkToExit; + +// Overrides + virtual BOOL InitInstance(); + +// Implementation + + //{{AFX_MSG(CSpanApp) + afx_msg void OnAppAbout(); + // 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() +}; + + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.MAK b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.MAK new file mode 100644 index 0000000..47220a5 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.MAK @@ -0,0 +1,297 @@ +# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE No configuration specified. Defaulting to Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "SPAN.MAK" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Win32 Debug" +MTL=MkTypLib.exe +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win32 Release" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "WinRel" +# PROP BASE Intermediate_Dir "WinRel" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "WinRel" +# PROP Intermediate_Dir "WinRel" +OUTDIR=.\WinRel +INTDIR=.\WinRel + +ALL : $(OUTDIR)/SPAN.exe $(OUTDIR)/SPAN.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE CPP /nologo /MD /W3 /GX /YX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /FR /c +# ADD CPP /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"STDAFX.H" /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"SPAN.pch" /Yu"STDAFX.H" /Fo$(INTDIR)/ /c +CPP_OBJS=.\WinRel/ +# ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"SPAN.res" /d "NDEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"SPAN.bsc" + +$(OUTDIR)/SPAN.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 oldnames.lib pkwdcl.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /MACHINE:IX86 +# ADD LINK32 oldnames.lib implodei.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /MACHINE:IX86 +# SUBTRACT LINK32 /INCREMENTAL:yes +LINK32_FLAGS=oldnames.lib implodei.lib /NOLOGO /STACK:0x10240\ + /SUBSYSTEM:windows /INCREMENTAL:no /PDB:$(OUTDIR)/"SPAN.pdb" /MACHINE:IX86\ + /OUT:$(OUTDIR)/"SPAN.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/SPAN.res \ + $(INTDIR)/STDAFX.OBJ \ + $(INTDIR)/SPAN.OBJ \ + $(INTDIR)/MAINFRM.OBJ \ + $(INTDIR)/SPANDOC.OBJ \ + $(INTDIR)/SPANVIEW.OBJ \ + $(INTDIR)/DCL.OBJ \ + $(INTDIR)/MULTFDLG.OBJ + +$(OUTDIR)/SPAN.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "WinDebug" +# PROP BASE Intermediate_Dir "WinDebug" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "WinDebug" +# PROP Intermediate_Dir "WinDebug" +OUTDIR=.\WinDebug +INTDIR=.\WinDebug + +ALL : $(OUTDIR)/SPAN.exe $(OUTDIR)/SPAN.bsc + +$(OUTDIR) : + if not exist $(OUTDIR)/nul mkdir $(OUTDIR) + +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE CPP /nologo /MD /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /FR /c +# ADD CPP /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"STDAFX.H" /c +# SUBTRACT CPP /Fr +CPP_PROJ=/nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"SPAN.pch" /Yu"STDAFX.H" /Fo$(INTDIR)/\ + /Fd$(OUTDIR)/"SPAN.pdb" /c +CPP_OBJS=.\WinDebug/ +# ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" +RSC_PROJ=/l 0x409 /fo$(INTDIR)/"SPAN.res" /d "_DEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +BSC32_SBRS= \ + +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"SPAN.bsc" + +$(OUTDIR)/SPAN.bsc : $(OUTDIR) $(BSC32_SBRS) +LINK32=link.exe +# ADD BASE LINK32 oldnames.lib pkwdcl.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /DEBUG /MACHINE:IX86 +# ADD LINK32 oldnames.lib implodei.lib /NOLOGO /STACK:0x10240 /SUBSYSTEM:windows /INCREMENTAL:no /DEBUG /MACHINE:IX86 +LINK32_FLAGS=oldnames.lib implodei.lib /NOLOGO /STACK:0x10240\ + /SUBSYSTEM:windows /INCREMENTAL:no /PDB:$(OUTDIR)/"SPAN.pdb" /DEBUG\ + /MACHINE:IX86 /OUT:$(OUTDIR)/"SPAN.exe" +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/SPAN.res \ + $(INTDIR)/STDAFX.OBJ \ + $(INTDIR)/SPAN.OBJ \ + $(INTDIR)/MAINFRM.OBJ \ + $(INTDIR)/SPANDOC.OBJ \ + $(INTDIR)/SPANVIEW.OBJ \ + $(INTDIR)/DCL.OBJ \ + $(INTDIR)/MULTFDLG.OBJ + +$(OUTDIR)/SPAN.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Group "Source Files" + +################################################################################ +# Begin Source File + +SOURCE=.\SPAN.RC +DEP_SPAN_=\ + .\RES\SPAN.ICO\ + .\RES\TOOLBAR.BMP\ + .\resource.h\ + .\res\span.rc2 + +$(INTDIR)/SPAN.res : $(SOURCE) $(DEP_SPAN_) $(INTDIR) + $(RSC) $(RSC_PROJ) $(SOURCE) + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STDAFX.CPP +DEP_STDAF=\ + .\stdafx.h + +!IF "$(CFG)" == "Win32 Release" + +# ADD BASE CPP /Yc"STDAFX.H" +# ADD CPP /Yc"STDAFX.H" + +$(INTDIR)/STDAFX.OBJ : $(SOURCE) $(DEP_STDAF) $(INTDIR) + $(CPP) /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"SPAN.pch" /Yc"STDAFX.H" /Fo$(INTDIR)/ /c\ + $(SOURCE) + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# ADD BASE CPP /Yc"STDAFX.H" +# ADD CPP /Yc"STDAFX.H" + +$(INTDIR)/STDAFX.OBJ : $(SOURCE) $(DEP_STDAF) $(INTDIR) + $(CPP) /nologo /MD /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D\ + "_AFXDLL" /D "_MBCS" /Fp$(OUTDIR)/"SPAN.pch" /Yc"STDAFX.H" /Fo$(INTDIR)/\ + /Fd$(OUTDIR)/"SPAN.pdb" /c $(SOURCE) + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SPAN.CPP +DEP_SPAN_C=\ + .\stdafx.h\ + .\span.h\ + .\mainfrm.h\ + .\spandoc.h\ + .\spanview.h\ + .\resource.h + +$(INTDIR)/SPAN.OBJ : $(SOURCE) $(DEP_SPAN_C) $(INTDIR) $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MAINFRM.CPP +DEP_MAINF=\ + .\stdafx.h\ + .\span.h\ + .\mainfrm.h\ + .\implode.h\ + .\dcl.h\ + .\multfdlg.h\ + .\resource.h + +$(INTDIR)/MAINFRM.OBJ : $(SOURCE) $(DEP_MAINF) $(INTDIR) $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SPANDOC.CPP +DEP_SPAND=\ + .\stdafx.h\ + .\span.h\ + .\spandoc.h\ + .\resource.h + +$(INTDIR)/SPANDOC.OBJ : $(SOURCE) $(DEP_SPAND) $(INTDIR) $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\SPANVIEW.CPP +DEP_SPANV=\ + .\stdafx.h\ + .\span.h\ + .\spandoc.h\ + .\spanview.h\ + .\resource.h + +$(INTDIR)/SPANVIEW.OBJ : $(SOURCE) $(DEP_SPANV) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\DCL.CPP +DEP_DCL_C=\ + .\stdafx.h\ + .\implode.h + +$(INTDIR)/DCL.OBJ : $(SOURCE) $(DEP_DCL_C) $(INTDIR) $(INTDIR)/STDAFX.OBJ + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\MULTFDLG.CPP +DEP_MULTF=\ + .\stdafx.h\ + .\multfdlg.h + +$(INTDIR)/MULTFDLG.OBJ : $(SOURCE) $(DEP_MULTF) $(INTDIR)\ + $(INTDIR)/STDAFX.OBJ + +# End Source File +# End Group +# End Project +################################################################################ diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.RC b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.RC new file mode 100644 index 0000000..15a7b64 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPAN.RC @@ -0,0 +1,214 @@ +//Microsoft App Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#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 + "#include ""res\\span.rc2"" // non-App Studio edited resources\r\n" + "\r\n" + "#include ""afxres.rc"" \011// Standard components\r\n" + "\0" +END + +///////////////////////////////////////////////////////////////////////////////////// +#endif // APSTUDIO_INVOKED + + +////////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +IDR_MAINFRAME ICON DISCARDABLE "RES\\SPAN.ICO" + +////////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDR_MAINFRAME BITMAP MOVEABLE PURE "RES\\TOOLBAR.BMP" + +////////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MAINFRAME MENU PRELOAD DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Compress Files", IDM_COMPRESS_FILES + MENUITEM "&Uncompress Files", IDM_UNCOMPRESS_FILES + MENUITEM SEPARATOR + MENUITEM "E&xit", ID_APP_EXIT + END + POPUP "&Options" + BEGIN + MENUITEM "&ASCII", IDM_CMP_ASCII + MENUITEM "&Binary", IDM_CMP_BINARY + MENUITEM SEPARATOR + MENUITEM "&1024", IDM_DICT_SIZE_1024 + MENUITEM "&2048", IDM_DICT_SIZE_2048 + MENUITEM "&4096", IDM_DICT_SIZE_4096 + END + POPUP "&View" + BEGIN + MENUITEM "&Status Bar", ID_VIEW_STATUS_BAR + END + POPUP "&Help" + BEGIN + MENUITEM "&About Multfile...", ID_APP_ABOUT + END +END + + +////////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 34, 22, 217, 55 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Span" +FONT 8, "MS Sans Serif" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20 + LTEXT "Span Application Version 1.0",IDC_STATIC,40,10,119,8 + LTEXT "Copyright \251 1995",IDC_STATIC,40,25,119,8 + DEFPUSHBUTTON "OK",IDOK,176,6,32,14,WS_GROUP +END + + +////////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + IDR_MAINFRAME "Span Windows Application\n\nSpan Document\n\n\nSpan.Document\nSpan Document" +END + +STRINGTABLE PRELOAD DISCARDABLE +BEGIN + AFX_IDS_APP_TITLE "Span Windows Application" + AFX_IDS_IDLEMESSAGE "Ready" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_INDICATOR_EXT "EXT" + ID_INDICATOR_CAPS "CAP" + ID_INDICATOR_NUM "NUM" + ID_INDICATOR_SCRL "SCRL" + ID_INDICATOR_OVR "OVR" + ID_INDICATOR_REC "REC" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_NEW "Create a new document" + ID_FILE_OPEN "Open an existing document" + ID_FILE_CLOSE "Close the active document" + ID_FILE_SAVE "Save the active document" + ID_FILE_SAVE_AS "Save the active document with a new name" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_APP_ABOUT "Display program information, version number and copyright" + ID_APP_EXIT "Quit the application; prompts to save documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_FILE_MRU_FILE1 "Open this document" + ID_FILE_MRU_FILE2 "Open this document" + ID_FILE_MRU_FILE3 "Open this document" + ID_FILE_MRU_FILE4 "Open this document" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_NEXT_PANE "Switch to the next window pane" + ID_PREV_PANE "Switch back to the previous window pane" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_EDIT_CLEAR "Erase the selection" + ID_EDIT_CLEAR_ALL "Erase everything" + ID_EDIT_COPY "Copy the selection and put it on the Clipboard" + ID_EDIT_CUT "Cut the selection and put it on the Clipboard" + ID_EDIT_FIND "Find the specified text" + ID_EDIT_PASTE "Insert Clipboard contents" + ID_EDIT_REPEAT "Repeat the last action" + ID_EDIT_REPLACE "Replace specific text with different text" + ID_EDIT_SELECT_ALL "Select the entire document" + ID_EDIT_UNDO "Undo the last action" + ID_EDIT_REDO "Redo the previously undone action" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_VIEW_TOOLBAR "Show or hide the toolbar" + ID_VIEW_STATUS_BAR "Show or hide the status bar" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCSIZE "Change the window size" + AFX_IDS_SCMOVE "Change the window position" + AFX_IDS_SCMINIMIZE "Reduce the window to an icon" + AFX_IDS_SCMAXIMIZE "Enlarge the window to full size" + AFX_IDS_SCNEXTWINDOW "Switch to the next document window" + AFX_IDS_SCPREVWINDOW "Switch to the previous document window" + AFX_IDS_SCCLOSE "Close the active window and prompts to save the documents" +END + +STRINGTABLE DISCARDABLE +BEGIN + AFX_IDS_SCRESTORE "Restore the window to normal size" + AFX_IDS_SCTASKLIST "Activate Task List" +END + + +#ifndef APSTUDIO_INVOKED +//////////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#include "res\span.rc2" // non-App Studio edited resources + +#include "afxres.rc" // Standard components + +///////////////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANDOC.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANDOC.CPP new file mode 100644 index 0000000..e268f55 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANDOC.CPP @@ -0,0 +1,88 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// spandoc.cpp : implementation of the CSpanDoc class +// + +#include "stdafx.h" +#include "span.h" + +#include "spandoc.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CSpanDoc + +IMPLEMENT_DYNCREATE(CSpanDoc, CDocument) + +BEGIN_MESSAGE_MAP(CSpanDoc, CDocument) + //{{AFX_MSG_MAP(CSpanDoc) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSpanDoc construction/destruction + +CSpanDoc::CSpanDoc() +{ + // TODO: add one-time construction code here +} + +CSpanDoc::~CSpanDoc() +{ +} + +BOOL CSpanDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // TODO: add reinitialization code here + // (SDI documents will reuse this document) + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +// CSpanDoc serialization + +void CSpanDoc::Serialize(CArchive& ar) +{ + if (ar.IsStoring()) + { + // TODO: add storing code here + } + else + { + // TODO: add loading code here + } +} + +///////////////////////////////////////////////////////////////////////////// +// CSpanDoc diagnostics + +#ifdef _DEBUG +void CSpanDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CSpanDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CSpanDoc commands diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANDOC.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANDOC.H new file mode 100644 index 0000000..fe29226 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANDOC.H @@ -0,0 +1,45 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// spandoc.h : interface of the CSpanDoc class +// +///////////////////////////////////////////////////////////////////////////// + +class CSpanDoc : public CDocument +{ +protected: // create from serialization only + CSpanDoc(); + DECLARE_DYNCREATE(CSpanDoc) + +// Attributes +public: +// Operations +public: + +// Implementation +public: + virtual ~CSpanDoc(); + virtual void Serialize(CArchive& ar); // overridden for document i/o +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + virtual BOOL OnNewDocument(); + +// Generated message map functions +protected: + //{{AFX_MSG(CSpanDoc) + // 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() +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANVIEW.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANVIEW.CPP new file mode 100644 index 0000000..c7fc730 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANVIEW.CPP @@ -0,0 +1,125 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// spanview.cpp : implementation of the CSpanView class +// + +#include "stdafx.h" +#include "span.h" + +#include "spandoc.h" +#include "spanview.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char BASED_CODE THIS_FILE[] = __FILE__; +#endif + + +char szHelpMsg[] = { + "To compress multiple files: Select Compress Files from the File " + "menu, and use the shift and control keys with the mouse to " + "highlight multiple files. Press Ok after selecting the files. " + "Enter the path and name of file to compress the selected files " + "to.\n\n" + "To uncompress a file: Select Uncompress Files from the File menu, " + "and enter or select the file to uncompress, then press the Ok " + "button. The files will be uncompressed to " }; + +extern char far *UncompressDir; + +///////////////////////////////////////////////////////////////////////////// +// CSpanView + +IMPLEMENT_DYNCREATE(CSpanView, CView) + +BEGIN_MESSAGE_MAP(CSpanView, CView) + //{{AFX_MSG_MAP(CSpanView) + ON_MESSAGE( WM_TURN_OFF_HELP, OnTurnOffHelp ) + ON_MESSAGE( WM_TURN_ON_HELP, OnTurnOnHelp ) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSpanView construction/destruction + +CSpanView::CSpanView() +{ + bDisplayHelp = TRUE; +} + +CSpanView::~CSpanView() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// CSpanView drawing + +void CSpanView::OnDraw(CDC* pDC) +{ + CSpanDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + + // TODO: add draw code for native data here + if( bDisplayHelp ) + { + RECT rect; + char *pszHelpString; + + pszHelpString = new char[1024]; + + strcpy( pszHelpString, szHelpMsg ); + strcat( pszHelpString, UncompressDir ); + + pDC->SetBkMode( TRANSPARENT ); + GetClientRect( &rect ); + pDC->DrawText( pszHelpString, -1, &rect, DT_LEFT | DT_WORDBREAK ); + } +} + +///////////////////////////////////////////////////////////////////////////// +// CSpanView diagnostics + +#ifdef _DEBUG +void CSpanView::AssertValid() const +{ + CView::AssertValid(); +} + +void CSpanView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CSpanDoc* CSpanView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSpanDoc))); + return (CSpanDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CSpanView message handlers + +LRESULT CSpanView::OnTurnOffHelp( WPARAM wParam, LPARAM lParam ) +{ + bDisplayHelp = FALSE; + InvalidateRect( NULL, TRUE ); + + return 0; +} + +LRESULT CSpanView::OnTurnOnHelp( WPARAM wParam, LPARAM lParam ) +{ + bDisplayHelp = TRUE; + InvalidateRect( NULL, TRUE ); + + return 0; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANVIEW.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANVIEW.H new file mode 100644 index 0000000..8833a0e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/SPANVIEW.H @@ -0,0 +1,54 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +// spanview.h : interface of the CSpanView class +// +///////////////////////////////////////////////////////////////////////////// + +class CSpanView : public CView +{ +private: + BOOL bDisplayHelp; + +protected: // create from serialization only + CSpanView(); + DECLARE_DYNCREATE(CSpanView) + +// Attributes +public: + CSpanDoc* GetDocument(); + +// Operations +public: + +// Implementation +public: + virtual ~CSpanView(); + virtual void OnDraw(CDC* pDC); // overridden to draw this view + afx_msg LRESULT OnTurnOffHelp( WPARAM wParam, LPARAM lParam ); + afx_msg LRESULT OnTurnOnHelp( WPARAM wParam, LPARAM lParam ); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CSpanView) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#ifndef _DEBUG // debug version in spanview.cpp +inline CSpanDoc* CSpanView::GetDocument() + { return (CSpanDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/STDAFX.CPP b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/STDAFX.CPP new file mode 100644 index 0000000..07f7b46 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/STDAFX.CPP @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// stdafx.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/STDAFX.H b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/STDAFX.H new file mode 100644 index 0000000..6179a32 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/MFC/SPAN/STDAFX.H @@ -0,0 +1,7 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#include // MFC core and standard components +#include // MFC extensions (including VB) diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/APPLDOCV.ICO b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/APPLDOCV.ICO new file mode 100644 index 0000000..b4843af Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/APPLDOCV.ICO differ diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/DCL.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/DCL.CPP new file mode 100644 index 0000000..6b5f7c1 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/DCL.CPP @@ -0,0 +1,478 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +/* + * DCL.cpp - File to call various DCL DLL functions + */ + +#include +#include + +#include +#include +#include + +#include "implode.h" + +typedef enum +{ + COMPRESSING = 1, + UNCOMPRESSING +} FILEMODE; + +typedef struct +{ + PBYTE Buffer; // POINTER TO BUFFER + UINT CurPos; // CURRENT POSITION IN BUFFER + UINT BuffSize; // SIZE OF THE BUFFER +} BUFFER_BLOCK, *PBUFFER_BLOCK; + +// STRUCT TO PASS TO THE FILE IO FUNCTIONS +typedef struct +{ + BUFFER_BLOCK FileBuff; // FILE BUFFER + BUFFER_BLOCK cmpBuff; // COMPRESSION BUFFER + BUFFER_BLOCK uncmpBuff; // UNCOMPRESSION BUFFER + FILEMODE mode; + DWORD dwCrc; // CRC + UINT nCompressSize; + BOOL ErrorOccurred; // ERROR FLAG +} DATABLOCK, *PDATABLOCK; + +UINT DataType = CMP_ASCII; // GLOBAL FOR DATA TYPE FOR COMPRESSION +UINT DictSize = 4096; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + +static int iLineCnt; // CURRENT LINE TO OUTPUT STRING + + +/********************************************************************* + * + * Function: ReadBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * read requests. If compressing, then the data read is + * in uncompressed form. If compressing, then the data + * read is data that was previously compressed. This + * function is called until zero is returned. + * + * Parameters: buffer -> Address of buffer to read the data into + * iSize -> Number of bytes to read into buffer + * dwParam -> User-defined parameter, in this case a + * pointer to the DATABLOCK + * + * Returns: Number of bytes actually read, or zero on EOF + * + *********************************************************************/ +UINT ReadBuffer( PCHAR buffer, UINT *iSize, void *pParam ) +{ + PDATABLOCK pDataBlock; + PBUFFER_BLOCK pBufferBlock; + UINT iRead; + + pDataBlock = (PDATABLOCK) pParam; + + // IF AN ERROR OCCURRED + if( pDataBlock->ErrorOccurred == TRUE ) + { + return 0; + } + + if( pDataBlock->mode == COMPRESSING ) + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE COMPRESSION BUFFER + pBufferBlock = &pDataBlock->FileBuff; + } + else + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE UNCOMPRESSION BUFFER + pBufferBlock = &pDataBlock->cmpBuff; + } + + if( pBufferBlock->CurPos < pBufferBlock->BuffSize ) + { + UINT BytesLeft = pBufferBlock->BuffSize - pBufferBlock->CurPos; + + // IF REQUESTING MORE BYTES THAN ARE LEFT + if( BytesLeft < *iSize ) + { + // SET NUMBER OF BYTES TO COPY TO WHAT IS LEFT + *iSize = BytesLeft; + } + + // COPY BYTES AND UPDATE COUNTER + memcpy( buffer, (pBufferBlock->Buffer + pBufferBlock->CurPos), *iSize ); + pBufferBlock->CurPos += *iSize; + + iRead = *iSize; + } + else // ELSE - NOTHING LEFT IN BUFFER SO RETURN 0 + { + iRead = 0; + } + + // IF COMPRESSING, THEN CALCULATE THE CRC + if( pDataBlock->mode == COMPRESSING ) + { + pDataBlock->dwCrc = crc32( buffer, &iRead, &pDataBlock->dwCrc ); + } + + return iRead; +} + +/********************************************************************* + * + * Function: WriteBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * write requests. + * + * Parameters: buffer -> Address of buffer to write data from + * iSize -> Number of bytes to write + * dwParam -> User-defined parameter, in this case a + * pointer to the DATABLOCK + * + * Returns: Zero, the return value is not used by the Data + * Compression Library + * + *********************************************************************/ +void WriteBuffer( PCHAR buffer, UINT *iSize, void *pParam ) +{ + PDATABLOCK pDataBlock; + PBUFFER_BLOCK pBufferBlock; + + pDataBlock = (PDATABLOCK) pParam; + + // IF AN ERROR OCCURRED + if( pDataBlock->ErrorOccurred == TRUE ) + { + return; + } + + if( pDataBlock->mode == COMPRESSING ) + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE COMPRESSION BUFFER + pBufferBlock = &pDataBlock->cmpBuff; + + // SINCE COMPRESSING, KEEP A TOTAL OF THE COMPRESSED FILE SIZE + pDataBlock->nCompressSize += *iSize; + } + else + { + // SINCE COMPRESSING THEN WANT TO WRITE DATA TO THE UNCOMPRESSION BUFFER + pBufferBlock = &pDataBlock->uncmpBuff; + } + + // IF NOT OUT OF BUFFER SPACE + if( pBufferBlock->CurPos < pBufferBlock->BuffSize ) + { + // IF WRITING MORE BYTES THAN ARE LEFT + if( (pBufferBlock->BuffSize - pBufferBlock->CurPos) < *iSize ) + { + MessageBox( NULL, "Out of buffer space - #1", "Compression Error", MB_OK ); + pDataBlock->ErrorOccurred = TRUE; + return; + } + + // COPY BYTES AND UPDATE COUNTER + memcpy( (pBufferBlock->Buffer + pBufferBlock->CurPos), + buffer, *iSize ); + pBufferBlock->CurPos += *iSize; + } + else // ELSE - NOTHING LEFT IN BUFFER SO RETURN 0 + { + MessageBox( NULL, "Out of buffer space - #2", "Compression Error", MB_OK ); + pDataBlock->ErrorOccurred = TRUE; + return; + } + + // IF COMPRESSING, THEN CALCULATE THE CRC + if (pDataBlock->mode == UNCOMPRESSING ) + { + pDataBlock->dwCrc = crc32( buffer, iSize, &pDataBlock->dwCrc ); + } + + return; +} + +/********************************************************************* + * + * Function: CompressMemToMem() + * + * Purpose: To compress a buffer to another buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * pnCompressedSize -> Number of bytes in the compressed + * buffer + * pFileBuffer -> Pointer to buffer to compress + * pCompressedBuffer -> Pointer to buffer to place + * compressed data + * BuffSize -> Size of the buffers (both are allocated + * for same number of bytes) + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressMemToMem( HWND hWnd, TDC *pDC, DWORD *pdwCrc, + UINT *pnCompressedSize, PBYTE pFileBuffer, + PBYTE pCompressedBuffer, UINT BuffSize ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + DATABLOCK DataBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + memset( &DataBlock, 0, sizeof(DataBlock) ); + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + DataBlock.mode = COMPRESSING; + DataBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + // SETUP BUFFER BLOCK FOR FILE BUFFER + DataBlock.FileBuff.Buffer = pFileBuffer; + DataBlock.FileBuff.BuffSize = BuffSize; + + // SETUP BUFFER BLOCK FOR COMPRESSION BUFFER + DataBlock.cmpBuff.Buffer = pCompressedBuffer; + DataBlock.cmpBuff.BuffSize = BuffSize; + + wsprintf( szVerbose, "Compressing %u byte buffer to memory ", BuffSize ); + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, szVerbose ); + + // COMPRESS THE FILE + iStatus = implode( ReadBuffer, WriteBuffer, pScratchPad, &DataBlock, + &DataType, &DictSize ); + + // IF THERE WAS AN ERROR COMPRESSING FILE + if( iStatus || DataBlock.ErrorOccurred ) + { + // DISPLAY ERROR STRING IF ERROR OCCURRED IN IMPLODE + wsprintf( szVerbose, "Error occurred while imploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else // ELSE - COMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + DataBlock.dwCrc = ~DataBlock.dwCrc; + + // RETURN CRC + *pdwCrc = DataBlock.dwCrc; + + // RETURN COMPRESSED BUFFER SIZE + *pnCompressedSize = DataBlock.nCompressSize; + + wsprintf( szVerbose, "Compressed file to memory -> CRC = %08lX ", + DataBlock.dwCrc ); + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, szVerbose ); + } + + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: ExpandMemToMem() + * + * Purpose: To expand a compressed buffer to a buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file after uncompression + * pCompressedBuffer -> Pointer to buffer to place + * compressed data + * nCompressedSize -> Number of bytes in the compressed + * buffer + * pUncompressedBuffer -> Pointer to buffer to place + * uncompressed data + * BuffSize -> Size of the uncompressed buffer + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int ExpandMemToMem( HWND hWnd, TDC *pDC, DWORD *pdwCrc, + PBYTE pCompressedBuffer, UINT nCompressedSize, + PBYTE pUncompressedBuffer, UINT BuffSize ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + DATABLOCK DataBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + memset( &DataBlock, 0, sizeof(DataBlock) ); + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + DataBlock.mode = UNCOMPRESSING; + DataBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + // SETUP BUFFER BLOCK FOR COMPRESSION BUFFER + DataBlock.cmpBuff.Buffer = pCompressedBuffer; + DataBlock.cmpBuff.BuffSize = nCompressedSize; + + // SETUP BUFFER BLOCK FOR UNCOMPRESSION BUFFER + DataBlock.uncmpBuff.Buffer = pUncompressedBuffer; + DataBlock.uncmpBuff.BuffSize = BuffSize; + + wsprintf( szVerbose, "Compressed buffer size = %u ", nCompressedSize ); + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, szVerbose ); + + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, "Uncompressing buffer to memory " ); + + // UNCOMPRESS THE FILE + iStatus = explode( ReadBuffer, WriteBuffer, pScratchPad, &DataBlock ); + + // IF THERE WAS AN ERROR UNCOMPRESSING FILE + if( iStatus || DataBlock.ErrorOccurred ) + { + // DISPLAY ERROR STRING IF ERROR OCCURRED IN IMPLODE + wsprintf( szVerbose, "Error occurred while exploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else // ELSE - UNCOMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + DataBlock.dwCrc = ~DataBlock.dwCrc; + + // RETURN CRC + *pdwCrc = DataBlock.dwCrc; + + wsprintf( szVerbose, "Uncompressed file to memory -> CRC = %08lX ", + DataBlock.dwCrc ); + pDC->TextOut( 10, (iLineCnt++ * 20) + 5, szVerbose ); + } + + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: MemToMemExample() + * + * Purpose: To load a file into memory. Then compress and uncompress + * the buffer in memory. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszFilename -> Name of file to load + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int MemToMemExample( HWND hWnd, TDC *pDC, PCHAR pszFilename ) +{ + TFile InFile; + int rc=1; // RETURN CODE + UINT BufferSize; + UINT cmpSize; + PBYTE pFileBuffer; // BUFFER FOR FILE DATA + PBYTE pCompressedBuffer; // BUFFER FOR THE COMPRESSED DATA + PBYTE pUncompressedBuffer; // BUFFER FOR THE UNCOMPRESSED DATA + DWORD cmpCrc; // CRC OF FILE BEFORE COMPRESSION + DWORD uncmpCrc; // CRC OF FILE AFTER UNCOMPRESSION + + + iLineCnt = 0; + + // OPEN THE FILE + if( !InFile.Open( pszFilename, TFile::ReadOnly, TFile::PermRdWr ) ) + { + MessageBox( hWnd, "Error opening file for compression", "Error", MB_OK ); + return 0; + } + + // CHECK IF FILE IS TOO LARGE + if( InFile.Length() > 64000U ) + { + MessageBox( hWnd, "File is too large to compress to memory", "Error", MB_OK ); + return 0; + } + + BufferSize = (UINT) InFile.Length(); + + // ALLOCATE BUFFER MEMORY + pFileBuffer = (PBYTE) new char[BufferSize]; + pCompressedBuffer = (PBYTE) new char[BufferSize]; + pUncompressedBuffer = (PBYTE) new char[BufferSize]; + + // IF SUCCESSFULLY ALLOCATED MEMORY + if( (pFileBuffer != NULL) && + (pCompressedBuffer != NULL) && + (pUncompressedBuffer != NULL) ) + { + // READ FILE + InFile.Read( pFileBuffer, BufferSize ); + + // IF COMPRESSED OK + if( CompressMemToMem( hWnd, pDC, &cmpCrc, &cmpSize, + pFileBuffer, pCompressedBuffer, BufferSize ) ) + { + // IF ERROR UNCOMPRESSING + if( !ExpandMemToMem( hWnd, pDC, &uncmpCrc, + pCompressedBuffer, cmpSize, + pUncompressedBuffer, BufferSize ) ) + { + MessageBox( hWnd, "Error uncompressing to memory", "Error", MB_OK ); + rc = 0; + } + } + else + { + MessageBox( hWnd, "Error compressing to memory", "Error", MB_OK ); + rc = 0; + } + } + + + if( pFileBuffer != NULL ) + { + delete pFileBuffer; + } + + if( pCompressedBuffer != NULL ) + { + delete pCompressedBuffer; + } + + if( pUncompressedBuffer != NULL ) + { + delete pUncompressedBuffer; + } + + return rc; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/DCL.H b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/DCL.H new file mode 100644 index 0000000..0ea3138 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/DCL.H @@ -0,0 +1,10 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +int MemToMemExample( HWND hWnd, TDC *pDC, LPSTR lpszFilename ); diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/IMPBORLI.LIB b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/IMPBORLI.LIB new file mode 100644 index 0000000..9ef7765 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/IMPBORLI.LIB differ diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MEM2MEM.IDE b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MEM2MEM.IDE new file mode 100644 index 0000000..9b1898b Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MEM2MEM.IDE differ diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMABD.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMABD.CPP new file mode 100644 index 0000000..f24049e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMABD.CPP @@ -0,0 +1,157 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include +#pragma hdrstop + +#if !defined(__FLAT__) +#include +#endif + +#include "mm2mmapp.h" +#include "mm2mmabd.h" + + +ProjectRCVersion::ProjectRCVersion (TModule *module) +{ + char appFName[255]; + char subBlockName[255]; + DWORD fvHandle; + UINT vSize; + + FVData = 0; + + module->GetModuleFileName(appFName, sizeof(appFName)); + OemToAnsi(appFName, appFName); + DWORD dwSize = ::GetFileVersionInfoSize(appFName, &fvHandle); + if (dwSize) { + FVData = (void FAR *)new char[(UINT)dwSize]; + if (::GetFileVersionInfo(appFName, fvHandle, dwSize, FVData)) { + // Copy string to buffer so if the -dc compiler switch (Put constant strings in code segments) + // is on VerQueryValue will work under Win16. This works around a problem in Microsoft's ver.dll + // which writes to the string pointed to by subBlockName. + strcpy(subBlockName, "\\VarFileInfo\\Translation"); + if (!::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)&TransBlock, &vSize)) { + delete FVData; + FVData = 0; + } else + // Swap the words so wsprintf will print the lang-charset in the correct format. + *(DWORD *)TransBlock = MAKELONG(HIWORD(*(DWORD *)TransBlock), LOWORD(*(DWORD *)TransBlock)); + } + } +} + + +ProjectRCVersion::~ProjectRCVersion () +{ + if (FVData) + delete FVData; +} + + +bool ProjectRCVersion::GetProductName (LPSTR &prodName) +{ + UINT vSize; + char subBlockName[255]; + + wsprintf(subBlockName, "\\StringFileInfo\\%08lx\\%s", *(DWORD *)TransBlock, (LPSTR)"ProductName"); + return FVData ? ::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)&prodName, &vSize) : false; +} + + +bool ProjectRCVersion::GetProductVersion (LPSTR &prodVersion) +{ + UINT vSize; + char subBlockName[255]; + + wsprintf(subBlockName, "\\StringFileInfo\\%08lx\\%s", *(DWORD *)TransBlock, (LPSTR)"ProductVersion"); + return FVData ? ::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)&prodVersion, &vSize) : false; +} + + +bool ProjectRCVersion::GetCopyright (LPSTR ©right) +{ + UINT vSize; + char subBlockName[255]; + + wsprintf(subBlockName, "\\StringFileInfo\\%08lx\\%s", *(DWORD *)TransBlock, (LPSTR)"LegalCopyright"); + return FVData ? ::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)©right, &vSize) : false; +} + + +bool ProjectRCVersion::GetDebug (LPSTR &debug) +{ + UINT vSize; + char subBlockName[255]; + + wsprintf(subBlockName, "\\StringFileInfo\\%08lx\\%s", *(DWORD *)TransBlock, (LPSTR)"SpecialBuild"); + return FVData ? ::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)&debug, &vSize) : false; +} + + +//{{mem2memAboutDlg Implementation}} + + +////////////////////////////////////////////////////////// +// mem2memAboutDlg +// ========== +// Construction/Destruction handling. +mem2memAboutDlg::mem2memAboutDlg (TWindow *parent, TResId resId, TModule *module) + : TDialog(parent, resId, module) +{ + // INSERT>> Your constructor code here. +} + + +mem2memAboutDlg::~mem2memAboutDlg () +{ + Destroy(); + + // INSERT>> Your destructor code here. +} + + +void mem2memAboutDlg::SetupWindow () +{ + LPSTR prodName = 0, prodVersion = 0, copyright = 0, debug = 0; + + // Get the static text for the value based on VERSIONINFO. + TStatic *versionCtrl = new TStatic(this, IDC_VERSION, 255); + TStatic *copyrightCtrl = new TStatic(this, IDC_COPYRIGHT, 255); + TStatic *debugCtrl = new TStatic(this, IDC_DEBUG, 255); + + TDialog::SetupWindow(); + + // Process the VERSIONINFO. + ProjectRCVersion applVersion(GetModule()); + + // Get the product name and product version strings. + if (applVersion.GetProductName(prodName) && applVersion.GetProductVersion(prodVersion)) { + // IDC_VERSION is the product name and version number, the initial value of IDC_VERSION is + // the word Version (in whatever language) product name VERSION product version. + char buffer[255]; + char versionName[128]; + + buffer[0] = '\0'; + versionName[0] = '\0'; + + versionCtrl->GetText(versionName, sizeof(versionName)); + wsprintf(buffer, "%s %s %s", prodName, versionName, prodVersion); + + versionCtrl->SetText(buffer); + } + + //Get the legal copyright string. + if (applVersion.GetCopyright(copyright)) + copyrightCtrl->SetText(copyright); + + // Only get the SpecialBuild text if the VERSIONINFO resource is there. + if (applVersion.GetDebug(debug)) + debugCtrl->SetText(debug); +} diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMABD.H b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMABD.H new file mode 100644 index 0000000..1ea0c5e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMABD.H @@ -0,0 +1,53 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#if !defined(__mm2mmabd_h) // Sentry, use file only if it's not already included. +#define __mm2mmabd_h + +#include +#pragma hdrstop + +#include "mm2mmapp.rh" // Definition of all resources. + + +//{{TDialog = mem2memAboutDlg}} +class mem2memAboutDlg : public TDialog { +public: + mem2memAboutDlg (TWindow *parent, TResId resId = IDD_ABOUT, TModule *module = 0); + virtual ~mem2memAboutDlg (); + +//{{mem2memAboutDlgVIRTUAL_BEGIN}} +public: + void SetupWindow (); +//{{mem2memAboutDlgVIRTUAL_END}} +}; //{{mem2memAboutDlg}} + + +// Reading the VERSIONINFO resource. +class ProjectRCVersion { +public: + ProjectRCVersion (TModule *module); + virtual ~ProjectRCVersion (); + + bool GetProductName (LPSTR &prodName); + bool GetProductVersion (LPSTR &prodVersion); + bool GetCopyright (LPSTR ©right); + bool GetDebug (LPSTR &debug); + +protected: + LPBYTE TransBlock; + void FAR *FVData; + +private: + // Don't allow this object to be copied. + ProjectRCVersion (const ProjectRCVersion &); + ProjectRCVersion & operator =(const ProjectRCVersion &); +}; + + +#endif // __mm2mmabd_h sentry. diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.CPP new file mode 100644 index 0000000..6ba50c8 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.CPP @@ -0,0 +1,208 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include +#pragma hdrstop + +#include "mm2mmapp.h" +#include "mm2mmedv.h" // Definition of client class. +#include "mm2mmabd.h" // Definition of about dialog. +#include "dcl.h" + +//{{mem2memApp Implementation}} + + + +//{{DOC_VIEW}} +DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, mem2memEditView, DocType1); +//{{DOC_VIEW_END}} + +//{{DOC_MANAGER}} +DocType1 __dvt1("All Files (*.*)", "*.*", 0, "TXT", dtAutoDelete | dtUpdateDir); +//{{DOC_MANAGER_END}} + + +// +// Build a response table for all messages/commands handled +// by the application. +// +DEFINE_RESPONSE_TABLE1(mem2memApp, TApplication) +//{{mem2memAppRSP_TBL_BEGIN}} + EV_OWLVIEW(dnCreate, EvNewView), + EV_OWLVIEW(dnClose, EvCloseView), + EV_COMMAND(CM_HELPABOUT, CmHelpAbout), +//{{mem2memAppRSP_TBL_END}} +END_RESPONSE_TABLE; + + +////////////////////////////////////////////////////////// +// mem2memApp +// ===== +// +mem2memApp::mem2memApp () : TApplication("mem2mem") +{ + SetDocManager(new TDocManager(dmSDI, this)); + + // INSERT>> Your constructor code here. +} + + +mem2memApp::~mem2memApp () +{ + // INSERT>> Your destructor code here. +} + + + + +////////////////////////////////////////////////////////// +// mem2memApp +// ===== +// Application intialization. +// +void mem2memApp::InitMainWindow () +{ + if (nCmdShow != SW_HIDE) + nCmdShow = (nCmdShow != SW_SHOWMINNOACTIVE) ? SW_SHOWNORMAL : nCmdShow; + + SDIDecFrame *frame = new SDIDecFrame(0, GetName(), 0, true, this); + + // + // Assign ICON w/ this application. + // + frame->SetIcon(this, IDI_SDIAPPLICATION); + + // + // Menu associated with window and accelerator table associated with table. + // + frame->AssignMenu(SDI_MENU); + + // + // Associate with the accelerator table. + // + frame->Attr.AccelTable = SDI_MENU; + + + TStatusBar *sb = new TStatusBar(frame, TGadget::Recessed, + TStatusBar::CapsLock | + TStatusBar::NumLock | + TStatusBar::ScrollLock | + TStatusBar::Overtype); + frame->Insert(*sb, TDecoratedFrame::Bottom); + + SetMainWindow(frame); + + frame->SetMenuDescr(TMenuDescr(SDI_MENU)); + +} + + +////////////////////////////////////////////////////////// +// mem2memApp +// ===== +// Response Table handlers: +// +void mem2memApp::EvNewView (TView& view) +{ + GetMainWindow()->SetClientWindow(view.GetWindow()); + if (!view.IsOK()) + GetMainWindow()->SetClientWindow(0); + else if (view.GetViewMenu()) + GetMainWindow()->MergeMenu(*view.GetViewMenu()); +} + + +void mem2memApp::EvCloseView (TView&) +{ + GetMainWindow()->SetClientWindow(0); + GetMainWindow()->SetCaption("mem2mem"); +} + + +// +// Build a response table for all messages/commands handled +// by the application. +// +DEFINE_RESPONSE_TABLE1(SDIDecFrame, TDecoratedFrame) +//{{SDIDecFrameRSP_TBL_BEGIN}} + EV_COMMAND(CM_TEST_DCL, OnTestDcl), + EV_COMMAND_ENABLE(CM_TEST_DCL, OnTestDclEnable), +//{{SDIDecFrameRSP_TBL_END}} +END_RESPONSE_TABLE; + + +//{{SDIDecFrame Implementation}} + + +SDIDecFrame::SDIDecFrame (TWindow *parent, const char far *title, TWindow *clientWnd, bool trackMenuSelection, TModule *module) + : TDecoratedFrame(parent, title, clientWnd, trackMenuSelection, module) +{ + // INSERT>> Your constructor code here. + +} + + +SDIDecFrame::~SDIDecFrame () +{ + // INSERT>> Your destructor code here. + +} + + +////////////////////////////////////////////////////////// +// mem2memApp +// =========== +// Menu Help About mem2mem.exe command +void mem2memApp::CmHelpAbout () +{ + // + // Show the modal dialog. + // + mem2memAboutDlg(GetMainWindow()).Execute(); +} + + +int OwlMain (int , char* []) +{ + try { + mem2memApp app; + return app.Run(); + } + catch (xmsg& x) { + ::MessageBox(0, x.why().c_str(), "Exception", MB_OK); + } + + return -1; +} + +void SDIDecFrame::OnTestDcl () +{ + TOpenSaveDialog::TData data( OFN_FILEMUSTEXIST|OFN_HIDEREADONLY| + OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR, + "All Files (*.*)|*.*|", 0, "", "*" ); + + if( TFileOpenDialog( this, data ).Execute() == IDOK ) + { + TWindow *ClientWnd = GetClientWindow(); + + // GET DC AND SET THE TEXT BACKGROUND COLOR TO WINDOW BACKGROUND COLOR + TWindowDC dc( ClientWnd->HWindow ); + TColor bkGroundColor = dc.GetPixel( 0, 0 ); + dc.SetBkColor( bkGroundColor ); + + MemToMemExample( ClientWnd->HWindow, &dc, data.FileName ); + } +} + + +void SDIDecFrame::OnTestDclEnable (TCommandEnabler &tce) +{ + tce.Enable( TRUE ); +} + diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.DEF b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.DEF new file mode 100644 index 0000000..b60e724 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.DEF @@ -0,0 +1,8 @@ +NAME mem2mem + +DESCRIPTION 'mem2mem Application' +EXETYPE WINDOWS +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE +HEAPSIZE 4096 +STACKSIZE 8192 diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.H b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.H new file mode 100644 index 0000000..a6a2d39 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.H @@ -0,0 +1,60 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#if !defined(__mm2mmapp_h) // Sentry, use file only if it's not already included. +#define __mm2mmapp_h + +#include +#pragma hdrstop + + +#include "mm2mmapp.rh" // Definition of all resources. + + +// +// FrameWindow must be derived to override Paint for Preview and Print. +// +//{{TDecoratedFrame = SDIDecFrame}} +class SDIDecFrame : public TDecoratedFrame { +public: + SDIDecFrame (TWindow *parent, const char far *title, TWindow *clientWnd, bool trackMenuSelection = false, TModule *module = 0); + ~SDIDecFrame (); + +//{{SDIDecFrameRSP_TBL_BEGIN}} +protected: + void OnTestDcl (); + void OnTestDclEnable (TCommandEnabler &tce); +//{{SDIDecFrameRSP_TBL_END}} +DECLARE_RESPONSE_TABLE(SDIDecFrame); +}; //{{SDIDecFrame}} + + +//{{TApplication = mem2memApp}} +class mem2memApp : public TApplication { +private: + +public: + mem2memApp (); + virtual ~mem2memApp (); + +//{{mem2memAppVIRTUAL_BEGIN}} +public: + virtual void InitMainWindow (); +//{{mem2memAppVIRTUAL_END}} + +//{{mem2memAppRSP_TBL_BEGIN}} +protected: + void EvNewView (TView& view); + void EvCloseView (TView& view); + void CmHelpAbout (); +//{{mem2memAppRSP_TBL_END}} +DECLARE_RESPONSE_TABLE(mem2memApp); +}; //{{mem2memApp}} + + +#endif // __mm2mmapp_h sentry. diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.RC b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.RC new file mode 100644 index 0000000..21c54ba --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.RC @@ -0,0 +1,389 @@ +/* Project mem2mem + PKWARE, INC. + Copyright © 1995. All Rights Reserved. + + SUBSYSTEM: mem2mem.exe Application + FILE: mm2mmapp.rc + AUTHOR: + + + OVERVIEW + ======== + All resources defined here. +*/ + +#if !defined(WORKSHOP_INVOKED) +#include +#endif +#include "mm2mmapp.rh" + +SDI_MENU MENU +{ + POPUP "&File" + { + MENUITEM "&Test Dcl", CM_TEST_DCL + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", CM_EXIT + } + + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + POPUP "&Help" + { + MENUITEM "&About...", CM_HELPABOUT + } + +} + + +// Accelerator table for short-cut to menu commands. (include\owl\editfile.rc) +SDI_MENU ACCELERATORS +BEGIN + VK_DELETE, CM_EDITDELETE, VIRTKEY + VK_DELETE, CM_EDITCUT, VIRTKEY, SHIFT + VK_INSERT, CM_EDITCOPY, VIRTKEY, CONTROL + VK_INSERT, CM_EDITPASTE, VIRTKEY, SHIFT + VK_DELETE, CM_EDITCLEAR, VIRTKEY, CONTROL + VK_BACK, CM_EDITUNDO, VIRTKEY, ALT + VK_F3, CM_EDITFINDNEXT, VIRTKEY +END + + +// Menu merged in when TEditView is active, notice the extra MENUITEM SEPARATORs which are +// for menu negotation. These separators are used as group markers by OWL. +IDM_EDITVIEW MENU +{ + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR +} + + +// Menu merged in when TListView is active, notice the extra MENUITEM SEPARATORs which are +// for menu negotation. These separators are used as group markers by OWL. +IDM_LISTVIEW MENU +{ + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR +} + + +IDM_DOCMANAGERFILE MENU +{ + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", CM_EXIT +} + + +// +// Table of help hints displayed in the status bar. +// +STRINGTABLE +BEGIN + -1, "File/document operations" + CM_FILENEW, "Creates a new document" + CM_FILEOPEN, "Opens an existing document" + CM_VIEWCREATE, "Create a new view for this document" + CM_FILEREVERT, "Reverts changes to last document save" + CM_FILECLOSE, "Close this document" + CM_FILESAVE, "Saves this document" + CM_FILESAVEAS, "Saves this document with a new name" + CM_EXIT, "Quits mem2memApp and prompts to save the documents" + CM_EDITUNDO-1, "Edit operations" + CM_EDITUNDO, "Reverses the last operation" + CM_EDITCUT, "Cuts the selection and puts it on the Clipboard" + CM_EDITCOPY, "Copies the selection and puts it on the Clipboard" + CM_EDITPASTE, "Inserts the clipboard contents at the insertion point" + CM_EDITDELETE, "Deletes the selection" + CM_EDITCLEAR, "Clear the document" + CM_EDITADD, "Insert a new line" + CM_EDITEDIT, "Edit the current line" + CM_EDITFIND-1, "Search/replace operations" + CM_EDITFIND, "Finds the specified text" + CM_EDITREPLACE, "Finds the specified text and changes it" + CM_EDITFINDNEXT, "Finds the next match" + CM_HELPABOUT-1, "Access About" + CM_HELPABOUT, "About the mem2mem application" +END + + +// +// OWL string table +// + +// EditFile (include\owl\editfile.rc and include\owl\editsear.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_CANNOTFIND, "Cannot find ""%s""." + IDS_UNABLEREAD, "Unable to read file %s from disk." + IDS_UNABLEWRITE, "Unable to write file %s to disk." + IDS_FILECHANGED, "The text in the %s file has changed.\n\nDo you want to save the changes?" + IDS_FILEFILTER, "Text files (*.TXT)|*.TXT|AllFiles (*.*)|*.*|" +END + + +// ListView (include\owl\listview.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_LISTNUM, "Line number %d" +END + + +// Doc/View (include\owl\docview.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_DOCMANAGERFILE, "&File" + IDS_DOCLIST, "--Document Type--" + IDS_VIEWLIST, "--View Type--" + IDS_UNTITLED, "Document" + IDS_UNABLEOPEN, "Unable to open document." + IDS_UNABLECLOSE, "Unable to close document." + IDS_READERROR, "Document read error." + IDS_WRITEERROR, "Document write error." + IDS_DOCCHANGED, "The document has been changed.\n\nDo you want to save the changes?" + IDS_NOTCHANGED, "The document has not been changed." + IDS_NODOCMANAGER, "Document Manager not present." + IDS_NOMEMORYFORVIEW, "Insufficient memory for view." + IDS_DUPLICATEDOC, "Document already loaded." +END + + +// Exception string resources (include\owl\except.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_OWLEXCEPTION, "ObjectWindows Exception" + IDS_UNHANDLEDXMSG, "Unhandled Exception" + IDS_OKTORESUME, "OK to resume?" + IDS_UNKNOWNEXCEPTION, "Unknown exception" + + IDS_UNKNOWNERROR, "Unknown error" + IDS_NOAPP, "No application object" + IDS_OUTOFMEMORY, "Out of memory" + IDS_INVALIDMODULE, "Invalid module specified for window" + IDS_INVALIDMAINWINDOW, "Invalid MainWindow" + IDS_VBXLIBRARYFAIL, "VBX Library init failure" + + IDS_INVALIDWINDOW, "Invalid window %s" + IDS_INVALIDCHILDWINDOW, "Invalid child window %s" + IDS_INVALIDCLIENTWINDOW, "Invalid client window %s" + + IDS_CLASSREGISTERFAIL, "Class registration fail for window %s" + IDS_CHILDREGISTERFAIL, "Child class registration fail for window %s" + IDS_WINDOWCREATEFAIL, "Create fail for window %s" + IDS_WINDOWEXECUTEFAIL, "Execute fail for window %s" + IDS_CHILDCREATEFAIL, "Child create fail for window %s" + + IDS_MENUFAILURE, "Menu creation failure" + IDS_VALIDATORSYNTAX, "Validator syntax error" + IDS_PRINTERERROR, "Printer error" + + IDS_LAYOUTINCOMPLETE, "Incomplete layout constraints specified in window %s" + IDS_LAYOUTBADRELWIN, "Invalid relative window specified in layout constraint in window %s" + + IDS_GDIFAILURE, "GDI failure" + IDS_GDIALLOCFAIL, "GDI allocate failure" + IDS_GDICREATEFAIL, "GDI creation failure" + IDS_GDIRESLOADFAIL, "GDI resource load failure" + IDS_GDIFILEREADFAIL, "GDI file read failure" + IDS_GDIDELETEFAIL, "GDI object %X delete failure" + IDS_GDIDESTROYFAIL, "GDI object %X destroy failure" + IDS_INVALIDDIBHANDLE, "Invalid DIB handle %X" +END + + +// General Window's status bar messages. (include\owl\statusba.rc) +STRINGTABLE +BEGIN + IDS_MODES "EXT|CAPS|NUM|SCRL|OVR|REC" + IDS_MODESOFF " | | | | | " + SC_SIZE, "Changes the size of the window" + SC_MOVE, "Moves the window to another position" + SC_MINIMIZE, "Reduces the window to an icon" + SC_MAXIMIZE, "Enlarges the window to it maximum size" + SC_RESTORE, "Restores the window to its previous size" + SC_CLOSE, "Closes the window" + SC_TASKLIST, "Opens task list" + SC_NEXTWINDOW, "Switches to next window" +END + + +// Validator messages (include\owl\validate.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_VALPXPCONFORM "Input does not conform to picture:\n""%s""" + IDS_VALINVALIDCHAR "Invalid character in input" + IDS_VALNOTINRANGE "Value is not in the range %ld to %ld." + IDS_VALNOTINLIST "Input is not in valid-list" +END + + +// +// Misc application definitions +// + +// Application ICON +IDI_SDIAPPLICATION ICON "appldocv.ico" + + +// About box. +IDD_ABOUT DIALOG 12, 17, 204, 65 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About mem2mem" +FONT 8, "MS Sans Serif" +BEGIN + CTEXT "Version", IDC_VERSION, 2, 14, 200, 8, SS_NOPREFIX + CTEXT "Memory To Memory Compression", -1, 2, 4, 200, 8, SS_NOPREFIX + CTEXT "", IDC_COPYRIGHT, 2, 27, 200, 17, SS_NOPREFIX + RTEXT "", IDC_DEBUG, 136, 55, 66, 8, SS_NOPREFIX + ICON IDI_SDIAPPLICATION, -1, 2, 2, 34, 34 + DEFPUSHBUTTON "OK", IDOK, 82, 48, 40, 14 +END + + +// TInputDialog class dialog box. +IDD_INPUTDIALOG DIALOG 20, 24, 180, 64 +STYLE WS_POPUP | WS_CAPTION | DS_SETFONT +FONT 8, "Helv" +BEGIN + LTEXT "", ID_PROMPT, 10, 8, 160, 10, SS_NOPREFIX + CONTROL "", ID_INPUT, "EDIT", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, 10, 20, 160, 12 + DEFPUSHBUTTON "&OK", IDOK, 47, 42, 40, 14 + PUSHBUTTON "&Cancel", IDCANCEL, 93, 42, 40, 14 +END + + +// Horizontal slider thumb bitmap for TSlider and VSlider (include\owl\slider.rc) +IDB_HSLIDERTHUMB BITMAP PRELOAD MOVEABLE DISCARDABLE +BEGIN + '42 4D 66 01 00 00 00 00 00 00 76 00 00 00 28 00' + '00 00 12 00 00 00 14 00 00 00 01 00 04 00 00 00' + '00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 10 00 00 00 00 00 00 00 00 00 C0 00 00 C0' + '00 00 00 C0 C0 00 C0 00 00 00 C0 00 C0 00 C0 C0' + '00 00 C0 C0 C0 00 80 80 80 00 00 00 FF 00 00 FF' + '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' + '00 00 FF FF FF 00 BB BB 0B BB BB BB B0 BB BB 00' + '00 00 BB B0 80 BB BB BB 08 0B BB 00 00 00 BB 08' + 'F8 0B BB B0 87 70 BB 00 00 00 B0 8F F8 80 BB 08' + '77 77 0B 00 00 00 08 F8 88 88 00 88 88 87 70 00' + '00 00 0F F7 77 88 00 88 77 77 70 00 00 00 0F F8' + '88 88 00 88 88 87 70 00 00 00 0F F7 77 88 00 88' + '77 77 70 00 00 00 0F F8 88 88 00 88 88 87 70 00' + '00 00 0F F7 77 88 00 88 77 77 70 00 00 00 0F F8' + '88 88 00 88 88 87 70 00 00 00 0F F7 77 88 00 88' + '77 77 70 00 00 00 0F F8 88 88 00 88 88 87 70 00' + '00 00 0F F7 77 88 00 88 77 77 70 00 00 00 0F F8' + '88 88 00 88 88 87 70 00 00 00 0F F7 77 88 00 88' + '77 77 70 00 00 00 0F F8 88 88 00 88 88 87 70 00' + '00 00 0F F7 77 78 00 88 77 77 70 00 00 00 0F FF' + 'FF FF 00 88 88 88 80 00 00 00 B0 00 00 00 BB 00' + '00 00 0B 00 00 00' +END + + +// Vertical slider thumb bitmap for TSlider and HSlider (include\owl\slider.rc) +IDB_VSLIDERTHUMB BITMAP PRELOAD MOVEABLE DISCARDABLE +BEGIN + '42 4D 2A 01 00 00 00 00 00 00 76 00 00 00 28 00' + '00 00 28 00 00 00 09 00 00 00 01 00 04 00 00 00' + '00 00 B4 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 10 00 00 00 00 00 00 00 00 00 C0 00 00 C0' + '00 00 00 C0 C0 00 C0 00 00 00 C0 00 C0 00 C0 C0' + '00 00 C0 C0 C0 00 80 80 80 00 00 00 FF 00 00 FF' + '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' + '00 00 FF FF FF 00 B0 00 00 00 00 00 00 00 00 0B' + 'B0 00 00 00 00 00 00 00 00 0B 0F 88 88 88 88 88' + '88 88 88 80 08 88 88 88 88 88 88 88 88 80 0F 77' + '77 77 77 77 77 77 77 80 08 77 77 77 77 77 77 77' + '77 80 0F 77 FF FF FF FF FF FF F7 80 08 77 FF FF' + 'FF FF FF FF F7 80 0F 70 00 00 00 00 00 00 77 80' + '08 70 00 00 00 00 00 00 77 80 0F 77 77 77 77 77' + '77 77 77 80 08 77 77 77 77 77 77 77 77 80 0F 77' + '77 77 77 77 77 77 77 80 08 77 77 77 77 77 77 77' + '77 80 0F FF FF FF FF FF FF FF FF F0 08 88 88 88' + '88 88 88 88 88 80 B0 00 00 00 00 00 00 00 00 0B' + 'B0 00 00 00 00 00 00 00 00 0B' +END + + +// Version info. +// +#if !defined(__DEBUG_) +// Non-Debug VERSIONINFO +1 VERSIONINFO LOADONCALL MOVEABLE +FILEVERSION 1, 0, 0, 0 +PRODUCTVERSION 1, 0, 0, 0 +FILEFLAGSMASK 0 +FILEFLAGS VS_FFI_FILEFLAGSMASK +FILEOS VOS__WINDOWS16 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + // Language type = U.S. English (0x0409) and Character Set = Windows, Multilingual(0x04e4) + BLOCK "040904E4" // Matches VarFileInfo Translation hex value. + BEGIN + VALUE "CompanyName", "PKWARE, INC.\000" + VALUE "FileDescription", "mem2mem for Windows\000" + VALUE "FileVersion", "1.0\000" + VALUE "InternalName", "mem2mem\000" + VALUE "LegalCopyright", "Copyright © 1995. All Rights Reserved.\000" + VALUE "LegalTrademarks", "Windows (TM) is a trademark of Microsoft Corporation\000" + VALUE "OriginalFilename", "mem2mem.EXE\000" + VALUE "ProductName", "mem2mem\000" + VALUE "ProductVersion", "1.0\000" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04e4 // U.S. English(0x0409) & Windows Multilingual(0x04e4) 1252 + END + +END +#else + +// Debug VERSIONINFO +1 VERSIONINFO LOADONCALL MOVEABLE +FILEVERSION 1, 0, 0, 0 +PRODUCTVERSION 1, 0, 0, 0 +FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE | VS_FF_PATCHED | VS_FF_PRIVATEBUILD | VS_FF_SPECIALBUILD +FILEFLAGS VS_FFI_FILEFLAGSMASK +FILEOS VOS__WINDOWS16 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + // Language type = U.S. English (0x0409) and Character Set = Windows, Multilingual(0x04e4) + BLOCK "040904E4" // Matches VarFileInfo Translation hex value. + BEGIN + VALUE "CompanyName", "PKWARE, INC.\000" + VALUE "FileDescription", "mem2mem for Windows\000" + VALUE "FileVersion", "1.0\000" + VALUE "InternalName", "mem2mem\000" + VALUE "LegalCopyright", "Copyright © 1995. All Rights Reserved.\000" + VALUE "LegalTrademarks", "Windows (TM) is a trademark of Microsoft Corporation\000" + VALUE "OriginalFilename", "mem2mem.EXE\000" + VALUE "ProductName", "mem2mem\000" + VALUE "ProductVersion", "1.0\000" + VALUE "SpecialBuild", "Debug Version\000" + VALUE "PrivateBuild", "Built by \000" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04e4 // U.S. English(0x0409) & Windows Multilingual(0x04e4) 1252 + END + +END +#endif diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.RH b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.RH new file mode 100644 index 0000000..98fdb0d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMAPP.RH @@ -0,0 +1,198 @@ +//#if !defined(__mm2mmapp_rh) // Sentry use file only if it's not already included. +//#define __mm2mmapp_rh + +/* Project mem2mem + PKWARE, INC. + Copyright © 1995. All Rights Reserved. + + SUBSYSTEM: mem2mem.exe Application + FILE: mm2mmapp.h + AUTHOR: + + + OVERVIEW + ======== + Constant definitions for all resources defined in mm2mmapp.rc. +*/ + + +// +// IDHELP BorButton for BWCC dialogs. +// +#define IDHELP 998 // Id of help button + + +// +// Application specific definitions: +// +#define IDI_SDIAPPLICATION 1001 // Application icon + +#define SDI_MENU 100 // Menu resource ID and Accelerator IDs +#define CM_TEST_DCL 101 + +#define IDM_DOCMANAGERFILE 32401 // Menu for DocManager merging. +#define IDM_EDITVIEW 32581 // Menu for TEditView merging. +#define IDM_LISTVIEW 32582 // Menu for TListView merging. + +// +// CM_FILEnnnn commands (include\owl\editfile.rh except for CM_FILEPRINTPREVIEW) +// +#define CM_FILENEW 24331 // SDI New +#define CM_FILEOPEN 24332 // SDI Open +#define CM_FILECLOSE 24339 +#define CM_FILESAVE 24333 +#define CM_FILESAVEAS 24334 +#define CM_FILEREVERT 24335 +#define CM_VIEWCREATE 24341 + + +// +// Window commands (include\owl\window.rh) +// +#define CM_EXIT 24310 + + +// +// CM_EDITnnnn commands (include\owl\window.rh) +// +#define CM_EDITUNDO 24321 +#define CM_EDITCUT 24322 +#define CM_EDITCOPY 24323 +#define CM_EDITPASTE 24324 +#define CM_EDITDELETE 24325 +#define CM_EDITCLEAR 24326 +#define CM_EDITADD 24327 +#define CM_EDITEDIT 24328 + + +// +// Search menu commands (include\owl\editsear.rh) +// +#define CM_EDITFIND 24351 +#define CM_EDITREPLACE 24352 +#define CM_EDITFINDNEXT 24353 + + +// +// Help menu commands. +// +#define CM_HELPABOUT 2009 + + +// +// About Dialogs +// +#define IDD_ABOUT 22000 +#define IDC_VERSION 22001 +#define IDC_COPYRIGHT 22002 +#define IDC_DEBUG 22003 + + +// +// OWL defined strings +// + +// Statusbar +#define IDS_MODES 32530 +#define IDS_MODESOFF 32531 + + +// EditFile +#define IDS_UNABLEREAD 32551 +#define IDS_UNABLEWRITE 32552 +#define IDS_FILECHANGED 32553 +#define IDS_FILEFILTER 32554 + +// EditSearch +#define IDS_CANNOTFIND 32540 + + +// +// General & application exception messages (include\owl\except.rh) +// +#define IDS_UNKNOWNEXCEPTION 32767 +#define IDS_OWLEXCEPTION 32766 +#define IDS_OKTORESUME 32765 +#define IDS_UNHANDLEDXMSG 32764 +#define IDS_UNKNOWNERROR 32763 +#define IDS_NOAPP 32762 +#define IDS_OUTOFMEMORY 32761 +#define IDS_INVALIDMODULE 32760 +#define IDS_INVALIDMAINWINDOW 32759 +#define IDS_VBXLIBRARYFAIL 32758 + +// +// Owl 1 compatibility messages +// +#define IDS_INVALIDWINDOW 32756 +#define IDS_INVALIDCHILDWINDOW 32755 +#define IDS_INVALIDCLIENTWINDOW 32754 + +// +// TXWindow messages +// +#define IDS_CLASSREGISTERFAIL 32749 +#define IDS_CHILDREGISTERFAIL 32748 +#define IDS_WINDOWCREATEFAIL 32747 +#define IDS_WINDOWEXECUTEFAIL 32746 +#define IDS_CHILDCREATEFAIL 32745 + +#define IDS_MENUFAILURE 32744 +#define IDS_VALIDATORSYNTAX 32743 +#define IDS_PRINTERERROR 32742 + +#define IDS_LAYOUTINCOMPLETE 32741 +#define IDS_LAYOUTBADRELWIN 32740 + +// +// TXGdi messages +// +#define IDS_GDIFAILURE 32739 +#define IDS_GDIALLOCFAIL 32738 +#define IDS_GDICREATEFAIL 32737 +#define IDS_GDIRESLOADFAIL 32736 +#define IDS_GDIFILEREADFAIL 32735 +#define IDS_GDIDELETEFAIL 32734 +#define IDS_GDIDESTROYFAIL 32733 +#define IDS_INVALIDDIBHANDLE 32732 + + +// ListView (include\owl\listview.rh) +#define IDS_LISTNUM 32584 + + +// DocView (include\owl\docview.rh) +#define IDS_DOCMANAGERFILE 32500 +#define IDS_DOCLIST 32501 +#define IDS_VIEWLIST 32502 +#define IDS_UNTITLED 32503 +#define IDS_UNABLEOPEN 32504 +#define IDS_UNABLECLOSE 32505 +#define IDS_READERROR 32506 +#define IDS_WRITEERROR 32507 +#define IDS_DOCCHANGED 32508 +#define IDS_NOTCHANGED 32509 +#define IDS_NODOCMANAGER 32510 +#define IDS_NOMEMORYFORVIEW 32511 +#define IDS_DUPLICATEDOC 32512 + + +// TInputDialog DIALOG resource (include\owl\inputdia.rh) +#define IDD_INPUTDIALOG 32514 +#define ID_PROMPT 4091 +#define ID_INPUT 4090 + + +// TSlider bitmaps (horizontal and vertical) (include\owl\slider.rh) +#define IDB_HSLIDERTHUMB 32000 +#define IDB_VSLIDERTHUMB 32001 + + +// Validation messages (include\owl\validate.rh) +#define IDS_VALPXPCONFORM 32520 +#define IDS_VALINVALIDCHAR 32521 +#define IDS_VALNOTINRANGE 32522 +#define IDS_VALNOTINLIST 32523 + + +//#endif // __mm2mmapp_rh sentry. diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMEDV.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMEDV.CPP new file mode 100644 index 0000000..959b5b9 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMEDV.CPP @@ -0,0 +1,38 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include +#pragma hdrstop + +#include "mm2mmapp.h" +#include "mm2mmedv.h" + +#include + + +//{{mem2memEditView Implementation}} + + +////////////////////////////////////////////////////////// +// mem2memEditView +// ========== +// Construction/Destruction handling. +mem2memEditView::mem2memEditView (TDocument& doc, TWindow* parent) + : TEditView(doc, parent) +{ + // INSERT>> Your constructor code here. + +} + + +mem2memEditView::~mem2memEditView () +{ + // INSERT>> Your destructor code here. + +} diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMEDV.H b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMEDV.H new file mode 100644 index 0000000..f734738 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/MEM2MEM/MM2MMEDV.H @@ -0,0 +1,27 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#if !defined(__mm2mmedv_h) // Sentry, use file only if it's not already included. +#define __mm2mmedv_h + +#include +#pragma hdrstop + + +#include "mm2mmapp.rh" // Definition of all resources. + + +//{{TEditView = mem2memEditView}} +class mem2memEditView : public TEditView { +public: + mem2memEditView (TDocument& doc, TWindow* parent = 0); + virtual ~mem2memEditView (); +}; //{{mem2memEditView}} + + +#endif // __mm2mmedv_h sentry. diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/APPLDOCV.ICO b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/APPLDOCV.ICO new file mode 100644 index 0000000..b4843af Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/APPLDOCV.ICO differ diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/DCL.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/DCL.CPP new file mode 100644 index 0000000..bf26645 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/DCL.CPP @@ -0,0 +1,939 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +/* + * DCL.cpp - File to call various DCL DLL functions + */ + +#include +#include +#include "implode.h" + +#include +#include +#include +#include + +#define TEMPFILENAME "~~~.$$$" // TEMPORARY FILENAME TO CREATE +#define APPENDBUFSIZE 32000 // SIZE OF BUFFER TO ALLOCATE FOR APPENDING + // A COMPRESSED FILE TO .MCF FILE + +typedef enum +{ + COMPRESSING = 1, + UNCOMPRESSING +} FILEMODE; + +typedef enum +{ + NO_ERRORS = 0, + ERROR_OCCURRED +} ERRORFLAG; + + +// STRUCT TO PASS TO THE FILE IO FUNCTIONS +typedef struct +{ + TFile *InFile; + TFile *OutFile; + TDC *pDC; + UINT nPrevNdx; + UINT nCnt; + DWORD dwCompressSize; + FILEMODE mode; + ERRORFLAG ErrorOccurred; + DWORD dwCrc; +}IOFILEBLOCK, *PIOFILEBLOCK; + +// FOUR LETTER IDENTIFIER TO IDENTIFY A FILE AS +// A .MCF (MULTIPLE COMPRESSED FILES) FILE +char MCF_FILEHEADER[] = { "MCFX" }; + +#pragma pack(2) + +// HEADER FOR EACH FILE COMPRESSED INTO THE .MCF FILE +typedef struct +{ + DWORD dwCompressSize; // SIZE OF FILE COMPRESSED + DWORD dwCrc; // THE CRC OF THE FILE BEFORE COMPRESSION + char filename[13]; // NAME OF THE FILE +}CMP_FILEHEADER, *PCMP_FILEHEADER; + +#pragma pack(8) + +/* + * FORMAT OF .MCF FILE: + * + * .MCF FILEHEADER => MCFX + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * COMPRESSED FILE FILEHEADER => { CMP_FILEHEADER } + * FOLLOWED BY { ... COMPRESSED FILE DATA ... } + * AND SO ON + * + */ + +static char *pszActiveString[] = { "|", "/", "-", "\\" }; + +UINT DataType = CMP_ASCII; // GLOBAL FOR DATA TYPE FOR COMPRESSION +UINT DictSize = 4096; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + +static PCHAR pszFilename; // NAME OF THE .MCF FILE + + +/********************************************************************* + * + * Function: ProcessMessages() + * + * Purpose: To allow Windows to process window messages which + * allows the user to multitask will compressing and + * uncompressing files. + * + * Returns: Nothing + * + *********************************************************************/ +void ProcessMessages(void) +{ + MSG msg; + + while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) + { + if (msg.message == WM_QUIT) + return; + + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + + +/********************************************************************* + * + * Function: ReadFromDisk() + * + * Purpose: To read data from disk, and prompt user for another + * disk when needed. This function makes a large assumption + * that if when reading a header zero bytes are read, then + * EOF has been reached. + * + * Parameters: Infile -> Pointer to already opened .MCF file + * pBuffer -> input buffer + * nSize -> number of bytes to read + * numread -> pointer to return actual number of bytes read + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred (A FileException is thrown) + * + *********************************************************************/ +int ReadFromDisk( TFile *InFile, PCHAR pBuffer, UINT nSize, UINT *numread, + BOOL ReadingHeader ) +{ + UINT bytesread; + + // READ DATA FROM DISK + *numread = bytesread = InFile->Read( pBuffer, nSize ); + + // IF READING A HEADER AND READ 0 BYTES, THEN ASSUME THIS IS THE END + if( bytesread == 0 && ReadingHeader ) + { + return 1; + } + + // IF COULD NOT READ ALL BYTES + if( bytesread < nSize ) + { + // CALCULATE NUMBER OF BYTES TO READ + nSize -= bytesread; + + // CLOSE THE FILE + InFile->Close(); + + // PROMPT USER FOR ANOTHER DISK + MessageBox( NULL, "Insert Next Disk", "Uncompress", MB_OK ); + + // OPEN .MCF FILE ON NEW DISK + if( !InFile->Open( pszFilename, + TFile::ReadOnly, TFile::PermRdWr ) ) + { + return 0; + } + + // READ DATA FROM DISK + bytesread = InFile->Read( (pBuffer + bytesread), nSize ); + + *numread += bytesread; + } + + return 1; +} + + +/********************************************************************* + * + * Function: ProcessInBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * read requests. If compressing, then the data read is + * in uncompressed form. If compressing, then the data + * read is data that was previously compressed. This + * function is called until zero is returned. + * + * Parameters: buffer -> Address of buffer to read the data into + * iSize -> Number of bytes to read into buffer + * dwParam -> User-defined parameter, in this case a + * pointer to the IOFILEBLOCK + * + * Returns: Number of bytes actually read, or zero on EOF + * + *********************************************************************/ +UINT ProcessInBuffer( PCHAR buffer, UINT *iSize, void *pParam ) +{ + PIOFILEBLOCK pFileIOBlock; + UINT iRead; + UINT ndx; + + pFileIOBlock = (PIOFILEBLOCK) pParam; + + if( pFileIOBlock->ErrorOccurred ) + { + return 0; + } + + // DISPLAY ROTATING LINE + ndx = (pFileIOBlock->nCnt >> 4) & 3; + if( ndx != pFileIOBlock->nPrevNdx ) + { + pFileIOBlock->pDC->TextOut( 10,2, pszActiveString[ndx] ); + pFileIOBlock->nPrevNdx = ndx; + } + pFileIOBlock->nCnt++; + + // THIS FUNCTION MAY ASK FOR UP TO 4K OF DATA AT A TIME. IF YOUR + // ARCHIVE FILE CONTAINS SEVERAL COMPRESSED FILES, YOU MAY READ TOO + // MUCH. FOR EXAMPLE, YOUR FIRST COMPRESSED FILE IN THE ARCHIVE MAY + // BE 100 BYTES. SO YOU DO NOT WANT TO READ MORE THAN 100 BYTES OR + // YOU WILL BE UNABLE TO UNCOMPRESS THE SECOND FILE, SINCE YOU WILL + // NOT BE LOCATED AT THE BEGINNING OF THE FILE ANY LONGER. + // WE WILL USE THE VARIABLE "dwCompressSize" TO CHECK FOR THIS + // CONDITION. + if( pFileIOBlock->mode == UNCOMPRESSING ) + { + // IF DCL REQUESTED MORE BYTES THAN ARE LEFT IN COMPRESSED FILE, THEN + // SET THE NUMBER OF BYTES TO READ TO THE AMOUNT LEFT IN THE BUFFER + if( (DWORD) *iSize > pFileIOBlock->dwCompressSize ) + *iSize = (UINT) pFileIOBlock->dwCompressSize; + + pFileIOBlock->dwCompressSize -= (DWORD) *iSize; + + // READ COMPRESSED FILE FILEHEADER + if( !ReadFromDisk( pFileIOBlock->InFile, buffer, *iSize, &iRead, FALSE ) ) + { + pFileIOBlock->ErrorOccurred = ERROR_OCCURRED; + return 0; + } + } + else + { + // READ BUFFER FROM DISK + iRead = (UINT)pFileIOBlock->InFile->Read( buffer, *iSize ); + } + + // IF COMPRESSING, THEN CALCULATE THE CRC + if( pFileIOBlock->mode == COMPRESSING ) + { + pFileIOBlock->dwCrc = crc32( buffer, &iRead, &pFileIOBlock->dwCrc ); + } + + // ENTER MESSAGE LOOP TO PROCESS BACKGROUND MESSAGES + // AND SIMULATE MULTITASKING + ProcessMessages(); + + return iRead; +} + +/********************************************************************* + * + * Function: ProcessOutBuffer() + * + * Purpose: To handle calls from the Data Compression Library for + * write requests. + * + * Parameters: buffer -> Address of buffer to write data from + * iSize -> Number of bytes to write + * dwParam -> User-defined parameter, in this case a + * pointer to the IOFILEBLOCK + * + * Returns: Zero, the return value is not used by the Data + * Compression Library + * + *********************************************************************/ +void ProcessOutBuffer( PCHAR buffer, UINT *iSize, void *pParam ) +{ + PIOFILEBLOCK pFileIOBlock; + UINT ndx; + + pFileIOBlock = (PIOFILEBLOCK) pParam; + + if( pFileIOBlock->ErrorOccurred ) + { + return; + } + + // DISPLAY ROTATING LINE PACIFIER + ndx = (pFileIOBlock->nCnt >> 4) & 3; + if( ndx != pFileIOBlock->nPrevNdx ) + { + pFileIOBlock->pDC->TextOut( 10,2, pszActiveString[ndx] ); + pFileIOBlock->nPrevNdx = ndx; + } + pFileIOBlock->nCnt++; + + // WRITE BUFFER TO DISK + if( pFileIOBlock->OutFile->Write(buffer, *iSize) != *iSize ) + { + pFileIOBlock->ErrorOccurred = ERROR_OCCURRED; + return; + } + + // IF COMPRESSING, THEN KEEP A TOTAL OF THE COMPRESSED FILE SIZE + if (pFileIOBlock->mode == COMPRESSING ) + { + pFileIOBlock->dwCompressSize += (DWORD) *iSize; + } + else // ELSE UNCOMPRESSING, SO CALCULATE CRC ON THE UNCOMPRESSED DATA + { + pFileIOBlock->dwCrc = crc32(buffer, iSize, &pFileIOBlock->dwCrc); + } + + // ENTER MESSAGE LOOP TO PROCESS BACKGROUND MESSAGES + // AND SIMULATE MULTITASKING + ProcessMessages(); + + return; +} + +/********************************************************************* + * + * Function: CompressFile() + * + * Purpose: To compress file to a separate temporary file. + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * pdwCompFileSize -> Pointer to DWORD buffer to return + * the size of the compressed file + * pszFileToCompress -> Name of file to compress + * OutputFile -> Name of file to write compressed data to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressFile( HWND hWnd, TDC *pDC, DWORD *pdwCrc, DWORD *pdwCompFileSize, + PCHAR pszFileToCompress, PCHAR OutputFile ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + IOFILEBLOCK FileIOBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + // OPEN THE INPUT AND OUTPUT FILES + FileIOBlock.InFile = new TFile; + FileIOBlock.OutFile = new TFile; + + // SETUP STRUCTURE USED BY ProcessReadBuffer() AND ProcessWriteBuffer() + FileIOBlock.mode = COMPRESSING; + FileIOBlock.dwCompressSize = 0; + FileIOBlock.pDC = pDC; + FileIOBlock.nCnt = 0; + FileIOBlock.nPrevNdx = 0; + FileIOBlock.ErrorOccurred = NO_ERRORS; + FileIOBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + pDC->TextOut( 10,2, " " ); + + // OPEN THE FILES + if (FileIOBlock.InFile->Open( pszFileToCompress, TFile::ReadOnly, TFile::PermRdWr ) && + FileIOBlock.OutFile->Open( OutputFile, TFile::Create | TFile::ReadWrite, TFile::PermRdWr )) + { + wsprintf( szVerbose, "Compressing file: %s ", pszFileToCompress ); + pDC->TextOut( 10,40, szVerbose ); + + // ONLY COMPRESS IF FILE IS NOT A ZERO LENGTH FILE + if( FileIOBlock.InFile->Length() ) + { + // COMPRESS THE FILE + iStatus = implode( ProcessInBuffer, ProcessOutBuffer, pScratchPad, + &FileIOBlock, &DataType, &DictSize ); + } + else + { + // SINCE THIS IS A ZERO LENGTH FILE, THERE IS NOTHING TO COMPRESS + // SET STATUS TO NO ERROR + iStatus = 0; + } + + // IF THERE WAS AN ERROR COMPRESSING FILE + if( iStatus ) + { + // DISPLAY ERROR STRING FROM DLL + wsprintf( szVerbose, "Error occurred while imploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else if( FileIOBlock.ErrorOccurred ) + { + MessageBox( hWnd, "Error occurred during compression", "Error", MB_OK ); + rc = 0; + } + else // ELSE - COMPRESSION WAS SUCCESSFUL + { + // POST-CONDITION CRC + FileIOBlock.dwCrc = ~FileIOBlock.dwCrc; + + // RETURN CRC + *pdwCrc = FileIOBlock.dwCrc; + + // RETURN COMPRESSED FILE SIZE + *pdwCompFileSize = FileIOBlock.dwCompressSize; + } + } + else // ELSE - ERROR OPENING FILES + { + MessageBox( hWnd, "Error opening files for compression", "Error", MB_OK ); + rc = 0; + } + + // CLEAN-UP + FileIOBlock.OutFile->Close(); + FileIOBlock.InFile->Close(); + delete FileIOBlock.InFile; + delete FileIOBlock.OutFile; + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: ExpandFile() + * + * Purpose: To uncompress file from a .MCF file. The .MCF file will + * have been read upto the compressed data stream. + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pdwCrc -> Pointer to DWORD buffer to return the CRC + * of the compressed file before compression + * dwCompFileSize -> Size of the compressed file + * pMcfFile -> Pointer to already opened .MCF file + * OutputFile -> Name of file to write uncompressed data to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int ExpandFile( HWND hWnd, TDC *pDC, DWORD *pdwCrc, DWORD dwCompFileSize, + TFile *pMcfFile, PCHAR OutputFile ) +{ + int iStatus; + int rc = 1; + char szVerbose[128]; + IOFILEBLOCK FileIOBlock; + PCHAR pScratchPad; + + if( (pScratchPad = (PCHAR) new char[CMP_BUFFER_SIZE]) == NULL ) + { + return 0; + } + + FileIOBlock.InFile = pMcfFile; + FileIOBlock.OutFile = new TFile; + + // SETUP STRUCTURE USED BY ProcessReadBuffer() and ProcessWriteBuffer() + FileIOBlock.mode = UNCOMPRESSING; + FileIOBlock.dwCompressSize = dwCompFileSize; + FileIOBlock.pDC = pDC; + FileIOBlock.nCnt = 0; + FileIOBlock.nPrevNdx = 0; + FileIOBlock.ErrorOccurred = NO_ERRORS; + FileIOBlock.dwCrc = ~((DWORD)0); // Pre-condition CRC + + pDC->TextOut( 10,2, " " ); + + if( FileIOBlock.OutFile->Open(OutputFile, TFile::Create | TFile::ReadWrite, TFile::PermRdWr ) ) + { + // ONLY UNCOMPRESS IF FILE IS NOT A ZERO LENGTH FILE + if( FileIOBlock.dwCompressSize ) + { + // UNCOMPRESS FILE + iStatus = explode( ProcessInBuffer, ProcessOutBuffer, pScratchPad, &FileIOBlock ); + } + else + { + // SINCE THIS IS A ZERO LENGTH FILE, THERE IS NOTHING TO UNCOMPRESS + // SET STATUS TO NO ERROR + iStatus = 0; + } + + if( iStatus ) + { + wsprintf( szVerbose, "Error occurred while exploding - %d ", iStatus ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + else if( FileIOBlock.ErrorOccurred ) + { + MessageBox( hWnd, "Error occurred during uncompression", "Error", MB_OK ); + rc = 0; + } + else + { + FileIOBlock.dwCrc = ~FileIOBlock.dwCrc; + *pdwCrc = FileIOBlock.dwCrc; + + if( FileIOBlock.dwCompressSize != 0 ) + { + wsprintf( szVerbose, "Error uncompressing file: %s", OutputFile ); + MessageBox( hWnd, szVerbose, "Error", MB_OK ); + rc = 0; + } + } + } + else + { + MessageBox( hWnd, "Error opening files for uncompression", "Error", MB_OK ); + rc = 0; + } + + FileIOBlock.OutFile->Close(); + delete FileIOBlock.OutFile; + delete pScratchPad; + + return rc; +} + + +/********************************************************************* + * + * Function: AmountDriveSpaceFree() + * + * Purpose: To calculate the number of bytes free on drive + * + * Parameters: drivenum -> Drive to check (A=1, B=2, ...) + * pdwBytesFree -> DWORD to return number of bytes free + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int AmountDriveSpaceFree( UINT drivenum, DWORD *pdwBytesFree ) +{ + static char RootStr[] = { "?:\\" }; + DWORD SectorsPerCluster, + BytesPerSector, + FreeClusters, + Clusters; + + *RootStr = (char) ('A' + drivenum - 1); + + if( GetDiskFreeSpace( RootStr, &SectorsPerCluster, &BytesPerSector, + &FreeClusters, &Clusters ) == FALSE ) + { + return 0; + } + + *pdwBytesFree = SectorsPerCluster * BytesPerSector * FreeClusters; + + return 1; +} + + +/********************************************************************* + * + * Function: WriteToDisk() + * + * Purpose: To write data to disk, and prompt user for another + * disk when full. + * + * Parameters: OutFile -> Pointer to already opened file + * pBuffer -> output buffer + * nSize -> number of bytes to write + * pdwBytesFree -> number of bytes left on disk + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int WriteToDisk( TFile *OutFile, PCHAR pBuffer, UINT nSize, DWORD *pdwBytesFree ) +{ + UINT drivenum; + + // IF THERE IS SPACE TO WRITE FILE + if( (ULONG) nSize <= (ULONG) *pdwBytesFree ) + { + OutFile->Write( pBuffer, nSize ); + *pdwBytesFree -= nSize; + } + else // ELSE - NOT ENOUGH SPACE TO WRITE FILE + { + // FILL UP REMAINING DISKSPACE IF ANY + if( *pdwBytesFree > 0 ) + { + OutFile->Write( pBuffer, (UINT) *pdwBytesFree ); + nSize -= (UINT) *pdwBytesFree; + } + OutFile->Close(); + + drivenum = *pszFilename - 'A' + 1; + + // IF ON A FIXED DRIVE, THEN GIVE DISKFULL ERROR + if( drivenum > 2 ) + { + return 0; + } + + UINT nBytesRead = (UINT) *pdwBytesFree; + + // PROMPT USER FOR ANOTHER DISK + MessageBox( NULL, "Insert Another Disk", "Compress", MB_OK ); + + // GET NUMBER OF BYTES FREE ON DISK + if( !AmountDriveSpaceFree( drivenum, pdwBytesFree ) ) + { + return 0; + } + + // CREATE NEW .MCF FILE + if( !OutFile->Open( pszFilename, TFile::Create | TFile::ReadWrite, TFile::PermRdWr ) ) + { + return 0; + } + + // WRITE REMAINING BYTES + if( OutFile->Write( (pBuffer + nBytesRead), nSize ) != nSize ) + { + return 0; + } + *pdwBytesFree -= nSize; + } + + return 1; +} + + +/********************************************************************* + * + * Function: AddFileToMcfFile() + * + * Purpose: To add a compressed file with header to a .MCF file. + * The file header is written followed by the compressed + * file data + * + * Parameters: pFileHeader -> File header for the compressed file + * pszInput -> Filename of the compressed file's data + * pszOutput -> Filename of .MCF file + * CompressedFileSize -> Size of the compressed file + * NewMcfFile -> Flag used to create a new .MCF file + * TRUE - A new .MCF file will be created + * FALSE - The .MCF file will appended to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int AddFileToMcfFile( PCMP_FILEHEADER pFileHeader, PCHAR pszInput, + DWORD CompressedFileSize, BOOL NewMcfFile ) +{ + PCHAR buf; + UINT read; + TFile InFile; + TFile OutFile; + UINT drivenum; + DWORD BytesFree; + + // ALLOCATE I/O BUFFER + if( (buf = new char[APPENDBUFSIZE]) == NULL ) + { + return 0; + } + + drivenum = *pszFilename - 'A' + 1; + + // OPEN THE FILES + InFile.Open( pszInput, TFile::ReadOnly, TFile::PermRdWr ); + + // IF NEW FILE, THEN CREATE MULTIPLE COMPRESSED FILES FILE + if( NewMcfFile ) + { + // CREATE NEW .MCF FILE + if( !OutFile.Open( pszFilename, TFile::Create | TFile::ReadWrite, TFile::PermRdWr ) ) + { + InFile.Close(); + delete buf; + return 0; + } + + // GET NUMBER OF BYTES FREE ON DISK + if( !AmountDriveSpaceFree( drivenum, &BytesFree ) ) + { + delete buf; + return 0; + } + + // WRITE .MCF FILE HEADER + if( !WriteToDisk( &OutFile, MCF_FILEHEADER, 4, &BytesFree ) ) + { + OutFile.Close(); + InFile.Close(); + delete buf; + return 0; + } + } + else + { + // OPEN OLD .MCF FILE + if( !OutFile.Open( pszFilename, TFile::ReadWrite, TFile::PermRdWr ) ) + { + InFile.Close(); + delete buf; + return 0; + } + + // GET NUMBER OF BYTES FREE ON DISK + if( !AmountDriveSpaceFree( drivenum, &BytesFree ) ) + { + delete buf; + return 0; + } + + // GO TO END OF FILE + OutFile.SeekToEnd(); + } + + // WRITE THE COMPRESSED FILE'S FILEHEADER + if( !WriteToDisk( &OutFile, (PCHAR) pFileHeader, sizeof(CMP_FILEHEADER), + &BytesFree ) ) + { + OutFile.Close(); + InFile.Close(); + delete buf; + return 0; + } + + do + { + // READ FROM COMPRESSED FILE + read = InFile.Read( buf, APPENDBUFSIZE ); + + // WRITE DATA TO .MCF FILE + if( !WriteToDisk( &OutFile, buf, read, &BytesFree ) ) + { + OutFile.Close(); + InFile.Close(); + delete buf; + return 0; + } + + // IF ERROR OCCURRED + if( CompressedFileSize < (DWORD) read ) + { + OutFile.Close(); + InFile.Close(); + delete buf; + return 0; + } + + CompressedFileSize -= (DWORD) read; + } + while( CompressedFileSize > 0 ); + + OutFile.Close(); + InFile.Close(); + + delete buf; + + return 1; +} + +/********************************************************************* + * + * Function: CompressFileToMCF() + * + * Purpose: To compress a file then add it to a .MCF file + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszMcfFile -> Filename of .MCF file + * pszFileToCompress -> Filename of file with full path + * pszFilenameOnly -> Filename of file without any path + * This is the filename that is stored + * in the compressed file's file header + * NewMcfFile -> Flag used to create a new .MCF file + * TRUE - A new .MCF file will be created + * FALSE - The .MCF file will appended to + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int CompressFileToMCF( HWND hWnd, TDC *pDC, PCHAR pszMcfFile, PCHAR pszFileToCompress, + PCHAR pszFilenameOnly, BOOL NewMcfFile ) +{ + CMP_FILEHEADER FileHeader; + + pszFilename = pszMcfFile; + + memset( &FileHeader, 0, sizeof(FileHeader) ); + + // ATTEMPT TO COMPRESS THE FILE + if( !CompressFile( hWnd, pDC, &FileHeader.dwCrc, + &FileHeader.dwCompressSize, pszFileToCompress, + TEMPFILENAME ) ) + { + remove( TEMPFILENAME ); + MessageBox( hWnd, "Compress File Failed", "Error", MB_OK ); + return 0; + } + + _fstrcpy( FileHeader.filename, pszFilenameOnly ); + + if( !AddFileToMcfFile( &FileHeader, TEMPFILENAME, FileHeader.dwCompressSize, NewMcfFile ) ) + { + remove( TEMPFILENAME ); + MessageBox( hWnd, "Compress File Failed", "Error", MB_OK ); + return 0; + } + + remove( TEMPFILENAME ); + + return 1; +} + +/********************************************************************* + * + * Function: UncompressFileToMCF() + * + * Purpose: To uncompress a .MCF file + * + * + * Parameters: HWnd -> Handle to window + * pDC -> Pointer to a device context + * pszMcfFilename -> Filename of .MCF file + * pszSaveDir -> Directory to save uncompressed files + * a backslash must be the last character + * + * Returns: 1 -> Successful completion + * 0 -> Error occurred + * + *********************************************************************/ +int UncompressMcfFile( HWND hWnd, TDC *pDC, PCHAR pszMcfFilename, PCHAR pszSaveDir ) +{ + CMP_FILEHEADER FileHeader; + char McfFileheader[5]; + char szOutMsg[128]; + char szOutputFilename[100]; + UINT nNumFiles = 0; + DWORD dwCrc; // CRC OF FILE BEFORE COMPRESSION + UINT read; + TFile McfFile; + + pszFilename = pszMcfFilename; + + // OPEN THE FILES + McfFile.Open( pszFilename, TFile::ReadOnly, TFile::PermRdWr ); + + memset( McfFileheader, 0, sizeof(McfFileheader) ); + + // MAKE SURE FILE IS A MULTIPLE COMPRESSED FILE + if( (!ReadFromDisk( &McfFile, McfFileheader, 4, &read, FALSE )) || + (read != 4) || + (strcmp( McfFileheader, MCF_FILEHEADER ) != 0) ) + { + MessageBox( hWnd, "Invalid file format", "Error", MB_OK ); + return 0; + } + + do + { + // READ COMPRESSED FILE FILEHEADER + if( !ReadFromDisk( &McfFile, (PCHAR)&FileHeader, sizeof(FileHeader), + &read, TRUE ) ) + { + McfFile.Close(); + MessageBox( hWnd, "Error Uncompressing file", "Error", MB_OK ); + return 0; + } + + // IF SUCCESSFULLY READ COMPRESSED FILE FILEHEADER + if( read == sizeof(FileHeader) ) + { + // CREATE OUTPUT FILENAME + strcpy( szOutputFilename, pszSaveDir ); + strcat( szOutputFilename, FileHeader.filename ); + + wsprintf( szOutMsg, "Uncompressing file: %s ", + FileHeader.filename ); + pDC->TextOut( 10,60, szOutMsg ); + + // ATTEMPT TO EXPAND THE FILE + if( !ExpandFile( hWnd, pDC, &dwCrc, + FileHeader.dwCompressSize, + &McfFile, szOutputFilename ) ) + { + McfFile.Close(); + wsprintf( szOutMsg, "Error Uncompressing file: %s", + szOutputFilename ); + MessageBox( hWnd, szOutMsg, "Error", MB_OK ); + return 0; + } + + // CHECK THE CRC OF THE FILE + if( dwCrc != FileHeader.dwCrc ) + { + wsprintf( szOutMsg, "There is an error in the CRC of %s", + szOutputFilename ); + MessageBox( hWnd, szOutMsg, "Error", MB_OK ); + } + + nNumFiles++; + } + } + while( read == sizeof(FileHeader) ); + + McfFile.Close(); + + if( read != 0 ) + { + MessageBox( hWnd, "Invalid file format", "Error", MB_OK ); + return 0; + } + else + { + wsprintf( szOutMsg, "Uncompressed %u file(s)", nNumFiles ); + MessageBox( hWnd, szOutMsg, "Span", MB_OK ); + } + + return 1; +} + + diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/DCL.H b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/DCL.H new file mode 100644 index 0000000..a4bd419 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/DCL.H @@ -0,0 +1,13 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +int CompressFileToMCF( HWND hWnd, TDC *pDC, + LPSTR lpszMcfFile, LPSTR lpszFileToCompress, + LPSTR lpszFilenameOnly, BOOL NewMcfFile ); +int UncompressMcfFile( HWND hWnd, TDC *pDC, LPSTR lpszMcfFile, LPSTR lpszSaveDir ); diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/IMPBORLI.LIB b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/IMPBORLI.LIB new file mode 100644 index 0000000..9ef7765 Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/IMPBORLI.LIB differ diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/IMPLODE.H b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/IMPLODE.H new file mode 100644 index 0000000..116934e --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int implode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int explode( + unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), + void (*write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/MULTFDLG.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/MULTFDLG.CPP new file mode 100644 index 0000000..e7e814d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/MULTFDLG.CPP @@ -0,0 +1,160 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include + +#include "multfdlg.h" + +#define FILELIST_BUFFSIZE 4096 // AMOUNT OF MEMORY TO ALLOCATE FOR FILE LIST + + +MultiSelFileDialog::MultiSelFileDialog( TWindow *pParentWnd, TData& data ) + :TFileOpenDialog( pParentWnd, data ) +{ + // ALLOCATE MEMORY FOR FILE LIST + pszFileList = (PCHAR) new char[FILELIST_BUFFSIZE]; + + // SET ALLOCATED BUFFER AS FILENAME BUFER IN OPENFILENAME STRUCT + // AND REPLACE IT IN THE OPENFILENAME STRUCT + pszOldPtr = ofn.lpstrFile; + ofn.lpstrFile = pszFileList; + ofn.nMaxFile = FILELIST_BUFFSIZE; + + // DO SOME INITIALIZATION + memset( pszFileList, 0, FILELIST_BUFFSIZE ); + strcpy( pszFileList, "*.*" ); + memset( szPath, 0, sizeof(szPath) ); + nPathLen = 0; + Done = TRUE; +} + + +MultiSelFileDialog::~MultiSelFileDialog() +{ + // REPLACE OLD POINTER AND FREE MEMORY + ofn.lpstrFile = pszOldPtr; + delete pszFileList; +} + + +BOOL MultiSelFileDialog::GetFirstFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ) +{ + PCHAR pszToken; + + nPathLen = 0; + Done = FALSE; + + // GET THE FIRST TOKEN WHICH SHOULD BE THE PATH + if( strchr( pszFileList, ' ' ) == NULL ) + { + // COULD NOT FIND TOKEN SO MUST BE PATH AND FILENAME + + Done = TRUE; + + memset( szPath, 0, sizeof(szPath) ); + nPathLen = 0; + + // MAKE SURE THE FILENAME + PATH WILL FIT + if( strlen( pszFileList ) > nPathBuffSize ) + { + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // COPY FILENAME ONLY + char *NameOnly = strrchr( pszFileList, '\\' ); + if( NameOnly == NULL || strlen( NameOnly ) > 13 ) + { + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + strcpy( pszFilenameBuff, ++NameOnly ); + + // COPY PATH AND FILENAME TO BUFFER + strcpy( pszFullPathBuff, pszFileList ); + + return TRUE; + } + + // GET THE FIRST TOKEN WHICH SHOULD BE THE PATH + if( (pszToken = strtok( pszFileList, " " )) == NULL ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + memset( szPath, 0, sizeof(szPath) ); + strcpy( szPath, pszToken ); + strcat( szPath, "\\" ); + + nPathLen = strlen( szPath ); + + return GetNextFilename( pszFullPathBuff, nPathBuffSize, pszFilenameBuff ); +} + + +// pszFilenameBuff MUST BE AT LEAST 13 BYTES +BOOL MultiSelFileDialog::GetNextFilename( PCHAR pszFullPathBuff, + UINT nPathBuffSize, + PCHAR pszFilenameBuff ) +{ + PCHAR pszToken; + + if( Done ) + { + return FALSE; + } + + // GET THE NEXT TOKEN WHICH SHOULD BE A FILENAME + if( (pszToken = strtok( NULL, " " )) == NULL ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // MAKE SURE THE FILENAME + PATH WILL FIT + if( (strlen( pszToken ) + nPathLen) > nPathBuffSize ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + // COPY PATH AND FILENAME TO BUFFER + strcpy( pszFullPathBuff, szPath ); + strcat( pszFullPathBuff, pszToken ); + + PCHAR pszNameOnly = strrchr( pszFullPathBuff, '\\' ); + + if( (pszNameOnly == NULL) || (strlen(pszNameOnly) > 13) ) + { + Done = TRUE; + *pszFullPathBuff = '\0'; + *pszFilenameBuff = '\0'; + return FALSE; + } + + strcpy( pszFilenameBuff, ++pszNameOnly ); + + return TRUE; +} + + + + + diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/MULTFDLG.H b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/MULTFDLG.H new file mode 100644 index 0000000..eed3ecc --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/MULTFDLG.H @@ -0,0 +1,30 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include + +class MultiSelFileDialog : public TFileOpenDialog +{ + private: + PCHAR pszFileList; + PCHAR pszOldPtr; + int nPathLen; + char szPath[80]; + BOOL Done; + + public: + MultiSelFileDialog( TWindow *pParentWnd, TData& data ); + ~MultiSelFileDialog(); + BOOL GetFirstFilename( PCHAR lpszFullPathBuff, + UINT nPathBuffSize, + PCHAR lpszFilenameBuff ); + BOOL GetNextFilename( PCHAR lpszFullPathBuff, + UINT nPathBuffSize, + PCHAR lpszFilenameBuff ); +}; diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPAN.IDE b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPAN.IDE new file mode 100644 index 0000000..ff384fa Binary files /dev/null and b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPAN.IDE differ diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.CPP new file mode 100644 index 0000000..73e7474 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.CPP @@ -0,0 +1,419 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include +#include +#pragma hdrstop + +#include "spanapp.h" +#include "spnedtvw.h" // Definition of client class. +#include "spnabtdl.h" // Definition of about dialog. +#include "multfdlg.h" +#include "dcl.h" +#include "implode.h" + +#include + +//{{spanApp Implementation}} + +//{{DOC_VIEW}} +DEFINE_DOC_TEMPLATE_CLASS(TFileDocument, spanEditView, DocType1); +//{{DOC_VIEW_END}} + +//{{DOC_MANAGER}} +DocType1 __dvt1("All Files (*.*)", "*.*", 0, "TXT", dtAutoDelete | dtUpdateDir); +//{{DOC_MANAGER_END}} + + +// +// Build a response table for all messages/commands handled +// by the application. +// +DEFINE_RESPONSE_TABLE1(spanApp, TApplication) +//{{spanAppRSP_TBL_BEGIN}} + EV_OWLVIEW(dnCreate, EvNewView), + EV_OWLVIEW(dnClose, EvCloseView), + EV_COMMAND(CM_HELPABOUT, CmHelpAbout), +//{{spanAppRSP_TBL_END}} +END_RESPONSE_TABLE; + + +extern UINT DataType; // GLOBAL FOR DATA TYPE FOR COMPRESSION +extern UINT DictSize; // GLOBAL FOR DICTIONARY SIZE FOR COMPRESSION + +// THE UNCOMPRESS DIRECTORY MUST END WITH A BACKSLASH +char far *UncompressDir = "C:\\TEMP\\"; + +// FLAG TO DETERMINE IF CURRENTLY COMPRESSING OR UNCOMPRESSING +static BOOL bActive = FALSE; + +////////////////////////////////////////////////////////// +// spanApp +// ===== +// +spanApp::spanApp () : TApplication("span") +{ + SetDocManager(new TDocManager(dmSDI, this)); + + // INSERT>> Your constructor code here. +} + + +spanApp::~spanApp () +{ + // INSERT>> Your destructor code here. +} + + + + +////////////////////////////////////////////////////////// +// spanApp +// ===== +// Application intialization. +// +void spanApp::InitMainWindow () +{ + if (nCmdShow != SW_HIDE) + nCmdShow = (nCmdShow != SW_SHOWMINNOACTIVE) ? SW_SHOWNORMAL : nCmdShow; + + SDIDecFrame *frame = new SDIDecFrame(0, GetName(), 0, true, this); + + // + // Assign ICON w/ this application. + // + frame->SetIcon(this, IDI_SDIAPPLICATION); + + // + // Menu associated with window and accelerator table associated with table. + // + frame->AssignMenu(SDI_MENU); + + // + // Associate with the accelerator table. + // + frame->Attr.AccelTable = SDI_MENU; + + + TStatusBar *sb = new TStatusBar(frame, TGadget::Recessed, + TStatusBar::CapsLock | + TStatusBar::NumLock | + TStatusBar::ScrollLock | + TStatusBar::Overtype); + frame->Insert(*sb, TDecoratedFrame::Bottom); + + SetMainWindow(frame); + + frame->SetMenuDescr(TMenuDescr(SDI_MENU)); + +} + + +////////////////////////////////////////////////////////// +// spanApp +// ===== +// Response Table handlers: +// +void spanApp::EvNewView (TView& view) +{ + GetMainWindow()->SetClientWindow(view.GetWindow()); + if (!view.IsOK()) + GetMainWindow()->SetClientWindow(0); + else if (view.GetViewMenu()) + GetMainWindow()->MergeMenu(*view.GetViewMenu()); +} + + +void spanApp::EvCloseView (TView&) +{ + GetMainWindow()->SetClientWindow(0); + GetMainWindow()->SetCaption("span"); +} + +// +// Build a response table for all messages/commands handled +// by the application. +// +DEFINE_RESPONSE_TABLE1(SDIDecFrame, TDecoratedFrame) +//{{SDIDecFrameRSP_TBL_BEGIN}} + EV_COMMAND(CM_COMPRESS_FILES, OnCompressFiles), + EV_COMMAND_ENABLE(CM_COMPRESS_FILES, OnCompressFilesEnable), + EV_COMMAND(CM_UNCOMPRESS_FILES, OnUncompressFiles), + EV_COMMAND_ENABLE(CM_UNCOMPRESS_FILES, OnUncompressFilesEnable), + EV_COMMAND(CM_COMP_TYPE_ASCII, OnCompTypeAscii), + EV_COMMAND_ENABLE(CM_COMP_TYPE_ASCII, OnCompTypeAsciiEnable), + EV_COMMAND(CM_COMP_TYPE_BINARY, OnCompTypeBinary), + EV_COMMAND_ENABLE(CM_COMP_TYPE_BINARY, OnCompTypeBinaryEnable), + EV_COMMAND(CM_DICT_SIZE_1024, OnDictSize1024), + EV_COMMAND_ENABLE(CM_DICT_SIZE_1024, OnDictSize1024Enable), + EV_COMMAND(CM_DICT_SIZE_2048, OnDictSize2048), + EV_COMMAND_ENABLE(CM_DICT_SIZE_2048, OnDictSize2048Enable), + EV_COMMAND(CM_DICT_SIZE_4096, OnDictSize4096), + EV_COMMAND_ENABLE(CM_DICT_SIZE_4096, OnDictSize4096Enable), +//{{SDIDecFrameRSP_TBL_END}} +END_RESPONSE_TABLE; + + +//{{SDIDecFrame Implementation}} + + +SDIDecFrame::SDIDecFrame (TWindow *parent, const char far *title, TWindow *clientWnd, bool trackMenuSelection, TModule *module) + : TDecoratedFrame(parent, title, clientWnd, trackMenuSelection, module) +{ +} + + +SDIDecFrame::~SDIDecFrame () +{ + // INSERT>> Your destructor code here. + +} + + +////////////////////////////////////////////////////////// +// spanApp +// =========== +// Menu Help About span.exe command +void spanApp::CmHelpAbout () +{ + // + // Show the modal dialog. + // + spanAboutDlg(GetMainWindow()).Execute(); +} + + +int OwlMain (int , char* []) +{ + try { + spanApp app; + return app.Run(); + } + catch (xmsg& x) { + ::MessageBox(0, x.why().c_str(), "Exception", MB_OK); + } + + return -1; +} + +void SDIDecFrame::OnCompressFiles () +{ + // TURN OFF HELP MESSAGE AND CLEAR SCREEN +// ChildBroadcastMessage( WM_TURN_OFF_HELP, 0, 0L ); + + TOpenSaveDialog::TData data( OFN_FILEMUSTEXIST|OFN_HIDEREADONLY| + OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR|OFN_ALLOWMULTISELECT, + "All Files (*.*)|*.*||", 0, "", "*" ); + + MultiSelFileDialog FileDlg( this, data ); + + if( FileDlg.Execute() == IDOK ) + { + TOpenSaveDialog::TData SaveData( OFN_HIDEREADONLY|OFN_PATHMUSTEXIST| + OFN_NOCHANGEDIR|OFN_OVERWRITEPROMPT, + "Mult. Compressed Files (*.MCF)|*.MCF||", 0, "*.MCF", "MCF" ); + + if( TFileSaveDialog( this, SaveData ).Execute() == IDOK ) + { + BOOL GotFilenameOk, + bError = FALSE, + CreateMcfFile; + UINT nNumCmpFiles = 0; + char szFilename[13]; // BUFFER FOR FILENAME ONLY + char szFullPathname[128]; // BUFFER FOR FULL PATH FOR FILE + char szOutBuff[64]; // TEMP OUTPUT BUFFER + + // GET DC AND SET THE TEXT BACKGROUND COLOR TO WINDOW BACKGROUND COLOR + TWindow *ClientWnd = GetClientWindow(); + TWindowDC dc( ClientWnd->HWindow ); + TColor bkGroundColor = dc.GetPixel( 0, 0 ); + dc.SetBkColor( bkGroundColor ); + + // SET FLAG TO PREVENT EXITING IN THE MIDDLE OF THE COMPRESSION + bActive = TRUE; + + wsprintf( szOutBuff, "Compressing to: %s ", (LPSTR) + SaveData.FileName ); + dc.TextOut( 10,20, szOutBuff ); + + // SET CREATE .MCF FILE FLAG TO TRUE, SO THAT THE FIRST TIME + // CompressFileToMCF IS CALLED THE .MCF WILL BE CREATED INSTEAD + // OF APPENDED TO + CreateMcfFile = TRUE; + + // GET THE FIRST FILENAME IN THE LIST + GotFilenameOk = FileDlg.GetFirstFilename( szFullPathname, + sizeof(szFullPathname), + szFilename ); + // WHILE GOT A FILENAME FROM THE LIST + while( GotFilenameOk ) + { + // COMPRESS THE FILE AND ADD IT TO THE .MCF FILE + if( !CompressFileToMCF( ClientWnd->HWindow, &dc, + SaveData.FileName, szFullPathname, + szFilename, CreateMcfFile ) ) + { + // ERROR OCCURRED SO DELETE THE .MCF FILE + remove( SaveData.FileName ); + bError = TRUE; + break; + } + // INCREMENT TOTAL + nNumCmpFiles++; + + // RESET .MCF FILE FLAG SO THAT .MCF FILE WILL NOT BE CREATED + CreateMcfFile = FALSE; + + // GET THE FIRST FILENAME IN THE LIST + GotFilenameOk = FileDlg.GetNextFilename( szFullPathname, + sizeof(szFullPathname), + szFilename ); + } + + // IF THERE WAS NOT ERROR, THEN DISPLAY MESSAGE + if( !bError ) + { + wsprintf( szOutBuff, "Compressed %u file(s)", nNumCmpFiles ); + MessageBox( szOutBuff, "Span" ); + } + + // DONE WITH COMPRESION SO ALLOW THE USER TO EXIT + bActive = FALSE; + } + } + + // TURN OFF HELP MESSAGE AND CLEAR SCREEN +// ChildBroadcastMessage( WM_TURN_ON_HELP, 0, 0L ); +} + + +void SDIDecFrame::OnUncompressFiles () +{ + // TURN OFF HELP MESSAGE AND CLEAR SCREEN +// ChildBroadcastMessage( WM_TURN_OFF_HELP, 0, 0L ); + + TOpenSaveDialog::TData data( OFN_FILEMUSTEXIST|OFN_HIDEREADONLY| + OFN_PATHMUSTEXIST|OFN_NOCHANGEDIR, + "Mult. Compressed Files (*.MCF)|*.MCF||", 0, "*.MCF", "MCF" ); + + if( TFileOpenDialog( this, data ).Execute() == IDOK ) + { + char szOutBuff[64]; // TEMP OUTPUT BUFFER + + // SET FLAG TO PREVENT EXITING IN THE MIDDLE OF THE UNCOMPRESSION + bActive = TRUE; + + // GET DC AND SET THE TEXT BACKGROUND COLOR TO WINDOW BACKGROUND COLOR + TWindow *ClientWnd = GetClientWindow(); + TWindowDC dc( ClientWnd->HWindow ); + TColor bkGroundColor = dc.GetPixel( 0, 0 ); + dc.SetBkColor( bkGroundColor ); + + wsprintf( szOutBuff, "Uncompressing: %s ",(LPSTR) data.FileName ); + dc.TextOut( 10,20, szOutBuff ); + + // UNCOMPRESS THE FILE + UncompressMcfFile( ClientWnd->HWindow, &dc, data.FileName, UncompressDir ); + + // DONE WITH UNCOMPRESION SO ALLOW THE USER TO EXIT + bActive = FALSE; + } + + // TURN OFF HELP MESSAGE AND CLEAR SCREEN +// ChildBroadcastMessage( WM_TURN_ON_HELP, 0, 0L ); +} + + + +void SDIDecFrame::OnCompressFilesEnable (TCommandEnabler &tce) +{ + tce.Enable( TRUE && !bActive ); +} + + +void SDIDecFrame::OnUncompressFilesEnable (TCommandEnabler &tce) +{ + tce.Enable( TRUE && !bActive ); +} + + +void SDIDecFrame::OnCompTypeAscii () +{ + DataType = CMP_ASCII; +} + + +void SDIDecFrame::OnCompTypeAsciiEnable (TCommandEnabler &tce) +{ + tce.Enable( (DataType != CMP_ASCII) && !bActive ); +} + + +void SDIDecFrame::OnCompTypeBinary () +{ + DataType = CMP_BINARY; +} + + +void SDIDecFrame::OnCompTypeBinaryEnable (TCommandEnabler &tce) +{ + tce.Enable( (DataType != CMP_BINARY) && !bActive ); +} + + +void SDIDecFrame::OnDictSize1024 () +{ + DictSize = 1024; +} + + +void SDIDecFrame::OnDictSize1024Enable (TCommandEnabler &tce) +{ + tce.Enable( (DictSize != 1024) && !bActive ); +} + + +void SDIDecFrame::OnDictSize2048 () +{ + DictSize = 2048; +} + + +void SDIDecFrame::OnDictSize2048Enable (TCommandEnabler &tce) +{ + tce.Enable( (DictSize != 2048) && !bActive ); +} + + +void SDIDecFrame::OnDictSize4096 () +{ + DictSize = 4096; +} + + +void SDIDecFrame::OnDictSize4096Enable (TCommandEnabler &tce) +{ + tce.Enable( (DictSize != 4096) && !bActive ); +} + + +bool SDIDecFrame::CanClose () +{ + bool result; + + if( bActive ) + return FALSE; + + result = TDecoratedFrame::CanClose(); + + return result; +} + + + diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.DEF b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.DEF new file mode 100644 index 0000000..f06100c --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.DEF @@ -0,0 +1,8 @@ +NAME span + +DESCRIPTION 'span Application' +EXETYPE WINDOWS +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE +HEAPSIZE 4096 +STACKSIZE 8192 diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.H b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.H new file mode 100644 index 0000000..4eef75d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.H @@ -0,0 +1,81 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#if !defined(__spanapp_h) // Sentry, use file only if it's not already included. +#define __spanapp_h + +#include +#pragma hdrstop + + +#include "spanapp.rh" // Definition of all resources. + + +#define WM_TURN_OFF_HELP WM_USER+1 +#define WM_TURN_ON_HELP WM_USER+2 + + +// +// FrameWindow must be derived to override Paint for Preview and Print. +// +//{{TDecoratedFrame = SDIDecFrame}} +class SDIDecFrame : public TDecoratedFrame { +public: + SDIDecFrame (TWindow *parent, const char far *title, TWindow *clientWnd, bool trackMenuSelection = false, TModule *module = 0); + ~SDIDecFrame (); + +//{{SDIDecFrameVIRTUAL_BEGIN}} +public: + virtual bool CanClose (); +//{{SDIDecFrameVIRTUAL_END}} + +//{{SDIDecFrameRSP_TBL_BEGIN}} +protected: + void OnCompressFiles (); + void OnCompressFilesEnable (TCommandEnabler &tce); + void OnUncompressFiles (); + void OnUncompressFilesEnable (TCommandEnabler &tce); + void OnCompTypeAscii (); + void OnCompTypeAsciiEnable (TCommandEnabler &tce); + void OnCompTypeBinary (); + void OnCompTypeBinaryEnable (TCommandEnabler &tce); + void OnDictSize1024 (); + void OnDictSize1024Enable (TCommandEnabler &tce); + void OnDictSize2048 (); + void OnDictSize2048Enable (TCommandEnabler &tce); + void OnDictSize4096 (); + void OnDictSize4096Enable (TCommandEnabler &tce); +//{{SDIDecFrameRSP_TBL_END}} +DECLARE_RESPONSE_TABLE(SDIDecFrame); +}; //{{SDIDecFrame}} + + +//{{TApplication = spanApp}} +class spanApp : public TApplication { +private: + +public: + spanApp (); + virtual ~spanApp (); + +//{{spanAppVIRTUAL_BEGIN}} +public: + virtual void InitMainWindow (); +//{{spanAppVIRTUAL_END}} + +//{{spanAppRSP_TBL_BEGIN}} +protected: + void EvNewView (TView& view); + void EvCloseView (TView& view); + void CmHelpAbout (); +//{{spanAppRSP_TBL_END}} +DECLARE_RESPONSE_TABLE(spanApp); +}; //{{spanApp}} + + +#endif // __spanapp_h sentry. diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.RC b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.RC new file mode 100644 index 0000000..37ef28d --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.RC @@ -0,0 +1,399 @@ +/* Project span + PKWARE, INC. + Copyright © 1995. All Rights Reserved. + + SUBSYSTEM: span.exe Application + FILE: spanapp.rc + AUTHOR: + + + OVERVIEW + ======== + All resources defined here. +*/ + +#if !defined(WORKSHOP_INVOKED) +#include +#endif +#include "spanapp.rh" + +SDI_MENU MENU +{ + POPUP "&File" + { + MENUITEM "&Compress Files", CM_COMPRESS_FILES + MENUITEM "&Uncompress Files", CM_UNCOMPRESS_FILES + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", CM_EXIT + } + + POPUP "&Options" + { + MENUITEM "&1024", CM_DICT_SIZE_1024 + MENUITEM "&2048", CM_DICT_SIZE_2048 + MENUITEM "&4096", CM_DICT_SIZE_4096 + MENUITEM SEPARATOR + MENUITEM "&ASCII", CM_COMP_TYPE_ASCII + MENUITEM "&Binary", CM_COMP_TYPE_BINARY + } + + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + POPUP "&Help" + { + MENUITEM "&About...", CM_HELPABOUT + } + +} + + +// Accelerator table for short-cut to menu commands. (include\owl\editfile.rc) +SDI_MENU ACCELERATORS +BEGIN + VK_DELETE, CM_EDITDELETE, VIRTKEY + VK_DELETE, CM_EDITCUT, VIRTKEY, SHIFT + VK_INSERT, CM_EDITCOPY, VIRTKEY, CONTROL + VK_INSERT, CM_EDITPASTE, VIRTKEY, SHIFT + VK_DELETE, CM_EDITCLEAR, VIRTKEY, CONTROL + VK_BACK, CM_EDITUNDO, VIRTKEY, ALT + VK_F3, CM_EDITFINDNEXT, VIRTKEY +END + + +// Menu merged in when TEditView is active, notice the extra MENUITEM SEPARATORs which are +// for menu negotation. These separators are used as group markers by OWL. +IDM_EDITVIEW MENU +{ + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR +} + + +// Menu merged in when TListView is active, notice the extra MENUITEM SEPARATORs which are +// for menu negotation. These separators are used as group markers by OWL. +IDM_LISTVIEW MENU +{ + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR + MENUITEM SEPARATOR +} + + +IDM_DOCMANAGERFILE MENU +{ + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+F4", CM_EXIT +} + + +// +// Table of help hints displayed in the status bar. +// +STRINGTABLE +BEGIN + -1, "File/document operations" + CM_FILENEW, "Creates a new document" + CM_FILEOPEN, "Opens an existing document" + CM_VIEWCREATE, "Create a new view for this document" + CM_FILEREVERT, "Reverts changes to last document save" + CM_FILECLOSE, "Close this document" + CM_FILESAVE, "Saves this document" + CM_FILESAVEAS, "Saves this document with a new name" + CM_EXIT, "Quits spanApp and prompts to save the documents" + CM_EDITUNDO-1, "Edit operations" + CM_EDITUNDO, "Reverses the last operation" + CM_EDITCUT, "Cuts the selection and puts it on the Clipboard" + CM_EDITCOPY, "Copies the selection and puts it on the Clipboard" + CM_EDITPASTE, "Inserts the clipboard contents at the insertion point" + CM_EDITDELETE, "Deletes the selection" + CM_EDITCLEAR, "Clear the document" + CM_EDITADD, "Insert a new line" + CM_EDITEDIT, "Edit the current line" + CM_EDITFIND-1, "Search/replace operations" + CM_EDITFIND, "Finds the specified text" + CM_EDITREPLACE, "Finds the specified text and changes it" + CM_EDITFINDNEXT, "Finds the next match" + CM_HELPABOUT-1, "Access About" + CM_HELPABOUT, "About the span application" +END + + +// +// OWL string table +// + +// EditFile (include\owl\editfile.rc and include\owl\editsear.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_CANNOTFIND, "Cannot find ""%s""." + IDS_UNABLEREAD, "Unable to read file %s from disk." + IDS_UNABLEWRITE, "Unable to write file %s to disk." + IDS_FILECHANGED, "The text in the %s file has changed.\n\nDo you want to save the changes?" + IDS_FILEFILTER, "Text files (*.TXT)|*.TXT|AllFiles (*.*)|*.*|" +END + + +// ListView (include\owl\listview.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_LISTNUM, "Line number %d" +END + + +// Doc/View (include\owl\docview.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_DOCMANAGERFILE, "&File" + IDS_DOCLIST, "--Document Type--" + IDS_VIEWLIST, "--View Type--" + IDS_UNTITLED, "Document" + IDS_UNABLEOPEN, "Unable to open document." + IDS_UNABLECLOSE, "Unable to close document." + IDS_READERROR, "Document read error." + IDS_WRITEERROR, "Document write error." + IDS_DOCCHANGED, "The document has been changed.\n\nDo you want to save the changes?" + IDS_NOTCHANGED, "The document has not been changed." + IDS_NODOCMANAGER, "Document Manager not present." + IDS_NOMEMORYFORVIEW, "Insufficient memory for view." + IDS_DUPLICATEDOC, "Document already loaded." +END + + +// Exception string resources (include\owl\except.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_OWLEXCEPTION, "ObjectWindows Exception" + IDS_UNHANDLEDXMSG, "Unhandled Exception" + IDS_OKTORESUME, "OK to resume?" + IDS_UNKNOWNEXCEPTION, "Unknown exception" + + IDS_UNKNOWNERROR, "Unknown error" + IDS_NOAPP, "No application object" + IDS_OUTOFMEMORY, "Out of memory" + IDS_INVALIDMODULE, "Invalid module specified for window" + IDS_INVALIDMAINWINDOW, "Invalid MainWindow" + IDS_VBXLIBRARYFAIL, "VBX Library init failure" + + IDS_INVALIDWINDOW, "Invalid window %s" + IDS_INVALIDCHILDWINDOW, "Invalid child window %s" + IDS_INVALIDCLIENTWINDOW, "Invalid client window %s" + + IDS_CLASSREGISTERFAIL, "Class registration fail for window %s" + IDS_CHILDREGISTERFAIL, "Child class registration fail for window %s" + IDS_WINDOWCREATEFAIL, "Create fail for window %s" + IDS_WINDOWEXECUTEFAIL, "Execute fail for window %s" + IDS_CHILDCREATEFAIL, "Child create fail for window %s" + + IDS_MENUFAILURE, "Menu creation failure" + IDS_VALIDATORSYNTAX, "Validator syntax error" + IDS_PRINTERERROR, "Printer error" + + IDS_LAYOUTINCOMPLETE, "Incomplete layout constraints specified in window %s" + IDS_LAYOUTBADRELWIN, "Invalid relative window specified in layout constraint in window %s" + + IDS_GDIFAILURE, "GDI failure" + IDS_GDIALLOCFAIL, "GDI allocate failure" + IDS_GDICREATEFAIL, "GDI creation failure" + IDS_GDIRESLOADFAIL, "GDI resource load failure" + IDS_GDIFILEREADFAIL, "GDI file read failure" + IDS_GDIDELETEFAIL, "GDI object %X delete failure" + IDS_GDIDESTROYFAIL, "GDI object %X destroy failure" + IDS_INVALIDDIBHANDLE, "Invalid DIB handle %X" +END + + +// General Window's status bar messages. (include\owl\statusba.rc) +STRINGTABLE +BEGIN + IDS_MODES "EXT|CAPS|NUM|SCRL|OVR|REC" + IDS_MODESOFF " | | | | | " + SC_SIZE, "Changes the size of the window" + SC_MOVE, "Moves the window to another position" + SC_MINIMIZE, "Reduces the window to an icon" + SC_MAXIMIZE, "Enlarges the window to it maximum size" + SC_RESTORE, "Restores the window to its previous size" + SC_CLOSE, "Closes the window" + SC_TASKLIST, "Opens task list" + SC_NEXTWINDOW, "Switches to next window" +END + + +// Validator messages (include\owl\validate.rc) +STRINGTABLE LOADONCALL MOVEABLE DISCARDABLE +BEGIN + IDS_VALPXPCONFORM "Input does not conform to picture:\n""%s""" + IDS_VALINVALIDCHAR "Invalid character in input" + IDS_VALNOTINRANGE "Value is not in the range %ld to %ld." + IDS_VALNOTINLIST "Input is not in valid-list" +END + + +// +// Misc application definitions +// + +// Application ICON +IDI_SDIAPPLICATION ICON "appldocv.ico" + + +// About box. +IDD_ABOUT DIALOG 12, 17, 204, 65 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About span" +FONT 8, "MS Sans Serif" +BEGIN + CTEXT "Version", IDC_VERSION, 2, 14, 200, 8, SS_NOPREFIX + CTEXT "Disk Spanning Example", -1, 2, 4, 200, 8, SS_NOPREFIX + CTEXT "", IDC_COPYRIGHT, 2, 27, 200, 17, SS_NOPREFIX + RTEXT "", IDC_DEBUG, 136, 55, 66, 8, SS_NOPREFIX + ICON IDI_SDIAPPLICATION, -1, 2, 2, 34, 34 + DEFPUSHBUTTON "OK", IDOK, 82, 48, 40, 14 +END + + +// TInputDialog class dialog box. +IDD_INPUTDIALOG DIALOG 20, 24, 180, 64 +STYLE WS_POPUP | WS_CAPTION | DS_SETFONT +FONT 8, "Helv" +BEGIN + LTEXT "", ID_PROMPT, 10, 8, 160, 10, SS_NOPREFIX + CONTROL "", ID_INPUT, "EDIT", WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, 10, 20, 160, 12 + DEFPUSHBUTTON "&OK", IDOK, 47, 42, 40, 14 + PUSHBUTTON "&Cancel", IDCANCEL, 93, 42, 40, 14 +END + + +// Horizontal slider thumb bitmap for TSlider and VSlider (include\owl\slider.rc) +IDB_HSLIDERTHUMB BITMAP PRELOAD MOVEABLE DISCARDABLE +BEGIN + '42 4D 66 01 00 00 00 00 00 00 76 00 00 00 28 00' + '00 00 12 00 00 00 14 00 00 00 01 00 04 00 00 00' + '00 00 F0 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 10 00 00 00 00 00 00 00 00 00 C0 00 00 C0' + '00 00 00 C0 C0 00 C0 00 00 00 C0 00 C0 00 C0 C0' + '00 00 C0 C0 C0 00 80 80 80 00 00 00 FF 00 00 FF' + '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' + '00 00 FF FF FF 00 BB BB 0B BB BB BB B0 BB BB 00' + '00 00 BB B0 80 BB BB BB 08 0B BB 00 00 00 BB 08' + 'F8 0B BB B0 87 70 BB 00 00 00 B0 8F F8 80 BB 08' + '77 77 0B 00 00 00 08 F8 88 88 00 88 88 87 70 00' + '00 00 0F F7 77 88 00 88 77 77 70 00 00 00 0F F8' + '88 88 00 88 88 87 70 00 00 00 0F F7 77 88 00 88' + '77 77 70 00 00 00 0F F8 88 88 00 88 88 87 70 00' + '00 00 0F F7 77 88 00 88 77 77 70 00 00 00 0F F8' + '88 88 00 88 88 87 70 00 00 00 0F F7 77 88 00 88' + '77 77 70 00 00 00 0F F8 88 88 00 88 88 87 70 00' + '00 00 0F F7 77 88 00 88 77 77 70 00 00 00 0F F8' + '88 88 00 88 88 87 70 00 00 00 0F F7 77 88 00 88' + '77 77 70 00 00 00 0F F8 88 88 00 88 88 87 70 00' + '00 00 0F F7 77 78 00 88 77 77 70 00 00 00 0F FF' + 'FF FF 00 88 88 88 80 00 00 00 B0 00 00 00 BB 00' + '00 00 0B 00 00 00' +END + + +// Vertical slider thumb bitmap for TSlider and HSlider (include\owl\slider.rc) +IDB_VSLIDERTHUMB BITMAP PRELOAD MOVEABLE DISCARDABLE +BEGIN + '42 4D 2A 01 00 00 00 00 00 00 76 00 00 00 28 00' + '00 00 28 00 00 00 09 00 00 00 01 00 04 00 00 00' + '00 00 B4 00 00 00 00 00 00 00 00 00 00 00 00 00' + '00 00 10 00 00 00 00 00 00 00 00 00 C0 00 00 C0' + '00 00 00 C0 C0 00 C0 00 00 00 C0 00 C0 00 C0 C0' + '00 00 C0 C0 C0 00 80 80 80 00 00 00 FF 00 00 FF' + '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' + '00 00 FF FF FF 00 B0 00 00 00 00 00 00 00 00 0B' + 'B0 00 00 00 00 00 00 00 00 0B 0F 88 88 88 88 88' + '88 88 88 80 08 88 88 88 88 88 88 88 88 80 0F 77' + '77 77 77 77 77 77 77 80 08 77 77 77 77 77 77 77' + '77 80 0F 77 FF FF FF FF FF FF F7 80 08 77 FF FF' + 'FF FF FF FF F7 80 0F 70 00 00 00 00 00 00 77 80' + '08 70 00 00 00 00 00 00 77 80 0F 77 77 77 77 77' + '77 77 77 80 08 77 77 77 77 77 77 77 77 80 0F 77' + '77 77 77 77 77 77 77 80 08 77 77 77 77 77 77 77' + '77 80 0F FF FF FF FF FF FF FF FF F0 08 88 88 88' + '88 88 88 88 88 80 B0 00 00 00 00 00 00 00 00 0B' + 'B0 00 00 00 00 00 00 00 00 0B' +END + + +// Version info. +// +#if !defined(__DEBUG_) +// Non-Debug VERSIONINFO +1 VERSIONINFO LOADONCALL MOVEABLE +FILEVERSION 1, 0, 0, 0 +PRODUCTVERSION 1, 0, 0, 0 +FILEFLAGSMASK 0 +FILEFLAGS VS_FFI_FILEFLAGSMASK +FILEOS VOS__WINDOWS16 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + // Language type = U.S. English (0x0409) and Character Set = Windows, Multilingual(0x04e4) + BLOCK "040904E4" // Matches VarFileInfo Translation hex value. + BEGIN + VALUE "CompanyName", "PKWARE, INC.\000" + VALUE "FileDescription", "span for Windows\000" + VALUE "FileVersion", "1.0\000" + VALUE "InternalName", "span\000" + VALUE "LegalCopyright", "Copyright © 1995. All Rights Reserved.\000" + VALUE "LegalTrademarks", "Windows (TM) is a trademark of Microsoft Corporation\000" + VALUE "OriginalFilename", "span.EXE\000" + VALUE "ProductName", "span\000" + VALUE "ProductVersion", "1.0\000" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04e4 // U.S. English(0x0409) & Windows Multilingual(0x04e4) 1252 + END + +END +#else + +// Debug VERSIONINFO +1 VERSIONINFO LOADONCALL MOVEABLE +FILEVERSION 1, 0, 0, 0 +PRODUCTVERSION 1, 0, 0, 0 +FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE | VS_FF_PATCHED | VS_FF_PRIVATEBUILD | VS_FF_SPECIALBUILD +FILEFLAGS VS_FFI_FILEFLAGSMASK +FILEOS VOS__WINDOWS16 +FILETYPE VFT_APP +BEGIN + BLOCK "StringFileInfo" + BEGIN + // Language type = U.S. English (0x0409) and Character Set = Windows, Multilingual(0x04e4) + BLOCK "040904E4" // Matches VarFileInfo Translation hex value. + BEGIN + VALUE "CompanyName", "PKWARE, INC.\000" + VALUE "FileDescription", "span for Windows\000" + VALUE "FileVersion", "1.0\000" + VALUE "InternalName", "span\000" + VALUE "LegalCopyright", "Copyright © 1995. All Rights Reserved.\000" + VALUE "LegalTrademarks", "Windows (TM) is a trademark of Microsoft Corporation\000" + VALUE "OriginalFilename", "span.EXE\000" + VALUE "ProductName", "span\000" + VALUE "ProductVersion", "1.0\000" + VALUE "SpecialBuild", "Debug Version\000" + VALUE "PrivateBuild", "Built by \000" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04e4 // U.S. English(0x0409) & Windows Multilingual(0x04e4) 1252 + END + +END +#endif diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.RH b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.RH new file mode 100644 index 0000000..f59b650 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPANAPP.RH @@ -0,0 +1,204 @@ +//#if !defined(__spanapp_rh) // Sentry use file only if it's not already included. +//#define __spanapp_rh + +/* Project span + PKWARE, INC. + Copyright © 1995. All Rights Reserved. + + SUBSYSTEM: span.exe Application + FILE: spanapp.h + AUTHOR: + + + OVERVIEW + ======== + Constant definitions for all resources defined in spanapp.rc. +*/ + + +// +// IDHELP BorButton for BWCC dialogs. +// +#define IDHELP 998 // Id of help button + + +// +// Application specific definitions: +// +#define IDI_SDIAPPLICATION 1001 // Application icon + +#define SDI_MENU 100 // Menu resource ID and Accelerator IDs +#define CM_COMP_TYPE_BINARY 107 +#define CM_COMP_TYPE_ASCII 106 +#define CM_DICT_SIZE_4096 105 +#define CM_DICT_SIZE_2048 104 +#define CM_DICT_SIZE_1024 103 +#define CM_UNCOMPRESS_FILES 102 +#define CM_COMPRESS_FILES 101 + +#define IDM_DOCMANAGERFILE 32401 // Menu for DocManager merging. +#define IDM_EDITVIEW 32581 // Menu for TEditView merging. +#define IDM_LISTVIEW 32582 // Menu for TListView merging. + +// +// CM_FILEnnnn commands (include\owl\editfile.rh except for CM_FILEPRINTPREVIEW) +// +#define CM_FILENEW 24331 // SDI New +#define CM_FILEOPEN 24332 // SDI Open +#define CM_FILECLOSE 24339 +#define CM_FILESAVE 24333 +#define CM_FILESAVEAS 24334 +#define CM_FILEREVERT 24335 +#define CM_VIEWCREATE 24341 + + +// +// Window commands (include\owl\window.rh) +// +#define CM_EXIT 24310 + + +// +// CM_EDITnnnn commands (include\owl\window.rh) +// +#define CM_EDITUNDO 24321 +#define CM_EDITCUT 24322 +#define CM_EDITCOPY 24323 +#define CM_EDITPASTE 24324 +#define CM_EDITDELETE 24325 +#define CM_EDITCLEAR 24326 +#define CM_EDITADD 24327 +#define CM_EDITEDIT 24328 + + +// +// Search menu commands (include\owl\editsear.rh) +// +#define CM_EDITFIND 24351 +#define CM_EDITREPLACE 24352 +#define CM_EDITFINDNEXT 24353 + + +// +// Help menu commands. +// +#define CM_HELPABOUT 2009 + + +// +// About Dialogs +// +#define IDD_ABOUT 22000 +#define IDC_VERSION 22001 +#define IDC_COPYRIGHT 22002 +#define IDC_DEBUG 22003 + + +// +// OWL defined strings +// + +// Statusbar +#define IDS_MODES 32530 +#define IDS_MODESOFF 32531 + + +// EditFile +#define IDS_UNABLEREAD 32551 +#define IDS_UNABLEWRITE 32552 +#define IDS_FILECHANGED 32553 +#define IDS_FILEFILTER 32554 + +// EditSearch +#define IDS_CANNOTFIND 32540 + + +// +// General & application exception messages (include\owl\except.rh) +// +#define IDS_UNKNOWNEXCEPTION 32767 +#define IDS_OWLEXCEPTION 32766 +#define IDS_OKTORESUME 32765 +#define IDS_UNHANDLEDXMSG 32764 +#define IDS_UNKNOWNERROR 32763 +#define IDS_NOAPP 32762 +#define IDS_OUTOFMEMORY 32761 +#define IDS_INVALIDMODULE 32760 +#define IDS_INVALIDMAINWINDOW 32759 +#define IDS_VBXLIBRARYFAIL 32758 + +// +// Owl 1 compatibility messages +// +#define IDS_INVALIDWINDOW 32756 +#define IDS_INVALIDCHILDWINDOW 32755 +#define IDS_INVALIDCLIENTWINDOW 32754 + +// +// TXWindow messages +// +#define IDS_CLASSREGISTERFAIL 32749 +#define IDS_CHILDREGISTERFAIL 32748 +#define IDS_WINDOWCREATEFAIL 32747 +#define IDS_WINDOWEXECUTEFAIL 32746 +#define IDS_CHILDCREATEFAIL 32745 + +#define IDS_MENUFAILURE 32744 +#define IDS_VALIDATORSYNTAX 32743 +#define IDS_PRINTERERROR 32742 + +#define IDS_LAYOUTINCOMPLETE 32741 +#define IDS_LAYOUTBADRELWIN 32740 + +// +// TXGdi messages +// +#define IDS_GDIFAILURE 32739 +#define IDS_GDIALLOCFAIL 32738 +#define IDS_GDICREATEFAIL 32737 +#define IDS_GDIRESLOADFAIL 32736 +#define IDS_GDIFILEREADFAIL 32735 +#define IDS_GDIDELETEFAIL 32734 +#define IDS_GDIDESTROYFAIL 32733 +#define IDS_INVALIDDIBHANDLE 32732 + + +// ListView (include\owl\listview.rh) +#define IDS_LISTNUM 32584 + + +// DocView (include\owl\docview.rh) +#define IDS_DOCMANAGERFILE 32500 +#define IDS_DOCLIST 32501 +#define IDS_VIEWLIST 32502 +#define IDS_UNTITLED 32503 +#define IDS_UNABLEOPEN 32504 +#define IDS_UNABLECLOSE 32505 +#define IDS_READERROR 32506 +#define IDS_WRITEERROR 32507 +#define IDS_DOCCHANGED 32508 +#define IDS_NOTCHANGED 32509 +#define IDS_NODOCMANAGER 32510 +#define IDS_NOMEMORYFORVIEW 32511 +#define IDS_DUPLICATEDOC 32512 + + +// TInputDialog DIALOG resource (include\owl\inputdia.rh) +#define IDD_INPUTDIALOG 32514 +#define ID_PROMPT 4091 +#define ID_INPUT 4090 + + +// TSlider bitmaps (horizontal and vertical) (include\owl\slider.rh) +#define IDB_HSLIDERTHUMB 32000 +#define IDB_VSLIDERTHUMB 32001 + + +// Validation messages (include\owl\validate.rh) +#define IDS_VALPXPCONFORM 32520 +#define IDS_VALINVALIDCHAR 32521 +#define IDS_VALNOTINRANGE 32522 +#define IDS_VALNOTINLIST 32523 + + +//#endif // __spanapp_rh sentry. diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNABTDL.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNABTDL.CPP new file mode 100644 index 0000000..e2dfc02 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNABTDL.CPP @@ -0,0 +1,157 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include +#pragma hdrstop + +#if !defined(__FLAT__) +#include +#endif + +#include "spanapp.h" +#include "spnabtdl.h" + + +ProjectRCVersion::ProjectRCVersion (TModule *module) +{ + char appFName[255]; + char subBlockName[255]; + DWORD fvHandle; + UINT vSize; + + FVData = 0; + + module->GetModuleFileName(appFName, sizeof(appFName)); + OemToAnsi(appFName, appFName); + DWORD dwSize = ::GetFileVersionInfoSize(appFName, &fvHandle); + if (dwSize) { + FVData = (void FAR *)new char[(UINT)dwSize]; + if (::GetFileVersionInfo(appFName, fvHandle, dwSize, FVData)) { + // Copy string to buffer so if the -dc compiler switch (Put constant strings in code segments) + // is on VerQueryValue will work under Win16. This works around a problem in Microsoft's ver.dll + // which writes to the string pointed to by subBlockName. + strcpy(subBlockName, "\\VarFileInfo\\Translation"); + if (!::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)&TransBlock, &vSize)) { + delete FVData; + FVData = 0; + } else + // Swap the words so wsprintf will print the lang-charset in the correct format. + *(DWORD *)TransBlock = MAKELONG(HIWORD(*(DWORD *)TransBlock), LOWORD(*(DWORD *)TransBlock)); + } + } +} + + +ProjectRCVersion::~ProjectRCVersion () +{ + if (FVData) + delete FVData; +} + + +bool ProjectRCVersion::GetProductName (LPSTR &prodName) +{ + UINT vSize; + char subBlockName[255]; + + wsprintf(subBlockName, "\\StringFileInfo\\%08lx\\%s", *(DWORD *)TransBlock, (LPSTR)"ProductName"); + return FVData ? ::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)&prodName, &vSize) : false; +} + + +bool ProjectRCVersion::GetProductVersion (LPSTR &prodVersion) +{ + UINT vSize; + char subBlockName[255]; + + wsprintf(subBlockName, "\\StringFileInfo\\%08lx\\%s", *(DWORD *)TransBlock, (LPSTR)"ProductVersion"); + return FVData ? ::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)&prodVersion, &vSize) : false; +} + + +bool ProjectRCVersion::GetCopyright (LPSTR ©right) +{ + UINT vSize; + char subBlockName[255]; + + wsprintf(subBlockName, "\\StringFileInfo\\%08lx\\%s", *(DWORD *)TransBlock, (LPSTR)"LegalCopyright"); + return FVData ? ::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)©right, &vSize) : false; +} + + +bool ProjectRCVersion::GetDebug (LPSTR &debug) +{ + UINT vSize; + char subBlockName[255]; + + wsprintf(subBlockName, "\\StringFileInfo\\%08lx\\%s", *(DWORD *)TransBlock, (LPSTR)"SpecialBuild"); + return FVData ? ::VerQueryValue(FVData, subBlockName, (void FAR* FAR*)&debug, &vSize) : false; +} + + +//{{spanAboutDlg Implementation}} + + +////////////////////////////////////////////////////////// +// spanAboutDlg +// ========== +// Construction/Destruction handling. +spanAboutDlg::spanAboutDlg (TWindow *parent, TResId resId, TModule *module) + : TDialog(parent, resId, module) +{ + // INSERT>> Your constructor code here. +} + + +spanAboutDlg::~spanAboutDlg () +{ + Destroy(); + + // INSERT>> Your destructor code here. +} + + +void spanAboutDlg::SetupWindow () +{ + LPSTR prodName = 0, prodVersion = 0, copyright = 0, debug = 0; + + // Get the static text for the value based on VERSIONINFO. + TStatic *versionCtrl = new TStatic(this, IDC_VERSION, 255); + TStatic *copyrightCtrl = new TStatic(this, IDC_COPYRIGHT, 255); + TStatic *debugCtrl = new TStatic(this, IDC_DEBUG, 255); + + TDialog::SetupWindow(); + + // Process the VERSIONINFO. + ProjectRCVersion applVersion(GetModule()); + + // Get the product name and product version strings. + if (applVersion.GetProductName(prodName) && applVersion.GetProductVersion(prodVersion)) { + // IDC_VERSION is the product name and version number, the initial value of IDC_VERSION is + // the word Version (in whatever language) product name VERSION product version. + char buffer[255]; + char versionName[128]; + + buffer[0] = '\0'; + versionName[0] = '\0'; + + versionCtrl->GetText(versionName, sizeof(versionName)); + wsprintf(buffer, "%s %s %s", prodName, versionName, prodVersion); + + versionCtrl->SetText(buffer); + } + + //Get the legal copyright string. + if (applVersion.GetCopyright(copyright)) + copyrightCtrl->SetText(copyright); + + // Only get the SpecialBuild text if the VERSIONINFO resource is there. + if (applVersion.GetDebug(debug)) + debugCtrl->SetText(debug); +} diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNABTDL.H b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNABTDL.H new file mode 100644 index 0000000..f7ad9bb --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNABTDL.H @@ -0,0 +1,53 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#if !defined(__spnabtdl_h) // Sentry, use file only if it's not already included. +#define __spnabtdl_h + +#include +#pragma hdrstop + +#include "spanapp.rh" // Definition of all resources. + + +//{{TDialog = spanAboutDlg}} +class spanAboutDlg : public TDialog { +public: + spanAboutDlg (TWindow *parent, TResId resId = IDD_ABOUT, TModule *module = 0); + virtual ~spanAboutDlg (); + +//{{spanAboutDlgVIRTUAL_BEGIN}} +public: + void SetupWindow (); +//{{spanAboutDlgVIRTUAL_END}} +}; //{{spanAboutDlg}} + + +// Reading the VERSIONINFO resource. +class ProjectRCVersion { +public: + ProjectRCVersion (TModule *module); + virtual ~ProjectRCVersion (); + + bool GetProductName (LPSTR &prodName); + bool GetProductVersion (LPSTR &prodVersion); + bool GetCopyright (LPSTR ©right); + bool GetDebug (LPSTR &debug); + +protected: + LPBYTE TransBlock; + void FAR *FVData; + +private: + // Don't allow this object to be copied. + ProjectRCVersion (const ProjectRCVersion &); + ProjectRCVersion & operator =(const ProjectRCVersion &); +}; + + +#endif // __spnabtdl_h sentry. diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNEDTVW.CPP b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNEDTVW.CPP new file mode 100644 index 0000000..783d687 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNEDTVW.CPP @@ -0,0 +1,38 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ + +#include +#pragma hdrstop + +#include "spanapp.h" +#include "spnedtvw.h" + +#include + + +//{{spanEditView Implementation}} + + +////////////////////////////////////////////////////////// +// spanEditView +// ========== +// Construction/Destruction handling. +spanEditView::spanEditView (TDocument& doc, TWindow* parent) + : TEditView(doc, parent) +{ + // INSERT>> Your constructor code here. + +} + + +spanEditView::~spanEditView () +{ + // INSERT>> Your destructor code here. + +} diff --git a/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNEDTVW.H b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNEDTVW.H new file mode 100644 index 0000000..b983307 --- /dev/null +++ b/src/Storm/PKWARE/EXAMPLES/OWL/SPAN/SPNEDTVW.H @@ -0,0 +1,27 @@ +/* + ******************************************************************* + *** Important information for use with the *** + *** PKWARE Data Compression Library (R) for Win32 *** + *** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** + *** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** + ******************************************************************* + */ +#if !defined(__spnedtvw_h) // Sentry, use file only if it's not already included. +#define __spnedtvw_h + +#include +#pragma hdrstop + + +#include "spanapp.rh" // Definition of all resources. + + +//{{TEditView = spanEditView}} +class spanEditView : public TEditView { +public: + spanEditView (TDocument& doc, TWindow* parent = 0); + virtual ~spanEditView (); +}; //{{spanEditView}} + + +#endif // __spnedtvw_h sentry. diff --git a/src/Storm/PKWARE/H/IMPLODE.H b/src/Storm/PKWARE/H/IMPLODE.H new file mode 100644 index 0000000..c65ccc1 --- /dev/null +++ b/src/Storm/PKWARE/H/IMPLODE.H @@ -0,0 +1,44 @@ +/*************************************************************** + PKWARE Data Compression Library (R) for Win32 + Copyright 1991,1992,1994,1995 PKWARE Inc. All Rights Reserved. + PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +***************************************************************/ + +#ifdef __cplusplus + extern "C" { +#endif + +unsigned int __cdecl implode( + unsigned int (__cdecl *read_buf)(char *buf, unsigned int *size, void *param), + void (__cdecl *write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param, + unsigned int *type, + unsigned int *dsize); + + +unsigned int __cdecl explode( + unsigned int (__cdecl *read_buf)(char *buf, unsigned int *size, void *param), + void (__cdecl *write_buf)(char *buf, unsigned int *size, void *param), + char *work_buf, + void *param); + +unsigned long __cdecl crc32(char *buffer, unsigned int *size, unsigned long *old_crc); + +#ifdef __cplusplus + } // End of 'extern "C"' declaration +#endif + + +#define CMP_BUFFER_SIZE 36312 +#define EXP_BUFFER_SIZE 12596 + +#define CMP_BINARY 0 +#define CMP_ASCII 1 + +#define CMP_NO_ERROR 0 +#define CMP_INVALID_DICTSIZE 1 +#define CMP_INVALID_MODE 2 +#define CMP_BAD_DATA 3 +#define CMP_ABORT 4 + diff --git a/src/Storm/PKWARE/LIB/IMPBORL.LIB b/src/Storm/PKWARE/LIB/IMPBORL.LIB new file mode 100644 index 0000000..f0fc096 Binary files /dev/null and b/src/Storm/PKWARE/LIB/IMPBORL.LIB differ diff --git a/src/Storm/PKWARE/LIB/IMPBORLI.LIB b/src/Storm/PKWARE/LIB/IMPBORLI.LIB new file mode 100644 index 0000000..9ef7765 Binary files /dev/null and b/src/Storm/PKWARE/LIB/IMPBORLI.LIB differ diff --git a/src/Storm/PKWARE/LIB/IMPLODE.LIB b/src/Storm/PKWARE/LIB/IMPLODE.LIB new file mode 100644 index 0000000..4cc55e1 Binary files /dev/null and b/src/Storm/PKWARE/LIB/IMPLODE.LIB differ diff --git a/src/Storm/PKWARE/LIB/IMPLODEI.LIB b/src/Storm/PKWARE/LIB/IMPLODEI.LIB new file mode 100644 index 0000000..ca0b4df Binary files /dev/null and b/src/Storm/PKWARE/LIB/IMPLODEI.LIB differ diff --git a/src/Storm/PKWARE/README b/src/Storm/PKWARE/README new file mode 100644 index 0000000..024007d --- /dev/null +++ b/src/Storm/PKWARE/README @@ -0,0 +1,79 @@ +******************************************************************* +*** Important information for use with the *** +*** PKWARE Data Compression Library (R) for Win32 *** +*** Copyright 1995 by PKWARE Inc. All Rights Reserved. *** +*** PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. *** +******************************************************************* + +* Please read the following file before calling PKWARE for technical support! + +*************************************************************************** + + +* When installing the PKWARE Data Compression Library for Win32, you + should keep the directory structure of the floppy intact on your hard + disk. Use the supplied INSTALL.BAT file to install the files from the + floppy disk to your hard disk. To use the INSTALL.BAT program, type: + + [source:]install [source:] [destination:] + + where [source:] is the PKWARE distribution disk + and [destination:] is the target disk. + + The PKWARE Data Compression Library will be installed in a directory + called PKW32DCL on the destination drive. + + +* For more information on the examples, read the EXAMPLES.TXT file. + + + F I L E D E S C R I P T I O N S +-------------------------------------------------------------- + +implode.lib Static link library (includes all .OBJ files). + +implodei.lib Dynamic link import library for use with DLL files. + +impborl.lib Static link library for Borland C++ compiler (includes + all .OBJ files). + +impborli.lib Dynamic link import library for Borland C++ compiler, + for use with DLL files. + +implode.dll Dynamic link library of the PKWARE Data Compression Library. + +impborl.dll Dynamic link library created by Borland C++ compiler. + +crc32.obj Object module file for CRC-32 error checking routine. + +crcborl.obj Borland C++ Object module file for CRC-32 error checking + routine. + +crcfast.obj __fastcall calling convention object module file for CRC-32 + error checking routine. + +crcstd.obj __stdcall calling convention object module file for CRC-32 + error checking routine. + +explode.obj Object module file for explode routine. + +expborl.obj Borland C++ Object module file for explode routine. + +expfast.obj __fastcall calling convention object module file for explode + routine. + +expstd.obj __stdcall calling convention object module file for explode + routine. + +implode.obj Object module file for implode routine. + +impborl.obj Borland C++ Object module file for implode routine. + +impfast.obj __fastcall calling convention object module file for implode + routine. + +impstd.obj __stdcall calling convention object module file for implode + routine. + +implode.h A C/C++ header file for use with the PKWARE Data Compression + Library. diff --git a/src/Storm/RELEASE/STORM.EXP b/src/Storm/RELEASE/STORM.EXP new file mode 100644 index 0000000..6dbfbdc Binary files /dev/null and b/src/Storm/RELEASE/STORM.EXP differ diff --git a/src/Storm/RELEASE/STORM.LIB b/src/Storm/RELEASE/STORM.LIB new file mode 100644 index 0000000..6e2815e Binary files /dev/null and b/src/Storm/RELEASE/STORM.LIB differ diff --git a/src/Storm/RELEASE/STORM.RES b/src/Storm/RELEASE/STORM.RES new file mode 100644 index 0000000..2433693 Binary files /dev/null and b/src/Storm/RELEASE/STORM.RES differ diff --git a/src/Storm/RELEASE/STORMDLL.DLL b/src/Storm/RELEASE/STORMDLL.DLL new file mode 100644 index 0000000..b1265ee Binary files /dev/null and b/src/Storm/RELEASE/STORMDLL.DLL differ diff --git a/src/Storm/RELEASE/STORMDLL.EXP b/src/Storm/RELEASE/STORMDLL.EXP new file mode 100644 index 0000000..c422641 Binary files /dev/null and b/src/Storm/RELEASE/STORMDLL.EXP differ diff --git a/src/Storm/RELEASE/STORMDLL.LIB b/src/Storm/RELEASE/STORMDLL.LIB new file mode 100644 index 0000000..39904eb Binary files /dev/null and b/src/Storm/RELEASE/STORMDLL.LIB differ diff --git a/src/Storm/RELEASE/STORMDLL.PCH b/src/Storm/RELEASE/STORMDLL.PCH new file mode 100644 index 0000000..b1f8319 Binary files /dev/null and b/src/Storm/RELEASE/STORMDLL.PCH differ diff --git a/src/Storm/RELEASE/VC50.IDB b/src/Storm/RELEASE/VC50.IDB new file mode 100644 index 0000000..d0eaee3 Binary files /dev/null and b/src/Storm/RELEASE/VC50.IDB differ diff --git a/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.CPP b/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.CPP new file mode 100644 index 0000000..a5a6990 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.CPP @@ -0,0 +1,241 @@ +/**************************************************************************** +* +* ANIM1.CPP +* +* This is the first of a series of programs that demonstrate progressively +* better ways to do animation. +* +* This first program just composites each frame to an offscreen buffer, +* then blits the offscreen buffer onto the screen. +* +***/ + +#include +#include +#include + +#define SPRITES 4 + +#define SIN(a) sintable[((a) & 255)] +#define COS(a) sintable[(((a)+64) & 255)] + +static LPBYTE backgroundbuffer = NULL; +static HSGDIFONT font = 0; +static LPBYTE offscreenbuffer = NULL; +static HSTRANS overlay = 0; +static int sintable[256]; +static HSTRANS sprite[SPRITES] = {0,0,0,0}; + +//=========================================================================== +static BOOL CreateBackgroundBuffer () { + backgroundbuffer = (LPBYTE)ALLOC(640*480); + if (!backgroundbuffer) + return 0; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\bkg.pcx",&pe[0],backgroundbuffer,640*480)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +static BOOL CreateOffscreenBuffer () { + offscreenbuffer = (LPBYTE)ALLOC(640*480); + if (!offscreenbuffer) + return 0; + CopyMemory(offscreenbuffer,backgroundbuffer,640*480); + return 1; +} + +//=========================================================================== +static void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + sintable[loop] = (int)(sin(angle)*128); + } +} + +//=========================================================================== +static void DisplayFramesPerSecond (LPBYTE buffer, int pitch) { + static DWORD frames = 0; + static DWORD lastfps = 0; + static DWORD lasttime = GetTickCount(); + + // UPDATE THE NUMBER OF FRAMES THIS SECOND + if (GetTickCount()-lasttime >= 1000) { + lastfps = frames; + frames = 0; + lasttime += 1000; + } + ++frames; + + // DISPLAY THE LAST NUMBER OF FRAMES PER SECOND + char outstr[16]; + wsprintf(outstr,"%3u FPS",lastfps); + RECT rect = {0,20,60,32}; + SGdiSetPitch(pitch); + SGdiExtTextOut(buffer, + 0, + 20, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + +} + +//=========================================================================== +static BOOL CALLBACK IdleProc (DWORD) { + + // INITIALIZE THE OFFSCREEN BUFFER USING THE BACKGROUND IMAGE + CopyMemory(offscreenbuffer,backgroundbuffer,640*480); + + // DRAW EACH SPRITE INTO THE OFFSCREEN BUFFER + { + static BYTE distance = 0; + static BYTE rotation = 0; + for (int loop = 0; loop < SPRITES; ++loop) { + int x = 170+(SIN(rotation+64*loop)*SIN(distance/2)/100); + int y = 165+(COS(rotation+64*loop)*SIN(distance/2)/100); + STransBlt(offscreenbuffer, + x, + y, + 640, + sprite[loop]); + } + ++distance; + rotation += 3; + } + + // DRAW THE STATUS BAR INTO THE OFFSCREEN BUFFER + STransBlt(offscreenbuffer, + 0, + 0, + 640, + overlay); + + // DRAW THE FRAMES PER SECOND COUNTER INTO THE OFFSCREEN BUFFER + DisplayFramesPerSecond(offscreenbuffer,640); + + // COPY THE OFFSCREEN BUFFER ONTO THE SCREEN + { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiBitBlt(videobuffer, + 0, + 0, + offscreenbuffer, + NULL, + 640, + 480); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + } + + return TRUE; +} + +//=========================================================================== +static BOOL LoadFont () { + { + HFONT winfont = CreateFont(-12,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +static BOOL LoadOverlay () { + LPBYTE temp = (LPBYTE)ALLOC(640*480); + if (!SBmpLoadImage("..\\demodata\\overlay.pcx",NULL,temp,640*480)) + return 0; + if (!STransCreate(temp,640,480,8,NULL,PALETTEINDEX(111),&overlay)) + return 0; + FREE(temp); + return 1; +} + +//=========================================================================== +static BOOL LoadSprites () { + LPBYTE temp = (LPBYTE)ALLOC(300*500); + if (!SBmpLoadImage("..\\demodata\\sprites.pcx",NULL,temp,300*500)) + return 0; + for (int loop = 0; loop < SPRITES; ++loop) { + RECT rect = {0,loop*125,299,loop*125+124}; + if (!STransCreate(temp,300,500,8,&rect,PALETTEINDEX(*temp),&sprite[loop])) + return 0; + } + FREE(temp); + return 1; +} + +//=========================================================================== +static void CALLBACK OnClose (LPPARAMS) { + FREE(backgroundbuffer); + FREE(offscreenbuffer); + SGdiDeleteObject(font); + STransDelete(overlay); + for (int loop = 0; loop < SPRITES; ++loop) + STransDelete(sprite[loop]); +} + +//=========================================================================== +static void CALLBACK OnPaint (LPPARAMS params) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SBltROP3(videobuffer, + offscreenbuffer, + 640, + 480, + videopitch, + 640, + 0, + SRCCOPY); + STransBlt(videobuffer, + 0, + 0, + videopitch, + overlay); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + ValidateRect(params->window,NULL); + params->useresult = TRUE; + params->result = 0; +} + +//=========================================================================== +static void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + CreateSinTable(); + if (!SDrawAutoInitialize(instance, + TEXT("ANIM1"), + TEXT("Animation Example 1"))) + FATALRESULT("SDrawAutoInitialize()"); + if (!CreateBackgroundBuffer()) + FATALRESULT("CreateBackgroundBuffer()"); + if (!CreateOffscreenBuffer()) + FATALRESULT("CreateOffsreenBuffer()"); + if (!LoadFont()) + FATALRESULT("LoadFont()"); + if (!LoadOverlay()) + FATALRESULT("LoadOverlay()"); + if (!LoadSprites()) + FATALRESULT("LoadSprites()"); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.CS b/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.EXE b/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.EXE new file mode 100644 index 0000000..a565b41 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/ANIM1/ANIM1.EXE differ diff --git a/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.CPP b/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.CPP new file mode 100644 index 0000000..435c245 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.CPP @@ -0,0 +1,234 @@ +/**************************************************************************** +* +* ANIM2.CPP +* +* This sample application demonstrates the use of overlays. +* +* Instead of drawing the entire screen every frame, this application draws +* only the portion which is not covered up by the status bar, since the +* status bar is known not to change. +* +***/ + +#include +#include +#include + +#define SPRITES 4 + +#define SIN(a) sintable[((a) & 255)] +#define COS(a) sintable[(((a)+64) & 255)] + +static LPBYTE backgroundbuffer = NULL; +static HSGDIFONT font = 0; +static LPBYTE offscreenbuffer = NULL; +static HSTRANS overlay = 0; +static HSTRANS updatemask = 0; +static int sintable[256]; +static HSTRANS sprite[SPRITES] = {0,0,0,0}; + +//=========================================================================== +static BOOL CreateBackgroundBuffer () { + backgroundbuffer = (LPBYTE)ALLOC(640*480); + if (!backgroundbuffer) + return 0; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\bkg.pcx",&pe[0],backgroundbuffer,640*480)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +static BOOL CreateOffscreenBuffer () { + offscreenbuffer = (LPBYTE)ALLOC(640*480); + if (!offscreenbuffer) + return 0; + CopyMemory(offscreenbuffer,backgroundbuffer,640*480); + return 1; +} + +//=========================================================================== +static void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + sintable[loop] = (int)(sin(angle)*128); + } +} + +//=========================================================================== +static void DisplayFramesPerSecond (LPBYTE buffer, int pitch) { + static DWORD frames = 0; + static DWORD lastfps = 0; + static DWORD lasttime = GetTickCount(); + + // UPDATE THE NUMBER OF FRAMES THIS SECOND + if (GetTickCount()-lasttime >= 1000) { + lastfps = frames; + frames = 0; + lasttime += 1000; + } + ++frames; + + // DISPLAY THE LAST NUMBER OF FRAMES PER SECOND + char outstr[16]; + wsprintf(outstr,"%3u FPS",lastfps); + RECT rect = {0,20,60,32}; + SGdiSetPitch(pitch); + SGdiExtTextOut(buffer, + 0, + 20, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + +} + +//=========================================================================== +static BOOL CALLBACK IdleProc (DWORD) { + + // INITIALIZE THE OFFSCREEN BUFFER USING THE BACKGROUND IMAGE + CopyMemory(offscreenbuffer,backgroundbuffer,640*480); + + // DRAW EACH SPRITE INTO THE OFFSCREEN BUFFER + { + static BYTE distance = 0; + static BYTE rotation = 0; + for (int loop = 0; loop < SPRITES; ++loop) { + int x = 170+(SIN(rotation+64*loop)*SIN(distance/2)/100); + int y = 165+(COS(rotation+64*loop)*SIN(distance/2)/100); + STransBlt(offscreenbuffer, + x, + y, + 640, + sprite[loop]); + } + ++distance; + rotation += 3; + } + + // DRAW THE FRAMES PER SECOND COUNTER INTO THE OFFSCREEN BUFFER + DisplayFramesPerSecond(offscreenbuffer,640); + + // DRAW THE OFFSCREEN BUFFER ONTO THE SCREEN, BLITTING AROUND THE + // STATUS BAR + { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + STransBltUsingMask(videobuffer, + offscreenbuffer, + videopitch, + 640, + updatemask); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + } + + return TRUE; +} + +//=========================================================================== +static BOOL LoadFont () { + { + HFONT winfont = CreateFont(-12,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +static BOOL LoadOverlay () { + LPBYTE temp = (LPBYTE)ALLOC(640*480); + if (!SBmpLoadImage("..\\demodata\\overlay.pcx",NULL,temp,640*480)) + return 0; + if (!STransCreate(temp,640,480,8,NULL,PALETTEINDEX(111),&overlay)) + return 0; + if (!STransInvertMask(overlay,&updatemask)) + return 0; + FREE(temp); + return 1; +} + +//=========================================================================== +static BOOL LoadSprites () { + LPBYTE temp = (LPBYTE)ALLOC(300*500); + if (!SBmpLoadImage("..\\demodata\\sprites.pcx",NULL,temp,300*500)) + return 0; + for (int loop = 0; loop < SPRITES; ++loop) { + RECT rect = {0,loop*125,299,loop*125+124}; + if (!STransCreate(temp,300,500,8,&rect,PALETTEINDEX(*temp),&sprite[loop])) + return 0; + } + FREE(temp); + return 1; +} + +//=========================================================================== +static void CALLBACK OnClose (LPPARAMS) { + FREE(backgroundbuffer); + FREE(offscreenbuffer); + SGdiDeleteObject(font); + STransDelete(overlay); + STransDelete(updatemask); + for (int loop = 0; loop < SPRITES; ++loop) + STransDelete(sprite[loop]); +} + +//=========================================================================== +static void CALLBACK OnPaint (LPPARAMS params) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + STransBltUsingMask(videobuffer, + offscreenbuffer, + videopitch, + 640, + updatemask); + STransBlt(videobuffer, + 0, + 0, + videopitch, + overlay); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + ValidateRect(params->window,NULL); + params->useresult = TRUE; + params->result = 0; +} + +//=========================================================================== +static void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + CreateSinTable(); + if (!SDrawAutoInitialize(instance, + TEXT("ANIM3"), + TEXT("Animation Example 3"))) + FATALRESULT("SDrawAutoInitialize()"); + if (!CreateBackgroundBuffer()) + FATALRESULT("CreateBackgroundBuffer()"); + if (!CreateOffscreenBuffer()) + FATALRESULT("CreateOffsreenBuffer()"); + if (!LoadFont()) + FATALRESULT("LoadFont()"); + if (!LoadOverlay()) + FATALRESULT("LoadOverlay()"); + if (!LoadSprites()) + FATALRESULT("LoadSprites()"); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.CS b/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.EXE b/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.EXE new file mode 100644 index 0000000..33d207b Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/ANIM2/ANIM2.EXE differ diff --git a/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.CPP b/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.CPP new file mode 100644 index 0000000..d23aa45 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.CPP @@ -0,0 +1,251 @@ +/**************************************************************************** +* +* ANIM3.CPP +* +* This sample application improves on the performance of Anim2 by reducing +* the amount of time it has to spend repainting the offscreen buffer. +* Instead of erasing the entire offscreen buffer with the background every +* frame, it only erases those portions that were covered by a sprite last +* frame. +* +* A weakness of this sample application is that it doesn't test whether +* a portion of the offscreen buffer has already been erased before erasing +* it again. This means its performance will degrade substantially as more +* of the screen gets covered by sprites, potentially at some point becoming +* slower than Anim2. +* +***/ + +#include +#include +#include + +#define SPRITES 4 + +#define SIN(a) sintable[((a) & 255)] +#define COS(a) sintable[(((a)+64) & 255)] + +static LPBYTE backgroundbuffer = NULL; +static HSGDIFONT font = 0; +static LPBYTE offscreenbuffer = NULL; +static HSTRANS overlay = 0; +static HSTRANS updatemask = 0; +static int sintable[256]; +static HSTRANS sprite[SPRITES] = {0,0,0,0}; + +//=========================================================================== +static BOOL CreateBackgroundBuffer () { + backgroundbuffer = (LPBYTE)ALLOC(640*480); + if (!backgroundbuffer) + return 0; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\bkg.pcx",&pe[0],backgroundbuffer,640*480)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +static BOOL CreateOffscreenBuffer () { + offscreenbuffer = (LPBYTE)ALLOC(640*480); + if (!offscreenbuffer) + return 0; + CopyMemory(offscreenbuffer,backgroundbuffer,640*480); + return 1; +} + +//=========================================================================== +static void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + sintable[loop] = (int)(sin(angle)*128); + } +} + +//=========================================================================== +static void DisplayFramesPerSecond (LPBYTE buffer, int pitch) { + static DWORD frames = 0; + static DWORD lastfps = 0; + static DWORD lasttime = GetTickCount(); + + // UPDATE THE NUMBER OF FRAMES THIS SECOND + if (GetTickCount()-lasttime >= 1000) { + lastfps = frames; + frames = 0; + lasttime += 1000; + } + ++frames; + + // DISPLAY THE LAST NUMBER OF FRAMES PER SECOND + char outstr[16]; + wsprintf(outstr,"%3u FPS",lastfps); + RECT rect = {0,20,60,32}; + SGdiSetPitch(pitch); + SGdiExtTextOut(buffer, + 0, + 20, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + +} + +//=========================================================================== +static BOOL CALLBACK IdleProc (DWORD) { + static BYTE distance = 0; + static BYTE rotation = 0; + + // ERASE EACH SPRITE THAT WAS DRAWN LAST FRAME FROM THE OFFSCREEN BUFFER + // BY OVERWRITING IT WITH DATA FROM THE BACKGROUND + { + for (int loop = 0; loop < SPRITES; ++loop) { + int x = 170+(SIN(rotation+64*loop)*SIN(distance/2)/100); + int y = 165+(COS(rotation+64*loop)*SIN(distance/2)/100); + STransBltUsingMask(offscreenbuffer+y*640+x, + backgroundbuffer+y*640+x, + 640, + 640, + sprite[loop]); + } + } + + // DRAW EACH SPRITE IN ITS NEW POSITION INTO THE OFFSCREEN BUFFER + ++distance; + rotation += 3; + { + for (int loop = 0; loop < SPRITES; ++loop) { + int x = 170+(SIN(rotation+64*loop)*SIN(distance/2)/100); + int y = 165+(COS(rotation+64*loop)*SIN(distance/2)/100); + STransBlt(offscreenbuffer, + x, + y, + 640, + sprite[loop]); + } + } + + // DRAW THE FRAMES PER SECOND COUNTER INTO THE OFFSCREEN BUFFER + DisplayFramesPerSecond(offscreenbuffer,640); + + // DRAW THE OFFSCREEN BUFFER ONTO THE SCREEN, BLITTING AROUND THE + // STATUS BAR + { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + STransBltUsingMask(videobuffer, + offscreenbuffer, + videopitch, + 640, + updatemask); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + } + + return TRUE; +} + +//=========================================================================== +static BOOL LoadFont () { + { + HFONT winfont = CreateFont(-12,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +static BOOL LoadOverlay () { + LPBYTE temp = (LPBYTE)ALLOC(640*480); + if (!SBmpLoadImage("..\\demodata\\overlay.pcx",NULL,temp,640*480)) + return 0; + if (!STransCreate(temp,640,480,8,NULL,PALETTEINDEX(111),&overlay)) + return 0; + if (!STransInvertMask(overlay,&updatemask)) + return 0; + FREE(temp); + return 1; +} + +//=========================================================================== +static BOOL LoadSprites () { + LPBYTE temp = (LPBYTE)ALLOC(300*500); + if (!SBmpLoadImage("..\\demodata\\sprites.pcx",NULL,temp,300*500)) + return 0; + for (int loop = 0; loop < SPRITES; ++loop) { + RECT rect = {0,loop*125,299,loop*125+124}; + if (!STransCreate(temp,300,500,8,&rect,PALETTEINDEX(*temp),&sprite[loop])) + return 0; + } + FREE(temp); + return 1; +} + +//=========================================================================== +static void CALLBACK OnClose (LPPARAMS) { + FREE(backgroundbuffer); + FREE(offscreenbuffer); + SGdiDeleteObject(font); + STransDelete(overlay); + STransDelete(updatemask); + for (int loop = 0; loop < SPRITES; ++loop) + STransDelete(sprite[loop]); +} + +//=========================================================================== +static void CALLBACK OnPaint (LPPARAMS params) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + STransBltUsingMask(videobuffer, + offscreenbuffer, + videopitch, + 640, + updatemask); + STransBlt(videobuffer, + 0, + 0, + videopitch, + overlay); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + ValidateRect(params->window,NULL); + params->useresult = TRUE; + params->result = 0; +} + +//=========================================================================== +static void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + CreateSinTable(); + if (!SDrawAutoInitialize(instance, + TEXT("ANIM3"), + TEXT("Animation Example 3"))) + FATALRESULT("SDrawAutoInitialize()"); + if (!CreateBackgroundBuffer()) + FATALRESULT("CreateBackgroundBuffer()"); + if (!CreateOffscreenBuffer()) + FATALRESULT("CreateOffsreenBuffer()"); + if (!LoadFont()) + FATALRESULT("LoadFont()"); + if (!LoadOverlay()) + FATALRESULT("LoadOverlay()"); + if (!LoadSprites()) + FATALRESULT("LoadSprites()"); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.CS b/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.EXE b/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.EXE new file mode 100644 index 0000000..c3a2293 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/ANIM3/ANIM3.EXE differ diff --git a/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.CPP b/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.CPP new file mode 100644 index 0000000..6ff9220 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.CPP @@ -0,0 +1,293 @@ +/**************************************************************************** +* +* ANIM4.CPP +* +* This sample application introduces the use of dirty rectangles. +* +* The application keeps an array of dirty cells, each one representing a +* 16x16 pixel area of the screen. Each cell contains one bit telling +* whether the cell has been updated this frame, and another bit telling +* whether it was updated last frame. For each frame we need to blit to +* the screen cells that have either bit set, so that sprites will be erased +* from their old positions and drawn to their new positions. +* +* The screen drawing function starts by clearing the update bits in each +* cell. Next, it erases the sprites from their old positions on the +* offscreen buffer, using an erase mask which will be described later. +* Next, it draws the sprites to their new positions on the offscreen buffer, +* and marks each cell that's touched by a sprite as dirty. Finally, it +* creates an update mask which is the intersection of the screen mask +* (that portion of the screen which is not covered by the status bar) and +* the array of dirty cells. It uses this update mask to blit the offscreen +* buffer onto the screen. Then it saves the update mask to use as the +* erase mask for the next frame. +* +* In addition to the use of a dirty rectangle system, the fact that we have +* a screen update mask which we are able to use as an erase mask for the +* next frame substantially decreases the amount of time required to erase +* the offscreen buffer. There is never a case when a portion of the +* offscreen buffer is erased more than once, as in Anim3. Also, the +* application never wastes time erasing the portion of the offscreen buffer +* which is covered up by the status bar. +* +***/ + +#include +#include +#include + +#define SPRITES 4 + +#define SIN(a) sintable[((a) & 255)] +#define COS(a) sintable[(((a)+64) & 255)] + +static LPBYTE backgroundbuffer = NULL; +static HSTRANS baseupdatemask = 0; +static HSTRANS currupdatemask = 0; +static LPBYTE dirtycells = NULL; +static HSGDIFONT font = 0; +static LPBYTE offscreenbuffer = NULL; +static HSTRANS overlay = 0; +static int sintable[256]; +static HSTRANS sprite[SPRITES] = {0,0,0,0}; + +//=========================================================================== +static BOOL CreateBackgroundBuffer () { + backgroundbuffer = (LPBYTE)ALLOC(640*480); + if (!backgroundbuffer) + return 0; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\bkg.pcx",&pe[0],backgroundbuffer,640*480)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +static BOOL CreateDirtyCellArray () { + dirtycells = (LPBYTE)ALLOC(40*30); + if (!dirtycells) + return 0; + ZeroMemory(dirtycells,40*30); + STransSetDirtyArrayInfo(640,480,16,16); + return 1; +} + +//=========================================================================== +static BOOL CreateOffscreenBuffer () { + offscreenbuffer = (LPBYTE)ALLOC(640*480); + if (!offscreenbuffer) + return 0; + CopyMemory(offscreenbuffer,backgroundbuffer,640*480); + return 1; +} + +//=========================================================================== +static void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + sintable[loop] = (int)(sin(angle)*128); + } +} + +//=========================================================================== +static void DisplayFramesPerSecond (LPBYTE buffer, int pitch) { + static DWORD frames = 0; + static DWORD lastfps = 0; + static DWORD lasttime = GetTickCount(); + + // UPDATE THE NUMBER OF FRAMES THIS SECOND + if (GetTickCount()-lasttime >= 1000) { + lastfps = frames; + frames = 0; + lasttime += 1000; + } + ++frames; + + // DISPLAY THE LAST NUMBER OF FRAMES PER SECOND + char outstr[16]; + wsprintf(outstr,"%3u FPS",lastfps); + RECT rect = {0,20,60,32}; + SGdiSetPitch(pitch); + SGdiExtTextOut(buffer, + 0, + 20, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + +} + +//=========================================================================== +static BOOL CALLBACK IdleProc (DWORD) { + static BYTE dirtyvalue = 1; + + // [1] BLT THE BACKGROUND BUFFER OVER THE DIRTY PORTIONS OF THE OFFSCREEN + // BUFFER + STransBltUsingMask(offscreenbuffer,backgroundbuffer,640,640,currupdatemask); + + // [2] CLEAR THE ARRAY OF DIRTY CELLS + dirtyvalue = 3-dirtyvalue; + { + for (int loop = 0; loop < 40*30; ++loop) + *(dirtycells+loop) &= ~dirtyvalue; + } + + // [3] DRAW THE SPRITES ONTO THE OFFSCREEN BUFFER, UPDATING THE ARRAY OF + // DIRTY CELLS + { + static BYTE distance = 0; + static BYTE rotation = 0; + for (int loop = 0; loop < SPRITES; ++loop) { + int x = 170+(SIN(rotation+64*loop)*SIN(distance/2)/100); + int y = 165+(COS(rotation+64*loop)*SIN(distance/2)/100); + STransBlt(offscreenbuffer, + x, + y, + 640, + sprite[loop]); + STransUpdateDirtyArray(dirtycells, + dirtyvalue, + x, + y, + sprite[loop], + 0); + } + ++distance; + rotation += 3; + } + + // [4] DELETE THE OLD UPDATE MASK, AND CREATE A NEW ONE WHICH IS THE + // INTERSECTION OF THE ARRAY OF THE CURRENTLY DIRTY CELLS AND THE + // AREA NOT COVERED BY THE OVERLAY + STransDelete(currupdatemask); + STransIntersectDirtyArray(baseupdatemask,dirtycells,3,&currupdatemask); + + // [5] BLT THE OFFSCREEN BUFFER ONTO THE SCREEN USING THE NEW MASK + { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + STransBltUsingMask(videobuffer, + offscreenbuffer, + videopitch, + 640, + currupdatemask); + DisplayFramesPerSecond(videobuffer,videopitch); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + } + + return TRUE; +} + +//=========================================================================== +static BOOL LoadFont () { + { + HFONT winfont = CreateFont(-12,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +static BOOL LoadOverlay () { + LPBYTE temp = (LPBYTE)ALLOC(640*480); + if (!SBmpLoadImage("..\\demodata\\overlay.pcx",NULL,temp,640*480)) + return 0; + if (!STransCreate(temp,640,480,8,NULL,PALETTEINDEX(111),&overlay)) + return 0; + if (!STransInvertMask(overlay,&baseupdatemask)) + return 0; + if (!STransDuplicate(baseupdatemask,&currupdatemask)) + return 0; + FREE(temp); + return 1; +} + +//=========================================================================== +static BOOL LoadSprites () { + LPBYTE temp = (LPBYTE)ALLOC(300*500); + if (!SBmpLoadImage("..\\demodata\\sprites.pcx",NULL,temp,300*500)) + return 0; + for (int loop = 0; loop < SPRITES; ++loop) { + RECT rect = {0,loop*125,299,loop*125+124}; + if (!STransCreate(temp,300,500,8,&rect,PALETTEINDEX(*temp),&sprite[loop])) + return 0; + } + FREE(temp); + return 1; +} + +//=========================================================================== +static void CALLBACK OnClose (LPPARAMS) { + FREE(backgroundbuffer); + FREE(dirtycells); + FREE(offscreenbuffer); + SGdiDeleteObject(font); + STransDelete(overlay); + STransDelete(baseupdatemask); + STransDelete(currupdatemask); + for (int loop = 0; loop < SPRITES; ++loop) + STransDelete(sprite[loop]); +} + +//=========================================================================== +static void CALLBACK OnPaint (LPPARAMS params) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + STransBltUsingMask(videobuffer, + offscreenbuffer, + videopitch, + 640, + baseupdatemask); + STransBlt(videobuffer, + 0, + 0, + videopitch, + overlay); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + ValidateRect(params->window,NULL); + params->useresult = TRUE; + params->result = 0; +} + +//=========================================================================== +static void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + CreateSinTable(); + if (!SDrawAutoInitialize(instance, + TEXT("ANIM4"), + TEXT("Animation Example 4"))) + FATALRESULT("SDrawAutoInitialize()"); + if (!CreateBackgroundBuffer()) + FATALRESULT("CreateBackgroundBuffer()"); + if (!CreateDirtyCellArray()) + FATALRESULT("CreateDirtyCellArray()"); + if (!CreateOffscreenBuffer()) + FATALRESULT("CreateOffsreenBuffer()"); + if (!LoadFont()) + FATALRESULT("LoadFont()"); + if (!LoadOverlay()) + FATALRESULT("LoadOverlay()"); + if (!LoadSprites()) + FATALRESULT("LoadSprites()"); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.CS b/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.EXE b/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.EXE new file mode 100644 index 0000000..0f55989 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/ANIM4/ANIM4.EXE differ diff --git a/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.CPP b/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.CPP new file mode 100644 index 0000000..25b0df9 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.CPP @@ -0,0 +1,270 @@ +/**************************************************************************** +* +* ANIM5.CPP +* +* Under construction... +* +***/ + +#include "pch.h" +#pragma hdrstop + +#include // note: take this out!! + +//#define COMBINEDOVERLAY + +#define ANIMSPRITES 4 +#define SPRITE_FPS (ANIMSPRITES+0) +#define SPRITE_BKG (ANIMSPRITES+1) +#define SPRITE_OVL1 (ANIMSPRITES+2) +#ifdef COMBINEDOVERLAY +#define SPRITES (ANIMSPRITES+3) +#else +#define SPRITE_OVL2 (ANIMSPRITES+3) +#define SPRITES (ANIMSPRITES+4) +#endif + +#define FPSWIDTH 60 +#define FPSHEIGHT 16 + +#define TRANSCOLOR PALETTEINDEX(111) + +#define SIN(a) s_sintable[((a) & 255)] +#define COS(a) s_sintable[(((a)+64) & 255)] + +static HSGDIFONT s_font; +static HSIMAGE s_fpsimage; +static int s_sintable[256]; +static HSSPRITE s_sprite[SPRITES]; +static HSTARGET s_target; + +static void UpdateFramesPerSecond (); + +//=========================================================================== +static void CreateFont () { + HFONT winfont = CreateFont(-12,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + SGdiImportFont(winfont,&s_font); + DeleteObject(winfont); + SGdiSelectObject(s_font); +} + +//=========================================================================== +static BOOL CreatePalette () { + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\bkg.pcx",&pe[0],NULL,0)) + return FALSE; + SDrawUpdatePalette(0,256,&pe[0]); + return TRUE; +} + +//=========================================================================== +static void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + s_sintable[loop] = (int)(sin(angle)*128); + } +} + +//=========================================================================== +static BOOL CreateSprites () { + DWORD loop; + HSIMAGE imagearray[SPRITES]; + + // LOAD THE ANIMATED SPRITE IMAGES + { + RECT rectarray[ANIMSPRITES]; + for (loop = 0; loop < ANIMSPRITES; ++loop) { + rectarray[loop].left = 0; + rectarray[loop].top = 125*loop; + rectarray[loop].right = 300; + rectarray[loop].bottom = 125*loop+125; + } + if (!S2dImageCreateFromFile("..\\demodata\\sprites.pcx", + TRANSCOLOR, + ANIMSPRITES, + rectarray, + imagearray)) + return FALSE; + } + + // CREATE THE FPS SPRITE IMAGE + S2dImageCreate(FPSWIDTH, + FPSHEIGHT, + 8, + TRANSCOLOR, + &imagearray[SPRITE_FPS]); + + // LOAD THE BACKGROUND SPRITE IMAGE + if (!S2dImageCreateFromFile("..\\demodata\\bkg.pcx", + TRANSCOLOR, + 1, + NULL, + &imagearray[SPRITE_BKG])) + return FALSE; + + // LOAD THE OVERLAY SPRITE IMAGES +#ifdef COMBINEDOVERLAY + if (!S2dImageCreateFromFile("..\\demodata\\overlay.pcx", + TRANSCOLOR, + 1, + NULL, + &imagearray[SPRITE_OVL1])) + return FALSE; +#else + { + RECT rectarray[2] = {{0,0,167,18},{0,295,640,480}}; + if (!S2dImageCreateFromFile("..\\demodata\\overlay.pcx", + TRANSCOLOR, + 2, + rectarray, + &imagearray[SPRITE_OVL1])) + return FALSE; + } +#endif + + // ATTACH THE IMAGES TO SPRITES, AND THEN CLOSE OR SAVE THE IMAGE HANDLES + for (loop = 0; loop < SPRITES; ++loop) { + S2dSpriteCreate(&s_sprite[loop]); + S2dSpriteSetImage(s_sprite[loop],imagearray[loop]); + if (loop == SPRITE_FPS) { + S2dSpriteSetPos(s_sprite[loop],0,20); + s_fpsimage = imagearray[loop]; + } + else { + S2dSpriteSetPos(s_sprite[loop],0,0); +#ifndef COMBINEDOVERLAY +if (loop == SPRITE_OVL2) S2dSpriteSetPos(s_sprite[loop],0,295); +#endif + S2dImageDelete(imagearray[loop]); + } + } + + // CREATE A TARGET, AND ATTACH THE SPRITES TO THE TARGET + S2dTargetCreate(&s_target); + for (loop = 0; loop < SPRITES; ++loop) + S2dSpriteSetTarget(s_sprite[loop], + s_target, + (loop >= SPRITE_OVL1) ? -1 : loop); + + return TRUE; +} + +//=========================================================================== +static BOOL CALLBACK IdleProc (DWORD) { + static BYTE rotation = 0; + static BYTE distance = 0; + ++distance; + rotation += 3; + for (DWORD loop = 0; loop < ANIMSPRITES; ++loop) + S2dSpriteSetPos(s_sprite[loop], + 170+(SIN(rotation+64*loop)*SIN(distance/2)/100), + 165+(COS(rotation+64*loop)*SIN(distance/2)/100)); + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { +//SGdiSetPitch(videopitch); +//SGdiRectangle(videobuffer,0,0,640,480,PALETTEINDEX(255)); + S2dTestDrawTarget(s_target,videobuffer,videopitch); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + UpdateFramesPerSecond(); +//return FALSE; + return TRUE; +} + +//=========================================================================== +static void CALLBACK OnClose (LPPARAMS) { + for (DWORD loop = 0; loop < SPRITES; ++loop) { + S2dSpriteDelete(s_sprite[loop]); + s_sprite[loop] = (HSSPRITE)0; + } + S2dImageDelete(s_fpsimage); + s_fpsimage = (HSIMAGE)0; + S2dTargetDelete(s_target); + s_target = (HSTARGET)0; + SGdiDeleteObject(s_font); + s_font = (HSGDIFONT)0; +} + +//=========================================================================== +static void CALLBACK OnPaint (LPPARAMS params) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + S2dTestDrawTarget(s_target,videobuffer,videopitch); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + ValidateRect(params->window,NULL); + params->useresult = TRUE; + params->result = 0; +} + +//=========================================================================== +static void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +static void UpdateFramesPerSecond () { + static DWORD frames = 0; + static DWORD starttime = GetTickCount(); + static DWORD lasttime = starttime; + + // INCREMENT THE NUMBER OF FRAMES + ++frames; + + // RETURN IF A SECOND HAS NOT YET ELAPSED + if (GetTickCount()-lasttime < 1000) + return; + lasttime += 1000; + + // DRAW THE AVERAGE NUMBER OF FRAMES PER SECOND + LPBYTE ptr; + if (S2dImageLockBuffer(s_fpsimage,FALSE,&ptr)) { + char outstr[16]; + wsprintf(outstr,"%3u FPS",frames/((lasttime-starttime)/1000)); + RECT rect = {0,0,FPSWIDTH,FPSHEIGHT}; + SGdiSetTargetDimensions(FPSWIDTH, + FPSHEIGHT, + 8, + FPSWIDTH); + SGdiExtTextOut(ptr, + 0, + 0, + &rect, + TRANSCOLOR, + ETO_TEXT_WHITE, + ETO_BKG_COLOR, + outstr); + S2dImageUnlockBuffer(s_fpsimage,ptr); + } + + // note: shouldn't be needed but it is for now... + S2dSpriteSetPos(s_sprite[SPRITE_FPS],0,20); + +static FILE *f = fopen("trace.txt","wt"); +fprintf(f,"%u\n",frames/((lasttime-starttime)/1000)); +fflush(f); + +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + CreateFont(); + CreateSinTable(); + if (!SDrawAutoInitialize(instance, + "ANIM5", + "Animation Example 5")) + FATALRESULT("SDrawAutoInitialize()"); + if (!CreatePalette()) + FATALRESULT("CreatePalette()"); + if (!CreateSprites()) + FATALRESULT("CreateSprites()"); + + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.CS b/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.EXE b/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.EXE new file mode 100644 index 0000000..74beca9 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/ANIM5/ANIM5.EXE differ diff --git a/src/Storm/SAMPLES/ANIM/ANIM5/FPS.TXT b/src/Storm/SAMPLES/ANIM/ANIM5/FPS.TXT new file mode 100644 index 0000000..da1cc45 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM5/FPS.TXT @@ -0,0 +1 @@ +276 - 283 diff --git a/src/Storm/SAMPLES/ANIM/ANIM5/PCH.H b/src/Storm/SAMPLES/ANIM/ANIM5/PCH.H new file mode 100644 index 0000000..8938a3f --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM5/PCH.H @@ -0,0 +1,6 @@ +#include +#include +#include +#include +#include "s2d.h" + diff --git a/src/Storm/SAMPLES/ANIM/ANIM5/S2D.CPP b/src/Storm/SAMPLES/ANIM/ANIM5/S2D.CPP new file mode 100644 index 0000000..b11371f --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM5/S2D.CPP @@ -0,0 +1,828 @@ +/**************************************************************************** +* +* S2D.CPP +* Storm 2d graphics engine +* +* By Michael O'Brien (8/8/97) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define MAXSPANLENGTH 0xFC + +#define SF_DISPLAYED 0x00000001 +#define SF_ERASEMARKER 0x00000002 + +DECLARE_STRICT_HANDLE(HLOCKEDIMAGE); +DECLARE_STRICT_HANDLE(HLOCKEDSPRITE); +DECLARE_STRICT_HANDLE(HLOCKEDTARGET); + +struct IMAGE; +struct SPRITE; +struct TARGET; + +static void SpriteRemoveImageReference (SPRITE *spriteptr); + +typedef BYTE SPAN; + +typedef struct _SPANPAIR { + SPAN copyspan; + SPAN skipspan; +} SPANPAIR, *SPANPAIRPTR; + +typedef struct _COMPOSITEDATA { + SPRITE *spriteptr; + BOOL stable; + BOOL erasing; + SPAN *spanptr; + int currspan; + LPBYTE dataptr; +} COMPOSITEDATA, *COMPOSITEDATAPTR; + +EXPORTOBJECTDECL(SPRITE) { + POINT pos; + RECT boundingrect; + DWORD flags; + int zorder; + IMAGE *image; + TARGET *target; + LINKEX(SPRITE) linkimage; + LINKEX(SPRITE) linkzlist; + + inline ~SPRITE () { + if (image) + SpriteRemoveImageReference(this); + } + +} *SPRITEPTR; + +typedef LISTEX(SPRITE,linkimage) SPRITEIMAGELIST; +typedef LISTEX(SPRITE,linkzlist) SPRITEZLIST; + +EXPORTOBJECTDECL(IMAGE) { + SIZE size; + RECT boundingrect; + BOOL transparent; + BYTE transidx; + BYTE reserved[3]; + LPBYTE imagedata; + DWORD refcount; + ARRAY(SPANPAIR) spandata; + ARRAY(DWORD) spanindex; + SPRITEIMAGELIST spritelist; + + inline ~IMAGE () { + FREEIFUSED(imagedata); + } + +} *IMAGEPTR; + +EXPORTOBJECTDECL(TARGET) { + ARRAY(COMPOSITEDATA) compositedata; + CSRgn dirtyrgn; + ARRAY(RECT) dirtyrects; + ARRAY(LPVOID) dirtyrectparams; +// SPRITEZLIST sparelist; + SPRITEZLIST spritezlist; +} *TARGETPTR; + +typedef EXPORTTABLE(IMAGE ,HSIMAGE ,HLOCKEDIMAGE ,SYNC_NONE) IMAGETABLE; +typedef EXPORTTABLE(SPRITE,HSSPRITE,HLOCKEDSPRITE,SYNC_NONE) SPRITETABLE; +typedef EXPORTTABLE(TARGET,HSTARGET,HLOCKEDTARGET,SYNC_NONE) TARGETTABLE; + +static CCritSect s_apicritsect; +static IMAGETABLE s_imagetable; +static SPRITETABLE s_spritetable; +static TARGETTABLE s_targettable; + +//=========================================================================== +static inline BOOL CheckForSupportedColorFormat (int bitdepth, + COLORREF colorkey) { + return ((bitdepth == 8) && + (colorkey & 0x01000000)); +} + +//=========================================================================== +static inline void ImageAddSpanPair (IMAGEPTR imageptr, + SPANPAIRPTR pair, + int nextx, + int y) { + + // ADD THIS SPAN PAIR TO THE ARRAY + imageptr->spandata.AddElement(pair); + + // IF THIS SPAN PAIR CONTAINS A COPY SPAN, COMPUTE THE STARTING AND + // ENDING X COORDINATES IN THE COPY SPAN, AND ADD THAT RANGE TO THE + // BOUNDING RECTANGLE + if (pair->copyspan) { + int x2 = nextx-pair->skipspan; + int x1 = x2-pair->copyspan; + imageptr->boundingrect.left = min(x1 ,imageptr->boundingrect.left); + imageptr->boundingrect.top = min(y ,imageptr->boundingrect.top); + imageptr->boundingrect.right = max(x2 ,imageptr->boundingrect.right); + imageptr->boundingrect.bottom = max(y+1,imageptr->boundingrect.bottom); + } + + // BLANK THE SPAN PAIR + pair->copyspan = pair->skipspan = 0; +} + +//=========================================================================== +static void ImageCreateSpanData (IMAGEPTR imageptr) { + + // RESET THE COMPUTED IMAGE DATA + imageptr->boundingrect.left = imageptr->size.cx; + imageptr->boundingrect.top = imageptr->size.cy; + imageptr->boundingrect.right = 0; + imageptr->boundingrect.bottom = 0; + imageptr->transparent = FALSE; + imageptr->spandata.SetNumElements(0); + imageptr->spandata.ReserveSpace(imageptr->size.cx*4); + imageptr->spanindex.SetNumElements(imageptr->size.cy); + + // BUILD THE SPAN ARRAY + LPBYTE currdata = imageptr->imagedata; + for (int y = 0; y < imageptr->size.cy; ++y) { + + // SAVE THE SPAN INDEX THE CORRESPONDS WITH THE BEGINNING OF THIS + // SCAN LINE + imageptr->spanindex[y] = imageptr->spandata.NumElements(); + + // INITIALIZE THE OUTPUT VARIABLES + SPANPAIR currpair = {0,0}; + SPAN *currspan = &currpair.copyspan; + + // IF THIS SCAN LINE HAS ZERO WIDTH, THEN JUST OUTPUT THE LINE TERMINATOR + if (imageptr->size.cx <= 0) { + ImageAddSpanPair(imageptr,&currpair,0,y); + continue; + } + + // OTHERWISE, BUILD AND OUTPUT SPANS + int x; + for (x = 0; x < imageptr->size.cx; ++x) { + if ((*(currdata++) != imageptr->transidx) != (currspan == &currpair.copyspan)) + if (currspan == &currpair.copyspan) { + imageptr->transparent = TRUE; + currspan = &currpair.skipspan; + } + else { + ImageAddSpanPair(imageptr,&currpair,x,y); + currspan = &currpair.copyspan; + } + if (*currspan == MAXSPANLENGTH) + ImageAddSpanPair(imageptr,&currpair,x,y); + ++*currspan; + } + ImageAddSpanPair(imageptr,&currpair,x,y); + + // OUTPUT THE LINE TERMINATOR + ImageAddSpanPair(imageptr,&currpair,x,y); + + } + +} + +//=========================================================================== +static void SpriteLinkToZList (TARGETPTR targetptr, + SPRITEPTR spriteptr) { + spriteptr->linkzlist.Unlink(); + SPRITEPTR before = NULL; + ITERATELIST(SPRITE,targetptr->spritezlist,curr) + if (curr->zorder > spriteptr->zorder) { + before = curr; + break; + } + targetptr->spritezlist.LinkNode(spriteptr,LIST_LINK_BEFORE,before); +} + +//=========================================================================== +static void SpriteRemoveImageReference (SPRITE *spriteptr) { + if (!--spriteptr->image->refcount) + delete spriteptr->image; + spriteptr->image = NULL; + spriteptr->linkimage.Unlink(); +} + +//=========================================================================== +static void TargetBuildDirtyRects (TARGETPTR targetptr) { + targetptr->dirtyrgn.Clear(); + ITERATELIST(SPRITE,targetptr->spritezlist,spriteptr) + if ((spriteptr->flags & SF_ERASEMARKER) || + !(spriteptr->flags & SF_DISPLAYED)) + targetptr->dirtyrgn.AddRect(&spriteptr->boundingrect,spriteptr); + else + targetptr->dirtyrgn.AddParam(&spriteptr->boundingrect,spriteptr); + DWORD numrects; + targetptr->dirtyrgn.GetRects(&numrects,NULL); + targetptr->dirtyrects.SetNumElements(numrects); + targetptr->dirtyrgn.GetRects(&numrects,targetptr->dirtyrects.Ptr()); +} + +//=========================================================================== +static void TargetCompositeRect (LPBYTE videoptr, + int pitch, + TARGETPTR targetptr, + LPCRECT rect, + DWORD sprites, + SPRITEPTR *spritearray) { + DWORD loop; + + // BUILD A LIST OF SPRITES TO COMPOSITE + targetptr->compositedata.SetNumElements(sprites); + COMPOSITEDATAPTR compositedata = targetptr->compositedata.Ptr(); + DWORD compositenum = 0; + { + BOOL erasing = FALSE; + DWORD lastdraw = UINT_MAX; + for (loop = 0; loop < sprites; ++loop) { + SPRITEPTR spriteptr = spritearray[loop]; + if (spriteptr->flags & SF_ERASEMARKER) + erasing = TRUE; + if (!(spriteptr->flags & SF_DISPLAYED)) + lastdraw = compositenum; + compositedata[compositenum].spriteptr = spriteptr; + compositedata[compositenum].stable + = ((spriteptr->flags & SF_DISPLAYED) != 0) + && !(spriteptr->flags & SF_ERASEMARKER); + compositedata[compositenum].erasing + = ((spriteptr->flags & SF_ERASEMARKER) != 0); + compositedata[compositenum].dataptr + = spriteptr->image->imagedata + +((rect->top-spriteptr->pos.y-1)*spriteptr->image->size.cx) + +(rect->left-spriteptr->pos.x) + +(rect->right-rect->left); + ++compositenum; + } + if (!erasing) + compositenum = lastdraw+1; + } + + LPBYTE destptr = videoptr+rect->top*pitch+rect->left; + for (int y = rect->top; y < rect->bottom; ++y) { + + // SETUP COMPOSITING INFO FOR THIS SCAN LINE FOR EACH SPRITE + for (loop = 0; loop < compositenum; ++loop) { + SPRITEPTR spriteptr = compositedata[loop].spriteptr; + compositedata[loop].dataptr += spriteptr->image->size.cx-(rect->right-rect->left); + if ((y >= spriteptr->boundingrect.top) && + (y < spriteptr->boundingrect.bottom)) { + compositedata[loop].spanptr = (SPAN *)(spriteptr->image->spandata.Ptr() + +spriteptr->image->spanindex[y-spriteptr->pos.y]); + compositedata[loop].currspan = spriteptr->pos.x-rect->left; + while (compositedata[loop].currspan <= 0) + if ((!((DWORD)compositedata[loop].spanptr & 1)) && + !*(LPWORD)compositedata[loop].spanptr) + compositedata[loop].currspan = INT_MAX; + else + compositedata[loop].currspan += *compositedata[loop].spanptr++; + } + else { + compositedata[loop].spanptr = NULL; + compositedata[loop].currspan = INT_MAX; + } + } + + int x = rect->left; + int xspan; + while ((xspan = rect->right-x) > 0) { + + BOOL belowerase = FALSE; + for (loop = 0; loop < compositenum; ++loop) { + xspan = min(xspan,compositedata[loop].currspan); + if ((DWORD)compositedata[loop].spanptr & 1) + if (compositedata[loop].erasing) + belowerase = TRUE; + else + break; + } + + if ((loop < compositenum) && + (belowerase || !compositedata[loop].stable)) { + LPBYTE sourceptr = compositedata[loop].dataptr; +#ifdef _X86_ + __asm { + + // SETUP REGISTERS + push esi + push edi + mov eax,[xspan] + xor ecx,ecx + mov esi,[sourceptr] + mov edi,[destptr] + + // PERFORM THE COPY + cmp al,3 + jbe ds_done4 + + // IF NECESSARY, MOVE A SINGLE BYTE TO WORD-ALIGN THE + // DESTINATION + test edi,1 + jz ds_aligned2 + mov cl,[esi] + inc esi + mov [edi],cl + inc edi + dec al + ds_aligned2: + + // IF NECESSARY, MOVE A SINGLE WORD TO DWORD-ALIGN THE + // DESTINATION + test edi,2 + jz ds_aligned4 + mov cx,[esi] + add esi,2 + mov [edi],cx + add edi,2 + sub al,2 + ds_aligned4: + + // MOVE AS MANY ALIGNED DWORDS AS POSSIBLE + // note: get rid of the rep movsd!! + mov ecx,eax + and ecx,0FCh + shr ecx,2 + rep movsd + ds_done4: + + // MOVE ONE MORE WORD IF NECESSARY + test al,2 + jz ds_done2 + mov cx,[esi] + add esi,2 + mov [edi],cx + add edi,2 + ds_done2: + + // MOVE ONE MORE BYTE IF NECESSARY + test al,1 + jz ds_done1 + mov cl,[esi] + inc esi + mov [edi],cl + inc edi + ds_done1: + + pop edi + pop esi + } +#else + CopyMemory(destptr, + sourceptr, + xspan); +#endif + } + + destptr += xspan; + x += xspan; + + for (loop = 0; loop < compositenum; ++loop) { + compositedata[loop].dataptr += xspan; + int advance = xspan; + while (advance >= compositedata[loop].currspan) { + advance -= compositedata[loop].currspan; + if ((!((DWORD)compositedata[loop].spanptr & 1)) && + !*(LPWORD)compositedata[loop].spanptr) + compositedata[loop].currspan = INT_MAX; + else + compositedata[loop].currspan = *compositedata[loop].spanptr++; + } + compositedata[loop].currspan -= advance; + } + + } + + destptr += pitch-(rect->right-rect->left); + } +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +void APIENTRY S2dImageCreate (int width, + int height, + int bitdepth, + COLORREF colorkey, + HSIMAGE *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATEENDVOID; + + if (!CheckForSupportedColorFormat(bitdepth,colorkey)) + return; + + s_apicritsect.Enter(); + + // CREATE A NEW IMAGE RECORD + HLOCKEDIMAGE lockedhandle; + IMAGEPTR imageptr = s_imagetable.NewLock(handle,&lockedhandle); + imageptr->size.cx = width; + imageptr->size.cy = height; + imageptr->boundingrect.left = UINT_MAX; + imageptr->boundingrect.top = UINT_MAX; + imageptr->boundingrect.right = UINT_MAX; + imageptr->boundingrect.bottom = UINT_MAX; + imageptr->transidx = (BYTE)(colorkey & 0xFF); + imageptr->refcount = 1; + s_imagetable.Unlock(lockedhandle); + + s_apicritsect.Leave(); +} + +//=========================================================================== +BOOL APIENTRY S2dImageCreateFromFile (LPCTSTR filename, + COLORREF colorkey, + DWORD numimages, + LPCRECT rectarray, + HSIMAGE *handlearray) { + if (numimages && handlearray) + ZeroMemory(handlearray,numimages*sizeof(HSIMAGE)); + + VALIDATEBEGIN; + VALIDATE(filename && *filename); + VALIDATE(numimages); + VALIDATE(handlearray); + VALIDATEEND; + + s_apicritsect.Enter(); + HSFILE file = (HSFILE)0; + LPBYTE filebuffer = NULL; + BOOL result = FALSE; + TRY { + + // LOAD THE FILE FROM DISK + if (!SFileOpenFile(filename,&file)) + LEAVE; + DWORD filesize = SFileGetFileSize(file,NULL); + filebuffer = (LPBYTE)ALLOC(filesize); + if (!SFileReadFile(file,filebuffer,filesize)) + LEAVE; + + // DETERMINE THE SOURCE IMAGE DIMENSIONS + int width, height, bitdepth; + if (!SBmpDecodeImage(SBMP_IMAGETYPE_AUTO, + filebuffer, + filesize, + NULL, + NULL, + 0, + &width, + &height, + &bitdepth)) + LEAVE; + + // VERIFY THAT THE FILE IS IN A SUPPORTED COLOR FORMAT + if (!CheckForSupportedColorFormat(bitdepth,colorkey)) + LEAVE; + + // DECODE THE FILE INTO A TEMPORARY BUFFER + int bytedepth = bitdepth/8; + DWORD sourcebytes = width*height*(DWORD)bytedepth; + LPBYTE buffer = (LPBYTE)ALLOC(sourcebytes); + SBmpDecodeImage(SBMP_IMAGETYPE_AUTO, + filebuffer, + filesize, + NULL, + buffer, + sourcebytes); + + // PROCESS EACH IMAGE + for (DWORD loop = 0; + loop < numimages; + ++loop) { + + // DETERMINE THE IMAGE DIMENSIONS + int destwidth = width; + int destheight = height; + if (rectarray) { + destwidth = min(destwidth ,rectarray[loop].right+1-rectarray[loop].left); + destheight = min(destheight,rectarray[loop].bottom+1-rectarray[loop].top); + } + + // CREATE THE IMAGE + S2dImageCreate(destwidth, + destheight, + bitdepth, + colorkey, + &handlearray[loop]); + + // LOCK THE IMAGE BUFFER + LPBYTE ptr; + S2dImageLockBuffer(handlearray[loop],TRUE,&ptr); + + // BLT THE SOURCE RECTANGLE INTO THE IMAGE BUFFER + SIZE adjdestsize = {destwidth*bytedepth, + destheight}; + SIZE adjsourcesize = {width*bytedepth, + height}; + RECT adjsourcerect = {0, + 0, + adjsourcesize.cx, + adjsourcesize.cy}; + if (rectarray) { + adjsourcerect.left = rectarray[loop].left*bytedepth; + adjsourcerect.top = rectarray[loop].top; + adjsourcerect.right = rectarray[loop].right*bytedepth; + adjsourcerect.bottom = rectarray[loop].bottom; + } + SBltROP3Clipped(ptr, + NULL, + &adjdestsize, + adjdestsize.cx, + buffer, + &adjsourcerect, + &adjsourcesize, + adjsourcesize.cx, + 0, + SRCCOPY); + + // UNLOCK THE IMAGE BUFFER + S2dImageUnlockBuffer(handlearray[loop],ptr); + + } + + // FREE THE TEMPORARY BUFFER + FREE(buffer); + + result = TRUE; + } + FINALLY { + FREEIFUSED(filebuffer); + if (file) + SFileCloseFile(file); + } + s_apicritsect.Leave(); + return result; +} + +//=========================================================================== +void APIENTRY S2dImageDelete (HSIMAGE handle) { + s_apicritsect.Enter(); + HLOCKEDIMAGE lockedhandle; + IMAGEPTR imageptr = s_imagetable.Lock(handle,&lockedhandle); + if (!--imageptr->refcount) + s_imagetable.DeleteUnlock(imageptr,lockedhandle); + else + s_imagetable.Unlock(lockedhandle); + s_apicritsect.Leave(); +} + +//=========================================================================== +BOOL APIENTRY S2dImageLockBuffer (HSIMAGE handle, + BOOL blank, + LPBYTE *ptr) { + VALIDATEBEGIN; + VALIDATEANDBLANK(ptr); + VALIDATEEND; + + s_apicritsect.Enter(); + for (ONCE) { + + // FIND THE IMAGE RECORD + HLOCKEDIMAGE lockedhandle; + IMAGEPTR imageptr = s_imagetable.Lock(handle,&lockedhandle); + if (!imageptr) + break; + + // ALLOCATE A BUFFER IF NECESSARY + DWORD bytes = imageptr->size.cx*imageptr->size.cy; + if (!imageptr->imagedata) + imageptr->imagedata = (LPBYTE)ALLOC(bytes); + + // BLANK THE BUFFER IF REQUESTED + if (blank) + FillMemory(imageptr->imagedata,bytes,imageptr->transidx); + + // RETURN THE BUFFER + *ptr = imageptr->imagedata; + + s_imagetable.Unlock(lockedhandle); + } + s_apicritsect.Leave(); + return (*ptr != NULL); +} + +//=========================================================================== +void APIENTRY S2dImageUnlockBuffer (HSIMAGE handle, + LPBYTE ptr) { + s_apicritsect.Enter(); + for (ONCE) { + + // FIND THE IMAGE RECORD + HLOCKEDIMAGE lockedhandle; + IMAGEPTR imageptr = s_imagetable.Lock(handle,&lockedhandle); + if (!imageptr) + break; + + // PRODUCE THE SPAN DATA + ImageCreateSpanData(imageptr); + + s_imagetable.Unlock(lockedhandle); + } + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteCreate (HSSPRITE *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + s_spritetable.New(handle); + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteDelete (HSSPRITE handle) { + s_apicritsect.Enter(); + s_spritetable.Delete(handle); + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteSetImage (HSSPRITE handle, + HSIMAGE imagehandle) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATE(imagehandle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + + // LOCK THE SPRITE AND IMAGE + HLOCKEDSPRITE lockedsprite; + HLOCKEDIMAGE lockedimage; + SPRITEPTR spriteptr = s_spritetable.Lock(handle,&lockedsprite); + IMAGEPTR imageptr = s_imagetable.Lock(imagehandle,&lockedimage); + if (spriteptr->image != imageptr) { + + // REMOVE THE REFERENCE TO THE SPRITE'S OLD IMAGE + if (spriteptr->image) + SpriteRemoveImageReference(spriteptr); + + // ASSOCIATE THE IMAGE WITH THE SPRITE + if (imageptr) { + ++imageptr->refcount; + spriteptr->image = imageptr; + imageptr->spritelist.LinkNode(spriteptr); + } + + } + + // UNLOCK THE SPRITE AND IMAGE + s_imagetable.Unlock(lockedimage); + s_spritetable.Unlock(lockedsprite); + + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteSetPos (HSSPRITE handle, + int x, + int y) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + for (ONCE) { + + // LOCK THE SPRITE + HLOCKEDSPRITE lockedhandle; + SPRITEPTR spriteptr = s_spritetable.Lock(handle,&lockedhandle); + if (!spriteptr) + break; + + // PLACE AN ERASE MARKER AT THE SPRITE'S OLD POSITION + if (spriteptr->flags & SF_DISPLAYED) { + SPRITEPTR newptr = spriteptr->target->spritezlist.NewNode(LIST_UNLINKED); + newptr->pos = spriteptr->pos; + newptr->boundingrect = spriteptr->boundingrect; + newptr->flags = SF_ERASEMARKER; + newptr->zorder = spriteptr->zorder; + newptr->target = spriteptr->target; + newptr->image = spriteptr->image; + ++spriteptr->image->refcount; + spriteptr->target->spritezlist.LinkNode(newptr,LIST_LINK_AFTER,spriteptr); + } + + // SET THE SPRITE'S POSITION AND BOUNDING RECTANGLE + spriteptr->pos.x = x; + spriteptr->pos.y = y; + spriteptr->boundingrect.left = x+spriteptr->image->boundingrect.left; + spriteptr->boundingrect.top = y+spriteptr->image->boundingrect.top; + spriteptr->boundingrect.right = x+spriteptr->image->boundingrect.right; + spriteptr->boundingrect.bottom = y+spriteptr->image->boundingrect.bottom; + spriteptr->flags &= ~SF_DISPLAYED; + + // UNLOCK THE SPRITE + s_spritetable.Unlock(lockedhandle); + + } + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteSetTarget (HSSPRITE handle, + HSTARGET targethandle, + int zorder) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATE(targethandle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + + // LOCK THE SPRITE AND TARGET + HLOCKEDSPRITE lockedsprite; + HLOCKEDTARGET lockedtarget; + SPRITEPTR spriteptr = s_spritetable.Lock(handle,&lockedsprite); + TARGETPTR targetptr = s_targettable.Lock(targethandle,&lockedtarget); + + // SET THE SPRITE'S Z ORDER AND LINK IT INTO THE TARGET'S Z LIST + spriteptr->zorder = zorder; + spriteptr->target = targetptr; + SpriteLinkToZList(targetptr,spriteptr); + + // UNLOCK THE SPRITE AND TARGET + s_targettable.Unlock(lockedtarget); + s_spritetable.Unlock(lockedsprite); + + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dTargetCreate (HSTARGET *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + s_targettable.New(handle); + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dTargetDelete (HSTARGET handle) { + s_apicritsect.Enter(); + s_targettable.Delete(handle); + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dTestDrawTarget (HSTARGET handle, + LPBYTE ptr, + int pitch) { + s_apicritsect.Enter(); + for (ONCE) { + + HLOCKEDTARGET lockedhandle; + TARGETPTR targetptr = s_targettable.Lock(handle,&lockedhandle); + if (!targetptr) + break; + + TargetBuildDirtyRects(targetptr); + for (DWORD rectindex = 0; + rectindex < targetptr->dirtyrects.NumElements(); + ++rectindex) { + DWORD totalparams; + targetptr->dirtyrgn.GetRectParams(&targetptr->dirtyrects[rectindex], + &totalparams, + NULL); + targetptr->dirtyrectparams.SetNumElements(totalparams); + targetptr->dirtyrgn.GetRectParams(&targetptr->dirtyrects[rectindex], + &totalparams, + targetptr->dirtyrectparams.Ptr()); +/* + SGdiRectangle(ptr, + targetptr->dirtyrects[rectindex].left, + targetptr->dirtyrects[rectindex].top, + targetptr->dirtyrects[rectindex].right, + targetptr->dirtyrects[rectindex].bottom, + PALETTEINDEX(111+totalparams)); +*/ + TargetCompositeRect(ptr, + pitch, + targetptr, + &targetptr->dirtyrects[rectindex], + totalparams, + (SPRITEPTR *)(targetptr->dirtyrectparams.Ptr())); + } + + ITERATELIST(SPRITE,targetptr->spritezlist,spriteptr) + if (spriteptr->flags & SF_ERASEMARKER) + ITERATE_DELETE + else + spriteptr->flags |= SF_DISPLAYED; + + s_targettable.Unlock(lockedhandle); + } + s_apicritsect.Leave(); +} diff --git a/src/Storm/SAMPLES/ANIM/ANIM5/S2D.H b/src/Storm/SAMPLES/ANIM/ANIM5/S2D.H new file mode 100644 index 0000000..ded5029 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM5/S2D.H @@ -0,0 +1,42 @@ +/**************************************************************************** +* +* 2D graphics engine functions +* +***/ + +DECLARE_STRICT_HANDLE(HSIMAGE); +DECLARE_STRICT_HANDLE(HSSPRITE); +DECLARE_STRICT_HANDLE(HSTARGET); + +void APIENTRY S2dImageCreate (int width, + int height, + int bitdepth, + COLORREF colorkey, + HSIMAGE *handle); +BOOL APIENTRY S2dImageCreateFromFile (LPCTSTR filename, + COLORREF colorkey, + DWORD numimages, + LPCRECT rectarray, + HSIMAGE *handlearray); +void APIENTRY S2dImageDelete (HSIMAGE handle); +BOOL APIENTRY S2dImageLockBuffer (HSIMAGE handle, + BOOL blank, + LPBYTE *ptr); +void APIENTRY S2dImageUnlockBuffer (HSIMAGE handle, + LPBYTE ptr); +void APIENTRY S2dSpriteCreate (HSSPRITE *handle); +void APIENTRY S2dSpriteDelete (HSSPRITE handle); +void APIENTRY S2dSpriteSetImage (HSSPRITE handle, + HSIMAGE imagehandle); +void APIENTRY S2dSpriteSetPos (HSSPRITE handle, + int x, + int y); +void APIENTRY S2dSpriteSetTarget (HSSPRITE handle, + HSTARGET targethandle, + int zorder); +void APIENTRY S2dTargetCreate (HSTARGET *handle); +void APIENTRY S2dTargetDelete (HSTARGET handle); + +void APIENTRY S2dTestDrawTarget (HSTARGET handle, + LPBYTE ptr, + int pitch); diff --git a/src/Storm/SAMPLES/ANIM/ANIM5/TRACE.TXT b/src/Storm/SAMPLES/ANIM/ANIM5/TRACE.TXT new file mode 100644 index 0000000..6eee0d1 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/ANIM5/TRACE.TXT @@ -0,0 +1,2 @@ +279 +275 diff --git a/src/Storm/SAMPLES/ANIM/DEMODATA/BKG.PCX b/src/Storm/SAMPLES/ANIM/DEMODATA/BKG.PCX new file mode 100644 index 0000000..d24cdf1 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/DEMODATA/BKG.PCX differ diff --git a/src/Storm/SAMPLES/ANIM/DEMODATA/FLAG.PCX b/src/Storm/SAMPLES/ANIM/DEMODATA/FLAG.PCX new file mode 100644 index 0000000..c83f1b4 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/DEMODATA/FLAG.PCX differ diff --git a/src/Storm/SAMPLES/ANIM/DEMODATA/OVERLAY.OLD b/src/Storm/SAMPLES/ANIM/DEMODATA/OVERLAY.OLD new file mode 100644 index 0000000..41818e2 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/DEMODATA/OVERLAY.OLD differ diff --git a/src/Storm/SAMPLES/ANIM/DEMODATA/OVERLAY.PCX b/src/Storm/SAMPLES/ANIM/DEMODATA/OVERLAY.PCX new file mode 100644 index 0000000..e9a3e67 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/DEMODATA/OVERLAY.PCX differ diff --git a/src/Storm/SAMPLES/ANIM/DEMODATA/SHIPS.PCX b/src/Storm/SAMPLES/ANIM/DEMODATA/SHIPS.PCX new file mode 100644 index 0000000..3fc7727 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/DEMODATA/SHIPS.PCX differ diff --git a/src/Storm/SAMPLES/ANIM/DEMODATA/SPRITES.PCX b/src/Storm/SAMPLES/ANIM/DEMODATA/SPRITES.PCX new file mode 100644 index 0000000..f9dc3e2 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/DEMODATA/SPRITES.PCX differ diff --git a/src/Storm/SAMPLES/ANIM/OLD/ANIM5.CPP b/src/Storm/SAMPLES/ANIM/OLD/ANIM5.CPP new file mode 100644 index 0000000..25b0df9 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/OLD/ANIM5.CPP @@ -0,0 +1,270 @@ +/**************************************************************************** +* +* ANIM5.CPP +* +* Under construction... +* +***/ + +#include "pch.h" +#pragma hdrstop + +#include // note: take this out!! + +//#define COMBINEDOVERLAY + +#define ANIMSPRITES 4 +#define SPRITE_FPS (ANIMSPRITES+0) +#define SPRITE_BKG (ANIMSPRITES+1) +#define SPRITE_OVL1 (ANIMSPRITES+2) +#ifdef COMBINEDOVERLAY +#define SPRITES (ANIMSPRITES+3) +#else +#define SPRITE_OVL2 (ANIMSPRITES+3) +#define SPRITES (ANIMSPRITES+4) +#endif + +#define FPSWIDTH 60 +#define FPSHEIGHT 16 + +#define TRANSCOLOR PALETTEINDEX(111) + +#define SIN(a) s_sintable[((a) & 255)] +#define COS(a) s_sintable[(((a)+64) & 255)] + +static HSGDIFONT s_font; +static HSIMAGE s_fpsimage; +static int s_sintable[256]; +static HSSPRITE s_sprite[SPRITES]; +static HSTARGET s_target; + +static void UpdateFramesPerSecond (); + +//=========================================================================== +static void CreateFont () { + HFONT winfont = CreateFont(-12,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + SGdiImportFont(winfont,&s_font); + DeleteObject(winfont); + SGdiSelectObject(s_font); +} + +//=========================================================================== +static BOOL CreatePalette () { + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\bkg.pcx",&pe[0],NULL,0)) + return FALSE; + SDrawUpdatePalette(0,256,&pe[0]); + return TRUE; +} + +//=========================================================================== +static void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + s_sintable[loop] = (int)(sin(angle)*128); + } +} + +//=========================================================================== +static BOOL CreateSprites () { + DWORD loop; + HSIMAGE imagearray[SPRITES]; + + // LOAD THE ANIMATED SPRITE IMAGES + { + RECT rectarray[ANIMSPRITES]; + for (loop = 0; loop < ANIMSPRITES; ++loop) { + rectarray[loop].left = 0; + rectarray[loop].top = 125*loop; + rectarray[loop].right = 300; + rectarray[loop].bottom = 125*loop+125; + } + if (!S2dImageCreateFromFile("..\\demodata\\sprites.pcx", + TRANSCOLOR, + ANIMSPRITES, + rectarray, + imagearray)) + return FALSE; + } + + // CREATE THE FPS SPRITE IMAGE + S2dImageCreate(FPSWIDTH, + FPSHEIGHT, + 8, + TRANSCOLOR, + &imagearray[SPRITE_FPS]); + + // LOAD THE BACKGROUND SPRITE IMAGE + if (!S2dImageCreateFromFile("..\\demodata\\bkg.pcx", + TRANSCOLOR, + 1, + NULL, + &imagearray[SPRITE_BKG])) + return FALSE; + + // LOAD THE OVERLAY SPRITE IMAGES +#ifdef COMBINEDOVERLAY + if (!S2dImageCreateFromFile("..\\demodata\\overlay.pcx", + TRANSCOLOR, + 1, + NULL, + &imagearray[SPRITE_OVL1])) + return FALSE; +#else + { + RECT rectarray[2] = {{0,0,167,18},{0,295,640,480}}; + if (!S2dImageCreateFromFile("..\\demodata\\overlay.pcx", + TRANSCOLOR, + 2, + rectarray, + &imagearray[SPRITE_OVL1])) + return FALSE; + } +#endif + + // ATTACH THE IMAGES TO SPRITES, AND THEN CLOSE OR SAVE THE IMAGE HANDLES + for (loop = 0; loop < SPRITES; ++loop) { + S2dSpriteCreate(&s_sprite[loop]); + S2dSpriteSetImage(s_sprite[loop],imagearray[loop]); + if (loop == SPRITE_FPS) { + S2dSpriteSetPos(s_sprite[loop],0,20); + s_fpsimage = imagearray[loop]; + } + else { + S2dSpriteSetPos(s_sprite[loop],0,0); +#ifndef COMBINEDOVERLAY +if (loop == SPRITE_OVL2) S2dSpriteSetPos(s_sprite[loop],0,295); +#endif + S2dImageDelete(imagearray[loop]); + } + } + + // CREATE A TARGET, AND ATTACH THE SPRITES TO THE TARGET + S2dTargetCreate(&s_target); + for (loop = 0; loop < SPRITES; ++loop) + S2dSpriteSetTarget(s_sprite[loop], + s_target, + (loop >= SPRITE_OVL1) ? -1 : loop); + + return TRUE; +} + +//=========================================================================== +static BOOL CALLBACK IdleProc (DWORD) { + static BYTE rotation = 0; + static BYTE distance = 0; + ++distance; + rotation += 3; + for (DWORD loop = 0; loop < ANIMSPRITES; ++loop) + S2dSpriteSetPos(s_sprite[loop], + 170+(SIN(rotation+64*loop)*SIN(distance/2)/100), + 165+(COS(rotation+64*loop)*SIN(distance/2)/100)); + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { +//SGdiSetPitch(videopitch); +//SGdiRectangle(videobuffer,0,0,640,480,PALETTEINDEX(255)); + S2dTestDrawTarget(s_target,videobuffer,videopitch); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + UpdateFramesPerSecond(); +//return FALSE; + return TRUE; +} + +//=========================================================================== +static void CALLBACK OnClose (LPPARAMS) { + for (DWORD loop = 0; loop < SPRITES; ++loop) { + S2dSpriteDelete(s_sprite[loop]); + s_sprite[loop] = (HSSPRITE)0; + } + S2dImageDelete(s_fpsimage); + s_fpsimage = (HSIMAGE)0; + S2dTargetDelete(s_target); + s_target = (HSTARGET)0; + SGdiDeleteObject(s_font); + s_font = (HSGDIFONT)0; +} + +//=========================================================================== +static void CALLBACK OnPaint (LPPARAMS params) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + S2dTestDrawTarget(s_target,videobuffer,videopitch); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + ValidateRect(params->window,NULL); + params->useresult = TRUE; + params->result = 0; +} + +//=========================================================================== +static void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +static void UpdateFramesPerSecond () { + static DWORD frames = 0; + static DWORD starttime = GetTickCount(); + static DWORD lasttime = starttime; + + // INCREMENT THE NUMBER OF FRAMES + ++frames; + + // RETURN IF A SECOND HAS NOT YET ELAPSED + if (GetTickCount()-lasttime < 1000) + return; + lasttime += 1000; + + // DRAW THE AVERAGE NUMBER OF FRAMES PER SECOND + LPBYTE ptr; + if (S2dImageLockBuffer(s_fpsimage,FALSE,&ptr)) { + char outstr[16]; + wsprintf(outstr,"%3u FPS",frames/((lasttime-starttime)/1000)); + RECT rect = {0,0,FPSWIDTH,FPSHEIGHT}; + SGdiSetTargetDimensions(FPSWIDTH, + FPSHEIGHT, + 8, + FPSWIDTH); + SGdiExtTextOut(ptr, + 0, + 0, + &rect, + TRANSCOLOR, + ETO_TEXT_WHITE, + ETO_BKG_COLOR, + outstr); + S2dImageUnlockBuffer(s_fpsimage,ptr); + } + + // note: shouldn't be needed but it is for now... + S2dSpriteSetPos(s_sprite[SPRITE_FPS],0,20); + +static FILE *f = fopen("trace.txt","wt"); +fprintf(f,"%u\n",frames/((lasttime-starttime)/1000)); +fflush(f); + +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + CreateFont(); + CreateSinTable(); + if (!SDrawAutoInitialize(instance, + "ANIM5", + "Animation Example 5")) + FATALRESULT("SDrawAutoInitialize()"); + if (!CreatePalette()) + FATALRESULT("CreatePalette()"); + if (!CreateSprites()) + FATALRESULT("CreateSprites()"); + + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/ANIM/OLD/ANIM5.CS b/src/Storm/SAMPLES/ANIM/OLD/ANIM5.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/OLD/ANIM5.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/ANIM/OLD/ANIM5.EXE b/src/Storm/SAMPLES/ANIM/OLD/ANIM5.EXE new file mode 100644 index 0000000..19ee8a1 Binary files /dev/null and b/src/Storm/SAMPLES/ANIM/OLD/ANIM5.EXE differ diff --git a/src/Storm/SAMPLES/ANIM/OLD/PCH.H b/src/Storm/SAMPLES/ANIM/OLD/PCH.H new file mode 100644 index 0000000..8938a3f --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/OLD/PCH.H @@ -0,0 +1,6 @@ +#include +#include +#include +#include +#include "s2d.h" + diff --git a/src/Storm/SAMPLES/ANIM/OLD/S2D.CPP b/src/Storm/SAMPLES/ANIM/OLD/S2D.CPP new file mode 100644 index 0000000..c96322f --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/OLD/S2D.CPP @@ -0,0 +1,815 @@ +/**************************************************************************** +* +* S2D.CPP +* Storm 2d graphics engine +* +* By Michael O'Brien (8/8/97) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define MAXSPANLENGTH 0xFC + +#define SF_DISPLAYED 0x00000001 +#define SF_ERASEMARKER 0x00000002 + +DECLARE_STRICT_HANDLE(HLOCKEDIMAGE); +DECLARE_STRICT_HANDLE(HLOCKEDSPRITE); +DECLARE_STRICT_HANDLE(HLOCKEDTARGET); + +struct IMAGE; +struct SPRITE; +struct TARGET; + +static void SpriteRemoveImageReference (SPRITE *spriteptr); + +typedef BYTE SPAN; + +typedef struct _SPANPAIR { + SPAN copyspan; + SPAN skipspan; +} SPANPAIR, *SPANPAIRPTR; + +typedef struct _COMPOSITEDATA { + SPRITE *spriteptr; + BOOL stable; + SPAN *spanptr; + int currspan; + LPBYTE dataptr; +} COMPOSITEDATA, *COMPOSITEDATAPTR; + +EXPORTOBJECTDECL(SPRITE) { + POINT pos; + RECT boundingrect; + DWORD flags; + int zorder; + IMAGE *image; + TARGET *target; + LINKEX(SPRITE) linkimage; + LINKEX(SPRITE) linkzlist; + + inline ~SPRITE () { + if (image) + SpriteRemoveImageReference(this); + } + +} *SPRITEPTR; + +typedef LISTEX(SPRITE,linkimage) SPRITEIMAGELIST; +typedef LISTEX(SPRITE,linkzlist) SPRITEZLIST; + +EXPORTOBJECTDECL(IMAGE) { + SIZE size; + RECT boundingrect; + BOOL transparent; + BYTE transidx; + BYTE reserved[3]; + LPBYTE imagedata; + DWORD refcount; + ARRAY(SPANPAIR) spandata; + ARRAY(DWORD) spanindex; + SPRITEIMAGELIST spritelist; + + inline ~IMAGE () { + FREEIFUSED(imagedata); + } + +} *IMAGEPTR; + +EXPORTOBJECTDECL(TARGET) { + ARRAY(COMPOSITEDATA) compositedata; + CSRgn dirtyrgn; + ARRAY(RECT) dirtyrects; + ARRAY(LPVOID) dirtyrectparams; +// SPRITEZLIST sparelist; + SPRITEZLIST spritezlist; +} *TARGETPTR; + +typedef EXPORTTABLE(IMAGE ,HSIMAGE ,HLOCKEDIMAGE ,SYNC_NONE) IMAGETABLE; +typedef EXPORTTABLE(SPRITE,HSSPRITE,HLOCKEDSPRITE,SYNC_NONE) SPRITETABLE; +typedef EXPORTTABLE(TARGET,HSTARGET,HLOCKEDTARGET,SYNC_NONE) TARGETTABLE; + +static CCritSect s_apicritsect; +static IMAGETABLE s_imagetable; +static SPRITETABLE s_spritetable; +static TARGETTABLE s_targettable; + +//=========================================================================== +static inline BOOL CheckForSupportedColorFormat (int bitdepth, + COLORREF colorkey) { + return ((bitdepth == 8) && + (colorkey & 0x01000000)); +} + +//=========================================================================== +static inline void ImageAddSpanPair (IMAGEPTR imageptr, + SPANPAIRPTR pair, + int nextx, + int y) { + + // ADD THIS SPAN PAIR TO THE ARRAY + imageptr->spandata.AddElement(pair); + + // IF THIS SPAN PAIR CONTAINS A COPY SPAN, COMPUTE THE STARTING AND + // ENDING X COORDINATES IN THE COPY SPAN, AND ADD THAT RANGE TO THE + // BOUNDING RECTANGLE + if (pair->copyspan) { + int x2 = nextx-pair->skipspan; + int x1 = x2-pair->copyspan; + imageptr->boundingrect.left = min(x1 ,imageptr->boundingrect.left); + imageptr->boundingrect.top = min(y ,imageptr->boundingrect.top); + imageptr->boundingrect.right = max(x2 ,imageptr->boundingrect.right); + imageptr->boundingrect.bottom = max(y+1,imageptr->boundingrect.bottom); + } + + // BLANK THE SPAN PAIR + pair->copyspan = pair->skipspan = 0; +} + +//=========================================================================== +static void ImageCreateSpanData (IMAGEPTR imageptr) { + + // RESET THE COMPUTED IMAGE DATA + imageptr->boundingrect.left = imageptr->size.cx; + imageptr->boundingrect.top = imageptr->size.cy; + imageptr->boundingrect.right = 0; + imageptr->boundingrect.bottom = 0; + imageptr->transparent = FALSE; + imageptr->spandata.SetNumElements(0); + imageptr->spandata.ReserveSpace(imageptr->size.cx*4); + imageptr->spanindex.SetNumElements(imageptr->size.cy); + + // BUILD THE SPAN ARRAY + LPBYTE currdata = imageptr->imagedata; + for (int y = 0; y < imageptr->size.cy; ++y) { + + // SAVE THE SPAN INDEX THE CORRESPONDS WITH THE BEGINNING OF THIS + // SCAN LINE + imageptr->spanindex[y] = imageptr->spandata.NumElements(); + + // INITIALIZE THE OUTPUT VARIABLES + SPANPAIR currpair = {0,0}; + SPAN *currspan = &currpair.copyspan; + + // IF THIS SCAN LINE HAS ZERO WIDTH, THEN JUST OUTPUT THE LINE TERMINATOR + if (imageptr->size.cx <= 0) { + ImageAddSpanPair(imageptr,&currpair,0,y); + continue; + } + + // OTHERWISE, BUILD AND OUTPUT SPANS + int x; + for (x = 0; x < imageptr->size.cx; ++x) { + if ((*(currdata++) != imageptr->transidx) != (currspan == &currpair.copyspan)) + if (currspan == &currpair.copyspan) { + imageptr->transparent = TRUE; + currspan = &currpair.skipspan; + } + else { + ImageAddSpanPair(imageptr,&currpair,x,y); + currspan = &currpair.copyspan; + } + if (*currspan == MAXSPANLENGTH) + ImageAddSpanPair(imageptr,&currpair,x,y); + ++*currspan; + } + ImageAddSpanPair(imageptr,&currpair,x,y); + + // OUTPUT THE LINE TERMINATOR + ImageAddSpanPair(imageptr,&currpair,x,y); + + } + +} + +//=========================================================================== +static void SpriteLinkToZList (TARGETPTR targetptr, + SPRITEPTR spriteptr) { + spriteptr->linkzlist.Unlink(); + SPRITEPTR before = NULL; + ITERATELIST(SPRITE,targetptr->spritezlist,curr) + if (curr->zorder > spriteptr->zorder) { + before = curr; + break; + } + targetptr->spritezlist.LinkNode(spriteptr,LIST_LINK_BEFORE,before); +} + +//=========================================================================== +static void SpriteRemoveImageReference (SPRITE *spriteptr) { + if (!--spriteptr->image->refcount) + delete spriteptr->image; + spriteptr->image = NULL; + spriteptr->linkimage.Unlink(); +} + +//=========================================================================== +static void TargetBuildDirtyRects (TARGETPTR targetptr) { + targetptr->dirtyrgn.Clear(); + ITERATELIST(SPRITE,targetptr->spritezlist,spriteptr) + if ((spriteptr->flags & SF_ERASEMARKER) || + !(spriteptr->flags & SF_DISPLAYED)) + targetptr->dirtyrgn.AddRect(&spriteptr->boundingrect,spriteptr); + else + targetptr->dirtyrgn.AddParam(&spriteptr->boundingrect,spriteptr); + DWORD numrects; + targetptr->dirtyrgn.GetRects(&numrects,NULL); + targetptr->dirtyrects.SetNumElements(numrects); + targetptr->dirtyrgn.GetRects(&numrects,targetptr->dirtyrects.Ptr()); +} + +//=========================================================================== +static void TargetCompositeRect (LPBYTE videoptr, + int pitch, + TARGETPTR targetptr, + LPCRECT rect, + DWORD sprites, + SPRITEPTR *spritearray) { + DWORD loop; + + // BUILD A LIST OF SPRITES TO COMPOSITE + targetptr->compositedata.SetNumElements(sprites); + COMPOSITEDATAPTR compositedata = targetptr->compositedata.Ptr(); + DWORD compositenum = 0; + { + BOOL aboveallchanges = TRUE; + BOOL erasing = FALSE; + DWORD lastdisplayed = UINT_MAX; + for (loop = 0; loop < sprites; ++loop) { + SPRITEPTR spriteptr = spritearray[loop]; + if (spriteptr->flags & SF_ERASEMARKER) { + aboveallchanges = FALSE; + erasing = TRUE; + } + else { + if (!(spriteptr->flags & SF_DISPLAYED)) { + aboveallchanges = FALSE; + lastdisplayed = compositenum; + } + compositedata[compositenum].spriteptr = spriteptr; + compositedata[compositenum].stable = aboveallchanges; + compositedata[compositenum].dataptr + = spriteptr->image->imagedata + +((rect->top-spriteptr->pos.y-1)*spriteptr->image->size.cx) + +(rect->left-spriteptr->pos.x) + +(rect->right-rect->left); + ++compositenum; + } + } + if (!erasing) + compositenum = lastdisplayed+1; + } + + LPBYTE destptr = videoptr+rect->top*pitch+rect->left; + for (int y = rect->top; y < rect->bottom; ++y) { + + // SETUP COMPOSITING INFO FOR THIS SCAN LINE FOR EACH SPRITE + for (loop = 0; loop < compositenum; ++loop) { + SPRITEPTR spriteptr = compositedata[loop].spriteptr; + compositedata[loop].dataptr += spriteptr->image->size.cx-(rect->right-rect->left); + if ((y >= spriteptr->boundingrect.top) && + (y < spriteptr->boundingrect.bottom)) { + compositedata[loop].spanptr = (SPAN *)(spriteptr->image->spandata.Ptr() + +spriteptr->image->spanindex[y-spriteptr->pos.y]); + compositedata[loop].currspan = spriteptr->pos.x-rect->left; + while (compositedata[loop].currspan <= 0) + if ((!((DWORD)compositedata[loop].spanptr & 1)) && + !*(LPWORD)compositedata[loop].spanptr) + compositedata[loop].currspan = INT_MAX; + else + compositedata[loop].currspan += *compositedata[loop].spanptr++; + } + else { + compositedata[loop].spanptr = NULL; + compositedata[loop].currspan = INT_MAX; + } + } + + int x = rect->left; + int xspan; + while ((xspan = rect->right-x) > 0) { + + for (loop = 0; loop < compositenum; ++loop) { + xspan = min(xspan,compositedata[loop].currspan); + if ((DWORD)compositedata[loop].spanptr & 1) + break; + } + + if ((loop < compositenum) && + !compositedata[loop].stable) { + LPBYTE sourceptr = compositedata[loop].dataptr; +#ifdef _X86_ + __asm { + + // SETUP REGISTERS + push esi + push edi + mov eax,[xspan] + xor ecx,ecx + mov esi,[sourceptr] + mov edi,[destptr] + + // PERFORM THE COPY + cmp al,3 + jbe ds_done4 + + // IF NECESSARY, MOVE A SINGLE BYTE TO WORD-ALIGN THE + // DESTINATION + test edi,1 + jz ds_aligned2 + mov cl,[esi] + inc esi + mov [edi],cl + inc edi + dec al + ds_aligned2: + + // IF NECESSARY, MOVE A SINGLE WORD TO DWORD-ALIGN THE + // DESTINATION + test edi,2 + jz ds_aligned4 + mov cx,[esi] + add esi,2 + mov [edi],cx + add edi,2 + sub al,2 + ds_aligned4: + + // MOVE AS MANY ALIGNED DWORDS AS POSSIBLE + mov ecx,eax + and ecx,0FCh + shr ecx,2 + rep movsd + ds_done4: + + // MOVE ONE MORE WORD IF NECESSARY + test al,2 + jz ds_done2 + mov cx,[esi] + add esi,2 + mov [edi],cx + add edi,2 + ds_done2: + + // MOVE ONE MORE BYTE IF NECESSARY + test al,1 + jz ds_done1 + mov cl,[esi] + inc esi + mov [edi],cl + inc edi + ds_done1: + + pop edi + pop esi + } +#else + CopyMemory(destptr, + sourceptr, + xspan); +#endif + } + + destptr += xspan; + x += xspan; + + for (loop = 0; loop < compositenum; ++loop) { + compositedata[loop].dataptr += xspan; + int advance = xspan; + while (advance >= compositedata[loop].currspan) { + advance -= compositedata[loop].currspan; + if ((!((DWORD)compositedata[loop].spanptr & 1)) && + !*(LPWORD)compositedata[loop].spanptr) + compositedata[loop].currspan = INT_MAX; + else + compositedata[loop].currspan = *compositedata[loop].spanptr++; + } + compositedata[loop].currspan -= advance; + } + + } + + destptr += pitch-(rect->right-rect->left); + } +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +void APIENTRY S2dImageCreate (int width, + int height, + int bitdepth, + COLORREF colorkey, + HSIMAGE *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATEENDVOID; + + if (!CheckForSupportedColorFormat(bitdepth,colorkey)) + return; + + s_apicritsect.Enter(); + + // CREATE A NEW IMAGE RECORD + HLOCKEDIMAGE lockedhandle; + IMAGEPTR imageptr = s_imagetable.NewLock(handle,&lockedhandle); + imageptr->size.cx = width; + imageptr->size.cy = height; + imageptr->boundingrect.left = UINT_MAX; + imageptr->boundingrect.top = UINT_MAX; + imageptr->boundingrect.right = UINT_MAX; + imageptr->boundingrect.bottom = UINT_MAX; + imageptr->transidx = (BYTE)(colorkey & 0xFF); + imageptr->refcount = 1; + s_imagetable.Unlock(lockedhandle); + + s_apicritsect.Leave(); +} + +//=========================================================================== +BOOL APIENTRY S2dImageCreateFromFile (LPCTSTR filename, + COLORREF colorkey, + DWORD numimages, + LPCRECT rectarray, + HSIMAGE *handlearray) { + if (numimages && handlearray) + ZeroMemory(handlearray,numimages*sizeof(HSIMAGE)); + + VALIDATEBEGIN; + VALIDATE(filename && *filename); + VALIDATE(numimages); + VALIDATE(handlearray); + VALIDATEEND; + + s_apicritsect.Enter(); + HSFILE file = (HSFILE)0; + LPBYTE filebuffer = NULL; + BOOL result = FALSE; + TRY { + + // LOAD THE FILE FROM DISK + if (!SFileOpenFile(filename,&file)) + LEAVE; + DWORD filesize = SFileGetFileSize(file,NULL); + filebuffer = (LPBYTE)ALLOC(filesize); + if (!SFileReadFile(file,filebuffer,filesize)) + LEAVE; + + // DETERMINE THE SOURCE IMAGE DIMENSIONS + int width, height, bitdepth; + if (!SBmpDecodeImage(SBMP_IMAGETYPE_AUTO, + filebuffer, + filesize, + NULL, + NULL, + 0, + &width, + &height, + &bitdepth)) + LEAVE; + + // VERIFY THAT THE FILE IS IN A SUPPORTED COLOR FORMAT + if (!CheckForSupportedColorFormat(bitdepth,colorkey)) + LEAVE; + + // DECODE THE FILE INTO A TEMPORARY BUFFER + int bytedepth = bitdepth/8; + DWORD sourcebytes = width*height*(DWORD)bytedepth; + LPBYTE buffer = (LPBYTE)ALLOC(sourcebytes); + SBmpDecodeImage(SBMP_IMAGETYPE_AUTO, + filebuffer, + filesize, + NULL, + buffer, + sourcebytes); + + // PROCESS EACH IMAGE + for (DWORD loop = 0; + loop < numimages; + ++loop) { + + // DETERMINE THE IMAGE DIMENSIONS + int destwidth = width; + int destheight = height; + if (rectarray) { + destwidth = min(destwidth ,rectarray[loop].right+1-rectarray[loop].left); + destheight = min(destheight,rectarray[loop].bottom+1-rectarray[loop].top); + } + + // CREATE THE IMAGE + S2dImageCreate(destwidth, + destheight, + bitdepth, + colorkey, + &handlearray[loop]); + + // LOCK THE IMAGE BUFFER + LPBYTE ptr; + S2dImageLockBuffer(handlearray[loop],TRUE,&ptr); + + // BLT THE SOURCE RECTANGLE INTO THE IMAGE BUFFER + SIZE adjdestsize = {destwidth*bytedepth, + destheight}; + SIZE adjsourcesize = {width*bytedepth, + height}; + RECT adjsourcerect = {0, + 0, + adjsourcesize.cx, + adjsourcesize.cy}; + if (rectarray) { + adjsourcerect.left = rectarray[loop].left*bytedepth; + adjsourcerect.top = rectarray[loop].top; + adjsourcerect.right = rectarray[loop].right*bytedepth; + adjsourcerect.bottom = rectarray[loop].bottom; + } + SBltROP3Clipped(ptr, + NULL, + &adjdestsize, + adjdestsize.cx, + buffer, + &adjsourcerect, + &adjsourcesize, + adjsourcesize.cx, + 0, + SRCCOPY); + + // UNLOCK THE IMAGE BUFFER + S2dImageUnlockBuffer(handlearray[loop],ptr); + + } + + // FREE THE TEMPORARY BUFFER + FREE(buffer); + + result = TRUE; + } + FINALLY { + FREEIFUSED(filebuffer); + if (file) + SFileCloseFile(file); + } + s_apicritsect.Leave(); + return result; +} + +//=========================================================================== +void APIENTRY S2dImageDelete (HSIMAGE handle) { + s_apicritsect.Enter(); + HLOCKEDIMAGE lockedhandle; + IMAGEPTR imageptr = s_imagetable.Lock(handle,&lockedhandle); + if (!--imageptr->refcount) + s_imagetable.DeleteUnlock(imageptr,lockedhandle); + else + s_imagetable.Unlock(lockedhandle); + s_apicritsect.Leave(); +} + +//=========================================================================== +BOOL APIENTRY S2dImageLockBuffer (HSIMAGE handle, + BOOL blank, + LPBYTE *ptr) { + VALIDATEBEGIN; + VALIDATEANDBLANK(ptr); + VALIDATEEND; + + s_apicritsect.Enter(); + for (ONCE) { + + // FIND THE IMAGE RECORD + HLOCKEDIMAGE lockedhandle; + IMAGEPTR imageptr = s_imagetable.Lock(handle,&lockedhandle); + if (!imageptr) + break; + + // ALLOCATE A BUFFER IF NECESSARY + DWORD bytes = imageptr->size.cx*imageptr->size.cy; + if (!imageptr->imagedata) + imageptr->imagedata = (LPBYTE)ALLOC(bytes); + + // BLANK THE BUFFER IF REQUESTED + if (blank) + FillMemory(imageptr->imagedata,bytes,imageptr->transidx); + + // RETURN THE BUFFER + *ptr = imageptr->imagedata; + + s_imagetable.Unlock(lockedhandle); + } + s_apicritsect.Leave(); + return (*ptr != NULL); +} + +//=========================================================================== +void APIENTRY S2dImageUnlockBuffer (HSIMAGE handle, + LPBYTE ptr) { + s_apicritsect.Enter(); + for (ONCE) { + + // FIND THE IMAGE RECORD + HLOCKEDIMAGE lockedhandle; + IMAGEPTR imageptr = s_imagetable.Lock(handle,&lockedhandle); + if (!imageptr) + break; + + // PRODUCE THE SPAN DATA + ImageCreateSpanData(imageptr); + + s_imagetable.Unlock(lockedhandle); + } + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteCreate (HSSPRITE *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + s_spritetable.New(handle); + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteDelete (HSSPRITE handle) { + s_apicritsect.Enter(); + s_spritetable.Delete(handle); + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteSetImage (HSSPRITE handle, + HSIMAGE imagehandle) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATE(imagehandle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + + // LOCK THE SPRITE AND IMAGE + HLOCKEDSPRITE lockedsprite; + HLOCKEDIMAGE lockedimage; + SPRITEPTR spriteptr = s_spritetable.Lock(handle,&lockedsprite); + IMAGEPTR imageptr = s_imagetable.Lock(imagehandle,&lockedimage); + if (spriteptr->image != imageptr) { + + // REMOVE THE REFERENCE TO THE SPRITE'S OLD IMAGE + if (spriteptr->image) + SpriteRemoveImageReference(spriteptr); + + // ASSOCIATE THE IMAGE WITH THE SPRITE + if (imageptr) { + ++imageptr->refcount; + spriteptr->image = imageptr; + imageptr->spritelist.LinkNode(spriteptr); + } + + } + + // UNLOCK THE SPRITE AND IMAGE + s_imagetable.Unlock(lockedimage); + s_spritetable.Unlock(lockedsprite); + + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteSetPos (HSSPRITE handle, + int x, + int y) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + for (ONCE) { + + // LOCK THE SPRITE + HLOCKEDSPRITE lockedhandle; + SPRITEPTR spriteptr = s_spritetable.Lock(handle,&lockedhandle); + if (!spriteptr) + break; + + // PLACE AN ERASE MARKER AT THE SPRITE'S OLD POSITION + if (spriteptr->flags & SF_DISPLAYED) { + SPRITEPTR newptr = spriteptr->target->spritezlist.NewNode(LIST_UNLINKED); + newptr->pos = spriteptr->pos; + newptr->boundingrect = spriteptr->boundingrect; + newptr->flags = SF_ERASEMARKER; + newptr->zorder = spriteptr->zorder; + newptr->target = spriteptr->target; + spriteptr->target->spritezlist.LinkNode(newptr,LIST_LINK_AFTER,spriteptr); + } + + // SET THE SPRITE'S POSITION AND BOUNDING RECTANGLE + spriteptr->pos.x = x; + spriteptr->pos.y = y; + spriteptr->boundingrect.left = x+spriteptr->image->boundingrect.left; + spriteptr->boundingrect.top = y+spriteptr->image->boundingrect.top; + spriteptr->boundingrect.right = x+spriteptr->image->boundingrect.right; + spriteptr->boundingrect.bottom = y+spriteptr->image->boundingrect.bottom; + spriteptr->flags &= ~SF_DISPLAYED; + + // UNLOCK THE SPRITE + s_spritetable.Unlock(lockedhandle); + + } + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dSpriteSetTarget (HSSPRITE handle, + HSTARGET targethandle, + int zorder) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATE(targethandle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + + // LOCK THE SPRITE AND TARGET + HLOCKEDSPRITE lockedsprite; + HLOCKEDTARGET lockedtarget; + SPRITEPTR spriteptr = s_spritetable.Lock(handle,&lockedsprite); + TARGETPTR targetptr = s_targettable.Lock(targethandle,&lockedtarget); + + // SET THE SPRITE'S Z ORDER AND LINK IT INTO THE TARGET'S Z LIST + spriteptr->zorder = zorder; + spriteptr->target = targetptr; + SpriteLinkToZList(targetptr,spriteptr); + + // UNLOCK THE SPRITE AND TARGET + s_targettable.Unlock(lockedtarget); + s_spritetable.Unlock(lockedsprite); + + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dTargetCreate (HSTARGET *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATEENDVOID; + + s_apicritsect.Enter(); + s_targettable.New(handle); + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dTargetDelete (HSTARGET handle) { + s_apicritsect.Enter(); + s_targettable.Delete(handle); + s_apicritsect.Leave(); +} + +//=========================================================================== +void APIENTRY S2dTestDrawTarget (HSTARGET handle, + LPBYTE ptr, + int pitch) { + s_apicritsect.Enter(); + for (ONCE) { + + HLOCKEDTARGET lockedhandle; + TARGETPTR targetptr = s_targettable.Lock(handle,&lockedhandle); + if (!targetptr) + break; + + TargetBuildDirtyRects(targetptr); + for (DWORD rectindex = 0; + rectindex < targetptr->dirtyrects.NumElements(); + ++rectindex) { + DWORD totalparams; + targetptr->dirtyrgn.GetRectParams(&targetptr->dirtyrects[rectindex], + &totalparams, + NULL); + targetptr->dirtyrectparams.SetNumElements(totalparams); + targetptr->dirtyrgn.GetRectParams(&targetptr->dirtyrects[rectindex], + &totalparams, + targetptr->dirtyrectparams.Ptr()); + TargetCompositeRect(ptr, + pitch, + targetptr, + &targetptr->dirtyrects[rectindex], + totalparams, + (SPRITEPTR *)(targetptr->dirtyrectparams.Ptr())); + } + + ITERATELIST(SPRITE,targetptr->spritezlist,spriteptr) + if (spriteptr->flags & SF_ERASEMARKER) + ITERATE_DELETE + else + spriteptr->flags |= SF_DISPLAYED; + + s_targettable.Unlock(lockedhandle); + } + s_apicritsect.Leave(); +} diff --git a/src/Storm/SAMPLES/ANIM/OLD/S2D.H b/src/Storm/SAMPLES/ANIM/OLD/S2D.H new file mode 100644 index 0000000..ded5029 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/OLD/S2D.H @@ -0,0 +1,42 @@ +/**************************************************************************** +* +* 2D graphics engine functions +* +***/ + +DECLARE_STRICT_HANDLE(HSIMAGE); +DECLARE_STRICT_HANDLE(HSSPRITE); +DECLARE_STRICT_HANDLE(HSTARGET); + +void APIENTRY S2dImageCreate (int width, + int height, + int bitdepth, + COLORREF colorkey, + HSIMAGE *handle); +BOOL APIENTRY S2dImageCreateFromFile (LPCTSTR filename, + COLORREF colorkey, + DWORD numimages, + LPCRECT rectarray, + HSIMAGE *handlearray); +void APIENTRY S2dImageDelete (HSIMAGE handle); +BOOL APIENTRY S2dImageLockBuffer (HSIMAGE handle, + BOOL blank, + LPBYTE *ptr); +void APIENTRY S2dImageUnlockBuffer (HSIMAGE handle, + LPBYTE ptr); +void APIENTRY S2dSpriteCreate (HSSPRITE *handle); +void APIENTRY S2dSpriteDelete (HSSPRITE handle); +void APIENTRY S2dSpriteSetImage (HSSPRITE handle, + HSIMAGE imagehandle); +void APIENTRY S2dSpriteSetPos (HSSPRITE handle, + int x, + int y); +void APIENTRY S2dSpriteSetTarget (HSSPRITE handle, + HSTARGET targethandle, + int zorder); +void APIENTRY S2dTargetCreate (HSTARGET *handle); +void APIENTRY S2dTargetDelete (HSTARGET handle); + +void APIENTRY S2dTestDrawTarget (HSTARGET handle, + LPBYTE ptr, + int pitch); diff --git a/src/Storm/SAMPLES/ANIM/OLD/TRACE.TXT b/src/Storm/SAMPLES/ANIM/OLD/TRACE.TXT new file mode 100644 index 0000000..37befe1 --- /dev/null +++ b/src/Storm/SAMPLES/ANIM/OLD/TRACE.TXT @@ -0,0 +1,6 @@ +3642 +3384 +3441 +3492 +3505 +3528 diff --git a/src/Storm/SAMPLES/BUILDALL.BAT b/src/Storm/SAMPLES/BUILDALL.BAT new file mode 100644 index 0000000..9536e14 --- /dev/null +++ b/src/Storm/SAMPLES/BUILDALL.BAT @@ -0,0 +1,2 @@ +@echo off +for /r %%a in (*.cs) do c /as %%a diff --git a/src/Storm/SAMPLES/SAMPLE.CS b/src/Storm/SAMPLES/SAMPLE.CS new file mode 100644 index 0000000..01ff78c --- /dev/null +++ b/src/Storm/SAMPLES/SAMPLE.CS @@ -0,0 +1,6 @@ +if not %project%==sample goto start +halt +:start +#include +#include +!if exist *.bak del *.bak diff --git a/src/Storm/SAMPLES/SBLT/BENCH/BENCH.CPP b/src/Storm/SAMPLES/SBLT/BENCH/BENCH.CPP new file mode 100644 index 0000000..2c11069 --- /dev/null +++ b/src/Storm/SAMPLES/SBLT/BENCH/BENCH.CPP @@ -0,0 +1,121 @@ +/**************************************************************************** +* +* BENCH.CPP +* +* Benchmarks Storm's bitblt performance. +* +***/ + +#include +#include + +#define ALIGNED + +LPBYTE bitmap = NULL; +HSGDIFONT font = (HSGDIFONT)0; +BOOL paused = 0; +DWORD iterations = 0; + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (paused) + return 0; + + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 640)-20; + int top = (rand() % 450)+12; +#ifdef ALIGNED + left = (left >> 2) << 2; +#endif + SGdiSetPitch(pitch); + SGdiBitBlt(videobuffer,left,top,bitmap,NULL,40,40); + ++iterations; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +BOOL LoadBitmap () { + PALETTEENTRY pe[256]; + if (!SBmpAllocLoadImage("blizlogo.pcx",&pe[0],&bitmap)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + KillTimer(params->window,1); + SGdiDeleteObject(font); + FREE(bitmap); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + char outstr[64]; + wsprintf(outstr,"%u bitblts per second",iterations); + RECT rect = {0,0,320,12}; + SGdiSetPitch(pitch); + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + iterations = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DDBENCH"), + TEXT("Benchmark"))) + return 1; + if (!LoadBitmap()) + return 1; + if (!LoadFont()) + return 1; + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SBLT/BENCH/BENCH.CS b/src/Storm/SAMPLES/SBLT/BENCH/BENCH.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SBLT/BENCH/BENCH.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SBLT/BENCH/BENCH.EXE b/src/Storm/SAMPLES/SBLT/BENCH/BENCH.EXE new file mode 100644 index 0000000..cfb0e3a Binary files /dev/null and b/src/Storm/SAMPLES/SBLT/BENCH/BENCH.EXE differ diff --git a/src/Storm/SAMPLES/SBLT/BENCH/BLIZLOGO.PCX b/src/Storm/SAMPLES/SBLT/BENCH/BLIZLOGO.PCX new file mode 100644 index 0000000..4dc0a66 Binary files /dev/null and b/src/Storm/SAMPLES/SBLT/BENCH/BLIZLOGO.PCX differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.CPP b/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.CPP new file mode 100644 index 0000000..d7b8db4 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.CPP @@ -0,0 +1,225 @@ +/**************************************************************************** +* +* LIGHT1.CPP +* +* This series of examples performs lighting, using table lookup, while +* blting a 40x40 image. +* +* This first example does the bitblt in assembly language, using a simple +* implementation that loads the next byte, looks it up in the lighting +* table, then writes it. +* +***/ + +#include +#include + +BYTE lightingtable[16][256]; + +LPBYTE bitmapbits = NULL; +HSGDIFONT font = (HSGDIFONT)0; +BOOL paused = 0; +DWORD rectangles = 0; + +int inline square (int a) { return a*a; } + +//=========================================================================== +void BitBltLighting (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + int lightlevel) { + LPVOID table = lightingtable; + __asm { + + // SAVE IMPORTANT REGISTERS + push esi + push edi + push ebp + + // SETUP THE SOURCE AND DESTINATION + mov esi,source + mov edi,dest + + // COMPUTE THE AMOUNT WE WILL ADJUST THE SOURCE AND + // DESTINATION AFTER EACH LINE + mov ebx,sourcecx + mov edx,destcx + sub ebx,width + sub edx,width + + // SAVE THE LOOP COUNTERS + mov eax,width + mov cl,al + mov eax,height + mov ch,al + push ecx + + // SETUP A POINTER TO THE LIGHTING TABLE + mov eax,lightlevel + mov ebp,table + shl eax,8 + add ebp,eax + + // BLANK OUT EAX FOR USE AS A WORK REGISTER + xor eax,eax + + // PERFORM THE BITBLT + next: mov al,[esi] + inc esi + mov al,[ebp+eax] + mov [edi],al + inc edi + dec cl + jnz next + mov cl,[esp] + add esi,ebx + add edi,edx + dec ch + jnz next + + // RESTORE REGISTERS + pop ecx + pop ebp + pop edi + pop esi + + } +} + +//=========================================================================== +void CreateLightingTable (LPPALETTEENTRY pe) { + for (int lightlevel = 0; lightlevel < 16; ++lightlevel) + for (int index = 0; index < 256; ++index) { + int red = ((int)(pe+index)->peRed )*lightlevel/8; + int green = ((int)(pe+index)->peGreen)*lightlevel/8; + int blue = ((int)(pe+index)->peBlue )*lightlevel/8; + int minval = 0x7FFFFFFF; + int minindex = 0; + for (int testindex = 0; testindex < 256; ++testindex) { + int proximity = square(red-(int)(pe+testindex)->peRed) + +square(green-(int)(pe+testindex)->peGreen) + +square(blue-(int)(pe+testindex)->peBlue); + if (proximity < minval) { + minval = proximity; + minindex = testindex; + } + } + lightingtable[lightlevel][index] = minindex; + } +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (paused) + return 0; + + static BYTE lightlevel = 0; + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 600); + int top = (rand() % 428)+12; + BitBltLighting(videobuffer+top*pitch+left,bitmapbits,40,40,pitch,40,lightlevel & 0x0F); + ++lightlevel; + ++rectangles; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + FREE(bitmapbits); + bitmapbits = NULL; + KillTimer(params->window,1); + SGdiDeleteObject(font); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + char outstr[80]; + wsprintf(outstr,"%u bitblts per second using assembly (bytes)",rectangles); + RECT rect = {0,0,639,12}; + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + rectangles = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + + // INITIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("LIGHTING"), + TEXT("Lighting Test"))) + return 1; + + // LOAD THE TEST BITMAP AND SET THE PALETTE + { + bitmapbits = (LPBYTE)ALLOC(40*40); + if (!bitmapbits) + return 1; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage(TEXT("test.pcx"),&pe[0],bitmapbits,40*40)) + return 1; + if (!SDrawUpdatePalette(0,256,&pe[0])) + return 1; + CreateLightingTable(&pe[0]); + } + + // LOAD AND SELECT THE FONT + if (!LoadFont()) + return 1; + + // REGISTER MESSAGE HANDLERS AND SET THE TIMER + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + + // RUN THE MESSAGE LOOP + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.CS b/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.CS new file mode 100644 index 0000000..c42d6c0 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.CS @@ -0,0 +1 @@ +#include "..\..\sample.cs" diff --git a/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.EXE b/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.EXE new file mode 100644 index 0000000..8114bf7 Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT1/LIGHT1.EXE differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT1/TEST.PCX b/src/Storm/SAMPLES/SCODE/LIGHT1/TEST.PCX new file mode 100644 index 0000000..5421a7d Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT1/TEST.PCX differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.CPP b/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.CPP new file mode 100644 index 0000000..b06c301 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.CPP @@ -0,0 +1,223 @@ +/**************************************************************************** +* +* LIGHT2.CPP +* +* This next example also uses an assembly language bitblt function, but this +* time it tries to read and write as many whole doublewords as possible. +* The inner loop of the function is taken from Diablo. +* +***/ + +#include +#include + +BYTE lightingtable[16][256]; + +LPBYTE bitmapbits = NULL; +HSGDIFONT font = (HSGDIFONT)0; +BOOL paused = 0; +DWORD rectangles = 0; + +int inline square (int a) { return a*a; } + +//=========================================================================== +void BitBltLighting (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + int lightlevel) { + LPVOID table = lightingtable; + DWORD destadjust = destcx-width; + DWORD sourceadjust = sourcecx-width; + __asm { + + // SAVE IMPORTANT REGISTERS + push esi + push edi + + // SETUP THE SOURCE AND DESTINATION + mov esi,source + mov edi,dest + + // SETUP REGISTERS + mov eax,lightlevel + mov ebx,table + shl eax,8 + add ebx,eax + mov edx,width + + // START THE NEXT LINE + startline: mov ecx,edx + and ecx,3 + jz startdword + + // USE BYTES FOR ODD PIXELS + nextbyte: lodsb + xlatb + stosb + loop nextbyte + + // USE DWORDS FOR THE REST + startdword: mov ecx,edx + shr ecx,2 + nextdword: lodsd + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + xlatb + ror eax,8 + stosd + loop nextdword + + // ADJUST FOR THE NEXT LINE + add esi,sourceadjust + add edi,destadjust + dec height + jnz startline + + // RESTORE REGISTERS + pop edi + pop esi + + } +} + +//=========================================================================== +void CreateLightingTable (LPPALETTEENTRY pe) { + for (int lightlevel = 0; lightlevel < 16; ++lightlevel) + for (int index = 0; index < 256; ++index) { + int red = ((int)(pe+index)->peRed )*lightlevel/8; + int green = ((int)(pe+index)->peGreen)*lightlevel/8; + int blue = ((int)(pe+index)->peBlue )*lightlevel/8; + int minval = 0x7FFFFFFF; + int minindex = 0; + for (int testindex = 0; testindex < 256; ++testindex) { + int proximity = square(red-(int)(pe+testindex)->peRed) + +square(green-(int)(pe+testindex)->peGreen) + +square(blue-(int)(pe+testindex)->peBlue); + if (proximity < minval) { + minval = proximity; + minindex = testindex; + } + } + lightingtable[lightlevel][index] = minindex; + } +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (paused) + return 0; + + static BYTE lightlevel = 0; + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 600); + int top = (rand() % 428)+12; + BitBltLighting(videobuffer+top*pitch+left,bitmapbits,40,40,pitch,40,lightlevel & 0x0F); + ++lightlevel; + ++rectangles; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + FREE(bitmapbits); + bitmapbits = NULL; + KillTimer(params->window,1); + SGdiDeleteObject(font); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + char outstr[80]; + wsprintf(outstr,"%u bitblts per second using assembly (dwords, complex instructions)",rectangles); + RECT rect = {0,0,639,12}; + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + rectangles = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + + // INITIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("LIGHTING"), + TEXT("Lighting Test"))) + return 1; + + // LOAD THE TEST BITMAP AND SET THE PALETTE + { + bitmapbits = (LPBYTE)ALLOC(40*40); + if (!bitmapbits) + return 1; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage(TEXT("test.pcx"),&pe[0],bitmapbits,40*40)) + return 1; + if (!SDrawUpdatePalette(0,256,&pe[0])) + return 1; + CreateLightingTable(&pe[0]); + } + + // LOAD AND SELECT THE FONT + if (!LoadFont()) + return 1; + + // REGISTER MESSAGE HANDLERS AND SET THE TIMER + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + + // RUN THE MESSAGE LOOP + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.CS b/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.CS new file mode 100644 index 0000000..c42d6c0 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.CS @@ -0,0 +1 @@ +#include "..\..\sample.cs" diff --git a/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.EXE b/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.EXE new file mode 100644 index 0000000..9d48dd8 Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT2/LIGHT2.EXE differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT2/TEST.PCX b/src/Storm/SAMPLES/SCODE/LIGHT2/TEST.PCX new file mode 100644 index 0000000..5421a7d Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT2/TEST.PCX differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.CPP b/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.CPP new file mode 100644 index 0000000..caff784 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.CPP @@ -0,0 +1,233 @@ +/**************************************************************************** +* +* LIGHT3.CPP +* +* This next version also uses assembly language, and also does reads and +* writes whole doublewords at a time where possible. The difference is +* that the inner loop has been recoded to avoid the use of complex +* instructions, which execute slowly on modern Intel processors. +* +***/ + +#include +#include + +BYTE lightingtable[16][256]; + +LPBYTE bitmapbits = NULL; +HSGDIFONT font = (HSGDIFONT)0; +BOOL paused = 0; +DWORD rectangles = 0; + +int inline square (int a) { return a*a; } + +//=========================================================================== +void BitBltLighting (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + int lightlevel) { + LPBYTE table = ((LPBYTE)lightingtable)+(lightlevel << 8); + BYTE width8 = width & 0xFF; + DWORD destadjust = destcx-width; + DWORD sourceadjust = sourcecx-width; + __asm { + + // SAVE IMPORTANT REGISTERS + push esi + push edi + + // SETUP THE SOURCE AND DESTINATION + mov esi,source + mov edi,dest + + // SETUP REGISTERS + xor eax,eax + xor ebx,ebx + + // START THE NEXT LINE + startline: mov ch,width8 + mov cl,ch + push ebp + mov ebp,table + shr ch,2 + and cl,3 + jz nextdword + + // USE BYTES FOR ODD PIXELS + nextbyte: mov al,[esi] + inc esi + mov al,[ebp+eax] + mov [edi],al + inc edi + dec cl + jnz nextbyte + + // USE DWORDS FOR THE REST + nextdword: mov edx,[esi] + add esi,4 + mov al,dl + mov bl,dh + mov dl,[ebp+eax] + mov dh,[ebp+ebx] + ror edx,16 + mov al,dl + mov bl,dh + mov dl,[ebp+eax] + mov dh,[ebp+ebx] + ror edx,16 + mov [edi],edx + add edi,4 + dec ch + jnz nextdword + + // ADJUST FOR THE NEXT LINE + pop ebp + add esi,sourceadjust + add edi,destadjust + dec height + jnz startline + + // RESTORE REGISTERS + pop edi + pop esi + + } +} + +//=========================================================================== +void CreateLightingTable (LPPALETTEENTRY pe) { + for (int lightlevel = 0; lightlevel < 16; ++lightlevel) + for (int index = 0; index < 256; ++index) { + int red = ((int)(pe+index)->peRed )*lightlevel/8; + int green = ((int)(pe+index)->peGreen)*lightlevel/8; + int blue = ((int)(pe+index)->peBlue )*lightlevel/8; + int minval = 0x7FFFFFFF; + int minindex = 0; + for (int testindex = 0; testindex < 256; ++testindex) { + int proximity = square(red-(int)(pe+testindex)->peRed) + +square(green-(int)(pe+testindex)->peGreen) + +square(blue-(int)(pe+testindex)->peBlue); + if (proximity < minval) { + minval = proximity; + minindex = testindex; + } + } + lightingtable[lightlevel][index] = minindex; + } +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (paused) + return 0; + + static BYTE lightlevel = 0; + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 600); + int top = (rand() % 428)+12; + BitBltLighting(videobuffer+top*pitch+left,bitmapbits,40,40,pitch,40,lightlevel & 0x0F); + ++lightlevel; + ++rectangles; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + FREE(bitmapbits); + bitmapbits = NULL; + KillTimer(params->window,1); + SGdiDeleteObject(font); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + char outstr[80]; + wsprintf(outstr,"%u bitblts per second using assembly (dwords, simple instructions)",rectangles); + RECT rect = {0,0,639,12}; + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + rectangles = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + + // INITIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("LIGHTING"), + TEXT("Lighting Test"))) + return 1; + + // LOAD THE TEST BITMAP AND SET THE PALETTE + { + bitmapbits = (LPBYTE)ALLOC(40*40); + if (!bitmapbits) + return 1; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage(TEXT("test.pcx"),&pe[0],bitmapbits,40*40)) + return 1; + if (!SDrawUpdatePalette(0,256,&pe[0])) + return 1; + CreateLightingTable(&pe[0]); + } + + // LOAD AND SELECT THE FONT + if (!LoadFont()) + return 1; + + // REGISTER MESSAGE HANDLERS AND SET THE TIMER + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + + // RUN THE MESSAGE LOOP + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.CS b/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.CS new file mode 100644 index 0000000..c42d6c0 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.CS @@ -0,0 +1 @@ +#include "..\..\sample.cs" diff --git a/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.EXE b/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.EXE new file mode 100644 index 0000000..6a6131d Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT3/LIGHT3.EXE differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT3/TEST.PCX b/src/Storm/SAMPLES/SCODE/LIGHT3/TEST.PCX new file mode 100644 index 0000000..5421a7d Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT3/TEST.PCX differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.CPP b/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.CPP new file mode 100644 index 0000000..248599c --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.CPP @@ -0,0 +1,240 @@ +/**************************************************************************** +* +* LIGHT4.CPP +* +* This version is similar to the previous one, except that it does aligned +* dword writes where possible. +* +***/ + +#include +#include + +BYTE lightingtable[16][256]; + +LPBYTE bitmapbits = NULL; +HSGDIFONT font = (HSGDIFONT)0; +BOOL paused = 0; +DWORD rectangles = 0; + +int inline square (int a) { return a*a; } + +//=========================================================================== +void BitBltLighting (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + int lightlevel) { + LPBYTE table = ((LPBYTE)lightingtable)+(lightlevel << 8); + DWORD destadjust = destcx-width; + DWORD sourceadjust = sourcecx-width; + __asm { + + // SAVE IMPORTANT REGISTERS + push esi + push edi + + // SETUP THE SOURCE AND DESTINATION + mov esi,source + mov edi,dest + + // SETUP REGISTERS + xor eax,eax + xor ebx,ebx + + // START THE NEXT LINE + startline: mov ecx,width + push ebp + mov ebp,table + + // USE BYTES FOR THE FIRST SET OF UNALIGNED PIXELS + nextbyte1: test edi,3 + jz nextdword + mov al,[esi] + inc esi + mov al,[ebp+eax] + dec ecx + mov [edi],al + inc edi + jmp nextbyte1 + + // USE DWORDS FOR THE MAIN BODY + nextdword: cmp ecx,4 + jb nextbyte2 + mov edx,[esi] + add esi,4 + mov al,dl + mov bl,dh + mov dl,[ebp+eax] + mov dh,[ebp+ebx] + ror edx,16 + mov al,dl + mov bl,dh + mov dl,[ebp+eax] + mov dh,[ebp+ebx] + ror edx,16 + sub ecx,4 + mov [edi],edx + add edi,4 + jmp nextdword + + // USE BYTES FOR THE SECOND SET OF UNALIGNED PIXELS + nextbyte2: dec ecx + js finish + mov al,[esi] + inc esi + mov al,[ebp+eax] + mov [edi],al + inc edi + jmp nextbyte2 + + // ADJUST FOR THE NEXT LINE + finish: pop ebp + add esi,sourceadjust + add edi,destadjust + dec height + jnz startline + + // RESTORE REGISTERS + pop edi + pop esi + + } +} + +//=========================================================================== +void CreateLightingTable (LPPALETTEENTRY pe) { + for (int lightlevel = 0; lightlevel < 16; ++lightlevel) + for (int index = 0; index < 256; ++index) { + int red = ((int)(pe+index)->peRed )*lightlevel/8; + int green = ((int)(pe+index)->peGreen)*lightlevel/8; + int blue = ((int)(pe+index)->peBlue )*lightlevel/8; + int minval = 0x7FFFFFFF; + int minindex = 0; + for (int testindex = 0; testindex < 256; ++testindex) { + int proximity = square(red-(int)(pe+testindex)->peRed) + +square(green-(int)(pe+testindex)->peGreen) + +square(blue-(int)(pe+testindex)->peBlue); + if (proximity < minval) { + minval = proximity; + minindex = testindex; + } + } + lightingtable[lightlevel][index] = minindex; + } +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (paused) + return 0; + + static BYTE lightlevel = 0; + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 600); + int top = (rand() % 428)+12; + BitBltLighting(videobuffer+top*pitch+left,bitmapbits,40,40,pitch,40,lightlevel & 0x0F); + ++lightlevel; + ++rectangles; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + FREE(bitmapbits); + bitmapbits = NULL; + KillTimer(params->window,1); + SGdiDeleteObject(font); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + char outstr[80]; + wsprintf(outstr,"%u bitblts per second using assembly (aligned dwords)",rectangles); + RECT rect = {0,0,639,12}; + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + rectangles = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + + // INITIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("LIGHTING"), + TEXT("Lighting Test"))) + return 1; + + // LOAD THE TEST BITMAP AND SET THE PALETTE + { + bitmapbits = (LPBYTE)ALLOC(40*40); + if (!bitmapbits) + return 1; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage(TEXT("test.pcx"),&pe[0],bitmapbits,40*40)) + return 1; + if (!SDrawUpdatePalette(0,256,&pe[0])) + return 1; + CreateLightingTable(&pe[0]); + } + + // LOAD AND SELECT THE FONT + if (!LoadFont()) + return 1; + + // REGISTER MESSAGE HANDLERS AND SET THE TIMER + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + + // RUN THE MESSAGE LOOP + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.CS b/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.CS new file mode 100644 index 0000000..c42d6c0 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.CS @@ -0,0 +1 @@ +#include "..\..\sample.cs" diff --git a/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.EXE b/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.EXE new file mode 100644 index 0000000..07f0754 Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT4/LIGHT4.EXE differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT4/TEST.PCX b/src/Storm/SAMPLES/SCODE/LIGHT4/TEST.PCX new file mode 100644 index 0000000..5421a7d Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT4/TEST.PCX differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.CPP b/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.CPP new file mode 100644 index 0000000..33285dd --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.CPP @@ -0,0 +1,189 @@ +/**************************************************************************** +* +* LIGHT5.CPP +* +* This final version uses Storm's S-code compiler instead of assembly +* language to perform the blt. The advantages are: +* 1. Storm compiles S-code into fully unrolled machine language loops, +* which can process an entire scan line with no loop counter or +* conditional jumps. +* 2. Storm ensures that all dword operations are aligned on dword +* boundaries. +* 3. Since there is no loop counter, an additional general purpose register +* is available for the code to use. (In this particular case, there was +* no need of the extra register, but in many programs this would provide +* an additional speed boost.) +* 4. Using S-code instead of assembly language simplifies the program. +* (In this case, the number of lines of code involved with the lighting +* blt was reduced from 87 to 16.) +* 5. Using S-code instead of assembly language simplifies porting the +* program to other platforms. +* +***/ + +#include +#include + +BYTE lightingtable[16][256]; + +LPBYTE bitmapbits = NULL; +HSGDIFONT font = (HSGDIFONT)0; +BOOL paused = 0; +DWORD rectangles = 0; +HSCODESTREAM scodestream = (HSCODESTREAM)0; +SCODEEXECUTEDATA scodeexec; + +int inline square (int a) { return a*a; } + +//=========================================================================== +void CreateLightingTable (LPPALETTEENTRY pe) { + for (int lightlevel = 0; lightlevel < 16; ++lightlevel) + for (int index = 0; index < 256; ++index) { + int red = ((int)(pe+index)->peRed )*lightlevel/8; + int green = ((int)(pe+index)->peGreen)*lightlevel/8; + int blue = ((int)(pe+index)->peBlue )*lightlevel/8; + int minval = 0x7FFFFFFF; + int minindex = 0; + for (int testindex = 0; testindex < 256; ++testindex) { + int proximity = square(red-(int)(pe+testindex)->peRed) + +square(green-(int)(pe+testindex)->peGreen) + +square(blue-(int)(pe+testindex)->peBlue); + if (proximity < minval) { + minval = proximity; + minindex = testindex; + } + } + lightingtable[lightlevel][index] = minindex; + } +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (paused) + return 0; + + static BYTE lightlevel = 0; + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + scodeexec.adjustdest = pitch-40; + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 600); + int top = (rand() % 428)+12; + scodeexec.dest = videobuffer+top*pitch+left; + scodeexec.table = &lightingtable[lightlevel & 0x0F][0]; + SCodeExecute(scodestream,&scodeexec); + ++lightlevel; + ++rectangles; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + FREE(bitmapbits); + bitmapbits = NULL; + KillTimer(params->window,1); + SGdiDeleteObject(font); + SCodeDelete(scodestream); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + char outstr[80]; + wsprintf(outstr,"%u bitblts per second using S-code",rectangles); + RECT rect = {0,0,639,12}; + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + rectangles = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + + // INITIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("LIGHTING"), + TEXT("Lighting Test"))) + return 1; + + // LOAD THE TEST BITMAP AND SET THE PALETTE + { + bitmapbits = (LPBYTE)ALLOC(40*40); + if (!bitmapbits) + return 1; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage(TEXT("test.pcx"),&pe[0],bitmapbits,40*40)) + return 1; + if (!SDrawUpdatePalette(0,256,&pe[0])) + return 1; + CreateLightingTable(&pe[0]); + } + + // LOAD AND SELECT THE FONT + if (!LoadFont()) + return 1; + + // CREATE THE S-CODE STREAM AND EXECUTE DATA + if (!SCodeCompile(TEXT("1 B=S D=TB"), + TEXT("4 W=S A1=W1 B1=W2 W1=TA W2=TB A1=W3 B1=W4 W3=TA W4=TB D=W"), + NULL, + 64, + SCODE_CF_AUTOALIGNDWORD, + &scodestream)) + return 1; + ZeroMemory(&scodeexec,sizeof(SCODEEXECUTEDATA)); + scodeexec.size = sizeof(SCODEEXECUTEDATA); + scodeexec.xiterations = 40; + scodeexec.yiterations = 40; + scodeexec.source = bitmapbits; + + // REGISTER MESSAGE HANDLERS AND SET THE TIMER + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + + // RUN THE MESSAGE LOOP + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.CS b/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.EXE b/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.EXE new file mode 100644 index 0000000..58acedb Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT5/LIGHT5.EXE differ diff --git a/src/Storm/SAMPLES/SCODE/LIGHT5/TEST.PCX b/src/Storm/SAMPLES/SCODE/LIGHT5/TEST.PCX new file mode 100644 index 0000000..5421a7d Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIGHT5/TEST.PCX differ diff --git a/src/Storm/SAMPLES/SCODE/LIST/LIST.CPP b/src/Storm/SAMPLES/SCODE/LIST/LIST.CPP new file mode 100644 index 0000000..53ebfc1 --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIST/LIST.CPP @@ -0,0 +1,42 @@ +/**************************************************************************** +* +* LIST.CPP +* +* This simple command line program can be used to check an S-code string for +* errors, and to list pseudocode for the compiled string. +* +***/ + +#include +#include +#include + +int __cdecl main () { + + // GET THE S-CODE STRING + printf("Enter S-code string: "); + char scodestring[256]; + gets(scodestring); + printf("\n"); + + // DO A TEST COMPILE TO CHECK FOR ERRORS + { + HSCODESTREAM handle; + const char *firsterror = NULL; + if (SCodeCompile(NULL,scodestring,&firsterror,1,0,&handle)) + SCodeDelete(handle); + else if (firsterror) { + printf("%s\n%*s^\n",scodestring,firsterror-scodestring,""); + return 0; + } + } + + // COMPILE IT INTO PSEUDOCODE AND LIST THE PSEUDOCODE + { + char buffer[1024] = ""; + SCodeGetPseudocode(scodestring,buffer,1024); + printf("%s\n",buffer); + } + + return 0; +} diff --git a/src/Storm/SAMPLES/SCODE/LIST/LIST.CS b/src/Storm/SAMPLES/SCODE/LIST/LIST.CS new file mode 100644 index 0000000..c4f052a --- /dev/null +++ b/src/Storm/SAMPLES/SCODE/LIST/LIST.CS @@ -0,0 +1,2 @@ +#include "..\..\sample.cs" +set subsystem=console diff --git a/src/Storm/SAMPLES/SCODE/LIST/LIST.EXE b/src/Storm/SAMPLES/SCODE/LIST/LIST.EXE new file mode 100644 index 0000000..0c45127 Binary files /dev/null and b/src/Storm/SAMPLES/SCODE/LIST/LIST.EXE differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.CPP b/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.CPP new file mode 100644 index 0000000..b28b1a0 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.CPP @@ -0,0 +1,72 @@ +/**************************************************************************** +* +* DLGEX1.CPP +* +* Creates a dialog box using the normal Windows dialog manager. +* +* The dialog looks functional enough, but there are some not-so-obvious +* problems using it in a DirectDraw game: +* +* 1. The dialog automatically adjusts itself to the display device's font +* size and pixels-per-inch ratio. This is a nice feature for normal +* Windows applications, but problematic for games that want their glue +* screens to always exactly fill the screen. +* +* 2. The dialog also displays itself using the system's currently selected +* color scheme and metrics. This, again, reduces the ability of the +* application to control exactly how its glue screens look. +* +* 3. It is difficult to customize the look of Windows dialog boxes. There +* is no support for background bitmaps or button textures. +* +* 4. Windows' dialog manager is not well integrated with DirectDraw. For +* example, if you alt+tab away from the application while the dialog is +* on the screen, you will never be able to switch back. +* +***/ + +#define STRICT +#include +#include +#include "resource.h" + +//=========================================================================== +BOOL CALLBACK DlgProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + + case IDOK: + EndDialog(window,1); + break; + + case IDCANCEL: + EndDialog(window,0); + break; + + } + break; + + case WM_INITDIALOG: + return 1; + + } + return 0; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DLGEX1"), + TEXT("Dialog Example 1"))) + return 1; + DialogBox(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + SDrawGetFrameWindow(), + DlgProc); + return 0; +} diff --git a/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.CS b/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.EXE b/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.EXE new file mode 100644 index 0000000..30dcb6f Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.EXE differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.RC b/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.RC new file mode 100644 index 0000000..492c4b8 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX1/DLGEX1.RC @@ -0,0 +1,97 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SAMPLES/SDLG/DLGEX1/RESOURCE.H b/src/Storm/SAMPLES/SDLG/DLGEX1/RESOURCE.H new file mode 100644 index 0000000..952cb72 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX1/RESOURCE.H @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by dlgex1.rc +// +#define IDD_DIALOG1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.CPP b/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.CPP new file mode 100644 index 0000000..dc1cafb --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.CPP @@ -0,0 +1,60 @@ +/**************************************************************************** +* +* DLGEX2.CPP +* +* This sample displays the same dialog as DLGEX1, but now using Storm's +* dialog manager instead of Windows'. +* +* No changes were required to the dialog resource. The only changes +* required in the program itself were changing Windows API calls to +* Storm equivalents (i.e. prepending everything with "SDlg") and making +* the dialog box procedure call SDlgDefDialogProc() instead of returning +* zero. +* +***/ + +#define STRICT +#include +#include +#include "resource.h" + +//=========================================================================== +BOOL CALLBACK DlgProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + + case IDOK: + SDlgEndDialog(window,1); + break; + + case IDCANCEL: + SDlgEndDialog(window,0); + break; + + } + break; + + case WM_INITDIALOG: + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DLGEX2"), + TEXT("Dialog Example 2"))) + return 1; + SDlgDialogBox(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + SDrawGetFrameWindow(), + DlgProc); + return 0; +} diff --git a/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.CS b/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.EXE b/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.EXE new file mode 100644 index 0000000..ca1edac Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.EXE differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.RC b/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.RC new file mode 100644 index 0000000..492c4b8 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX2/DLGEX2.RC @@ -0,0 +1,97 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SAMPLES/SDLG/DLGEX2/RESOURCE.H b/src/Storm/SAMPLES/SDLG/DLGEX2/RESOURCE.H new file mode 100644 index 0000000..19f6760 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX2/RESOURCE.H @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by dlgex2.rc +// +#define IDD_DIALOG1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SAMPLES/SDLG/DLGEX3/BKG1.PCX b/src/Storm/SAMPLES/SDLG/DLGEX3/BKG1.PCX new file mode 100644 index 0000000..539db54 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX3/BKG1.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.CPP b/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.CPP new file mode 100644 index 0000000..8f1fb00 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.CPP @@ -0,0 +1,95 @@ +/**************************************************************************** +* +* DLGEX3.CPP +* +* Demonstrates the use of background bitmaps. +* +* This sample displays the same simple dialog box again. However, it +* has been modified to use a background bitmap. It loads the bitmap from +* disk during the WM_INITDIALOG message, and registers it with Storm's +* dialog manager. It frees the bitmap on WM_DESTROY. +* +***/ + +#define STRICT +#include +#include +#include "resource.h" + +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height); + +//=========================================================================== +BOOL CALLBACK DlgProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + static LPBYTE backgroundbitmap = NULL; + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + + case IDOK: + SDlgEndDialog(window,1); + break; + + case IDCANCEL: + SDlgEndDialog(window,0); + break; + + } + break; + + case WM_DESTROY: + if (backgroundbitmap) { + FREE(backgroundbitmap); + backgroundbitmap = NULL; + } + break; + + case WM_INITDIALOG: + { + int width, height; + backgroundbitmap = LoadBitmap(TEXT("bkg1.pcx"),&width,&height); + if (backgroundbitmap) + SDlgSetBitmap(window, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + } + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height) { + if (!SBmpLoadImage(filename,NULL,NULL,0,width,height)) + return NULL; + LPBYTE bitmapbits = (LPBYTE)ALLOC((*width)*(*height)); + if (!bitmapbits) + return NULL; + PALETTEENTRY pe[256]; + if (SBmpLoadImage(filename,&pe[0],bitmapbits,(*width)*(*height))) + SDrawUpdatePalette(10,236,&pe[10]); + return bitmapbits; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DLGEX3"), + TEXT("Dialog Example 3"))) + return 1; + SDlgDialogBox(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + SDrawGetFrameWindow(), + DlgProc); + return 0; +} diff --git a/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.CS b/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.EXE b/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.EXE new file mode 100644 index 0000000..13e73fa Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.EXE differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.RC b/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.RC new file mode 100644 index 0000000..492c4b8 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX3/DLGEX3.RC @@ -0,0 +1,97 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SAMPLES/SDLG/DLGEX3/RESOURCE.H b/src/Storm/SAMPLES/SDLG/DLGEX3/RESOURCE.H new file mode 100644 index 0000000..ce4d1a3 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX3/RESOURCE.H @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by dlgex3.rc +// +#define IDD_DIALOG1 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/BKG1.PCX b/src/Storm/SAMPLES/SDLG/DLGEX4/BKG1.PCX new file mode 100644 index 0000000..539db54 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX4/BKG1.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/BKG2.PCX b/src/Storm/SAMPLES/SDLG/DLGEX4/BKG2.PCX new file mode 100644 index 0000000..37352b0 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX4/BKG2.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/BKG3.PCX b/src/Storm/SAMPLES/SDLG/DLGEX4/BKG3.PCX new file mode 100644 index 0000000..105d203 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX4/BKG3.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/BKG4.PCX b/src/Storm/SAMPLES/SDLG/DLGEX4/BKG4.PCX new file mode 100644 index 0000000..f69bfd2 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX4/BKG4.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.CPP b/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.CPP new file mode 100644 index 0000000..38b1cd9 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.CPP @@ -0,0 +1,118 @@ +/**************************************************************************** +* +* DLGEX4.CPP +* +* Demonstrates multiple overlapping dialog boxes. +* +* The dialog box has been given a new button, named "Create...", which +* creates a child dialog. The dialogs all share a common dialog box +* procedure, but each has a different background bitmap. Since each dialog +* box must have a unique pointer to its bitmap data, the pointers are now +* kept as window properties rather than static variables. +* +***/ + +#define STRICT +#include +#include +#include "resource.h" + +HINSTANCE instance = (HINSTANCE)0; + +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height); + +//=========================================================================== +BOOL CALLBACK DlgProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + + case IDOK: + SDlgEndDialog(window,1); + break; + + case IDCANCEL: + SDlgEndDialog(window,0); + break; + + case IDC_BUTTON1: + SDlgDialogBoxParam(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + window, + DlgProc, + (LPARAM)GetProp(window,TEXT("RecursionDepth"))+1); + break; + + } + break; + + case WM_DESTROY: + if (GetProp(window,TEXT("BackgroundBitmap"))) + FREE((LPVOID)GetProp(window,TEXT("BackgroundBitmap"))); + break; + + case WM_INITDIALOG: + + // SAVE THE RECURSION DEPTH + SetProp(window,TEXT("RecursionDepth"),(HANDLE)lparam); + + // POSITION THE DIALOG BOX ON THE SCREEN + SetWindowPos(window,NULL,lparam*22,lparam*22,0,0,SWP_NOSIZE | SWP_NOZORDER); + + // LOAD THE BACKGROUND BITMAP + { + TCHAR filename[16]; + wsprintf(filename,TEXT("bkg%u.pcx"),(lparam & 3)+1); + int width, height; + LPBYTE backgroundbitmap = LoadBitmap(filename,&width,&height); + if (backgroundbitmap) { + SetProp(window,TEXT("BackgroundBitmap"),(HANDLE)backgroundbitmap); + SDlgSetBitmap(window, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + } + } + + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height) { + if (!SBmpLoadImage(filename,NULL,NULL,0,width,height)) + return NULL; + LPBYTE bitmapbits = (LPBYTE)ALLOC((*width)*(*height)); + if (!bitmapbits) + return NULL; + PALETTEENTRY pe[256]; + if (SBmpLoadImage(filename,&pe[0],bitmapbits,(*width)*(*height))) + SDrawUpdatePalette(10,236,&pe[10]); + return bitmapbits; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE passinstance, HINSTANCE, LPSTR, int) { + instance = passinstance; + if (!SDrawAutoInitialize(instance, + TEXT("DLGEX4"), + TEXT("Dialog Example 4"))) + return 1; + SDlgDialogBoxParam(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + SDrawGetFrameWindow(), + DlgProc, + 0); + return 0; +} diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.CS b/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.EXE b/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.EXE new file mode 100644 index 0000000..0c81ac1 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.EXE differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.RC b/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.RC new file mode 100644 index 0000000..b4aab45 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX4/DLGEX4.RC @@ -0,0 +1,98 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + PUSHBUTTON "&Create...",IDC_BUTTON1,129,41,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SAMPLES/SDLG/DLGEX4/RESOURCE.H b/src/Storm/SAMPLES/SDLG/DLGEX4/RESOURCE.H new file mode 100644 index 0000000..7e6877b --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX4/RESOURCE.H @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by dlgex4.RC +// +#define IDD_DIALOG1 101 +#define IDC_BUTTON1 1000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/BKG1.PCX b/src/Storm/SAMPLES/SDLG/DLGEX5/BKG1.PCX new file mode 100644 index 0000000..539db54 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX5/BKG1.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/BKG2.PCX b/src/Storm/SAMPLES/SDLG/DLGEX5/BKG2.PCX new file mode 100644 index 0000000..37352b0 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX5/BKG2.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/BKG3.PCX b/src/Storm/SAMPLES/SDLG/DLGEX5/BKG3.PCX new file mode 100644 index 0000000..105d203 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX5/BKG3.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/BKG4.PCX b/src/Storm/SAMPLES/SDLG/DLGEX5/BKG4.PCX new file mode 100644 index 0000000..f69bfd2 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX5/BKG4.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.CPP b/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.CPP new file mode 100644 index 0000000..8e2e16a --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.CPP @@ -0,0 +1,134 @@ +/**************************************************************************** +* +* DLGEX5.CPP +* +* Adds button textures. +* +***/ + +#define STRICT +#include +#include +#include "resource.h" + +HINSTANCE instance = (HINSTANCE)0; + +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height); + +//=========================================================================== +BOOL CALLBACK DlgProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + + case IDOK: + SDlgEndDialog(window,1); + break; + + case IDCANCEL: + SDlgEndDialog(window,0); + break; + + case IDC_BUTTON1: + SDlgDialogBoxParam(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + window, + DlgProc, + (LPARAM)GetProp(window,TEXT("RecursionDepth"))+1); + break; + + } + break; + + case WM_DESTROY: + if (GetProp(window,TEXT("BackgroundBitmap"))) + FREE((LPVOID)GetProp(window,TEXT("BackgroundBitmap"))); + break; + + case WM_INITDIALOG: + + // SAVE THE RECURSION DEPTH + SetProp(window,TEXT("RecursionDepth"),(HANDLE)lparam); + + // POSITION THE DIALOG BOX ON THE SCREEN + SetWindowPos(window,NULL,lparam*22,lparam*22,0,0,SWP_NOSIZE | SWP_NOZORDER); + + // LOAD THE BACKGROUND BITMAP + { + TCHAR filename[16]; + wsprintf(filename,TEXT("bkg%u.pcx"),(lparam & 3)+1); + int width, height; + LPBYTE backgroundbitmap = LoadBitmap(filename,&width,&height); + if (backgroundbitmap) { + SetProp(window,TEXT("BackgroundBitmap"),(HANDLE)backgroundbitmap); + SDlgSetBitmap(window, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + SDlgSetBitmap(NULL, + window, + TEXT("Button"), + SDLG_STYLE_ANYPUSHBUTTON, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + } + } + + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height) { + if (!SBmpLoadImage(filename,NULL,NULL,0,width,height)) + return NULL; + LPBYTE bitmapbits = (LPBYTE)ALLOC((*width)*(*height)); + if (!bitmapbits) + return NULL; + PALETTEENTRY pe[256]; + if (SBmpLoadImage(filename,&pe[0],bitmapbits,(*width)*(*height))) + SDrawUpdatePalette(10,236,&pe[10]); + return bitmapbits; +} + +//=========================================================================== +void CALLBACK OnEraseBkgnd (LPPARAMS params) { + params->useresult = 1; + params->result = 0; +} + +//=========================================================================== +void CALLBACK OnPaint (LPPARAMS params) { + PAINTSTRUCT ps; + HDC dc = SDlgBeginPaint(params->window,&ps); + SDlgEndPaint(params->window,&ps); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE passinstance, HINSTANCE, LPSTR, int) { + instance = passinstance; + if (!SDrawAutoInitialize(instance, + TEXT("DLGEX5"), + TEXT("Dialog Example 5"))) + return 1; + SDlgDialogBoxParam(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + SDrawGetFrameWindow(), + DlgProc, + 0); + return 0; +} diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.CS b/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.EXE b/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.EXE new file mode 100644 index 0000000..994a381 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.EXE differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.RC b/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.RC new file mode 100644 index 0000000..b4aab45 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX5/DLGEX5.RC @@ -0,0 +1,98 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + PUSHBUTTON "&Create...",IDC_BUTTON1,129,41,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SAMPLES/SDLG/DLGEX5/RESOURCE.H b/src/Storm/SAMPLES/SDLG/DLGEX5/RESOURCE.H new file mode 100644 index 0000000..342aec3 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX5/RESOURCE.H @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by dlgex5.RC +// +#define IDD_DIALOG1 101 +#define IDC_BUTTON1 1000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/BKG.PCX b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG.PCX new file mode 100644 index 0000000..01568e3 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/BKG1.PCX b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG1.PCX new file mode 100644 index 0000000..539db54 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG1.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/BKG2.PCX b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG2.PCX new file mode 100644 index 0000000..37352b0 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG2.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/BKG3.PCX b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG3.PCX new file mode 100644 index 0000000..105d203 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG3.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/BKG4.PCX b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG4.PCX new file mode 100644 index 0000000..f69bfd2 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX6/BKG4.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.CPP b/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.CPP new file mode 100644 index 0000000..a746298 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.CPP @@ -0,0 +1,154 @@ +/**************************************************************************** +* +* DLGEX6.CPP +* +* Demonstrates the use of a background bitmap. +* +***/ + +#define STRICT +#include +#include +#include "resource.h" + +HINSTANCE instance = (HINSTANCE)0; + +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height); + +//=========================================================================== +BOOL CALLBACK DlgProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + + case IDOK: + SDlgEndDialog(window,1); + break; + + case IDCANCEL: + SDlgEndDialog(window,0); + break; + + case IDC_BUTTON1: +Sleep(1000); + SDlgDialogBoxParam(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + window, + DlgProc, + (LPARAM)GetProp(window,TEXT("RecursionDepth"))+1); + break; + + } + break; + + case WM_DESTROY: + if (GetProp(window,TEXT("BackgroundBitmap"))) + FREE((LPVOID)GetProp(window,TEXT("BackgroundBitmap"))); + break; + + case WM_INITDIALOG: + + // SAVE THE RECURSION DEPTH + SetProp(window,TEXT("RecursionDepth"),(HANDLE)lparam); + + // POSITION THE DIALOG BOX ON THE SCREEN + SetWindowPos(window,NULL,lparam*22,lparam*22,0,0,SWP_NOSIZE | SWP_NOZORDER); + + // LOAD THE BACKGROUND BITMAP + { + TCHAR filename[16]; + wsprintf(filename,TEXT("bkg%u.pcx"),(lparam & 3)+1); + int width, height; + LPBYTE backgroundbitmap = LoadBitmap(filename,&width,&height); + if (backgroundbitmap) { + SetProp(window,TEXT("BackgroundBitmap"),(HANDLE)backgroundbitmap); + SDlgSetBitmap(window, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + SDlgSetBitmap(NULL, + window, + TEXT("Button"), + SDLG_STYLE_ANYPUSHBUTTON, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + } + } + + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height) { + if (!SBmpLoadImage(filename,NULL,NULL,0,width,height)) + return NULL; + LPBYTE bitmapbits = (LPBYTE)ALLOC((*width)*(*height)); + if (!bitmapbits) + return NULL; + PALETTEENTRY pe[256]; + if (SBmpLoadImage(filename,&pe[0],bitmapbits,(*width)*(*height))) + SDrawUpdatePalette(10,236,&pe[10]); + return bitmapbits; +} + +//=========================================================================== +void CALLBACK OnEraseBkgnd (LPPARAMS params) { + params->useresult = 1; + params->result = 0; +} + +//=========================================================================== +void CALLBACK OnPaint (LPPARAMS params) { + PAINTSTRUCT ps; + HDC dc = SDlgBeginPaint(params->window,&ps); + SDlgEndPaint(params->window,&ps); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE passinstance, HINSTANCE, LPSTR, int) { + instance = passinstance; + if (!SDrawAutoInitialize(instance, + TEXT("DLGEX6"), + TEXT("Dialog Example 6"))) + return 1; + { + int width, height; + LPBYTE backgroundbitmap = LoadBitmap(TEXT("bkg.pcx"),&width,&height); + if (backgroundbitmap) { + SMsgRegisterMessage(NULL,WM_ERASEBKGND,OnEraseBkgnd); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SDlgSetBitmap(SDrawGetFrameWindow(), + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + } + SDlgDialogBoxParam(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + SDrawGetFrameWindow(), + DlgProc, + 0); + if (backgroundbitmap) + FREE(backgroundbitmap); + } + return 0; +} diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.CS b/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.EXE b/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.EXE new file mode 100644 index 0000000..83784bf Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.EXE differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.RC b/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.RC new file mode 100644 index 0000000..b4aab45 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX6/DLGEX6.RC @@ -0,0 +1,98 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + PUSHBUTTON "&Create...",IDC_BUTTON1,129,41,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SAMPLES/SDLG/DLGEX6/RESOURCE.H b/src/Storm/SAMPLES/SDLG/DLGEX6/RESOURCE.H new file mode 100644 index 0000000..9921dd2 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX6/RESOURCE.H @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by dlgex6.RC +// +#define IDD_DIALOG1 101 +#define IDC_BUTTON1 1000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/BKG.PCX b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG.PCX new file mode 100644 index 0000000..01568e3 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/BKG1.PCX b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG1.PCX new file mode 100644 index 0000000..539db54 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG1.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/BKG2.PCX b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG2.PCX new file mode 100644 index 0000000..37352b0 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG2.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/BKG3.PCX b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG3.PCX new file mode 100644 index 0000000..105d203 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG3.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/BKG4.PCX b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG4.PCX new file mode 100644 index 0000000..f69bfd2 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/BKG4.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/CIMAGE.BMP b/src/Storm/SAMPLES/SDLG/DLGEX7/CIMAGE.BMP new file mode 100644 index 0000000..b4d02b6 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/CIMAGE.BMP differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/CIMAGE.PCX b/src/Storm/SAMPLES/SDLG/DLGEX7/CIMAGE.PCX new file mode 100644 index 0000000..7db4b97 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/CIMAGE.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/CMASK.BMP b/src/Storm/SAMPLES/SDLG/DLGEX7/CMASK.BMP new file mode 100644 index 0000000..23c7b10 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/CMASK.BMP differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/CMASK.PCX b/src/Storm/SAMPLES/SDLG/DLGEX7/CMASK.PCX new file mode 100644 index 0000000..f0ced17 Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/CMASK.PCX differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.CPP b/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.CPP new file mode 100644 index 0000000..ad5cf0f --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.CPP @@ -0,0 +1,163 @@ +/**************************************************************************** +* +* DLGEX7.CPP +* +* Demonstrates the use of a cursor. +* +***/ + +#define STRICT +#include +#include +#include "resource.h" + +HINSTANCE instance = (HINSTANCE)0; + +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height); + +//=========================================================================== +BOOL CALLBACK DlgProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + + case IDOK: + SDlgEndDialog(window,1); + break; + + case IDCANCEL: + SDlgEndDialog(window,0); + break; + + case IDC_BUTTON1: + SDlgDialogBoxParam(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + window, + DlgProc, + (LPARAM)GetProp(window,TEXT("RecursionDepth"))+1); + break; + + } + break; + + case WM_DESTROY: + if (GetProp(window,TEXT("BackgroundBitmap"))) + FREE((LPVOID)GetProp(window,TEXT("BackgroundBitmap"))); + break; + + case WM_INITDIALOG: + + // SAVE THE RECURSION DEPTH + SetProp(window,TEXT("RecursionDepth"),(HANDLE)lparam); + + // POSITION THE DIALOG BOX ON THE SCREEN + SetWindowPos(window,NULL,lparam*22,lparam*22,0,0,SWP_NOSIZE | SWP_NOZORDER); + + // LOAD THE BACKGROUND BITMAP + { + TCHAR filename[16]; + wsprintf(filename,TEXT("bkg%u.pcx"),(lparam & 3)+1); + int width, height; + LPBYTE backgroundbitmap = LoadBitmap(filename,&width,&height); + if (backgroundbitmap) { + SetProp(window,TEXT("BackgroundBitmap"),(HANDLE)backgroundbitmap); + SDlgSetBitmap(window, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + SDlgSetBitmap(NULL, + window, + TEXT("Button"), + SDLG_STYLE_ANYPUSHBUTTON, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + } + } + + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +LPBYTE LoadBitmap (LPCTSTR filename, int *width, int *height) { + if (!SBmpLoadImage(filename,NULL,NULL,0,width,height)) + return NULL; + LPBYTE bitmapbits = (LPBYTE)ALLOC((*width)*(*height)); + if (!bitmapbits) + return NULL; + PALETTEENTRY pe[256]; + if (SBmpLoadImage(filename,&pe[0],bitmapbits,(*width)*(*height))) + SDrawUpdatePalette(10,236,&pe[10]); + return bitmapbits; +} + +//=========================================================================== +void CALLBACK OnEraseBkgnd (LPPARAMS params) { + params->useresult = 1; + params->result = 0; +} + +//=========================================================================== +void CALLBACK OnPaint (LPPARAMS params) { + PAINTSTRUCT ps; + HDC dc = SDlgBeginPaint(params->window,&ps); + SDlgEndPaint(params->window,&ps); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE passinstance, HINSTANCE, LPSTR, int) { + instance = passinstance; + if (!SDrawAutoInitialize(instance, + TEXT("DLGEX7"), + TEXT("Dialog Example 7"))) + return 1; + ShowCursor(0); + { + int width, height; + LPBYTE backgroundbitmap = LoadBitmap(TEXT("bkg.pcx"),&width,&height); + if (backgroundbitmap) { + SMsgRegisterMessage(NULL,WM_ERASEBKGND,OnEraseBkgnd); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SDlgSetBitmap(SDrawGetFrameWindow(), + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + backgroundbitmap, + NULL, + width, + height); + } + SIZE cursorsize; + LPBYTE maskbitmap = LoadBitmap(TEXT("cmask.bmp") ,(int *)&cursorsize.cx,(int *)&cursorsize.cy); + LPBYTE imagebitmap = LoadBitmap(TEXT("cimage.bmp"),(int *)&cursorsize.cx,(int *)&cursorsize.cy); + SDlgSetSystemCursor(maskbitmap,imagebitmap,&cursorsize); + SDlgDialogBoxParam(instance, + MAKEINTRESOURCE(IDD_DIALOG1), + SDrawGetFrameWindow(), + DlgProc, + 0); + if (backgroundbitmap) + FREE(backgroundbitmap); + if (maskbitmap) + FREE(maskbitmap); + if (imagebitmap) + FREE(imagebitmap); + } + ShowCursor(1); + return 0; +} diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.CS b/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.EXE b/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.EXE new file mode 100644 index 0000000..d3e150d Binary files /dev/null and b/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.EXE differ diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.RC b/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.RC new file mode 100644 index 0000000..b4aab45 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX7/DLGEX7.RC @@ -0,0 +1,98 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 + PUSHBUTTON "&Create...",IDC_BUTTON1,129,41,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SAMPLES/SDLG/DLGEX7/RESOURCE.H b/src/Storm/SAMPLES/SDLG/DLGEX7/RESOURCE.H new file mode 100644 index 0000000..9921dd2 --- /dev/null +++ b/src/Storm/SAMPLES/SDLG/DLGEX7/RESOURCE.H @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by dlgex6.RC +// +#define IDD_DIALOG1 101 +#define IDC_BUTTON1 1000 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.CPP b/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.CPP new file mode 100644 index 0000000..41f7b91 --- /dev/null +++ b/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.CPP @@ -0,0 +1,63 @@ +/**************************************************************************** +* +* DDEX1.CPP +* +* This simple DirectDraw application loads a bitmap and draws it on the +* screen. +* +***/ + +#include +#include + +LPBYTE backgroundbitmap = NULL; +int backgroundwidth = 0; +int backgroundheight = 0; + +//=========================================================================== +BOOL LoadBackgroundBitmap () { + if (!SBmpLoadImage("..\\demodata\\flag.pcx",NULL,NULL,NULL,&backgroundwidth,&backgroundheight)) + return 0; + backgroundbitmap = (LPBYTE)ALLOC(backgroundwidth*backgroundheight); + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\flag.pcx",&pe[0],backgroundbitmap,backgroundwidth*backgroundheight)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS) { + FREE(backgroundbitmap); +} + +//=========================================================================== +void CALLBACK OnPaint (LPPARAMS) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + SGdiRectangle(videobuffer,0,0,639,479,PALETTEINDEX(255)); + SGdiBitBlt(videobuffer,0,0,backgroundbitmap,NULL,backgroundwidth,backgroundheight); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DDEX1"), + TEXT("DirectDraw Example 1"))) + FATALRESULT("SDrawAutoInitialize"); + if (!LoadBackgroundBitmap()) + FATALRESULT("LoadBackgroundBitmap"); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(NULL); +} diff --git a/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.CS b/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.EXE b/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.EXE new file mode 100644 index 0000000..9b2b3e8 Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DDEX1/DDEX1.EXE differ diff --git a/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.CPP b/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.CPP new file mode 100644 index 0000000..8b55eca --- /dev/null +++ b/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.CPP @@ -0,0 +1,67 @@ +/**************************************************************************** +* +* DDEX2.CPP +* +* This sample application loads a bitmap and repeatedly tiles it onto the +* screen, changing the tiling offset each frame. +* +***/ + +#include +#include + +LPBYTE backgroundbitmap = NULL; +int backgroundwidth = 0; +int backgroundheight = 0; +int tilingoffset = 0; + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + RECT destrect = {0,0,639,479}; + RECT sourcerect = {0,0,backgroundwidth-1,backgroundheight-1}; + SBltROP3Tiled(videobuffer,&destrect,pitch, + backgroundbitmap,&sourcerect,backgroundwidth, + tilingoffset,tilingoffset,0,SRCCOPY); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + tilingoffset += 4; + return 1; +} + +//=========================================================================== +BOOL LoadBackgroundBitmap () { + if (!SBmpLoadImage("..\\demodata\\flag.pcx",NULL,NULL,NULL,&backgroundwidth,&backgroundheight)) + return 0; + backgroundbitmap = (LPBYTE)ALLOC(backgroundwidth*backgroundheight); + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\flag.pcx",&pe[0],backgroundbitmap,backgroundwidth*backgroundheight)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS) { + FREE(backgroundbitmap); +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DDEX2"), + TEXT("DirectDraw Example 2"))) + FATALRESULT("SDrawAutoInitialize"); + if (!LoadBackgroundBitmap()) + FATALRESULT("LoadBackgroundBitmap"); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.CS b/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.EXE b/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.EXE new file mode 100644 index 0000000..1f5c71d Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DDEX2/DDEX2.EXE differ diff --git a/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.CPP b/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.CPP new file mode 100644 index 0000000..322dfa1 --- /dev/null +++ b/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.CPP @@ -0,0 +1,119 @@ +/**************************************************************************** +* +* DDEX3.CPP +* +* This sample application demonstrates the use of transparent bitmaps. +* For each frame, the application performs the following steps: +* +* 1. Draws the background on an offscreen video page +* 2. Overlays transparent bitmaps onto the background +* 3. Flips the video page +* +* The use of page flipping prevents tearing. +* +***/ + +#include +#include +#include + +#define SPRITES 4 + +#define SIN(a) sintable[((a) & 255)] +#define COS(a) sintable[(((a)+64) & 255)] + +LPBYTE backgroundbitmap = NULL; +int backgroundwidth = 0; +int backgroundheight = 0; +BYTE rotation = 0; +int sintable[256]; +HSTRANS sprite[SPRITES] = {0,0,0,0}; +int tilingoffset = 0; + +//=========================================================================== +void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + sintable[loop] = (int)(sin(angle)*128); + } +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_BACK,NULL,&videobuffer,&pitch)) { + RECT destrect = {0,0,639,479}; + RECT sourcerect = {0,0,backgroundwidth-1,backgroundheight-1}; + SBltROP3Tiled(videobuffer,&destrect,pitch, + backgroundbitmap,&sourcerect,backgroundwidth, + tilingoffset,tilingoffset,0,SRCCOPY); + for (int loop = 0; loop < SPRITES; ++loop) + STransBlt(videobuffer, + 170+SIN(rotation+64*loop), + 165+COS(rotation+64*loop), + pitch, + sprite[loop]); + SDrawUnlockSurface(SDRAW_SURFACE_BACK,videobuffer); + SDrawFlipPage(); + } + rotation += 3; + tilingoffset += 8; + return 1; +} + +//=========================================================================== +BOOL LoadBackgroundBitmap () { + if (!SBmpLoadImage("..\\demodata\\flag.pcx",NULL,NULL,NULL,&backgroundwidth,&backgroundheight)) + return 0; + backgroundbitmap = (LPBYTE)ALLOC(backgroundwidth*backgroundheight); + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\flag.pcx",&pe[0],backgroundbitmap,backgroundwidth*backgroundheight)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +BOOL LoadSprites () { + LPBYTE temp = (LPBYTE)ALLOC(300*500); + if (!SBmpLoadImage("..\\demodata\\sprites.pcx",NULL,temp,300*500)) + return 0; + for (int loop = 0; loop < SPRITES; ++loop) { + RECT rect = {0,loop*125,299,loop*125+124}; + if (!STransCreate(temp,300,500,8,&rect,PALETTEINDEX(*temp),&sprite[loop])) + return 0; + } + FREE(temp); + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS) { + FREE(backgroundbitmap); + for (int loop = 0; loop < SPRITES; ++loop) + STransDelete(sprite[loop]); +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + CreateSinTable(); + if (!SDrawAutoInitialize(instance, + TEXT("DDEX3"), + TEXT("DirectDraw Example 3"), + NULL, + SDRAW_SERVICE_PAGEFLIP)) + FATALRESULT("SDrawAutoInitialize"); + if (!LoadBackgroundBitmap()) + FATALRESULT("LoadBackgroundBitmap"); + if (!LoadSprites()) + FATALRESULT("LoadSprites"); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.CS b/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.EXE b/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.EXE new file mode 100644 index 0000000..ccde142 Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DDEX3/DDEX3.EXE differ diff --git a/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.CPP b/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.CPP new file mode 100644 index 0000000..107bdd6 --- /dev/null +++ b/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.CPP @@ -0,0 +1,116 @@ +/**************************************************************************** +* +* DDEX4.CPP +* +* This sample application produces the same output as DDEX3, but it goes +* about it a different way. Instead of drawing to an offscreen page and +* then page flipping, it draws into system memory and the blts the entire +* screen at once onto video memory. This allows it to work on video cards +* that don't support page flipping in high-res mode. +* +***/ + +#include +#include +#include + +#define SPRITES 4 + +#define SIN(a) sintable[((a) & 255)] +#define COS(a) sintable[(((a)+64) & 255)] + +LPBYTE backgroundbitmap = NULL; +int backgroundwidth = 0; +int backgroundheight = 0; +BYTE rotation = 0; +int sintable[256]; +HSTRANS sprite[SPRITES] = {0,0,0,0}; +int tilingoffset = 0; + +//=========================================================================== +void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + sintable[loop] = (int)(sin(angle)*128); + } +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + LPBYTE systembuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_SYSTEM,NULL,&systembuffer,&pitch)) { + RECT destrect = {0,0,639,479}; + RECT sourcerect = {0,0,backgroundwidth-1,backgroundheight-1}; + SBltROP3Tiled(systembuffer,&destrect,pitch, + backgroundbitmap,&sourcerect,backgroundwidth, + tilingoffset,tilingoffset,0,SRCCOPY); + for (int loop = 0; loop < SPRITES; ++loop) + STransBlt(systembuffer, + 170+SIN(rotation+64*loop), + 165+COS(rotation+64*loop), + pitch, + sprite[loop]); + SDrawUnlockSurface(SDRAW_SURFACE_SYSTEM,systembuffer); + SDrawUpdateScreen(NULL); + } + rotation += 3; + tilingoffset += 8; + return 1; +} + +//=========================================================================== +BOOL LoadBackgroundBitmap () { + if (!SBmpLoadImage("..\\demodata\\flag.pcx",NULL,NULL,NULL,&backgroundwidth,&backgroundheight)) + return 0; + backgroundbitmap = (LPBYTE)ALLOC(backgroundwidth*backgroundheight); + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("..\\demodata\\flag.pcx",&pe[0],backgroundbitmap,backgroundwidth*backgroundheight)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + return 1; +} + +//=========================================================================== +BOOL LoadSprites () { + LPBYTE temp = (LPBYTE)ALLOC(300*500); + if (!SBmpLoadImage("..\\demodata\\sprites.pcx",NULL,temp,300*500)) + return 0; + for (int loop = 0; loop < SPRITES; ++loop) { + RECT rect = {0,loop*125,299,loop*125+124}; + if (!STransCreate(temp,300,500,8,&rect,PALETTEINDEX(*temp),&sprite[loop])) + return 0; + } + FREE(temp); + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS) { + FREE(backgroundbitmap); + for (int loop = 0; loop < SPRITES; ++loop) + STransDelete(sprite[loop]); +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + CreateSinTable(); + if (!SDrawAutoInitialize(instance, + TEXT("DDEX4"), + TEXT("DirectDraw Example 4"), + NULL, + SDRAW_SERVICE_DOUBLEBUFFER)) + FATALRESULT("SDrawAutoInitialize"); + if (!LoadBackgroundBitmap()) + FATALRESULT("LoadBackgroundBitmap"); + if (!LoadSprites()) + FATALRESULT("LoadSprites"); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.CS b/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.EXE b/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.EXE new file mode 100644 index 0000000..91dc91d Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DDEX4/DDEX4.EXE differ diff --git a/src/Storm/SAMPLES/SDRAW/DEMODATA/BKG.PCX b/src/Storm/SAMPLES/SDRAW/DEMODATA/BKG.PCX new file mode 100644 index 0000000..d24cdf1 Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DEMODATA/BKG.PCX differ diff --git a/src/Storm/SAMPLES/SDRAW/DEMODATA/FLAG.PCX b/src/Storm/SAMPLES/SDRAW/DEMODATA/FLAG.PCX new file mode 100644 index 0000000..c83f1b4 Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DEMODATA/FLAG.PCX differ diff --git a/src/Storm/SAMPLES/SDRAW/DEMODATA/OVERLAY.PCX b/src/Storm/SAMPLES/SDRAW/DEMODATA/OVERLAY.PCX new file mode 100644 index 0000000..e9a3e67 Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DEMODATA/OVERLAY.PCX differ diff --git a/src/Storm/SAMPLES/SDRAW/DEMODATA/SHIPS.PCX b/src/Storm/SAMPLES/SDRAW/DEMODATA/SHIPS.PCX new file mode 100644 index 0000000..3fc7727 Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DEMODATA/SHIPS.PCX differ diff --git a/src/Storm/SAMPLES/SDRAW/DEMODATA/SPRITES.PCX b/src/Storm/SAMPLES/SDRAW/DEMODATA/SPRITES.PCX new file mode 100644 index 0000000..f9dc3e2 Binary files /dev/null and b/src/Storm/SAMPLES/SDRAW/DEMODATA/SPRITES.PCX differ diff --git a/src/Storm/SAMPLES/SFILE/DDATEST/CDROM.PCX b/src/Storm/SAMPLES/SFILE/DDATEST/CDROM.PCX new file mode 100644 index 0000000..796c571 Binary files /dev/null and b/src/Storm/SAMPLES/SFILE/DDATEST/CDROM.PCX differ diff --git a/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.CPP b/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.CPP new file mode 100644 index 0000000..6380e30 --- /dev/null +++ b/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.CPP @@ -0,0 +1,250 @@ +/**************************************************************************** +* +* DDATEST.CPP +* +* This sample program demonstrates the use of direct digital audio streaming +* from a CD. +* +***/ + +#include +#include +#include + +#define ARCHIVE "e:\\diabdat.mpq" +#define SONGS 6 +#define TITLE "DDA Test" + +static const LPCSTR songname[SONGS] = {"sfx\\towners\\drunk25.wav", + "sfx\\towners\\witch40.wav", + "sfx\\towners\\bsmith47.wav", + "sfx\\towners\\healer39.wav", + "sfx\\towners\\wound01.wav", + "sfx\\towners\\deadguy2.wav"}; + +HSARCHIVE archive = (HSARCHIVE)0; +DWORD currsong = SONGS-1; +HSGDIFONT font = (HSGDIFONT)0; +DWORD iterations = 0; +LPDIRECTSOUND lpds = NULL; +HSFILE soundfile[SONGS] = {0}; +HSTRANS transparency = (HSTRANS)0; + +//=========================================================================== +BOOL LoadTransparency () { + LPBYTE bitmap = (LPBYTE)ALLOC(32*32); + if (!bitmap) + return 0; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("cdrom.pcx",&pe[0],bitmap,32*32)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + STransCreate(bitmap,32,32,8,NULL,PALETTEINDEX(*bitmap),&transparency); + FREE(bitmap); + return 1; +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 640)-20; + int top = (rand() % 420)+30; +#ifdef ALIGNED + left = (left >> 2) << 2; +#endif + STransBlt(videobuffer,left,top,pitch,transparency); + ++iterations; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +BOOL InitializeDirectSound () { + + // CREATE A DIRECTSOUND OBJECT + DirectSoundCreate(NULL,&lpds,NULL); + if (!lpds) + return 0; + + // CREATE A PRIMARY BUFFER + LPDIRECTSOUNDBUFFER primarybuffer = NULL; + { + DSBUFFERDESC desc; + ZeroMemory(&desc,sizeof(DSBUFFERDESC)); + desc.dwSize = sizeof(DSBUFFERDESC); + desc.dwFlags = DSBCAPS_PRIMARYBUFFER; + lpds->CreateSoundBuffer(&desc,&primarybuffer,NULL); + } + if (!primarybuffer) + return 0; + + // START PLAYING THE PRIMARY BUFFER + if (lpds->SetCooperativeLevel(SDrawGetFrameWindow(),DSSCL_EXCLUSIVE) != DS_OK) + return 0; + if (primarybuffer->Play(0,0,DSBPLAY_LOOPING) != DS_OK) + return 0; + + // GIVE OUR DIRECTSOUND POINTER TO STORM + SFileDdaInitialize(lpds); + + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + KillTimer(params->window,1); + SGdiDeleteObject(font); + STransDelete(transparency); + SFileCloseArchive(archive); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + + { + char outstr[64]; + wsprintf(outstr,"%u transparent bitblts per second",iterations); + RECT rect = {0,0,320,15}; + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + } + + if (soundfile[currsong]) { + DWORD position; + DWORD maxposition; + char outstr[64] = ""; + if (SFileDdaGetPos(soundfile[currsong],&position,&maxposition)) + wsprintf(outstr,"%u%% complete",position*100/maxposition); + RECT rect = {320,0,639,15}; + SGdiExtTextOut(videobuffer, + 320, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + } + + SGdiTextOut(videobuffer, 0,10,PALETTEINDEX(255),"[S] Start DDA playback"); + SGdiTextOut(videobuffer, 0,20,PALETTEINDEX(255),"[X] Terminate DDA playback"); + SGdiTextOut(videobuffer,320,10,PALETTEINDEX(255),"[L] Left [C] Center [R] Right"); + SGdiTextOut(videobuffer,320,20,PALETTEINDEX(255),"[Q] Toggle Quiet Mode"); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + iterations = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkC (LPPARAMS) { + SFileDdaSetVolume(soundfile[currsong],0x7FFFFFFF,0); +} + +//=========================================================================== +void CALLBACK OnVkL (LPPARAMS) { + SFileDdaSetVolume(soundfile[currsong],0x7FFFFFFF,10000); +} + +//=========================================================================== +void CALLBACK OnVkQ (LPPARAMS) { + LONG volume; + SFileDdaGetVolume(soundfile[currsong],&volume,NULL); + SFileDdaSetVolume(soundfile[currsong],volume ? 0 : -2000,0x7FFFFFFF); +} + +//=========================================================================== +void CALLBACK OnVkR (LPPARAMS) { + SFileDdaSetVolume(soundfile[currsong],0x7FFFFFFF,-10000); +} + +//=========================================================================== +void CALLBACK OnVkS (LPPARAMS) { + currsong = (currsong+1) % SONGS; + if (!soundfile[currsong]) + SFileOpenFile(songname[currsong],&soundfile[currsong]); + if (soundfile[currsong]) + if (!SFileDdaBegin(soundfile[currsong],0x40000,0)) { + SFileCloseFile(soundfile[currsong]); + soundfile[currsong] = (HSFILE)0; + } +} + + +//=========================================================================== +void CALLBACK OnVkX (LPPARAMS) { + if (soundfile[currsong]) + SFileDdaEnd(soundfile[currsong]); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DDATEST"), + TITLE)) { + SDrawMessageBox("Unable to initialize DirectDraw.",TITLE,0); + return 1; + } + if (!InitializeDirectSound()) { + SDrawMessageBox("Unable to initialize DirectSound.",TITLE,0); + return 1; + } + if (!SFileOpenArchive(ARCHIVE,0,0,&archive)) { + SDrawMessageBox("Unable to open MPQ data file.",TITLE,0); + return 0; + } + SFileEnableDirectAccess(1); + if (!LoadTransparency()) { + SDrawMessageBox("Unable to load transparency.",TITLE,0); + return 1; + } + if (!LoadFont()) { + SDrawMessageBox("Unable to load font.",TITLE,0); + return 1; + } + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,'C' ,OnVkC); + SMsgRegisterKeyDown(NULL,'L' ,OnVkL); + SMsgRegisterKeyDown(NULL,'Q' ,OnVkQ); + SMsgRegisterKeyDown(NULL,'R' ,OnVkR); + SMsgRegisterKeyDown(NULL,'S' ,OnVkS); + SMsgRegisterKeyDown(NULL,'X' ,OnVkX); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.CS b/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.CS new file mode 100644 index 0000000..cbe1fed --- /dev/null +++ b/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set extralib=%extralib% dsound.lib diff --git a/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.EXE b/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.EXE new file mode 100644 index 0000000..2a34b84 Binary files /dev/null and b/src/Storm/SAMPLES/SFILE/DDATEST/DDATEST.EXE differ diff --git a/src/Storm/SAMPLES/SGDI/RECT/RECT.CPP b/src/Storm/SAMPLES/SGDI/RECT/RECT.CPP new file mode 100644 index 0000000..3104f15 --- /dev/null +++ b/src/Storm/SAMPLES/SGDI/RECT/RECT.CPP @@ -0,0 +1,110 @@ +/**************************************************************************** +* +* RECT.CPP +* +* Benchmarks Storm's pattern blt performance. +* +***/ + +#include +#include + +#define ALIGNED + +HSGDIFONT font = (HSGDIFONT)0; +BOOL paused = 0; +DWORD iterations = 0; + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (paused) + return 0; + + static BYTE color = 0; + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 640)-20; + int top = (rand() % 450)+12; +#ifdef ALIGNED + left = (left >> 2) << 2; +#endif + SGdiSetPitch(pitch); + SGdiRectangle(videobuffer,left,top,left+40,top+40,PALETTEINDEX(color)); + ++color; + ++iterations; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + KillTimer(params->window,1); + SGdiDeleteObject(font); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + char outstr[64]; + wsprintf(outstr,"%u rectangles per second",iterations); + RECT rect = {0,0,320,12}; + SGdiSetPitch(pitch); + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + iterations = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DDBENCH"), + TEXT("Benchmark"))) + return 1; + if (!LoadFont()) + return 1; + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SGDI/RECT/RECT.CS b/src/Storm/SAMPLES/SGDI/RECT/RECT.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SGDI/RECT/RECT.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SGDI/RECT/RECT.EXE b/src/Storm/SAMPLES/SGDI/RECT/RECT.EXE new file mode 100644 index 0000000..2ed0cac Binary files /dev/null and b/src/Storm/SAMPLES/SGDI/RECT/RECT.EXE differ diff --git a/src/Storm/SAMPLES/SNET/CHAT/CHAT.CPP b/src/Storm/SAMPLES/SNET/CHAT/CHAT.CPP new file mode 100644 index 0000000..24431e3 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/CHAT/CHAT.CPP @@ -0,0 +1,258 @@ +/**************************************************************************** +* +* CHAT.CPP +* +* This is a simple chat program which uses Storm's networking. +* It demonstrates enumerating and selecting a network service provider, +* enumerating and selecting a game, asynchronous messaging, and event +* handlers. +* +***/ + +#include +#include +#include +#include + +#define TITLE "Chat" +#define PROGRAMID 'Chat' +#define VERSIONID 1 +#define MAXPLAYERS 16 + +typedef struct _GAME { + int number; + DWORD id; + char name[SNET_MAXNAMELENGTH]; + _GAME *next; +} GAME, *GAMEPTR; + +typedef struct _PROVIDER { + int number; + DWORD id; + _PROVIDER *next; +} PROVIDER, *PROVIDERPTR; + +GAMEPTR gamehead = NULL; +int games = 0; +char playername[SNET_MAXNAMELENGTH] = ""; +char playerdesc[SNET_MAXDESCLENGTH] = ""; +PROVIDERPTR providerhead = NULL; +int providers = 0; + +//=========================================================================== +void Chat () { + printf("Press escape to exit.\n\n"); + for (;;) { + if (_kbhit()) { + char ch = _getch(); + if (ch == 27) + return; + SNetSendMessage(SNET_BROADCASTPLAYERID,&ch,sizeof(char)); + } + LPVOID data = NULL; + DWORD databytes = 0; + if (SNetReceiveMessage(NULL,&data,&databytes)) + if (data && (databytes == sizeof(char))) + if (*(char *)data == 13) + printf("\n"); + else + printf("%c",*(char *)data); + Sleep(1); + } +} + +//=========================================================================== +BOOL CALLBACK EnumGamesCallback (DWORD id, + LPCSTR name, + LPCSTR description) { + + // IF THIS GAME IS ALREADY IN THE LIST, IGNORE IT + GAMEPTR curr = gamehead; + while (curr) + if (curr->id == id) + return 1; + else + curr = curr->next; + + // ADD THE GAME TO THE LIST + GAME game; + game.number = ++games; + game.id = id; + strncpy(game.name,name,SNET_MAXNAMELENGTH); + LISTADDEND(&gamehead,&game); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK EnumProvidersCallback (DWORD id, + LPCSTR description, + LPCSTR requirements, + SNETCAPSPTR caps) { + PROVIDER provider; + provider.number = ++providers; + provider.id = id; + LISTADD(&providerhead,&provider); + printf("[%u] %s\n",providers,description); + return 1; +} + +//=========================================================================== +void GetPlayerName () { + char username[MAX_PATH] = ""; + char computername[MAX_PATH] = ""; + DWORD usernamelength = MAX_PATH; + DWORD computernamelength = MAX_PATH; + GetUserName(username,&usernamelength); + GetComputerName(computername,&computernamelength); + strncpy(playername,username,SNET_MAXNAMELENGTH); + if (usernamelength+computernamelength+14 < SNET_MAXDESCLENGTH) + sprintf(playerdesc,"%s on computer %s",username,computername); +} + +//=========================================================================== +BOOL InitializeProvider (DWORD providerid) { + SNETPROGRAMDATA programdata; + ZeroMemory(&programdata,sizeof(SNETPROGRAMDATA)); + programdata.size = sizeof(SNETPROGRAMDATA); + programdata.programname = TITLE; + programdata.programid = PROGRAMID; + programdata.versionid = VERSIONID; + programdata.maxplayers = MAXPLAYERS; + SNETPLAYERDATA playerdata; + ZeroMemory(&playerdata,sizeof(SNETPLAYERDATA)); + playerdata.size = sizeof(SNETPLAYERDATA); + playerdata.playername = playername; + playerdata.playerdescription = playerdesc; + return SNetInitializeProvider(providerid, + &programdata, + &playerdata, + NULL, + NULL); +} + +//=========================================================================== +void CALLBACK OnPlayerJoin (SNETEVENTPTR event) { + char name[SNET_MAXNAMELENGTH] = ""; + if (SNetGetPlayerName(event->playerid,name,SNET_MAXNAMELENGTH)) + printf("\n%s has entered the room.\n\n",name); +} + +//=========================================================================== +void CALLBACK OnPlayerLeave (SNETEVENTPTR) { + printf("\nSomeone has left the room.\n\n"); +} + +//=========================================================================== +int Select (int lowest, int highest) { + int selection; + do { + printf("Choice: "); + scanf("%u",&selection); + } while ((selection < lowest) || (selection > highest)); + printf("\n"); + return selection; +} + +//=========================================================================== +BOOL SelectGame () { + + // BUILD A LIST OF GAMES + DWORD hintnextcall = 0; + SNetEnumGames(0,0,EnumGamesCallback,&hintnextcall); + + // SLEEP FOR THE HINTED AMOUNT OF TIME TO MAKE SURE THAT THE PROVIDER'S + // LIST OF GAMES IS COMPLETE + Sleep(hintnextcall); + + // UPDATE THE LIST OF GAMES + SNetEnumGames(0,0,EnumGamesCallback,NULL); + + // DISPLAY THE LIST OF GAMES, ALONG WITH A CHOICE TO CREATE A GAME + printf("[0] Create Game\n"); + { + GAMEPTR curr = gamehead; + while (curr) { + printf("[%u] %s\n",curr->id,curr->name); + curr = curr->next; + } + } + + // GET THE SELECTION + int selection = Select(0,games); + + // IF THE USER SELECTED THE CREATE GAME OPTION, THEN CREATE A NEW GAME + // USING THE PLAYER NAME AND DESCRIPTION AS THE GAME NAME AND DESCRIPTION + BOOL success; + DWORD playerid = 0; + if (!selection) + success = SNetCreateGame(playername, + NULL, + playerdesc, + 0, + NULL, + 0, + MAXPLAYERS, + playername, + playerdesc, + &playerid); + + // OTHERWISE, JOIN THE GAME THAT THE USER SELECTED + else { + GAMEPTR curr = gamehead; + while (curr && (curr->number != selection)) + curr = curr->next; + if (curr) + success = SNetJoinGame(curr->id, + NULL, + NULL, + playername, + playerdesc, + &playerid); + } + + // FREE THE LIST OF GAMES + LISTCLEAR(&gamehead); + + return success; +} + +//=========================================================================== +DWORD SelectProvider () { + + // BUILD AND DISPLAY THE LIST OF PROVIDERS + if (!SNetEnumProviders(NULL,EnumProvidersCallback)) + return 0; + + // SELECT A PROVIDER FROM THE LIST + int selection = Select(0,providers); + + // FIND THE PROVIDER'S ID AND FREE THE LIST OF PROVIDERS + DWORD id = 0; + while (providerhead) { + if (providerhead->number == selection) + id = providerhead->id; + LISTFREE(&providerhead,providerhead); + } + + return id; +} + +//=========================================================================== +int __cdecl main () { + GetPlayerName(); + if (!InitializeProvider(SelectProvider())) { + printf("ERROR: Unable to initialize network provider\n"); + return 1; + } + if (!SelectGame()) { + printf("ERROR: Unable to join game\n"); + return 1; + } + SNetRegisterEventHandler(SNET_EVENT_PLAYERJOIN ,OnPlayerJoin); + SNetRegisterEventHandler(SNET_EVENT_PLAYERLEAVE,OnPlayerLeave); + Chat(); + SNetLeaveGame(0); + SNetDestroy(); + return 0; +} diff --git a/src/Storm/SAMPLES/SNET/CHAT/CHAT.CS b/src/Storm/SAMPLES/SNET/CHAT/CHAT.CS new file mode 100644 index 0000000..eb521a7 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/CHAT/CHAT.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set subsystem=console diff --git a/src/Storm/SAMPLES/SNET/CHAT/CHAT.EXE b/src/Storm/SAMPLES/SNET/CHAT/CHAT.EXE new file mode 100644 index 0000000..58eaab7 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/CHAT/CHAT.EXE differ diff --git a/src/Storm/SAMPLES/SNET/JOIN/BKG.PCX b/src/Storm/SAMPLES/SNET/JOIN/BKG.PCX new file mode 100644 index 0000000..fa9417d Binary files /dev/null and b/src/Storm/SAMPLES/SNET/JOIN/BKG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/JOIN/BNAD.PCX b/src/Storm/SAMPLES/SNET/JOIN/BNAD.PCX new file mode 100644 index 0000000..9d13d02 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/JOIN/BNAD.PCX differ diff --git a/src/Storm/SAMPLES/SNET/JOIN/BNBKG.PCX b/src/Storm/SAMPLES/SNET/JOIN/BNBKG.PCX new file mode 100644 index 0000000..5b03842 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/JOIN/BNBKG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/JOIN/BNBUTTON.PCX b/src/Storm/SAMPLES/SNET/JOIN/BNBUTTON.PCX new file mode 100644 index 0000000..8788d73 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/JOIN/BNBUTTON.PCX differ diff --git a/src/Storm/SAMPLES/SNET/JOIN/BNCACHE.DAT b/src/Storm/SAMPLES/SNET/JOIN/BNCACHE.DAT new file mode 100644 index 0000000..91aab1b Binary files /dev/null and b/src/Storm/SAMPLES/SNET/JOIN/BNCACHE.DAT differ diff --git a/src/Storm/SAMPLES/SNET/JOIN/BUTTON.PCX b/src/Storm/SAMPLES/SNET/JOIN/BUTTON.PCX new file mode 100644 index 0000000..86bdb14 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/JOIN/BUTTON.PCX differ diff --git a/src/Storm/SAMPLES/SNET/JOIN/JOIN.CPP b/src/Storm/SAMPLES/SNET/JOIN/JOIN.CPP new file mode 100644 index 0000000..7169bf4 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/JOIN/JOIN.CPP @@ -0,0 +1,100 @@ +/**************************************************************************** +* +* JOIN.CPP +* +* This program demonstrates the SNetUi functions used for selecting a +* network provider and joining a game. +* +***/ + +#include +#include + +#define TITLE "SNetUi Sample Program" +#define PROGRAMID 'Join' +#define VERSIONID 1 +#define MAXPLAYERS 8 + +//=========================================================================== +BOOL CALLBACK ArtCallback (DWORD providerid, + DWORD artid, + LPPALETTEENTRY pe, + LPBYTE buffer, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + char filename[MAX_PATH] = ""; + if (providerid == 'BTLN') + switch (artid) { + case SNET_ART_BACKGROUND: strcpy(filename,"bnbkg.pcx" ); break; + case SNET_ART_BUTTONTEXTURE: strcpy(filename,"bnbutton.pcx"); break; + } + else + switch (artid) { + case SNET_ART_BACKGROUND: strcpy(filename,"bkg.pcx" ); break; + case SNET_ART_BUTTONTEXTURE: strcpy(filename,"button.pcx" ); break; + } + if (filename[0]) + return SBmpLoadImage(filename,pe,buffer,buffersize,width,height,bitdepth); + else + return 0; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR cmdline, int) { + + // INITIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TITLE, + TITLE)) + return 1; + + // BUILD A PROGRAM DATA STRUCTURE + SNETPROGRAMDATA programdata; + ZeroMemory(&programdata,sizeof(SNETPROGRAMDATA)); + programdata.size = sizeof(SNETPROGRAMDATA); + programdata.programname = TITLE; + programdata.programid = PROGRAMID; + programdata.versionid = VERSIONID; + programdata.maxplayers = MAXPLAYERS; + + // BUILD A PLAYER DATA STRUCTURE + SNETPLAYERDATA playerdata; + ZeroMemory(&playerdata,sizeof(SNETPLAYERDATA)); + playerdata.size = sizeof(SNETPLAYERDATA); + playerdata.playername = "PlayerName"; + playerdata.playerdescription = "PlayerDesc"; + + // BUILD AN INTERFACE DATA STRUCTURE + SNETUIDATA interfacedata; + ZeroMemory(&interfacedata,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = SDrawGetFrameWindow(); + interfacedata.artcallback = ArtCallback; + + // SELECT A NETWORK PROVIDER + DWORD providerid; + if (!SNetSelectProvider(NULL, + &programdata, + &playerdata, + &interfacedata, + NULL, + &providerid)) + return 1; + + // SELECT A GAME + DWORD playerid; + if (!SNetSelectGame(0, + &programdata, + &playerdata, + &interfacedata, + NULL, + &playerid)) + return 1; + + // SHUTDOWN + StormDestroy(); + + return 0; +} diff --git a/src/Storm/SAMPLES/SNET/JOIN/JOIN.CS b/src/Storm/SAMPLES/SNET/JOIN/JOIN.CS new file mode 100644 index 0000000..732d435 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/JOIN/JOIN.CS @@ -0,0 +1,2 @@ +#include +set extralib=storm.lib diff --git a/src/Storm/SAMPLES/SNET/JOIN/JOIN.EXE b/src/Storm/SAMPLES/SNET/JOIN/JOIN.EXE new file mode 100644 index 0000000..1d5214d Binary files /dev/null and b/src/Storm/SAMPLES/SNET/JOIN/JOIN.EXE differ diff --git a/src/Storm/SAMPLES/SNET/PONG/ARTWORK.MPQ b/src/Storm/SAMPLES/SNET/PONG/ARTWORK.MPQ new file mode 100644 index 0000000..5a98ada Binary files /dev/null and b/src/Storm/SAMPLES/SNET/PONG/ARTWORK.MPQ differ diff --git a/src/Storm/SAMPLES/SNET/PONG/PONG.CPP b/src/Storm/SAMPLES/SNET/PONG/PONG.CPP new file mode 100644 index 0000000..964acce --- /dev/null +++ b/src/Storm/SAMPLES/SNET/PONG/PONG.CPP @@ -0,0 +1,724 @@ +/**************************************************************************** +* +* PONG.CPP +* +* This is a simple game which demonstrates the use of asynchronous +* messaging. It is sort of a cross between Pong and Breakout. Players +* bounce balls off of bricks in the center of the screen, and when they +* have eliminated enough bricks, they try to bounce their ball into the +* opponent's territory in the hopes he will miss it. +* +* Pong is actually a good example of a game in which it is very difficult to +* support an arbitrary latency network. You cannot simply model the ball +* locally and accept periodic updates from the remote player, because the +* ball's trajectory will change significantly every time the remote player +* hits it, depending on exactly where his paddle was at the moment of +* contact. Therefore, what this implementation does is take the ball +* out of play (make it invisible and nonmoving) when it gets to a point +* where it may or may not have collided with the opponent's paddle, and +* then waits for a message from the opponent telling whether he hit or +* missed, and what the new position and trajectory of the ball are. It can +* then model the ball locally until the next time it comes into possible +* contact with the opponent's paddle. +* +* Despite this, it is still possible for the game to become out of sync, +* because there are two balls in play. When one of them is taken out of +* play pending a message from the opponent, the other one continues to +* move. On a high latency network, the end result is that, one the local +* system, the ball that the local player just hit will tend to be slightly +* farther along than the ball the remote player just hit, and on the remote +* system, the inverse will be true. So if the two balls hit the same +* brick at the same time, each player will think that his own ball was +* deflected and the opponent's wasn't. If the balls are deflected straight +* back to the players and the players both miss, then each player might +* think that he missed but the opponent didn't. This is actually no big +* deal. Players send out messages saying they missed the ball when they +* do, and the recipient of the message will always take the player's word +* for it that he did, in fact, miss the ball. A worse situation happens +* if the balls are not deflected straight back to the players, but instead, +* each ball bounces off another brick and goes on to the opposing player. +* This would be more serious, as now each player would take the ball out of +* play while waiting for a message from the opposing player telling whether +* he hit or missed the ball. Since neither play would think that the ball +* came to him, neither player would ever send out such a message. Just in +* case this situation ever happens, what Pong does is send out a messsage +* whenever it thinks that the opponent needs to tell it whether he hit or +* missed the ball. When the opponent gets this message, if he finds that +* he is waiting for the same message from the other player, then he knows +* that a deadlock has occurred. He breaks the deadlock by putting the ball +* back into play with a new position and velocity, and sending that position +* and velocity to the other player. +* +***/ + +#include +#include +#include +#include + +#define PROGRAMID 'Pong' +#define VERSIONID 1 +#define MAXPLAYERS 2 +#define TITLE "Pong" + +#define BRICKCOLS 7 +#define BRICKROWS 24 + +#define SIN(a) sintable[((a) & 255)] +#define COS(a) sintable[(((a)+64) & 255)] + +#define NETID_BALLPOS 1 +#define NETID_CHECKSYNC 2 +#define NETID_MISSED 3 +#define NETID_PADDLEPOS 4 +#define NETID_QUIT 5 +#define NETID_RESTART 6 + +typedef BYTE ANGLE; +typedef LONG FIXEDINT; + +typedef struct _POINTF { + FIXEDINT x; + FIXEDINT y; +} POINTF; + +HSARCHIVE archive = (HSARCHIVE)0; +ANGLE ballangle[2]; +POINTF ballpos[2]; +SIZE ballsize = {5,5}; +int ballwait[2]; +BYTE brick[BRICKCOLS][BRICKROWS]; +BOOL computer = 0; +int lives[2]; +int missed[2]; +POINT paddle[2] = {{15,240},{624,240}}; +SIZE paddlesize = {5,40}; +DWORD player = 0; +FIXEDINT sintable[256]; +FIXEDINT speed[2]; +BOOL started = 0; + +BOOL CALLBACK CreateCallback (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +void CreateSinTable (); +FIXEDINT FixedMul (FIXEDINT a, FIXEDINT b); +BOOL ProcessNetworkMessages (); +void SendNetworkMessage (LPDWORD paramarray, DWORD paramcount); +void StartBall (int number, DWORD player); +void StartGame (); + +//=========================================================================== +BOOL CALLBACK ArtCallback (DWORD providerid, + DWORD artid, + LPPALETTEENTRY pe, + LPBYTE buffer, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + char filename[MAX_PATH] = ""; + switch (artid) { + case SNET_ART_BACKGROUND: strcpy(filename,"bkg.pcx" ); break; + case SNET_ART_BUTTONTEXTURE: strcpy(filename,"button.pcx"); break; + } + if (filename[0]) + return SBmpLoadImage(filename,pe,buffer,buffersize,width,height,bitdepth); + else + return 0; +} + +//=========================================================================== +BOOL Bounce (ANGLE *angle, int xdir, int ydir) { + BOOL bounced = 0; + if (((xdir < 0) && ((ANGLE)(64+*angle) < 128)) || + ((xdir > 0) && ((ANGLE)(64+*angle) > 128))) { + *angle = 192-(64+*angle); + bounced = 1; + } + if (((ydir < 0) && (*angle < 128)) || + ((ydir > 0) && (*angle > 128))) { + *angle = -*angle; + bounced = 1; + } + return bounced; +} + +//=========================================================================== +void ComputerMovePaddle () { + BOOL consider[2]; + int ball; + for (ball = 0; ball < 2; ++ball) + consider[ball] = ((ballwait[ball] < 0) && + ((ballpos[ball].x > 320*0x10000) == (int)player) && + (((ANGLE)(ballangle[ball]+64) < 128) == (int)player)); + if (!(consider[0] ^ consider[1])) + ball = ((ballpos[0].x > ballpos[1].x) == (int)player) ? 0 : 1; + else if (consider[0]) + ball = 0; + else + ball = 1; + if (ball >= 0) { + int y = ballpos[ball].y/0x10000; + y -= (y-240)*paddlesize.cy/240; + if (y < paddle[player].y) + paddle[player].y -= min(12,paddle[player].y-y); + else if (y > paddle[player].y) + paddle[player].y += min(12,y-paddle[player].y); + } +} + +//=========================================================================== +BOOL Connect () { + + // BUILD A PROGRAM DATA RECORD + SNETPROGRAMDATA programdata; + ZeroMemory(&programdata,sizeof(SNETPROGRAMDATA)); + programdata.size = sizeof(SNETPROGRAMDATA); + programdata.programname = TITLE; + programdata.programid = PROGRAMID; + programdata.versionid = VERSIONID; + programdata.maxplayers = MAXPLAYERS; + + // GENERATE A PLAYER NAME + char computername[MAX_COMPUTERNAME_LENGTH+1] = ""; + DWORD size = MAX_COMPUTERNAME_LENGTH+1; + GetComputerName(computername,&size); + + // BUILD A PLAYER DATA RECORD + SNETPLAYERDATA playerdata; + ZeroMemory(&playerdata,sizeof(SNETPLAYERDATA)); + playerdata.size = sizeof(SNETPLAYERDATA); + playerdata.playername = computername; + + // BUILD AN INTERFACE DATA RECORD + SNETUIDATA interfacedata; + ZeroMemory(&interfacedata,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = SDrawGetFrameWindow(); + interfacedata.artcallback = ArtCallback; + interfacedata.createcallback = CreateCallback; + + // SELECT A NETWORK PROVIDER + while (SNetSelectProvider(NULL, + &programdata, + &playerdata, + &interfacedata, + NULL, + NULL)) { + + // SELECT A GAME + if (SNetSelectGame(0, + &programdata, + &playerdata, + &interfacedata, + NULL, + &player)) + return 1; + + } + return 0; +} + +//=========================================================================== +void ConnectIdleProc () { + + // IF WE ARE STILL WAITING TO CONNECT, UPDATE THE WAITING BANNER AND RETURN + { + DWORD activeplayers = 0; + SNetGetNumPlayers(NULL,NULL,&activeplayers); + if (activeplayers < 2) { + static BYTE intensity = 0; + static int direction = 1; + PALETTEENTRY pe = {intensity,intensity,0x80+(intensity >> 1),0}; + SDrawUpdatePalette(128,1,&pe); + intensity += direction; + if (intensity >= 127) + direction = -1; + else if (!intensity) + direction = 1; + Sleep(1); + return; + } + } + + // START THE GAME + CreateSinTable(); + StartGame(); + started = 1; + +} + +//=========================================================================== +BOOL CALLBACK CreateCallback (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + return SNetCreateGame(playerdata->playername, + NULL, + NULL, + 0, + NULL, + 0, + programdata->maxplayers, + playerdata->playername, + NULL, + playerid); +} + +//=========================================================================== +void CreateSinTable () { + for (int loop = 0; loop < 256; ++loop) { + double angle = (loop*3.14159265359)/128.0; + sintable[loop] = (FIXEDINT)(sin(angle)*0x10000); + } +} + +//=========================================================================== +void DrawScreen () { + LPBYTE videobuffer; + int videopitch; + SDrawClearSurface(SDRAW_SURFACE_BACK); + if (SDrawLockSurface(SDRAW_SURFACE_BACK,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + + // DRAW THE PADDLES + { + for (int loop = 0; loop <= 1; ++loop) + if (!missed[loop]) + SGdiRectangle(videobuffer, + paddle[loop].x-paddlesize.cx, + paddle[loop].y-paddlesize.cy, + paddle[loop].x+paddlesize.cx, + paddle[loop].y+paddlesize.cy, + PALETTEINDEX(255)); + } + + // DRAW THE BRICKS + { + for (int row = 0; row < BRICKROWS; ++row) + for (int col = 0; col < BRICKCOLS; ++col) + if (brick[col][row]) + SGdiRectangle(videobuffer, + col*25+240, + row*20+2, + col*25+250, + row*20+17, + PALETTEINDEX(248+col)); + } + + // DRAW THE BALLS + { + for (int loop = 0; loop <= 1; ++loop) + if (ballwait[loop] < 0) + SGdiRectangle(videobuffer, + (ballpos[loop].x/0x10000)-ballsize.cx, + (ballpos[loop].y/0x10000)-ballsize.cy, + (ballpos[loop].x/0x10000)+ballsize.cx, + (ballpos[loop].y/0x10000)+ballsize.cy, + PALETTEINDEX(255)); + } + + // DRAW LIVES LEFT + { + for (DWORD loop = 0; loop <= 1; ++loop) + if (missed[loop]) + if (lives[loop]) { + char buffer[64]; + wsprintf(buffer, + "%u %s LEFT", + lives[loop], + (lives[loop] == 1) ? "LIFE" : "LIVES"); + SGdiTextOut(videobuffer, + loop*400+100, + 235, + PALETTEINDEX(255), + buffer); + } + else if (loop == player) + SGdiTextOut(videobuffer, + loop*400+100, + 235, + PALETTEINDEX(255), + "LOSER!"); + else + SGdiTextOut(videobuffer, + (!loop)*400+100, + 235, + PALETTEINDEX(255), + "WINNER!"); + } + + SDrawUnlockSurface(SDRAW_SURFACE_BACK,videobuffer); + SDrawFlipPage(); + } +} + +//=========================================================================== +void ExecuteGameLoop () { + + // MOVE THE BALLS + { + for (int loop = 0; loop < 2; ++loop) + if (ballwait[loop] < 0) { + POINT lastpos = {ballpos[loop].x/0x10000, + ballpos[loop].y/0x10000}; + POINT nextpos = {(ballpos[loop].x+FixedMul(COS(ballangle[loop]),speed[loop]))/0x10000, + (ballpos[loop].y+FixedMul(SIN(ballangle[loop]),speed[loop]))/0x10000}; + + // IF THE BALL HAS MOVED TO WHERE IT MAY OR MAY NOT HAVE COLLIDED + // WITH THE REMOTE PLAYER'S PADDLE, PUT THE BALL ON HOLD UNTIL WE + // FIND OUT FROM THE REMOTE PLAYER WHAT HAPPENED + if (( player && (nextpos.x-ballsize.cx < paddle[0].x+paddlesize.cx)) || + ((!player) && (nextpos.x+ballsize.cx > paddle[1].x-paddlesize.cx))) { + ballwait[loop] = !player; + DWORD paramarray[2] = {NETID_CHECKSYNC,loop}; + SendNetworkMessage(¶marray[0],2); + continue; + } + + // CHECK FOR COLLISION WITH THE LOCAL PLAYER'S PADDLE + if ((!missed[player]) && + (nextpos.x-ballsize.cx < paddle[player].x+paddlesize.cx) && + (nextpos.x+ballsize.cx > paddle[player].x-paddlesize.cx) && + (nextpos.y-ballsize.cy < paddle[player].y+paddlesize.cy) && + (nextpos.y+ballsize.cy > paddle[player].y-paddlesize.cy)) { + int ydir = 0; + if (nextpos.y-ballsize.cy < paddle[player].y-paddlesize.cy) + ydir = -1; + else if (nextpos.y+ballsize.cy > paddle[player].y+paddlesize.cy) + ydir = 1; + if (Bounce(&ballangle[loop],player ? -1 : 1,ydir)) { + ANGLE target = (ANGLE)((nextpos.y-paddle[player].y)*32/paddlesize.cy); + if (player) + target = 128-target; + ballangle[loop] += ((char)(target-ballangle[loop]))/2; + DWORD paramarray[6] = {NETID_BALLPOS, + loop, + ballpos[loop].x, + ballpos[loop].y, + ballangle[loop], + speed[loop]}; + SendNetworkMessage(¶marray[0],6); + continue; + } + } + + // CHECK FOR COLLISION WITH THE EDGE OF THE SCREEN, INDICATING THAT + // THE PLAYER MISSED THE BALL + if (( player && (nextpos.x+ballsize.cx > 639)) || + ((!player) && (nextpos.x-ballsize.cx < 0))) { + ballwait[loop] = player; + if (missed[player]) + missed[player] = 30; + else { + --lives[player]; + missed[player] = 100; + } + DWORD paramarray[4] = {NETID_MISSED, + loop, + missed[player], + lives[player]}; + SendNetworkMessage(¶marray[0],4); + continue; + } + + // CHECK FOR COLLISION WITH THE TOP OR BOTTOM OF THE SCREEN + if (nextpos.y-ballsize.cy < 0) + Bounce(&ballangle[loop],0,1); + if (nextpos.y+ballsize.cy > 479) + Bounce(&ballangle[loop],0,-1); + + // CHECK FOR COLLISION WITH A BRICK + { + for (int col = 0; col < BRICKCOLS; ++col) + if ((nextpos.x-ballsize.cx <= col*25+250) && + (nextpos.x+ballsize.cx >= col*25+240)) + for (int row = 0; row < BRICKROWS; ++row) + if (brick[col][row] && + ((nextpos.y-ballsize.cy <= row*20+17) && + (nextpos.y+ballsize.cy >= row*20+2))) { + int xdir = 0; + int ydir = 0; + if ((lastpos.x+ballsize.cx < col*25+240) && + (nextpos.x+ballsize.cx >= col*25+240)) + xdir = -1; + else if ((lastpos.x-ballsize.cx > col*25+250) && + (nextpos.x-ballsize.cx <= col*25+250)) + xdir = 1; + if ((lastpos.y+ballsize.cy < row*20+2) && + (nextpos.y+ballsize.cy >= row*20+2)) + ydir = -1; + else if ((lastpos.y-ballsize.cy > row*20+17) && + (nextpos.y-ballsize.cy <= row*20+17)) + ydir = 1; + Bounce(&ballangle[loop],xdir,ydir); + brick[col][row] = 0; + } + } + + ballpos[loop].x += FixedMul(COS(ballangle[loop]),speed[loop]); + ballpos[loop].y += FixedMul(SIN(ballangle[loop]),speed[loop]); + speed[loop] += 48; + } + } + + // IF THE PLAYER RECENTLY MISSED THE BALL, CHECK TO SEE IF HE CAN + // REENTER THE GAME + if (missed[player]) + if (missed[player] > 1) + --missed[player]; + else { + DWORD side[2]; + for (int loop = 0; loop < 2; ++loop) { + if (ballwait[loop] >= 0) + side[loop] = -1; + else if ((ballpos[loop].x < 320*0x10000) && (COS(ballangle[loop]) < 0)) + side[loop] = 0; + else if ((ballpos[loop].x > 320*0x10000) && (COS(ballangle[loop]) > 0)) + side[loop] = 1; + else + side[loop] = -1; + } + if ((side[0] != player) && (side[1] != player)) { + missed[player] = 0; + if (ballwait[0] == (int)player) { + StartBall(0,player); + if (ballwait[1] == (int)player) + StartBall(1,!player); + } + else if (ballwait[1] == (int)player) + StartBall(1,player); + } + } + + // MOVE THE PLAYER'S PADDLE + if (computer) + ComputerMovePaddle(); + else { + POINT pt; + GetCursorPos(&pt); + paddle[player].y = pt.y; + } + paddle[player].y = max(paddlesize.cy,min(479-paddlesize.cy,paddle[player].y)); + +} + +//=========================================================================== +FIXEDINT FixedMul (FIXEDINT a, FIXEDINT b) { + return MulDiv(a,b,0x10000); +} + +//=========================================================================== +void GameIdleProc () { + DWORD currtime = GetTickCount(); + + // PROCESS NETWORK MESSAGES + BOOL processed = ProcessNetworkMessages(); + + // EXECUTE THE GAME LOOP 60 TIMES PER SECOND + if (lives[0] && lives[1]) { + static DWORD lasttime = GetTickCount(); + static DWORD cycle = 0; + if (currtime-lasttime > 1000) + lasttime = currtime; + else + while (currtime-lasttime >= 17) { + ExecuteGameLoop(); + processed = 1; + lasttime += cycle++ ? 17 : 16; + if (cycle > 2) + cycle = 0; + } + } + + // SEND OUT OUR PADDLE POSITION 10 TIMES PER SECOND + { + static DWORD lasttime = GetTickCount(); + if (currtime-lasttime > 1000) + lasttime = currtime; + else + while (currtime-lasttime >= 100) { + DWORD paramarray[2] = {NETID_PADDLEPOS,paddle[player].y}; + SendNetworkMessage(¶marray[0],2); + lasttime += 100; + } + } + + // UPDATE THE SCREEN + if (processed) + DrawScreen(); + +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (started) + GameIdleProc(); + else + ConnectIdleProc(); + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + HSGDIFONT font; + { + HFONT winfont = CreateFont(-17,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_ROMAN,TEXT("Times New Roman")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +void CALLBACK OnKeyDown (LPPARAMS params) { + if (params->wparam == VK_ESCAPE) { + if (started) { + DWORD param = NETID_QUIT; + SendNetworkMessage(¶m,1); + } + SDrawPostClose(); + } + else if (started && (!lives[0]) || (!lives[1])) { + DWORD param = NETID_RESTART; + SendNetworkMessage(¶m,1); + StartGame(); + } +} + +//=========================================================================== +void CALLBACK OnPaint (LPPARAMS params) { + if (!started) { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + SGdiRectangle(videobuffer,0,0,639,479,PALETTEINDEX(128)); + SGdiTextOut(videobuffer,240,235,PALETTEINDEX(255),"Waiting to connect..."); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + } +} + +//=========================================================================== +BOOL ProcessNetworkMessages () { + BOOL processed = 0; + LPVOID data = NULL; + DWORD databytes = 0; + while (SNetReceiveMessage(NULL,&data,&databytes)) + if (databytes >= sizeof(DWORD)) { + LPDWORD param = (LPDWORD)data; + switch (*param) { + + case NETID_BALLPOS: + ballpos[*(param+1)].x = *(param+2); + ballpos[*(param+1)].y = *(param+3); + ballangle[*(param+1)] = (ANGLE)*(param+4); + speed[*(param+1)] = *(param+5); + ballwait[*(param+1)] = -1; + missed[!player] = 0; + break; + + case NETID_CHECKSYNC: + if (ballwait[*(param+1)] == !player) + StartBall(*(param+1),player); + break; + + case NETID_MISSED: + ballwait[*(param+1)] = !player; + missed[!player] = *(param+2); + lives[!player] = *(param+3); + break; + + case NETID_PADDLEPOS: + paddle[!player].y = *(param+1); + break; + + case NETID_QUIT: + SDrawPostClose(); + break; + + case NETID_RESTART: + StartGame(); + break; + + } + processed = 1; + } + return processed; +} + +//=========================================================================== +void SendNetworkMessage (LPDWORD paramarray, DWORD paramcount) { + SNetSendMessage(!player, + paramarray, + paramcount*sizeof(DWORD)); +} + +//=========================================================================== +void StartBall (int number, DWORD player) { + ballangle[number] = (rand() & 63)+(player ? 224 : 96); + ballpos[number].x = (player ? 420 : 220)*0x10000; + int besty = paddle[player].y-(abs((ballpos[number].x >> 16)-paddle[player].x)*SIN(ballangle[number]) >> 16); + ballpos[number].y = max(0,min(479,besty))*0x10000; + ballwait[number] = -1; + DWORD paramarray[6] = {NETID_BALLPOS, + number, + ballpos[number].x, + ballpos[number].y, + ballangle[number], + speed[number]}; + SendNetworkMessage(¶marray[0],6); +} + +//=========================================================================== +void StartGame () { + srand(GetTickCount()); + FillMemory(brick,BRICKCOLS*BRICKROWS,1); + for (int loop = 0; loop < 2; ++loop) { + lives[loop] = 3; + missed[loop] = 0; + speed[loop] = 0x50000; + } + StartBall(player,player); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR cmdline, int) { + if (cmdline && *cmdline) + computer = 1; + if (!SDrawAutoInitialize(instance, + TITLE "_CLASS", + TITLE, + NULL, + SDRAW_SERVICE_PAGEFLIP)) { + SDrawMessageBox("Unable to initialize DirectDraw.",TITLE,0); + return 1; + } + if (!SFileOpenArchive("artwork.mpq",0,0,&archive)) { + SDrawMessageBox("Unable to open artwork.",TITLE,0); + return 1; + } + if (!Connect()) { + SDrawMessageBox("Unable to initialize networking.",TITLE,0); + return 1; + } + if (!LoadFont()) { + SDrawMessageBox("Unable to load font.",TITLE,0); + return 1; + } + SMsgRegisterMessage(NULL,WM_KEYDOWN,OnKeyDown); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SNET/PONG/PONG.CS b/src/Storm/SAMPLES/SNET/PONG/PONG.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/PONG/PONG.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SNET/PONG/PONG.EXE b/src/Storm/SAMPLES/SNET/PONG/PONG.EXE new file mode 100644 index 0000000..4b317ed Binary files /dev/null and b/src/Storm/SAMPLES/SNET/PONG/PONG.EXE differ diff --git a/src/Storm/SAMPLES/SNET/README.TXT b/src/Storm/SAMPLES/SNET/README.TXT new file mode 100644 index 0000000..97c80f4 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/README.TXT @@ -0,0 +1,7 @@ +The networking examples have not been updated recently, so they do not +include all of the necessary user interface callback functions and artwork. +This affects the create/join game process but does not affect the +functionality of the example games themselves. + +For sample implementations of all required user interface callback +functions, see the DiabloUI source code. diff --git a/src/Storm/SAMPLES/SNET/RPG/ART/CURSOR.PCX b/src/Storm/SAMPLES/SNET/RPG/ART/CURSOR.PCX new file mode 100644 index 0000000..488d3ca Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/ART/CURSOR.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/ART/MAP.PCX b/src/Storm/SAMPLES/SNET/RPG/ART/MAP.PCX new file mode 100644 index 0000000..b5f47f4 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/ART/MAP.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/ART/PLAYER.PCX b/src/Storm/SAMPLES/SNET/RPG/ART/PLAYER.PCX new file mode 100644 index 0000000..9fe13f3 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/ART/PLAYER.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/ART/TILESET.PCX b/src/Storm/SAMPLES/SNET/RPG/ART/TILESET.PCX new file mode 100644 index 0000000..7a98692 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/ART/TILESET.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/BNETART.H b/src/Storm/SAMPLES/SNET/RPG/BNETART.H new file mode 100644 index 0000000..bf6299e --- /dev/null +++ b/src/Storm/SAMPLES/SNET/RPG/BNETART.H @@ -0,0 +1,19 @@ +/**************************************************************************** +* +* bnetart.h +* +* This file should be included by an application that wants to provide +* battle.net-specific artwork in its art callback. +* +***/ + +enum _BATTLENET_ART { + SNET_ART_BATTLE_BTNS = 0x80000000, + SNET_ART_BATTLE_JOIN_BKG, + SNET_ART_BATTLE_HELP_BKG, + SNET_ART_BATTLE_LISTBOX, + SNET_ART_BATTLE_GREENLAG, + SNET_ART_BATTLE_YELLOWLAG, + SNET_ART_BATTLE_REDLAG, +}; + diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BKG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BKG.PCX new file mode 100644 index 0000000..10d285d Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BKG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BNBUTTNS.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BNBUTTNS.PCX new file mode 100644 index 0000000..bf07cec Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BNBUTTNS.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BNCREATE.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BNCREATE.PCX new file mode 100644 index 0000000..3933f50 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BNCREATE.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BNHELP.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BNHELP.PCX new file mode 100644 index 0000000..71f5da6 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BNHELP.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BNJOIN.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BNJOIN.PCX new file mode 100644 index 0000000..962e07d Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BNJOIN.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BNJOINBG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BNJOINBG.PCX new file mode 100644 index 0000000..c3a6bbf Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BNJOINBG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BNLIST.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BNLIST.PCX new file mode 100644 index 0000000..7652964 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BNLIST.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BNQUIT.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BNQUIT.PCX new file mode 100644 index 0000000..1b26038 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BNQUIT.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BUTTON.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BUTTON.PCX new file mode 100644 index 0000000..2d0986f Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BUTTON.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_LRG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_LRG.PCX new file mode 100644 index 0000000..c9e1682 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_LRG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_MED.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_MED.PCX new file mode 100644 index 0000000..a4989f0 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_MED.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_SML.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_SML.PCX new file mode 100644 index 0000000..27f2fb5 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_SML.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_XSM.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_XSM.PCX new file mode 100644 index 0000000..018ca53 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/BUT_XSM.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/CHAT_BKG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/CHAT_BKG.PCX new file mode 100644 index 0000000..8deb560 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/CHAT_BKG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/CONNECT.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/CONNECT.PCX new file mode 100644 index 0000000..350dbe6 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/CONNECT.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/CREAHERO.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/CREAHERO.PCX new file mode 100644 index 0000000..10282d6 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/CREAHERO.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/CREAT_BG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/CREAT_BG.PCX new file mode 100644 index 0000000..38f2c98 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/CREAT_BG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/CREDITS.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/CREDITS.PCX new file mode 100644 index 0000000..2270e85 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/CREDITS.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/GREENLAG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/GREENLAG.PCX new file mode 100644 index 0000000..1533218 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/GREENLAG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/HEROS.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/HEROS.PCX new file mode 100644 index 0000000..7ded7e7 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/HEROS.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/IPX_BKG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/IPX_BKG.PCX new file mode 100644 index 0000000..440f69e Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/IPX_BKG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/LISTBOX.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/LISTBOX.PCX new file mode 100644 index 0000000..8a3af8b Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/LISTBOX.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/LIST_GRY.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/LIST_GRY.PCX new file mode 100644 index 0000000..68b16b4 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/LIST_GRY.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/LPOPUP.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/LPOPUP.PCX new file mode 100644 index 0000000..3cfbed5 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/LPOPUP.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/LRPOPUP.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/LRPOPUP.PCX new file mode 100644 index 0000000..441c1d7 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/LRPOPUP.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/MENU.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/MENU.PCX new file mode 100644 index 0000000..6eae183 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/MENU.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/PROG_BG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/PROG_BG.PCX new file mode 100644 index 0000000..1ae2df4 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/PROG_BG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/PROG_FIL.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/PROG_FIL.PCX new file mode 100644 index 0000000..3cb44a7 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/PROG_FIL.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/R1_GRY.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/R1_GRY.PCX new file mode 100644 index 0000000..ca710ca Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/R1_GRY.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/R3_GRY.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/R3_GRY.PCX new file mode 100644 index 0000000..17a7013 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/R3_GRY.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO1.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO1.PCX new file mode 100644 index 0000000..9963ae1 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO1.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO2.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO2.PCX new file mode 100644 index 0000000..d6b1be4 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO2.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO3.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO3.PCX new file mode 100644 index 0000000..78d2bac Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO3.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO4.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO4.PCX new file mode 100644 index 0000000..0331c72 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/RADIO4.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/REDLAG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/REDLAG.PCX new file mode 100644 index 0000000..7fdd67d Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/REDLAG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/SELHERO.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/SELHERO.PCX new file mode 100644 index 0000000..42faf9c Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/SELHERO.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/SPOPUP.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/SPOPUP.PCX new file mode 100644 index 0000000..0029f35 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/SPOPUP.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/SRPOPUP.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/SRPOPUP.PCX new file mode 100644 index 0000000..8216de5 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/SRPOPUP.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/TITLE.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/TITLE.PCX new file mode 100644 index 0000000..558b552 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/TITLE.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/YELLOLAG.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/YELLOLAG.PCX new file mode 100644 index 0000000..760a153 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/YELLOLAG.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/NETART/_BACKUP_.PCX b/src/Storm/SAMPLES/SNET/RPG/NETART/_BACKUP_.PCX new file mode 100644 index 0000000..1533218 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/NETART/_BACKUP_.PCX differ diff --git a/src/Storm/SAMPLES/SNET/RPG/RESOURCE.H b/src/Storm/SAMPLES/SNET/RPG/RESOURCE.H new file mode 100644 index 0000000..db969d3 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/RPG/RESOURCE.H @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by rpg.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SAMPLES/SNET/RPG/RPG.CPP b/src/Storm/SAMPLES/SNET/RPG/RPG.CPP new file mode 100644 index 0000000..673ad48 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/RPG/RPG.CPP @@ -0,0 +1,760 @@ +/**************************************************************************** +* +* RPG.CPP +* +* This is a simple game which demonstrates the use of synchonous networking. +* It is basically an Ultima IV style tiled graphics engine, with Warcraft +* style mouse controls. +* +* At the beginning of the game, each player sends out two null orders. +* During the game, players send out orders as they are received from the +* user (a sample order would be "move to this location"), and fabricate +* null orders as necessary to make sure there are always at least two in +* transit. +* +* Each turn, each player waits until he has received the next set of orders +* from all players, and then executes all orders, starting at the lowest +* player number. Since orders are processed at the same time and in the +* same order on every computer in the network, the game stays in sync. +* +***/ + +#include +#include +#include "bnetart.h" + +#define PROGRAMID 'RPG1' +#define VERSIONID 1 +#define MAXPLAYERS 8 +#define TITLE "RPG Example" +#define ARTDIR "art\\" +#define NETARTDIR "netart\\" + +#define ORDER_NULL 0 +#define ORDER_START 1 +#define ORDER_MOVE 2 +#define ORDER_QUIT 3 + +#define TILE_DEEPSEA 0 +#define TILE_SEA 1 +#define TILE_SHALLOWSEA 2 +#define TILE_SWAMP 3 +#define TILE_GRASS 4 +#define TILE_BRUSH 5 +#define TILE_FOREST 6 +#define TILE_HILLS 7 +#define TILE_MOUNTAINS 8 +#define TILE_DUNGEON 9 +#define TILE_TOWN 10 +#define TILE_CASTLE 11 +#define TILE_VILLAGE 12 + +#define SCREENCX 640 +#define SCREENCY 480 +#define SCREENTILESX 20 +#define SCREENTILESY 15 +#define SCROLLCX 672 +#define SCROLLCY 512 +#define SCROLLTILESX 21 +#define SCROLLTILESY 16 +#define TILES 16 +#define TILECX 32 +#define TILECY 32 +#define WORLDMAPCX 256 +#define WORLDMAPCY 256 + +LPBYTE cursor = NULL; +POINT cursorpos = {0,0}; +DWORD localplayer = 0; +POINT orderpos[MAXPLAYERS]; +PALETTEENTRY pe[256]; +LPBYTE player = NULL; +POINT playerpos[MAXPLAYERS]; +DWORD players = 0; +LPBYTE scrollbuffer = NULL; +POINT scrollpos; +POINT scrollvel = {0,0}; +BOOL started = 0; +LPBYTE tileset = NULL; +LPBYTE worldmap = NULL; + +BOOL CALLBACK CreateCallback (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +BOOL LoadGraphicsData (); +void MovePlayer (DWORD player); +void CALLBACK OnButtonDown (LPPARAMS params); +void CALLBACK OnClose (LPPARAMS params); +void CALLBACK OnEraseBkgnd (LPPARAMS params); +void CALLBACK OnPaint (LPPARAMS params); +void CALLBACK OnVkEscape (LPPARAMS params); +void CALLBACK OnVkSpace (LPPARAMS params); +BOOL ProcessOrders (); +BOOL UpdateScrollVelocity (); + +//=========================================================================== +BOOL CALLBACK ArtCallback (DWORD providerid, + DWORD artid, + LPPALETTEENTRY pe, + LPBYTE buffer, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + + char filename[MAX_PATH] = ""; + + if (providerid == 'BNET') { + // Check for battlenet specific art + switch (artid) { + + case SNET_ART_BACKGROUND: strcpy(filename,NETARTDIR "chat_bkg.pcx"); break; + case SNET_ART_BATTLE_LISTBOX: strcpy(filename, NETARTDIR "bnlist.pcx"); break; + + case SNET_ART_BATTLE_BTNS: strcpy(filename, NETARTDIR "bnbuttns.pcx"); break; + + case SNET_ART_BATTLE_HELP_BKG: strcpy(filename, NETARTDIR "lpopup.pcx"); break; + case SNET_ART_JOINBACKGROUND: strcpy(filename, NETARTDIR "bnjoinbg.pcx"); break; + + case SNET_ART_BATTLE_REDLAG: strcpy(filename, NETARTDIR "redlag.pcx"); break; + case SNET_ART_BATTLE_YELLOWLAG: strcpy(filename, NETARTDIR "yellolag.pcx"); break; + case SNET_ART_BATTLE_GREENLAG: strcpy(filename, NETARTDIR "greenlag.pcx"); break; + } + + } + else if ((providerid == 'IPXN') || (providerid == 'TEST')) { + switch (artid) { + case SNET_ART_BACKGROUND: strcpy(filename, NETARTDIR "ipx_bkg.pcx"); break; + } + } + else if (providerid == 0) { + switch (artid) { + case SNET_ART_BACKGROUND: strcpy(filename, NETARTDIR "connect.pcx"); break; + } + } + + if (!filename[0]) { + // Check for generic artwork + switch (artid) { + case SNET_ART_JOINBACKGROUND: // fall through + case SNET_ART_BACKGROUND: strcpy(filename,NETARTDIR "menu.pcx"); break; + case SNET_ART_BUTTONTEXTURE: strcpy(filename,NETARTDIR "but_lrg.pcx"); break; + case SNET_ART_POPUPBACKGROUND: strcpy(filename,NETARTDIR "lpopup.pcx"); break; + case SNET_ART_HELPBACKGROUND: strcpy(filename,NETARTDIR "lpopup.pcx"); break; + + case SNET_ART_BUTTON_XSML: strcpy(filename,NETARTDIR "but_xsm.pcx"); break; + case SNET_ART_BUTTON_SML: strcpy(filename,NETARTDIR "but_sml.pcx"); break; + case SNET_ART_BUTTON_MED: strcpy(filename,NETARTDIR "but_med.pcx"); break; + case SNET_ART_BUTTON_LRG: strcpy(filename,NETARTDIR "but_lrg.pcx"); break; + } + } + + if (filename[0]) + return SBmpLoadImage(filename,pe,buffer,buffersize,width,height,bitdepth); + else + return 0; + +} + +//=========================================================================== +void ChooseStartingLocations () { + for (DWORD loop = 0; loop < MAXPLAYERS; ++loop) { + BOOL found = 0; + while (!found) { + int x = rand() % WORLDMAPCX; + int y = rand() % WORLDMAPCY; + if (*(worldmap+y*WORLDMAPCX+x) == TILE_GRASS) { + found = 1; + for (DWORD loop2 = 1; loop2 < loop; ++loop2) + if ((playerpos[loop2].x == x) && (playerpos[loop2].y == y)) + found = 0; + if (found) { + orderpos[loop].x = x; + orderpos[loop].y = y; + playerpos[loop].x = x; + playerpos[loop].y = y; + } + } + } + } +} + +//=========================================================================== +BOOL Connect () { + + // BUILD A PROGRAM DATA RECORD + SNETPROGRAMDATA programdata; + ZeroMemory(&programdata,sizeof(SNETPROGRAMDATA)); + programdata.size = sizeof(SNETPROGRAMDATA); + programdata.programname = TITLE; + programdata.programid = PROGRAMID; + programdata.versionid = VERSIONID; + programdata.maxplayers = MAXPLAYERS; + + // GENERATE A PLAYER NAME + char computername[MAX_COMPUTERNAME_LENGTH+1] = ""; + DWORD size = MAX_COMPUTERNAME_LENGTH+1; + GetComputerName(computername,&size); + + // BUILD A PLAYER DATA RECORD + SNETPLAYERDATA playerdata; + ZeroMemory(&playerdata,sizeof(SNETPLAYERDATA)); + playerdata.size = sizeof(SNETPLAYERDATA); + playerdata.playername = computername; + + // BUILD AN INTERFACE DATA RECORD + SNETUIDATA interfacedata; + ZeroMemory(&interfacedata,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = SDrawGetFrameWindow(); + interfacedata.artcallback = ArtCallback; + interfacedata.createcallback = CreateCallback; + + // SELECT A NETWORK PROVIDER + while (SNetSelectProvider(NULL, + &programdata, + &playerdata, + &interfacedata, + NULL, + NULL)) { + + // SELECT A GAME + if (SNetSelectGame(0, + &programdata, + &playerdata, + &interfacedata, + NULL, + &localplayer)) + return 1; + + } + return 0; +} + +//=========================================================================== +BOOL CALLBACK ConnectIdleProc (DWORD) { + DWORD currtime = GetTickCount(); + + // TWICE A SECOND, UPDATE THE LIST OF PLAYERS + { + static DWORD lasttime = 0; + if (currtime-lasttime > 1000) + lasttime = currtime-500; + while (currtime-lasttime >= 500) { + + // DRAW THE LIST + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + SNetGetNumPlayers(NULL,&players,NULL); + ++players; + for (DWORD loop = 0; loop < players; ++loop) { + char buffer[SNET_MAXNAMELENGTH+2] = "0 "; + buffer[0] += (char)loop; + if (SNetGetPlayerName(loop,buffer+2,SNET_MAXNAMELENGTH)) + SGdiTextOut(videobuffer,4,loop*20,PALETTEINDEX(255-loop),buffer); + } + SGdiTextOut(videobuffer,440,20,PALETTEINDEX(255),"PRESS SPACE TO START"); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + + lasttime += 500; + } + } + + // FOUR TIMES A SECOND, PROCESS ORDERS + { + static DWORD lasttime = 0; + if (currtime-lasttime > 1000) + lasttime = currtime-250; + while (currtime-lasttime >= 250) { + if (ProcessOrders()) + lasttime += 250; + else + lasttime = GetTickCount(); + currtime = GetTickCount(); + } + } + + return 1; +} + +//=========================================================================== +BOOL CALLBACK CreateCallback (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + return SNetCreateGame(playerdata->playername, + NULL, + NULL, + 0, + NULL, + 0, + createdata->maxplayers, + playerdata->playername, + NULL, + playerid); +} + +//=========================================================================== +BOOL CreateScrollBuffer () { + scrollbuffer = (LPBYTE)ALLOC(SCROLLTILESX*TILECX*SCROLLTILESY*TILECY); + return (scrollbuffer != NULL); +} + +//=========================================================================== +void Destroy () { + if (cursor) { + FREE(cursor); + cursor = NULL; + } + if (player) { + FREE(player); + player = NULL; + } + if (scrollbuffer) { + FREE(scrollbuffer); + scrollbuffer = NULL; + } + if (tileset) { + FREE(tileset); + tileset = NULL; + } + if (worldmap) { + FREE(worldmap); + worldmap = NULL; + } +} + +//=========================================================================== +void DrawScreen () { + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_BACK,NULL,&videobuffer,&pitch)) { + int startx = scrollpos.x % SCROLLCX; + int starty = scrollpos.y % SCROLLCY; + + // BLT FROM THE SCROLL BUFFER ONTO THE BACK SURFACE + SBltROP3(videobuffer, + scrollbuffer+starty*SCROLLCX+startx, + min(SCREENCX,SCROLLCX-startx), + min(SCREENCY,SCROLLCY-starty), + pitch, + SCROLLCX, + 0, + SRCCOPY); + if (SCROLLCX-startx < SCREENCX) + SBltROP3(videobuffer+SCROLLCX-startx, + scrollbuffer+starty*SCROLLCX, + SCREENCX+startx-SCROLLCX, + min(SCREENCY,SCROLLCY-starty), + pitch, + SCROLLCX, + 0, + SRCCOPY); + if (SCROLLCY-starty < SCREENCY) + SBltROP3(videobuffer+(SCROLLCY-starty)*pitch, + scrollbuffer+startx, + min(SCREENCX,SCROLLCX-startx), + SCREENCY+starty-SCROLLCY, + pitch, + SCROLLCX, + 0, + SRCCOPY); + if ((SCROLLCX-startx < SCREENCX) && + (SCROLLCY-starty < SCREENCY)) + SBltROP3(videobuffer+(SCROLLCY-starty)*pitch+SCROLLCX-startx, + scrollbuffer, + SCREENCX+startx-SCROLLCX, + SCREENCY+starty-SCROLLCY, + pitch, + SCROLLCX, + 0, + SRCCOPY); + + // DRAW THE MOUSE CURSOR ONTO THE BACK SURFACE + if (started) { + GetCursorPos(&cursorpos); + SBltROP3(videobuffer+cursorpos.y*pitch+cursorpos.x, + cursor, + min(32,SCREENCX-cursorpos.x), + min(32,SCREENCY-cursorpos.y), + pitch, + 32, + 0, + SRCPAINT); + } + + SDrawUnlockSurface(SDRAW_SURFACE_BACK,videobuffer); + SDrawFlipPage(); + } +} + +//=========================================================================== +void FillScrollBuffer (LPRECT rect) { + int startxtile = scrollpos.x/TILECX; + int startytile = scrollpos.y/TILECY; + int startxpos = (scrollpos.x % SCROLLCX)/TILECX; + int startypos = (scrollpos.y % SCROLLCY)/TILECY; + for (int y = rect->top; y <= rect->bottom; ++y) { + int mapy = startytile+y+((y >= startypos) ? 0 : SCROLLTILESY)-startypos; + for (int x = rect->left; x <= rect->right; ++x) { + int mapx = startxtile+x+((x >= startxpos) ? 0 : SCROLLTILESX)-startxpos; + int tile = min(TILES-1,*(worldmap+mapy*WORLDMAPCX+mapx)); + SBltROP3(scrollbuffer+y*TILECY*SCROLLCX+x*TILECX, + tileset+tile*TILECX, + TILECX, + TILECY, + SCROLLCX, + TILES*TILECX, + 0, + SRCCOPY); + } + } + for (DWORD loop = 0; loop < players; ++loop) { + if ((playerpos[loop].x >= startxtile) && + (playerpos[loop].y >= startytile) && + (playerpos[loop].x < startxtile+SCROLLTILESX) && + (playerpos[loop].y < startytile+SCROLLTILESY)) { + int posx = (startxpos+(playerpos[loop].x-startxtile)) % SCROLLTILESX; + int posy = (startypos+(playerpos[loop].y-startytile)) % SCROLLTILESY; + if ((posx >= rect->left) && (posx <= rect->right) && + (posy >= rect->top) && (posy <= rect->bottom)) { + DWORD pattern = ((255-loop) << 24) | ((255-loop) << 16) | ((255-loop) << 8) | (255-loop); + // pattern 11110000 + // source 11001100 + // dest 10101010 + // -------- + // rop 11100010 = 0xE2 + SBltROP3(scrollbuffer+posy*TILECY*SCROLLCX+posx*TILECX, + player, + TILECX, + TILECY, + SCROLLCX, + TILECX, + pattern, + 0xE20746); + } + } + } +} + +//=========================================================================== +BOOL CALLBACK GameIdleProc (DWORD) { + DWORD currtime = GetTickCount(); + + // FOUR TIMES A SECOND, MOVE THE PLAYERS + { + static DWORD lasttime = GetTickCount(); + if (currtime-lasttime > 1000) + lasttime = currtime-250; + while (currtime-lasttime >= 250) { + for (DWORD loop = 0; loop < players; ++loop) + MovePlayer(loop); + RECT rect = {0,0,SCROLLTILESX-1,SCROLLTILESY-1}; + FillScrollBuffer(&rect); + lasttime += 250; + } + } + + // TWICE A SECOND, PROCESS ORDERS + { + static DWORD lasttime = GetTickCount(); + if (currtime-lasttime > 2000) + lasttime = currtime-500; + while (currtime-lasttime >= 500) { + if (ProcessOrders()) + lasttime += 500; + else + lasttime = GetTickCount(); + currtime = GetTickCount(); + } + } + + // PROCESS SCROLLING + if (UpdateScrollVelocity()) { + + // UPDATE THE SCROLL POSITION + POINT oldscrollpos = scrollpos; + scrollpos.x = max(0,min(WORLDMAPCX*TILECX-SCROLLCX,scrollpos.x+scrollvel.x)); + scrollpos.y = max(0,min(WORLDMAPCY*TILECY-SCROLLCY,scrollpos.y+scrollvel.y)); + + // UPDATE THE SCROLL BUFFER + if (scrollpos.x/TILECX != oldscrollpos.x/TILECX) { + int updatex = (scrollvel.x > 0) ? (oldscrollpos.x % SCROLLCX)/TILECX + : (scrollpos.x % SCROLLCX)/TILECX; + RECT rect = {updatex,0,updatex,SCROLLTILESY-1}; + FillScrollBuffer(&rect); + } + if (scrollpos.y/TILECY != oldscrollpos.y/TILECY) { + int updatey = (scrollvel.y > 0) ? (oldscrollpos.y % SCROLLCY)/TILECY + : (scrollpos.y % SCROLLCY)/TILECY; + RECT rect = {0,updatey,SCROLLTILESX-1,updatey}; + FillScrollBuffer(&rect); + } + + } + + // DRAW THE SCREEN + DrawScreen(); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD count) { + if (started) + return GameIdleProc(count); + else + return ConnectIdleProc(count); +} + +//=========================================================================== +void IssueOrder (LPDWORD paramarray, DWORD paramcount) { + SNetSendTurn(paramarray, + paramcount*sizeof(DWORD)); +} + +//=========================================================================== +BOOL Initialize (HINSTANCE instance) { + if (!SDrawAutoInitialize(instance, + TITLE "_CLASS", + TITLE, + NULL, + SDRAW_SERVICE_PAGEFLIP)) { + SDrawMessageBox("Unable to initialize DirectDraw.",TITLE,0); + return 0; + } + if (!LoadGraphicsData()) { + SDrawMessageBox("Unable to load graphics data.",TITLE,0); + return 0; + } + if (!CreateScrollBuffer()) { + SDrawMessageBox("Out of memory.",TITLE,0); + return 0; + } + SMsgRegisterMessage(NULL,WM_ERASEBKGND,OnEraseBkgnd); + if (!Connect()) + return 0; + ChooseStartingLocations(); + scrollpos.x = max(0,min(WORLDMAPCX*TILECX-SCROLLCX,playerpos[localplayer].x*TILECX-SCROLLCX/2)); + scrollpos.y = max(0,min(WORLDMAPCY*TILECY-SCROLLCY,playerpos[localplayer].y*TILECY-SCROLLCY/2)); + SDrawUpdatePalette(0,256,&pe[0]); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_LBUTTONDOWN,OnButtonDown); + SMsgRegisterMessage(NULL,WM_PAINT ,OnPaint); + SMsgRegisterMessage(NULL,WM_RBUTTONDOWN,OnButtonDown); + SMsgRegisterKeyDown(NULL,VK_ESCAPE ,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + return 1; +} + +//=========================================================================== +BOOL LoadGraphicsData () { + + // LOAD IN THE CURSOR + cursor = (LPBYTE)ALLOC(32*32); + if (!cursor) + return 0; + if (!SBmpLoadImage(ARTDIR "cursor.pcx",NULL,cursor,32*32)) + return 0; + + // LOAD IN THE PLAYER IMAGE + player = (LPBYTE)ALLOC(32*32); + if (!player) + return 0; + if (!SBmpLoadImage(ARTDIR "player.pcx",NULL,player,32*32)) + return 0; + + // LOAD IN THE WORLD MAP + worldmap = (LPBYTE)ALLOC(WORLDMAPCX*WORLDMAPCY); + if (!worldmap) + return 0; + if (!SBmpLoadImage(ARTDIR "map.pcx",NULL,worldmap,WORLDMAPCX*WORLDMAPCY)) + return 0; + + // LOAD IN THE GRAPHICS TILESET + tileset = (LPBYTE)ALLOC(TILES*TILECX*TILECY); + if (!tileset) + return 0; + if (!SBmpLoadImage(ARTDIR "tileset.pcx",&pe[0],tileset,TILES*TILECX*TILECY)) + return 0; + + // CREATE A FONT + HSGDIFONT font; + { + HFONT winfont = CreateFont(-17,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_ROMAN,TEXT("Times New Roman")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + + return 1; +} + +//=========================================================================== +void MovePlayer (DWORD player) { + int xdir = orderpos[player].x-playerpos[player].x; + xdir = (xdir > 0) ? 1 : xdir ? -1 : 0; + int ydir = orderpos[player].y-playerpos[player].y; + ydir = (ydir > 0) ? 1 : ydir ? -1 : 0; + if (xdir) { + BYTE tile = *(worldmap+playerpos[player].y*WORLDMAPCX+playerpos[player].x+xdir); + if ((tile >= TILE_GRASS) && (tile != TILE_MOUNTAINS)) + playerpos[player].x += xdir; + } + if (ydir) { + BYTE tile = *(worldmap+(playerpos[player].y+ydir)*WORLDMAPCX+playerpos[player].x); + if ((tile >= TILE_GRASS) && (tile != TILE_MOUNTAINS)) + playerpos[player].y += ydir; + } +} + +//=========================================================================== +void CALLBACK OnButtonDown (LPPARAMS params) { + if (started) { + DWORD order[3] = {ORDER_MOVE, + (scrollpos.x+LOWORD(params->lparam))/TILECX, + (scrollpos.y+HIWORD(params->lparam))/TILECY}; + IssueOrder(&order[0],3); + } +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS) { + Destroy(); +} + +//=========================================================================== +void CALLBACK OnEraseBkgnd (LPPARAMS params) { + params->useresult = 1; + params->result = 1; +} + +//=========================================================================== +void CALLBACK OnPaint (LPPARAMS params) { + if (scrollbuffer && tileset) { + RECT rect = {0,0,SCROLLTILESX-1,SCROLLTILESY-1}; + FillScrollBuffer(&rect); + DrawScreen(); + } +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + DWORD order = ORDER_QUIT; + IssueOrder(&order,1); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + if (!started) { + DWORD order = ORDER_START; + IssueOrder(&order,1); + } +} + +//=========================================================================== +BOOL ProcessOrders () { + + // MAKE SURE THERE ARE ALWAYS AT LEAST TWO ORDERS IN TRANSIT + { + DWORD turns; + if (SNetGetTurnsInTransit(&turns)) { + while (turns < 2) { + DWORD order = ORDER_NULL; + IssueOrder(&order,1); + ++turns; + } + } + } + + // GATHER ORDERS FROM ALL PLAYERS + LPDWORD data[MAXPLAYERS]; + DWORD databytes[MAXPLAYERS]; + DWORD playerstatus[MAXPLAYERS]; + BOOL insync = 1; + { + int timeout = 20; + while ((!SNetReceiveTurns(0,players,(LPVOID *)&data[0],&databytes[0],&playerstatus[0])) && + --timeout) { + insync = 0; + Sleep(50); + } + if (!timeout) { + SDrawMessageBox("network error",TITLE,0); + SDrawPostClose(); + } + } + + // PROCESS EACH PLAYER'S ORDERS + for (DWORD player = 0; player < players; ++player) + if (data[player] && databytes[player]) + switch (*data[player]) { + + case ORDER_START: + started = 1; + break; + + case ORDER_MOVE: + orderpos[player].x = *(data[player]+1); + orderpos[player].y = *(data[player]+2); + break; + + case ORDER_QUIT: + SDrawPostClose(); + break; + + } + + return insync; +} + +//=========================================================================== +BOOL UpdateScrollVelocity () { + + // DETERMINE THE SCROLL DIRECTION + POINT pos; + GetCursorPos(&pos); + int x = (pos.x == 639) ? 1 : pos.x ? 0 : -1; + int y = (pos.y == 479) ? 1 : pos.y ? 0 : -1; + int velx = (scrollvel.x > 0) ? 1 : scrollvel.x ? -1 : 0; + int vely = (scrollvel.y > 0) ? 1 : scrollvel.y ? -1 : 0; + + // UPDATE THE X VELOCITY + if (x) { + if ((velx != x) || (abs(scrollvel.x) < 24)) + scrollvel.x += (abs(scrollvel.x) > 12) ? 2*x : x; + } + else if (velx) + scrollvel.x -= velx; + + // UPDATE THE Y VELOCITY + if (y) { + if ((vely != y) || (abs(scrollvel.y) < 16)) + scrollvel.y += (abs(scrollvel.y) > 8) ? 2*y : y; + } + else if (vely) + scrollvel.y -= vely; + + return (scrollvel.x || scrollvel.y); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!Initialize(instance)) { + Destroy(); + return 1; + } + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/SNET/RPG/RPG.CS b/src/Storm/SAMPLES/SNET/RPG/RPG.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/RPG/RPG.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SNET/RPG/RPG.EXE b/src/Storm/SAMPLES/SNET/RPG/RPG.EXE new file mode 100644 index 0000000..b483e4d Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/RPG.EXE differ diff --git a/src/Storm/SAMPLES/SNET/RPG/RPG.RC b/src/Storm/SAMPLES/SNET/RPG/RPG.RC new file mode 100644 index 0000000..9d9c0f3 --- /dev/null +++ b/src/Storm/SAMPLES/SNET/RPG/RPG.RC @@ -0,0 +1,105 @@ +//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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#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 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Blizzard Entertainment\0" + VALUE "FileDescription", "RPG Example\0" + VALUE "FileVersion", "1.0\0" + VALUE "InternalName", "RPG\0" + VALUE "LegalCopyright", "Copyright © 1996, Blizzard Entertainment\0" + VALUE "OriginalFilename", "RPG.exe\0" + VALUE "ProductName", "RPG Example\0" + VALUE "ProductVersion", "1.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SAMPLES/SNET/RPG/STANDARD.SNP b/src/Storm/SAMPLES/SNET/RPG/STANDARD.SNP new file mode 100644 index 0000000..8366cf5 Binary files /dev/null and b/src/Storm/SAMPLES/SNET/RPG/STANDARD.SNP differ diff --git a/src/Storm/SAMPLES/SRGN/BENCH/BENCH.CPP b/src/Storm/SAMPLES/SRGN/BENCH/BENCH.CPP new file mode 100644 index 0000000..8a3b139 --- /dev/null +++ b/src/Storm/SAMPLES/SRGN/BENCH/BENCH.CPP @@ -0,0 +1,100 @@ +/**************************************************************************** +* +* BENCH.CPP +* +* This program benchmarks the performance of Storm's region manager. +* +***/ + +#include +#include +#include + +#define TESTRECTS 3 +#define MAXCOMBINEDRECS 64 + +const RECT testrect[TESTRECTS] = {{100,100,300,300}, + {200,200,400,400}, + {100,300,300,500}}; + +//=========================================================================== +static void TestStorm (BOOL print) { + CSRgn rgn; + + for (DWORD loop = 0; loop < TESTRECTS; ++loop) + rgn.AddRect(&testrect[loop],NULL); + + RECT rectarray[MAXCOMBINEDRECS]; + DWORD numrects = MAXCOMBINEDRECS; + rgn.GetRects(&numrects,&rectarray[0]); + + if (print) { + printf("Storm\n"); + for (DWORD loop = 0; loop < numrects; ++loop) + printf("%u (%d,%d)-(%d,%d)\n", + loop, + rectarray[loop].left, + rectarray[loop].top, + rectarray[loop].right, + rectarray[loop].bottom); + printf("\n"); + } +} + +//=========================================================================== +static void TestWindows (BOOL print) { + HRGN rgn = CreateRectRgn(testrect[0].left, + testrect[0].top, + testrect[0].right, + testrect[0].bottom); + + for (DWORD loop = 1; loop < TESTRECTS; ++loop) { + HRGN newrgn = CreateRectRgn(testrect[loop].left, + testrect[loop].top, + testrect[loop].right, + testrect[loop].bottom); + CombineRgn(rgn,rgn,newrgn,RGN_OR); + DeleteObject(newrgn); + } + +#define BUFFERSIZE sizeof(RGNDATA)+MAXCOMBINEDRECS*sizeof(RECT) + BYTE buffer[BUFFERSIZE]; + RGNDATA *data = (RGNDATA *)&buffer[0]; + DWORD numrects = GetRegionData(rgn,BUFFERSIZE,data); +#undef BUFFERSIZE + + if (print) { + printf("Windows\n"); + for (DWORD loop = 0; loop < data->rdh.nCount; ++loop) + printf("%u (%d,%d)-(%d,%d)\n", + loop, + (((LPRECT)&data->Buffer[0])+loop)->left, + (((LPRECT)&data->Buffer[0])+loop)->top, + (((LPRECT)&data->Buffer[0])+loop)->right, + (((LPRECT)&data->Buffer[0])+loop)->bottom); + printf("\n"); + } + + DeleteObject(rgn); +} + +//=========================================================================== +static DWORD Benchmark (void (*func)(BOOL)) { + DWORD iterations = 0; + DWORD start = GetTickCount(); + while (GetTickCount()-start < 1000) + for (DWORD loop = 0; loop < 10; ++loop) { + func(FALSE); + ++iterations; + } + return iterations; +} + +//=========================================================================== +int __cdecl main () { + TestStorm(TRUE); + TestWindows(TRUE); + printf("Storm: %u iterations/sec\n",Benchmark(TestStorm)); + printf("Windows: %u iterations/sec\n",Benchmark(TestWindows)); + return 0; +} diff --git a/src/Storm/SAMPLES/SRGN/BENCH/BENCH.CS b/src/Storm/SAMPLES/SRGN/BENCH/BENCH.CS new file mode 100644 index 0000000..eb521a7 --- /dev/null +++ b/src/Storm/SAMPLES/SRGN/BENCH/BENCH.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set subsystem=console diff --git a/src/Storm/SAMPLES/SRGN/BENCH/BENCH.EXE b/src/Storm/SAMPLES/SRGN/BENCH/BENCH.EXE new file mode 100644 index 0000000..4ee3379 Binary files /dev/null and b/src/Storm/SAMPLES/SRGN/BENCH/BENCH.EXE differ diff --git a/src/Storm/SAMPLES/SSTR/BENCH/BENCH.CPP b/src/Storm/SAMPLES/SSTR/BENCH/BENCH.CPP new file mode 100644 index 0000000..910e554 --- /dev/null +++ b/src/Storm/SAMPLES/SSTR/BENCH/BENCH.CPP @@ -0,0 +1,57 @@ +/**************************************************************************** +* +* SSTR.CPP +* +* Benchmarks Storm's pattern blt performance. +* +***/ + +#include +#include +#include + +#define BENCHMARK(name,expr,reset) \ + do { \ + DWORD start = GetTickCount(); \ + DWORD curr; \ + while ((curr = GetTickCount()) == start) \ + ; \ + start = curr; \ + int dummy = 0; \ + DWORD iterations = 0; \ + while (GetTickCount()-start < 1000) { \ + for (int loop = 0; loop < 1000; ++loop) { \ + (expr); \ + (reset); \ + } \ + iterations += 1000; \ + } \ + printf("%-20s %7u/sec\n",(name),iterations); \ + } while (0) + + +//=========================================================================== +int __cdecl main () { + char buffer[] = "this is a test"; + char buffer2[256]; + BENCHMARK("strcpy()" ,strcpy(buffer2,buffer) ,0); + BENCHMARK("strncpy()" ,strncpy(buffer2,buffer,256) ,0); + BENCHMARK("lstrcpy()" ,lstrcpy(buffer2,buffer) ,0); + BENCHMARK("lstrcpyn()",lstrcpyn(buffer2,buffer,256),0); + BENCHMARK("SStrCopy()",SStrCopy(buffer2,buffer,256),0); + printf("\n"); + BENCHMARK("strcat()" ,strcat(buffer2,buffer) ,buffer2[14] = 0); + BENCHMARK("strncat()" ,strncat(buffer2,buffer,256-14),buffer2[14] = 0); + BENCHMARK("lstrcat()" ,lstrcat(buffer2,buffer) ,buffer2[14] = 0); + BENCHMARK("SStrPack()",SStrPack(buffer2,buffer,256) ,buffer2[14] = 0); + printf("\n"); + BENCHMARK("strlen()" ,dummy += strlen(buffer) ,0); + BENCHMARK("lstrlen()" ,dummy += lstrlen(buffer),0); + BENCHMARK("SStrLen()" ,dummy += SStrLen(buffer),0); + printf("\n"); + BENCHMARK("strchr()" ,dummy += (strchr(buffer,' ') != NULL) ,0); + BENCHMARK("SStrChr()" ,dummy += (SStrChr(buffer,' ') != NULL),0); + printf("\n"); + return 0; +} + diff --git a/src/Storm/SAMPLES/SSTR/BENCH/BENCH.CS b/src/Storm/SAMPLES/SSTR/BENCH/BENCH.CS new file mode 100644 index 0000000..eb521a7 --- /dev/null +++ b/src/Storm/SAMPLES/SSTR/BENCH/BENCH.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set subsystem=console diff --git a/src/Storm/SAMPLES/SSTR/BENCH/BENCH.EXE b/src/Storm/SAMPLES/SSTR/BENCH/BENCH.EXE new file mode 100644 index 0000000..d1e04b1 Binary files /dev/null and b/src/Storm/SAMPLES/SSTR/BENCH/BENCH.EXE differ diff --git a/src/Storm/SAMPLES/SSTR/CHECK/CHECK.CPP b/src/Storm/SAMPLES/SSTR/CHECK/CHECK.CPP new file mode 100644 index 0000000..028c4b8 --- /dev/null +++ b/src/Storm/SAMPLES/SSTR/CHECK/CHECK.CPP @@ -0,0 +1,195 @@ +/**************************************************************************** +* +* CHECK.CPP +* +* Checks the functionality of SStr functions +* +***/ + +#include +#include +#include + +#define FILLCHAR1 0x11 +#define FILLCHAR2 0x22 +#define FINDCHAR 100 +#define MAXLEN 260 +#define BUFFERSIZE (MAXLEN+2*sizeof(DWORD)+2) +#define FMTSTRING "Checking %-12s " + +#define FATALERROR \ + do { \ + printf("FAILURE!\n" \ + " str1len=%u\n" \ + " str1ofs=%u\n" \ + " str2len=%u\n" \ + " str2ofs=%u\n", \ + str1len, \ + str1ofs, \ + str2len, \ + str2ofs); \ + for (DWORD loop = 0; loop < BUFFERSIZE; ++loop) { \ + printf("%02x ",(DWORD)(BYTE)str1[loop]); \ + if ((loop & 15) == 15) \ + printf("\n"); \ + } \ + exit(1); \ + } while (0) + +#define ALLOCBUF \ + LPTSTR str1 = (LPTSTR)ALLOC(BUFFERSIZE); \ + LPTSTR str2 = (LPTSTR)ALLOC(BUFFERSIZE); \ + LPTSTR src = (LPTSTR)ALLOC(BUFFERSIZE) + +#define FREEBUF \ + FREE(str1); \ + FREE(str2); \ + FREE(src) + +#define ITERATE_1LEVEL \ + DWORD str2len = 0; \ + DWORD str2ofs = 0; \ + for (DWORD str1len = 0; str1len < MAXLEN; ++str1len) \ + for (DWORD str1ofs = 0; str1ofs < sizeof(DWORD); ++str1ofs) + +#define ITERATE_2LEVEL \ + for (DWORD str1len = 0; str1len < MAXLEN; ++str1len) \ + for (DWORD str1ofs = 0; str1ofs < sizeof(DWORD); ++str1ofs) \ + for (DWORD str2len = 0; str2len < MAXLEN; ++str2len) \ + for (DWORD str2ofs = 0; str2ofs <= sizeof(DWORD); ++str2ofs) + +#define RESETBUF \ + FillMemory(str1,BUFFERSIZE,FILLCHAR1); \ + FillMemory(str2,BUFFERSIZE,FILLCHAR2) + +#define BUILDSOURCE \ + do { \ + for (DWORD loop = 0; loop < BUFFERSIZE; ++loop) \ + src[loop] = ' '+(BYTE)(loop & 0x3F); \ + } while (0) + +#define COPYSOURCE(buffer,length) \ + if (length > 0) \ + CopyMemory((buffer),src,(length)); \ + (buffer)[(length)] = 0 + +#define SHOWPROGRESS \ + static DWORD iterations; \ + if (!(++iterations & 0xFFFF)) \ + printf(".") + +#define CHECKBEGIN \ + DWORD check = 0; \ + DWORD checkstart + +#define CHECK_FILLCHAR(num) \ + for (checkstart = check; check < checkstart+(num); ++check) \ + if (str1[check] != FILLCHAR1) \ + FATALERROR + +#define CHECK_SOURCE(num) \ + for (checkstart = check; check+1 < checkstart+(num); ++check) \ + if (str1[check] != src[check-checkstart]) \ + FATALERROR + +#define CHECK_NULL(num) \ + for (checkstart = check; check < checkstart+(num); ++check) \ + if (str1[check]) \ + FATALERROR + +#define CHECKEND + +//=========================================================================== +static void CheckSStrChr () { + printf(FMTSTRING,"SStrChr()"); + ALLOCBUF; + BUILDSOURCE; + ITERATE_2LEVEL { + RESETBUF; + COPYSOURCE(str1+str1ofs,BUFFERSIZE-str1ofs-1); + str1[str1ofs+str1len] = FINDCHAR; + str1[str1ofs+str2len] = FINDCHAR; + LPTSTR first = str1+str1ofs+min(str1len,str2len); + LPTSTR last = str1+str1ofs+max(str1len,str2len); + if (SStrChr(str1+str1ofs,FINDCHAR) != first) + FATALERROR; + if (SStrChr(str1+str1ofs,FINDCHAR,TRUE) != last) + FATALERROR; + SHOWPROGRESS; + } + FREEBUF; + printf(" done\n"); +} + +//=========================================================================== +static void CheckSStrCopy () { + printf(FMTSTRING,"SStrCopy()"); + ALLOCBUF; + BUILDSOURCE; + ITERATE_2LEVEL { + RESETBUF; + COPYSOURCE(str2+str2ofs,str2len); + SStrCopy(str1+str1ofs,str2+str2ofs,str1len); + CHECKBEGIN; + CHECK_FILLCHAR(str1ofs); + CHECK_SOURCE(min(str1len,str2len+1)); + CHECK_NULL(str1len ? 1 : 0); + CHECK_FILLCHAR(BUFFERSIZE-checkstart); + CHECKEND; + SHOWPROGRESS; + } + FREEBUF; + printf(" done\n"); +} + +//=========================================================================== +static void CheckSStrLen () { + printf(FMTSTRING,"SStrLen()"); + ALLOCBUF; + BUILDSOURCE; + ITERATE_1LEVEL { + RESETBUF; + COPYSOURCE(str1+str1ofs,str1len); + if (SStrLen(str1+str1ofs) != str1len) + FATALERROR; + SHOWPROGRESS; + } + FREEBUF; + printf("done\n"); +} + +//=========================================================================== +static void CheckSStrPack () { + printf(FMTSTRING,"SStrPack()"); + ALLOCBUF; + BUILDSOURCE; + ITERATE_2LEVEL { + RESETBUF; + COPYSOURCE(str1+str1ofs,str1len); + COPYSOURCE(str2+str2ofs,str2len); + DWORD bufferlen = BUFFERSIZE-str1ofs; + SStrPack(str1+str1ofs,str2+str2ofs,bufferlen); + CHECKBEGIN; + CHECK_FILLCHAR(str1ofs); + CHECK_SOURCE(str1len+1); + CHECK_SOURCE(min(bufferlen-str1len,str2len+1)); + CHECK_NULL(1); + CHECK_FILLCHAR(BUFFERSIZE-checkstart-1); + if (check < BUFFERSIZE) + CHECK_NULL(1); + CHECKEND; + SHOWPROGRESS; + } + FREEBUF; + printf(" done\n"); +} + +//=========================================================================== +int __cdecl main () { + CheckSStrChr(); + CheckSStrCopy(); + CheckSStrLen(); + CheckSStrPack(); + printf("No errors detected.\n"); + return 0; +} diff --git a/src/Storm/SAMPLES/SSTR/CHECK/CHECK.CS b/src/Storm/SAMPLES/SSTR/CHECK/CHECK.CS new file mode 100644 index 0000000..eb521a7 --- /dev/null +++ b/src/Storm/SAMPLES/SSTR/CHECK/CHECK.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set subsystem=console diff --git a/src/Storm/SAMPLES/SSTR/CHECK/CHECK.EXE b/src/Storm/SAMPLES/SSTR/CHECK/CHECK.EXE new file mode 100644 index 0000000..a87b14f Binary files /dev/null and b/src/Storm/SAMPLES/SSTR/CHECK/CHECK.EXE differ diff --git a/src/Storm/SAMPLES/STRANS/BENCH/BENCH.CPP b/src/Storm/SAMPLES/STRANS/BENCH/BENCH.CPP new file mode 100644 index 0000000..702afff --- /dev/null +++ b/src/Storm/SAMPLES/STRANS/BENCH/BENCH.CPP @@ -0,0 +1,130 @@ +/**************************************************************************** +* +* BENCH.CPP +* +* Benchmarks Storm's transparent bitblt performance. +* +***/ + +#include +#include + +#define ALIGNED + +HSGDIFONT font = (HSGDIFONT)0; +HSTRANS transparency[4] = {0,0,0,0}; +BOOL paused = 0; +DWORD iterations = 0; + +//=========================================================================== +BOOL LoadTransparency () { + LPBYTE bitmap = (LPBYTE)ALLOC(80*80); + if (!bitmap) + return 0; + PALETTEENTRY pe[256]; + if (!SBmpLoadImage("blizlogo.pcx",&pe[0],bitmap,80*80)) + return 0; + SDrawUpdatePalette(0,256,&pe[0]); + for (int loop = 0; loop < 4; ++loop) { + RECT rect = {loop*40,0,loop*40+39,39}; + STransCreate(bitmap,160,40,8,&rect,PALETTEINDEX(0),&transparency[loop]); + } + FREE(bitmap); + return 1; +} + +//=========================================================================== +BOOL LoadFont () { + { + HFONT winfont = CreateFont(-10,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_SWISS,TEXT("Arial")); + if (!SGdiImportFont(winfont,&font)) + return 0; + DeleteObject(winfont); + } + if (!SGdiSelectObject(font)) + return 0; + return 1; +} + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (paused) + return 0; + + static DWORD transnumber = 0; + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + for (int loop = 0; loop < 100; ++loop) { + int left = (rand() % 640)-20; + int top = (rand() % 450)+12; +#ifdef ALIGNED + left = (left >> 2) << 2; +#endif + STransBlt(videobuffer,left,top,pitch,transparency[transnumber++ & 3]); + ++iterations; + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + KillTimer(params->window,1); + SGdiDeleteObject(font); + for (int loop = 0; loop < 4; ++loop) + STransDelete(transparency[loop]); +} + +//=========================================================================== +void CALLBACK OnTimer (LPPARAMS) { + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + char outstr[64]; + wsprintf(outstr,"%u transparent bitblts per second",iterations); + RECT rect = {0,0,320,12}; + SGdiSetPitch(pitch); + SGdiExtTextOut(videobuffer, + 0, + 0, + &rect, + 0, + ETO_TEXT_WHITE, + ETO_BKG_BLACK, + outstr); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + iterations = 0; +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + if (!SDrawAutoInitialize(instance, + TEXT("DDBENCH"), + TEXT("Benchmark"))) + return 1; + if (!LoadTransparency()) + return 1; + if (!LoadFont()) + return 1; + SetTimer(SDrawGetFrameWindow(),1,1000,NULL); + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterMessage(NULL,WM_TIMER ,OnTimer); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + return SMsgDoMessageLoop(IdleProc); +} diff --git a/src/Storm/SAMPLES/STRANS/BENCH/BENCH.CS b/src/Storm/SAMPLES/STRANS/BENCH/BENCH.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/STRANS/BENCH/BENCH.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/STRANS/BENCH/BENCH.EXE b/src/Storm/SAMPLES/STRANS/BENCH/BENCH.EXE new file mode 100644 index 0000000..21697e8 Binary files /dev/null and b/src/Storm/SAMPLES/STRANS/BENCH/BENCH.EXE differ diff --git a/src/Storm/SAMPLES/STRANS/BENCH/BLIZLOGO.PCX b/src/Storm/SAMPLES/STRANS/BENCH/BLIZLOGO.PCX new file mode 100644 index 0000000..e7eeaab Binary files /dev/null and b/src/Storm/SAMPLES/STRANS/BENCH/BLIZLOGO.PCX differ diff --git a/src/Storm/SAMPLES/SVID/MULTI/MULTI.CPP b/src/Storm/SAMPLES/SVID/MULTI/MULTI.CPP new file mode 100644 index 0000000..e2ee8a6 --- /dev/null +++ b/src/Storm/SAMPLES/SVID/MULTI/MULTI.CPP @@ -0,0 +1,85 @@ +/**************************************************************************** +* +* MULTI.CPP +* +* Demonstrates playing back multiple video streams simultaneously. +* +***/ + +#include +#include + +#define VIDEOS 4 + +DWORD started = 0; +HSVIDEO video[VIDEOS] = {0,0,0,0}; + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + + // CHECK WHETHER WE NEED TO START A NEW VIDEO + static DWORD lasttime = 0; + DWORD currtime = GetTickCount(); + if ((currtime-lasttime > 1000) && (started < VIDEOS)) { + RECT rect; + rect.left = (started & 1)*320; + rect.top = (started & 2)*120; + rect.right = rect.left+319; + rect.bottom = rect.top+143; + SVidPlayBegin(TEXT("blizzard.smk"), + NULL,&rect,NULL,NULL, + SVID_FLAG_TOSCREEN | SVID_FLAG_1XSIZE, + &video[started++]); + lasttime = currtime; + } + + // CONTINUE PLAYING VIDEOS + if (!SVidPlayContinue()) + SDrawPostClose(); + + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + for (int loop = 0; loop < VIDEOS; ++loop) + if (video[loop]) + SVidPlayEnd(video[loop]); +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS params) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR cmdline, int) { + + // INTIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("VIDEOCLASS"), + TEXT("Video Player"))) + return 1; + ShowCursor(0); + + // REGISTER WINDOW MESSAGES + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + + // INITIALIZE THE VIDEO PLAYER + if (!SVidInitialize(NULL)) + return 1; + + // PLAY VIDEOS, STARTING A NEW ONE EACH SECOND UNTIL THEY ARE ALL STARTED, + // CONTINUING UNTIL THEY ARE ALL FINISHED + SMsgDoMessageLoop(IdleProc); + + // CLOSE ALL VIDEOS + { + for (DWORD loop = 0; loop < started; ++loop) + SVidPlayEnd(video[loop]); + } + + ShowCursor(1); + return 0; +} diff --git a/src/Storm/SAMPLES/SVID/MULTI/MULTI.CS b/src/Storm/SAMPLES/SVID/MULTI/MULTI.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SVID/MULTI/MULTI.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SVID/MULTI/MULTI.EXE b/src/Storm/SAMPLES/SVID/MULTI/MULTI.EXE new file mode 100644 index 0000000..8423ad8 Binary files /dev/null and b/src/Storm/SAMPLES/SVID/MULTI/MULTI.EXE differ diff --git a/src/Storm/SAMPLES/SVID/PAN/PAN.CPP b/src/Storm/SAMPLES/SVID/PAN/PAN.CPP new file mode 100644 index 0000000..2b4419e --- /dev/null +++ b/src/Storm/SAMPLES/SVID/PAN/PAN.CPP @@ -0,0 +1,91 @@ +/**************************************************************************** +* +* PAN.CPP +* +* Demonstrates panning the sound for a video. +* +***/ + +#include +#include + +#define VIDEOS 2 + +HSVIDEO video[VIDEOS] = {0,0}; + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + + // CHECK WHETHER WE NEED TO START A NEW VIDEO + static DWORD laststart = 0; + DWORD currtime = GetTickCount(); + for (DWORD loop = 0; loop < VIDEOS; ++loop) + if (video[loop]) { + BOOL updated; + if (!SVidPlayContinueSingle(video[loop],FALSE,&updated)) { + SVidPlayEnd(video[loop]); + video[loop] = (HSVIDEO)0; + } + } + else if (currtime-laststart > 3000) { + laststart = currtime; + RECT rect; + rect.left = (loop & 1)*320; + rect.top = (loop & 1)*240; + rect.right = rect.left+319; + rect.bottom = rect.top+143; + SVidPlayBegin(TEXT("blizzard.smk"), + NULL,&rect,NULL,NULL, + SVID_FLAG_TOSCREEN + | SVID_FLAG_1XSIZE + | SVID_FLAG_NEEDPAN, + &video[loop]); + SVidSetVolume(video[loop], + 0, + loop ? 10000 : -10000); + } + + return TRUE; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + for (int loop = 0; loop < VIDEOS; ++loop) + if (video[loop]) + SVidPlayEnd(video[loop]); +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS params) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR cmdline, int) { + + // INTIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("VIDEOCLASS"), + TEXT("Video Player"))) + return 1; + ShowCursor(0); + + // REGISTER WINDOW MESSAGES + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + + // INITIALIZE THE VIDEO PLAYER + if (!SVidInitialize(NULL)) + return 1; + + // PLAY VIDEOS + SMsgDoMessageLoop(IdleProc); + + // CLOSE ALL VIDEOS + for (DWORD loop = 0; loop < VIDEOS; ++loop) + if (video[loop]) + SVidPlayEnd(video[loop]); + + ShowCursor(1); + return 0; +} diff --git a/src/Storm/SAMPLES/SVID/PAN/PAN.CS b/src/Storm/SAMPLES/SVID/PAN/PAN.CS new file mode 100644 index 0000000..ad5af12 --- /dev/null +++ b/src/Storm/SAMPLES/SVID/PAN/PAN.CS @@ -0,0 +1 @@ +#include "../../sample.cs" diff --git a/src/Storm/SAMPLES/SVID/PAN/PAN.EXE b/src/Storm/SAMPLES/SVID/PAN/PAN.EXE new file mode 100644 index 0000000..30725a8 Binary files /dev/null and b/src/Storm/SAMPLES/SVID/PAN/PAN.EXE differ diff --git a/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.CPP b/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.CPP new file mode 100644 index 0000000..bee7a3e --- /dev/null +++ b/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.CPP @@ -0,0 +1,103 @@ +/**************************************************************************** +* +* PLAYER2.CPP +* +* A simple video player. +* +***/ + +#include +#include +#include + +HSVIDEO video = (HSVIDEO)0; + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (!SVidPlayContinue()) + SDrawPostClose(); + return 1; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + if (video) + SVidPlayEnd(video); +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS params) { + SDrawPostClose(); +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR cmdline, int) { + + // CHECK THE COMMAND LINE + if (!(cmdline && *cmdline)) { + MessageBox(0, + "Usage: PLAYER1 filename.smk", + "Video Player", + MB_ICONSTOP); + return 1; + } + + // INITIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("VIDEOCLASS"), + TEXT("Video Player"))) + return 1; + + // INITIALIZE DIRECTSOUND + LPDIRECTSOUND lpds = NULL; + if (DirectSoundCreate(NULL,&lpds,NULL) == DS_OK) { + + // SET THE COOPERATIVE LEVEL + if (lpds->SetCooperativeLevel(SDrawGetFrameWindow(),DSSCL_PRIORITY) != DS_OK) + if (lpds->SetCooperativeLevel(SDrawGetFrameWindow(),DSSCL_NORMAL) != DS_OK) + return 1; + + // CREAT A PRIMARY SOUND BUFFER + DSBUFFERDESC desc; + ZeroMemory(&desc,sizeof(DSBUFFERDESC)); + desc.dwSize = sizeof(DSBUFFERDESC); + desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; + LPDIRECTSOUNDBUFFER lpbuf; + lpds->CreateSoundBuffer(&desc,&lpbuf,NULL); + + // SET THE FORMAT OF THE PRIMARY SOUND BUFFER + WAVEFORMATEX format; + ZeroMemory(&format,sizeof(WAVEFORMATEX)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = 2; + format.nSamplesPerSec = 22050; + format.wBitsPerSample = 16; + format.nBlockAlign = (2*16)/8; // (nChannels*wBitsPerSample)/8 + format.nAvgBytesPerSec = ((2*16)/8)*22050; // nBlockAlign*nSamplesPerSec + format.cbSize = 0; + lpbuf->SetFormat(&format); + + } + + // REGISTER WINDOW MESSAGES + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + + // INITIALIZE THE VIDEO PLAYER + TCHAR dir[MAX_PATH] = TEXT(""); + GetCurrentDirectory(MAX_PATH,dir); + SFileSetBasePath(dir); + if (!SVidInitialize(lpds)) + return 1; + + // PLAY THE VIDEO + ShowCursor(0); + SVidPlayBegin(cmdline, + NULL,NULL,NULL,NULL, + SVID_AUTOCUTSCENE, + &video); + int result = SMsgDoMessageLoop(IdleProc); + ShowCursor(1); + + return result; +} diff --git a/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.CS b/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.CS new file mode 100644 index 0000000..f05ca5a --- /dev/null +++ b/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.CS @@ -0,0 +1,3 @@ +#include "../../sample.cs" +set extralib=dsound.lib + diff --git a/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.EXE b/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.EXE new file mode 100644 index 0000000..f07dbb8 Binary files /dev/null and b/src/Storm/SAMPLES/SVID/PLAYER1/PLAYER1.EXE differ diff --git a/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.CPP b/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.CPP new file mode 100644 index 0000000..27b17ef --- /dev/null +++ b/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.CPP @@ -0,0 +1,127 @@ +/**************************************************************************** +* +* PLAYER2.CPP +* +* A sample video player. This version allows the user to pause and to set +* the playback quality level. +* +***/ + +#include +#include +#include + +BOOL paused = 0; +HSVIDEO video = (HSVIDEO)0; + +//=========================================================================== +BOOL CALLBACK IdleProc (DWORD) { + if (!paused) { + if (!SVidPlayContinue()) + SDrawPostClose(); + } + return !paused; +} + +//=========================================================================== +void CALLBACK OnClose (LPPARAMS params) { + if (video) + SVidPlayEnd(video); +} + +//=========================================================================== +void CALLBACK OnVkEscape (LPPARAMS params) { + SDrawPostClose(); +} + +//=========================================================================== +void CALLBACK OnVkSpace (LPPARAMS params) { + paused = !paused; +} + +//=========================================================================== +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR cmdline, int) { + + // PARSE THE COMMAND LINE + if (!(cmdline && *cmdline)) { + MessageBox(0, + "Usage: PLAYER2 [qualitylevel] filename.smk\n\n" + "Quality Levels:\n" + "1 = Low (skip scans)\n" + "2 = Low (zoom)\n" + "3 = High (skip scans)\n" + "4 = High (zoom)", + "Video Player", + MB_ICONSTOP); + return 1; + } + int qualitylevel = SVID_QUALITY_HIGH; + if (atoi(cmdline)) { + switch (atoi(cmdline)) { + case 1: qualitylevel = SVID_QUALITY_LOW_SKIPSCANS; break; + case 2: qualitylevel = SVID_QUALITY_LOW; break; + case 3: qualitylevel = SVID_QUALITY_HIGH_SKIPSCANS; break; + case 4: qualitylevel = SVID_QUALITY_HIGH; break; + } + if (strchr(cmdline,' ')) + cmdline = strchr(cmdline,' ')+1; + else + cmdline += strlen(cmdline); + } + + // INTIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance, + TEXT("VIDEOCLASS"), + TEXT("Video Player"))) + return 1; + + // INITIALIZE DIRECTSOUND + LPDIRECTSOUND lpds = NULL; + if (DirectSoundCreate(NULL,&lpds,NULL) == DS_OK) { + + // SET THE COOPERATIVE LEVEL + lpds->SetCooperativeLevel(SDrawGetFrameWindow(), + DSSCL_NORMAL); + + // CREAT A PRIMARY SOUND BUFFER + DSBUFFERDESC desc; + ZeroMemory(&desc,sizeof(DSBUFFERDESC)); + desc.dwSize = sizeof(DSBUFFERDESC); + desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN; + LPDIRECTSOUNDBUFFER lpbuf; + lpds->CreateSoundBuffer(&desc,&lpbuf,NULL); + + // SET THE FORMAT OF THE PRIMARY SOUND BUFFER + WAVEFORMATEX format; + ZeroMemory(&format,sizeof(WAVEFORMATEX)); + format.wFormatTag = WAVE_FORMAT_PCM; + format.nChannels = 2; + format.nSamplesPerSec = 22050; + format.wBitsPerSample = 16; + format.nBlockAlign = (2*16)/8; // (nChannels*wBitsPerSample)/8 + format.nAvgBytesPerSec = ((2*16)/8)*22050; // nBlockAlign*nSamplesPerSec + format.cbSize = 0; + lpbuf->SetFormat(&format); + + } + + // REGISTER WINDOW MESSAGES + SMsgRegisterMessage(NULL,WM_CLOSE ,OnClose); + SMsgRegisterKeyDown(NULL,VK_ESCAPE,OnVkEscape); + SMsgRegisterKeyDown(NULL,VK_SPACE ,OnVkSpace); + + // INITIALIZE THE VIDEO PLAYER + if (!SVidInitialize(lpds)) + return 1; + + // PLAY THE VIDEO + ShowCursor(0); + SVidPlayBegin(cmdline, + NULL,NULL,NULL,NULL, + SVID_CUTSCENE | qualitylevel, + &video); + SMsgDoMessageLoop(IdleProc); + ShowCursor(1); + + return 0; +} diff --git a/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.CS b/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.CS new file mode 100644 index 0000000..a879725 --- /dev/null +++ b/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set extralib=dsound.lib diff --git a/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.EXE b/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.EXE new file mode 100644 index 0000000..db583f1 Binary files /dev/null and b/src/Storm/SAMPLES/SVID/PLAYER2/PLAYER2.EXE differ diff --git a/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.CPP b/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.CPP new file mode 100644 index 0000000..5e1ab5e --- /dev/null +++ b/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.CPP @@ -0,0 +1,42 @@ +/**************************************************************************** +* +* BASIC.CPP +* +* This sample demonstrates basic linked list operation using Storm's +* list manager. +* +***/ + +#include +#include +#include + +NODEDECL(TEST) { + LPCSTR string; +} *TESTPTR; + +static LIST(TEST) s_list; + +#define TESTSTRINGS 5 + +static const LPCSTR s_teststring[TESTSTRINGS] = + {"one","two","three","four","five"}; + +//=========================================================================== +int __cdecl main () { + + // ALLOCATE AND INITIALIZE THE NODES + for (int loop = 0; loop < TESTSTRINGS; ++loop) { + TESTPTR newnode = s_list.NewNode(); + newnode->string = s_teststring[loop]; + } + + // DUMP THE LIST CONTENTS TO THE SCREEN + ITERATELIST(TEST,s_list,curr) + printf("%s\n",curr->string); + + // DELETE ALL NODES + s_list.Clear(); + + return 0; +} diff --git a/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.CS b/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.CS new file mode 100644 index 0000000..eb521a7 --- /dev/null +++ b/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set subsystem=console diff --git a/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.EXE b/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.EXE new file mode 100644 index 0000000..79d042d Binary files /dev/null and b/src/Storm/SAMPLES/TSLIST/BASIC/BASIC.EXE differ diff --git a/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.CPP b/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.CPP new file mode 100644 index 0000000..2492b60 --- /dev/null +++ b/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.CPP @@ -0,0 +1,65 @@ +/**************************************************************************** +* +* MULTI.CPP +* +* This sample demonstrates the use of multiple links, allowing one node +* to be linked into more than one list. +* +***/ + +#include +#include +#include + +NODEDECLEX(TEST) { + LPCSTR string; + LINKEX(TEST) normallink; + LINKEX(TEST) sortedlink; +} *TESTPTR; + +static LISTEX(TEST,normallink) s_list; +static LISTEX(TEST,sortedlink) s_sortedlist; + +#define TESTSTRINGS 5 + +static const LPCSTR s_teststring[TESTSTRINGS] = + {"one","two","three","four","five"}; + +//=========================================================================== +static void DumpList (LISTPTREX(TEST) list) { + ITERATELISTPTR(TEST,list,curr) + printf("%s\n",curr->string); +} + +//=========================================================================== +int __cdecl main () { + + // ALLOCATE AND INITIALIZE THE NODES + for (int loop = 0; loop < TESTSTRINGS; ++loop) { + + // ALLOCATE A NEW NODE AND FILL IN ITS STRING + TESTPTR newnode = s_list.NewNode(); + newnode->string = s_teststring[loop]; + + // ADD IT TO THE SORTED LIST IN THE CORRECT ORDER + TESTPTR checknode = s_sortedlist.Head(); + while (checknode && (_stricmp(checknode->string,newnode->string) < 0)) + checknode = s_sortedlist.Next(checknode); + s_sortedlist.LinkNode(newnode,LIST_LINK_BEFORE,checknode); + + } + + // DUMP BOTH LISTS TO THE SCREEN + printf("List Sorted By Add Order\n"); + DumpList(&s_list); + printf("\nList Sorted Alphabetically\n"); + DumpList(&s_sortedlist); + + // DELETE ALL NODES + // (UPON DELETION, EACH NODE IS AUTOMATICALLY UNLINKED FROM EVERY LIST + // IT'S LINKED INTO, SO THERE'S NO NEED TO SEPARATELY PROCESS THE + // SORTED LIST) + s_list.Clear(); + + return 0; +} diff --git a/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.CS b/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.CS new file mode 100644 index 0000000..eb521a7 --- /dev/null +++ b/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set subsystem=console diff --git a/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.EXE b/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.EXE new file mode 100644 index 0000000..82d050c Binary files /dev/null and b/src/Storm/SAMPLES/TSLIST/MULTI/MULTI.EXE differ diff --git a/src/Storm/SAMPLES/TSLIST/TREE/TREE.CPP b/src/Storm/SAMPLES/TSLIST/TREE/TREE.CPP new file mode 100644 index 0000000..a85f4ff --- /dev/null +++ b/src/Storm/SAMPLES/TSLIST/TREE/TREE.CPP @@ -0,0 +1,63 @@ +/**************************************************************************** +* +* TREE.CPP +* +* This sample demonstrates using linked lists to implement a tree structure. +* +***/ + +#include +#include +#include + +NODEDECL(TEST) { + LPCSTR string; + LIST(TEST) children; + + ~TEST () { + children.Clear(); + } + +} *TESTPTR; + +static LIST(TEST) s_list; + +//=========================================================================== +static void DumpListRecursive (LISTPTR(TEST) list, int depth) { + ITERATELISTPTR(TEST,list,curr) { + printf("%*s%s\n",depth,"",curr->string); + DumpListRecursive(&curr->children,depth+1); + } +} + +//=========================================================================== +int __cdecl main () { + + // CREATE A TREE STRUCTURE FOR TESTING PURPOSES + TESTPTR one = s_list.NewNode(); + TESTPTR two = one->children.NewNode(); + TESTPTR three = one->children.NewNode(); + TESTPTR four = one->children.NewNode(); + TESTPTR five = three->children.NewNode(); + one->string = "one"; + two->string = "two"; + three->string = "three"; + four->string = "four"; + five->string = "five"; + + // DUMP THE TREE TO THE SCREEN + printf("Original Tree Structure\n"); + DumpListRecursive(&s_list,0); + + // DEMONSTRATE DELETING A NODE + delete three; + + // DUMP THE MODIFIED TREE TO THE SCREEN + printf("\nAfter Deleting Node Three\n"); + DumpListRecursive(&s_list,0); + + // DELETE ALL REMAINING NODES + s_list.Clear(); + + return 0; +} diff --git a/src/Storm/SAMPLES/TSLIST/TREE/TREE.CS b/src/Storm/SAMPLES/TSLIST/TREE/TREE.CS new file mode 100644 index 0000000..eb521a7 --- /dev/null +++ b/src/Storm/SAMPLES/TSLIST/TREE/TREE.CS @@ -0,0 +1,2 @@ +#include "../../sample.cs" +set subsystem=console diff --git a/src/Storm/SAMPLES/TSLIST/TREE/TREE.EXE b/src/Storm/SAMPLES/TSLIST/TREE/TREE.EXE new file mode 100644 index 0000000..d0c08f3 Binary files /dev/null and b/src/Storm/SAMPLES/TSLIST/TREE/TREE.EXE differ diff --git a/src/Storm/SAVE/STORM9~1.ZIP b/src/Storm/SAVE/STORM9~1.ZIP new file mode 100644 index 0000000..a049b04 Binary files /dev/null and b/src/Storm/SAVE/STORM9~1.ZIP differ diff --git a/src/Storm/SMACKER/BIN/SMACKW32.DLL b/src/Storm/SMACKER/BIN/SMACKW32.DLL new file mode 100644 index 0000000..0e9c4a0 Binary files /dev/null and b/src/Storm/SMACKER/BIN/SMACKW32.DLL differ diff --git a/src/Storm/SMACKER/H/RAD.H b/src/Storm/SMACKER/H/RAD.H new file mode 100644 index 0000000..480662e --- /dev/null +++ b/src/Storm/SMACKER/H/RAD.H @@ -0,0 +1,499 @@ +#ifndef __RAD__ +#define __RAD__ + +#define RADCOPYRIGHT "Copyright (C) 1994-97 RAD Game Tools, Inc." + +#ifndef __RADRES__ + +// __RADDOS__ means DOS code (16 or 32 bit) +// __RAD16__ means 16 bit code (Win16) +// __RAD32__ means 32 bit code (DOS, Win386, Win32s, Mac) +// __RADWIN__ means Windows code (Win16, Win386, Win32s) +// __RADWINEXT__ means Windows 386 extender (Win386) +// __RADNT__ means Win32s code +// __RADMAC__ means Macintosh +// __RAD68K__ means 68K Macintosh +// __RADPPC__ means PowerMac + + +#if defined(__MWERKS__) || defined(THINK_C) || defined(powerc) || defined(macintosh) || defined(__powerc) + + #define __RADMAC__ + #if defined(powerc) || defined(__powerc) + #define __RADPPC__ + #else + #define __RAD68K__ + #endif + + #define __RAD32__ + +#else + + #ifdef __DOS__ + #define __RADDOS__ + #endif + + #ifdef __386__ + #define __RAD32__ + #endif + + #ifdef _Windows //For Borland + #ifdef __WIN32__ + #define WIN32 + #else + #define __WINDOWS__ + #endif + #endif + + #ifdef _WINDOWS //For MS + #ifndef _WIN32 + #define __WINDOWS__ + #endif + #endif + + #ifdef _WIN32 + #define __RADWIN__ + #define __RADNT__ + #define __RAD32__ + #else + #ifdef __NT__ + #define __RADWIN__ + #define __RADNT__ + #define __RAD32__ + #else + #ifdef __WINDOWS_386__ + #define __RADWIN__ + #define __RADWINEXT__ + #define __RAD32__ + #else + #ifdef __WINDOWS__ + #define __RADWIN__ + #define __RAD16__ + #else + #ifdef WIN32 + #define __RADWIN__ + #define __RADNT__ + #define __RAD32__ + #endif + #endif + #endif + #endif + #endif + +#endif + +#if (!defined(__RADDOS__) && !defined(__RADWIN__) && !defined(__RADMAC__)) + #error RAD.H did not detect your platform. Define __DOS__, __WINDOWS__, WIN32, macintosh, or powerc. +#endif + +#ifdef __RADMAC__ + + // this define is for CodeWarrior 11's stupid new libs (even though + // we don't use longlong's). + + #define __MSL_LONGLONG_SUPPORT__ + + #define RADLINK + #define RADEXPLINK + + #ifdef __CFM68K__ + #ifdef __RADINDLL__ + #define RADEXPFUNC RADDEFFUNC __declspec(export) + #else + #define RADEXPFUNC RADDEFFUNC __declspec(import) + #endif + #else + #define RADEXPFUNC RADDEFFUNC + #endif + #define RADASMLINK + +#else + + #ifdef __RADNT__ + #ifndef _WIN32 + #define _WIN32 + #endif + #ifndef WIN32 + #define WIN32 + #endif + #endif + + #ifdef __RADWIN__ + #ifdef __RAD32__ + #ifdef __RADNT__ + + #define RADLINK __stdcall + #define RADEXPLINK __stdcall + + #ifdef __RADINEXE__ + #define RADEXPFUNC RADDEFFUNC + #else + #ifndef __RADINDLL__ + #define RADEXPFUNC RADDEFFUNC __declspec(dllimport) + #ifdef __BORLANDC__ + #if __BORLANDC__<=0x460 + #undef RADEXPFUNC + #define RADEXPFUNC RADDEFFUNC + #endif + #endif + #else + #define RADEXPFUNC RADDEFFUNC __declspec(dllexport) + #endif + #endif + #else + #define RADLINK __pascal + #define RADEXPLINK __far __pascal + #define RADEXPFUNC RADDEFFUNC + #endif + #else + #define RADLINK __pascal + #define RADEXPLINK __far __pascal __export + #define RADEXPFUNC RADDEFFUNC + #endif + #else + #define RADLINK __pascal + #define RADEXPLINK __pascal + #define RADEXPFUNC RADDEFFUNC + #endif + + #define RADASMLINK __cdecl + +#endif + +#ifdef __RADWIN__ + #ifndef _WINDOWS + #define _WINDOWS + #endif +#endif + +#ifdef __cplusplus + #define RADDEFFUNC extern "C" + #define RADDEFSTART extern "C" { + #define RADDEFEND } +#else + #define RADDEFFUNC + #define RADDEFSTART + #define RADDEFEND +#endif + + +RADDEFSTART + +#define s8 signed char +#define u8 unsigned char +#define u32 unsigned long +#define s32 signed long + +#ifdef __RAD32__ + #define PTR4 + + #define u16 unsigned short + #define s16 signed short + + #ifdef __RADMAC__ + + #include + #include + #include + + #define radstrlen strlen + + #define radmemset memset + + #define radmemcmp memcmp + + #define radmemcpy(dest,source,size) BlockMoveData((Ptr)(source),(Ptr)(dest),size) + + #define radmemcpydb(dest,source,size) BlockMoveData((Ptr)(source),(Ptr)(dest),size) + + #define radstrcpy strcpy + + #ifdef __RAD68K__ + + #pragma parameter __D0 mult64anddiv(__D0,__D1,__D2) + u32 mult64anddiv(u32 m1,u32 m2,u32 d) ={0x4C01,0x0C01,0x4C42,0x0C01}; + // muls.l d1,d1:d0 divs.l d2,d1:d0 + + #pragma parameter radconv32a(__A0,__D0) + void radconv32a(void* p,u32 n) ={0x4A80,0x600C,0x2210,0xE059,0x4841,0xE059,0x20C1,0x5380,0x6EF2}; + // tst.l d0 bra.s @loope @loop: move.l (a0),d1 ror.w #8,d1 swap d1 ror.w #8,d1 move.l d1,(a0)+ sub.l #1,d0 bgt.s @loop @loope: + + #else + + u32 mult64anddiv(u32 m1,u32 m2,u32 d); + + void radconv32a(void* p,u32 n); + + #endif + + #else + + #ifdef __WATCOMC__ + + u32 radsqr(s32 a); + #pragma aux radsqr = "mul eax" parm [eax] modify [EDX eax]; + + u32 mult64anddiv(u32 m1,u32 m2,u32 d); + #pragma aux mult64anddiv = "mul ecx" "div ebx" parm [eax] [ecx] [ebx] modify [EDX eax]; + + s32 radabs(s32 ab); + #pragma aux radabs = "test eax,eax" "jge skip" "neg eax" "skip:" parm [eax]; + + #define radabs32 radabs + + u32 DOSOut(const char* str); + #pragma aux DOSOut = "cld" "mov ecx,0xffffffff" "xor eax,eax" "mov edx,edi" "repne scasb" "not ecx" "dec ecx" "mov ebx,1" "mov ah,0x40" "int 0x21" parm [EDI] modify [EAX EBX ECX EDX EDI] value [ecx]; + + void DOSOutNum(const char* str,u32 len); + #pragma aux DOSOutNum = "mov ah,0x40" "mov ebx,1" "int 0x21" parm [edx] [ecx] modify [eax ebx]; + + u32 ErrOut(const char* str); + #pragma aux ErrOut = "cld" "mov ecx,0xffffffff" "xor eax,eax" "mov edx,edi" "repne scasb" "not ecx" "dec ecx" "xor ebx,ebx" "mov ah,0x40" "int 0x21" parm [EDI] modify [EAX EBX ECX EDX EDI] value [ecx]; + + void ErrOutNum(const char* str,u32 len); + #pragma aux ErrOutNum = "mov ah,0x40" "xor ebx,ebx" "int 0x21" parm [edx] [ecx] modify [eax ebx]; + + void radmemset16(void* dest,u16 value,u32 size); + #pragma aux radmemset16 = "cld" "mov bx,ax" "shl eax,16" "mov ax,bx" "mov bl,cl" "shr ecx,1" "rep stosd" "mov cl,bl" "and cl,1" "rep stosw" parm [EDI] [EAX] [ECX] modify [EAX EDX EBX ECX EDI]; + + void radmemset(void* dest,u8 value,u32 size); + #pragma aux radmemset = "cld" "mov ah,al" "mov bx,ax" "shl eax,16" "mov ax,bx" "mov bl,cl" "shr ecx,2" "and bl,3" "rep stosd" "mov cl,bl" "rep stosb" parm [EDI] [AL] [ECX] modify [EAX EDX EBX ECX EDI]; + + void radmemset32(void* dest,u32 value,u32 size); + #pragma aux radmemset32 = "cld" "rep stosd" parm [EDI] [EAX] [ECX] modify [EAX EDX EBX ECX EDI]; + + void radmemcpy(void* dest,const void* source,u32 size); + #pragma aux radmemcpy = "cld" "mov bl,cl" "shr ecx,2" "rep movsd" "mov cl,bl" "and cl,3" "rep movsb" parm [EDI] [ESI] [ECX] modify [EBX ECX EDI ESI]; + + void __far *radfmemcpy(void __far* dest,const void __far* source,u32 size); + #pragma aux radfmemcpy = "cld" "push es" "push ds" "mov es,cx" "mov ds,dx" "mov ecx,eax" "shr ecx,2" "rep movsd" "mov cl,al" "and cl,3" "rep movsb" "pop ds" "pop es" parm [CX EDI] [DX ESI] [EAX] modify [ECX EDI ESI] value [CX EDI]; + + void radmemcpydb(void* dest,const void* source,u32 size); //Destination bigger + #pragma aux radmemcpydb = "std" "mov bl,cl" "lea esi,[esi+ecx-4]" "lea edi,[edi+ecx-4]" "shr ecx,2" "rep movsd" "and bl,3" "jz dne" "add esi,3" "add edi,3" "mov cl,bl" "rep movsb" "dne:" "cld" parm [EDI] [ESI] [ECX] modify [EBX ECX EDI ESI]; + + char* radstrcpy(void* dest,const void* source); + #pragma aux radstrcpy = "cld" "mov edx,edi" "lp:" "mov al,[esi]" "inc esi" "mov [edi],al" "inc edi" "cmp al,0" "jne lp" parm [EDI] [ESI] modify [EAX EDX EDI ESI] value [EDX]; + + char __far* radfstrcpy(void __far* dest,const void __far* source); + #pragma aux radfstrcpy = "cld" "push es" "push ds" "mov es,cx" "mov ds,dx" "mov edx,edi" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" "pop ds" "pop es" parm [CX EDI] [DX ESI] modify [EAX EDX EDI ESI] value [CX EDX]; + + char* radstpcpy(void* dest,const void* source); + #pragma aux radstpcpy = "cld" "lp:" "mov al,[esi]" "inc esi" "mov [edi],al" "inc edi" "cmp al,0" "jne lp" "dec edi" parm [EDI] [ESI] modify [EAX EDI ESI] value [EDI]; + + char* radstpcpyrs(void* dest,const void* source); + #pragma aux radstpcpyrs = "cld" "lp:" "mov al,[esi]" "inc esi" "mov [edi],al" "inc edi" "cmp al,0" "jne lp" "dec esi" parm [EDI] [ESI] modify [EAX EDI ESI] value [ESI]; + + u32 radstrlen(const void* dest); + #pragma aux radstrlen = "cld" "mov ecx,0xffffffff" "xor eax,eax" "repne scasb" "not ecx" "dec ecx" parm [EDI] modify [EAX ECX EDI] value [ECX]; + + char* radstrcat(void* dest,const void* source); + #pragma aux radstrcat = "cld" "mov ecx,0xffffffff" "mov edx,edi" "xor eax,eax" "repne scasb" "dec edi" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" \ + parm [EDI] [ESI] modify [EAX ECX EDI ESI] value [EDX]; + + char* radstrchr(const void* dest,char chr); + #pragma aux radstrchr = "cld" "lp:" "lodsb" "cmp al,dl" "je fnd" "cmp al,0" "jnz lp" "mov esi,1" "fnd:" "dec esi" parm [ESI] [DL] modify [EAX ESI] value [esi]; + + s8 radmemcmp(const void* s1,const void* s2,u32 len); + #pragma aux radmemcmp = "cld" "rep cmpsb" "setne al" "jbe end" "neg al" "end:" parm [EDI] [ESI] [ECX] modify [ECX EDI ESI]; + + s8 radstrcmp(const void* s1,const void* s2); + #pragma aux radstrcmp = "lp:" "mov al,[esi]" "mov ah,[edi]" "cmp al,ah" "jne set" "cmp al,0" "je set" "inc esi" "inc edi" "jmp lp" "set:" "setne al" "jbe end" "neg al" "end:" \ + parm [EDI] [ESI] modify [EAX EDI ESI]; + + s8 radstricmp(const void* s1,const void* s2); + #pragma aux radstricmp = "lp:" "mov al,[esi]" "mov ah,[edi]" "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub al,32" "c1:" "cmp ah,'a'" "jb c2" "cmp ah,'z'" "ja c2" "sub ah,32" "c2:" "cmp al,ah" "jne set" "cmp al,0" "je set" \ + "inc esi" "inc edi" "jmp lp" "set:" "setne al" "jbe end" "neg al" "end:" \ + parm [EDI] [ESI] modify [EAX EDI ESI]; + + s8 radstrnicmp(const void* s1,const void* s2,u32 len); + #pragma aux radstrnicmp = "lp:" "mov al,[esi]" "mov ah,[edi]" "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub al,32" "c1:" "cmp ah,'a'" "jb c2" "cmp ah,'z'" "ja c2" "sub ah,32" "c2:" "cmp al,ah" "jne set" "cmp al,0" "je set" \ + "dec ecx" "jz set" "inc esi" "inc edi" "jmp lp" "set:" "setne al" "jbe end" "neg al" "end:" \ + parm [EDI] [ESI] [ECX] modify [EAX ECX EDI ESI]; + + char* radstrupr(void* s1); + #pragma aux radstrupr = "mov ecx,edi" "lp:" "mov al,[edi]" "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub [edi],32" "c1:" "inc edi" "cmp al,0" "jne lp" parm [EDI] modify [EAX EDI] value [ecx]; + + char* radstrlwr(void* s1); + #pragma aux radstrlwr = "mov ecx,edi" "lp:" "mov al,[edi]" "cmp al,'A'" "jb c1" "cmp al,'Z'" "ja c1" "add [edi],32" "c1:" "inc edi" "cmp al,0" "jne lp" parm [EDI] modify [EAX EDI] value [ecx]; + + u32 radstru32(const void* dest); + #pragma aux radstru32 = "cld" "xor ecx,ecx" "xor ebx,ebx" "xor edi,edi" "lodsb" "cmp al,45" "jne skip2" "mov edi,1" "jmp skip" "lp:" "mov eax,10" "mul ecx" "lea ecx,[eax+ebx]" \ + "skip:" "lodsb" "skip2:" "cmp al,0x39" "ja dne" "cmp al,0x30" "jb dne" "mov bl,al" "sub bl,0x30" "jmp lp" "dne:" "test edi,1" "jz pos" "neg ecx" "pos:" \ + parm [ESI] modify [EAX EBX EDX EDI ESI] value [ecx]; + + u16 GetDS(); + #pragma aux GetDS = "mov ax,ds" value [ax]; + + #ifdef __RADWINEXT__ + + #define _16To32(ptr16) ((void*)(((GetSelectorBase((u16)(((u32)(ptr16))>>16))+((u16)(u32)(ptr16)))-GetSelectorBase(GetDS())))) + + #endif + + #ifndef __RADWIN__ + #define int86 int386 + #define int86x int386x + #endif + + #define u32regs x + #define u16regs w + + #else + + #define radstrcpy strcpy + #define radstrcat strcat + #define radmemcpy memcpy + #define radmemcpydb memmove + #define radmemcmp memcmp + #define radmemset memset + #define radstrlen strlen + #define radstrchr strchr + #define radtoupper toupper + #define radstru32(s) ((u32)atol(s)) + #define radstricmp _stricmp + #define radstrcmp strcmp + #define radstrupr _strupr + #define radstrlwr _strlwr + #define BreakPoint() _asm {int 3} + + #ifdef _MSC_VER + + #pragma warning( disable : 4035) + + typedef char* RADPCHAR; + + u32 __inline radsqr(u32 m){ _asm { _asm mov eax,[m] _asm mul eax } } + u32 __inline mult64anddiv(u32 m1,u32 m2, u32 d){ _asm { _asm mov eax,[m1] _asm mov ecx,[m2] _asm mul ecx _asm mov ecx,[d] _asm div ecx } } + s32 __inline radabs(s32 ab) { _asm { _asm mov eax,[ab] _asm test eax,eax _asm jge skip _asm neg eax _asm skip:} } + u8 __inline radinp(u16 p) { _asm { _asm mov dx,[p] _asm in al,dx } } + void __inline radoutp(u16 p,u8 v) { _asm { _asm mov dx,[p] _asm mov al,[v] _asm out dx,al } } + RADPCHAR __inline radstpcpy(char* p1, char* p2) { _asm { _asm mov edx,[p1] _asm mov ecx,[p2] _asm cld _asm lp: _asm mov al,[ecx] _asm inc ecx _asm mov [edx],al _asm inc edx _asm cmp al,0 _asm jne lp _asm dec edx _asm mov eax,edx } } + RADPCHAR __inline radstpcpyrs(char* p1, char* p2) { _asm { _asm mov edx,[p1] _asm mov ecx,[p2] _asm cld _asm lp: _asm mov al,[ecx] _asm inc ecx _asm mov [edx],al _asm inc edx _asm cmp al,0 _asm jne lp _asm dec ecx _asm mov eax,ecx } } + void __inline radmemset16(void* dest,u16 value,u32 sizeb) { _asm { _asm mov edi,[dest] _asm mov ax,[value] _asm mov ecx,[sizeb] _asm shl eax,16 _asm cld _asm mov ax,[value] _asm mov bl,cl _asm shr ecx,1 _asm rep stosd _asm mov cl,bl _asm and cl,1 _asm rep stosw } } + void __inline radmemset32(void* dest,u32 value,u32 sizeb) { _asm { _asm mov edi,[dest] _asm mov eax,[value] _asm mov ecx,[sizeb] _asm cld _asm rep stosd } } + + #pragma warning( default : 4035) + + #endif + + #endif + + #endif + +#else + + #define PTR4 __far + + #define u16 unsigned int + #define s16 signed int + + #ifdef __WATCOMC__ + + u32 radsqr(s32 a); + #pragma aux radsqr = "shl edx,16" "mov dx,ax" "mov eax,edx" "xor edx,edx" "mul eax" "shld edx,eax,16" parm [dx ax] modify [DX ax] value [dx ax]; + + s16 radabs(s16 ab); + #pragma aux radabs = "test ax,ax" "jge skip" "neg ax" "skip:" parm [ax] value [ax]; + + s32 radabs32(s32 ab); + #pragma aux radabs32 = "test dx,dx" "jge skip" "neg dx" "neg ax" "sbb dx,0" "skip:" parm [dx ax] value [dx ax]; + + u32 DOSOut(const char far* dest); + #pragma aux DOSOut = "cld" "and edi,0xffff" "mov dx,di" "mov ecx,0xffffffff" "xor eax,eax" 0x67 "repne scasb" "not ecx" "dec ecx" "mov bx,1" "push ds" "push es" "pop ds" "mov ah,0x40" "int 0x21" "pop ds" "movzx eax,cx" "shr ecx,16" \ + parm [ES DI] modify [AX BX CX DX DI ES] value [CX AX]; + + void DOSOutNum(const char far* str,u16 len); + #pragma aux DOSOutNum = "push ds" "mov ds,cx" "mov cx,bx" "mov ah,0x40" "mov bx,1" "int 0x21" "pop ds" parm [cx dx] [bx] modify [ax bx cx]; + + u32 ErrOut(const char far* dest); + #pragma aux ErrOut = "cld" "and edi,0xffff" "mov dx,di" "mov ecx,0xffffffff" "xor eax,eax" 0x67 "repne scasb" "not ecx" "dec ecx" "xor bx,bx" "push ds" "push es" "pop ds" "mov ah,0x40" "int 0x21" "pop ds" "movzx eax,cx" "shr ecx,16" \ + parm [ES DI] modify [AX BX CX DX DI ES] value [CX AX]; + + void ErrOutNum(const char far* str,u16 len); + #pragma aux ErrOutNum = "push ds" "mov ds,cx" "mov cx,bx" "mov ah,0x40" "xor bx,bx" "int 0x21" "pop ds" parm [cx dx] [bx] modify [ax bx cx]; + + void radmemset(void far *dest,u8 value,u32 size); + #pragma aux radmemset = "cld" "and edi,0ffffh" "shl ecx,16" "mov cx,bx" "mov ah,al" "mov bx,ax" "shl eax,16" "mov ax,bx" "mov bl,cl" "shr ecx,2" 0x67 "rep stosd" "mov cl,bl" "and cl,3" "rep stosb" parm [ES DI] [AL] [CX BX]; + + void radmemset16(void far* dest,u16 value,u32 size); + #pragma aux radmemset16 = "cld" "and edi,0ffffh" "shl ecx,16" "mov cx,bx" "mov bx,ax" "shl eax,16" "mov ax,bx" "mov bl,cl" "shr ecx,1" "rep stosd" "mov cl,bl" "and cl,1" "rep stosw" parm [ES DI] [AX] [CX BX]; + + void radmemcpy(void far* dest,const void far* source,u32 size); + #pragma aux radmemcpy = "cld" "push ds" "mov ds,dx" "and esi,0ffffh" "and edi,0ffffh" "shl ecx,16" "mov cx,bx" "shr ecx,2" 0x67 "rep movsd" "mov cl,bl" "and cl,3" "rep movsb" "pop ds" parm [ES DI] [DX SI] [CX BX] modify [CX SI DI ES]; + + s8 radmemcmp(const void far* s1,const void far* s2,u32 len); + #pragma aux radmemcmp = "cld" "push ds" "mov ds,dx" "shl ecx,16" "mov cx,bx" "rep cmpsb" "setne al" "jbe end" "neg al" "end:" "pop ds" parm [ES DI] [DX SI] [CX BX] modify [CX SI DI ES]; + + char far* radstrcpy(void far* dest,const void far* source); + #pragma aux radstrcpy = "cld" "push ds" "mov ds,dx" "and esi,0xffff" "and edi,0xffff" "mov dx,di" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" "pop ds" parm [ES DI] [DX SI] modify [AX DX DI SI ES] value [es dx]; + + char far* radstpcpy(void far* dest,const void far* source); + #pragma aux radstpcpy = "cld" "push ds" "mov ds,dx" "and esi,0xffff" "and edi,0xffff" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" "dec di" "pop ds" parm [ES DI] [DX SI] modify [DI SI ES] value [es di]; + + u32 radstrlen(const void far* dest); + #pragma aux radstrlen = "cld" "and edi,0xffff" "mov ecx,0xffffffff" "xor eax,eax" 0x67 "repne scasb" "not ecx" "dec ecx" "movzx eax,cx" "shr ecx,16" parm [ES DI] modify [AX CX DI ES] value [CX AX]; + + char far* radstrcat(void far* dest,const void far* source); + #pragma aux radstrcat = "cld" "and edi,0xffff" "mov ecx,0xffffffff" "and esi,0xffff" "push ds" "mov ds,dx" "mov dx,di" "xor eax,eax" 0x67 "repne scasb" "dec edi" "lp:" "lodsb" "stosb" "test al,0xff" "jnz lp" "pop ds" \ + parm [ES DI] [DX SI] modify [AX CX DI SI ES] value [es dx]; + + char far* radstrchr(const void far* dest,char chr); + #pragma aux radstrchr = "cld" "lp:" 0x26 "lodsb" "cmp al,dl" "je fnd" "cmp al,0" "jnz lp" "xor ax,ax" "mov es,ax" "mov si,1" "fnd:" "dec si" parm [ES SI] [DL] modify [AX SI ES] value [es si]; + + s8 radstricmp(const void far* s1,const void far* s2); + #pragma aux radstricmp = "and edi,0xffff" "push ds" "mov ds,dx" "and esi,0xffff" "lp:" "mov al,[esi]" "mov ah,[edi]" "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub al,32" "c1:" \ + "cmp ah,'a'" "jb c2" "cmp ah,'z'" "ja c2" "sub ah,32" "c2:" "cmp al,ah" "jne set" "cmp al,0" "je set" \ + "inc esi" "inc edi" "jmp lp" "set:" "setne al" "jbe end" "neg al" "end:" "pop ds" \ + parm [ES DI] [DX SI] modify [AX DI SI]; + + u32 radstru32(const void far* dest); + #pragma aux radstru32 = "cld" "xor ecx,ecx" "xor ebx,ebx" "xor edi,edi" 0x26 "lodsb" "cmp al,45" "jne skip2" "mov edi,1" "jmp skip" "lp:" "mov eax,10" "mul ecx" "lea ecx,[eax+ebx]" \ + "skip:" 0x26 "lodsb" "skip2:" "cmp al,0x39" "ja dne" "cmp al,0x30" "jb dne" "mov bl,al" "sub bl,0x30" "jmp lp" "dne:" "test edi,1" "jz pos" "neg ecx" "pos:" \ + "movzx eax,cx" "shr ecx,16" parm [ES SI] modify [AX BX DX DI SI] value [cx ax]; + + u32 mult64anddiv(u32 m1,u32 m2,u32 d); + #pragma aux mult64anddiv = "shl ecx,16" "mov cx,ax" "shrd eax,edx,16" "mov ax,si" "mul ecx" "shl edi,16" "mov di,bx" "div edi" "shld edx,eax,16" "and edx,0xffff" "and eax,0xffff" parm [cx ax] [dx si] [di bx] \ + modify [ax bx cx dx si di] value [dx ax]; + + #endif + +#endif + +RADDEFEND + +#define u32neg1 ((u32)(s32)-1) +#define RAD_align(var) var; u8 junk##var[4-(sizeof(var)&3)]; +#define RAD_align_after(var) u8 junk##var[4-(sizeof(var)&3)]={0}; +#define RAD_align_init(var,val) var=val; u8 junk##var[4-(sizeof(var)&3)]={0}; +#define RAD_align_array(var,num) var[num]; u8 junk##var[4-(sizeof(var)&3)]; +#define RAD_align_string(var,str) char var[]=str; u8 junk##var[4-(sizeof(var)&3)]={0}; + +RADEXPFUNC void PTR4* RADEXPLINK radmalloc(u32 numbytes); +RADEXPFUNC void RADEXPLINK radfree(void PTR4* ptr); + +#ifdef __WATCOMC__ + + char bkbhit(); + #pragma aux bkbhit = "mov ah,1" "int 0x16" "lahf" "shr eax,14" "and eax,1" "xor al,1" ; + + char bgetch(); + #pragma aux bgetch = "xor ah,ah" "int 0x16" "test al,0xff" "jnz done" "mov al,ah" "or al,0x80" "done:" modify [AX]; + + void BreakPoint(); + #pragma aux BreakPoint = "int 3"; + + u8 radinp(u16 p); + #pragma aux radinp = "in al,dx" parm [DX]; + + u8 radtoupper(u8 p); + #pragma aux radtoupper = "cmp al,'a'" "jb c1" "cmp al,'z'" "ja c1" "sub al,32" "c1:" parm [al] value [al]; + + void radoutp(u16 p,u8 v); + #pragma aux radoutp = "out dx,al" parm [DX] [AL]; + +#endif + +#endif + +#endif + diff --git a/src/Storm/SMACKER/H/SMACK.H b/src/Storm/SMACKER/H/SMACK.H new file mode 100644 index 0000000..8ed535f --- /dev/null +++ b/src/Storm/SMACKER/H/SMACK.H @@ -0,0 +1,409 @@ +#ifndef SMACKH +#define SMACKH + +#define SMACKVERSION "3.1a" + +#ifndef __RADRES__ + + +#include "rad.h" + + +RADDEFSTART + +typedef struct SmackTag { + u32 Version; // SMK2 only right now + u32 Width; // Width (1 based, 640 for example) + u32 Height; // Height (1 based, 480 for example) + u32 Frames; // Number of frames (1 based, 100 = 100 frames) + u32 MSPerFrame; // Frame Rate + u32 SmackerType; // bit 0 set=ring frame + u32 LargestInTrack[7]; // Largest single size for each track + u32 tablesize; // Size of the init tables + u32 codesize; // Compression info + u32 absize; // ditto + u32 detailsize; // ditto + u32 typesize; // ditto + u32 TrackType[7]; // high byte=0x80-Comp,0x40-PCM data,0x20-16 bit,0x10-stereo + u32 extra; // extra value (should be zero) + u32 NewPalette; // set to one if the palette changed + u8 Palette[772]; // palette data + u32 PalType; // type of palette + u32 FrameNum; // Frame Number to be displayed + u32 FrameSize; // The current frame's size in bytes + u32 SndSize; // The current frame sound tracks' size in bytes + s32 LastRectx; // Rect set in from SmackToBufferRect (X coord) + s32 LastRecty; // Rect set in from SmackToBufferRect (Y coord) + s32 LastRectw; // Rect set in from SmackToBufferRect (Width) + s32 LastRecth; // Rect set in from SmackToBufferRect (Height) + u32 OpenFlags; // flags used on open + u32 LeftOfs; // Left Offset used in SmackTo + u32 TopOfs; // Top Offset used in SmackTo + u32 LargestFrameSize; // Largest frame size + u32 Highest1SecRate; // Highest 1 sec data rate + u32 Highest1SecFrame; // Highest 1 sec data rate starting frame + u32 ReadError; // Set to non-zero if a read error has ocurred + u32 addr32; // translated address for 16 bit interface +} Smack; + +#define SmackHeaderSize(smk) ((((u8*)&((smk)->extra))-((u8*)(smk)))+4) + +typedef struct SmackSumTag { + u32 TotalTime; // total time + u32 MS100PerFrame; // MS*100 per frame (100000/MS100PerFrame=Frames/Sec) + u32 TotalOpenTime; // Time to open and prepare for decompression + u32 TotalFrames; // Total Frames displayed + u32 SkippedFrames; // Total number of skipped frames + u32 SoundSkips; // Total number of sound skips + u32 TotalBlitTime; // Total time spent blitting + u32 TotalReadTime; // Total time spent reading + u32 TotalDecompTime; // Total time spent decompressing + u32 TotalBackReadTime; // Total time spent reading in background + u32 TotalReadSpeed; // Total io speed (bytes/second) + u32 SlowestFrameTime; // Slowest single frame time + u32 Slowest2FrameTime; // Second slowest single frame time + u32 SlowestFrameNum; // Slowest single frame number + u32 Slowest2FrameNum; // Second slowest single frame number + u32 AverageFrameSize; // Average size of the frame + u32 HighestMemAmount; // Highest amount of memory allocated + u32 TotalExtraMemory; // Total extra memory allocated + u32 HighestExtraUsed; // Highest extra memory actually used +} SmackSum; + + +//======================================================================= +#define SMACKNEEDPAN 0x00020L // Will be setting the pan +#define SMACKNEEDVOLUME 0x00040L // Will be setting the volume +#define SMACKFRAMERATE 0x00080L // Override fr (call SmackFrameRate first) +#define SMACKLOADEXTRA 0x00100L // Load the extra buffer during SmackOpen +#define SMACKPRELOADALL 0x00200L // Preload the entire animation +#define SMACKNOSKIP 0x00400L // Don't skip frames if falling behind +#define SMACKSIMULATE 0x00800L // Simulate the speed (call SmackSim first) +#define SMACKFILEHANDLE 0x01000L // Use when passing in a file handle +#define SMACKTRACK1 0x02000L // Play audio track 1 +#define SMACKTRACK2 0x04000L // Play audio track 2 +#define SMACKTRACK3 0x08000L // Play audio track 3 +#define SMACKTRACK4 0x10000L // Play audio track 4 +#define SMACKTRACK5 0x20000L // Play audio track 5 +#define SMACKTRACK6 0x40000L // Play audio track 6 +#define SMACKTRACK7 0x80000L // Play audio track 7 +#define SMACKTRACKS (SMACKTRACK1|SMACKTRACK2|SMACKTRACK3|SMACKTRACK4|SMACKTRACK5|SMACKTRACK6|SMACKTRACK7) + +#define SMACKBUFFERREVERSED 0x00000001 +#define SMACKBUFFER555 0x80000000 +#define SMACKBUFFER565 0xc0000000 +#define SMACKBUFFER16 (SMACKBUFFER555|SMACKBUFFER565) + +#define SMACKYINTERLACE 0x100000L // Force interleaving Y scaling +#define SMACKYDOUBLE 0x200000L // Force doubling Y scaling +#define SMACKYNONE (SMACKYINTERLACE|SMACKYDOUBLE) // Force normal Y scaling +#define SMACKFILEISSMK 0x2000000L // Internal flag for 16 to 32 bit thunking + +#define SMACKAUTOEXTRA 0xffffffffL // NOT A FLAG! - Use as extrabuf param +//======================================================================= + +#define SMACKSURFACEFAST 0 +#define SMACKSURFACESLOW 1 +#define SMACKSURFACEDIRECT 2 +#define SMACKSURFACEFASTWITHZERORECT 3 + + +RADEXPFUNC Smack PTR4* RADEXPLINK SmackOpen(const char PTR4* name,u32 flags,u32 extrabuf); + +#if defined(__RADMAC__) + #include + + RADEXPFUNC Smack PTR4* RADEXPLINK SmackMacOpen(FSSpec* fsp,u32 flags,u32 extrabuf); +#endif + +RADEXPFUNC u32 RADEXPLINK SmackDoFrame(Smack PTR4* smk); +RADEXPFUNC void RADEXPLINK SmackNextFrame(Smack PTR4* smk); +RADEXPFUNC u32 RADEXPLINK SmackWait(Smack PTR4* smk); +RADEXPFUNC void RADEXPLINK SmackClose(Smack PTR4* smk); + +RADEXPFUNC void RADEXPLINK SmackVolumePan(Smack PTR4* smk, u32 trackflag,u32 volume,u32 pan); + +RADEXPFUNC void RADEXPLINK SmackSummary(Smack PTR4* smk,SmackSum PTR4* sum); + +RADEXPFUNC u32 RADEXPLINK SmackSoundInTrack(Smack PTR4* smk,u32 trackflags); +RADEXPFUNC u32 RADEXPLINK SmackSoundOnOff(Smack PTR4* smk,u32 on); + +#ifndef __RADMAC__ +RADEXPFUNC void RADEXPLINK SmackToScreen(Smack PTR4* smk,u32 left,u32 top,u32 BytePS,const u16 PTR4* WinTbl,void* SetBank,u32 Flags); +#endif + +RADEXPFUNC void RADEXPLINK SmackToBuffer(Smack PTR4* smk,u32 left,u32 top,u32 Pitch,u32 destheight,const void PTR4* buf,u32 Flags); +RADEXPFUNC u32 RADEXPLINK SmackToBufferRect(Smack PTR4* smk, u32 SmackSurface); + +RADEXPFUNC void RADEXPLINK SmackGoto(Smack PTR4* smk,u32 frame); +RADEXPFUNC void RADEXPLINK SmackColorRemap(Smack PTR4* smk,const void PTR4* remappal,u32 numcolors,u32 paltype); +RADEXPFUNC void RADEXPLINK SmackColorTrans(Smack PTR4* smk,const void PTR4* trans); +RADEXPFUNC void RADEXPLINK SmackFrameRate(u32 forcerate); +RADEXPFUNC void RADEXPLINK SmackSimulate(u32 sim); + +RADEXPFUNC u32 RADEXPLINK SmackGetTrackData(Smack PTR4* smk,void PTR4* dest,u32 trackflag); + +RADEXPFUNC void RADEXPLINK SmackSoundCheck(void); + + +//====================================================================== + +// the functions for the new SmackBlit API + +typedef struct _SMACKBLIT PTR4* HSMACKBLIT; + +typedef struct _SMACKBLIT { + u32 Flags; + u8 PTR4* Palette; + u32 PalType; + u16 PTR4* SmoothTable; + u16 PTR4* Conv8to16Table; + u32 whichmode; + u32 palindex; + u32 t16index; + u32 smoothindex; + u32 smoothtype; +} SMACKBLIT; + +#define SMACKBLIT1X 1 +#define SMACKBLIT2X 2 +#define SMACKBLIT2XSMOOTHING 4 +#define SMACKBLIT2XINTERLACE 8 + +RADEXPFUNC HSMACKBLIT RADEXPLINK SmackBlitOpen(u32 flags); +RADEXPFUNC void RADEXPLINK SmackBlitSetPalette(HSMACKBLIT sblit, void PTR4* Palette,u32 PalType); +RADEXPFUNC u32 RADEXPLINK SmackBlitSetFlags(HSMACKBLIT sblit,u32 flags); +RADEXPFUNC void RADEXPLINK SmackBlit(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch); +RADEXPFUNC void RADEXPLINK SmackBlitClear(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, u32 destw, u32 desth, s32 color); +RADEXPFUNC void RADEXPLINK SmackBlitClose(HSMACKBLIT sblit); +RADEXPFUNC void RADEXPLINK SmackBlitTrans(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans); +RADEXPFUNC void RADEXPLINK SmackBlitMask(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans,void PTR4* mask); +RADEXPFUNC void RADEXPLINK SmackBlitMerge(HSMACKBLIT sblit,void PTR4* dest, u32 destpitch, u32 destx, u32 desty, void PTR4* src, u32 srcpitch, u32 srcx, u32 srcy, u32 srcw, u32 srch, u32 trans,void PTR4* back); +RADEXPFUNC char PTR4* RADEXPLINK SmackBlitString(HSMACKBLIT sblit,char PTR4* dest); + +#ifndef __RADMAC__ +RADEXPFUNC u32 RADEXPLINK SmackUseMMX(u32 flag); //0=off, 1=on, 2=query current +#endif + +//====================================================================== +#ifdef __RADDOS__ + + #define SMACKSOUNDNONE -1 + + extern void* SmackTimerSetupAddr; + extern void* SmackTimerReadAddr; + extern void* SmackTimerDoneAddr; + + typedef void RADEXPLINK (*SmackTimerSetupType)(void); + typedef u32 RADEXPLINK (*SmackTimerReadType)(void); + typedef void RADEXPLINK (*SmackTimerDoneType)(void); + + #define SmackTimerSetup() ((SmackTimerSetupType)(SmackTimerSetupAddr))() + #define SmackTimerRead() ((SmackTimerReadType)(SmackTimerReadAddr))() + #define SmackTimerDone() ((SmackTimerDoneType)(SmackTimerDoneAddr))() + + RADEXPFUNC u8 RADEXPLINK SmackSoundUseMSS(void* DigDriver); + + #ifndef AIL_startup + #ifdef __SW_3R + extern s32 cdecl AIL_startup_reg(void); + #define AIL_startup AIL_startup_reg + #else + extern s32 cdecl AIL_startup_stack(void); + #define AIL_startup AIL_startup_stack + #endif + #endif + #define SmackSoundMSSLiteInit() SmackSoundMSSLiteInitWithStart(&AIL_startup); + RADEXPFUNC void RADEXPLINK SmackSoundMSSLiteInitWithStart(void* start); + RADEXPFUNC void RADEXPLINK SmackSoundMSSLiteDone(void); + + RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS3r(u32 SOSDriver,u32 MaxTimerSpeed); + RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS3s(u32 SOSDriver,u32 MaxTimerSpeed); + RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS4r(u32 SOSDriver,u32 MaxTimerSpeed); + RADEXPFUNC u8 RADEXPLINK SmackSoundUseSOS4s(u32 SOSDriver,u32 MaxTimerSpeed); + + #ifdef __SW_3R + #define SmackSoundUseSOS3 SmackSoundUseSOS3r + #define SmackSoundUseSOS4 SmackSoundUseSOS4r + #else + #define SmackSoundUseSOS3 SmackSoundUseSOS3s + #define SmackSoundUseSOS4 SmackSoundUseSOS4s + #endif + +#else + + #define SMACKRESRESET 0 + #define SMACKRES640X400 1 + #define SMACKRES640X480 2 + #define SMACKRES800X600 3 + #define SMACKRES1024X768 4 + + RADEXPFUNC u32 RADEXPLINK SmackSetSystemRes(u32 mode); // use SMACKRES* values + + #define SMACKNOCUSTOMBLIT 128 + #define SMACKSMOOTHBLIT 256 + #define SMACKINTERLACEBLIT 512 + + #ifdef __RADMAC__ + + #include + #include + #include + + #define SmackTimerSetup() + #define SmackTimerDone() + RADEXPFUNC u32 RADEXPLINK SmackTimerRead(void); + + RADEXPFUNC u32 RADEXPLINK SmackBufferUseGDevice( GDHandle gd ); + + #define SMACKAUTOBLIT 0 + #define SMACKDIRECTBLIT 1 + #define SMACKGWORLDBLIT 2 + + typedef struct SmackBufTag { + u32 Reversed; + u32 SurfaceType; // SMACKSURFACExxxxxx + u32 BlitType; // SMACKxxxxxBLIT + u32 Width; + u32 Height; + u32 Pitch; + u32 Zoomed; + u32 ZWidth; + u32 ZHeight; + u32 DispColors; // colors on screen + u32 MaxPalColors; + u32 PalColorsInUse; + u32 StartPalColor; + u32 EndPalColor; + void* Buffer; + void* Palette; + u32 PalType; + u32 cursortype; + + WindowPtr wp; + GWorldPtr gwp; + CTabHandle cth; + PaletteHandle palh; + } SmackBuf; + + #else + + #ifdef __RADWIN__ + + #define INCLUDE_MMSYSTEM_H + #include "windows.h" + #include "windowsx.h" + + #ifdef __RADNT__ // to combat WIN32_LEAN_AND_MEAN + + #include "mmsystem.h" + + RADEXPFUNC s32 RADEXPLINK SmackDDSurfaceType(void* lpDDS); + + #endif + + #define SMACKAUTOBLIT 0 + #define SMACKFULL320X240BLIT 1 + #define SMACKFULL320X200BLIT 2 + #define SMACKFULL320X200DIRECTBLIT 3 + #define SMACKSTANDARDBLIT 4 + #define SMACKWINGBLIT 5 + #define SMACKDIBSECTIONBLIT 5 + + #define WM_SMACKACTIVATE WM_USER+0x5678 + + typedef struct SmackBufTag { + u32 Reversed; // 1 if the buffer is upside down + u32 SurfaceType; // SMACKSURFACExxxx defines + u32 BlitType; // SMACKxxxxBLIT defines + u32 FullScreen; // 1 if full-screen + u32 Width; + u32 Height; + u32 Pitch; + u32 Zoomed; + u32 ZWidth; + u32 ZHeight; + u32 DispColors; // colors on the screen + u32 MaxPalColors; // total possible colors in palette (usually 256) + u32 PalColorsInUse; // Used colors in palette (usually 236) + u32 StartPalColor; // first usable color index (usually 10) + u32 EndPalColor; // last usable color index (usually 246) + RGBQUAD Palette[256]; + u32 PalType; + u32 forceredraw; // force a complete redraw on next blit (for >8bit) + u32 didapalette; // force an invalidate on the next palette change + + void PTR4* Buffer; + void PTR4* DIBRestore; + u32 OurBitmap; + u32 OrigBitmap; + u32 OurPalette; + u32 WinGDC; + u32 FullFocused; + u32 ParentHwnd; + u32 OldParWndProc; + u32 OldDispWndProc; + u32 DispHwnd; + u32 WinGBufHandle; + void PTR4* lpDD; + void PTR4* lpDDSP; + u32 DDSurfaceType; + HSMACKBLIT DDblit; + s32 ddSoftwarecur; + s32 didaddblit; + s32 lastwasdd; + RECT ddscreen; + } SmackBuf; + + RADEXPFUNC void RADEXPLINK SmackGet(Smack PTR4* smk,void PTR4* dest); + RADEXPFUNC void RADEXPLINK SmackBufferGet( SmackBuf PTR4* sbuf, void PTR4* dest); + + RADEXPFUNC u8 RADEXPLINK SmackSoundUseMSS(void PTR4* dd); + RADEXPFUNC u8 RADEXPLINK SmackSoundUseDirectSound(void PTR4* dd); // NULL=Create + RADEXPFUNC void RADEXPLINK SmackSoundSetDirectSoundHWND(HWND hw); + RADEXPFUNC u8 RADEXPLINK SmackSoundUseDW(u32 openfreq, u32 openbits, u32 openchans); + + #define SmackTimerSetup() + #define SmackTimerDone() + #define SmackTimerRead timeGetTime + + #endif + + #endif + + #ifdef __RADMAC__ + RADEXPFUNC SmackBuf PTR4* RADEXPLINK SmackBufferOpen( WindowPtr wp, u32 BlitType, u32 width, u32 height, u32 ZoomW, u32 ZoomH ); + RADEXPFUNC u32 RADEXPLINK SmackBufferBlit( SmackBuf PTR4* sbuf, s32 hwndx, s32 hwndy, s32 subx, s32 suby, s32 subw, s32 subh ); + RADEXPFUNC void RADEXPLINK SmackBufferFromScreen( SmackBuf PTR4* destbuf, s32 x, s32 y); + #else + RADEXPFUNC SmackBuf PTR4* RADEXPLINK SmackBufferOpen( HWND wnd, u32 BlitType, u32 width, u32 height, u32 ZoomW, u32 ZoomH ); + RADEXPFUNC u32 RADEXPLINK SmackBufferBlit( SmackBuf PTR4* sbuf, HDC dc, s32 hwndx, s32 hwndy, s32 subx, s32 suby, s32 subw, s32 subh ); + RADEXPFUNC void RADEXPLINK SmackBufferFromScreen( SmackBuf PTR4* destbuf, HWND hw, s32 x, s32 y); + RADEXPFUNC s32 RADEXPLINK SmackIsSoftwareCursor(void* lpDDSP,HCURSOR cur); + RADEXPFUNC s32 RADEXPLINK SmackCheckCursor(HWND wnd,s32 x,s32 y,s32 w,s32 h); + RADEXPFUNC void RADEXPLINK SmackRestoreCursor(s32 checkcount); + #endif + + RADEXPFUNC char PTR4* RADEXPLINK SmackBufferString(SmackBuf PTR4* sb,char PTR4* dest); + + RADEXPFUNC void RADEXPLINK SmackBufferNewPalette( SmackBuf PTR4* sbuf, const void PTR4* pal, u32 paltype ); + RADEXPFUNC u32 RADEXPLINK SmackBufferSetPalette( SmackBuf PTR4* sbuf ); + RADEXPFUNC void RADEXPLINK SmackBufferClose( SmackBuf PTR4* sbuf ); + + RADEXPFUNC void RADEXPLINK SmackBufferClear( SmackBuf PTR4* destbuf, u32 color); + + RADEXPFUNC void RADEXPLINK SmackBufferToBuffer( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh); + RADEXPFUNC void RADEXPLINK SmackBufferToBufferTrans( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor); + RADEXPFUNC void RADEXPLINK SmackBufferToBufferMask( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor,const SmackBuf PTR4* maskbuf); + RADEXPFUNC void RADEXPLINK SmackBufferToBufferMerge( SmackBuf PTR4* destbuf, s32 destx, s32 desty, const SmackBuf PTR4* sourcebuf,s32 sourcex,s32 sourcey,s32 sourcew,s32 sourceh,u32 TransColor,const SmackBuf PTR4* mergebuf); + RADEXPFUNC void RADEXPLINK SmackBufferCopyPalette( SmackBuf PTR4* destbuf, SmackBuf PTR4* sourcebuf, u32 remap); + + RADEXPFUNC u32 RADEXPLINK SmackBufferFocused( SmackBuf PTR4* sbuf); + +#endif + +RADDEFEND + +#endif + +#endif diff --git a/src/Storm/SMACKER/H/SVGA.H b/src/Storm/SMACKER/H/SVGA.H new file mode 100644 index 0000000..b9f51e9 --- /dev/null +++ b/src/Storm/SMACKER/H/SVGA.H @@ -0,0 +1,53 @@ +#ifndef SVGAH +#define SVGAH + +RADDEFSTART + + typedef void (SETBANKTYPE)(u16); + #pragma aux SETBANKTYPE "*" parm [eax] modify [eax]; + + typedef void (SETINITTYPE)(); + #pragma aux SETINITTYPE "*" modify [eax ebx ecx edx]; + + #define SVGAMode() (curmodetouse) + u8 RADLINK SVGASetup(u32 width,u32 height); + char* RADLINK SVGADetected(char* buf); + void RADLINK SVGASetText(); + void RADLINK SVGASetGraph(); + void RADLINK SVGAClear(u8 col); + void RADLINK SVGADetect(u32 flags); + u32 RADLINK SVGABytesPS(); + u16* RADLINK SVGAWinTbl(); + void* RADLINK SVGASetBank(); + u32 RADLINK SVGAFlags(); + + void RADASMLINK SVGABlit(void* buf,u32 bleft,u32 btop,u32 subbwidth,u32 subbheight,u32 bPitch,u32 screenleft,u32 screentop); + + void RADASMLINK SVGABlitTrans(void* buf,u32 bleft,u32 btop,u32 subbwidth,u32 subbheight,u32 bwidth,u32 screenleft,u32 screentop,u8 trans); + void RADASMLINK SVGABlitFrom (void* buf,u32 bleft,u32 btop,u32 subbwidth,u32 subbheight,u32 bwidth,u32 screenleft,u32 screentop); + void RADASMLINK SVGABlitMask (void* buf,u32 bleft,u32 btop,u32 subbwidth,u32 subbheight,u32 bwidth,u32 screenleft,u32 screentop,u8 maskcolor,void*backbuf); + void RADASMLINK SVGABlitMerge(void* buf,u32 bleft,u32 btop,u32 subbwidth,u32 subbheight,u32 bwidth,u32 screenleft,u32 screentop,u8 mergecolor,void*backbuf); + + void RADASMLINK SVGASetPalette(void PTR4* pal); + + extern u8 curmodetouse; + extern u32 BytesPerScanToUse; + extern u32 WidthToUse; + extern u32 HeightToUse; + extern SETBANKTYPE* SetBankToUse; + extern u16* WinTblToUse; + extern u32 FlagsToUse; + extern void* StartVGA; + extern void* EndVGA; + extern u32 VGASize; + extern u8 PaletteSkipZero; + extern u8 IsBanked; + extern u8 SVGAVESASetting; + + +#define SVGAFINDSVGA 1 +#define SVGAUSE16BIT 2 + +RADDEFEND + +#endif diff --git a/src/Storm/SMACKER/HISTORY.TXT b/src/Storm/SMACKER/HISTORY.TXT new file mode 100644 index 0000000..7830931 --- /dev/null +++ b/src/Storm/SMACKER/HISTORY.TXT @@ -0,0 +1,828 @@ + ============================================================================ + + This file contains most of the development history of Smacker. + + It contains changes, updates, and fixes in the Smacker Tools, the + Smacker SDK, and the Smacker Xtra. + +============================================================================ + +3.1 a - 9/29/97 +--------------- +Added MMX support throughout Smacker - playback can now be up to 200% + faster on MMX machines! +Added the new SmackBlit API for all Smacker platforms - gives SDK users a + high-performance, low-level blitting library. Supports 1x, 2x, + 2x smoothed, 2x interlaced to either 8-bit or 16-bit surfaces! See the + ExamSmkB.C example program for a nifty demo of this new API. +Added replacement blitters for machines where DirectDraw has been installed + with using the SmackBuffer API - now, whenever possible, Smacker does its + own direct to screen blitting rather than using DIBSections. +Added masked and merged blitting to the SmackBuffer, SmackBlit, and DOS + SVGA blit libraries (for much faster transparencies). +The front-end can now process a group of files one-by-one instead of only + as a group. +Added a cursor API for detecting software cursors and then easily hiding and + restoring them (for direct to screen blitting or playback). +Rewrote the DirectSound support code - should now have perfect synch and + work on most emulated sound drivers. +The Xtra and the scriptor now use the merging blitter for faster playback. +Added BitmapToBitmapMerge and BitmapToScreenMerge command to the scriptor. +Fixed a bug on the Mac when decompressing 16-bit, stereo sound. +Added a "Play Last" button on the player tab that will play the last Smacker + animation that was compressed, mixed, played, etc. Great for quickly + viewing the last animation that you created. +Made the Smacker PC Xtra not use DirectSound unless you call the new + SmackUseDirectSound global command. +Added a 2x playback mode to the Smacker Xtra (including interlaced and + smoothed modes). +Added a SmackHideVideo command to the Smacker Xtra which allows you to + hide the video without closing the Smacker object. +Added a SmackSetAlignment command to the Smacker Xtra to control how the + playback window is automatically aligned. +Added the SmackScreenMethod call to the PC Xtra. +Switched to MASM 6.11 for most of the assembly files. +Added error return codes to the SmackSetTransBackground in the Xtra. +Fixed a playback bug in the Xtra when using a cast member background. +Added Win95, Win95 OSR2, WinNT, MMX, and Pentium II detection to RADSI. +Merged the 16-bit and 32-bit blitters into one 32-bit module. +On NT and 95, SmackBuffers now always use top-down DIBSections (even when + standard DIBS are requested). + +3.0 r - 8/6/97 +-------------- +Fixed a nasty race condition in the DirectSound shutdown code. +Fixed the compressor to honor the height when it was larger than the input + height (pads with black pixels). + +3.0 q - 8/1/97 +-------------- +Fixed an optimizer crash in the compressor and graphic processor when + halftoning both 8 and 24 bit files together. +Fixed crash in graphics processor if the input and output filenames matched. +Added some extra debug dumping info in the DirectSound module. + +3.0 p - 7/25/97 (skipped "o") +----------------------------- +Fixed the filename quoting in the mixer when you used a wave file with a + space in it. +Fixed a bug in the Mac decompression code where one of the block types was + decoded incorrectly. +Fixed a bug in the summary window in the Mac 68K player. +Fixed a Mac Xtra bug where the palette wasn't being copied from the Smacker + frame. + +3.0 n - 7/15/97 +--------------- +Fixed a bug in the graphics file input routines that could cause a crash + when compressing or converting under NT 4. +Added a debug dumping facility in the SDK. (Add "debug=1" under [Smacker] + in the win.ini file to enable.) + +3.0 m - 6/25/97 +--------------- +Worked around an optimizer bug that caused list files not be saved correctly. +Added AVI files as an output file in the graphics processor. +Added a true color support to the graphics processor (it can now copy + directly from a true color input file to a true color output file). +Fixed crash in RAD system information utility. +Fixed the close button not working in the player. + +3.0 L - 6/20/97 +--------------- +Converted all the Win32 code to the Microsoft compiler - the tools now run + about 20% faster! +Improved the color quantizer slightly by using human vision color model. +Put all of the common internal Smacker APIs into a utility DLL - saved about + 400K after installation. +Fixed a crash in SmackOpen when the Smack file could not be found. +Fixed a crash in the 16-bit Smacker Xtra. +Fixed the ScreenWindowHWND command in the scriptor. +Removed the SmkW32MS.LIB file from the SDK - use SmackW32.LIB for both + Microsoft and Watcom compilers. + +3.0 k - 6/2/97 +-------------- +Added new Smacker file compiler - compile one or more Smks into an EXE. +Player tab can now view files other than Smacks (double-click). +Added many speed-ups in the Mac Xtra. +Cleaned-up some palette problems in the Mac Xtra. +Fixed the preload option in the Xtra on both PCs and Macs. +Added new SmackGetSummary command in the Xtra to report runtime performance. +Fixed return codes on the utilities. +Tools check for running out of disk space more frequently. +Fixed bug in 16-bit SDK when playing with a file handle. +Fixed a bug in the DOS player where playback could stick on the final frame. +Added a new example for 16-bit DirectDraw with 8-bit off-screen surface. +Updated to Delphi 3 for the Tools front-end. +Dropped the DOS based Tools (the DOS player, scriptor and SDK remain). + +3.0 j - 5/14/97 +-------------- +Fixed SmackGoto not setting the 16-bit palette. +Compressed the front-end executable. +Fixed the left offsets when playing into a 16-bit surface. +Finished the Mac Xtra for Director. + +3.0 i - 5/4/97 +-------------- +Smacker can decompress directly into a 16-bit buffer (on- or off-screen). +DirectDraw example programs now all support 16-bit surfaces. +Fixed the Windows and icons moving when changing the video mode in Win 95. +Changed the Mac version to try to allocate the GWorld in temp memory if + normal memory fails (helps in low mem situations). +Fixed scriptor FileFind command to return all files under Win 95 or Win NT. +Set the primary buffer format when NULL is passed to SmackSoundUseDirectSound. +Added 16-bit VESA support to SDK - use SVGAUSE16BIT in SVGADetect. +Added a flags parameter to the SmackToScreen call - you will usually just + pass SVGAFlags() - see Example.c for details. +Added a warning when the hint file could not be opened. +Fixed a problem in the front-end where compressing losslessly didn't always + work correctly. + +3.0 h - 4/14/97 +-------------- +Fixed a bug in high-color mode on the Mac. +Fixed a bug if SmackSoundOnOff was called when no sound was playing. +Fixed bug in Xtra destructor (it was harmless - but a bug nonetheless). +Added MSS Xtra support into the Smacker Xtra. + +3.0 g - 3/9/97 +-------------- +Fixed Xtra to not display a black frame when playback begins. +Switched to new Causeway extender. +Fixed a bug in the VESA linear address code when switching to a new VESA + mode without switching to text mode first. +Added ability to convert 4-bit (16 color AVIs) - these AVIs are very rare. +Fixed a DirectSound deadlock when you use MSS and Smacker both with + DirectSound - you should now call SmackSoundUseDirectSound only if + you are using Smacker without MSS - otherwise, always call + SmackSoundUseMSS. +Added CFM Smacker library to the Mac SDK. +Added an A4-relative library to the Mac SDK. + +3.0 f - 2/16/97 +--------------- +Fixed mixing error when mixing with very slow frame rates and very fast + sound data rates. +Fixed some Xtra problems with focus control and mouse clicking. +Fixed some Xtra weirdnesses with odd palette remapping modes. +Fixed some Xtra problems with full-screen mode. +Fixed Xtra playback in 16-bit color depth mode. +Improved quality of halftoned images. + +3.0 e - 1/28/97 +--------------- +Try to open a graphics file as a TGA before a JPEG to handle TGAs that + have "jpeg-ish" headers. +Made the maximum frame rate 10000 fps. +Added new mouse functions and display mode switching to the Smacker Xtra. + +3.0 d - 1/22/97 +--------------- +Fixed the front-end resizing when new screen size is too small for the + front-end window. +Fixed the front-end to allow negative frame rates (for ms per frame). +Fixed the front-end when clicking on the change frame rate button. +Fixed display of centered movies that exactly matched the current screen + size under Windows NT. +Fixed crash when displaying a Smacker summary with the Win32 player under + Windows 3.x. +Fixed crash in the 16-bit player under Windows NT 4.0 (worked around the + new, buggy DPMI host). +Added a simple RAW graphics import type for each Smacker input (call us for + the exact file format). +Fixed halftoning of 8-bit input files. + +3.0 c - 1/20/97 +--------------- +Added ability to directly Smack wave files into a sound-only Smk file. +Added a double-buffered DispDIB 320x200 mode in the SDK. +Speeded-up Smacker batch file processing. +Fixed batch file processing of very long commmand lines. +Updated copyright notices. +Fixed halftoning when processing list files. +Fixed Smacking of non-4x4 animation files. + +3.0 b - 1/10/97 +--------------- +Added the new help file. +Merged in the Xtra code changes. +Added a few const defines in the SDK. +Made the Smacker DLLs check to see if they are incorrectly installed + in the Windows or Windows system directory. +Added some hint text in the Expert sub-tab on the Smack tab. +Added a specific lossless compression mode in the Smack tab. +Fixed a crash in the DOS mixer. +Changed the auto-key frame default to 95%. +Made the main tab hook directly to our web page. +Updated the Mac SDK to 3.0b. +Fixed offset blitting in SmackBufferBlit on Mac. + +3.0 a - 1/8/97 +-------------- +Fixed processing of single image filenames that are zero-padded. +Switched to an hourglass when reading large directories. +Fixed the directory and drive properties window. +Made some small changes to the short-cuts in the front-end. + +2.2 k - 1/2/97 +-------------- +Added intelligent halftoning (tries to only halftone gradients). +Reversed the order of this history file. +Allow multiple calls to UseMSS under Windows NT. + +2.2 j - 12/17/96 +---------------- +The compressor can now process sound while it is compressing the video. +The front-end has new compression settings for sound in the Smack tab. +You can now use any data rate (not just 11025, 22050, and 44100) for sound. +Fixed a bug when encoding some Smacker palettes. +Fixed conversion of 32-bit AVIs (24-bit worked fine). +Fixed problem with Borland 4.5 and Smacker header file in SDK. +Added switch for the player to use DirectSound (/Z). +Added command for the scriptor to use DirectSound (SYSTEMUSEDIRECTSOUND). +The mixer and the sound processor can take a list of sound files. +Fixed border when compressing different sized list files with a ring frame. +Added ability to show frame numbers in the Windows player. + +2.2 i - 12/8/96 +--------------- +Fixed zooming with CreateDIBSection blitter. +Fixed error when playing extremely long movies with high data rate sound. +Improved frame timing slightly (should help on > 15 minute movies). +Added an option to the player to only show the differences between frames. +Added an option to the player to not pause the video when the focus is lost. + +2.2 h - 11/22/96 +---------------- +Changed the way file handles are read to work with all C compilers under + Windows - use _lopen for 16-bit, CreateFile for 32-bit. +Integrated Diamondware sound support to Windows version. +Added CreateDIBSection support for Win95 and WinNT - WinG is now only + necessary for 16-bit and Win32s playback. +Added a DirectDraw example that shows how to use Smacker with a 16-bit + color pimary surface (ExamDDP6.C and DoDDP6.BAT). + +2.2 g - 11/19/96 +---------------- +Fixed overly large frame compression on palette switches. +Fixed problem when compressing with "% of its size" option. +Fixed weird palette compression bug when rotating palette counter-clockwise. +Added raw output type to Sound Processor. +Fixed ring frame creation when using a non-final end frame. +Added non-sound mixing to SmackMixer. +Expanded compression ranges for "% of average" and "% of its size" (1-200%). +Fixed Smacker's support for DirectX II (DirectX III worked fine). +Smacker commands minimize nicer now. + +2.2 f - 11/15/96 +---------------- +Fixed every frame full window repaints on high-color video cards. +Removed the second parameter from SmackSoundUseMSS under DOS (wasn't + necessary anymore). +SmackMix can now take WAVs, AVIs or Smks as sound input files. +SmackMix can change the sound format type on the fly. +SmackMix mixes sound into Smacker files with ring frames correctly. +Major improvements in compressor quality over multiple frames. +Compressor is much faster with certain types of flics. +Smacker analysis tool doesn't count the first frame in the moving average. + +2.2 e - 11/11/96 +---------------- +Changed front-end notification message number to avoid control conflicts. +Fixed conversions of 24-bit still images. +Fixed left-over temp files when you cancel during SmackC. + +2.2 d - 11/07/96 +---------------- +Fixed AVI sound extraction. +Fixed focus order in Front-end. +Fixed click on same name from a different tab with no highlighting. +Changed the utility sub-windows to be 3D. +Changed the player utility window to be 3D and added several other + window styles (/I#). +Added new scriptor command to change window border type: + SCREENWINDOWBORDER type. 0=thick, 1=thin, 2=none. +Removed setting of thread priorities in Scriptor and player. + +2.2 c - 11/05/96 +---------------- +The Smacker compressor can now compress AVIs, BMPs, TGAs, GIFs, TIFs, + PCXs, JPGs and list files directly. +Fixed pop-up window after playing movie from Explorer in NT. +Added a list file editor to the front-end. +You can now highlight a group of files to create a list file from. +Added the new Sound Processor utility. It takes Wavs, Smks and AVIs + files as input and writes out wave files. It comes in both DOS + and Windows versions. +Sound Processor filters sound when scaling to different rates to avoid + the "tinny" sound when upscaling. +ToWav, SmackUnm, and SmackUnW have all been removed (replaced by the + general purpose sound processor. +OSmk2Flc removed and placed separately on ftp site. +Added starting and ending millisecond times to the Sound Processor. + +2.2 b - 10/23/96 +---------------- +Simplied front-end for converters. +Multimedia tab has been removed - just double-click on a file to play it. +Front-end has built-in viewers for bmp, gif, pcx, tif, tga, and jpg. +Graphics processor uses an improved color reduction method. +Graphics processor can take an input palette. +Graphics processor can overlay windows colors on conversion. +Graphics processor can extract portions of a frame (X,Y,W,H). +Graphics processor can take Smack files as input. +Graphics processor can take a list of files to convert. +Crash when converting single image files is fixed. +SmkInfo can display info on wav,avi,bmp,gif,pcx,tif,tga and jpg files. +FlicJoin and FlicCpy were dropped (GraphPr has these features now). +Graphics processor can save as BMPs, GIFs, PCXs, TIFs, TGAs or JPGs. +Added multiple Smacks example program (ExamMult.C) to SDK. +Smacker now requires 3.50F of MSS. +Fixed pause of Smacker animations on MSSW with large internal MSS buffers. +Made the Smacker decompressor tolerant of file i/o errors - when an read + error occurs, Smacker goes into a friendly skip mode. +Fixed crash when playing two flics in a row with the 320x200 and 320x240 + full screen modes. + +2.2 a - 9/23/96 +--------------- +Fixed scrolling in front end for goto and find editor commands. +Added web page button in front end. + +2.1 m - 9/20/96 +--------------- +Utilities 32-bit only - Win95 and Windows NT - no more Win3.x. +New 32-bit front end - long filenames. +SmackTune now built into the front end. +ToFlic now runs under NT and is much, much faster. +SmackC now has more compress types. +Fixed bug in SmackC when compressing multiple files. +Fixed error in calling SmackSoundOnOff back to on. +Added BitmapToBitmapMask and BitmapToScreenMask commands to scriptor. +Added SystemCurrentExe to scriptor. +Made scriptor clip when blitting, lines, rects, etc. +Fixed scriptor loosing current directory on FilePieces. + +2.1 l - 9/10/96 +--------------- +Fixed the return value of SmackDoFrame when SMACKNOSKIP is specified. + +2.1 k - 8/22/96 +--------------- +Rewrote compressor lossy engine to be data rate based +Added auto-key framing to compressor. +Raised limit on code overflows in compressor. +Add new frame skipping logic resulting in much fewer frame skips on low + data rate devices. +New cursor management code on Macs. +Fixed crashes in scriptor. +Added AnimationTracks command in the scriptor. +Added auto run feature to scriptor - rename script to autoexec.ss and they + run when scriptor is run without parameters. +Removed the SmackToScreen option from the Mac (use SmackBuffers with the + SMACKDIRECTBLIT option). + +2.1 j - 08/10/96 +---------------- +Switched to new MSS for DOS and Windows. +Fixed 16-bit sound on 68K Macs. +Switched to Microseconds call on Macs. +Switched to new 64-bit divide on Macs. +Fixed palette problems on Mac. +Fixed 44 Khz sound on Mac. +Improved 2x blitting on Mac by 8 times. +SmackBufferFocused uses process id to determine focus. +Added new blit type for Mac (it is the default on 8-bit): + SMACKGWORLDCUSTOMBLIT. +Blitters are 25% faster on Mac. + +2.1 i - 07/10/96 +---------------- +Allow multiple calls to SmackSoundUseMSS (make sure all smks are closed 1st). +RADSIW returns accurate Mhz for Pentium Pros. + +2.1 h - 06/21/96 +---------------- +Now query the VTD vxd device for timing info under Win3 and Win95 DOS boxes. + +2.1 g - 06/19/96 +---------------- +Fixed non-export of hook procedure in 16-bit DLL - cause full 320x200 to fail. +Fixed sync of 22Khz sound with MSS for DOS. +Removed outputdebugstring in directsound code. +Fixed odd-sized SmackBuffer problem (use Pitch in SmackToBuffer, BTW). + +2.1 f - 06/06/96 +---------------- +Fixed capitalization of the Unsmack function. +Made the 16-bit SmackW16 thunk to SmackW32 on WinNT. +Switched to the stdcall calling convention in SmackW32. +Use declspec imports in Smack.H to optimize Smacker calls. +The 16-bit DLL can switch modes under NT. +Fixed extra mode reset under Windows NT. +Now ship with Borland DEF file. +Fixed SmackFromScreen when hwnd is valid and not at 0,0. + +2.1 e - 05/25/96 +---------------- +Fixed SmkInfo opening files in read/write mode. +Fixed Mac looping of sound. +Improved sound synch on Mac. +Fixed ToFlic and MMInfo reading PCXs with TGA-style headers. +Fixed compressing palette fade-ins. +Fixed palette fades on >256 color cards. +Optimized palette fade-ins and fade-outs. +Rewrote low-level decompressor - up to 30% faster on 586, up to 12% on 486. +Added doubled playback along the y axis. +Fixed opening more than 32 Smackers in the 16-bit DLL. +Improved memory allocation code. +Made SmackSoundUseDirectSound take a DirectSound object instead of a HWND. +Fixed mixer sound type switches and descriptions in front end. +Added new compression and playback options to front end. +Added three directdraw example programs: examdds, examddp, and examddf. + +2.1 d - 04/25/96 +---------------- +Added interleaving to Smack compressor. +Compiled with Watcom 10.6. +Fixed stupid looping sound synch error for MSS and MSSW. +Change new palette logic to handle jumping to the same frame that you're on. +Fixed DirectSound volume control. +Use NewPtr and MultiFinder temporary memory instead on malloc on Mac. +Fixed looping of Smacker movies with sound on Mac. +Fixed looping of preloaded Smacker movies on Mac. + +2.1 c - 04/09/96 +---------------- +Made NULL buf in call to SmackToBuffer turn off video but leave sound on. +Adjusted mixer to be more tolerant of weird format headers in WAV files. +Fixed SOS code for new version of SOS 4 (must now have SOS4 1/26/96 version). +Mac memory allocation now uses NewPtr and NewSysPtr for memory allocation. + +2.1 b - 03/18/96 +---------------- +Added new switch to SmackPlay to force the extra buffer to be filled on open. +Fixed stupid clipping error in the sound mixer for 16 bit sound. + +2.1 a - 03/11/96 +---------------- +Fixed error when you changed the volume with SOS before the first frame. + +2.0 y - 02/27/96 +---------------- +Fixed leak if preloading a smack file, and not enough memory was available. +Fixed divide by zero error in the Miles Sound System code. +Fixed divide by zero error in the HMI code. +Fixed nasty overwrite bug in the background buffering code. +Fixed color palette weirdness on Mac Quadra AVs. + +2.0 x - 02/19/96 +---------------- +Used new Causeway extender. +Fixed a problem with offsets when zoomed on the Mac. +Adjusted the way ToFlic creates its palettes (weight green higher). +Fixed a problem with the smacker extra buffer when specified as zero. + +2.0 w - 02/07/96 +---------------- +Switched to new combined Win32/Win32s MSS DLL. + +2.0 v - 01/16/96 +---------------- +Fixed MSS and MSSW sync code. + +2.0 u - 01/09/96 +---------------- +Remerged final Mac SDK. +Major changes in sound subsystem - simplified third-pary lib use. +Fairly major changes for Windows DLLs - just the two DLLs now. +Half dozen or so minor SDK changes to match Mac. + +2.0 t - 01/02/96 +---------------- +Fixed buffer bug when using very tiny extra buffer amounts. +Add ability for player (/D##) and scriptor (WindowsDisplayResolution) to + set the screen display mode (under Win95 and NT only). +Fixed ToFlic converter leaving a DLL in memory. +Fixed ToFlic converter for mostly dark images. +Optimized skipping to a frame that is already in the read ahead buffer. +Added new Smacker DLL for WAIL with Win32s. + +2.0 s - 12/22/95 +---------------- +Major improvement in buffering system - will lower dropped frames by half. +Adjust VGA detection routine to allow for strange VGAs. +Fixed AIL too agressively dropping frames. + +2.0 r - 12/04/95 +---------------- +First Mac code integrated back into RAD.h Smack.h Rfile,h lowsnd.h + and Smackinp.cpp. +Header files pretty drastically modified (to add Mac support). +Upgraded to patch level 'a' for Watcom 10.5 - fixes several DOS problems. + +2.0 q - 11/28/95 +---------------- +Recompiled with WAIL 3.03D - you must update to this version for Smacker. +Fixed caption option in the 16-bit Smacker playback utility. +Optimized palette fade out compression. + +2.0 p - 11/27/95 +---------------- +Fixed nasty bug in 16-bit WAIL support code (good catch Illumina). +Tweaked DOS HMI timer code. + +2.0 o +----- +Speeded up looping of ring frames in scriptor. +Added new DebugFile command that dumps your script to a file as it runs. +Added new DebugText command that dumps to the DumpFile output. +Dialed in DirectSound synching code. + +2.0 n +----- +Fixed resync after loss of synch in WAIL. +Changed SmackToBufferRect param to a u32. + +2.0 m +----- +Tweaked WAIL synching code. +Added ability to set ms per frame down to hundredth of a ms to all utilities. +Remove BreakPoints from ToFlic and SmackW32.DLL. + +2.0 l +----- +Tweaking SmackBuffer close code. + +2.0 k +----- +Fixed stupid flag reversal in SmackBufferNewPalette code. +Fix Y coordinate in fliccpy. +Locked more of the AIL data structures for DOS under Win95. +Added example program that does its own i/o. +DirectSound support. + +2.0 j +----- +WAIL DLL unloaded problem fixed. +AIL under DOS locking problem fixed. +Added palette type for SmackBufferNewPalette (same flags as SmackColorRemap). +Added check for null pointers in all Smack functions. + +2.0 i +----- +Temporary DirectSound support for Zombie. + +2.0 h +----- +Fixed timer code for AIL under DOS. + +2.0 g +----- +Added WAIL support to the SDK. +Took out automatic timer slow down on SVGASetText and SVGASetGraphics. + +2.0 f +----- +Added mousemode command for absolute mouse devices under DOS. +Used the new dead code eliminator in Watcom 10.5 to make utilities smaller. +Minor optimizations to compressor and toflic converter. +Tweaked flic output code so that copies will byte compare as identical. +Fixed double-buffered playback under DOS with larger vesa modes. + +2.0 e +----- +Fixed stack error with HMI 4 (make sure you have HMI 4 from 9/11/95). +Fixed error in front end with blank switches. +Fixed error on exit from player after help displayed. +Fixed conversion of 16-bit images to flics. + +2.0 d +----- +Tweaked timer code. +Fixed looping error in scriptor. +Fixed button highlighting in scriptor tab. +Fixed file i/o in scriptor under Win386. +Added support in the SDK for HMI4. + +2.0 c +----- +Fixed bug when playing multiple sound Smacker file in a row with SmackPly. + +2.0 b +----- +Switched to Watcom 10.5 (files got smaller for some reason). +Added API support for Borland (Windows only - no powerpack). +Tweaked full-screen mode setting for 16-bit SmackBuffers. +Added SmackBufferFocused command. + +2.0 a +----- +Fixed palette clearing after mode set. +Added new fliccpy command. +Finished demo. +Keep fractional frame rates hidden in the flic file. +Fixed line and button settings on restore of edit tab in Scriptor tab. +Fixed saving current edit position in scriptor tab. +ESC on command to run in command tab will clear the line first. +Fixed Ctrl-PageDown in edit memo boxes. +Changed Multimedia tab, so that it doesn't automatically open the MCI file. +Fixed file highlight after a file find or recent file choice. +Fixed crash when sound interrupted under NT. +Fixed beeping under Win32s +Fixed loop around slowdown when using animationadvance to the end of a flic. +Updated help files. +Fixed a null region select in weird palette reselect cases. +Fixed GPF when using Recent Directories after running the scriptor. +Fixed multiple notification to parent from scriptor. +Created better default mouse for scriptor (12x20). +Fixed crash on looping under NT 3.51. +Fixed dragging on a lower priority for smoother dragging. +Switched to AIL-lite sound library for DOS version. +Switched to the Causeway extender for DOS version (compressed EXEs). +Major change to the DispDIB code for greater compatibility (changed API). +Improved ToFlic quantoning on darker colors. +Made palettes into keypalettes on keyframes. +Allow copy from the pop-up copy file option to a directory name. + +1.9 u +----- +Took thread priorities out of Smackinp - put into player and + scriptor directly. +Took out feature of calling SmackerW with SMK or SS - put into SMACKGO.EXE. +Fixed misspellings and always asking to install FFS, VFW or Win32s. +Fixed cursor on utility windows. +Fixed compressing flics directly from read-only media. +Fixed div error when mixed non-sound data. +Fixed new palette on input change error in toflic. +Fixed using SmackBuffers with SYSPAL_NOSTATIC turned on. +Fixed error using ".." with DirChange in scriptor. +Added SystemPaletteLock command in scriptor. +Fixed centering error on odd-sized flics under the DOS scriptor. + +1.9 t +----- +Cleaned up help significantly. +The front-end has context-sensitive help for the scriptor (Ctrl-F1). +Fixed locating file associations under Win95. +Fixed rare crash when compressing under Win32s. +First CD-based version. +All new set-up programs. +Can call SmackerW with an SMK or a SS to play. + +1.9 s +----- +Added help to front end. +Fixed scriptor problem where you move up to 640x480 then back to 320x200. +Fixed error passing in SMACKTRACKS to SmackVolume. + +1.9 r +----- +Renamed a few executables for consistency (ToFlicW6, SmkInfoW, MMInfoW). +Front-end figures out if it is running WinNT/Win95/Win32 and runs Win32s + versions of the utilities, otherwise it runs the 16 bit versions. +Fixed crash at end of toflic.exe under NT and Win95. +Fixed reversal of channels and quality flags in SmackUnmix. +Added the built-in SVGA (non-vesa) drivers from FastGraph. +Fixed too short entry for simulate and extra mem in front-end for player. +Fixed error where high indexes mapped to lower indexes in SmackC. +SmackOnOff releases the Windows waveout handle while it is off (SDK). +Fixed simulation speeds under Windows 3.11 with SmackPlay. +Fixed variable deletion when another variable holds same variable (scriptor). +Fixed palette loading in AnimationLoadToBitmap command. +Added VESA controls in player (/A option). +Added VESA control in DOS scriptor-SCREENSETTINGS num (num same as /A). +Added blitter control in Windows scriptor-SCREENSETTINGS num (num same as + /V in Windows player). +Added ScreenInfo command in scriptor - returns settings used for display. +Added frame specific settings in DOS and Windows. + +1.9 q +----- +Added ScreenWindowAutoPause command in SmackScript (pauses when lose focus). +Added ScreenWindowHasFocus (returns whether SmackScript has focus). +Fixed slow loading of the player from 16 bit apps under WinNT. +Bump up the thread priority automatically under NT and Win95. +Fixed support for VBEs that hose the top of the extended registers (UNIVBE). +Added support for VBE 2.0 32 bit bank switching. +Added support for VBE 2.0 32 bit linear frame buffering - very,very fast. +Fixed bug in playback of very large, or very unusual flics. +Removed support for FlashTek's X32. + +1.9 p +----- +Adjusted RAD.H for Microsoft. +Fixed SmackW32.DLL linker error. +Fixed file buffering for NT (fixes all sorts of weird errors on 3.51). +Fixed port calls to avoid NT exceptions. +Did import library for MSC 2 - nightmare city. +Added support for full-screen under Win95 - another nightmare city. +Made front-end icon show in title bar under Win95. +Made copy command in front-end retain the file times. +Fixed front-end not restoring with Win95 (bug in build 490 and below). +Fixed front-end error when sub-process sends finish flag at awkward time. + +1.9 o +----- +Fixed non-display of VESA modes with DOS radsi.exe. +Switched all of the windows utilities to Win32s versions (normal Windows + versions of the scriptor and player are still licenseable). This allows + the utilities to run well under Win NT and Win95. + +1.9 n +----- +Fixed directory command in SmackerW. +Fixed playback problem with extremely small Smks (less than 2K). +Added Recently used file and directory options. +Fixed error on directory with invalid file date/times. +Fixed error renaming/copying twice in a row. +Now allow more than one rename/copy window open at a time. +You can use wildcards in del, ren, copy. +Rename directory remembers where it is. +Can make Smacker Batch files (*.SBT files). +File attributes windows and command. +Find File command. +Batch file editor. +Fixed error holding down down arrow in command history. +Added Cls,SaveHist,type and edit commands in command line. +Handle switching away from default drive and back again. +Fixed problem where script files weren't being closed. +Fixed problem where utilities couldn't allocate a window. +Speeded up fades in the Windows scriptor. + +1.9 m +----- +Fixed SmackMixing into non-first frame . +Created SmackMix option to loop the sound over and over. +New front-end (tab based, written in Delphi). + +1.9 l +----- +Fixed blip that occurred when playing very short sound files. + +1.9 k +----- +Fixed 100* error in negative frame rates with SmackPly. +Finished sound extractor - can also convert between wav formats. + +1.9 j +----- +Changed the way the SmackBlw.DLL initializes palettes to account for + buggy Diamond display drivers. +Added replaceable font support in SmackScript . + (TEXTFONTFROMBITMAP bitmapvariable,charwidth,charheight,startcharnum,endcharnum) +Added easy loading bitmap support in SmackScript . + (opens a smk, allocs a bitmap, puts each frame into a bitmap) + (ANIMATIONLOADTOBITMAP smkname, bitmap1, bitmap2, etc). +Added BitmapWidth, BitmapHeight commands in SmackScript. +Switched to latest HMI version (2/5/95). +Set the blit mode when using STANDARDBLIT to COLORONCOLOR in Windows. + +1.9 i +----- +Fix divide by zero error when compressing unusual flics. +Palette fades compress better. + +1.9 h +----- +8/16 bit AVIs are handled by ToFlic. +TGA, PCX, BMP, GIF, TIF, and JPEG are handled by ToFlic. +Palette remapping has been improved - it is now the default on 256 cards. +Can specify key frames with SmackC. +SmackC handle negative frame rates correctly (as MS Per Frame). + +1.9 g +----- +Fixed off by one error on ScreenFilledBox when on reversed WinG screens. +Added file handle options on SmackOpen. + +1.9 f +----- +Windows front end updated. +New palette setting code. +Fixed bug in scriptor. +Scriptor sped up by 100%. +Fixed bug in Windows scriptor when playing a sound. + +1.9 d +----- +Scriptor added. +Most of the utilities slightly updated. + +1.8 s +----- +Fixed SmackScr when using unusual multiple VESA windows. + +1.8 q +----- +SmackScr will reset the mouse cursor on a mouse add. +SmackPlw will skip frames if it is falling behind the audio. + +1.8 p +----- +Smackc can take a list of flics to compressed instead of just one (useful + when your flics are huge and you don't want to join them.) +ToFlic gives info on PCX, GIF, TIF, TGA, JPG, and BMP files. + diff --git a/src/Storm/SMACKER/LIB/MSSLITE.LIB b/src/Storm/SMACKER/LIB/MSSLITE.LIB new file mode 100644 index 0000000..4c81134 Binary files /dev/null and b/src/Storm/SMACKER/LIB/MSSLITE.LIB differ diff --git a/src/Storm/SMACKER/LIB/SMACK.LIB b/src/Storm/SMACKER/LIB/SMACK.LIB new file mode 100644 index 0000000..5730d52 Binary files /dev/null and b/src/Storm/SMACKER/LIB/SMACK.LIB differ diff --git a/src/Storm/SMACKER/LIB/SMACKW16.LIB b/src/Storm/SMACKER/LIB/SMACKW16.LIB new file mode 100644 index 0000000..f8fa543 Binary files /dev/null and b/src/Storm/SMACKER/LIB/SMACKW16.LIB differ diff --git a/src/Storm/SMACKER/LIB/SMACKW32.LIB b/src/Storm/SMACKER/LIB/SMACKW32.LIB new file mode 100644 index 0000000..e70aa45 Binary files /dev/null and b/src/Storm/SMACKER/LIB/SMACKW32.LIB differ diff --git a/src/Storm/SOURCE/BATTLE/AD.CPP b/src/Storm/SOURCE/BATTLE/AD.CPP new file mode 100644 index 0000000..d44c1a5 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/AD.CPP @@ -0,0 +1,558 @@ +/*************************************************************************** +* +* ad.cpp +* Battle.net advertisement handling +* +* +* By Michael Morhaime +* +* NOTE: The advertisement window is implimented as a modeless dialog. Since the chatroom is a modal +* dialog, the bnetlogo dialog (the chatroom's parent) is disabled. If we were to impliment the +* ad window as a simple window and child of bnetlogo, the ad window also would be disabled and would +* never receive mouse click messages. +* +* Therefore, the advertisement window is, in fact, a modeless dialog with no child windows. Whenever +* it receives a mouse click, it processes the click without allowing the window to activate. +***/ + + +//**************************************************************************** +// Modification Log: +// +// Diablo Patch #1 +// 2/17/97 MM - Added call to SrvNotifyDisplayAd() upon successful display of ad. +// +// Starcraft Modifications +// 10/21/97 DML - Changed ad window to industry standard 468x60 pixels +// Will blt old ads clipped to this window +//**************************************************************************** + +#include "pch.h" + +//*************************************************************************** +#define MAX_URL_SIZE 1024 +#define BATTLE_HTML_FILE "battle.htm" +#define AD_TIMER_DELAY 50 // 20 fps is our max frame rate +#define AD_WIDTH 468 +#define AD_HEIGHT 60 + +#define PREFSKEY "Preferences" +#define PREFSVALUE_USEDLINK "Clicked Link" + +//*************************************************************************** +typedef struct _TADINFO { + DWORD dwAdId; + DWORD dwAdType; + char szAdURL[MAX_URL_SIZE]; + char szAdFilename[MAX_PATH]; +} TADINFO, *PTADINFO; + +//*************************************************************************** + +static HWND sghWndAd = NULL; + +static LPBYTE sgpAdData = NULL; +static SIZE sgAdSize; + +static HSVIDEO sghVideo = NULL; +static LPBYTE sgpAdAnimation = NULL; // Holds Smack flic +static UINT sgAdTimer = 0; + + +// Current ad information +static TADINFO sgCurrAdInfo = { 0 }; +static TADINFO sgNextAdInfo = { 0 }; + + +BOOL UiSetCustomArt (HWND hWnd, + PALETTEENTRY *pe, + int nFirstColor, + int nNumColorsUsed, + BOOL bSetPaletteNow, + LPBYTE data, + int nWidth, + int nHeight); + + + + +//*************************************************************************** +static void AdStopAd(void) { + // free any memory associated with the current Ad + sgCurrAdInfo.szAdURL[0] = 0; + sgCurrAdInfo.szAdFilename[0] = 0; + + if (sgAdTimer) { + SDlgKillTimer(sghWndAd, sgAdTimer); + sgAdTimer = 0; + } + + if (sghVideo) { + SVidPlayEnd(sghVideo); + sghVideo = NULL; + } + + if (sgpAdAnimation) { + FREE(sgpAdAnimation); + sgpAdAnimation = NULL; + } +} + +//*************************************************************************** +static BOOL AdInitWindow(HWND hWndAd, SNETGETARTPROC artcallback) { + RECT r; + LPBYTE pTemp = NULL; + SIZE tempSize; + int nSize; + + sghWndAd = hWndAd; + if (!sghWndAd) + return FALSE; + + + SetWindowPos( + sghWndAd, + NULL, + 0, 0, AD_WIDTH, AD_HEIGHT, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); + + GetClientRect(hWndAd, &r); + sgAdSize.cx = r.right; + sgAdSize.cy = r.bottom; + + // make sure window has double word width + sgAdSize.cx += (4 - sgAdSize.cx%4); + nSize = sgAdSize.cx * sgAdSize.cy; + sgpAdData = (LPBYTE)ALLOC(nSize); + if (sgpAdData == NULL) + return FALSE; + + // Init to blackness + ZeroMemory(sgpAdData, nSize); + + SDlgSetBitmap( + hWndAd, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + sgpAdData, + NULL, + sgAdSize.cx, + sgAdSize.cy); + + + UiLoadCustomArt( + artcallback, + NULL, + SNET_ART_BATTLE_WELCOME_AD, + 32, + 64, + TRUE, + &pTemp, + &tempSize); + + // Set up welcome ad to point to battle.net + strcpy(sgCurrAdInfo.szAdURL, "http://www.battle.net"); + + if (pTemp) { + // Copy bitmap to Ad buffer + SBltROP3(sgpAdData, pTemp, min(tempSize.cx, sgAdSize.cx), min(tempSize.cy, sgAdSize.cy), sgAdSize.cx, tempSize.cx, NULL, SRCCOPY); + + // Free bitmap + FREE(pTemp); + } + + return (TRUE); +} + +//*************************************************************************** +static void AdDestroyWindow(void) { + AdStopAd(); + + sghWndAd = NULL; + if (sgpAdData) { + FREE(sgpAdData); + sgpAdData = NULL; + } +} + + +//*************************************************************************** +void AdSetInfo(SNADINFOPTR pAdInfo) { + + // Set type of ad + sgNextAdInfo.dwAdType = pAdInfo->adtype; + sgNextAdInfo.dwAdId = pAdInfo->id; + + // Copy url string + if (strlen(pAdInfo->url) < sizeof(sgNextAdInfo.szAdURL)) + strcpy(sgNextAdInfo.szAdURL, pAdInfo->url); + else + sgNextAdInfo.szAdURL[0] = 0; + + // Copy filename string + if (strlen(pAdInfo->filename) < sizeof(sgNextAdInfo.szAdFilename)) + strcpy(sgNextAdInfo.szAdFilename, pAdInfo->filename); + else + sgNextAdInfo.szAdFilename[0] = 0; +} + + + +//*************************************************************************** +static BOOL AdDisplayPCX(LPBYTE pPCXData, DWORD dwSize) { + PALETTEENTRY pe[256]; + LPBYTE pBuffer; + DWORD dwBufferSize; + int nWidth, nHeight, nBitDepth; + + + if (!sghWndAd) + return FALSE; + + // Query decode function for dimensions of pcx + if (!SBmpDecodeImage(SBMP_IMAGETYPE_PCX, + pPCXData, + dwSize, + &pe[0], + NULL, + 0, + &nWidth, + &nHeight, + &nBitDepth)) + return 0; + + dwBufferSize = nWidth*nHeight*nBitDepth/8; + pBuffer = (LPBYTE)ALLOC(dwBufferSize); + if (pBuffer == NULL) + return 0; + + if (!SBmpDecodeImage(SBMP_IMAGETYPE_PCX, + pPCXData, + dwSize, + &pe[0], + pBuffer, + dwBufferSize, + &nWidth, + &nHeight, + &nBitDepth)) { + FREE(pBuffer); + return 0; + } + + + // Clear window before changing palette + RECT r; + GetClientRect(sghWndAd, &r); + SDlgBltToWindow( + sghWndAd, + NULL, + 0, 0, + pBuffer, // This isn't used, but can't be NULL anyways + &r, + (LPSIZE)&r.right, + 0xffffffff, + 0, + BLACKNESS); + + + + // Set this bitmap in the add window + if (!UiSetCustomArt(NULL, // This means just set palette entries (leave window bitmap ptr unchanged) + &pe[0], + 32, // FIRST AD COLOR + 64, // NUM AD COLORS + TRUE, // Set palette now + pBuffer, // Ad data + nWidth, + nHeight)) { + FREE(pBuffer); + return 0; + } + + // Copy bitmap to AdData ptr + SBltROP3(sgpAdData, + pBuffer, + min(nWidth, sgAdSize.cx), + min(nHeight, sgAdSize.cy), + sgAdSize.cx, + nWidth, + NULL, + SRCCOPY); + InvalidateRect(sghWndAd, NULL, FALSE); + + // Free bitmap + FREE(pBuffer); + return 1; +} + + +//*************************************************************************** +static void CALLBACK AdSMKTimer(HWND hWnd, UINT uMsg, UINT uID, DWORD dwTime) { + BOOL bUpdated = FALSE; + + if (sghVideo == NULL) + return; + + SVidPlayContinueSingle (sghVideo, FALSE, &bUpdated); + + if (bUpdated) + InvalidateRect(hWnd, NULL, FALSE); +} + +//*************************************************************************** +static BOOL AdDisplaySMK(LPBYTE pSMKData, DWORD dwSize) { +// @#@ resolve crash playing smacks to different sized buffer + return 0; + + RECT r; + SVIDPALETTEUSE paletteUse = { sizeof(SVIDPALETTEUSE), 32, 64 }; + + + if (!sghWndAd) + return FALSE; + + sgpAdAnimation = (LPBYTE)ALLOC(dwSize); + if (!sgpAdAnimation) + return FALSE; + + // Make our own copy of the animation + memcpy(sgpAdAnimation, pSMKData, dwSize); + + SetRect(&r, 0, 0, sgAdSize.cx-1, sgAdSize.cy-1); + SVidPlayBeginFromMemory(sgpAdAnimation, + dwSize, + sgpAdData, + &r, + &sgAdSize, + &paletteUse, + SVID_FLAG_TOBUFFER | SVID_FLAG_LOOP, + &sghVideo); + sgAdTimer = SDlgSetTimer(sghWndAd, 1, AD_TIMER_DELAY, AdSMKTimer); + + GetClientRect(sghWndAd, &r); + SDlgBltToWindow( + sghWndAd, + NULL, + 0, 0, + sgpAdAnimation, // This isn't used, but can't be NULL anyways + &r, + (LPSIZE)&r.right, + 0xffffffff, + 0, + BLACKNESS); + + return 1; +} + +//*************************************************************************** +void AdDisplay(LPVOID pData, DWORD dwSize) { + BOOL bSuccess; + + + if (!sghWndAd) + return; + + AdStopAd(); + + // Handle advertisement data based on ad type + switch(sgNextAdInfo.dwAdType) { + case ADTYPE_PCX: + bSuccess = AdDisplayPCX((LPBYTE) pData, dwSize); + break; + + case ADTYPE_SMK: + bSuccess = AdDisplaySMK((LPBYTE) pData, dwSize); + break; + } + + if (bSuccess) { + sgCurrAdInfo = sgNextAdInfo; + SrvNotifyDisplayAd(sgCurrAdInfo.dwAdId, sgCurrAdInfo.szAdFilename, sgCurrAdInfo.szAdURL); + } +} + + + +//*************************************************************************** +void AdNavigate(SNETUIDATAPTR interfacedata) { + char szText[256]; + char szTitle[32]; + char szBrowserApp[MAX_PATH]; + char szURLSave[MAX_URL_SIZE]; + FILE *fp; + BOOL bAdSuccess = TRUE; // Assume user will successful get to the internet + + if (sgCurrAdInfo.szAdURL[0] == 0) + return; + + if (interfacedata->soundcallback) + interfacedata->soundcallback(PROVIDERID, SNET_SND_CHANGEFOCUS, 0); + + // Save a copy of the url, in case it changes while user is viewing the message box + strcpy(szURLSave, sgCurrAdInfo.szAdURL); + + + + // Prompt user if they really want to launch their browser (only prompt the first time they click) + DWORD dwUsedLink = 0; + SRegLoadValue(PREFSKEY,PREFSVALUE_USEDLINK,SREG_FLAG_BATTLENET,&dwUsedLink); + if (dwUsedLink == 0) { + dwUsedLink = 1; + SRegSaveValue(PREFSKEY,PREFSVALUE_USEDLINK,SREG_FLAG_BATTLENET,dwUsedLink); + + LoadString(global_hinstance, IDS_QUERYBROWSEWEB, szText, sizeof(szText)); + LoadString(global_hinstance, IDS_BATTLENET, szTitle, sizeof(szTitle)); + if (IDOK != UiMessageBox(interfacedata->messageboxcallback, interfacedata->parentwindow, szText, szTitle, MB_OKCANCEL)) { + SrvNotifyClickAd(sgCurrAdInfo.dwAdId, FALSE); + return; + } + } + + + // Switching to the Desktop will cause us to be minimized and switch out of Direct Draw Mode. + // We'll want to minimize our app before calling ShellExecute(). + // SetForegroundWindow() works better than ShowWindow(SDrawGetFrameWindow(), SW_MINIMIZE), which causes the + // task bar (if auto hidden) to be drawn whenever the frame window is displayed. + SetForegroundWindow(GetDesktopWindow()); + + // First try to launch browser by just passing ShellExecute() a url + if (32 >= (unsigned int)ShellExecute( + SDrawGetFrameWindow(), + "open", + szURLSave, + NULL, + NULL, + SW_SHOWNORMAL)) { + + // Okay.. that didn't work. Let's run the browser explicitly + + // create dummy battle.htm file + fp = fopen(BATTLE_HTML_FILE, "wb"); + fclose(fp); + + if (32 >= (unsigned int)FindExecutable(BATTLE_HTML_FILE, NULL, szBrowserApp)) { + // Get focus back + UiRestoreApp(); + + // Display message + LoadString(global_hinstance, IDS_BROWSERERROR, szText, sizeof(szText)); + LoadString(global_hinstance, IDS_BATTLENET, szTitle, sizeof(szTitle)); + UiMessageBox(interfacedata->messageboxcallback, interfacedata->parentwindow, szText, szTitle, MB_OK | MB_ICONWARNING); + bAdSuccess = FALSE; + goto FILE_CLEANUP; + } + + + // Launch browser window + if (32 >= (unsigned int)ShellExecute( + SDrawGetFrameWindow(), + "open", + szBrowserApp, + szURLSave, + NULL, + SW_SHOWNORMAL)) { + + // Get focus back + UiRestoreApp(); + + // Display Error + LoadString(global_hinstance, IDS_BROWSERERROR, szText, sizeof(szText)); + LoadString(global_hinstance, IDS_BATTLENET, szTitle, sizeof(szTitle)); + UiMessageBox(interfacedata->messageboxcallback, interfacedata->parentwindow, szText, szTitle, MB_OK | MB_ICONWARNING); + bAdSuccess = FALSE; + goto FILE_CLEANUP; + } + + FILE_CLEANUP: + DeleteFile(BATTLE_HTML_FILE); + + } + + SrvNotifyClickAd(sgCurrAdInfo.dwAdId, bAdSuccess); +} + + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + + + +//=========================================================================== +BOOL CALLBACK AdDialogProc ( HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + static SNETUIDATAPTR sInterfacedata = NULL; + static HCURSOR shCursor; + static BOOL sbNavigating = 0; + + switch (message) { + case WM_DESTROY: + AdDestroyWindow(); + sInterfacedata = NULL; + DeleteObject(shCursor); + shCursor = NULL; + break; + + case WM_INITDIALOG: + RECT testrect; + GetClientRect(window,&testrect); + + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + sInterfacedata = (SNETUIDATAPTR)lparam; + + if (sInterfacedata == NULL) { + SDlgEndDialog(window, 0); + return 0; + } + + AdInitWindow(window, sInterfacedata->artcallback); + + // Get link cursor + if (sInterfacedata->getdatacallback) { + sInterfacedata->getdatacallback( + PROVIDERID, + SNET_DATA_CURSORLINK, + &shCursor, + sizeof(shCursor), + NULL); + } + + return 1; + + case WM_MOUSEACTIVATE: + // Don't activate window, but process the mouse click anyway + SetWindowLong(window, DWL_MSGRESULT, MA_NOACTIVATE); + return 1; + + case WM_LBUTTONDOWN: + // Protect this code + if (sbNavigating) + return 1; + + sbNavigating = 1; + AdNavigate(sInterfacedata); + sbNavigating = 0; + return 1; + + case WM_SETCURSOR: + // Ignore cursor, if we have already clicked on the ad. + if (sbNavigating) + break; + + if (shCursor && sgCurrAdInfo.szAdURL[0] != 0) + SetCursor(shCursor); + return 1; + } + + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + diff --git a/src/Storm/SOURCE/BATTLE/BATTLE.CPP b/src/Storm/SOURCE/BATTLE/BATTLE.CPP new file mode 100644 index 0000000..b174cf3 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/BATTLE.CPP @@ -0,0 +1,103 @@ +/**************************************************************************** +* +* BATTLE.CPP +* battle.net network provider +* +* By Michael O'Brien (6/10/96) +* +***/ + +#include "pch.h" + +HINSTANCE global_hinstance = (HINSTANCE)0; +DWORD global_maxplayers = MAXPLAYERS; +DWORD global_programid = 0; +DWORD global_versionid = 0; + +/**************************************************************************** +* +* EXPORTED DATA AND FUNCTIONS +* +***/ + +DWORD bn_id = 'BNET'; +LPCSTR bn_desc = "Battle.net"; +LPCSTR bn_req = "An active connection to an Internet provider, or a " + "direct connection to the Internet."; +SNETCAPS bn_caps = {sizeof(SNETCAPS), // size +#ifdef _DEBUG + SNET_CAPS_DEBUGONLY, // flags +#else + SNET_CAPS_RETAILONLY, // flags +#endif + MAXMESSAGESIZE, // max message size + 16, // max queue size, + MAXPLAYERS, // max players, + 1500, // bytes per second + 500, // latency (ms) + 4, // default turns per second + 2}; // default turns in transit +SNETSPI bn_spi = {sizeof(SNETSPI), + SpiCompareNetAddresses, + SpiDestroy, + SpiFree, + SpiFreeExternalMessage, + SpiGetGameInfo, + SpiGetPerformanceData, + SpiInitialize, + SpiInitializeDevice, + SpiLockDeviceList, + SpiLockGameList, + SpiReceive, + SpiReceiveExternalMessage, + SpiSelectGame, + SpiSend, + SpiSendExternalMessage, + SpiStartAdvertisingGame, + SpiStopAdvertisingGame, + SpiUnlockDeviceList, + SpiUnlockGameList, + SpiGetLocalPlayerName}; + +//=========================================================================== +extern "C" BOOL APIENTRY SnpQuery (DWORD index, + DWORD *id, + LPCSTR *description, + LPCSTR *requirements, + SNETCAPSPTR *caps) { + if ((index != 0) || !(id && description && requirements && caps)) + return 0; + *id = bn_id; + *description = bn_desc; + *requirements = bn_req; + *caps = &bn_caps; + return 1; +} + +//=========================================================================== +extern "C" BOOL APIENTRY SnpBind (DWORD index, + SNETSPIPTR *spi) { + if ((index != 0) || !spi) + return 0; + *spi = &bn_spi; + return 1; +} + +//=========================================================================== +extern "C" BOOL APIENTRY DllMain (HINSTANCE instance, DWORD reason, LPVOID) { + + switch (reason) { + case DLL_PROCESS_ATTACH: + ComboRegisterClass(); + ScrollbarRegisterClass(); + break; + + case DLL_PROCESS_DETACH: + ScrollbarUnregisterClass(); + ComboUnregisterClass(); + break; + } + + global_hinstance = instance; + return 1; +} diff --git a/src/Storm/SOURCE/BATTLE/BATTLE.CS b/src/Storm/SOURCE/BATTLE/BATTLE.CS new file mode 100644 index 0000000..356a6e5 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/BATTLE.CS @@ -0,0 +1,18 @@ +#include +#include +set deffile=battle.def +set extralib=wsock32.lib shell32.lib +set linkopt=%linkopt% -base:0x19000000 + +// DETERMINE THE PROJECT NAME +if %debug% set project=%project%d +set outfile=%project%.snp + +// ADD THE CAPS SIGNATURE TO THE END OF THE FILE +!copy /b %project%.dll+caps.mpq > NUL: + +// RENAME IT TO .SNP AND COPY IT TO THE OUTPUT DIRECTORY +!if exist %outfile% del %outfile% +!rename %project%.dll %outfile% +!copy %outfile% ..\..\bin > NUL: +!if exist *.bak del *.bak diff --git a/src/Storm/SOURCE/BATTLE/BATTLE.DEF b/src/Storm/SOURCE/BATTLE/BATTLE.DEF new file mode 100644 index 0000000..e2987e5 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/BATTLE.DEF @@ -0,0 +1,3 @@ +EXPORTS +SnpBind +SnpQuery diff --git a/src/Storm/SOURCE/BATTLE/BATTLE.H b/src/Storm/SOURCE/BATTLE/BATTLE.H new file mode 100644 index 0000000..5b3c573 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/BATTLE.H @@ -0,0 +1,464 @@ +/**************************************************************************** +* +* COMMON DEFINES, TYPES AND STRUCTURES +* +***/ + +#define DATAPORT 6112 +#define MAXMESSAGESIZE 512 +#define MAXPLAYERS 256 +#define MAXSTRINGLENGTH SNETSPI_MAXSTRINGLENGTH +#define PROVIDERID 'BNET' + +#define STARCRAFT_BNBETA 1 // 0 in final + +#define PKT_GAMEDATA 0 +#define PKT_CLIENTREQ 3 +#define PKT_SERVERPING 5 + +/**************************************************************************** +* +* GLOBAL VARIABLES +* +***/ + +extern HINSTANCE global_hinstance; +extern DWORD global_maxplayers; +extern DWORD global_programid; +extern DWORD global_versionid; + +extern BOOL gbConnectionLost; + +/**************************************************************************** +* +* CACHE FUNCTIONS +* +***/ + +void CacheDestroy (); +BOOL CacheFree (LPVOID data, DWORD databytes); +BOOL CacheInitialize (); +BOOL CacheLoadFile (LPCSTR filename, + FILETIME *lastwritetime, + LPVOID *data, + DWORD *databytes); +BOOL CacheSaveFile (LPCSTR filename, + LPVOID data, + DWORD databytes, + FILETIME *lastwritetime, + DWORD minexpireseconds, + DWORD maxexpireseconds); + +/**************************************************************************** +* +* SERVICE PROVIDER INTERFACE FUNCTIONS +* +***/ + +void SpiAddGame (SNETSPI_GAMELISTPTR game); +BOOL CALLBACK SpiCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude); +BOOL CALLBACK SpiDestroy (); +BOOL CALLBACK SpiFree (SNETADDRPTR addr, + LPVOID data, + DWORD databytes); +BOOL CALLBACK SpiFreeExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR message); +BOOL CALLBACK SpiGetGameInfo (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + SNETSPI_GAMELIST *gameinfo); +BOOL CALLBACK SpiGetLocalPlayerName (LPSTR namebuffer, + DWORD namechars, + LPSTR descbuffer, + DWORD descchars); +BOOL CALLBACK SpiGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +BOOL CALLBACK SpiInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + HANDLE event); +BOOL CALLBACK SpiInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +BOOL CALLBACK SpiLockDeviceList (SNETSPI_DEVICELISTPTR *devicelist); +BOOL CALLBACK SpiLockGameList (DWORD categorybits, + DWORD categorymask, + SNETSPI_GAMELISTPTR *gamelist); +void SpiQueueExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR message); +BOOL CALLBACK SpiReceive (SNETADDRPTR *addr, + LPVOID *data, + DWORD *databytes); +BOOL CALLBACK SpiReceiveExternalMessage (LPCSTR *senderpath, + LPCSTR *sendername, + LPCSTR *message); +BOOL CALLBACK SpiSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +BOOL CALLBACK SpiSend (DWORD addresses, + SNETADDRPTR *addrlist, + LPVOID data, + DWORD databytes); +BOOL CALLBACK SpiSendExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR targetpath, + LPCSTR targetname, + LPCSTR message); +BOOL SpiSendSpecial (SNETADDRPTR addr, + DWORD packettype, + LPVOID data, + DWORD databytes); +BOOL CALLBACK SpiStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD gameage, + DWORD gamecategorybits, + DWORD optcategorybits, + LPCVOID clientdata, + DWORD clientdatabytes); +BOOL CALLBACK SpiStopAdvertisingGame (); +BOOL CALLBACK SpiUnlockDeviceList (SNETSPI_DEVICELISTPTR devicelist); +BOOL CALLBACK SpiUnlockGameList (SNETSPI_GAMELISTPTR gamelist, + DWORD *hintnextcall); + +/**************************************************************************** +* +* SERVER COMMUNICATION FUNCTIONS +* +***/ + +#define SN_ADDCHANNEL 1 // param = LPCSTR (channel name) +#define SN_DELETECHANNEL 2 // param = LPCSTR (channel name) +#define SN_JOINCHANNEL 3 // param = SNJOINCHANNELPTR +#define SN_ADDUSER 4 // param = SNADDUSERPTR +#define SN_DELETEUSER 5 // param = SNDELETEUSERPTR +#define SN_DISPLAYSTRING 6 // param = SNDISPLAYSTRINGPTR +#define SN_DOWNLOADINGUPGRADE 8 // param = LPDWORD (percent complete) +#define SN_DOWNLOADFAILED 9 // param = unused +#define SN_DOWNLOADSUCCEEDED 10 // param = unused +#define SN_FAILEDTOCONNECT 11 // param = LPDWORD (error code) +#define SN_USERNAME 12 // param = LPCSTR (user name) +#define SN_LOSTCONNECTION 13 // param = unused +#define SN_CHANGEUSERFLAGS 14 // param = SNCHANGEUSERFLAGSPTR +#define SN_UPDATEPINGTIME 15 // param = SNUPDATEPINGTIMEPTR +#define SN_CHANNELISFULL 16 // param = LPCSTR (channel name) +#define SN_CHANNELDOESNOTEXIST 17 // param = LPCSTR (channel name) +#define SN_CHANNELISRESTRICTED 18 // param = LPCSTR (channel name) +#define SN_SQUELCHUSER 19 // param = SNSQUELCHUSERPTR +#define SN_UNSQUELCHUSER 20 // param = SNSQUELCHUSERPTR +#define SN_BADCONNECTION 21 // param = unused +#define SN_SETADINFO 22 // param = SNADINFOPTR +#define SN_DISPLAYAD 23 // param = LPVOID (ad data) +#define SN_MESSAGEBOX 24 // param = SNMESSAGEBOXPTR + +#define SN_ERROR_UNREACHABLE 1 +#define SN_ERROR_NOTRESPONDING 2 +#define SN_ERROR_UNABLETOUPGRADE 3 +#define SN_ERROR_BADCONNECTION 4 + +#define SN_STRING_WHISPER 1 +#define SN_STRING_WHISPERSENT 2 +#define SN_STRING_TALK 3 +#define SN_STRING_BROADCAST 4 +#define SN_STRING_INFORMATION 5 +#define SN_STRING_ERROR 7 + +#define ADTYPE_PCX 0x7863702e +#define ADTYPE_SMK 0x6b6d732e + +#define CF_PUBLIC 0x00000001 +#define CF_MODERATED 0x00000002 +#define CF_RESTRICTED 0x00000004 + +#define UF_BLIZZARD SNET_DDPF_BLIZZARD +#define UF_MODERATOR SNET_DDPF_MODERATOR +#define UF_SPEAKER SNET_DDPF_SPEAKER +#define UF_SYSOP SNET_DDPF_SYSOP +#define UF_BADCONNECTION 0x00000010 +#define UF_SQUELCHED SNET_DDPF_SQUELCHED + +typedef struct _SNADDUSERREC { + LPCSTR name; + LPCSTR description; + DWORD flags; + BOOL notifyuser; +} SNADDUSERREC, *SNADDUSERPTR; + +typedef struct _SNADINFOREC { + DWORD id; + DWORD adtype; + LPCSTR filename; + LPCSTR url; +} SNADINFOREC, *SNADINFOPTR; + +typedef struct _SNCHANGEUSERFLAGSREC { + LPCSTR name; + DWORD flags; +} SNCHANGEUSERFLAGSREC, *SNCHANGEUSERFLAGSPTR; + +typedef struct _SNDELETEUSERREC { + LPCSTR name; + LPCSTR reason; + BOOL notifyuser; +} SNDELETEUSERREC, *SNDELETEUSERPTR; + +typedef struct _SNDISPLAYSTRINGREC { + LPCSTR sender; + DWORD senderflags; + DWORD stringtype; + LPCSTR string; +} SNDISPLAYSTRINGREC, *SNDISPLAYSTRINGPTR; + +typedef struct _SNJOINCHANNELREC { + LPCSTR name; + DWORD flags; +} SNJOINCHANNELREC, *SNJOINCHANNELPTR; + +typedef struct _SNMESSAGEBOXREC { + LPCSTR text; + LPCSTR caption; + DWORD type; +} SNMESSAGEBOXREC, *SNMESSAGEBOXPTR; + +typedef struct _SNSQUELCHUSERREC { + LPCSTR name; + DWORD flags; +} SNSQUELCHUSERREC, *SNSQUELCHUSERPTR; + +typedef struct _SNUPDATEPINGTIMEREC { + LPCSTR name; + DWORD pingtime; + BOOL relayed; +} SNUPDATEPINGTIMEREC, *SNUPDATEPINGTIMEPTR; + +BOOL SrvBeginChat (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + LPCSTR preferredchannel); +void SrvCancel (); +BOOL SrvCreateAccount (LPCSTR username, + LPCSTR password); +void SrvDestroy (); +BOOL SrvDisconnect (); +BOOL SrvEndChat (); +BOOL SrvGetGameList (LPCSTR gamename, + LPCSTR gamepassword, + DWORD categorybits, + DWORD categorymask, + DWORD maxitems); +BOOL SrvGetLatency (SNETADDRPTR addr, + DWORD *latency); +void SrvGetLocalPlayerDesc (LPSTR buffer, + DWORD bufferchars); +void SrvGetLocalPlayerName (LPSTR buffer, + DWORD bufferchars); +BOOL SrvGetUiNotification (DWORD *notifycode, + LPVOID *param, + DWORD *parambytes); +BOOL SrvInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETVERSIONDATAPTR versiondata); +BOOL SrvIsConnected (); +BOOL SrvIsWaitingForResponse (); +BOOL SrvJoinChannel (LPCSTR channel, + BOOL joinalways = 0); +BOOL SrvLogon (LPCSTR username, + LPCSTR password, + DWORD *errorcode); +void SrvMaintainAds (); +void SrvMaintainLatencies (); +void SrvNotifyClickAd (DWORD adid, + BOOL result); +void SrvNotifyDisplayAd (DWORD id, + LPCSTR filename, + LPCSTR url); +void SrvNotifyJoin (LPCSTR gamename, + LPCSTR gamepassword); +void SrvPingAddress (SNETADDRPTR addr); +void SrvProcessClientReq (SNETADDRPTR addr, + LPBYTE data, + DWORD databytes); +void SrvProcessServerPing (LPBYTE data, + DWORD databytes); +BOOL SrvSendChatString (LPCSTR command); +void SrvSetBetaId (DWORD betaid); +BOOL SrvStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD creationtime, + DWORD gamecategorybits, + DWORD optcategorybits); +BOOL SrvStopAdvertisingGame (); + +/**************************************************************************** +* +* USER INTERFACE FUNCTIONS +* +***/ + +//**************************************************************************** +// User Defined messages +//**************************************************************************** + +// chatchnnl.cpp +#define WM_CHANNEL_DOESNOTEXIST (WM_USER+100) +#define WM_CHANNEL_JOINED (WM_USER+101) +#define WM_CHANNEL_RESTRICTED (WM_USER+102) + +// bnetlogo.cpp +#define WM_ERR_NOTRESPONDING (WM_USER+103) + +// chatroom.cpp +#define WM_CHAT_PROCESS_MSG (WM_USER+104) //(wparam = msg color, lparam = (LPCSTR)szText) + +// ui.cpp..etc +#define WM_NOTIFICATION_WAITING (WM_USER+105) + +// scrollbar.cpp +#define WM_STORMSCROLL_INIT (WM_USER+106) // (lparam = (HWND)hWndParent) + +//**************************************************************************** +//**************************************************************************** + +typedef struct _UIPARAMS { + DWORD flags; + SNETPROGRAMDATAPTR programdata; + SNETPLAYERDATAPTR playerdata; + SNETUIDATAPTR interfacedata; + SNETVERSIONDATAPTR versiondata; + LPDWORD playeridptr; +} UIPARAMS, *UIPARAMSPTR; + + +#define MAX_CHANNEL_LEN 32 +typedef struct _CHANNEL_LIST { + char szChannel[MAX_CHANNEL_LEN]; + _CHANNEL_LIST *next; +} TCHANNEL_LIST, *PTCHANNEL_LIST; + +typedef struct _bmp { + LPBYTE data; + SIZE datasize; +} TBMP, * TPBMP; + + +BOOL CALLBACK BattleNetDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); + +BOOL UiInitialize(SNETUIDATAPTR interfacedata); +void UiDestroy(void); +BOOL UiBeginConnect (SNETPROGRAMDATAPTR programdata, + SNETUIDATAPTR interfacedata); +void UiEndConnect (BOOL connected); + +void UiRestoreApp(void); + +BOOL UiSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +BOOL UiLogon (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +BOOL UiDisconnect(void); +BOOL UiAskUpdate(SNETUIDATAPTR interfacedata); +void UiNotificationWaiting (); +BOOL UiPrepRestart(SNETUIDATAPTR interfacedata); +BOOL UiProcessWindowMessages (); +BOOL UiUpgradeMessage (); +void UiNotification(void); +void UiWSockErrMessage(void); + +BOOL UiMessageBox(SNETMESSAGEBOXPROC messageboxcallback, HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType); + + + +typedef int (CALLBACK *PROGRESSFCN)(void); +HWND UiModelessProgressDialog(SNETUIDATAPTR interfacedata, + LPCSTR progresstext, + BOOL abortable, + PROGRESSFCN progressfcn, + DWORD callspersec); + + +void ColorPrefDestroy(void); +BOOL ColorPrefInit(SNETGETDATAPROC getdatacallback); +void ColorPrefActivate(BOOL bActivate); + + +//=========================================================================== +// Useful misc. routines +//=========================================================================== +BOOL UiLoadArtwork (SNETGETARTPROC artcallback, + HWND hWnd, + HWND hWndParent, + DWORD artid, + LPCTSTR controltype, + DWORD controlstyle, + LONG usageflags, + BOOL loadpalette, + BOOL prepfadein, + LPBYTE *data, + SIZE *size); + + +BOOL UiLoadCustomArt ( + SNETGETARTPROC artcallback, + HWND hWnd, + DWORD artid, + int nFirstColor, + int nNumColorsUsed, + BOOL bSetPaletteNow, + LPBYTE *data, + SIZE *size); + +BOOL UiGetData(SNETGETDATAPROC getdatacallback, + DWORD dataid, + LPBYTE *data, + DWORD *datasize); + +//* Fading routines +#define DEFAULT_STEPS 5 +#define FADE_TIMER_ID 10 +#define FADE_TIMER_DELAY 50 + +extern int gFadeStep; +void UiVidFade(int max, int curr); +void UiVidFadeOut(int steps); + +void UiLoadCursors(HWND hWnd, SNETUIDATAPTR interfacedata); + +// Scrollbar routines +void ScrollbarRegisterClass (void); +void ScrollbarUnregisterClass(void); +void ScrollbarLink(HWND hWndList, HWND hWndScroll); +void ListUpdateScrollbar(HWND hWndList); +void EditUpdateScrollbar(HWND hWndEdit); +int ScrollbarGetWidth(void); +void ScrollbarLoadArtwork(SNETGETARTPROC artcallback); +void ScrollbarDestroyArtwork(void); + +// ComboBox routines +void ComboRegisterClass (void); +void ComboUnregisterClass (void); +void ComboboxLoadArtwork(SNETGETARTPROC artcallback); +void ComboboxDestroyArtwork(void); + diff --git a/src/Storm/SOURCE/BATTLE/BATTLE.RC b/src/Storm/SOURCE/BATTLE/BATTLE.RC new file mode 100644 index 0000000..7399ab9 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/BATTLE.RC @@ -0,0 +1,602 @@ +//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 + +///////////////////////////////////////////////////////////////////////////// +// +// TEXT +// + +CHAT_HELP TEXT MOVEABLE PURE "chathelp.txt" + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "DIALOG_CHATROOM", DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 247 + TOPMARGIN, 2 + BOTTOMMARGIN, 143 + END + + "DIALOG_JOIN_GAME", DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 244 + TOPMARGIN, 10 + BOTTOMMARGIN, 141 + END + + "DIALOG_CHAT_HELP", DIALOG + BEGIN + LEFTMARGIN, 18 + RIGHTMARGIN, 137 + TOPMARGIN, 4 + BOTTOMMARGIN, 110 + END + + "DIALOG_LOGON", DIALOG + BEGIN + LEFTMARGIN, 2 + VERTGUIDE, 22 + VERTGUIDE, 134 + VERTGUIDE, 180 + VERTGUIDE, 244 + VERTGUIDE, 248 + TOPMARGIN, 4 + BOTTOMMARGIN, 200 + HORZGUIDE, 4 + HORZGUIDE, 62 + HORZGUIDE, 74 + HORZGUIDE, 86 + HORZGUIDE, 112 + HORZGUIDE, 170 + END + + "DIALOG_CHAT_CHANNEL", DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 244 + TOPMARGIN, 8 + BOTTOMMARGIN, 136 + END + + "DIALOG_CONNECT_BG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "DIALOG_PROGRESS", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 105 + TOPMARGIN, 7 + BOTTOMMARGIN, 52 + END + + "DIALOG_BATTLENET", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "DIALOG_CONNECT_CANCEL", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 105 + TOPMARGIN, 7 + BOTTOMMARGIN, 53 + END + + "DIALOG_AD", DIALOG + BEGIN + LEFTMARGIN, 1 + RIGHTMARGIN, 186 + TOPMARGIN, 1 + BOTTOMMARGIN, 23 + END + + "DIALOG_SET_PASSWORD", DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 142 + TOPMARGIN, 10 + BOTTOMMARGIN, 111 + END + + "DIALOG_ENTER_PASSWORD", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 110 + END + + "DIALOG_RENAME_ACCOUNT", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 110 + END + + "DIALOG_CREATE_NAME", DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 150 + TOPMARGIN, 5 + BOTTOMMARGIN, 115 + END + + "DIALOG_FILTER_JOIN_GAME", DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 244 + TOPMARGIN, 10 + BOTTOMMARGIN, 141 + END + + "DIALOG_NEW_ACCOUNT", DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 244 + VERTGUIDE, 23 + TOPMARGIN, 2 + BOTTOMMARGIN, 141 + HORZGUIDE, 32 + HORZGUIDE, 58 + HORZGUIDE, 83 + END +END +#endif // APSTUDIO_INVOKED + + +#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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +DIALOG_CHATROOM DIALOGEX 0, 61, 256, 146 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_CHATEDIT,46,128,122,10,ES_AUTOHSCROLL | NOT + WS_BORDER + PUSHBUTTON "C&hannel",ID_CHATCHANNEL,4,2,34,30,BS_BOTTOM | + BS_MULTILINE + PUSHBUTTON "&Create",ID_CHATCREATE,4,39,34,30,BS_BOTTOM | + BS_MULTILINE + PUSHBUTTON "&Join",ID_CHATJOIN,4,76,34,30,BS_BOTTOM | BS_MULTILINE + PUSHBUTTON "&Quit",IDQUIT,4,113,34,30,BS_BOTTOM + LISTBOX IDC_USERLIST,184,27,57,92,LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | NOT WS_BORDER | WS_TABSTOP + LISTBOX IDC_CHATWINDOW,46,10,115,108,NOT LBS_NOTIFY | + LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_USETABSTOPS | + LBS_NOSEL | NOT WS_BORDER | WS_TABSTOP + PUSHBUTTON "&Send",IDOK,181,128,34,15 + PUSHBUTTON "&Whisper",ID_WHISPER,219,128,34,15 + CTEXT "",IDC_STATIC_CHANNEL,181,8,66,9 + CONTROL "",IDC_USERLIST_SCROLLBAR,"StormScrollbar",0x0,241,27,7, + 88 + CONTROL "",IDC_MSGLIST_SCROLLBAR,"StormScrollbar",0x0,161,10,7, + 106 + PUSHBUTTON "&Verbose",ID_VERBOSE,86,112,28,11,NOT WS_VISIBLE | NOT + WS_TABSTOP +END + +DIALOG_LADDER_CHATROOM DIALOGEX 0, 61, 256, 146 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_CHATEDIT,46,128,122,12,ES_AUTOHSCROLL | NOT + WS_BORDER + PUSHBUTTON "C&hannel",ID_CHATCHANNEL,4,2,34,23,BS_BOTTOM | + BS_MULTILINE + PUSHBUTTON "&Create",ID_CHATCREATE,4,31,34,23,BS_BOTTOM | + BS_MULTILINE + PUSHBUTTON "&Join",ID_CHATJOIN,4,60,34,23,BS_BOTTOM | BS_MULTILINE + PUSHBUTTON "&Ladder",ID_CHATLADDER,4,89,34,23,BS_BOTTOM | + BS_MULTILINE + PUSHBUTTON "&Quit",IDQUIT,4,118,34,23,BS_BOTTOM + LISTBOX IDC_USERLIST,184,27,57,92,LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | NOT WS_BORDER | WS_TABSTOP + LISTBOX IDC_CHATWINDOW,46,10,115,108,NOT LBS_NOTIFY | + LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_USETABSTOPS | + LBS_NOSEL | NOT WS_BORDER | WS_TABSTOP + PUSHBUTTON "&Send",IDOK,179,128,34,15 + PUSHBUTTON "&Whisper",ID_WHISPER,214,128,34,15 + CTEXT "",IDC_STATIC_CHANNEL,181,8,66,9 + CONTROL "",IDC_USERLIST_SCROLLBAR,"StormScrollbar",0x0,241,27,7, + 88 + CONTROL "",IDC_MSGLIST_SCROLLBAR,"StormScrollbar",0x0,161,10,7, + 106 + PUSHBUTTON "&Verbose",ID_VERBOSE,86,112,28,11,NOT WS_VISIBLE | NOT + WS_TABSTOP +END + +DIALOG_JOIN_GAME DIALOGEX 0, 61, 256, 146 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT_NAME,168,50,76,12,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_PASSWORD,168,69,76,12,ES_AUTOHSCROLL + LISTBOX IDC_GAMELIST,10,23,97,117,LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_USETABSTOPS | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,179,128,34,15 + PUSHBUTTON "Cancel",IDCANCEL,214,128,34,15 + CTEXT "Join Game",IDC_TITLE,130,8,114,9,0,WS_EX_TRANSPARENT + RTEXT "Name:",IDC_STATIC,130,50,36,12,0,WS_EX_TRANSPARENT + RTEXT "Password:",IDC_STATIC,130,69,36,12,0,WS_EX_TRANSPARENT + LTEXT "To Join a game, enter the game information below.", + IDC_STATIC,130,23,114,18,0,WS_EX_TRANSPARENT + CTEXT "Matching Public Games",IDC_STATIC,10,8,104,9,0, + WS_EX_TRANSPARENT + LTEXT "",IDC_GAMEDESCRIPTION,130,88,114,27 + CONTROL "",IDC_SCROLLBAR,"StormScrollbar",0x0,107,24,7,110 +END + +DIALOG_CHAT_HELP DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,56,95,34,15 + EDITTEXT IDC_EDIT1,18,16,112,70,ES_MULTILINE | ES_READONLY + CTEXT "Help",IDC_TITLE,18,4,119,9,0,WS_EX_TRANSPARENT + CONTROL "",IDC_SCROLLBAR,"StormScrollbar",0x0,130,16,7,70 + DEFPUSHBUTTON "Cancel",IDCANCEL,94,95,34,15 +END + +DIALOG_LOGON DIALOGEX 0, 0, 256, 203 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT_PASSWORD,23,114,85,12,ES_PASSWORD | + ES_AUTOHSCROLL | WS_CLIPSIBLINGS + PUSHBUTTON "New Account",IDS_NEWACCOUNT,33,157,66,15 + CTEXT "Battle.net Login",IDC_TITLE,2,61,254,12,0, + WS_EX_TRANSPARENT + LTEXT "Name",IDC_STATIC,22,77,32,10,0,WS_EX_TRANSPARENT + LTEXT "Password",IDC_STATIC,22,103,32,10,0,WS_EX_TRANSPARENT + CONTROL "",IDC_COMBO_NAME,"StormComboBox",WS_CLIPSIBLINGS | + WS_TABSTOP,22,87,88,14,WS_EX_CONTROLPARENT + DEFPUSHBUTTON "Ok",IDOK,179,185,34,15 + PUSHBUTTON "Cancel",IDCANCEL,214,185,34,15 + LTEXT "Profile:",IDC_STATIC,134,76,114,10,0,WS_EX_TRANSPARENT + LTEXT "",IDC_PROFILE,134,85,110,86,WS_BORDER,WS_EX_TRANSPARENT +END + +DIALOG_CHAT_CHANNEL DIALOGEX 0, 61, 256, 146 +STYLE WS_POPUP +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT_NAME,168,50,76,12,ES_AUTOHSCROLL + LISTBOX IDC_CHANNELLIST,10,23,97,117,LBS_USETABSTOPS | + WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,179,128,34,15 + PUSHBUTTON "Cancel",IDCANCEL,214,128,34,15 + LTEXT "To join or create a Private Channel, enter a name below.", + IDC_STATIC,130,23,114,18,0,WS_EX_TRANSPARENT + CTEXT "Select Channel",IDC_TITLE,130,8,114,9,0, + WS_EX_TRANSPARENT + RTEXT "Channel:",IDC_STATIC,130,50,36,12,0,WS_EX_TRANSPARENT + CTEXT "Channels",IDC_STATIC,10,8,104,9,0,WS_EX_TRANSPARENT + CONTROL "",IDC_SCROLLBAR,"StormScrollbar",0x0,107,24,7,110 +END + +DIALOG_CONNECT_BG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CONTROL "",IDC_LOGO_ANIMATE,"Static",SS_BLACKFRAME,0,0,104,43 +END + +DIALOG_PROGRESS DIALOGEX 0, 0, 112, 61 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "",IDC_PROGRESS_TEXT,0,4,112,18,0,WS_EX_TRANSPARENT + PUSHBUTTON "Cancel",IDCANCEL,34,42,44,12 + CONTROL "",IDC_UIGENERIC_PROGRESS,"Static",SS_BLACKFRAME,10,22, + 91,16 +END + +DIALOG_BATTLENET DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CONTROL "",IDC_LOGO_ANIMATE,"Static",SS_BLACKFRAME,0,0,104,47 +END + +DIALOG_CONNECT_CANCEL DIALOGEX 0, 0, 112, 61 +STYLE DS_CENTER | WS_POPUP +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Searching for the fastest Battle.net server...", + IDC_TITLE,7,9,98,27 + PUSHBUTTON "Cancel",IDCANCEL,34,39,44,12 +END + +DIALOG_AD DIALOGEX 37, 29, 187, 25 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN +END + +DIALOG_SET_PASSWORD DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT1,32,73,92,12,ES_AUTOHSCROLL | NOT WS_BORDER + DEFPUSHBUTTON "OK",IDOK,42,90,34,15 + DEFPUSHBUTTON "Cancel",IDCANCEL,80,90,34,15 + CTEXT "Set Password",IDC_TITLE,10,10,132,9,0,WS_EX_TRANSPARENT + LTEXT "Please enter a password for your character. This will prevent other people from using your name on Battle.net.", + IDC_STATIC,10,27,132,42,0,WS_EX_TRANSPARENT +END + +DIALOG_ENTER_PASSWORD DIALOGEX 0, 0, 154, 117 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT1,32,73,92,12,ES_AUTOHSCROLL | NOT WS_BORDER + DEFPUSHBUTTON "OK",IDOK,55,92,44,12 + PUSHBUTTON "Cancel",IDCANCEL,103,92,44,12 + PUSHBUTTON "New Account",IDC_NEWACCOUNT,7,92,44,12 + CTEXT "Enter Password",IDC_TITLE,10,10,132,9,0, + WS_EX_TRANSPARENT + LTEXT "",IDC_STATIC,10,27,132,36,0,WS_EX_TRANSPARENT +END + +DIALOG_RENAME_ACCOUNT DIALOGEX 0, 0, 154, 117 +STYLE DS_MODALFRAME | WS_POPUP +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Rename Character",IDC_TITLE,10,10,132,9,0, + WS_EX_TRANSPARENT + LTEXT "",IDC_STATIC,10,27,132,36,0,WS_EX_TRANSPARENT + DEFPUSHBUTTON "OK",IDOK,42,90,34,15 + DEFPUSHBUTTON "Cancel",IDCANCEL,80,90,34,15 + EDITTEXT IDC_EDIT1,32,73,92,12,ES_AUTOHSCROLL | NOT WS_BORDER +END + +DIALOG_CREATE_NAME DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Create Name",IDC_STATIC,4,5,146,12 + RTEXT "Name",IDC_STATIC,2,46,46,12 + RTEXT "Password",IDC_STATIC,2,69,46,12 + EDITTEXT IDC_EDIT_NAME,52,46,94,12,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_PASSWORD,52,69,94,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "Accept",IDOK,26,98,40,15 + PUSHBUTTON "Cancel",IDESCAPE,88,98,40,15 +END + +DIALOG_FILTER_JOIN_GAME DIALOGEX 0, 61, 256, 146 +STYLE WS_POPUP | WS_VISIBLE | WS_CLIPCHILDREN +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT_NAME,168,50,76,12,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_PASSWORD,168,69,76,12,ES_AUTOHSCROLL + LISTBOX IDC_GAMELIST,10,40,97,99,LBS_OWNERDRAWFIXED | + LBS_HASSTRINGS | LBS_USETABSTOPS | WS_CLIPSIBLINGS | + WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,179,128,34,15 + PUSHBUTTON "Cancel",IDCANCEL,214,128,34,15 + CTEXT "Join Game",IDC_TITLE,130,8,114,9,0,WS_EX_TRANSPARENT + RTEXT "Name:",IDC_STATIC,130,50,36,12,0,WS_EX_TRANSPARENT + RTEXT "Password:",IDC_STATIC,130,69,36,12,0,WS_EX_TRANSPARENT + LTEXT "To Join a game, enter the game information below.", + IDC_STATIC,130,23,114,18,0,WS_EX_TRANSPARENT + CTEXT "Matching Public Games",IDC_STATIC,10,8,104,9,0, + WS_EX_TRANSPARENT + LTEXT "",IDC_GAMEDESCRIPTION,130,88,114,27 + CONTROL "",IDC_SCROLLBAR,"StormScrollbar",WS_CLIPSIBLINGS,107,40, + 7,99 + CONTROL "",IDC_FILTER,"StormComboBox",WS_CLIPSIBLINGS | + WS_TABSTOP | 0x3,10,22,104,14 +END + +DIALOG_NEW_ACCOUNT DIALOGEX DISCARDABLE 0, 61, 256, 146 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,179,128,34,15 + PUSHBUTTON "Cancel",IDCANCEL,214,128,34,15 + EDITTEXT IDC_NAME,23,32,85,12,ES_AUTOHSCROLL + EDITTEXT IDC_PASS1,23,58,85,12,ES_AUTOHSCROLL|ES_PASSWORD + EDITTEXT IDC_PASS2,23,83,85,12,ES_AUTOHSCROLL|ES_PASSWORD + LTEXT "Password:",IDC_STATIC,23,50,72,8,0,WS_EX_TRANSPARENT + LTEXT "Name:",IDC_STATIC,23,24,72,8,0,WS_EX_TRANSPARENT + LTEXT "Repeat Password:",IDC_STATIC,23,75,72,8,0,WS_EX_TRANSPARENT + CTEXT "New Account",IDC_STATIC,10,4,234,10,0,WS_EX_TRANSPARENT +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1997,3,21,1 + PRODUCTVERSION 1997,3,21,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Blizzard Entertainment\0" + VALUE "FileDescription", "Battle.snp\0" + VALUE "FileVersion", "1.03\0" + VALUE "InternalName", "Battle.snp\0" + VALUE "LegalCopyright", "Copyright © 1997, Blizzard Entertainment\0" + VALUE "OriginalFilename", "Battle.snp\0" + VALUE "ProductName", "Battle.net Service Provider\0" + VALUE "ProductVersion", "1.03\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_PASSWORD_MISMATCH "The passwords you have typed do not match. Please enter the same password twice." + IDS_CHAT_HELP_RES "chat_help" + IDS_NAME_REQUIRED "You must enter a name for the game." + IDS_ASK_UPDATE "There is a new version of software available. Battle.net requires that you use the latest version. Your software will be updated now." + IDS_PREP_RESTART "The update has been downloaded successfully. Your application will now restart." + IDS_CHAT_JOIN_ROOM "%cJoining channel: %s" + IDS_CHAT_PLAYER_LEFT_ROOM "%c%s has left the channel." + IDS_CHAT_PLAYER_ENTERED_ROOM "%c%s has joined the channel." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_JOIN_FAILED "You were unable to join the selected game." + IDS_ERR_UNREACHABLE "Battle.net is not responding, please wait and try connecting again later." + IDS_BATTLENET "Battle.net" + IDS_ERR_NOTRESPONDING "The connection to Battle.net has been interrupted. Please try again later." + IDS_ERR_UNABLETOUPGRADE "Battle.net was unable to properly identify your application version. Please reinstall the application from the CD and then reconnect to Battle.net." + IDS_ERR_DOWNLOADFAILED "The update has been interrupted. No changes were made. Please try this process again." + IDS_DOWNLOADPROGRESS "Downloading software upgrade." + IDS_WHISPER_FROM "From: " + IDS_WHISPER_TO "To: " + IDS_ERR_INVALIDBETAID "You have entered an Invalid ID." + IDS_ERR_CANTWHISPER "You have not chosen a player to whisper to. You must first select a player from the list. Then, click whisper to send your message only to that player." + IDS_CHANNEL_NAME_INVALID + "Invalid channel name. A channel name cannot contain reserved characters." + IDS_FIRST_NASTY "gvdl" + IDS_NASTY0 "dvou" + IDS_NASTY1 "tiju" + IDS_NASTY2 "cjudi" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NASTY3 "bttipmf" + IDS_NASTY4 "ojhhfs" + IDS_NASTY5 "cmj{{bse" + IDS_LAST_NASTY "benjo" + IDS_ERR_CHATNOTHINGTOSEND + "To chat with other players, you must first type a message to send." + IDS_PROMPT_CREATECHANNEL + "The ""%s"" channel is currently empty. Do you want to create a new channel with this name?" + IDS_CHANNEL_FULL "The ""%s"" channel is currently full. Please try again later." + IDS_ERR_BADCONNECTION "Unable to connect to the Battle.net. If you are using a modem to access your service provider and are not configured for Dialup Networking, you may have to initiate the the connection manually." + IDS_ERR_BADSERVICEPROVIDER + "Your Internet connection is either very poor or is not processing UDP packets. Contact your service provider or your system administrator for assistance. When connected to Battle.net, you will be able to chat but will not be able to play games." + IDS_CHANNEL_FMT "%s (%d)" + IDS_USERUNSQUELCHED_FMT "%cAccepting messages from %s." + IDS_USERSQUELCHED_FMT "%cIgnoring messages from %s." + IDS_VERBOSE_FMT "%cEnter/Leave notifications: ON" + IDS_NONVERBOSE_FMT "%cEnter/Leave notifications: OFF" + IDS_ERR_NOWSOCK32 "Your system has not been configured to support 32 bit Internet applications or Dialup Networking has not been configured for Auto Dial. You may have to connect to your internet provider manually before logging into Battle.net." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_QUERYBROWSEWEB "You have clicked on a link to the Internet. Your web browser will now be launched. You can use the Windows Taskbar to return to Battle.net." + IDS_QUERYDISCONNECT "You have disconnected from Battle.net. Press OK to hangup the connection to %s. Press Cancel to stay connected." + IDS_BROWSERERROR "Battle.net was unable to launch your default browser." + IDS_ERR_HOST_UNREACHABLE + "You were unable to join. The game you have selected is not responding. " + IDS_ERR_GAME_FULL "You were unable to join. The game you have selected is currently full." + IDS_ENTERPASSWORD """%1"" is a registered Battle.net name. Please enter the password for ""%1"", or select New Account to choose a different name." + IDS_RENAMECHARACTER """%1"" is already registered as a unique Battle.net name. Please enter a new name for your character." + IDS_ERR_INVALIDPASSWORD "You have entered an incorrect password. If your character has not been on Battle.net for 3 months, or if you forgot your password, you can select ""New Account"" to choose a new name and password." + IDS_TITLE_INVALIDPASSWORD "Invalid Password" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SOURCE/BATTLE/BNETART.H b/src/Storm/SOURCE/BATTLE/BNETART.H new file mode 100644 index 0000000..9b902d9 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/BNETART.H @@ -0,0 +1,35 @@ +/**************************************************************************** +* +* bnetart.h +* +* This file should be included by an application that wants to provide +* battle.net-specific artwork in its art callback. +* +***/ + +enum _BATTLENET_ART { + SNET_ART_BATTLE_BTNS = 0x80000000, + SNET_ART_BATTLE_CHAT_BKG, + SNET_ART_BATTLE_GREENLAG, + SNET_ART_BATTLE_YELLOWLAG, + SNET_ART_BATTLE_REDLAG, + SNET_ART_BATTLE_CONNECT_BKG, + SNET_ART_BATTLE_SELECT_CHNL_BKG, + SNET_ART_BATTLE_LOGIN_BKG, + SNET_ART_BATTLE_NEW_ACCOUNT_BKG, + + SNET_ART_BATTLE_BADCONNECTION, + SNET_ART_BATTLE_WELCOME_AD, + SNET_ART_BATTLE_LRG_EDIT_POPUP_BKG, +}; + +#define SNET_ART_SCOMBOLEFT 19 +#define SNET_ART_SCOMBOMIDDLE 20 +#define SNET_ART_SCOMBORIGHT 21 + +#define SNET_UIFLAG_SUPPORTS_LADDER 0x00000001 + +enum _BATTLENET_DATA { + SNET_DATA_BATTLE_LOGODELAY = 0x80000000, // (DWORD) delay between frames +}; + diff --git a/src/Storm/SOURCE/BATTLE/BNETLOGO.CPP b/src/Storm/SOURCE/BATTLE/BNETLOGO.CPP new file mode 100644 index 0000000..7962cb2 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/BNETLOGO.CPP @@ -0,0 +1,307 @@ +/*************************************************************************** +* +* bnetlogo.cpp +* Battle.net parent dialog +* +* This routine displays the Battle.net game logo and advertisement while +* the user is logged into Battle.net. +* +* By Michael Morhaime +* +***/ + +#include "pch.h" + +extern HWND ghWndUiMainParent; +extern HWND ghWndChat; + +//*************************************************************************** +extern BOOL CALLBACK ChatRoomDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); + +extern BOOL LogoInit(HWND child, SNETGETARTPROC artcallback); +extern void LogoAnimate(HWND hWndParent, HWND hWndLogo); +extern void LogoFramesDestroy(void); +extern BOOL LogoSetTimer(HWND window, int nTimer, SNETGETDATAPROC getdatacallback); + +extern BOOL UiLoadCustomArt( + SNETGETARTPROC artcallback, + HWND hWnd, + DWORD artid, + int nFirstColor, + int nNumColorsUsed, + BOOL bSetPaletteNow, + LPBYTE *data, + SIZE *size); + +extern BOOL CALLBACK AdDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); + + +//*************************************************************************** + +#define LOGO_TIMER_ID 1 +#define SRVMAINTAIN_TIMER_ID 2 +#define SRVMAINTAIN_TIMER_DELAY 5000 // every 5 seconds + +static LPBYTE backgroundbitmap = NULL; + +//=========================================================================== +static void DestroyArtwork (HWND window) { + TPBMP tpBmp = (TPBMP) GetWindowLong(GetDlgItem(window, IDC_LOGO_ANIMATE), GWL_USERDATA); + + // tpBmp->data points to a sgBackgroundBmp, which will be freed below + if (tpBmp) + FREE(tpBmp); + + LogoFramesDestroy(); + + + if (backgroundbitmap) { + FREE(backgroundbitmap); + backgroundbitmap = NULL; + } + + // Free artwork for scrollbar + ScrollbarDestroyArtwork(); +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window, SNETGETARTPROC artcallback) { + SIZE bgSize; + + + UiLoadArtwork( + artcallback, + window, + NULL, + SNET_ART_BACKGROUND, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TRUE, // Get palette from this artwork + TRUE, // Prep palette for 'fade in' + &backgroundbitmap, + &bgSize); + + + + // set up a TPBMP for the logo window, it will have information about the background bitmap + HWND hWndLogo = GetDlgItem(window, IDC_LOGO_ANIMATE); + + if (hWndLogo && backgroundbitmap) { + TPBMP tpBmp = (TPBMP) ALLOC(sizeof(TBMP)); + SetWindowLong(hWndLogo, GWL_USERDATA, (LONG) tpBmp); + if (tpBmp) { + tpBmp->data = backgroundbitmap; + tpBmp->datasize = bgSize; + } + + // set up the animating application logo + LogoInit(hWndLogo,artcallback); + LogoAnimate(window, hWndLogo); + } + + // Load Scrollbar art (shared by many children of this dialog) + ScrollbarLoadArtwork(artcallback); + return 0; +} + + + + +//=========================================================================== +static BOOL DoChatRoom (UIPARAMSPTR pUIparams, HWND hWndBattleNet) { + UIPARAMS UIparams; + SNETUIDATA interfacedata; + + // Create a copy of the UIparams and replace the parent window. + UIparams = *pUIparams; + interfacedata = *UIparams.interfacedata; + interfacedata.parentwindow = hWndBattleNet; + UIparams.interfacedata = &interfacedata; + + LPCTSTR pszTemplate = TEXT("DIALOG_CHATROOM"); + if (interfacedata.uiflags & SNET_UIFLAG_SUPPORTS_LADDER) + pszTemplate = TEXT("DIALOG_LADDER_CHATROOM"); + + return (1 == SDlgDialogBoxParam( + global_hinstance, + pszTemplate, + hWndBattleNet, + ChatRoomDialogProc, + (LPARAM)&UIparams)); +} + +//=========================================================================== +void KillChildWindows(HWND hWndParent, HWND hWndTop) { + HWND hWnd; + BOOL bKilledChat = FALSE; + + if (hWndTop != NULL) { + hWnd = hWndTop; + while (hWnd != hWndParent) { + if (hWnd == ghWndChat) + bKilledChat = TRUE; + + SDlgEndDialog(hWnd, 0); + hWnd = GetParent(hWnd); + } + } + + // Make sure chat room was killed (it might have hidden itself and started another child of the big window) + if (!bKilledChat) + SDlgEndDialog(ghWndChat, 0); +} + +//=========================================================================== +BOOL CALLBACK BattleNetDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + static UIPARAMSPTR uiparams = NULL; + + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: { + HWND hWndAd = NULL; + SNETUIDATA Interfacedata; + + // First make sure window has been drawn + UpdateWindow(window); + + // This is our signal to launch the ChatRoom and the advertisement window. + if (uiparams) { + // Advertisement window is a modeless dialog. + Interfacedata = *(uiparams->interfacedata); + Interfacedata.parentwindow = window; + hWndAd = SDlgCreateDialogParam( + global_hinstance, + TEXT("DIALOG_AD"), + window, + AdDialogProc, + (LPARAM)&Interfacedata); + } + + + + // Once the chatroom returns, we are finished. + // Note that the WM_TIMER will continue firing, so we can display + // things like advertisements and continue animating the application logo. + SDlgEndDialog(window, DoChatRoom(uiparams, window)); + + if (hWndAd && IsWindow(hWndAd)) + DestroyWindow(hWndAd); + return 1; + } + } + break; + + case WM_ERR_NOTRESPONDING: { + char szText[256]; + char szTitle[32]; + + LoadString(global_hinstance, IDS_BATTLENET, szTitle, sizeof(szTitle)); + LoadString(global_hinstance, IDS_ERR_NOTRESPONDING, szText, sizeof(szText)); + UiMessageBox(uiparams->interfacedata->messageboxcallback, window, szText, szTitle, MB_OK | MB_ICONERROR); + return 1; + } + + case WM_TIMER: + if (wparam == LOGO_TIMER_ID) { + LogoAnimate(window, GetDlgItem(window, IDC_LOGO_ANIMATE)); + + // Make sure the connection is still active. + if (gbConnectionLost) { + char szText[256]; + char szTitle[32]; + + // Save current top level window for application + HWND hWnd = GetActiveWindow(); + + gbConnectionLost = FALSE; // Reset flag so we can continue animating logo while dialog is up. + + LoadString(global_hinstance, IDS_BATTLENET, szTitle, sizeof(szTitle)); + LoadString(global_hinstance, IDS_ERR_NOTRESPONDING, szText, sizeof(szText)); + UiMessageBox(uiparams->interfacedata->messageboxcallback, hWnd, szText, szTitle, MB_OK | MB_ICONERROR); + + // Kill off children dialogs + KillChildWindows(window, hWnd); + } + } + else if (wparam == SRVMAINTAIN_TIMER_ID) { + // Update lag counters in chat room + SrvMaintainLatencies(); + + // Download new ads + SrvMaintainAds(); + } + + return 0; + + case WM_NOTIFICATION_WAITING: + UiNotification(); + return 1; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + + case WM_QUERYNEWPALETTE: { + // We are gaining focus, so set our own prefs + UpdateWindow(window); // draw window first.. syscolor stuff may take a while + ColorPrefActivate(TRUE); + break; + } + case WM_ACTIVATEAPP: + // If we are losing focus, restore windows system prefs + if (!wparam) + ColorPrefActivate(FALSE); + break; + + case WM_DESTROY: + ghWndUiMainParent = NULL; + + UiVidFadeOut(DEFAULT_STEPS*2); + + SDlgKillTimer(window, LOGO_TIMER_ID); + SDlgKillTimer(window, SRVMAINTAIN_TIMER_ID); + + DestroyArtwork(window); + break; + + case WM_INITDIALOG: + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + uiparams = (UIPARAMSPTR)lparam; + if (!uiparams) + return 1; + + LoadArtwork(window, uiparams->interfacedata->artcallback); + + LogoSetTimer(window, LOGO_TIMER_ID, uiparams->interfacedata->getdatacallback); + SDlgSetTimer(window, SRVMAINTAIN_TIMER_ID, SRVMAINTAIN_TIMER_DELAY, NULL); + + // Signal for us to launch the Chatroom. We launch it here, since the chatroom is modal. + PostMessage(window, WM_COMMAND, IDOK, (LPARAM)NULL); + + // This window will receive wm_notification_waiting message + ghWndUiMainParent = window; + + UiLoadCursors(window, uiparams->interfacedata); + + // Turn on colors + UiVidFade(1,1); + return 1; + } + + return SDlgDefDialogProc(window,message,wparam,lparam); + +} diff --git a/src/Storm/SOURCE/BATTLE/CACHE.CPP b/src/Storm/SOURCE/BATTLE/CACHE.CPP new file mode 100644 index 0000000..9a18071 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/CACHE.CPP @@ -0,0 +1,593 @@ +/**************************************************************************** +* +* CACHE.CPP +* battle.net file caching functions +* +* By Michael O'Brien (11/24/96) +* +***/ + +#include "pch.h" + +#define ARCHIVENAME "bncache.dat" +#define DEFENTRIES 1024 // must be a power of two +#define DEFLCID MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT) +#define MAXFILESIZE 0x01000000 +#define FILEFLAGS 0xC0000000 +#define SIGNATURE 0x1A434E42 +#define DEALLOCATED 0xFFFFFFFE +#define NOBLOCK 0xFFFFFFFF + +#define HASH_INDEX 0 +#define HASH_CHECK0 1 +#define HASH_CHECK1 2 +#define HASH_ENCRYPTKEY 3 +#define HASH_ENCRYPTDATA 4 + +typedef struct _ARCHIVEHEADER { + DWORD signature; + DWORD headersize; + DWORD archivesize; + DWORD version; + DWORD hashoffset; + DWORD blockoffset; + DWORD hashentries; + DWORD blockentries; +} ARCHIVEHEADER, *ARCHIVEHEADERPTR; + +typedef struct _HASHENTRY { + DWORD hashcheck[2]; + LCID lcid; + DWORD block; +} HASHENTRY, *HASHENTRYPTR; + +typedef struct _BLOCKENTRY { + DWORD offset; + DWORD sizealloc; + DWORD sizefile; + DWORD flags; +} BLOCKENTRY, *BLOCKENTRYPTR; + +typedef struct _FILEHEADER { + DWORD headersize; // must be first field + DWORD headerversion; + DWORD attributes; + DWORD reserved1; + FILETIME lastaccesstime; + FILETIME lastwritetime; + FILETIME creationtime; + FILETIME minexpiretime; + FILETIME maxexpiretime; + char filename[MAX_PATH]; +} FILEHEADER, *FILEHEADERPTR; + +static HANDLE cache_archivefile = INVALID_HANDLE_VALUE; +static ARCHIVEHEADERPTR cache_archiveheader = NULL; +static BLOCKENTRYPTR cache_blocktable = NULL; +static CCritSect cache_critsect; +static LPDWORD cache_hashsource = NULL; +static HASHENTRYPTR cache_hashtable = NULL; +static BOOL cache_initialized = 0; + +//=========================================================================== +static void inline Decrypt (LPDWORD data, DWORD bytes, DWORD key) { + DWORD adjust = 0xEEEEEEEE; + DWORD iter = bytes >> 2; + while (iter--) { + adjust += *(cache_hashsource+(HASH_ENCRYPTDATA << 8)+(key & 0xFF)); + adjust += (*data++ ^= adjust+key)+(adjust << 5)+3; + key = (key >> 11) | ((key << 21) ^ 0xFFE00000)+0x11111111; + } +} + +//=========================================================================== +static void inline Encrypt (LPDWORD data, DWORD bytes, DWORD key) { + DWORD adjust = 0xEEEEEEEE; + DWORD iter = bytes >> 2; + while (iter--) { + DWORD origdata = *data; + adjust += *(cache_hashsource+(HASH_ENCRYPTDATA << 8)+(key & 0xFF)); + *data++ = origdata ^ (adjust+key); + adjust += origdata + (adjust << 5)+3; + key = (key >> 11) | ((key << 21) ^ 0xFFE00000)+0x11111111; + } +} + +//=========================================================================== +static FILETIME *GetCurrentFileTime (DWORD offsetseconds) { + static FILETIME filetime; + static DWORD lastoffset = 0; + static DWORD lastcall = 0; + if ((offsetseconds != lastoffset) || + (GetTickCount() != lastcall)) { + SYSTEMTIME systime; + GetSystemTime(&systime); + SystemTimeToFileTime(&systime,&filetime); + __int64 offset = 10000000ul; + offset *= (__int64)offsetseconds; + *(__int64 *)&filetime += offset; + lastoffset = offsetseconds; + lastcall = GetTickCount(); + } + return &filetime; +} + +//=========================================================================== +static DWORD inline Hash (LPCSTR filename, int hashtype) { + DWORD result = 0x7FED7FED; + DWORD adjust = 0xEEEEEEEE; + while (filename && *filename) { + char origchar = toupper(*filename++); + result = (result+adjust) ^ *(cache_hashsource+(hashtype << 8)+origchar); + adjust += origchar+result+(adjust << 5)+3; + } + return result; +} + +//=========================================================================== +static void inline InitializeHashSource () { + if (cache_hashsource) { + DWORD seed = 0x100001; + for (int loop1 = 0; loop1 < 256; ++loop1) + for (int loop2 = 0; loop2 < 5; ++loop2) { + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand1 = seed & 0xFFFF; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand2 = seed & 0xFFFF; + *(cache_hashsource+(loop2 << 8)+loop1) = (rand1 << 16) | rand2; + } + } +} + +//=========================================================================== +static DWORD inline SearchHashTable (LPCSTR filename, LCID lcid) { + DWORD hashindex = Hash(filename,HASH_INDEX); + DWORD hashcheck0 = Hash(filename,HASH_CHECK0); + DWORD hashcheck1 = Hash(filename,HASH_CHECK1); + DWORD entry = hashindex & (cache_archiveheader->hashentries-1); + DWORD firstentry = entry; + DWORD found = 0xFFFFFFFF; + while ((cache_hashtable+entry)->block != NOBLOCK) { + if (((cache_hashtable+entry)->hashcheck[0] == hashcheck0) && + ((cache_hashtable+entry)->hashcheck[1] == hashcheck1) && + ((cache_hashtable+entry)->block != DEALLOCATED)) + if ((cache_hashtable+entry)->lcid == lcid) + return entry; + else if ((cache_hashtable+entry)->lcid == MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT)) + found = entry; + entry = (entry+1) & (cache_archiveheader->hashentries-1); + if (entry == firstentry) + break; + } + return found; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +void CacheDestroy () { + cache_critsect.Enter(); + cache_initialized = 0; + if (cache_blocktable) { + FREE(cache_blocktable); + cache_blocktable = NULL; + } + if (cache_hashtable) { + FREE(cache_hashtable); + cache_hashtable = NULL; + } + if (cache_archiveheader) { + FREE(cache_archiveheader); + cache_archiveheader = NULL; + } + if (cache_archivefile) { + CloseHandle(cache_archivefile); + cache_archivefile = INVALID_HANDLE_VALUE; + } + if (cache_hashsource) { + FREE(cache_hashsource); + cache_hashsource = NULL; + } + cache_critsect.Leave(); +} + +//=========================================================================== +BOOL CacheFree (LPVOID data, DWORD databytes) { + if (!data) + return 0; + FREE(data); + return 1; +} + +//=========================================================================== +BOOL CacheInitialize () { + cache_critsect.Enter(); + if (cache_initialized) + CacheDestroy(); + __try { + + // INITIALIZE THE HASH TABLES + cache_hashsource = (LPDWORD)ALLOC(5*256*sizeof(DWORD)); + if (cache_hashsource) + InitializeHashSource(); + else + __leave; + + // DETERMINE THE PATH TO THE ARCHIVE FILE + TCHAR archivefilename[MAX_PATH] = ""; + GetModuleFileName(GetModuleHandle(NULL),archivefilename,MAX_PATH); + { + LPTSTR separator = strchr(archivefilename,'\\'); + while (separator && strchr(separator+1,'\\')) + separator = strchr(separator+1,'\\'); + if (separator) + *separator = 0; + } + strcat(archivefilename,"\\" ARCHIVENAME); + + // OPEN THE ARCHIVE FILE + cache_archivefile = CreateFile(archivefilename, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (cache_archivefile == INVALID_HANDLE_VALUE) + __leave; + + // LOAD THE ARCHIVE HEADER + cache_archiveheader = NEW(ARCHIVEHEADER); + if (!cache_archiveheader) + __leave; + { + DWORD bytesread = 0; + ReadFile(cache_archivefile,cache_archiveheader,sizeof(ARCHIVEHEADER),&bytesread,NULL); + } + if (cache_archiveheader->signature != SIGNATURE) { + ZeroMemory(cache_archiveheader,sizeof(ARCHIVEHEADER)); + cache_archiveheader->signature = SIGNATURE; + cache_archiveheader->headersize = sizeof(ARCHIVEHEADER); + } + + // LOAD THE HASH TABLE + DWORD hashentries = max(DEFENTRIES,cache_archiveheader->hashentries); + cache_hashtable = (HASHENTRYPTR)ALLOC(hashentries*sizeof(HASHENTRY)); + if (cache_hashtable) + ZeroMemory(cache_hashtable,hashentries*sizeof(HASHENTRY)); + else + __leave; + if (cache_archiveheader->hashoffset || cache_archiveheader->hashentries) { + SetFilePointer(cache_archivefile,cache_archiveheader->hashoffset,NULL,FILE_BEGIN); + DWORD bytesread; + ReadFile(cache_archivefile,cache_hashtable,hashentries*sizeof(HASHENTRY),&bytesread,NULL); + Decrypt((LPDWORD)cache_hashtable,hashentries*sizeof(HASHENTRY),Hash("(hash table)",HASH_ENCRYPTKEY)); + } + else { + cache_archiveheader->hashoffset = sizeof(ARCHIVEHEADER); + cache_archiveheader->hashentries = DEFENTRIES; + cache_archiveheader->archivesize = max(cache_archiveheader->archivesize, + cache_archiveheader->hashoffset + +DEFENTRIES*sizeof(HASHENTRY)); + for (DWORD loop = 0; loop < DEFENTRIES; ++loop) + (cache_hashtable+loop)->block = NOBLOCK; + } + + // LOAD THE BLOCK TABLE + DWORD blockentries = max(DEFENTRIES,cache_archiveheader->blockentries); + cache_blocktable = (BLOCKENTRYPTR)ALLOC(blockentries*sizeof(BLOCKENTRY)); + if (cache_blocktable) + ZeroMemory(cache_blocktable,DEFENTRIES*sizeof(BLOCKENTRY)); + else + __leave; + if (cache_archiveheader->blockoffset || cache_archiveheader->blockentries) { + SetFilePointer(cache_archivefile,cache_archiveheader->blockoffset,NULL,FILE_BEGIN); + DWORD bytesread; + ReadFile(cache_archivefile,cache_blocktable,blockentries*sizeof(BLOCKENTRY),&bytesread,NULL); + Decrypt((LPDWORD)cache_blocktable,blockentries*sizeof(BLOCKENTRY),Hash("(block table)",HASH_ENCRYPTKEY)); + } + else { + cache_archiveheader->blockoffset = sizeof(ARCHIVEHEADER)+DEFENTRIES*sizeof(HASHENTRY); + cache_archiveheader->archivesize = max(cache_archiveheader->archivesize, + cache_archiveheader->blockoffset + +DEFENTRIES*sizeof(BLOCKENTRY)); + } + + } + __finally { + if (cache_archiveheader && cache_blocktable && cache_hashtable) + cache_initialized = 1; + else + CacheDestroy(); + } + cache_critsect.Leave(); + return 1; +} + +//=========================================================================== +BOOL CacheLoadFile (LPCSTR filename, + FILETIME *lastwritetime, + LPVOID *data, + DWORD *databytes) { + if (lastwritetime) + ZeroMemory(lastwritetime,sizeof(FILETIME)); + if (data) + *data = NULL; + if (databytes) + *databytes = 0; + if (!(filename && *filename && data && databytes && cache_initialized)) + return 0; + cache_critsect.Enter(); + + // FIND THE REQUESTED FILE + DWORD index = SearchHashTable(filename,DEFLCID); + if (index == 0xFFFFFFFF) { + cache_critsect.Leave(); + return 0; + } + DWORD block = (cache_hashtable+index)->block; + if (block >= cache_archiveheader->blockentries) { + cache_critsect.Leave(); + return 0; + } + + // LOAD ITS DATA BLOCK + FILEHEADER fileheader; + ZeroMemory(&fileheader,sizeof(FILEHEADER)); + if ((cache_blocktable+block)->flags & FILEFLAGS) { + SetFilePointer(cache_archivefile, + (cache_blocktable+block)->offset, + NULL, + FILE_BEGIN); + DWORD bytesread; + ReadFile(cache_archivefile, + &fileheader.headersize, + sizeof(DWORD), + &bytesread, + NULL); + ReadFile(cache_archivefile, + &fileheader.headersize+1, + min(fileheader.headersize,sizeof(FILEHEADER))-sizeof(DWORD), + &bytesread, + NULL); + } + + // VERIFY THAT IT IS THE CORRECT FILE AND THAT IT HASN'T EXPIRED + if (_stricmp(filename,fileheader.filename)) { + cache_critsect.Leave(); + return 0; + } + if (CompareFileTime(GetCurrentFileTime(0),&fileheader.maxexpiretime) > 0) { + cache_critsect.Leave(); + return 0; + } + + // VERIFY THAT THE SIZE IS REASONABLE + if ((cache_blocktable+block)->sizefile > MAXFILESIZE) { + cache_critsect.Leave(); + return 0; + } + + // GET THE LAST WRITE TIME + if (lastwritetime) + CopyMemory(lastwritetime,&fileheader.lastwritetime,sizeof(FILETIME)); + + // UPDATE THE LAST ACCESS TIME + CopyMemory(&fileheader.lastaccesstime,GetCurrentFileTime(0),sizeof(FILETIME)); + SetFilePointer(cache_archivefile, + (cache_blocktable+block)->offset, + NULL, + FILE_BEGIN); + { + DWORD byteswritten; + WriteFile(cache_archivefile, + &fileheader, + min(sizeof(FILEHEADER),fileheader.headersize), + &byteswritten, + NULL); + } + + // ALLOCATE A BUFFER AND READ THE FILE DATA + *data = ALLOC((cache_blocktable+block)->sizefile); + if (!*data) { + cache_critsect.Leave(); + return 0; + } + SetFilePointer(cache_archivefile, + (cache_blocktable+block)->offset+fileheader.headersize, + NULL, + FILE_BEGIN); + ReadFile(cache_archivefile, + *data, + (cache_blocktable+block)->sizefile, + databytes, + NULL); + + cache_critsect.Leave(); + return 1; +} + +//=========================================================================== +BOOL CacheSaveFile (LPCSTR filename, + LPVOID data, + DWORD databytes, + FILETIME *lastwritetime, + DWORD minexpireseconds, + DWORD maxexpireseconds) { + if (!(filename && *filename && data && databytes && lastwritetime && + maxexpireseconds && cache_initialized)) + return 0; + cache_critsect.Enter(); + + // REMOVE ANY EXISTING INSTANCES OF THIS FILE + { + DWORD index = SearchHashTable(filename,DEFLCID); + while (index != 0xFFFFFFFF) { + DWORD block = (cache_hashtable+index)->block; + if (block < cache_archiveheader->blockentries) { + (cache_blocktable+block)->sizefile = 0; + (cache_blocktable+block)->flags = 0; + } + (cache_hashtable+index)->block = DEALLOCATED; + index = SearchHashTable(filename,DEFLCID); + } + } + + // SEARCH FOR A FREE BLOCK WHICH IS BIG ENOUGH TO STORE THE FILE + DWORD minalloc = sizeof(FILEHEADER)+databytes; + DWORD block = 0; + while ((block < cache_archiveheader->blockentries) && + ((cache_blocktable+block)->flags || + ((cache_blocktable+block)->sizealloc < minalloc))) + ++block; + + // IF WE DIDN'T FIND ONE, THEN SEARCH FOR A BLOCK WHICH IS PAST ITS + // MINIMUM EXPIRATION TIME AND IS BIG ENOUGH TO STORE THE FILE + if (block >= cache_archiveheader->blockentries) { + block = 0; + while (block < cache_archiveheader->blockentries) { + if ((cache_blocktable+block)->sizealloc >= minalloc) { + SetFilePointer(cache_archivefile, + (cache_blocktable+block)->offset, + NULL, + FILE_BEGIN); + FILEHEADER fileheader; + ZeroMemory(&fileheader,sizeof(FILEHEADER)); + DWORD bytesread; + ReadFile(cache_archivefile, + &fileheader.headersize, + sizeof(DWORD), + &bytesread, + NULL); + ReadFile(cache_archivefile, + &fileheader.headersize+1, + min(fileheader.headersize,sizeof(FILEHEADER))-sizeof(DWORD), + &bytesread, + NULL); + if (CompareFileTime(GetCurrentFileTime(0),&fileheader.minexpiretime) > 0) + break; + } + ++block; + } + } + + // IF WE FOUND A BLOCK TO USE, REMOVE ANY HASH TABLE REFERENCES TO IT + if (block < cache_archiveheader->blockentries) { + for (DWORD index = 0; index < cache_archiveheader->hashentries; ++index) + if ((cache_hashtable+index)->block == block) + (cache_hashtable+index)->block = DEALLOCATED; + } + + // OTHERWISE, TRY TO CREATE A NEW BLOCK + else { + if (block >= DEFENTRIES) + return 0; + else { + (cache_blocktable+block)->offset = cache_archiveheader->archivesize; + (cache_blocktable+block)->sizealloc = minalloc; + cache_archiveheader->archivesize += minalloc; + cache_archiveheader->blockentries = block+1; + } + } + + // ADD A HASH TABLE ENTRY FOR THE BLOCK + { + DWORD hashindex = Hash(filename,HASH_INDEX); + DWORD hashcheck0 = Hash(filename,HASH_CHECK0); + DWORD hashcheck1 = Hash(filename,HASH_CHECK1); + DWORD entry = hashindex & (cache_archiveheader->hashentries-1); + DWORD firstentry = entry; + DWORD found = NOBLOCK; + while (((cache_hashtable+entry)->block != NOBLOCK) && + ((cache_hashtable+entry)->block != DEALLOCATED)) { + entry = (entry+1) & (cache_archiveheader->hashentries-1); + if (entry == firstentry) + break; + } + if (((cache_hashtable+entry)->block == NOBLOCK) || + ((cache_hashtable+entry)->block == DEALLOCATED)) { + (cache_hashtable+entry)->hashcheck[0] = hashcheck0; + (cache_hashtable+entry)->hashcheck[1] = hashcheck1; + (cache_hashtable+entry)->lcid = DEFLCID; + (cache_hashtable+entry)->block = block; + } + else { + cache_critsect.Leave(); + return 0; + } + } + + // FILL IN THE FILE'S BLOCK ENTRY + (cache_blocktable+block)->sizefile = databytes; + (cache_blocktable+block)->flags = FILEFLAGS; + + // FILL IN THE FILE HEADER + FILEHEADER fileheader; + ZeroMemory(&fileheader,sizeof(FILEHEADER)); + fileheader.headersize = sizeof(FILEHEADER); + CopyMemory(&fileheader.creationtime ,GetCurrentFileTime(0) ,sizeof(FILETIME)); + CopyMemory(&fileheader.lastwritetime ,lastwritetime ,sizeof(FILETIME)); + CopyMemory(&fileheader.minexpiretime ,GetCurrentFileTime(minexpireseconds),sizeof(FILETIME)); + CopyMemory(&fileheader.maxexpiretime ,GetCurrentFileTime(maxexpireseconds),sizeof(FILETIME)); + CopyMemory(&fileheader.lastaccesstime,GetCurrentFileTime(0) ,sizeof(FILETIME)); + strcpy(fileheader.filename,filename); + + // SAVE THE FILE + SetFilePointer(cache_archivefile, + (cache_blocktable+block)->offset, + NULL, + FILE_BEGIN); + { + DWORD byteswritten; + WriteFile(cache_archivefile, + &fileheader, + sizeof(FILEHEADER), + &byteswritten, + NULL); + WriteFile(cache_archivefile, + data, + databytes, + &byteswritten, + NULL); + } + + // SAVE THE FILE SYSTEM DATA + { + DWORD byteswritten; + SetFilePointer(cache_archivefile,0,NULL,FILE_BEGIN); + WriteFile(cache_archivefile, + cache_archiveheader, + sizeof(ARCHIVEHEADER), + &byteswritten, + NULL); + DWORD hashsize = max(DEFENTRIES,cache_archiveheader->hashentries )*sizeof(HASHENTRY); + DWORD blocksize = max(DEFENTRIES,cache_archiveheader->blockentries)*sizeof(BLOCKENTRY); + LPVOID buffer = ALLOC(max(hashsize,blocksize)); + if (buffer) { + SetFilePointer(cache_archivefile,cache_archiveheader->hashoffset,NULL,FILE_BEGIN); + CopyMemory(buffer,cache_hashtable,hashsize); + Encrypt((LPDWORD)buffer,hashsize,Hash("(hash table)",HASH_ENCRYPTKEY)); + WriteFile(cache_archivefile, + buffer, + hashsize, + &byteswritten, + NULL); + SetFilePointer(cache_archivefile,cache_archiveheader->blockoffset,NULL,FILE_BEGIN); + CopyMemory(buffer,cache_blocktable,blocksize); + Encrypt((LPDWORD)buffer,blocksize,Hash("(block table)",HASH_ENCRYPTKEY)); + WriteFile(cache_archivefile, + buffer, + blocksize, + &byteswritten, + NULL); + FREE(buffer); + } + } + + cache_critsect.Leave(); + return 1; +} diff --git a/src/Storm/SOURCE/BATTLE/CANCEL.CPP b/src/Storm/SOURCE/BATTLE/CANCEL.CPP new file mode 100644 index 0000000..b2443d7 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/CANCEL.CPP @@ -0,0 +1,136 @@ +/**************************************************************************** +* +* cancel.CPP +* battle.net +* +* By Michael Morhaime +* +***/ + +#include "pch.h" + + + +//**************************************************************************** +//**************************************************************************** + +static LPBYTE sgBackgroundBmp = NULL; +static LPBYTE sgButtonBmp = NULL; + + +//=========================================================================== +static void DestroyArtwork (HWND window) { + if (sgBackgroundBmp) { + FREE(sgBackgroundBmp); + sgBackgroundBmp = NULL; + } + + if (sgButtonBmp) { + FREE(sgButtonBmp); + sgButtonBmp = NULL; + } +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window, SNETGETARTPROC artcallback) { + int btn_ids[] = { + IDCANCEL, + 0 + }; + + int btn_static[] = { + IDC_TITLE, + 0 + }; + + SIZE sizeBtns; + SIZE bgSize; + + UiLoadArtwork( + artcallback, + window, + NULL, + SNET_ART_POPUPBACKGROUND_SML, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, // Palette is already loaded + FALSE, + &sgBackgroundBmp, + &bgSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BUTTON_SML, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgButtonBmp, + &sizeBtns); + + SDlgSetControlBitmaps (window, btn_ids, NULL, sgButtonBmp, &sizeBtns, SDLG_ADJUST_VERTICAL); + SDlgSetControlBitmaps (window, btn_static, NULL, sgBackgroundBmp, &bgSize, SDLG_ADJUST_CONTROLPOS); + + + return 1; +} + + + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + + + +//=========================================================================== +BOOL CALLBACK ConnectCancelDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + static SNETUIDATAPTR sInterfacedata; + static HWND shWndCancelDlg; + + switch (message) { + case WM_COMMAND: { + switch (LOWORD(wparam)) { + case IDOK: + case IDCANCEL: + SrvCancel(); + return 0; + } + break; + } + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + case WM_DESTROY: + DestroyArtwork(window); + break; + + case WM_INITDIALOG: + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + sInterfacedata = (SNETUIDATAPTR)lparam; + UiLoadCursors(window, sInterfacedata); + + if (sInterfacedata) + LoadArtwork(window, sInterfacedata->artcallback); + return 1; + + } + + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + diff --git a/src/Storm/SOURCE/BATTLE/CAPS.DAT b/src/Storm/SOURCE/BATTLE/CAPS.DAT new file mode 100644 index 0000000..b47082b Binary files /dev/null and b/src/Storm/SOURCE/BATTLE/CAPS.DAT differ diff --git a/src/Storm/SOURCE/BATTLE/CAPS.MPQ b/src/Storm/SOURCE/BATTLE/CAPS.MPQ new file mode 100644 index 0000000..c3a821c Binary files /dev/null and b/src/Storm/SOURCE/BATTLE/CAPS.MPQ differ diff --git a/src/Storm/SOURCE/BATTLE/CHAT.H b/src/Storm/SOURCE/BATTLE/CHAT.H new file mode 100644 index 0000000..b32aa85 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/CHAT.H @@ -0,0 +1,33 @@ +/**************************************************************************** +* +* chat.h +* +* By Michael Morhaime +* +***/ + + +// If connection is so bad, disable ability to create/join games +extern BOOL gbConnectionSucks; + + +// Defined in Chat.cpp, and chatchnnl.cpp +void ChatAddUser (SNADDUSERPTR pAddUserRec); +void ChatDeleteUser(SNDELETEUSERPTR pDeleteUserRec); +void ChatReceiveMsg(SNDISPLAYSTRINGPTR pDispStringRec); +void ChatAddChannel(LPCSTR szChannel); +void ChatDeleteChannel(LPCSTR szChanell); +void ChatJoinChannel(SNJOINCHANNELPTR pJoinChannelRec); +void ChatUpdatePingTime(SNUPDATEPINGTIMEPTR pUpdatePingTimeRec); +void ChatChannelFull(LPCSTR szChannel); +void ChatChannelDoesNotExist(LPCSTR szChannel); +void ChatSetUserName(LPCSTR szUserName); +void ChatChangeUserFlags(SNCHANGEUSERFLAGSPTR pChangeUserFlagsRec); +void ChatChannelRestricted(LPCSTR szChannel); +void ChatSquelchUser(SNSQUELCHUSERPTR pSquelchUserRec); +void ChatUnsquelchUser(SNSQUELCHUSERPTR pSquelchUserRec); + + +// Defined in Ad.cpp +void AdSetInfo(SNADINFOPTR pAdInfo); +void AdDisplay(LPVOID pVoid, DWORD dwSize); diff --git a/src/Storm/SOURCE/BATTLE/CHATCHNL.CPP b/src/Storm/SOURCE/BATTLE/CHATCHNL.CPP new file mode 100644 index 0000000..2c4507f --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/CHATCHNL.CPP @@ -0,0 +1,472 @@ +/**************************************************************************** +* +* chatchnl.cpp +* battle.net user interface functions +* +* By Michael Morhaime +* +***/ + +#include "pch.h" + +#define MAX_STRING_LEN 256 + +static HWND sghWndChannel = NULL; +static char sgszChannel[MAX_CHANNEL_LEN]; +static char *sgpszLastChannel; +static PTCHANNEL_LIST sgpChannelListHead = NULL; + +static LPBYTE sgBackgroundBmp = NULL; +static LPBYTE sgButtonBmp = NULL; +static SNETUIDATAPTR sgInterfacedata; + + + + +//=========================================================================== +// External Functions +//=========================================================================== +UINT ChatGetUserFlags(void); + +//=========================================================================== +static void DestroyArtwork (HWND window) { + if (sgBackgroundBmp) { + FREE(sgBackgroundBmp); + sgBackgroundBmp = NULL; + } + + if (sgButtonBmp) { + FREE(sgButtonBmp); + sgButtonBmp = NULL; + } +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window, SNETGETARTPROC artcallback) { + int btn_ids[] = { + IDOK, + IDCANCEL, + 0 + }; + + int btn_desc[] = { + IDC_GAMEDESCRIPTION, + 0, + }; + + SIZE sizeBtns; + SIZE bgSize; + + UiLoadArtwork( + artcallback, + window, + NULL, + SNET_ART_BATTLE_SELECT_CHNL_BKG, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgBackgroundBmp, + &bgSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BUTTON_XSML, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgButtonBmp, + &sizeBtns); + + SDlgSetControlBitmaps (window, btn_ids, NULL, sgButtonBmp, &sizeBtns, SDLG_ADJUST_VERTICAL); + SDlgSetControlBitmaps (window, btn_desc, NULL, sgBackgroundBmp, &bgSize, SDLG_ADJUST_CONTROLPOS); + return 1; +} + + +//=========================================================================== +static int ProcessName(LPSTR szName) { + char szTemp[MAX_CHANNEL_LEN]; + int nStart, nEnd; + + // Take the name and remove leading and trailing spaces + strcpy(szTemp, szName); + + + // Proceed until we find a non-space or null termination + for (nStart=0; ;nStart++) { + if (szTemp[nStart] != ' ') + break; + if (szTemp[nStart] == 0) + return 0; + } + + + // Now start at the end and look for a non-space character. Proceed until + // we reach the beginning + for (nEnd=strlen(szTemp)-1; ;nEnd--) { + + if (szTemp[nEnd] != ' ') + break; + + if (nEnd <= nStart) + return 0; + } + + szTemp[++nEnd] = 0; // NULL terminate string before trailing spaces + + strcpy(szName, &szTemp[nStart]); + return(nEnd - nStart); // Length of string not including NULL termination +} + + + +//**************************************************************************** +//**************************************************************************** +static void convert_nasty(LPSTR nasty) { + while (*nasty != 0) { + (*nasty)--; + nasty++; + } +} + +//**************************************************************************** +//**************************************************************************** +BOOL IsNastyName(LPCTSTR name) { + TCHAR tempname[MAX_CHANNEL_LEN]; + TCHAR nasty[MAX_CHANNEL_LEN]; + + strcpy(tempname, name); + _strlwr(tempname); + + for (int index = IDS_FIRST_NASTY; index <= IDS_LAST_NASTY; index++) { + LoadString(global_hinstance, index, nasty, MAX_CHANNEL_LEN); + convert_nasty(nasty); + _strlwr(nasty); + if (strstr(tempname, nasty)) { + return TRUE; + } + } + return FALSE; +} + + +//**************************************************************************** +// InvalidChars() +// +// NOTE: SPACE is not included as a bad char. SPACE and any other additional bad +// characters should be placed into the additional string. Things like GAME NAME +// may include spaces. +//**************************************************************************** +BOOL InvalidChars(LPCTSTR name, LPCTSTR additionalbad) { + LPTSTR basicbad = ",<>%&\\\"?*#/"; + unsigned char c; + + if (strpbrk(name, basicbad)) + return TRUE; + + if (strpbrk(name, additionalbad)) + return TRUE; + + while (0 != (c = *name)) { + if (c < ' ') return TRUE; + if ((c > '~') && (c < 0xc0)) return TRUE; + name++; + } + return FALSE; +} + + + +//=========================================================================== +static void AddChannels(HWND window) { + PTCHANNEL_LIST pCurr; + HWND hWndList; + + hWndList = GetDlgItem(window, IDC_CHANNELLIST); + if (!hWndList) + return; + + + // Add all the channels we know about to the linked list + pCurr = sgpChannelListHead; + while (pCurr) { + SendMessage(hWndList, LB_ADDSTRING, 0, (LPARAM)pCurr->szChannel); + pCurr = pCurr->next; + } + + // update our scroll bar + ListUpdateScrollbar(hWndList); +} + + +//=========================================================================== +// NOTE: szChannel will no longer be valid after hitting a PeekMessage loop +//=========================================================================== +void ChatChannelFull(LPCSTR szChannel) { + char szText[256]; + char szFmt[256]; + + // Protect this routine + if (!sghWndChannel || !sgInterfacedata) + return; + + LoadString(global_hinstance,IDS_CHANNEL_FULL,szFmt, sizeof(szFmt)); + sprintf(szText, szFmt, szChannel); + UiMessageBox(sgInterfacedata->messageboxcallback, sghWndChannel, szText, NULL, MB_OK); + + // Allow user to enter another channel name + EnableWindow(GetDlgItem(sghWndChannel, IDOK), TRUE); +} + + +//=========================================================================== +// NOTE: szChannel will no longer be valid after hitting a PeekMessage loop +//=========================================================================== +void ChatChannelDoesNotExist(LPCSTR szChannel) { + char szText[256]; + + // Make sure window is still around + if (!sghWndChannel) + return; + + // Make copy before sending this to a messagebox. + strcpy(szText, szChannel); + SendMessage(sghWndChannel, WM_CHANNEL_DOESNOTEXIST, 0, (LPARAM)szText); +} + +//=========================================================================== +// NOTE: szChannel will no longer be valid after hitting a PeekMessage loop +//=========================================================================== +void ChatChannelRestricted(LPCSTR szChannel) { + TCHAR szUserName[MAXSTRINGLENGTH]; + TCHAR szUserDesc[MAXSTRINGLENGTH]; + UINT nFlags; + char szError[256] = ""; + + if (!sghWndChannel) + return; + + if (sgInterfacedata->authcallback) { + SrvGetLocalPlayerName (szUserName,sizeof(szUserName)); + SrvGetLocalPlayerDesc (szUserDesc,sizeof(szUserDesc)); + nFlags = ChatGetUserFlags(); + + + if (!sgInterfacedata->authcallback(SNET_AUTHTYPE_CHANNEL, szUserName, szUserDesc, nFlags, szChannel, szError, sizeof(szError))) { + SendMessage(sghWndChannel, WM_CHANNEL_RESTRICTED, 0, (LPARAM)szError); + return; + } + + // Ok to join channel + SrvJoinChannel(szChannel, TRUE); + } + +} + +//=========================================================================== +void ChatChannelJoined(LPCSTR szChannel) { + if (!sghWndChannel) + return; + + SendMessage(sghWndChannel, WM_CHANNEL_JOINED, 0, 0); +} + +//=========================================================================== +BOOL CALLBACK ChannelDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: { + char szText[MAX_STRING_LEN]; + + if (sgInterfacedata->soundcallback) + sgInterfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + SendDlgItemMessage(window, IDC_EDIT_NAME, WM_GETTEXT, MAX_CHANNEL_LEN, (LPARAM)(LPCSTR)szText); + + // Don't validate channel name if we selected a public channel from the list + if (LB_ERR == SendDlgItemMessage(window, IDC_CHANNELLIST, LB_GETCURSEL, 0, 0)) { + if (InvalidChars(szText, "") || !ProcessName(szText)) { + LoadString(global_hinstance,IDS_CHANNEL_NAME_INVALID,szText,MAX_STRING_LEN); + UiMessageBox(sgInterfacedata->messageboxcallback, window, szText, NULL, MB_OK | MB_ICONERROR); + return 1; + } + } + + // If user has requested the current channel, just exist the dialog + if (!strcmp(szText,sgpszLastChannel)) { + SDlgEndDialog(window, 0); + return 1; + } + + // Send request to join channel + SrvJoinChannel(szText, FALSE); + + // Name was okay, so save in the global channel string and return TRUE + strcpy(sgszChannel, szText); + + // Disable Window, until we know if we succeeded + EnableWindow((HWND)lparam, FALSE); + return 1; + } + + case IDCANCEL: + if (sgInterfacedata->soundcallback) + sgInterfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + sgszChannel[0] = 0; + SDlgEndDialog(window, 0); + return 1; + + case IDC_EDIT_NAME: + if (HIWORD(wparam) == EN_CHANGE) { + // If user types in name edit control, remove selection from list box. + if (GetFocus() == (HWND)lparam) + SendDlgItemMessage(window,IDC_CHANNELLIST,LB_SETCURSEL,(WPARAM)-1,0); + } + break; + + case IDC_CHANNELLIST: + if (HIWORD(wparam) == LBN_DBLCLK) { + HWND hWndChannelList = (HWND)lparam; + int nIndex; + + nIndex = SendMessage(hWndChannelList, LB_GETCURSEL, 0, 0); + if (nIndex != LB_ERR) { + // Make sure we update the edit control first + SendMessage(window,WM_COMMAND,MAKELONG(IDC_CHANNELLIST,LBN_SELCHANGE),(LPARAM)hWndChannelList); + + // Behave like OK was just pressed + SendMessage(window,WM_COMMAND,MAKELONG(IDOK,BN_CLICKED),(LPARAM)GetDlgItem(window, IDOK)); + } + } + else if (HIWORD(wparam) == LBN_SELCHANGE) { + HWND hWndChannelList = (HWND)lparam; + int nIndex = SendMessage(hWndChannelList, LB_GETCURSEL, 0, 0); + char szText[MAX_CHANNEL_LEN]; + + // Change text in Edit Control + if (nIndex != LB_ERR) { + SendMessage(hWndChannelList,LB_GETTEXT, nIndex, (LPARAM)(LPCSTR)szText); + SendDlgItemMessage(window, IDC_EDIT_NAME, WM_SETTEXT, 0, (LPARAM)(LPCSTR)szText); + } + + // update our scroll bar + ListUpdateScrollbar(hWndChannelList); + } + break; + } + break; + + case WM_CHANNEL_DOESNOTEXIST: { + char szText[256]; + char szFmt[256]; + int nResult; + + LoadString(global_hinstance,IDS_PROMPT_CREATECHANNEL,szFmt,sizeof(szFmt)); + sprintf(szText, szFmt, (LPCSTR)lparam); + nResult = (IDOK == UiMessageBox(sgInterfacedata->messageboxcallback, window, szText, NULL, MB_OKCANCEL)); + + if (!nResult) { + // If user said no, reenable OK button. + EnableWindow(GetDlgItem(window, IDOK), !nResult); + } + else { + // Send request to join channel, this time setting 'joinalways' flag + SrvJoinChannel((LPCSTR)lparam, TRUE); + } + + return 1; + } + + case WM_CHANNEL_RESTRICTED: { + UiMessageBox(sgInterfacedata->messageboxcallback, window, (LPCSTR)lparam, NULL, MB_OK | MB_ICONWARNING); + + // Allow user to select another channel + EnableWindow(GetDlgItem(window, IDOK), TRUE); + return 1; + } + + case WM_CHANNEL_JOINED: { + // This means that we have joined a channel + SDlgEndDialog(window, 1); + return 1; + } + + case WM_CTLCOLORSTATIC: + if (GetWindowLong((HWND)lparam, GWL_ID) == IDC_TITLE) { + SetTextColor((HDC) wparam, RGB(0xff, 0xff, 0x00)); + return (BOOL) GetStockObject(NULL_BRUSH); + } + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + + case WM_DESTROY: + sghWndChannel = NULL; + DestroyArtwork(window); + break; + + + case WM_INITDIALOG: + sgInterfacedata = (SNETUIDATAPTR) lparam; + sghWndChannel = window; + + LoadArtwork(window, sgInterfacedata->artcallback); + + ScrollbarLink(GetDlgItem(window, IDC_CHANNELLIST), GetDlgItem(window, IDC_SCROLLBAR)); + + SetWindowText(GetDlgItem(window, IDC_EDIT_NAME), sgpszLastChannel); + SendDlgItemMessage(window, IDC_EDIT_NAME, EM_LIMITTEXT, MAX_CHANNEL_LEN-1, 0); + + // Set height of channel list items (some systems get strange heights) + SendDlgItemMessage(window, IDC_CHANNELLIST, LB_SETITEMHEIGHT, 0, 19); + + AddChannels(window); + return 1; + + } + + return SDlgDefDialogProc(window,message,wparam,lparam); + +} + + +//=========================================================================== +// Exported functions +//=========================================================================== + + +//=========================================================================== +BOOL ChatSelectChannel(SNETUIDATAPTR interfacedata, char *szChannel, PTCHANNEL_LIST pChannelListHead) { + int nResult; + + // Clear channel string + sgszChannel[0] = 0; + sgpszLastChannel = szChannel; // Save a pointer to the old channel + sgpChannelListHead = pChannelListHead; + + nResult = SDlgDialogBoxParam( + global_hinstance, + TEXT("DIALOG_CHAT_CHANNEL"), + (interfacedata) ? interfacedata->parentwindow : SDrawGetFrameWindow(), + ChannelDialogProc, + (LPARAM)interfacedata); + + return (nResult == 1); +} + diff --git a/src/Storm/SOURCE/BATTLE/CHATHELP.TXT b/src/Storm/SOURCE/BATTLE/CHATHELP.TXT new file mode 100644 index 0000000..14f42af --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/CHATHELP.TXT @@ -0,0 +1,38 @@ +The buttons along the left side of the chat screen have the following functions: + +CHANNEL: Select a new channel to join or create a private channel. You will be prompted to choose either a Public Channel, or enter the name of a Private Channel that you wish to enter. To start a new Channel, enter the name of the Channel that you wish to create. + +CREATE: Create a new game for other players to join. You will be prompted to enter a name for this game and to choose a difficulty level at which you wish to play. You also have the option to make the game Private by assigning a password to the game. Other players who wish to join your game will need to know the password you have selected. + +JOIN: Enter an existing game. You can join either a Public or Private game. Public games can be joined any time they have less than four players within them. To join a Private game you will be required to enter the name of the game and its assigned password. + +QUIT: Exits the Battle.net Connection Screen and returns you to the previous screen. + + +The window on the right side of the chat screen displays the name of the Channel that you are currently in and lists the other members within that Channel. The portrait for each player displays the class and level of their character. To the right of the player's name is a colored bar that indicates their Internet latency. The longer the bar, the slower their connection. + +To communicate with other members of a Channel, type your message within the box at the bottom of the screen and then click on either the SEND or the WHISPER button. + +SEND will display your message to everyone in your Channel. + +WHISPER will send your message to the selected player only. + +To select the player to whom you wish to WHISPER, click on the player's name. Only the player whose name is highlighted will receive messages that you WHISPER. + +To toggle player joining/leaving notifications, press Alt. + + +Special Chat Commands: + +/whereis : Searches for another player in public chat rooms and games. + +/whisper : Sends a private message to this player. (Short form: /w or /msg) + +/squelch : Ignore messages from this player. + +/unsquelch : Turns off squelch for this player. + +To quickly enter a player's name, double click on the player's name from the list. + +\ +*** (Do not remove '\') *** diff --git a/src/Storm/SOURCE/BATTLE/CHATROOM.CPP b/src/Storm/SOURCE/BATTLE/CHATROOM.CPP new file mode 100644 index 0000000..8c84455 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/CHATROOM.CPP @@ -0,0 +1,2045 @@ +/*************************************************************************** +* +* chatroom.cpp +* battle.net chat room +* +* By Michael Morhaime +* +* +* 10/26/96 DML - added ladder button +* +***/ + +#include "pch.h" + +#define LADDER_BUTTON 0 // 1 in final +#define TEST_USERLIST 0 // 0 in final + +//*************************************************************************** +BOOL CALLBACK JoinGameDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); + + +void ChatChannelJoined(LPCSTR szChannel); + +//*************************************************************************** +#define MAX_NAME_LEN 128 +#define MAX_CHAT_LEN (MAX_MSG_LEN+MAX_NAME_LEN+3) //+3 is for "<> " around players name +#define MAX_MSG_LEN 256 +#define MAX_USERLIST_LEN (2*MAX_NAME_LEN+24) + +#define MAX_CHAT_LINES 5000 +#define PRIVATE_CHANNEL_INDEX 0 + +#define MAX_NET_LAG 6 +#define LAG_UNIT_WIDTH 3 +#define RED_THRESHOLD 5 +#define YELLOW_THRESHOLD 3 + +#define CHAT_INDENT 12 + +#define BEGIN_NAME_CHAR '<' +#define END_NAME_CHAR '>' + +#define PREFSKEY "Preferences" +#define PREFSVALUE_VERBOSE "Verbose" + +#define USER_OFFICIAL_MASK (UF_BLIZZARD|UF_MODERATOR|UF_SPEAKER|UF_SYSOP) +#define IsUserOfficial() (gnUserFlags & USER_OFFICIAL_MASK) + + + + + + HWND ghWndChat = NULL; +static HWND sghWndMsgList = NULL; +static HFONT sghChatFont = 0; + +static LPBYTE backgroundbitmap = NULL; +static LPBYTE bnBtnbitmap = NULL; +static LPBYTE SmlBtnbitmap = NULL; + +static LPBYTE redlagbitmap = NULL; +static LPBYTE yellowlagbitmap = NULL; +static LPBYTE greenlagbitmap = NULL; +static LPBYTE bmpBadConn = NULL; + +static SIZE redSize; +static SIZE yellowSize; +static SIZE greenSize; +static SIZE sizeBadConn; + +static SIZE sgBtnSize; + +static char gszCurrentChannel[MAX_MSG_LEN] = ""; +static BOOL sgbModeratedChannel = FALSE; + +static int sgnTab = CHAT_INDENT; +static BOOL sgbLadderEnabled; + +enum _hilite_colors { + FIRST_COLOR_CHAR = 0x10, + eCOLOR_NORMAL = FIRST_COLOR_CHAR, + eCOLOR_WHISPER, + eCOLOR_NOTIFY, + eCOLOR_USERNAME, + eCOLOR_MYNAME, + eCOLOR_BLIZZARD, + eCOLOR_SYSOP, + eCOLOR_MODERATOR, + eCOLOR_SPEAKER, + eCOLOR_BROADCAST, + eCOLOR_INFORMATION, + eCOLOR_ERROR, + LAST_COLOR_CHAR = eCOLOR_ERROR, +}; + +static COLORREF sgHiliteColors[] = { + RGB(0xff, 0xff, 0xff), // COLOR_NORMAL (white) + RGB(0x80, 0x80, 0x80), // COLOR_WHISPER (gray) + RGB(0, 0xff, 0), // COLOR_NOTIFY (green) + RGB(0xff, 0xff, 0), // COLOR_USERNAME (yellow) + RGB(0, 0xff, 0xff), // COLOR_MYNAME (cyan) + RGB(0, 0xff, 0xff), // COLOR_BLIZZARD (cyan) + RGB(0, 0xff, 0xff), // COLOR_SYSOP (cyan) + RGB(0xff, 0xff, 0xff), // COLOR_MODERATOR (white) + RGB(0xff, 0xff, 0), // COLOR_SPEAKER (yellow) + RGB(0xff, 0, 0), // COLOR_BROADCAST (red) + RGB(0xff, 0xff, 0), // COLOR_INFORMATION (yellow) + RGB(0xff, 0, 0), // COLOR_ERROR (red) +}; + + + +typedef struct _SQUELCH_LIST { + char szName[MAX_NAME_LEN]; + _SQUELCH_LIST *next; +} TSQUELCH_LIST, *PTSQUELCH_LIST; + +static PTCHANNEL_LIST sgpChannelListHead = NULL; +static PTSQUELCH_LIST sgpSquelchListHead = NULL; +static char sgszUserName[MAX_NAME_LEN] = ""; +static char sgszUserDesc[MAX_USERLIST_LEN]; +static DWORD sgdwVerboseMode = FALSE; // Default join/leave messages to OFF +static BOOL sgbFirstChannel = FALSE; +int gnUserFlags = 0; + +//=========================================================================== +// External Decl +//=========================================================================== +extern BOOL ChatSelectChannel(SNETUIDATAPTR interfacedata, char *szChannel, PTCHANNEL_LIST pChannelListHead); + +//=========================================================================== +// Forward Decl +//=========================================================================== +void ChatAddUser (SNADDUSERPTR pAddUserRec); +void ChatDeleteUser(SNDELETEUSERPTR pDeleteUserRec); +void ChatAddChannel(LPCSTR szChannel); +void ChatDeleteChannel(LPCSTR szChanell); +void ChatJoinChannel(SNJOINCHANNELPTR pJoinChannelRec); +void ChatReceiveMsg(SNDISPLAYSTRINGPTR pDispStringRec); + + + + + +//=========================================================================== +static void DestroyArtwork (HWND window) { + if (backgroundbitmap) { + FREE(backgroundbitmap); + backgroundbitmap = NULL; + } + + if (bnBtnbitmap) { + FREE(bnBtnbitmap); + bnBtnbitmap = NULL; + } + + if (SmlBtnbitmap) { + FREE(SmlBtnbitmap); + SmlBtnbitmap = NULL; + } + + if (redlagbitmap) { + FREE(redlagbitmap); + redlagbitmap = NULL; + } + + if (yellowlagbitmap) { + FREE(yellowlagbitmap); + yellowlagbitmap = NULL; + } + + if (greenlagbitmap) { + FREE(greenlagbitmap); + greenlagbitmap = NULL; + } + if (bmpBadConn) { + FREE(bmpBadConn); + bmpBadConn = NULL; + } +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window, SNETGETARTPROC artcallback) { + int btn_ids[] = { + ID_CHATCHANNEL, + ID_CHATCREATE, + ID_CHATJOIN, + IDQUIT, + 0, + }; + int ladder_ids[] = { + ID_CHATCHANNEL, + ID_CHATCREATE, + ID_CHATJOIN, + ID_CHATLADDER, + IDQUIT, + 0, + }; + + int btn_small[] = { + IDOK, + ID_WHISPER, + 0, + }; + + int static_txt[] = { + IDC_STATIC_CHANNEL, + 0, + }; + + SIZE bnBtnSize; + SIZE SmlBtnSize; + SIZE bgSize; + + + UiLoadArtwork( + artcallback, + window, + NULL, + SNET_ART_BATTLE_CHAT_BKG, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, // Don't get palette from this artwork + FALSE, // Don't set pallete + &backgroundbitmap, + &bgSize); + + + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BATTLE_GREENLAG, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &greenlagbitmap, + &greenSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BATTLE_YELLOWLAG, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &yellowlagbitmap, + &yellowSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BATTLE_REDLAG, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &redlagbitmap, + &redSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BATTLE_BTNS, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &bnBtnbitmap, + &bnBtnSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BUTTON_XSML, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &SmlBtnbitmap, + &SmlBtnSize); + + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BATTLE_BADCONNECTION, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &bmpBadConn, + &sizeBadConn); + + if (sgbLadderEnabled) + SDlgSetControlBitmaps (window, + ladder_ids, + NULL, + bnBtnbitmap, + &bnBtnSize, + SDLG_ADJUST_VERTICAL); + else + SDlgSetControlBitmaps (window, + btn_ids, + NULL, + bnBtnbitmap, + &bnBtnSize, + SDLG_ADJUST_VERTICAL); + + SDlgSetControlBitmaps (window, btn_small, NULL, SmlBtnbitmap, &SmlBtnSize, SDLG_ADJUST_VERTICAL); + SDlgSetControlBitmaps (window, static_txt, NULL, backgroundbitmap, &bgSize, SDLG_ADJUST_CONTROLPOS); + + return 0; +} + + + + + + +//=========================================================================== +static BOOL CALLBACK ChatHelpDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + static UIPARAMSPTR uiparams = NULL; + static LPBYTE spHelpBmp = NULL; + static LPBYTE spHelpBtnsBmp = NULL; + static HGLOBAL hResource; + + + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: + case IDCANCEL: + if (uiparams->interfacedata->soundcallback) + uiparams->interfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + SDlgEndDialog(window, 0); + return 1; + } + + case WM_CTLCOLORSTATIC: + if (GetWindowLong((HWND)lparam, GWL_ID) == IDC_TITLE) { + SetTextColor((HDC) wparam, RGB(0xff, 0xff, 0x00)); + return (BOOL) GetStockObject(NULL_BRUSH); + } + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + case WM_HELP: + // Prevent parent window from bringing up another help window + return 1; + + + case WM_DESTROY: + if (spHelpBmp) { + FREE(spHelpBmp); + spHelpBmp = NULL; + } + + if (spHelpBtnsBmp) { + FREE(spHelpBtnsBmp); + spHelpBtnsBmp = NULL; + } + + //This is not necessary in Win95 or WinNT + //FreeResource(hResource); + break; + + case WM_INITDIALOG: { + char szHelpRes[20]; + char *pText; + char *pSearch; + char *pHelpText; + int i; + + HRSRC hRsrc; + SIZE sizeBtns; + int nSize; + int btn_ids[] = { + IDOK, + IDCANCEL, + 0, + }; + + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + uiparams = (UIPARAMSPTR)lparam; + + // Load artwork from callback + UiLoadArtwork( + uiparams->interfacedata->artcallback, + window, + NULL, + SNET_ART_HELPBACKGROUND, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &spHelpBmp, + NULL); + + + UiLoadArtwork( + uiparams->interfacedata->artcallback, + NULL, + NULL, + SNET_ART_BUTTON_SML, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &spHelpBtnsBmp, + &sizeBtns); + + SDlgSetControlBitmaps (window, btn_ids, NULL, spHelpBtnsBmp, &sizeBtns, SDLG_ADJUST_VERTICAL); + + + // Now load in help text + + LoadString(global_hinstance, IDS_CHAT_HELP_RES, szHelpRes, sizeof(szHelpRes)); + hRsrc = FindResource(global_hinstance, szHelpRes, "TEXT"); + hResource = LoadResource(global_hinstance, hRsrc); + + pText = (char *) LockResource(hResource); + nSize = SizeofResource(global_hinstance, hRsrc); + + // Make a copy of the resource, since Windows doesn't seem to + // like when we modify the original data. Not sure why. + pHelpText = (char *)ALLOC(nSize); + if (!pHelpText) + return 1; + + memcpy(pHelpText, pText, nSize); + for (i=0, pSearch=pHelpText; iparentwindow; + DWORD dwReturn; + + + // Hide the chat room so its controls don't get drawn when Select Channel Dlg disappears. + SetActiveWindow(hWndParent); + ShowWindow(ghWndChat, SW_HIDE); + + // Display the Select Channel Dlg + dwReturn = ChatSelectChannel(interfacedata, szChannel, pChannelListHead); + + // Restore Chatroom always + ShowWindow(ghWndChat, SW_SHOW); + + return dwReturn; +} +//=========================================================================== +static BOOL DoCreateGame (UIPARAMSPTR uiparams) { + DWORD dwReturn; + HWND hWndParent = uiparams->interfacedata->parentwindow; + + if (!uiparams->interfacedata->createcallback) + return 0; + + // BUILD A NEW INTERFACE DATA STRUCTURE CONTAINING OUR WINDOW HANDLE + SNETUIDATA interfacedata; + ZeroMemory(&interfacedata,sizeof(SNETUIDATA)); + if (uiparams->interfacedata) + CopyMemory(&interfacedata,uiparams->interfacedata,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = hWndParent; + + // BUILD A CREATION DATA STRUCTURE + SNETCREATEDATA createdata; + ZeroMemory(&createdata,sizeof(SNETCREATEDATA)); + createdata.size = sizeof(SNETCREATEDATA); + createdata.providerid = PROVIDERID; + createdata.maxplayers = global_maxplayers; + createdata.createflags = SNET_CF_ALLOWPRIVATEGAMES; + + // Hide the chat room so its controls don't get drawn when Create Dlg disappears. + SetActiveWindow(hWndParent); + ShowWindow(ghWndChat, SW_HIDE); + + // CALL THE CREATE GAME CALLBACK + dwReturn = uiparams->interfacedata->createcallback(&createdata, + uiparams->programdata, + uiparams->playerdata, + &interfacedata, + uiparams->versiondata, + uiparams->playeridptr); + + + // If game was not created, restore chatroom. + if (!dwReturn) + ShowWindow(ghWndChat, SW_SHOW); + + return dwReturn; +} + + + +//=========================================================================== +static BOOL DoJoinGame (UIPARAMSPTR uiparams) { + DWORD dwReturn; + HWND hWndParent = uiparams->interfacedata->parentwindow; + + // Hide chat room so it's controls don't get drawn after Join Dialog disappears, unless we want + SetActiveWindow(hWndParent); + ShowWindow(ghWndChat, SW_HIDE); + + // Determine which join game dialog to display + TCHAR *pszTemplate = TEXT("DIALOG_JOIN_GAME"); + if (uiparams->interfacedata->categorylistcallback) + pszTemplate = TEXT("DIALOG_FILTER_JOIN_GAME"); + + dwReturn = SDlgDialogBoxParam( + global_hinstance, + pszTemplate, + hWndParent, + JoinGameDialogProc, + (LPARAM)uiparams); + + // Convert return value to BOOLEAN + dwReturn = (dwReturn == 1); + + // If user didn't join a game, restore chatroom. + if (!dwReturn) + ShowWindow(ghWndChat, SW_SHOW); + + return dwReturn; +} + + +//=========================================================================== +static HFONT SetChatFonts (HWND window) { + HFONT hFont = NULL; + LOGFONT lFont; + + if ((hFont = (HFONT) SendMessage(window, WM_GETFONT, 0, 0L))) { + // Start with dialog font and modify size and weight + if (GetObject(hFont, sizeof(LOGFONT), (LPSTR) &lFont)) { + lFont.lfHeight = -MulDiv(8, 96, 72); // height of 8 pixels + lFont.lfWidth = 0; // let Windows autosize width + lFont.lfWeight = FW_NORMAL; // change to non Bold + strcpy(lFont.lfFaceName, "Arial"); + + + if (hFont = CreateFontIndirect((LPLOGFONT) &lFont)) { + SendDlgItemMessage(window, IDC_USERLIST, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(window, IDC_CHATWINDOW, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(window, IDC_CHATEDIT, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(window, IDC_STATIC_CHANNEL, WM_SETFONT, (WPARAM)hFont, 0); + } + } + } + return hFont; +} + +//=========================================================================== +static void ToggleVerboseMode(void) { + char szText[256]; + char szFmt[128]; + + + sgdwVerboseMode = !sgdwVerboseMode; + LoadString( + global_hinstance, + (sgdwVerboseMode) ? IDS_VERBOSE_FMT : IDS_NONVERBOSE_FMT, + szFmt, + sizeof(szFmt)); + sprintf(szText, szFmt, eCOLOR_NOTIFY, szText); + SendMessage(ghWndChat, WM_CHAT_PROCESS_MSG, eCOLOR_NOTIFY, (LPARAM)szText); + + SRegSaveValue(PREFSKEY,PREFSVALUE_VERBOSE,SREG_FLAG_BATTLENET,sgdwVerboseMode); +} + +//=========================================================================== +static void SendChatMsg(char *szText, BOOL bWhisper) { + if (bWhisper) { + // Fix up text string so that message goes only to the people specified + char szString[MAX_MSG_LEN*2]; + char szUser[128]; + char *pUserName; + int nIdx; + HWND hWndUserList; + + + hWndUserList = GetDlgItem(ghWndChat, IDC_USERLIST); + nIdx = SendMessage(hWndUserList, LB_GETCURSEL, 0, 0); + if (nIdx == LB_ERR) + return; + + // Send a whisper message to selected user + SendMessage(hWndUserList, LB_GETTEXT, nIdx, (LPARAM)(LPCSTR)szUser); + pUserName = strchr(szUser, '\t'); + if (!pUserName) + return; + + // NULL terminate name + *pUserName = 0; + sprintf(szString, "/whisper %s %s", szUser, szText); + SrvSendChatString(szString); + } + else + SrvSendChatString (szText); +} + + + +//**************************************************************************** +// ScrollToBtm(HWND) +// +//**************************************************************************** +static void ScrollToBtm(HWND hWnd) { + SCROLLINFO si; + int nPos = SendMessage(hWnd, LB_GETCOUNT, 0, 0)-1; + SendMessage(hWnd, LB_SETTOPINDEX, nPos, 0); + + // Update scrollbar that belongs to this listbox + HWND hWndScroll = (HWND)GetWindowLong(hWnd, GWL_USERDATA); + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS; + si.nPos = nPos; + SendMessage(hWndScroll, SBM_SETSCROLLINFO, TRUE, (LPARAM)&si); +} + +//**************************************************************************** +// DisplayMsg(szMsg, bTextColor) +// +// bTextColor is the color that additional lines of text should be printed in. +//**************************************************************************** +static void DisplayMsg(LPCSTR szMsg, BYTE bTextColor) { + BYTE charSave; + char *pszText; + HDC hDC; + int nFit; + SIZE size; + RECT windowRect; + HFONT hOldFont; + BOOL bScrollToBtm = TRUE; // Normally, we'll want to always scroll to end of msg list + BOOL bDeletedLines = FALSE; + int nPixHt,nItems, nTopItem; + int nTotalLines; + + // make sure we are still in the chatroom + if (!sghWndMsgList) + return; + + hDC = GetDC(sghWndMsgList); + if (!hDC) + return; + + pszText = (char *)szMsg; + + hOldFont = (HFONT)SelectObject(hDC, sghChatFont); + + GetClientRect(sghWndMsgList, &windowRect); + + + // First set flag to indicate if list box is already scrolled to the end + nPixHt = SendMessage(sghWndMsgList, LB_GETITEMHEIGHT, 0, 0); + nItems = SendMessage(sghWndMsgList, LB_GETCOUNT, 0, 0); + nTopItem = SendMessage(sghWndMsgList, LB_GETTOPINDEX, 0, 0); + + // If user has scrolled up in list, we don't want to mess with the scroll position + if (nPixHt != LB_ERR && nItems != LB_ERR) { + if (nTopItem + windowRect.bottom/nPixHt < nItems) + bScrollToBtm = FALSE; + } + + + // Don't allow redraw until we have finished making changes to the listbox + SendMessage(sghWndMsgList, WM_SETREDRAW, FALSE, 0); + + // add message to list box + while (TRUE) { + int nStrLen; + int nLine; + int nRight; + char *p; + + + // GetTextExtentExPoint() doesn't take tabs into account, so adjust width of line manually. + nRight = windowRect.right; + p = pszText; + if (pszText[0] == '\t') { + nRight -= CHAT_INDENT; + p++; + } + + // If there is a color byte here, don't include it in the extent calculation + if (*p>=FIRST_COLOR_CHAR && *p<=LAST_COLOR_CHAR) + p++; + + nStrLen = strlen((const char *)p); + GetTextExtentExPoint( + hDC, + (const char *)p, + nStrLen, + nRight, + &nFit, + NULL, + &size); + + + // Search for a good place to end the line + if (nFit != nStrLen) { + for (nLine=nFit; nLine>0; nLine--) { + if (p[nLine] == ' ') { + nFit = nLine; + break; + } + } + } + + charSave = p[nFit]; + p[nFit] = 0; // null terminate first part of string + + // add the text line by line to the list box + nTotalLines = SendMessage(sghWndMsgList, LB_ADDSTRING, 0, (LPARAM) ((LPSTR)pszText)); + + + // did we get the whole string that time? + if (nStrLen == nFit) + break; + + // Skip past current line + pszText = p + nFit; + if (charSave == ' ') pszText++; // Don't print a space at the beginning of a line + else pszText[0] = charSave; + + // Indent start of next line + pszText-=2; + pszText[0] = '\t'; + pszText[1] = bTextColor; + } + + // Have we gone past our line limit? + if (nTotalLines >= MAX_CHAT_LINES) { + for ( ; nTotalLines >= MAX_CHAT_LINES; nTotalLines--) + // Remove oldest messages first + SendMessage(sghWndMsgList, LB_DELETESTRING, 0, 0); + bDeletedLines = TRUE; + } + + + // Update position in listbox + if (bScrollToBtm) + ScrollToBtm(sghWndMsgList); + else if (bDeletedLines) { + // restore scroll position after LB_DELETESTRING + SendMessage(sghWndMsgList, LB_SETTOPINDEX, max(0,nTopItem-1), 0); + } + + // Okay, now we're ready to redraw + SendMessage(sghWndMsgList, WM_SETREDRAW, TRUE, 0); + + // Update scrollbar that belongs to this listbox + ListUpdateScrollbar(sghWndMsgList); + + // Cleanup gdi objects + SelectObject(hDC, hOldFont); + ReleaseDC(sghWndMsgList, hDC); +} + + +//**************************************************************************** +#if TEST_USERLIST +void CreateDummyUsers(void) { + SNADDUSERREC AddUserRec; + char szName[128]; + char szDesc[128]; + + + AddUserRec.name = (LPSTR) szName; + AddUserRec.description = (LPSTR) szDesc; + AddUserRec.flags = 0; + + for (int i=0;i<50; i++) { + sprintf(szName, "Mike%d", i); + sprintf(szDesc, "%d %d 0 0 0 0 0", i, i%3); + ChatAddUser(&AddUserRec); + } + +} + +void AddDummyUser(void) { + SNADDUSERREC AddUserRec; + char szName[128]; + char szDesc[128]; + + + AddUserRec.name = (LPSTR) szName; + AddUserRec.description = (LPSTR) szDesc; + AddUserRec.flags = 0; + + static int i=0; + i++; + if (i>99) i=0; + sprintf(szName, "Mike%d", i); + sprintf(szDesc, "%d %d 0 0 0 0 0", i, i%3); + ChatAddUser(&AddUserRec); +} + +void DeleteDummyUser(void) { + SNDELETEUSERREC DeleteUserRec; + char szName[128]; + + DeleteUserRec.name = (LPSTR) szName; + DeleteUserRec.notifyuser = 1; + + static int i = 2; + i++; + if (i>99) i=0; + sprintf(szName, "Mike%d", i); + ChatDeleteUser(&DeleteUserRec); +} +#endif + + +//**************************************************************************** +//**************************************************************************** +int ListFindName(HWND hWndList, LPCSTR szName) { + int nItems; + BOOL bFound; + char *p; + int i; + + nItems = SendMessage(hWndList, LB_GETCOUNT, 0, 0); + if (nItems == LB_ERR) + return LB_ERR; + + bFound = FALSE; + for (i=0; i= sizeof(szText) || nLen == 0) + continue; + + SendMessage(hWndList, LB_GETTEXT, i, (LPARAM)(LPCSTR)szText); + + // A player name entry has a '\t' after the name before battle.net data + p = strchr(szText, '\t'); + if (p == NULL) + continue; + + // NULL terminate player name so we can do string compare. + *p = 0; + + if (!strcmp((char *)szText, szName)) { + bFound = TRUE; + break; + } + } + + if (!bFound) + i = LB_ERR; + + return i; +} + +//**************************************************************************** +//**************************************************************************** +static void BuildMsg(LPSTR pszMsg, LPCSTR pszFromTo, LPCSTR pszSender, LPCSTR pszString, BYTE bColorName, BYTE bColorString) { + sprintf(pszMsg, "%c%c%s%s%c %c%s", + bColorName, + BEGIN_NAME_CHAR, + pszFromTo, + pszSender, + END_NAME_CHAR, + bColorString, + pszString); +} + + + +//**************************************************************************** +//**************************************************************************** +static BOOL CopyNameToEditCtl(HWND hWndList, HWND hWndEdit) { + char szUser[128]; + char *pUserName; + int nIdx; + + + nIdx = SendMessage(hWndList, LB_GETCURSEL, 0, 0); + if (nIdx == LB_ERR) + return 0; + + SendMessage(hWndList, LB_GETTEXT, nIdx, (LPARAM)(LPSTR)szUser); + pUserName = strchr(szUser, '\t'); + if (!pUserName) + return 0; + + // NULL terminate name + *pUserName = 0; + + // Copy text to current cursor position + SendMessage(hWndEdit, EM_REPLACESEL, TRUE, (LPARAM)(LPSTR)szUser); + return 1; +} + +//**************************************************************************** +//**************************************************************************** +static BOOL IsUserSquelched(LPCSTR szName) { + PTSQUELCH_LIST pCurr; + + pCurr = sgpSquelchListHead; + while (pCurr) { + // Search for this name through tht squelch list + if (!strcmp(pCurr->szName, szName)) + return TRUE; + + pCurr = pCurr->next; + } + + // This guy is okay + return FALSE; +} + + +//**************************************************************************** +//**************************************************************************** +void ChannelWindowUpdate(void) { + char szText[256]; + char szFmt[64]; + int nUsers; + + // Update Channel description to include # of people in room + nUsers = SendMessage(GetDlgItem(ghWndChat, IDC_USERLIST), LB_GETCOUNT, 0, 0); + LoadString(global_hinstance, IDS_CHANNEL_FMT, szFmt, sizeof(szFmt)); + sprintf(szText, szFmt, gszCurrentChannel, nUsers); + SetWindowText(GetDlgItem(ghWndChat, IDC_STATIC_CHANNEL), szText); +} + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +UINT ChatGetUserFlags(void) { + return gnUserFlags; +} + + +//=========================================================================== +int NormalizeNetLag(DWORD dwMilliSec) { + // Assume if lag is <10millisecs, that we are dealing with the player himself + if (dwMilliSec < 10) + return 0; + + // divide millisec by 100 + dwMilliSec/=200; + + if (dwMilliSec >= MAX_NET_LAG) + return MAX_NET_LAG; + + // Best non-zero lag is a single green bar! + if (!dwMilliSec) + return 1; + + + return dwMilliSec; +} + + +//=========================================================================== +void DrawBadConnection(LPDRAWITEMSTRUCT lpdis) { + RECT srcRect; + + + // init source rect + SetRect(&srcRect, 0, 0, (LAG_UNIT_WIDTH*MAX_NET_LAG)-1, sizeBadConn.cy-1); + + // use this to center icon vertically + int vertOff = ((lpdis->rcItem.bottom - lpdis->rcItem.top + 1) - sizeBadConn.cy)/2; + + SDlgBltToWindow( + lpdis->hwndItem, + NULL, + lpdis->rcItem.right - (LAG_UNIT_WIDTH*(MAX_NET_LAG+1)), + lpdis->rcItem.top + vertOff, + bmpBadConn, + &srcRect, + &sizeBadConn); +} + + +//=========================================================================== +void DrawNetLag(int nNetLag, LPDRAWITEMSTRUCT lpdis) { + LPBYTE bmp; + SIZE size; + RECT srcRect; + + if (!nNetLag) + return; + + // Get netlag color + if (nNetLag >= RED_THRESHOLD) { + bmp = redlagbitmap; + size = redSize; + } + else if (nNetLag < YELLOW_THRESHOLD) { + bmp = greenlagbitmap; + size = greenSize; + } + else { + bmp = yellowlagbitmap; + size = yellowSize; + } + + // init source rect + srcRect.left = 0; + srcRect.right = LAG_UNIT_WIDTH*nNetLag - 1; + srcRect.top = 0; + srcRect.bottom = size.cy - 1; + + + // We'll use a rating of 1 to MAX_NET_LAG (MAX_NET_LAG being slowest) + int vertOff = ((lpdis->rcItem.bottom - lpdis->rcItem.top + 1) - size.cy)/2; + + + SDlgBltToWindow( + lpdis->hwndItem, + NULL, + lpdis->rcItem.right - (LAG_UNIT_WIDTH*(MAX_NET_LAG+1)), + lpdis->rcItem.top + vertOff, + bmp, + &srcRect, + &size); +} + + + +//**************************************************************************** +void ChatAddUser (SNADDUSERPTR pAddUserRec) { + HWND hWndList; + char szText[MAX_USERLIST_LEN]; + char szFmt[128]; + + if (!ghWndChat) + return; + + + hWndList = GetDlgItem(ghWndChat, IDC_USERLIST); + + // Make sure we haven't already added this person to the listbox + if (LB_ERR != ListFindName(hWndList, (LPCSTR)pAddUserRec->name)) + return; + + // Add squelched flag, if this user is squelched + if (IsUserSquelched(pAddUserRec->name)) + pAddUserRec->flags |= UF_SQUELCHED; + + sprintf(szText, "%s\t%d %d\t%s", + pAddUserRec->name, + pAddUserRec->flags, + 0, // Starting ping time + pAddUserRec->description); + + // Add player name to user list box (official users get added at the top of the list) + SendMessage( + hWndList, + (pAddUserRec->flags & USER_OFFICIAL_MASK) ? LB_INSERTSTRING : LB_ADDSTRING, + 0, + (LPARAM)(LPCSTR)szText); + + if (!sgbModeratedChannel && pAddUserRec->notifyuser && sgdwVerboseMode) { + // display "Johnny has entered" + LoadString(global_hinstance, IDS_CHAT_PLAYER_ENTERED_ROOM, szFmt, sizeof(szFmt)); + sprintf(szText, szFmt, eCOLOR_NOTIFY, pAddUserRec->name); + SendMessage(ghWndChat, WM_CHAT_PROCESS_MSG, eCOLOR_NOTIFY, (LPARAM)szText); + } + + if (!strcmp(pAddUserRec->name, sgszUserName)) { + gnUserFlags = pAddUserRec->flags; + strcpy(sgszUserDesc, pAddUserRec->description); + } + + ChannelWindowUpdate(); + + // Update scrollbar that belongs to this listbox + ListUpdateScrollbar(hWndList); +} + +//**************************************************************************** +void ChatDeleteUser(SNDELETEUSERPTR pDeleteUserRec) { + HWND hWndList; + char szText[MAX_USERLIST_LEN]; + char szFmt[128]; + int nIndex; + int nTopIndex; + + + if (!ghWndChat) + return; + + // Remove player name from user list box + hWndList = GetDlgItem(ghWndChat, IDC_USERLIST); + nIndex = ListFindName(hWndList, (LPCSTR)pDeleteUserRec->name); + if (nIndex == LB_ERR) + return; + + // Delete the user from the list + nTopIndex = SendMessage(hWndList, LB_GETTOPINDEX, 0, 0); + SendMessage(hWndList, WM_SETREDRAW, FALSE, 0); + SendMessage(hWndList, LB_DELETESTRING, nIndex, 0); + SendMessage(hWndList, LB_SETTOPINDEX, nTopIndex, 0); // restore scroll position after LB_DELETESTRING + + SendMessage(hWndList, WM_SETREDRAW, TRUE, 0); + + if (!sgbModeratedChannel && pDeleteUserRec->notifyuser && sgdwVerboseMode) { + // display "Johnny has left" + LoadString(global_hinstance, IDS_CHAT_PLAYER_LEFT_ROOM, szFmt, sizeof(szFmt)); + sprintf(szText, szFmt, eCOLOR_NOTIFY, pDeleteUserRec->name); + SendMessage(ghWndChat, WM_CHAT_PROCESS_MSG, eCOLOR_NOTIFY, (LPARAM)szText); + } + + // Update users in channel + ChannelWindowUpdate(); + + // Update scrollbar that belongs to this listbox + ListUpdateScrollbar(hWndList); +} + + +//**************************************************************************** +void ChatUpdatePingTime(SNUPDATEPINGTIMEPTR pUpdatePingTimeRec) { + HWND hWndList; + int nIndex, nCurSel, nTopIndex; + DWORD dwFlags, dwNewPingTime, dwOldPingTime; + + char szNewUserText[MAX_USERLIST_LEN]; + char szOldUserText[MAX_USERLIST_LEN]; + char *pszName; + char *pszInfo; + char *pszDesc; + + + if (!ghWndChat) + return; + + hWndList = GetDlgItem(ghWndChat, IDC_USERLIST); + nIndex = ListFindName(hWndList, (LPCSTR)pUpdatePingTimeRec->name); + if (nIndex == LB_ERR) + return; + + // Get current entry for this user + SendMessage(hWndList, LB_GETTEXT, nIndex, (LPARAM)(LPCSTR)szOldUserText); + + // Get pointer to user name + pszName = &szOldUserText[0]; + + // Get pointer to user info + pszInfo = strchr(szOldUserText, '\t'); + if (!pszInfo) + return; + *pszInfo++ = 0; // Null terminate name, and pointer to user info + + + // Get pointer to user description + pszDesc = strchr(pszInfo, '\t'); + if (!pszDesc) + return; + *pszDesc++ = 0; // Null terminate info and point to user description + + // Get old information about the player + if (2 != sscanf(pszInfo, "%d %d", &dwFlags, &dwOldPingTime)) + return; + + // Update new ping time + dwNewPingTime = NormalizeNetLag(pUpdatePingTimeRec->pingtime); + + // Check if ping time has changed + if (dwNewPingTime == dwOldPingTime) + return; + + // Now rebuild text string + sprintf(szNewUserText, "%s\t%d %d\t%s", + pszName, + dwFlags, + dwNewPingTime, + pszDesc); + + + // Save a couple of things for later + nTopIndex = SendMessage(hWndList, LB_GETTOPINDEX, 0, 0); + nCurSel = SendMessage(hWndList, LB_GETCURSEL, 0, 0); + + // Actually set the new user entry + SendMessage(hWndList, WM_SETREDRAW, FALSE, 0); + SendMessage(hWndList, LB_DELETESTRING, nIndex, 0); + SendMessage(hWndList, LB_INSERTSTRING, nIndex, (LPARAM)(LPCSTR)szNewUserText); + if (nCurSel == nIndex) + SendMessage(hWndList, LB_SETCURSEL, nCurSel, 0); + + // We need to restore the scrollbox position, since LB_DELETESTRING seems to scroll to the top. + SendMessage(hWndList, LB_SETTOPINDEX, nTopIndex, 0); + + SendMessage(hWndList, WM_SETREDRAW, TRUE, 0); + + // Update scrollbar that belongs to this listbox + ListUpdateScrollbar(hWndList); +} + + +//**************************************************************************** +void ChatSetUserName(LPCSTR szUserName) { + SrvGetLocalPlayerName(sgszUserName,MAX_NAME_LEN); +#if 0 + if (strlen(szUserName) >= sizeof(sgszUserName)) { + memcpy(sgszUserName, szUserName, sizeof(sgszUserName)); + sgszUserName[sizeof(sgszUserName)-1] = 0; + } + else + strcpy(sgszUserName, szUserName); +#endif +} + +//**************************************************************************** +void ChatChangeUserFlags(SNCHANGEUSERFLAGSPTR pChangeUserFlagsRec) { + HWND hWndList; + int nOldIndex, nNewIndex; + DWORD dwOldFlags, dwNewFlags, dwPingTime; + char szNewUserText[MAX_USERLIST_LEN]; + char szOldUserText[MAX_USERLIST_LEN]; + char *pszName; + char *pszInfo; + char *pszDesc; + BOOL bWasOfficial, bIsOfficial; + + + if (!ghWndChat) + return; + + hWndList = GetDlgItem(ghWndChat, IDC_USERLIST); + nOldIndex = ListFindName(hWndList, (LPCSTR)pChangeUserFlagsRec->name); + if (nOldIndex == LB_ERR) + return; + + // Get current entry for this user + SendMessage(hWndList, LB_GETTEXT, nOldIndex, (LPARAM)(LPCSTR)szOldUserText); + + // Get pointer to user name + pszName = &szOldUserText[0]; + + // Get pointer to user info + pszInfo = strchr(szOldUserText, '\t'); + if (!pszInfo) + return; + *pszInfo++ = 0; // Null terminate name, and pointer to user info + + + // Get pointer to user description + pszDesc = strchr(pszInfo, '\t'); + if (!pszDesc) + return; + *pszDesc++ = 0; // Null terminate info and point to user description + + // Get old information about the player + if (2 != sscanf(pszInfo, "%d %d", &dwOldFlags, &dwPingTime)) + return; + + // Check if flags have really changed + dwNewFlags = pChangeUserFlagsRec->flags; + if (IsUserSquelched(pChangeUserFlagsRec->name)) + dwNewFlags |= UF_SQUELCHED; + + if (dwNewFlags == dwOldFlags) + return; + + // Now rebuild text string + sprintf(szNewUserText, "%s\t%d %d\t%s", + pszName, + dwNewFlags, + dwPingTime, + pszDesc); + + // Save new user flags + if (!strcmp(pChangeUserFlagsRec->name, sgszUserName)) + gnUserFlags = dwNewFlags; + + bWasOfficial = (0 != (dwOldFlags & USER_OFFICIAL_MASK)); + bIsOfficial = (0 != (dwNewFlags & USER_OFFICIAL_MASK)); + + + // Actually set the new user entry + int nTopIndex = SendMessage(hWndList, LB_GETTOPINDEX, 0, 0); + int nCurSel = SendMessage(hWndList, LB_GETCURSEL, 0, 0); + SendMessage(hWndList, WM_SETREDRAW, FALSE, 0); + SendMessage(hWndList, LB_DELETESTRING, nOldIndex, 0); + + if (bWasOfficial == bIsOfficial) { + nNewIndex = SendMessage(hWndList, LB_INSERTSTRING, nOldIndex, (LPARAM)(LPCSTR)szNewUserText); + } + else { + // Move user to new position in list based on new flags + // (Special users get moved to the top, non-specials get moved to the bottom) + nNewIndex = SendMessage( + hWndList, + (bIsOfficial) ? LB_INSERTSTRING : LB_ADDSTRING, + 0, + (LPARAM)(LPCSTR)szNewUserText); + } + + + // LB_DELETESTRING moves the scroll position, so reset it to where it was + SendMessage(hWndList, LB_SETTOPINDEX, nTopIndex, 0); + if (nCurSel == nOldIndex) + SendMessage(hWndList, LB_SETCURSEL, nNewIndex, 0); + + SendMessage(hWndList, WM_SETREDRAW, TRUE, 0); + + // Update scrollbar that belongs to this listbox + ListUpdateScrollbar(hWndList); +} + +//**************************************************************************** +// NOTE: pJoinChannelRec will only be valid as long as we don't go into a peekmessage loop. +//**************************************************************************** +void ChatJoinChannel(SNJOINCHANNELPTR pJoinChannelRec) { + HWND hWndList; + char szText[MAX_CHAT_LEN]; + char szFmt[128]; + + // if this is the first channel we are entering, add this channel to our list of known channels + if (sgbFirstChannel) { + ChatAddChannel(pJoinChannelRec->name); + sgbFirstChannel = FALSE; + } + + // Save channel name + strcpy(gszCurrentChannel,pJoinChannelRec->name); + sgbModeratedChannel = pJoinChannelRec->flags & CF_MODERATED; + + if (ghWndChat) { + // Let select channel window know, in case user is waiting for confirmation + ChatChannelJoined(pJoinChannelRec->name); + + hWndList = GetDlgItem(ghWndChat, IDC_USERLIST); + + // Dump all users from list and prepare to add the new ones. + SendMessage(hWndList, LB_RESETCONTENT, 0, 0); + + // Display a message that we are in a new room now + LoadString(global_hinstance, IDS_CHAT_JOIN_ROOM, szFmt, sizeof(szFmt)); + sprintf(szText, szFmt, eCOLOR_NOTIFY, pJoinChannelRec->name); + SendMessage(ghWndChat, WM_CHAT_PROCESS_MSG, eCOLOR_NOTIFY, (LPARAM)szText); + + // Update scrollbar that belongs to this listbox + ListUpdateScrollbar(hWndList); + + // Set button text to display new channel name + ChannelWindowUpdate(); + } + +} + + +//**************************************************************************** +void ChatAddChannel(LPCSTR szChannel) { + TCHANNEL_LIST ChannelList; + TCHANNEL_LIST *pCurr; + + strcpy(ChannelList.szChannel, szChannel); + + pCurr = sgpChannelListHead; + while (pCurr) { + // If this string already exists in our list, don't bother adding it again + if (!strcmp(pCurr->szChannel, szChannel)) + return; + + pCurr = pCurr->next; + } + + LISTADDEND(&sgpChannelListHead, &ChannelList); + return; +} + +//**************************************************************************** +void ChatDeleteChannel(LPCSTR szChannel) { + TCHANNEL_LIST *pCurr; + + pCurr = sgpChannelListHead; + while (pCurr) { + // If this string already exists in our list, don't bother adding it again + if (!strcmp(pCurr->szChannel, szChannel)) { + LISTFREE(&sgpChannelListHead, pCurr); + return; + } + + pCurr = pCurr->next; + } + + return; +} + + +//**************************************************************************** +void ChatSquelchUser(SNSQUELCHUSERPTR pSquelchUserRec) { + TSQUELCH_LIST SquelchList; + TSQUELCH_LIST *pCurr; + SNCHANGEUSERFLAGSREC ChangeUserFlagsRec; + char szText[256]; + char szFmt[128]; + + strcpy(SquelchList.szName, pSquelchUserRec->name); + + pCurr = sgpSquelchListHead; + while (pCurr) { + // If this string already exists in our list, don't bother adding it again + if (!strcmp(pCurr->szName, pSquelchUserRec->name)) + return; + + pCurr = pCurr->next; + } + + LISTADDEND(&sgpSquelchListHead, &SquelchList); + + ChangeUserFlagsRec.name = pSquelchUserRec->name; + ChangeUserFlagsRec.flags = pSquelchUserRec->flags | UF_SQUELCHED; + ChatChangeUserFlags(&ChangeUserFlagsRec); + + // Display a message that user is being squelched + LoadString(global_hinstance, IDS_USERSQUELCHED_FMT, szFmt, sizeof(szFmt)); + sprintf(szText, szFmt, eCOLOR_NOTIFY, pSquelchUserRec->name); + SendMessage(ghWndChat, WM_CHAT_PROCESS_MSG, eCOLOR_NOTIFY, (LPARAM)szText); + + return; +} + +//**************************************************************************** +void ChatUnsquelchUser(SNSQUELCHUSERPTR pSquelchUserRec) { + SNCHANGEUSERFLAGSREC ChangeUserFlagsRec; + TSQUELCH_LIST *pCurr; + char szText[256]; + char szFmt[128]; + + pCurr = sgpSquelchListHead; + while (pCurr) { + // If this user is currently squelched, remove him from squelch list + if (!strcmp(pCurr->szName, pSquelchUserRec->name)) { + LISTFREE(&sgpSquelchListHead, pCurr); + break; + } + + pCurr = pCurr->next; + } + + ChangeUserFlagsRec.name = pSquelchUserRec->name; + ChangeUserFlagsRec.flags = pSquelchUserRec->flags; + ChatChangeUserFlags(&ChangeUserFlagsRec); + + // Display a message that user is no longer being squelched + LoadString(global_hinstance, IDS_USERUNSQUELCHED_FMT, szFmt, sizeof(szFmt)); + sprintf(szText, szFmt, eCOLOR_NOTIFY, pSquelchUserRec->name); + SendMessage(ghWndChat, WM_CHAT_PROCESS_MSG, eCOLOR_NOTIFY, (LPARAM)szText); + return; +} + + +//**************************************************************************** +void ChatReceiveMsg(SNDISPLAYSTRINGPTR pDispStringRec) { + BYTE szFromTo[16]; + BYTE szMsg[MAX_CHAT_LEN+3+sizeof(szFromTo)]; + BYTE bColorName, bColorString; + BYTE bShowName = TRUE; + + + // Init this to null string, its only used when whispering is occuring + szFromTo[0] = 0; + + // Set colors + switch (pDispStringRec->stringtype) { + case SN_STRING_WHISPER: + // Ignore squelched people + if (IsUserSquelched(pDispStringRec->sender)) + return; + + bColorName = eCOLOR_USERNAME; + bColorString = eCOLOR_WHISPER; + LoadString(global_hinstance, IDS_WHISPER_FROM, (char *)szFromTo, sizeof(szFromTo)); + break; + + case SN_STRING_WHISPERSENT: + bColorName = eCOLOR_MYNAME; + bColorString = eCOLOR_WHISPER; + LoadString(global_hinstance, IDS_WHISPER_TO, (char *)szFromTo, sizeof(szFromTo)); + break; + + + case SN_STRING_BROADCAST: + bColorString = eCOLOR_BROADCAST; + bShowName = FALSE; + break; + + case SN_STRING_INFORMATION: + bColorString = eCOLOR_INFORMATION; + bShowName = FALSE; + break; + + case SN_STRING_ERROR: + bColorString = eCOLOR_ERROR; + bShowName = FALSE; + break; + + case SN_STRING_TALK: + // Ignore squelched people + if (IsUserSquelched(pDispStringRec->sender)) + return; + + if (pDispStringRec->senderflags & UF_BLIZZARD) { + bColorName = eCOLOR_BLIZZARD; + bColorString = eCOLOR_BLIZZARD; + break; + } + else if (pDispStringRec->senderflags & UF_SYSOP) { + bColorName = eCOLOR_SYSOP; + bColorString = eCOLOR_SYSOP; + break; + } + else if (pDispStringRec->senderflags & UF_SPEAKER) { + bColorName = eCOLOR_SPEAKER; + bColorString = eCOLOR_SPEAKER; + break; + } + else if (pDispStringRec->senderflags & UF_MODERATOR) { + bColorName = eCOLOR_MODERATOR; + bColorString = eCOLOR_MODERATOR; + break; + } + // fall through + default: + bColorName = eCOLOR_USERNAME; + bColorString = eCOLOR_NORMAL; + break; + } + + + + // Format string with sender's name in front + if (bShowName && pDispStringRec->sender[0]) + BuildMsg((LPSTR)szMsg, + (LPCSTR) szFromTo, + pDispStringRec->sender, + pDispStringRec->string, + bColorName, bColorString); + else + sprintf((char *)szMsg, "%c%s", + bColorString, + pDispStringRec->string); + + SendMessage(ghWndChat, WM_CHAT_PROCESS_MSG, bColorString, (LPARAM)szMsg); +} + + + +//=========================================================================== +BOOL CALLBACK ChatRoomDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + static UIPARAMSPTR uiparams = NULL; + static HWND hWndEdit; + + + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case ID_WHISPER: { + char szTitle[32]; + char szText[256]; + + // make sure we have selected a user to whisper to + if (LB_ERR == SendDlgItemMessage(window, IDC_USERLIST, LB_GETCURSEL, 0, 0)) { + + LoadString(global_hinstance, IDS_BATTLENET, szTitle, sizeof(szTitle)); + LoadString(global_hinstance, IDS_ERR_CANTWHISPER, szText, sizeof(szText)); + + // Don't let user press whisper while error message is up + EnableWindow((HWND)lparam, FALSE); + uiparams->interfacedata->messageboxcallback( + window, + szText, + szTitle, + MB_OK | MB_ICONERROR); + EnableWindow((HWND)lparam, TRUE); + + return 1; + } + } + // Fall through to IDOK + // + // + case IDOK: { + char szText[MAX_CHAT_LEN]; + + // Get message from edit control. Only send the chat message, if the edit control contained text. + if (SendMessage(hWndEdit, WM_GETTEXT, MAX_MSG_LEN, (LPARAM)(LPSTR)szText) ) { + SendChatMsg((char *)szText, (LOWORD(wparam) == ID_WHISPER)); + + // Clear edit text + SendMessage(hWndEdit, WM_SETTEXT, 0, (LPARAM) ((LPSTR)"")); + + // Local echo, unless we are whispering or user typed a command string + if (LOWORD(wparam) == IDOK && szText[0] != '/') { + char szMsg[MAX_CHAT_LEN+3]; // include space for "< >" around name + char szPlayerName[MAX_NAME_LEN]; + int nTextColor; + + SrvGetLocalPlayerName(szPlayerName,MAX_NAME_LEN); + nTextColor = (sgbModeratedChannel && !IsUserOfficial()) ? + eCOLOR_WHISPER : eCOLOR_NORMAL; + BuildMsg((char *)szMsg, + "", + szPlayerName, + (LPCSTR)szText, + eCOLOR_MYNAME, + nTextColor); + + SendMessage(ghWndChat, WM_CHAT_PROCESS_MSG, nTextColor, (LPARAM)szMsg); + } + + ScrollToBtm(sghWndMsgList); + } + + // Give focus back to edit control + SetFocus(hWndEdit); + return 1; + + } + + case ID_VERBOSE: + ToggleVerboseMode(); + return 1; + + + case ID_CHATCHANNEL: { + if (uiparams->interfacedata->soundcallback) + uiparams->interfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + DoChatSelectChannel(uiparams->interfacedata, gszCurrentChannel, sgpChannelListHead); + SetFocus(hWndEdit); + return 1; + } + + case IDC_USERLIST: { + if (HIWORD(wparam) == LBN_SELCHANGE) { + // Give the focus back to the edit control + SetFocus(hWndEdit); + + ListUpdateScrollbar((HWND) lparam); + } + else if (HIWORD(wparam) == LBN_DBLCLK) { + CopyNameToEditCtl((HWND)lparam, hWndEdit); + SetFocus(hWndEdit); + } + break; + } + + + case IDC_CHATWINDOW: + SetFocus(hWndEdit); + return 0; + + case ID_CHATCREATE: { + if (uiparams->interfacedata->soundcallback) + uiparams->interfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + if (DoCreateGame(uiparams)) + SDlgEndDialog(window,1); + else + SetFocus(hWndEdit); + return 1; + } + + case ID_CHATJOIN: + if (uiparams->interfacedata->soundcallback) + uiparams->interfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + if (DoJoinGame(uiparams)) + SDlgEndDialog(window, 1); + else + SetFocus(hWndEdit); + return 1; + + case IDQUIT: + if (uiparams->interfacedata->soundcallback) + uiparams->interfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + SDlgEndDialog(window, 0); + return 1; + + } + break; + + case WM_CLOSE: + // Simulate a Quit button click so that we exit + SendDlgItemMessage(window, IDQUIT, BM_CLICK, 0, 0); + return 1; + + case WM_HELP: +#if TEST_USERLIST + { + // Get Users coming and going constantly (whenever a key is pressed) + for (int i=0; i<5000; i++) { + static BOOL sbAdd=FALSE; + if (sbAdd) + AddDummyUser(); + else + DeleteDummyUser(); + sbAdd = !sbAdd; + } + return 1; + } +#endif + + + if (uiparams->interfacedata->soundcallback) + uiparams->interfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + SDlgDialogBoxParam( global_hinstance, + TEXT("DIALOG_CHAT_HELP"), + window, + ChatHelpDialogProc, + (LPARAM) uiparams); + SetFocus(hWndEdit); + return 1; + + + case WM_DRAWITEM: { + UINT idCtl = (UINT) wparam; // control identifier + LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) lparam; // item-drawing information + char szString[256]; + BOOL bFirstLine = TRUE; + int nNetLag = 0; + DWORD dwItemFlags = 0; + + if (idCtl == IDC_CHATWINDOW) { + COLORREF oldTextColor, oldBkColor; + LPSTR pText = szString; + UINT nAlignMode; + POINT pt; + int nStartX; + + + // Get line of text + if (LB_ERR == SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM)(LPCSTR)szString)) + return 0; + + // make sure we have something to draw + if (!szString[0] || !lpdis->hDC) + return 0; + + + oldTextColor = SetTextColor(lpdis->hDC, RGB(0xff, 0xff, 0xff)); + oldBkColor = SetBkColor(lpdis->hDC, RGB(0,0,0)); + + // manually indent string, if necessary + nStartX = lpdis->rcItem.left + 1; // +1 is so letters like W will not get clipped on the left + if (pText[0] == '\t') { + nStartX += CHAT_INDENT; + pText++; + bFirstLine = FALSE; + } + MoveToEx( + lpdis->hDC, + nStartX, + lpdis->rcItem.top, + &pt); + + nAlignMode = SetTextAlign(lpdis->hDC, TA_UPDATECP); + + // Print Text + while (*pText) { + int nCount; + + // Check for color control character + if (*pText >= FIRST_COLOR_CHAR && *pText <= LAST_COLOR_CHAR) { + SetTextColor(lpdis->hDC, sgHiliteColors[*pText - FIRST_COLOR_CHAR]); + pText++; + } + + // Count characters that are in this color + char *p = pText; + for (nCount = 0; *p != 0; nCount++, *p++) { + if (*p >= FIRST_COLOR_CHAR && *p <= LAST_COLOR_CHAR) + break; + } + + // Draw characters + TextOut(lpdis->hDC,0,0,pText,nCount); + + // Skip characters that we've drawn + pText+=nCount; + } + + + // Restore colors to hdc + SetTextColor(lpdis->hDC, oldTextColor); + SetBkColor(lpdis->hDC, oldBkColor); + + // Restore align mode + SetTextAlign(lpdis->hDC, nAlignMode); + + // restore position also + MoveToEx(lpdis->hDC, pt.x, pt.y, NULL); + return 1; + } + else if (idCtl == IDC_USERLIST) { + char *szDesc = ""; + char *szPlayerData = ""; + char *p; + + // Get user name/description + if (LB_ERR == SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM)(LPCSTR)szString)) + return 0; + + // Get player data + p = strchr(szString,'\t'); + if (p) { + *p++ = 0; + szPlayerData = p; + + // Get player description + p = strchr(szPlayerData,'\t'); + if (p) { + *p++ = 0; + szDesc = p; + } + } + + // make sure we have something to draw + if (!szString[0] || !lpdis->hDC) + return 0; + + // If item count changes, change if constant + if (2 != sscanf(szPlayerData, "%d %d", &dwItemFlags, &nNetLag)) { +// #ifndef NDEBUG +// char txt[256]; +// sprintf(txt, "Info: %s", szPlayerData); +// MessageBox(SDrawGetFrameWindow(), txt, "", MB_OK); +// return 0; +// #endif + } + + // IF THE APPLICATION HAS REGISTERED A DRAW DESCRIPTION CALLBACK, + // LET IT DRAW THE DESCRIPTION + if (uiparams->interfacedata && uiparams->interfacedata->drawdesccallback) { + DWORD dwDrawFlags; + + dwDrawFlags = SNET_DDF_INCLUDENAME; + uiparams->interfacedata->drawdesccallback( + PROVIDERID, + SNET_DRAWTYPE_PLAYER, + szString, + szDesc, + dwItemFlags, + dwDrawFlags, + 0, + lpdis); + } + else { + // OTHERWISE, DRAW THE USER'S NAME OURSELF + COLORREF oldTextColor, oldBkColor; + BOOL bSelected = lpdis->itemState & ODS_SELECTED; + + // Draw username and net lag into list box + // Don't worry about text highlighting + oldTextColor = SetTextColor(lpdis->hDC, RGB(0xff, 0xff, 0xff)); + oldBkColor = SetBkColor(lpdis->hDC, (bSelected) ? GetSysColor(COLOR_HIGHLIGHT) : RGB(0, 0, 0)); + ExtTextOut( + lpdis->hDC, + lpdis->rcItem.left, + lpdis->rcItem.top, + ETO_CLIPPED | ETO_OPAQUE, + &lpdis->rcItem, + szString, + strlen(szString), + NULL); + + // Restore colors to hdc + SetTextColor(lpdis->hDC, oldTextColor); + SetBkColor(lpdis->hDC, oldBkColor); + } + + // Draw net lag + if (!(dwItemFlags & UF_BADCONNECTION)) + DrawNetLag(nNetLag, lpdis); + else + DrawBadConnection(lpdis); + + return 1; + } + + break; + } + + case WM_CHAT_PROCESS_MSG: + DisplayMsg((LPCSTR)lparam, wparam); + return 1; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + + case WM_DESTROY: + SrvEndChat(); + DestroyArtwork(window); + if (sghChatFont) + DeleteObject(sghChatFont); + + ghWndChat = sghWndMsgList = NULL; + hWndEdit = NULL; + LISTCLEAR(&sgpChannelListHead); + LISTCLEAR(&sgpSquelchListHead); + break; + + + case WM_INITDIALOG: + + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + uiparams = (UIPARAMSPTR)lparam; + + sgbLadderEnabled = uiparams->interfacedata->uiflags & + SNET_UIFLAG_SUPPORTS_LADDER ? TRUE : FALSE; + LoadArtwork(window, uiparams->interfacedata->artcallback); + + sghChatFont = SetChatFonts(window); + + // save some window handles for later + ghWndChat = window; + sghWndMsgList = GetDlgItem(window, IDC_CHATWINDOW); + hWndEdit = GetDlgItem(window, IDC_CHATEDIT); + + // Link Userlist scrollbar to UserList Listbox + ScrollbarLink(GetDlgItem(window, IDC_USERLIST), GetDlgItem(window, IDC_USERLIST_SCROLLBAR)); + + // Link Messagelist scrollbar to msglist listbox + ScrollbarLink(sghWndMsgList, GetDlgItem(window, IDC_MSGLIST_SCROLLBAR)); + + + SendMessage(hWndEdit, EM_LIMITTEXT, MAX_MSG_LEN-1, 0L); + SendMessage(sghWndMsgList, LB_SETTABSTOPS, 1, (LPARAM) (int *) &sgnTab); + + // Set the height of the chat text list box items (so we can fit more lines in it) + SendMessage(sghWndMsgList, LB_SETITEMHEIGHT, 0, 14); + + // Set hight of userlist box items (some systems get strange heights) + SendDlgItemMessage(window, IDC_USERLIST, LB_SETITEMHEIGHT, 0, 16); + + // Set flag for first time + sgbFirstChannel = TRUE; + + // Get the local user's name + SrvGetLocalPlayerName(sgszUserName,MAX_NAME_LEN); + + if (!SrvBeginChat(uiparams->programdata, uiparams->playerdata, gszCurrentChannel)) { + // Have parent window display error message. + PostMessage(GetParent(sghWndMsgList), WM_ERR_NOTRESPONDING, 0, 0); + SDlgEndDialog(window, 0); + } + + + // Don't let player with bad connection do anything (encourage them to + // change their ISP). + if (gbConnectionSucks) { + EnableWindow(GetDlgItem(window, ID_CHATCREATE), FALSE); + EnableWindow(GetDlgItem(window, ID_CHATJOIN), FALSE); + } + + // Hide 'verbose' button. It will still generate a WM_COMMAND + // if user hits Alt-V hotkey. + ShowWindow(GetDlgItem(window, ID_VERBOSE), SW_HIDE); + + // Set Verbose preference + SRegLoadValue(PREFSKEY,PREFSVALUE_VERBOSE,SREG_FLAG_BATTLENET,&sgdwVerboseMode); + + UiLoadCursors(window, uiparams->interfacedata); + +#if TEST_USERLIST + CreateDummyUsers(); +#endif + return 1; + } + + return SDlgDefDialogProc(window,message,wparam,lparam); + +} diff --git a/src/Storm/SOURCE/BATTLE/CLRPREF.CPP b/src/Storm/SOURCE/BATTLE/CLRPREF.CPP new file mode 100644 index 0000000..f672517 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/CLRPREF.CPP @@ -0,0 +1,115 @@ +/**************************************************************************** +* +* CLRPREF.CPP +* +* Handle app specific system color preferences. +* By Michael Morhaime +* +***/ + +#include "pch.h" + + +typedef struct _prefcolors { + int nElements; + INT *pElements; + COLORREF *pAppValues; + COLORREF *pWindowsValues; +} TPREFCOLORS; +static TPREFCOLORS sgPrefColors = { 0, NULL, NULL, NULL }; + + + +//=========================================================================== +//=========================================================================== +static void ColorPrefRestoreWindowsColors(void) { + if (!sgPrefColors.nElements) + return; + + SetSysColors(sgPrefColors.nElements, sgPrefColors.pElements, sgPrefColors.pWindowsValues); +} + +//=========================================================================== +static void ColorPrefSetAppColors(void) { + if (!sgPrefColors.nElements) + return; + + SetSysColors(sgPrefColors.nElements, sgPrefColors.pElements, sgPrefColors.pAppValues); +} + + +//=========================================================================== +//=========================================================================== +//=========================================================================== +void ColorPrefDestroy(void) { + // Restore Windows system colors + ColorPrefRestoreWindowsColors(); + + // Free PrefColors table + if (sgPrefColors.pElements) { + FREE(sgPrefColors.pElements); + sgPrefColors.pElements = NULL; + } + + if (sgPrefColors.pAppValues) { + FREE(sgPrefColors.pAppValues); + sgPrefColors.pAppValues = NULL; + } + + if (sgPrefColors.pWindowsValues) { + FREE(sgPrefColors.pWindowsValues); + sgPrefColors.pWindowsValues = NULL; + } + + sgPrefColors.nElements = 0; +} + + +//=========================================================================== +BOOL ColorPrefInit(SNETGETDATAPROC getdatacallback) { + SNET_DATA_SYSCOLORTABLE *pSysColorTbl; + DWORD dwBytes; + int nEntries; + + if (!UiGetData(getdatacallback, SNET_DATA_SYSCOLORS, (LPBYTE *)&pSysColorTbl, &dwBytes)) + return 0; + + nEntries = dwBytes/sizeof(SNET_DATA_SYSCOLORTABLE); + if (!nEntries) + return 0; + + sgPrefColors.pElements = (INT *)ALLOC(nEntries*sizeof(int)); + sgPrefColors.pAppValues = (COLORREF *)ALLOC(nEntries*sizeof(COLORREF)); + sgPrefColors.pWindowsValues = (COLORREF *)ALLOC(nEntries*sizeof(COLORREF)); + + if ( sgPrefColors.pElements == NULL || + sgPrefColors.pAppValues == NULL || + sgPrefColors.pWindowsValues == NULL ) { + ColorPrefDestroy(); + FREE(pSysColorTbl); + return 0; + } + + // Fill in structure with actual values. + sgPrefColors.nElements = nEntries; + for (int i=0; i + +// these values depend on the artwork +#define BEVEL_THICKNESS 3 + +#define PROP_COMBOLBOX "ComboLbox" +#define PROP_COMBOEDIT "ComboEdit" +#define PROP_COMBOEDITBKG "ComboEditBkg" +#define PROP_COMBOARROWRCT "ComboArrowRct" +#define PROP_LBOXSCROLL "LboxScroll" +#define PROP_OLDPROC "OldProc" + +#define CUSTOM_EN_SCROLLDOWN (WM_USER+2032) +#define CUSTOM_EN_SCROLLUP (WM_USER+2033) + +#define EDIT_ID 7173 +#define LBOX_ID 7174 +#define SCROLL_ID 7175 + +//---------------------------------------------------------------------------// +// PRIVATE +//---------------------------------------------------------------------------// + +enum { + LEFT = 0, + MIDDLE, + RIGHT, + NUM_TILES +}; + +typedef struct _COMBOBMP { + LPBYTE bitmap; + SIZE size; +} COMBOBMP, *COMBOBMPPTR; + +// Allow more than one combobox to share artwork +static int sgnComboCnt = 0; +static LPBYTE sgComboBmp[3]; +static SIZE sgComboSize[3]; +static LPBYTE sgSComboBmp[3]; +static SIZE sgSComboSize[3]; +static BOOL sgbPopup = FALSE; + +//---------------------------------------------------------------------------// +static BOOL ClosePopup(HWND window) { + if (!sgbPopup) return FALSE; + sgbPopup = FALSE; + + HWND hLbox = (HWND)GetProp(window,PROP_COMBOLBOX); + RECT comboRect,lboxRect; + GetWindowRect(window,&comboRect); + GetWindowRect(hLbox,&lboxRect); + + ShowWindow(hLbox,SW_HIDE); + ShowWindow((HWND)GetProp(window,PROP_LBOXSCROLL),SW_HIDE); + + SetWindowPos(window, + 0, + 0, + 0, + comboRect.right - comboRect.left, + comboRect.bottom - comboRect.top - + (lboxRect.bottom - lboxRect.top + BEVEL_THICKNESS*2), + SWP_NOZORDER|SWP_NOMOVE); + + SendMessage(GetParent(window), + WM_COMMAND, + MAKEWPARAM(GetWindowLong(window,GWL_ID), + CBN_SELCHANGE), + (LPARAM)window); + return TRUE; +} + +//---------------------------------------------------------------------------// +static BOOL OpenPopup(HWND window) { + if (sgbPopup) return FALSE; + sgbPopup = TRUE; + + HWND hLbox = (HWND)GetProp(window,PROP_COMBOLBOX); + RECT comboRect,lboxRect; + GetWindowRect(window,&comboRect); + GetWindowRect(hLbox,&lboxRect); + + SetWindowPos(window, + HWND_TOP, + 0, + 0, + comboRect.right - comboRect.left, + comboRect.bottom - comboRect.top + + (lboxRect.bottom - lboxRect.top + BEVEL_THICKNESS*2), + SWP_NOMOVE); + + ShowWindow(hLbox,SW_SHOWNORMAL); + ShowWindow((HWND)GetProp(window,PROP_LBOXSCROLL),SW_SHOWNORMAL); + + SetFocus(hLbox); + SetCapture(hLbox); + return TRUE; +} + +//---------------------------------------------------------------------------// +static LRESULT CALLBACK ComboEditWndProc(HWND hEdit, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + WNDPROC oldProc = (WNDPROC)GetProp(hEdit,PROP_OLDPROC); + if (message == WM_KEYDOWN) { + HWND hCombo = GetParent(hEdit); + if (wparam == VK_UP) { + SendMessage(hCombo, + WM_COMMAND, + MAKEWPARAM(EDIT_ID,CUSTOM_EN_SCROLLUP), + (LPARAM)hEdit); + return 0; + } + else if (wparam == VK_DOWN) { + SendMessage(hCombo, + WM_COMMAND, + MAKEWPARAM(EDIT_ID,CUSTOM_EN_SCROLLDOWN), + (LPARAM)hEdit); + return 0; + } + } + return CallWindowProc(oldProc,hEdit,message,wparam,lparam); +} + +//---------------------------------------------------------------------------// +static LRESULT CALLBACK ComboLboxWndProc(HWND hLbox, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + static bInScroll = FALSE; + WNDPROC oldProc = (WNDPROC)GetProp(hLbox,PROP_OLDPROC); + switch (message) { + case WM_SHOWWINDOW: + bInScroll = FALSE; + break; + + case WM_LBUTTONDOWN: { + RECT lboxRect,scrollRect; + HWND hScroll = (HWND)GetProp(GetParent(hLbox),PROP_LBOXSCROLL); + + GetClientRect(hLbox,&lboxRect); + GetClientRect(hScroll,&scrollRect); + scrollRect.left += lboxRect.right; + scrollRect.right += lboxRect.right; + + POINT pt = { (short)LOWORD(lparam), (short)HIWORD(lparam) }; + if (PtInRect(&scrollRect,pt)) { + LPARAM newlparam = MAKELPARAM(pt.x - lboxRect.right, + pt.y - lboxRect.top); + return SendMessage(hScroll,message,wparam,newlparam); + } + if (!PtInRect(&lboxRect,pt)) { + ReleaseCapture(); + ClosePopup(GetParent(hLbox)); + return 0; + } + break; + } + + case WM_LBUTTONUP: { + LRESULT result = CallWindowProc(oldProc, + hLbox, + message, + wparam, + lparam); + ReleaseCapture(); + ClosePopup(GetParent(hLbox)); + return result; + } + + case WM_KILLFOCUS: + bInScroll = FALSE; + ReleaseCapture(); + ClosePopup(GetParent(hLbox)); + return 0; + } + return CallWindowProc(oldProc,hLbox,message,wparam,lparam); +} + +//---------------------------------------------------------------------------// +static void UpdateSelection(HWND hLbox, HWND hEdit) { + int idx = SendMessage(hLbox,LB_GETCURSEL,0,0); + if (idx == LB_ERR) return; + TCHAR szBuf[256]; + SendMessage(hLbox,LB_GETTEXT,(WPARAM)idx,(LPARAM)szBuf); + SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)szBuf); + if (!(GetWindowLong(GetParent(hLbox),GWL_STYLE) & CBS_DROPDOWNLIST)) + SendMessage(hEdit,EM_SETSEL,0,(LPARAM)-1); + ListUpdateScrollbar(hLbox); +} + +//---------------------------------------------------------------------------// +static BOOL ComboCreate(HWND window) { + RECT comboRect,dlgRect,comboRelRect; + LPBYTE pBmp[3]; + LPSIZE pSize[3]; + int editHgt; + BOOL bUp = TRUE; + + GetWindowRect(GetParent(window),&dlgRect); + GetWindowRect(window,&comboRect); + GetClientRect(window,&comboRelRect); + + // + // Reposition the combo to its full size. We'll hide the popup + // (bottom) later. + // + + editHgt = comboRelRect.bottom - BEVEL_THICKNESS*2; + if (comboRect.top + sgComboSize[0].cy > GetSystemMetrics(SM_CYSCREEN)) { + // use short popup + comboRelRect.bottom = sgSComboSize[0].cy; + for (int i = 0; i < 3; ++i) { + pBmp[i] = sgSComboBmp[i]; + pSize[i] = &sgSComboSize[i]; + } + } + else { + comboRelRect.bottom = sgComboSize[0].cy; + for (int i = 0; i < 3; ++i) { + pBmp[i] = sgComboBmp[i]; + pSize[i] = &sgComboSize[i]; + } + } + + int mod; + if (0 != (mod = comboRelRect.right % pSize[0]->cx)) + comboRelRect.right += pSize[0]->cx - mod; + + SetWindowPos(window, + NULL, // z-order + 0, // x position + 0, // y position + comboRelRect.right, // width + comboRelRect.bottom, // height + SWP_NOMOVE|SWP_NOZORDER); + + // + // Create the backgrounds for the combo box. + // + + COMBOBMPPTR pComboBmp = (COMBOBMPPTR)ALLOC(sizeof(COMBOBMP)); + pComboBmp->size.cx = comboRelRect.right; + pComboBmp->size.cy = comboRelRect.bottom; + pComboBmp->bitmap = (LPBYTE)ALLOC(comboRelRect.right*comboRelRect.bottom); + SetProp(window,PROP_COMBOEDITBKG,(HANDLE)pComboBmp); + + // + // Draw left + SBltROP3(pComboBmp->bitmap, + pBmp[0], + pSize[0]->cx, + pSize[0]->cy, + pComboBmp->size.cx, + pSize[0]->cx, + NULL, + SRCCOPY); + + // + // Draw middle + for (int tile = comboRelRect.right/pSize[1]->cx - 2, + xoffset = pSize[1]->cx; + tile; + --tile, xoffset += pSize[1]->cx) + { + SBltROP3(pComboBmp->bitmap + xoffset, + pBmp[1], + pSize[1]->cx, + pSize[1]->cy, + pComboBmp->size.cx, + pSize[1]->cx, + NULL, + SRCCOPY); + } + + // + // Draw right + SBltROP3(pComboBmp->bitmap + xoffset, + pBmp[2], + pSize[2]->cx, + pSize[2]->cy, + pComboBmp->size.cx, + pSize[2]->cx, + NULL, + SRCCOPY); + + // + // Set as control background + SDlgSetBitmap(window, + GetParent(window), + TEXT("ComboBox"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + pComboBmp->bitmap, + NULL, + pComboBmp->size.cx, + pComboBmp->size.cy); + + SetWindowPos(window, + 0,0,0, // z,x,y + comboRelRect.right, + editHgt + BEVEL_THICKNESS*2, + SWP_NOMOVE|SWP_NOZORDER); + + // + // Create the edit box control + HWND hEdit = CreateWindow(GetWindowLong(window,GWL_STYLE) & + CBS_DROPDOWNLIST ? + TEXT("STATIC") : TEXT("EDIT"), + NULL, + WS_CHILD | WS_VISIBLE | WS_TABSTOP, + BEVEL_THICKNESS, + BEVEL_THICKNESS, + comboRelRect.right - pSize[2]->cx - + BEVEL_THICKNESS, + editHgt, + window, + (HMENU)EDIT_ID, + global_hinstance, + NULL); + + // Replace the wndproc so we can receive the arrow key msgs + WNDPROC oldProc = (WNDPROC)SetWindowLong(hEdit, + GWL_WNDPROC, + (LONG)ComboEditWndProc); + SetProp(hEdit,PROP_OLDPROC,(HANDLE)oldProc); + SetProp(window,PROP_COMBOEDIT,(HANDLE)hEdit); + + RECT lboxRect; + // pop DOWN + SetRect(&lboxRect, + comboRelRect.left + BEVEL_THICKNESS, + comboRelRect.top + editHgt + BEVEL_THICKNESS*2, + comboRelRect.right - BEVEL_THICKNESS - ScrollbarGetWidth(), + comboRelRect.bottom - BEVEL_THICKNESS); + + // + // Create the listbox + HWND hLbox = CreateWindowEx(0, + TEXT("LISTBOX"), + NULL, + WS_CHILD | WS_TABSTOP | + LBS_NOTIFY | WS_CLIPSIBLINGS | + LBS_NOINTEGRALHEIGHT, + lboxRect.left, + lboxRect.top, + lboxRect.right - lboxRect.left, + lboxRect.bottom - lboxRect.top, + window, + (HMENU)LBOX_ID, + global_hinstance, + NULL); + if (!hLbox) return FALSE; + SetProp(window,PROP_COMBOLBOX, (HANDLE)hLbox); + + // Replace the wndproc so we can receive the focus and capture msgs + oldProc = (WNDPROC)SetWindowLong(hLbox, + GWL_WNDPROC, + (LONG)ComboLboxWndProc); + SetProp(hLbox,PROP_OLDPROC,(HANDLE)oldProc); + + // + // Create the listbox scrollbar + HWND hScroll = CreateWindowEx(0, + TEXT("StormScrollbar"), + NULL, + WS_CHILD, + lboxRect.right, + lboxRect.top, + ScrollbarGetWidth(), + lboxRect.bottom - lboxRect.top, + window, + (HMENU)SCROLL_ID, + global_hinstance, + NULL); + if (!hScroll) return FALSE; + + // Link listbox scrollbar to combo listbox + ScrollbarLink(hLbox, hScroll); + SetProp(window,PROP_LBOXSCROLL,(HANDLE)hScroll); + + LPRECT pDropRect = (LPRECT)ALLOC(sizeof(RECT)); + SetRect(pDropRect, + (GetWindowLong(window,GWL_STYLE) & CBS_DROPDOWNLIST) ? + comboRelRect.left + BEVEL_THICKNESS : + comboRelRect.right - BEVEL_THICKNESS - ScrollbarGetWidth(), + comboRelRect.top + BEVEL_THICKNESS, + comboRelRect.right - BEVEL_THICKNESS, + comboRelRect.top + BEVEL_THICKNESS + editHgt); + SetProp(window,PROP_COMBOARROWRCT,(HANDLE)pDropRect); + + sgbPopup = FALSE; + return TRUE; +} + +//---------------------------------------------------------------------------// +static LRESULT CALLBACK StormComboWndProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case EDIT_ID: + if (HIWORD(wparam) == EN_CHANGE) { + wparam = MAKEWPARAM(GetWindowLong(window,GWL_ID), + CBN_EDITCHANGE); + return SendMessage(GetParent(window), + message, + wparam, + (LPARAM)window); + } + else if (HIWORD(wparam) == CUSTOM_EN_SCROLLDOWN) { + HWND hLbox = (HWND)GetProp(window,PROP_COMBOLBOX); + int nSel = SendMessage(hLbox,LB_GETCURSEL,0,0); + if (nSel == LB_ERR) nSel = -1; + if (LB_ERR != SendMessage(hLbox, + LB_SETCURSEL, + (WPARAM)nSel + 1, + 0)) + { + UpdateSelection(hLbox, + (HWND)GetProp(window, + PROP_COMBOEDIT)); + } + return 0; + } + else if (HIWORD(wparam) == CUSTOM_EN_SCROLLUP) { + HWND hLbox = (HWND)GetProp(window,PROP_COMBOLBOX); + int nSel = SendMessage(hLbox,LB_GETCURSEL,0,0); + if (nSel == LB_ERR) nSel = 1; + if (nSel && LB_ERR != SendMessage(hLbox, + LB_SETCURSEL, + (WPARAM)nSel - 1, + 0)) + { + UpdateSelection(hLbox, + (HWND)GetProp(window, + PROP_COMBOEDIT)); + } + return 0; + } + break; + case LBOX_ID: + if (HIWORD(wparam) == LBN_SELCHANGE) { + UpdateSelection((HWND)lparam, + (HWND)GetProp(window,PROP_COMBOEDIT)); + return 0; + } + break; + } + break; + + case WM_CREATE: + if (!ComboCreate(window)) + return -1; + break; + + case WM_DESTROY: { + // free artwork + COMBOBMPPTR pBmp = + (COMBOBMPPTR)RemoveProp(window,PROP_COMBOEDITBKG); + + if (pBmp) { + if (pBmp->bitmap) FREE(pBmp->bitmap); + FREE(pBmp); + } + + RemoveProp(window,PROP_COMBOEDIT); + LPRECT pRect = (LPRECT)RemoveProp(window,PROP_COMBOARROWRCT); + if (pRect) FREE(pRect); + break; + } + + case WM_PAINT: { + PAINTSTRUCT ps; + HDC dc = BeginPaint(window,&ps); + + // PAINT THE BITMAP(S) + SDlgDrawBitmap(window,SDLG_USAGE_BACKGROUND,(HRGN)0); + EndPaint(window,&ps); + return 0; + } + + case WM_SETFOCUS: + SetFocus((HWND)GetProp(window,PROP_COMBOEDIT)); + return 0; + + case WM_LBUTTONDOWN: + SetCapture(window); + return 0; + + case WM_LBUTTONUP: { + if (window != GetCapture()) break; + ReleaseCapture(); + + if (ClosePopup(window)) return 0; + + HWND hLbox = (HWND)GetProp(window,PROP_COMBOLBOX); + POINT pt = { (short)LOWORD(lparam), (short)HIWORD(lparam) }; + if (PtInRect((LPRECT)GetProp(window,PROP_COMBOARROWRCT),pt)) + OpenPopup(window); + return 0; + } + + case WM_SETFONT: + SendMessage((HWND)GetProp(window,PROP_COMBOEDIT), + message, + wparam, + lparam); + SendMessage((HWND)GetProp(window,PROP_COMBOLBOX), + message, + wparam, + lparam); + break; + + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLOREDIT: + SetTextColor((HDC)wparam,0xFFFFFF); + SetBkColor((HDC)wparam,0); + SetBkMode((HDC)wparam,OPAQUE); + return (BOOL)GetStockObject(BLACK_BRUSH); + + case CB_ADDSTRING: { + HWND hLbox = (HWND)GetProp(window,PROP_COMBOLBOX); + LRESULT result = SendMessage(hLbox,LB_ADDSTRING,wparam,lparam); + ListUpdateScrollbar(hLbox); + ShowWindow((HWND)GetProp(window,PROP_LBOXSCROLL),SW_HIDE); + return result; + } + case WM_SETTEXT: { + HWND hEdit = (HWND)GetProp(window,PROP_COMBOEDIT); + if (TRUE == SendMessage(hEdit,message,wparam,lparam)) { + if (GetWindowLong(window,GWL_STYLE) & CBS_DROPDOWNLIST) + return TRUE; + SendMessage(hEdit, + EM_SETSEL, + 0, + (LPARAM)_tcslen((LPCTSTR)lparam)); + return TRUE; + } + return CB_ERRSPACE; + } + case WM_GETTEXT: + case WM_GETTEXTLENGTH: + return SendMessage((HWND)GetProp(window,PROP_COMBOEDIT), + message, + wparam, + lparam); + case CB_GETCOUNT: + return SendMessage((HWND)GetProp(window,PROP_COMBOLBOX), + LB_GETCOUNT, + wparam, + lparam); + case CB_GETCURSEL: + return SendMessage((HWND)GetProp(window,PROP_COMBOLBOX), + LB_GETCURSEL, + wparam, + lparam); + case CB_GETITEMDATA: + return SendMessage((HWND)GetProp(window,PROP_COMBOLBOX), + LB_GETITEMDATA, + wparam, + lparam); + case CB_GETLBTEXT: + return SendMessage((HWND)GetProp(window,PROP_COMBOLBOX), + LB_GETTEXT, + wparam, + lparam); + case CB_LIMITTEXT: + message = EM_LIMITTEXT; + return SendMessage((HWND)GetProp(window,PROP_COMBOEDIT), + message, + wparam, + lparam); + case CB_SETCURSEL: { + HWND hLbox = (HWND)GetProp(window,PROP_COMBOLBOX); + SendMessage(hLbox,LB_SETCURSEL,wparam,lparam); + UpdateSelection(hLbox,(HWND)GetProp(window,PROP_COMBOEDIT)); + return (LRESULT)wparam; + } + case CB_SETEDITSEL: + message = EM_SETSEL; + return SendMessage((HWND)GetProp(window,PROP_COMBOEDIT), + message, + wparam, + lparam); + case CB_SETITEMDATA: + return SendMessage((HWND)GetProp(window,PROP_COMBOLBOX), + LB_SETITEMDATA, + wparam, + lparam); + case CB_RESETCONTENT: + return SendMessage((HWND)GetProp(window,PROP_COMBOLBOX), + LB_RESETCONTENT, + wparam, + lparam); + } + return DefWindowProc(window,message,wparam,lparam); +} + +//---------------------------------------------------------------------------// +// EXPORTED FUNCTIONS +//---------------------------------------------------------------------------// + +//---------------------------------------------------------------------------// +void ComboboxLoadArtwork(SNETGETARTPROC artcallback) { + if (!sgnComboCnt++) { + + static int COMBO_ARTID[3] = { + SNET_ART_COMBOLEFT, + SNET_ART_COMBOMIDDLE, + SNET_ART_COMBORIGHT + }; + static int SCOMBO_ARTID[3] = { + SNET_ART_SCOMBOLEFT, + SNET_ART_SCOMBOMIDDLE, + SNET_ART_SCOMBORIGHT + }; + + for (int pos = LEFT; pos < NUM_TILES; ++pos) { + UiLoadArtwork( + artcallback, + NULL, + NULL, + COMBO_ARTID[pos], + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgComboBmp[pos], + &sgComboSize[pos]); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SCOMBO_ARTID[pos], + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgSComboBmp[pos], + &sgSComboSize[pos]); + } + + } +} + +//---------------------------------------------------------------------------// +void ComboboxDestroyArtwork(void) { + // Only Destroy if this if the only combobox currently using the artwork + if (!--sgnComboCnt) { + for (int pos = LEFT; pos < NUM_TILES; ++pos) { + if (sgComboBmp[pos]) { + FREE(sgComboBmp[pos]); + sgComboBmp[pos] = NULL; + } + if (sgSComboBmp[pos]) { + FREE(sgSComboBmp[pos]); + sgSComboBmp[pos] = NULL; + } + } + } +} + +//---------------------------------------------------------------------------// +void ComboRegisterClass (void) { + WNDCLASS wndclass; + ZeroMemory(&wndclass,sizeof(WNDCLASS)); + wndclass.style = CS_GLOBALCLASS; + wndclass.lpfnWndProc = StormComboWndProc; + wndclass.hInstance = global_hinstance; + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.lpszClassName = "StormCombobox"; + RegisterClass(&wndclass); +} + +//---------------------------------------------------------------------------// +void ComboUnregisterClass (void) { + UnregisterClass("StormCombobox", global_hinstance); +} diff --git a/src/Storm/SOURCE/BATTLE/CONNECT.CPP b/src/Storm/SOURCE/BATTLE/CONNECT.CPP new file mode 100644 index 0000000..d9c4bfe --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/CONNECT.CPP @@ -0,0 +1,421 @@ +/**************************************************************************** +* +* connect.CPP +* battle.net +* +* By Michael Morhaime +* +***/ + +#include "pch.h" + +#define PREVENT_MINIMIZE 0 // 0 in final + +//**************************************************************************** +//**************************************************************************** +#define MILLISEC_PER_SEC 1000 + +#define LOGO_TIMER_ID 1 +#define MAX_FRAMES 32 + + + +static HTRANS sgTransHandles[MAX_FRAMES]; +static int sgFrame; + +static LPBYTE sgBackgroundBmp = NULL; +static LPBYTE sgButtonBmp = NULL; +static LPBYTE sgLogoBmp = NULL; +static SIZE sgLogoBmpSize; + +static BOOL sgbPreventMinimize = FALSE; +static HWND sgRudeWindow = NULL; +static HWND sgRudeWindowParent = NULL; + +extern void UiHideConnectCancel(void); +extern BOOL UiProcessWindowMessages(void); +extern HWND ghWndUiMainParent; + + + +//**************************************************************************** +//**************************************************************************** +BOOL LogoSetTimer(HWND window, int nTimer, SNETGETDATAPROC getdatacallback) { + LPBYTE pData; + DWORD dwSize; + + if (UiGetData(getdatacallback, SNET_DATA_BATTLE_LOGODELAY, &pData, &dwSize)) { + if (dwSize == sizeof(DWORD)) { + DWORD dwDelay; + int nResult; + + dwDelay = *((DWORD *)pData); + nResult = SDlgSetTimer(window, nTimer, dwDelay, NULL); + FREE(pData); + return (nResult != NULL); + } + } + + return 0; +} + +//**************************************************************************** +//**************************************************************************** +void LogoAnimate(HWND window, HWND child) { + RECT rect; + + TPBMP tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + + if (! child) return; + if (! tpBmp) return; + if (! sgLogoBmp) return; + if (! sgTransHandles[0]) return; + + + sgFrame++; + if ((! sgTransHandles[sgFrame]) || (sgFrame >= MAX_FRAMES)) + sgFrame = 0; + + + GetWindowRect(child, &rect); + ScreenToClient(window, (LPPOINT)&rect.left); + ScreenToClient(window, (LPPOINT)&rect.right); + + // Copy from Background bitmap to buffer for animating logo + SBltROP3 ( + sgLogoBmp, + tpBmp->data + (rect.top * tpBmp->datasize.cx) + rect.left, + sgLogoBmpSize.cx, + sgLogoBmpSize.cy, + sgLogoBmpSize.cx, + tpBmp->datasize.cx, + NULL, + SRCCOPY + ); + + STransBlt(sgLogoBmp, 0, 0, sgLogoBmpSize.cx, sgTransHandles[sgFrame]); + + InvalidateRect(child, NULL, FALSE); +} + + +//**************************************************************************** +//**************************************************************************** +void LogoFramesDestroy(void) { + for (int index = 0; index < MAX_FRAMES; index++) { + if (sgTransHandles[index]) { + STransDelete(sgTransHandles[index]); + sgTransHandles[index] = NULL; + } + } + + if (sgLogoBmp) { + FREE(sgLogoBmp); + sgLogoBmp = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL LogoInit(HWND child, SNETGETARTPROC artcallback) { + RECT rect; + LPBYTE srcframes; + SIZE srcsize; + + GetClientRect(child, &rect); + sgLogoBmpSize.cx = rect.right; + sgLogoBmpSize.cy = rect.bottom; + + // Get logo animation + if (!UiLoadArtwork(artcallback, + NULL, + NULL, // don't register the artwork + SNET_ART_APP_LOGO_SML, + 0, + 0, + 0, + FALSE, + FALSE, + &srcframes, + &srcsize)) { + ShowWindow(child,SW_HIDE); + sgLogoBmp = NULL; + return FALSE; + } + + memset(sgTransHandles, 0, sizeof(sgTransHandles)); + if (srcframes && sgLogoBmpSize.cy) { + int frames = srcsize.cy / sgLogoBmpSize.cy; + if (frames > MAX_FRAMES) + frames = MAX_FRAMES; + // create an HTRANS for each frame in the animation + for (int index = 0; index < frames; index++) { + + rect.left = 0; + rect.right = sgLogoBmpSize.cx - 1; + rect.top = index * sgLogoBmpSize.cy; + rect.bottom = rect.top + sgLogoBmpSize.cy - 1; + + STransCreate( + srcframes, + sgLogoBmpSize.cx, + sgLogoBmpSize.cy, + 8, + &rect, + PALETTEINDEX(250), + &sgTransHandles[index] + ); + } + + FREE(srcframes); + } + sgFrame = 0; + + sgLogoBmp = (LPBYTE) ALLOC(rect.right * rect.bottom); + if (!sgLogoBmp) + return FALSE; + + SDlgSetBitmap( + child, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + sgLogoBmp, + NULL, + rect.right, + rect.bottom + ); + return TRUE; +} + + +//=========================================================================== +static void DestroyArtwork (HWND window) { + TPBMP tpBmp = (TPBMP) GetWindowLong(GetDlgItem(window, IDC_LOGO_ANIMATE), GWL_USERDATA); + + // tpBmp->data points to a sgBAckgroundBmp, which will be freed below + if (tpBmp) + FREE(tpBmp); + + if (sgBackgroundBmp) { + FREE(sgBackgroundBmp); + sgBackgroundBmp = NULL; + } + + if (sgButtonBmp) { + FREE(sgButtonBmp); + sgButtonBmp = NULL; + } + + LogoFramesDestroy(); +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window, SNETGETARTPROC artcallback) { + int btn_ids[] = { + IDCANCEL, + 0 + }; + + int btn_static[] = { + IDC_STATIC_TEXT, + 0 + }; + + SIZE sizeBtns; + SIZE bgSize; + + UiLoadArtwork( + artcallback, + window, + NULL, + SNET_ART_BATTLE_CONNECT_BKG, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TRUE, // Use palette from this art + TRUE, // Prep palette for a fade + &sgBackgroundBmp, + &bgSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BUTTON_SML, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgButtonBmp, + &sizeBtns); + + SDlgSetControlBitmaps (window, btn_ids, NULL, sgButtonBmp, &sizeBtns, SDLG_ADJUST_VERTICAL); + SDlgSetControlBitmaps (window, btn_static, NULL, sgBackgroundBmp, &bgSize, SDLG_ADJUST_CONTROLPOS); + + + // set up a TPBMP for the logo window, it will have information about the background bitmap + HWND hWndLogo = GetDlgItem(window, IDC_LOGO_ANIMATE); + + if (hWndLogo && sgBackgroundBmp) { + TPBMP tpBmp = (TPBMP) ALLOC(sizeof(TBMP)); + SetWindowLong(hWndLogo, GWL_USERDATA, (LONG) tpBmp); + if (tpBmp) { + tpBmp->data = sgBackgroundBmp; + tpBmp->datasize = bgSize; + } + + // set up the animating diablo logo + LogoInit(hWndLogo,artcallback); + LogoAnimate(window, hWndLogo); + } + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +void ProtectMinimize(BOOL bEnable) { +#if PREVENT_MINIMIZE + static sOldStyle; + + // Protect this code + if (sgbPreventMinimize == bEnable) + return; + + sgbPreventMinimize = bEnable; + + HWND hWndFrame = SDrawGetFrameWindow(); + + if (bEnable) { + sgRudeWindow = NULL; + sgRudeWindowParent = NULL; + + sOldStyle = GetWindowLong(hWndFrame,GWL_EXSTYLE); + SetWindowLong(hWndFrame, GWL_EXSTYLE, sOldStyle & ~WS_EX_TOPMOST); + } + else if (sgRudeWindow) { + if (IsWindow(sgRudeWindow) && IsWindow(sgRudeWindowParent)) + SetParent(sgRudeWindow, sgRudeWindowParent); + + sgRudeWindow = NULL; + sgRudeWindowParent = NULL; + + SetWindowLong(hWndFrame, GWL_EXSTYLE, sOldStyle); + + // Give our application back the focus + SetForegroundWindow(GetActiveWindow()); + } +#else + + sgbPreventMinimize = bEnable; + if (!bEnable) + UiRestoreApp(); + +#endif +} + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + + + +//=========================================================================== +BOOL CALLBACK ConnectDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + static UIPARAMSPTR uiparams; + static HWND shWndCancelDlg; + + switch (message) { + case WM_TIMER: + if (wparam == LOGO_TIMER_ID) { + LogoAnimate(window, GetDlgItem(window, IDC_LOGO_ANIMATE)); + } + return 1; + +#if PREVENT_MINIMIZE + case WM_NCACTIVATE: + if (!sgbPreventMinimize) + break; + + if (wparam == FALSE) { + PostMessage(window, WM_USER+100, 0, 0); + + SetWindowLong(window, DWL_MSGRESULT, 0); // This means don't minimize this window + return 1; + } + break; + + case WM_USER+100: + // Make new window our child so it will draw on the directX surface + if (GetForegroundWindow() != GetActiveWindow()) { + sgRudeWindow = GetForegroundWindow(); + sgRudeWindowParent = GetParent(sgRudeWindow); + SetParent(sgRudeWindow, window); + + // Hide Connect Dialog. Dialup networking will provide its own. + UiHideConnectCancel(); + } + return 1; +#endif + + case WM_NOTIFICATION_WAITING: + UiNotification(); + return 1; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + case WM_DESTROY: + ghWndUiMainParent = NULL; + + UiVidFadeOut(DEFAULT_STEPS*2); // Note that VidFadeOut also erase the screen + + ShowCursor(FALSE); // Leave cursor off + UiVidFade(1,1); // restore palette for parent window + + SDlgKillTimer(window, LOGO_TIMER_ID); + DestroyArtwork(window); + break; + + + + case WM_INITDIALOG: + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + uiparams = (UIPARAMSPTR)lparam; + if (!uiparams || !uiparams->interfacedata) + return 0; + + if (uiparams->interfacedata) + LoadArtwork(window, uiparams->interfacedata->artcallback); + + UiLoadCursors(window, uiparams->interfacedata); + + // Set timer to poll for messages + LogoSetTimer(window, LOGO_TIMER_ID, uiparams->interfacedata->getdatacallback); + + // Set this window up to process SN_NOTIFY messages + ghWndUiMainParent = window; + + UiVidFade(1,1); + + return 1; + } + + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + diff --git a/src/Storm/SOURCE/BATTLE/DISCONN.CPP b/src/Storm/SOURCE/BATTLE/DISCONN.CPP new file mode 100644 index 0000000..a3a3f88 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/DISCONN.CPP @@ -0,0 +1,39 @@ +/**************************************************************************** +* +* disconn.CPP +* battle.net user interface functions +* +* By Michael Morhaime +* +***/ + +#include "pch.h" + + + +//******************************************** +//******************************************** +BOOL CALLBACK RasEnumCallback(LPCTSTR szEntryName, LPVOID rashandle, LPVOID lpContext) { + SNETUIDATAPTR interfacedata; + char szFmt[256]; + char szMsg[512]; + char szTitle[32]; + BOOL bResult; + + interfacedata = (SNETUIDATAPTR) lpContext; + + LoadString(global_hinstance, IDS_QUERYDISCONNECT, szFmt, sizeof(szFmt)); + LoadString(global_hinstance, IDS_BATTLENET, szTitle, sizeof(szTitle)); + sprintf(szMsg, szFmt, szEntryName); + + if (interfacedata->messageboxcallback && GetActiveWindow()) + bResult = UiMessageBox(interfacedata->messageboxcallback, GetActiveWindow(), szMsg, szTitle, MB_OKCANCEL); + else + bResult = MessageBox(GetActiveWindow(), szMsg, szTitle, MB_OKCANCEL); + + if (bResult == IDOK) + HangupRASConnection(rashandle); + + return 1; +} + diff --git a/src/Storm/SOURCE/BATTLE/JOINGAME.CPP b/src/Storm/SOURCE/BATTLE/JOINGAME.CPP new file mode 100644 index 0000000..8e5a8f1 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/JOINGAME.CPP @@ -0,0 +1,815 @@ +/**************************************************************************** +* +* JOINGAME.CPP +* battle.net chat room +* +* By Michael Morhaime +* +***/ + +//**************************************************************************** +// Modification Log: +// +// Diablo Patch #1 +// 2/3/97 MM - Instead of calling UpdateGameList every 10 seconds, +// we now only call it once. Then, after waiting 3 seconds, +// we go through the list of games calling SpiGetGameInfo() +// for each game. +// +// 2/5/97 MM - Added better error messages for not being able to join a game. +// +// 2/17/97 MM - Added call to SrvNotifyJoin() when successfully joining a game. +// +// Diablo Patch #2 +// 3/21/97 MM - Added support for requesting a list of games by category. +//**************************************************************************** + +#include "pch.h" + +#define MAX_STRING_LEN 128 + +typedef struct _CATEGORYDATA { + DWORD categorybits; + DWORD categorymask; +} CATEGORYDATA, *CATEGORYDATAPTR; + +static LPBYTE sgBackgroundBmp = NULL; +static LPBYTE sgButtonBmp = NULL; +static LPBYTE sgListboxBmp = NULL; + +static char sgszGameName[MAX_STRING_LEN] = ""; +static char sgszGamePassword[MAX_STRING_LEN] = ""; + +//### MM Diablo Patch #2 3/21/97 +static DWORD sgdwCategoryBits; +static DWORD sgdwCategoryMask; + +static HWND sghFilterCombo; + +extern int gnUserFlags; +//=========================================================================== +// External routines +//=========================================================================== +int NormalizeNetLag(DWORD dwMilliSec); +void DrawNetLag(int nNetLag, LPDRAWITEMSTRUCT lpdis); +int ListFindName(HWND hWndList, LPCSTR szName); + +//=========================================================================== +static void DestroyArtwork (HWND window) { + if (sgBackgroundBmp) { + FREE(sgBackgroundBmp); + sgBackgroundBmp = NULL; + } + + if (sgButtonBmp) { + FREE(sgButtonBmp); + sgButtonBmp = NULL; + } + + + if (sgListboxBmp) { + FREE(sgListboxBmp); + sgListboxBmp = NULL; + } +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window, SNETGETARTPROC artcallback) { + int btn_ids[] = { + IDOK, + IDCANCEL, + 0 + }; + + int btn_desc[] = { + IDC_GAMEDESCRIPTION, + 0, + }; + + SIZE sizeBtns; + SIZE bgSize; + + UiLoadArtwork( + artcallback, + window, + NULL, + SNET_ART_JOINBACKGROUND, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgBackgroundBmp, + &bgSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BUTTON_XSML, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgButtonBmp, + &sizeBtns); + + SDlgSetControlBitmaps (window, btn_ids, NULL, sgButtonBmp, &sizeBtns, SDLG_ADJUST_VERTICAL); + SDlgSetControlBitmaps (window, btn_desc, NULL, sgBackgroundBmp, &bgSize, SDLG_ADJUST_CONTROLPOS); + return 1; +} + + +//=========================================================================== +//=========================================================================== +static HFONT InitCustomFonts(HWND hWnd) { +#if 0 + HFONT hFont = NULL; + LOGFONT lFont; + + if ((hFont = (HFONT) SendMessage(hWnd, WM_GETFONT, 0, 0L))) { + // Start with dialog font and modify face name + if (GetObject(hFont, sizeof(LOGFONT), (LPSTR) &lFont)) { + //lFont.lfHeight = -MulDiv(8, 96, 72); // height of 8 pixels + //lFont.lfWidth = 0; // let Windows autosize width + //lFont.lfWeight = FW_NORMAL; // change to non Bold + strcpy(lFont.lfFaceName, "Arial"); + + + if (hFont = CreateFontIndirect((LPLOGFONT) &lFont)) { + SendDlgItemMessage(hWnd, IDC_GAMEDESCRIPTION, WM_SETFONT, (WPARAM)hFont, 0); + } + } + } + return hFont; +#else + return 0; +#endif + +} + +//=========================================================================== +static void UpdateGameList (HWND dialog, HWND listbox, BOOL bSelGame) { + + SNETSPI_GAMELISTPTR curr, gamelist; + int nIndex; + + + // Get current linked list of games + if (!SpiLockGameList(sgdwCategoryBits, sgdwCategoryMask, &gamelist)) //### MM Diablo Patch #2 3/21/97 + return; + + curr = gamelist; + + + // MAKE SURE ALL GAMES IN THE LINKED LIST ARE REPRESENTED IN THE LIST BOX + SendMessage(listbox, WM_SETREDRAW, FALSE, 0); + while (curr) { + // Ignore private games + if (curr->gamemode & SNET_GM_PRIVATE) { + curr = curr->next; + continue; + } + + nIndex = ListFindName(listbox, curr->gamename); + + char szString[2*SNETSPI_MAXSTRINGLENGTH]; + + //### PATCH 2/3/97 MM Added gameid to string. +// sprintf(szString,"%s\t%x %x\t%s",curr->gamename, NormalizeNetLag(curr->ownerlatency), curr->creationtime, curr->gamedescription); + sprintf(szString,"%s\t%x %x %x\t%s",curr->gamename, curr->gameid, NormalizeNetLag(curr->ownerlatency), curr->creationtime, curr->gamedescription); + + // Is this game in the list box at all? + if (nIndex == LB_ERR) { + SendMessage(listbox,LB_ADDSTRING,0,(LPARAM)szString); + + // If there is no current list box selection, and there is no text in the + // NAME control, select this item as the default selection. + if ( bSelGame && + SendMessage(listbox,LB_GETCURSEL,0,0) == LB_ERR && + SendDlgItemMessage(dialog,IDC_EDIT_NAME,WM_GETTEXTLENGTH,0,0) == 0) { + SendMessage(listbox,LB_SETCURSEL,0,0); + SendMessage(dialog,WM_COMMAND,MAKELONG(IDC_GAMELIST,LBN_SELCHANGE),(LPARAM)listbox); + } + } + else { + char szOldString[2*SNETSPI_MAXSTRINGLENGTH]; + + // Game is in the list box, but is the information still correct? + SendMessage(listbox,LB_GETTEXT,nIndex,(LPARAM)szOldString); + if (strcmp(szString, szOldString)) { + int nSelect; + + // Save current selection for later + nSelect = SendMessage(listbox, LB_GETCURSEL, 0, 0); + + // Set new game info + SendMessage(listbox, LB_DELETESTRING, nIndex, 0); + SendMessage(listbox, LB_INSERTSTRING, nIndex, (LPARAM)(LPCSTR)szString); + + // Restore selection if necessary + if (nSelect == nIndex) + SendMessage(listbox, LB_SETCURSEL, nIndex, 0); + } + } + curr = curr->next; + } + + // MAKE SURE THERE ARE NO GAMES IN THE LIST BOX THAT AREN'T IN THE LINKED LIST + + { + char liststring[2*SNETSPI_MAXSTRINGLENGTH]; + WPARAM index = 0; + + while (SendMessage(listbox,LB_GETTEXT,index,(LPARAM)liststring) != LB_ERR) { + char *p; + + curr = gamelist; + + // Add NULL termination following game name + p = strchr(liststring, '\t'); + if (p) *p = 0; + + while (curr) { + if (!strcmp(curr->gamename,liststring)) + break; + else + curr = curr->next; + } + if (!curr) { + if ((WPARAM)SendMessage(listbox,LB_GETCURSEL,0,0) == index) { + SendMessage(listbox,LB_SETCURSEL,index-1,0); + SendMessage(dialog,WM_COMMAND,MAKELONG(IDC_GAMELIST,LBN_SELCHANGE),(LPARAM)listbox); + } + SendMessage(listbox,LB_DELETESTRING,index,0); + } + else + ++index; + } + } + + SpiUnlockGameList(gamelist, NULL); + + //### PATCH MM 2/5/97 + SrvMaintainLatencies(); + + SendMessage(listbox, WM_SETREDRAW, TRUE, 0); + + // update our scroll bar + ListUpdateScrollbar(listbox); + + +} + + +//### PATCH MM 2/3/97 +//=========================================================================== +static void UpdateGameLags(HWND hWndList) { + SNETSPI_GAMELIST curr; + char szString[2*SNETSPI_MAXSTRINGLENGTH]; + int nCount; + int nGameId, nLag, nTime; + char *p; + DWORD dwLatency; + + // Update latency counters + SrvMaintainLatencies(); + SendMessage(hWndList, WM_SETREDRAW, FALSE, 0); + + nCount = SendMessage(hWndList, LB_GETCOUNT, 0, 0); + if (nCount == LB_ERR) + return; + + for (int i=0; iinterfacedata && uiparams->interfacedata->drawdesccallback) { + DWORD dwItemFlags, dwDrawFlags; + + dwItemFlags = 0; + dwDrawFlags = SNET_DDF_MULTILINE; + return uiparams->interfacedata->drawdesccallback( + PROVIDERID, + SNET_DRAWTYPE_GAME, + name, + description, + dwItemFlags, + dwDrawFlags, + nTime, + (LPDRAWITEMSTRUCT)lparam); + } + + // OTHERWISE, LET THE DEFAULT DIALOG BOX PROCEDURE DRAW (OR ERASE) THE + // DESCRIPTION FROM THE STATIC TEXT + else + goto DRAW_BREAK; + + } + else if (wparam == IDC_GAMELIST) { + char szString[2*SNETSPI_MAXSTRINGLENGTH]; + LPSTR szLag = ""; + LPSTR description = ""; + LPSTR p; + int nLag = 0; + int nTime = 0; + COLORREF oldTextColor, oldBkColor; + LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lparam; + BOOL bSelected = lpdis->itemState & ODS_SELECTED; + + // Get user name/description + if (LB_ERR == SendMessage(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, (LPARAM)(LPCSTR)szString)) + goto DRAW_BREAK; + + // make sure we have something to draw + if (!szString[0] || !lpdis->hDC) + goto DRAW_BREAK; + + if (NULL != (p = strchr(szString,'\t'))) { + //### PATCH MM 2/3/97 Added gameid to string. + int nGameId; + + *p++ = 0; + + // Get Lag and Creation Time + szLag = p; + + //### PATCH MM 2/3/97 Added gameid to string. + //sscanf(szLag, "%x %x", &nLag, &nTime); + sscanf(szLag, "%x %x %x", &nGameId, &nLag, &nTime); + + if (NULL != (p = strchr(szLag,'\t'))) { + description = p; + *description++ = 0; + } + } + + // Draw gamename and net lag into list box + + // If the app has registered a draw description callback, + // let it draw the game name in the listbox. + if (uiparams->interfacedata && uiparams->interfacedata->drawdesccallback) { + DWORD dwItemFlags, dwDrawFlags; + + dwItemFlags = 0; + dwDrawFlags = SNET_DDF_INCLUDENAME; + uiparams->interfacedata->drawdesccallback( + PROVIDERID, + SNET_DRAWTYPE_GAME, + szString, + description, + dwItemFlags, + dwDrawFlags, + nTime, + (LPDRAWITEMSTRUCT)lparam); + } + else { + oldTextColor = SetTextColor(lpdis->hDC, RGB(0xff, 0xff, 0xff)); + oldBkColor = SetBkColor(lpdis->hDC, (bSelected) ? GetSysColor(COLOR_HIGHLIGHT) : RGB(0, 0, 0)); + ExtTextOut( + lpdis->hDC, + lpdis->rcItem.left, + lpdis->rcItem.top, + ETO_CLIPPED | ETO_OPAQUE, + &lpdis->rcItem, + szString, + strlen(szString), + NULL); + + // Restore colors to hdc + SetTextColor(lpdis->hDC, oldTextColor); + SetBkColor(lpdis->hDC, oldBkColor); + } + + // Draw net lag + DrawNetLag(nLag, lpdis); + return 1; + } +DRAW_BREAK: + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +static void CALLBACK JoinAddCategory(LPCSTR pszCategoryName, + DWORD categorybits, + DWORD categorymask) +{ + if (!sghFilterCombo) return; + int nPos = SendMessage(sghFilterCombo, + CB_ADDSTRING, + 0, + (LPARAM)pszCategoryName); + if (nPos == CB_ERR) return; + CATEGORYDATAPTR data = (CATEGORYDATAPTR)ALLOC(sizeof(CATEGORYDATA)); + data->categorybits = categorybits; + data->categorymask = categorymask; + SendMessage(sghFilterCombo,CB_SETITEMDATA,(WPARAM)nPos,(LPARAM)data); +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL CALLBACK JoinGameDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + static UIPARAMSPTR uiparams = NULL; + static BOOL sbSecondTimerActive = FALSE; + static HFONT shCustomFont; + + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: { + HWND hWndName, hWndPassword; + char szText[MAX_STRING_LEN]; + SNETSPI_GAMELIST GameInfo; + + + if (uiparams->interfacedata->soundcallback) + uiparams->interfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + hWndName = GetDlgItem(window, IDC_EDIT_NAME); + hWndPassword = GetDlgItem(window, IDC_EDIT_PASSWORD); + + + + // First, verify user entered required information + if (!SendMessage(hWndName, WM_GETTEXTLENGTH, 0, 0L)) { + LoadString(global_hinstance,IDS_NAME_REQUIRED,szText,MAX_STRING_LEN); + UiMessageBox( + uiparams->interfacedata->messageboxcallback, + window, + szText, + "", + MB_OK | MB_ICONWARNING); + return 0; + } + + + // Fill create game structure + SendMessage(hWndName, WM_GETTEXT, sizeof(sgszGameName), (LPARAM)((LPSTR)sgszGameName)); + SendMessage(hWndPassword, WM_GETTEXT, sizeof(sgszGamePassword), (LPARAM)((LPSTR)sgszGamePassword)); + + // Don't let user click ok twice + EnableWindow((HWND)lparam, FALSE); + + // Get Game info + TCHAR szPlayerName[MAX_STRING_LEN]; + TCHAR szPlayerDesc[MAX_STRING_LEN]; + SrvGetLocalPlayerName(szPlayerName,MAX_STRING_LEN); + SrvGetLocalPlayerDesc(szPlayerDesc,MAX_STRING_LEN); + if (SpiGetGameInfo (0, sgszGameName, sgszGamePassword, &GameInfo)) { + // Are we authorized to join this game + if (!uiparams->interfacedata->authcallback( + SNET_AUTHTYPE_GAME, + szPlayerName, + szPlayerDesc, + gnUserFlags, + GameInfo.gamedescription, + szText, + sizeof(szText))) { + UiMessageBox(uiparams->interfacedata->messageboxcallback, window, szText, NULL, MB_ICONWARNING | MB_OK); + EnableWindow((HWND)lparam, TRUE); + return 0; + } + + if (SNetJoinGame(0, + sgszGameName, + sgszGamePassword, + szPlayerName, + szPlayerDesc, + uiparams->playeridptr)) { + char progvers[32]; + wsprintf(progvers,"%08x%08x",global_programid,global_versionid); + SRegSaveString("Recent Games",progvers,SREG_FLAG_BATTLENET,sgszGameName); + + SrvNotifyJoin(sgszGameName, sgszGamePassword); //### PATCH MM 2/17/97 + + SDlgEndDialog(window, TRUE); + return 0; + } + } + + //### PATCH MM 2/5/97 + // Either join failed, or we couldn't get GameInfo about it. + + int nError = GetLastError(); + int nMsg = IDS_JOIN_FAILED; // Default Message + + if (nError == SNET_ERROR_HOST_UNREACHABLE) + nMsg = IDS_ERR_HOST_UNREACHABLE; + else if (nError == SNET_ERROR_GAME_FULL) + nMsg = IDS_ERR_GAME_FULL; + + LoadString(global_hinstance,nMsg,szText,MAX_STRING_LEN); + //### END + + UiMessageBox(uiparams->interfacedata->messageboxcallback, window, szText, "", MB_OK | MB_ICONWARNING); + EnableWindow((HWND)lparam, TRUE); + return 0; + + } + case IDCANCEL: + if (uiparams->interfacedata->soundcallback) + uiparams->interfacedata->soundcallback(PROVIDERID, SNET_SND_SELECTITEM, 0); + + SDlgEndDialog(window, FALSE); + return 0; + + case IDC_EDIT_NAME: + if (HIWORD(wparam) == EN_CHANGE) { + HWND hWndGameList = GetDlgItem(window, IDC_GAMELIST); + + // If the focus is in the edit control, assume the user + // just modified it, so remove any selection from the list box. + if ((HWND) lparam == GetFocus()) { + SendMessage(hWndGameList,LB_SETCURSEL,(WPARAM)-1,0); + SendMessage(window,WM_COMMAND,MAKELONG(IDC_GAMELIST,LBN_SELCHANGE),(LPARAM)hWndGameList); + } + } + break; + + case IDC_GAMELIST: + if (HIWORD(wparam) == LBN_DBLCLK) { + HWND hWndGameList = (HWND)lparam; + int nIndex; + + nIndex = SendMessage(hWndGameList, LB_GETCURSEL, 0, 0); + if (nIndex != LB_ERR) { + // Make sure we update the edit control first + SendMessage(window,WM_COMMAND,MAKELONG(IDC_GAMELIST,LBN_SELCHANGE),(LPARAM)hWndGameList); + + // Behave like OK was just pressed + SendMessage(window,WM_COMMAND,MAKELONG(IDOK,BN_CLICKED),(LPARAM)GetDlgItem(window, IDOK)); + } + + } + else if (HIWORD(wparam) == LBN_SELCHANGE) { + HWND hWndGameList = (HWND)lparam; + int nIndex = SendMessage(hWndGameList, LB_GETCURSEL, 0, 0); + char szText[MAX_STRING_LEN]; + + // Change text in Edit Control + if (nIndex != LB_ERR) { + char *p; + + SendMessage(hWndGameList,LB_GETTEXT, nIndex, (LPARAM)(LPCSTR)szText); + + + // NULL terminate game name (chop of description, and latency) + if (p = strchr(szText,'\t')) + *p = 0; + + // Set name and reset password (public games don't have a password) + SendDlgItemMessage(window, IDC_EDIT_NAME, WM_SETTEXT, 0, (LPARAM)(LPCSTR)szText); + SendDlgItemMessage(window, IDC_EDIT_PASSWORD, WM_SETTEXT, 0, (LPARAM)(LPCSTR)""); + } + + InvalidateRect(GetDlgItem(window, IDC_GAMEDESCRIPTION), NULL, TRUE); + + // Update scrollbar in case user scrolled the list with the mouse + ListUpdateScrollbar(hWndGameList); + } + break; + + case IDC_FILTER: { + if (HIWORD(wparam) == CBN_SELCHANGE) { + int nPos = SendMessage((HWND)lparam,CB_GETCURSEL,0,0); + if (nPos == CB_ERR) break; + CATEGORYDATAPTR data = (CATEGORYDATAPTR)SendMessage((HWND)lparam, + CB_GETITEMDATA, + (WPARAM)nPos, + 0); + if (!data) break; + sgdwCategoryBits = data->categorybits; + sgdwCategoryMask = data->categorymask; + UpdateGameList(window, GetDlgItem(window, IDC_GAMELIST), TRUE); + } + break; + } + } + break; + + case WM_CTLCOLORSTATIC: + if (GetWindowLong((HWND)lparam, GWL_ID) == IDC_TITLE) { + SetTextColor((HDC) wparam, RGB(0xff, 0xff, 0x00)); + return (BOOL) GetStockObject(NULL_BRUSH); + } + break; + + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + + case WM_TIMER: + if (sbSecondTimerActive) { + SDlgKillTimer(window, 2); + sbSecondTimerActive = FALSE; + } + + //### PATCH MM 2/4/97 + //UpdateGameList(window, GetDlgItem(window, IDC_GAMELIST), uiparams->programdata->selectioncriteria, FALSE); + UpdateGameLags(GetDlgItem(window, IDC_GAMELIST)); + //### END + break; + + case WM_DRAWITEM: + return JoinDrawItem(uiparams,message,window,wparam,lparam); + + case WM_DESTROY: + DestroyArtwork(window); + + if (sghFilterCombo) { + int nItems = SendMessage(sghFilterCombo,CB_GETCOUNT,0,0); + while(nItems--) { + CATEGORYDATAPTR data = + (CATEGORYDATAPTR)SendMessage(sghFilterCombo, + CB_GETITEMDATA, + (WPARAM)nItems, + 0); + if (data) FREE(data); + } + } + + //### PATCH MM 2/4/97 + //SDlgKillTimer(window, 1); + + if (sbSecondTimerActive) + SDlgKillTimer(window, 2); + + if (shCustomFont) { + DeleteObject(shCustomFont); + shCustomFont = NULL; + } + break; + + case WM_INITDIALOG: { + HWND hWndGameList; + RECT rect; + + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + uiparams = (UIPARAMSPTR)lparam; + + sbSecondTimerActive = TRUE; + + LoadArtwork(window, uiparams->interfacedata->artcallback); + + hWndGameList = GetDlgItem(window, IDC_GAMELIST); + ScrollbarLink(hWndGameList, GetDlgItem(window, IDC_SCROLLBAR)); + + //### MM Diablo Patch #2 3/21/97 + //### Added category support + // DML 10/16/97 + // Made "cancel" out of category callback (filter) possible + if (uiparams->interfacedata->categorycallback && + !uiparams->interfacedata-> + categorycallback(FALSE, + uiparams->programdata, + uiparams->playerdata, + uiparams->interfacedata, + uiparams->versiondata, + &sgdwCategoryBits, + &sgdwCategoryMask)) + SDlgEndDialog(window, FALSE); + + if (uiparams->interfacedata->categorylistcallback && + NULL != (sghFilterCombo = GetDlgItem(window,IDC_FILTER))) + { + uiparams->interfacedata->categorylistcallback(uiparams->playerdata, + JoinAddCategory); + SendMessage(sghFilterCombo,CB_SETCURSEL,0,0); + SendMessage(window, + WM_COMMAND, + MAKEWPARAM(IDC_FILTER,CBN_SELCHANGE), + (LPARAM)sghFilterCombo); + // CBN_SELCHANGE will cause a call to UpdateGameList + } + else { + sghFilterCombo = NULL; + UpdateGameList(window, hWndGameList, TRUE); + } + + //### PATCH MM 2/4/97 + //### Moved timer stuff below first UpdateGameList() call. + //### Eliminated 10 second timer. + //SDlgSetTimer(window,1,10000,NULL); // Poll for game list every 10 seconds + //SDlgSetTimer(window,2,1000,NULL); // One Shot One Second timer (so we can get latency info on games) + + SDlgSetTimer(window, 2, 3000,NULL); // Update latencies after 3 seconds + //### END + + // SET TAB STOPS FOR LIST BOX WIDE ENOUGH TO HIDE ALL TABBED TEXT + GetClientRect(hWndGameList,&rect); + SendMessage(hWndGameList,LB_SETTABSTOPS,1,(LPARAM) &rect.right); + + // Set the height of the games list box items (so lines don't overlap) + SendMessage(hWndGameList, LB_SETITEMHEIGHT, 0, 20); + + shCustomFont = InitCustomFonts(window); + return 1; + } + + } + + return SDlgDefDialogProc(window,message,wparam,lparam); + +} diff --git a/src/Storm/SOURCE/BATTLE/LOGON.CPP b/src/Storm/SOURCE/BATTLE/LOGON.CPP new file mode 100644 index 0000000..61b7f0d --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/LOGON.CPP @@ -0,0 +1,461 @@ +/**************************************************************************** +* +* Logon.CPP +* battle.net user interface functions +* +* By Dan Liebgold +* +***/ + +#include "pch.h" +#pragma hdrstop + +#include + +extern HWND ghWndUiMainParent; + +//=========================================================================== +#define MAX_NAME_LEN 30 +#define MAX_PASS_LEN 8 + +static LPBYTE sgBkgBmp; +static LPBYTE sgNewBkgBmp; +static LPBYTE sgButtonBmp; +static SIZE sgButtonSize; +static LPBYTE sgMedBtnBmp; +static SNETUIDATAPTR sgpInterfacedata; +static TCHAR sgszNewName[256]; +static TCHAR sgszPassword[256]; + +#define PLAYSELECTSND \ + if (sgpInterfacedata->soundcallback) \ + sgpInterfacedata->soundcallback(PROVIDERID, \ + SNET_SND_SELECTITEM, \ + 0) + + +//=========================================================================== +static void NewLoadArtwork(HWND window, SNETGETARTPROC artcallback) { + int btn_ids[] = { + IDOK, + IDCANCEL, + 0 + }; + + SIZE bgSize; + + UiLoadArtwork( + artcallback, + window, + NULL, + SNET_ART_BATTLE_NEW_ACCOUNT_BKG, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TRUE, + FALSE, + &sgNewBkgBmp, + &bgSize); + + SDlgSetControlBitmaps(window, + btn_ids, + NULL, + sgButtonBmp, + &sgButtonSize, + SDLG_ADJUST_VERTICAL); +} + +//=========================================================================== +static BOOL CheckPassword(HWND window) { + TCHAR szPass2[256]; + + SendMessage(GetDlgItem(window,IDC_PASS1), + WM_GETTEXT, + (WPARAM)sizeof(sgszPassword), + (LPARAM)sgszPassword); + SendMessage(GetDlgItem(window,IDC_PASS2), + WM_GETTEXT, + (WPARAM)sizeof(szPass2), + (LPARAM)szPass2); + + if (_tcscmp(sgszPassword,szPass2)) return FALSE; + return TRUE; +} + +//=========================================================================== +static BOOL CALLBACK NewDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) +{ + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: { + SendMessage(GetDlgItem(window,IDC_NAME), + WM_GETTEXT, + (WPARAM)sizeof(sgszNewName), + (LPARAM)sgszNewName); + + PLAYSELECTSND; + + if (CheckPassword(window)) { + SDlgEndDialog(window,TRUE); + return 0; + } + + char szPassErr[256]; + LoadString(global_hinstance, + IDS_PASSWORD_MISMATCH, + szPassErr, + sizeof(szPassErr)); + + UiMessageBox(sgpInterfacedata->messageboxcallback, + window, + szPassErr, + "", + MB_OK|MB_ICONWARNING); + break; + } + + case IDCANCEL: + PLAYSELECTSND; + SDlgEndDialog(window,FALSE); + break; + + + case IDC_PASS2: + if (HIWORD(wparam) == EN_CHANGE) { + int len = 0; + len += SendMessage(GetDlgItem(window, IDC_NAME), + WM_GETTEXTLENGTH, + 0,0); + len += SendMessage(GetDlgItem(window, IDC_PASS1), + WM_GETTEXTLENGTH, + 0,0); + len += SendMessage((HWND)lparam, + WM_GETTEXTLENGTH, + 0,0); + EnableWindow(GetDlgItem(window, IDOK), len); + } + break; + + } + break; + + case WM_DESTROY: + if (sgNewBkgBmp) { + FREE(sgNewBkgBmp); + sgNewBkgBmp = NULL; + } + break; + + case WM_INITDIALOG: + NewLoadArtwork(window, sgpInterfacedata->artcallback); + HWND name = GetDlgItem(window, IDC_NAME); + SetFocus(name); + SendMessage(name, EM_LIMITTEXT, MAX_NAME_LEN - 1, 0); + + EnableWindow(GetDlgItem(window, IDOK), FALSE); + + return 0; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//=========================================================================== +static void DestroyArtwork (HWND window) { + if (sgBkgBmp) { + FREE(sgBkgBmp); sgBkgBmp = NULL; + } + if (sgButtonBmp) { + FREE(sgButtonBmp); sgButtonBmp = NULL; + } + if (sgMedBtnBmp) { + FREE(sgMedBtnBmp); sgMedBtnBmp = NULL; + } +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window, SNETGETARTPROC artcallback) { + int btn_ids[] = { + IDOK, + IDCANCEL, + 0 + }; + + int static_txt[] = { + IDC_TITLE, + 0 + }; + + SIZE bgSize; + SIZE medBtnSize; + + UiLoadArtwork( + artcallback, + window, + NULL, + SNET_ART_BATTLE_LOGIN_BKG, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TRUE, + FALSE, + &sgBkgBmp, + &bgSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BUTTON_XSML, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgButtonBmp, + &sgButtonSize); + + UiLoadArtwork( + artcallback, + GetDlgItem(window,IDS_NEWACCOUNT), + NULL, + SNET_ART_BUTTON_MED, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgMedBtnBmp, + &medBtnSize); + + SDlgSetControlBitmaps (window,btn_ids,NULL,sgButtonBmp,&sgButtonSize,SDLG_ADJUST_VERTICAL); + return 1; +} + +//=========================================================================== +static LPBYTE LogonGetNames(LPCTSTR key, LPCTSTR value, DWORD *pBytes) { + LPBYTE buffer = NULL; + DWORD bytesread = 0; + DWORD datatype = REG_MULTI_SZ; + DWORD dwNameLen = pBytes ? *pBytes : 0; + LONG lError; + for (int iter = 0; iter < 2; ++iter) { + HKEY keyhandle; + if (ERROR_SUCCESS == (lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + key, + 0, + KEY_READ, + &keyhandle))) + { + RegQueryValueEx(keyhandle, + value, + 0, + &datatype, + buffer, + &bytesread); + RegCloseKey(keyhandle); + if (!buffer) buffer = (LPBYTE)ALLOCZERO(bytesread + dwNameLen + 2); + } + else { + + } + } + if (pBytes) *pBytes = bytesread; + return buffer; +} + +//=========================================================================== +static void LogonRememberName(LPCSTR szName) { + TCHAR key[MAX_PATH]; + DWORD dwNameLen = _tcslen(szName); + BOOL success = 0; + + SRegGetBaseKey(SREG_FLAG_BATTLENET,key,MAX_PATH); + _tcscat(key,TEXT("Characters")); + TCHAR valuename[MAX_PATH] = TEXT("Names"); + + DWORD bytesread = _tcslen(szName); + LPBYTE buffer = LogonGetNames(key,valuename,&bytesread); + + if (!buffer) { + buffer = (LPBYTE)ALLOCZERO(dwNameLen + 2); + *buffer = 0; + } + + TCHAR *pszTemp = (TCHAR*)buffer,*pszName; + while (*pszTemp) { + pszName = pszTemp; + if (!_tcscmp(szName,pszName)) + goto REMEMBER_EXIT; // name is already there + pszTemp += _tcslen(pszName) + 1; + } + + // Add the name to front of list + memmove(buffer + dwNameLen + 1, buffer, bytesread); + _tcscpy((TCHAR*)buffer,szName); + *(buffer + dwNameLen) = 0; + + // Write the buffer back to the registry + HKEY keyhandle; + DWORD disposition; + if (!RegCreateKeyEx(HKEY_LOCAL_MACHINE, + key, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_WRITE, + (LPSECURITY_ATTRIBUTES)NULL, + &keyhandle, + &disposition)) { + success |= !RegSetValueEx(keyhandle, + valuename, + 0, + REG_MULTI_SZ, + (const BYTE *)buffer, + bytesread + dwNameLen + 2); + RegCloseKey(keyhandle); + } +REMEMBER_EXIT: + FREE(buffer); +} + + +//=========================================================================== +static void LogonGetNames(HWND combo) { + TCHAR key[MAX_PATH]; + + SRegGetBaseKey(SREG_FLAG_BATTLENET,key,MAX_PATH); + _tcscat(key,TEXT("Characters")); + TCHAR valuename[MAX_PATH] = TEXT("Names"); + + DWORD bytesread = 0; + LPBYTE buffer = LogonGetNames(key,valuename,&bytesread); + + if (!buffer) return; + + TCHAR *pszName = (TCHAR*)buffer; + while (*pszName) { + SendMessage(combo,CB_ADDSTRING,0,(LPARAM)pszName); + pszName += _tcslen(pszName) + 1; + } + + // select the first name + SendMessage(combo,CB_SETCURSEL,0,0); + FREE(buffer); +} + + +//=========================================================================== +BOOL CALLBACK LogonDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: + PLAYSELECTSND; + + TCHAR szName[MAX_NAME_LEN]; + TCHAR szPass[MAX_PASS_LEN]; + SendDlgItemMessage(window, IDC_COMBO_NAME, WM_GETTEXT, MAX_NAME_LEN, (LPARAM)(LPCSTR)szName); + SendDlgItemMessage(window, IDC_EDIT_PASSWORD, WM_GETTEXT, MAX_PASS_LEN, (LPARAM)(LPCSTR)szPass); + + DWORD errorcode; + if (SrvLogon (szName,szPass, &errorcode)) { + LogonRememberName(szName); + SDlgEndDialog(window, 1); + return 0; + } + + SDlgEndDialog(window, 0); + return 0; + + case IDCANCEL: + PLAYSELECTSND; + SDlgEndDialog(window, 0); + return 0; + + case IDS_NEWACCOUNT: + PLAYSELECTSND; + BOOL bRes; + bRes = SDlgDialogBox(global_hinstance, + TEXT("DIALOG_NEW_ACCOUNT"), + window, + (DLGPROC)NewDialogProc); + if (bRes) { + HWND combo = GetDlgItem(window,IDC_COMBO_NAME); + int nPos = SendMessage(combo, + CB_ADDSTRING, + 0, + (LPARAM)sgszNewName); + SendMessage(combo,CB_SETCURSEL,(WPARAM)nPos,0); + SendMessage(window, + WM_COMMAND, + MAKEWPARAM(IDC_COMBO_NAME,CBN_SELCHANGE), + (LPARAM)combo); + } + return 0; + + case IDC_COMBO_NAME: + if (HIWORD(wparam) == CBN_EDITCHANGE) { + EnableWindow( + GetDlgItem(window, IDOK), + (BOOL)SendMessage((HWND)LOWORD(lparam), WM_GETTEXTLENGTH, 0, 0)); + } + return 0; + } + break; + + case WM_CTLCOLORSTATIC: + if (GetWindowLong((HWND)lparam, GWL_ID) == IDC_TITLE) { + SetTextColor((HDC) wparam, RGB(0xff, 0xff, 0x00)); + return (BOOL) GetStockObject(NULL_BRUSH); + } + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + case WM_DESTROY: + ghWndUiMainParent = NULL; + + UiVidFadeOut(DEFAULT_STEPS*2); // Note that VidFadeOut also erase the screen + + ShowCursor(FALSE); // Leave cursor off + UiVidFade(1,1); // restore palette for parent window + + DestroyArtwork(window); + break; + + + case WM_INITDIALOG: + ghWndUiMainParent = window; + + sgpInterfacedata = (SNETUIDATAPTR) lparam; + if (sgpInterfacedata->artcallback) + LoadArtwork(window, sgpInterfacedata->artcallback); + EnableWindow(GetDlgItem(window, IDOK), FALSE); + + HWND namecombo = GetDlgItem(window, IDC_COMBO_NAME); + SetFocus(namecombo); + SendMessage(namecombo, CB_LIMITTEXT, MAX_NAME_LEN - 1, 0); + + LogonGetNames(namecombo); + + UiLoadCursors(window, sgpInterfacedata); + + UiVidFade(1,1); + return 0; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + diff --git a/src/Storm/SOURCE/BATTLE/MESSAGE.CPP b/src/Storm/SOURCE/BATTLE/MESSAGE.CPP new file mode 100644 index 0000000..6ffd4f1 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/MESSAGE.CPP @@ -0,0 +1,31 @@ +/**************************************************************************** +* +* message.cpp +* +* MessageBox routines. +* +* By Michael Morhaime +* +***/ + +#include "pch.h" + + + + +//**************************************************************************** +BOOL UiMessageBox(SNETMESSAGEBOXPROC messageboxcallback, HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) { + BOOL bResult; + + // Make sure we have a visible cursor for the message box. + ShowCursor(TRUE); + + if (messageboxcallback) + bResult = messageboxcallback(hWnd, lpText, lpCaption, uType); + else + bResult = MessageBox(SDrawGetFrameWindow(), lpText, lpCaption, uType); + + ShowCursor(FALSE); + + return bResult; +} diff --git a/src/Storm/SOURCE/BATTLE/PCH.H b/src/Storm/SOURCE/BATTLE/PCH.H new file mode 100644 index 0000000..9a357d9 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/PCH.H @@ -0,0 +1,19 @@ +#define OEMRESOURCE +#define STRICT +#define SDLG_USE_INCLUSIVE_RECTS +#define STRANS_USE_INCLUSIVE_RECTS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "battle.h" +#include "bnetart.h" +#include "chat.h" +#include "rasmgr.h" +#include "resource.h" +#include "string.h" diff --git a/src/Storm/SOURCE/BATTLE/PROGRESS.CPP b/src/Storm/SOURCE/BATTLE/PROGRESS.CPP new file mode 100644 index 0000000..d30441d --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/PROGRESS.CPP @@ -0,0 +1,309 @@ +//**************************************************************************** +// Progress.cpp +// Diablo UI progress bar popup dialog +// +// By Frank Pearce +// created 9.26.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + #define PROGRESS_TIMER_ID 1 + #define MILLISEC_PER_SEC 1000 + #define CALLS_PER_SEC 20 + #define USER_DELAY (MILLISEC_PER_SEC / sgCallsPerSec) + #define DEFAULT_DELAY (MILLISEC_PER_SEC / CALLS_PER_SEC) + + #define FILL_X 0 + #define FILL_Y 0 + + static LPBYTE sgBgBmp = NULL; + static LPBYTE sgBtnBmp = NULL; + + // the progress bar background + static LPBYTE sgProgBgBmp = NULL; + static SIZE sgProgBgSize; + + // the fill image for the progress bar + static LPBYTE sgProgFillBmp = NULL; + static SIZE sgProgFillSize; + + // the current image based on percent complete + static LPBYTE sgProgBmp = NULL; + static SIZE sgProgSize; + + static BOOL sgAbortable; + static DWORD sgCallsPerSec; + static PROGRESSFCN sgProgressFcn; + static sgszProgressText[256]; + + +//**************************************************************************** +//**************************************************************************** +static void ProgressDraw(HWND window, int percent) { + RECT rect; + HWND child = GetDlgItem(window, IDC_UIGENERIC_PROGRESS); + + if (!sgProgBmp || !sgProgBgBmp) + return; + + // Bound percent + if (percent > 100) + percent = 100; + if (percent < 0) + percent = 0; + + + // draw the bg + SBltROP3( + sgProgBmp, + sgProgBgBmp, + sgProgSize.cx, + sgProgSize.cy, + sgProgSize.cx, + sgProgBgSize.cx, + NULL, + SRCCOPY + ); + + // draw the fill + SBltROP3( + sgProgBmp + (FILL_Y * sgProgSize.cx) + FILL_X, + sgProgFillBmp, + ((sgProgSize.cx - (2 * FILL_X)) * percent) / 100, + sgProgSize.cy - (2 * FILL_Y), + sgProgSize.cx, + sgProgFillSize.cx, + NULL, + SRCCOPY + ); + + // invalidate the region + GetWindowRect(child, &rect); + ScreenToClient(window, (LPPOINT)&rect.left); + ScreenToClient(window, (LPPOINT)&rect.right); + InvalidateRect(window, &rect, FALSE); +} + + +//**************************************************************************** +//**************************************************************************** +static void ProgressDestroy(HWND window) { + if (sgBgBmp) { + FREE(sgBgBmp); + sgBgBmp = NULL; + } + if (sgBtnBmp) { + FREE(sgBtnBmp); + sgBtnBmp = NULL; + } + if (sgProgBgBmp) { + FREE(sgProgBgBmp); + sgProgBgBmp = NULL; + } + if (sgProgFillBmp) { + FREE(sgProgFillBmp); + sgProgFillBmp = NULL; + } + if (sgProgBmp) { + FREE(sgProgBmp); + sgProgBmp = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ProgressInit(HWND window, SNETGETARTPROC artcallback) { + HWND child; + RECT rect; + SIZE btnsize; + int BtnIDs[] = { IDCANCEL, 0 }; + + if (sgCallsPerSec) + SDlgSetTimer(window,PROGRESS_TIMER_ID,USER_DELAY,NULL); + else + SDlgSetTimer(window,PROGRESS_TIMER_ID,DEFAULT_DELAY,NULL); + + + // load ctrl/dlg bmps + UiLoadArtwork( + artcallback, + window, + GetParent(window), + SNET_ART_POPUPBACKGROUND_SML, + TEXT("Popup"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgBgBmp, + NULL + ); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_BUTTON_SML, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgBtnBmp, + &btnsize); + + SDlgSetControlBitmaps (window, BtnIDs, NULL, sgBtnBmp, &btnsize, SDLG_ADJUST_VERTICAL); + + + // load progress bar textures + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_PROGRESS_BACKGROUND, + 0, + 0, + 0, + FALSE, + FALSE, + &sgProgBgBmp, + &sgProgBgSize); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_PROGRESS_FILLER, + 0, + 0, + 0, + FALSE, + FALSE, + &sgProgFillBmp, + &sgProgFillSize); + + + // alloc/create a bitmap for the progress indicator + child = GetDlgItem(window, IDC_UIGENERIC_PROGRESS); + GetClientRect(child, &rect); + + sgProgBmp = (LPBYTE) ALLOC(rect.right * rect.bottom); + sgProgSize.cx = rect.right; + sgProgSize.cy = rect.bottom; + + SDlgSetBitmap( + child, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + sgProgBmp, + NULL, + rect.right, + rect.bottom + ); + ProgressDraw(window, 0); + + // set the text describing what progress is being monitored + child = GetDlgItem(window, IDC_PROGRESS_TEXT); + SetWindowText(child, (LPCSTR)sgszProgressText); + + // show/hide cancel button based on abortable flag + child = GetDlgItem(window, IDCANCEL); + ShowWindow(child, (sgAbortable ? SW_SHOWNORMAL : SW_HIDE)); + EnableWindow(child, sgAbortable); +} + + +//**************************************************************************** +//**************************************************************************** +static void ProgressTimer(HWND window) { + int percent = 0; + + if (sgProgressFcn) + percent = sgProgressFcn(); + + ProgressDraw(window, percent); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK ProgressDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + static SNETUIDATAPTR interfacedata; + switch (message) { + + case WM_COMMAND: + if (LOWORD(wparam) == IDCANCEL) { + SrvCancel(); + SDlgEndDialog(window, 0); + return 0; + } + break; + + case WM_DESTROY: + SDlgKillTimer(window, PROGRESS_TIMER_ID); + ProgressDestroy(window); + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + case WM_INITDIALOG: + interfacedata = (SNETUIDATAPTR) lparam; + ProgressInit(window, interfacedata->artcallback); + return 1; + + case WM_TIMER: + ProgressTimer(window); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +HWND UiModelessProgressDialog(SNETUIDATAPTR interfacedata, + LPCSTR progresstext, + BOOL abortable, + PROGRESSFCN progressfcn, + DWORD callspersec +) { + sgProgressFcn = progressfcn; + sgAbortable = abortable; + sgCallsPerSec = callspersec; + + if (strlen(progresstext) < sizeof(sgszProgressText)) + strcpy((LPSTR)sgszProgressText, progresstext); + + if (!interfacedata) + return NULL; + + return SDlgCreateDialogParam( + global_hinstance, + TEXT("DIALOG_PROGRESS"), + interfacedata->parentwindow, + ProgressDialogProc, + (LPARAM) interfacedata + ); + +} diff --git a/src/Storm/SOURCE/BATTLE/RASMGR.CPP b/src/Storm/SOURCE/BATTLE/RASMGR.CPP new file mode 100644 index 0000000..3843c18 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/RASMGR.CPP @@ -0,0 +1,240 @@ +/**************************************************************************** +* +* RASMGR.CPP +* Remote Access Service Connection Manager +* +* By Jeff Strain (12/9/96) +* +***/ + +#include "pch.h" + +#define MAXACTIVECONNECTIONS 10 + +typedef DWORD (CALLBACK *RASHANGUP)(HRASCONN); +typedef DWORD (CALLBACK *RASENUMCONN)(LPRASCONN, LPDWORD, LPDWORD); +typedef DWORD (CALLBACK *RASGETSTATUS)(HRASCONN, LPRASCONNSTATUS); + +static HRASCONN sg_ahActiveConn[MAXACTIVECONNECTIONS] = {0}; +static HINSTANCE sg_hRasDLL = NULL; +static RASENUMCONN sg_pRasEnumConnections = NULL; +static RASHANGUP sg_pRasHangUp = NULL; +static RASGETSTATUS sg_pRasGetConnectStatus = NULL; + +/**************************************************************************** +* +* Private Functions +* +***/ + +// GETS A SAFE RASCONN STRUCTURE. IT IS UP TO THE CALLING FUNCTION TO +// FREE THE STRUCTURE WHEN IT IS DONE WITH IT! +static LPRASCONN WINAPI InternalRasEnumConnections(LPDWORD dwConnections) +{ + LPRASCONN lpRasConn = NULL; + DWORD dwBytes; + DWORD dwReturn; + + // FILL OUT A SINGLE RASCONN STRUCTURE + dwBytes = sizeof(RASCONN); + // LOOP UNTIL WE HAVE ALLOCATED A LARGE ENOUGH BUFFER TO HOLD ALL + // ACTIVE RAS CONNECTIONS + do { + if (lpRasConn) + LocalFree(lpRasConn); + lpRasConn = (LPRASCONN) LocalAlloc(LPTR, dwBytes); + ASSERT(lpRasConn); + if (!lpRasConn) + return NULL; + + lpRasConn[0].dwSize = sizeof(RASCONN); + dwReturn = sg_pRasEnumConnections(lpRasConn, &dwBytes, dwConnections); + + if (!(!dwReturn || dwReturn == ERROR_BUFFER_TOO_SMALL)) { + if (lpRasConn) + LocalFree(lpRasConn); + return NULL; + } + } while (dwReturn == ERROR_BUFFER_TOO_SMALL); + + return lpRasConn; +} + +/**************************************************************************** +* +* Public Session Management Functions +* +***/ + +// SHOULD BE CALLED ONE TIME ONLY AT STARTUP. STORES ALL ACTIVE +// RAS CONNECTIONS AND USES THIS AS A FILTER FOR ENUMNEWCALLS() +BOOL WINAPI InitRASManager() +{ + LPRASCONN lpRasConn = NULL; + DWORD dwConnections; + + // MANUALLY LOAD RAS DLL SINCE SYSTEMS WITHOUT DIALUP NETWORKING + // INSTALLED WON'T HAVE IT. + if (!sg_hRasDLL) { + sg_hRasDLL = LoadLibrary(TEXT("rasapi32")); + if (!sg_hRasDLL) + return FALSE; + } +#ifdef _UNICODE + sg_pRasEnumConnections = + (RASENUMCONN)GetProcAddress(sg_hRasDLL, TEXT("RasEnumConnectionsW")); + sg_pRasHangUp = + (RASHANGUP)GetProcAddress(sg_hRasDLL, TEXT("RasHangUpW")); + sg_pRasGetConnectStatus = + (RASGETSTATUS)GetProcAddress(sg_hRasDLL, TEXT("RasGetConnectStatusW")); +#else + sg_pRasEnumConnections = + (RASENUMCONN)GetProcAddress(sg_hRasDLL, TEXT("RasEnumConnectionsA")); + sg_pRasHangUp = + (RASHANGUP)GetProcAddress(sg_hRasDLL, TEXT("RasHangUpA")); + sg_pRasGetConnectStatus = + (RASGETSTATUS)GetProcAddress(sg_hRasDLL, TEXT("RasGetConnectStatusA")); +#endif + ASSERT(sg_pRasEnumConnections && sg_pRasHangUp && sg_pRasGetConnectStatus); + if (!(sg_pRasEnumConnections && sg_pRasHangUp && sg_pRasGetConnectStatus)) + return FALSE; + + lpRasConn = InternalRasEnumConnections(&dwConnections); + if (!lpRasConn) + return FALSE; + + for (DWORD i = 0; i < min(dwConnections, MAXACTIVECONNECTIONS); i++) + sg_ahActiveConn[i] = lpRasConn[i].hrasconn; + if (i < MAXACTIVECONNECTIONS) + sg_ahActiveConn[i] = NULL; + + if (lpRasConn) + LocalFree(lpRasConn); + + return TRUE; +} + +//=========================================================================== +DWORD WINAPI GetNumActiveRASConnections() +{ + LPRASCONN lpRasConn = NULL; + DWORD dwConnections; + + if (!sg_hRasDLL) + return 0; + + lpRasConn = InternalRasEnumConnections(&dwConnections); + ASSERT(lpRasConn); + if (!lpRasConn) + return 0; + + if (lpRasConn) + LocalFree(lpRasConn); + + return dwConnections; +} + +//=========================================================================== +BOOL WINAPI EnumNewRASConnections(LPRASENUMCALLBACK lpCallback, + LPVOID lpContext) +{ + LPRASCONN lpRasConn = NULL; + DWORD dwConnections; + + if (!sg_hRasDLL) + return FALSE; + + ASSERT(lpCallback); + if (!lpCallback) + return FALSE; + + lpRasConn = InternalRasEnumConnections(&dwConnections); + if (!lpRasConn) + return FALSE; + + // CALL THE CALLBACK WITH THE NAME AND HANDLE OF EACH RAS CONNECTION + BOOL bReturn; + for (DWORD i = 0; i < dwConnections; i++) { + for (DWORD j = 0; j < MAXACTIVECONNECTIONS; j++) { + if (!sg_ahActiveConn[j]) + break; + if (sg_ahActiveConn[j] == lpRasConn[i].hrasconn) + break; + } + if (j == MAXACTIVECONNECTIONS || !sg_ahActiveConn[j]) { + bReturn = lpCallback((LPCTSTR)lpRasConn[i].szEntryName, + (LPVOID)lpRasConn[i].hrasconn, lpContext); + if (bReturn) + break; + } + } + + if (lpRasConn) + LocalFree(lpRasConn); + + return TRUE; +} + +//=========================================================================== +BOOL WINAPI EnumActiveRASConnections(LPRASENUMCALLBACK lpCallback, + LPVOID lpContext) +{ + LPRASCONN lpRasConn = NULL; + DWORD dwConnections; + + if (!sg_hRasDLL) + return FALSE; + + ASSERT(lpCallback); + if (!lpCallback) + return FALSE; + + lpRasConn = InternalRasEnumConnections(&dwConnections); + ASSERT(lpRasConn); + if (!lpRasConn) + return FALSE; + + // CALL THE CALLBACK WITH THE NAME AND HANDLE OF EACH RAS CONNECTION + BOOL bReturn; + for (DWORD i = 0; i < dwConnections; i++) { + bReturn = lpCallback((LPCTSTR)lpRasConn[i].szEntryName, + (LPVOID)lpRasConn[i].hrasconn, lpContext); + if (bReturn) + break; + } + + if (lpRasConn) + LocalFree(lpRasConn); + + return TRUE; +} + +//=========================================================================== +// NOTE THAT THIS IS POTENTIALLY A BLOCKING CALL +BOOL WINAPI HangupRASConnection(LPVOID rasconn) +{ + DWORD dwReturn; + RASCONNSTATUS rcStatus; + HRASCONN hRasConn = (HRASCONN)rasconn; + + ASSERT(sg_hRasDLL); + if (!sg_hRasDLL) + return FALSE; + + ASSERT(hRasConn); + if (!hRasConn) + return FALSE; + + // HANGUP LINE + dwReturn = sg_pRasHangUp(hRasConn); + ASSERT(!dwReturn); + if (dwReturn) + return FALSE; + + // WAIT FOR STATE MACHINE TO RESET PORT PROPERLY + rcStatus.dwSize = sizeof(RASCONNSTATUS); + while (sg_pRasGetConnectStatus(hRasConn, &rcStatus) != ERROR_INVALID_HANDLE) + Sleep(0); + + return TRUE; +} diff --git a/src/Storm/SOURCE/BATTLE/RASMGR.H b/src/Storm/SOURCE/BATTLE/RASMGR.H new file mode 100644 index 0000000..5c6a127 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/RASMGR.H @@ -0,0 +1,41 @@ +#ifndef __RASMGR_H +#define __RASMGR_H + +/**************************************************************************** +* +* Session Management Functions +* +***/ + +// CALLBACK FOR EnumActiveRASConnections(). THE LPVOID RASHADLE +// PARAMETER SHOULD BE STORED AS AN OPAQUE POINTER AND PASSED +// TO HangupRASConnection(). THE FUNCTION SHOULD RETURN TRUE +// TO CONTINUE THE ENUMERATION, FALSE TO CANCEL. +typedef BOOL (APIENTRY *LPRASENUMCALLBACK)(LPCTSTR szEntryName, + LPVOID rashandle, + LPVOID lpContext); + +// INITIALIZES RAS MANAGER - CALL ONE TIME *BEFORE* DIALING +BOOL WINAPI InitRASManager(); + +// RETURNS THE NUMBER OF ACTIVE RAS CONNECTIONS +DWORD WINAPI GetNumActiveRASConnections(); + +// ENUMERATES ALL *ACTIVE* DIALUP CONNECTIONS. RETURN OF TRUE +// INDICATES THAT 0 - N CONNECTIONS WERE SUCCESSFULLY ENUMERATED, +// I.E. RETURN OF 0 DOES NOT INDICATE NO ACTIVE CONNECTIONS. +BOOL WINAPI EnumActiveRASConnections(LPRASENUMCALLBACK lpCallback, + LPVOID lpContext); + +// ENUMERATES ALL ACTIVE DIALUP CONNECTIONS THAT HAVE BEEN +// ESTABLISHED AFTER THE CALL TO InitRASManager(). RETURN OF TRUE +// INDICATES THAT 0 - N CONNECTIONS WERE SUCCESSFULLY ENUMERATED, +// I.E. RETURN OF 0 DOES NOT INDICATE NO ACTIVE CONNECTIONS. +BOOL WINAPI EnumNewRASConnections(LPRASENUMCALLBACK lpCallback, + LPVOID lpContext); + +// HANGS UP LINE. THIS FUNCTION WILL BLOCK UNTIL THE TAPI STATE +// MACHINE MANAGING THE COMM PORT HAS CLEANED UP THE PORT +BOOL WINAPI HangupRASConnection(LPVOID rashandle); + +#endif // __RASMGR_H diff --git a/src/Storm/SOURCE/BATTLE/RESOURCE.H b/src/Storm/SOURCE/BATTLE/RESOURCE.H new file mode 100644 index 0000000..f1ef531 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/RESOURCE.H @@ -0,0 +1,121 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by BATTLE.RC +// +#define IDD_DIALOG1 122 +#define ID_SCROLL_WINDOW 1000 +#define IDS_CHAT_HELP_RES 1000 +#define IDS_NAME_REQUIRED 1001 +#define IDC_AD 1001 +#define IDS_INVALID_ID 1002 +#define IDC_USERLIST 1003 +#define IDS_ASK_UPDATE 1003 +#define IDS_PREP_RESTART 1004 +#define IDC_CHATWINDOW 1005 +#define IDS_CHAT_JOIN_ROOM 1005 +#define IDC_CHATEDIT 1006 +#define IDS_CHAT_PLAYER_LEFT_ROOM 1006 +#define ID_CHATJOIN 1007 +#define IDS_CHAT_PLAYER_ENTERED_ROOM 1007 +#define ID_CHATCREATE 1008 +#define IDS_JOIN_FAILED 1008 +#define ID_SENDMSG 1009 +#define IDS_ERR_UNREACHABLE 1009 +#define ID_CHATLADDER 1009 +#define IDC_EDIT_NAME 1010 +#define IDS_BATTLENET 1010 +#define IDC_EDIT_PASSWORD 1011 +#define IDS_ERR_NOTRESPONDING 1011 +#define IDC_TYPE_PUBLIC 1012 +#define ID_CHAT_CHANNEL 1012 +#define IDS_ERR_UNABLETOUPGRADE 1012 +#define ID_CHATCHANNEL 1012 +#define IDC_TYPE_PRIVATE 1013 +#define IDS_ERR_DOWNLOADFAILED 1013 +#define IDS_DOWNLOADPROGRESS 1014 +#define IDS_WHISPER_FROM 1015 +#define IDS_WHISPER_TO 1016 +#define IDS_ERR_INVALIDBETAID 1017 +#define IDS_ERR_CANTWHISPER 1018 +#define IDS_CHANNEL_NAME_INVALID 1019 +#define IDC_COMBO1 1020 +#define IDC_CHAT_CHANNEL 1020 +#define IDS_FIRST_NASTY 1020 +#define IDC_COMBO_NAME 1020 +#define IDC_DIFFICULTY 1021 +#define IDS_NASTY0 1021 +#define IDC_EDIT1 1022 +#define IDS_NASTY1 1022 +#define IDC_GAMETYPE 1023 +#define IDS_NASTY2 1023 +#define IDC_PASS1 1023 +#define IDS_NASTY3 1024 +#define IDC_PASS2 1024 +#define IDS_NASTY4 1025 +#define IDS_NASTY5 1026 +#define IDC_LIST1 1027 +#define IDC_GAMELIST 1027 +#define IDS_LAST_NASTY 1027 +#define IDS_ERR_CHATNOTHINGTOSEND 1028 +#define IDC_STATIC_DESC 1029 +#define IDS_PROMPT_CREATECHANNEL 1029 +#define IDC_TITLE 1030 +#define IDS_CHANNEL_FULL 1030 +#define IDC_GAMEDESCRIPTION 1031 +#define IDS_CHANNEL_RESTRICTED 1031 +#define IDC_ANIMATE 1032 +#define IDS_ERR_BADCONNECTION 1032 +#define IDS_ERR_BADSERVICEPROVIDER 1033 +#define IDS_CHANNEL_FMT 1034 +#define ID_WHISPER 1035 +#define IDS_USERUNSQUELCHED_FMT 1035 +#define IDS_USERSQUELCHED_FMT 1036 +#define IDS_VERBOSE_FMT 1037 +#define IDC_EDIT_ID 1038 +#define IDS_NONVERBOSE_FMT 1038 +#define IDC_CHANNELLIST 1039 +#define IDS_ERR_NOWSOCK32 1039 +#define IDC_EDIT_ID2 1039 +#define IDC_LOGO_ANIMATE 1040 +#define IDS_QUERYBROWSEWEB 1040 +#define IDC_STATIC_TEXT 1041 +#define IDS_QUERYDISCONNECT 1041 +#define IDC_PROGRESS_TEXT 1042 +#define IDC_RADIO1 1042 +#define IDS_BROWSERERROR 1042 +#define IDC_UIGENERIC_PROGRESS 1043 +#define IDC_STATIC_DESC_HDR 1043 +#define IDS_ERR_HOST_UNREACHABLE 1043 +#define IDS_ERR_GAME_FULL 1044 +#define IDQUIT 1045 +#define IDS_ENTERPASSWORD 1045 +#define IDC_STATIC_CHANNEL 1046 +#define IDS_RENAMECHARACTER 1046 +#define IDS_ERR_INVALIDPASSWORD 1047 +#define IDC_SCROLLBAR1 1048 +#define IDS_TITLE_INVALIDPASSWORD 1048 +#define IDC_USERLIST_SCROLLBAR 1049 +#define IDC_MSGLIST_SCROLLBAR 1050 +#define ID_VERBOSE 1051 +#define IDC_SCROLLBAR 1052 +#define IDC_NEWACCOUNT 1054 +#define IDS_NEWACCOUNT 1055 +#define IDC_LOGIN_ATTR 1056 +#define IDESCAPE 1058 +#define IDC_CUSTOM_NAM 1058 +#define IDC_COMBO3 1061 +#define IDC_PROFILE 1062 +#define IDC_FILTER 1063 +#define IDC_NAME 1064 +#define IDS_PASSWORD_MISMATCH 1065 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1065 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SOURCE/BATTLE/SCRLLBAR.CPP b/src/Storm/SOURCE/BATTLE/SCRLLBAR.CPP new file mode 100644 index 0000000..63eebd2 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/SCRLLBAR.CPP @@ -0,0 +1,890 @@ +/*************************************************************************** +* +* scrllbar.cpp +* +* By Michael Morhaime +* +* Custom Scrollbar control used by listbox. +* +* +* +* NOTES: ScrollbarLink() must be called to setup the link between the scrollbar and the +* window that will receive notify messages. +* +* ListUpdateScrollbar() This routine should be called whenever the scroll position, +* scroll range, or page size changes. The scrollbar must +* be notified whenever the listbox generates LBN_SELCHANGE +* messages as they may be the result of a scroll. The scrollbar +* will query the listbox to get the appropriate information. +* You could also send the scrollbar SBM_SETSCROLLINFO messages +* manually if you wish. +* +* EditUpdateScrollbar() This is the equivalent of the above routine when the linked +* window is an Edittext control. +***/ + +#include "pch.h" + + + +#define NUM_ARROWS 4 // Number of arrows expected in art file (up/down) +#define REPEAT_RATE 100 // repeat every 100 millisec's + +static int sgnCreateCnt = 0; // Allow more than one scrollbar to share artwork +static LPBYTE sgBmpArrows = NULL; +static LPBYTE sgBmpThumb = NULL; +static LPBYTE sgBmpBar = NULL; + +static SIZE sgSizeArrows; +static SIZE sgSizeThumb; +static SIZE sgSizeBar; + +static int sgnArrowHgt; +static int sgnThumbHgt; +static int sgnBarHgt; + +static HWND sghPrevCapture; + +typedef struct _ScrollBmp { + LPBYTE data; + SIZE datasize; +} TSCROLLBMP, * PTSCROLLBMP; + +typedef struct _ScrollRects { + RECT rectArrowUp; + RECT rectArrowDown; + RECT rectThumb; + RECT rectBar; +} TSCROLLRECTS, * PTSCROLLRECTS; + +typedef struct _ScrollDrag { + union { + unsigned fModes; + struct _clicked { + unsigned ArrowUp :1; + unsigned ArrowDown :1; + unsigned PageUp :1; + unsigned PageDown :1; + unsigned Thumb :1; + } Clicked; + } dm; +} TSCROLLDRAG, * PTSCROLLDRAG; + +#define PROP_SCROLLBMP "ScrollBitmap" +#define PROP_SCROLLRECTS "ScrollRects" +#define PROP_SCROLLPARENT "ScrollParent" +#define PROP_SCROLLINFO "ScrollInfo" +#define PROP_SCROLLDRAG "ScrollDrag" + + +//**************************************************************************** +//**************************************************************************** +void ScrollbarLoadArtwork(SNETGETARTPROC artcallback) { + if (!sgnCreateCnt++) { + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_SCROLLBARARROWS, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgBmpArrows, + &sgSizeArrows); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_SCROLLTHUMB, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgBmpThumb, + &sgSizeThumb); + + UiLoadArtwork( + artcallback, + NULL, + NULL, + SNET_ART_SCROLLBAR, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + FALSE, + FALSE, + &sgBmpBar, + &sgSizeBar); + + // Calculate pixel heights of components + sgnThumbHgt = sgSizeThumb.cy; + sgnArrowHgt = sgSizeArrows.cy/NUM_ARROWS; + sgnBarHgt = sgSizeBar.cy; + } + +} + +//**************************************************************************** +//**************************************************************************** +void ScrollbarDestroyArtwork(void) { + // Only Destroy if this if the only scrollbar currently using the artwork + if (--sgnCreateCnt) + return; + + if (sgBmpArrows) { + FREE(sgBmpArrows); + sgBmpArrows = NULL; + } + + if (sgBmpThumb) { + FREE(sgBmpThumb); + sgBmpThumb = NULL; + } + + if (sgBmpBar) { + FREE(sgBmpBar); + sgBmpBar = NULL; + } + +} +//**************************************************************************** +//**************************************************************************** +static BOOL ScrollbarCreate(HWND window) { + RECT rWnd; + PTSCROLLBMP pTBmp = NULL; + PTSCROLLRECTS pTRects = NULL; + LPSCROLLINFO pScrollInfo = NULL; + PTSCROLLDRAG pScrollDrag = NULL; + + + if (!sgBmpArrows || !sgBmpThumb | !sgBmpBar) + return 0; + + GetClientRect(window, &rWnd); + pTBmp = (PTSCROLLBMP) ALLOC(sizeof(TSCROLLBMP)); + if (!pTBmp) + return 0; + + pTBmp->data = (LPBYTE) ALLOC(rWnd.right*rWnd.bottom); + if (!pTBmp->data) { + FREE(pTBmp); + return 0; + } + + ZeroMemory(pTBmp->data, rWnd.right*rWnd.bottom); + memset(pTBmp->data, 2, rWnd.right*rWnd.bottom); //xxx del + + pTBmp->datasize.cx = rWnd.right; + pTBmp->datasize.cy = rWnd.bottom; + SetProp(window, PROP_SCROLLBMP, (HANDLE) pTBmp); + + + SDlgSetBitmap( + window, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + pTBmp->data, + NULL, + rWnd.right, + rWnd.bottom + ); + + + // Initialize hit detection rects + pTRects = (PTSCROLLRECTS) ALLOC(sizeof(TSCROLLRECTS)); + if (!pTRects) + return 0; + + SetRect(&pTRects->rectArrowUp, 0, 0, rWnd.right, sgnArrowHgt); + SetRect(&pTRects->rectArrowDown, 0, rWnd.bottom - sgnArrowHgt, rWnd.right, rWnd.bottom); + SetRect(&pTRects->rectThumb, 0, sgnArrowHgt, rWnd.right, sgnArrowHgt + sgnThumbHgt); + SetRect(&pTRects->rectBar, 0, sgnArrowHgt, rWnd.right, rWnd.bottom - sgnArrowHgt); + SetProp(window, PROP_SCROLLRECTS, (HANDLE) pTRects); + + + pScrollInfo = (SCROLLINFO *)ALLOC(sizeof(SCROLLINFO)); + if (!pScrollInfo) + return 0; + ZeroMemory(pScrollInfo, sizeof(SCROLLINFO)); + pScrollInfo->cbSize = sizeof(SCROLLINFO); + SetProp(window, PROP_SCROLLINFO, (HANDLE) pScrollInfo); + + + pScrollDrag = (PTSCROLLDRAG)ALLOC(sizeof(TSCROLLDRAG)); + if (!pScrollDrag) + return 0; + ZeroMemory(pScrollDrag, sizeof(TSCROLLDRAG)); + SetProp(window, PROP_SCROLLDRAG, (HANDLE) pScrollDrag); + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static void ScrollbarDestroy(HWND window) { + PTSCROLLBMP pTBmp; + PTSCROLLRECTS pTRects; + PTSCROLLDRAG pScrollDrag; + SCROLLINFO *pScrollInfo; + + + pTBmp = (PTSCROLLBMP)RemoveProp(window, PROP_SCROLLBMP); + if (pTBmp) { + if (pTBmp->data) { + FREE(pTBmp->data); + } + FREE(pTBmp); + } + + pTRects = (PTSCROLLRECTS)RemoveProp(window, PROP_SCROLLRECTS); + if (pTRects) + FREE(pTRects); + + pScrollInfo = (SCROLLINFO *)RemoveProp(window, PROP_SCROLLINFO); + if (pScrollInfo) + FREE(pScrollInfo); + + pScrollDrag = (PTSCROLLDRAG)RemoveProp(window, PROP_SCROLLDRAG); + if (pScrollDrag) + FREE(pScrollDrag); + + RemoveProp(window, PROP_SCROLLPARENT); +} + +//**************************************************************************** +//**************************************************************************** +static void ScrollbarDraw (HWND window) { + PTSCROLLBMP pTBmp; + PTSCROLLRECTS pTRects; + + RECT r; + + pTBmp = (PTSCROLLBMP)GetProp(window, PROP_SCROLLBMP); + pTRects = (PTSCROLLRECTS)GetProp(window, PROP_SCROLLRECTS); + + if (!pTBmp || !pTRects) + return; + + // Draw Arrows + r = pTRects->rectArrowUp; + SBltROP3 ( + pTBmp->data + (r.top * pTBmp->datasize.cx) + r.left, + sgBmpArrows, + r.right - r.left, + r.bottom - r.top, + pTBmp->datasize.cx, + sgSizeArrows.cx, + NULL, + SRCCOPY + ); + + r = pTRects->rectArrowDown; + SBltROP3 ( + pTBmp->data + (r.top * pTBmp->datasize.cx) + r.left, + sgBmpArrows + (sgnArrowHgt*sgSizeArrows.cx), + r.right - r.left, + r.bottom - r.top, + pTBmp->datasize.cx, + sgSizeArrows.cx, + NULL, + SRCCOPY + ); + + RECT rSrc, rDst; + SetRect(&rSrc, 0, 0, pTBmp->datasize.cx, sgSizeBar.cy); + rDst = pTRects->rectBar; + + SBltROP3Tiled ( + pTBmp->data, + &rDst, + pTBmp->datasize.cx, + sgBmpBar, + &rSrc, + sgSizeBar.cx, + 0, + 0, + NULL, + SRCCOPY); + + r = pTRects->rectThumb; + SBltROP3 ( + pTBmp->data + (r.top * pTBmp->datasize.cx) + r.left, + sgBmpThumb, + r.right - r.left, + r.bottom - r.top, + pTBmp->datasize.cx, + sgSizeThumb.cx, + NULL, + SRCCOPY + ); +} + + +//**************************************************************************** +//**************************************************************************** +int MouseToScrollPos(POINT *pt, PTSCROLLRECTS pTRects, LPSCROLLINFO pScrollInfo) { + int nScrollRange; + int nPixRange; + int nScrollPos; + int y; + + + + nScrollRange = pScrollInfo->nMax - pScrollInfo->nMin; + if (nScrollRange == 0) + return 0; + + // Make sure we don't treat a negative y value as a large positive value. + y = (int)pt->y; + if (y < pTRects->rectBar.top) + y = pTRects->rectBar.top; + + nPixRange = pTRects->rectBar.bottom - pTRects->rectBar.top - sgnThumbHgt; + nScrollPos = (y - pTRects->rectBar.top) * nScrollRange / nPixRange; + nScrollPos += pScrollInfo->nMin; + + // bound scrollpos to scroll range + if (nScrollPos < pScrollInfo->nMin) + nScrollPos = pScrollInfo->nMin; + if (nScrollPos > pScrollInfo->nMax) + nScrollPos = pScrollInfo->nMax; + + return nScrollPos; +} + + +//**************************************************************************** +//**************************************************************************** +static void ScrollbarPaint (HWND window) { + PAINTSTRUCT ps; + HDC dc = BeginPaint(window,&ps); + + // PAINT THE BITMAP + SDlgDrawBitmap(window,SDLG_USAGE_BACKGROUND,(HRGN)0); + EndPaint(window,&ps); +} + + + +//**************************************************************************** +//**************************************************************************** +static void ScrollbarUpdate(HWND window) { + SCROLLINFO *pScrollInfo = (SCROLLINFO *) GetProp(window, PROP_SCROLLINFO); + PTSCROLLRECTS pTRects = (PTSCROLLRECTS) GetProp(window, PROP_SCROLLRECTS); + int nScrollRange, nPixRange; + int nNewPos; + + if (!pScrollInfo) + return; + + // Update Thumb position + nScrollRange = pScrollInfo->nMax - pScrollInfo->nMin; + if (nScrollRange == 0) { + ShowWindow(window, SW_HIDE); + return; + } + + nPixRange = pTRects->rectBar.bottom - pTRects->rectBar.top - sgnThumbHgt; + nNewPos = (pScrollInfo->nPos-pScrollInfo->nMin) * nPixRange / nScrollRange; + nNewPos += pTRects->rectBar.top; + if (nNewPos == pTRects->rectThumb.top) + return; + + OffsetRect(&pTRects->rectThumb, 0, nNewPos - pTRects->rectThumb.top); + ScrollbarDraw(window); + InvalidateRect(window, NULL, FALSE); +} + + +//**************************************************************************** +//**************************************************************************** +void ScrollDragThumb(HWND window, POINT *pt, PTSCROLLRECTS pTRects, LPSCROLLINFO pScrollInfo) { + int nTarget; + + // Position cursor in middle of thumb + pt->y -= sgnThumbHgt/2; + + // Move the thumb to where the mouse is. + if (pt->y < pTRects->rectBar.top) + nTarget = pTRects->rectBar.top; + else if (pt->y > pTRects->rectBar.bottom - sgnThumbHgt) + nTarget = pTRects->rectBar.bottom - sgnThumbHgt; + else + nTarget = pt->y; + + OffsetRect(&pTRects->rectThumb, 0, nTarget - pTRects->rectThumb.top); + ScrollbarDraw(window); + InvalidateRect(window, NULL, FALSE); //&pTRects->rectThumb, FALSE); +} + +//**************************************************************************** +//**************************************************************************** +static void ScrollbarScroll(HWND window, int nAmount) { + SCROLLINFO *pScrollInfo = (SCROLLINFO *) GetProp(window, PROP_SCROLLINFO); + int nPosSave; + + if (!pScrollInfo) + return; + + nPosSave = pScrollInfo->nPos; + pScrollInfo->nPos += nAmount; + if (pScrollInfo->nPos < pScrollInfo->nMin) + pScrollInfo->nPos = pScrollInfo->nMin; + if (pScrollInfo->nPos > pScrollInfo->nMax) + pScrollInfo->nPos = pScrollInfo->nMax; + + if (nPosSave != pScrollInfo->nPos) + ScrollbarUpdate(window); +} + + + +//**************************************************************************** +//**************************************************************************** +static BOOL ScrollbarSetPos(HWND window, int nPos, BOOL bRedraw) { + LPSCROLLINFO pScrollInfo = (LPSCROLLINFO) GetProp(window, PROP_SCROLLINFO); + int nPosSave; + + if (!pScrollInfo) + return 0; + + nPosSave = pScrollInfo->nPos; + pScrollInfo->nPos = nPos; + if (pScrollInfo->nPos < pScrollInfo->nMin) + pScrollInfo->nPos = pScrollInfo->nMin; + if (pScrollInfo->nPos > pScrollInfo->nMax) + pScrollInfo->nPos = pScrollInfo->nMax; + + if (nPosSave != pScrollInfo->nPos) { + ScrollbarUpdate(window); + return nPosSave; + } + + return 0; + +} + +//**************************************************************************** +//**************************************************************************** +static BOOL ScrollbarSetRange(HWND window, int nMin, int nMax) { + LPSCROLLINFO pScrollInfo = (LPSCROLLINFO) GetProp(window, PROP_SCROLLINFO); + int nSavePos; + + if (!pScrollInfo) + return 0; + + if (pScrollInfo->nMin == nMin && pScrollInfo->nMax == nMax) { + return 0; + } + + if (nMin == nMax && pScrollInfo->nMin != pScrollInfo->nMax) { + if (!(pScrollInfo->fMask & SIF_DISABLENOSCROLL)) + ShowWindow(window, SW_HIDE); + else + EnableWindow(window, FALSE); + } + else if (nMin != nMax && pScrollInfo->nMin == pScrollInfo->nMax) { + EnableWindow(window, TRUE); + ShowWindow(window, SW_SHOW); + } + + nSavePos = pScrollInfo->nPos; + pScrollInfo->nMin = nMin; + pScrollInfo->nMax = nMax; + if (pScrollInfo->nPos < pScrollInfo->nMin) + pScrollInfo->nPos = pScrollInfo->nMin; + if (pScrollInfo->nPos > pScrollInfo->nMax) + pScrollInfo->nPos = pScrollInfo->nMax; + ScrollbarUpdate(window); + return nSavePos; +} + +//**************************************************************************** +//**************************************************************************** +static BOOL ScrollbarSetInfo(HWND window, LPSCROLLINFO lpsi) { + LPSCROLLINFO pScrollInfo = (LPSCROLLINFO) GetProp(window, PROP_SCROLLINFO); + + if (!pScrollInfo) + return 0; + + if (lpsi->fMask & SIF_PAGE) + pScrollInfo->nPage = lpsi->nPage; + + if (lpsi->fMask & SIF_RANGE) + ScrollbarSetRange(window, lpsi->nMin, lpsi->nMax); + + if (lpsi->fMask & SIF_POS) + ScrollbarSetPos(window, lpsi->nPos, TRUE); + + + return pScrollInfo->nPos; +} + + +//**************************************************************************** +//**************************************************************************** +static void ScrollbarBtnDown(HWND window, int x, int y) { + PTSCROLLRECTS pTRects; + SCROLLINFO *pScrollInfo; + PTSCROLLDRAG pScrollDrag; + POINT pt; + HWND hWndParent; + int nNotify; + + // do hit detection + pTRects = (PTSCROLLRECTS) GetProp(window, PROP_SCROLLRECTS); + hWndParent = (HWND) GetProp(window, PROP_SCROLLPARENT); + pScrollInfo = (SCROLLINFO *) GetProp(window, PROP_SCROLLINFO); + pScrollDrag = (PTSCROLLDRAG) GetProp(window, PROP_SCROLLDRAG); + + if (!pTRects || !hWndParent || !pScrollInfo || !pScrollDrag) + return; + + + pt.x = x; + pt.y = y; + + // Capture the mouse until the user releases the button + if (window != GetCapture()) + sghPrevCapture = SetCapture(window); + else { + // Are we scrolling using the thumbnail? + if (pScrollDrag->dm.Clicked.Thumb) { + ScrollDragThumb(window, &pt, pTRects, pScrollInfo); + SendMessage( + hWndParent, + WM_VSCROLL, + MAKEWPARAM(SB_THUMBTRACK,MouseToScrollPos(&pt, pTRects, pScrollInfo)), + (LPARAM)window); + return; + } + } + + + + if (PtInRect(&pTRects->rectArrowUp, pt)) { + if (pScrollDrag->dm.fModes && !pScrollDrag->dm.Clicked.ArrowUp) + return; + + if (!pScrollDrag->dm.Clicked.ArrowUp) { + // Set repeat rate for scrolling, and set mode flag + SDlgSetTimer(window, 0, REPEAT_RATE, NULL); + pScrollDrag->dm.Clicked.ArrowUp = 1; + } + + ScrollbarScroll(window, -1); + nNotify = MAKEWPARAM(SB_LINEUP,0); + } + else if (PtInRect(&pTRects->rectArrowDown, pt)) { + if (pScrollDrag->dm.fModes && !pScrollDrag->dm.Clicked.ArrowDown) + return; + + if (!pScrollDrag->dm.Clicked.ArrowDown) { + // Set repeat rate for scrolling, and set mode flag + SDlgSetTimer(window, 0, REPEAT_RATE, NULL); + pScrollDrag->dm.Clicked.ArrowDown = 1; + } + + ScrollbarScroll(window, 1); + nNotify = MAKEWPARAM(SB_LINEDOWN,0); + } + else if (PtInRect(&pTRects->rectBar, pt)) { + if (PtInRect(&pTRects->rectThumb, pt)) { + if (!pScrollDrag->dm.fModes) { + // Thumb doesn't use timer, just set a flag, we'll get mousemove because of GetCapture() + pScrollDrag->dm.Clicked.Thumb = 1; + return; + } + } + else if (pt.y < pTRects->rectThumb.top) { + if (pScrollDrag->dm.fModes && !pScrollDrag->dm.Clicked.PageUp) + return; + + if (!pScrollDrag->dm.Clicked.PageUp) { + // Set repeat rate for scrolling, and set mode flag + SDlgSetTimer(window, 0, REPEAT_RATE, NULL); + pScrollDrag->dm.Clicked.PageUp = 1; + } + + ScrollbarScroll(window, -(int)pScrollInfo->nPage); + nNotify = MAKEWPARAM(SB_THUMBPOSITION,pScrollInfo->nPos); + } + else { + if (pScrollDrag->dm.fModes && !pScrollDrag->dm.Clicked.PageDown) + return; + + if (!pScrollDrag->dm.Clicked.PageDown) { + // Set repeat rate for scrolling, and set mode flag + SDlgSetTimer(window, 0, REPEAT_RATE, NULL); + pScrollDrag->dm.Clicked.PageDown = 1; + } + + // page down + ScrollbarScroll(window, pScrollInfo->nPage); + nNotify = MAKEWPARAM(SB_THUMBPOSITION,pScrollInfo->nPos); + } + } + else { + // User didn't click in any hot regions + return; + } + + + // Notify attached window what to do + SendMessage(hWndParent, WM_VSCROLL, nNotify, (LPARAM) window); +} + +//**************************************************************************** +//**************************************************************************** +static void ScrollbarBtnUp(HWND window, int x, int y) { + // End capture, + if (window == GetCapture()) { + PTSCROLLDRAG pScrollDrag; + LPSCROLLINFO pScrollInfo; + PTSCROLLRECTS pTRects; + HWND hWndParent; + + pScrollDrag = (PTSCROLLDRAG) GetProp(window, PROP_SCROLLDRAG); + pScrollInfo = (LPSCROLLINFO) GetProp(window, PROP_SCROLLINFO); + pTRects = (PTSCROLLRECTS) GetProp(window, PROP_SCROLLRECTS); + hWndParent = (HWND) GetProp(window, PROP_SCROLLPARENT); + + ReleaseCapture(); + if (sghPrevCapture) SetCapture(sghPrevCapture); + SDlgKillTimer(window, 0); + + if (!pScrollDrag || !pScrollInfo || !pTRects || !hWndParent) + return; + + if (pScrollDrag->dm.Clicked.Thumb) { + POINT pt; + pt.x = x; + pt.y = y; + + ScrollDragThumb(window, &pt, pTRects, pScrollInfo); + pScrollInfo->nPos = MouseToScrollPos(&pt, pTRects, pScrollInfo); + + SendMessage(hWndParent, WM_VSCROLL, MAKEWPARAM(SB_ENDSCROLL,pScrollInfo->nPos), (LPARAM) window); + } + + // Clear Drag Modes + pScrollDrag->dm.fModes = 0; + } + +} + + +//**************************************************************************** +//**************************************************************************** +static LRESULT CALLBACK StormScrollbarWndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == LBN_SELCHANGE) { + ListUpdateScrollbar((HWND)lparam); + return 0; + } + break; + + case WM_CREATE: + if (!ScrollbarCreate(window)) + return -1; + + ScrollbarDraw(window); + break; + + case WM_DESTROY: + ScrollbarDestroy(window); + break; + + case WM_LBUTTONDOWN: + // cast mouse coords to short to force sign extension + ScrollbarBtnDown(window, (short)LOWORD(lparam), (short)HIWORD(lparam)); + return 0; + + case WM_LBUTTONUP: + // cast mouse coords to short to force sign extension + ScrollbarBtnUp(window, (short)LOWORD(lparam), (short)HIWORD(lparam)); + break; + + case WM_MOUSEMOVE: + if (window == GetCapture()) { + PTSCROLLDRAG pScrollDrag = (PTSCROLLDRAG) GetProp(window, PROP_SCROLLDRAG); + + if (!pScrollDrag) + break; + + // Only worry about MouseMove messages if we're dragging the thumb around + if (pScrollDrag->dm.Clicked.Thumb) { + // cast mouse coords to short to force sign extension + ScrollbarBtnDown(window, (short)LOWORD(lparam), (short)HIWORD(lparam)); + } + } + break; + + case WM_PAINT: + ScrollbarPaint(window); + return 0; + + case WM_STORMSCROLL_INIT: + SetProp(window, PROP_SCROLLPARENT, (HANDLE)lparam); + ShowWindow(window, SW_HIDE); // Default to hidden unless we support 'disabled' scrollbar + return 0; + + case WM_TIMER: + POINT pt; + + // Make sure we are still capturing the mouse + if (window != GetCapture()) + return 0; + GetCursorPos(&pt); + ScreenToClient(window, &pt); + ScrollbarBtnDown(window, pt.x, pt.y); + return 0; + + case SBM_GETPOS: + break; + + case SBM_GETRANGE: + break; + + case SBM_SETPOS: + return ScrollbarSetPos(window, wparam, (BOOL)lparam); + + case SBM_SETRANGE: + return ScrollbarSetRange(window, wparam, lparam); + + case SBM_SETRANGEREDRAW: + BOOL bReturn; + bReturn = ScrollbarSetRange(window, wparam, lparam); + return bReturn; + + + case SBM_SETSCROLLINFO: + return ScrollbarSetInfo(window, (LPSCROLLINFO)lparam); + + case SBM_GETSCROLLINFO: + return FALSE; + + + + } + return DefWindowProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + +//**************************************************************************** +int ScrollbarGetWidth(void) { + return (int)sgSizeArrows.cx; +} + +//**************************************************************************** +void ScrollbarLink(HWND hWndList, HWND hWndScroll) { + if (hWndList) { + SendMessage(hWndScroll, WM_STORMSCROLL_INIT, 0, (LPARAM)hWndList); + SetWindowLong(hWndList, GWL_USERDATA, (LONG)hWndScroll); + } +} + +//**************************************************************************** +void ListUpdateScrollbar(HWND hWndList) { + HWND hWndScroll; + RECT r; + int min, max; + int nPixHt, nItems, nItemsInWindow; + + hWndScroll = (HWND)GetWindowLong(hWndList, GWL_USERDATA); + if (hWndScroll == NULL) + return; + + GetClientRect(hWndList, &r); + nPixHt = SendMessage(hWndList, LB_GETITEMHEIGHT, 0, 0); + nItems = SendMessage(hWndList, LB_GETCOUNT, 0, 0); + if (!nPixHt) + return; + nItemsInWindow = r.bottom/nPixHt; + + GetClientRect(hWndList, &r); + + min = max = 0; + if (nPixHt != LB_ERR && nItems != LB_ERR) { + max = nItems - nItemsInWindow; + + if (max < 0) + max = 0; + } + else { + max = 0; + } + + + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; + si.nPos = SendMessage(hWndList, LB_GETTOPINDEX, 0, 0); + si.nMin = min; + si.nMax = max; + si.nPage = nItemsInWindow-1; + SendMessage(hWndScroll, SBM_SETSCROLLINFO, TRUE, (LPARAM)&si); +} + +//**************************************************************************** +void EditUpdateScrollbar(HWND hWndEdit) { + HWND hWndScroll; + int min, max; + int nItems; + + hWndScroll = (HWND)GetWindowLong(hWndEdit, GWL_USERDATA); + if (hWndScroll == NULL) + return; + + nItems = SendMessage(hWndEdit, EM_GETLINECOUNT, 0, 0); + + min = 0; + max = nItems-1; + + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; + si.nPos = 0; // don't know how to get current line from edit control! + si.nMin = min; + si.nMax = max; + si.nPage = 10; // arbitrary number + SendMessage(hWndScroll, SBM_SETSCROLLINFO, TRUE, (LPARAM)&si); +} + +//**************************************************************************** +//**************************************************************************** +void ScrollbarRegisterClass (void) { + WNDCLASS wndclass; + ZeroMemory(&wndclass,sizeof(WNDCLASS)); + wndclass.style = CS_GLOBALCLASS; + wndclass.lpfnWndProc = StormScrollbarWndProc; + wndclass.hInstance = global_hinstance; + wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); + wndclass.lpszClassName = "StormScrollbar"; + RegisterClass(&wndclass); +} + +//**************************************************************************** +//**************************************************************************** +void ScrollbarUnregisterClass (void) { + UnregisterClass("StormScrollbar", global_hinstance); +} diff --git a/src/Storm/SOURCE/BATTLE/SPI.CPP b/src/Storm/SOURCE/BATTLE/SPI.CPP new file mode 100644 index 0000000..93f98f2 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/SPI.CPP @@ -0,0 +1,844 @@ +/**************************************************************************** +* +* SPI.CPP +* battle.net service provider interface functinos +* +* By Michael O'Brien (10/9/96) +* +***/ + +#include "pch.h" + +#define OVERHEADESTIMATE 39 // PPP, IP, and UDP headers + +#define PERF_PKTSENT 0 +#define PERF_PKTRECV 1 +#define PERF_BYTESSENT 2 +#define PERF_BYTESRECV 3 +#define PERFNUM 4 + +#define RECVDATATHREADS 2 + +typedef struct _EXTMSG { + char senderpath[SNETSPI_MAXSTRINGLENGTH]; // must be first field in structure + char sendername[SNETSPI_MAXSTRINGLENGTH]; + char message[MAXMESSAGESIZE]; + _EXTMSG *next; +} EXTMSG, *EXTMSGPTR; + +typedef struct _PACKET { + SNETADDR addr; // must be first field in structure + DWORD packettype; // must be immediately prior to data + BYTE data[MAXMESSAGESIZE]; + DWORD databytes; + _PACKET *next; +} PACKET, *PACKETPTR; + +typedef struct _THREAD { + unsigned id; + HANDLE handle; + _THREAD *next; +} THREAD, *THREADPTR; + +static SOCKET spi_datasocket = (SOCKET)0; +static CCritSect spi_extmsgcritsect; +static EXTMSGPTR spi_extmsghead = NULL; +static CCritSect spi_gamecritsect; +static SNETSPI_GAMELISTPTR spi_gamehead = NULL; +static CCritSect spi_packetcritsect; +static PACKETPTR spi_packethead = NULL; +static DWORD spi_perfdata[PERFNUM] = {0}; +static HANDLE spi_recvevent = (HANDLE)0; +static BOOL spi_shutdown = 0; +static THREADPTR spi_threadhead = NULL; + +static unsigned CALLBACK RecvDataThreadProc (LPVOID param); + +//=========================================================================== +static BOOL InitializeSockets () { + + // INITIALIZE THE RAS MANAGER + InitRASManager(); + + // INITIALIZE WINDOWS SOCKETS + { + WSADATA data; + if (WSAStartup(MAKEWORD(1,1),&data)) { + SpiDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + } + + // CREATE A LISTENING SOCKET + spi_datasocket = socket(AF_INET,SOCK_DGRAM,0); + if (!spi_datasocket) { + SpiDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + + // BIND TO THE SOCKET + { + sockaddr_in addr; + ZeroMemory(&addr,sizeof(sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = htons(DATAPORT); + if (bind(spi_datasocket, + (const struct sockaddr *)&addr, + sizeof(sockaddr_in))) { + SpiDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + } + + // CREATE THREADS TO READ PACKETS FROM THE DATA SOCKET + { + BOOL win95 = GetVersion() & 0x80000000; + int threads = win95 ? 1 : RECVDATATHREADS; + for (int loop = 0; loop < threads; ++loop) { + THREAD thread; + thread.handle = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + RecvDataThreadProc, + NULL, + 0, + &thread.id); + if (thread.handle) { + SetThreadPriority(thread.handle,THREAD_PRIORITY_HIGHEST); + LISTADD(&spi_threadhead,&thread); + } + else { + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + } + + return 1; +} + +//=========================================================================== +static unsigned CALLBACK RecvDataThreadProc (LPVOID param) { + while (spi_datasocket && !spi_shutdown) { + + // ALLOCATE MEMORY FOR THE NEXT INCOMING PACKET + PACKETPTR pkt = NEW(PACKET); + + // RECEIVE A PACKET, BLOCKING IF ONE IS NOT AVAILABLE YET. WHEN THE + // NETWORK DRIVER HAS INCOMING DATA ON A PORT, IT WILL COPY IT DIRECTLY + // TO THE APPLICATION'S ADDRESS SPACE IF THE APPLICATION IS BLOCKING ON + // A READ. FOR THIS REASON, WE TRY TO ALWAYS HAVE AT LEAST ONE READ + // PENDING. + int addrsize = sizeof(sockaddr_in); + int bytesread = recvfrom(spi_datasocket, + (char *)&pkt->packettype, + sizeof(DWORD)+MAXMESSAGESIZE, + 0, + (sockaddr *)&pkt->addr, + &addrsize); + pkt->databytes = (bytesread >= sizeof(DWORD)) + ? (DWORD)bytesread-sizeof(DWORD) + : 0; + ZeroMemory(((LPBYTE)&pkt->addr)+min(8,addrsize),sizeof(SNETADDR)-min(8,addrsize)); + + // SINCE WE DON'T TIME OUT ON READS, THE ONLY WAY A READ CAN FAIL IS + // IF THE SOCKET WAS CLOSED. IN THIS CASE, SHUT DOWN THE THREAD. + if ((bytesread < 0) || spi_shutdown) { + FREE(pkt); + _endthreadex(0); + return 0; + } + + // ON A SUCCESSFUL READ, PROCESS THE PACKET + ++spi_perfdata[PERF_PKTRECV]; + spi_perfdata[PERF_BYTESRECV] += bytesread+OVERHEADESTIMATE; + switch (pkt->packettype) { + + case PKT_GAMEDATA: + spi_packetcritsect.Enter(); + LISTADDPTREND(&spi_packethead,pkt); + spi_packetcritsect.Leave(); + SetEvent(spi_recvevent); + break; + + case PKT_CLIENTREQ: + SrvProcessClientReq(&pkt->addr, + &pkt->data[0], + pkt->databytes); + FREE(pkt); + break; + + case PKT_SERVERPING: + SrvProcessServerPing(&pkt->data[0], + pkt->databytes); + FREE(pkt); + break; + + default: + FREE(pkt); + break; + + } + + } + _endthreadex(0); + return 0; +} + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +void SpiAddGame (SNETSPI_GAMELISTPTR game) { + + // CREATE A RECORD FOR THIS GAME + SNETSPI_GAMELISTPTR newgame = NEW(SNETSPI_GAMELIST); + if (!newgame) + return; + CopyMemory(newgame,game,sizeof(SNETSPI_GAMELIST)); + + // IF THIS GAME IS ALREADY IN THE LINKED LIST, REMOVE IT + spi_gamecritsect.Enter(); + SNETSPI_GAMELISTPTR *nextptr = &spi_gamehead; + while (*nextptr) + if (!memcmp(&(*nextptr)->owner,&newgame->owner,sizeof(sockaddr_in))) { + SNETSPI_GAMELISTPTR curr = *nextptr; + *nextptr = curr->next; + FREE(curr); + } + else + nextptr = &(*nextptr)->next; + + // ADD THIS GAME TO THE LINKED LIST OF GAMES + static DWORD idsequence = 0; + if (!(newgame->gameid = ++idsequence)) + newgame->gameid = ++idsequence; + newgame->next = NULL; + *nextptr = newgame; + spi_gamecritsect.Leave(); + +} + +//=========================================================================== +BOOL CALLBACK SpiCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude) { + if (diffmagnitude) + *diffmagnitude = 0; + if (!(addr1 && addr2 && diffmagnitude)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + sockaddr_in *inaddr1 = (sockaddr_in *)addr1; + sockaddr_in *inaddr2 = (sockaddr_in *)addr2; + if (inaddr1->sin_addr.S_un.S_un_b.s_b1 != + inaddr2->sin_addr.S_un.S_un_b.s_b1) + *diffmagnitude = 4; + else if (inaddr1->sin_addr.S_un.S_un_b.s_b2 != + inaddr2->sin_addr.S_un.S_un_b.s_b2) + *diffmagnitude = 3; + else if (inaddr1->sin_addr.S_un.S_un_b.s_b3 != + inaddr2->sin_addr.S_un.S_un_b.s_b3) + *diffmagnitude = 2; + else if (inaddr1->sin_addr.S_un.S_un_b.s_b4 != + inaddr2->sin_addr.S_un.S_un_b.s_b4) + *diffmagnitude = 1; + else + *diffmagnitude = 0; + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiDestroy () { + + // START THE SHUTDOWN PROCESS + spi_shutdown = 1; + + // STOP ADVERTISING OUR GAME + SpiStopAdvertisingGame(); + + // DISCONNECT FROM THE BATTLENET SERVER + SrvDestroy(); + + // CLEAR THE EXTERNAL MESSAGE QUEUE + spi_extmsgcritsect.Enter(); + LISTCLEAR(&spi_extmsghead); + spi_extmsgcritsect.Leave(); + + // SEND DATA TO THE RECEIVE THREADS TO WAKE THEM UP + { + sockaddr_in addr; + ZeroMemory(&addr,sizeof(sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = htons(DATAPORT); + addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); + char buffer[] = " "; + SOCKET newsocket = socket(AF_INET,SOCK_DGRAM,0); + for (int loop = 0; loop < RECVDATATHREADS; ++loop) + sendto(newsocket,buffer,1,0,(sockaddr *)&addr,sizeof(sockaddr_in)); + closesocket(newsocket); + } + + // WAIT FOR ALL THREADS TO TERMINATE + while (spi_threadhead) { + WaitForSingleObject(spi_threadhead->handle,INFINITE); + CloseHandle(spi_threadhead->handle); + LISTFREE(&spi_threadhead,spi_threadhead); + } + + // CLOSE THE DATA SOCKET + if (spi_datasocket) { + closesocket(spi_datasocket); + spi_datasocket = (SOCKET)0; + } + + // TAKE CONTROL OF THE PACKET CRITICAL SECTION + spi_packetcritsect.Enter(); + + // FREE ALL UNPROCESSED PACKETS + LISTCLEAR(&spi_packethead); + + // FREE THE GAME LIST + LISTCLEAR(&spi_gamehead); + + // CLEAN UP WINDOWS SOCKETS + WSACleanup(); + + // DESTROY OTHER MODULES + UiDestroy(); + CacheDestroy(); + + // LEAVE THE PACKET CRITICAL SECTION + spi_packetcritsect.Leave(); + + // FINISH THE SHUTDOWN PROCESS + spi_shutdown = 0; + + // ASK THE USER WHETHER HE WANTS TO HANG UP + UiDisconnect(); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiFree (SNETADDRPTR addr, + LPVOID data, + DWORD databytes) { + if (!(addr && data)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + FREE(addr); + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiFreeExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR message) { + if (!(senderpath && sendername && message)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + FREE((LPVOID)senderpath); + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiGetGameInfo (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + SNETSPI_GAMELIST *gameinfo) { + if (gameinfo) + ZeroMemory(gameinfo,sizeof(SNETSPI_GAMELIST)); + if (!(gamename && gameinfo && (gameid || *gamename))) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // CLEAR THE EXTERNAL MESSAGE QUEUE + spi_extmsgcritsect.Enter(); + LISTCLEAR(&spi_extmsghead); + spi_extmsgcritsect.Leave(); + + // ENTER THE CRITICAL SECTION + spi_gamecritsect.Enter(); + + // SEARCH FOR A GAME IN THE GAME LIST MATCHING THE QUERY PARAMETERS + SNETSPI_GAMELISTPTR found = NULL; + BOOL remove = 0; + { + SNETSPI_GAMELISTPTR curr = spi_gamehead; + while (curr) + if (((!gameid) || (gameid == curr->gameid)) && + ((!*gamename) || !_stricmp(gamename,curr->gamename))) { + found = curr; + break; + } + else + curr = curr->next; + } + + // IF WE DIDN'T FIND A MATCH, AND IF A GAME NAME BUT NO GAME ID WAS + // GIVEN, THEN REQUEST INFORMATION ABOUT THAT GAME FROM THE SERVER + // AND THEN SEARCH AGAIN. + if ((!found) && (gamename && !gameid)) { + if (!SrvIsWaitingForResponse()) { + spi_gamecritsect.Leave(); + SrvGetGameList(gamename,gamepassword,0,0,1); + spi_gamecritsect.Enter(); + } + SNETSPI_GAMELISTPTR curr = spi_gamehead; + while (curr) + if (!_stricmp(gamename,curr->gamename)) { + found = curr; + remove = 1; + break; + } + else + curr = curr->next; + } + + // IF WE FOUND A MATCH, COPY INFORMATION ABOUT THE MATCH INTO THE + // CALLER'S INFORMATION STRUCTURE + if (found) + CopyMemory(gameinfo,found,sizeof(SNETSPI_GAMELIST)); + if (remove) + LISTFREE(&spi_gamehead,found); + + // LEAVE THE GAME CRITICAL SECTION + spi_gamecritsect.Leave(); + + if (found) + return 1; + else { + SetLastError(SNET_ERROR_GAME_NOT_FOUND); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK SpiGetLocalPlayerName (LPSTR namebuffer, + DWORD namechars, + LPSTR descbuffer, + DWORD descchars) { + if (namebuffer && namechars) + SrvGetLocalPlayerName(namebuffer, + namechars); + if (descbuffer && descchars) + SrvGetLocalPlayerDesc(descbuffer, + descchars); + return TRUE; +} + + +//=========================================================================== +BOOL CALLBACK SpiGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq) { + switch (counterid) { + + case SNET_PERFID_PKTSENTONWIRE: + *countervalue = spi_perfdata[PERF_PKTSENT]; + return 1; + + case SNET_PERFID_PKTRECVONWIRE: + *countervalue = spi_perfdata[PERF_PKTRECV]; + return 1; + + case SNET_PERFID_BYTESSENTONWIRE: + *countervalue = spi_perfdata[PERF_BYTESSENT]; + return 1; + + case SNET_PERFID_BYTESRECVONWIRE: + *countervalue = spi_perfdata[PERF_BYTESRECV]; + return 1; + + } + return 0; +} + +//=========================================================================== +BOOL CALLBACK SpiInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + HANDLE event) { + + // SAVE THE PROGRAM AND VERSION IDS AND THE RECEIVE EVENT HANDLE + global_programid = programdata->programid; + global_versionid = programdata->versionid; + global_maxplayers = min(programdata->maxplayers,MAXPLAYERS); + spi_recvevent = event; + + // RESET PERFORMANCE DATA + ZeroMemory(&spi_perfdata[0],PERFNUM*sizeof(DWORD)); + + // INITIALIZE OTHER MODULES + CacheInitialize(); + UiInitialize(interfacedata); + + // BRING UP THE CONNECTION SCREEN + if (!UiBeginConnect(programdata, + interfacedata)) { + SrvDestroy(); + SpiDestroy(); + SetLastError(SNET_ERROR_INVALID_PARAMETER); + } + + // INITIALIZE SOCKETS + BOOL result = 1; + DWORD lasterror = 0; + UiProcessWindowMessages(); + if (!InitializeSockets()) { + UiWSockErrMessage(); + result = 0; + lasterror = GetLastError(); + } + + // CONNECT TO THE BATTLENET SERVER + if (result) { + UiProcessWindowMessages(); + if (!SrvInitialize(programdata,playerdata,versiondata)) { + result = 0; + lasterror = GetLastError(); + } + } + + // CLOSE THE CONNECTION SCREEN + UiEndConnect(result); + if (result) { + if (!UiLogon(programdata, + playerdata, + interfacedata, + versiondata)) { + lasterror = GetLastError(); + result = FALSE; + } + } + + // IF WE DIDN'T SUCCEED IN CONNECTING TO THE BATTLE.NET SERVER, + // SHUT DOWN THE SNP + if (!result) { + SpiDestroy(); + SetLastError(lasterror); + return 0; + } + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + + // WE NEVER RETURN ANY DEVICES, SO THIS FUNCTION SHOULD NEVER BE CALLED + return 0; +} + +//=========================================================================== +BOOL CALLBACK SpiLockDeviceList (SNETSPI_DEVICELISTPTR *devicelist) { + *devicelist = NULL; + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiLockGameList (DWORD categorybits, + DWORD categorymask, + SNETSPI_GAMELISTPTR *gamelist) { + if (!gamelist) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // CLEAR THE EXTERNAL MESSAGE QUEUE + spi_extmsgcritsect.Enter(); + LISTCLEAR(&spi_extmsghead); + spi_extmsgcritsect.Leave(); + + // GET A CURRENT LIST OF GAMES FROM THE SERVER + if (!SrvIsWaitingForResponse()) { + LISTCLEAR(&spi_gamehead); + char progvers[32]; + wsprintf(progvers,"%08x%08x",global_programid,global_versionid); + char lastgame[SNETSPI_MAXSTRINGLENGTH] = ""; + SRegLoadString("Recent Games",progvers,SREG_FLAG_BATTLENET,lastgame,SNETSPI_MAXSTRINGLENGTH); + if (lastgame[0]) + SrvGetGameList(lastgame,NULL,categorybits,categorymask,1); + SrvGetGameList(NULL,NULL,categorybits,categorymask,spi_gamehead ? 12 : 13); + } + + // ENTER THE GAME CRITICAL SECTION + spi_gamecritsect.Enter(); + + // UPDATE THE LATENCY FOR EACH GAME + { + SNETSPI_GAMELISTPTR curr = spi_gamehead; + while (curr) { + SrvGetLatency(&curr->owner,&curr->ownerlatency); + curr = curr->next; + } + } + + // RETURN THE GAME LIST TO THE CALLER + *gamelist = spi_gamehead; + + return 1; +} + +//=========================================================================== +void SpiQueueExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR message) { + spi_extmsgcritsect.Enter(); + EXTMSGPTR newptr = NEW(EXTMSG); + if (newptr) { + strncpy(newptr->senderpath,senderpath,SNETSPI_MAXSTRINGLENGTH); + strncpy(newptr->sendername,sendername,SNETSPI_MAXSTRINGLENGTH); + strncpy(newptr->message,message,MAXMESSAGESIZE); + newptr->senderpath[SNETSPI_MAXSTRINGLENGTH-1] = 0; + newptr->sendername[SNETSPI_MAXSTRINGLENGTH-1] = 0; + newptr->message[MAXMESSAGESIZE-1] = 0; + LISTADDPTREND(&spi_extmsghead,newptr); + } + spi_extmsgcritsect.Leave(); + SetEvent(spi_recvevent); +} + +//=========================================================================== +BOOL CALLBACK SpiReceive (SNETADDRPTR *addr, + LPVOID *data, + DWORD *databytes) { + if (addr) + *addr = NULL; + if (data) + *data = NULL; + if (databytes) + *databytes = NULL; + if (!(addr && data && databytes && spi_datasocket)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // IF THERE IS A PACKET QUEUED, REMOVE IT FROM THE QUEUE AND RETURN + // POINTERS TO THE CALLER. NOTE THAT WE UNLINK THE PACKET BUT DON'T + // FREE IT FROM MEMORY; IT IS THE CALLER'S RESPONSIBILITY TO CALL + // OUR FREE FUNCTION WHEN IT IS DONE WITH THE PACKET. + if (spi_packethead) { + spi_packetcritsect.Enter(); + *addr = &spi_packethead->addr; + *data = spi_packethead->data; + *databytes = spi_packethead->databytes; + spi_packethead = spi_packethead->next; + spi_packetcritsect.Leave(); + return 1; + } + else { + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK SpiReceiveExternalMessage (LPCSTR *senderpath, + LPCSTR *sendername, + LPCSTR *message) { + if (senderpath) + *senderpath = NULL; + if (sendername) + *sendername = NULL; + if (message) + *message = NULL; + if (!(senderpath && sendername && message)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // IF THERE IS A MESSAGE QUEUED, REMOVE IT FROM THE QUEUE AND RETURN + // POINTERS TO THE CALLER. NOTE THAT WE UNLINK THE MESSAGE BUT DON'T + // FREE IT FROM MEMORY; IT IS THE CALLER'S RESPONSIBILITY TO CALL + // OUR FREE FUNCTION WHEN IT IS DONE WITH THE PACKET. + if (spi_extmsghead) { + spi_extmsgcritsect.Enter(); + *senderpath = spi_extmsghead->senderpath; + *sendername = spi_extmsghead->sendername; + *message = spi_extmsghead->message; + spi_extmsghead = spi_extmsghead->next; + spi_extmsgcritsect.Leave(); + return 1; + } + else { + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK SpiSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + return UiSelectGame(flags, + programdata, + playerdata, + interfacedata, + versiondata, + playerid); +} + +//=========================================================================== +BOOL CALLBACK SpiSend (DWORD addresses, + SNETADDRPTR *addrlist, + LPVOID data, + DWORD databytes) { + if (!(addresses && + addrlist && data && databytes && (databytes <= MAXMESSAGESIZE) && + spi_datasocket)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // CREATE A FULLY FORMED PACKET + PACKET pkt; + pkt.packettype = PKT_GAMEDATA; + CopyMemory(&pkt.data[0],data,databytes); + + // SEND IT TO EACH TARGET ADDRESS + while (addresses--) { + sendto(spi_datasocket, + (const char *)&pkt.packettype, + sizeof(DWORD)+databytes, + 0, + (const sockaddr *)*(addrlist+addresses), + sizeof(sockaddr_in)); + ++spi_perfdata[PERF_PKTSENT]; + spi_perfdata[PERF_BYTESSENT] += sizeof(DWORD)+databytes+OVERHEADESTIMATE; + } + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiSendExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR targetpath, + LPCSTR targetname, + LPCSTR message) { + if ((!*targetpath) && (!*targetname)) + SrvSendChatString(message); + return 1; +} + +//=========================================================================== +BOOL SpiSendSpecial (SNETADDRPTR addr, + DWORD packettype, + LPVOID data, + DWORD databytes) { + if (!(addr && data && databytes && (databytes <= MAXMESSAGESIZE) && + spi_datasocket)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // CREATE A FULLY FORMED PACKET + PACKET pkt; + pkt.packettype = packettype; + CopyMemory(&pkt.data[0],data,databytes); + + // SEND IT TO THE TARGET ADDRESS + sendto(spi_datasocket, + (const char *)&pkt.packettype, + sizeof(DWORD)+databytes, + 0, + (const sockaddr *)addr, + sizeof(sockaddr_in)); + ++spi_perfdata[PERF_PKTSENT]; + spi_perfdata[PERF_BYTESSENT] += sizeof(DWORD)+databytes+OVERHEADESTIMATE; + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD gameage, + DWORD gamecategorybits, + DWORD optcategorybits, + LPCVOID clientdata, + DWORD clientdatabytes) { + if (!(gamename && gamedescription)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // IF WE'RE NOT CONNECTED TO A BATTLENET SERVER, RETURN FAILURE + if (!SrvIsConnected()) { + SetLastError(SNET_ERROR_NOT_CONNECTED); + return 0; + } + + // SEND THE GAME INFORMATION TO THE BATTLENET SERVER + if (!SrvStartAdvertisingGame(gamename, + gamepassword, + gamedescription, + gamemode, + gameage, + gamecategorybits, + optcategorybits)) { + SetLastError(SNET_ERROR_ALREADY_EXISTS); + return 0; + } + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiStopAdvertisingGame () { + + // IF WE'RE NOT CONNECTED TO A BATTLENET SERVER, RETURN FAILURE + if (!SrvIsConnected()) { + SetLastError(SNET_ERROR_NOT_CONNECTED); + return 0; + } + + // TELL THE BATTLENET SERVER TO REMOVE THE GAME + SrvStopAdvertisingGame(); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiUnlockDeviceList (SNETSPI_DEVICELISTPTR devicelist) { + return 1; +} + +//=========================================================================== +BOOL CALLBACK SpiUnlockGameList (SNETSPI_GAMELISTPTR gamelist, + DWORD *hintnextcall) { + + // LEAVE THE GAME CRITICAL SECTION + spi_gamecritsect.Leave(); + + // TELL THE CALLER TO CALL BACK IN A SECOND TO GET AN UPDATED LIST + // OF LATENCIES + if (hintnextcall) + *hintnextcall = 1000; + + return 1; +} diff --git a/src/Storm/SOURCE/BATTLE/SRV.CPP b/src/Storm/SOURCE/BATTLE/SRV.CPP new file mode 100644 index 0000000..900c059 --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/SRV.CPP @@ -0,0 +1,2546 @@ +/**************************************************************************** +* +* SRV.CPP +* battle.net server communication functions +* +* By Michael O'Brien (10/9/96) +* +***/ + +#include "pch.h" + +#ifdef _X86_ +#define PLATFORMID 'IX86' +#endif + +#define MAXLATENCY 2000 +#define PINGFREQUENCY 30000 +#define SERVERPORT 6112 +#define CONNTYPE_CLIENT 0x01 +#define CONNTYPE_FILE 0x02 +#define SERVERBUFFERSIZE 16384 +#define SERVERVERSION 1 +#define CONFIGREGKEY "Configuration" +#define CONFIGREGVALUE_PINGLIST "Ping List" +#define CONFIGREGVALUE_SERVERLIST "Server List" +#define CONFIGREGVALUE_SERVERVER "Server Version" +#define CONFIGREGVALUE_REGAUTH "Registration Authority" +#define CONFIGREGVALUE_REGVER "Registration Version" +#define CONFIGREGVALUE_CLIENTID "Client ID" +#define CONFIGREGVALUE_CLIENTCHECK "Client Token" +#define COOKIEREGKEY "Cookies" +#define PATCHREGKEY "Patch" +#define PATCHREGVALUE_LAUNCHER "Launcher" +#define PATCHREGVALUE_SRCDATA "SrcData" +#define PATCHREGVALUE_DSTDATA "DstData" +#define PATCHREGVALUE_PATCHES "Patches" + +#define CHAT_DISPLAYUSER 1 +#define CHAT_ADDUSER 2 +#define CHAT_REMOVEUSER 3 +#define CHAT_WHISPER 4 +#define CHAT_TALK 5 +#define CHAT_BROADCAST 6 +#define CHAT_JOINCHANNEL 7 +#define CHAT_USERFLAGS 9 +#define CHAT_WHISPERSENT 10 +#define CHAT_CHANNELISFULL 13 +#define CHAT_CHANNELDOESNOTEXIST 14 +#define CHAT_CHANNELISRESTRICTED 15 +#define CHAT_INFORMATION 18 +#define CHAT_ERROR 19 +#define CHAT_SQUELCH 21 +#define CHAT_UNSQUELCH 22 + +#define CLI_PING 0 +#define CLI_PINGRESPONSE 1 + +#define DOWNLOAD_VERSIONING 1 +#define DOWNLOAD_PATCH 2 +#define DOWNLOAD_AD 3 + +#define JCF_DEFAULTCHANNEL 0x00000001 +#define JCF_JOINALWAYS 0x00000002 + +#define SAVE_CACHE 0x00000001 +#define SAVE_DISK 0x00000002 + +#define SID_NULL 0x00 +#define SID_STARTADV 0x01 +#define SID_STOPADV 0x02 +#define SID_GETADVLIST 0x03 +#define SID_SERVERLIST 0x04 +#define SID_CLIENTID 0x05 +#define SID_STARTVERSIONING 0x06 +#define SID_REPORTVERSION 0x07 +#define SID_STARTADVEX 0x08 +#define SID_GETADVLISTEX 0x09 +#define SID_ENTERCHAT 0x0A +#define SID_GETCHANNELLIST 0x0B +#define SID_JOINCHANNEL 0x0C +#define SID_CHATCOMMAND 0x0E +#define SID_CHATEVENT 0x0F +#define SID_LEAVECHAT 0x10 +#define SID_LOCALEINFO 0x12 +#define SID_FLOODDETECTED 0x13 +#define SID_UDPPINGRESPONSE 0x14 +#define SID_CHECKAD 0x15 +#define SID_CLICKAD 0x16 +#define SID_QUERYMEM 0x17 +#define SID_QUERYREG 0x18 +#define SID_MESSAGEBOX 0x19 +#define SID_BROADCAST 0x20 +#define SID_DISPLAYAD 0x21 +#define SID_NOTIFYJOIN 0x22 +#define SID_SETCOOKIE 0x23 +#define SID_GETCOOKIE 0x24 +#define SID_PING 0x25 +#define SERVERIDS 0x26 + +#define VER_RESULT_BADVERSION 0 +#define VER_RESULT_UPGRADEREQUIRED 1 +#define VER_RESULT_CURRENT 2 + +#define WAIT_FLAG_INFINITE 0x00000001 +#define WAIT_FLAG_NOMESSAGELOOP 0x00000004 + +typedef struct _CONNECTREC { + SOCKET socket; + HANDLE thread; + _CONNECTREC *next; +} CONNECTREC, *CONNECTPTR; + +typedef struct _FILEREQ { + DWORD requestbytes; + DWORD platformid; + DWORD programid; + DWORD fileid; + DWORD filedatatype; + FILETIME filetime; + char filename[MAX_PATH]; + // the following fields are not sent to the server, and should not + // be reflected in requestbytes + char url[MAX_PATH]; + DWORD downloadtype; + DWORD savetype; +} FILEREQ, *FILEREQPTR; + +typedef struct _FILERESPONSE { + DWORD headerbytes; + DWORD filebytes; + DWORD fileid; + DWORD filedatatype; + FILETIME filetime; + char filename[MAX_PATH]; +} FILERESPONSE, *FILERESPONSEPTR; + +typedef struct _PINGREC { + sockaddr_in addr; + char username[SNETSPI_MAXSTRINGLENGTH]; + DWORD latency; + DWORD lastpingtime; + DWORD lastresponsetime; + _PINGREC *next; +} PINGREC, *PINGPTR; + +typedef struct _SRVMSG { + BYTE signature; + BYTE id; + WORD bytes; +} SRVMSG, *SRVMSGPTR; + +typedef struct _UINOTIFICATION { + DWORD notifycode; + LPVOID buffer; + DWORD parambytes; + _UINOTIFICATION *next; +} UINOTIFICATION, *UINOTIFICATIONPTR; + +static DWORD srv_adnumber = 0; +static DWORD srv_addisplaytime = 0; +static char srv_argstring[256] = ""; +static DWORD srv_authenticated = 0; +static BOOL srv_cancelwait = 0; +static CCritSect srv_connectcritsect; +static BOOL srv_connected = 0; +static CONNECTPTR srv_connecthead = NULL; +static LONG srv_connectthreads = 0; +static LONG srv_downloadthreads = 0; +static BOOL srv_inchat = 0; +static HANDLE srv_keepalivethread = (HANDLE)0; +static CCritSect srv_patchcritsect; +static char srv_patchfiles[256] = "\0"; +static DWORD srv_patchhighcomplete = 0; +static DWORD srv_patchpercent = 0; +static CCritSect srv_pingcritsect; +static PINGPTR srv_pinghead = NULL; +static BOOL srv_pingsuccess = 0; +static LONG srv_pingthreads = 0; +static BOOL srv_responded[SERVERIDS] = {0}; +static SOCKET srv_serversocket = (SOCKET)0; +static HANDLE srv_serverthread = (HANDLE)0; +static BOOL srv_shutdown = 0; +static HANDLE srv_shutdownevent = 0; +static BOOL srv_startadvsuccess = 0; +static DWORD srv_udppingdata = 0; +static CCritSect srv_uinotificationcritsect; +static UINOTIFICATIONPTR srv_uinotificationhead = NULL; +static LPVOID srv_uinotificationhold = NULL; +static char srv_userdesc[MAXSTRINGLENGTH] = ""; +static char srv_username[MAXSTRINGLENGTH] = ""; +static char srv_versionfile[MAX_PATH] = ""; +static HANDLE srv_waitevent = (HANDLE)0; +static LONG srv_waiting = 0; + +static void DeleteConnectThread (SOCKET socket); +static unsigned CALLBACK PingThreadProc (LPVOID param); +static void ProcessFile (DWORD downloadtype, + DWORD savetype, + DWORD fileid, + DWORD filedatatype, + FILETIME *filetime, + LPCSTR filename, + LPCSTR url, + LPVOID data, + DWORD databytes); +static void QueueUiNotification (DWORD notifycode, + LPVOID param, + DWORD parambytes, + LPCSTR *string1ptr, + LPCSTR *string2ptr); +static void RemovePingUser (LPCSTR username, sockaddr_in *addr); +static void RequestFile (DWORD downloadtype, + DWORD savetype, + DWORD fileid, + DWORD filedatatype, + FILETIME *filetime, + LPCSTR filename, + LPCSTR url); +static void SaveFile (LPCSTR filename, + LPVOID buffer, + DWORD bytes); +static BOOL SendServerMessage (BYTE id, LPVOID data, DWORD databytes); +static void UpdatePatchPercent (LPCSTR filename, + DWORD offset, + DWORD totalsize); +static BOOL WaitOnce (DWORD flags); + +//=========================================================================== +static void AddConnectThread (SOCKET socket) { + CONNECTPTR newptr = NEW(CONNECTREC); + if (!newptr) + return; + DuplicateHandle(GetCurrentProcess(), + GetCurrentThread(), + GetCurrentProcess(), + &newptr->thread, + 0, + 0, + DUPLICATE_SAME_ACCESS); + newptr->socket = socket; + srv_connectcritsect.Enter(); + LISTADDPTR(&srv_connecthead,newptr); + srv_connectcritsect.Leave(); +} + +//=========================================================================== +static void AddPingUser (LPCSTR username, sockaddr_in *addr) { + RemovePingUser(username,addr); + + // NORMALIZE THE ADDRESS TO POINT TO THE DATA PORT + sockaddr_in dataportaddr; + CopyMemory(&dataportaddr,addr,sizeof(sockaddr_in)); + dataportaddr.sin_port = htons(DATAPORT); + ZeroMemory(&dataportaddr.sin_zero[0],8); + + // CREATE A NEW RECORD FOR THIS USER + PINGPTR newptr = NEW(PINGREC); + if (newptr) + ZeroMemory(newptr,sizeof(PINGREC)); + else + return; + CopyMemory(&newptr->addr,&dataportaddr,sizeof(sockaddr_in)); + if (username) { + strncpy(newptr->username,username,SNETSPI_MAXSTRINGLENGTH); + newptr->username[SNETSPI_MAXSTRINGLENGTH-1] = 0; + } + newptr->lastpingtime = GetTickCount(); + + // ADD IT TO THE LINKED LIST OF PING USERS + srv_pingcritsect.Enter(); + newptr->next = srv_pinghead; + srv_pinghead = newptr; + srv_pingcritsect.Leave(); + + // SEND AN INITIAL PING MESSAGE TO THE USER + DWORD request = CLI_PING; + SpiSendSpecial((SNETADDRPTR)&dataportaddr, + PKT_CLIENTREQ, + &request, + sizeof(DWORD)); + +} + +//=========================================================================== +static BOOL CheckVersion (DWORD *revisionid, DWORD *checkvalue, LPSTR comment) { + if (revisionid) + *revisionid = 0; + if (checkvalue) + *checkvalue = 0; + if (comment) + *comment = 0; + + HSARCHIVE archive = (HSARCHIVE)0; + LPVOID buffer = NULL; + char dllname[MAX_PATH] = ""; + HSFILE file = (HSFILE)0; + HINSTANCE lib = (HINSTANCE)0; + BOOL success = 0; + + // OPEN THE MOPAQ ARCHIVE THAT WE JUST DOWNLOADED + if (!SFileOpenArchive(srv_versionfile,0,0,&archive)) + return 0; + + __try { + + // VERIFY THE SIGNATURE ON THE ARCHIVE FILE + DWORD authtype; + SFileAuthenticateArchive(archive,&authtype); + if ((authtype != SFILE_AUTH_UNABLETOAUTHENTICATE) && + (authtype < SFILE_AUTH_FIRSTAUTHENTIC)) + __leave; + + // EXTRACT THE EMBEDDED DLL + strcpy(dllname,srv_versionfile); + if (strchr(dllname,'.')) + *strchr(dllname,'.') = 0; + strcat(dllname,".dll"); + if (!SFileOpenFileEx(archive,dllname,0,&file)) + __leave; + DWORD size = SFileGetFileSize(file); + buffer = ALLOC(size); + if (!buffer) + __leave; + SFileReadFile(file,buffer,size,NULL,NULL); + { + HANDLE outfile = CreateFile(dllname, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (outfile != INVALID_HANDLE_VALUE) { + DWORD byteswritten; + WriteFile(outfile,buffer,size,&byteswritten,NULL); + CloseHandle(outfile); + } + else + __leave; + } + + // BIND TO THE DLL + lib = LoadLibrary(dllname); + if (!lib) + __leave; + BOOL (APIENTRY *checkrevision)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,DWORD *,DWORD *,LPSTR); + *(LPVOID *)&checkrevision = GetProcAddress(lib,"CheckRevision"); + if (!checkrevision) + __leave; + + // CALL THE REVISION CHECKING FUNCTION + char appfilename[MAX_PATH] = ""; + char stormfilename[MAX_PATH] = ""; + char providerfilename[MAX_PATH] = ""; + GetModuleFileName(GetModuleHandle(NULL),appfilename,MAX_PATH); + GetModuleFileName((HMODULE)global_hinstance,providerfilename,MAX_PATH); + { + strcpy(stormfilename,providerfilename); + LPSTR curr = stormfilename; + while (strchr(curr,':')) + curr = strchr(curr,':')+1; + while (strchr(curr,'\\')) + curr = strchr(curr,'\\')+1; + strcpy(curr,"storm.dll"); + } + success = checkrevision(appfilename, + stormfilename, + providerfilename, + srv_argstring, + revisionid, + checkvalue, + comment); + + } + __finally { + if (lib) + FreeLibrary(lib); + if (buffer) + FREE(buffer); + if (file) + SFileCloseFile(file); + if (archive) + SFileCloseArchive(archive); + DeleteFile(srv_versionfile); + if (dllname[0]) + DeleteFile(dllname); + } + + return success; +} + +//=========================================================================== +static unsigned CALLBACK ConnectThreadProc (LPVOID param) { + + // CREATE A NEW SOCKET + SOCKET newsocket = socket(PF_INET,SOCK_STREAM,0); + if (srv_serversocket || !newsocket) { + if (newsocket) + closesocket(newsocket); + InterlockedDecrement(&srv_connectthreads); + _endthreadex(0); + return 0; + } + AddConnectThread(newsocket); + + // PERFORM A DNS LOOKUP ON THIS SERVER + DWORD ipaddress; + if (isdigit(*(const char *)param)) + ipaddress = inet_addr((const char *)param); + else { + const hostent *host = gethostbyname((const char *)param); + if (srv_serversocket || !host) { + DeleteConnectThread(newsocket); + closesocket(newsocket); + InterlockedDecrement(&srv_connectthreads); + _endthreadex(0); + return 0; + } + ipaddress = *(LPDWORD)host->h_addr_list[0]; + } + + // CONNECT TO THE SERVER + { + sockaddr_in addr; + ZeroMemory(&addr,sizeof(sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = htons(SERVERPORT); + addr.sin_addr.S_un.S_addr = ipaddress; + if (connect(newsocket,(sockaddr *)&addr,sizeof(sockaddr_in))) { + DeleteConnectThread(newsocket); + closesocket(newsocket); + InterlockedDecrement(&srv_connectthreads); + _endthreadex(0); + return 0; + } + } + + // IF WE WERE THE FIRST THREAD TO CONNECT, SAVE THIS SOCKET. + // OTHERWISE, CLOSE IT. + static CCritSect critsect; + critsect.Enter(); + if (!srv_serversocket) + srv_serversocket = newsocket; + else + closesocket(newsocket); + critsect.Leave(); + + DeleteConnectThread(newsocket); + InterlockedDecrement(&srv_connectthreads); + _endthreadex(0); + return 0; +} + +//=========================================================================== +static BOOL ConnectToServer () { + + // CREATE A SHUTDOWN EVENT + srv_shutdownevent = CreateEvent(NULL,1,0,NULL); + + // READ THE CACHED LIST OF BATTLENET SERVERS FROM THE REGISTRY + static DWORD serverversion = 0; + static char serverlist[256] = ""; + SRegLoadValue(CONFIGREGKEY,CONFIGREGVALUE_SERVERVER,SREG_FLAG_BATTLENET,&serverversion); + if (serverversion == SERVERVERSION) + SRegLoadString(CONFIGREGKEY,CONFIGREGVALUE_SERVERLIST,SREG_FLAG_BATTLENET,serverlist,256); + + // IF THERE WASN'T A LIST IN THE REGISTRY, USE THE DEFAULT LIST + if (!serverlist[0]) + if (GetTickCount() & 1) + strcpy(serverlist,"206.79.254.192;exodus.battle.net"); + else + strcpy(serverlist,"206.79.254.193;exodus.battle.net"); + +#if STARCRAFT_BNBETA + strcpy(serverlist,"206.79.254.204"); +#endif + + // SPAWN THREADS TO ATTEMPT TO CONNECT SIMULTANEOUSLY TO EVERY SERVER + srv_connectthreads = 0; + { + char *server = strtok(serverlist," ,;"); + while (server && *server) { + unsigned threadid; + HANDLE threadhandle = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + ConnectThreadProc, + server, + 0, + &threadid); + if (threadhandle) { + InterlockedIncrement(&srv_connectthreads); + CloseHandle(threadhandle); + } + server = strtok(NULL," ,;"); + } + } + + // WAIT UNTIL ONE OF THE THREADS SUCCEEDS OR UNTIL ALL OF THE THREADS EXIT + while ((!srv_serversocket) && (srv_connectthreads > 0)) { + if (srv_cancelwait) { + srv_cancelwait = 0; + SetLastError(SNET_ERROR_CANCELLED); + return 0; + } + if (!UiProcessWindowMessages()) + return 0; + Sleep(10); + } + if (!srv_serversocket) { + srv_connectthreads = 0; + srv_pingsuccess = 0; + + // IF WE COULDN'T CONNECT, FIND OUT WHETHER IT'S BATTLE.NET'S FAULT + // OR A BAD NET CONNECTION BY TRYING TO CONNECT TO SOME OTHER WELL + // KNOWN SITES + static char pinglist[256] = ""; + SRegLoadString(CONFIGREGKEY,CONFIGREGVALUE_PINGLIST,SREG_FLAG_BATTLENET,pinglist,256); + + // IF THERE WASN'T A LIST IN THE REGISTRY, USE THE DEFAULT LIST + if (!pinglist[0]) + strcpy(pinglist,"206.79.254.116;206.79.240.58;38.8.8.2"); + + // SPAWN THREADS TO ATTEMPT TO CONNECT SIMULTANEOUSLY TO EVERY TARGET + srv_pingthreads = 0; + { + char *target = strtok(pinglist," ,;"); + while (target && *target) { + unsigned threadid; + HANDLE threadhandle = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + PingThreadProc, + target, + 0, + &threadid); + if (threadhandle) { + InterlockedIncrement(&srv_pingthreads); + CloseHandle(threadhandle); + } + target = strtok(NULL," ,;"); + } + } + + // WAIT UNTIL ALL OF THE THREADS EXIT + while (srv_pingthreads > 0) { + if (srv_cancelwait) { + srv_cancelwait = 0; + SetLastError(SNET_ERROR_CANCELLED); + return 0; + } + if (!UiProcessWindowMessages()) + return 0; + Sleep(10); + } + + // REPORT WHETHER WE WERE ABLE TO PING ANY OF THE TARGETS + DWORD error; + if (srv_pingsuccess) + error = SN_ERROR_UNREACHABLE; + else + error = SN_ERROR_BADCONNECTION; + QueueUiNotification(SN_FAILEDTOCONNECT,&error,sizeof(DWORD),NULL,NULL); + + return 0; + } + + return 1; +} + +//=========================================================================== +static void DeleteConnectThread (SOCKET socket) { + srv_connectcritsect.Enter(); + CONNECTPTR *nextptr = &srv_connecthead; + while (*nextptr) + if ((*nextptr)->socket == socket) { + CONNECTPTR curr = *nextptr; + *nextptr = curr->next; + FREE(curr); + } + else + nextptr = &(*nextptr)->next; + srv_connectcritsect.Leave(); +} + +//=========================================================================== +static void DestroyConnectThreads (DWORD phase) { + srv_connectcritsect.Enter(); + switch (phase) { + + case 1: + { + CONNECTPTR curr = srv_connecthead; + while (curr) { + closesocket(curr->socket); + curr = curr->next; + } + } + break; + + case 2: + while (srv_connecthead) { + TerminateThread(srv_connecthead->thread,0); + DeleteConnectThread(srv_connecthead->socket); + InterlockedDecrement(&srv_connectthreads); + } + break; + + } + srv_connectcritsect.Leave(); +} + +//=========================================================================== +static void DisconnectFromServer () { + srv_connected = 0; + if (srv_serversocket) { + closesocket(srv_serversocket); + srv_serversocket = (SOCKET)0; + } +} + +//=========================================================================== +static unsigned CALLBACK DownloadThreadProc (LPVOID param) { + LPBYTE buffer = NULL; + SOCKET newsocket = (SOCKET)0; + FILEREQPTR requestptr = (FILEREQPTR)param; + FILERESPONSEPTR responseptr = NULL; + __try { + + // GET THE ADDRESS OF THE SERVER WE'RE CONNECTED TO + sockaddr_in addr; + int addrlen = sizeof(sockaddr_in); + if ((!srv_serversocket) || + (getpeername(srv_serversocket,(sockaddr *)&addr,&addrlen) == SOCKET_ERROR)) + __leave; + + // CONNECT TO THE SERVER'S FILE DOWNLOAD PORT + addr.sin_port = htons(SERVERPORT); + ZeroMemory(&addr.sin_zero[0],8); + newsocket = socket(PF_INET,SOCK_STREAM,0); + if (!newsocket) + __leave; + if (connect(newsocket,(sockaddr *)&addr,sizeof(sockaddr_in))) + __leave; + + // SEND THE CONNECTION TYPE + BYTE conntype = CONNTYPE_FILE; + if (send(newsocket, + (const char *)&conntype, + sizeof(BYTE), + 0) != sizeof(BYTE)) + __leave; + + // SEND THE SERVER THE DOWNLOAD REQUEST + if (send(newsocket, + (const char *)requestptr, + requestptr->requestbytes, + 0) != (int)requestptr->requestbytes) + __leave; + + // WAIT FOR THE RETURNED FILE HEADER + DWORD headersize; + if (recv(newsocket, + (char *)&headersize, + sizeof(DWORD), + 0) != sizeof(DWORD)) + __leave; + responseptr = (FILERESPONSEPTR)ALLOC(headersize); + if (!responseptr) + __leave; + if (recv(newsocket, + ((char *)responseptr)+sizeof(DWORD), + headersize-sizeof(DWORD), + 0) != (int)(headersize-sizeof(DWORD))) + __leave; + + // ALLOCATE MEMORY FOR THE FILE + buffer = (LPBYTE)ALLOC(responseptr->filebytes); + if (!buffer) + __leave; + + // RECEIVE THE FILE + DWORD currpos = 0; + while (currpos < responseptr->filebytes) { + int bytes = recv(newsocket, + (char *)(buffer+currpos), + responseptr->filebytes-currpos, + 0); + if ((bytes == SOCKET_ERROR) || (bytes < 0)) + __leave; + currpos += (DWORD)bytes; + + // IF THIS IS A PATCH, UPDATE THE PERCENT COMPLETE + if (requestptr->downloadtype == DOWNLOAD_PATCH) + UpdatePatchPercent(responseptr->filename, + currpos, + responseptr->filebytes); + + } + + // SAVE IT + if (requestptr->savetype & SAVE_CACHE) + CacheSaveFile(responseptr->filename, + buffer, + responseptr->filebytes, + &responseptr->filetime, + 1296000, + 2592000); + if (requestptr->savetype & SAVE_DISK) + SaveFile(responseptr->filename, + buffer, + responseptr->filebytes); + + // PROCESS THE FILE + ProcessFile(requestptr->downloadtype, + requestptr->savetype, + responseptr->fileid, + responseptr->filedatatype, + &responseptr->filetime, + responseptr->filename, + requestptr->url, + buffer, + responseptr->filebytes); + + } + __finally { + if (buffer) + FREE(buffer); + if (responseptr) + FREE(responseptr); + if (newsocket) + closesocket(newsocket); + if (param) + FREE(param); + } + InterlockedDecrement(&srv_downloadthreads); + _endthreadex(0); + return 0; +} + +//=========================================================================== +static unsigned CALLBACK KeepAliveThreadProc (LPVOID) { + while (!srv_shutdown) + if (WaitForSingleObject(srv_shutdownevent,180000) != WAIT_OBJECT_0) + SendServerMessage(SID_NULL,NULL,0); + _endthreadex(0); + return 0; +} + +//=========================================================================== +static void OnBroadcast (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 1)) + return; + if (srv_inchat) { + SNDISPLAYSTRINGREC rec; + rec.sender = ""; + rec.senderflags = 0; + rec.string = (LPCSTR)data; + rec.stringtype = SN_STRING_BROADCAST; + QueueUiNotification(SN_DISPLAYSTRING,&rec,sizeof(SNDISPLAYSTRINGREC),&rec.sender,&rec.string); + } + else + SpiQueueExternalMessage("","",(LPCSTR)data); +} + +//=========================================================================== +static void OnChatEvent (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 2*sizeof(DWORD)+2)) + return; + DWORD eventid = *(LPDWORD)data; + DWORD flags = *((LPDWORD)data+1); + sockaddr_in *address = (sockaddr_in *)(data+2*sizeof(DWORD)); + LPCSTR username = (LPCSTR)data+sizeof(sockaddr_in)+2*sizeof(DWORD); + LPCSTR string = username+strlen(username)+1; + switch (eventid) { + + case CHAT_ADDUSER: + case CHAT_DISPLAYUSER: + { + SNADDUSERREC rec; + rec.name = username; + rec.description = string; + rec.flags = flags; + rec.notifyuser = (eventid == CHAT_ADDUSER); + QueueUiNotification(SN_ADDUSER,&rec,sizeof(SNADDUSERREC),&rec.name,&rec.description); + AddPingUser(username,address); + } + break; + + case CHAT_REMOVEUSER: + { + SNDELETEUSERREC rec; + rec.name = username; + rec.reason = string; + rec.notifyuser = 1; + QueueUiNotification(SN_DELETEUSER,&rec,sizeof(SNDELETEUSERREC),&rec.name,NULL); + RemovePingUser(username,address); + } + break; + + case CHAT_BROADCAST: + case CHAT_WHISPER: + case CHAT_TALK: + case CHAT_WHISPERSENT: + case CHAT_INFORMATION: + case CHAT_ERROR: + if (srv_inchat) { + SNDISPLAYSTRINGREC rec; + rec.sender = username; + rec.senderflags = flags; + rec.string = string; + rec.stringtype = 0; + switch (eventid) { + case CHAT_WHISPER: rec.stringtype = SN_STRING_WHISPER; break; + case CHAT_TALK: rec.stringtype = SN_STRING_TALK; break; + case CHAT_BROADCAST: rec.stringtype = SN_STRING_BROADCAST; break; + case CHAT_WHISPERSENT: rec.stringtype = SN_STRING_WHISPERSENT; break; + case CHAT_INFORMATION: rec.stringtype = SN_STRING_INFORMATION; break; + case CHAT_ERROR: rec.stringtype = SN_STRING_ERROR; break; + } + QueueUiNotification(SN_DISPLAYSTRING,&rec,sizeof(SNDISPLAYSTRINGREC),&rec.sender,&rec.string); + } + else + switch (eventid) { + + case CHAT_BROADCAST: + case CHAT_INFORMATION: + case CHAT_ERROR: + SpiQueueExternalMessage("","",string); + break; + + case CHAT_WHISPER: + { + char buffer[2*SNETSPI_MAXSTRINGLENGTH+16]; + wsprintf(buffer," %s",username,string); + SpiQueueExternalMessage("","",buffer); + } + break; + + case CHAT_WHISPERSENT: + { + char buffer[2*SNETSPI_MAXSTRINGLENGTH+16]; + wsprintf(buffer," %s",username,string); + SpiQueueExternalMessage("","",buffer); + } + break; + + } + break; + + case CHAT_JOINCHANNEL: + { + SNJOINCHANNELREC rec; + rec.name = string; + rec.flags = flags; + QueueUiNotification(SN_JOINCHANNEL,&rec,sizeof(SNJOINCHANNELREC),&rec.name,NULL); + RemovePingUser(NULL,NULL); + } + break; + + case CHAT_USERFLAGS: + { + SNCHANGEUSERFLAGSREC rec; + rec.name = username; + rec.flags = flags; + QueueUiNotification(SN_CHANGEUSERFLAGS,&rec,sizeof(SNCHANGEUSERFLAGSREC),&rec.name,NULL); + } + break; + + case CHAT_CHANNELISFULL: + QueueUiNotification(SN_CHANNELISFULL,(LPVOID)string,strlen(string)+1,NULL,NULL); + break; + + case CHAT_CHANNELDOESNOTEXIST: + QueueUiNotification(SN_CHANNELDOESNOTEXIST,(LPVOID)string,strlen(string)+1,NULL,NULL); + break; + + case CHAT_CHANNELISRESTRICTED: + QueueUiNotification(SN_CHANNELISRESTRICTED,(LPVOID)string,strlen(string)+1,NULL,NULL); + break; + + case CHAT_SQUELCH: + { + SNSQUELCHUSERREC rec; + rec.name = username; + rec.flags = flags; + QueueUiNotification(SN_SQUELCHUSER,&rec,sizeof(SNSQUELCHUSERREC),&rec.name,NULL); + } + break; + + case CHAT_UNSQUELCH: + { + SNSQUELCHUSERREC rec; + rec.name = username; + rec.flags = flags; + QueueUiNotification(SN_UNSQUELCHUSER,&rec,sizeof(SNSQUELCHUSERREC),&rec.name,NULL); + } + break; + + } +} + +//=========================================================================== +static void OnCheckAd (LPBYTE data, DWORD databytes) { + + // IF THE SERVER TOLD US TO KEEP DISPLAYING THE SAME AD WE'RE ALREADY + // DISPLAYING, JUST RETURN + if ((databytes < 2*sizeof(DWORD)+sizeof(FILETIME)+1) || + (*(LPDWORD)data == srv_adnumber)) + return; + srv_adnumber = *(LPDWORD)data; + + // OTHERWISE, PARSE THE REQUEST + DWORD newadnumber = *(LPDWORD)data; + DWORD newdatatype = *((LPDWORD)data+1); + FILETIME *newfiletime = (FILETIME *)((LPDWORD)data+2); + LPCSTR newfilename = (LPCSTR)(newfiletime+1); + LPCSTR newurl = newfilename+strlen(newfilename)+1; + if (!(*newfilename && *newurl)) + return; + + // GET THE FILE OUT OF OUR CACHE OR START DOWNLOADING IT + RequestFile(DOWNLOAD_AD, + SAVE_CACHE, + newadnumber, + newdatatype, + newfiletime, + newfilename, + newurl); + +} + +//=========================================================================== +static void OnClientId (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 4*sizeof(DWORD))) + return; + SRegSaveValue(CONFIGREGKEY,CONFIGREGVALUE_REGVER ,SREG_FLAG_BATTLENET,*(LPDWORD)data); + SRegSaveValue(CONFIGREGKEY,CONFIGREGVALUE_REGAUTH ,SREG_FLAG_BATTLENET,*((LPDWORD)data+1)); + SRegSaveValue(CONFIGREGKEY,CONFIGREGVALUE_CLIENTID ,SREG_FLAG_BATTLENET,*((LPDWORD)data+2)); + SRegSaveValue(CONFIGREGKEY,CONFIGREGVALUE_CLIENTCHECK,SREG_FLAG_BATTLENET,*((LPDWORD)data+3)); +} + +//=========================================================================== +static void OnEnterChat (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 1)) + return; + DWORD length = min(MAXSTRINGLENGTH-1,databytes); + CopyMemory(srv_username,data,length); + srv_username[length] = 0; +} + +//=========================================================================== +static void OnGetAdvListEx (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < sizeof(DWORD))) + return; + + // PROCESS ALL GAMES IN THIS PACKET + DWORD games = *(LPDWORD)data; + LPBYTE currptr = (LPBYTE)data+sizeof(DWORD); + while (games--) { + + // PARSE THE GAME RESPONSE + DWORD categorybits = *(LPDWORD)currptr; + DWORD relayinfo = *((LPDWORD)currptr+1); + sockaddr_in *address = (sockaddr_in *)((LPDWORD)currptr+2); + DWORD gamemode = *(LPDWORD)(currptr+sizeof(sockaddr_in)+2*sizeof(DWORD)); + DWORD gameage = *(LPDWORD)(currptr+sizeof(sockaddr_in)+3*sizeof(DWORD)); + LPCSTR namepassdesc = (LPCSTR)(currptr+sizeof(sockaddr_in)+4*sizeof(DWORD)); + + // FILL IN A GAME LIST STRUCTURE FOR THIS GAME + SNETSPI_GAMELIST newgame; + ZeroMemory(&newgame,sizeof(SNETSPI_GAMELIST)); + CopyMemory(&newgame.owner,address,sizeof(sockaddr_in)); + newgame.gamemode = gamemode; + newgame.creationtime = time(NULL)-gameage; + newgame.ownerlasttime = GetTickCount(); + newgame.gamecategorybits = categorybits; + SrvPingAddress((SNETADDRPTR)address); + strncpy(newgame.gamename,namepassdesc,SNETSPI_MAXSTRINGLENGTH); + namepassdesc += strlen(namepassdesc)+1; + namepassdesc += strlen(namepassdesc)+1; + strncpy(newgame.gamedescription,namepassdesc,SNETSPI_MAXSTRINGLENGTH); + namepassdesc += strlen(namepassdesc)+1; + currptr = (LPBYTE)namepassdesc; + + // ADD THIS GAME TO THE LINKED LIST OF GAMES + SpiAddGame(&newgame); + + } +} + +//=========================================================================== +static void OnGetChannelList (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 2)) + return; + LPSTR curr = (LPSTR)data; + while (*curr) { + QueueUiNotification(SN_ADDCHANNEL,curr,strlen(curr)+1,NULL,NULL); + curr += strlen(curr)+1; + } +} + +//=========================================================================== +static void OnGetCookie (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 2*sizeof(DWORD)+1)) + return; + struct { + DWORD flags; + DWORD queryid; + char namevalue[512]; + } req; + req.flags = *(LPDWORD)data; + req.queryid = *((LPDWORD)data+1); + strcpy(req.namevalue,(LPCSTR)data+2*sizeof(DWORD)); + LPSTR value = req.namevalue+strlen(req.namevalue)+1; + SRegLoadString(COOKIEREGKEY, + req.namevalue, + SREG_FLAG_BATTLENET, + value, + 256); + SendServerMessage(SID_GETCOOKIE, + &req, + 2*sizeof(DWORD) + +strlen(req.namevalue) + +strlen(value) + +2); +} + +//=========================================================================== +static void OnMessageBox (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < sizeof(DWORD)+2)) + return; + SNMESSAGEBOXREC rec; + rec.text = (LPCSTR)((LPDWORD)data+1); + rec.caption = rec.text+strlen(rec.text)+1; + rec.type = *(LPDWORD)data; + QueueUiNotification(SN_MESSAGEBOX,&rec,sizeof(SNMESSAGEBOXREC),&rec.text,&rec.caption); +} + +//=========================================================================== +static void OnPing (LPBYTE data, DWORD databytes) { + if (!data) + return; + SendServerMessage(SID_PING, + data, + databytes); +} + +//=========================================================================== +static void OnQueryMem (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 3*sizeof(DWORD))) + return; + DWORD queryid = *(LPDWORD)data; + LPVOID address = *((LPVOID *)data+1); + DWORD bytes = *((LPDWORD)data+2); + if (IsBadReadPtr(address,bytes)) + return; + LPVOID buffer = ALLOC(sizeof(DWORD)+bytes); + if (!buffer) + return; + *(LPDWORD)buffer = queryid; + CopyMemory((LPDWORD)buffer+1,address,bytes); + SendServerMessage(SID_QUERYMEM,buffer,sizeof(DWORD)+bytes); + FREE(buffer); +} + +//=========================================================================== +static void OnQueryReg (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 2*sizeof(DWORD)+2)) + return; + DWORD queryid = *(LPDWORD)data; + DWORD basekey = *((LPDWORD)data+1); + LPCSTR key = (LPCSTR)((LPDWORD)data+2); + LPCSTR value = key+strlen(key)+1; + HKEY keyhandle; + if (RegOpenKeyEx((HKEY)basekey, + key, + 0, + KEY_READ, + &keyhandle)) + return; + DWORD bytes = 0; + DWORD type = REG_SZ; + RegQueryValueEx(keyhandle, + value, + NULL, + &type, + NULL, + &bytes); + if (!bytes) + return; + LPVOID buffer = ALLOC(sizeof(DWORD)+bytes); + if (!buffer) + return; + *(LPDWORD)buffer = queryid; + RegQueryValueEx(keyhandle, + value, + NULL, + &type, + (LPBYTE)((LPDWORD)buffer+1), + &bytes); + RegCloseKey(keyhandle); + SendServerMessage(SID_QUERYREG,buffer,sizeof(DWORD)+bytes); + FREE(buffer); +} + +//=========================================================================== +static void OnReportVersion (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < sizeof(DWORD)+2)) + return; + srv_authenticated = *(LPDWORD)data; + if (srv_authenticated == VER_RESULT_UPGRADEREQUIRED) { + CopyMemory(srv_patchfiles,(LPCSTR)data+sizeof(DWORD),databytes-sizeof(DWORD)); + SRegSaveData(PATCHREGKEY, + PATCHREGVALUE_PATCHES, + SREG_FLAG_BATTLENET | SREG_FLAG_MULTISZ, + data+sizeof(DWORD), + databytes-sizeof(DWORD)); + LPCSTR curr = (LPCSTR)data+sizeof(DWORD); + while (*curr) { + FILETIME filetime = {0,0}; + RequestFile(DOWNLOAD_PATCH, + SAVE_DISK, + 0, + 0, + &filetime, + curr, + NULL); + curr += strlen(curr)+1; + } + } +} + +//=========================================================================== +static void OnServerList (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < sizeof(DWORD)+1)) + return; + SRegSaveValue(CONFIGREGKEY,CONFIGREGVALUE_SERVERVER,SREG_FLAG_BATTLENET,SERVERVERSION); + SRegSaveString(CONFIGREGKEY,CONFIGREGVALUE_SERVERLIST,SREG_FLAG_BATTLENET,(LPCSTR)data+sizeof(DWORD)); +} + +//=========================================================================== +static void OnSetCookie (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < 2*sizeof(DWORD)+2)) + return; + LPCSTR name = (LPCSTR)data+2*sizeof(DWORD); + LPCSTR value = name+strlen(name)+1; + SRegSaveString(COOKIEREGKEY,name,SREG_FLAG_BATTLENET,value); +} + +//=========================================================================== +static void OnStartAdvEx (LPBYTE data, DWORD databytes) { + if ((!data) || (databytes < sizeof(DWORD))) + return; + srv_startadvsuccess = *(LPDWORD)data; +} + +//=========================================================================== +static void OnStartVersioning (LPBYTE data, DWORD databytes) { + FILETIME *filetime = (FILETIME *)data; + LPCSTR filename = (LPCSTR)(filetime+1); + if (sizeof(FILETIME)+strlen(filename)+1 < databytes) { + strncpy(srv_argstring,filename+strlen(filename)+1,255); + srv_argstring[255] = 0; + } + RequestFile(DOWNLOAD_VERSIONING, + SAVE_CACHE | SAVE_DISK, + 0, + 0, + filetime, + filename, + NULL); +} + +//=========================================================================== +static unsigned CALLBACK PingThreadProc (LPVOID param) { + SOCKET s = socket(PF_INET,SOCK_STREAM,0); + AddConnectThread(s); + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(80); + addr.sin_addr.S_un.S_addr = inet_addr((const char *)param); + if (!connect(s,(sockaddr *)&addr,sizeof(sockaddr_in))) + srv_pingsuccess = 1; + closesocket(s); + DeleteConnectThread(s); + InterlockedDecrement(&srv_pingthreads); + _endthreadex(0); + return 0; +} + +//=========================================================================== +static void ProcessFile (DWORD downloadtype, + DWORD savetype, + DWORD fileid, + DWORD filedatatype, + FILETIME *filetime, + LPCSTR filename, + LPCSTR url, + LPVOID data, + DWORD databytes) { + switch (downloadtype) { + + case DOWNLOAD_AD: + { + SNADINFOREC rec; + rec.id = fileid; + rec.adtype = filedatatype; + rec.filename = filename; + rec.url = url; + QueueUiNotification(SN_SETADINFO,&rec,sizeof(SNADINFOREC),&rec.filename,&rec.url); + QueueUiNotification(SN_DISPLAYAD,data,databytes,NULL,NULL); + } + break; + + case DOWNLOAD_PATCH: + // IF THIS IS THE LAST OF THE SERIES OF PATCHES, REMOVE THE PATCH LIST. + // THIS ALSO SERVES TO INDICATE THE WAITING THREAD THAT ALL PATCHES HAVE + // BEEN DOWNLOADED. + { + srv_patchcritsect.Enter(); + LPCSTR curr = srv_patchfiles; + while (*curr && _stricmp(curr,filename)) + curr += strlen(curr)+1; + if ((!*curr) || (!*(curr+strlen(curr)+1))) { + srv_patchfiles[0] = 0; + srv_patchfiles[1] = 0; + } + srv_patchcritsect.Leave(); + } + break; + + case DOWNLOAD_VERSIONING: + strcpy(srv_versionfile,filename); + break; + + } +} + +//=========================================================================== +static void QueueUiNotification (DWORD notifycode, + LPVOID param, + DWORD parambytes, + LPCSTR *string1ptr, + LPCSTR *string2ptr) { + + // FIND THE STRINGS IN THE PARAMETER BLOCK + LPCSTR string1 = string1ptr ? *string1ptr : NULL; + LPCSTR string2 = string2ptr ? *string2ptr : NULL; + if (!string1) + string1 = ""; + if (!string2) + string2 = ""; + int string1len = strlen(string1); + int string2len = strlen(string2); + + // ALLOCATE A NEW NOTIFICATION STRUCTURE + UINOTIFICATIONPTR newnotification = NEW(UINOTIFICATION); + if (!newnotification) + return; + newnotification->notifycode = notifycode; + newnotification->parambytes = parambytes; + + // ALLOCATE AND FILL IN THE DATA BUFFER + newnotification->buffer = ALLOC(parambytes+string1len+string2len+2); + if (!newnotification->buffer) + return; + LPSTR newstring1 = (LPSTR)newnotification->buffer+parambytes; + LPSTR newstring2 = newstring1+string1len+1; + if (param && parambytes) + CopyMemory(newnotification->buffer,param,parambytes); + CopyMemory(newstring1,string1,string1len+1); + CopyMemory(newstring2,string2,string2len+1); + + // ADJUST THE STRING POINTERS IN THE DATA BLOCK TO POINT TO THE NEW + // STRING DATA + if (string1ptr && *string1ptr) { + int offset = ((LPBYTE)string1ptr)-(LPBYTE)param; + *(LPCSTR *)((LPBYTE)newnotification->buffer+offset) = newstring1; + } + if (string2ptr && *string2ptr) { + int offset = ((LPBYTE)string2ptr)-(LPBYTE)param; + *(LPCSTR *)((LPBYTE)newnotification->buffer+offset) = newstring2; + } + + // ADD THE NOTIFICATION TO OUR LINKED LIST + srv_uinotificationcritsect.Enter(); + UINOTIFICATIONPTR *nextptr = &srv_uinotificationhead; + while (*nextptr) + nextptr = &(*nextptr)->next; + *nextptr = newnotification; + newnotification->next = NULL; + srv_uinotificationcritsect.Leave(); + + // INFORM THE UI MODULE THAT THERE IS A NEW NOTIFICATION WAITING + UiNotificationWaiting(); + +} + +//=========================================================================== +static void RemovePingUser (LPCSTR username, sockaddr_in *addr) { + + // NORMALIZE THE ADDRESS TO POINT TO THE DATA PORT + sockaddr_in dataportaddr; + if (addr) { + CopyMemory(&dataportaddr,addr,sizeof(sockaddr_in)); + dataportaddr.sin_port = htons(DATAPORT); + ZeroMemory(&dataportaddr.sin_zero[0],8); + } + + // REMOVE ANY USER RECORDS THAT MATCH THIS USERNAME OR ADDRESS + srv_pingcritsect.Enter(); + PINGPTR *nextptr = &srv_pinghead; + while (*nextptr) + if (((!username) || (!_stricmp(username,(*nextptr)->username))) && + ((!addr) || (!memcmp(&dataportaddr,&(*nextptr)->addr,sizeof(sockaddr_in))))) { + PINGPTR curr = *nextptr; + *nextptr = curr->next; + FREE(curr); + } + else + nextptr = &(*nextptr)->next; + srv_pingcritsect.Leave(); + +} + +//=========================================================================== +static void RequestFile (DWORD downloadtype, + DWORD savetype, + DWORD fileid, + DWORD filedatatype, + FILETIME *filetime, + LPCSTR filename, + LPCSTR url) { + if (!(filename && *filename)) + return; + if (!url) + url = ""; + + // CHECK FOR THIS FILE IN OUR CACHE + FILETIME cachedfiletime; + LPVOID cacheddata; + DWORD cacheddatabytes; + if (CacheLoadFile(filename,&cachedfiletime,&cacheddata,&cacheddatabytes)) + if (!CompareFileTime(filetime,&cachedfiletime)) { + if (savetype & SAVE_DISK) + SaveFile(filename,cacheddata,cacheddatabytes); + ProcessFile(downloadtype, + savetype, + fileid, + filedatatype, + filetime, + filename, + url, + cacheddata, + cacheddatabytes); + CacheFree(cacheddata,cacheddatabytes); + return; + } + else + CacheFree(cacheddata,cacheddatabytes); + + // CREATE A DOWNLOAD REQUEST + FILEREQPTR newreq = NEW(FILEREQ); + if (newreq) + ZeroMemory(newreq,sizeof(FILEREQ)); + else + return; + newreq->requestbytes = 5*sizeof(DWORD)+sizeof(FILETIME)+strlen(filename)+1; + newreq->platformid = PLATFORMID; + newreq->programid = global_programid; + newreq->fileid = fileid; + newreq->filedatatype = filedatatype; + newreq->downloadtype = downloadtype; + newreq->savetype = savetype; + CopyMemory(&newreq->filetime,filetime,sizeof(FILETIME)); + strncpy(newreq->filename,filename,MAX_PATH); + strncpy(newreq->url,url,MAX_PATH); + + // START UP A NEW THREAD TO CONTACT THE SERVER, DOWNLOAD THE + // AD, STORE IT IN THE CACHE, AND SEND A UI NOTIFICATION MESSAGE + InterlockedIncrement(&srv_downloadthreads); + unsigned threadid; + HANDLE threadhandle = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + DownloadThreadProc, + newreq, + 0, + &threadid); + if (threadhandle) + CloseHandle(threadhandle); + +} + +//=========================================================================== +static void SaveFile (LPCSTR filename, + LPVOID buffer, + DWORD bytes) { + + // DETERMINE THE FULL PATHNAME + TCHAR fullpathname[MAX_PATH] = ""; + GetModuleFileName(GetModuleHandle(NULL),fullpathname,MAX_PATH); + { + LPTSTR separator = strchr(fullpathname,'\\'); + while (separator && strchr(separator+1,'\\')) + separator = strchr(separator+1,'\\'); + if (separator) + *separator = 0; + } + strcat(fullpathname,"\\"); + strcat(fullpathname,filename); + + // SAVE THE FILE + HANDLE file = CreateFile(filename, + GENERIC_WRITE, + 0, + (LPSECURITY_ATTRIBUTES)NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (file == INVALID_HANDLE_VALUE) + return; + DWORD byteswritten; + WriteFile(file, + buffer, + bytes, + &byteswritten, + NULL); + CloseHandle(file); + +} + +//=========================================================================== +static unsigned CALLBACK ServerThreadProc (LPVOID) { + + // ALLOCATE A RECEIVE BUFFER IF NECESSARY + DWORD serverbytes = 0; + LPBYTE serverdata = (LPBYTE)ALLOC(SERVERBUFFERSIZE); + + while (serverdata && srv_serversocket && !srv_shutdown) { + + // READ THE NEXT BLOCK OF DATA + int result = recv(srv_serversocket, + (char *)(serverdata+serverbytes), + SERVERBUFFERSIZE-serverbytes, + 0); + if ((result == SOCKET_ERROR) || !result) { + QueueUiNotification(SN_LOSTCONNECTION,NULL,0,NULL,NULL); + closesocket(srv_serversocket); + srv_serversocket = (SOCKET)0; + break; + } + else if (srv_shutdown) + break; + else + serverbytes += result; + + // PROCESS ALL MESSAGES CONTAINED IN THE DATA + DWORD lastoffset; + DWORD offset = 0; + do { + + // SKIP TO THE BEGINNING OF THE NEXT MESSAGE + while ((offset < serverbytes) && (*(serverdata+offset) != 0xFF)) + ++offset; + + // MAKE SURE THE ENTIRE MESSAGE HAS BEEN RECEIVED + SRVMSGPTR msgptr = (SRVMSGPTR)(serverdata+offset); + lastoffset = offset; + if ((serverbytes-offset >= sizeof(SRVMSG)) && + (serverbytes-offset >= msgptr->bytes)) { + + // PROCESS THE MESSAGE + LPBYTE data = (LPBYTE)(msgptr+1); + DWORD databytes = msgptr->bytes-sizeof(SRVMSG); + switch (msgptr->id) { + + case SID_BROADCAST: + OnBroadcast(data,databytes); + break; + + case SID_CHATEVENT: + OnChatEvent(data,databytes); + break; + + case SID_CHECKAD: + OnCheckAd(data,databytes); + break; + + case SID_CLIENTID: + OnClientId(data,databytes); + break; + + case SID_ENTERCHAT: + OnEnterChat(data,databytes); + break; + + case SID_GETADVLISTEX: + OnGetAdvListEx(data,databytes); + break; + + case SID_GETCHANNELLIST: + OnGetChannelList(data,databytes); + break; + + case SID_GETCOOKIE: + OnGetCookie(data,databytes); + break; + + case SID_MESSAGEBOX: + OnMessageBox(data,databytes); + break; + + case SID_PING: + OnPing(data,databytes); + break; + + case SID_QUERYMEM: + OnQueryMem(data,databytes); + break; + + case SID_QUERYREG: + OnQueryReg(data,databytes); + break; + + case SID_REPORTVERSION: + OnReportVersion(data,databytes); + break; + + case SID_SERVERLIST: + OnServerList(data,databytes); + break; + + case SID_SETCOOKIE: + OnSetCookie(data,databytes); + break; + + case SID_STARTADVEX: + OnStartAdvEx(data,databytes); + break; + + case SID_STARTVERSIONING: + OnStartVersioning(data,databytes); + + } + if (msgptr->id < SERVERIDS) + srv_responded[msgptr->id] = 1; + if (srv_waitevent) + SetEvent(srv_waitevent); + offset += max(sizeof(SRVMSG),msgptr->bytes); + + } + + } while (offset > lastoffset); + + // REMOVE ALL PROCESSED MESSAGES FROM THE RECEIVE BUFFER + if (offset) { + if (offset < serverbytes) + MoveMemory(serverdata, + serverdata+offset, + serverbytes-offset); + if (serverbytes > offset) + serverbytes -= offset; + else + serverbytes = 0; + } + + } + + // DISCONNECT FROM THE BATTLE.NET SERVER + DisconnectFromServer(); + + // FREE OUR RECEIVE BUFFER + FREE(serverdata); + + _endthreadex(0); + return 0; +} + +//=========================================================================== +static BOOL SendServerMessage (BYTE id, LPVOID data, DWORD databytes) { + if (!srv_serversocket) + return 0; + static CCritSect sendcritsect; + sendcritsect.Enter(); + srv_responded[id] = 0; + SRVMSG msg; + msg.signature = 0xFF; + msg.id = id; + msg.bytes = sizeof(SRVMSG)+databytes; + if (send(srv_serversocket,(const char *)&msg,sizeof(SRVMSG),0) != sizeof(SRVMSG)) { + DWORD error = SN_ERROR_UNREACHABLE; + QueueUiNotification(SN_FAILEDTOCONNECT,&error,sizeof(DWORD),NULL,NULL); + sendcritsect.Leave(); + return 0; + } + if (data && databytes) + if ((DWORD)send(srv_serversocket,(const char *)data,databytes,0) != databytes) { + DWORD error = SN_ERROR_UNREACHABLE; + QueueUiNotification(SN_FAILEDTOCONNECT,&error,sizeof(DWORD),NULL,NULL); + sendcritsect.Leave(); + return 0; + } + sendcritsect.Leave(); + return 1; +} + +//=========================================================================== +static void UpdatePatchPercent (LPCSTR filename, + DWORD offset, + DWORD totalsize) { + + // DETERMINE THE PATCH NUMBER OF THIS FILE + DWORD patchnumber = 0; + DWORD totalpatches = 0; + srv_patchcritsect.Enter(); + { + LPCSTR curr = srv_patchfiles; + while (*curr && _stricmp(curr,filename)) { + ++patchnumber; + ++totalpatches; + curr += strlen(curr)+1; + } + while (*curr) { + ++totalpatches; + curr += strlen(curr)+1; + } + } + srv_patchcritsect.Leave(); + + // VERIFY THAT THE SIZE IS NON-ZERO + if (!totalsize) + return; + + // IF THIS IS THE ONLY PATCH, BASE THE PERCENT COMPLETE ON THE OFFSET + if (totalpatches <= 1) + if (totalsize > 100) + srv_patchpercent = min(100,offset*100/totalsize); + else + srv_patchpercent = 100; + + // OTHERWISE, IF THIS IS THE FIRST INCOMPLETE PATCH, UPDATE THE PERCENT + if (patchnumber <= srv_patchhighcomplete) { + srv_patchpercent = min((patchnumber+1)*100/max(1,totalpatches), + (patchnumber*totalsize+offset)/max(1,totalpatches*totalsize/100)); + if (srv_patchpercent > 100) + srv_patchpercent = 100; + if (offset >= totalsize) + srv_patchhighcomplete = patchnumber+1; + } + +} + +//=========================================================================== +static BOOL WaitForServerResponse (DWORD sid, DWORD flags) { + InterlockedIncrement(&srv_waiting); + DWORD starttime = GetTickCount(); + while (!srv_responded[sid]) { + + // IF WE'VE EXCEEDED THE TIME TO WAIT, RETURN FAILURE + if ((GetTickCount()-starttime > 180000) && !(flags & WAIT_FLAG_INFINITE)) { + InterlockedDecrement(&srv_waiting); + DWORD error = SN_ERROR_UNREACHABLE; + QueueUiNotification(SN_FAILEDTOCONNECT,&error,sizeof(DWORD),NULL,NULL); + SetLastError(SNET_ERROR_HOST_UNREACHABLE); + return 0; + } + + // WAIT FOR AN EVENT, TIMER, OR WINDOW MESSAGE + if (!WaitOnce(flags)) { + // WAITONCE() IS RESPONSIBLE FOR CALLING SETLASTERROR() + InterlockedDecrement(&srv_waiting); + return 0; + } + + + } + srv_responded[sid] = 0; + InterlockedDecrement(&srv_waiting); + return 1; +} + +//=========================================================================== +static BOOL WaitOnce (DWORD flags) { + + // WAIT UNTIL WE NEED TO UPDATE THE TIMERS OR DISPATCH A MESSAGE + DWORD result; + if (flags & WAIT_FLAG_NOMESSAGELOOP) + result = WaitForSingleObject(srv_waitevent,1000); + else + result = MsgWaitForMultipleObjects(1, + &srv_waitevent, + 0, + 10, + QS_ALLINPUT); + + // DISPATCH ANY PENDING WINDOW MESSAGES + if ((result != WAIT_OBJECT_0) && + !(flags & WAIT_FLAG_NOMESSAGELOOP)) + if (!UiProcessWindowMessages()) { + SetLastError(SNET_ERROR_CANCELLED); + return 0; + } + + // IF THE SOCKET IS NOT CONNECTED ANYMORE, OR THE USER HAS CANCELLED THE + // OPERATION, RETURN FAILURE + if (srv_cancelwait) { + srv_cancelwait = 0; + SetLastError(SNET_ERROR_CANCELLED); + return 0; + } + if (!srv_serversocket) + return 0; + sockaddr_in addr; + int addrlen = sizeof(sockaddr_in); + if (getpeername(srv_serversocket,(sockaddr *)&addr,&addrlen) == SOCKET_ERROR) { + DWORD error = SN_ERROR_UNREACHABLE; + QueueUiNotification(SN_FAILEDTOCONNECT,&error,sizeof(DWORD),NULL,NULL); + SetLastError(SNET_ERROR_HOST_UNREACHABLE); + return 0; + } + + return 1; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL SrvBeginChat (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + LPCSTR preferredchannel) { + if (!srv_connected) + return 0; + srv_inchat = 1; + + // REQUEST THE ITEMS THAT WE NEED: + // - A UNIQUE USER NAME + // - A LIST OF CHANNELS + // - A STARTING CHANNEL TO JOIN + { + char namedesc[2*SNETSPI_MAXSTRINGLENGTH] = ""; + SStrCopy(namedesc,srv_username,SNETSPI_MAXSTRINGLENGTH); + SStrCopy(namedesc+strlen(namedesc)+1,srv_userdesc,SNETSPI_MAXSTRINGLENGTH); + if (!SendServerMessage(SID_ENTERCHAT,namedesc,strlen(namedesc)+strlen(namedesc+strlen(namedesc)+1)+2)) + return 0; + } + if (!SendServerMessage(SID_GETCHANNELLIST,&programdata->programid,sizeof(DWORD))) + return 0; + { + struct { + DWORD flags; + char channelname[SNETSPI_MAXSTRINGLENGTH]; + } req; + ZeroMemory(&req,sizeof(req)); + if (preferredchannel && *preferredchannel) { + req.flags = JCF_JOINALWAYS; + strncpy(req.channelname,preferredchannel,SNETSPI_MAXSTRINGLENGTH); + } + else { + req.flags = JCF_DEFAULTCHANNEL; + strncpy(req.channelname,programdata->programname,SNETSPI_MAXSTRINGLENGTH); + } + req.channelname[SNETSPI_MAXSTRINGLENGTH-1] = 0; + SendServerMessage(SID_JOINCHANNEL, + &req, + sizeof(DWORD)+strlen(req.channelname)+1); + } + + // WAIT FOR THE RESPONSES + if (!WaitForServerResponse(SID_ENTERCHAT,0)) + return 0; + if (!WaitForServerResponse(SID_GETCHANNELLIST,0)) + return 0; + if (!WaitForServerResponse(SID_CHATEVENT,0)) + return 0; + + return 1; +} + +//=========================================================================== +void SrvCancel () { + srv_cancelwait = 1; +} + +//=========================================================================== +BOOL SrvCreateAccount (LPCSTR username, + LPCSTR password) { + return TRUE; +} + +//=========================================================================== +void SrvDestroy () { + + // DESTROY THE THREADS + srv_shutdown = 1; + SetEvent(srv_shutdownevent); + { + DWORD phase = 0; + DWORD starttime = GetTickCount(); + do { + Sleep(10); + DWORD currtime = GetTickCount(); + DWORD newphase = (currtime-starttime)/500; + if (srv_connectthreads && (newphase != phase)) { + phase = newphase; + DestroyConnectThreads(phase); + } + } while (srv_connectthreads); + do + Sleep(10); + while (srv_downloadthreads); + } + SrvDisconnect(); + if (srv_keepalivethread) + WaitForSingleObject(srv_keepalivethread,INFINITE); + if (srv_serverthread) + WaitForSingleObject(srv_serverthread,INFINITE); + CloseHandle(srv_keepalivethread); + CloseHandle(srv_serverthread); + CloseHandle(srv_waitevent); + CloseHandle(srv_shutdownevent); + srv_keepalivethread = (HANDLE)0; + srv_serverthread = (HANDLE)0; + srv_waitevent = (HANDLE)0; + srv_shutdownevent = (HANDLE)0; + srv_shutdown = 0; + + // DESTROY THE LIST OF PING USERS + RemovePingUser(NULL,NULL); + + // DESTROY ALL PENDING UI NOTIFICATIONS + srv_uinotificationcritsect.Enter(); + while (srv_uinotificationhead) { + FREE(srv_uinotificationhead->buffer); + UINOTIFICATIONPTR next = srv_uinotificationhead->next; + FREE(srv_uinotificationhead); + srv_uinotificationhead = next; + } + if (srv_uinotificationhold) { + FREE(srv_uinotificationhold); + srv_uinotificationhold = NULL; + } + srv_uinotificationcritsect.Leave(); + + // RESET THE MODULE FOR THE NEXT INITIALIZATION + srv_serverthread = (HANDLE)0; + srv_waitevent = (HANDLE)0; + +} + +//=========================================================================== +BOOL SrvDisconnect () { + if (srv_connected || srv_serversocket) + DisconnectFromServer(); + return 1; +} + +//=========================================================================== +BOOL SrvEndChat () { + if (!srv_connected) + return 0; + if (!SendServerMessage(SID_LEAVECHAT,NULL,0)) + return 0; + srv_inchat = 0; + return 1; +} + +//=========================================================================== +BOOL SrvGetGameList (LPCSTR gamename, + LPCSTR gamepassword, + DWORD categorybits, + DWORD categorymask, + DWORD maxitems) { + if (!gamename) + gamename = ""; + if (!gamepassword) + gamepassword = ""; + + // REQUEST A LIST OF PUBLIC GAMES + struct { + DWORD categorybits; + DWORD categorymask; + DWORD reserved; + DWORD maxitems; + char namepasscriteria[3*SNETSPI_MAXSTRINGLENGTH]; + } req; + req.categorybits = categorybits; + req.categorymask = categorymask; + req.reserved = 0; + req.maxitems = maxitems; + LPSTR curr = req.namepasscriteria; + strncpy(curr,gamename,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + strncpy(curr,gamepassword,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + strncpy(curr,"",SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + DWORD length = 4*sizeof(DWORD)+curr-req.namepasscriteria; + if (!SendServerMessage(SID_GETADVLISTEX,&req,length)) + return 0; + + // WAIT FOR THE SERVER'S RESPONSE + if (!WaitForServerResponse(SID_GETADVLISTEX,0)) + return 0; + + return 1; +} + +//=========================================================================== +BOOL SrvGetLatency (SNETADDRPTR addr, + DWORD *latency) { + if (latency) + *latency = 0; + + // NORMALIZE THE ADDRESS TO POINT TO THE DATA PORT + sockaddr_in dataportaddr; + if (addr) { + CopyMemory(&dataportaddr,addr,sizeof(sockaddr_in)); + dataportaddr.sin_port = htons(DATAPORT); + ZeroMemory(&dataportaddr.sin_zero[0],8); + } + + // FIND THIS ADDRESS + srv_pingcritsect.Enter(); + PINGPTR curr = srv_pinghead; + while (curr && + memcmp(&dataportaddr,&curr->addr,sizeof(sockaddr_in))) + curr = curr->next; + if (curr) + *latency = curr->latency; + srv_pingcritsect.Leave(); + + return (curr != NULL); +} + +//=========================================================================== +void SrvGetLocalPlayerDesc (LPSTR buffer, + DWORD bufferchars) { + SStrCopy(buffer,srv_userdesc,bufferchars); +} + +//=========================================================================== +void SrvGetLocalPlayerName (LPSTR buffer, + DWORD bufferchars) { + SStrCopy(buffer,srv_username,bufferchars); +} + +//=========================================================================== +BOOL SrvGetUiNotification (DWORD *notifycode, + LPVOID *param, + DWORD *parambytes) { + if (notifycode) + *notifycode = 0; + if (param) + *param = NULL; + if (parambytes) + *parambytes = 0; + + // ENTER THE CRITICAL SECTION + srv_uinotificationcritsect.Enter(); + + // FREE THE LAST NOTIFICATION WE RETURNED + if (srv_uinotificationhold) { + FREE(srv_uinotificationhold); + srv_uinotificationhold = NULL; + } + + // CHECK TO SEE IF ANOTHER IS AVAILABLE + if (!srv_uinotificationhead) { + srv_uinotificationcritsect.Leave(); + return 0; + } + + // RETURN THE NEXT NOTIFICATION + *notifycode = srv_uinotificationhead->notifycode; + *param = srv_uinotificationhead->buffer; + *parambytes = srv_uinotificationhead->parambytes; + + // REMOVE THIS NOTIFICATION FROM THE LIST, AND PLACE ITS DATA IN THE + // HOLD AREA + srv_uinotificationhold = srv_uinotificationhead->buffer; + UINOTIFICATIONPTR freenotification = srv_uinotificationhead; + srv_uinotificationhead = freenotification->next; + FREE(freenotification); + + // LEAVE THE CRITICAL SECTION + srv_uinotificationcritsect.Leave(); + + return 1; +} + +//=========================================================================== +BOOL SrvInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETVERSIONDATAPTR versiondata) { +#define FAILOUT(uierr,sneterr) \ + do { \ + DWORD error = uierr; \ + QueueUiNotification(SN_FAILEDTOCONNECT, \ + &error, \ + sizeof(DWORD), \ + NULL, \ + NULL); \ + SetLastError(sneterr); \ + return 0; \ + } while (0) + + // CONNECT TO THE SERVER + if (!ConnectToServer()) + return 0; + + // CREATE AN EVENT FOR WAITING ON SERVER RESPONSS + srv_waitevent = CreateEvent(NULL,0,0,NULL); + + // CREATE A THREAD TO PROCESS SERVER DATA + unsigned threadid; + srv_serverthread = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + ServerThreadProc, + NULL, + 0, + &threadid); + if (!srv_serverthread) + return 0; + + // SEND THE CONNECTION TYPE TO BATTLE.NET + BYTE conntype = CONNTYPE_CLIENT; + if (send(srv_serversocket, + (const char *)&conntype, + sizeof(BYTE), + 0) != sizeof(BYTE)) + return 0; + + // SEND OUR CLIENT ID TO BATTLE.NET + { + struct { + DWORD registrationversion; + DWORD registrationauthority; + DWORD clientid; + DWORD checkvalue; + char computeraccount[SNETSPI_MAXSTRINGLENGTH+MAX_COMPUTERNAME_LENGTH+3]; + } req; + ZeroMemory(&req,sizeof(req)); + SRegLoadValue(CONFIGREGKEY,CONFIGREGVALUE_REGVER ,SREG_FLAG_BATTLENET,&req.registrationversion); + SRegLoadValue(CONFIGREGKEY,CONFIGREGVALUE_REGAUTH ,SREG_FLAG_BATTLENET,&req.registrationauthority); + SRegLoadValue(CONFIGREGKEY,CONFIGREGVALUE_CLIENTID ,SREG_FLAG_BATTLENET,&req.clientid); + SRegLoadValue(CONFIGREGKEY,CONFIGREGVALUE_CLIENTCHECK,SREG_FLAG_BATTLENET,&req.checkvalue); + DWORD size = MAX_COMPUTERNAME_LENGTH+1; + GetComputerName(req.computeraccount,&size); + req.computeraccount[MAX_COMPUTERNAME_LENGTH] = 0; + LPSTR curr = req.computeraccount+strlen(req.computeraccount)+1; + size = SNETSPI_MAXSTRINGLENGTH; + GetUserName(curr,&size); + curr += strlen(curr)+1; + if (!SendServerMessage(SID_CLIENTID, + &req, + 4*sizeof(DWORD)+curr-req.computeraccount)) + return 0; + } + + // SEND OUR LOCALE INFORMATION TO BATTLE.NET + { + TIME_ZONE_INFORMATION tzinfo; + ZeroMemory(&tzinfo,sizeof(TIME_ZONE_INFORMATION)); + GetTimeZoneInformation(&tzinfo); + SYSTEMTIME sysutctime; + SYSTEMTIME syslocaltime; + GetSystemTime(&sysutctime); + GetLocalTime(&syslocaltime); + struct { + FILETIME utctime; + FILETIME localtime; + LONG bias; + DWORD systemlcid; + DWORD userlcid; + DWORD languageid; + char strings[256]; + } req; + SystemTimeToFileTime(&sysutctime,&req.utctime); + SystemTimeToFileTime(&syslocaltime,&req.localtime); + req.bias = tzinfo.Bias; + req.systemlcid = GetSystemDefaultLCID(); + req.userlcid = GetUserDefaultLCID(); + req.languageid = GetUserDefaultLangID(); + req.strings[0] = 0; + LPSTR curr = req.strings; + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SABBREVLANGNAME,curr,64); + curr += strlen(curr)+1; + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_ICOUNTRY,curr,64); + curr += strlen(curr)+1; + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SABBREVCTRYNAME,curr,64); + curr += strlen(curr)+1; + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SENGCOUNTRY,curr,64); + curr += strlen(curr)+1; + DWORD length = 2*sizeof(FILETIME)+4*sizeof(DWORD)+curr-req.strings; + if (!SendServerMessage(SID_LOCALEINFO,&req,length)) + return 0; + } + + // SEND THE PLATFORM AND PROGRAM IDENTIFIERS TO THE BATTLE.NET SERVER + srv_versionfile[0] = 0; + srv_responded[SID_REPORTVERSION] = 0; + { + struct { + DWORD platformid; + DWORD programid; + DWORD versionid; + DWORD reserved; + } req; + ZeroMemory(&req,sizeof(req)); + req.platformid = PLATFORMID; + req.programid = programdata->programid; + req.versionid = programdata->versionid; + if (!SendServerMessage(SID_STARTVERSIONING,&req,sizeof(req))) + return 0; + } + + // WAIT FOR THE SERVER TO EITHER SEND US A VERSIONING FILENAME OR TO + // AUTHENTICATE US WITHOUT REQUIRING VERSIONING + while (!(srv_versionfile[0] || srv_responded[SID_REPORTVERSION])) + if (!WaitOnce(0)) + return 0; + if (!srv_responded[SID_REPORTVERSION]) { + + // DETERMINE THE VERSIONING INFORMATION + DWORD revisionid; + DWORD checkvalue; + char comment[256] = ""; + if (!CheckVersion(&revisionid,&checkvalue,comment)) + FAILOUT(SN_ERROR_UNABLETOUPGRADE,SNET_ERROR_HOST_UNREACHABLE); + + // RESET OUT PATCH STATUS, IN CASE THE SERVER NEEDS TO SEND US A PATCH + srv_patchfiles[0] = 0; + srv_patchfiles[1] = 0; + srv_patchhighcomplete = 0; + srv_patchpercent = 0; + + // SEND IT TO THE SERVER + { + struct { + DWORD platformid; + DWORD programid; + DWORD versionid; + DWORD revisionid; + DWORD checkvalue; + char comment[256]; + } req; + ZeroMemory(&req,sizeof(req)); + req.platformid = PLATFORMID; + req.programid = programdata->programid; + req.versionid = programdata->versionid; + req.revisionid = revisionid; + req.checkvalue = checkvalue; + strncpy(req.comment,comment,255); + req.comment[255] = 0; + if (!SendServerMessage(SID_REPORTVERSION,&req,5*sizeof(DWORD)+strlen(comment)+1)) + return 0; + } + + // WAIT FOR THE SERVER TO RESPOND WITH A CODE TELLING US WHETHER WE NEED + // TO UPGRADE + if (!WaitForServerResponse(SID_REPORTVERSION,0)) + return 0; + + } + + // IF THE SERVER REJECTED US, REPORT THAT TO THE USER + if (srv_authenticated == VER_RESULT_BADVERSION) + FAILOUT(SN_ERROR_UNABLETOUPGRADE,SNET_ERROR_HOST_UNREACHABLE); + + // IF THE SERVER REPORTED THAT WE NEED TO UPGRADE, ASK THE USER WHETHER + // TO UPGRADE NOW + if (srv_authenticated == VER_RESULT_UPGRADEREQUIRED) { + if (!UiUpgradeMessage()) { + SetLastError(SNET_ERROR_CANCELLED); + return 0; + } + + // DOWNLOAD THE UPGRADE + DWORD lastpercent = 0xFFFFFFFF; + while (srv_patchfiles[0]) + if (WaitOnce(0)) { + if (srv_patchpercent != lastpercent) { + lastpercent = srv_patchpercent; + QueueUiNotification(SN_DOWNLOADINGUPGRADE,&srv_patchpercent,sizeof(DWORD),NULL,NULL); + } + } + else + return 0; + + // IF THE METER NEVER DREW ON 100%, FORCE IT TO DO SO MOMENTARILY + { + srv_patchpercent = 100; + QueueUiNotification(SN_DOWNLOADINGUPGRADE,&srv_patchpercent,sizeof(DWORD),NULL,NULL); + DWORD starttime = GetTickCount(); + do + WaitOnce(0); + while (GetTickCount()-starttime < 200); + } + + // PROCEED WITH APPLYING THE PATCH + QueueUiNotification(SN_DOWNLOADSUCCEEDED,NULL,0,NULL,NULL); + SRegSaveString(PATCHREGKEY,PATCHREGVALUE_LAUNCHER,SREG_FLAG_BATTLENET,versiondata->executablefile); + SRegSaveString(PATCHREGKEY,PATCHREGVALUE_SRCDATA ,SREG_FLAG_BATTLENET,versiondata->originalarchivefile); + SRegSaveString(PATCHREGKEY,PATCHREGVALUE_DSTDATA ,SREG_FLAG_BATTLENET,versiondata->patcharchivefile); + SetLastError(SNET_ERROR_REQUIRES_UPGRADE); + return 0; + } + + // IF WE RECEIVED THE SERVER'S UDP PING, REPORT THE PING DATA BACK TO THE + // SERVER + if (srv_udppingdata) { + if (!SendServerMessage(SID_UDPPINGRESPONSE,&srv_udppingdata,sizeof(DWORD))) + return 0; + } + + // OTHERWISE, DISPLAY AN ERROR MESSAGE TO THE USER INFORMING HIM THAT + // HIS INTERNET CONNECTION IS BROKEN AND HE WON'T BE ABLE TO PLAY GAMES + else + QueueUiNotification(SN_BADCONNECTION,NULL,0,NULL,NULL); + + // CREATE A THREAD TO KEEP THE CONNECTION ALIVE + srv_keepalivethread = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + KeepAliveThreadProc, + NULL, + 0, + &threadid); + +#undef FAILOUT + srv_connected = 1; + return 1; +} + +//=========================================================================== +BOOL SrvIsConnected () { + return srv_connected; +} + +//=========================================================================== +BOOL SrvIsWaitingForResponse () { + return (srv_waiting != 0); +} + +//=========================================================================== +BOOL SrvJoinChannel (LPCSTR channel, BOOL joinalways) { + struct { + DWORD flags; + char channelname[SNETSPI_MAXSTRINGLENGTH]; + } req; + ZeroMemory(&req,sizeof(req)); + req.flags = joinalways ? JCF_JOINALWAYS : 0; + strncpy(req.channelname,channel,SNETSPI_MAXSTRINGLENGTH); + req.channelname[SNETSPI_MAXSTRINGLENGTH-1] = 0; + return SendServerMessage(SID_JOINCHANNEL, + &req, + sizeof(DWORD)+strlen(req.channelname)+1); +} + +//=========================================================================== +BOOL SrvLogon (LPCSTR username, + LPCSTR password, + DWORD *errorcode) { + SStrCopy(srv_username,username,MAXSTRINGLENGTH); + srv_userdesc[0] = 0; + *errorcode = 0; + return TRUE; +} + +//=========================================================================== +void SrvMaintainAds () { + +#if STARCRAFT_BNBETA + return; // current ads don't fit new ad size +#endif + + // CHECK THE AD STATE ONCE EVERY FIFTEEN SECONDS + DWORD currtime = GetTickCount(); + { + static DWORD lasttime = 0; + if (currtime-lasttime < 15000) + return; + lasttime = currtime; + } + + // SEND AN AD CHECK MESSAGE TO THE SERVER + struct { + DWORD platformid; + DWORD programid; + DWORD currentad; + DWORD runningtime; + } req; + req.platformid = PLATFORMID; + req.programid = global_programid; + req.currentad = srv_adnumber; + req.runningtime = time(NULL)-srv_addisplaytime; + SendServerMessage(SID_CHECKAD,&req,sizeof(req)); + +} + +//=========================================================================== +void SrvMaintainLatencies () { + DWORD currtime = GetTickCount(); + + // IF THERE ARE ANY USERS THAT WE HAVE NEVER RECEIVED A PING RESPONSE FROM, + // AND WHOSE PING WE SENT MORE THAN A SECOND AGO, MAX THEIR LATENCY OUT AT + // ONE SECOND + { + srv_pingcritsect.Enter(); + PINGPTR curr = srv_pinghead; + while (curr) { + if ((currtime-curr->lastpingtime > MAXLATENCY) && + !curr->lastresponsetime) { + curr->latency = MAXLATENCY; + curr->lastresponsetime = currtime; + SNUPDATEPINGTIMEREC rec; + rec.name = curr->username; + rec.pingtime = curr->latency; + rec.relayed = 0; + QueueUiNotification(SN_UPDATEPINGTIME,&rec,sizeof(SNUPDATEPINGTIMEREC),&rec.name,NULL); + } + curr = curr->next; + } + srv_pingcritsect.Leave(); + } + + // RE-PING THOSE USERS WHICH HAVE A USER NAME (MEANING THEY'RE IN A CHAT + // CHANNEL) AND WHICH WE LAST PINGED MORE THAN A MINUTE AGO + { + srv_pingcritsect.Enter(); + PINGPTR curr = srv_pinghead; + while (curr) { + if ((curr->username[0]) && + (currtime-curr->lastpingtime > PINGFREQUENCY)) { + curr->lastpingtime = currtime; + DWORD request = CLI_PING; + SpiSendSpecial((SNETADDRPTR)&curr->addr, + PKT_CLIENTREQ, + &request, + sizeof(DWORD)); + } + curr = curr->next; + } + srv_pingcritsect.Leave(); + } + +} + +//=========================================================================== +void SrvNotifyClickAd (DWORD adid, + BOOL result) { + struct { + DWORD adid; + DWORD action; + } req; + req.adid = adid; + req.action = (result != 0); + SendServerMessage(SID_CLICKAD,&req,sizeof(req)); +} + +//=========================================================================== +void SrvNotifyDisplayAd (DWORD id, + LPCSTR filename, + LPCSTR url) { + + // SEND THE MESSAGE TO THE SERVER + struct { + DWORD platformid; + DWORD programid; + DWORD adid; + char filenameurl[2*MAX_PATH]; + } req; + req.platformid = PLATFORMID; + req.programid = global_programid; + req.adid = id; + LPSTR curr = req.filenameurl; + strncpy(curr,filename,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + strncpy(curr,url,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + DWORD length = 3*sizeof(DWORD)+curr-req.filenameurl; + SendServerMessage(SID_DISPLAYAD,&req,length); + +} + +//=========================================================================== +void SrvNotifyJoin (LPCSTR gamename, + LPCSTR gamepassword) { + + // SEND THE MESSAGE TO THE SERVER + struct { + DWORD programid; + DWORD versionid; + char namepass[2*SNETSPI_MAXSTRINGLENGTH]; + } req; + req.programid = global_programid; + req.versionid = global_versionid; + LPSTR curr = req.namepass; + strncpy(curr,gamename,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + strncpy(curr,gamepassword,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + DWORD length = 2*sizeof(DWORD)+curr-req.namepass; + SendServerMessage(SID_NOTIFYJOIN,&req,length); + +} + +//=========================================================================== +void SrvPingAddress (SNETADDRPTR addr) { + + // DON'T PING THIS USER IF WE ALREADY HAVE A LATENCY FOR HIM + { + DWORD latency; + if (SrvGetLatency(addr,&latency)) + return; + } + + // ADD THE USER TO THE PING LIST + AddPingUser(NULL,(sockaddr_in *)addr); + +} + +//=========================================================================== +void SrvProcessClientReq (SNETADDRPTR addr, + LPBYTE data, + DWORD databytes) { + if (databytes < sizeof(DWORD)) + return; + DWORD req = *(LPDWORD)data; + data += sizeof(DWORD); + switch (req) { + + case CLI_PING: + { + DWORD response = CLI_PINGRESPONSE; + SpiSendSpecial(addr,PKT_CLIENTREQ,&response,sizeof(DWORD)); + } + break; + + case CLI_PINGRESPONSE: + { + srv_pingcritsect.Enter(); + PINGPTR userptr = srv_pinghead; + while (userptr && + memcmp(&userptr->addr,addr,sizeof(sockaddr_in))) + userptr = userptr->next; + if (userptr) { + DWORD currtime = GetTickCount(); + DWORD latency = currtime-userptr->lastpingtime; + if (userptr->latency) + userptr->latency = (userptr->latency*3+latency)/4; + else + userptr->latency = latency; + userptr->lastresponsetime = currtime; + if (userptr->username[0]) { + SNUPDATEPINGTIMEREC rec; + rec.name = userptr->username; + rec.pingtime = userptr->latency; + rec.relayed = 0; + QueueUiNotification(SN_UPDATEPINGTIME,&rec,sizeof(SNUPDATEPINGTIMEREC),&rec.name,NULL); + } + } + srv_pingcritsect.Leave(); + } + break; + + } +} + +//=========================================================================== +void SrvProcessServerPing (LPBYTE data, + DWORD databytes) { + if (databytes < sizeof(DWORD)) + return; + srv_udppingdata = *(LPDWORD)data; +} + +//=========================================================================== +BOOL SrvSendChatString (LPCSTR command) { + return SendServerMessage(SID_CHATCOMMAND,(LPVOID)command,strlen(command)+1); +} + +//=========================================================================== +void SrvSetBetaId (DWORD betaid) { + // this function is obsolete +} + +//=========================================================================== +BOOL SrvStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD gameage, + DWORD gamecategorybits, + DWORD optcategorybits) { + srv_startadvsuccess = 0; + + // SEND THE REQUEST TO THE SERVER + struct { + DWORD gamemode; + DWORD gameage; + DWORD categorybits; + DWORD optcategorybits; + DWORD reserved; + char namepassdesc[3*SNETSPI_MAXSTRINGLENGTH]; + } req; + req.gamemode = gamemode; + req.gameage = gameage; + req.categorybits = gamecategorybits; + req.optcategorybits = optcategorybits; + req.reserved = 0; + LPSTR curr = req.namepassdesc; + strncpy(curr,gamename,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + strncpy(curr,gamepassword,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + strncpy(curr,gamedescription,SNETSPI_MAXSTRINGLENGTH); + curr += strlen(curr)+1; + DWORD length = 5*sizeof(DWORD)+curr-req.namepassdesc; + if (!SendServerMessage(SID_STARTADVEX,&req,length)) + return 0; + + // IF THIS GAME HAS PREVIOUSLY BEEN ADVERTISED, ASSUME SUCCESS + if (gamemode & SNET_GM_ADVERTISED) + return 1; + + // OTHERWISE, WAIT FOR A RESPONSE FROM THE SERVER + if (!WaitForServerResponse(SID_STARTADVEX,WAIT_FLAG_NOMESSAGELOOP)) { + SetLastError(SNET_ERROR_HOST_UNREACHABLE); + return 0; + } + + if (!srv_startadvsuccess) + SetLastError(SNET_ERROR_ALREADY_EXISTS); + return srv_startadvsuccess; +} + +//=========================================================================== +BOOL SrvStopAdvertisingGame () { + if (!SendServerMessage(SID_STOPADV,NULL,0)) + return 0; + return 1; +} + diff --git a/src/Storm/SOURCE/BATTLE/UI.CPP b/src/Storm/SOURCE/BATTLE/UI.CPP new file mode 100644 index 0000000..75c59ee --- /dev/null +++ b/src/Storm/SOURCE/BATTLE/UI.CPP @@ -0,0 +1,882 @@ +/**************************************************************************** +* +* UI.CPP +* battle.net user interface functions +* +* By Michael Morhaime +* +***/ + +#include "pch.h" + +//**************************************************************************** +//**************************************************************************** +#define MESS_WITH_PARENT 1 // 1 in final + + +//**************************************************************************** +BOOL gbConnectionLost = FALSE; +BOOL gbConnectionSucks = FALSE; + +// This is the window that is currently ready to +// process the Battle.net nofication messages +HWND ghWndUiMainParent = (HWND) 0; + +static HWND sghDlgConnect = (HWND)0; +static HWND sghDlgCancel = (HWND)0; +static HWND sghDlgProgress = (HWND)0; + +static SNETUIDATA sgInterfacedata = { 0 }; +static int sgnDownloadProgress = 0; + +#define PALETTE_REGISTERS 256 + +static PALETTEENTRY sgPalette[PALETTE_REGISTERS]; +static PALETTEENTRY sgFadePal[PALETTE_REGISTERS]; + + + +//**************************************************************************** +static BOOL UiConnectMsg(SNETUIDATAPTR interfacedata, UINT nMessage, UINT flags); + +BOOL CALLBACK ConnectDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +BOOL CALLBACK ConnectCancelDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +BOOL CALLBACK LogonDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); + + +void ProtectMinimize(BOOL bEnable); +//**************************************************************************** +//**************************************************************************** +static void UiClearPalette(PALETTEENTRY * pe) { + for (int palreg = 0; palreg < PALETTE_REGISTERS; palreg++) { + pe[palreg].peRed = 0; + pe[palreg].peGreen = 0; + pe[palreg].peBlue = 0; + } +} + + + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + + +//**************************************************************************** +//**************************************************************************** +BOOL UiInitialize(SNETUIDATAPTR interfacedata) { + if (!interfacedata->artcallback) return FALSE; + + // Load scrollbar and combobox art (shared by many dialogs) + ScrollbarLoadArtwork(interfacedata->artcallback); + ComboboxLoadArtwork(interfacedata->artcallback); + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +void UiDestroy(void) { + ScrollbarDestroyArtwork(); + ComboboxDestroyArtwork(); +} + + +//**************************************************************************** +//**************************************************************************** +void RestoreWindowsColors(void) { + HPALETTE hPal; + + // Get Windows Default colors from the system + hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); + + GetPaletteEntries(hPal, 0, 10, &sgFadePal[0]); + GetPaletteEntries(hPal, 10, 10, &sgFadePal[PALETTE_REGISTERS-10]); + + SDrawUpdatePalette(0, PALETTE_REGISTERS, &sgFadePal[0], TRUE); +} + +//**************************************************************************** +//**************************************************************************** +int gFadeStep; +//**************************************************************************** +// an async fade function +//**************************************************************************** +void UiVidFade(int max, int curr) { + + if (max == curr) { + memcpy(sgFadePal, sgPalette, (PALETTE_REGISTERS * sizeof(PALETTEENTRY))); + ShowCursor(TRUE); + } + else if (curr == 0) { + memcpy(sgFadePal, sgPalette, (PALETTE_REGISTERS * sizeof(PALETTEENTRY))); + UiClearPalette(sgFadePal); + } + else { + for (int palreg = 0; palreg < PALETTE_REGISTERS; palreg++) { + sgFadePal[palreg].peRed = (sgPalette[palreg].peRed * curr) / max; + sgFadePal[palreg].peGreen = (sgPalette[palreg].peGreen * curr) / max; + sgFadePal[palreg].peBlue = (sgPalette[palreg].peBlue * curr) / max; + } + } + SDrawUpdatePalette(0, PALETTE_REGISTERS, sgFadePal, TRUE); +} + + +//**************************************************************************** +//**************************************************************************** +void UiVidFadeOut(int steps) { + ShowCursor(FALSE); + + memcpy(sgFadePal, sgPalette, (PALETTE_REGISTERS * sizeof(PALETTEENTRY))); + + for (int index = 0; index < steps; index++) { + for (int palreg = 0; palreg < PALETTE_REGISTERS; palreg++) { + sgFadePal[palreg].peRed -= (sgPalette[palreg].peRed / steps); + sgFadePal[palreg].peGreen -= (sgPalette[palreg].peGreen / steps); + sgFadePal[palreg].peBlue -= (sgPalette[palreg].peBlue / steps); + } + SDrawUpdatePalette(0, PALETTE_REGISTERS, sgFadePal, TRUE); + } + + UiClearPalette(sgFadePal); + SDrawUpdatePalette(0, PALETTE_REGISTERS, sgFadePal, TRUE); + + SDrawClearSurface(SDRAW_SURFACE_FRONT); + RestoreWindowsColors(); +} + +//=========================================================================== +// UiSetCursors() +// +// This routine must be called once the first time a dialog with a new class +// is displayed, so we can set the cursor for that particular class. +//=========================================================================== +void UiLoadCursors(HWND hWnd, SNETUIDATAPTR interfacedata) { + HCURSOR OldArrow = NULL; + HCURSOR OldIBeam = NULL; + + if (!interfacedata || !interfacedata->getdatacallback) + return; + +#if 0 + HCURSOR hCursor; + + // Get arrow cursor + if (interfacedata->getdatacallback( + PROVIDERID, + SNET_DATA_CURSORARROW, + &hCursor, + sizeof(hCursor), + NULL)) + SDlgSetCursor(hWnd, hCursor, OCR_NORMAL); + + + // Get ibeam cursor + if (interfacedata->getdatacallback( + PROVIDERID, + SNET_DATA_CURSORIBEAM, + &hCursor, + sizeof(hCursor), + NULL)) + SDlgSetCursor(hWnd, hCursor, OCR_IBEAM); +#else + + // Use System default cursors until we solve modal dialog issues. + // (whenever the mouse is over a disabled window (like the parent of a modal dialog) + // windows will display the default system cursor)). + SDlgSetCursor(hWnd, LoadCursor(NULL, IDC_ARROW), OCR_NORMAL, &OldArrow); + SDlgSetCursor(hWnd, LoadCursor(NULL, IDC_IBEAM), OCR_IBEAM, &OldIBeam); + +#endif +} + +//=========================================================================== +BOOL UiGetData(SNETGETDATAPROC getdatacallback, + DWORD dataid, + LPBYTE *data, + DWORD *datasize) { + + DWORD dwSize; + + *data = 0; + + if (!getdatacallback) + return 0; + + + // CALL THE GET DATA CALLBACK TO DETERMINE DATA SIZE + if (!getdatacallback(PROVIDERID, + dataid, + NULL, + 0, + &dwSize)) + return 0; + + + // ALLOCATE MEMORY FOR THE IMAGE + if (!(*data = (LPBYTE)ALLOC(dwSize))) + return 0; + + // LOAD THE DATA BLOCK + if (!getdatacallback(PROVIDERID, + dataid, + *data, + dwSize, + NULL)) { + FREE(*data); + *data = NULL; + return 0; + } + + *datasize = dwSize; + return 1; +} + +//=========================================================================== +BOOL UiLoadArtwork (SNETGETARTPROC artcallback, + HWND hWnd, + HWND hWndParent, + DWORD artid, + LPCTSTR controltype, + DWORD controlstyle, + LONG usageflags, + BOOL loadpalette, + BOOL prepfadein, + LPBYTE *data, + SIZE *size) { + PALETTEENTRY pe[256]; + + *data = 0; + + // VERIFY THAT THE APPLICATION HAS REGISTERED AN ARTWORK CALLBACK + if (!artcallback) + return 0; + + // CALL THE ARTWORK CALLBACK TO DETERMINE THE IMAGE DIMENSIONS + int width = 0; + int height = 0; + int bitdepth; + if (!artcallback(PROVIDERID, + artid, + NULL, + NULL, + 0, + &width, + &height, + &bitdepth)) + return 0; + if (size) { + size->cx = width; + size->cy = height; + } + + + // ALLOCATE MEMORY FOR THE IMAGE + DWORD bytes = width*height*bitdepth/8; + if (!(*data = (LPBYTE)ALLOC(bytes))) + return 0; + + // LOAD THE IMAGE + if (!artcallback(PROVIDERID, + artid, + &pe[0], + *data, + bytes, + &width, + &height, + &bitdepth)) { + FREE(*data); + *data = NULL; + return 0; + } + + + // IF THIS IS A SCREEN BACKGROUND, USE ITS PALETTE + if (loadpalette) { + HPALETTE hPal; + + // Get Windows Default colors from the system + hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); + GetPaletteEntries(hPal, 0, 10, &pe[0]); + GetPaletteEntries(hPal, 10, 10, &pe[PALETTE_REGISTERS-10]); + memcpy(sgPalette, pe, (PALETTE_REGISTERS * sizeof(PALETTEENTRY))); + + if (!prepfadein) { + SDrawUpdatePalette(0, PALETTE_REGISTERS, &sgPalette[0], TRUE); + } + else { + UiClearPalette(pe); + SDrawUpdatePalette(0, PALETTE_REGISTERS, pe, TRUE); + gFadeStep = 0; + } + } + + + // If we have a window to associate it with, register the bitmap, + if (hWnd || hWndParent) { + SDlgSetBitmap( + hWnd, + hWndParent, + controltype, + controlstyle, + usageflags, + *data, + NULL, + width, + height); + } + + return 1; +} + + +//=========================================================================== +BOOL UiSetCustomArt (HWND hWnd, + PALETTEENTRY *pe, + int nFirstColor, + int nNumColorsUsed, + BOOL bSetPaletteNow, + LPBYTE data, + int nWidth, + int nHeight) { + + if (nNumColorsUsed) + memcpy(&sgPalette[nFirstColor], &pe[nFirstColor], (nNumColorsUsed * sizeof(PALETTEENTRY))); + + if (bSetPaletteNow) + SDrawUpdatePalette(nFirstColor, nNumColorsUsed, &sgPalette[nFirstColor]); + + // If we have a window to associate it with, register the bitmap, + if (hWnd) { + SDlgSetBitmap( + hWnd, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + data, + NULL, + nWidth, + nHeight); + + InvalidateRect(hWnd, NULL, FALSE); + } + + return 1; +} + + +//=========================================================================== +BOOL UiLoadCustomArt ( + SNETGETARTPROC artcallback, + HWND hWnd, + DWORD artid, + int nFirstColor, + int nNumColorsUsed, + BOOL bSetPaletteNow, + LPBYTE *data, + SIZE *size) { + PALETTEENTRY pe[256]; + + *data = 0; + + // VERIFY THAT THE APPLICATION HAS REGISTERED AN ARTWORK CALLBACK + if (!artcallback) + return 0; + + // CALL THE ARTWORK CALLBACK TO DETERMINE THE IMAGE DIMENSIONS + int width = 0; + int height = 0; + int bitdepth; + if (!artcallback(PROVIDERID, + artid, + NULL, + NULL, + 0, + &width, + &height, + &bitdepth)) + return 0; + if (size) { + size->cx = width; + size->cy = height; + } + + + // ALLOCATE MEMORY FOR THE IMAGE + DWORD bytes = width*height*bitdepth/8; + if (!(*data = (LPBYTE)ALLOC(bytes))) + return 0; + + // LOAD THE IMAGE + if (!artcallback(PROVIDERID, + artid, + &pe[0], + *data, + bytes, + &width, + &height, + &bitdepth)) { + FREE(*data); + *data = NULL; + return 0; + } + + + UiSetCustomArt( + hWnd, + &pe[0], + nFirstColor, + nNumColorsUsed, + bSetPaletteNow, + *data, + width, + height); + + return 1; +} + +//=========================================================================== +BOOL UiLogon (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) +{ + return (1 == SDlgDialogBoxParam( + global_hinstance, + TEXT("DIALOG_LOGON"), + (interfacedata) ? interfacedata->parentwindow : SDrawGetFrameWindow(), + LogonDialogProc, + (LPARAM) interfacedata)); +} + + +//=========================================================================== +BOOL UiBeginConnect (SNETPROGRAMDATAPTR programdata, + SNETUIDATAPTR interfacedata) { + + static UIPARAMS suiparams; + HWND hWndParent; + + + ZeroMemory(&suiparams,sizeof(UIPARAMS)); + suiparams.flags = 0; + suiparams.programdata = programdata; + suiparams.playerdata = NULL; + suiparams.interfacedata = interfacedata; + suiparams.versiondata = 0; + suiparams.playeridptr = 0; + + gbConnectionLost = FALSE; // Make sure this is reset. + gbConnectionSucks = FALSE; // If it sucks, Storm will tell us. + + + // Display a popup of some sort that has some sort of + // connecting animation. + + if (!interfacedata) + return 0; + + hWndParent = interfacedata->parentwindow; + +#if MESS_WITH_PARENT + // Hide parent window before dialog can set palette (if parent is not the frame window) + if (SDrawGetFrameWindow() != hWndParent) { + SetActiveWindow(GetParent(hWndParent)); + ShowWindow(hWndParent, SW_HIDE); + } +#endif + + // Erase screen + SDrawClearSurface(SDRAW_SURFACE_FRONT); + + // DISPLAY THE DIALOG BOX + sghDlgConnect = SDlgCreateDialogParam( + global_hinstance, + TEXT("DIALOG_CONNECT_BG"), + hWndParent, + ConnectDialogProc, + (LPARAM)&suiparams); + + // Copy interfacedata for use later by children of connect dlg + sgInterfacedata = *interfacedata; + sgInterfacedata.parentwindow = sghDlgConnect; + + if (sghDlgConnect) { + // Display popup to allow user to cancel + sghDlgCancel = SDlgCreateDialogParam( + global_hinstance, + TEXT("DIALOG_CONNECT_CANCEL"), + sghDlgConnect, + ConnectCancelDialogProc, + (LPARAM)&sgInterfacedata); + + ProtectMinimize(TRUE); + } + + return (sghDlgConnect != (HWND)0); +} + +//=========================================================================== +void UiEndConnect (BOOL connected) { + if (sghDlgConnect) { + ProtectMinimize(FALSE); + +#if MESS_WITH_PARENT + if (SDrawGetFrameWindow() != GetParent(sghDlgConnect)) { + if (connected) { + // Parent is hidden right now. Make the frame window active so that + // we don't lose the focus completely when sghDlgConnect is destroyed. + SetActiveWindow(GetParent(GetParent(sghDlgConnect))); + } + else + ShowWindow(GetParent(sghDlgConnect), SW_SHOW); + } +#endif + + DestroyWindow(sghDlgConnect); + sghDlgConnect = (HWND) 0; + sghDlgCancel = (HWND) 0; // Cancel will be destroyed automatically + + } + + sgInterfacedata.parentwindow = NULL; +} + + +//**************************************************************************** +//**************************************************************************** +void UiRestoreApp(void) { + // Switch back to our app and do a restore + SetActiveWindow(SDrawGetFrameWindow()); + ShowWindow(SDrawGetFrameWindow(), SW_RESTORE); + + // Flush out messages before continuing to allow all our windows to + // know that we are back. + UiProcessWindowMessages(); +} + + +//******************************************** +//******************************************** +extern BOOL CALLBACK RasEnumCallback(LPCTSTR szEntryName, LPVOID rashandle, LPVOID lpContext); + +BOOL UiDisconnect(void) { + EnumNewRASConnections(RasEnumCallback, (LPVOID) &sgInterfacedata); + return 1; +} + +//=========================================================================== +static BOOL UiConnectMsg(SNETUIDATAPTR interfacedata, UINT nMessage, UINT flags) { + char szText[512]; + char szTitle[32]; + DWORD dwReturn; + + if (!interfacedata) + return 0; + + if (!interfacedata->messageboxcallback) + return 0; + + if (!interfacedata->parentwindow) + return 0; + + + LoadString(global_hinstance, IDS_BATTLENET, szTitle, sizeof(szTitle)); + LoadString(global_hinstance, nMessage, szText, sizeof(szText)); + + dwReturn = UiMessageBox( + interfacedata->messageboxcallback, + interfacedata->parentwindow, + szText, + szTitle, + flags); + + return (dwReturn == IDOK); +} + + +//=========================================================================== +static int CALLBACK GetDownloadProgress(void) { + return sgnDownloadProgress; +} + +//=========================================================================== +BOOL UiProcessWindowMessages (void) { + MSG message; + while (PeekMessage(&message,(HWND)0,0,0,PM_REMOVE)) { + if (message.message == WM_QUIT) { + PostMessage(message.hwnd,message.message,message.wParam,message.lParam); + return 0; + } + else if (((!sghDlgConnect) || (!IsDialogMessage(sghDlgConnect ,&message))) && + ((!sghDlgProgress) || (!IsDialogMessage(sghDlgProgress,&message))) && + ((!sghDlgCancel) || (!IsDialogMessage(sghDlgCancel ,&message)))) { + TranslateMessage(&message); + DispatchMessage(&message); + } + } + + SDlgCheckTimers(); + return 1; +} + +//=========================================================================== +void UiHideConnectCancel(void) { + // Hide cancel button when any popups are displayed + if (!sghDlgCancel) + return; + + // Get rid of Cancel Dlg + DestroyWindow(sghDlgCancel); + sghDlgCancel = NULL; +} + +//=========================================================================== +void UiWSockErrMessage(void) { + UiHideConnectCancel(); + UiConnectMsg(&sgInterfacedata, IDS_ERR_NOWSOCK32, MB_OK | MB_ICONWARNING); + return; +} + +//=========================================================================== +BOOL UiUpgradeMessage(void) { + UiHideConnectCancel(); + + // Okay minimization fears are over also + ProtectMinimize(FALSE); + return UiConnectMsg(&sgInterfacedata, IDS_ASK_UPDATE, MB_OKCANCEL); +} + + +//=========================================================================== +void UiNotificationWaiting(void) { + if (!ghWndUiMainParent) + return; + + PostMessage(ghWndUiMainParent, WM_NOTIFICATION_WAITING, 0, 0); +} + +//=========================================================================== +//=========================================================================== +void UiNotification (void) { + DWORD notifycode; + LPVOID paramdata; + DWORD parambytes; + + // NOTE: paramdata will no longer be valid after hitting a PeekMessage loop, + // All routines called from here must make sure that data from paramdata is + // copied before sent to a message box or to any routines that might yield control!!! + while (SrvGetUiNotification (¬ifycode, ¶mdata, ¶mbytes)) { + switch (notifycode) { + case SN_ADDCHANNEL: + ChatAddChannel((LPCSTR) paramdata); + break; + case SN_DELETECHANNEL: + ChatDeleteChannel((LPCSTR) paramdata); + break; + case SN_JOINCHANNEL: + ChatJoinChannel((SNJOINCHANNELPTR) paramdata); + break; + case SN_CHANNELISFULL: + ChatChannelFull((LPCSTR) paramdata); + break; + case SN_CHANNELDOESNOTEXIST: + ChatChannelDoesNotExist((LPCSTR) paramdata); + break; + case SN_CHANNELISRESTRICTED: + ChatChannelRestricted((LPCSTR) paramdata); + break; + + case SN_ADDUSER: + ChatAddUser((SNADDUSERPTR) paramdata); + break; + case SN_DELETEUSER: + ChatDeleteUser((SNDELETEUSERPTR) paramdata); + break; + case SN_USERNAME: + ChatSetUserName((LPCSTR) paramdata); + break; + + case SN_CHANGEUSERFLAGS: + ChatChangeUserFlags((SNCHANGEUSERFLAGSPTR) paramdata); + break; + + case SN_UPDATEPINGTIME: + ChatUpdatePingTime((SNUPDATEPINGTIMEPTR) paramdata); + break; + + case SN_DISPLAYSTRING: + // Got a message from someone + ChatReceiveMsg((SNDISPLAYSTRINGPTR) paramdata); + break; + + case SN_SQUELCHUSER: + ChatSquelchUser((SNSQUELCHUSERPTR) paramdata); + break; + + case SN_UNSQUELCHUSER: + ChatUnsquelchUser((SNSQUELCHUSERPTR) paramdata); + break; + + + case SN_BADCONNECTION: + UiConnectMsg(&sgInterfacedata, IDS_ERR_BADSERVICEPROVIDER, MB_OK | MB_ICONERROR); + gbConnectionSucks = TRUE; + break; + + case SN_SETADINFO: + AdSetInfo((SNADINFOPTR) paramdata); + break; + + case SN_DISPLAYAD: + AdDisplay((LPVOID) paramdata, parambytes); + break; + + case SN_DOWNLOADINGUPGRADE: { + DWORD *pDword = (DWORD *)paramdata; + sgnDownloadProgress = *pDword; + + if (!sghDlgProgress) { + char szText[128]; + + LoadString(global_hinstance, IDS_DOWNLOADPROGRESS, szText, sizeof(szText)); + sghDlgProgress = UiModelessProgressDialog( + &sgInterfacedata, + szText, + TRUE, // Allow user to abort + GetDownloadProgress, + 20); // Frequency of progress update (FPS) + } + + break; + } + + case SN_DOWNLOADFAILED: + if (sghDlgProgress) { + DestroyWindow(sghDlgProgress); + sghDlgProgress = NULL; + } + UiConnectMsg(&sgInterfacedata, IDS_ERR_DOWNLOADFAILED, MB_OK | MB_ICONERROR); + break; + + case SN_DOWNLOADSUCCEEDED: + if (sghDlgProgress) { + DestroyWindow(sghDlgProgress); + sghDlgProgress = NULL; + } + + UiConnectMsg(&sgInterfacedata, IDS_PREP_RESTART, MB_OK); + break; + + + case SN_FAILEDTOCONNECT: { + DWORD *pdwError = (DWORD *)paramdata; + int nMsgNo; + + switch (*pdwError) { + case SN_ERROR_NOTRESPONDING: + nMsgNo = IDS_ERR_NOTRESPONDING; + break; + + case SN_ERROR_BADCONNECTION: + nMsgNo = IDS_ERR_BADCONNECTION; + break; + + case SN_ERROR_UNABLETOUPGRADE: + nMsgNo = IDS_ERR_UNABLETOUPGRADE; + break; + + case SN_ERROR_UNREACHABLE: + nMsgNo = IDS_ERR_UNREACHABLE; + break; + + default: + nMsgNo = IDS_ERR_UNREACHABLE; + } + + UiHideConnectCancel(); + + // Okay minimization fears are over also + ProtectMinimize(FALSE); + UiConnectMsg(&sgInterfacedata, nMsgNo, MB_OK | MB_ICONERROR); + break; + } + case SN_LOSTCONNECTION: + // We can't display a message here, so set a flag to display a message. + // This will cause the chatroom to abort. + gbConnectionLost = TRUE; + break; + + case SN_MESSAGEBOX: { + SNMESSAGEBOXPTR ptr; + + ptr = (SNMESSAGEBOXPTR)paramdata; + if (!sgInterfacedata.messageboxcallback) + MessageBox(ghWndUiMainParent, ptr->text, ptr->caption, ptr->type); + else + sgInterfacedata.messageboxcallback(ghWndUiMainParent, ptr->text, ptr->caption, ptr->type); + + break; + } + + } // end switch + + } // end while + +} + + + +//=========================================================================== +BOOL UiSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + + // BUILD A USER INTERFACE DATA BLOCK + UIPARAMS uiparams; + ZeroMemory(&uiparams,sizeof(UIPARAMS)); + uiparams.flags = flags; + uiparams.programdata = programdata; + uiparams.playerdata = playerdata; + uiparams.interfacedata = interfacedata; + uiparams.versiondata = versiondata; + uiparams.playeridptr = playerid; + + + if (!interfacedata) + return 0; + + + // Take control of system colors using app preferences + ColorPrefInit(interfacedata->getdatacallback); + + + // DISPLAY THE DIALOG BOX + DWORD result = (DWORD)SDlgDialogBoxParam(global_hinstance, + TEXT("DIALOG_BATTLENET"), + interfacedata->parentwindow, + BattleNetDialogProc, + (LPARAM)&uiparams); + + // Restore Windows System Colors + ColorPrefDestroy(); + + return (result == 1); +} diff --git a/src/Storm/SOURCE/BLIZZARD.KEY b/src/Storm/SOURCE/BLIZZARD.KEY new file mode 100644 index 0000000..bcf2484 Binary files /dev/null and b/src/Storm/SOURCE/BLIZZARD.KEY differ diff --git a/src/Storm/SOURCE/BUILDMC.BAT b/src/Storm/SOURCE/BUILDMC.BAT new file mode 100644 index 0000000..7afc5a9 --- /dev/null +++ b/src/Storm/SOURCE/BUILDMC.BAT @@ -0,0 +1,4 @@ +@echo off +mc stormerr.mc +del stormerr.h +del stormerr.rc diff --git a/src/Storm/SOURCE/C.EXE b/src/Storm/SOURCE/C.EXE new file mode 100644 index 0000000..be3a0a4 Binary files /dev/null and b/src/Storm/SOURCE/C.EXE differ diff --git a/src/Storm/SOURCE/CRTDLL.LIB b/src/Storm/SOURCE/CRTDLL.LIB new file mode 100644 index 0000000..bdf4b59 Binary files /dev/null and b/src/Storm/SOURCE/CRTDLL.LIB differ diff --git a/src/Storm/SOURCE/EXPORTS.DEF b/src/Storm/SOURCE/EXPORTS.DEF new file mode 100644 index 0000000..4d0679c --- /dev/null +++ b/src/Storm/SOURCE/EXPORTS.DEF @@ -0,0 +1,236 @@ +EXPORTS +; +; Network functions (101-131) +; +SNetCreateGame @101 NONAME +SNetDestroy @102 NONAME +SNetEnumDevices @103 NONAME +SNetEnumGames @104 NONAME +SNetEnumProviders @105 NONAME +SNetDropPlayer @106 NONAME +SNetGetGameInfo @107 NONAME +SNetGetNetworkLatency @108 NONAME +SNetGetNumPlayers @109 NONAME +SNetGetOwnerTurnsWaiting @110 NONAME +SNetGetPerformanceData @111 NONAME +SNetGetPlayerCaps @112 NONAME +SNetGetPlayerName @113 NONAME +SNetGetProviderCaps @114 NONAME +SNetGetTurnsInTransit @115 NONAME +SNetInitializeDevice @116 NONAME +SNetInitializeProvider @117 NONAME +SNetJoinGame @118 NONAME +SNetLeaveGame @119 NONAME +SNetPerformUpgrade @120 NONAME +SNetReceiveMessage @121 NONAME +SNetReceiveTurns @122 NONAME +SNetRegisterEventHandler @123 NONAME +SNetResetLatencyMeasurements @124 NONAME +SNetSelectGame @125 NONAME +SNetSelectProvider @126 NONAME +SNetSendMessage @127 NONAME +SNetSendTurn @128 NONAME +SNetSetBasePlayer @129 NONAME +SNetSetGameMode @130 NONAME +SNetUnregisterEventHandler @131 NONAME +SNetGetOwnerId @132 NONAME +SNetEnumGamesEx @133 NONAME +SNetSendServerChatCommand @134 NONAME +; +; Dialog manager functions (201-220) +; +SDlgBeginPaint @201 NONAME +SDlgBltToWindowI @202 NONAME +SDlgCheckTimers @203 NONAME +SDlgCreateDialogIndirectParam @204 NONAME +SDlgCreateDialogParam @205 NONAME +SDlgDefDialogProc @206 NONAME +SDlgDialogBoxIndirectParam @208 NONAME +SDlgDialogBoxParam @209 NONAME +SDlgDrawBitmap @210 NONAME +SDlgEndDialog @211 NONAME +SDlgEndPaint @212 NONAME +SDlgKillTimer @213 NONAME +SDlgSetBaseFont @214 NONAME +SDlgSetBitmapI @215 NONAME +SDlgSetControlBitmaps @216 NONAME +SDlgSetCursor @217 NONAME +SDlgSetSystemCursor @218 NONAME +SDlgSetTimer @219 NONAME +SDlgUpdateCursor @220 NONAME +SDlgBltToWindowE @221 NONAME +SDlgSetBitmapE @222 NONAME +; +; File I/O functions (251-272) +; +SFileAuthenticateArchive @251 NONAME +SFileCloseArchive @252 NONAME +SFileCloseFile @253 NONAME +SFileDdaBegin @254 NONAME +SFileDdaBeginEx @255 NONAME +SFileDdaDestroy @256 NONAME +SFileDdaEnd @257 NONAME +SFileDdaGetPos @258 NONAME +SFileDdaGetVolume @259 NONAME +SFileDdaInitialize @260 NONAME +SFileDdaSetVolume @261 NONAME +SFileEnableDirectAccess @263 NONAME +SFileGetFileArchive @264 NONAME +SFileGetFileSize @265 NONAME +SFileOpenArchive @266 NONAME +SFileOpenFile @267 NONAME +SFileOpenFileEx @268 NONAME +SFileReadFile @269 NONAME +SFileSetBasePath @270 NONAME +SFileSetFilePointer @271 NONAME +SFileSetLocale @272 NONAME +SFileGetBasePath @273 NONAME +SFileSetIoErrorMode @274 NONAME +SFileGetArchiveName @275 NONAME +SFileGetFileName @276 NONAME +SFileGetArchiveInfo @277 NONAME +; +; Other functions (301+) +; +StormDestroy @301 NONAME +SBltGetSCode @312 NONAME +SBltROP3 @313 NONAME +SBltROP3Clipped @314 NONAME +SBltROP3Tiled @315 NONAME +SBmpDecodeImage @321 NONAME +SBmpLoadImage @323 NONAME +SBmpSaveImage @324 NONAME +SBmpAllocLoadImage @325 NONAME +SCodeCompile @331 NONAME +SCodeDelete @332 NONAME +SCodeExecute @334 NONAME +SCodeGetPseudocode @335 NONAME +SDrawAutoInitialize @341 NONAME +SDrawCaptureScreen @342 NONAME +SDrawClearSurface @343 NONAME +SDrawDestroy @344 NONAME +SDrawFlipPage @345 NONAME +SDrawGetFrameWindow @346 NONAME +SDrawGetObjects @347 NONAME +SDrawGetScreenSize @348 NONAME +SDrawGetServiceLevel @349 NONAME +SDrawLockSurface @350 NONAME +SDrawManualInitialize @351 NONAME +SDrawMessageBox @352 NONAME +SDrawPostClose @353 NONAME +SDrawRealizePalette @354 NONAME +SDrawSelectGdiSurface @355 NONAME +SDrawUnlockSurface @356 NONAME +SDrawUpdatePalette @357 NONAME +SDrawUpdateScreen @358 NONAME +SEvtDispatch @372 NONAME +SEvtRegisterHandler @373 NONAME +SEvtUnregisterHandler @374 NONAME +SEvtUnregisterType @375 NONAME +SEvtPopState @376 NONAME +SEvtPushState @377 NONAME +SEvtBreakHandlerChain @378 NONAME +SGdiBitBlt @381 NONAME +SGdiCreateFont @382 NONAME +SGdiDeleteObject @383 NONAME +SGdiExtTextOut @385 NONAME +SGdiImportFont @386 NONAME +SGdiLoadFont @387 NONAME +SGdiRectangle @388 NONAME +SGdiSelectObject @389 NONAME +SGdiSetPitch @390 NONAME +SGdiTextOut @391 NONAME +SGdiSetTargetDimensions @392 NONAME +SGdiGetTextExtent @393 NONAME +SMemAlloc @401 NONAME +SMemFree @403 NONAME +SMsgDispatchMessage @412 NONAME +SMsgDoMessageLoop @413 NONAME +SMsgRegisterCommand @414 NONAME +SMsgRegisterKeyDown @415 NONAME +SMsgRegisterKeyUp @416 NONAME +SMsgRegisterMessage @417 NONAME +SMsgPopRegisterState @418 NONAME +SMsgPushRegisterState @419 NONAME +SRegLoadData @421 NONAME +SRegLoadString @422 NONAME +SRegLoadValue @423 NONAME +SRegSaveData @424 NONAME +SRegSaveString @425 NONAME +SRegSaveValue @426 NONAME +SRegGetBaseKey @427 NONAME +STransBlt @431 NONAME +STransBltUsingMask @432 NONAME +STransCreateI @433 NONAME +STransDelete @434 NONAME +STransDuplicate @436 NONAME +STransIntersectDirtyArray @437 NONAME +STransInvertMask @438 NONAME +STransLoadI @439 NONAME +STransSetDirtyArrayInfo @440 NONAME +STransUpdateDirtyArray @441 NONAME +STransIsPixelInMask @442 NONAME +STransCombineMasks @443 NONAME +STransCreateMaskI @444 NONAME +STransCreateE @445 NONAME +STransCreateMaskE @446 NONAME +STransLoadE @447 NONAME +SVidDestroy @451 NONAME +SVidGetSize @452 NONAME +SVidInitialize @453 NONAME +SVidPlayBegin @454 NONAME +SVidPlayBeginFromMemory @455 NONAME +SVidPlayContinue @456 NONAME +SVidPlayContinueSingle @457 NONAME +SVidPlayEnd @458 NONAME +SVidSetVolume @459 NONAME +SErrDisplayError @461 NONAME +SErrGetErrorStr @462 NONAME +SErrGetLastError @463 NONAME +SErrRegisterMessageSource @464 NONAME +SErrSetLastError @465 NONAME +SErrReportResourceLeak @467 NONAME +SErrSuppressErrors @468 NONAME +SCmdGetBool @472 NONAME +SCmdGetNum @473 NONAME +SCmdGetString @474 NONAME +SCmdProcess @475 NONAME +SCmdRegisterArgList @476 NONAME +SCmdRegisterArgument @477 NONAME +SCmdCheckId @478 NONAME +SMemFindNextBlock @481 NONAME +SMemFindNextHeap @482 NONAME +SMemGetHeapByCaller @483 NONAME +SMemGetHeapByPtr @484 NONAME +SMemHeapAlloc @485 NONAME +SMemHeapCreate @486 NONAME +SMemHeapDestroy @487 NONAME +SMemHeapFree @488 NONAME +SStrCopy @501 NONAME +SStrHash @502 NONAME +SStrPack @503 NONAME +SStrTokenize @504 NONAME +SStrChr @505 NONAME +SStrLen @506 NONAME +SMsgBreakHandlerChain @511 NONAME +SMsgUnregisterCommand @512 NONAME +SMsgUnregisterKeyDown @513 NONAME +SMsgUnregisterKeyUp @514 NONAME +SMsgUnregisterMessage @515 NONAME +SRgnClear @521 NONAME +SRgnCombineRect @523 NONAME +SRgnCreate @524 NONAME +SRgnDelete @525 NONAME +SRgnDuplicate @527 NONAME +SRgnGetRectParams @528 NONAME +SRgnGetRects @529 NONAME +SRgnGetBoundingRect @530 NONAME +SLogClose @541 NONAME +SLogCreate @542 NONAME +SLogDump @544 NONAME +SLogFlush @545 NONAME +SLogFlushAll @546 NONAME +SLogPend @547 NONAME +SLogWrite @548 NONAME +SCompCompress @551 NONAME +SCompDecompress @552 NONAME diff --git a/src/Storm/SOURCE/IPXTEST/IPXTEST.CPP b/src/Storm/SOURCE/IPXTEST/IPXTEST.CPP new file mode 100644 index 0000000..e0c9cf6 --- /dev/null +++ b/src/Storm/SOURCE/IPXTEST/IPXTEST.CPP @@ -0,0 +1,1445 @@ +/**************************************************************************** +* +* IPXTEST.CPP +* IPX test network provider +* +* By Michael O'Brien (9/25/96) +* +***/ + +#define STRICT +#include +#include +#include +#include +#include "resource.h" + +#define ADVPORT 6113 +#define MAINPORT 6114 +#define MAXMESSAGESIZE 504 +#define MAXPLAYERS 256 +#define PROVIDERID 'TEST' +#define RECVDATATHREADS 2 + +#define ADTYPE_GAMEINFO 0 +#define ADTYPE_REMOVE 1 +#define ADTYPE_REQUEST 2 + +typedef struct _ADVHEADER { + WORD checksum; // must be first field + WORD length; + WORD type; + WORD reserved; + DWORD programid; + DWORD versionid; + DWORD gamemode; +} ADVHEADER, *ADVHEADERPTR; + +typedef struct _ADVPACKET { + ADVHEADER header; + char strings[SNETSPI_MAXSTRINGLENGTH*2]; +} ADVPACKET, *ADVPACKETPTR; + +typedef struct _PACKET { + SNETADDR addr; // must be first field in structure + BYTE data[MAXMESSAGESIZE]; + DWORD databytes; + _PACKET *next; +} PACKET, *PACKETPTR; + +typedef struct _SENDREC { + DWORD sendtime; + SOCKET s; + SOCKADDR_IPX addr; + char *data; + int databytes; + _SENDREC *next; +} SENDREC, *SENDPTR; + +typedef struct _UIPARAMS { + DWORD flags; + SNETPROGRAMDATAPTR programdata; + SNETPLAYERDATAPTR playerdata; + SNETUIDATAPTR interfacedata; + SNETVERSIONDATAPTR versiondata; + LPDWORD playeridptr; +} UIPARAMS, *UIPARAMSPTR; + +typedef struct _THREAD { + DWORD id; + HANDLE handle; + _THREAD *next; +} THREAD, *THREADPTR; + +typedef struct _TESTPARMS { + DWORD mindelay; + DWORD maxdelay; + DWORD corruptpercent; +} TESTPARMS, *TESTPARMSPTR; + +static ADVPACKETPTR ipx_advgameinfo = NULL; +static SOCKET ipx_advsocket = (SOCKET)0; +static SOCKADDR_IPX ipx_broadcastaddr = {0}; +static CCritSect ipx_critsect; +static SNETSPI_GAMELISTPTR ipx_gamehead = NULL; +static HINSTANCE ipx_instance = (HINSTANCE)0; +static SOCKADDR_IPX ipx_localaddr = {0}; +static DWORD ipx_nextgameid = 0; +static SOCKET ipx_mainsocket = (SOCKET)0; +static DWORD ipx_maxplayers = MAXPLAYERS; +static PACKETPTR ipx_packethead = NULL; +static DWORD ipx_programid = 0; +static HANDLE ipx_recvevent = NULL; +static SENDPTR ipx_sendhead = NULL; +static BOOL ipx_shutdown = 0; +static TESTPARMS ipx_testparms = {200,300,5}; +static THREADPTR ipx_threadhead = NULL; +static DWORD ipx_versionid = 0; + +static void SendAdvertisement (); +static void SendRequest (); +static void TrimGameList (DWORD timeout); +static void UpdateGameList (HWND dialog, HWND listbox); +BOOL CALLBACK IpxCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude); +BOOL CALLBACK IpxStopAdvertisingGame (); + +//=========================================================================== +static WORD ComputeChecksum (LPVOID data, DWORD databytes) { + DWORD checkval1 = 0; + DWORD checkval2 = 0; + LPBYTE ptr = ((LPBYTE)data)+databytes-1; + while (databytes--) { + checkval1 += *ptr--; + if (checkval1 >= 0xFF) + checkval1 -= 0xFF; + checkval2 += checkval1; + } + checkval2 %= 255; + return MAKEWORD((checkval2 & 0xFF),(checkval1 & 0xFF)); +} + +//=========================================================================== +static WORD GenerateChecksum (LPVOID packet, DWORD bytes) { + + // COMPUTE THE CURRENT CHECKSUM FOR THE MESSAGE + WORD checksum = ComputeChecksum(((LPBYTE)packet)+sizeof(WORD), + bytes-sizeof(WORD)); + + // COMPUTE A NEW VALUE FOR THE CHECKSUM FIELD THAT WILL MAKE THE NEW + // CHECKSUM OF THE ENTIRE MESSAGE ZERO + BYTE hibyte = 0xFF-((checksum >> 8)+(checksum & 0xFF)) % 0xFF; + BYTE lobyte = 0xFF-((checksum >> 8)+hibyte) % 0xFF; + return MAKEWORD(lobyte,hibyte); +} + +//=========================================================================== +static BOOL LoadArtwork (SNETGETARTPROC artcallback, + DWORD providerid, + DWORD artid, + BOOL setpalette, + LPBYTE *data, + SIZE *size) { + *data = 0; + size->cx = 0; + size->cy = 0; + + // VERIFY THAT THE APPLICATION HAS REGISTERED AN ARTWORK CALLBACK + if (!artcallback) + return 0; + + // CALL THE ARTWORK CALLBACK TO DETERMINE THE IMAGE DIMENSIONS + int width; + int height; + int bitdepth; + if (!artcallback(providerid, + artid, + NULL, + NULL, + 0, + &width, + &height, + &bitdepth)) + return 0; + if (size) { + size->cx = width; + size->cy = height; + } + + // ALLOCATE MEMORY FOR THE IMAGE + DWORD bytes = width*height*bitdepth/8; + if (!(*data = (LPBYTE)ALLOC(bytes))) + return 0; + + // LOAD THE IMAGE + PALETTEENTRY pe[256]; + if (!artcallback(providerid, + artid, + &pe[0], + *data, + bytes, + &width, + &height, + &bitdepth)) { + FREE(*data); + *data = NULL; + return 0; + } + + // IF REQUESTED, UPDATE THE SYSTEM PALETTE + if (setpalette) + SDrawUpdatePalette(1,254,&pe[1]); + + return 1; +} + +//=========================================================================== +static DWORD PickRandomNumber () { + // RETURN A DWORD-SIZED RANDOM NUMBER. IT IS IMPORTANT THAT WE DON'T + // USE THE RUNTIME LIBRARY RANDOM GENERATOR, BECAUSE WE DON'T WANT TO + // INTERFERE WITH THE APPLICATION'S RANDOM SEQUENCE. + LARGE_INTEGER perfcount; + POINT pos; + QueryPerformanceCounter(&perfcount); + GetCursorPos(&pos); + + static DWORD seed = 0x100001; + seed ^= perfcount.LowPart ^ GetTickCount() ^ pos.x ^ pos.y; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand1 = seed & 0xFFFF; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand2 = seed & 0xFFFF; + return (rand1 << 16) | rand2; +} + +//=========================================================================== +static void ProcessIncomingAd (SOCKADDR_IPX *incomingaddr, + ADVPACKETPTR incomingad, + BOOL remove) { + + // FIX THE INCOMING ADDRESS SO IT POINTS TO THE MAIN PORT, + // NOT THE ADVERTISING PORT + incomingaddr->sa_socket = htons(MAINPORT); + + // ENTER THE CRITICAL SECTION + ipx_critsect.Enter(); + + // DELETE ALL GAMES IN OUR LIST FROM THIS ADDRESS + DWORD gameid = 0; + { + SNETSPI_GAMELISTPTR curr = ipx_gamehead; + while (curr) + if (!memcmp(&curr->owner,incomingaddr,sizeof(SOCKADDR_IPX))) { + gameid = curr->gameid; + SNETSPI_GAMELISTPTR next = curr->next; + LISTFREE(&ipx_gamehead,curr); + curr = next; + } + else + curr = curr->next; + } + + // IF THIS GAME WAS NOT ALREADY IN THE LIST, ADD A NEW ID FOR IT. + // MAKE SURE WE NEVER ASSIGN AN ID OF ZERO. + if (!gameid) + gameid = ++ipx_nextgameid; + if (!gameid) + gameid = ++ipx_nextgameid; + + // IF THIS GAME MATCHES OUR PROGRAM ID AND VERSION ID, AND WE'RE NOT + // REMOVING, THEN ADD IT TO THE LIST + if ((incomingad->header.programid == ipx_programid) && + (incomingad->header.versionid == ipx_versionid) && + !remove) { + SNETSPI_GAMELIST game; + ZeroMemory(&game,sizeof(SNETSPI_GAMELIST)); + game.gameid = gameid; + CopyMemory(&game.owner,incomingaddr,sizeof(SOCKADDR_IPX)); + game.ownerlatency = 50; + game.ownerlasttime = GetTickCount(); + strncpy(game.gamename, + incomingad->strings, + SNETSPI_MAXSTRINGLENGTH); + strncpy(game.gamedescription, + incomingad->strings+strlen(incomingad->strings)+1, + SNETSPI_MAXSTRINGLENGTH); + LISTADD(&ipx_gamehead,&game); + } + + // LEAVE THE CRITICAL SECTION + ipx_critsect.Leave(); + +} + +//=========================================================================== +static void QueueSendTo (SOCKET s, + const char *buffer, + int length, + int flags, + const sockaddr *addr, + int addrlen) { + if (!(s && buffer && addr && (addrlen == sizeof(SOCKADDR_IPX)))) + return; + + // CREATE A NEW RECORD + SENDPTR newptr = NEW(SENDREC); + if (!newptr) + return; + newptr->data = (char *)ALLOC(length); + if (!newptr->data) { + FREE(newptr); + return; + } + newptr->s = s; + newptr->databytes = length; + CopyMemory(&newptr->addr,addr,sizeof(SOCKADDR_IPX)); + CopyMemory(newptr->data,buffer,length); + + // PERFORM RANDOM PACKET CORRUPTION + if ((PickRandomNumber() % 100) < ipx_testparms.corruptpercent) { + BOOL corrupted = 0; + DWORD corruptiontype = PickRandomNumber(); + + // TRUNCATE SOME PACKETS + if (newptr->databytes && !(corruptiontype & 0x0000000F)) { + newptr->databytes = PickRandomNumber() % newptr->databytes; + corrupted = 1; + } + + // OFFSET SOME PACKETS BY ONE BYTE + if (!(corruptiontype & 0x000000F0)) { + MoveMemory(newptr->data, + newptr->data+1, + newptr->databytes-1); + corrupted = 1; + } + if (!(corruptiontype & 0x00000F00)) { + MoveMemory(newptr->data+1, + newptr->data, + newptr->databytes-1); + corrupted = 1; + } + + // CORRUPT THE ADDRESS FOR SOME PACKETS + if (!(corruptiontype & 0x0000F000)) { + *(((LPBYTE)&newptr->addr)+(PickRandomNumber() & 0x0F)) += PickRandomNumber() & 0xFF; + corrupted = 1; + } + + // TOGGLE SINGLE BITS IN SOME PACKETS + if (newptr->databytes && + ((!corrupted) || !(corruptiontype & 0x000F0000))) { + DWORD bit = PickRandomNumber(); + DWORD bytenumber = (bit >> 3) % newptr->databytes; + BYTE bitvalue = (BYTE)(1 << (bit & 7)); + *((LPBYTE)newptr->data+bytenumber) ^= bitvalue; + } + + } + + // DETERMINE THE TIME AT WHICH THE PACKET SHOULD BE SENT + newptr->sendtime = GetTickCount() + +ipx_testparms.mindelay + +(PickRandomNumber() % (ipx_testparms.maxdelay-ipx_testparms.mindelay)); + + // ADD IT TO THE LINKED LIST + ipx_critsect.Enter(); + LISTADDPTREND(&ipx_sendhead,newptr); + ipx_critsect.Leave(); + +} + +//=========================================================================== +static DWORD CALLBACK RecvAdThreadProc (LPVOID param) { + + // SEND OUT A REQUEST FOR ADVERTISEMENTS + SendRequest(); + + // ALLOCATE MEMORY FOR INCOMING PACKETS + ADVPACKETPTR incomingad = NEW(ADVPACKET); + if (!incomingad) + return 0; + + while (ipx_advsocket && !ipx_shutdown) { + + // PROCESS ALL INCOMING ADVERTISEMENTS + SOCKADDR_IPX incomingaddr; + int addrsize = sizeof(SOCKADDR_IPX); + int bytesread = recvfrom(ipx_advsocket, + (char *)incomingad, + sizeof(ADVPACKET), + 0, + (sockaddr *)&incomingaddr, + &addrsize); + if ((bytesread >= sizeof(ADVHEADER)) && + (incomingad->header.length == bytesread) && + !ComputeChecksum(incomingad,incomingad->header.length)) + switch (incomingad->header.type) { + + case ADTYPE_GAMEINFO: + case ADTYPE_REMOVE: + ProcessIncomingAd(&incomingaddr, + incomingad, + (incomingad->header.type == ADTYPE_REMOVE)); + break; + + case ADTYPE_REQUEST: + SendAdvertisement(); + break; + + } + + } + + // FREE THE INCOMING GAME BUFFER + FREE(incomingad); + + // FREE THE LIST OF GAMES + LISTCLEAR(&ipx_gamehead); + + return 0; +} + +//=========================================================================== +static DWORD CALLBACK RecvDataThreadProc (LPVOID param) { + while (ipx_mainsocket && !ipx_shutdown) { + + // ALLOCATE MEMORY FOR THE NEXT INCOMING PACKET + PACKETPTR pkt = NEW(PACKET); + + // RECEIVE A PACKET, BLOCKING IF ONE IS NOT AVAILABLE YET. WHEN THE + // NETWORK DRIVER HAS INCOMING DATA ON A PORT, IT WILL COPY IT DIRECTLY + // TO THE APPLICATION'S ADDRESS SPACE IF THE APPLICATION IS BLOCKING ON + // A READ. FOR THIS REASON, WE TRY TO ALWAYS HAVE AT LEAST ONE READ + // PENDING. + int addrsize = sizeof(SOCKADDR_IPX); + int bytesread = recvfrom(ipx_mainsocket, + (char *)&pkt->data, + MAXMESSAGESIZE, + 0, + (sockaddr *)&pkt->addr, + &addrsize); + pkt->databytes = bytesread; + ZeroMemory(((LPBYTE)&pkt->addr)+addrsize,sizeof(SNETADDR)-addrsize); + + // SINCE WE DON'T TIME OUT ON READS, THE ONLY WAY A READ CAN FAIL IS + // IF THE SOCKET WAS CLOSED. IN THIS CASE, SHUT DOWN THE THREAD. + if ((bytesread < 0) || ipx_shutdown) { + FREE(pkt); + return 0; + } + + // ON A SUCCESSFUL READ, QUEUE THE PACKET + ipx_critsect.Enter(); + LISTADDPTREND(&ipx_packethead,pkt); + ipx_critsect.Leave(); + SetEvent(ipx_recvevent); + + } + return 0; +} + +//=========================================================================== +static DWORD CALLBACK SendThreadProc (LPVOID param) { + while (!ipx_shutdown) { + if (ipx_sendhead) { + ipx_critsect.Enter(); + + // TRAVERSE THE SEND QUEUE, LOOKING FOR PACKETS THAT ARE READY TO + // BE SENT + DWORD currtime = GetTickCount(); + SENDPTR *next = &ipx_sendhead; + while (*next) + if ((DWORD)(currtime-(*next)->sendtime) <= 0x7FFFFFFF) { + SENDPTR curr = *next; + + // SEND THE PACKET + sendto(curr->s, + curr->data, + curr->databytes, + 0, + (const sockaddr *)&curr->addr, + sizeof(SOCKADDR_IPX)); + + // UNLINK IT FROM THE QUEUE + *next = curr->next; + + // FREE THE RECORD AND PACKET DATA + FREE(curr->data); + FREE(curr); + + // SLEEP FOR ONE QUANTUM BEFORE PROCESSING THE NEXT PACKET + Sleep(1); + + } + else + next = &(*next)->next; + + ipx_critsect.Leave(); + } + Sleep(50); + } + return 0; +} + +//=========================================================================== +static BOOL CALLBACK SelectGameDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + static LPBYTE background = NULL; + static LPBYTE buttontexture = NULL; + static UIPARAMSPTR uiparams = NULL; + switch (message) { + + case WM_COMMAND: + + // IF THE USER CLICKED 'JOIN GAME', TRY TO JOIN THE SELECTED GAME + if (LOWORD(wparam) == IDOK) { + LPARAM cursel = SendDlgItemMessage(window,IDC_GAMELIST,LB_GETCURSEL,0,0); + if (cursel != LB_ERR) { + char fullname[2*SNETSPI_MAXSTRINGLENGTH] = ""; + SendDlgItemMessage(window,IDC_GAMELIST,LB_GETTEXT,cursel,(LPARAM)fullname); + if (fullname[0]) { + if (strchr(fullname,'\t')) + *strchr(fullname,'\t') = 0; + if (SNetJoinGame(0, + fullname, + NULL, + uiparams->playerdata->playername, + uiparams->playerdata->playerdescription, + uiparams->playeridptr)) { + KillTimer(window,1); + SDlgEndDialog(window,1); + } + else + uiparams->interfacedata->messageboxcallback(window, + "Unable to connect.", + uiparams->programdata->programname, + 0); + } + } + } + + // IF THE USER CLICKED 'CREATE GAME', CALL THE CREATE GAME CALLBACK + else if ((LOWORD(wparam) == IDC_CREATEGAME) && + uiparams->interfacedata->createcallback) { + + // BUILD A NEW INTERFACE DATA STRUCTURE CONTAINING OUR WINDOW HANDLE + SNETUIDATA interfacedata; + CopyMemory(&interfacedata,uiparams->interfacedata,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = window; + + // BUILD A CREATION DATA STRUCTURE + SNETCREATEDATA createdata; + ZeroMemory(&createdata,sizeof(SNETCREATEDATA)); + createdata.size = sizeof(SNETCREATEDATA); + createdata.providerid = PROVIDERID; + createdata.maxplayers = ipx_maxplayers; + createdata.createflags = 0; + + // CALL THE CREATE GAME CALLBACK + if (uiparams->interfacedata->createcallback(&createdata, + uiparams->programdata, + uiparams->playerdata, + &interfacedata, + uiparams->versiondata, + uiparams->playeridptr)) { + KillTimer(window,1); + SDlgEndDialog(window,1); + } + + } + + // IF THE USER CLICKED 'DISCONNECT', END THE DIALOG + else if (LOWORD(wparam) == IDCANCEL) { + KillTimer(window,1); + SDlgEndDialog(window,0); + } + + // IF THE USER SELECTED A NEW LIST BOX ITEM, UPDATE THE GAME + // DESCRIPTION + else if ((LOWORD(wparam) == IDC_GAMELIST) && + (HIWORD(wparam) == LBN_SELCHANGE)) + InvalidateRect(GetDlgItem(window,IDC_GAMEDESCRIPTION),NULL,1); + + // IF THE USER DOUBLE-CLICKED A LIST BOX ITEM, POST AN 'OK' COMMAND + else if ((LOWORD(wparam) == IDC_GAMELIST) && + (HIWORD(wparam) == LBN_DBLCLK)) + PostMessage(window,WM_COMMAND,MAKELONG(IDOK,BN_CLICKED),(LPARAM)GetDlgItem(window,IDOK)); + + break; + + case WM_DESTROY: + if (background) { + FREE(background); + background = NULL; + } + if (buttontexture) { + FREE(buttontexture); + buttontexture = NULL; + } + uiparams = NULL; + break; + + case WM_DRAWITEM: + if (wparam == IDC_GAMEDESCRIPTION) { + + // GET THE GAME NAME AND DESCRIPTION + char name[256] = ""; + { + LRESULT sel = SendDlgItemMessage(window,IDC_GAMELIST,LB_GETCURSEL,0,0); + if (sel != LB_ERR) + SendDlgItemMessage(window,IDC_GAMELIST,LB_GETTEXT,sel,(LPARAM)name); + } + LPSTR description = ""; + if (strchr(name,'\t')) { + description = strchr(name,'\t'); + *description++ = 0; + } + + // UPDATE THE DESCRIPTION IN THE STATIC TEXT CONTROL + { + char buffer[256] = ""; + GetDlgItemText(window,IDC_GAMEDESCRIPTION,buffer,256); + buffer[255] = 0; + if (strcmp(buffer,description)) + SetDlgItemText(window,IDC_GAMEDESCRIPTION,description); + } + + // IF THE APPLICATION HAS REGISTERED A DRAW DESCRIPTION CALLBACK, + // LET IT DRAW THE DESCRIPTION + if (uiparams->interfacedata->drawdesccallback) + return uiparams->interfacedata->drawdesccallback(PROVIDERID, + SNET_DRAWTYPE_GAME, + name, + description, + 0, + 0, + SNET_DDF_MULTILINE, + (LPDRAWITEMSTRUCT)lparam); + + // OTHERWISE, LET THE DEFAULT DIALOG BOX PROCEDURE DRAW THE + // DESCRIPTION FROM THE STATIC TEXT + else + return 0; + + } + break; + + case WM_INITDIALOG: + + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + uiparams = (UIPARAMSPTR)lparam; + + // LOAD THE ARTWORK FOR THIS DIALOG + { + SIZE size; + if (LoadArtwork(uiparams->interfacedata->artcallback, + PROVIDERID, + SNET_ART_BACKGROUND, + 1, + &background, + &size)) { + SDlgSetBitmap(window, + NULL, + "", + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + background, + NULL, + size.cx, + size.cy); + int controllist[2] = {IDC_GAMEDESCRIPTION,0}; + SDlgSetControlBitmaps(window, + &controllist[0], + NULL, + background, + &size, + SDLG_ADJUST_CONTROLPOS); + } + if (LoadArtwork(uiparams->interfacedata->artcallback, + PROVIDERID, + SNET_ART_BUTTONTEXTURE, + 0, + &buttontexture, + &size)) { + int controllist[4] = {IDC_CREATEGAME,IDOK,IDCANCEL,0}; + SDlgSetControlBitmaps(window, + &controllist[0], + NULL, + buttontexture, + &size, + SDLG_ADJUST_VERTICAL); + } + } + + // DRAW THE PROGRAM DESCRIPTION + SetDlgItemTextA(window,IDC_PROGRAMDESCRIPTION,uiparams->programdata->programdescription); + + // SET THE FIRST TAB STOP FOR THE GAME LIST TO WIDER THAN THE LIST BOX, + // TO HIDE ALL TABBED TEXT + { + RECT rect; + GetClientRect(GetDlgItem(window,IDC_GAMELIST),&rect); + SendDlgItemMessage(window,IDC_GAMELIST,LB_SETTABSTOPS,1,(LPARAM)&rect.right); + } + + PostMessage(window,WM_USER,0,0); + SetTimer(window,1,500,NULL); + return 1; + + case WM_TIMER: + case WM_USER: + SendRequest(); + TrimGameList(3000); + UpdateGameList(window,GetDlgItem(window,IDC_GAMELIST)); + break; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +static void SendAdvertisement () { + ipx_critsect.Enter(); + if (ipx_advgameinfo) + QueueSendTo(ipx_advsocket, + (const char *)ipx_advgameinfo, + ipx_advgameinfo->header.length, + 0, + (const sockaddr *)&ipx_broadcastaddr, + sizeof(SOCKADDR_IPX)); + ipx_critsect.Leave(); +} + +//=========================================================================== +static void SendRequest () { + ADVHEADER request; + ZeroMemory(&request,sizeof(ADVHEADER)); + request.checksum = 0; + request.length = sizeof(ADVHEADER); + request.type = ADTYPE_REQUEST; + request.reserved = 0; + request.programid = ipx_programid; + request.versionid = ipx_versionid; + request.checksum = GenerateChecksum(&request,sizeof(ADVHEADER)); + QueueSendTo(ipx_advsocket, + (const char *)&request, + request.length, + 0, + (const sockaddr *)&ipx_broadcastaddr, + sizeof(SOCKADDR_IPX)); +} + +//=========================================================================== +static void TrimGameList (DWORD timeout) { + ipx_critsect.Enter(); + { + DWORD currtime = GetTickCount(); + SNETSPI_GAMELISTPTR *next = &ipx_gamehead; + while (*next) + if (currtime-(*next)->ownerlasttime > timeout) { + SNETSPI_GAMELISTPTR freeptr = *next; + *next = (*next)->next; + FREE(freeptr); + } + else + next = &(*next)->next; + } + ipx_critsect.Leave(); +} + +//=========================================================================== +static void UpdateGameList (HWND dialog, HWND listbox) { + ipx_critsect.Enter(); + + // MAKE SURE ALL GAMES IN THE LINKED LIST ARE REPRESENTED IN THE LIST BOX + { + SNETSPI_GAMELISTPTR curr = ipx_gamehead; + while (curr) { + if (!(curr->gamemode & SNET_GM_PRIVATE)) { + char fullstring[2*SNETSPI_MAXSTRINGLENGTH]; + sprintf(fullstring,"%s\t%s",curr->gamename,curr->gamedescription); + if (SendMessage(listbox,LB_FINDSTRINGEXACT,(WPARAM)-1,(LPARAM)fullstring) == LB_ERR) { + SendMessage(listbox,LB_ADDSTRING,0,(LPARAM)fullstring); + EnableWindow(GetDlgItem(dialog,IDOK),1); + if (SendMessage(listbox,LB_GETCURSEL,0,0) == LB_ERR) { + SendMessage(listbox,LB_SETCURSEL,0,0); + SendMessage(dialog,WM_COMMAND,MAKELONG(IDC_GAMELIST,LBN_SELCHANGE),(LPARAM)listbox); + } + } + } + curr = curr->next; + } + } + + // MAKE SURE THERE ARE NO GAME IN THE LIST BOX THAT AREN'T IN THE LINKED LIST + { + char liststring[2*SNETSPI_MAXSTRINGLENGTH]; + WPARAM index = 0; + while (SendMessage(listbox,LB_GETTEXT,index,(LPARAM)liststring) != LB_ERR) { + SNETSPI_GAMELISTPTR curr = ipx_gamehead; + while (curr) { + if (!(curr->gamemode & SNET_GM_PRIVATE)) { + char fullstring[2*SNETSPI_MAXSTRINGLENGTH]; + sprintf(fullstring,"%s\t%s",curr->gamename,curr->gamedescription); + if (!strcmp(fullstring,liststring)) + break; + } + curr = curr->next; + } + if (!curr) { + if (SendMessage(listbox,LB_GETCURSEL,0,0) == index) { + SendMessage(listbox,LB_SETCURSEL,index-1,0); + SendMessage(dialog,WM_COMMAND,MAKELONG(IDC_GAMELIST,LBN_SELCHANGE),(LPARAM)listbox); + } + if (!SendMessage(listbox,LB_DELETESTRING,index,0)) + EnableWindow(GetDlgItem(dialog,IDOK),0); + } + else + ++index; + } + } + + ipx_critsect.Leave(); +} + +/**************************************************************************** +* +* SERVICE PROVIDER INTERFACE FUNCTIONS +* +***/ + +//=========================================================================== +BOOL CALLBACK IpxCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude) { + if (diffmagnitude) + *diffmagnitude = 0; + if (!(addr1 && addr2 && diffmagnitude)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // COMPARE THE ADDRESSES, AND RETURN: + // 2 IF THEY ARE ON DIFFERENT NETWORKS + // 1 IF THEY ARE DIFFERENT ADDRESSES ON THE SAME NETWORK + // 0 IF THEY ARE THE SAME ADDRESS + SOCKADDR_IPX *ipxaddr1 = (SOCKADDR_IPX *)addr1; + SOCKADDR_IPX *ipxaddr2 = (SOCKADDR_IPX *)addr2; + if ((*(DWORD *)&ipxaddr1->sa_netnum) != + (*(DWORD *)&ipxaddr2->sa_netnum)) + *diffmagnitude = 2; + else if (memcmp(ipxaddr1,ipxaddr2,sizeof(SOCKADDR_IPX))) + *diffmagnitude = 1; + else + *diffmagnitude = 0; + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxDestroy () { + + // START THE SHUTDOWN PROCESS + ipx_shutdown = 1; + + // SEND DATA TO THE RECEIVE THREADS TO WAKE THEM UP + { + SOCKADDR_IPX sendaddr; + CopyMemory(&sendaddr,&ipx_broadcastaddr,sizeof(SOCKADDR_IPX)); + BYTE buffer[8] = {0x08,0xEF,0x08,0x00,0x00,0x00,0x00,0x00}; + sendaddr.sa_socket = htons(ADVPORT); + sendto(ipx_advsocket,(const char *)&buffer[0],8,0,(const sockaddr *)&sendaddr,sizeof(SOCKADDR_IPX)); + sendaddr.sa_socket = htons(MAINPORT); + for (int loop = 0; loop < RECVDATATHREADS; ++loop) + sendto(ipx_mainsocket,(const char *)&buffer[0],8,0,(sockaddr *)&sendaddr,sizeof(SOCKADDR_IPX)); + } + + // WAIT FOR ALL THREADS TO TERMINATE + while (ipx_threadhead) { + WaitForSingleObject(ipx_threadhead->handle,100); + CloseHandle(ipx_threadhead->handle); + LISTFREE(&ipx_threadhead,ipx_threadhead); + } + + // CLOSE THE SOCKETS + if (ipx_mainsocket) { + closesocket(ipx_mainsocket); + ipx_mainsocket = (SOCKET)0; + } + if (ipx_advsocket) { + closesocket(ipx_advsocket); + ipx_advsocket = (SOCKET)0; + } + + // TAKE CONTROL OF THE CRITICAL SECTION + ipx_critsect.Enter(); + + // FREE THE GAME INFO + IpxStopAdvertisingGame(); + + // CLEAR OUT THE SEND QUEUE + while (ipx_sendhead) { + FREE(ipx_sendhead->data); + LISTFREE(&ipx_sendhead,ipx_sendhead); + } + + // FREE ALL UNPROCESSED PACKETS + LISTCLEAR(&ipx_packethead); + + // CLEAN UP WINDOWS SOCKETS + WSACleanup(); + + // LEAVE THE CRITICAL SECTION + ipx_critsect.Leave(); + + // FINISH THE SHUTDOWN PROCESS + ipx_shutdown = 0; + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxFree (SNETADDRPTR addr, + LPVOID data, + DWORD databytes) { + if (!(addr && data)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + FREE(addr); + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxFreeExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR mesage) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxGetGameInfo (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + SNETSPI_GAMELIST *gameinfo) { + if (gameinfo) + ZeroMemory(gameinfo,sizeof(SNETSPI_GAMELIST)); + if (!(gamename && gameinfo && (gameid || *gamename))) + return 0; + + // SEARCH FOR A GAME IN THE GAME LIST MATCHING THE QUERY PARAMETERS + ipx_critsect.Enter(); + { + SNETSPI_GAMELISTPTR curr = ipx_gamehead; + while (curr) + if (((!gameid) || (gameid == curr->gameid)) && + ((!*gamename) || !_stricmp(gamename,curr->gamename))) { + CopyMemory(gameinfo,curr,sizeof(SNETSPI_GAMELIST)); + break; + } + else + curr = curr->next; + } + ipx_critsect.Leave(); + + if (gameinfo->gameid) + return 1; + else { + SetLastError(SNET_ERROR_GAME_NOT_FOUND); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK IpxGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq) { + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + HANDLE event) { + + // SAVE THE PROGRAM AND VERSION IDS AND THE RECEIVE EVENT HANDLE + ipx_programid = programdata->programid; + ipx_versionid = programdata->versionid; + ipx_maxplayers = min(programdata->maxplayers,MAXPLAYERS); + ipx_recvevent = event; + + // INITIALIZE WINDOWS SOCKETS + { + WSADATA data; + if (WSAStartup(MAKEWORD(1,1),&data)) { + IpxDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + } + + // CREATE TWO SOCKETS: ONE FOR APPLICATION DATA AND ONE FOR ADVERTISING + ipx_advsocket = socket(PF_NS,SOCK_DGRAM,NSPROTO_IPX); + ipx_mainsocket = socket(PF_NS,SOCK_DGRAM,NSPROTO_IPX); + if (!(ipx_advsocket && ipx_mainsocket)) { + IpxDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + + // DETERMINE THE BROADCAST ADDRESS + { + ZeroMemory(&ipx_broadcastaddr,sizeof(SOCKADDR_IPX)); + for (int loop = 0; loop < 6; ++loop) + ipx_broadcastaddr.sa_nodenum[loop] = 0xFF; + ipx_broadcastaddr.sa_family = AF_IPX; + ipx_broadcastaddr.sa_socket = htons(ADVPORT); + } + + // BIND TO THE MAIN SOCKET, DETERMINING OUR LOCAL ADDRESS + ZeroMemory(&ipx_localaddr,sizeof(SOCKADDR_IPX)); + ipx_localaddr.sa_family = AF_IPX; + ipx_localaddr.sa_socket = htons(MAINPORT); + if (bind(ipx_mainsocket, + (const struct sockaddr *)&ipx_localaddr, + sizeof(SOCKADDR_IPX))) { + IpxDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + + // BIND TO THE ADVERTISING SOCKET + { + SOCKADDR_IPX advaddr; + CopyMemory(&advaddr,&ipx_localaddr,sizeof(SOCKADDR_IPX)); + advaddr.sa_socket = htons(ADVPORT); + if (bind(ipx_advsocket, + (const struct sockaddr *)&advaddr, + sizeof(SOCKADDR_IPX))) { + IpxDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + } + + // ALLOW BROADCASTS TO BE SENT ON THE SOCKETS (DUE TO A BUG IN WINDOWS 95, + // THIS OPTION IS ALSO REQUIRED FOR RECEIVING BROADCASTS) + { + BOOL value = 1; + setsockopt(ipx_advsocket, + SOL_SOCKET, + SO_BROADCAST, + (const char *)&value, + sizeof(BOOL)); + setsockopt(ipx_mainsocket, + SOL_SOCKET, + SO_BROADCAST, + (const char *)&value, + sizeof(BOOL)); + } + + // CREATE A THREAD TO RECEIVE PACKETS ON THE ADVERTISING SOCKET + { + THREAD thread; + thread.handle = CreateThread((LPSECURITY_ATTRIBUTES)NULL, + 0, + RecvAdThreadProc, + NULL, + 0, + &thread.id); + if (thread.handle) { + SetThreadPriority(thread.handle,THREAD_PRIORITY_ABOVE_NORMAL); + LISTADD(&ipx_threadhead,&thread); + } + } + + // CREATE THREADS TO READ PACKETS FROM THE MAIN SOCKET + { + for (int loop = 0; loop < RECVDATATHREADS; ++loop) { + THREAD thread; + thread.handle = CreateThread((LPSECURITY_ATTRIBUTES)NULL, + 0, + RecvDataThreadProc, + NULL, + 0, + &thread.id); + if (thread.handle) { + SetThreadPriority(thread.handle,THREAD_PRIORITY_ABOVE_NORMAL); + LISTADD(&ipx_threadhead,&thread); + } + } + } + + // CREATE A THREAD TO DEQUEUE PACKETS FROM THE SEND QUEUE AND SEND THEM + // OUT ON THE WIRE + { + THREAD thread; + thread.handle = CreateThread((LPSECURITY_ATTRIBUTES)NULL, + 0, + SendThreadProc, + NULL, + 0, + &thread.id); + if (thread.handle) { + SetThreadPriority(thread.handle,THREAD_PRIORITY_ABOVE_NORMAL); + LISTADD(&ipx_threadhead,&thread); + } + } + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + + // WE NEVER RETURN ANY DEVICES, SO THIS FUNCTION SHOULD NEVER BE CALLED + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxLockDeviceList (SNETSPI_DEVICELISTPTR *devicelist) { + *devicelist = NULL; + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxLockGameList (LPCSTR selectioncriteria, + SNETSPI_GAMELISTPTR *gamelist) { + if (!gamelist) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // TRIM ANY GAMES THAT WE HAVEN'T HEARD FROM IN A WHILE + { + static DWORD lasttime = GetTickCount(); + DWORD currtime = GetTickCount(); + TrimGameList(max(3000,2*(currtime-lasttime))); + } + + // LOCK THE GAME LIST + ipx_critsect.Enter(); + *gamelist = ipx_gamehead; + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxReceive (SNETADDRPTR *addr, + LPVOID *data, + DWORD *databytes) { + if (addr) + *addr = NULL; + if (data) + *data = NULL; + if (databytes) + *databytes = NULL; + if (!(addr && data && databytes && ipx_mainsocket)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // IF THERE IS A PACKET QUEUED, REMOVE IT FROM THE QUEUE AND RETURN + // POINTERS TO THE CALLER. NOTE THAT WE UNLINK THE PACKET BUT DON'T + // FREE IT FROM MEMORY; IT IS THE CALLER'S RESPONSIBILITY TO CALL + // OUR FREE FUNCTION WHEN IT IS DONE WITH THE PACKET. + if (ipx_packethead) { + ipx_critsect.Enter(); + *addr = &ipx_packethead->addr; + *data = ipx_packethead->data; + *databytes = ipx_packethead->databytes; + ipx_packethead = ipx_packethead->next; + ipx_critsect.Leave(); + return 1; + } + else { + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK IpxReceiveExternalMessage (LPCSTR *senderpath, + LPCSTR *sendername, + LPCSTR *message) { + if (senderpath) + *senderpath = NULL; + if (sendername) + *sendername = NULL; + if (message) + *message = NULL; + + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + + // BUILD A USER INTERFACE DATA BLOCK + UIPARAMS uiparams; + ZeroMemory(&uiparams,sizeof(UIPARAMS)); + uiparams.flags = flags; + uiparams.programdata = programdata; + uiparams.playerdata = playerdata; + uiparams.interfacedata = interfacedata; + uiparams.versiondata = versiondata; + uiparams.playeridptr = playerid; + + // DISPLAY THE DIALOG BOX + DWORD result = (DWORD)SDlgDialogBoxParam(ipx_instance, + "IPXSELECTGAME_DIALOG", + interfacedata ? interfacedata->parentwindow + : SDrawGetFrameWindow(), + SelectGameDialogProc, + (LPARAM)&uiparams); + + return (result != 0); +} + +//=========================================================================== +BOOL CALLBACK IpxSend (DWORD addresses, + SNETADDRPTR *addrlist, + LPVOID data, + DWORD databytes) { + if (!(addresses && addrlist && data && databytes && ipx_mainsocket)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // SEND THE PACKET + while (addresses--) + QueueSendTo(ipx_mainsocket, + (const char *)data, + databytes, + 0, + (const sockaddr *)*(addrlist+addresses), + sizeof(SOCKADDR_IPX)); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxSendExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR targetpath, + LPCSTR targetname, + LPCSTR message) { + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD creationtime) { + if (!(gamename && gamedescription)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // CREATE A STRUCTURE TO CONTAIN THE DATA WE NEED TO ADVERTISE + ipx_critsect.Enter(); + if (!ipx_advgameinfo) { + ipx_advgameinfo = NEW(ADVPACKET); + if (!ipx_advgameinfo) { + ipx_critsect.Leave(); + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + ZeroMemory(ipx_advgameinfo,sizeof(ADVPACKET)); + ipx_advgameinfo->header.checksum = 0; + ipx_advgameinfo->header.length = sizeof(ADVHEADER) + +strlen(gamename) + +strlen(gamedescription) + +2; + ipx_advgameinfo->header.type = ADTYPE_GAMEINFO; + ipx_advgameinfo->header.reserved = 0; + ipx_advgameinfo->header.programid = ipx_programid; + ipx_advgameinfo->header.versionid = ipx_versionid; + strncpy(ipx_advgameinfo->strings, + gamename, + SNETSPI_MAXSTRINGLENGTH); + strncpy(ipx_advgameinfo->strings + +min(SNETSPI_MAXSTRINGLENGTH,strlen(ipx_advgameinfo->strings)+1), + gamedescription, + SNETSPI_MAXSTRINGLENGTH); + ipx_advgameinfo->header.checksum = GenerateChecksum(ipx_advgameinfo, + ipx_advgameinfo->header.length); + ipx_critsect.Leave(); + + // SEND THE FIRST ADVERTISEMENT + SendAdvertisement(); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxStopAdvertisingGame () { + + // DELETE THE ADVERTISEMENT DATA AND SEND OUT A REMOVE GAME MESSAGE + ipx_critsect.Enter(); + if (ipx_advgameinfo) { + ipx_advgameinfo->header.checksum = 0; + ipx_advgameinfo->header.type = ADTYPE_REMOVE; + ipx_advgameinfo->header.checksum = GenerateChecksum(ipx_advgameinfo, + ipx_advgameinfo->header.length); + QueueSendTo(ipx_advsocket, + (const char *)ipx_advgameinfo, + ipx_advgameinfo->header.length, + 0, + (const sockaddr *)&ipx_broadcastaddr, + sizeof(SOCKADDR_IPX)); + FREE(ipx_advgameinfo); + ipx_advgameinfo = NULL; + } + ipx_critsect.Leave(); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxUnlockDeviceList (SNETSPI_DEVICELISTPTR devicelist) { + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxUnlockGameList (SNETSPI_GAMELISTPTR gamelist, + DWORD *hintnextcall) { + if (gamelist != ipx_gamehead) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // UNLOCK THE GAME LIST + ipx_critsect.Leave(); + if (hintnextcall) + *hintnextcall = 1000; + + // SEND OUT A REQUEST FOR ADVERTISEMENTS, SO WE WILL HAVE UPDATED DATA + // THE NEXT TIME IT IS REQUESTED + { + static DWORD lasttime = 0; + DWORD currtime = GetTickCount(); + if (currtime-lasttime > 400) { + lasttime = currtime; + SendRequest(); + } + } + + return 1; +} + +/**************************************************************************** +* +* EXPORTED STRUCTURES +* +***/ + +DWORD ipx_id = PROVIDERID; +LPCSTR ipx_desc = "IPX Latency/Corrupt Test"; +LPCSTR ipx_req = "All computers must be connected to an IPX-compatible network."; +SNETCAPS ipx_caps = {sizeof(SNETCAPS), // size + SNET_CAPS_PAGELOCKEDBUFFERS // flags + | SNET_CAPS_BASICINTERFACE, + MAXMESSAGESIZE, // max message size + 16, // max queue size, + MAXPLAYERS, // max players, + 1500, // bytes per second + 500, // latency (ms) + 4, // default turns per second + 2}; // default turns in transit +SNETSPI ipx_spi = {sizeof(SNETSPI), + IpxCompareNetAddresses, + IpxDestroy, + IpxFree, + IpxFreeExternalMessage, + IpxGetGameInfo, + IpxGetPerformanceData, + IpxInitialize, + IpxInitializeDevice, + IpxLockDeviceList, + IpxLockGameList, + IpxReceive, + IpxReceiveExternalMessage, + IpxSelectGame, + IpxSend, + IpxSendExternalMessage, + IpxStartAdvertisingGame, + IpxStopAdvertisingGame, + IpxUnlockDeviceList, + IpxUnlockGameList}; + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +extern "C" BOOL APIENTRY Query (DWORD index, + DWORD *id, + LPCSTR *description, + LPCSTR *requirements, + SNETCAPSPTR *caps) { + if (!(id && description && requirements && caps)) + return 0; + switch (index) { + + case 0: + *id = ipx_id; + *description = ipx_desc; + *requirements = ipx_req; + *caps = &ipx_caps; + return 1; + + default: + return 0; + + } +} + +//=========================================================================== +extern "C" BOOL APIENTRY Bind (DWORD index, + SNETSPIPTR *spi) { + if (!spi) + return 0; + + switch (index) { + + case 0: + *spi = &ipx_spi; + return 1; + + default: + return 0; + + } +} + +//=========================================================================== +extern "C" BOOL APIENTRY DllMain (HINSTANCE passinstance, DWORD reason, LPVOID) { + if (reason == DLL_PROCESS_ATTACH) + ipx_instance = passinstance; + return 1; +} diff --git a/src/Storm/SOURCE/IPXTEST/IPXTEST.CS b/src/Storm/SOURCE/IPXTEST/IPXTEST.CS new file mode 100644 index 0000000..85552a3 --- /dev/null +++ b/src/Storm/SOURCE/IPXTEST/IPXTEST.CS @@ -0,0 +1,8 @@ +#include +set extralib=storm.lib wsock32.lib +set linkopt=%linkopt% -base:0x17000000 +!if exist %project%.snp del %project%.snp +!rename %project%.dll %project%.snp +!copy %project%.snp ..\..\bin > NUL: +!if %debug% copy %project%.snp ..\..\bin\debug > NUL: +!if exist *.bak del *.bak diff --git a/src/Storm/SOURCE/IPXTEST/IPXTEST.DEF b/src/Storm/SOURCE/IPXTEST/IPXTEST.DEF new file mode 100644 index 0000000..9b40e88 --- /dev/null +++ b/src/Storm/SOURCE/IPXTEST/IPXTEST.DEF @@ -0,0 +1,4 @@ +LIBRARY ipxtest +EXPORTS +Bind +Query diff --git a/src/Storm/SOURCE/IPXTEST/IPXTEST.RC b/src/Storm/SOURCE/IPXTEST/IPXTEST.RC new file mode 100644 index 0000000..d88e307 --- /dev/null +++ b/src/Storm/SOURCE/IPXTEST/IPXTEST.RC @@ -0,0 +1,105 @@ +//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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IPXSELECTGAME_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE DS_3DLOOK | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700 +BEGIN + LTEXT "IPX Games Available",IDC_STATIC,10,62,124,10,0, + WS_EX_TRANSPARENT + LISTBOX IDC_GAMELIST,10,74,124,80,LBS_SORT | LBS_USETABSTOPS | + WS_VSCROLL | WS_TABSTOP + LTEXT "Description:",IDC_STATIC,10,152,124,10,0, + WS_EX_TRANSPARENT + LTEXT "",IDC_GAMEDESCRIPTION,10,162,124,30 + LTEXT "",IDC_PROGRAMDESCRIPTION,10,192,124,9,0, + WS_EX_TRANSPARENT + DEFPUSHBUTTON "&Join Game",IDOK,160,147,90,12,WS_DISABLED + PUSHBUTTON "&Create Game",IDC_CREATEGAME,160,161,90,12 + PUSHBUTTON "&Disconnect",IDCANCEL,160,175,90,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "SELECTGAME_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 250 + TOPMARGIN, 7 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SOURCE/IPXTEST/RESOURCE.H b/src/Storm/SOURCE/IPXTEST/RESOURCE.H new file mode 100644 index 0000000..efa17cc --- /dev/null +++ b/src/Storm/SOURCE/IPXTEST/RESOURCE.H @@ -0,0 +1,20 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by ipxtest.rc +// +#define IDC_CREATEGAME 3 +#define IDC_GAMELIST 1001 +#define IDC_STATIC -1 +#define IDC_GAMEDESCRIPTION 103 +#define IDC_PROGRAMDESCRIPTION 104 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SOURCE/MAIN.CPP b/src/Storm/SOURCE/MAIN.CPP new file mode 100644 index 0000000..267a02c --- /dev/null +++ b/src/Storm/SOURCE/MAIN.CPP @@ -0,0 +1,7 @@ + +#include + +int main(int argc, char *argv[]) +{ + return EXIT_SUCCESS; +} diff --git a/src/Storm/SOURCE/MSG00001.BIN b/src/Storm/SOURCE/MSG00001.BIN new file mode 100644 index 0000000..a00ce8c Binary files /dev/null and b/src/Storm/SOURCE/MSG00001.BIN differ diff --git a/src/Storm/SOURCE/PCH.H b/src/Storm/SOURCE/PCH.H new file mode 100644 index 0000000..839808e --- /dev/null +++ b/src/Storm/SOURCE/PCH.H @@ -0,0 +1,21 @@ +#define OEMRESOURCE +#define STRICT +#define _WIN32_WINNT 0x0400 +#define STORMSTATIC // see prototypes for initialize and destroy functions +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "storm.h" +#include "sintern.h" +#include "resource.h" diff --git a/src/Storm/SOURCE/RESOURCE.H b/src/Storm/SOURCE/RESOURCE.H new file mode 100644 index 0000000..cd634a7 --- /dev/null +++ b/src/Storm/SOURCE/RESOURCE.H @@ -0,0 +1,38 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by STORM.RC +// +#define IDS_BASE 0x5100 +#define IDS_ERROR 0x5100 +#define IDS_HEADER 0x5101 +#define IDS_PROGRAM 0x5102 +#define IDS_FILELINE 0x5103 +#define IDS_FUNCTION 0x5104 +#define IDS_OBJECT 0x5105 +#define IDS_HANDLE 0x5106 +#define IDS_EXPRESSION 0x5107 +#define IDS_DESCRIPTION 0x5108 +#define IDS_TERMINATE 0x5109 +#define IDS_RECOVERABLE 0x510A +#define IDS_FILE 0x510B +#define IDS_BADARGUMENT 0x5201 +#define IDS_NOTENOUGHARGUMENTS 0x5202 +#define IDS_OPENFAILED 0x5203 + +#define IDC_CREATEGAME 0x5180 +#define IDC_PROVIDERLIST 0x5181 +#define IDC_MAXPLAYERS 0x5182 +#define IDC_REQUIREMENTS 0x5183 +#define IDC_PROGRAMDESCRIPTION 0x5184 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1002 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SOURCE/SBLT.CPP b/src/Storm/SOURCE/SBLT.CPP new file mode 100644 index 0000000..9968ac3 --- /dev/null +++ b/src/Storm/SOURCE/SBLT.CPP @@ -0,0 +1,431 @@ +/**************************************************************************** +* +* SBLT.CPP +* Storm bitblt engine +* +* By Michael O'Brien (3/13/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define OPT_SRCCOPY 0 +#define OPT_PATCOPY 1 +#define OPTSTREAMS 2 + +#define UNROLL 180 + +typedef struct _OPTSTREAMDATA { + HSCODESTREAM stream; + LPBYTE *jumptable; + LPDWORD patchlocation; +} OPTSTREAMDATA, *OPTSTREAMDATAPTR; + +typedef struct _BLTINFO { + BOOL used; + HSCODESTREAM stream; + DWORD time; + DWORD reserved; +} BLTINFO, *BLTINFOPTR; + +static OPTSTREAMDATA s_optstream[OPTSTREAMS] = {{0},{0}}; +static BLTINFOPTR s_scode = NULL; + +//=========================================================================== +static BOOL InitOptStream (LPCSTR sourcestring, + OPTSTREAMDATAPTR optdata) { + if (!SCodeCompile(NULL,sourcestring,NULL,UNROLL,0,&optdata->stream)) + return FALSE; + if (!SCodeGetJumpTable(optdata->stream, + &optdata->jumptable, + NULL, + &optdata->patchlocation, + NULL)) + return FALSE; + return TRUE; +} + +//=========================================================================== +static void inline OptimizeROP3 (DWORD *rop, DWORD *pattern) { + switch (*rop) { + + case BLACKNESS: + *rop = PATCOPY; + *pattern = 0; + break; + + case WHITENESS: + *rop = PATCOPY; + *pattern = 0xFFFFFFFF; + break; + + case 0x000F0001: + *rop = PATCOPY; + *pattern = !*pattern; + break; + + } +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SBltDestroy () { + if (s_scode) { + int loop; + for (loop = 0; loop < OPTSTREAMS; ++loop) { + SCodeDelete(s_optstream[loop].stream); + ZeroMemory(&s_optstream[loop],sizeof(OPTSTREAMDATA)); + } + for (loop = 0; loop < 256; ++loop) + if ((s_scode+loop)->stream) + SCodeDelete((s_scode+loop)->stream); + FREE(s_scode); + s_scode = NULL; + } + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SBltGetSCode (DWORD rop3, + LPSTR buffer, + DWORD buffersize, + BOOL optimize) { + VALIDATEBEGIN; + VALIDATE(rop3); + VALIDATE(buffer); + VALIDATE(buffersize); + VALIDATEEND; + + // OPTIMIZE THE RASTER OPERATION CODE IF REQUESTED + if (optimize) { + DWORD pattern = 0; + OptimizeROP3(&rop3,&pattern); + } + + // DEFINE THE SOURCE AND OPERATION TEMPLATE STRINGS + static const char optemplate[] = "~^|&"; + static const char sourcetemplate[8][16] = {"SCDDDDDD", + "SCDSCDSC", + "SDCSDCSD", + "DDDDDDDD", + "DDDDDDDD", + "SASCADSS", + "SASCACDS", + "SASDACDS"}; + + // CREATE THE SOURCE STRING IN RPN ORDER + char sourcestring[16]; + SStrCopy(sourcestring,sourcetemplate[(rop3 >> 2) & 7]+(rop3 & 3),16); + + // CREATE THE OPERATION STRING + char opstring[16]; + { + DWORD currrop = rop3 >> 6; + for (int loop = 0; loop < 5; ++loop) { + opstring[loop] = optemplate[currrop & 3]; + currrop >>= 2; + } + opstring[loop] = 0; + if (rop3 & 32) + SStrPack(opstring,"~",16); + } + + // ELIMINATE REDUNDANT NOT OPERATIONS + while ((SStrLen(opstring) >= 2) && + (!strcmp(opstring+SStrLen(opstring)-2,"~~"))) + opstring[SStrLen(opstring)-2] = 0; + + // COUNT BINARY OPERATIONS + int binops = 0; + { + LPCSTR curr = opstring; + while (*curr) { + if (*curr != '~') + ++binops; + ++curr; + } + } + + // COMPUTE THE NUMBER OF SOURCES THAT WILL BE USED BY THE BINARY OPERATIONS + int sources = binops+1; + { + int loop = 0; + while (loop < sources) + if (sourcestring[loop++] == 'A') + ++sources; + } + + // COMPUTE THE SCODE STRING + char scode[32] = "# D="; + DWORD scodelen = 0; + { + char *curr = scode+SStrLen(scode); + char *currop = opstring; + BOOL savedval = 0; + *curr++ = *(sourcestring+(--sources)); + while (*currop) + if (*currop == '~') { + *curr++ = '^'; + *curr++ = '1'; + ++currop; + } + else if ((*(sourcestring+sources-1) == 'A') && !savedval) { + --sources; + scode[2] = 'A'; + *curr++ = ' '; + *curr++ = 'D'; + *curr++ = '='; + *curr++ = *(sourcestring+(--sources)); + savedval = 1; + } + else { + *curr++ = *currop++; + *curr++ = *(sourcestring+(--sources)); + } + *curr++ = 0; + scodelen = curr-scode; + } + + // COPY THE SCODE STRING INTO THE RESULT BUFFER + SStrCopy(buffer,scode,buffersize); + + return (scodelen <= buffersize); +} + +//=========================================================================== +BOOL APIENTRY SBltROP3 (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + DWORD pattern, + DWORD rop3) { + // to minimize function call overhead for this time critical function, + // we use assert instead of validate so that the retail version has + // no parameter checking code + ASSERT(dest); + ASSERT(destcx >= width); + +//__asm int 0x3; + + // IGNORE ZERO-SIZED BLTS + if ((width <= 0) || (height <= 0)) + return TRUE; + + // INITIALIZE THIS MODULE IF NECESSARY + if (!s_scode) { + s_scode = (BLTINFOPTR)ALLOCZERO(256*sizeof(BLTINFO)); + if (!(InitOptStream("4 D=S",&s_optstream[OPT_SRCCOPY]) && + InitOptStream("4 D=A",&s_optstream[OPT_PATCOPY]))) { + SCodeDestroy(); + return FALSE; + } + } + + // FOR ALIGNED SRCCOPY AND PATCOPY OPERATIONS ON X86 SYSTEMS ONLY, + // PERFORM THE OPERATION DIRECTLY WITHOUT CALLING SCODEEXECUTE() AND + // WITHOUT WORRYING ABOUT BYTE OPERATIONS. THIS IS AN IMPORTANT + // OPTIMIZATION BECAUSE THESE BLT TYPES ARE VERY COMMON AND TEND TO BE + // THE MOST TIME CRITICAL BLTS IN A GAME. + +#ifdef _X86_ + if (((rop3 == SRCCOPY) || (rop3 == PATCOPY)) && !(((DWORD)dest | width) & 3)) { + DWORD adjustdest = destcx-width; + DWORD adjustsource = sourcecx-width; + LPBYTE retptr; + __asm mov retptr,OFFSET opt_loop + OPTSTREAMDATAPTR optdata = &s_optstream[rop3 == PATCOPY]; + LPBYTE jumpptr = *(optdata->jumptable+(width >> 2)); + *optdata->patchlocation = retptr-(LPBYTE)(optdata->patchlocation+1); + __asm { + push edi + push esi + + //int 0x3 + // mov eax,eax + + // FILL IN THE REGISTERS + mov edi,dest + mov esi,source + mov ebx,jumpptr + mov ecx,pattern + mov edx,height + + // EXECUTE THE FIRST SCAN LINE + jmp ebx + + // EXECUTE SUBSEQUENT SCAN LINES + align 16 + opt_loop: dec edx + jz opt_done + add edi,adjustdest + add esi,adjustsource + jmp ebx + + opt_done: pop esi + pop edi + } + + return TRUE; + } +#endif + + // CONVERT SELECTED RASTER OPERATIONS TO MORE EFFICIENT EQUIVALENTS + if ((rop3 != SRCCOPY) && (rop3 != PATCOPY)) + OptimizeROP3(&rop3,&pattern); + + // FIND OR CREATE TWO SCODE STREAMS TO CARRY OUT THIS RASTER OPERATION + DWORD index = (rop3 >> 16) & 0xFF; + if (!(s_scode+index)->used) { + DWORD currtime = GetTickCount(); +// note: write this +// FreeOldCodeStreams(currtime); + char scodestring[64] = ""; + SBltGetSCode(rop3,scodestring,64,0); + SCodeCompile(scodestring, + scodestring, + NULL, + UNROLL, + SCODE_CF_AUTOALIGNDWORD, + &(s_scode+index)->stream); + if ((s_scode+index)->stream) { + (s_scode+index)->used = 1; + (s_scode+index)->time = currtime; + } + else + return FALSE; + } + + // PERFORM THE BLT USING SCODE + SCODEEXECUTEDATA executedata; + executedata.size = sizeof(SCODEEXECUTEDATA); + executedata.flags = 0; + executedata.xiterations = width; + executedata.yiterations = height; + executedata.dest = dest; + executedata.source = source; + executedata.adjustdest = destcx-width; + executedata.adjustsource = sourcecx-width; + executedata.c = pattern; + return SCodeExecute((s_scode+index)->stream,&executedata); +} + +//=========================================================================== +BOOL APIENTRY SBltROP3Clipped (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + DWORD pattern, + DWORD rop3) { + // to minimize function call overhead for this time critical function, + // we use assert instead of validate so that the retail version has + // no parameter checking code + ASSERT(dest); + ASSERT(destpitch > 0); + + int destx = 0; + int desty = 0; + int destwidth = INT_MAX; + int destheight = INT_MAX; + int sourcex = 0; + int sourcey = 0; + int sourcewidth = INT_MAX; + int sourceheight = INT_MAX; + if (destrect) { + destx = max(0,destrect->left); + desty = max(0,destrect->top); + destwidth = destrect->right-destrect->left; + destheight = destrect->bottom-destrect->top; + } + if (destsize) { + destwidth = min(destwidth ,max(0,destsize->cx-destx)); + destheight = min(destheight,max(0,destsize->cy-desty)); + } + if (sourcerect) { + sourcex = max(0,sourcerect->left); + sourcey = max(0,sourcerect->top); + sourcewidth = sourcerect->right-sourcerect->left; + sourceheight = sourcerect->bottom-sourcerect->top; + } + if (sourcesize) { + sourcewidth = min(sourcewidth ,max(0,sourcesize->cx-sourcex)); + sourceheight = min(sourceheight,max(0,sourcesize->cy-sourcey)); + } + destwidth = min(destwidth ,sourcewidth ); + destheight = min(destheight,sourceheight); + if ((destwidth < 1) || (destheight < 1)) + return TRUE; + else + return SBltROP3(dest+desty*destpitch+destx, + source ? source+sourcey*sourcepitch+sourcex : NULL, + destwidth, + destheight, + destpitch, + sourcepitch, + pattern, + rop3); +} + +//=========================================================================== +BOOL APIENTRY SBltROP3Tiled (LPBYTE dest, + LPRECT destrect, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3) { + // to minimize function call overhead for this time critical function, + // we use assert instead of validate so that the retail version has + // no parameter checking code + ASSERT(dest); + ASSERT(destrect); + ASSERT(destpitch > 0); + + int sourcecx = sourcerect->right-sourcerect->left; + int sourcecy = sourcerect->bottom-sourcerect->top; + int y = destrect->top; + while (y < destrect->bottom) { + int tiley = sourcerect->top; + if (y == destrect->top) + tiley += (sourceoffsety+sourcecy) % sourcecy; + int tilecy = min(sourcerect->bottom-tiley, + destrect->bottom-y); + LPBYTE basedest = dest+y*destpitch; + LPBYTE basesource = source+tiley*sourcepitch; + int x = destrect->left; + while (x < destrect->right) { + int tilex = sourcerect->left; + if (x == destrect->left) + tilex += (sourceoffsetx+sourcecx) % sourcecx; + int tilecx = min(sourcerect->right-tilex, + destrect->right-x); + if (!SBltROP3(basedest+x, + basesource+tilex, + tilecx, + tilecy, + destpitch, + sourcepitch, + pattern, + rop3)) + return FALSE; + x += tilecx; + } + y += tilecy; + } + + return TRUE; +} diff --git a/src/Storm/SOURCE/SBMP.CPP b/src/Storm/SOURCE/SBMP.CPP new file mode 100644 index 0000000..b4cee46 --- /dev/null +++ b/src/Storm/SOURCE/SBMP.CPP @@ -0,0 +1,1137 @@ +/**************************************************************************** +* +* SBMP.CPP +* Storm bitmap functions +* +* By Michael O'Brien (2/8/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define BMPSIGNATURE 0x4D42 +#define PCXSIGNATURE 0x050A + + +/**************************************************************************** +* +* BMP ENCODER/DECODER +* +***/ + +static void FlipImage (LPBYTE dest, + LPBYTE source, + DWORD destbytes, + int destwidth, + int sourcewidth, + int height); + +//=========================================================================== +static BOOL DecodeBmpFile (HSFILE file, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + + // READ THE FILE HEADER + BITMAPFILEHEADER fileheader; + if (!SFileReadFile(file,&fileheader,sizeof(BITMAPFILEHEADER))) + return FALSE; + + // READ THE BITMAP INFO HEADER + BITMAPINFOHEADER infoheader; + if (!SFileReadFile(file,&infoheader,sizeof(BITMAPINFOHEADER))) + return FALSE; + if (width) + *width = infoheader.biWidth; + if (height) + *height = infoheader.biHeight; + if (bitdepth) + *bitdepth = infoheader.biBitCount; + + // READ THE PALETTE ENTRIES + if (infoheader.biBitCount > 8) + paletteentries = NULL; + if (paletteentries) { + RGBQUAD palettedata[256]; + if (!SFileReadFile(file,palettedata,256*sizeof(RGBQUAD))) + return FALSE; + + // CONVERT FROM RGBQUAD TO PALETTEENTRY FORMAT + for (int loop = 0; loop < 256; ++loop) { + (paletteentries+loop)->peRed = palettedata[loop].rgbRed; + (paletteentries+loop)->peGreen = palettedata[loop].rgbGreen; + (paletteentries+loop)->peBlue = palettedata[loop].rgbBlue; + (paletteentries+loop)->peFlags = 0; + } + } + + // READ THE BITMAP BITS + if (bitmapbits) { + SFileSetFilePointer(file, + fileheader.bfOffBits + -sizeof(BITMAPFILEHEADER) + -sizeof(BITMAPINFOHEADER) + -(paletteentries ? 256*sizeof(RGBQUAD) : 0), + NULL, + FILE_CURRENT); + DWORD bytesread = 0; + + { + LPBYTE temp = (LPBYTE)ALLOC(infoheader.biSizeImage); + SFileReadFile(file,temp,infoheader.biSizeImage,&bytesread); + int destwidth = (infoheader.biWidth*infoheader.biBitCount) >> 3; + int sourcewidth = destwidth; + if (sourcewidth & 3) + sourcewidth += 4-(sourcewidth & 3); + FlipImage(bitmapbits, + temp, + buffersize, + destwidth, + sourcewidth, + infoheader.biHeight); + FREE(temp); + } + + if (bytesread < infoheader.biSizeImage) + return FALSE; + } + + return TRUE; +} + +//=========================================================================== +static BOOL DecodeBmpMem (LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + + // PROCESS THE HEADERS + LPBITMAPFILEHEADER fileheader = (LPBITMAPFILEHEADER)imagedata; + LPBITMAPINFOHEADER infoheader = (LPBITMAPINFOHEADER)(fileheader+1); + if (width) + *width = infoheader->biWidth; + if (height) + *height = infoheader->biHeight; + if (bitdepth) + *bitdepth = infoheader->biBitCount; + + // PROCESS THE PALETTE ENTRIES + if (infoheader->biBitCount > 8) + paletteentries = NULL; + if (paletteentries) { + RGBQUAD *palettedata = (RGBQUAD *)(infoheader+1); + for (int loop = 0; loop < 256; ++loop) { + (paletteentries+loop)->peRed = (palettedata+loop)->rgbRed; + (paletteentries+loop)->peGreen = (palettedata+loop)->rgbGreen; + (paletteentries+loop)->peBlue = (palettedata+loop)->rgbBlue; + (paletteentries+loop)->peFlags = 0; + } + } + + // PROCESS THE BITMAP BITS + if (bitmapbits) { + DWORD offset = fileheader->bfOffBits + -sizeof(BITMAPFILEHEADER) + -sizeof(BITMAPINFOHEADER) + -(paletteentries ? 256*sizeof(RGBQUAD) : 0); + int destwidth = (infoheader->biWidth*infoheader->biBitCount) >> 3; + int sourcewidth = destwidth; + if (sourcewidth & 3) + sourcewidth += 4-(sourcewidth & 3); + FlipImage(bitmapbits, + imagedata+offset, + buffersize, + destwidth, + sourcewidth, + infoheader->biHeight); + } + + return TRUE; +} + +//=========================================================================== +static BOOL EncodeBmp256File (HANDLE file, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height) { + + // WRITE THE FILE HEADER + { + BITMAPFILEHEADER fileheader; + ZeroMemory(&fileheader,sizeof(BITMAPFILEHEADER)); + fileheader.bfType = BMPSIGNATURE; + fileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + +sizeof(BITMAPINFOHEADER) + +256*sizeof(RGBQUAD); + fileheader.bfSize = fileheader.bfOffBits+width*height; + DWORD byteswritten; + WriteFile(file,&fileheader,sizeof(BITMAPFILEHEADER),&byteswritten,NULL); + } + + // WRITE THE BITMAP INFO HEADER + { + BITMAPINFOHEADER infoheader; + ZeroMemory(&infoheader,sizeof(BITMAPINFOHEADER)); + infoheader.biSize = sizeof(BITMAPINFOHEADER); + infoheader.biWidth = width; + infoheader.biHeight = height; + infoheader.biPlanes = 1; + infoheader.biBitCount = 8; + infoheader.biCompression = BI_RGB; + infoheader.biSizeImage = width*height; + infoheader.biClrUsed = 256; + infoheader.biClrImportant = 256; + DWORD byteswritten; + WriteFile(file,&infoheader,sizeof(BITMAPINFOHEADER),&byteswritten,NULL); + } + + // WRITE THE PALETTE ENTRIES + { + RGBQUAD palettedata[256]; + for (int loop = 0; loop < 256; ++loop) { + palettedata[loop].rgbRed = (paletteentries+loop)->peRed; + palettedata[loop].rgbGreen = (paletteentries+loop)->peGreen; + palettedata[loop].rgbBlue = (paletteentries+loop)->peBlue; + palettedata[loop].rgbReserved = 0; + } + DWORD byteswritten; + WriteFile(file,palettedata,256*sizeof(RGBQUAD),&byteswritten,NULL); + } + + // WRITE THE BITMAP BITS + { + DWORD byteswritten; + int destwidth = width; + if (destwidth & 3) + destwidth += 4-(destwidth & 3); + LPBYTE temp = (LPBYTE)ALLOC(destwidth*height); + FlipImage(temp, + bitmapbits, + destwidth*height, + destwidth, + width, + height); + WriteFile(file,temp,destwidth*height,&byteswritten,NULL); + FREE(temp); + } + + return TRUE; +} + +//=========================================================================== +static void FlipImage (LPBYTE dest, + LPBYTE source, + DWORD destbytes, + int destwidth, + int sourcewidth, + int height) { + VALIDATEBEGIN; + VALIDATE(dest); + VALIDATE(source); + VALIDATE(destbytes); + VALIDATE(destwidth); + VALIDATE(sourcewidth); + VALIDATE(height); + VALIDATEENDVOID; + + source += (height-1)*sourcewidth; + + LPBYTE destterm = dest+destbytes; + while (height--) { + DWORD bytestocopy = min(destwidth,destterm-dest); + if (!bytestocopy) + break; + CopyMemory(dest,source,bytestocopy); + dest += bytestocopy; + source -= sourcewidth; + } + +} + + +/**************************************************************************** +* +* GIF ENCODER/DECODER +* +***/ + +typedef struct _GIFCOMPRESSREC { + int bits; + int max_code; + int init_bits; + int cur_accum; + int cur_bits; + + int waiting_code; + BOOL first_byte; + + int clearcode; + int EOFcode; + int freecode; + + int *hash_code; + int *hash_value; + + int bytesinpkt; + BYTE packetbuf[256]; +} GIFCOMPRESSREC; + +#pragma pack(1) +typedef struct _GIFHEADERREC { + char signature[6]; + WORD width; + WORD height; + BYTE flags; + BYTE bgidx; + BYTE reserved; +} GIFHEADERREC; +#pragma pack() + +typedef struct _GIFIMAGEDESCREC { + WORD x; + WORD y; + WORD width; + WORD height; + BYTE flags; + BYTE codesize; +} GIFIMAGEDESCREC; + +typedef struct _GIFPALREC { + struct { + BYTE red; + BYTE green; + BYTE blue; + } idx[256]; +} GIFPALREC; + +typedef struct _GIFMARKERREC { + char ch; +} GIFMARKERREC; + +#define HASH_ENTRY(prefix,suffix) ((((int) (prefix)) << 8) | (suffix)) +#define MAX_LZW_BITS 12 /* maximum LZW code size (4096 symbols) */ +#define LZW_TABLE_SIZE ((int) 1 << MAX_LZW_BITS) +#define HSIZE 5003 /* hash table size for 80% occupancy */ +#define MAXCODE(bits) (((int) 1 << (bits)) - 1) + +static inline void Output (GIFCOMPRESSREC *compress, + LPVOID *dest, + int code); + +//=========================================================================== +static void ClearBlock (GIFCOMPRESSREC *compress, + LPVOID *dest) { + ZeroMemory(compress->hash_code,HSIZE*sizeof(int)); + compress->freecode = compress->clearcode + 2; + Output(compress, + dest, + compress->clearcode); + compress->bits = compress->init_bits; /* reset code size */ + compress->max_code = MAXCODE(compress->bits); +} + +//=========================================================================== +static void FlushPacket (GIFCOMPRESSREC *compress, + LPVOID *dest) { + if (!compress->bytesinpkt) + return; + compress->packetbuf[0] = (BYTE)(compress->bytesinpkt++); + CopyMemory(*dest,compress->packetbuf,compress->bytesinpkt); + *dest = (LPBYTE)*dest + compress->bytesinpkt; + compress->bytesinpkt = 0; +} + +//=========================================================================== +static inline void Output (GIFCOMPRESSREC *compress, + LPVOID *dest, + int code) { + compress->cur_accum |= code << compress->cur_bits; + compress->cur_bits += compress->bits; + + while (compress->cur_bits >= 8) { + compress->packetbuf[++compress->bytesinpkt] = + (BYTE)(compress->cur_accum & 0xFF); + if (compress->bytesinpkt >= 255) + FlushPacket(compress, + dest); + compress->cur_accum >>= 8; + compress->cur_bits -= 8; + } + + /* + * If the next entry is going to be too big for the code size, + * then increase it, if possible. We do this here to ensure + * that it's done in sync with the decoder's codesize increases. + */ + if (compress->freecode > compress->max_code) { + compress->bits++; + if (compress->bits == MAX_LZW_BITS) + compress->max_code = LZW_TABLE_SIZE; /* freecode will never exceed this */ + else + compress->max_code = MAXCODE(compress->bits); + } +} + +//=========================================================================== +static inline void CompressGifByte (GIFCOMPRESSREC *compress, + LPVOID *dest, + int val) { + register int i; + register int disp; + register int probe_value; + + if (compress->first_byte) { /* need to initialize waiting_code */ + compress->waiting_code = val; + compress->first_byte = FALSE; + return; + } + + /* Probe hash table to see if a symbol exists for + * waiting_code followed by val. + * If so, replace waiting_code by that symbol and return. + */ + i = ((int) val << (MAX_LZW_BITS-8)) + compress->waiting_code; + /* i is less than twice 2**MAX_LZW_BITS, therefore less than twice HSIZE */ + if (i >= HSIZE) + i -= HSIZE; + + probe_value = HASH_ENTRY(compress->waiting_code, val); + + if (compress->hash_code[i] != 0) { /* is first probed slot empty? */ + if (compress->hash_value[i] == probe_value) { + compress->waiting_code = compress->hash_code[i]; + return; + } + if (i == 0) /* secondary hash (after G. Knott) */ + disp = 1; + else + disp = HSIZE - i; + for (;;) { + i -= disp; + if (i < 0) + i += HSIZE; + if (compress->hash_code[i] == 0) + break; /* hit empty slot */ + if (compress->hash_value[i] == probe_value) { + compress->waiting_code = compress->hash_code[i]; + return; + } + } + } + + /* here when hashtable[i] is an empty slot; desired symbol not in table */ + Output(compress, + dest, + compress->waiting_code); + if (compress->freecode < LZW_TABLE_SIZE) { + compress->hash_code[i] = compress->freecode++; /* add symbol to hashtable */ + compress->hash_value[i] = probe_value; + } else + ClearBlock(compress, + dest); + compress->waiting_code = val; +} + +//=========================================================================== +static DWORD CompressGifImage (LPVOID dest, + LPCVOID source, + DWORD sourcebytes) { + LPVOID basedest = dest; + + // INITIALIZE COMPRESSION + GIFCOMPRESSREC compress; + ZeroMemory(&compress,sizeof(GIFCOMPRESSREC)); + compress.bits = 9; + compress.init_bits = 9; + compress.max_code = MAXCODE(compress.bits); + compress.clearcode = 1 << (compress.bits-1); + compress.EOFcode = compress.clearcode+1; + compress.freecode = compress.clearcode+2; + compress.first_byte = TRUE; + compress.hash_code = (int *)ALLOCZERO(HSIZE*sizeof(int)); + compress.hash_value = (int *)ALLOCZERO(HSIZE*sizeof(int)); + Output(&compress, + &dest, + compress.clearcode); + + // COMPRESS THE IMAGE + while (sourcebytes--) { + CompressGifByte(&compress, + &dest, + *(LPBYTE)source); + source = (LPBYTE)source+1; + } + + // CLEANUP + if (!compress.first_byte) + Output(&compress, + &dest, + compress.waiting_code); + Output(&compress, + &dest, + compress.EOFcode); + if (compress.cur_bits > 0) + compress.packetbuf[++compress.bytesinpkt] = + (BYTE)(compress.cur_accum & 0xFF); + FlushPacket(&compress, + &dest); + + FREE(compress.hash_code); + FREE(compress.hash_value); + + return (LPBYTE)dest-(LPBYTE)basedest; +} + +//=========================================================================== +static BOOL EncodeGif256File (HANDLE file, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height) { + + // WRITE THE HEADER + { + GIFHEADERREC rec; + rec.signature[0] = 'G'; + rec.signature[1] = 'I'; + rec.signature[2] = 'F'; + rec.signature[3] = '8'; + rec.signature[4] = '7'; + rec.signature[5] = 'a'; + rec.width = (WORD)width; + rec.height = (WORD)height; + rec.flags = 0x80 // global color table + | 0x70 // 256 color image + | 0x07; // 256 colors in global color table; + rec.bgidx = 0; + rec.reserved = 0; + DWORD byteswritten; + WriteFile(file,&rec,sizeof(GIFHEADERREC),&byteswritten,NULL); + } + + // WRITE THE COLOR TABLE + { + GIFPALREC pal; + for (int loop = 0; loop < 256; ++loop) { + pal.idx[loop].red = (paletteentries+loop)->peRed; + pal.idx[loop].green = (paletteentries+loop)->peGreen; + pal.idx[loop].blue = (paletteentries+loop)->peBlue; + } + DWORD byteswritten; + WriteFile(file,&pal,sizeof(GIFPALREC),&byteswritten,NULL); + } + + // WRITE THE SEPARATOR + { + GIFMARKERREC rec; + rec.ch = ','; + DWORD byteswritten; + WriteFile(file,&rec,sizeof(GIFMARKERREC),&byteswritten,NULL); + } + + // WRITE THE IMAGE DESCRIPTOR + { + GIFIMAGEDESCREC rec; + rec.x = 0; + rec.y = 0; + rec.width = (WORD)width; + rec.height = (WORD)height; + rec.flags = 0; + rec.codesize = 8; + DWORD byteswritten; + WriteFile(file,&rec,sizeof(GIFIMAGEDESCREC),&byteswritten,NULL); + } + + // WRITE THE BITMAP BITS + { + LPBYTE compressed = (LPBYTE)ALLOC(width*height*2); + DWORD bytes = CompressGifImage(compressed, + bitmapbits, + width*height); + DWORD byteswritten; + WriteFile(file,compressed,bytes,&byteswritten,NULL); + FREE(compressed); + } + + // WRITE THE TERMINATOR + { + GIFMARKERREC rec; + rec.ch = 0; + DWORD byteswritten; + WriteFile(file,&rec,sizeof(GIFMARKERREC),&byteswritten,NULL); + rec.ch = ';'; + WriteFile(file,&rec,sizeof(GIFMARKERREC),&byteswritten,NULL); + } + + return TRUE; +} + + +/**************************************************************************** +* +* PCX ENCODER/DECODER +* +***/ + +typedef struct _PCXHEADERREC { + WORD signature; + BYTE encoding; + BYTE bitsperpixel; + WORD x1; + WORD y1; + WORD x2; + WORD y2; + WORD screenwidth; + WORD screenheight; +} PCXHEADERREC; + +typedef struct _PCXINFOREC { + BYTE mode; + BYTE planes; + WORD bytesperline; + BYTE unused[60]; +} PCXINFOREC; + +typedef struct _PCXRGBREC { + BYTE red; + BYTE green; + BYTE blue; +} PCXRGBREC; + +typedef struct _PCXFILEREC { + PCXHEADERREC header; + PCXRGBREC pal16[16]; + PCXINFOREC info; +} PCXFILEREC; + +typedef struct _PCXEXTPALREC { + BYTE number; + PCXRGBREC pal256[256]; +} PCXEXTPALREC; + +static void UncompressPcxImage (LPBYTE dest, + LPBYTE source, + DWORD destbytes, + DWORD sourcebytes); + +//=========================================================================== +static void CompressPcxRow (LPBYTE *dest, LPBYTE *source, int width) { + do { + BYTE ch = *(*source)++; + int count = 1; + --width; + while (width && (ch == **source) && (count < 63)) { + ++count; + --width; + ++*source; + } + if ((count > 1) || (ch >= 0xC0)) { + count |= 0xC0; + *(*dest)++ = (BYTE)(count & 0xFF); + } + *(*dest)++ = ch; + } while (width); +} + +//=========================================================================== +static BOOL DecodePcxFile (HSFILE file, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + + // READ THE HEADER + PCXFILEREC rec; + if (!SFileReadFile(file,&rec,sizeof(PCXFILEREC))) + return 0; + int imagewidth = rec.header.x2+1-rec.header.x1; + int imageheight = rec.header.y2+1-rec.header.y1; + int imagebitdepth = rec.header.bitsperpixel; + if (width) + *width = imagewidth; + if (height) + *height = imageheight; + if (bitdepth) + *bitdepth = imagebitdepth; + + // READ THE BITMAP BITS + if (bitmapbits) { + DWORD bytestoread = SFileGetFileSize(file)-SFileSetFilePointer(file,0,NULL,FILE_CURRENT); + LPBYTE compressed = (LPBYTE)ALLOC(bytestoread); + SFileReadFile(file,compressed,bytestoread); + UncompressPcxImage(bitmapbits, + compressed, + buffersize, + bytestoread); + FREE(compressed); + } + else + SFileSetFilePointer(file,0,NULL,FILE_END); + + // READ THE PALETTE ENTRIES + if (paletteentries && (imagebitdepth == 8)) { + PCXRGBREC paldata[256]; + SFileSetFilePointer(file,-256*(int)sizeof(PCXRGBREC),NULL,FILE_CURRENT); + SFileReadFile(file,paldata,256*sizeof(PCXRGBREC)); + + // CONVERT FROM PCXRGBREC TO PALETTEENTRY FORMAT + for (int loop = 0; loop < 256; ++loop) { + (paletteentries+loop)->peRed = paldata[loop].red; + (paletteentries+loop)->peGreen = paldata[loop].green; + (paletteentries+loop)->peBlue = paldata[loop].blue; + (paletteentries+loop)->peFlags = 0; + } + } + + return TRUE; +} + +//=========================================================================== +static BOOL DecodePcxMem (LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + + // PROCESS THE HEADER + PCXFILEREC *rec = (PCXFILEREC *)imagedata; + int imagewidth = rec->header.x2+1-rec->header.x1; + int imageheight = rec->header.y2+1-rec->header.y1; + int imagebitdepth = rec->header.bitsperpixel; + if (width) + *width = imagewidth; + if (height) + *height = imageheight; + if (bitdepth) + *bitdepth = imagebitdepth; + + // PROCESS THE BITMAP BITS + if (bitmapbits) + UncompressPcxImage(bitmapbits, + (LPBYTE)(rec+1), + min(buffersize,(DWORD)(imagewidth*imageheight)), + imagebytes-sizeof(PCXFILEREC)); + + // PROCESS THE PALETTE ENTRIES + if (paletteentries && (imagebitdepth == 8)) { + PCXRGBREC *paldata = (PCXRGBREC *)(imagedata+imagebytes-256*sizeof(PCXRGBREC)); + for (int loop = 0; loop < 256; ++loop) { + (paletteentries+loop)->peRed = (paldata+loop)->red; + (paletteentries+loop)->peGreen = (paldata+loop)->green; + (paletteentries+loop)->peBlue = (paldata+loop)->blue; + (paletteentries+loop)->peFlags = 0; + } + } + + return TRUE; +} + +//=========================================================================== +static BOOL EncodePcx256File (HANDLE file, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height) { + + // WRITE THE HEADER + { + PCXFILEREC rec; + ZeroMemory(&rec,sizeof(PCXFILEREC)); + rec.header.signature = PCXSIGNATURE; + rec.header.encoding = 1; + rec.header.bitsperpixel = 8; + rec.header.x2 = width-1; + rec.header.y2 = height-1; + rec.header.screenwidth = width; + rec.header.screenheight = height; + rec.info.planes = 1; + rec.info.bytesperline = width; + DWORD byteswritten; + WriteFile(file,&rec,sizeof(PCXFILEREC),&byteswritten,NULL); + } + + // WRITE THE BITMAP BITS + { + LPBYTE compressed = (LPBYTE)ALLOC(width*height*2); + LPBYTE source = bitmapbits; + LPBYTE dest = compressed; + for (int loop = 0; loop < height; ++loop) + CompressPcxRow(&dest,&source,width); + DWORD byteswritten; + WriteFile(file,compressed,dest-compressed,&byteswritten,NULL); + FREE(compressed); + } + + // WRITE THE PALETTE ENTRIES + { + PCXEXTPALREC pal; + pal.number = 12; + for (int loop = 0; loop < 256; ++loop) { + pal.pal256[loop].red = (paletteentries+loop)->peRed; + pal.pal256[loop].green = (paletteentries+loop)->peGreen; + pal.pal256[loop].blue = (paletteentries+loop)->peBlue; + } + DWORD byteswritten; + WriteFile(file,&pal,sizeof(PCXEXTPALREC),&byteswritten,NULL); + } + + return TRUE; +} + +//=========================================================================== +static void UncompressPcxImage (LPBYTE dest, + LPBYTE source, + DWORD destbytes, + DWORD sourcebytes) { + LPBYTE destterm = dest+destbytes; + LPBYTE sourceterm = source+sourcebytes; + while ((dest < destterm) && (source < sourceterm)) { + BYTE val = *source++; + if (val >= 0xC0) { + DWORD count = val & 0x3F; + count = min(count,(DWORD)(destterm-dest)); + val = *source++; + FillMemory(dest,count,val); + dest += count; + } + else + *dest++ = val; + } +} + + +/**************************************************************************** +* +* SUPPORT FUNCTIONS +* +***/ + +//=========================================================================== +static LPCTSTR FindExtension (LPCTSTR filename) { + LPCTSTR result = filename; + while (SStrChr(result,'\\')) + result = SStrChr(result,'\\')+1; + while (SStrChr(result+1,'.')) + result = SStrChr(result+1,'.'); + return result; +} + +//=========================================================================== +static DWORD DetermineImageType (WORD signature) { + switch (signature) { + + case BMPSIGNATURE: + return SBMP_IMAGETYPE_BMP; + + case PCXSIGNATURE: + return SBMP_IMAGETYPE_PCX; + + default: + return 0; + + } +} + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SBmpAllocLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE *returnedbuffer, + int *width, + int *height, + int *bitdepth, + int requestedbitdepth, + SBMPALLOCPROC allocproc) { + if (returnedbuffer) + *returnedbuffer = NULL; + if (width) + *width = 0; + if (height) + *height = 0; + if (bitdepth) + *bitdepth = 0; + + VALIDATEBEGIN; + VALIDATE(filename); + VALIDATE(*filename); + VALIDATE(returnedbuffer); + VALIDATEEND; + + // OPEN THE FILE + HSFILE file; + if (!SFileOpenFile(filename,&file)) + return FALSE; + + // LOAD THE FILE INTO MEMORY + DWORD filesize = SFileGetFileSize(file); + LPBYTE filedata = (LPBYTE)ALLOC(filesize); + SFileReadFile(file, + filedata, + filesize); + SFileCloseFile(file); + + BOOL success = FALSE; + TRY { + + // DETERMINE THE SOURCE IMAGE DIMENSIONS + int localwidth, localheight, localbitdepth; + if (!SBmpDecodeImage(SBMP_IMAGETYPE_AUTO, + filedata, + filesize, + NULL, + NULL, + 0, + &localwidth, + &localheight, + &localbitdepth)) + LEAVE; + + // IF THE REQUESTED BIT DEPTH DOES NOT MATCH THE ACTUAL BIT DEPTH, + // RETURN AN ERROR, SINCE WE DO NOT CURRENTLY IMPLEMENT IMAGE FORMAT + // CONVERSION + if (!requestedbitdepth) + requestedbitdepth = localbitdepth; + if (requestedbitdepth != localbitdepth) + LEAVE; + + // ALLOCATE A BUFFER TO HOLD THE IMAGE + DWORD imagesize = localwidth*localheight*requestedbitdepth/8; + if (allocproc) + *returnedbuffer = (LPBYTE)allocproc(imagesize); + else + *returnedbuffer = (LPBYTE)SMemAlloc(imagesize, + filename, + SERR_LINECODE_FILE, + 0); + if (!*returnedbuffer) + LEAVE; + + // DECODE THE IMAGE INTO THE BUFFER + SBmpDecodeImage(SBMP_IMAGETYPE_AUTO, + filedata, + filesize, + paletteentries, + *returnedbuffer, + imagesize); + + // RETURN THE WIDTH, HEIGHT, AND BITDEPTH + if (width) + *width = localwidth; + if (height) + *height = localheight; + if (bitdepth) + *bitdepth = requestedbitdepth; + + success = TRUE; + } + FINALLY { + FREE(filedata); + } + + return success; +} + +//=========================================================================== +BOOL APIENTRY SBmpDecodeImage (DWORD imagetype, + LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + if (width) + *width = 0; + if (height) + *height = 0; + if (bitdepth) + *bitdepth = 0; + + VALIDATEBEGIN; + VALIDATE(imagedata); + VALIDATE(imagebytes); + VALIDATE(buffersize || !bitmapbits); + VALIDATEEND; + + // IF NO IMAGE TYPE WAS GIVEN, TRY TO DETERMINE IT FROM THE SIGNATURE + if ((imagetype == SBMP_IMAGETYPE_AUTO) && + (imagebytes >= sizeof(WORD))) + imagetype = DetermineImageType(*(LPWORD)imagedata); + + // DECODE THE IMAGE + switch (imagetype) { + + case SBMP_IMAGETYPE_BMP: + return DecodeBmpMem(imagedata, + imagebytes, + paletteentries, + bitmapbits, + buffersize, + width, + height, + bitdepth); + + case SBMP_IMAGETYPE_PCX: + return DecodePcxMem(imagedata, + imagebytes, + paletteentries, + bitmapbits, + buffersize, + width, + height, + bitdepth); + + default: + return FALSE; + + } +} + +//=========================================================================== +BOOL APIENTRY SBmpLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + if (width) + *width = 0; + if (height) + *height = 0; + if (bitdepth) + *bitdepth = 0; + + VALIDATEBEGIN; + VALIDATE(filename); + VALIDATE(*filename); + VALIDATE(buffersize || !bitmapbits); + VALIDATEEND; + + // OPEN THE FILE + HSFILE file; + if (!SFileOpenFile(filename,&file)) + return FALSE; + + // DETERMINE THE IMAGE TYPE + DWORD imagetype = 0; + { + WORD signature; + if (SFileReadFile(file,&signature,sizeof(WORD))) { + SFileSetFilePointer(file,-2,NULL,FILE_CURRENT); + imagetype = DetermineImageType(signature); + } + } + + // READ AND DECODE THE IMAGE + BOOL result = FALSE; + switch (imagetype) { + + case SBMP_IMAGETYPE_BMP: + result = DecodeBmpFile(file, + paletteentries, + bitmapbits, + buffersize, + width, + height, + bitdepth); + break; + + case SBMP_IMAGETYPE_PCX: + result = DecodePcxFile(file, + paletteentries, + bitmapbits, + buffersize, + width, + height, + bitdepth); + break; + + } + + // CLOSE THE FILE + SFileCloseFile(file); + + return result; +} + +//=========================================================================== +BOOL APIENTRY SBmpSaveImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height, + int bitdepth) { + VALIDATEBEGIN; + VALIDATE(filename); + VALIDATE(*filename); + VALIDATE(paletteentries); + VALIDATE(bitmapbits); + VALIDATE(width > 0); + VALIDATE(height > 0); + VALIDATEEND; + + // STORM CURRENTLY ONLY SUPPORTS 256-COLOR MODE, SO FOR THE TIME BEING, + // REJECT ALL BIT DEPTHS EXCEPT 8BPP + if (bitdepth != 8) + return FALSE; + + // OPEN THE FILE + HANDLE file = CreateFile(filename, + GENERIC_WRITE, + 0, + (LPSECURITY_ATTRIBUTES)NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (file == INVALID_HANDLE_VALUE) + return FALSE; + + // WRITE THE IMAGE + LPCTSTR ext = FindExtension(filename); + BOOL result = 0; + if (ext && !_stricmp(ext,".pcx")) + result = EncodePcx256File(file, + paletteentries, + bitmapbits, + width, + height); + else if (ext && !_stricmp(ext,".gif")) + result = EncodeGif256File(file, + paletteentries, + bitmapbits, + width, + height); + else + result = EncodeBmp256File(file, + paletteentries, + bitmapbits, + width, + height); + + // CLOSE THE FILE + CloseHandle(file); + + return result; +} diff --git a/src/Storm/SOURCE/SCMD.CPP b/src/Storm/SOURCE/SCMD.CPP new file mode 100644 index 0000000..b847cd1 --- /dev/null +++ b/src/Storm/SOURCE/SCMD.CPP @@ -0,0 +1,686 @@ +/**************************************************************************** +* +* SCMD.CPP +* Storm command line parsing functions +* +* By Michael O'Brien (4/14/97) +* Based on cmdline.cpp by Patrick Wyatt (1/21/93) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define ARGVAL(f) ((f) & SCMD_ARG_MASK) +#define BOOLVAL(f) ((f) & SCMD_BOOL_MASK) +#define NUMVAL(f) ((f) & SCMD_NUM_MASK) +#define TYPEVAL(f) ((f) & SCMD_TYPE_MASK) + +#define MAXNAMELENGTH 16 +#define FLAGCHARS "-/" +#define WHITESPACE " ,;\"\t\n\r\x1A" + +#define STR_BADARGUMENT 0 +#define STR_NOTENOUGHARGUMENTS 1 +#define STR_OPENFAILED 2 +#define STRINGS 3 + +static const LPCTSTR s_errorstr[STRINGS] = + {"Invalid argument: %s", + "The syntax of the command is incorrect.", + "Unable to open response file: %s"}; + +NODEDECL(CMDDEF) { + DWORD flags; + DWORD id; + char name[MAXNAMELENGTH]; + int namelength; + DWORD setvalue; + DWORD setmask; + LPVOID variableptr; + DWORD variablebytes; + SCMDCALLBACK callback; + BOOL found; + union { + DWORD currvalue; + LPTSTR currvaluestr; + }; +} *CMDDEFPTR; + +typedef struct _PROCESSING { + CMDDEFPTR ptr; + char name[MAXNAMELENGTH]; + int namelength; +} PROCESSING, *PROCESSINGPTR; + +static BOOL s_addedoptional = FALSE; +static LIST(CMDDEF) s_arglist; +static LIST(CMDDEF) s_flaglist; + +static BOOL ProcessString (LPCTSTR *stringptr, + PROCESSINGPTR processing, + CMDDEFPTR *nextarg, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback); +static BOOL ProcessToken (LPCTSTR string, + BOOL quoted, + PROCESSINGPTR processing, + CMDDEFPTR *nextarg, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback); + +//=========================================================================== +static void ConvertBool (CMDDEFPTR ptr, + LPCTSTR string, + int *datachars) { + + // DETERMINE WHETHER THE FLAG WILL BE SET OR CLEARED + BOOL set; + if (*string == '-') { + set = FALSE; + *datachars = 1; + } + else if (*string == '+') { + set = TRUE; + *datachars = 1; + } + else if (BOOLVAL(ptr->flags) == SCMD_BOOL_CLEAR) + set = FALSE; + else + set = TRUE; + + // MODIFY IT LOCALLY + ptr->currvalue &= ~ptr->setmask; + if (set) + ptr->currvalue |= ptr->setvalue; + + // MODIFY IT IN THE APPLICATION'S MEMORY + if (ptr->variableptr) { + *(LPDWORD)ptr->variableptr &= ~ptr->setmask; + if (set) + *(LPDWORD)ptr->variableptr |= ptr->setvalue; + } + +} + +//=========================================================================== +static void ConvertNumber (CMDDEFPTR ptr, + LPCTSTR string, + int *datachars) { + + // DETERMINE THE NUMERIC VALUE + LPTSTR endptr = NULL; + if (NUMVAL(ptr->flags) == SCMD_NUM_SIGNED) + ptr->currvalue = (DWORD)strtol(string,&endptr,0); + else + ptr->currvalue = strtoul(string,&endptr,0); + if (endptr) + *datachars = endptr-string; + else + *datachars = SStrLen(string); + + // WRITE IT INTO THE APPLICATION'S MEMORY + if (ptr->variableptr) + CopyMemory(ptr->variableptr, + &ptr->currvalue, + min(sizeof(ptr->currvalue),ptr->variablebytes)); + +} + +//=========================================================================== +static void ConvertString (CMDDEFPTR ptr, + LPCTSTR string, + int *datachars) { + *datachars = SStrLen(string); + + // SAVE THE STRING + if (ptr->currvaluestr) + FREE(ptr->currvaluestr); + ptr->currvaluestr = (LPTSTR)ALLOC(SStrLen(string)+1); + SStrCopy(ptr->currvaluestr,string); + + // COPY THE STRING INTO THE APPLICATION'S MEMORY + if (ptr->variableptr) + SStrCopy((LPTSTR)ptr->variableptr, + string, + ptr->variablebytes); + +} + +//=========================================================================== +static CMDDEFPTR FindFlagDef (LPCTSTR string, + CMDDEFPTR firstdef, + int minlength) { + int strlength = SStrLen(string); + int bestlength = minlength-1; + CMDDEFPTR bestptr = NULL; + for (CMDDEFPTR curr = firstdef; + curr; + curr = curr->Next()) + if ((curr->namelength > bestlength) && + (curr->namelength <= strlength)) { + BOOL match = FALSE; + if (curr->flags & SCMD_CASESENSITIVE) + match = !strncmp(curr->name,string,curr->namelength); + else + match = !_strnicmp(curr->name,string,curr->namelength); + if (match) { + bestlength = curr->namelength; + bestptr = curr; + } + } + return bestptr; +} + +//=========================================================================== +static void GenerateError (SCMDERRORCALLBACK errorcallback, + DWORD errorcode, + LPCTSTR itemstring) { + + // GENERATE THE COMPLETE ERROR MESSAGE + char errorstr[256] = ""; + { + DWORD strid; + UINT resid; + switch (errorcode) { + + case SCMD_ERROR_BAD_ARGUMENT: + strid = STR_BADARGUMENT; + resid = IDS_BADARGUMENT; + break; + + case SCMD_ERROR_NOT_ENOUGH_ARGUMENTS: + strid = STR_NOTENOUGHARGUMENTS; + resid = IDS_NOTENOUGHARGUMENTS; + break; + + case SCMD_ERROR_OPEN_FAILED: + strid = STR_OPENFAILED; + resid = IDS_OPENFAILED; + break; + + default: + return; + + } + char buffer[256] = ""; + LoadString(StormGetInstance(),resid,buffer,256); + if (!buffer[0]) + SStrCopy(buffer,s_errorstr[strid],256); + if (strstr(buffer,"%s")) + wsprintf(errorstr,buffer,itemstring); + else + SStrCopy(errorstr,buffer,256); + if (errorstr[0]) + SStrPack(errorstr,"\n",256); + } + + // SET THE LAST ERROR CODE + SErrSetLastError(errorcode); + + // CALL THE APPLICATION'S CALLBACK FUNCTION + CMDERROR data; + data.errorcode = errorcode; + data.itemstr = itemstring; + data.errorstr = errorstr; + errorcallback(&data); + +} + +//=========================================================================== +static BOOL PerformConversion (CMDDEFPTR ptr, + LPCTSTR string, + int *datachars) { + + // PERFORM THE CONVERSION + *datachars = 0; + switch (TYPEVAL(ptr->flags)) { + + case SCMD_TYPE_BOOL: + ConvertBool(ptr,string,datachars); + break; + + case SCMD_TYPE_NUMERIC: + ConvertNumber(ptr,string,datachars); + break; + + case SCMD_TYPE_STRING: + ConvertString(ptr,string,datachars); + break; + + default: + return FALSE; + + } + + // MARK THE PARAMETER AS FOUND + ptr->found = TRUE; + + // CALL THE APPLICATION'S CALLBACK FUNCTION + if (ptr->callback) { + CMDPARAMS params; + params.flags = ptr->flags; + params.id = ptr->id; + params.name = ptr->name; + params.variable = ptr->variableptr; + params.setvalue = ptr->setvalue; + params.setmask = ptr->setmask; + params.unsignedvalue = ptr->currvalue; + if (!ptr->callback(¶ms,string)) + return FALSE; + } + + // PROPAGATE THE CURRENT VALUE TO ANY OTHER ARGUMENTS WITH THE SAME ID, + // SO THAT IF THE USER QUERIES THE VALUE BY ID THEN THE QUERY FUNCTION + // CAN SIMPLY RETURN THE FIRST HIT + for (BOOL flaglist = FALSE; flaglist <= TRUE; ++flaglist) + ITERATELIST(CMDDEF, + flaglist ? s_flaglist : s_arglist, + currptr) + if ((currptr->id == ptr->id) && + (TYPEVAL(currptr->flags) == TYPEVAL(ptr->flags)) && + (currptr != ptr)) { + currptr->found = TRUE; + if (TYPEVAL(currptr->flags) == SCMD_TYPE_STRING) { + if (currptr->currvaluestr) + FREE(currptr->currvaluestr); + currptr->currvaluestr = (LPTSTR)ALLOC(SStrLen(ptr->currvaluestr)+1); + SStrCopy(currptr->currvaluestr,ptr->currvaluestr); + } + else + currptr->currvalue = ptr->currvalue; + } + + return TRUE; +} + +//=========================================================================== +static BOOL ProcessCurrentFlag (LPCTSTR string, + PROCESSINGPTR processing, + int *datachars) { + *datachars = 0; + CMDDEFPTR ptr = processing->ptr; + processing->ptr = NULL; + while (ptr) { + int currdatachars; + if (!PerformConversion(ptr,string,&currdatachars)) + return FALSE; + *datachars = max(*datachars,currdatachars); + ptr = FindFlagDef(processing->name,ptr->Next(),processing->namelength); + } + return TRUE; +} + +//=========================================================================== +static BOOL ProcessFile (LPCTSTR filename, + PROCESSINGPTR processing, + CMDDEFPTR *nextarg, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback) { + + // OPEN THE FILE + HANDLE file = CreateFile(filename, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if (!file) { + if (errorcallback) + GenerateError(errorcallback,SCMD_ERROR_OPEN_FAILED,filename); + return FALSE; + } + + // READ IT INTO MEMORY + DWORD size = GetFileSize(file,NULL); + LPVOID buffer = ALLOC(size+1); + DWORD bytesread; + ReadFile(file,buffer,size,&bytesread,NULL); + CloseHandle(file); + + // NULL TERMINATE THE ENTIRE FILE + *((LPBYTE)buffer+bytesread) = 0; + + // PROCESS IT AS ONE LARGE STRING + LPCTSTR curr = (LPCTSTR)buffer; + BOOL success = ProcessString(&curr, + processing, + nextarg, + extracallback, + errorcallback); + + // FREE THE BUFFER + FREE(buffer); + + return success; +} + +//=========================================================================== +static BOOL ProcessFlags (LPCTSTR string, + PROCESSINGPTR processing, + SCMDERRORCALLBACK errorcallback) { + char lastflag[256] = ""; + while (*string) { + + // FIND THE BEST MATCHED FLAG DEFINITION, COMBINING THIS FLAG WITH THE + // HEADER CHARACTERS FROM THE LAST FLAG IN THIS TOKEN IF POSSIBLE + int strlength = SStrLen(string); + int lastflaglength = max(1,SStrLen(lastflag)); + CMDDEFPTR ptr = NULL; + while (lastflaglength--) + if (strlength+lastflaglength < 256) { + SStrCopy(lastflag+lastflaglength,string,256); + if ((ptr = FindFlagDef(lastflag,s_flaglist.Head(),0)) != NULL) { + lastflaglength = ptr->namelength; + lastflag[lastflaglength] = 0; + break; + } + } + if (!ptr) { + if (errorcallback) + GenerateError(errorcallback,SCMD_ERROR_BAD_ARGUMENT,string); + return FALSE; + } + + // MOVE THE STRING POINTER PAST THE FLAG NAME + string += lastflaglength; + + // SETUP THE PROCESSING STRUCTURE + processing->ptr = ptr; + processing->namelength = lastflaglength; + SStrCopy(processing->name,lastflag); + + // IF THERE IS NO DATA PAST THE FLAG NAME AND THIS IS A NON-BOOLEAN + // FLAG, DELAY PROCESSING UNTIL WE GET THE DATA FROM THE NEXT TOKEN + if ((!*string) && + (TYPEVAL(ptr->flags) != SCMD_TYPE_BOOL)) + return TRUE; + + // PROCESS ALL INSTANCES OF THE BEST MATCHED FLAG + int datachars; + if (!ProcessCurrentFlag(string,processing,&datachars)) + return FALSE; + + // MOVE THE STRING POINTER PAST THE FLAG DATA + string += datachars; + + } + return TRUE; +} + +//=========================================================================== +static BOOL ProcessString (LPCTSTR *stringptr, + PROCESSINGPTR processing, + CMDDEFPTR *nextarg, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback) { + + // PROCESS EACH TOKEN IN THE STRING + while (**stringptr) { + LPCTSTR nextptr = *stringptr; + char buffer[256] = ""; + BOOL quoted = FALSE; + SStrTokenize(&nextptr, + buffer, + 256, + WHITESPACE, + "ed); + if (!ProcessToken(buffer, + quoted, + processing, + nextarg, + extracallback, + errorcallback)) + break; + *stringptr = nextptr; + } + + // RETURN SUCCESS IF WE PROCESSED THE ENTIRE STRING + return !**stringptr; + +} + +//=========================================================================== +static BOOL ProcessToken (LPCTSTR string, + BOOL quoted, + PROCESSINGPTR processing, + CMDDEFPTR *nextarg, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback) { + + // IF THIS IS A RESPONSE FILE, PROCESS IT RECURSIVELY + if ((*string == '@') && !quoted) + return ProcessFile(string+1, + processing, + nextarg, + extracallback, + errorcallback); + + // IF THIS TOKEN CONTAINS FLAGS, PROCESS THEM + if (SStrChr(FLAGCHARS,*string) && !quoted) { + processing->ptr = NULL; + return ProcessFlags(string+1,processing,errorcallback); + } + + // IF WE ARE STILL PROCESSING A PREVIOUS ARGUMENT, USE THIS TOKEN + // AS DATA FOR THAT ARGUMENT + if (processing->ptr) { + int datachars; + return ProcessCurrentFlag(string,processing,&datachars); + } + + // IF THERE ARE ADDITIONAL REQUIRED/OPTIONAL ARGUMENTS TO FILL, + // USE THIS TOKEN AS ONE + if (*nextarg) { + int datachars; + if (!PerformConversion(*nextarg,string,&datachars)) + return FALSE; + *nextarg = (*nextarg)->Next(); + return TRUE; + } + + // IF THERE IS AN EXTRA CALLBACK DEFINED, PASS THIS TOKEN TO THE + // EXTRA CALLBACK + if (extracallback) + return extracallback(string); + + // OTHERWISE, DISPLAY AN ERROR AND RETURN FALSE TO STOP THE COMMAND + // LINE PARSING BECAUSE WE ARE UNABLE TO IDENTIFY OR PROCESS THE TOKEN + if (errorcallback) + GenerateError(errorcallback,SCMD_ERROR_BAD_ARGUMENT,string); + return FALSE; + +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SCmdCheckId (DWORD id) { + for (BOOL flaglist = FALSE; flaglist <= TRUE; ++flaglist) + ITERATELIST(CMDDEF, + flaglist ? s_flaglist : s_arglist, + currptr) + if (currptr->id == id) + return currptr->found; + return FALSE; +} + +//=========================================================================== +BOOL APIENTRY SCmdDestroy () { + for (BOOL flaglist = FALSE; flaglist <= TRUE; ++flaglist) + ITERATELIST(CMDDEF, + flaglist ? s_flaglist : s_arglist, + currptr) + if ((TYPEVAL(currptr->flags) == SCMD_TYPE_STRING) && + currptr->currvaluestr) { + FREE(currptr->currvaluestr); + currptr->currvaluestr = NULL; + } + s_arglist.Clear(); + s_flaglist.Clear(); + s_addedoptional = FALSE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SCmdGetBool (DWORD id) { + return (SCmdGetNum(id) != 0); +} + +//=========================================================================== +DWORD APIENTRY SCmdGetNum (DWORD id) { + for (BOOL flaglist = FALSE; flaglist <= TRUE; ++flaglist) + ITERATELIST(CMDDEF, + flaglist ? s_flaglist : s_arglist, + currptr) + if (currptr->id == id) + return currptr->currvalue; + return 0; +} + +//=========================================================================== +BOOL APIENTRY SCmdGetString (DWORD id, + LPTSTR buffer, + DWORD bufferchars) { + if (buffer) + *buffer = 0; + + VALIDATEBEGIN; + VALIDATE(buffer); + VALIDATE(bufferchars); + VALIDATEEND; + + for (BOOL flaglist = FALSE; flaglist <= TRUE; ++flaglist) + ITERATELIST(CMDDEF, + flaglist ? s_flaglist : s_arglist, + currptr) + if (currptr->id == id) { + if (currptr->currvaluestr) + SStrCopy(buffer,currptr->currvaluestr,bufferchars); + return TRUE; + } + return FALSE; +} + +//=========================================================================== +BOOL APIENTRY SCmdProcess (LPCTSTR cmdline, + BOOL skipprogname, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback) { + VALIDATEBEGIN; + VALIDATE(cmdline); + VALIDATEEND; + + // IF REQUESTED, SKIP PAST THE PROGRAM NAME AT THE START OF THE COMMAND + // LINE + if (skipprogname) + SStrTokenize(&cmdline, + NULL, + 0, + WHITESPACE, + NULL); + + // PROCESS EACH ARGUMENT + PROCESSING processing; + ZeroMemory(&processing,sizeof(PROCESSING)); + CMDDEFPTR nextarg = s_arglist.Head(); + if (!ProcessString(&cmdline, + &processing, + &nextarg, + extracallback, + errorcallback)) + return FALSE; + + // DETERMINE WHETHER ALL REQUIRED ARGUMENTS WERE FILLED IN + BOOL allfilled = TRUE; + while (nextarg && allfilled) + if (ARGVAL(nextarg->flags) == SCMD_ARG_REQUIRED) + allfilled = FALSE; + else + nextarg = nextarg->Next(); + if (errorcallback && !allfilled) + GenerateError(errorcallback,SCMD_ERROR_NOT_ENOUGH_ARGUMENTS,""); + + return allfilled; +} + +//=========================================================================== +BOOL APIENTRY SCmdRegisterArgList (const ARGLIST *listptr, + DWORD numargs) { + VALIDATEBEGIN; + VALIDATE(listptr); + VALIDATEEND; + + for (DWORD loop = 0; loop < numargs; ++loop) { + if (!SCmdRegisterArgument(listptr->flags, + listptr->id, + listptr->name, + NULL, + 0, + TRUE, + 0xFFFFFFFF, + listptr->callback)) + return FALSE; + ++listptr; + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SCmdRegisterArgument (DWORD flags, + DWORD id, + LPCTSTR name, + LPVOID variableptr, + DWORD variablebytes, + DWORD setvalue, + DWORD setmask, + SCMDCALLBACK callback) { + if (!name) + name = ""; + int namelength = SStrLen(name); + + VALIDATEBEGIN; + VALIDATE(namelength < MAXNAMELENGTH); + VALIDATE((!variablebytes) || variableptr); + VALIDATE((ARGVAL(flags) != SCMD_ARG_REQUIRED) || (!s_addedoptional)); + VALIDATE((ARGVAL(flags) != SCMD_ARG_FLAGGED) || (namelength > 0)); + VALIDATE((TYPEVAL(flags) != SCMD_TYPE_BOOL) || (!variableptr) || (variablebytes == sizeof(DWORD))); + VALIDATEEND; + + // ADD THE ARGUMENT TO THE END OF THE APPROPRIATE LINKED LIST + CMDDEFPTR newptr; + if (ARGVAL(flags) == SCMD_ARG_FLAGGED) + newptr = s_flaglist.NewNode(); + else + newptr = s_arglist.NewNode(); + SStrCopy(newptr->name,name,MAXNAMELENGTH); + newptr->id = id; + newptr->namelength = namelength; + newptr->flags = flags; + newptr->variableptr = variableptr; + newptr->variablebytes = variablebytes; + newptr->setvalue = setvalue; + newptr->setmask = setmask; + newptr->callback = callback; + + // SET THE INITIAL VALUE + if ((TYPEVAL(flags) == SCMD_TYPE_BOOL) && + (BOOLVAL(flags) == SCMD_BOOL_CLEAR)) + newptr->currvalue = setvalue; + else + newptr->currvalue = 0; + + // IF THIS IS AN OPTIONAL ARGUMENT, KEEP TRACK OF THE FACT THAT WE'VE + // ADDED AT LEAST ONE OPTIONAL ARGUMENT SO THAT WE WILL REFUSE TO ADD + // ANY MORE REQUIRED ARGUMENTS IN THE FUTURE + if (ARGVAL(flags) == SCMD_ARG_OPTIONAL) + s_addedoptional = TRUE; + + return TRUE; +} diff --git a/src/Storm/SOURCE/SCODE.CPP b/src/Storm/SOURCE/SCODE.CPP new file mode 100644 index 0000000..ab8d3b5 --- /dev/null +++ b/src/Storm/SOURCE/SCODE.CPP @@ -0,0 +1,1312 @@ +/**************************************************************************** +* +* SCODE.CPP +* Storm S-Code compiler +* +* By Michael O'Brien (4/8/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define BUFFERSIZE 1024 + +#define EQUALITY "=" +#define OPERATIONS "&|^+-" +#define LOGICALOPS "&|^+-" +#define PORTIONS "1234" +#define REGISTERS "WSDTABC01" +#define INDEXREGS "WABC" +#define SIZES "124" + +#define REG_UNDEF 0 +#define REG_WORK 1 +#define REG_DEST 2 +#define REG_SOURCE 3 +#define REG_TABLE 4 +#define REG_A 5 +#define REG_B 6 +#define REG_C 7 +#define REG_CONST0 8 +#define REG_CONST1 9 +#define NUMREGS 10 + +#define OP_MOVE 0 +#define OP_AND 1 +#define OP_OR 2 +#define OP_XOR 3 +#define OP_ADD 4 +#define OP_SUB 5 +#define OP_NOT 6 +#define OP_SWAP 7 +#define NUMOPS 8 + +#define USE_UNUSED 0 +#define USE_INTER 1 +#define USE_CONST 2 +#define USE_POINTER 3 +#define USE_CACHE 4 + +#define CACHE_DEST 0 +#define CACHE_SOURCE 1 +#define CACHE_TABLE 2 +#define CACHE_CONST0 3 +#define CACHE_CONST1 4 +#define NUMCACHE 5 + +#define CHARTOID(c) (SStrChr(regidtable,(c))-regidtable) +#define COMPAREREGS(a,b) (*(LPDWORD)&(a) == *(LPDWORD)&(b)) +#define COPYREG(d,s) (*(LPDWORD)&(d) = *(LPDWORD)&(s)) +#define FATALERROR(c) do { \ + if (firsterror) \ + *firsterror = (c); \ + ClearQueue(); \ + return 0; \ + } while (0) +#define IDTOCHAR(i) regidtable[i] +#define OPTOID(c) (SStrChr(opidtable,(c))-opidtable) +#define ZEROREG(r) *(LPDWORD)&(r) = 0 + +typedef struct _BUF { + LPBYTE data; + DWORD bytes; +} BUF, *BUFPTR; + +typedef struct _REG { + BYTE id; + BYTE portion; + BYTE indexid; + BYTE indirect; +} REG, *REGPTR; + +NODEDECL(INST) { + REG dest; + REG source; + int op; + int opsize; +} *INSTPTR; + +NODEDECL(STREAM) { + BOOL flags; + DWORD checkvalue; + LPBYTE executeptr; + LPBYTE prologstreambase; + DWORD prologbytes; + LPBYTE prologstreamexec[4]; + LPBYTE epilogstreambase; + DWORD epilogbytes; + LPBYTE epilogstreamexec[4]; + LPBYTE loopstreambase; + DWORD loopbytes; + LPBYTE loopstreamexec[1]; +} *STREAMPTR; + +static BUF s_codebuf = {NULL,0}; +static LIST(INST) s_instlist; +static REG s_nullreg = {0,0,0,0}; +static BUF s_retbuf = {NULL,0}; +static LIST(STREAM) s_streamlist; + +/**************************************************************************** +* +* INTEL X86 CODE GENERATOR +* +***/ + +static const BYTE s_intelx86opencodetable[NUMOPS][3][2] = + {{{0x8B,0},{0x89,0},{0xC7,0}}, // = + {{0x23,0},{0x21,0},{0x81,4}}, // & + {{0x0B,0},{0x09,0},{0x81,1}}, // | + {{0x33,0},{0x31,0},{0x81,6}}, // ^ + {{0x03,0},{0x01,0},{0x81,0}}, // + + {{0x2B,0},{0x29,0},{0x81,5}}, // - + {{0xF7,2},{0xF7,2},{0xF7,2}}, // ~ + {{0xC1,1},{0xC1,1},{0xC1,1}}};// @ +static const BYTE s_intelx86regencodetable32[NUMREGS] = + {4,0,7,6,5,1,2,3,0,0}; +static const BYTE s_intelx86regencodetable8[NUMREGS][2] = + {{0,0},{0,4},{0,0},{0,0},{0,0}, + {1,5},{2,6},{3,7},{0,0},{0,0}}; + +//=========================================================================== +static LPBYTE IntelX86GenerateCode (LPBYTE dest, INSTPTR inst) { + + // PERFORM SPECIAL PROCESSING FOR INCREMENT INSTRUCTIONS + if ((inst->op == OP_ADD) && !inst->source.id) { + *dest++ = (inst->opsize > 1) ? 0x81 : 0xFF; + *dest++ = 0xC0 | s_intelx86regencodetable32[inst->dest.id]; + if (inst->opsize > 1) { + *(LPDWORD)dest = inst->opsize; + dest += sizeof(DWORD); + } + return dest; + } + + // REPLACE "R=0" WITH "R^=R", WHICH IS FEWER BYTES IN THE INTEL ARCHITECTURE + if ((inst->op == OP_MOVE) && + (inst->dest.id == REG_CONST0) && + (!inst->source.indirect) && + (!inst->source.indexid)) { + inst->op = OP_XOR; + COPYREG(inst->dest,s_nullreg); + } + + // DETERMINE THE INSTRUCTION ENCODING + int operandtype = 0; + if ((inst->source.id == REG_CONST0) || + (inst->source.id == REG_CONST1) || + !inst->source.id) + operandtype = 2; + else if (inst->dest.indirect || inst->dest.indexid) + operandtype = 1; + BYTE instenc = s_intelx86opencodetable[inst->op][operandtype][0]; + BYTE instreg = s_intelx86opencodetable[inst->op][operandtype][1]; + if (inst->opsize == 1) + instenc &= 0xFE; + + // DETERMINE THE VALUES OF THE MODR/M AND SIB BYTES + BYTE modrm = 0; + BYTE sib = 0; + BOOL usesib = 0; + { + REGPTR simplereg = operandtype ? &inst->source : &inst->dest; + REGPTR complexreg = operandtype ? &inst->dest : &inst->source; + if (complexreg->indirect && (!complexreg->indexid) && + ((complexreg->id == REG_SOURCE) || (complexreg->id == REG_DEST))) + modrm = s_intelx86regencodetable32[complexreg->id]; + else if (complexreg->indirect || complexreg->indexid) { + modrm = 4; + usesib = 1; + if (complexreg->id == REG_TABLE) + if (complexreg->indexid) + sib = s_intelx86regencodetable32[complexreg->indexid] + | (s_intelx86regencodetable32[REG_TABLE] << 3); + else + modrm = 0x45; + else + sib = s_intelx86regencodetable32[complexreg->id] + | (s_intelx86regencodetable32[complexreg->indexid] << 3); + } + else + modrm = 0xC0 | (complexreg->portion + ? s_intelx86regencodetable8[complexreg->id][complexreg->portion-1] + : s_intelx86regencodetable32[complexreg->id]); + if ((operandtype == 2) || instreg) + modrm |= (instreg << 3); + else + modrm |= simplereg->portion + ? (s_intelx86regencodetable8[simplereg->id][simplereg->portion-1] << 3) + : (s_intelx86regencodetable32[simplereg->id] << 3); + } + + // WRITE A SIZE OVERRIDE PREFIX IF WE ARE DEALING WITH TWO-BYTE DATA + if (inst->opsize == 2) + *dest++ = 0x66; + + // WRITE THE OPCODE, MODR/M BYTE, AND THE SIB BYTE IF NECESSARY + *dest++ = instenc; + *dest++ = modrm; + if (usesib) + *dest++ = sib; + + // WRITE A CONSTANT IF NECESSARY + if (inst->op == OP_SWAP) + *dest++ = 16; + else if ((inst->source.id == REG_CONST0) || (inst->source.id == REG_CONST1)) { + *(LPDWORD)dest = (inst->source.id == REG_CONST1) ? 0xFFFFFFFF : 0; + dest += inst->opsize; + } + + return dest; +} + +//=========================================================================== +static LPBYTE IntelX86GenerateReturn (LPBYTE dest) { + + // ON INTEL PROCESSORS, WE USE A JUMP INSTEAD OF A RETURN, AND FILL IN + // THE JUMP TARGET AT EXECUTE TIME + *dest++ = 0xE9; + *(LPDWORD)dest = 0; + dest += sizeof(DWORD); + + return dest; +} + +/**************************************************************************** +* +* TEXT CODE GENERATOR +* +***/ + +static const LPSTR s_textopencodetable[NUMOPS] = + {"move ","and ","or ","xor ", + "add ","sub ","not ","ror "}; +static const char s_textregencodetable[NUMREGS+1] = + "?wdstabc01"; + +//=========================================================================== +static LPBYTE TextGenerateCode (LPBYTE dest, INSTPTR inst) { + + // PERFORM SPECIAL PROCESSING FOR INCREMENT INSTRUCTIONS + if ((inst->op == OP_ADD) && !inst->source.id) { + wsprintf((LPSTR)dest, + "inc %c,%u\n", + s_textregencodetable[inst->dest.id], + inst->opsize); + return dest+SStrLen((LPSTR)dest); + } + + // ADD THE INSTRUCTION TEXT + dest += SStrCopy((LPSTR)dest,s_textopencodetable[inst->op]); + + // ADD THE TEXT FOR EACH REGISTER + for (int regnum = 1; regnum >= 0; --regnum) { + REGPTR reg = regnum ? &inst->dest : &inst->source; + if (reg->id) { + if (!regnum) + *dest++ = ','; + if (reg->indirect || reg->indexid) + *dest++ = '['; + + // ADD THE REGISTER BASE NAME + if (reg->id == REG_CONST1) { + switch (inst->opsize) { + case 1: dest += SStrCopy((LPSTR)dest,"0FFh"); break; + case 2: dest += SStrCopy((LPSTR)dest,"0FFFFh"); break; + case 4: dest += SStrCopy((LPSTR)dest,"0FFFFFFFFh"); break; + } + } + else + *dest++ = s_textregencodetable[reg->id]; + + // ADD THE PORTION IDENTIFIER + if ((inst->opsize < 4) && !(reg->indirect || reg->indexid)) + if (inst->opsize == 2) + *dest++ = 'x'; + else + *dest++ = (reg->portion == 1) ? 'l' : 'h'; + + // ADD THE INDEX REGISTER NAME + if (reg->indexid) { + *dest++ = '+'; + *dest++ = s_textregencodetable[reg->indexid]; + } + + if (reg->indirect || reg->indexid) + *dest++ = ']'; + } + } + + *dest++ = '\n'; + return dest; +} + +//=========================================================================== +static LPBYTE TextGenerateReturn (LPBYTE dest) { + return dest+SStrCopy((LPSTR)dest,"ret\n"); +} + +/**************************************************************************** +* +* COMPILER FRONT-END (PLATFORM INDEPENDENT) +* +***/ + +static const char cacheidtable[] = "DST01"; +static const char regidtable[] = " WDSTABC01"; +static const char opidtable[] = "=&|^+-~@"; + +static inline BOOL IsRegisterUsed (LPCSTR codestring, BYTE regnum, BOOL singleequation); +static void QueueInstruction (int opsize, REG dest, REG operand1, REG operand2, char operation); + +//=========================================================================== +static void ClearQueue () { + s_instlist.Clear(); +} + +//=========================================================================== +static int FindLargestUnindexedAccess (BYTE regid) { + int result = 0; + ITERATELIST(INST,s_instlist,curr) + if ((((curr->dest.id == regid) && + (!curr->dest.indexid) && + (curr->dest.indirect)) || + ((curr->source.id == regid) && + (!curr->source.indexid) && + (curr->source.indirect))) && + (curr->opsize > result)) + result = curr->opsize; + return result; +} + +//=========================================================================== +static BOOL GenerateCode (LPCSTR codestring, LPCSTR *firsterror, BOOL pseudocode) { + if (firsterror) + *firsterror = NULL; + + VALIDATEBEGIN; + VALIDATE(codestring); + VALIDATEEND; + + // VERIFY THAT THE CODE STRING IS IN A VALID FORMAT + if (SStrLen(codestring) < 3) + FATALERROR(codestring); + + // DETERMINE HOW EACH REGISTER IS USED IN THIS CODE STRING. A REGISTER + // MAY NOT BE USED AT ALL, OR IT MAY BE USED IN ONE OF THE FOLLOWING + // FOUR WAYS: + // 1. TO STORE INTERMEDIATE RESULTS (EX: A=S D=A) + // 2. TO STORE A CONSTANT VALUE (EX: D=S^A) + // 3. TO STORE A VALUE THAT IS USED AND MODIFIED IN EACH ITERATION OF + // THE LOOP (EX: A=A+B D=A) + // 4. TO STORE A POINTER (EX: D=S) + // THE SECOND AND THIRD CASES ARE TREATED THE SAME, BECAUSE THEY BOTH + // COMPLETELY PREVENT US FROM USING THE REGISTER AS A WORK REGISTER. + // WE IDENTIFY THESE CASES BY LOOKING FOR REGISTERS THAT ARE USED WITHOUT + // PREVIOUSLY HAVING BEEN SET. + int reguse[NUMREGS]; + { + for (int loop = 1; loop < NUMREGS; ++loop) { + BOOL foundany = FALSE; + BOOL foundpermanent = FALSE; + { + BOOL set = FALSE; + BOOL seteeq = FALSE; + LPCSTR curr = codestring; + while (*curr) { + if (*curr == regidtable[loop]) + if ((*(curr+1) == '=') || + (*(curr+1) && SStrChr(PORTIONS,*(curr+1)) && (*(curr+2) == '='))) { + foundany = TRUE; + seteeq = TRUE; + } + else { + foundany = TRUE; + if (!set) + foundpermanent = TRUE; + } + if (*curr == ' ') { + set = seteeq; + seteeq = FALSE; + } + ++curr; + } + } + switch (loop) { + + case REG_WORK: + reguse[loop] = USE_INTER; + break; + + case REG_SOURCE: + case REG_DEST: + case REG_TABLE: + reguse[loop] = foundany ? USE_POINTER : USE_UNUSED; + break; + + case REG_CONST0: + case REG_CONST1: + reguse[loop] = USE_CONST; + break; + + default: + reguse[loop] = foundany ? foundpermanent ? USE_CONST + : USE_INTER + : USE_UNUSED; + break; + + } + } + } + + // START TRAVERSING THE CODE STRING FROM LEFT TO RIGHT + ClearQueue(); + BYTE cache[NUMCACHE] = {0,0,0,0,0}; + LPCSTR curr = codestring; + REG destreg = {0,0,0,0}; + REG holdreg = {0,0,0,0}; + char holdop = 0; + int opsize = 4; + do { + + // IF WE HIT A SIZE CHARACTER, CHANGE THE CURRENT OPERATION SIZE + if ((*curr) && + ((curr == codestring) || (*(curr-1) == ' ')) && + SStrChr(SIZES,*curr)) + opsize = (*curr)-'0'; + + // IF WE HIT AN OPERATOR, SAVE IT AS THE NEXT OPERATION + else if ((*curr) && SStrChr(OPERATIONS,*curr)) + holdop = *curr; + + // IF WE HIT A REGISTER NAME, THEN PROCESS ANY BYTE MODIFIERS AND + // INDEXES, AND THEN: + // 1. SAVE IT AS THE DESTINATION REGISTER + // 2. SAVE IT AS THE SOURCE REGISTER FOR THE NEXT OPERATION, OR + // 3. PERFORM THE CURRENT OPERATION AND SAVE THE RESULT AS THE SOURCE + // REGISTER FOR THE NEXT OPERATION + // IF WE HIT WHITESPACE, THEN PERFORM A SPECIAL CASE OPERATION TO + // STORE THE RESULT. + else if ((!*curr) || (*curr == ' ') || + SStrChr(REGISTERS,*curr)) { + + // DECODE THE REGISTER, PORTION IDENTIFIERS, AND INDEX REGISTERS + BOOL retire = ((!*curr) || (*curr == ' ')); + REG reg = {0,0,0,0}; + if (!retire) { + reg.id = CHARTOID(*curr); + reg.indirect = (reguse[reg.id] == USE_POINTER); + BOOL again; + do { + again = FALSE; + if ((*(curr+1)) && SStrChr(INDEXREGS,*(curr+1))) { + reg.indexid = CHARTOID(*(curr+1)); + ++curr; + again = TRUE; + } + if ((*(curr+1)) && SStrChr(PORTIONS,*(curr+1))) { + reg.portion = *(curr+1)-'0'; + ++curr; + again = TRUE; + } + if (again && ((reg.id == REG_CONST0) || (reg.id == REG_CONST1))) + FATALERROR(curr); + } while (again); + } + + // IF WE DON'T YET HAVE A DESTINATION REGISTER OR A SOURCE REGISTER + // FOR THE NEXT OPERATION, SAVE THIS REGISTER + if (!destreg.id) + if (*(curr+1) == '=') + if ((reg.id == REG_CONST0) || (reg.id == REG_CONST1)) + FATALERROR(curr); + else { + ++curr; + COPYREG(destreg,reg); + ZEROREG(holdreg); + holdop = 0; + } + else { + if (!retire) + FATALERROR(curr+1); + } + else if (!holdreg.id) { + COPYREG(holdreg,reg); + holdop = 0; + } + + // OTHERWISE, PERFORM THE SAVED OPERATION + else { + + // IF EITHER THE SOURCE REGISTER OR DESTINATION REGISTER IS USED AS + // AN OPERAND, FIND A PLACE TO STORE THE RESULT OF THE INDIRECTION. + // SIMILARLY, IF A CONSTANT VALUE IS USED IN ANYTHING BUT A SIMPLE + // LOGICAL OPERATION, FIND A PLACE TO STORE THE VALUE. + // CACHE THE RESULT IF THERE IS A FREE REGISTER, THE VALUE WILL BE + // USED AGAIN, AND THERE IS NO INDEXING INVOLVED. + if ((!retire) || (reguse[destreg.id] == USE_POINTER)) { + for (int operandnum = 0; operandnum <= 1; ++operandnum) + for (int regnum = 0; regnum <= 3; ++regnum) { + REG *regptr = operandnum ? ® : &holdreg; + BYTE *cacheptr = &cache[regnum]; + int checkid; + int checkuse; + switch (regnum) { + case CACHE_DEST: checkid = REG_DEST; checkuse = USE_POINTER; break; + case CACHE_SOURCE: checkid = REG_SOURCE; checkuse = USE_POINTER; break; + case CACHE_TABLE: checkid = REG_TABLE; checkuse = USE_POINTER; break; + case CACHE_CONST0: checkid = REG_CONST0; checkuse = USE_CONST; break; + case CACHE_CONST1: checkid = REG_CONST1; checkuse = USE_CONST; break; + } + if ((regptr->id == checkid) && + (reguse[checkid] == checkuse) && + ((regnum == CACHE_DEST) || + (regnum == CACHE_SOURCE) || + (regnum == CACHE_TABLE) || + (!holdop) || + (!SStrChr(LOGICALOPS,holdop)))) + + // IF THIS VALUE IS ALREADY CACHED, USE THAT + if ((*cacheptr) && (!regptr->indexid)) { + regptr->id = *cacheptr; + regptr->indirect = 0; + } + else { + + // OTHERWISE, DETERMINE WHETHER WE WANT TO CACHE IT, BASED + // ON WHETHER IT IS USED AGAIN AND WHETHER AN INDEX IS + // BEING APPLIED + BOOL wanttocache = IsRegisterUsed(curr+1,checkid,0) + && !regptr->indexid; + + // IF WE DO WANT TO CACHE IT, FIND A PLACE TO DO SO + BYTE found = 0; + if (wanttocache || (holdreg.id == REG_WORK)) { + BYTE loop; + + // LOOK FOR UNUSED REGISTERS, OR REGISTERS USED FOR + // INTERMEDIATE VALUES WHICH WON'T BE USED AGAIN + for (loop = NUMREGS-1; loop >= 1; --loop) + if ((loop != REG_WORK) && + ((reguse[loop] == USE_UNUSED) || + ((reguse[loop] == USE_INTER) && + (!SStrChr(curr,regidtable[loop]))))) { + found = loop; + break; + } + + // LOOK FOR REGISTERS USED FOR CACHING VALUES THAT + // NO LONGER NEED TO BE CACHED + if (!found) + for (loop = NUMREGS-1; loop >= 1; --loop) + if (reguse[loop] == USE_CACHE) { + BYTE findreg = 0; + for (int loop2 = 0; loop2 < NUMCACHE; ++loop2) + if (cache[loop2] == loop) + findreg = CHARTOID(cacheidtable[loop2]); + if (findreg) + found = IsRegisterUsed(curr,findreg,0) ? 0 : loop; + } + + } + + // IF WE DON'T WANT TO CACHE IT OR COULDN'T FIND A PLACE, + // PUT THE VALUE IN EITHER THE DESTINATION REGISTER OR + // THE WORK REGISTER + if (!found) + if (destreg.id && + (!destreg.indexid) && + (!destreg.portion) && + (!destreg.indirect) && + (reguse[destreg.id] == USE_INTER) && + (holdreg.id != destreg.id) && + !IsRegisterUsed(curr,destreg.id,1)) + found = destreg.id; + else if (holdreg.id != REG_WORK) + found = REG_WORK; + else + FATALERROR(curr); + + // ADD AN INSTRUCTION TO MOVE THE VALUE INTO THE CACHE OR + // WORK REGISTER + REG storereg = {found,0,0,0}; + QueueInstruction(opsize,storereg,*regptr,s_nullreg,0); + + // SAVE THE NEW LOCATION OF THE VALUE + if (wanttocache && (found != REG_WORK)) { + *cacheptr = found; + reguse[*cacheptr] = USE_CACHE; + } + COPYREG(*regptr,storereg); + + } + } + } + + // DETERMINE WHETHER ONE OF THE OPERANDS OR THE DESTINATION REGISTER + // CAN BE USED FOR THE RESULT OF THE OPERATION. IF NOT, WE WILL USE + // THE WORK REGISTER FOR THE RESULT. + REG resultreg = {REG_WORK,0,0,0}; + if (retire) { + COPYREG(resultreg,destreg); + ZEROREG(destreg); + } + else { + + // THE DESTINATION REGISTER CAN BE USED FOR THE RESULT IF IT IS + // NOT USED AGAIN IN THIS EQUATION, AND IT IS NOT A POINTER + if ((!IsRegisterUsed(curr+1,destreg.id,1)) && + (reguse[destreg.id] != USE_POINTER) && + !(destreg.indexid || destreg.indirect)) + COPYREG(resultreg,destreg); + + // OTHERWISE, IF ONE OF THE OPERANDS IS THE WORK REGISTER, WE + // CAN USE THAT FOR THE RESULT + else if ((holdreg.id == REG_WORK) && !(holdreg.indexid || holdreg.indirect)) + COPYREG(resultreg,holdreg); + else if ((reg.id == REG_WORK) && !(reg.indexid || reg.indirect)) + COPYREG(resultreg,reg); + + // OTHERWISE, WE CAN STILL USE ONE OF THE OPERANDS IF WE CAN FIND + // ONE THAT IS NOT A POINTER, IS NOT USED AGAIN, AND IS USED ONLY + // FOR INTERMEDIATE RESULTS OR AS A CACHE + else { + for (int operand = 0; operand <= 1; ++operand) { + REG *regptr = operand ? ® : &holdreg; + if ((!(regptr->indexid || regptr->indirect)) && + ((reguse[regptr->id] == USE_INTER) || + (reguse[regptr->id] == USE_CACHE))) { + char findreg = regptr->id; + if (reguse[regptr->id] == USE_CACHE) { + for (int loop = 0; loop < NUMCACHE; ++loop) + if (cache[loop] == regptr->id) + findreg = CHARTOID(cacheidtable[loop]); + } + if (!IsRegisterUsed(curr+1,findreg,0)) + COPYREG(resultreg,*regptr); + } + } + } + + } + + // ENCODE THE OPERATION + if (retire) { + if ((resultreg.id != holdreg.id) || + (resultreg.portion != holdreg.portion)) + QueueInstruction(opsize,resultreg,holdreg,s_nullreg,0); + } + else + QueueInstruction(opsize,resultreg,holdreg,reg,holdop); + + // SAVE THE RESULT REGISTER FOR USE BY THE NEXT OPERATION + if (retire) + ZEROREG(holdreg); + else + COPYREG(holdreg,resultreg); + holdop = 0; + + } + + } + + // IF WE DIDN'T HIT ANY OF THE ABOVE, THEN REPORT AN ERROR IN THE + // CODE STRING + else + FATALERROR(curr); + + } while (*curr++); + if (s_instlist.IsEmpty()) + return FALSE; + + // SEARCH THE QUEUE FOR THE LARGEST UNINDEXED READ OR WRITE WE DID FOR EACH + // OF THE POINTERS, THEN INCREMENT THE POINTER BY THAT AMOUNT + { + int largestsource = FindLargestUnindexedAccess(REG_SOURCE); + int largesttable = FindLargestUnindexedAccess(REG_TABLE); + int largestdest = FindLargestUnindexedAccess(REG_DEST); + REG reg = {0,0,0,0}; + if (largestsource) { + reg.id = REG_SOURCE; + QueueInstruction(largestsource,reg,s_nullreg,s_nullreg,'+'); + } + if (largesttable) { + reg.id = REG_TABLE; + QueueInstruction(largesttable,reg,s_nullreg,s_nullreg,'+'); + } + if (largestdest) { + reg.id = REG_DEST; + QueueInstruction(largestdest,reg,s_nullreg,s_nullreg,'+'); + } + } + + // ADD ROTATE INSTRUCTIONS AS NECESSARY TO ELIMINATE ACCESSES TO + // INVIDIDUAL BYTES IN THE HIGH WORDS OF REGISTERS + { + ITERATELIST(INST,s_instlist,curr) + for (int operandnum = 0; operandnum <= 1; ++operandnum) { + REGPTR currreg = operandnum ? &curr->dest : &curr->source; + REGPTR otherreg = operandnum ? &curr->source : &curr->dest; + if (currreg->portion > 2) + if ((currreg->id == otherreg->indexid) || + ((currreg->id == otherreg->id) && (otherreg->portion <= 2))) + FATALERROR(codestring+SStrLen(codestring)); + else { + REG destreg = {currreg->id,0,0,0}; + for (BOOL after = FALSE; after <= TRUE; ++after) { + INSTPTR inst = s_instlist.NewNode(LIST_UNLINKED); + COPYREG(inst->dest,destreg); + COPYREG(inst->source,s_nullreg); + inst->op = OP_SWAP; + inst->opsize = 4; + s_instlist.LinkNode(inst, + after ? LIST_LINK_AFTER + : LIST_LINK_BEFORE, + curr); + } + currreg->portion -= 2; + if (otherreg->id == currreg->id) + otherreg->portion -= 2; + } + } + } + + // REMOVE DUPLICATE ROTATE INSTRUCTIONS + { + ITERATELIST(INST,s_instlist,curr) + if (curr->op == OP_SWAP) + ITERATEPARTIALLIST(INST,s_instlist,curr->Next(),search) + if ((search->op == OP_SWAP) && (search->dest.id == curr->dest.id)) { + s_instlist.DeleteNode(search); + s_instlist.DeleteNode(curr); + curr = s_instlist.Head(); + break; + } + else if ((search->dest.id == curr->dest.id) || + (search->source.id == curr->dest.id) || + (search->dest.indexid == curr->dest.id) || + (search->source.indexid == curr->dest.id)) + break; + } + + // SIMPLIFY INSTRUCTIONS INVOLVING CONSTANT VALUES. SOME EXAMPLES: + // 1. "W&=1" IS REMOVED + // 2. "W&=0" IS REPLACED WITH "W=0" + // 3. "W^=1" IS REPLACED WITH "W~=" + { + ITERATELIST(INST,s_instlist,curr) { + BOOL remove = FALSE; + BOOL setto0 = FALSE; + BOOL setto1 = FALSE; + BOOL usenot = FALSE; + if (curr->source.id == REG_CONST0) + switch (curr->op) { + case OP_MOVE: setto0 = TRUE; break; + case OP_AND : setto0 = TRUE; break; + case OP_OR : remove = TRUE; break; + case OP_XOR : remove = TRUE; break; + case OP_ADD : remove = TRUE; break; + case OP_SUB : remove = TRUE; break; + } + else if (curr->source.id == REG_CONST1) + switch (curr->op) { + case OP_MOVE: remove = TRUE; break; + case OP_OR : setto1 = TRUE; break; + case OP_XOR : usenot = TRUE; break; + } + if (remove) { + ITERATE_DELETE; + } + else if (setto0 || setto1) { + curr->op = OP_MOVE; + REG sourcereg = {setto1 ? REG_CONST1 : REG_CONST0,0,0,0}; + COPYREG(curr->source,sourcereg); + } + else if (usenot) { + curr->op = OP_NOT; + COPYREG(curr->source,s_nullreg); + } + } + } + + // OPTIMIZE THE INSTRUCTION ORDERING. TO DO THIS, WE FIND PAIRS OF + // INSTRUCTIONS WHICH ARE UNPAIRABLE BECAUSE OF DATA DEPENDENCE, THEN + // LOOK FOR OTHER INSTRUCTIONS WHICH CAN BE MOVED BETWEEN THEM. + { + INSTPTR last = s_instlist.Head(); + INSTPTR curr = last->Next(); + while (curr) { + if ((curr->source.id && (curr->source.id == last->dest.id)) || + (curr->source.indexid && (curr->source.indexid == last->dest.id)) || + (curr->dest.id && (curr->dest.id == last->dest.id) && curr->op)) { + + // WE FOUND TWO UNPAIRABLE INSTRUCTIONS; NOW START SEARCHING FOR + // SOMETHING TO SPLIT THEM UP + BOOL set[NUMREGS]; ZeroMemory(set,NUMREGS*sizeof(BOOL)); + BOOL used[NUMREGS]; ZeroMemory(used,NUMREGS*sizeof(BOOL)); + ITERATEPARTIALLIST(INST,s_instlist,curr,searchcurr) { + if ((searchcurr > curr) && + ((!searchcurr->source.id) || (!set[searchcurr->source.id])) && + ((!searchcurr->source.indexid) || (!set[searchcurr->source.indexid])) && + ((!searchcurr->dest.id) || + ((!set[searchcurr->dest.id]) && + (!used[searchcurr->dest.id])))) { + + // WE FOUND AN INSTRUCTION WHICH CAN BE USED TO SPLIT THESE TWO + // INSTRUCTIONS, SO MOVE IT BETWEEN THEM + s_instlist.LinkNode(searchcurr,LIST_LINK_BEFORE,curr); + + break; + } + set[searchcurr->dest.id] = TRUE; + used[searchcurr->source.id] = TRUE; + used[searchcurr->source.indexid] = TRUE; + } + + } + last = curr; + curr = curr->Next(); + } + } + + // ALLOCATE OUTPUT BUFFERS IF THEY HAVEN'T ALREADY BEEN ALLOCATED + if (!s_codebuf.data) + s_codebuf.data = (LPBYTE)ALLOC(BUFFERSIZE); + if (!s_retbuf.data) + s_retbuf.data = (LPBYTE)ALLOC(BUFFERSIZE); + + // GET POINTERS TO THE PROCESSOR-SPECIFIC PORTION OF THE CODE GENERATOR + LPBYTE (*addinst)(LPBYTE,INSTPTR) = NULL; + LPBYTE (*addret )(LPBYTE) = NULL; + if (pseudocode) { + addinst = TextGenerateCode; + addret = TextGenerateReturn; + } + else { +#ifdef _X86_ + addinst = IntelX86GenerateCode; + addret = IntelX86GenerateReturn; +#endif + } + if (!(addinst && addret)) + FATALERROR(codestring+SStrLen(codestring)); + + // GENERATE PROCESSOR-SPECIFIC CODE INTO THE OUTPUT BUFFERS + { + LPBYTE dest = s_codebuf.data; + ITERATELIST(INST,s_instlist,curr) + dest = addinst(dest,curr); + s_codebuf.bytes = dest-s_codebuf.data; + } + { + LPBYTE dest = addret(s_retbuf.data); + s_retbuf.bytes = dest-s_retbuf.data; + } + + ClearQueue(); + return TRUE; +} + +//=========================================================================== +static inline BOOL IsRegisterUsed (LPCSTR codestring, BYTE regnum, BOOL singleequation) { + char regid = regidtable[regnum]; + for (;;) + if ((!*codestring) || ((*codestring == ' ') && singleequation)) + return FALSE; + else if ((*codestring == regid) && (*(codestring+1) != '=')) + return TRUE; + else + ++codestring; +} + +//=========================================================================== +static void QueueInstruction (int opsize, REG dest, REG operand1, REG operand2, char operation) { + + // IF THE RESULT REGISTER OR EITHER OF THE OPERANDS CONTAIN A PORTION + // IDENTIFIER, TEMPORARILY SET THE OPERATION SIZE TO A SINGLE BYTE + if (dest.portion || operand1.portion || operand2.portion) + opsize = 1; + + // IF WE ARE USING SINGLE BYTE OPERATIONS, THEN FORCE ALL NON-POINTER + // OPERANDS TO USE PORTIONS + if (opsize == 1) { + if (!(dest.portion || dest.indexid || dest.indirect)) + if ((dest.id == operand1.id) && operand1.portion) + dest.portion = operand1.portion; + else if ((dest.id == operand2.id) && operand2.portion) + dest.portion = operand2.portion; + else + dest.portion = 1; + if (!(operand1.portion || operand1.indexid || operand1.indirect)) + operand1.portion = 1; + if (operand2.id && + !(operand2.portion || operand2.indexid || operand2.indirect)) + operand2.portion = 1; + } + + // IF THERE ARE TWO OPERANDS, NORMALIZE THE INSTRUCTION SO THAT: + // 1. IF ONE OF THE OPERANDS IS THE SAME AS THE RESULT REGISTER, IT IS + // ON THE LEFT + // 2. IF ONE OF THE OPERANDS IS A CONSTANT, IT IS ON THE RIGHT + if (operand2.id && operation && + (COMPAREREGS(dest,operand2) && !COMPAREREGS(dest,operand1)) || + (((operand1.id == REG_CONST0) || (operand1.id == REG_CONST1)) && + !((operand2.id == REG_CONST0) || (operand2.id == REG_CONST1)))) { + REG temp; + COPYREG(temp,operand1); + COPYREG(operand1,operand2); + COPYREG(operand2,temp); + } + + // SIMPLIFY THE INSTRUCTION SO THAT IT CAN BE EXPRESSED AS ONE OPERATION, + // ONE RESULT OPERAND, AND ONE SOURCE OPERAND. THIS MAY INVOLVE SPLITTING + // IT INTO TWO INSTRUCTIONS. SOME EXAMPLES: + // 1. "W=W^A" BECOMES "W^=A" + // 2. "W=A^B" BECOMES "W=A" FOLLOWED BY "W^=B" + if (operand2.id && operation && + (!COMPAREREGS(dest,operand1)) && (!COMPAREREGS(dest,operand2))) { + REG nullop = {0,0,0,0}; + QueueInstruction(opsize,dest,operand1,nullop,0); + COPYREG(operand1,dest); + } + + // QUEUE THE INSTRUCTION + INSTPTR inst = s_instlist.NewNode(); + COPYREG(inst->dest ,dest); + COPYREG(inst->source,operand2.id ? operand2 : operand1); + inst->op = operation ? OPTOID(operation) : OP_MOVE; + inst->opsize = opsize; + +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SCodeCompile (LPCSTR prologstring, + LPCSTR loopstring, + LPCSTR *firsterror, + DWORD maxiterations, + DWORD flags, + HSCODESTREAM *handle) { + if (firsterror) + *firsterror = NULL; + + VALIDATEBEGIN; + VALIDATE(loopstring); + VALIDATE(*loopstring); + VALIDATE(maxiterations >= 1); + VALIDATE(handle); + VALIDATEEND; + + // CREATE NORMALIZED VERSIONS OF THE STRINGS + BOOL align = (flags & SCODE_CF_AUTOALIGNDWORD) != 0; + char localprologstring[256] = "W=0 "; + char localloopstring[256] = ""; + char *userprologstring = localprologstring; + char *userloopstring = localloopstring; + if (prologstring) + if (align) + SStrCopy(localprologstring,prologstring); + else { + userprologstring += SStrLen(localprologstring); + SStrPack(localprologstring,prologstring,256); + } + if (loopstring) + SStrCopy(localloopstring,loopstring); + if (align) { + if (localprologstring[0] == '#') + localprologstring[0] = '1'; + if (localloopstring[0] == '#') + localloopstring[0] = '4'; + } + _strupr(localprologstring); + _strupr(localloopstring); + + // CREATE A NEW CODE STREAM BUFFER + STREAMPTR stream = s_streamlist.NewNode(LIST_HEAD,maxiterations*sizeof(LPBYTE)); + stream->flags = flags; + stream->checkvalue = 0xFFFFFFFF; + + // COMPILE AND UNROLL THE PROLOG/EPILOG S-CODE STRING + { + BOOL result = GenerateCode(localprologstring,firsterror,0); + if (firsterror && *firsterror) + *firsterror = prologstring+(*firsterror-userprologstring); + if (!result) + return SCodeDelete((HSCODESTREAM)stream); + DWORD iterations = align ? 3 : 1; + stream->prologbytes = s_codebuf.bytes*iterations+s_retbuf.bytes; + stream->prologstreambase = (LPBYTE)ALLOC(stream->prologbytes); + if (align) { + stream->epilogbytes = s_codebuf.bytes*iterations+s_retbuf.bytes; + stream->epilogstreambase = (LPBYTE)ALLOC(stream->epilogbytes); + } + LPBYTE prologdest = stream->prologstreambase; + LPBYTE epilogdest = stream->epilogstreambase; + DWORD loop; + for (loop = 0; loop < iterations; ++loop) { + CopyMemory(prologdest,s_codebuf.data,s_codebuf.bytes); + prologdest += s_codebuf.bytes; + if (align) { + CopyMemory(epilogdest,s_codebuf.data,s_codebuf.bytes); + epilogdest += s_codebuf.bytes; + } + } + CopyMemory(prologdest,s_retbuf.data,s_retbuf.bytes); + if (align) { + CopyMemory(epilogdest,s_retbuf.data,s_retbuf.bytes); + for (loop = 0; loop <= iterations; ++loop) { + stream->prologstreamexec[loop] = stream->prologstreambase + +(iterations-loop)*s_codebuf.bytes; + if (align) + stream->epilogstreamexec[loop] = stream->epilogstreambase + +(iterations-loop)*s_codebuf.bytes; + } + } + } + + // COMPILE AND UNROLL THE LOOP S-CODE STRING + { + BOOL result = GenerateCode(localloopstring,firsterror,0); + if (firsterror && *firsterror) + *firsterror = loopstring+(*firsterror-userloopstring); + if (!result) + return SCodeDelete((HSCODESTREAM)stream); + stream->loopbytes = s_codebuf.bytes*maxiterations+s_retbuf.bytes; + stream->loopstreambase = (LPBYTE)ALLOC(stream->loopbytes); + LPBYTE dest = stream->loopstreambase; + DWORD loop; + for (loop = 0; loop < maxiterations; ++loop) { + CopyMemory(dest,s_codebuf.data,s_codebuf.bytes); + dest += s_codebuf.bytes; + } + CopyMemory(dest,s_retbuf.data,s_retbuf.bytes); + for (loop = 0; loop <= maxiterations; ++loop) + stream->loopstreamexec[loop] = stream->loopstreambase + +(maxiterations-loop)*s_codebuf.bytes; + } + + *handle = (HSCODESTREAM)stream; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SCodeDelete (HSCODESTREAM handle) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATEEND; + + // FREE THE CODE BUFFERS + STREAMPTR stream = (STREAMPTR)handle; + if (stream->prologstreambase) { + FREE(stream->prologstreambase); + stream->prologstreambase = NULL; + } + if (stream->epilogstreambase) { + FREE(stream->epilogstreambase); + stream->epilogstreambase = NULL; + } + if (stream->loopstreambase) { + FREE(stream->loopstreambase); + stream->loopstreambase = NULL; + } + + // UNLINK AND FREE THE NODE. THE MEMORY IS FREED EVEN IF THE NODE IS NOT + // FOUND IN THE LINKED LIST, WHICH WOULD BE THE CASE IF WE ARE BEING CALLED + // BECAUSE OF AN ERROR DURING COMPILATION. + s_streamlist.DeleteNode(stream); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SCodeDestroy () { + + // DELETE ALL CODE STREAMS + while (!s_streamlist.IsEmpty()) { + REPORTRESOURCELEAK(HSCODESTREAM); + SCodeDelete((HSCODESTREAM)s_streamlist.Head()); + } + + // FREE THE CODE BUFFER AND RETURN BUFFER IF NECESSARY + if (s_codebuf.data) + FREE(s_codebuf.data); + ZeroMemory(&s_codebuf,sizeof(BUF)); + if (s_retbuf.data) + FREE(s_retbuf.data); + ZeroMemory(&s_retbuf,sizeof(BUF)); + + // CLEAR THE INSTRUCTION QUEUE IF NECESSARY + ClearQueue(); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SCodeExecute (HSCODESTREAM handle, + SCODEEXECUTEDATAPTR executedata) { + STREAMPTR stream = (STREAMPTR)handle; + DWORD xiterations = executedata->xiterations; + + // IF WE ARE DOING AUTO-ALIGNMENT, FIX UP THE JUMP OFFSETS AS FOLLOWS: + // 1. EXECUTE PROLOG CODE FOR BYTE OPERATIONS, UP TO A DWORD BOUNDARY + // 2. EXECUTE LOOP CODE FOR WHOLE DWORD OPERATIONS + // 3. EXECUTE EPILOG CODE FOR FINAL BYTE OPERATIONS + // "XITERATIONS" REFERS TO THE TOTAL NUMBER OF BYTES TO PROCESS + if (stream->flags & SCODE_CF_AUTOALIGNDWORD) { + DWORD checkvalue = (xiterations << 2) ^ ((DWORD)executedata->dest & 3); + if (stream->checkvalue != checkvalue) { + stream->checkvalue = checkvalue; + DWORD align1 = (4-((DWORD)executedata->dest & 3)) & 3; + if (align1 > xiterations) + align1 = xiterations; + DWORD dwords = (xiterations -= align1) >> 2; + DWORD align2 = xiterations & 3; +#ifdef _X86_ + LPBYTE retptr1, retptr2; + __asm mov retptr1,OFFSET ex_loop1 + __asm mov retptr2,OFFSET ex_loop2 + if (align1 || align2) { + stream->executeptr = stream->prologstreamexec[align1]; + *(LPDWORD)(stream->prologstreambase+stream->prologbytes-sizeof(DWORD)) + = stream->loopstreamexec[dwords]-(stream->prologstreambase+stream->prologbytes); + *(LPDWORD)(stream->loopstreambase+stream->loopbytes-sizeof(DWORD)) + = stream->epilogstreamexec[align2] + -(stream->loopstreambase+stream->loopbytes); + *(LPDWORD)(stream->epilogstreambase+stream->epilogbytes-sizeof(DWORD)) + = ((stream->flags & SCODE_CF_USESALTADJUSTS) ? retptr2 : retptr1) + -(stream->epilogstreambase+stream->epilogbytes); + } + else { + stream->executeptr = stream->loopstreamexec[dwords]; + *(LPDWORD)(stream->loopstreambase+stream->loopbytes-sizeof(DWORD)) + = ((stream->flags & SCODE_CF_USESALTADJUSTS) ? retptr2 : retptr1) + -(stream->loopstreambase+stream->loopbytes); + } +#endif + } + } + + // OTHERWISE, FIX UP THE JUMP OFFSETS SO THAT WE CALL THE PROLOG CODE + // ONCE, FOLLOWED BY "XITERATIONS" ITERATIONS OF THE LOOP CODE + else { + if (stream->checkvalue != xiterations) { + stream->checkvalue = xiterations; +#ifdef _X86_ + LPBYTE retptr1, retptr2; + __asm mov retptr1,OFFSET ex_loop1 + __asm mov retptr2,OFFSET ex_loop2 + stream->executeptr = stream->prologstreambase; + *(LPDWORD)(stream->prologstreambase+stream->prologbytes-sizeof(DWORD)) + = stream->loopstreamexec[xiterations] + -(stream->prologstreambase+stream->prologbytes); + *(LPDWORD)(stream->loopstreambase+stream->loopbytes-sizeof(DWORD)) + = ((stream->flags & SCODE_CF_USESALTADJUSTS) ? retptr2 : retptr1) + -(stream->loopstreambase+stream->loopbytes); +#endif + } + } + + // EXECUTE THE LOOPS FOR INTEL X86 PROCESSORS +#ifdef _X86_ +#define LOCAL_JUMPPTR DWORD PTR [esp] +#define LOCAL_YCOUNT DWORD PTR [esp+4] +#define LOCAL_EXECUTEDATA DWORD PTR [esp+8] +#define LOCAL_ADJUSTSOURCE DWORD PTR [esp+12] +#define LOCAL_ADJUSTDEST DWORD PTR [esp+16] + __asm { + push edi + push esi + push ebp + + // PREPARE OUR LOCAL DATA AREA ON THE STACK + mov eax,executedata + mov ebx,stream + sub esp,20 + mov ecx,[eax]SCODEEXECUTEDATA.yiterations + mov esi,[eax]SCODEEXECUTEDATA.adjustsource + mov edi,[eax]SCODEEXECUTEDATA.adjustdest + mov ebx,[ebx]STREAM.executeptr + mov LOCAL_EXECUTEDATA,eax + mov LOCAL_JUMPPTR,ebx + mov LOCAL_YCOUNT,ecx + mov LOCAL_ADJUSTSOURCE,esi + mov LOCAL_ADJUSTDEST,edi + + // PREPARE THE REGISTERS + mov edi,[eax]SCODEEXECUTEDATA.dest + mov esi,[eax]SCODEEXECUTEDATA.source + mov ebp,[eax]SCODEEXECUTEDATA.table + mov ecx,[eax]SCODEEXECUTEDATA.a + mov edx,[eax]SCODEEXECUTEDATA.b + mov ebx,[eax]SCODEEXECUTEDATA.c + + // EXECUTE THE FIRST LOOP + mov eax,LOCAL_JUMPPTR + jmp eax + + // EXECUTE THE NEXT LOOP FOR TYPE 1 (STANDARD) + align 16 + ex_loop1: dec LOCAL_YCOUNT + mov eax,LOCAL_JUMPPTR + jz ex_done + add esi,LOCAL_ADJUSTSOURCE + add edi,LOCAL_ADJUSTDEST + jmp eax + + // EXECUTE THE NEXT LOOP FOR TYPE 2 (ALTERNATING) + align 16 + ex_loop2: test LOCAL_YCOUNT,1 + jnz ex_loop2odd + dec LOCAL_YCOUNT + mov eax,LOCAL_JUMPPTR + add esi,LOCAL_ADJUSTSOURCE + add edi,LOCAL_ADJUSTDEST + jmp eax + ex_loop2odd: dec LOCAL_YCOUNT + jz ex_done + mov eax,LOCAL_EXECUTEDATA + add esi,[eax]SCODEEXECUTEDATA.adjustsourcealt + add edi,[eax]SCODEEXECUTEDATA.adjustdestalt + mov eax,LOCAL_JUMPPTR + jmp eax + + // RESTORE THE STACK + ex_done: add esp,20 + pop ebp + pop esi + pop edi + + // SAVE THE VALUE OF EACH VARIABLE + mov eax,executedata + mov [eax]SCODEEXECUTEDATA.a,ecx + mov [eax]SCODEEXECUTEDATA.b,edx + mov [eax]SCODEEXECUTEDATA.c,ebx + + } +#undef LOCAL_JUMPPTR +#undef LOCAL_YCOUNT +#undef LOCAL_ADJUSTSOURCE +#undef LOCAL_ADJUSTDEST +#endif + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SCodeGetJumpTable (HSCODESTREAM handle, + LPBYTE **jumptableptr, + LPDWORD *prologpatchlocation, + LPDWORD *looppatchlocation, + LPDWORD *epilogpatchlocation) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATEEND; + + STREAMPTR stream = (STREAMPTR)handle; + + if (jumptableptr) + *jumptableptr = &stream->loopstreamexec[0]; + if (prologpatchlocation) + *prologpatchlocation = (LPDWORD)(stream->prologstreambase+stream->prologbytes-sizeof(DWORD)); + if (looppatchlocation) + *looppatchlocation = (LPDWORD)(stream->loopstreambase+stream->loopbytes-sizeof(DWORD)); + if (epilogpatchlocation) + *epilogpatchlocation = (LPDWORD)(stream->epilogstreambase+stream->epilogbytes-sizeof(DWORD)); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SCodeGetPseudocode (LPCSTR scodestring, + LPSTR buffer, + DWORD buffersize) { + VALIDATEBEGIN; + VALIDATE(scodestring); + VALIDATE(*scodestring); + VALIDATE(buffer); + VALIDATE(buffersize); + VALIDATEEND; + + // CREATE A NORMALIZED VERSION OF THE STRING + char localstring[256] = ""; + SStrCopy(localstring,scodestring,256); + _strupr(localstring); + + // COMPILE THE S-CODE INTO PSEUDOCODE + if (!GenerateCode(localstring,NULL,1)) { + *buffer = 0; + return FALSE; + } + *(s_codebuf.data+s_codebuf.bytes) = 0; + + // COPY THE PSEUDOCODE INTO THE BUFFER + SStrCopy(buffer,(LPSTR)s_codebuf.data,buffersize); + + return (s_codebuf.bytes < buffersize); +} diff --git a/src/Storm/SOURCE/SCOMP.CPP b/src/Storm/SOURCE/SCOMP.CPP new file mode 100644 index 0000000..a941ef5 --- /dev/null +++ b/src/Storm/SOURCE/SCOMP.CPP @@ -0,0 +1,1267 @@ +/**************************************************************************** +* +* SCOMP.CPP +* Storm compression functions +* +* By Michael O'Brien (10/17/97) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define SOURCESYMBOLS 256 +#define EOS 256 +#define ESCAPE 257 +#define SYMBOLS 258 + +static const BYTE s_probability[SCOMP_HINTS][SYMBOLS] = + { + + // BASIC PROBABILITY TABLE + {10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2}, + + // BINARY PROBABILITY TABLE + {84,22,22,13,12,8,6,5,6,5,6,3,4,4,3,5, + 14,11,20,19,19,9,11,6,5,4,3,2,3,2,2,2, + 13,7,9,6,6,4,3,2,4,3,3,3,3,3,2,2, + 9,6,4,4,4,4,3,2,3,2,2,2,2,3,2,4, + 8,3,4,7,9,5,3,3,3,3,2,2,2,3,2,2, + 3,2,2,2,2,2,2,2,2,1,1,1,2,1,2,2, + 6,10,8,8,6,7,4,3,4,4,2,2,4,2,3,3, + 4,3,7,7,9,6,4,3,3,2,1,2,2,2,2,2, + 10,2,2,3,2,2,1,1,2,2,2,6,3,5,2,3, + 2,1,1,1,1,1,1,1,1,1,1,2,3,1,1,1, + 2,1,1,1,1,1,1,2,4,4,4,7,9,8,12,2, + 1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,3, + 4,1,2,4,5,1,1,1,1,1,1,1,2,1,1,1, + 4,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1, + 2,1,1,1,1,1,1,2,2,1,1,2,2,2,6,75}, + + // TEXT PROBABILITY TABLE + {0,0,0,0,0,0,0,0,0,3,39,0,0,35,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 255,1,1,1,1,1,1,1,2,2,1,1,6,14,16,4, + 6,8,5,4,4,3,3,2,2,3,3,1,1,2,1,1, + 1,4,2,4,2,2,2,1,1,4,1,1,2,3,3,2, + 3,1,3,6,4,1,1,1,1,1,1,2,1,2,1,1, + 1,41,7,22,18,64,10,10,17,37,1,3,23,16,38,42, + 16,1,35,35,47,16,6,7,2,9,1,1,1,1,1,0}, + + // EXECUTABLE PROBABILITY TABLE + {255,11,7,5,11,2,2,2,6,2,2,1,4,2,1,3, + 9,1,1,1,3,4,1,1,2,1,1,1,2,1,1,1, + 5,1,1,1,13,1,1,1,1,1,1,1,1,1,1,1, + 2,1,1,3,1,1,1,1,1,1,1,2,1,1,1,1, + 10,4,2,1,6,3,2,1,1,1,1,1,3,1,1,1, + 5,2,3,4,3,3,3,2,1,1,1,2,1,2,3,3, + 1,3,1,1,2,5,1,1,4,3,5,1,3,1,3,3, + 2,1,4,3,10,6,1,1,1,1,1,1,1,1,1,1, + 2,2,1,10,2,5,1,1,2,7,2,23,1,5,1,1, + 14,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 6,2,1,4,5,1,1,2,1,1,1,1,2,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,7,1,1,2,1,1,1,1, + 2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,17}, + + // ADPCM4 PROBABILITY TABLE + {255,251,152,154,132,133,99,100,62,62,34,34,19,19,24,23}, + + // ADPCM6 PROBABILITY TABLE + {255,241,157,158,154,155,154,151,147,147,140,142,134,136,128,130, + 124,124,114,115,105,107,95,96,85,86,74,75,64,65,55,55, + 47,47,39,39,33,33,27,28,23,23,19,19,16,16,13,13, + 11,11,9,9,8,8,7,7,6,5,5,4,4,4,25,24} + + }; + +/**************************************************************************** +* +* BITWISE I/O SUPPORT +* +***/ + +namespace { + +class CBitInput { + + private: + const DWORD *m_currsource; + DWORD m_rack; + DWORD m_rackbits; + + public: + CBitInput (LPCVOID source, + DWORD sourcebytes); + inline DWORD InputBit (); + inline DWORD InputBits (DWORD count, + DWORD mask); + inline DWORD PeekBits (DWORD count, + DWORD mask); + inline void RemoveBits (DWORD count); + +}; + +class CBitOutput { + + private: + LPBYTE m_basedest; + DWORD m_bytesleft; + LPBYTE m_currdest; + DWORD m_rack; + DWORD m_rackbits; + + public: + CBitOutput (LPVOID dest, + DWORD destsize); + DWORD GetTotalBytes (); + inline void OutputBits (DWORD value, + DWORD count); + void Pad (); + +}; + +//=========================================================================== +CBitInput::CBitInput (LPCVOID source, + DWORD sourcebytes) { + m_currsource = (const DWORD *)source; + m_rack = *m_currsource++; + m_rackbits = 32; +} + +//=========================================================================== +DWORD CBitInput::InputBit () { + DWORD result = (m_rack & 1); + m_rack >>= 1; + if (!--m_rackbits) { + m_rack = *m_currsource++; + m_rackbits = 32; + } + return result; +} + +//=========================================================================== +DWORD CBitInput::InputBits (DWORD count, + DWORD mask) { + DWORD result = PeekBits(count,mask); + RemoveBits(count); + return result; +} + +//=========================================================================== +DWORD CBitInput::PeekBits (DWORD count, + DWORD mask) { + while (m_rackbits <= count) { + m_rack |= *(LPBYTE)m_currsource << m_rackbits; + m_rackbits += 8; + m_currsource = (LPDWORD)((LPBYTE)m_currsource+1); + } + return m_rack & mask; +} + +//=========================================================================== +void CBitInput::RemoveBits (DWORD count) { + m_rack >>= count; + m_rackbits -= count; +} + +//=========================================================================== +CBitOutput::CBitOutput (LPVOID dest, + DWORD destsize) { + m_basedest = m_currdest = (LPBYTE)dest; + m_bytesleft = destsize; + m_rack = 0; + m_rackbits = 0; +} + +//=========================================================================== +DWORD CBitOutput::GetTotalBytes () { + return m_currdest-m_basedest; +} + +//=========================================================================== +void CBitOutput::OutputBits (DWORD value, + DWORD count) { + m_rack |= (value << m_rackbits); + m_rackbits += count; + while (m_rackbits >= 8) { + if (m_bytesleft) { + *m_currdest++ = (BYTE)m_rack; + --m_bytesleft; + } + m_rack >>= 8; + m_rackbits -= 8; + } +} + +//=========================================================================== +void CBitOutput::Pad () { + while (m_rackbits) { + if (m_bytesleft) { + *m_currdest++ = (BYTE)m_rack; + --m_bytesleft; + } + m_rack >>= 8; + m_rackbits -= min(8,m_rackbits); + } +} + +} // end of namespace + +/**************************************************************************** +* +* HUFFMAN ENCODER +* +***/ + +namespace { + +NODEDECL(HUFFNODE) { + int symbol; + DWORD weight; + HUFFNODE *parent; + HUFFNODE *child; +} *HUFFNODEPTR; + +class CHuffman { + + protected: + BOOL m_adaptive; + DWORD m_changesequence; + LIST(HUFFNODE) m_nodelist; + HUFFNODEPTR m_symbol[SYMBOLS]; + + void AddSymbol (int symbol); + void BuildTree (BYTE hint); + inline void IncrementWeight (HUFFNODEPTR node); + + public: + CHuffman (); + ~CHuffman (); + +}; + +class CHuffmanDecoder : public CHuffman { + + private: + DWORD m_cachebits[SYMBOLS]; + DWORD m_cachesequence[SYMBOLS]; + int m_cachesymbol[SYMBOLS]; + + inline int DecodeSymbol (CBitInput *input); + + public: + CHuffmanDecoder (); + DWORD Decompress (LPVOID dest, + CBitInput *input); + +}; + +class CHuffmanEncoder : public CHuffman { + + private: + inline void EncodeSymbol (CBitOutput *output, + int symbol); + + public: + DWORD Compress (CBitOutput *output, + LPCVOID source, + DWORD sourcesize, + BYTE hint); + +}; + +//=========================================================================== +CHuffman::CHuffman () { + m_changesequence = 1; +} + +//=========================================================================== +CHuffman::~CHuffman () { + m_nodelist.Clear(); +} + +//=========================================================================== +void CHuffman::AddSymbol (int symbol) { + + // CONVERT THE LIGHTEST WEIGHT LEAF NODE INTO A BRANCH + HUFFNODEPTR parent = m_nodelist.Head(); + HUFFNODEPTR oldchild = m_nodelist.NewNode(LIST_HEAD); + oldchild->symbol = parent->symbol; + oldchild->weight = parent->weight; + oldchild->parent = parent; + m_symbol[oldchild->symbol] = oldchild; + + // ALLOCATE A NEW LEAF NODE FOR THIS SYMBOL + HUFFNODEPTR newchild = m_nodelist.NewNode(LIST_HEAD); + newchild->symbol = symbol; + newchild->weight = 0; + newchild->parent = parent; + m_symbol[symbol] = newchild; + + // ATTACH THE PARENT NODE TO THESE TWO LEAF NODES + parent->child = newchild; + + // INCREMENT THE NEW LEAF NODE'S WEIGHT + IncrementWeight(newchild); + +} + +//=========================================================================== +void CHuffman::BuildTree (BYTE hint) { + + // REMOVE ALL NODES FROM THE EXISTING NODE LIST + m_nodelist.Clear(); + + // ADD LEAF NODES FOR EACH SYMBOL + ZeroMemory(m_symbol,SYMBOLS*sizeof(HUFFNODEPTR)); + DWORD maxweight = 0; + int symbol; + for (symbol = 0; symbol < SOURCESYMBOLS; ++symbol) + if (s_probability[hint][symbol]) { + + // CREATE A NEW NODE FOR THIS SYMBOL + HUFFNODEPTR newnode = m_symbol[symbol] = m_nodelist.NewNode(LIST_TAIL); + newnode->symbol = symbol; + newnode->weight = s_probability[hint][symbol]; + + // LINK IT INTO THE NODE LIST IN SORTED ORDER + if (newnode->weight >= maxweight) + maxweight = newnode->weight; + else { + HUFFNODEPTR checknode = m_nodelist.Head(); + while (checknode && (checknode->weight < newnode->weight)) + checknode = checknode->Next(); + m_nodelist.LinkNode(newnode,LIST_LINK_BEFORE,checknode); + } + + } + for (; symbol < SYMBOLS; ++symbol) { + HUFFNODEPTR newnode = m_symbol[symbol] = m_nodelist.NewNode(LIST_HEAD); + newnode->symbol = symbol; + newnode->weight = 1; + } + + // BUILD THE NODE TREE UP FROM THE LEAF NODES + for (HUFFNODEPTR currnode = m_nodelist.Head(), nextnode; + currnode && (nextnode = currnode->Next()); + currnode = nextnode->Next()) { + + // CREATE A NEW NODE TO BE THE PARENT OF THESE TWO NODES + HUFFNODEPTR newnode = m_nodelist.NewNode(LIST_TAIL); + newnode->weight = currnode->weight+nextnode->weight; + newnode->child = currnode; + + // SET EACH NODE'S PARENT TO THE NEW NODE + currnode->parent = newnode; + nextnode->parent = newnode; + + // LINK THE NEW NODE INTO THE LIST, SORTED BY WEIGHT + if (newnode->weight >= maxweight) + maxweight = newnode->weight; + else { + HUFFNODEPTR checknode = nextnode->Next(); + while (checknode && (checknode->weight < newnode->weight)) + checknode = checknode->Next(); + m_nodelist.LinkNode(newnode,LIST_LINK_BEFORE,checknode); + } + + } + + // INITIALIZE THE SEQUENCE NUMBER + m_changesequence = 1; + +} + +//=========================================================================== +void CHuffman::IncrementWeight (HUFFNODEPTR node) { + + // PROPAGATE THE WEIGHT CHANGE UP THE TREE + for (HUFFNODEPTR currnode = node; + currnode; + currnode = currnode->parent) { + + // UPDATE THIS NODE'S WEIGHT + ++currnode->weight; + + // CHECK TO SEE IF THIS NODE NEEDS TO BE MOVED UP THE TREE + HUFFNODEPTR checknode = currnode; + HUFFNODEPTR nextchecknode; + while ((nextchecknode = checknode->Next()) != NULL) + if (nextchecknode->weight < currnode->weight) + checknode = nextchecknode; + else + break; + + // IF IT DOES, THEN SWAP IT WITH THE NODE THAT HAS THE NEXT + // HIGHER WEIGHT + if (checknode != currnode) { + + // SWAP THE TWO NODES' POSITIONS IN THE LIST + m_nodelist.LinkNode(checknode,LIST_LINK_BEFORE,currnode); + m_nodelist.LinkNode(currnode,LIST_LINK_BEFORE,nextchecknode); + + // SWAP THE TWO NODES' PARENTS + HUFFNODEPTR currnodefirstchild = currnode->parent->child; + HUFFNODEPTR checknodefirstchild = checknode->parent->child; + if (currnodefirstchild == currnode) + currnode->parent->child = checknode; + if (checknodefirstchild == checknode) + checknode->parent->child = currnode; + SWAP(currnode->parent,checknode->parent); + + // INVALIDATE THE CACHE + ++m_changesequence; + + } + + } + +} + +//=========================================================================== +CHuffmanDecoder::CHuffmanDecoder () { + ZeroMemory(m_cachesequence,SYMBOLS*sizeof(DWORD)); +} + +//=========================================================================== +int CHuffmanDecoder::DecodeSymbol (CBitInput *input) { + + // CHECK TO SEE WHETHER THE DECODING OF THE NEXT SYMBOL IS CACHED + DWORD nextbyte = input->PeekBits(8,0xFF); + if (m_cachesequence[nextbyte] == m_changesequence) { + input->RemoveBits(m_cachebits[nextbyte]); + return m_cachesymbol[nextbyte];; + } + + // IF NOT, DECODE THE SYMBOL BY WALKING THE TREE, THEN ADD IT TO THE CACHE + DWORD bits = 0; + for (HUFFNODEPTR currnode = m_nodelist.Tail(); + currnode->child; + ++bits) { + currnode = currnode->child; + if (input->InputBit()) + currnode = currnode->Next(); + } + int symbol = currnode->symbol; + if (bits <= 8) { + m_cachebits[nextbyte] = bits; + m_cachesequence[nextbyte] = m_changesequence; + m_cachesymbol[nextbyte] = symbol; + } + return symbol; + +} + +//=========================================================================== +DWORD CHuffmanDecoder::Decompress (LPVOID dest, + CBitInput *input) { + + // INITIALIZE THE DECOMPRESSION TREE + BYTE hint = (BYTE)input->InputBits(8,0xFF); + BuildTree(hint); + m_adaptive = (hint == SCOMP_HINT_NONE); + + // DECOMPRESS THE DATA + LPBYTE currdest = (LPBYTE)dest; + for (;;) { + + // DECODE THE NEXT SYMBOL + int symbol = DecodeSymbol(input); + + // PROCESS THE SYMBOL + if (symbol == ESCAPE) { + symbol = (int)input->InputBits(8,0xFF); + AddSymbol(symbol); + if (!m_adaptive) + IncrementWeight(m_symbol[symbol]); + } + if (symbol == EOS) + break; + *currdest++ = (BYTE)symbol; + + // UPDATE SYMBOL'S WEIGHT + if (m_adaptive) + IncrementWeight(m_symbol[symbol]); + + } + + return currdest-(LPBYTE)dest; +} + +//=========================================================================== +DWORD CHuffmanEncoder::Compress (CBitOutput *output, + LPCVOID source, + DWORD sourcesize, + BYTE hint) { + + // INITIALIZE THE COMPRESSION TREE USING THE HINT, AND SAVE THE HINT + // TO THE DESTINATION BUFFER + BuildTree(hint); + m_adaptive = (hint == SCOMP_HINT_NONE); + output->OutputBits(hint,8); + + // COMPRESS THE DATA + const BYTE *currsource = (const BYTE *)source; + while (sourcesize--) { + int symbol = *currsource++; + + // IF THIS IS THE FIRST USE OF THIS SYMBOL, ENCODE AN ESCAPE SEQUENCE + if (!m_symbol[symbol]) { + EncodeSymbol(output,ESCAPE); + output->OutputBits(symbol,8); + AddSymbol(symbol); + if (!m_adaptive) + IncrementWeight(m_symbol[symbol]); + } + + // OTHERWISE, ENCODE THE SYMBOL + else + EncodeSymbol(output,symbol); + + // UPDATE SYMBOL'S WEIGHT + if (m_adaptive) + IncrementWeight(m_symbol[symbol]); + + } + + // ENCODE AN END-OF-STREAM SEQUENCE + EncodeSymbol(output,EOS); + output->Pad(); + + return output->GetTotalBytes(); +} + +//=========================================================================== +void CHuffmanEncoder::EncodeSymbol (CBitOutput *output, + int symbol) { + DWORD encoding = 0; + DWORD encodingbits = 0; + for (HUFFNODEPTR currnode = m_symbol[symbol], parent; + parent = currnode->parent; + currnode = parent) { + encoding <<= 1; + encoding |= (parent->child != currnode); + ++encodingbits; + } + output->OutputBits(encoding, + encodingbits); +} + +} // end of namespace + +/**************************************************************************** +* +* ADPCM ENCODER +* +***/ + +namespace { + +static const DWORD s_adpcm_2bit[2] = {51,102}; +static const DWORD s_adpcm_3bit[4] = {58,58,80,112}; +static const DWORD s_adpcm_4bit[8] = {58,58,58,58,77,102,128,154}; +static const DWORD s_adpcm_6bit[32] = {58,58,58,58,58,58,58,58, + 58,58,58,58,58,58,58,58, + 70,83,96,109,122,134,147,160, + 173,186,198,211,224,237,250,262}; + +class CAdpcm { + + protected: + const DWORD *m_adapttable; + DWORD m_bitspersample; + DWORD m_minadapt; + DWORD m_maxadapt; + DWORD m_steps; + + inline void AdjustValue (int *last, + DWORD *adapt, + DWORD scaleddelta, + BOOL negative); + void Initialize (DWORD bitspersample); + inline void PredictNextValue (int *last); + +}; + +class CAdpcmDecoder : public CAdpcm { + + public: + DWORD Decompress (short *dest, + const BYTE *source, + DWORD sourcesize, + DWORD channels); + +}; + +class CAdpcmEncoder : public CAdpcm { + + public: + DWORD Compress (LPBYTE dest, + const short *source, + DWORD sourcesize, + DWORD channels, + DWORD bitspersample); + +}; + +//=========================================================================== +void CAdpcm::AdjustValue (int *last, + DWORD *adapt, + DWORD scaleddelta, + BOOL negative) { + + // SAVE THE NEW VALUE, ADJUSTED BY THE SCALED DELTA, AS THE VALUE TO + // BE USED AS THE LAST VALUE FOR THE NEXT ITERATION OF THE LOOP + int quantdiff = (int)((scaleddelta+1)*(*adapt)+m_steps) >> m_bitspersample; + if (negative) { + *last -= quantdiff; + if (*last < -32768) + *last = -32768; + } + else { + *last += quantdiff; + if (*last > 32767) + *last = 32767; + } + + // ADJUST THE ADAPTATION FACTOR + *adapt = ((*adapt)*m_adapttable[scaleddelta]+128) >> 6; + if (*adapt < m_minadapt) + *adapt = m_minadapt; + if (*adapt > m_maxadapt) + *adapt = m_maxadapt; + +} + +//=========================================================================== +void CAdpcm::Initialize (DWORD bitspersample) { + + // SELECT THE ADAPTATION TABLE TO USE + switch (bitspersample) { + case 2: m_adapttable = s_adpcm_2bit; break; + case 3: m_adapttable = s_adpcm_3bit; break; + case 4: m_adapttable = s_adpcm_4bit; break; + case 6: m_adapttable = s_adpcm_6bit; break; + default: m_adapttable = NULL; break; + } + ASSERT(m_adapttable); + + // SAVE THE NUMBER OF BITS PER SAMPLE + m_bitspersample = bitspersample; + + // COMPUTE THE NUMBER OF STEPS IN THE ADAPTATION TABLE, AND THE MINIMUM + // AND MAXIMUM ADAPTATION VALUES + m_steps = (1 << m_bitspersample) / 2; + m_minadapt = 1 << m_bitspersample; + m_maxadapt = 131072; + +} + +//=========================================================================== +void CAdpcm::PredictNextValue (int *last) { + *last = (230*(*last)+128) >> 8; +} + +//=========================================================================== +DWORD CAdpcmDecoder::Decompress (short *dest, + const BYTE *source, + DWORD sourcesize, + DWORD channels) { + const BYTE *basesource = source; + short *basedest = dest; + DWORD loop; + + // READ THE BITRATE AND INITIALIZE ADPCM DECOMPRESSION + Initialize(*source++); + + // READ THE ACCUMULATED ERROR FOR THIS BLOCK FOR EACH CHANNEL + DWORD absaccumerror[2]; + DWORD negaccumerror[2]; + for (loop = 0; loop < channels; ++loop) { + BYTE code = *source++; + absaccumerror[loop] = code >> 1; + negaccumerror[loop] = code & 1; + } + + // READ THE STARTING ADAPTATION VALUE FOR EACH CHANNEL + DWORD adapt[2]; + for (loop = 0; loop < channels; ++loop) { + adapt[loop] = ((DWORD)(*(LPWORD)source)) << m_bitspersample; + source += 2; + } + + // READ THE INITIAL SAMPLE FOR EACH CHANNEL + int last[2]; + for (loop = 0; loop < channels; ++loop) { + last[loop] = *(const short *)source; + source += 2; + *dest++ = (short)last[loop]; + } + + // PROCESS ALL THE COMPRESSED SAMPLES IN THIS BLOCK + DWORD channel = 0; + for (loop = source-basesource; loop < sourcesize; ++loop) { + + // ADJUST THE LAST VALUE BY A CONSTANT SCALING FACTOR + PredictNextValue(&last[channel]); + + // READ THE NEXT COMPRESSED SAMPLE + BYTE code = *source++; + DWORD scaled = code >> 1; + BOOL neg = code & 1; + + // GENERATE THE VALUE OF THE UNCOMPRESSED SAMPLE, AND ADJUST THE + // ADAPTATION VALUE + AdjustValue(&last[channel], + &adapt[channel], + scaled, + neg); + + // IF WE ARE NEARING THE END OF THE BLOCK, ADD IN A LITTLE BIT OF + // THE ERROR TERM INTO EACH SAMPLE, SO THAT THE BLOCK WILL END ON + // EXACTLY THE CORRECT VALUE + int output = last[channel]; + DWORD samplesleft = (sourcesize-(loop+1)) >> (channels-1); + if (samplesleft < absaccumerror[channel]) + if (negaccumerror[channel]) { + output += absaccumerror[channel]-samplesleft; + if (output > 32767) + output = 32767; + } + else { + output -= absaccumerror[channel]-samplesleft; + if (output < -32768) + output = -32768; + } + *dest++ = (short)output; + + // ALTERNATE CHANNELS + if (channels == 2) + channel = !channel; + + } + + return (LPBYTE)dest-(LPBYTE)basedest; +} + +//=========================================================================== +DWORD CAdpcmEncoder::Compress (LPBYTE dest, + const short *source, + DWORD sourcesize, + DWORD channels, + DWORD bitspersample) { + LPBYTE basedest = dest; + DWORD loop; + + // INITIALIZE ADPCM COMPRESSION + Initialize(bitspersample); + + // SAVE THE NUMBER OF BITS PER SAMPLE + *dest++ = (BYTE)bitspersample; + + // RESERVE SPACE FOR THE ACCUMULATED ERROR FOR EACH CHANNEL + LPBYTE accumerrorptr[2]; + for (loop = 0; loop < channels; ++loop) + accumerrorptr[loop] = dest++; + + // COMPUTE AND SAVE THE STARTING ADAPTATION VALUE FOR EACH CHANNEL + DWORD adapt[2]; + for (loop = 0; loop < channels; ++loop) { + int last = source[loop]; + PredictNextValue(&last); + DWORD firstdiff = abs(source[loop+channels]-last) << m_bitspersample; + DWORD bestadapt = firstdiff*2/m_steps; + bestadapt = max(bestadapt,m_minadapt); + bestadapt = min(bestadapt,m_maxadapt); + DWORD savevalue = bestadapt >> m_bitspersample; + *(LPWORD)dest = (WORD)savevalue; + dest += 2; + adapt[loop] = savevalue << m_bitspersample; + } + + // SAVE THE VALUE OF THE FIRST SAMPLE FOR EACH CHANNEL + int last[2]; + for (loop = 0; loop < channels; ++loop) { + last[loop] = *source++; + *(short *)dest = (short)last[loop]; + dest += 2; + } + + // PROCESS EACH OF THE REMAINING SAMPLES + int val[2]; + DWORD channel = 0; + DWORD samples = sourcesize/2; + for (loop = channels; loop < samples; ++loop) { + + // ADJUST THE LAST VALUE BY A CONSTANT SCALING FACTOR + PredictNextValue(&last[channel]); + + // READ THE NEXT SAMPLE + val[channel] = *source++; + DWORD diff = abs(val[channel]-last[channel]); + BOOL neg = last[channel] > val[channel]; + + // PRODUCE A DELTA WHICH IS SCALED BY THE ADAPTATION FACTOR + DWORD unscaled = diff << bitspersample; + DWORD scaled = 0; + if (unscaled > adapt[channel]) + scaled = min((unscaled - (adapt[channel] >> 1)) / adapt[channel], + m_steps-1); + + // PACK THE SCALED NUMBER AND THE SIGN INTO THE DESIRED NUMBER OF BITS + *dest++ = (BYTE)((scaled << 1) | neg); + + // ADJUST THE ADAPTATION FACTOR, AND GENERATE THE VALUE OF THE + // COMPRESSED AND DECOMPRESSED SAMPLE, WHICH WE WILL USE AS THE + // VALUE OF THE LAST SAMPLE IN THE NEXT ITERATION OF THE LOOP + AdjustValue(&last[channel], + &adapt[channel], + scaled, + neg); + + // ALTERNATE CHANNELS + if (channels == 2) + channel = !channel; + + } + + // COMPUTE AND SAVE THE ACCUMULATED ERROR FOR EACH CHANNEL + for (loop = 0; loop < channels; ++loop) { + int accumerror = last[loop]-val[loop]; + DWORD absaccumerror = abs(accumerror); + BOOL negaccumerror = accumerror < 0; + absaccumerror = min(127,absaccumerror); + *accumerrorptr[loop] = (BYTE)(absaccumerror << 1) | negaccumerror; + } + + return dest-basedest; +} + +} // end of namespace + +/**************************************************************************** +* +* PKWARE ENCODER +* +***/ + +typedef struct _PKWAREINFO { + LPVOID dest; + DWORD destpos; + DWORD destsize; + LPCVOID source; + DWORD sourcepos; + DWORD sourcesize; +} PKWAREINFO, *PKWAREINFOPTR; + +//=========================================================================== +static UINT __cdecl PkwareBufferRead (LPSTR buffer, + UINT *size, + LPVOID param) { + PKWAREINFOPTR infoptr = (PKWAREINFOPTR)param; + UINT bytes = min(*size,infoptr->sourcesize-infoptr->sourcepos); + CopyMemory(buffer, + (const BYTE *)infoptr->source+infoptr->sourcepos, + bytes); + infoptr->sourcepos += bytes; + return bytes; +} + +//=========================================================================== +static void __cdecl PkwareBufferWrite (LPSTR buffer, + UINT *size, + LPVOID param) { + PKWAREINFOPTR infoptr = (PKWAREINFOPTR)param; + UINT bytes = min(*size,infoptr->destsize-infoptr->destpos); + CopyMemory((LPBYTE)infoptr->dest+infoptr->destpos, + buffer, + bytes); + infoptr->destpos += bytes; +} + +//=========================================================================== +static void PkwareCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD *hint, + DWORD optimization) { + + // CREATE A COMPRESSION BUFFER + LPSTR implodebuffer = (LPSTR)ALLOC(CMP_BUFFER_SIZE); + + // CREATE AN INFORMATION RECORD + PKWAREINFO info; + info.dest = dest; + info.destpos = 0; + info.destsize = *destsize; + info.source = source; + info.sourcepos = 0; + info.sourcesize = sourcesize; + + // DETERMINE THE SOURCE TYPE + unsigned type = (*hint == SCOMP_HINT_TEXT) + ? CMP_ASCII + : CMP_BINARY; + unsigned dictsize = (sourcesize >= 3072) + ? 4096 + : (sourcesize >= 1536) + ? 2048 + : 1024; + + // PERFORM THE DECOMPRESSION + implode(PkwareBufferRead, + PkwareBufferWrite, + (LPSTR)implodebuffer, + &info, + &type, + &dictsize); + + // FREE THE DECOMPRESSION BUFFER + FREE(implodebuffer); + + *destsize = info.destpos; + *hint = SCOMP_HINT_NONE; +} + +//=========================================================================== +static void PkwareDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize) { + + // CREATE A DECOMPRESSION BUFFER + LPSTR explodebuffer = (LPSTR)ALLOC(EXP_BUFFER_SIZE); + + // CREATE AN INFORMATION RECORD + PKWAREINFO info; + info.dest = dest; + info.destpos = 0; + info.destsize = *destsize; + info.source = source; + info.sourcepos = 0; + info.sourcesize = sourcesize; + + // PERFORM THE DECOMPRESSION + explode(PkwareBufferRead, + PkwareBufferWrite, + (LPSTR)explodebuffer, + &info); + + // FREE THE DECOMPRESSION BUFFER + FREE(explodebuffer); + + *destsize = info.destpos; +} + +/**************************************************************************** +* +* WRAPPER FUNCTIONS +* +***/ + +//=========================================================================== +static void AdpcmMonoCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD *hint, + DWORD optimization) { + CAdpcmEncoder adpcm; + *destsize = adpcm.Compress((LPBYTE)dest, + (const short *)source, + sourcesize, + 1, + (optimization == SCOMP_OPT_COMPRESSION) + ? 4 + : 6); + *hint = (optimization == SCOMP_OPT_COMPRESSION) + ? SCOMP_HINT_ADPCM4 + : SCOMP_HINT_ADPCM6; +} + +//=========================================================================== +static void AdpcmMonoDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize) { + CAdpcmDecoder adpcm; + *destsize = adpcm.Decompress((short *)dest, + (const BYTE *)source, + sourcesize, + 1); +} + +//=========================================================================== +static void AdpcmStereoCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD *hint, + DWORD optimization) { + CAdpcmEncoder adpcm; + *destsize = adpcm.Compress((LPBYTE)dest, + (const short *)source, + sourcesize, + 2, + (optimization == SCOMP_OPT_COMPRESSION) + ? 4 + : 6); + *hint = SCOMP_HINT_ADPCM6; +} + +//=========================================================================== +static void AdpcmStereoDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize) { + CAdpcmDecoder adpcm; + *destsize = adpcm.Decompress((short *)dest, + (const BYTE *)source, + sourcesize, + 2); +} + +//=========================================================================== +static void HuffmanCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD *hint, + DWORD optimization) { + CBitOutput output(dest,*destsize); + CHuffmanEncoder huff; + *destsize = huff.Compress(&output, + source, + sourcesize, + (BYTE)*hint); +} + +//=========================================================================== +static void HuffmanDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize) { + CBitInput input(source,sourcesize); + CHuffmanDecoder huff; + *destsize = huff.Decompress(dest,&input); +} + +/**************************************************************************** +* +* UTILITY FUNCTIONS +* +***/ + +//=========================================================================== +static inline BOOL BuffersOverlap (LPCVOID buf1, + LPCVOID buf2, + DWORD length) { + return (((LPBYTE)buf1+length > (LPBYTE)buf2) && + ((LPBYTE)buf2+length > (LPBYTE)buf1)); +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +#define ALGORITHMS 4 + +typedef void (*COMPRESSFUNC)(LPVOID,DWORD *,LPCVOID,DWORD,DWORD *,DWORD); +typedef void (*DECOMPRESSFUNC)(LPVOID,DWORD *,LPCVOID,DWORD); + +typedef struct _COMPRESSALGORITHM { + DWORD id; + COMPRESSFUNC func; +} COMPRESSALGORITHM; + +typedef struct _DECOMPRESSALGORITHM { + DWORD id; + DECOMPRESSFUNC func; +} DECOMPRESSALGORITHM; + +static const COMPRESSALGORITHM s_compressalgorithm[ALGORITHMS] = + {{SCOMP_TYPE_LOSSY_ADPCM_MONO ,AdpcmMonoCompress}, + {SCOMP_TYPE_LOSSY_ADPCM_STEREO,AdpcmStereoCompress}, + {SCOMP_TYPE_HUFFMAN ,HuffmanCompress}, + {SCOMP_TYPE_PKWARE ,PkwareCompress}}; +static const DECOMPRESSALGORITHM s_decompressalgorithm[ALGORITHMS] = + {{SCOMP_TYPE_LOSSY_ADPCM_MONO ,AdpcmMonoDecompress}, + {SCOMP_TYPE_LOSSY_ADPCM_STEREO,AdpcmStereoDecompress}, + {SCOMP_TYPE_HUFFMAN ,HuffmanDecompress}, + {SCOMP_TYPE_PKWARE ,PkwareDecompress}}; + +//=========================================================================== +BOOL APIENTRY SCompCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD compressiontypes, + DWORD hint, + DWORD optimization) { + VALIDATEBEGIN; + VALIDATE(dest); + VALIDATE(destsize); + VALIDATE(*destsize >= sourcesize); + VALIDATE(source); + VALIDATEEND; + + // COUNT THE NUMBER OF OPERATIONS + DWORD operations = 0; + int loop; + for (loop = 0; loop < ALGORITHMS; ++loop) + if (compressiontypes & s_compressalgorithm[loop].id) + ++operations; + + // ALLOCATE A WORK BUFFER IF NECESSARY + LPVOID work = NULL; + if ((operations >= 2) || + (BuffersOverlap(dest,source,sourcesize) && operations)) + work = ALLOC(sourcesize); + + // APPLY EACH OPERATION + LPCVOID curr = source; + DWORD size = sourcesize; + for (loop = 0; loop < ALGORITHMS; ++loop) + if (compressiontypes & s_compressalgorithm[loop].id) { + --operations; + + // DETERMINE WHICH BUFFER WE WILL COMPRESS INTO FOR THIS OPERATION + LPVOID target = (operations & 1) ? work : ((LPBYTE)dest+1); + if (BuffersOverlap(target,curr,size)) + target = BuffersOverlap(target,work,size) ? ((LPBYTE)dest+1) : work; + + // PERFORM THE COMPRESSION OPERATION + DWORD targetsize = size-1; + s_compressalgorithm[loop].func(target, + &targetsize, + curr, + size, + &hint, + optimization); + + // IF THE OPERATION FAILED TO COMPRESS THE DATA, THEN DISCARD THE + // RESULT + if (targetsize+1 < size) { + curr = target; + size = targetsize; + } + else + compressiontypes &= ~s_compressalgorithm[loop].id; + + } + + // COPY THE FINAL RESULT TO THE DESTINATION BUFFER IF NECESSARY, AND + // SAVE THE COMPRESSION TYPES USED + if (curr != dest) + if (curr == (LPBYTE)dest+1) { + *(LPBYTE)dest = (BYTE)compressiontypes; + ++size; + } + else if (compressiontypes) { + CopyMemory((LPBYTE)dest+1,curr,size); + *(LPBYTE)dest = (BYTE)compressiontypes; + ++size; + } + else + CopyMemory(dest,curr,size); + *destsize = size; + + // FREE THE WORK BUFFER + FREEIFUSED(work); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SCompDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize) { + VALIDATEBEGIN; + VALIDATE(dest); + VALIDATE(destsize); + VALIDATE(*destsize >= sourcesize); + VALIDATE(source); + VALIDATEEND; + + // IF THE DATA IS NOT COMPRESSED, JUST COPY IT TO THE DESTINATION BUFFER + // AND RETURN + if (sourcesize == *destsize) { + if (dest != source) + CopyMemory(dest,source,sourcesize); + return TRUE; + } + + // EXTRACT THE COMPRESSION TYPES + DWORD compressiontypes = *(LPBYTE)source; + source = (LPBYTE)source+1; + --sourcesize; + + // COUNT THE NUMBER OF OPERATIONS + DWORD operations = 0; + int loop; + for (loop = ALGORITHMS-1; loop >= 0; --loop) + if (compressiontypes & s_decompressalgorithm[loop].id) + ++operations; + + // ALLOCATE A WORK BUFFER IF NECESSARY + LPVOID work = NULL; + if ((operations >= 2) || + (BuffersOverlap(dest,source,sourcesize) && operations)) + work = ALLOC(*destsize); + + // APPLY EACH OPERATION + LPCVOID curr = source; + DWORD size = sourcesize; + for (loop = ALGORITHMS-1; loop >= 0; --loop) + if (compressiontypes & s_decompressalgorithm[loop].id) { + --operations; + + // DETERMINE WHICH BUFFER WE WILL DECOMPRESS INTO FOR THIS OPERATION + LPVOID target = (operations & 1) ? work : dest; + if (BuffersOverlap(target,curr,size)) + target = BuffersOverlap(target,work,size) ? dest : work; + + // PERFORM THE DECOMPRESSION OPERATION + DWORD targetsize = *destsize; + s_decompressalgorithm[loop].func(target, + &targetsize, + curr, + size); + curr = target; + size = targetsize; + + } + + // COPY THE FINAL RESULT TO THE DESTINATION BUFFER IF NECESSARY + if (curr != dest) + CopyMemory(dest,curr,size); + *destsize = size; + + // FREE THE WORK BUFFER + FREEIFUSED(work); + + return TRUE; +} diff --git a/src/Storm/SOURCE/SDLG.CPP b/src/Storm/SOURCE/SDLG.CPP new file mode 100644 index 0000000..74273e4 --- /dev/null +++ b/src/Storm/SOURCE/SDLG.CPP @@ -0,0 +1,2249 @@ +/**************************************************************************** +* +* SDLG.CPP +* Storm dialog box functions +* +* By Michael O'Brien (5/22/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define ANYBITMAP 0x0000FFFF +#define CONTROLTYPELENGTH 32 + +#define BLT_FLAG_TILED 0x00000001 +#define BLT_FLAG_LOCKSURFACE 0x00000002 +#define BLT_FLAG_DESTRECTCLIENTCOORDS 0x00000100 +#define BLT_FLAG_HIDECURSOR 0x00001000 +#define BLT_FLAG_RESTORECURSOR 0x00002000 + +#define CONVDLGX(x) (((x)*baseunitx)/4) +#define CONVDLGY(y) (((y)*baseunity)/8) + +#define NOTIFY(window,code) SendMessage(GetParent(window), \ + WM_COMMAND, \ + MAKELONG(GetDlgCtrlID(window),code), \ + (LPARAM)window) + +typedef struct _BASEFONT { + int pointsize; + int weight; + DWORD flags; + DWORD family; + char face[32]; +} BASEFONT, *BASEFONTPTR; + +NODEDECL(BITMAPREC) { + HWND window; + HWND parentwindow; + DWORD usage; + DWORD controlstyle; + LPBYTE bitmapbits; + RECT rect; + int width; + int height; + int offsetx; + int offsety; + char controltype[CONTROLTYPELENGTH]; +} *BITMAPPTR; + +NODEDECL(TIMERREC) { + HWND window; + UINT id; + DWORD elapse; + TIMERPROC callback; + DWORD lasttime; +} *TIMERPTR; + +static BASEFONTPTR s_basefont = NULL; +static LIST(BITMAPREC) s_bitmaplist; +static BOOL s_cursorhidden = FALSE; +static LPBYTE s_cursorimage = NULL; +static LPBYTE s_cursormask = NULL; +static POINT s_cursorpos = {-1,-1}; +static SIZE s_cursorsize = {32,32}; +static BOOL s_initialized = FALSE; +static int s_inpaint = 0; +static BOOL s_nodefproc = FALSE; +static LIST(TIMERREC) s_timerlist; + +static BOOL DrawButton (LPDRAWITEMSTRUCT item); +static BITMAPPTR FindBitmap (HWND window, DWORD usage); +static void IntersectRgnWithWindow (HWND updatewindow, + HRGN region, + HWND window); +static BOOL IsButton (HWND window, BOOL *ownerdraw); +static BOOL IsPointInWindow (LPPOINTS point, HWND window); +static void ParseDlgTemplate (LPCDLGTEMPLATE templatedata, + LPDLGTEMPLATE parsedtemplate, + LPCWSTR *title, + short *fontsize, + short *fontweight, + short *fontitalics, + LPCWSTR *fontname, + LPDLGITEMTEMPLATE *firstitem); +static void ParseDlgTemplateEx (LPCDLGTEMPLATE templatedata, + LPDLGTEMPLATE parsedtemplate, + LPCWSTR *title, + short *fontsize, + short *fontweight, + short *fontitalics, + LPCWSTR *fontname, + LPDLGITEMTEMPLATE *firstitem); +static LRESULT SendMessageNoDefProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); + +//=========================================================================== +static void AdjustCursorPos (HWND window, int x, int y) { + if (window) { + DWORD processid; + GetWindowThreadProcessId(window,&processid); + if (processid == GetCurrentProcessId()) { + RECT cursorrect = {x,y,x+s_cursorsize.cx,y+s_cursorsize.cy}; + RECT windowrect; GetWindowRect(window,&windowrect); + RECT rect; + if (IntersectRect(&rect,&cursorrect,&windowrect)) { + ScreenToClient(window,(LPPOINT)&rect.left); + ScreenToClient(window,(LPPOINT)&rect.right); + InvalidateRect(window,&rect,0); + } + } + window = GetTopWindow(window); + while (window) { + AdjustCursorPos(window,x,y); + window = GetNextWindow(window,GW_HWNDNEXT); + } + } + else { + AdjustCursorPos(GetDesktopWindow(),s_cursorpos.x,s_cursorpos.y); + s_cursorpos.x = x; + s_cursorpos.y = y; + AdjustCursorPos(GetDesktopWindow(),s_cursorpos.x,s_cursorpos.y); + } +} + +//=========================================================================== +static void CheckCursorPos () { + POINT pt; + GetCursorPos(&pt); + if ((s_cursorpos.x >= 0) && + (s_cursorpos.y >= 0) && + ((pt.x != s_cursorpos.x) || + (pt.y != s_cursorpos.y))) + AdjustCursorPos((HWND)0,pt.x,pt.y); +} + +//=========================================================================== +static void ComputeBaseUnits (HFONT font, int *baseunitx, int *baseunity) { + HDC screendc = GetDC(GetDesktopWindow()); + HDC memdc = CreateCompatibleDC(screendc); + HFONT oldfont = (HFONT)SelectObject(memdc,font); + + // USE GETTEXTEXTENT() TO DETERMINE THE AVERAGE CHARACTER WIDTH + SIZE size; + if (GetTextExtentPoint32(memdc, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz", + 52, + &size)) + *baseunitx = (size.cx/26+1)/2; + + // USE GETTEXTMETRICS() TO DETERMINE THE CHARACTER HEIGHT + TEXTMETRIC tm; + if (GetTextMetrics(memdc,&tm)) + *baseunity = tm.tmHeight; + + SelectObject(memdc,oldfont); + DeleteDC(memdc); + ReleaseDC(GetDesktopWindow(),screendc); +} + +//=========================================================================== +static LRESULT CALLBACK ControlSubclassWndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + LONG origstyle = 0; + + // PERFORM INTERNAL PROCESSING ON SOME MESSAGES + switch (message) { + + case BM_SETCHECK: + if (wparam == BST_CHECKED) + break; + // fall through to BM_SETSTATE + + case BM_SETSTATE: + case WM_PAINT: + if (IsButton(window,NULL)) { + DWORD style = GetWindowLong(window,GWL_STYLE); + if (((style & 0x0000000F) == BS_RADIOBUTTON) || + ((style & 0x0000000F) == BS_AUTORADIOBUTTON)) { + origstyle = GetWindowLong(window,GWL_STYLE); + SetWindowLong(window,GWL_STYLE,(origstyle & 0xFFFFFFF0) | BS_OWNERDRAW); + } + } + break; + + case WM_ERASEBKGND: + if ((GetWindowLong(window,GWL_EXSTYLE) & WS_EX_TRANSPARENT) || + FindBitmap(window,ANYBITMAP)) + return 0; + break; + + case WM_KEYUP: + if (wparam == VK_SNAPSHOT) { + SDrawCaptureScreen(); + SetFocus(window); + } + break; + + case WM_NCDESTROY: + RemoveProp(window,"SDlg_WndProc"); + if (GetProp(window,"SDlg_OrigStyle")) + RemoveProp(window,"SDlg_OrigStyle"); + break; + + case WM_STYLECHANGED: + case WM_STYLECHANGING: + return 0; + + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + SendMessage(GetParent(window),message,wparam,lparam); + break; + + } + + // CALL THE ORIGINAL WINDOW PROCEDURE + LRESULT result; + { + WNDPROC wndproc = NULL; + if (message != WM_NCDESTROY) + wndproc = (WNDPROC)GetProp(window,"SDlg_WndProc"); + if (wndproc) + result = CallWindowProc(wndproc,window,message,wparam,lparam); + else + result = DefWindowProc(window,message,wparam,lparam); + } + + if (origstyle) + SetWindowLong(window,GWL_STYLE,origstyle); + return result; +} + +//=========================================================================== +static LRESULT CALLBACK ControlStaticWndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_DESTROY: + RemoveProp(window,"SDlg_Font"); + break; + + case WM_ERASEBKGND: + if ((GetWindowLong(window,GWL_EXSTYLE) & WS_EX_TRANSPARENT) || + FindBitmap(window,ANYBITMAP)) + return 0; + break; + + case WM_GETFONT: + return (LRESULT)GetProp(window,"SDlg_Font"); + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC dc = SDlgBeginPaint(window,&ps); + + // SELECT THE FONT + SelectObject(dc,(HFONT)GetProp(window,"SDlg_Font")); + SetBkMode(dc,TRANSPARENT); + + // SEND A WM_DRAWITEM MESSAGE, IN CASE THE APPLICATION WANTS TO + // DRAW THE TEXT MANUALLY + BOOL drawn = 0; + { + DRAWITEMSTRUCT drawitem; + ZeroMemory(&drawitem,sizeof(DRAWITEMSTRUCT)); + drawitem.CtlType = ODT_STATIC; + drawitem.CtlID = GetDlgCtrlID(window); + drawitem.itemAction = ODA_DRAWENTIRE; + drawitem.hwndItem = window; + drawitem.hDC = dc; + GetClientRect(window,&drawitem.rcItem); + drawn = (BOOL)SendMessageNoDefProc(GetParent(window), + WM_DRAWITEM, + GetDlgCtrlID(window), + (LPARAM)&drawitem); + } + + // IF THE APPLICATION DIDN'T DRAW THE TEXT, DO IT OURSELF + if (!drawn) { + int chars = GetWindowTextLength(window); + char *text = (char *)ALLOC(chars+1); + GetWindowText(window,text,chars+1); + + // DETERMINE THE FORMAT + DWORD format = DT_EXPANDTABS | DT_WORDBREAK; + { + DWORD style = (DWORD)GetWindowLong(window,GWL_STYLE); + if (style & SS_LEFT) + format |= DT_LEFT; + else if (style & SS_CENTER) + format |= DT_CENTER; + else if (style & SS_RIGHT) + format |= DT_RIGHT; + } + + // DRAW THE DROP SHADOW + { + RECT rect; + GetClientRect(window,&rect); + ++rect.left; + ++rect.top; + SetTextColor(dc,0); + DrawText(dc,text,chars,&rect,format); + } + + // DRAW THE TEXT + { + RECT rect; + GetClientRect(window,&rect); + --rect.right; + --rect.bottom; + SetTextColor(dc,0xFFFFFF); + SendMessage(GetParent(window),WM_CTLCOLORSTATIC,(WPARAM)dc,(LPARAM)window); + DrawText(dc,text,chars,&rect,format); + } + + FREE(text); + } + + SDlgEndPaint(window,&ps); + } + return 0; + + case WM_SETFONT: + SetProp(window,"SDlg_Font",(HANDLE)wparam); + if (lparam & 1) + InvalidateRect(window,NULL,1); + break; + + case WM_SETTEXT: + InvalidateRect(window,NULL,1); + break; + + } + return DefWindowProc(window,message,wparam,lparam); +} + +//=========================================================================== +static void DeleteBitmaps (HWND window) { + + // DELETE ALL BITMAPS ASSOCIATED WITH THIS WINDOW + ITERATELIST(BITMAPREC,s_bitmaplist,curr) + if ((curr->window == window) || + (curr->parentwindow == window)) + ITERATE_DELETE; + + // RECURSE ALL CHILD WINDOWS + if ((window = GetTopWindow(window)) != (HWND)0) + do + DeleteBitmaps(window); + while ((window = GetNextWindow(window,GW_HWNDNEXT)) != (HWND)0); + +} + +//=========================================================================== +static BOOL CALLBACK DlgProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + // PERFORM INTERNAL PROCESSING ON SOME MESSAGES + switch (message) { + + case WM_CREATE: + SetCursor(LoadCursor(0,IDC_ARROW)); + break; + + case WM_DESTROY: + RemoveProp(window,"SDlg_Font"); + DeleteBitmaps(window); + break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT item = (LPDRAWITEMSTRUCT)lparam; + if (item->CtlType == ODT_BUTTON) + return DrawButton(item); + } + break; + + case WM_ERASEBKGND: + if ((GetWindowLong(window,GWL_EXSTYLE) & WS_EX_TRANSPARENT) || + FindBitmap(window,ANYBITMAP)) + return 0; + break; + + case WM_GETFONT: + return (LRESULT)GetProp(window,"SDlg_Font"); + + case WM_NCDESTROY: + { + HDC dc = GetDC(window); + SelectObject(dc,GetStockObject(SYSTEM_FONT)); + ReleaseDC(window,dc); + } + DeleteObject((HFONT)SendMessage(window,WM_GETFONT,0,0)); + break; + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC dc = SDlgBeginPaint(window,&ps); + SDlgEndPaint(window,&ps); + } + if ((GetProp(window,"SDlg_Modal")) && + IsWindowEnabled(GetParent(window))) { + EnableWindow(GetParent(window),0); + if (GetActiveWindow() == GetParent(window)) + SetActiveWindow(window); + } + return 0; + + case WM_SETFONT: + SetProp(window,"SDlg_Font",(HANDLE)wparam); + break; + + case WM_SHOWWINDOW: + if ((!wparam) && + ((!lparam) || + (lparam == SW_PARENTCLOSING)) && + (GetProp(window,"SDlg_Modal"))) + EnableWindow(GetParent(window),1); + break; + + } + + // CALL THE DEFAULT DIALOG BOX PROCEDURE, WHICH WILL CALL THE + // APPLICATION'S DIALOG BOX PROCEDURE + BOOL result; + if (s_nodefproc) { + s_nodefproc = 0; + result = CallWindowProc((WNDPROC)GetWindowLong(window,DWL_DLGPROC),window,message,wparam,lparam); + } + else + result = DefDlgProc(window,message,wparam,lparam); + + // ON A WM_NCCREATE MESSAGE, SET THE POINTER TO THE APPLICATION'S + // DIALOG BOX PROCEDURE + if (message == WM_NCCREATE) + SetWindowLong(window,DWL_DLGPROC,(LONG)((LPCREATESTRUCT)lparam)->lpCreateParams); + + return result; +} + +//=========================================================================== +static BOOL DoMessageLoop (HWND dialogwindow) { + MSG message; + if (PeekMessage(&message,(HWND)0,0,0,PM_REMOVE)) { + if (message.message == WM_QUIT) + PostQuitMessage(message.wParam); + else if ((!dialogwindow) || + (!IsDialogMessage(dialogwindow,&message))) { + TranslateMessage(&message); + DispatchMessage(&message); + } + return TRUE; + } + else { + SDlgCheckTimers(); + SDlgUpdateCursor(); + return FALSE; + } +} + +//=========================================================================== +static BOOL DrawButton (LPDRAWITEMSTRUCT item) { + RECT clientrect; GetClientRect(item->hwndItem,&clientrect); + HDC dc = GetDC(item->hwndItem); + BOOL selected = ((item->itemState & ODS_SELECTED) != 0); + if (SendMessage(item->hwndItem,BM_GETSTATE,0,0) & BST_CHECKED) + selected = TRUE; + BOOL grayed = ((item->itemState & (ODS_DISABLED | ODS_GRAYED)) != 0); + DWORD style = (DWORD)GetWindowLong(item->hwndItem,GWL_STYLE); + if (GetProp(item->hwndItem,"SDlg_OrigStyle")) + style = (DWORD)GetProp(item->hwndItem,"SDlg_OrigStyle"); + BOOL pushbutton = ((style & 0x0000000F) == BS_PUSHBUTTON) || + ((style & 0x0000000F) == BS_DEFPUSHBUTTON) || + ((style & 0x0000000F) == BS_OWNERDRAW); + + // DETERMINE THE BOUNDING OFFSET + RECT boundingoffset = {0,0,0,0}; + if (!pushbutton) { + boundingoffset.left = 1; + boundingoffset.bottom = -1; + } + + // IF A BITMAP HAS BEEN REGISTERED SPECIFICALLY FOR THIS ITEM STATE, + // DRAW THAT + DWORD usage = selected + ? grayed + ? SDLG_USAGE_SELECTED_GRAYED + : (item->itemState & ODS_FOCUS) + ? SDLG_USAGE_SELECTED_FOCUSED + : SDLG_USAGE_SELECTED_UNFOCUSED + : grayed + ? SDLG_USAGE_NORMAL_GRAYED + : (item->itemState & ODS_FOCUS) + ? SDLG_USAGE_NORMAL_FOCUSED + : SDLG_USAGE_NORMAL_UNFOCUSED; + BITMAPPTR bitmap = FindBitmap(item->hwndItem,usage); + if (bitmap) + SDlgDrawBitmap(item->hwndItem, + usage, + (HRGN)0, + 0, + 0, + &boundingoffset, + pushbutton ? (SDLG_DBF_TILE | SDLG_DBF_VCENTER) : 0); + + // OTHERWISE, ERASE THE BACKGROUND AND DRAW A BEVEL AROUND IT + else { + SDlgDrawBitmap(item->hwndItem, + SDLG_USAGE_BACKGROUND, + (HRGN)0, + 1-selected, + 1-selected, + &boundingoffset, + pushbutton ? (SDLG_DBF_TILE | SDLG_DBF_VCENTER) : 0); + if (pushbutton) { + UINT edge = selected ? (BDR_SUNKENINNER | BDR_SUNKENOUTER) + : (BDR_RAISEDOUTER | BDR_RAISEDOUTER); + DrawEdge(dc,&clientrect,edge,BF_RECT); + } + } + + // DRAW THE TEXT + { + + // GET THE TEXT + int chars = GetWindowTextLength(item->hwndItem); + char *text = (char *)ALLOC(chars+1); + GetWindowText(item->hwndItem,text,chars+1); + + // SELECT THE FONT + SelectObject(dc,GetCurrentObject(item->hDC,OBJ_FONT)); + SetTextAlign(dc,TA_TOP | TA_LEFT); + SetBkMode(dc,TRANSPARENT); + + // DETERMINE THE TEXT LOCATION + RECT rect = {clientrect.left +3, + clientrect.top +3, + clientrect.right -1, + clientrect.bottom-1}; + if (pushbutton) { + DWORD style = (DWORD)GetWindowLong(item->hwndItem,GWL_STYLE); + SIZE size = {16,16}; + GetTextExtentPoint32(dc,"~,_Oy",5,&size); + if (style & BS_BOTTOM) + rect.top += rect.bottom-(size.cy+6); + else if ((style & BS_VCENTER) || !(style & BS_TOP)) + rect.top += (rect.bottom-(rect.top+size.cy))/2+1; + if (selected) { + ++rect.left; + ++rect.top; + ++rect.right; + ++rect.bottom; + } + } + else if (bitmap) { + rect.top -= 1; + rect.left += 6+bitmap->rect.right-bitmap->rect.left; + } + + // DRAW THE DROP SHADOW + SetTextColor(dc,0); + DrawText(dc,text,chars,&rect, + (pushbutton ? DT_CENTER : DT_LEFT) | DT_TOP); + + // DRAW THE TEXT + --rect.left; + --rect.top; + --rect.right; + --rect.bottom; + SetTextColor(dc,grayed ? 0x808080 : 0xFFFFFF); + DrawText(dc,text,chars,&rect, + (pushbutton ? DT_CENTER : DT_LEFT) | DT_TOP); + + FREE(text); + } + + // IF THIS IS A PUSHBUTTON, DRAW THE FOCUS RECTANGLE + if (pushbutton && + (item->itemState & ODS_FOCUS) && + !FindBitmap(item->hwndItem,SDLG_USAGE_NORMAL_FOCUSED | SDLG_USAGE_SELECTED_FOCUSED)) { + RECT rect = {clientrect.left +selected+4, + clientrect.top +selected+4, + clientrect.right +selected-3, + clientrect.bottom+selected-3}; + DrawFocusRect(dc,&rect); + } + + ReleaseDC(item->hwndItem,dc); + return TRUE; +} + +//=========================================================================== +static BITMAPPTR FindBitmap (HWND window, DWORD usage) { + + // FIND THE BITMAP FOR THIS WINDOW + BITMAPPTR curr = s_bitmaplist.Head(); + while (curr && + ((curr->window != window) || + (!(curr->usage & usage)))) + curr = curr->Next(); + + // IF THIS WINDOW DOESN'T HAVE ITS OWN BITMAP, FIND THE DEFAULT + // BITMAP FOR THIS CONTROL TYPE AND STYLE + if (!curr) { + HWND parentwindow = GetParent(window); + char classname[256] = ""; + GetClassName(window,classname,256); + LPCTSTR classnameptr = classname; + if (!_strnicmp(classnameptr,"SDlg",4)) + classnameptr += 4; + DWORD style = (DWORD)GetWindowLong(window,GWL_STYLE); + if (GetProp(window,"SDlg_OrigStyle")) + style = (DWORD)GetProp(window,"SDlg_OrigStyle"); + curr = s_bitmaplist.Head(); + while (curr && + (curr->window || + (curr->parentwindow && (curr->parentwindow != parentwindow)) || + (!(usage & curr->usage)) || + ((style & 0x0000000F) & ~curr->controlstyle) || + ((!(curr->controlstyle & 0x00010000)) && + ((style & curr->controlstyle) != curr->controlstyle)) || + _stricmp(curr->controltype,classnameptr))) + curr = curr->Next(); + } + + return curr; +} + +//=========================================================================== +static LPCDLGTEMPLATE GetTemplateData (HINSTANCE instance, + LPCTSTR templatename) { + HRSRC resourcehandle = FindResource(instance,templatename,RT_DIALOG); + if (!resourcehandle) + return NULL; + HGLOBAL resourcedata = LoadResource(instance,resourcehandle); + if (!resourcedata) + return NULL; + return (LPCDLGTEMPLATE)LockResource(resourcedata); +} + +//=========================================================================== +static BOOL InitializeDialogManager () { + s_initialized = TRUE; + + // REGISTER OUR OWN DIALOG BOX CLASS + { + WNDCLASS wndclass; + ZeroMemory(&wndclass,sizeof(WNDCLASS)); + wndclass.style = CS_DBLCLKS; + wndclass.lpfnWndProc = (WNDPROC)DlgProc; + wndclass.cbWndExtra = DLGWINDOWEXTRA; + wndclass.hInstance = (HINSTANCE)GetModuleHandle(NULL); + wndclass.hCursor = LoadCursor(0,IDC_ARROW); + wndclass.lpszClassName = "SDlgDialog"; + if (!RegisterClass(&wndclass)) + return FALSE; + } + + // REGISTER OUR OWN STATIC CONTROL CLASS + { + WNDCLASS wndclass; + ZeroMemory(&wndclass,sizeof(WNDCLASS)); + GetClassInfo((HINSTANCE)GetModuleHandle(NULL),"Static",&wndclass); + wndclass.lpfnWndProc = (WNDPROC)ControlStaticWndProc; + wndclass.hInstance = (HINSTANCE)GetModuleHandle(NULL); + wndclass.hCursor = LoadCursor(0,IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); + wndclass.lpszClassName = "SDlgStatic"; + if (!RegisterClass(&wndclass)) + return FALSE; + } + + return TRUE; +} + +//=========================================================================== +static BOOL InternalBltClippedToRgn (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3, + LPPOINT clientpos, + HRGN region, + DWORD flags, + int surfacenumber, + int *cursorhidden) { + + // RETRIEVE A LIST OF RECTANGLES THAT MAKE UP THE CLIPPING REGION + LPRGNDATA data; + DWORD numrects; + LPRECT rectarray; + { + DWORD bytes = GetRegionData(region,0,NULL); + data = (LPRGNDATA)ALLOC(bytes); + GetRegionData(region,bytes,data); + numrects = data->rdh.nCount; + rectarray = (LPRECT)&data->Buffer[0]; + } + + // VERIFY THAT WE HAVE AT LEAST ONE RECTANGLE TO DRAW + if (!(numrects && rectarray)) { + if (data) + FREE(data); + return TRUE; + } + + // MODIFY THE RECTANGLES SO THAT THEY ARE IN SCREEN COORDINATES, THEN CLIP + // THEM AGAINST THE BOUNDING RECTANGLE. + { + for (DWORD loop = 0; loop < numrects; ++loop) { + (rectarray+loop)->left = max(destrect->left ,(rectarray+loop)->left +clientpos->x); + (rectarray+loop)->top = max(destrect->top ,(rectarray+loop)->top +clientpos->y); + (rectarray+loop)->right = min(destrect->right ,(rectarray+loop)->right +clientpos->x); + (rectarray+loop)->bottom = min(destrect->bottom,(rectarray+loop)->bottom+clientpos->y); + } + } + + // IF THE SYSTEM CURSOR IS VISIBLE AND IS WITHIN ONE OF THE RECTANGLES, + // AND WE ARE PROTECTING IT, THEN HIDE IT + int hidden = 0; + if (flags & BLT_FLAG_HIDECURSOR) { + POINT cursor; + GetCursorPos(&cursor); + for (DWORD loop = 0; loop < numrects; ++loop) + if ((cursor.x+32 >= (rectarray+loop)->left) && + (cursor.y+32 >= (rectarray+loop)->top) && + (cursor.x-32 <= (rectarray+loop)->right) && + (cursor.y-32 <= (rectarray+loop)->bottom)) { + do + ++hidden; + while (ShowCursor(0) >= 0); + break; + } + GdiFlush(); + } + + // IF NECESSARY, LOCK THE SURFACE + if (flags & BLT_FLAG_LOCKSURFACE) + SDrawLockSurface(surfacenumber,NULL,&dest,&destpitch); + + // PAINT THE REGION WITH THE SELECTED BITMAP, TILING IT IF NECESSARY + if (dest && destpitch) { + for (DWORD loop = 0; loop < numrects; ++loop) { + if (flags & BLT_FLAG_TILED) + SBltROP3Tiled(dest, + rectarray+loop, + destpitch, + source, + sourcerect, + sourcepitch, + (rectarray+loop)->left+sourceoffsetx-clientpos->x, + (rectarray+loop)->top +sourceoffsety-clientpos->y, + pattern, + rop3); + else { + RECT offsetsourcerect = {sourcerect->left, + sourcerect->top, + sourcerect->right, + sourcerect->bottom}; + offsetsourcerect.left += (rectarray+loop)->left+sourceoffsetx-destrect->left; + offsetsourcerect.top += (rectarray+loop)->top +sourceoffsety-destrect->top; + SBltROP3Clipped(dest, + rectarray+loop, + NULL, + destpitch, + source, + &offsetsourcerect, + sourcesize, + sourcepitch, + pattern, + rop3); + } + } + } + + // IF NECESSARY, UNLOCK THE SURFACE + if (flags & BLT_FLAG_LOCKSURFACE) + SDrawUnlockSurface(surfacenumber,dest,numrects,rectarray); + + // IF WE HID THE CURSOR, UNHIDE IT + if (flags & BLT_FLAG_RESTORECURSOR) + if (hidden) + do + ShowCursor(1); + while (--hidden); + if (cursorhidden) + *cursorhidden += hidden; + + // FREE THE LIST OF RECTANGLES + FREE(data); + + return TRUE; +} + +//=========================================================================== +static BOOL InternalBltClippedToWindow (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3, + HWND window, + HRGN region, + DWORD flags, + int surfacenumber, + int *cursorhidden) { + if (cursorhidden) + *cursorhidden = 0; + + VALIDATEBEGIN; + VALIDATE(destrect); + VALIDATE(window); + VALIDATEEND; + + if (!((flags & BLT_FLAG_LOCKSURFACE) || (dest && (destpitch > 0)))) + return FALSE; + + // INTERSECT THE DESTINATION RECTANGLE WITH THE DESTINATION SIZE + RECT moddestrect = {destrect->left,destrect->top,destrect->right,destrect->bottom}; + if (destsize) { + if ((moddestrect.right-moddestrect.left) > destsize->cx) + moddestrect.right = moddestrect.left+destsize->cx; + if ((moddestrect.bottom-moddestrect.top) > destsize->cy) + moddestrect.bottom = sourcerect->bottom+destsize->cy; + } + + // IF WE'RE NOT TILING, INTERSECT THE DESTINATION RECTANGLE WITH THE + // SOURCE SIZE + if (sourcerect && !(flags & BLT_FLAG_TILED)) { + if ((moddestrect.right-moddestrect.left) > (sourcerect->right-sourcerect->left)) + moddestrect.right = sourcerect->right+moddestrect.left-sourcerect->left; + if ((moddestrect.bottom-moddestrect.top) > (sourcerect->bottom-sourcerect->top)) + moddestrect.bottom = sourcerect->bottom+moddestrect.top-sourcerect->top; + } + + // GET THE TARGET WINDOW'S CLIENT RECTANGLE, IN SCREEN COORDINATES + RECT boundingrect; + GetClientRect(window,&boundingrect); + ClientToScreen(window,(LPPOINT)&boundingrect.left); + ClientToScreen(window,(LPPOINT)&boundingrect.right); + POINT clientpos = {boundingrect.left,boundingrect.top}; + + // IF NECESSARY, CONVERT THE DESTINATION RECTANGLE TO SCREEN COORDINATES + if (flags & BLT_FLAG_DESTRECTCLIENTCOORDS) { + moddestrect.left += clientpos.x; + moddestrect.top += clientpos.y; + moddestrect.right += clientpos.x; + moddestrect.bottom += clientpos.y; + } + + // INTERSECT THE CLIENT RECTANGLE WITH THE DESTINATION RECTANGLE + { + RECT intersectrect = {moddestrect.left, + moddestrect.top, + moddestrect.right, + moddestrect.bottom}; + IntersectRect(&boundingrect,&boundingrect,&intersectrect); + } + + // IF THE RESULTING RECTANGLE IS COMPLETELY CLIPPED OUT, RETURN WITHOUT + // ATTEMPTING TO DRAW + if ((boundingrect.right <= boundingrect.left) || + (boundingrect.bottom <= boundingrect.top)) + return 1; + + // CREATE A CLIPPING REGION THAT INITIALLY CONTAINS THE INTERSECTION OF + // THE REGION WE WERE PASSED (IF ANY) WITH THE CLIENT AREA OF THIS WINDOW + HRGN clipregion; + { + RECT clientrect; + GetClientRect(window,&clientrect); + clipregion = CreateRectRgn(clientrect.left, + clientrect.top, + clientrect.right, + clientrect.bottom); + if (!clipregion) + return FALSE; + if (region) + CombineRgn(clipregion,clipregion,region,RGN_AND); + } + + // REMOVE FROM THE CLIPPING REGION THOSE PORTIONS OF THE WINDOW COVERED BY + // OTHER OVERLAPPING, NON-TRANSPARENT WINDOWS + { + IntersectRgnWithWindow(window,clipregion,window); + HWND startwindow = window; + do { + HWND sibling = startwindow; + while ((sibling = GetNextWindow(sibling,GW_HWNDPREV)) != (HWND)0) + IntersectRgnWithWindow(window,clipregion,sibling); + if (GetWindowLong(startwindow,GWL_STYLE) & WS_CHILD) + startwindow = GetParent(startwindow); + else + startwindow = (HWND)0; + } while (startwindow && (startwindow != GetDesktopWindow())); + } + + // DETERMINE WHETHER WE'RE DISPLAYING A CUSTOM CURSOR + BOOL customcursor = (s_cursormask && s_cursorimage && + (s_cursorpos.x >= 0) && (s_cursorpos.y >= 0)); + + // SPLIT THE CLIPPING REGION INTO TWO DIFFERENT REGIONS: ONE THAT CONTAINS + // ONLY THE PORTION OF THE REGION WHICH IS COVERED BY THE CURSOR, AND ONE + // THAT CONTAINS EVERYTHING THAT IS NOT COVERED BY THE CURSOR + HRGN cursorregion; + if (customcursor) { + cursorregion = CreateRectRgn(s_cursorpos.x-clientpos.x, + s_cursorpos.y-clientpos.y, + s_cursorpos.x+s_cursorsize.cx-clientpos.x, + s_cursorpos.y+s_cursorsize.cy-clientpos.y); + HRGN normalregion = CreateRectRgn(0,0,1,1); + CombineRgn(normalregion,clipregion,cursorregion,RGN_DIFF); + CombineRgn(cursorregion,clipregion,cursorregion,RGN_AND); + DeleteObject(clipregion); + clipregion = normalregion; + } + + // BLT THE NON-CURSOR REGION ONTO THE SCREEN + InternalBltClippedToRgn(dest, + &boundingrect, + destsize, + destpitch, + source, + sourcerect, + sourcesize, + sourcepitch, + sourceoffsetx, + sourceoffsety, + pattern, + rop3, + &clientpos, + clipregion, + flags, + surfacenumber, + cursorhidden); + DeleteObject(clipregion); + + // IF WE'RE DISPLAYING A CUSTOM CURSOR THEN PROCESS THE CURSOR REGION + if (customcursor) { + + // ALLOCATE AN OFFSCREEN BUFFER TO HOLD THE COMPOSITE IMAGE + LPBYTE compositebuffer = (LPBYTE)ALLOC(s_cursorsize.cx*s_cursorsize.cy); + RECT cursorrect = {0,0,s_cursorsize.cx,s_cursorsize.cy}; + + // BLT THE CURSOR REGION ONTO THE OFFSCREEN BUFFER + POINT offset = {clientpos.x-s_cursorpos.x, + clientpos.y-s_cursorpos.y}; + InternalBltClippedToRgn(compositebuffer, + &cursorrect, + &s_cursorsize, + s_cursorsize.cx, + source, + sourcerect, + sourcesize, + sourcepitch, + sourceoffsetx, + sourceoffsety, + pattern, + rop3, + &offset, + cursorregion, + flags & BLT_FLAG_TILED, + surfacenumber, + NULL); + + // DRAW THE CURSOR ONTO THE OFFSCREEN BUFFER + SBltROP3(compositebuffer, + s_cursormask, + s_cursorsize.cx, + s_cursorsize.cy, + s_cursorsize.cx, + s_cursorsize.cx, + 0, + SRCAND); + SBltROP3(compositebuffer, + s_cursorimage, + s_cursorsize.cx, + s_cursorsize.cy, + s_cursorsize.cx, + s_cursorsize.cx, + 0, + SRCPAINT); + + // BLT THE OFFSCREEN BUFFER ONTO THE SCREEN + boundingrect.left = s_cursorpos.x; + boundingrect.top = s_cursorpos.y; + InternalBltClippedToRgn(dest, + &boundingrect, + destsize, + destpitch, + compositebuffer, + &cursorrect, + &s_cursorsize, + s_cursorsize.cx, + 0, + 0, + 0, + SRCCOPY, + &clientpos, + cursorregion, + flags & ~BLT_FLAG_TILED, + surfacenumber, + cursorhidden); + DeleteObject(cursorregion); + + // FREE THE OFFSCREEN BUFFER + FREE(compositebuffer); + + } + + return TRUE; +} + +//=========================================================================== +static HWND InternalCreateDialogBox (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam) { + + // IF NO PARENT WINDOW WAS GIVEN, THEN USE THE APPLICATION'S FRAME WINDOW + // AS THE PARENT. IT'S IMPORTANT TO HAVE A PARENT WINDOW BECAUSE IF + // WE CREATE A NEW TOP-LEVEL WINDOW WHILE A DIRECTDRAW APPLICATION IS + // ACTIVE IN EXCLUSIVE MODE, THE DIRECTDRAW APPLICATION WILL BE MINIMIZED. + HWND framewindow = SDrawGetFrameWindow(); + if (!parentwindow) + parentwindow = framewindow; + + // PARSE THE TEMPLATE + BOOL extendedformat = 0; + LPCWSTR title; + short fontsize; + short fontweight; + short fontitalics; + LPCWSTR fontname; + LPDLGITEMTEMPLATE firstitem; + DLGTEMPLATE parsedtemplate; + if (templatedata->style == 0xFFFF0001) { + extendedformat = 1; + ParseDlgTemplateEx(templatedata, + &parsedtemplate, + &title, + &fontsize, + &fontweight, + &fontitalics, + &fontname, + &firstitem); + } + else + ParseDlgTemplate(templatedata, + &parsedtemplate, + &title, + &fontsize, + &fontweight, + &fontitalics, + &fontname, + &firstitem); + + // CONVERT THE TITLE AND FONT NAME TO ANSI + char ansititle[256] = ""; + char ansifontname[256] = ""; + if (title && *title && (*title != 0xFFFF)) + wcstombs(ansititle,title,255); + if (fontname && *fontname && (*fontname != 0xFFFF)) + wcstombs(ansifontname,fontname,255); + + // CREATE A FONT FOR THE DIALOG BOX CONTROLS. WE USE A HARD-CODED VALUE OF + // 96 VERTICAL PIXELS PER LOGICAL INCH INSTEAD OF QUERYING THE DEVICE CAPS + // BECAUSE WE WANT OUR DIALOG BOXES TO LOOK EXACTLY THE SAME ON ALL + // DISPLAYS. + HFONT font = (HFONT)0; + if (ansifontname[0]) + if (s_basefont) + font = CreateFont(-MulDiv(s_basefont->pointsize,96,72),0,0,0, + s_basefont->weight,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + DEFAULT_PITCH | s_basefont->family, + s_basefont->face); + else + font = CreateFont(-MulDiv(fontsize,96,72),0,0,0,fontweight,fontitalics,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + DEFAULT_PITCH | FF_DONTCARE,ansifontname); + + // VERIFY THAT THE FONT WE CREATED WAS A TRUETYPE FONT, BECAUSE ONLY + // TRUETYPE FONTS BE SIZED THE SAME ON ALL SYSTEMS. IF THE FONT ISN'T A + // TRUETYPE FONT, DESTROY IT AND CREATE A DEFAULT TRUETYPE FONT. + if (font) { + BOOL truetype; + { + HDC parentdc = GetDC(parentwindow); + HDC memdc = CreateCompatibleDC(parentdc); + HFONT oldfont = (HFONT)SelectObject(memdc,font); + TEXTMETRIC tm; + ZeroMemory(&tm,sizeof(TEXTMETRIC)); + GetTextMetrics(memdc,&tm); + truetype = ((tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0); + SelectObject(memdc,oldfont); + DeleteDC(memdc); + ReleaseDC(parentwindow,parentdc); + } + if (!truetype) { + DeleteObject(font); + if (s_basefont) + font = CreateFont(-MulDiv(s_basefont->pointsize,96,72),0,0,0, + s_basefont->weight,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + DEFAULT_PITCH | FF_SWISS,"Arial"); + else + font = CreateFont(-MulDiv(fontsize,96,72),0,0,0,fontweight,fontitalics,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + DEFAULT_PITCH | FF_SWISS,"Arial"); + } + } + + // DETERMINE THE FONT'S AVERAGE CHARACTER SIZE, WHICH WE USE FOR CONVERTING + // DIALOG UNITS TO SCREEN COORDINATES + int baseunitx = 8; + int baseunity = 16; + if (font) + ComputeBaseUnits(font,&baseunitx,&baseunity); + + // DETERMINE THE WINDOW STYLE + DWORD windowstyle = parsedtemplate.style & ~WS_VISIBLE; + DWORD windowexstyle = parsedtemplate.dwExtendedStyle + | WS_EX_CONTROLPARENT + | ((windowstyle & DS_MODALFRAME) ? WS_EX_DLGMODALFRAME + : 0); + + // DETERMINE THE WINDOW POSITION + RECT windowrect = {CONVDLGX(parsedtemplate.x), + CONVDLGY(parsedtemplate.y), + CONVDLGX(parsedtemplate.x)+CONVDLGX(parsedtemplate.cx)-1, + CONVDLGY(parsedtemplate.y)+CONVDLGY(parsedtemplate.cy)-1}; + AdjustWindowRectEx(&windowrect,windowstyle & 0xFFFF0000,0,windowexstyle); + int screencx; + int screency; + SDrawGetScreenSize(&screencx,&screency); + int windowcx = windowrect.right+1-windowrect.left; + int windowcy = windowrect.bottom+1-windowrect.top; + int windowx = (windowstyle & DS_CENTER) ? ((screencx-windowcx) >> 1) + : CONVDLGX(parsedtemplate.x); + int windowy = (windowstyle & DS_CENTER) ? ((screency-windowcy) >> 1) + : CONVDLGY(parsedtemplate.y); + windowx = max(0,min(windowx,screencx-windowcx)); + windowy = max(0,min(windowy,screency-windowcy)); + + // IF THE APPLICATION'S FRAME WINDOW IS MINIMIZED, RESTORE IT + { + if (framewindow && IsIconic(framewindow)) { + ShowWindow(framewindow,SW_SHOWMAXIMIZED); + while (DoMessageLoop((HWND)0)) + ; + SetActiveWindow(parentwindow); + SetFocus(parentwindow); + } + } + + // CREATE THE DIALOG BOX WINDOW + HWND dialogwindow = CreateWindowEx(windowexstyle, + "SDlgDialog", + ansititle, + windowstyle, + windowx, + windowy, + windowcx, + windowcy, + parentwindow, + (HMENU)0, + instance, + dialogproc); + if (!dialogwindow) + return dialogwindow; + + // SELECT THE FONT INTO THE DIALOG WINDOW + { + HDC dc = GetDC(dialogwindow); + SelectObject(dc,font); + ReleaseDC(dialogwindow,dc); + } + + // SET THE DEFAULT RETURN VALUE + SetProp(dialogwindow,"SDlg_EndDialog",(HANDLE)0); + SetProp(dialogwindow,"SDlg_EndResult",(HANDLE)0); + + // CREATE THE CONTROLS + HWND focuswindow = dialogwindow; + { + LPDLGITEMTEMPLATE itemdata = firstitem; + for (int itemnum = 0; itemnum < parsedtemplate.cdit; ++itemnum) { + + // ADVANCE TO THE NEXT DOUBLEWORD BOUNDARY + { + int misaligned = ((LPBYTE)itemdata-(LPBYTE)templatedata) & 3; + if (misaligned) + itemdata = (LPDLGITEMTEMPLATE)(((LPBYTE)itemdata)+4-misaligned); + } + + // PARSE THE CONTROL TEMPLATE + if (extendedformat) + itemdata = (LPDLGITEMTEMPLATE)(((LPBYTE)itemdata)+sizeof(DWORD)); + LPCWSTR controlclassname = (LPCWSTR)(itemdata+1); + if (extendedformat) + ++controlclassname; + LPCWSTR controltitle; + LPCVOID controldata; + if (*controlclassname == 0xFFFF) + controltitle = controlclassname+2; + else + controltitle = controlclassname+wcslen(controlclassname)+1; + if (*controltitle == 0xFFFF) + controldata = controltitle+3; + else + controldata = controltitle+wcslen(controltitle)+2; + + // CONVERT THE CLASS NAME AND TITLE TO ANSI + char ansicontrolclassname[256] = ""; + char ansicontroltitle[256] = ""; + if (*controlclassname == 0xFFFF) + switch (*(controlclassname+1)) { + case 0x0080: SStrCopy(ansicontrolclassname,"Button" ,256); break; + case 0x0081: SStrCopy(ansicontrolclassname,"Edit" ,256); break; + case 0x0082: SStrCopy(ansicontrolclassname,"SDlgStatic",256); break; + case 0x0083: SStrCopy(ansicontrolclassname,"Listbox" ,256); break; + case 0x0084: SStrCopy(ansicontrolclassname,"Scrollbar" ,256); break; + case 0x0085: SStrCopy(ansicontrolclassname,"Combobox" ,256); break; + } + else + wcstombs(ansicontrolclassname,controlclassname,255); + if (*controltitle != 0xFFFF) + wcstombs(ansicontroltitle,controltitle,255); + + // CREATE THE CONTROL WINDOW + DWORD style = extendedformat ? itemdata->dwExtendedStyle : itemdata->style; + DWORD exstyle = extendedformat ? itemdata->style : itemdata->dwExtendedStyle; + HWND window = CreateWindowEx(exstyle, + ansicontrolclassname, + ansicontroltitle, + style, + CONVDLGX(itemdata->x), + CONVDLGY(itemdata->y), + CONVDLGX(itemdata->cx), + CONVDLGY(itemdata->cy), + dialogwindow, + (HMENU)itemdata->id, + instance, + (LPVOID)controldata); + + // SUBCLASS THE CONTROL, SET ITS INTERNAL PROPERTIES, THEN SHOW IT + SetProp(window,"SDlg_WndProc",(HANDLE)GetWindowLong(window,GWL_WNDPROC)); + SetWindowLong(window,GWL_WNDPROC,(LONG)ControlSubclassWndProc); + if (window && font) + SendMessage(window,WM_SETFONT,(WPARAM)font,0); + ShowWindow(window,SW_SHOW); + + // DETERMINE WHETHER THIS CONTROL SHOULD RECEIVE THE KEYBOARD FOCUS + if (window && + (focuswindow == dialogwindow) && + (!(itemdata->style & WS_DISABLED)) && + _stricmp(ansicontrolclassname,"Static") && + _stricmp(ansicontrolclassname,"SDlgStatic")) + focuswindow = window; + + itemdata = (LPDLGITEMTEMPLATE)(((LPBYTE)controldata)+*((LPWORD)controldata-1)); + } + } + + // SEND THE WM_SETFONT MESSAGE + if (font) + SendMessage(dialogwindow,WM_SETFONT,(WPARAM)font,0); + + // SEND THE WM_INITDIALOG MESSAGE + if (!SendMessage(dialogwindow,WM_INITDIALOG,(WPARAM)focuswindow,initparam)) + focuswindow = (HWND)0; + + // TURN ON THE OWNER DRAW STYLE FOR ANY CONTROLS FOR WHICH WE HAVE TEXTURES + { + HWND window = GetTopWindow(dialogwindow); + while (window) { + if (FindBitmap(window,ANYBITMAP)) { + DWORD origstyle = (DWORD)GetWindowLong(window,GWL_STYLE); + SetProp(window,"SDlg_OrigStyle",(HANDLE)origstyle); + DWORD style = origstyle; + char classname[256] = ""; + GetClassName(window,classname,256); + if ((!_stricmp(classname,"Button")) && + (((origstyle & 0x0000000F) == BS_PUSHBUTTON) || + ((origstyle & 0x0000000F) == BS_DEFPUSHBUTTON))) + style |= BS_OWNERDRAW; + else if (!_stricmp(classname,"ComboBox")) + style |= CBS_OWNERDRAWFIXED; + else if (!_stricmp(classname,"ListBox")) + style |= LBS_OWNERDRAWFIXED; + if (style != origstyle) + SetWindowLong(window,GWL_STYLE,(LONG)style); + } + window = GetNextWindow(window,GW_HWNDNEXT); + } + } + + // UNLESS THE APPLICATION CALLED ENDDIALOG() DURING THE WM_INITDIALOG + // MESSAGE, SHOW THE DIALOG WINDOW AND SET THE FOCUS + if (!GetProp(dialogwindow,"SDlg_EndDialog")) { + ShowWindow(dialogwindow,SW_SHOWNORMAL); + if (focuswindow) + SetFocus(focuswindow); + } + + return dialogwindow; +} + +//=========================================================================== +static void IntersectRgnWithWindow (HWND updatewindow, + HRGN region, + HWND window) { + VALIDATEBEGIN; + VALIDATE(updatewindow); + VALIDATE(region); + VALIDATE(window); + VALIDATEENDVOID; + + if (!IsWindowVisible(window)) + return; + + // INTERSECT THIS WINDOW WITH THE REGION + { + DWORD exstyle = GetWindowLong(window,GWL_EXSTYLE); + if ((window != updatewindow) && + !(exstyle & WS_EX_TRANSPARENT)) { + RECT rect; + GetWindowRect(window,&rect); + ScreenToClient(updatewindow,(LPPOINT)&rect.left); + ScreenToClient(updatewindow,(LPPOINT)&rect.right); + if (RectInRegion(region,&rect)) { + HRGN rectregion = CreateRectRgn(rect.left,rect.top,rect.right,rect.bottom); + CombineRgn(region,region,rectregion,RGN_DIFF); + DeleteObject(rectregion); + } + } + } + + // RECURSIVELY INTERSECT CHILD WINDOWS + { + HWND childwindow = GetTopWindow(window); + while (childwindow) { + IntersectRgnWithWindow(updatewindow,region,childwindow); + childwindow = GetNextWindow(childwindow,GW_HWNDNEXT); + } + } + +} + +//=========================================================================== +static BOOL IsButton (HWND window, BOOL *ownerdraw) { + if (ownerdraw) + *ownerdraw = 0; + + // DETERMINE WHETHER THIS IS A BUTTON WINDOW + if (!IsWindow(window)) + return FALSE; + char classname[256] = ""; + GetClassName(window,classname,256); + if (_stricmp(classname,"Button")) + return FALSE; + + // DETERMINE WHETHER IT IS OWNER DRAWN + DWORD style = (DWORD)GetWindowLong(window,GWL_STYLE); + if (ownerdraw) + *ownerdraw = ((style & 0x0000000F) == BS_OWNERDRAW); + + return TRUE; +} + +//=========================================================================== +static BOOL IsPointInWindow (LPPOINTS point, HWND window) { + RECT rect; + GetClientRect(window,&rect); + return ((point->x >= rect.left) && + (point->x < rect.right) && + (point->y >= rect.top) && + (point->y < rect.bottom)); +} + +//=========================================================================== +static void ParseDlgTemplate (LPCDLGTEMPLATE templatedata, + LPDLGTEMPLATE parsedtemplate, + LPCWSTR *title, + short *fontsize, + short *fontweight, + short *fontitalics, + LPCWSTR *fontname, + LPDLGITEMTEMPLATE *firstitem) { + + // PREPARE THE PARSED TEMPLATE STRUCTURE + CopyMemory(parsedtemplate,templatedata,sizeof(DLGTEMPLATE)); + + // FIND THE TITLE + { + LPCWSTR menuname = (LPCWSTR)(templatedata+1); + LPCWSTR classname; + if ((*menuname == 0x0000) || (*menuname == 0xFFFF)) + classname = menuname+1; + else + classname = menuname+wcslen(menuname)+1; + if ((*classname == 0x0000) || (*classname == 0xFFFF)) + *title = classname+1; + else + *title = classname+wcslen(classname)+1; + } + + // FIND THE FONT INFORMATION + if (parsedtemplate->style & DS_SETFONT) { + *fontsize = *((*title)+wcslen(*title)+1); + *fontweight = 0; + *fontitalics = 0; + *fontname = (*title)+wcslen(*title)+2; + *firstitem = (LPDLGITEMTEMPLATE)((*fontname)+wcslen(*fontname)+1); + } + else { + *fontsize = 0; + *fontweight = 0; + *fontitalics = 0; + *fontname = NULL; + *firstitem = (LPDLGITEMTEMPLATE)((*title)+wcslen(*title)+1); + } + +} + +//=========================================================================== +static void ParseDlgTemplateEx (LPCDLGTEMPLATE templatedata, + LPDLGTEMPLATE parsedtemplate, + LPCWSTR *title, + short *fontsize, + short *fontweight, + short *fontitalics, + LPCWSTR *fontname, + LPDLGITEMTEMPLATE *firstitem) { + + // PREPARE THE PARSED TEMPLATE STRUCTURE + { + CopyMemory(parsedtemplate,((LPBYTE)templatedata)+8,sizeof(DLGTEMPLATE)); + DWORD temp = parsedtemplate->style; + parsedtemplate->style = parsedtemplate->dwExtendedStyle; + parsedtemplate->dwExtendedStyle = temp; + } + + // FIND THE TITLE + { + LPCWSTR menuname = (LPCWSTR)(((LPBYTE)templatedata)+26); + LPCWSTR classname; + if ((*menuname == 0x0000) || (*menuname == 0xFFFF)) + classname = menuname+1; + else + classname = menuname+wcslen(menuname)+1; + if ((*classname == 0x0000) || (*classname == 0xFFFF)) + *title = classname+1; + else + *title = classname+wcslen(classname)+1; + } + + // FIND THE FONT INFORMATION + if (parsedtemplate->style & DS_SETFONT) { + const short *ptr = (const short *)((*title)+wcslen(*title)+1); + *fontsize = *ptr++; + *fontweight = *ptr++; + *fontitalics = (*ptr++) & 1; + *fontname = (LPCWSTR)ptr; + *firstitem = (LPDLGITEMTEMPLATE)((*fontname)+wcslen(*fontname)+1); + } + else { + *fontsize = 0; + *fontweight = 0; + *fontitalics = 0; + *fontname = NULL; + *firstitem = (LPDLGITEMTEMPLATE)((*title)+wcslen(*title)+1); + } +} + +//=========================================================================== +static LRESULT SendMessageNoDefProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + s_nodefproc = 1; + return SendMessage(window,message,wparam,lparam); +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +HDC APIENTRY SDlgBeginPaint (HWND window, LPPAINTSTRUCT ps) { + VALIDATEBEGIN; + VALIDATE(window); + VALIDATE(ps); + VALIDATEEND; + + if (!IsWindow(window)) + return (HDC)0; + ++s_inpaint; + + // IF THIS WINDOW DOESN'T HAVE A SELECTED BACKGROUND, OR IF IT IS + // TRANSPARENT, JUST CALL THE NORMAL BEGINPAINT() FUNCTION AND LET IT + // PAINT THE BACKGROUND WITH THE BRUSH REGISTERED IN THE WINDOW CLASS + if ((GetWindowLong(window,GWL_EXSTYLE) & WS_EX_TRANSPARENT) || + !FindBitmap(window,SDLG_USAGE_BACKGROUND)) + return BeginPaint(window,ps); + + // SAVE THE UPDATE REGION FOR THIS WINDOW + HRGN region = CreateRectRgn(0,0,1,1); + GetUpdateRgn(window,region,0); + + // TEMPORARILY SAVE AND REMOVE THE BACKGROUND BRUSH FOR THIS WINDOW'S + // CLASS, SO THAT BEGINPAINT() WILL NOT TRY TO ERASE THE BACKGROUND + DWORD brush = GetClassLong(window,GCL_HBRBACKGROUND); + SetClassLong(window,GCL_HBRBACKGROUND,0); + + // CALL BEGINPAINT() + HDC dc = BeginPaint(window,ps); + + // RESTORE THE BACKGROUND BRUSH + SetClassLong(window,GCL_HBRBACKGROUND,brush); + + // IF THE BACKGROUND DOES NOT NEED ERASING, RETURN NOW + if (!ps->fErase) { + DeleteObject(region); + return dc; + } + + // ERASE THE BACKGROUND + SDlgDrawBitmap(window, + SDLG_USAGE_BACKGROUND, + region, + 0, + 0, + NULL, + SDLG_DBF_TILE | SDLG_DBF_VCENTER); + ps->fErase = 0; + + DeleteObject(region); + return dc; +} + +//=========================================================================== +BOOL APIENTRY SDlgBltToWindowE (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey, + DWORD pattern, + DWORD rop3) { + VALIDATEBEGIN; + VALIDATE(window); + VALIDATEEND; + + if (!(IsWindow(window) && IsWindowVisible(window) && !IsIconic(window))) + return FALSE; + + // REJECT ANY ATTEMPT TO SET A TRANSPARENCY COLOR, SINCE TRANSPARENCY + // IS NOT CURRENTLY IMPLEMENTED + if (colorkey != 0xFFFFFFFF) + return FALSE; + + // DETERMINE THE SCREEN DIMENSIONS + SIZE screensize; + SDrawGetScreenSize((int *)&screensize.cx,(int *)&screensize.cy); + + // DETERMINE THE DESTINATION LOCATION + RECT clientrect; + GetClientRect(window,&clientrect); + clientrect.left += x; + clientrect.top += y; + + // DETERMINE WHETHER WE WILL HIDE AND/OR RESTORE THE CURSOR + DWORD bltflags = BLT_FLAG_LOCKSURFACE | BLT_FLAG_DESTRECTCLIENTCOORDS; + if (!s_cursorhidden) { + bltflags |= BLT_FLAG_HIDECURSOR; + if (!s_inpaint) + bltflags |= BLT_FLAG_RESTORECURSOR; + } + + // PERFORM THE BITBLT + InternalBltClippedToWindow(NULL, + &clientrect, + &screensize, + 0, + bitmapbits, + bitmaprect, + bitmapsize, + bitmapsize->cx, + 0, + 0, + pattern, + rop3, + window, + region, + bltflags, + SDRAW_SURFACE_FRONT, + s_cursorhidden ? NULL : &s_cursorhidden); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDlgBltToWindowI (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey, + DWORD pattern, + DWORD rop3) { + RECT exclrect; + LPRECT exclrectptr = bitmaprect; + if (bitmaprect) { + exclrect.left = bitmaprect->left; + exclrect.top = bitmaprect->top; + exclrect.right = bitmaprect->right+1; + exclrect.bottom = bitmaprect->bottom+1; + exclrectptr = &exclrect; + } + return SDlgBltToWindowE(window, + region, + x, + y, + bitmapbits, + exclrectptr, + bitmapsize, + colorkey, + pattern, + rop3); +} + +//=========================================================================== +BOOL APIENTRY SDlgCheckTimers () { + TIMERPTR callback = NULL; + DWORD currtime = GetTickCount(); + ITERATELIST(TIMERREC,s_timerlist,curr) + if (currtime-curr->lasttime >= curr->elapse) { + if (currtime-curr->lasttime > 2*curr->elapse) + curr->lasttime = currtime; + else + curr->lasttime += curr->elapse; + if (curr->callback) { + callback = curr; + break; + } + else + PostMessage(curr->window,WM_TIMER,curr->id,0); + } + if (callback) + callback->callback(callback->window,WM_TIMER,callback->id,currtime); + return TRUE; +} + +//=========================================================================== +HWND APIENTRY SDlgCreateDialogIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam) { + if (!s_initialized) + if (!InitializeDialogManager()) + return (HWND)0; + + return InternalCreateDialogBox(instance, + templatedata, + parentwindow, + dialogproc, + initparam); +} + +//=========================================================================== +HWND APIENTRY SDlgCreateDialogParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam) { + LPCDLGTEMPLATE templatedata = GetTemplateData(instance,templatename); + if (!templatedata) + return (HWND)0; + + return SDlgCreateDialogIndirectParam((HINSTANCE)GetModuleHandle(NULL), + templatedata, + parentwindow, + dialogproc, + initparam); +} + +//=========================================================================== +BOOL APIENTRY SDlgDefDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_CTLCOLORSTATIC: + { + char classname[256] = ""; + GetClassName((HWND)lparam,classname,256); + if (!_stricmp(classname,"SDlgStatic")) { + SetTextColor((HDC)wparam,0xFFFFFF); + SetBkMode((HDC)wparam,TRANSPARENT); + return (BOOL)GetStockObject(NULL_BRUSH); + } + } + // IF IT'S NOT A STATIC CONTROL, FALL THROUGH TO WM_CTLCOLOREDIT + + case WM_CTLCOLOREDIT: + case WM_CTLCOLORLISTBOX: + SetTextColor((HDC)wparam,0xFFFFFF); + SetBkColor((HDC)wparam,0); + SetBkMode((HDC)wparam,OPAQUE); + return (BOOL)GetStockObject(BLACK_BRUSH); + + case WM_INITDIALOG: + return 1; + + } + return 0; +} + +//=========================================================================== +BOOL APIENTRY SDlgDestroy () { + SDlgSetSystemCursor(NULL,NULL,NULL,OCR_NORMAL); + TIMERPTR curr; + while ((curr = s_timerlist.Head()) != NULL) + SDlgKillTimer(curr->window,curr->id); + s_bitmaplist.Clear(); + if (s_basefont) { + DEL(s_basefont); + s_basefont = NULL; + } + return TRUE; +} + +//=========================================================================== +int APIENTRY SDlgDialogBoxIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam) { + if (!s_initialized) + if (!InitializeDialogManager()) + return -1; + + // CREATE THE DIALOG BOX + HWND dialogwindow = InternalCreateDialogBox(instance, + templatedata, + parentwindow, + dialogproc, + initparam); + if (!dialogwindow) + return -1; + + // FLAG THE DIALOG BOX AS MODAL AND DISABLE THE PARENT WINDOW + if (parentwindow && (parentwindow != GetDesktopWindow())) { + SetProp(dialogwindow,"SDlg_Modal",(HANDLE)1); + if (!IsIconic(parentwindow)) + EnableWindow(parentwindow,0); + } + + // ENTER THE MESSAGE LOOP + while (!GetProp(dialogwindow,"SDlg_EndDialog")) + DoMessageLoop(dialogwindow); + int result = (int)GetProp(dialogwindow,"SDlg_EndResult"); + RemoveProp(dialogwindow,"SDlg_EndDialog"); + RemoveProp(dialogwindow,"SDlg_EndResult"); + RemoveProp(dialogwindow,"SDlg_Modal"); + DestroyWindow(dialogwindow); + + // REENABLE THE PARENT WINDOW + if (parentwindow && (parentwindow != GetDesktopWindow())) + EnableWindow(parentwindow,1); + + // RETURN THE VALUE THAT WAS PASSED TO SDLGENDDIALOG() + return result; +} + +//=========================================================================== +int APIENTRY SDlgDialogBoxParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam) { + LPCDLGTEMPLATE templatedata = GetTemplateData(instance,templatename); + if (!templatedata) + return -1; + + return SDlgDialogBoxIndirectParam((HINSTANCE)GetModuleHandle(NULL), + templatedata, + parentwindow, + dialogproc, + initparam); +} + +//=========================================================================== +BOOL APIENTRY SDlgDrawBitmap (HWND window, + DWORD usage, + HRGN region, + int offsetx, + int offsety, + LPRECT boundingoffset, + DWORD flags) { + VALIDATEBEGIN; + VALIDATE(window); + VALIDATE(usage); + VALIDATEEND; + + if (!IsWindow(window)) + return FALSE; + if ((usage == SDLG_USAGE_BACKGROUND) && + (GetWindowLong(window,GWL_EXSTYLE) & WS_EX_TRANSPARENT)) + return TRUE; + + // FIND THE REQUESTED BITMAP + BITMAPPTR bitmap = FindBitmap(window,usage); + if (!bitmap) + return FALSE; + + // DETERMINE THE BOUNDING RECTANGLE, IN SCREEN COORDINATES, FOR THIS + // WINDOW'S CLIENT AREA + RECT boundingrect; + GetClientRect(window,&boundingrect); + ClientToScreen(window,(LPPOINT)&boundingrect.left); + ClientToScreen(window,(LPPOINT)&boundingrect.right); + + // APPLY ANY BOUNDING RECTANGLE OFFSETS + if (boundingoffset) { + boundingrect.left += max(0,boundingoffset->left); + boundingrect.top += max(0,boundingoffset->top); + boundingrect.right += min(0,boundingoffset->right); + boundingrect.bottom += min(0,boundingoffset->bottom); + } + + // IF WE'RE NOT TILING THEN CLIP THE SIZE OF THE BOUNDING RECTANGLE + // TO THE SIZE OF THE BITMAP + if (!(flags & SDLG_DBF_TILE)) { + boundingrect.right = min(boundingrect.right, + boundingrect.left+bitmap->rect.right-bitmap->rect.left); + if (flags & SDLG_DBF_VCENTER) { + int vertspace = ((boundingrect.bottom-boundingrect.top) + -(bitmap->rect.bottom-bitmap->rect.top))/2; + if (vertspace > 0) { + boundingrect.top += vertspace; + boundingrect.bottom = boundingrect.top+bitmap->rect.bottom-bitmap->rect.top; + } + } + else + boundingrect.bottom = min(boundingrect.bottom, + boundingrect.top+bitmap->rect.bottom-bitmap->rect.top); + } + + // DETERMINE THE BITMAP AND SCREEN DIMENSIONS + SIZE bitmapsize = {bitmap->width,bitmap->height}; + SIZE screensize; + SDrawGetScreenSize((int *)&screensize.cx,(int *)&screensize.cy); + + // DETERMINE WHETHER WE WILL HIDE AND/OR RESTORE THE CURSOR + DWORD bltflags = BLT_FLAG_LOCKSURFACE | BLT_FLAG_TILED; + if (!s_cursorhidden) { + bltflags |= BLT_FLAG_HIDECURSOR; + if (!s_inpaint) + bltflags |= BLT_FLAG_RESTORECURSOR; + } + + // PERFORM THE BITBLT + InternalBltClippedToWindow(NULL, + &boundingrect, + &screensize, + 0, + bitmap->bitmapbits, + &bitmap->rect, + &bitmapsize, + bitmap->width, + offsetx, + offsety, + 0, + SRCCOPY, + window, + region, + bltflags, + SDRAW_SURFACE_FRONT, + s_cursorhidden ? NULL : &s_cursorhidden); + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SDlgEndDialog (HWND window, + int result) { + SetProp(window,"SDlg_EndDialog",(HANDLE)1); + SetProp(window,"SDlg_EndResult",(HANDLE)result); + return EndDialog(window,result); +} + +//=========================================================================== +BOOL APIENTRY SDlgEndPaint (HWND window, LPPAINTSTRUCT ps) { + if (s_cursorhidden) + do + ShowCursor(1); + while (--s_cursorhidden); + --s_inpaint; + return EndPaint(window,ps); +} + +//=========================================================================== +BOOL APIENTRY SDlgKillTimer (HWND window, + UINT event) { + BOOL found = FALSE; + ITERATELIST(TIMERREC,s_timerlist,curr) + if ((curr->window == window) && + (curr->id == event)) { + found = TRUE; + ITERATE_DELETE; + } + return found; +} + +//=========================================================================== +BOOL APIENTRY SDlgSetBaseFont (int pointsize, + int weight, + DWORD flags, + DWORD family, + LPCTSTR face) { + if (!(pointsize && weight && face && *face)) + return FALSE; + if (!s_basefont) + s_basefont = NEW(BASEFONT); + s_basefont->pointsize = pointsize; + s_basefont->weight = weight; + s_basefont->flags = flags; + s_basefont->family = family; + SStrCopy(s_basefont->face,face,32); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDlgSetBitmapE (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey) { + VALIDATEBEGIN; + VALIDATE(window || (controltype && *controltype)); + VALIDATE(usage); + VALIDATE(!(usage & ~ANYBITMAP)); + VALIDATEEND; + + if (!controltype) + controltype = ""; + + // REJECT ANY ATTEMPT TO SET A TRANSPARENCY COLOR, SINCE TRANSPARENCY + // IS NOT CURRENTLY IMPLEMENTED + if (colorkey != 0xFFFFFFFF) + return FALSE; + + // REMOVE ANY BITMAPS ASSOCIATED WITH WINDOWS THAT NO LONGER EXIST + { + ITERATELIST(BITMAPREC,s_bitmaplist,curr) + if ((curr->window && !IsWindow(curr->window)) || + (curr->parentwindow && !IsWindow(curr->parentwindow))) + ITERATE_DELETE; + } + + // REMOVE THE PREVIOUS BITMAP FOR THIS WINDOW + { + BITMAPPTR curr = s_bitmaplist.Head(); + while (curr && + ((curr->window != window) || + (curr->parentwindow != parentwindow) || + (curr->usage != usage) || + (curr->controlstyle != controlstyle) || + _stricmp(curr->controltype,controltype))) + curr = curr->Next(); + if (curr) + s_bitmaplist.DeleteNode(curr); + } + + // ADD A NEW RECORD FOR THIS BITMAP + if (bitmapbits && (width > 0) && (height > 0)) { + BITMAPPTR bitmap = s_bitmaplist.NewNode(LIST_HEAD); + bitmap->window = window; + bitmap->parentwindow = parentwindow; + bitmap->usage = usage; + bitmap->controlstyle = controlstyle; + bitmap->bitmapbits = bitmapbits; + bitmap->width = width; + bitmap->height = height; + bitmap->offsetx = 0; + bitmap->offsety = 0; + BOOL overflow = 0; + if (rect) { + bitmap->rect.left = rect->left % width; + bitmap->rect.top = rect->top % height; + bitmap->rect.right = bitmap->rect.left+rect->right-rect->left; + bitmap->rect.bottom = bitmap->rect.top+rect->bottom-rect->top; + if ((bitmap->rect.right > width) || + (bitmap->rect.bottom > height)) { + overflow = 1; + bitmap->offsetx = bitmap->rect.left; + bitmap->offsety = bitmap->rect.top; + } + } + if ((!rect) || overflow) { + bitmap->rect.left = 0; + bitmap->rect.top = 0; + bitmap->rect.right = width; + bitmap->rect.bottom = height; + } + SStrCopy(bitmap->controltype,controltype,CONTROLTYPELENGTH); + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDlgSetBitmapI (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey) { + RECT exclrect; + LPRECT exclrectptr = rect; + if (rect) { + exclrect.left = rect->left; + exclrect.top = rect->top; + exclrect.right = rect->right+1; + exclrect.bottom = rect->bottom+1; + exclrectptr = &exclrect; + } + return SDlgSetBitmapE(window, + parentwindow, + controltype, + controlstyle, + usage, + bitmapbits, + exclrectptr, + width, + height, + colorkey); +} + +//=========================================================================== +BOOL APIENTRY SDlgSetControlBitmaps (HWND parentwindow, + LPINT controllist, + LPDWORD usagelist, + LPBYTE bitmapbits, + LPSIZE bitmapsize, + DWORD adjusttype, + DWORD colorkey) { + VALIDATEBEGIN; + VALIDATE(parentwindow); + VALIDATE(controllist); + VALIDATE(bitmapbits); + VALIDATE(bitmapsize); + VALIDATE(bitmapsize->cx > 0); + VALIDATE(bitmapsize->cy > 0); + VALIDATEEND; + + // IF THE USAGE LIST WAS NOT PROVIDED, SUPPLY A DEFAULT LIST + // BASED ON THE ADJUSTMENT TYPE + static const DWORD defaultcontrolposlist[2] = {SDLG_USAGE_BACKGROUND, + 0}; + static const DWORD defaultverticallist[6] = {SDLG_USAGE_NORMAL_UNFOCUSED, + SDLG_USAGE_SELECTED_UNFOCUSED, + SDLG_USAGE_NORMAL_FOCUSED, + SDLG_USAGE_SELECTED_FOCUSED, + SDLG_USAGE_GRAYED, + 0}; + if (!usagelist) + if (adjusttype == SDLG_ADJUST_VERTICAL) + usagelist = (LPDWORD)&defaultverticallist[0]; + else + usagelist = (LPDWORD)&defaultcontrolposlist[0]; + + // PROCESS ALL CONTROLS AND USAGE TYPES + RECT rect = {0,0,0,0}; + BOOL success = 1; + for (LPINT currcontrol = controllist; *currcontrol; ++currcontrol) { + HWND window = GetDlgItem(parentwindow,*currcontrol); + if (window) { + RECT clientrect; + RECT windowrect; + GetClientRect(window,&clientrect); + GetWindowRect(window,&windowrect); + for (LPDWORD currusage = usagelist; *currusage; ++currusage) { + + // IF REQUESTED, ADJUST THE RECTANGLE BASED ON THE CONTROL POSITION + if (adjusttype == SDLG_ADJUST_CONTROLPOS) { + rect.left = windowrect.left; + rect.top = windowrect.top; + ScreenToClient(parentwindow,(LPPOINT)&rect); + } + + // DETERMINE THE WIDTH AND HEIGHT OF THE RECTANGLE BASED ON THE + // SIZE OF THE WINDOW + rect.right = rect.left+clientrect.right-clientrect.left; + rect.bottom = rect.top+clientrect.bottom-clientrect.top; + + // REGISTER THE BITMAP + if (!SDlgSetBitmapE(window, + (HWND)0, + NULL, + SDLG_STYLE_ANY, + *currusage, + bitmapbits, + &rect, + bitmapsize->cx, + bitmapsize->cy, + colorkey)) + success = 0; + + // IF REQUESTED, OFFSET THE RECTANGLE VERTICALLY + if (adjusttype == SDLG_ADJUST_VERTICAL) { + rect.top = rect.bottom; + if (rect.top >= bitmapsize->cy) + rect.top = 0; + } + + } + } + else + success = 0; + } + + return success; +} + +//=========================================================================== +BOOL APIENTRY SDlgSetCursor (HWND window, + HCURSOR cursor, + DWORD id, + HCURSOR *oldcursor) { + if (oldcursor) + *oldcursor = (HCURSOR)0; + LPCSTR normalclasslist[6] = {"Button","SDlgStatic","ListBox","Scrollbar","ComboBox",NULL}; + LPCSTR ibeamclasslist[2] = {"Edit",NULL}; + LPCSTR *classlist; + switch (id) { + case OCR_NORMAL: classlist = normalclasslist; break; + case OCR_IBEAM: classlist = ibeamclasslist; break; + default: return 0; + } + if (id == OCR_NORMAL) { + if (oldcursor) + *oldcursor = (HCURSOR)GetClassLong(window,GCL_HCURSOR); + SetClassLong(window,GCL_HCURSOR,(LONG)cursor); + } + while (*classlist) { + HWND classwindow = FindWindowEx(window,(HWND)0,*classlist,NULL); + if (classwindow) { + if (oldcursor && (id != OCR_NORMAL)) + *oldcursor = (HCURSOR)GetClassLong(window,GCL_HCURSOR); + SetClassLong(classwindow,GCL_HCURSOR,(LONG)cursor); + } + ++classlist; + } + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDlgSetSystemCursor (LPBYTE maskbitmap, + LPBYTE imagebitmap, + LPSIZE size, + DWORD id) { + if (id != OCR_NORMAL) + return FALSE; + if (maskbitmap && imagebitmap) { + SDlgSetSystemCursor(NULL,NULL,NULL,id); + s_cursormask = maskbitmap; + s_cursorimage = imagebitmap; + s_cursorsize.cx = size->cx; + s_cursorsize.cy = size->cy; + POINT pt; + GetCursorPos(&pt); + AdjustCursorPos((HWND)0,pt.x,pt.y); + } + else { + s_cursormask = NULL; + s_cursorimage = NULL; + s_cursorpos.x = -1; + s_cursorpos.y = -1; + } + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDlgSetTimer (HWND window, + UINT event, + UINT elapse, + TIMERPROC timerfunc) { + SDlgKillTimer(window,event); + TIMERPTR ptr = s_timerlist.NewNode(); + ptr->window = window; + ptr->id = event; + ptr->elapse = elapse; + ptr->callback = timerfunc; + ptr->lasttime = GetTickCount(); + return event; +} + +//=========================================================================== +BOOL APIENTRY SDlgUpdateCursor () { + CheckCursorPos(); + return TRUE; +} diff --git a/src/Storm/SOURCE/SDRAW.CPP b/src/Storm/SOURCE/SDRAW.CPP new file mode 100644 index 0000000..f904be0 --- /dev/null +++ b/src/Storm/SOURCE/SDRAW.CPP @@ -0,0 +1,978 @@ +/**************************************************************************** +* +* SDRAW.CPP +* Storm DirectDraw functions +* +* By Michael O'Brien (2/8/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define SURFACES 4 + +#define REGKEY "Internal" +#define REGVAL_WINDOWMODE "Window Mode" + +typedef HRESULT (WINAPI *ddcreatetype)(GUID *,LPDIRECTDRAW *,IUnknown *); + +static DWORD s_asyncsystemblt = 0; +static BOOL s_autoinit = FALSE; +static BOOL s_createdgdipalette = FALSE; +static HCURSOR s_cursor = (HCURSOR)0; +static BOOL s_dlgactive = FALSE; +static HWND s_framewindow = (HWND)0; +static HPALETTE s_gdipalette = (HPALETTE)0; +static HINSTANCE s_libinst = (HINSTANCE)0; +static LPDIRECTDRAW s_lpdd = NULL; +static LPDIRECTDRAWPALETTE s_palette = NULL; +static PALETTEENTRY s_paletteentries[256] = {0}; +static BOOL s_redirectingprimary = FALSE; +static RECT s_redirectingrect = {0}; +static int s_screenbitdepth = 8; +static SIZE s_screensize = {640,480}; +static LPDIRECTDRAWSURFACE s_surface[SURFACES] = {NULL}; + +//=========================================================================== +static BOOL CheckUseWindowMode () { + static BOOL init = FALSE; + static DWORD window = 0; + if (!init) { + init = TRUE; + SRegLoadValue(REGKEY,REGVAL_WINDOWMODE,0,&window); +#ifdef _DEBUG + SRegSaveValue(REGKEY,REGVAL_WINDOWMODE,0,window); +#endif + } + return (window != 0); +} + +//=========================================================================== +static void CreateGdiPalette () { + if (s_palette) + s_palette->GetEntries(0,0,256,&s_paletteentries[0]); + { + LOGPALETTE *gdipal = (LOGPALETTE *)ALLOC(sizeof(LOGPALETTE)+255*sizeof(PALETTEENTRY)); + gdipal->palVersion = 0x300; + gdipal->palNumEntries = 256; + CopyMemory(gdipal->palPalEntry,&s_paletteentries[0],256*sizeof(PALETTEENTRY)); + s_gdipalette = CreatePalette(gdipal); + s_createdgdipalette = TRUE; + FREE(gdipal); + } + if (s_framewindow && s_gdipalette) { + HDC dc = GetDC(s_framewindow); + SelectPalette(dc,s_gdipalette,0); + ReleaseDC(s_framewindow,dc); + } +} + +//=========================================================================== +static BOOL inline IsRunningInWindow (HWND window) { + if (GetWindowLong(window,GWL_STYLE) & WS_MAXIMIZE) + return FALSE; + if (!(GetWindowLong(window,GWL_EXSTYLE) & WS_EX_TOPMOST)) + return TRUE; + RECT rect; + GetWindowRect(window,&rect); + return ((rect.right < GetSystemMetrics(SM_CXFULLSCREEN)) && + (rect.bottom < GetSystemMetrics(SM_CYFULLSCREEN))); +} + +//=========================================================================== +static void CALLBACK OnDestroy (LPPARAMS) { + SDrawDestroy(); + PostQuitMessage(0); +} + +//=========================================================================== +static void CALLBACK OnPaletteChanged (LPPARAMS params) { + if ((GetForegroundWindow() == SDrawGetFrameWindow()) && + ((HWND)(params->wparam) != SDrawGetFrameWindow())) + SDrawRealizePalette(); +} + +//=========================================================================== +static void CALLBACK OnQueryNewPalette (LPPARAMS params) { + SDrawRealizePalette(); + params->useresult = TRUE; + params->result = TRUE; +} + +//=========================================================================== +static void CALLBACK OnVkSnapshot (LPPARAMS) { + SDrawCaptureScreen(NULL); +} + +//=========================================================================== +static LRESULT CALLBACK WndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + BOOL useresult = FALSE; + LRESULT result = 0; + if (SMsgDispatchMessage(window,message,wparam,lparam,&useresult,&result)) + if (useresult) + return result; + return DefWindowProc(window,message,wparam,lparam); +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SDrawAutoInitialize (HINSTANCE instance, + LPCTSTR classname, + LPCTSTR title, + WNDPROC wndproc, + int servicelevel, + int width, + int height, + int bitdepth) { + VALIDATEBEGIN; + VALIDATE(instance); + VALIDATE(classname); + VALIDATE(*classname); + VALIDATE(title); + VALIDATE(servicelevel > 0); + VALIDATE(servicelevel <= SDRAW_SERVICE_MAX); + VALIDATEEND; + + // STORE THE FACT THE WE AUTO-INITIALIZED DIRECTDRAW, SO THAT WE CAN + // UNDO EVERYTHING AT DESTRUCTION TIME + s_autoinit = TRUE; + s_dlgactive = FALSE; + + // CREATE A BLANK CURSOR + if (!s_cursor) { + int cursorcx = GetSystemMetrics(SM_CXCURSOR); + int cursorcy = GetSystemMetrics(SM_CYCURSOR); + int bytes = ((cursorcx+31)/32)*4*cursorcy; + LPVOID buffer1 = ALLOC(bytes); + LPVOID buffer2 = ALLOCZERO(bytes); + FillMemory(buffer1,bytes,0xFF); + s_cursor = CreateCursor(instance, + 0, + 0, + cursorcx, + cursorcy, + buffer1, + buffer2); + FREE(buffer1); + FREE(buffer2); + } + + // REGISTER THE FRAME WINDOW CLASS + { + WNDCLASS wndclass; + ZeroMemory(&wndclass,sizeof(WNDCLASS)); + wndclass.lpfnWndProc = wndproc ? wndproc : WndProc; + wndclass.hInstance = instance; + wndclass.hIcon = LoadIcon(0,IDI_APPLICATION); + wndclass.hCursor = s_cursor; + wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wndclass.lpszClassName = classname; + RegisterClass(&wndclass); + } + + // CREATE THE FRAME WINDOW + { + DWORD exstyle; + int windowwidth, windowheight; + if (CheckUseWindowMode()) { + exstyle = 0; + windowwidth = width; + windowheight = height; + } + else { + exstyle = WS_EX_TOPMOST; + windowwidth = GetSystemMetrics(SM_CXSCREEN); + windowheight = GetSystemMetrics(SM_CYSCREEN); + } + if (!(s_framewindow = CreateWindowEx(exstyle, + classname, + title, + WS_POPUP | WS_VISIBLE, + 0, + 0, + windowwidth, + windowheight, + (HWND)0, + (HMENU)0, + instance, + NULL))) + return FALSE; + } + + // REGISTER MESSAGES FOR THE FRAME WINDOW + SMsgRegisterMessage(s_framewindow,WM_DESTROY ,OnDestroy); + SMsgRegisterMessage(s_framewindow,WM_PALETTECHANGED ,OnPaletteChanged); + SMsgRegisterMessage(s_framewindow,WM_QUERYNEWPALETTE,OnQueryNewPalette); + SMsgRegisterKeyUp(s_framewindow,VK_SNAPSHOT,OnVkSnapshot); + SMsgPushRegisterState(s_framewindow); + + // LOAD THE DIRECTDRAW LIBRARY + if (!s_libinst) + s_libinst = LoadLibrary("ddraw.dll"); + + // INITIALIZE DIRECTDRAW + if (s_libinst) { + ddcreatetype ddcreatefunc = + (ddcreatetype)GetProcAddress(s_libinst,"DirectDrawCreate"); + if (ddcreatefunc) + ddcreatefunc(NULL,&s_lpdd,NULL); + if (s_lpdd) { + if (CheckUseWindowMode()) + s_lpdd->SetCooperativeLevel(s_framewindow,DDSCL_NORMAL); + else { + s_lpdd->SetCooperativeLevel(s_framewindow, + DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); + s_lpdd->SetDisplayMode(width,height,bitdepth); + } + s_screenbitdepth = bitdepth; + s_screensize.cx = width; + s_screensize.cy = height; + } + } + + // IF WE FAILED TO LOAD THE LIBRARY OR INITIALIZE DIRECTDRAW, INFORM + // THE USER + if (!s_lpdd) { + MessageBox(s_framewindow, + "DirectDraw services are not available. You must install " + "Microsoft DirectX version 2.0 or higher. If you have " + "difficulty installing or using Microsoft DirectX on your " + "computer, please contact Microsoft Product Support " + "Services.", + title, + MB_SETFOREGROUND | MB_ICONSTOP); + return FALSE; + } + + // DETERMINE THE CAPABILITIES OF THE HARDWARE + s_asyncsystemblt = 0; + { + DDCAPS caps; + ZeroMemory(&caps,sizeof(DDCAPS)); + caps.dwSize = sizeof(DDCAPS); + if (s_lpdd->GetCaps(&caps,NULL) == DD_OK) + if ((caps.dwCaps & DDCAPS_CANBLTSYSMEM) && + (caps.dwSVBCaps & DDCAPS_BLTQUEUE)) + s_asyncsystemblt = 1; + } + + // CREATE THE VIDEO MEMORY SURFACES + { + DDSURFACEDESC desc; + ZeroMemory(&desc,sizeof(DDSURFACEDESC)); + desc.dwSize = sizeof(DDSURFACEDESC); + desc.dwFlags = DDSD_CAPS; + desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + if (servicelevel == SDRAW_SERVICE_PAGEFLIP) { + desc.dwFlags |= DDSD_BACKBUFFERCOUNT; + desc.dwBackBufferCount = 1; + desc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX; + } + if (s_lpdd->CreateSurface(&desc,&s_surface[SDRAW_SURFACE_FRONT],NULL) != DD_OK) + return FALSE; + if (servicelevel == SDRAW_SERVICE_PAGEFLIP) { + DDSCAPS caps; + ZeroMemory(&caps,sizeof(DDSCAPS)); + caps.dwCaps = DDSCAPS_BACKBUFFER; + if (s_surface[SDRAW_SURFACE_FRONT]) + s_surface[SDRAW_SURFACE_FRONT]->GetAttachedSurface(&caps,&s_surface[SDRAW_SURFACE_BACK]); + } + } + + // CREATE THE SYSTEM MEMORY SURFACE + if (servicelevel == SDRAW_SERVICE_DOUBLEBUFFER) { + DDSURFACEDESC desc; + ZeroMemory(&desc,sizeof(DDSURFACEDESC)); + desc.dwSize = sizeof(DDSURFACEDESC); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + desc.dwHeight = height; + desc.dwWidth = width; + s_lpdd->CreateSurface(&desc,&s_surface[SDRAW_SURFACE_SYSTEM],NULL); + } + + // VERIFY THAT ALL SURFACES WERE CREATED SUCCESSFULLY + { + if (!s_surface[SDRAW_SURFACE_FRONT]) + return FALSE; + if ((servicelevel == SDRAW_SERVICE_PAGEFLIP) && + !s_surface[SDRAW_SURFACE_BACK]) + return FALSE; + if ((servicelevel == SDRAW_SERVICE_DOUBLEBUFFER) && + !s_surface[SDRAW_SURFACE_SYSTEM]) + return FALSE; + } + + // ATTEMPT TO LOCK THE PRIMARY VIDEO SURFACE. IF WE'RE UNABLE TO LOCK + // IT, THEN CREATE A TEMPORARY SURFACE IN SYSTEM MEMORY TO BLT FROM. + { + DDSURFACEDESC desc; + ZeroMemory(&desc,sizeof(DDSURFACEDESC)); + desc.dwSize = sizeof(DDSURFACEDESC); + HRESULT result = s_surface[SDRAW_SURFACE_FRONT]->Lock(NULL, + &desc, + DDLOCK_WAIT, + NULL); + if (desc.lpSurface) + s_surface[SDRAW_SURFACE_FRONT]->Unlock(desc.lpSurface); + else if ((result != DDERR_SURFACELOST) && + (result != DDERR_WASSTILLDRAWING)) { + DDSURFACEDESC desc; + ZeroMemory(&desc,sizeof(DDSURFACEDESC)); + desc.dwSize = sizeof(DDSURFACEDESC); + desc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + desc.dwHeight = height; + desc.dwWidth = width; + s_lpdd->CreateSurface(&desc,&s_surface[SDRAW_SURFACE_TEMPORARY],NULL); + } + } + + // CREATE A DIRECTDRAW PALETTE AND A MATCHING GDI PALETTE + if (bitdepth == 8) { + { + HDC dc = GetDC((HWND)0); + GetSystemPaletteEntries(dc,0,256,&s_paletteentries[0]); + ReleaseDC((HWND)0,dc); + } + { + for (int loop = 10; loop < 246; ++loop) + s_paletteentries[loop].peFlags = PC_RESERVED | PC_NOCOLLAPSE; + } + s_lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 + | DDPCAPS_INITIALIZE, + &s_paletteentries[0], + &s_palette, + NULL); + if (!s_palette) { + SDrawDestroy(); + return FALSE; + } + CreateGdiPalette(); + } + + // BLANK OUT THE NEWLY CREATED SURFACES, AND SELECT THE NEW PALETTE + // INTO EACH ONE + { + for (int loop = 0; loop < SURFACES; ++loop) + if (s_surface[loop]) { + SDrawClearSurface(loop); + if (s_palette) + s_surface[loop]->SetPalette(s_palette); + } + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDrawCaptureScreen (LPCTSTR filename) { + if (!(s_lpdd && + s_framewindow && + s_surface[SDRAW_SURFACE_FRONT])) + return FALSE; + if (s_screenbitdepth != 8) + return FALSE; + + // SWITCH TO THE GDI SCREEN IF NECESSARY + SDrawSelectGdiSurface(1,1); + + // SAVE THE CURRENT SURFACE + LPBYTE savebuffer = (LPBYTE)ALLOC(s_screensize.cx*s_screensize.cy); + if (s_palette) + s_palette->GetEntries(0,0,256,&s_paletteentries[0]); + { + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + SBltROP3(savebuffer, + videobuffer, + s_screensize.cx, + s_screensize.cy, + s_screensize.cx, + pitch, + 0, + SRCCOPY); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + } + + // IF NO FILENAME WAS PROVIDED, PROMPT THE USER FOR ONE + char localfilename[MAX_PATH] = ""; + if (filename && *filename) + SStrCopy(localfilename,filename,MAX_PATH); + else { + OPENFILENAME ofn; + ZeroMemory(&ofn,sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = s_framewindow; + ofn.hInstance = (HINSTANCE)GetModuleHandle(NULL); + ofn.lpstrFilter = "Graphics Interchange (*.gif)\0*.gif\0" + "PC Paintbrush (*.pcx)\0*.pcx\0" + "Windows Bitmap (*.bmp)\0*.bmp\0" + "All Files (*.*)\0*.*\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFile = localfilename; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrTitle = "Save Screen Capture"; + ofn.Flags = OFN_HIDEREADONLY + | OFN_NOCHANGEDIR + | OFN_OVERWRITEPROMPT + | OFN_PATHMUSTEXIST; + ofn.lpstrDefExt = ".gif"; + s_dlgactive = 1; + BOOL result = GetSaveFileName(&ofn); + s_dlgactive = 0; + if (!result) { + FREE(savebuffer); + return FALSE; + } + } + + // SAVE THE FILE + SBmpSaveImage(localfilename, + &s_paletteentries[0], + savebuffer, + s_screensize.cx, + s_screensize.cy, + s_screenbitdepth); + + FREE(savebuffer); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDrawClearSurface (int surfacenumber) { + VALIDATEBEGIN; + VALIDATE(surfacenumber >= 0); + VALIDATE(surfacenumber < SURFACES); + VALIDATEEND; + + if ((!s_lpdd) || + (!s_surface[surfacenumber])) + return FALSE; + + // HIDE THE CURSOR IF IT IS VISIBLE + int hidden = 0; + do + ++hidden; + while (ShowCursor(0) >= 0); + + // CLEAR THE SURFACE + { + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(surfacenumber,NULL,&videobuffer,&videopitch)) { + SGdiSetPitch(videopitch); + SGdiRectangle(videobuffer, + 0, + 0, + s_screensize.cx, + s_screensize.cy, + PALETTEINDEX(0)); + SDrawUnlockSurface(surfacenumber,videobuffer); + } + } + + // RESTORE THE CURSOR + while (hidden--) + ShowCursor(1); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDrawDestroy () { + + // DESTROY OTHER MODULES WHICH RELY ON THIS MODULE + BOOL result = TRUE; +#ifndef STATICLIB + result &= SDlgDestroy(); + result &= SGdiDestroy(); + result &= SVidDestroy(); +#endif + + // DESTROY THE GDI PALETTE IF WE CREATED ONE + if (s_gdipalette && s_createdgdipalette) { + s_createdgdipalette = 0; + DeleteObject(s_gdipalette); + } + + // RETURN THE SCREEN DIMENSIONS TO THEIR DEFAULTS + s_screenbitdepth = 8; + s_screensize.cx = 640; + s_screensize.cy = 480; + + // IF DIRECTDRAW WAS INITIALIZED THROUGH SDRAWAUTOINITIALIZE(), RELEASE + // ALL DIRECTDRAW OBJECTS THAT WE CREATED + if (s_autoinit) { + s_autoinit = FALSE; + if (s_cursor) + DestroyCursor(s_cursor); + } + + // ZERO OUT ALL OBJECT POINTERS AND HANDLES + s_gdipalette = (HPALETTE)0; + s_palette = NULL; + for (int loop = SURFACES-1; loop >= 0; --loop) + s_surface[loop] = NULL; + s_lpdd = NULL; + s_framewindow = (HWND)0; + s_cursor = (HCURSOR)0; + + return result; +} + +//=========================================================================== +BOOL APIENTRY SDrawFlipPage () { + if (s_dlgactive || + !(s_lpdd && + s_surface[SDRAW_SURFACE_FRONT] && + s_surface[SDRAW_SURFACE_BACK])) + return FALSE; + + HRESULT result; + do { + result = s_surface[SDRAW_SURFACE_FRONT]->Flip(NULL,DDFLIP_WAIT); + if ((result == DDERR_SURFACELOST) && s_surface[SDRAW_SURFACE_FRONT]) + if (s_surface[SDRAW_SURFACE_FRONT]->Restore() == DD_OK) + InvalidateRect(s_framewindow,NULL,0); + else + return FALSE; + } while ((result == DDERR_WASSTILLDRAWING) || + (result == DDERR_SURFACELOST)); + + return TRUE; +} + +//=========================================================================== +HWND APIENTRY SDrawGetFrameWindow (HWND *window) { + if (window) + *window = s_framewindow; + return s_framewindow; +} + +//=========================================================================== +BOOL APIENTRY SDrawGetObjects (LPDIRECTDRAW *directdraw, + LPDIRECTDRAWSURFACE *frontbuffer, + LPDIRECTDRAWSURFACE *backbuffer, + LPDIRECTDRAWSURFACE *systembuffer, + LPDIRECTDRAWSURFACE *temporarybuffer, + LPDIRECTDRAWPALETTE *palette, + HPALETTE *gdipalette) { + if (directdraw) + *directdraw = s_lpdd; + if (frontbuffer) + *frontbuffer = s_surface[SDRAW_SURFACE_FRONT]; + if (backbuffer) + *backbuffer = s_surface[SDRAW_SURFACE_BACK]; + if (systembuffer) + *systembuffer = s_surface[SDRAW_SURFACE_SYSTEM]; + if (palette) + *palette = s_palette; + if (gdipalette) + *gdipalette = s_gdipalette; + return (s_lpdd != NULL); +} + +//=========================================================================== +BOOL APIENTRY SDrawGetScreenSize (int *width, + int *height, + int *bitdepth) { + if (width) + *width = s_lpdd ? s_screensize.cx : GetSystemMetrics(SM_CXSCREEN); + if (height) + *height = s_lpdd ? s_screensize.cy : GetSystemMetrics(SM_CYSCREEN); + if (bitdepth) + if (s_lpdd) + *bitdepth = s_screenbitdepth; + else { + HDC dc = GetDC(GetDesktopWindow()); + *bitdepth = GetDeviceCaps(dc,BITSPIXEL)*GetDeviceCaps(dc,PLANES); + ReleaseDC(GetDesktopWindow(),dc); + } + return (width || height || bitdepth); +} + +//=========================================================================== +BOOL APIENTRY SDrawGetServiceLevel (int *servicelevel) { + VALIDATEBEGIN; + VALIDATE(servicelevel); + VALIDATEEND; + + if (!s_surface[SDRAW_SURFACE_FRONT]) + return FALSE; + if (s_surface[SDRAW_SURFACE_SYSTEM]) + *servicelevel = SDRAW_SERVICE_DOUBLEBUFFER; + else if (s_surface[SDRAW_SURFACE_BACK]) + *servicelevel = SDRAW_SERVICE_PAGEFLIP; + else + *servicelevel = SDRAW_SERVICE_BASIC; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDrawLockSurface (int surfacenumber, + LPCRECT rect, + LPBYTE *ptr, + int *pitch, + DWORD flags) { + if (ptr) + *ptr = NULL; + if (pitch) + *pitch = 0; + + VALIDATEBEGIN; + VALIDATE(surfacenumber >= 0); + VALIDATE(surfacenumber < SURFACES); + VALIDATE(ptr); + VALIDATEEND; + + if ((!s_lpdd) || + (!s_surface[surfacenumber])) + return FALSE; + + // LOCK THE SURFACE AND RETURN A POINTER TO VIDEO MEMORY + { + DDSURFACEDESC desc; + ZeroMemory(&desc,sizeof(DDSURFACEDESC)); + desc.dwSize = sizeof(DDSURFACEDESC); + do { + HRESULT result = s_surface[surfacenumber]->Lock((LPRECT)rect, + &desc, + DDLOCK_WAIT, + NULL); + if ((result == DDERR_SURFACELOST) && s_surface[SDRAW_SURFACE_FRONT]) + if (s_surface[SDRAW_SURFACE_FRONT]->Restore() == DD_OK) + InvalidateRect(s_framewindow,NULL,0); + else + return FALSE; + else if ((result != DD_OK) && + (result != DDERR_WASSTILLDRAWING) && + !desc.lpSurface) { + + // IF WE COULDN'T LOCK THE PRIMARY SURFACE BUT WE HAVE BEEN GIVEN + // A TEMPORARY SURFACE, REDIRECT OUTPUT TO THE TEMPORARY SURFACE + if ((surfacenumber == SDRAW_SURFACE_FRONT) && + s_surface[SDRAW_SURFACE_TEMPORARY] && + !s_redirectingprimary) { + s_redirectingprimary = TRUE; + if (rect) + CopyMemory(&s_redirectingrect,rect,sizeof(RECT)); + else { + s_redirectingrect.left = 0; + s_redirectingrect.top = 0; + s_redirectingrect.right = s_screensize.cx; + s_redirectingrect.bottom = s_screensize.cy; + } + return SDrawLockSurface(SDRAW_SURFACE_TEMPORARY,rect,ptr,pitch,flags); + } + + return FALSE; + } + } while (!desc.lpSurface); + *ptr = (LPBYTE)desc.lpSurface; + if (pitch) + *pitch = desc.lPitch; + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDrawManualInitialize (HWND framewindow, + LPDIRECTDRAW directdraw, + LPDIRECTDRAWSURFACE frontbuffer, + LPDIRECTDRAWSURFACE backbuffer, + LPDIRECTDRAWSURFACE systembuffer, + LPDIRECTDRAWSURFACE temporarybuffer, + LPDIRECTDRAWPALETTE palette, + HPALETTE gdipalette) { + + // SAVE THE OBJECT HANDLES AND POINTERS + s_autoinit = 0; + s_dlgactive = 0; + s_framewindow = framewindow; + s_gdipalette = gdipalette; + s_lpdd = directdraw; + s_surface[SDRAW_SURFACE_FRONT] = frontbuffer; + s_surface[SDRAW_SURFACE_BACK] = backbuffer; + s_surface[SDRAW_SURFACE_SYSTEM] = systembuffer; + s_surface[SDRAW_SURFACE_TEMPORARY] = temporarybuffer; + s_palette = palette; + + // IF THE APPLICATION PASSED US A DIRECTDRAW PALETTE BUT NOT A GDI PALETTE, + // CREATE ONE OURSELF FOR USE BY SDLG + if (s_palette && !s_gdipalette) + CreateGdiPalette(); + + return TRUE; +} + +//=========================================================================== +int APIENTRY SDrawMessageBox (LPCTSTR text, + LPCTSTR title, + UINT flags) { + + // SWITCH TO THE GDI SCREEN IF NECESSARY + SDrawSelectGdiSurface(TRUE,TRUE); + + // IF THE APPLICATION IS CONTROLLING THE SYSTEM PALETTE DIRECTLY + // THROUGH DIRECTDRAW, NORMALIZE THE PALETTE SO THAT THE MESSAGEBOX() + // FUNCTION CAN DISPLAY ITS TEXT + PALETTEENTRY pe[256]; + if (s_palette) { + + // SAVE THE APPLICATION'S PALETTE + s_palette->GetEntries(0,0,256,&pe[0]); + + // MODIFY THE IMPORTANT SYSTEM COLORS TO USE ONLY BLACK AND WHITE + { + HRSRC resource = FindResource(StormGetInstance(),"SYSTEMPALETTE","#256"); + HGLOBAL handle = LoadResource(StormGetInstance(),resource); + DWORD bytes = SizeofResource(StormGetInstance(),resource); + LPBYTE ptr = (LPBYTE)LockResource(handle); + if (bytes && ptr) { + PALETTEENTRY modpe[256]; + SBmpDecodeImage(SBMP_IMAGETYPE_PCX, + ptr, + bytes, + &modpe[0], + NULL, + 0); + s_palette->SetEntries(0,0,256,&modpe[0]); + } + FreeResource(handle); + } + + } + + // DISPLAY THE MESSAGE BOX + s_dlgactive = TRUE; + int result = MessageBox(GetActiveWindow(), + text, + title, + flags); + s_dlgactive = FALSE; + + // RESTORE THE ORIGINAL PALETTE + if (s_palette) + s_palette->SetEntries(0,0,256,&pe[0]); + + return result; +} + +//=========================================================================== +BOOL APIENTRY SDrawPostClose () { + if (!s_framewindow) + return FALSE; + + PostMessage(s_framewindow,WM_CLOSE,0,0); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDrawRealizePalette () { + if ((!s_lpdd) || (!s_palette)) + return FALSE; + + // UPDATE THE DIRECTDRAW PALETTE + BOOL success = (s_palette->SetEntries(0,0,256,&s_paletteentries[0]) == DD_OK); + + // UPDATE THE GDI PALETTE + if (s_gdipalette) + SetPaletteEntries(s_gdipalette,0,256,&s_paletteentries[0]); + + // IF WE ARE RUNNING IN A WINDOW, REALIZE THE PALETTE THROUGH GDI + if (s_gdipalette && s_framewindow && + IsRunningInWindow(s_framewindow)) { + HDC dc = GetDC(s_framewindow); + SelectPalette(dc,s_gdipalette,0); + RealizePalette(dc); + ReleaseDC(s_framewindow,dc); + } + + return success; +} + +//=========================================================================== +BOOL APIENTRY SDrawSelectGdiSurface (BOOL select, BOOL copy) { + if (s_dlgactive || + !(s_lpdd && + s_surface[SDRAW_SURFACE_FRONT] && + s_surface[SDRAW_SURFACE_BACK])) + return FALSE; + + // IF THE GDI SURFACE IS NOT ALREADY IN THE REQUESTED POSITION, DO A + // PAGE FLIP + LPDIRECTDRAWSURFACE gdisurface = NULL; + s_lpdd->GetGDISurface(&gdisurface); + if ((gdisurface != s_surface[SDRAW_SURFACE_FRONT]) == (select != 0)) { + if (copy) + s_surface[SDRAW_SURFACE_BACK]->Blt(NULL, + s_surface[SDRAW_SURFACE_FRONT], + NULL, + 0, + NULL); + return SDrawFlipPage(); + } + else + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDrawUnlockSurface (int surfacenumber, + LPBYTE ptr, + DWORD numrects, + LPCRECT rectarray) { + VALIDATEBEGIN; + VALIDATE(surfacenumber >= 0); + VALIDATE(surfacenumber < SURFACES); + VALIDATEEND; + + if ((!s_lpdd) || + (!s_surface[surfacenumber])) + return FALSE; + + // PROCESS REDIRECTED CALLS TO LOCK THE PRIMARY SURFACE + if ((surfacenumber == SDRAW_SURFACE_FRONT) && + s_redirectingprimary) + surfacenumber = SDRAW_SURFACE_TEMPORARY; + + // UNLOCK THE SURFACE + if (s_surface[surfacenumber]->Unlock(ptr) != DD_OK) + return FALSE; + + // IF WE JUST UNLOCKED THE TEMPORARY SURFACE, AND WE WERE REDIRECTING + // OUTPUT TO THE TEMPORARY SURFACE BECAUSE WE WERE UNABLE TO LOCK THE + // PRIMARY SURFACE, THEN COPY THE MODIFIED CONTENTS OF THE TEMPORARY + // SURFACE INTO THE PRIMARY SURFACE + if ((surfacenumber == SDRAW_SURFACE_TEMPORARY) && + s_redirectingprimary) { + s_redirectingprimary = FALSE; + if (s_surface[SDRAW_SURFACE_FRONT]) + if (numrects) + for (DWORD loop = 0; loop < numrects; ++loop) + s_surface[SDRAW_SURFACE_FRONT]->Blt((LPRECT)&rectarray[loop], + s_surface[SDRAW_SURFACE_TEMPORARY], + (LPRECT)&rectarray[loop], + DDBLT_WAIT, + NULL); + else + s_surface[SDRAW_SURFACE_FRONT]->Blt(&s_redirectingrect, + s_surface[SDRAW_SURFACE_TEMPORARY], + &s_redirectingrect, + DDBLT_WAIT, + NULL); + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SDrawUpdatePalette (DWORD firstentry, + DWORD numentries, + LPPALETTEENTRY entries, + BOOL reservedentries) { + VALIDATEBEGIN; + VALIDATE(firstentry+numentries <= 256); + VALIDATE(entries); + VALIDATEEND; + + if ((!s_lpdd) || (!s_palette)) + return FALSE; + + // PREVENT THE APPLICATION FROM SETTING THE FIRST OR LAST PALETTE + // ENTRIES (BLACK AND WHITE) + if ((!firstentry) && !reservedentries) { + ++firstentry; + --numentries; + ++entries; + } + if ((firstentry+numentries == 256) && !reservedentries) + --numentries; + + // SAVE THE NEW PALETTE ENTRIES + CopyMemory(&s_paletteentries[firstentry],entries,numentries*sizeof(PALETTEENTRY)); + + // UPDATE THE DIRECTDRAW PALETTE + BOOL success = (s_palette->SetEntries(0,firstentry,numentries,entries) == DD_OK); + + // UPDATE THE GDI PALETTE + if (s_gdipalette) { + for (DWORD loop = 0; loop < numentries; ++loop) + (entries+loop)->peFlags = (((firstentry+loop) >= 10) && ((firstentry+loop) <= 245)) + ? PC_RESERVED | PC_NOCOLLAPSE + : 0; + SetPaletteEntries(s_gdipalette,firstentry,numentries,entries); + } + + // IF WE ARE RUNNING IN A WINDOW, REALIZE THE PALETTE THROUGH GDI + if (s_gdipalette && s_framewindow && + IsRunningInWindow(s_framewindow)) { + HDC dc = GetDC(s_framewindow); + SelectPalette(dc,s_gdipalette,0); + RealizePalette(dc); + ReleaseDC(s_framewindow,dc); + } + + return success; +} + +//=========================================================================== +BOOL APIENTRY SDrawUpdateScreen (LPCRECT rect) { + if (!(s_lpdd && + s_surface[SDRAW_SURFACE_FRONT] && + s_surface[SDRAW_SURFACE_SYSTEM])) + return FALSE; + + // IF THE HARDWARE IS CAPABLE OF DOING ASYNCHRONOUS BLTS FROM SYSTEM + // MEMORY, USE THE HARDWARE BLITTER + if (s_asyncsystemblt) { + DDBLTFX fx; + ZeroMemory(&fx,sizeof(DDBLTFX)); + fx.dwSize = sizeof(DDBLTFX); + fx.dwDDFX = DDBLTFX_NOTEARING; + return (s_surface[SDRAW_SURFACE_FRONT]->Blt((LPRECT)rect, + s_surface[SDRAW_SURFACE_SYSTEM], + (LPRECT)rect, + DDBLT_ASYNC | DDBLT_DDFX, + &fx) == DD_OK); + } + + // OTHERWISE, USE OUR OWN BLT FUNCTION, WHICH IS FASTER THAT DIRECTDRAW'S + else { + BOOL success = FALSE; + LPBYTE videobuffer; + int videopitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&videopitch)) { + LPBYTE systembuffer; + int systempitch; + if (SDrawLockSurface(SDRAW_SURFACE_SYSTEM,NULL,&systembuffer,&systempitch)) { + success = SBltROP3(videobuffer, + systembuffer, + (s_screenbitdepth == 8) + ? s_screensize.cx + : (s_screensize.cx*s_screenbitdepth) >> 3, + s_screensize.cy, + videopitch, + systempitch, + 0, + SRCCOPY); + SDrawUnlockSurface(SDRAW_SURFACE_SYSTEM,systembuffer); + } + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } + return success; + } + +} diff --git a/src/Storm/SOURCE/SERR.CPP b/src/Storm/SOURCE/SERR.CPP new file mode 100644 index 0000000..00a4b9a --- /dev/null +++ b/src/Storm/SOURCE/SERR.CPP @@ -0,0 +1,440 @@ +/**************************************************************************** +* +* SERR.CPP +* Storm error handling functions +* +* By Michael O'Brien (4/10/97) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define STR_ERROR 0 +#define STR_HEADER 1 +#define STR_PROGRAM 2 +#define STR_FILELINE 3 +#define STR_FUNCTION 4 +#define STR_OBJECT 5 +#define STR_HANDLE 6 +#define STR_EXPRESSION 7 +#define STR_DESCRIPTION 8 +#define STR_TERMINATE 9 +#define STR_RECOVERABLE 10 +#define STR_FILE 11 +#define STRINGS 12 + +static const LPCTSTR s_displaystr[STRINGS] = + {"ERROR #%u (0x%08x)", + "This application has encountered a critical error:\n\n%s\n", + "Program:\t%s\n", + "File:\t%s\nLine:\t%d\n", + "Function:\t%s\n", + "Object:\t%s\n", + "Handle:\t%s\n", + "Expr:\t%s\n\n", + "\n%s\n\n", + "Press OK to terminate the application.", + "Do you wish to terminate the application?", + "File:\t%s\n"}; + +typedef struct _MSGSRC { + WORD facility; + WORD reserved; + HMODULE module; + _MSGSRC *next; +} MSGSRC, *MSGSRCPTR; + +static CRITICAL_SECTION s_critsect; +static LONG s_critsectinit = -1; +static MSGSRCPTR s_msgsrchead = NULL; +static BOOL s_msgsrcinit = FALSE; +static BOOL s_suppress = FALSE; +//#ifdef _MAC +static DWORD s_lasterror = 0; +//#endif + +static void InternalEnterCriticalSection (); +static void InternalLeaveCriticalSection (); + +//=========================================================================== +static void AddStormFacility (WORD facility) { + + // ADD THE DEFINITION OF STORM'S ERROR CODES TO THE END OF THE LIST + MSGSRCPTR *nextptr = &s_msgsrchead; + while (*nextptr) + nextptr = &(*nextptr)->next; + *nextptr = (MSGSRCPTR)HeapAlloc(GetProcessHeap(), + HEAP_GENERATE_EXCEPTIONS, + sizeof(MSGSRC)); + (*nextptr)->facility = facility; + (*nextptr)->module = StormGetInstance(); + (*nextptr)->next = NULL; + +} + +//=========================================================================== +static void AddStormMessages () { + AddStormFacility(STORMFAC); +#ifdef _FACDD + AddStormFacility(_FACDD); +#else + AddStormFacility(0x876); +#endif +#ifdef _FACDS + AddStormFacility(_FACDS); +#else + AddstormFacility(0x878); +#endif +} + +//=========================================================================== +static LPCTSTR GetString (UINT id) { + static char buffer[256]; + if (LoadString(StormGetInstance(),IDS_BASE+id,buffer,256)) + return buffer; + else + return s_displaystr[id]; +} + +//=========================================================================== +static void InternalEnterCriticalSection () { + if (!InterlockedIncrement(&s_critsectinit)) + InitializeCriticalSection(&s_critsect); + else + InterlockedDecrement(&s_critsectinit); + EnterCriticalSection(&s_critsect); +} + +//=========================================================================== +static void InternalLeaveCriticalSection () { + LeaveCriticalSection(&s_critsect); +} + +//=========================================================================== +static BOOL UndecorateObjectName (LPCSTR source, + LPSTR dest, + DWORD destchars) { + + // THIS IS A NON-CRITICAL FUNCTION WHOSE ONLY PURPOSE IS TO MAKE THE + // DISPLAYED ERROR MESSAGES EASIER TO READ. SINCE NAME DECORATION IS + // PERFORMED DIFFERENTLY BY EACH COMPILER, THIS FUNCTION ONLY ATTEMPTS + // TO UNDECORATE NAMES UNDER MICROSOFT VISUAL C++. +#ifndef _MSC_VER + return FALSE; +#endif + + // CHECK THE SOURCE NAME TO VERIFY THAT IT APPEARS TO BE A STRUCTURE + // OR OBJECT + if ((SStrLen(source) < 6) || + (source[0] != '.') || + (source[3] != 'U') || + !strpbrk(source+4,"?@")) + return FALSE; + + // COPY THE SOURCE NAME, MINUS THE PREFIX, INTO THE DESTINATION BUFFER + SStrCopy(dest,source+4,destchars); + + // STRIP OFF THE DETAILED TYPE INFORMATION + LPSTR separator = strpbrk(dest,"?@"); + if (!separator) + return FALSE; + *separator-- = 0; + + // STRIP OFF ANY TRAILING UNDERSCORES + while ((separator >= dest) && + (*separator == '_')) + *separator-- = 0; + + return TRUE; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SErrDestroy () { + s_msgsrcinit = FALSE; + while (s_msgsrchead) { + MSGSRCPTR next = s_msgsrchead->next; + HeapFree(GetProcessHeap(),0,s_msgsrchead); + s_msgsrchead = next; + } + if (s_critsectinit != -1) { + DeleteCriticalSection(&s_critsect); + s_critsectinit = -1; + } + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SErrDisplayError (DWORD errorcode, + LPCTSTR filename, + int linenumber, + LPCTSTR description, + BOOL recoverable, + UINT exitcode) { + if (s_suppress) + return FALSE; + + // ENTER THE CRITICAL SECTION + InternalEnterCriticalSection(); + + // FLUSH ALL OPEN LOGS +#ifndef STATICLIB + SLogFlushAll(); +#endif + + // DETERMINE THE NAME OF THE APPLICATION + char appfilename[MAX_PATH] = ""; + char appname[MAX_PATH] = ""; + { + GetModuleFileName((HMODULE)0,appfilename,MAX_PATH); + WIN32_FIND_DATA finddata; + ZeroMemory(&finddata,sizeof(WIN32_FIND_DATA)); + HANDLE findhandle = FindFirstFile(appfilename,&finddata); + if (findhandle) + FindClose(findhandle); + SStrCopy(appname,finddata.cFileName,MAX_PATH); + if (SStrChr(appname,'.',TRUE)) + *SStrChr(appname,'.',TRUE) = 0; + } + + // GET THE ERROR STRING + char errorstr[256] = ""; + SErrGetErrorStr(errorcode, + errorstr, + 256); + if (!errorstr[0]) + wsprintf(errorstr,GetString(STR_ERROR),errorcode & 0xFFFF,errorcode); + + // UNDECORATE THE HANDLE OR OBJECT NAME IF APPLICABLE + char localnamebuffer[256]; + LPCSTR localnameptr = filename; + if (localnameptr && *localnameptr && + ((linenumber == SERR_LINECODE_OBJECT) || + (linenumber == SERR_LINECODE_HANDLE))) + if (UndecorateObjectName(localnameptr, + localnamebuffer, + 256)) + localnameptr = localnamebuffer; + + // LOG THE ERROR TO THE ACTIVE DEBUGGER IF APPLICABLE + char outstr[1024]; + LPSTR curr = outstr; + curr += SStrCopy(curr,localnameptr); + if (linenumber > 0) { + wsprintf(curr,"(%u)",linenumber); + curr += SStrLen(curr); + } + wsprintf(curr," : error %u: ",errorcode & 0xFFFF); + curr += SStrLen(curr); + SStrCopy(curr,errorstr); + OutputDebugString(outstr); + + // BUILD THE FULL ERROR MESSAGE + curr = outstr; + wsprintf(curr,GetString(STR_HEADER),errorstr); + curr += SStrLen(curr); + wsprintf(curr,GetString(STR_PROGRAM),appfilename); + curr += SStrLen(curr); + if (localnameptr && *localnameptr) { + switch (linenumber) { + + case SERR_LINECODE_FUNCTION: + wsprintf(curr,GetString(STR_FUNCTION),localnameptr); + break; + + case SERR_LINECODE_OBJECT: + wsprintf(curr,GetString(STR_OBJECT),localnameptr); + break; + + case SERR_LINECODE_HANDLE: + wsprintf(curr,GetString(STR_HANDLE),localnameptr); + break; + + case SERR_LINECODE_FILE: + wsprintf(curr,GetString(STR_FILE),localnameptr); + break; + + default: + wsprintf(curr,GetString(STR_FILELINE),localnameptr,linenumber); + break; + + } + curr += SStrLen(curr); + } + if (errorcode == STORM_ERROR_ASSERTION) + wsprintf(curr,GetString(STR_EXPRESSION),description ? description : ""); + else + wsprintf(curr,GetString(STR_DESCRIPTION),description ? description : ""); + curr += SStrLen(curr); + if (recoverable) + SStrCopy(curr,GetString(STR_RECOVERABLE)); + else + SStrCopy(curr,GetString(STR_TERMINATE)); + + // DISPLAY THE MESSAGE BOX + UINT buttons = recoverable ? MB_YESNOCANCEL + : MB_OKCANCEL; + UINT flags = MB_ICONSTOP + | MB_SETFOREGROUND + | MB_TASKMODAL + | MB_TOPMOST + | buttons; +#ifdef STATICLIB + int result = MessageBox((HWND)0,outstr,appname,flags); +#else + int result = SDrawMessageBox(outstr,appname,flags); +#endif + + // LEAVE THE CRITICAL SECTION + InternalLeaveCriticalSection(); + + // IF THE USER WANTS TO TRY TO RECOVER FROM THE ERROR THEN RETURN + // CONTROL TO THE APPLICATION + if (recoverable && (result == IDNO)) + return TRUE; + + // IF THE USER CLICKED CANCEL, GENERATE A DEBUG BREAK + if (result == IDCANCEL) +#ifdef _X86_ + __asm int 3; +#else + DebugBreak(); +#endif + + // OTHERWISE, ATTEMPT TO STOP THE PROCESS. WE USE TERMINATEPROCESS() + // RATHER THAN EXITPROCESS() TO PREVENT STORM FROM GETTING A + // DLL_PROCESS_DETACH NOTIFICATION AND POTENTIALLY RECURSING INTO ITS + // CLEANUP FUNCTIONS. IF WE ARE RUNNING ON A WIN95/98 SYSTEM AND THE + // PROCESS IS ALREADY BEING TERMINATED, THEN CALLING TERMINATEPROCESS() + // AGAIN WILL CAUSE A KERNEL EXCEPTION. IN THIS CASE, WE JUST SUPPRESS + // ALL ERROR MESSAGES AND LET THE CLEANUP PROCESS CONTINUE TO ITS + // CONCLUSION. + SErrSuppressErrors(TRUE); + { + DWORD terminationcode; + if ((!(GetVersion() & 0x80000000)) || + (!GetExitCodeProcess(GetCurrentProcess(),&terminationcode)) || + (terminationcode == STILL_ACTIVE)) + TerminateProcess(GetCurrentProcess(),exitcode); + } + + return FALSE; +} + +//=========================================================================== +BOOL APIENTRY SErrGetErrorStr (DWORD errorcode, + LPTSTR buffer, + DWORD bufferchars) { + VALIDATEBEGIN; + VALIDATE(buffer); + VALIDATE(bufferchars); + VALIDATEEND; + + // ENTER THE CRITICAL SECTION + InternalEnterCriticalSection(); + + // IF WE HAVEN'T ADDED OUR OWN MESSAGE FACILITIES TO THE MODULE LIST, + // DO SO NOW + if (!s_msgsrcinit) { + s_msgsrcinit = TRUE; + AddStormMessages(); + } + + // EXTRACT THE ERROR'S FACILITY CODE, AND LOOK UP THE MODULE CONTAINING + // ERROR STRINGS FOR THAT FACILITY + WORD facility = (WORD)((errorcode >> 16) & 0xFFF); + HMODULE module = (HMODULE)0; + { + MSGSRCPTR curr = s_msgsrchead; + while (curr && (curr->facility != facility)) + curr = curr->next; + if (curr) + module = curr->module; + } + + // LEAVE THE CRITICAL SECTION + InternalLeaveCriticalSection(); + + // EXTRACT AND RETURN THE ERROR STRING + *buffer = 0; + return (FormatMessage(module + ? FORMAT_MESSAGE_FROM_HMODULE + : FORMAT_MESSAGE_FROM_SYSTEM, + module, + errorcode, + MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + buffer, + bufferchars, + NULL) != 0); + +} + +//=========================================================================== +DWORD APIENTRY SErrGetLastError () { +//#ifdef _MAC + return s_lasterror; +//#else +// return GetLastError(); +//#endif +} + +//=========================================================================== +BOOL APIENTRY SErrRegisterMessageSource (WORD facility, + HMODULE module, + LPVOID reserved) { + InternalEnterCriticalSection(); + MSGSRCPTR ptr = (MSGSRCPTR)HeapAlloc(GetProcessHeap(), + HEAP_GENERATE_EXCEPTIONS, + sizeof(MSGSRC)); + ptr->facility = facility; + ptr->module = module; + ptr->next = s_msgsrchead; + s_msgsrchead = ptr; + InternalLeaveCriticalSection(); + return TRUE; +} + +//=========================================================================== +void APIENTRY SErrReportResourceLeak (LPCTSTR handlename) { + + // DETERMINE WHETHER MEMORY TRACKING IS ENABLED +#ifndef _DEBUG + static BOOL checked = FALSE; + static BOOL debugmode = FALSE; + if (!checked) { + checked = TRUE; + SRegLoadValue("Internal","Debug Memory",0,(LPDWORD)&debugmode); + } + if (!debugmode) + return; +#endif + + // DISPLAY THE ERROR + SErrDisplayError(STORM_ERROR_HANDLE_NEVER_RELEASED, + handlename, + SERR_LINECODE_HANDLE, + NULL, + TRUE); + +} + +//=========================================================================== +void APIENTRY SErrSetLastError (DWORD errorcode) { +//#ifdef _MAC + s_lasterror = errorcode; +//#else +// SetLastError(errorcode); +//#endif +} + +//=========================================================================== +void APIENTRY SErrSuppressErrors (BOOL suppress) { + s_suppress = suppress; +} + diff --git a/src/Storm/SOURCE/SEVT.CPP b/src/Storm/SOURCE/SEVT.CPP new file mode 100644 index 0000000..01db999 --- /dev/null +++ b/src/Storm/SOURCE/SEVT.CPP @@ -0,0 +1,482 @@ +/**************************************************************************** +* +* SEVT.CPP +* Storm event dispatching functions +* +* By Michael O'Brien (5/9/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +NODEDECL(BREAKCMD) { + LPVOID data; +} *BREAKCMDPTR; + +typedef struct _IDHASHENTRY { + DWORD id; + DWORD sequence; + SEVTHANDLER handler; + _IDHASHENTRY *next; +} IDHASHENTRY, *IDHASHENTRYPTR; + +typedef struct _IDHASHTABLE { + IDHASHENTRYPTR *data; + DWORD size; + DWORD used; + _IDHASHTABLE *next; +} IDHASHTABLE, *IDHASHTABLEPTR; + +typedef struct _TYPEHASHENTRY { + DWORD type; + DWORD subtype; + DWORD sequence; + IDHASHTABLEPTR idhashtable; + _TYPEHASHENTRY *next; +} TYPEHASHENTRY, *TYPEHASHENTRYPTR; + +static LIST(BREAKCMD) s_breakcmdlist; +static CCritSect s_critsect; +static LONG s_dispatchesinprogress = 0; +static BOOL s_modified; +static TYPEHASHENTRYPTR *s_typehashtable = NULL; +static DWORD s_typehashtablesize = 0; +static DWORD s_typehashtableused = 0; + +//=========================================================================== +static DWORD inline ComputeNewTableSize (DWORD currentused) { + DWORD newsize = 1; + while (newsize <= ((s_typehashtableused+1) << 1)) + newsize <<= 1; + return newsize; +} + +//=========================================================================== +static void CopyIdHashTable (IDHASHTABLEPTR dest, + IDHASHTABLEPTR source) { + + // ALLOCATE SPACE FOR THE TABLE + dest->size = source->size; + dest->used = source->used; + dest->data = (IDHASHENTRYPTR *)ALLOC(dest->size*sizeof(IDHASHENTRYPTR)); + + // FILL IN EACH TABLE SLOT + for (DWORD id = 0; id < source->size; ++id) { + IDHASHENTRYPTR sourcecurr = *(source->data+id); + IDHASHENTRYPTR *destnext = dest->data+id; + while (sourcecurr) { + *destnext = NEW(IDHASHENTRY); + CopyMemory(*destnext,sourcecurr,sizeof(IDHASHENTRY)); + sourcecurr = sourcecurr->next; + destnext = &(*destnext)->next; + } + *destnext = NULL; + } + +} + +//=========================================================================== +static void DeleteIdHashTable (IDHASHTABLEPTR idhashtable) { + for (DWORD id = 0; id < idhashtable->size; ++id) { + IDHASHENTRYPTR currid; + while ((currid = *(idhashtable->data+id)) != NULL) { + *(idhashtable->data+id) = currid->next; + DEL(currid); + } + } + FREE(idhashtable->data); + DEL(idhashtable); +} + +//=========================================================================== +static TYPEHASHENTRYPTR inline FindTypeHashEntry (DWORD type, DWORD subtype) { + if (!(s_typehashtable && s_typehashtablesize)) + return NULL; + + DWORD slot = (type ^ subtype) & (s_typehashtablesize-1); + TYPEHASHENTRYPTR ptr = *(s_typehashtable+slot); + while (ptr && ((ptr->type != type) || (ptr->subtype != subtype))) + ptr = ptr->next; + return ptr; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SEvtBreakHandlerChain (LPVOID data) { + s_critsect.Enter(); + BREAKCMDPTR newcmd = s_breakcmdlist.NewNode(); + newcmd->data = data; + s_critsect.Leave(); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SEvtDestroy () { + s_critsect.Enter(); + for (DWORD type = 0; type < s_typehashtablesize; ++type) { + TYPEHASHENTRYPTR currtype; + while ((currtype = *(s_typehashtable+type)) != NULL) { + IDHASHTABLEPTR currhashtable; + while ((currhashtable = currtype->idhashtable) != NULL) { + currtype->idhashtable = currhashtable->next; + DeleteIdHashTable(currhashtable); + } + *(s_typehashtable+type) = currtype->next; + DEL(currtype); + } + } + if (s_typehashtable) + DEL(s_typehashtable); + s_typehashtable = NULL; + s_typehashtablesize = 0; + s_typehashtableused = 0; + s_modified = TRUE; + s_critsect.Leave(); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SEvtDispatch (DWORD type, + DWORD subtype, + DWORD id, + LPVOID data) { + InterlockedIncrement(&s_dispatchesinprogress); + BOOL success = FALSE; + DWORD currsequence = 0xFFFFFFFF; + IDHASHENTRYPTR currptr = NULL; + for (;;) { + + // ENTER THE CRITICAL SECTION + s_critsect.Enter(); + + // IF THERE IS A BREAK COMMAND FOR THIS HANDLER, EXIT + BOOL breakcmd = FALSE; + ITERATELIST(BREAKCMD,s_breakcmdlist,curr) + if (curr->data == data) { + breakcmd = TRUE; + ITERATE_DELETEANDBREAK; + } + if (breakcmd) { + s_critsect.Leave(); + break; + } + + // IF WE DON'T HAVE A VALID POINTER TO THE NEXT HANDLER RECORD, + // FIND ONE USING THE TYPE, SUBTYPE, ID, AND SEQUENCE + if ((!currptr) || s_modified) { + currptr = NULL; + for (ONCE) { + + // FIND THE TYPE/SUBTYPE ENTRY IN THE TYPE HASH TABLE + TYPEHASHENTRYPTR typeentry = FindTypeHashEntry(type,subtype); + if (!typeentry) + break; + + // FIND THE SLOT FOR THIS ID IN THE TYPE'S ID HASH TABLE + if (!(typeentry->idhashtable->data && typeentry->idhashtable->size)) + break; + DWORD slot = id & (typeentry->idhashtable->size-1); + currptr = *(typeentry->idhashtable->data+slot); + + // FIND THE NEXT HANDLER AFTER THE CURRENT SEQUENCE + while (currptr && + ((currptr->id != id) || + (currptr->sequence >= currsequence))) + currptr = currptr->next; + + // IF WE ARE THE ONLY ACTIVE THREAD CURRENTLY DISPATCHING, THEN + // RESET THE MODIFIED VARIABLE + if (s_dispatchesinprogress == 1) + s_modified = FALSE; + + } + } + + // SAVE THE HANDLER FOR THIS POINTER, AND MOVE THE POINTER AND SEQUENCE + // NUMBER TO THE NEXT RECORD + SEVTHANDLER handler = NULL; + if (currptr) { + handler = currptr->handler; + currsequence = currptr->sequence; + do + currptr = currptr->next; + while (currptr && (currptr->id != id)); + } + + // LEAVE THE CRITICAL SECTION + s_critsect.Leave(); + + // DISPATCH THE EVENT + if (handler) { + success = TRUE; + handler(data); + } + + // IF THIS IS THE LAST HANDLER IN THE CHAIN, EXIT THE LOOP + if (!currptr) + break; + + } + InterlockedDecrement(&s_dispatchesinprogress); + + // CLEAR OUT ANY LEFT-OVER BREAK COMMANDS FOR THIS HANDLER CHAIN + if (s_breakcmdlist.Head()) { + s_critsect.Enter(); + ITERATELIST(BREAKCMD,s_breakcmdlist,curr) + if (curr->data == data) + ITERATE_DELETE; + s_critsect.Leave(); + } + + return success; +} + +//=========================================================================== +BOOL APIENTRY SEvtPopState (DWORD type, + DWORD subtype) { + BOOL success = FALSE; + s_critsect.Enter(); + for (ONCE) { + + // FIND THE TYPE/SUBTYPE ENTRY IN THE TYPE HASH TABLE + TYPEHASHENTRYPTR typeentry = FindTypeHashEntry(type,subtype); + if (!typeentry) + break; + + // CHECK FOR A STACK UNDERFLOW + if (!typeentry->idhashtable->next) { + success = SEvtUnregisterType(type,subtype); + break; + } + + // FREE THE ID HASH TABLE AT THE TOP OF THE STACK + IDHASHTABLEPTR next = typeentry->idhashtable->next; + DeleteIdHashTable(typeentry->idhashtable); + typeentry->idhashtable = next; + + } + s_modified = TRUE; + s_critsect.Leave(); + return success; +} + +//=========================================================================== +BOOL APIENTRY SEvtPushState (DWORD type, + DWORD subtype) { + BOOL success = FALSE; + s_critsect.Enter(); + for (ONCE) { + + // FIND THE TYPE/SUBTYPE ENTRY IN THE TYPE HASH TABLE + TYPEHASHENTRYPTR typeentry = FindTypeHashEntry(type,subtype); + if (!typeentry) + break; + + // MAKE A COPY OF THE ID HASH TABLE + IDHASHTABLEPTR newtable = NEW(IDHASHTABLE); + CopyIdHashTable(newtable,typeentry->idhashtable); + + // LINK IT AT THE HEAD OF THE LIST + newtable->next = typeentry->idhashtable; + typeentry->idhashtable = newtable; + + s_modified = TRUE; + success = TRUE; + } + s_critsect.Leave(); + return success; +} + +//=========================================================================== +BOOL APIENTRY SEvtRegisterHandler (DWORD type, + DWORD subtype, + DWORD id, + DWORD flags, + SEVTHANDLER handler) { + VALIDATEBEGIN; + VALIDATE(handler); + VALIDATE(!flags); + VALIDATEEND; + + s_critsect.Enter(); + + // FIND THE TYPE/SUBTYPE ENTRY IN THE TYPE HASH TABLE + TYPEHASHENTRYPTR typeentry = FindTypeHashEntry(type,subtype); + + // IF WE COULDN'T FIND AN ENTRY, ADD ONE + if (!typeentry) { + + // GROW THE TYPE HASH TABLE IF NECESSARY + if (s_typehashtableused >= (s_typehashtablesize >> 1)) { + + // ALLOCATE A NEW TABLE + DWORD newsize = ComputeNewTableSize(s_typehashtableused); + TYPEHASHENTRYPTR *newtable = (TYPEHASHENTRYPTR *)ALLOCZERO(newsize*sizeof(TYPEHASHENTRYPTR)); + + // REHASH THE OLD TABLE INTO THE NEW TABLE + if (s_typehashtable && s_typehashtablesize) + for (DWORD loop = 0; loop < s_typehashtablesize; ++loop) { + TYPEHASHENTRYPTR ptr = *(s_typehashtable+loop); + while (ptr) { + DWORD slot = (ptr->type ^ ptr->subtype) & (newsize-1); + TYPEHASHENTRYPTR next = ptr->next; + ptr->next = *(newtable+slot); + *(newtable+slot) = ptr; + ptr = next; + } + } + + // REPLACE THE OLD TABLE WITH THE NEW TABLE + if (s_typehashtable) + DEL(s_typehashtable); + s_typehashtable = newtable; + s_typehashtablesize = newsize; + + } + + // CREATE A NEW ENTRY FOR THIS TYPE/SUBTYPE + { + DWORD slot = (type ^ subtype) & (s_typehashtablesize-1); + TYPEHASHENTRYPTR entry = NEWZERO(TYPEHASHENTRY); + entry->type = type; + entry->subtype = subtype; + entry->idhashtable = NEWZERO(IDHASHTABLE); + entry->next = *(s_typehashtable+slot); + *(s_typehashtable+slot) = entry; + ++s_typehashtableused; + typeentry = *(s_typehashtable+slot); + } + + } + + // GROW THE TYPE'S ID HASH TABLE IF NECESSARY + if (typeentry->idhashtable->used >= (typeentry->idhashtable->size >> 1)) { + + // ALLOCATE A NEW TABLE + DWORD newsize = ComputeNewTableSize(typeentry->idhashtable->size); + IDHASHENTRYPTR *newtable = (IDHASHENTRYPTR *)ALLOCZERO(newsize*sizeof(IDHASHENTRYPTR)); + + // REHASH THE OLD TABLE INTO THE NEW TABLE + if (typeentry->idhashtable->data && typeentry->idhashtable->size) + for (DWORD loop = 0; loop < typeentry->idhashtable->size; ++loop) { + IDHASHENTRYPTR ptr = *(typeentry->idhashtable->data+loop); + while (ptr) { + DWORD slot = ptr->id & (newsize-1); + IDHASHENTRYPTR next = ptr->next; + ptr->next = *(newtable+slot); + *(newtable+slot) = ptr; + ptr = next; + } + } + + // REPLACE THE OLD TABLE WITH THE NEW TABLE + if (typeentry->idhashtable->data) + FREE(typeentry->idhashtable->data); + typeentry->idhashtable->data = newtable; + typeentry->idhashtable->size = newsize; + + } + + // CREATE A NEW ENTRY FOR THIS ID + { + DWORD slot = id & (typeentry->idhashtable->size-1); + IDHASHENTRYPTR entry = NEWZERO(IDHASHENTRY); + entry->id = id; + entry->sequence = ++typeentry->sequence; + entry->handler = handler; + entry->next = *(typeentry->idhashtable->data+slot); + *(typeentry->idhashtable->data+slot) = entry; + ++typeentry->idhashtable->used; + } + + s_modified = TRUE; + s_critsect.Leave(); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SEvtUnregisterHandler (DWORD type, + DWORD subtype, + DWORD id, + SEVTHANDLER handler) { + BOOL success = FALSE; + s_critsect.Enter(); + for (ONCE) { + + // FIND THE TYPE/SUBTYPE ENTRY IN THE TYPE HASH TABLE + TYPEHASHENTRYPTR typeentry = FindTypeHashEntry(type,subtype); + if (!typeentry) + return FALSE; + + // FIND THE SLOT FOR THIS ID IN THE TYPE'S ID HASH TABLE + if (!(typeentry->idhashtable->data && typeentry->idhashtable->size)) + return FALSE; + DWORD slot = id & (typeentry->idhashtable->size-1); + + // IF WE WERE GIVEN A POINTER TO A HANDLER, FREE THE ID ENTRY MATCHING + // THE ID AND HANDLER. OTHERWISE, FREE ALL ENTRIES MATCHING THE ID. + IDHASHENTRYPTR *nextptr = typeentry->idhashtable->data+slot; + while (*nextptr) + if (((*nextptr)->id == id) && + ((!handler) || ((*nextptr)->handler == handler))) { + IDHASHENTRYPTR curr = *nextptr; + *nextptr = curr->next; + DEL(curr); + s_modified = TRUE; + success = TRUE; + --typeentry->idhashtable->used; + } + else + nextptr = &(*nextptr)->next; + + } + s_critsect.Leave(); + return success; +} + +//=========================================================================== +BOOL APIENTRY SEvtUnregisterType (DWORD type, + DWORD subtype) { + BOOL success = FALSE; + s_critsect.Enter(); + for (ONCE) { + + // FIND THE TYPE/SUBTYPE ENTRY IN THE TYPE HASH TABLE + TYPEHASHENTRYPTR typeentry = FindTypeHashEntry(type,subtype); + if (!typeentry) + break; + + // FREE ALL ID ENTRIES AND THE ID HASH TABLE FOR THIS TYPE/SUBTYPE + { + IDHASHTABLEPTR currhashtable; + while ((currhashtable = typeentry->idhashtable) != NULL) { + typeentry->idhashtable = currhashtable->next; + DeleteIdHashTable(currhashtable); + } + } + + // FREE THE RECORD FOR THIS TYPE/SUBTYPE + DWORD slot = (type ^ subtype) & (s_typehashtablesize-1); + TYPEHASHENTRYPTR *nextptr = s_typehashtable+slot; + while (*nextptr) + if ((*nextptr) == typeentry) { + TYPEHASHENTRYPTR curr = *nextptr; + *nextptr = curr->next; + DEL(curr); + --s_typehashtableused; + } + else + nextptr = &(*nextptr)->next; + + s_modified = TRUE; + success = TRUE; + } + s_critsect.Leave(); + return success; +} diff --git a/src/Storm/SOURCE/SFILE.CPP b/src/Storm/SOURCE/SFILE.CPP new file mode 100644 index 0000000..811dd19 --- /dev/null +++ b/src/Storm/SOURCE/SFILE.CPP @@ -0,0 +1,2642 @@ +/**************************************************************************** +* +* SFILE.CPP +* Storm file I/O functions +* +* By Michael O'Brien (6/23/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define CDROM_FALSE 0 +#define CDROM_USEDFORDDA 1 +#define CDROM_TRUE 2 + +#define FILL_UNREQUESTED 0 +#define FILL_REQUESTED 1 +#define FILL_PLAYING 2 +#define FILL_CLOSING 3 + +#define HASH_INDEX 0 +#define HASH_CHECK0 1 +#define HASH_CHECK1 2 +#define HASH_ENCRYPTKEY 3 +#define HASH_ENCRYPTDATA 4 + +#define MPQ_COMPRESSED_PKWARE 0x00000100 +#define MPQ_COMPRESSED_SCOMP 0x00000200 +#define MPQ_COMPRESSEDMASK 0x0000FF00 +#define MPQ_ENCRYPTED 0x00010000 +#define MPQ_ENCRYPTED_FIXLOC 0x00020000 +#define MPQ_ALLOCATED 0x80000000 + +#define RS_IDLE 0 +#define RS_READING 1 +#define RS_SEEKING 2 + +#define DEALLOCATED 0xFFFFFFFE +#define NOBLOCK 0xFFFFFFFF +#define SIGNATURE 0x1A51504D +#define DATACHUNKSIZE 0x20000 +#define WAVECHUNKSIZE 0x4000 +#define READAHEAD 0x1000 + +#define KEYCONTAINER "Blizzard_Storm" +#define SIGNATUREFILE "(signature)" +#define LISTFILE "(listfile)" +#define AUTHCOMPANIES 1 + +typedef struct _AUTHCOMPANYINFO { + LPCTSTR keyname; + DWORD authresult; +} AUTHCOMPANYINFO, *AUTHCOMPANYINFOPTR; + +typedef struct _CRYPTOAPI { + BOOL (APIENTRY *CryptAcquireContext )(HCRYPTPROV *,LPCTSTR,LPCTSTR,DWORD,DWORD); + BOOL (APIENTRY *CryptCreateHash )(HCRYPTPROV,ALG_ID,HCRYPTKEY,DWORD,HCRYPTHASH *); + BOOL (APIENTRY *CryptDestroyHash )(HCRYPTHASH); + BOOL (APIENTRY *CryptDestroyKey )(HCRYPTKEY); + BOOL (APIENTRY *CryptHashData )(HCRYPTHASH,BYTE *,DWORD,DWORD); + BOOL (APIENTRY *CryptImportKey )(HCRYPTPROV,BYTE *,DWORD,HCRYPTKEY,DWORD,HCRYPTKEY *); + BOOL (APIENTRY *CryptReleaseContext )(HCRYPTPROV,DWORD); + BOOL (APIENTRY *CryptSignHash )(HCRYPTHASH,DWORD,LPCTSTR,DWORD,BYTE *,DWORD *); + BOOL (APIENTRY *CryptVerifySignature)(HCRYPTHASH,BYTE *,DWORD,HCRYPTKEY,LPCTSTR,DWORD); +} CRYPTOAPI, *CRYPTOAPIPTR; + +typedef struct _SIGNATUREHEADER { + DWORD companyid; + DWORD reserved; +} SIGNATUREHEADER, *SIGNATUREHEADERPTR; + +typedef struct _FILEHEADER { + DWORD signature; + DWORD headersize; + DWORD filesize; + WORD version; + WORD sectorsizeid; + DWORD hashoffset; + DWORD blockoffset; + DWORD hashcount; + DWORD blockcount; +} FILEHEADER, *FILEHEADERPTR; + +typedef struct _HASHENTRY { + DWORD hashcheck[2]; + LCID lcid; + DWORD block; +} HASHENTRY, *HASHENTRYPTR; + +typedef struct _BLOCKENTRY { + DWORD offset; + DWORD sizealloc; + DWORD sizefile; + DWORD flags; +} BLOCKENTRY, *BLOCKENTRYPTR; + +NODEDECL(ARCHIVEREC) { + char name[MAX_PATH]; + HANDLE handle; + BOOL cdrom; + int priority; + LPVOID sectorfile; + DWORD sectorlocation; + DWORD sectorsize; + LPBYTE sectorbuffer; + DWORD sectorbytesread; + DWORD startinglocation; + BLOCKENTRYPTR blocktable; + FILEHEADERPTR fileheader; + HASHENTRYPTR hashtable; + DWORD lastlocation; +} *ARCHIVEPTR; + +NODEDECL(FILEREC) { + char name[MAX_PATH]; + HANDLE handle; + ARCHIVEPTR archive; + BLOCKENTRYPTR block; + DWORD key; + DWORD location; + DWORD lastlocation; + DWORD sectors; + LPDWORD sectoroffsettable; + BOOL sectoroffsettablevalid; + BOOL dda; + LPVOID readaheadbuffer; + DWORD readaheadoffset; + DWORD readaheadbytes; +} *FILEPTR; + +typedef struct CKINFO { + DWORD size; + DWORD offset; +} CKINFO; + +NODEDECL(AUDIOSTREAM) { + FILEPTR file; + DWORD nextwrite; + DWORD bytespersecond; + BOOL loop; + DWORD fillstatus; + DWORD bytespastend; + DWORD startinglocation; + DWORD totalsize; + LONG volume; + LONG pan; + LPDIRECTSOUNDBUFFER soundbuffer; + DWORD soundbuffersize; + BYTE fillvalue; +} *AUDIOSTREAMPTR; + +NODEDECL(REQUEST) { + HANDLE event; + FILEPTR file; + DWORD location; + DWORD approxarchivelocation; + DWORD requiredcompletiontime; + LPVOID buffer; + LPDIRECTSOUNDBUFFER soundbuffer; + DWORD soundbufferoffset; + AUDIOSTREAMPTR stream; + DWORD bytestoread; + BOOL autodelrequest; + DWORD bytesread; + DWORD sequence; + DWORD dependentsequence; +} *REQUESTPTR; + +static const AUTHCOMPANYINFO s_authcompany[AUTHCOMPANIES] = {{"BLIZZARDKEY",SFILE_AUTH_AUTHENTICBLIZZARD}}; + +static LIST(ARCHIVEREC) s_archivelist; +static char s_basepath[MAX_PATH] = ""; +static HANDLE s_cdevent = INVALID_HANDLE_VALUE; +static LIST(REQUEST) s_cdreqlist; +static BOOL s_cdshutdown = 0; +static HANDLE s_cdthread = INVALID_HANDLE_VALUE; +static CCritSect s_critsect; +static LPDIRECTSOUND s_directsound = NULL; +static BOOL s_enabledirect = 0; +static LPVOID s_explodebuffer = NULL; +static LIST(FILEREC) s_filelist; +static LPDWORD s_hashsource = NULL; +static DWORD s_ioerrormode = SFILE_ERRORMODE_FATAL; +static SFILEERRORPROC s_ioerrorproc = NULL; +static LCID s_lcid = MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT); +static LPVOID s_soundreadbuffer = NULL; +static LIST(AUDIOSTREAM) s_streamlist; + +#ifdef _DEBUG +static CSLog s_log("Internal","SFile Trace File"); +#define TRACEHANDLE s_log.GetHandle() +#define TRACEOUT SLogWrite +#else +#define TRACEHANDLE 0 +#define TRACEOUT +#endif + +/**************************************************************************** +* +* DATA DECOMPRESSION (PKWARE) SUPPORT +* +***/ + +typedef struct _DECOMPRESSIONINFO { + LPVOID sourcebuffer; + DWORD sourceoffset; + LPVOID destbuffer; + DWORD destoffset; + DWORD bytes; +} DECOMPRESSIONINFO, *DECOMPRESSIONPTR; + +//=========================================================================== +static UINT __cdecl DecompressLzw_BufferRead (LPSTR buffer, + UINT *size, + LPVOID param) { + DECOMPRESSIONPTR infoptr = (DECOMPRESSIONPTR)param; + UINT bytes = min(*size,infoptr->bytes-infoptr->sourceoffset); + CopyMemory(buffer,(LPSTR)infoptr->sourcebuffer+infoptr->sourceoffset,bytes); + infoptr->sourceoffset += bytes; + return bytes; +} + +//=========================================================================== +static void __cdecl DecompressLzw_BufferWrite (LPSTR buffer, + UINT *size, + LPVOID param) { + DECOMPRESSIONPTR infoptr = (DECOMPRESSIONPTR)param; + CopyMemory((LPSTR)infoptr->destbuffer+infoptr->destoffset,buffer,*size); + infoptr->destoffset += *size; +} + +//=========================================================================== +static BOOL DecompressLzw (LPBYTE dest, LPBYTE source, DWORD sourcebytes) { + + // CREATE A DECOMPRESSION BUFFER IF ONE DOES NOT ALREADY EXIST + if (!s_explodebuffer) + s_explodebuffer = ALLOC(EXP_BUFFER_SIZE); + + // CREATE AN INFORMATION RECORD + DECOMPRESSIONINFO info; + info.sourcebuffer = source; + info.sourceoffset = 0; + info.destbuffer = dest; + info.destoffset = 0; + info.bytes = sourcebytes; + + // PERFORM THE DECOMPRESSION + explode(DecompressLzw_BufferRead, + DecompressLzw_BufferWrite, + (LPSTR)s_explodebuffer, + &info); + + return 1; +} + +/**************************************************************************** +* +* DATA DECRYPTION SUPPORT +* +***/ + +//=========================================================================== +static void inline Decrypt (LPDWORD data, DWORD bytes, DWORD key) { + DWORD adjust = 0xEEEEEEEE; + DWORD iter = bytes >> 2; + while (iter--) { + adjust += *(s_hashsource+(HASH_ENCRYPTDATA << 8)+(key & 0xFF)); + adjust += (*data++ ^= adjust+key)+(adjust << 5)+3; + key = (key >> 11) | ((key << 21) ^ 0xFFE00000)+0x11111111; + } +} + +/**************************************************************************** +* +* MOPAQ FILE PROCESSING FUNCTIONS +* +***/ + +static BOOL ReadFileChecked (HANDLE file, + LPVOID buffer, + DWORD bytestoread, + DWORD *bytesread, + LPOVERLAPPED overlapped, + LPCTSTR filename); + +//=========================================================================== +static DWORD inline Hash (LPCSTR filename, int hashtype) { + DWORD result = 0x7FED7FED; + DWORD adjust = 0xEEEEEEEE; + while (filename && *filename) { + char origchar = toupper(*filename++); + result = (result+adjust) ^ *(s_hashsource+(hashtype << 8)+origchar); + adjust += origchar+result+(adjust << 5)+3; + } + return result; +} + +//=========================================================================== +static DWORD inline Hash (LPCWSTR filename, int hashtype) { + DWORD result = 0x7FED7FED; + DWORD adjust = 0xEEEEEEEE; + while (filename && *filename) { + char origchar = toupper((char)((*filename++) & 0xFF)); + result = (result+adjust) ^ *(s_hashsource+(hashtype << 8)+origchar); + adjust += origchar+result+(adjust << 5)+3; + } + return result; +} + +//=========================================================================== +static void inline InitializeHashSource () { + if (!s_hashsource) + return; + DWORD seed = 0x100001; + for (int loop1 = 0; loop1 < 256; ++loop1) + for (int loop2 = 0; loop2 < 5; ++loop2) { + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand1 = seed & 0xFFFF; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand2 = seed & 0xFFFF; + *(s_hashsource+(loop2 << 8)+loop1) = (rand1 << 16) | rand2; + } +} + +//=========================================================================== +static DWORD InternalReadAligned (FILEPTR file, + DWORD location, + LPVOID buffer, + DWORD bytes) { + + // ENSURE THAT THE READ IS SECTOR ALIGNED + VALIDATEBEGIN; + VALIDATE(!(location & (file->archive->sectorsize-1))); + VALIDATE(!(bytes & (file->archive->sectorsize-1))); + VALIDATEEND; + + // CHECK FOR A NULL READ + if (!bytes) + return FALSE; + + // IF THIS FILE IS COMPRESSED AND WE HAVEN'T YET READ THE SECTOR + // OFFSET TABLE, READ IT NOW + if ((file->block->flags & MPQ_COMPRESSEDMASK) && + !file->sectoroffsettablevalid) { + if (file->block->offset != file->archive->lastlocation) + SetFilePointer(file->archive->handle,file->block->offset,NULL,FILE_BEGIN); + DWORD bytesread = 0; + ReadFileChecked(file->archive->handle, + file->sectoroffsettable, + (file->sectors+1)*sizeof(DWORD), + &bytesread, + NULL, + file->archive->name); + if (file->block->flags & MPQ_ENCRYPTED) + Decrypt((LPDWORD)file->sectoroffsettable, + bytesread, + file->key+0xFFFFFFFF); + file->sectoroffsettablevalid = TRUE; + file->archive->lastlocation = file->block->offset+bytesread; + } + + // DETERMINE THE DISK LOCATION AND SIZE, GIVEN THE UNCOMPRESSED LOCATION + // AND SIZE + DWORD disklocation = location; + DWORD diskbytes = bytes; + if (file->block->flags & MPQ_COMPRESSEDMASK) { + disklocation = *(file->sectoroffsettable+location/file->archive->sectorsize); + diskbytes = *(file->sectoroffsettable+(location+bytes)/file->archive->sectorsize) + -disklocation; + } + + // PROVIDE A SECONDARY BUFFER IF NECESSARY FOR DECOMPRESSION + LPVOID diskbuffer = buffer; + if (file->block->flags & MPQ_COMPRESSEDMASK) + diskbuffer = ALLOC(diskbytes+sizeof(DWORD)); + + // SET THE ARCHIVE FILE POINTER IF NECESSARY + DWORD archivelocation = file->block->offset+disklocation; + if (archivelocation != file->archive->lastlocation) + SetFilePointer(file->archive->handle,archivelocation,NULL,FILE_BEGIN); + + // PERFORM THE READ + DWORD diskbytesread = 0; + ReadFileChecked(file->archive->handle, + diskbuffer, + diskbytes, + &diskbytesread, + NULL, + file->archive->name); + + // SAVE THE NEW ARCHIVE FILE POINTER + file->archive->lastlocation = archivelocation+diskbytesread; + + // IF WE WERE NOT ABLE TO READ THE ENTIRE REQUEST, DETERMINE A NUMBER OF + // UNCOMPRESSED BYTES THAT WE KNOW AT A MINIMUM WE READ SUCCESSFULLY + DWORD bytesread = bytes; + if (diskbytesread < diskbytes) + if (file->block->flags & MPQ_COMPRESSEDMASK) { + bytesread = 0; + DWORD checksector = location/file->archive->sectorsize+1; + while ((checksector <= file->sectors) && + (diskbytesread >= (*(file->sectoroffsettable+checksector)-disklocation))) { + ++checksector; + bytesread += file->archive->sectorsize; + } + } + else + bytesread = diskbytesread; + + // DECRYPT THE DATA IF NECESSARY + if (file->block->flags & MPQ_ENCRYPTED) { + DWORD offset = 0; + DWORD sector = location/file->archive->sectorsize; + DWORD sectors = (bytesread+file->archive->sectorsize-1)/file->archive->sectorsize; + while ((sector < file->sectors) && sectors--) { + DWORD processbytes; + if (file->block->flags & MPQ_COMPRESSEDMASK) + processbytes = *(file->sectoroffsettable+sector+1)-*(file->sectoroffsettable+sector); + else { + processbytes = min(file->archive->sectorsize,bytesread-offset); + if ((sector == file->sectors-1) && + (file->block->sizefile & (file->archive->sectorsize-1))) + processbytes = min(processbytes,file->block->sizefile & (file->archive->sectorsize-1)); + } + Decrypt((LPDWORD)((LPBYTE)diskbuffer+offset), + processbytes & 0xFFFFFFFC, + file->key+sector); + ++sector; + offset += processbytes; + } + } + + // DECOMPRESS THE DATA IF NECESSARY + if (file->block->flags & MPQ_COMPRESSEDMASK) { + DWORD destoffset = 0; + DWORD sourceoffset = 0; + DWORD sector = location/file->archive->sectorsize; + DWORD sectors = (bytesread+file->archive->sectorsize-1)/file->archive->sectorsize; + while ((sector < file->sectors) && sectors--) { + DWORD sourcebytes = *(file->sectoroffsettable+sector+1)-*(file->sectoroffsettable+sector); + DWORD targetbytes = (sector == file->sectors-1) + ? (file->block->sizefile && !(file->block->sizefile & (file->archive->sectorsize-1))) + ? file->archive->sectorsize + : (file->block->sizefile & (file->archive->sectorsize-1)) + : file->archive->sectorsize; + if (targetbytes > sourcebytes) + switch (file->block->flags & MPQ_COMPRESSEDMASK) { + + case MPQ_COMPRESSED_PKWARE: + DecompressLzw((LPBYTE)buffer+destoffset, + (LPBYTE)diskbuffer+sourceoffset, + sourcebytes); + break; + + case MPQ_COMPRESSED_SCOMP: + { + DWORD destsize = targetbytes; + SCompDecompress((LPBYTE)buffer+destoffset, + &destsize, + (LPBYTE)diskbuffer+sourceoffset, + sourcebytes); + } + break; + + } + else if (diskbuffer != buffer) + CopyMemory((LPBYTE)buffer+destoffset, + (LPBYTE)diskbuffer+sourceoffset, + targetbytes); + destoffset += targetbytes; + sourceoffset += sourcebytes; + ++sector; + } + } + + // FREE THE DECOMPRESSION BUFFER IF NECESSARY + if (diskbuffer != buffer) + FREE(diskbuffer); + + // RETURN THE NUMBER OF BYTES READ + return bytesread; +} + +//=========================================================================== +static DWORD InternalReadAlignedSector (FILEPTR file, + DWORD location) { + + // IF THIS SECTOR IS ALREADY IN THE SECTOR BUFFER, JUST RETURN THE + // PREVIOUS RESULTS + if ((file->archive->sectorfile == file) && + (file->archive->sectorlocation == location)) + return file->archive->sectorbytesread; + + // OTHERWISE, READ THE SECTOR + file->archive->sectorfile = file; + file->archive->sectorlocation = location; + file->archive->sectorbytesread = InternalReadAligned(file, + location, + file->archive->sectorbuffer, + file->archive->sectorsize); + + return file->archive->sectorbytesread; +} + +//=========================================================================== +static DWORD InternalReadUnaligned (FILEPTR file, + DWORD location, + LPVOID buffer, + DWORD bytes) { + + // CLIP THE READ SIZE AGAINST THE END OF THE FILE + if (file->block->sizefile <= location) + return 0; + else + bytes = min(bytes,file->block->sizefile-location); + + // READ THE FIRST SECTOR + DWORD firstbytesread = 0; + if (location & (file->archive->sectorsize-1)) { + DWORD sectorbytesread = InternalReadAlignedSector(file,location & ~(file->archive->sectorsize-1)); + DWORD unalignedbytes = min(bytes,file->archive->sectorsize-(location & (file->archive->sectorsize-1))); + CopyMemory(buffer, + file->archive->sectorbuffer+(location & (file->archive->sectorsize-1)), + unalignedbytes); + buffer = (LPBYTE)buffer+unalignedbytes; + bytes -= unalignedbytes; + if ((sectorbytesread != file->archive->sectorsize) || !bytes) + if (sectorbytesread < (location & (file->archive->sectorsize-1))) + return 0; + else + return min(unalignedbytes,sectorbytesread-(location & (file->archive->sectorsize-1))); + else + firstbytesread = unalignedbytes; + location += unalignedbytes; + } + + // READ IN THE MIDDLE SECTORS + DWORD middlebytesread = 0; + if (bytes) { + DWORD middlebytes = bytes & ~(file->archive->sectorsize-1); + middlebytesread = InternalReadAligned(file, + location, + buffer, + bytes & ~(file->archive->sectorsize-1)); + buffer = (LPBYTE)buffer+middlebytes; + bytes -= middlebytes; + location += middlebytes; + if ((middlebytes != middlebytesread) || !bytes) + return firstbytesread+middlebytesread; + } + + // READ IN THE LAST SECTOR + DWORD lastbytesread = 0; + if (bytes) { + DWORD sectorbytesread = InternalReadAlignedSector(file,location); + CopyMemory(buffer, + file->archive->sectorbuffer, + bytes); + lastbytesread = min(bytes,sectorbytesread); + } + + return firstbytesread+middlebytesread+lastbytesread; +} + +//=========================================================================== +static BOOL ReadFileChecked (HANDLE file, + LPVOID buffer, + DWORD bytestoread, + DWORD *bytesread, + LPOVERLAPPED overlapped, + LPCTSTR filename) { + for (;;) { + BOOL result = ReadFile(file, + buffer, + bytestoread, + bytesread, + overlapped); + if (result && (*bytesread == bytestoread)) + return TRUE; + DWORD errorcode = GetLastError(); + switch (s_ioerrormode) { + + case SFILE_ERRORMODE_RETURNCODE: + return result; + + case SFILE_ERRORMODE_CUSTOM: + if ((!s_ioerrorproc) || + (!s_ioerrorproc(filename,errorcode))) + return result; + break; + + case SFILE_ERRORMODE_FATAL: + SErrDisplayError(errorcode, + filename, + SERR_LINECODE_FILE, + NULL, + FALSE, + 1); + break; + + } + } +} + +//=========================================================================== +static DWORD inline SearchHashTable (ARCHIVEPTR archive, LPCTSTR filename, LCID lcid) { + DWORD hashindex = Hash(filename,HASH_INDEX); + DWORD hashcheck0 = Hash(filename,HASH_CHECK0); + DWORD hashcheck1 = Hash(filename,HASH_CHECK1); + DWORD entry = hashindex & (archive->fileheader->hashcount-1); + DWORD firstentry = entry; + DWORD found = 0xFFFFFFFF; + while ((archive->hashtable+entry)->block != NOBLOCK) { + if (((archive->hashtable+entry)->hashcheck[0] == hashcheck0) && + ((archive->hashtable+entry)->hashcheck[1] == hashcheck1) && + ((archive->hashtable+entry)->block != DEALLOCATED)) + if ((archive->hashtable+entry)->lcid == lcid) + return entry; + else if ((archive->hashtable+entry)->lcid == MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT)) + found = entry; + entry = (entry+1) & (archive->fileheader->hashcount-1); + if (entry == firstentry) + break; + } + return found; +} + +/**************************************************************************** +* +* STREAMING AND OVERLAPPED I/O FUNCTIONS +* +***/ + +static REQUESTPTR IssueRequest (FILEPTR file, + DWORD locationoffset, + LPVOID buffer, + LPDIRECTSOUNDBUFFER soundbuffer, + DWORD soundbufferoffset, + AUDIOSTREAMPTR stream, + DWORD bytestoread, + DWORD requiredms, + DWORD dependentsequence, + HANDLE event, + BOOL autodelrequest, + BOOL triggerreadthread, + DWORD *sequence); + +//=========================================================================== +static inline BOOL CanProcessRequest (REQUESTPTR request) { + DWORD dependentsequence = request->dependentsequence; + if (dependentsequence) + ITERATELIST(REQUEST,s_cdreqlist,curr) + if (curr->sequence == dependentsequence) + return FALSE; + return TRUE; +} + +//=========================================================================== +static DWORD CALLBACK CdThreadProc (LPVOID) { + ARCHIVEPTR lastarchive = NULL; + DWORD lastarchivelocation = 0; + while (!s_cdshutdown) { + BOOL processed; + do { + processed = 0; + + // IF THERE ARE ANY ACTIVE AUDIO STREAMS, ISSUE READ REQUESTS AS + // NECESSARY TO KEEP THEIR BUFFERS FULL + s_critsect.Enter(); + { + AUDIOSTREAMPTR curr = s_streamlist.Head(); + while (curr) { + + // IF THIS STREAM HAS REACHED THE END OF THE WAVE FILE, EITHER LOOP + // OR WAIT UNTIL THE BUFFER IS DONE PLAYING BEFORE CLOSING THE + // STREAM + if ((curr->fillstatus == FILL_CLOSING) || + ((curr->fillstatus == FILL_PLAYING) && + (curr->file->location >= curr->totalsize))) + if (curr->loop) + curr->file->location = curr->startinglocation; + else { + DWORD playcursor = 0; + DWORD writecursor = 0; + curr->soundbuffer->GetCurrentPosition(&playcursor,&writecursor); + if (((playcursor-curr->nextwrite) % curr->soundbuffersize) >= WAVECHUNKSIZE) { + DWORD sizeneeded = min(WAVECHUNKSIZE,curr->soundbuffersize-curr->nextwrite); + LPVOID buffer = NULL; + DWORD bytes = sizeneeded; + if (curr->soundbuffer->Lock(curr->nextwrite, + sizeneeded, + &buffer, + &bytes, + NULL, + NULL, + 0) == DS_OK) { + FillMemory(buffer,bytes,curr->fillvalue); + curr->soundbuffer->Unlock(buffer, + bytes, + NULL, + 0); + curr->bytespastend += bytes; + curr->nextwrite += bytes; + if (curr->nextwrite >= curr->soundbuffersize) + curr->nextwrite -= curr->soundbuffersize; + } + } + curr->fillstatus = FILL_CLOSING; + } + + // IF THIS STREAM IS CURRENTLY PLAYING, CHECK WHETHER THERE IS ROOM + // TO LOAD ANOTHER CHUNK OF DATA + if (curr->fillstatus == FILL_PLAYING) { + DWORD playcursor = 0; + DWORD writecursor = 0; + curr->soundbuffer->GetCurrentPosition(&playcursor,&writecursor); + if (((playcursor-curr->nextwrite) % curr->soundbuffersize) >= WAVECHUNKSIZE) { + DWORD sizeneeded = min(WAVECHUNKSIZE,curr->soundbuffersize-curr->nextwrite); + sizeneeded = min(sizeneeded,curr->totalsize-curr->file->location); + IssueRequest(curr->file, + curr->file->location, + NULL, + curr->soundbuffer, + curr->nextwrite, + curr, + sizeneeded, + ((curr->soundbuffersize-0x20000)*1000)/curr->bytespersecond, + 0, + NULL, + TRUE, + FALSE, + NULL); + curr->file->location += sizeneeded; + curr->nextwrite += (curr->loop ? sizeneeded : WAVECHUNKSIZE); + if (curr->nextwrite >= curr->soundbuffersize) + curr->nextwrite -= curr->soundbuffersize; + } + } + + // IF THIS STREAM IS NOT YET PLAYING, ISSUE THE INITIAL REQUESTS + // TO FILL THE BUFFER + else if (curr->fillstatus == FILL_UNREQUESTED) { + DWORD offset = 0; + DWORD maxoffset = min(curr->soundbuffersize,curr->totalsize); + DWORD timeoffset = 0; + while (offset < maxoffset) { + IssueRequest(curr->file, + curr->file->location, + NULL, + curr->soundbuffer, + offset, + curr, + min(WAVECHUNKSIZE,maxoffset-offset), + 1000+(timeoffset += 500), + 0, + NULL, + TRUE, + FALSE, + NULL); + curr->file->location += WAVECHUNKSIZE; + offset += WAVECHUNKSIZE; + } + curr->fillstatus = FILL_REQUESTED; + curr->nextwrite = offset % curr->soundbuffersize; + } + + curr = curr->Next(); + } + } + + // FIND THE MOST URGENT REQUEST, AND THE REQUEST WHICH IS NEXT IN + // SEEK ORDER + REQUESTPTR nextreq = NULL; + REQUESTPTR urgentreq = NULL; + DWORD lowcompletetime = UINT_MAX; + { + DWORD lowseektime = UINT_MAX; + DWORD currtime = GetTickCount(); + ITERATELIST(REQUEST,s_cdreqlist,curr) + if (CanProcessRequest(curr)) { + + // CHECK THIS REQUEST FOR SEEK ORDER + { + DWORD adjlastlocation = 0; + if (lastarchivelocation > curr->file->archive->sectorsize) + adjlastlocation = lastarchivelocation-curr->file->archive->sectorsize; + DWORD seektime; + if (curr->file->archive == lastarchive) + if (curr->approxarchivelocation < adjlastlocation) + seektime = 0x8000000+curr->approxarchivelocation; + else + seektime = curr->approxarchivelocation-adjlastlocation; + else + seektime = UINT_MAX-1; + if (seektime <= lowseektime) { + lowseektime = seektime; + nextreq = curr; + } + } + + // CHECK THIS REQUEST FOR URGENCY + { + DWORD completetime; + if (currtime-curr->requiredcompletiontime < 0x7FFFFFFF) + completetime = 0; + else + completetime = curr->requiredcompletiontime-currtime; + if (completetime <= lowcompletetime) { + lowcompletetime = completetime; + urgentreq = curr; + } + } + + } + } + s_critsect.Leave(); + + // IF THE MOST URGENT REQUEST MUST COMPLETE IN THE NEXT + // 700 MILLISECONDS, PROCESS THAT REQUEST. OTHERWISE, PROCESS + // THE NEXT REQUEST IN SEEK ORDER + REQUESTPTR request = NULL; + if (urgentreq && (lowcompletetime <= 700)) + request = urgentreq; + else if (nextreq) + request = nextreq; + + // PERFORM THE REQUEST + if (request) { + + // READ THE DATA FROM CD + lastarchive = request->file->archive; + lastarchivelocation = request->approxarchivelocation; + LPVOID readbuffer = request->buffer; + if (request->soundbuffer) + readbuffer = s_soundreadbuffer; + if (readbuffer) + request->bytesread = InternalReadUnaligned(request->file, + request->location, + readbuffer, + request->bytestoread); + else + request->bytesread = 0; + + // IF THE DATA IS GOING INTO A SOUND BUFFER, LOCK THE SOUND BUFFER + // AND MOVE THE DATA + if (request->soundbuffer) { + request->soundbuffer->Lock(request->soundbufferoffset, + request->bytestoread, + &request->buffer, + &request->bytestoread, + NULL, + NULL, + 0); + CopyMemory(request->buffer,readbuffer,request->bytesread); + DWORD fullbytes = min(WAVECHUNKSIZE,request->stream->soundbuffersize-request->soundbufferoffset); + if ((request->bytesread < fullbytes) && !request->stream->loop) + FillMemory((LPBYTE)request->buffer+request->bytesread,fullbytes-request->bytesread,request->stream->fillvalue); + request->soundbuffer->Unlock(request->buffer, + request->bytestoread, + NULL, + 0); + if ((request->stream->fillstatus == FILL_REQUESTED) && + ((request->location+request->bytestoread >= request->stream->soundbuffersize) || + (request->location+request->bytestoread-request->stream->startinglocation >= request->stream->totalsize))) { + request->stream->soundbuffer->Play(0,0,DSBPLAY_LOOPING); + request->stream->fillstatus = FILL_PLAYING; + } + } + + // REMOVE THIS REQUEST + s_critsect.Enter(); + processed = TRUE; + HANDLE event = request->event; + if (request->autodelrequest) + s_cdreqlist.DeleteNode(request); + else + s_cdreqlist.UnlinkNode(request); + s_critsect.Leave(); + if (event) + SetEvent(event); + + } + + } while (processed); + WaitForSingleObject(s_cdevent,s_streamlist.IsEmpty() ? INFINITE : 250); + } + s_cdshutdown = FALSE; + _endthreadex(0); + return 0; +} + +//=========================================================================== +static void CreateCdThread () { + if (s_cdthread != INVALID_HANDLE_VALUE) + return; + s_cdevent = CreateEvent((LPSECURITY_ATTRIBUTES)NULL, + 0, + 0, + NULL); + DWORD threadid; + s_cdthread = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + CdThreadProc, + NULL, + 0, + &threadid); + SetThreadPriority(s_cdthread,THREAD_PRIORITY_ABOVE_NORMAL); +} + +//=========================================================================== +static REQUESTPTR IssueRequest (FILEPTR file, + DWORD offset, + LPVOID buffer, + LPDIRECTSOUNDBUFFER soundbuffer, + DWORD soundbufferoffset, + AUDIOSTREAMPTR stream, + DWORD bytestoread, + DWORD requiredms, + DWORD dependentsequence, + HANDLE event, + BOOL autodelrequest, + BOOL triggerreadthread, + DWORD *sequence) { + VALIDATEBEGIN; + VALIDATE(buffer || soundbuffer); + VALIDATEEND; + + // CREATE A REQUEST RECORD + s_critsect.Enter(); + static DWORD currsequence = 0; + REQUESTPTR request = s_cdreqlist.NewNode(); + DWORD requestsequence = 0; + request->event = event; + request->file = file; + request->location = offset; + request->approxarchivelocation = file->block->offset+offset/2; + request->requiredcompletiontime = GetTickCount()+requiredms; + request->buffer = buffer; + request->soundbuffer = soundbuffer; + request->soundbufferoffset = soundbufferoffset; + request->stream = stream; + request->bytestoread = bytestoread; + request->autodelrequest = autodelrequest; + request->dependentsequence = dependentsequence; + do + requestsequence = request->sequence = ++currsequence; + while (!requestsequence); + s_critsect.Leave(); + + // TRIGGER THE CD READ THREAD + if (triggerreadthread) + SetEvent(s_cdevent); + + if (sequence) + *sequence = requestsequence; + return request; +} + +/**************************************************************************** +* +* SUPPORT/UTILITY FUNCTIONS +* +***/ + +//=========================================================================== +static void BuildDefaultBasePath () { + GetModuleFileName(GetModuleHandle(NULL),s_basepath,MAX_PATH); + { + LPTSTR separator = SStrChr(s_basepath,'\\'); + while (separator && SStrChr(separator+1,'\\')) + separator = SStrChr(separator+1,'\\'); + if (separator) + *separator = 0; + } + SStrPack(s_basepath,"\\",MAX_PATH); +} + +//=========================================================================== +static BOOL CheckArchiveHandle (HSARCHIVE archive, ARCHIVEPTR *archiveptr) { + + // CONVERT THE FILE HANDLE INTO AN ARCHIVE POINTER + *archiveptr = (ARCHIVEPTR)archive; + + // DETERMINE WHETHER THE ARCHIVE POINTER IS VALID + BOOL valid = FALSE; + ITERATELIST(ARCHIVEREC,s_archivelist,currptr) + if (currptr == *archiveptr) { + valid = TRUE; + break; + } + + // IF IT IS VALID, RETURN SUCCESS + if (valid) + return TRUE; + + // OTHERWISE, SET THE ERROR CODE + SErrSetLastError(SFILE_ERROR_INVALID_HANDLE); + + // GENERATE AN ERROR MESSAGE + switch (s_ioerrormode) { + + case SFILE_ERRORMODE_CUSTOM: + if (s_ioerrorproc) + s_ioerrorproc("", + SFILE_ERROR_INVALID_HANDLE); + break; + + case SFILE_ERRORMODE_FATAL: + SErrDisplayError(SFILE_ERROR_INVALID_HANDLE, + "HSARCHIVE", + SERR_LINECODE_HANDLE, + NULL, + TRUE, + 1); + break; + + } + + return FALSE; +} + +//=========================================================================== +static BOOL CheckFileHandle (HSFILE file, FILEPTR *fileptr) { + + // CONVERT THE FILE HANDLE INTO A FILE POINTER + *fileptr = (FILEPTR)file; + + // DETERMINE WHETHER THE FILE POINTER IS VALID + BOOL valid = FALSE; + ITERATELIST(FILEREC,s_filelist,currptr) + if (currptr == *fileptr) { + valid = TRUE; + break; + } + + // IF IT IS VALID, RETURN SUCCESS + if (valid) + return TRUE; + + // OTHERWISE, SET THE ERROR CODE + SErrSetLastError(SFILE_ERROR_INVALID_HANDLE); + + // GENERATE AN ERROR MESSAGE + switch (s_ioerrormode) { + + case SFILE_ERRORMODE_CUSTOM: + if (s_ioerrorproc) + s_ioerrorproc("", + SFILE_ERROR_INVALID_HANDLE); + break; + + case SFILE_ERRORMODE_FATAL: + SErrDisplayError(SFILE_ERROR_INVALID_HANDLE, + "HSFILE", + SERR_LINECODE_HANDLE, + NULL, + TRUE, + 1); + break; + + } + + return FALSE; +} + +//=========================================================================== +static BOOL inline CheckForCdRom (LPCTSTR path) { + + // DETERMINE THE ROOT PATH OF THE DRIVE + char rootpath[4]; + SStrCopy(rootpath,path,4); + + // GET THE DRIVE TYPE + UINT drivetype = GetDriveType(rootpath); + + // GET THE FILE SYSTEM INFORMATION. RETURN FAILURE IF THERE IS NO MEDIA + // IN THE DRIVE. + DWORD fsflags = 0; + char fsname[MAX_PATH]; + ZeroMemory(fsname,MAX_PATH); + if (!GetVolumeInformation(rootpath,NULL,0,NULL,NULL,&fsflags,fsname,MAX_PATH)) + return 0; + + // GET THE SECTOR FORMAT AND NUMBER OF FREE SECTORS + DWORD sectorspercluster = 0; + DWORD bytespersector = 0; + DWORD freeclusters = 0; + DWORD totalclusters = 0; + if (!GetDiskFreeSpace(rootpath,§orspercluster,&bytespersector,&freeclusters,&totalclusters)) + return 0; + + // CONFIRM THAT: + // 1. THE DRIVE TYPE IS CD-ROM + // 2. THE FILE SYSTEM IS CDFS OR UNKNOWN (BLANK) + // 3. THE FILE SYSTEM DOES NOT SUPPORT UNICODE + // 4. THE SECTORS ARE 2048 BYTES EACH + // 5. THERE ARE NO FREE CLUSTERS ON THE DISK + DWORD value = drivetype ^ (*(LPDWORD)fsname) + ^ (fsflags & FS_UNICODE_STORED_ON_DISK) + ^ bytespersector + ^ freeclusters; + WORD check = LOWORD(value) ^ HIWORD(value); + return ((check == 0x1F00) || (check == 0x0805)); +} + +//=========================================================================== +static void ConvertRelativePathName (LPCTSTR inputpath, LPTSTR outputpath) { + + // DETERMINE THE BASE PATH + if (!s_basepath[0]) + BuildDefaultBasePath(); + + // COMBINE THE BASE PATH AND THE INPUT PATH TO FORM THE OUTPUT PATH + char absolutepath[MAX_PATH] = ""; + wsprintf(absolutepath,"%s%s",s_basepath,inputpath); + _fullpath(outputpath,absolutepath,MAX_PATH); + +} + +//=========================================================================== +static BOOL FindChunk (HSFILE handle, FOURCC ckid, CKINFO *pck) { + struct { + FOURCC ckid; + DWORD size; + } ckhdr; + + for (;;) { + if (!SFileReadFile(handle,&ckhdr,sizeof(ckhdr),NULL,NULL)) + return 0; + if (ckhdr.ckid == ckid) + break; + if (SFileSetFilePointer(handle,ckhdr.size,NULL,FILE_CURRENT) == 0xFFFFFFFF) + return 0; + } + + pck->size = ckhdr.size; + pck->offset = SFileSetFilePointer(handle,0,NULL,FILE_CURRENT); + return (pck->offset != 0xFFFFFFFF); +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SFileAuthenticateArchive (HSARCHIVE handle, + DWORD *extendedresult) { + TRACEOUT(TRACEHANDLE, + "SFileAuthenticateArchive(0x%x,*extendedresult)", + handle); + + if (extendedresult) + *extendedresult = SFILE_AUTH_UNABLETOAUTHENTICATE; + + // CHECK THE ARCHIVE HANDLE + ARCHIVEPTR archiveptr; + if (!CheckArchiveHandle(handle,&archiveptr)) + return FALSE; + + // DO A PRELIMINARY CHECK FOR A SIGNATURE BLOCK IN THIS ARCHIVE BEFORE + // WE GO TO ALL THE TROUBLE OF BINDING TO THE CRYPTO API AND SECURITY + // SUPPORT PROVIDER + LCID defaultlcid = MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT); + if (SearchHashTable(archiveptr,SIGNATUREFILE,defaultlcid) == 0xFFFFFFFF) { + if (extendedresult) + *extendedresult = SFILE_AUTH_NOSIGNATURE; + SErrSetLastError(SFILE_ERROR_NOT_AUTHENTICATED); + return 0; + } + + CRYPTOAPIPTR cryptoapi = NULL; + HCRYPTHASH hash = (HCRYPTHASH)0; + HCRYPTKEY key = (HCRYPTKEY)0; + HINSTANCE lib = (HINSTANCE)0; + HANDLE map = (HANDLE)0; + HCRYPTPROV provider = (HCRYPTPROV)0; + BOOL result = 0; + LPVOID view = NULL; + + TRY { + + // BIND TO THE CRYPTOGRAPHY LIBRARY + lib = LoadLibrary("advapi32.dll"); + if (!lib) + LEAVE; + cryptoapi = (CRYPTOAPIPTR)ALLOC(sizeof(CRYPTOAPI)); +#define BIND(a,b) *(void **)&cryptoapi->##a = GetProcAddress(lib,b); \ + if (!cryptoapi->##a) LEAVE; + BIND(CryptAcquireContext ,"CryptAcquireContextA" ); + BIND(CryptCreateHash ,"CryptCreateHash" ); + BIND(CryptDestroyHash ,"CryptDestroyHash" ); + BIND(CryptDestroyKey ,"CryptDestroyKey" ); + BIND(CryptHashData ,"CryptHashData" ); + BIND(CryptImportKey ,"CryptImportKey" ); + BIND(CryptReleaseContext ,"CryptReleaseContext" ); + BIND(CryptSignHash ,"CryptSignHashA" ); + BIND(CryptVerifySignature,"CryptVerifySignatureA"); +#undef BIND + + // INITIALIZE SECURITY SUPPORT + if (!cryptoapi->CryptAcquireContext(&provider,KEYCONTAINER,MS_DEF_PROV,PROV_RSA_FULL,0)) + if (!cryptoapi->CryptAcquireContext(&provider,KEYCONTAINER,MS_DEF_PROV,PROV_RSA_FULL,CRYPT_NEWKEYSET)) + LEAVE; + + // MAP THE ENTIRE ARCHIVE FILE INTO MEMORY + map = CreateFileMapping(archiveptr->handle,NULL,PAGE_READONLY | SEC_COMMIT,0,0,NULL); + if (!map) + LEAVE; + view = MapViewOfFile(map,FILE_MAP_READ,0,0,0); + if (!view) + LEAVE; + + // DETERMINE THE LOCATION OF THE SIGNATURE BLOCK + DWORD index = SearchHashTable(archiveptr,SIGNATUREFILE,defaultlcid); + if (index == 0xFFFFFFFF) + LEAVE; + BLOCKENTRYPTR block = archiveptr->blocktable+(archiveptr->hashtable+index)->block; + if ((block->flags & (MPQ_COMPRESSEDMASK | MPQ_ENCRYPTED)) || + (block->sizefile <= sizeof(SIGNATUREHEADER)) || + !block->offset) { + if (extendedresult) + *extendedresult = SFILE_AUTH_BADSIGNATURE; + LEAVE; + } + + // DETERMINE THE COMPANY ID + DWORD companyid = ((SIGNATUREHEADERPTR)((LPBYTE)view+block->offset))->companyid; + if (companyid >= AUTHCOMPANIES) { + if (extendedresult) + *extendedresult = SFILE_AUTH_UNKNOWNSIGNATURE; + LEAVE; + } + + // LOAD THE APPROPRIATE COMPANY'S PUBLIC KEY INTO THE KEY DATABASE + { + HRSRC resource = FindResource(StormGetInstance(),s_authcompany[companyid].keyname,"#256"); + HGLOBAL handle = LoadResource(StormGetInstance(),resource); + LPVOID ptr = LockResource(handle); + if (ptr) + cryptoapi->CryptImportKey(provider, + (LPBYTE)ptr, + SizeofResource(StormGetInstance(),resource), + NULL, + 0, + &key); + FreeResource(handle); + } + if (!key) + LEAVE; + + // HASH THE ARCHIVE FILE, REPLACING THE SIGNATURE BLOCK WITH ZEROES. + // IF THIS ARCHIVE FILE IS EMBEDDED IN A LARGER FILE, ONLY HASH THE + // MOPAQ PORTION. + if (!cryptoapi->CryptCreateHash(provider,CALG_MD5,NULL,0,&hash)) + LEAVE; + if (!cryptoapi->CryptHashData(hash, + (LPBYTE)view+archiveptr->startinglocation, + block->offset-archiveptr->startinglocation, + 0)) + LEAVE; + { + LPVOID zeroblock = ALLOCZERO(block->sizefile); + BOOL hashresult = cryptoapi->CryptHashData(hash, + (LPBYTE)zeroblock, + block->sizefile, + 0); + FREE(zeroblock); + if (!hashresult) + LEAVE; + } + if (block->offset+block->sizefile < archiveptr->startinglocation+archiveptr->fileheader->filesize) + if (!cryptoapi->CryptHashData(hash, + (LPBYTE)view+block->offset+block->sizefile, + archiveptr->startinglocation+archiveptr->fileheader->filesize + -(block->offset+block->sizefile), + 0)) + LEAVE; + + // VERIFY THE SIGNATURE BLOCK AGAINST THE HASH VALUE + if (cryptoapi->CryptVerifySignature(hash, + (LPBYTE)view+block->offset+sizeof(SIGNATUREHEADER), + block->sizefile-sizeof(SIGNATUREHEADER), + key, + NULL, + 0)) { + result = 1; + if (extendedresult) + *extendedresult = s_authcompany[companyid].authresult; + } + else if (extendedresult) + *extendedresult = SFILE_AUTH_BADSIGNATURE; + + } + FINALLY { + if (hash) + cryptoapi->CryptDestroyHash(hash); + if (key) + cryptoapi->CryptDestroyKey(key); + if (view) + UnmapViewOfFile(view); + if (map) + CloseHandle(map); + if (provider) { + cryptoapi->CryptReleaseContext(provider,0); + cryptoapi->CryptAcquireContext(&provider,KEYCONTAINER,MS_DEF_PROV,PROV_RSA_FULL,CRYPT_DELETEKEYSET); + } + if (cryptoapi) + FREE(cryptoapi); + if (lib) + FreeLibrary(lib); + } + + if (!result) + SErrSetLastError(SFILE_ERROR_NOT_AUTHENTICATED); + return result; +} + +//=========================================================================== +BOOL APIENTRY SFileCloseArchive (HSARCHIVE handle) { + TRACEOUT(TRACEHANDLE, + "SFileCloseArchive(0x%x)", + handle); + + // CHECK THE ARCHIVE HANDLE + ARCHIVEPTR archiveptr; + if (!CheckArchiveHandle(handle,&archiveptr)) + return FALSE; + + // CLOSE ALL FILES ASSOCIATED WITH THIS ARCHIVE + { + FILEPTR curr = s_filelist.Head(); + while (curr) { + FILEPTR next = curr->Next(); + if (curr->archive == archiveptr) + SFileCloseFile((HSFILE)curr); + curr = next; + } + } + + // FREE MEMORY + if (archiveptr->sectorbuffer) + FREE(archiveptr->sectorbuffer); + if (archiveptr->blocktable) + FREE(archiveptr->blocktable); + if (archiveptr->fileheader) + DEL(archiveptr->fileheader); + if (archiveptr->hashtable) + FREE(archiveptr->hashtable); + + // CLOSE THE ARCHIVE FILE + CloseHandle(archiveptr->handle); + + // UNLINK AND FREE THE ARCHIVE + s_critsect.Enter(); + s_archivelist.DeleteNode(archiveptr); + s_critsect.Leave(); + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileCloseFile (HSFILE handle) { + TRACEOUT(TRACEHANDLE, + "SFileCloseFile(0x%x)", + handle); + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return FALSE; + + // END ANY DDA STREAMS ASSOCIATED WITH THIS FILE + if (fileptr->dda) + SFileDdaEnd(handle); + + // WAIT UNTIL ALL OUTSTANDING READ OPERATIONS FOR THIS FILE COMPLETE. + // IF WE ARE IN DEBUG MODE, DISPLAY A WARNING IF THE APPLICATION TRIES + // TO CLOSE A FILE WHILE THERE ARE OUTSTANDING OVERLAPPED READ OPERATIONS + // ON THAT FILE. + s_critsect.Enter(); + for (;;) { + BOOL outstanding = FALSE; + ITERATELIST(REQUEST,s_cdreqlist,curr) + if (curr->file == fileptr) { + outstanding = TRUE; + break; + } + if (outstanding) { +#ifdef _DEBUG + SErrDisplayError(ERROR_IO_PENDING, + "SFileCloseFile()", + SERR_LINECODE_FUNCTION, + NULL, + TRUE); +#endif + Sleep(1); + } + else + break; + } + + // CLOSE THE FILE HANDLE IF USED + if (fileptr->handle != INVALID_HANDLE_VALUE) + CloseHandle(fileptr->handle); + + // CLEAR THE SECTOR CACHE + if (fileptr->archive) + fileptr->archive->sectorfile = NULL; + + // FREE THE SECTOR OFFSET TABLE + if (fileptr->sectoroffsettable) + FREE(fileptr->sectoroffsettable); + + // FREE THE READ AHEAD BUFFER + if (fileptr->readaheadbuffer) + FREE(fileptr->readaheadbuffer); + + // UNLINK AND FREE THE FILE + s_filelist.DeleteNode(fileptr); + s_critsect.Leave(); + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileDdaBegin (HSFILE handle, + DWORD buffersize, + DWORD flags) { + TRACEOUT(TRACEHANDLE, + "SFileDdaBegin(0x%x,%u,0x%x)", + handle,buffersize,flags); + + return SFileDdaBeginEx(handle, + buffersize, + flags, + 0, + 0x7FFFFFFF, + 0x7FFFFFFF, + NULL); +} + +//=========================================================================== +BOOL APIENTRY SFileDdaBeginEx (HSFILE handle, + DWORD buffersize, + DWORD flags, + DWORD offset, + LONG volume, + LONG pan, + LPVOID reserved) { + VALIDATEBEGIN; + VALIDATE(buffersize); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileDdaBeginEx(0x%x,%u,0x%x,%u,%d,%d,%u)", + handle,buffersize,flags,offset,volume,pan,reserved); + + if (!s_directsound) { + SErrSetLastError(SFILE_ERROR_NOT_INITIALIZED); + return 0; + } + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return FALSE; + + // STOP PLAYING THIS FILE IF IT IS ALREADY PLAYING + if (fileptr->dda) + SFileDdaEnd(handle); + + // ENSURE THAT THE FILE IS IN AN ARCHIVE + if ((fileptr->handle != INVALID_HANDLE_VALUE) || !fileptr->archive) { + SErrSetLastError(SFILE_ERROR_NOT_IN_ARCHIVE); + return 0; + } + + // MARK THIS FILE AS PLAYING + fileptr->dda = 1; + + // CREATE A SOUND READ BUFFER IF NECESSARY + if (!s_soundreadbuffer) + s_soundreadbuffer = ALLOC(WAVECHUNKSIZE); + + // IF THE FILE'S ARCHIVE IS NOT ON CD, START PROCESSING IT AS A CD ARCHIVE + // ANYWAY, BECAUSE THE CD READ THREAD DOES THE WORK OF READING BACKGROUND + // STREAM DATA + if (fileptr->archive->cdrom == CDROM_FALSE) { + fileptr->archive->cdrom = CDROM_USEDFORDDA; + if (s_cdthread == INVALID_HANDLE_VALUE) + CreateCdThread(); + } + + // ADJUST THE BUFFER SIZE SO IT IS A MULTIPLE OF 64K AND AT LEAST 128K + if (buffersize & (WAVECHUNKSIZE-1)) + buffersize += WAVECHUNKSIZE-(buffersize & (WAVECHUNKSIZE-1)); + if (buffersize < 2*WAVECHUNKSIZE) + buffersize = 2*WAVECHUNKSIZE; + + // READ THE WAVE FILE HEADER + WAVEFORMATEX format; + DWORD startinglocation; + DWORD totalsize; + { + SFileSetFilePointer(handle,0,NULL,FILE_BEGIN); + MMCKINFO mmck; + if (!SFileReadFile(handle,&mmck,sizeof(FOURCC)*2+sizeof(DWORD),NULL,NULL)) + return 0; + if ((mmck.ckid != FOURCC_RIFF) || (mmck.fccType != mmioFOURCC('W','A','V','E'))) { + SErrSetLastError(SFILE_ERROR_INVALID_DATA); + return 0; + } + CKINFO info; + if (!FindChunk(handle,mmioFOURCC('f','m','t',' '),&info)) { + SErrSetLastError(SFILE_ERROR_INVALID_DATA); + return 0; + } + if (info.size < sizeof(PCMWAVEFORMAT)) { + SErrSetLastError(SFILE_ERROR_INVALID_DATA); + return 0; + } + PCMWAVEFORMAT pcm; + if (!SFileReadFile(handle,&pcm,sizeof(PCMWAVEFORMAT),NULL,NULL)) + return 0; + if (SFileSetFilePointer(handle,info.size-sizeof(PCMWAVEFORMAT),NULL,FILE_CURRENT) == 0xFFFFFFFF) + return 0; + format.wFormatTag = pcm.wf.wFormatTag; + format.nChannels = pcm.wf.nChannels; + format.nSamplesPerSec = pcm.wf.nSamplesPerSec; + format.nAvgBytesPerSec = pcm.wf.nAvgBytesPerSec; + format.nBlockAlign = pcm.wf.nBlockAlign; + format.wBitsPerSample = pcm.wBitsPerSample; + format.cbSize = 0; + if (!FindChunk(handle,mmioFOURCC('d','a','t','a'),&info)) { + SErrSetLastError(SFILE_ERROR_INVALID_DATA); + return 0; + } + startinglocation = info.offset; + totalsize = info.size; + } + + // CREATE A STREAM RECORD + s_critsect.Enter(); + AUDIOSTREAMPTR stream = s_streamlist.NewNode(); + stream->file = fileptr; + stream->soundbuffersize = buffersize; + stream->bytespersecond = format.nAvgBytesPerSec; + stream->loop = ((flags & SFILE_DDA_LOOP) != 0); + stream->fillstatus = FILL_UNREQUESTED; + stream->startinglocation = startinglocation+min(offset,totalsize-startinglocation); + stream->totalsize = totalsize; + stream->volume = volume; + stream->pan = pan; + stream->fillvalue = (format.wBitsPerSample == 8) ? 0x80 : 0x00; + + // CREATE A SECONDARY SOUND BUFFER + { + DSBUFFERDESC desc; + ZeroMemory(&desc,sizeof(DSBUFFERDESC)); + desc.dwSize = sizeof(DSBUFFERDESC); + desc.dwFlags = DSBCAPS_CTRLDEFAULT; + desc.dwBufferBytes = buffersize; + desc.lpwfxFormat = &format; + s_directsound->CreateSoundBuffer(&desc,&stream->soundbuffer,NULL); + if (stream->soundbuffer) { + if (stream->volume != 0x7FFFFFFF) + stream->soundbuffer->SetVolume(stream->volume); + if (stream->pan != 0x7FFFFFFF) + stream->soundbuffer->SetPan(stream->pan); + } + } + s_critsect.Leave(); + + // TRIGGER THE CD READ THREAD + SetEvent(s_cdevent); + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileDdaDestroy () { + TRACEOUT(TRACEHANDLE, + "SFileDdaDestroy()"); + + // FREE ALL STREAMS + s_critsect.Enter(); + { + AUDIOSTREAMPTR curr; + while ((curr = s_streamlist.Head()) != NULL) { + curr->file->dda = TRUE; + s_critsect.Leave(); + SFileDdaEnd((HSFILE)curr->file); + s_critsect.Enter(); + } + } + s_critsect.Leave(); + + // DELETE THE POINTER TO THE DIRECTSOUND OBJECT + s_directsound = NULL; + + // FREE THE SOUND READ BUFFER + if (s_soundreadbuffer) { + FREE(s_soundreadbuffer); + s_soundreadbuffer = NULL; + } + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileDdaEnd (HSFILE handle) { + TRACEOUT(TRACEHANDLE, + "SFileDdaEnd(0x%x)", + handle); + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return FALSE; + + // FREE ALL STREAMS ASSOCIATED WITH THIS FILE + BOOL again; + do { + again = FALSE; + s_critsect.Enter(); + AUDIOSTREAMPTR curr = s_streamlist.Head(); + while (curr) { + AUDIOSTREAMPTR next = curr->Next(); + if (curr->file == fileptr) { + curr->fillstatus = FILL_CLOSING; + + // CHECK WHETHER THERE ARE OUTSTANDING READ REQUESTS FOR THE STREAM + BOOL found = FALSE; + REQUESTPTR currreq = s_cdreqlist.Head(); + while (currreq && !found) { + if ((currreq->stream == curr) || + (currreq->soundbuffer == curr->soundbuffer)) + found = TRUE; + currreq = currreq->Next(); + } + + // IF NOT, DELETE THE STREAM + if (found) + again = TRUE; + else { + if (curr->soundbuffer) + curr->soundbuffer->Release(); + next = s_streamlist.DeleteNode(curr); + } + + } + curr = next; + } + s_critsect.Leave(); + if (again) + Sleep(1); + } while (again); + + fileptr->dda = FALSE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SFileDdaGetPos (HSFILE handle, + DWORD *position, + DWORD *maxposition) { + TRACEOUT(TRACEHANDLE, + "SFileDdaGetPos(0x%x,*position,*maxposition)", + handle); + + if (position) + *position = 0; + if (maxposition) + *maxposition = 0; + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return FALSE; + + // ENTER THE CRITICAL SECTION + s_critsect.Enter(); + + // FIND THE STREAM ASSOCIATED WITH THIS FILE + AUDIOSTREAMPTR curr = s_streamlist.Head(); + while (curr && (curr->file != fileptr)) + curr = curr->Next(); + if (!curr) { + s_critsect.Leave(); + SErrSetLastError(SFILE_ERROR_NOT_PLAYING); + return 0; + } + + // DETERMINE THE CURRENT PLAY POSITION + DWORD playposition = 0; + if ((curr->fillstatus == FILL_PLAYING) || + (curr->fillstatus == FILL_CLOSING)) { + DWORD playcursor = 0; + DWORD writecursor = 0; + curr->soundbuffer->GetCurrentPosition(&playcursor,&writecursor); + DWORD writeposition = curr->file->location+curr->bytespastend-curr->startinglocation; + playposition = (writeposition/curr->soundbuffersize)*curr->soundbuffersize+playcursor; + if (playposition >= writeposition) + if (playposition > curr->soundbuffersize) + playposition -= curr->soundbuffersize; + else + playposition = 0; + playposition = min(playposition,curr->totalsize-curr->startinglocation); + } + + // RETURN THE CURRENT POSITIONS + if (position) + *position = playposition; + if (maxposition) + *maxposition = curr->totalsize-curr->startinglocation; + + // LEAVE THE CRITICAL SECTION + s_critsect.Leave(); + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileDdaGetVolume (HSFILE handle, + LONG *volume, + LONG *pan) { + TRACEOUT(TRACEHANDLE, + "SFileDdaGetVolume(0x%x,*volume,*pan)", + handle); + + if (volume) + *volume = 0; + if (pan) + *pan = 0; + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return FALSE; + + // ENTER THE CRITICAL SECTION + s_critsect.Enter(); + + // FIND THE STREAM ASSOCIATED WITH THIS FILE + AUDIOSTREAMPTR curr = s_streamlist.Head(); + while (curr && (curr->file != fileptr)) + curr = curr->Next(); + if (!curr) { + s_critsect.Leave(); + SErrSetLastError(SFILE_ERROR_NOT_PLAYING); + return 0; + } + + // IF WE DON'T KNOW WHAT THE VOLUME OR PAN OF THIS AUDIO STREAM IS, + // DETERMINE IT NOW + if (curr->volume == 0x7FFFFFFF) + curr->soundbuffer->GetVolume(&curr->volume); + if (curr->pan == 0x7FFFFFFF) + curr->soundbuffer->GetPan(&curr->pan); + + // RETURN THE REQUESTED VALUES + if (volume) + *volume = curr->volume; + if (pan) + *pan = curr->pan; + + // LEAVE THE CRITICAL SECTION + s_critsect.Leave(); + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileDdaInitialize (LPDIRECTSOUND directsound) { + VALIDATEBEGIN; + VALIDATE(directsound); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileDdaInitialize(0x%x)", + directsound); + + s_directsound = directsound; + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileDdaSetVolume (HSFILE handle, + LONG volume, + LONG pan) { + TRACEOUT(TRACEHANDLE, + "SFileDdaSetVolume(0x%x,%d,%d)", + handle,volume,pan); + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return FALSE; + + // ENTER THE CRITICAL SECTION + s_critsect.Enter(); + + // FIND THE STREAM ASSOCIATED WITH THIS FILE + AUDIOSTREAMPTR curr = s_streamlist.Head(); + while (curr && (curr->file != fileptr)) + curr = curr->Next(); + if (!curr) { + s_critsect.Leave(); + SErrSetLastError(SFILE_ERROR_NOT_PLAYING); + return 0; + } + + // ADJUST THE SETTINGS + if ((volume != 0x7FFFFFFF) && (volume != curr->volume)) { + curr->volume = volume; + curr->soundbuffer->SetVolume(volume); + } + if ((pan != 0x7FFFFFFF) && (pan != curr->pan)) { + curr->pan = pan; + curr->soundbuffer->SetPan(pan); + } + + // LEAVE THE CRITICAL SECTION + s_critsect.Leave(); + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileDestroy () { + TRACEOUT(TRACEHANDLE, + "SFileDestroy()"); + + // WAIT FOR ALL OUTSTANDING REQUESTS TO COMPLETE + while (!s_cdreqlist.IsEmpty()) + Sleep(10); + + // SHUT DOWN THE CD THREAD READ ROUTINE + if (s_cdthread != INVALID_HANDLE_VALUE) { + s_cdshutdown = 1; + SetEvent(s_cdevent); + WaitForSingleObject(s_cdthread,INFINITE); + if (s_cdevent != INVALID_HANDLE_VALUE) { + CloseHandle(s_cdevent); + s_cdevent = INVALID_HANDLE_VALUE; + } + if (s_cdthread != INVALID_HANDLE_VALUE) { + CloseHandle(s_cdthread); + s_cdthread = INVALID_HANDLE_VALUE; + } + } + + // DESTROY DDA + SFileDdaDestroy(); + + // DELETE THE OPEN FILES AND ARCHIVES + { + FILEPTR curr; + while ((curr = s_filelist.Head()) != NULL) { + REPORTRESOURCELEAK(HSFILE); + SFileCloseFile((HSFILE)curr); + } + } + { + ARCHIVEPTR curr; + while ((curr = s_archivelist.Head()) != NULL) { + REPORTRESOURCELEAK(HSARCHIVE); + SFileCloseArchive((HSARCHIVE)curr); + } + } + + // DELETE THE HASH TABLES + if (s_hashsource) { + FREE(s_hashsource); + s_hashsource = NULL; + } + + // DELETE THE DECOMPRESSION DATA + if (s_explodebuffer) { + FREE(s_explodebuffer); + s_explodebuffer = NULL; + } + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileEnableDirectAccess (BOOL enable) { + TRACEOUT(TRACEHANDLE, + "SFileEnableDirectAccess(%u)", + enable); + + s_enabledirect = enable; + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileGetArchiveInfo (HSARCHIVE archive, + int *priority, + BOOL *cdrom) { + if (priority) + *priority = 0; + if (cdrom) + *cdrom = FALSE; + + // CHECK THE ARCHIVE HANDLE + ARCHIVEPTR archiveptr; + if (!CheckArchiveHandle(archive,&archiveptr)) + return FALSE; + + // RETURN THE INFORMATION + if (priority) + *priority = archiveptr->priority; + if (cdrom) + *cdrom = (archiveptr->cdrom == CDROM_TRUE); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SFileGetArchiveName (HSARCHIVE archive, + LPTSTR buffer, + DWORD bufferchars) { + VALIDATEBEGIN; + VALIDATEANDBLANK(buffer); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileGetArchiveName(0x%x,0x%x,%u)", + archive,buffer,bufferchars); + + // CHECK THE ARCHIVE HANDLE + ARCHIVEPTR archiveptr; + if (!CheckArchiveHandle(archive,&archiveptr)) + return FALSE; + + SStrCopy(buffer,archiveptr->name,bufferchars); + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileGetBasePath (LPTSTR buffer, + DWORD bufferchars) { + TRACEOUT(TRACEHANDLE, + "SFileGetBasePath(0x%x,%u)", + buffer,bufferchars); + + if (!s_basepath[0]) + BuildDefaultBasePath(); + SStrCopy(buffer,s_basepath,bufferchars); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SFileGetFileArchive (HSFILE file, + HSARCHIVE *archive) { + VALIDATEBEGIN; + VALIDATEANDBLANK(archive); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileGetFileArchive(0x%x,*archive)", + file); + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(file,&fileptr)) + return FALSE; + + *archive = (HSARCHIVE)(fileptr->archive); + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileGetFileName (HSFILE file, + LPTSTR buffer, + DWORD bufferchars) { + VALIDATEBEGIN; + VALIDATEANDBLANK(buffer); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileGetFileName(0x%x,0x%x,%u)", + file,buffer,bufferchars); + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(file,&fileptr)) + return FALSE; + + SStrCopy(buffer,fileptr->name,bufferchars); + return 1; +} + +//=========================================================================== +DWORD APIENTRY SFileGetFileSize (HSFILE handle, + LPDWORD filesizehigh) { + TRACEOUT(TRACEHANDLE, + "SFileGetFileSize(0x%x,*filesizehigh)", + handle); + + if (filesizehigh) + *filesizehigh = NULL; + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return 0xFFFFFFFF; + + // IF THIS HANDLE REPRESENTS A REAL FILE, FORWARD THE REQUEST TO THE + // STANDARD WIN32 API + if (fileptr->handle != INVALID_HANDLE_VALUE) + return GetFileSize(fileptr->handle,filesizehigh); + + // RETURN THE FILE SIZE + return fileptr->block->sizefile; +} + +//=========================================================================== +BOOL APIENTRY SFileOpenArchive (LPCTSTR archivename, + int priority, + BOOL cdonly, + HSARCHIVE *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATE(archivename); + VALIDATE(*archivename); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileOpenArchive(\"%s\",%d,%u,*handle)", + archivename,priority,cdonly); + + // INITIALIZE THE HASH TABLES IF NECESSARY + if (!s_hashsource) { + s_hashsource = (LPDWORD)ALLOC(5*256*sizeof(DWORD)); + InitializeHashSource(); + } + + // IF THE ARCHIVE FILENAME DOES NOT CONTAIN AN ABSOLUTE PATH AND THE + // ARCHIVE DOES NOT EXIST IN THE GIVEN LOCATION RELATIVE TO THE CURRENT + // DIRECTORY, CHECK FOR IT IN THE GIVEN LOCATION RELATIVE TO THE + // EXECUTABLE DIRECTORY + char localarchivename[MAX_PATH]; + SStrCopy(localarchivename,archivename,MAX_PATH); + localarchivename[MAX_PATH-1] = 0; + if (GetFileAttributes(localarchivename) & FILE_ATTRIBUTE_DIRECTORY) + if ((*archivename == '\\') || + strstr(archivename,":\\") || + strstr(archivename,"\\\\")) + SStrCopy(localarchivename,archivename,MAX_PATH); + else + ConvertRelativePathName(archivename,localarchivename); + + // DETERMINE WHETHER THIS ARCHIVE IS ON A CD-ROM DRIVE + BOOL cdrom = CheckForCdRom(localarchivename); + if (cdonly && !cdrom) { + SErrSetLastError(SFILE_ERROR_INVALID_DRIVE); + return 0; + } + + // OPEN THE ARCHIVE FILE + HANDLE archivehandle = CreateFile(localarchivename, + GENERIC_READ, + FILE_SHARE_READ, + (LPSECURITY_ATTRIBUTES)NULL, + OPEN_EXISTING, + 0, + NULL); + if (archivehandle == INVALID_HANDLE_VALUE) + return 0; + + // CREATE A RECORD FOR THIS ARCHIVE + ARCHIVEPTR archiveptr = s_archivelist.NewNode(LIST_UNLINKED); + SStrCopy(archiveptr->name,localarchivename,MAX_PATH); + archiveptr->handle = archivehandle; + archiveptr->cdrom = cdrom ? CDROM_TRUE : CDROM_FALSE; + archiveptr->priority = priority; + + // SINCE THE MOPAQ FILE MAY BE TACKED ON BELOW OTHER FILE DATA, SEARCH + // FOR THE SIGNATURE TO DETERMINE THE STARTING LOCATION OF THE MOPAQ + // FILE + archiveptr->fileheader = NEW(FILEHEADER); + DWORD bytesread; + archiveptr->startinglocation = 0; + do { + SetFilePointer(archivehandle,archiveptr->startinglocation,NULL,FILE_BEGIN); + bytesread = 0; + ReadFile(archivehandle, + archiveptr->fileheader, + sizeof(FILEHEADER), + &bytesread, + NULL); + if (bytesread != sizeof(FILEHEADER)) { + DEL(archiveptr->fileheader); + s_archivelist.DeleteNode(archiveptr); + CloseHandle(archivehandle); + SErrSetLastError(SFILE_ERROR_NOT_ARCHIVE); + return 0; + } + if (archiveptr->fileheader->signature != SIGNATURE) + archiveptr->startinglocation += 512; + } while (archiveptr->fileheader->signature != SIGNATURE); + + // DETERMINE THE SECTOR SIZE AND ALLOCATE A SECTOR BUFFER + archiveptr->sectorsize = (512 << archiveptr->fileheader->sectorsizeid); + archiveptr->sectorbuffer = (LPBYTE)ALLOC(archiveptr->sectorsize); + + // READ THE HASH TABLE + archiveptr->hashtable = (HASHENTRYPTR)ALLOC(archiveptr->fileheader->hashcount*sizeof(HASHENTRY)); + SetFilePointer(archivehandle,archiveptr->startinglocation+archiveptr->fileheader->hashoffset,NULL,FILE_BEGIN); + ReadFileChecked(archivehandle, + archiveptr->hashtable, + archiveptr->fileheader->hashcount*sizeof(HASHENTRY), + &bytesread, + NULL, + archiveptr->name); + Decrypt((LPDWORD)archiveptr->hashtable, + archiveptr->fileheader->hashcount*sizeof(HASHENTRY), + Hash("(hash table)",HASH_ENCRYPTKEY)); + + // READ THE BLOCK TABLE + archiveptr->blocktable = (BLOCKENTRYPTR)ALLOC(archiveptr->fileheader->blockcount*sizeof(BLOCKENTRY)); + SetFilePointer(archivehandle,archiveptr->startinglocation+archiveptr->fileheader->blockoffset,NULL,FILE_BEGIN); + ReadFileChecked(archivehandle, + archiveptr->blocktable, + archiveptr->fileheader->blockcount*sizeof(BLOCKENTRY), + &bytesread, + NULL, + archiveptr->name); + Decrypt((LPDWORD)archiveptr->blocktable, + archiveptr->fileheader->blockcount*sizeof(BLOCKENTRY), + Hash("(block table)",HASH_ENCRYPTKEY)); + + // IF THE STARTING LOCATION IS NOT ZERO, OFFSET ALL OF THE BLOCKS IN THE + // BLOCK TABLE + if (archiveptr->startinglocation) { + for (DWORD block = 0; block < archiveptr->fileheader->blockcount; ++block) + if ((archiveptr->blocktable+block)->offset) + (archiveptr->blocktable+block)->offset += archiveptr->startinglocation; + } + + // ADD THE ARCHIVE TO OUR LINKED LIST IN PRIORITY ORDER + s_critsect.Enter(); + { + ARCHIVEPTR curr = s_archivelist.Head(); + while (curr && (curr->priority > priority)) + curr = curr->Next(); + s_archivelist.LinkNode(archiveptr,LIST_LINK_BEFORE,curr); + } + s_critsect.Leave(); + + // IF THIS ARCHIVE IS ON A CD-ROM AND THERE IS NO CD-ROM READ THREAD YET, + // CREATE ONE + if (cdrom && (s_cdthread == INVALID_HANDLE_VALUE)) + CreateCdThread(); + else if (cdonly && !cdrom) { + SFileCloseArchive((HSARCHIVE)archiveptr); + SErrSetLastError(SFILE_ERROR_INVALID_DRIVE); + return 0; + } + + // RETURN A HANDLE TO THE ARCHIVE + *handle = (HSARCHIVE)archiveptr; + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileOpenFile (LPCTSTR filename, + HSFILE *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATE(filename); + VALIDATE(*filename); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileOpenFile(\"%s\",*handle)", + filename); + + // IF THIS FILE IS AVAILABLE OUTSIDE OF AN ARCHIVE, OPEN IT DIRECTLY + if (s_enabledirect || s_archivelist.IsEmpty()) { + char localfilename[MAX_PATH] = ""; + if ((*filename == '\\') || + strstr(filename,":\\") || + strstr(filename,"\\\\")) + SStrCopy(localfilename,filename,MAX_PATH); + else + ConvertRelativePathName(filename,localfilename); + HANDLE filehandle = CreateFile(localfilename, + GENERIC_READ, + FILE_SHARE_READ, + (LPSECURITY_ATTRIBUTES)NULL, + OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if (filehandle != INVALID_HANDLE_VALUE) { + s_critsect.Enter(); + FILEPTR fileptr = s_filelist.NewNode(); + fileptr->handle = filehandle; + s_critsect.Leave(); + *handle = (HSFILE)fileptr; + return TRUE; + } + } + + // OTHERWISE, SEARCH FOR THE REQUESTED FILE IN THE CURRENTLY OPEN ARCHIVES + if (s_archivelist.IsEmpty() || !s_hashsource) { + SErrSetLastError(SFILE_ERROR_FILE_NOT_FOUND); + return 0; + } + ARCHIVEPTR archiveptr = s_archivelist.Head(); + DWORD index; + do { + index = SearchHashTable(archiveptr,filename,s_lcid); + if (index == 0xFFFFFFFF) + archiveptr = archiveptr->Next(); + } while (archiveptr && (index == 0xFFFFFFFF)); + if (!archiveptr) { + SErrSetLastError(SFILE_ERROR_FILE_NOT_FOUND); + return 0; + } + + return SFileOpenFileEx((HSARCHIVE)archiveptr,filename,0,handle); +} + +//=========================================================================== +BOOL APIENTRY SFileOpenFileEx (HSARCHIVE archivehandle, + LPCTSTR filename, + DWORD flags, + HSFILE *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATE(filename); + VALIDATE(*filename); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileOpenFileEx(0x%x,\"%s\",0x%x,*handle)", + archivehandle,filename,flags); + + // CHECK THE ARCHIVE HANDLE + ARCHIVEPTR archiveptr; + if (!CheckArchiveHandle(archivehandle,&archiveptr)) + return FALSE; + + // DETERMINE THE HASH INDEX + DWORD index = SearchHashTable(archiveptr,filename,s_lcid); + if (index == 0xFFFFFFFF) { + SErrSetLastError(SFILE_ERROR_FILE_NOT_FOUND); + return 0; + } + + // DETERMINE THE BLOCK POINTER + BLOCKENTRYPTR block = archiveptr->blocktable+(archiveptr->hashtable+index)->block; + + // CONFIRM THAT THIS IS A VALID FILE + if ((!block->sizefile) || + !(block->flags & MPQ_ALLOCATED)) { + SErrSetLastError(SFILE_ERROR_FILE_INVALID); + return 0; + } + + // DETERMINE THE FILE NAME PORTION OF THE REQUESTED FILE + LPCTSTR name = filename; + while (SStrChr(name,':')) + name = SStrChr(name,':')+1; + while (SStrChr(name,'\\')) + name = SStrChr(name,'\\')+1; + + // CREATE A DECRYPTION KEY BASED ON THE FILE NAME + DWORD key = Hash(name,HASH_ENCRYPTKEY); + if (block->flags & MPQ_ENCRYPTED_FIXLOC) + key = (key + (block->offset-archiveptr->startinglocation)) ^ block->sizefile; + + // CREATE A RECORD FOR THE FILE + DWORD sectors = (block->sizefile+archiveptr->sectorsize-1)/archiveptr->sectorsize; + LPDWORD sectoroffsettable = NULL; + if (block->flags & MPQ_COMPRESSEDMASK) + sectoroffsettable = (LPDWORD)ALLOC((sectors+1)*sizeof(DWORD)); + s_critsect.Enter(); + FILEPTR fileptr = s_filelist.NewNode(); + SStrCopy(fileptr->name,filename,MAX_PATH); + fileptr->handle = INVALID_HANDLE_VALUE; + fileptr->archive = archiveptr; + fileptr->block = block; + fileptr->key = key; + fileptr->sectors = sectors; + fileptr->sectoroffsettable = sectoroffsettable; + fileptr->readaheadbuffer = ALLOC(READAHEAD); + s_critsect.Leave(); + + // RETURN A HANDLE TO THE FILE + *handle = (HSFILE)fileptr; + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileOpenFileWin32 (LPCTSTR filename, + HANDLE *handle) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATE(filename); + VALIDATE(*filename); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileOpenFileWin32(\"%s\",*handle)", + filename); + + // IF THIS FILE IS AVAILABLE OUTSIDE OF AN ARCHIVE, OPEN IT DIRECTLY + { + char localfilename[MAX_PATH] = ""; + if ((*filename == '\\') || + strstr(filename,":\\") || + strstr(filename,"\\\\")) + SStrCopy(localfilename,filename,MAX_PATH); + else + ConvertRelativePathName(filename,localfilename); + *handle = CreateFile(localfilename, + GENERIC_READ, + FILE_SHARE_READ, + (LPSECURITY_ATTRIBUTES)NULL, + OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if (*handle != INVALID_HANDLE_VALUE) + return 1; + } + + // OTHERWISE, SEARCH FOR THE REQUESTED FILE IN THE CURRENTLY OPEN ARCHIVES + if (s_archivelist.IsEmpty() || !s_hashsource) { + SErrSetLastError(SFILE_ERROR_FILE_NOT_FOUND); + return 0; + } + ARCHIVEPTR archiveptr = s_archivelist.Head(); + DWORD index; + do { + index = SearchHashTable(archiveptr,filename,s_lcid); + if (index == 0xFFFFFFFF) + archiveptr = archiveptr->Next(); + } while (archiveptr && (index == 0xFFFFFFFF)); + if (!archiveptr) { + SErrSetLastError(SFILE_ERROR_FILE_NOT_FOUND); + return 0; + } + + // DETERMINE THE BLOCK POINTER + BLOCKENTRYPTR block = archiveptr->blocktable+(archiveptr->hashtable+index)->block; + + // CONFIRM THAT THIS IS A VALID FILE, AND IS NOT COMPRESSED OR ENCRYPTED. + // WE CAN'T RETURN WIN32 HANDLES TO COMPRESSED OR ENCRYPTED FILES. + if ((!block->sizefile) || + (block->flags & (MPQ_COMPRESSEDMASK | MPQ_ENCRYPTED)) || + !(block->flags & MPQ_ALLOCATED)) { + SErrSetLastError(SFILE_ERROR_FILE_INVALID); + return 0; + } + + // OPEN THE ARCHIVE THAT CONTAINS THE FILE + *handle = CreateFile(archiveptr->name, + GENERIC_READ, + FILE_SHARE_READ, + (LPSECURITY_ATTRIBUTES)NULL, + OPEN_EXISTING, + FILE_FLAG_SEQUENTIAL_SCAN, + NULL); + if (*handle == INVALID_HANDLE_VALUE) + return 0; + + // SEEK TO THE BEGINNING OF THE FILE + SetFilePointer(*handle,block->offset,0,FILE_BEGIN); + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SFileReadFile (HSFILE handle, + LPVOID buffer, + DWORD bytestoread, + LPDWORD bytesread, + LPOVERLAPPED overlapped) { + if (bytesread) + *bytesread = 0; + + VALIDATEBEGIN; + VALIDATE(buffer); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileReadFile(0x%x,0x%x,%u,*bytesread,0x%x)", + handle,buffer,bytestoread,overlapped); + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return FALSE; + + if (!bytestoread) + return TRUE; + + // IF THIS HANDLE REPRESENTS A REAL FILE, FORWARD THE REQUEST TO THE + // STANDARD WIN32 API + if (fileptr->handle != INVALID_HANDLE_VALUE) { + DWORD localbytesread = 0; + HANDLE event = NULL; + if (overlapped) { + event = overlapped->hEvent; + overlapped->hEvent = NULL; + } + ReadFileChecked(fileptr->handle, + buffer, + bytestoread, + &localbytesread, + overlapped, + fileptr->name); + if (event) + SetEvent(event); + if (bytesread) + *bytesread = localbytesread; + return (localbytesread == bytestoread); + } + + // TRY TO SATISFY, OR PARTIALLY SATISFY, THIS REQUEST FROM THE READ + // AHEAD BUFFER + if (fileptr->readaheadbuffer && + (fileptr->readaheadoffset < fileptr->readaheadbytes) && + !overlapped) { + DWORD satisfybytes = min(bytestoread,fileptr->readaheadbytes-fileptr->readaheadoffset); + CopyMemory(buffer,(LPBYTE)fileptr->readaheadbuffer+fileptr->readaheadoffset,satisfybytes); + fileptr->location += satisfybytes; + fileptr->readaheadoffset += satisfybytes; + buffer = (LPBYTE)buffer+satisfybytes; + bytestoread -= satisfybytes; + if (bytesread) + *bytesread = satisfybytes; + if (!bytestoread) + return TRUE; + } + + // DETERMINE THE AMOUNT OF DATA TO READ + // (NO READ-AHEAD IS DONE FOR OVERLAPPED I/O, BECAUSE THE EVENT WILL + // BE TRIGGERED BEFORE WE HAVE A CHANCE TO DO THE BUFFER COPY) + LPVOID readbuffer = buffer; + DWORD readbytes = bytestoread; + if (!overlapped) { + DWORD desiredreadahead = min(READAHEAD, + fileptr->archive->sectorsize-(fileptr->location & (fileptr->archive->sectorsize-1))); + if (bytestoread < desiredreadahead) { + readbuffer = fileptr->readaheadbuffer; + readbytes = desiredreadahead; + } + } + + // IF THERE IS NOTHING TO READ, RETURN + if (!readbytes) + return TRUE; + + // IF THIS FILE IS ON A CD-ROM DRIVE, QUEUE THE REQUEST FOR THE CD-ROM + // I/O THREAD + DWORD location = overlapped ? overlapped->Offset : fileptr->location; + DWORD totalbytesread = 0; + if (fileptr->archive->cdrom != CDROM_FALSE) { + REQUESTPTR requestptr; + HANDLE event = overlapped ? overlapped->hEvent + : CreateEvent(NULL,TRUE,FALSE,NULL); + DWORD blocks = (readbytes+DATACHUNKSIZE-1)/DATACHUNKSIZE; + DWORD prevseq = 0; + DWORD loop; + for (loop = 0; loop < blocks; ++loop) { + BOOL lastblock = (loop == blocks-1); + DWORD offset = loop*DATACHUNKSIZE; + DWORD bytes = min(DATACHUNKSIZE,readbytes-offset); + requestptr = IssueRequest(fileptr, + location+loop*DATACHUNKSIZE, + (LPBYTE)readbuffer+offset, + NULL, + 0, + NULL, + bytes, + INT_MAX, + prevseq, + lastblock ? event : NULL, + overlapped || !lastblock, + lastblock, + &prevseq); + if (!lastblock) + totalbytesread += bytes; + } + if (overlapped) { + SErrSetLastError(ERROR_IO_PENDING); + return FALSE; + } + WaitForSingleObject(event,INFINITE); + CloseHandle(event); + totalbytesread += requestptr->bytesread; + FREE(requestptr); + } + + // OTHERWISE, READ THE REQUESTED DATA + else { + totalbytesread = InternalReadUnaligned(fileptr, + location, + readbuffer, + readbytes); + if (overlapped && overlapped->hEvent) + SetEvent(overlapped->hEvent); + } + + // COPY THE READ DATA TO THE USER'S BUFFER + DWORD userbytesread = min(bytestoread,totalbytesread); + if (readbuffer != buffer) { + CopyMemory(buffer,readbuffer,userbytesread); + fileptr->readaheadoffset = userbytesread; + fileptr->readaheadbytes = totalbytesread; + } + + // UPDATE THE FILE POINTER + if (!overlapped) + fileptr->location += userbytesread; + + // RETURN THE NUMBER OF BYTES READ + if (bytesread) + *bytesread += userbytesread; + + if (userbytesread == bytestoread) + return TRUE; + else { + SErrSetLastError(SFILE_ERROR_HANDLE_EOF); + return FALSE; + } +} + +//=========================================================================== +BOOL APIENTRY SFileSetBasePath (LPCTSTR path) { + VALIDATEBEGIN; + VALIDATE(path); + VALIDATEEND; + + TRACEOUT(TRACEHANDLE, + "SFileSetBasePath(\"%s\")", + path); + + // IF WE WERE GIVEN A NULL PATH, RESET THE BASE PATH VARIABLE. IT WILL + // BE AUTOMATICALLY SET ON NEXT USE TO THE PROGRAM PATH. + if (!*path) + s_basepath[0] = 0; + + // OTHERWISE, SET THE BASE PATH TO THE GIVEN PATH + else { + BOOL terminated = (*(path+SStrLen(path)-1) == '\\'); + if ((SStrLen(path)+1+!terminated) > MAX_PATH) { + SErrSetLastError(SFILE_ERROR_BAD_PATHNAME); + return 0; + } + SStrCopy(s_basepath,path,MAX_PATH); + if (!terminated) + SStrPack(s_basepath,"\\",MAX_PATH); + } + + return TRUE; +} + +//=========================================================================== +DWORD APIENTRY SFileSetFilePointer (HSFILE handle, + LONG distancetomove, + PLONG distancetomovehigh, + DWORD movemethod) { + TRACEOUT(TRACEHANDLE, + "SFileSetFilePointer(0x%x,%d,0x%x,%u)", + handle,distancetomove,distancetomovehigh,movemethod); + + if (distancetomovehigh && *distancetomovehigh) { + SErrSetLastError(SFILE_ERROR_INVALID_PARAMETER); + return 0xFFFFFFFF; + } + + // CHECK THE FILE HANDLE + FILEPTR fileptr; + if (!CheckFileHandle(handle,&fileptr)) + return 0xFFFFFFFF; + + // IF THIS HANDLE REPRESENTS A REAL FILE, FORWARD THE REQUEST TO THE + // STANDARD WIN32 API + if (fileptr->handle != INVALID_HANDLE_VALUE) + return SetFilePointer(fileptr->handle,distancetomove,NULL,movemethod); + + // SET THE NEW FILE LOCATION + switch (movemethod) { + + case FILE_BEGIN: + fileptr->location = distancetomove; + break; + + case FILE_CURRENT: + if ((distancetomove < 0) && (fileptr->location < (DWORD)-distancetomove)) + fileptr->location = 0; + else + fileptr->location += distancetomove; + break; + + case FILE_END: + if ((distancetomove < 0) && (fileptr->block->sizefile < (DWORD)-distancetomove)) + fileptr->location = 0; + else + fileptr->location = fileptr->block->sizefile+distancetomove; + break; + + } + fileptr->location = min(fileptr->location,fileptr->block->sizefile-1); + fileptr->readaheadoffset = 0; + fileptr->readaheadbytes = 0; + + // RETURN THE NEW LOCATION + return fileptr->location; +} + +//=========================================================================== +BOOL APIENTRY SFileSetIoErrorMode (DWORD errormode, + SFILEERRORPROC errorproc) { + TRACEOUT(TRACEHANDLE, + "SFileSetIoErrorMode(%u,0x%x)", + errormode,errorproc); + + s_ioerrormode = errormode; + s_ioerrorproc = errorproc; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SFileSetLocale (LCID lcid) { + TRACEOUT(TRACEHANDLE, + "SFileSetLocale(0x%x)", + lcid); + + s_lcid = lcid; + return 1; +} diff --git a/src/Storm/SOURCE/SGDI.CPP b/src/Storm/SOURCE/SGDI.CPP new file mode 100644 index 0000000..2310a49 --- /dev/null +++ b/src/Storm/SOURCE/SGDI.CPP @@ -0,0 +1,860 @@ +/**************************************************************************** +* +* SGDI.CPP +* Storm GDI functions +* (direct replacements for popular Windows GDI functions) +* +* By Michael O'Brien (2/21/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define SIGNATURE 0x4F4D + +#define TYPE_FONT 0 +#define NUMTYPES 1 + +// USE A PITCH TABLE TO AVOID INTEGER MULTIPLIES, EXCEPT ON POWERPC, WHERE +// AN INTEGER MULTIPLY IS FASTER THAN A MEMORY ACCESS +#if defined(powerc) || defined(__powerc) +#define USEPITCHTABLE 0 +#define LINEOFFSET(line) (s_pitch*(line)) +#define ISPITCHVALID (s_pitch != 0) +#else +#define USEPITCHTABLE 1 +#define LINEOFFSET(line) (*(s_pitchtable+(line))) +#define ISPITCHVALID (s_pitchtable != NULL) +#endif + +typedef struct _BITMAPINFO256 { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[256]; +} BITMAPINFO256, *LPBITMAPINFO256; + +NODEDECL(SGDIOBJ) { + WORD signature; + WORD type; + LPBYTE bits; +} *LPSGDIOBJ; + +typedef struct SGDIFONT : public SGDIOBJ { + int filecharwidth; + int filecharheight; + int filepitch; + int filecolumnand; + int filerowshift; + SIZE charsize[256]; +} *LPSGDIFONT; + +static LIST(SGDIOBJ) s_objectlist; +static int s_pitch = 640; +#if USEPITCHTABLE +static LPDWORD s_pitchtable = NULL; +static int s_pitchtablealloc = 0; +static int s_pitchtablelines = 0; +#endif +static int s_screenbpp = 8; +static int s_screenbppshift = 0; +static int s_screencx = 640; +static int s_screency = 480; +static LPSGDIOBJ s_selected[NUMTYPES] = {NULL}; +static LPBYTE s_tempbuffer = NULL; +static int s_tempbuffersize = 0; + +//=========================================================================== +static BOOL AllocateTempBuffer (int size) { + + // USE THE EXISTING BUFFER IF IT IS BIG ENOUGH + if (size && (size <= s_tempbuffersize)) + return 1; + + // OTHERWISE, FREE THE OLD BUFFER + if (s_tempbuffer) { + FREE(s_tempbuffer); + s_tempbuffer = NULL; + s_tempbuffersize = 0; + } + + // ALLOCATE A NEW BUFFER + if (size) { + s_tempbuffer = (LPBYTE)ALLOC(size); + s_tempbuffersize = size; + return TRUE; + } + + return FALSE; +} + +//=========================================================================== +static void inline ClipRectangle (LPRECT rect) { + if (rect->left < 0) + rect->left = 0; + if (rect->top < 0) + rect->top = 0; + if (rect->right > s_screencx) + rect->right = s_screencx; + if (rect->bottom > s_screency) + rect->bottom = s_screency; +} + +//=========================================================================== +static DWORD inline ConvertColorRefToPattern (COLORREF colorref) { + DWORD colordata = 0; + + // IF WE WERE GIVEN A PALETTE INDEX, USE IT + if (colorref & 0x01000000) + if (s_screenbpp == 8) + colordata = colorref & 0x00FFFFFF; + else + colordata = 0; + + // OTHERWISE, CONVERT THE COLOR TO THE CURRENT SCREEN FORMAT + else switch (s_screenbpp) { + + case 8: + colordata = 0; + break; + + case 16: + colordata = ((GetBValue(colorref) >> 3) << 10) + | ((GetGValue(colorref) >> 3) << 5) + | (GetRValue(colorref) >> 3); + break; + + } + + // PROPAGATE THE COLOR INTO THE PATTERN + switch (s_screenbpp) { + + case 8: + colordata |= (colordata << 8) | (colordata << 16) | (colordata << 24); + break; + + case 16: + colordata |= (colordata << 16); + break; + + } + + return colordata; +} + +//=========================================================================== +static LPSGDIOBJ InternalCreateGdiObject (int size, WORD type) { + LPSGDIOBJ ptr = s_objectlist.NewNode(LIST_HEAD,size-sizeof(SGDIOBJ)); + ptr->signature = SIGNATURE; + ptr->type = type; + ptr->bits = NULL; + return ptr; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SGdiBitBlt (LPBYTE videobuffer, + int destx, + int desty, + LPBYTE sourcedata, + LPRECT sourcerect, + int sourcecx, + int sourcecy, + COLORREF color, + DWORD rop) { + VALIDATEBEGIN; + VALIDATE(videobuffer); + VALIDATE(sourcedata); + VALIDATE(s_pitch); + VALIDATEEND; + + // MAKE LOCAL COPIES OF THE SOURCE AND DESTINATION RECTANGLES + RECT localdestrect = {destx,desty,4095,4095}; + SIZE localdestsize = {s_screencx,s_screency}; + SIZE localsourcesize = {sourcecx,sourcecy}; + RECT localsourcerect; + if (sourcerect) + CopyMemory(&localsourcerect,sourcerect,sizeof(RECT)); + + // IF NECESSARY, CONVERT THE COLORREF TO A PATTERN + DWORD localpattern = 0; + if (color && (rop != SRCCOPY)) + localpattern = ConvertColorRefToPattern(color); + + // IF WE ARE NOT IN 8-BIT MODE, CONVERT PIXELS TO BYTES + if (s_screenbppshift) { + localdestrect.left <<= s_screenbppshift; + localdestrect.right <<= s_screenbppshift; + localdestsize.cx <<= s_screenbppshift; + localsourcerect.left <<= s_screenbppshift; + localsourcerect.right <<= s_screenbppshift; + localsourcesize.cx <<= s_screenbppshift; + } + + // PERFORM THE BITBLT + return SBltROP3Clipped(videobuffer, + &localdestrect, + &localdestsize, + s_pitch, + sourcedata, + sourcerect ? &localsourcerect : NULL, + &localsourcesize, + sourcecx << s_screenbppshift, + localpattern, + rop); +} + +//=========================================================================== +BOOL APIENTRY SGdiCreateFont (LPBYTE bits, + int width, + int height, + int bitdepth, + int filecharwidth, + int filecharheight, + LPSIZE charsizetable, + HSGDIFONT *handle) { + if (handle) + *handle = (HSGDIFONT)0; + + VALIDATEBEGIN; + VALIDATE(bits); + VALIDATE(width); + VALIDATE(height); + VALIDATE(filecharwidth); + VALIDATE(filecharheight); + VALIDATE(charsizetable); + VALIDATE(handle); + VALIDATEEND; + + // CREATE A RECORD FOR THE FONT + LPSGDIFONT newptr = (LPSGDIFONT)InternalCreateGdiObject(sizeof(SGDIFONT), + TYPE_FONT); + if (!newptr) + return FALSE; + LPBYTE savebits = (LPBYTE)ALLOC((width*height*bitdepth) >> 3); + CopyMemory(savebits,bits,(width*height*bitdepth) >> 3); + CopyMemory(&newptr->charsize[0],charsizetable,256*sizeof(SIZE)); + newptr->bits = savebits; + newptr->filecharwidth = filecharwidth; + newptr->filecharheight = filecharheight; + newptr->filepitch = width; + newptr->filecolumnand = 1; + newptr->filerowshift = 0; + int charspercolumn = 1; + while (charspercolumn < width/filecharwidth) { + charspercolumn <<= 1; + newptr->filecolumnand <<= 1; + ++newptr->filerowshift; + } + --newptr->filecolumnand; + + // RETURN A HANDLE TO THE FONT + if (handle) + *handle = (HSGDIFONT)newptr; + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SGdiDeleteObject (HSGDIOBJ handle) { + + // GET A POINTER TO THE OBJECT + LPSGDIOBJ ptr = (LPSGDIOBJ)handle; + if ((!ptr) || (ptr->signature != SIGNATURE) || (ptr->type >= NUMTYPES)) + return FALSE; + + // UNSELECT THE OBJECT + if (s_selected[ptr->type] == ptr) + s_selected[ptr->type] = NULL; + + // FREE ANY DATA ALLOCATED FOR THIS OBJECT + if (ptr->bits) { + FREE(ptr->bits); + ptr->bits = NULL; + } + + // UNLINK AND FREE THE OBJECT + s_objectlist.DeleteNode(ptr); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SGdiDestroy () { + LPSGDIOBJ curr; + while ((curr = s_objectlist.Head()) != NULL) { + switch (curr->type) { + + case TYPE_FONT: + REPORTRESOURCELEAK(HSGDIFONT); + break; + + default: + REPORTRESOURCELEAK(HSGDIOBJ); + break; + + } + SGdiDeleteObject((HSGDIOBJ)curr); + } + AllocateTempBuffer(0); +#if USEPITCHTABLE + if (s_pitchtable) { + FREE(s_pitchtable); + s_pitchtable = NULL; + s_pitchtablealloc = 0; + s_pitchtablelines = 0; + } +#endif + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SGdiExtTextOut (LPBYTE videobuffer, + int x, + int y, + LPRECT rect, + COLORREF color, + int textcoloruse, + int bkgcoloruse, + LPCTSTR string, + int chars) { + VALIDATEBEGIN; + VALIDATE(videobuffer); + VALIDATE(rect); + VALIDATE(string); + VALIDATEEND; + + if (!(ISPITCHVALID && s_selected[TYPE_FONT])) + return FALSE; + if (chars < 0) + chars = SStrLen(string); + + // CLIP THE RECTANGLE AND COORDINATES AGAINST THE SCREEN + RECT clippedrect; + clippedrect.left = max(rect->left,0); + clippedrect.top = max(rect->top,0); + clippedrect.right = max(rect->left,min(rect->right,s_screencx)); + clippedrect.bottom = max(rect->top,min(rect->bottom,s_screency)); + x = max(clippedrect.left,min(x,s_screencx)); + y = max(clippedrect.top ,min(y,s_screency)); + + // IF THE TEXT AND BACKGROUND ARE TO BE THE SAME COLOR, USE THE RECTANGLE() + // FUNCTION INSTEAD + if (textcoloruse == bkgcoloruse) + if (textcoloruse == ETO_TEXT_TRANSPARENT) + return TRUE; + else + return SGdiRectangle(videobuffer, + clippedrect.left, + clippedrect.right, + clippedrect.top, + clippedrect.bottom, + (textcoloruse == ETO_TEXT_COLOR) + ? color + : (textcoloruse == ETO_TEXT_BLACK) + ? PALETTEINDEX(0x00) + : PALETTEINDEX(0xFF)); + + // DETERMINE THE PATTERN AND ROP CODE + DWORD pattern = ConvertColorRefToPattern(color); + DWORD rop = 0; + switch (textcoloruse) { + + case ETO_TEXT_TRANSPARENT: + switch (bkgcoloruse) { + case ETO_BKG_COLOR: rop = 0x00E20746; break; + case ETO_BKG_BLACK: rop = 0x00220326; break; + case ETO_BKG_WHITE: rop = 0x00EE0086; break; + } + break; + + case ETO_TEXT_COLOR: + switch (bkgcoloruse) { + case ETO_BKG_TRANSPARENT: rop = 0x00B8074A; break; + case ETO_BKG_BLACK: rop = 0x0030032A; break; + case ETO_BKG_WHITE: rop = 0x00FC008A; break; + } + break; + + case ETO_TEXT_BLACK: + switch (bkgcoloruse) { + case ETO_BKG_TRANSPARENT: rop = 0x008800C6; break; + case ETO_BKG_COLOR: rop = 0x00C000CA; break; + case ETO_BKG_WHITE: rop = 0x00CC0020; break; + } + break; + + case ETO_TEXT_WHITE: + switch (bkgcoloruse) { + case ETO_BKG_TRANSPARENT: rop = 0x00BB0226; break; + case ETO_BKG_COLOR: rop = 0x00F3022A; break; + case ETO_BKG_BLACK: rop = 0x00330008; break; + } + break; + + } + if (!rop) + return FALSE; + + // DRAW THE TEXT + LPSGDIFONT currfont = (LPSGDIFONT)s_selected[TYPE_FONT]; + int textx = x; + { + SIZE destsize = {s_screencx,s_screency}; + while (chars--) { + RECT sourcerect; + sourcerect.left = (int)(((BYTE)*string) & currfont->filecolumnand)*currfont->filecharwidth; + sourcerect.top = (int)(((BYTE)*string) >> currfont->filerowshift)*currfont->filecharheight; + sourcerect.right = sourcerect.left+min(clippedrect.right-textx, + currfont->filecharwidth); + sourcerect.bottom = sourcerect.top+min(clippedrect.bottom-y, + currfont->filecharheight); + SGdiBitBlt(videobuffer, + textx, + y, + currfont->bits, + &sourcerect, + currfont->filepitch, + 0x7FFF, + color, + rop); + textx += currfont->charsize[(BYTE)*(string++)].cx; + } + } + textx = min(textx,s_screencx-1); + + // IF THE BACKGROUND IS TRANSPARENT, RETURN NOW + if (bkgcoloruse == ETO_BKG_TRANSPARENT) + return TRUE; + + // DETERMINE A ROP CODE FOR DRAWING THE UNOBSTRUCTED BACKGROUND AREA + switch (bkgcoloruse) { + case ETO_BKG_COLOR: rop = PATCOPY; break; + case ETO_BKG_BLACK: rop = BLACKNESS; break; + case ETO_BKG_WHITE: rop = WHITENESS; break; + } + + // DRAW THE AREA TO THE LEFT OF THE TEXT + if (x > rect->left) + SBltROP3(videobuffer+LINEOFFSET(y)+rect->left, + NULL, + x-rect->left, + min(currfont->filecharheight,rect->bottom-y), + s_pitch, + 0, + pattern, + rop); + + // DRAW THE AREA TO THE RIGHT OF THE TEXT + if (textx < rect->right) + SBltROP3(videobuffer+LINEOFFSET(y)+textx, + NULL, + rect->right-textx, + min(currfont->filecharheight,rect->bottom-y), + s_pitch, + 0, + pattern, + rop); + + // DRAW THE AREA ABOVE THE TEXT + if (y > rect->top) + SBltROP3(videobuffer+LINEOFFSET(rect->top)+rect->left, + NULL, + rect->right-rect->left, + y-rect->top, + s_pitch, + 0, + pattern, + rop); + + // DRAW THE AREA BELOW THE TEXT + if (y+currfont->filecharheight < rect->bottom) + SBltROP3(videobuffer+LINEOFFSET(y+currfont->filecharheight)+rect->left, + NULL, + rect->right-rect->left, + rect->bottom-(y+currfont->filecharheight), + s_pitch, + 0, + pattern, + rop); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SGdiGetTextExtent (LPCTSTR string, + int chars, + LPSIZE size) { + if (size) { + size->cx = 0; + size->cy = 0; + } + + VALIDATEBEGIN; + VALIDATE(string); + VALIDATE(size); + VALIDATEEND; + + LPSGDIFONT currfont = (LPSGDIFONT)s_selected[TYPE_FONT]; + if (!currfont) + return FALSE; + if (chars < 0) + chars = SStrLen(string); + + while (chars--) { + size->cx += currfont->charsize[(BYTE)*string].cx; + size->cy = max(size->cy,currfont->charsize[(BYTE)*string].cy); + ++string; + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SGdiImportFont (HFONT windowsfont, + HSGDIFONT *handle) { + if (handle) + *handle = (HSGDIFONT)0; + + VALIDATEBEGIN; + VALIDATE(windowsfont); + VALIDATE(handle); + VALIDATEEND; + + HBITMAP bitmap = (HBITMAP)0; + LPSIZE charsizetable = NULL; + HDC dc = (HDC)0; + HDC memdc = (HDC)0; + HFONT oldfont = (HFONT)0; + LPBYTE packedbits = NULL; + BOOL success = FALSE; + LPBYTE unpackedbits = NULL; + + TRY { + + // CREATE A DC AND SELECT THE FONT INTO IT + dc = GetDC(GetDesktopWindow()); + memdc = CreateCompatibleDC(dc); + if (!(dc && memdc)) + LEAVE; + oldfont = (HFONT)SelectObject(memdc,windowsfont); + + // VERIFY THAT THE FONT IS A TRUETYPE FONT + { + TEXTMETRIC tm; + ZeroMemory(&tm,sizeof(TEXTMETRIC)); + GetTextMetrics(memdc,&tm); + if (!(tm.tmPitchAndFamily & TMPF_TRUETYPE)) + LEAVE; + } + + // BUILD THE CHARACTER SIZE TABLE, AND DETERMINE THE MAXIMUM SIZE OF ANY + // CHARACTER IN THE FONT, AS WELL AS THE MAXIMUM EXPECTED HEIGHT OF ANY + // COMBINATION OF CHARACTERS + SIZE maxsize = {0,0}; + { + LPCTSTR testchars = "W_y,|'"; + GetTextExtentPoint32(memdc,testchars,SStrLen(testchars),&maxsize); + maxsize.cx = 0; + } + charsizetable = (LPSIZE)ALLOC(256*sizeof(SIZE)); + { + for (int loop = 0; loop < 256; ++loop) { + char teststring[2] = {loop,0}; + GetTextExtentPoint32(memdc,teststring,1,charsizetable+loop); + maxsize.cx = max(maxsize.cx,(charsizetable+loop)->cx+1); + maxsize.cy = max(maxsize.cy,(charsizetable+loop)->cy+1); + } + } + if (!(maxsize.cx && maxsize.cy)) + LEAVE; + + // ADD ONE TO THE WIDTH TO LEAVE A SPACE BETWEEN CHARACTERS, AND ROUND + // THE RESULT UP TO A MULTIPLE OF FOUR PIXELS + if (maxsize.cx & 3) + maxsize.cx += 4-(maxsize.cx & 3); + SIZE bitmapsize = {maxsize.cx*16,maxsize.cy*16}; + + // PREPARE A BITMAP HEADER AND COLOR TABLE + BITMAPINFO256 info; + ZeroMemory(&info,sizeof(BITMAPINFO256)); + info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info.bmiHeader.biWidth = bitmapsize.cx; + info.bmiHeader.biHeight = bitmapsize.cy; + info.bmiHeader.biPlanes = 1; + info.bmiHeader.biBitCount = 1; + info.bmiHeader.biCompression = BI_RGB; + + // CREATE A DEVICE INDEPENDENT BITMAP AND SELECT IT INTO THE MEMORY DC + bitmap = CreateDIBitmap(memdc,&info.bmiHeader,0,NULL,(LPBITMAPINFO)&info,DIB_RGB_COLORS); + if (!bitmap) + LEAVE; + HBITMAP oldbitmap = (HBITMAP)SelectObject(memdc,bitmap); + + // BLANK OUT THE BITMAP + { + HBRUSH oldbrush = (HBRUSH)SelectObject(memdc,GetStockObject(WHITE_BRUSH)); + HPEN oldpen = (HPEN) SelectObject(memdc,GetStockObject(WHITE_PEN)); + Rectangle(memdc,0,0,bitmapsize.cx,bitmapsize.cy); + SelectObject(memdc,oldbrush); + SelectObject(memdc,oldpen); + } + + // DRAW THE FONT INTO THE BITMAP + SetTextAlign(memdc,TA_LEFT | TA_TOP); + SetTextColor(memdc,0); + SetBkColor(memdc,0xFFFFFF); + SetBkMode(memdc,OPAQUE); + { + char string[2] = "?"; + for (int y = 0; y < 16; ++y) + for (int x = 0; x < 16; ++x) { + string[0] = y*16+x; + RECT rect = {x*maxsize.cx, + y*maxsize.cy, + (x+1)*maxsize.cx, + (y+1)*maxsize.cy}; + ExtTextOut(memdc, + x*maxsize.cx+1, + y*maxsize.cy+1, + ETO_OPAQUE, + &rect, + string, + 1, + NULL); + } + } + + // UNSELECT THE BITMAP + SelectObject(memdc,oldbitmap); + + // GET THE BITMAP BITS + packedbits = (LPBYTE)ALLOC(bitmapsize.cx*bitmapsize.cy/8); + if (!GetDIBits(memdc,bitmap,0,bitmapsize.cy,packedbits,(LPBITMAPINFO)&info,DIB_RGB_COLORS)) + LEAVE; + + // UNPACK THE BITMAP BITS INTO 8-BIT TOP-DOWN FORMAT + unpackedbits = (LPBYTE)ALLOC(bitmapsize.cx*bitmapsize.cy); + { + LPBYTE source = packedbits+(bitmapsize.cy-1)*bitmapsize.cx/8; + LPBYTE dest = unpackedbits; + for (int y = 0; y < bitmapsize.cy; ++y) { + for (int x = 0; x < bitmapsize.cx/8; ++x) { + for (int bit = 128; bit; bit >>= 1) + *dest++ = ((*source) & bit) ? 0xFF : 0; + ++source; + } + source -= bitmapsize.cx/4; + } + } + + // CREATE A STORM FONT FROM THE BITMAP BITS + success = SGdiCreateFont(unpackedbits, + bitmapsize.cx, + bitmapsize.cy, + 8, + maxsize.cx, + maxsize.cy, + charsizetable, + handle); + + } + FINALLY { + if (unpackedbits) + FREE(unpackedbits); + if (packedbits) + FREE(packedbits); + if (charsizetable) + FREE(charsizetable); + if (memdc && oldfont) + SelectObject(memdc,oldfont); + if (bitmap) + DeleteObject(bitmap); + if (memdc) + DeleteDC(memdc); + if (dc) + ReleaseDC(GetDesktopWindow(),dc); + } + + return success; +} + +//=========================================================================== +BOOL APIENTRY SGdiLoadFont (LPCTSTR filename, + int filecharwidth, + int filecharheight, + int basecharwidth, + LPSIZE charsizetable, + HSGDIFONT *handle) { + VALIDATEBEGIN; + VALIDATE(filename); + VALIDATE(*filename); + VALIDATE(filecharwidth); + VALIDATE(filecharheight); + VALIDATE(basecharwidth || charsizetable); + VALIDATE(handle); + VALIDATEEND; + + // DETERMINE THE SIZE OF THE FONT FILE + int width; + int height; + int bitdepth; + if (!SBmpLoadImage(filename,NULL,NULL,0,&width,&height,&bitdepth)) + return FALSE; + + // ALLOCATE MEMORY FOR THE FONT BITS + if (!AllocateTempBuffer(width*height)) + return FALSE; + + // READ THE FONT BITS + if (!SBmpLoadImage(filename,NULL,s_tempbuffer,width*height)) + return FALSE; + + // IF WE WEREN'T PASSED A CHARACTER SIZE TABLE, CREATE ONE BASED ON THE + // BASE CHARACTER WIDTH + SIZE charsize[256]; + if (!charsizetable) + for (int loop = 0; loop < 256; ++loop) { + charsize[loop].cx = basecharwidth; + charsize[loop].cy = basecharwidth; + } + + // CREATE THE FONT + return SGdiCreateFont(s_tempbuffer, + width, + height, + bitdepth, + filecharwidth, + filecharheight, + charsizetable ? charsizetable : &charsize[0], + handle); +} + +//=========================================================================== +BOOL APIENTRY SGdiRectangle (LPBYTE videobuffer, + int left, + int top, + int right, + int bottom, + COLORREF color) { + VALIDATEBEGIN; + VALIDATE(videobuffer); + VALIDATEEND; + + if (!ISPITCHVALID) + return FALSE; + RECT destrect = {left,top,right,bottom}; + DWORD pattern = ConvertColorRefToPattern(color); + ClipRectangle(&destrect); + return SBltROP3(videobuffer+LINEOFFSET(destrect.top)+(destrect.left << s_screenbppshift), + NULL, + (destrect.right-destrect.left) << s_screenbppshift, + destrect.bottom-destrect.top, + s_pitch, + 0, + pattern, + PATCOPY); +} + +//=========================================================================== +BOOL APIENTRY SGdiSelectObject (HSGDIOBJ handle) { + + // GET A POINTER TO THE OBJECT + LPSGDIOBJ ptr = (LPSGDIOBJ)handle; + if ((!ptr) || (ptr->signature != SIGNATURE) || (ptr->type >= NUMTYPES)) + return FALSE; + + // SELECT THE OBJECT + s_selected[ptr->type] = ptr; + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SGdiSetPitch (int pitch) { + VALIDATEBEGIN; + VALIDATE(pitch > 0); + VALIDATEEND; + + SDrawGetScreenSize(&s_screencx, + &s_screency, + &s_screenbpp); + return SGdiSetTargetDimensions(s_screencx, + s_screency, + s_screenbpp, + pitch); +} + +//=========================================================================== +BOOL APIENTRY SGdiSetTargetDimensions (int width, + int height, + int bitdepth, + int pitch) { + + // UPDATE THE CACHED DIMENSIONS + s_screencx = width; + s_screency = height; + s_screenbpp = bitdepth; + s_screenbppshift = (s_screenbpp == 16); + + // DON'T RECOMPUTE THE PITCH IF IT HASN'T CHANGED + if ((pitch == s_pitch) && + (height == s_pitchtablelines) && + ISPITCHVALID) + return TRUE; + s_pitch = pitch; + +#if USEPITCHTABLE + + // REALLOCATE THE PITCH TABLE IF NECESSARY + if (s_screency > s_pitchtablealloc) { + if (s_pitchtable) + FREE(s_pitchtable); + s_pitchtablealloc = s_screency; + s_pitchtable = (LPDWORD)ALLOC(s_screency*sizeof(DWORD)); + } + + // BUILD THE NEW PITCH TABLE + s_pitchtablelines = s_screency; + { + DWORD offset = 0; + for (int loop = 0; loop < s_pitchtablelines; ++loop) { + *(s_pitchtable+loop) = offset; + offset += pitch; + } + } + +#endif + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SGdiTextOut (LPBYTE videobuffer, + int x, + int y, + COLORREF color, + LPCTSTR string, + int chars) { + int textcoloruse; + if (!color) + textcoloruse = ETO_TEXT_BLACK; + else if (color == PALETTEINDEX(0xFF)) + textcoloruse = ETO_TEXT_WHITE; + else + textcoloruse = ETO_TEXT_COLOR; + RECT rect = {0,0,INT_MAX,INT_MAX}; + return SGdiExtTextOut(videobuffer, + x, + y, + &rect, + color, + textcoloruse, + ETO_BKG_TRANSPARENT, + string, + chars); +} diff --git a/src/Storm/SOURCE/SINTERN.H b/src/Storm/SOURCE/SINTERN.H new file mode 100644 index 0000000..170d9b6 --- /dev/null +++ b/src/Storm/SOURCE/SINTERN.H @@ -0,0 +1,19 @@ +#define _beginthreadex CreateThread +#define _endthreadex(a) + +/**************************************************************************** +* +* Storm functions +* +***/ + +HINSTANCE StormGetInstance (); + +/**************************************************************************** +* +* SFile functions +* +***/ + +BOOL APIENTRY SFileOpenFileWin32 (LPCTSTR filename, + HANDLE *handle); diff --git a/src/Storm/SOURCE/SLOG.CPP b/src/Storm/SOURCE/SLOG.CPP new file mode 100644 index 0000000..31c20ce --- /dev/null +++ b/src/Storm/SOURCE/SLOG.CPP @@ -0,0 +1,387 @@ +/**************************************************************************** +* +* SLOG.CPP +* Storm logging functions +* +* By Michael O'Brien (10/14/97) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define BUFFERSIZE 0x10000 +#define FLUSHMARK 0xC000 +#define SLOTS 4 // must be a power of two + +DECLARE_STRICT_HANDLE(HLOCKEDLOG); + +typedef struct _LOG { + HSLOG log; + _LOG *next; + HANDLE file; + DWORD bufferused; + DWORD pendpoint; + char buffer[BUFFERSIZE]; +} LOG, *LOGPTR; + +static CRITICAL_SECTION s_critsect[SLOTS]; +static LOGPTR s_loghead[SLOTS]; +static HSLOG s_sequence; + +//=========================================================================== +static void FlushLog (LOGPTR logptr) { + if (!logptr->bufferused) + return; + DWORD byteswritten; + WriteFile(logptr->file, + logptr->buffer, + logptr->bufferused, + &byteswritten, + NULL); + logptr->bufferused = 0; + logptr->pendpoint = 0; +} + +//=========================================================================== +static LOGPTR LockLog (HSLOG log, + HLOCKEDLOG *lockedhandle, + BOOL createifnecessary) { + + // IF THE LOG HANDLE IS NULL, JUST RETURN A NULL POINTER, INDICATING TO + // THE CALLER THAT IT SHOULD SILENTLY FAIL. THIS ALLOWS APPLICATIONS + // TO USE THE SAME CODE WHETHER LOGGING IS ENABLED OR DISABLED. + if (!log) { + *lockedhandle = (HLOCKEDLOG)0xFFFFFFFF; + return NULL; + } + + // DETERMINE WHICH SLOT THE LOG RECORD SHOULD BE IN + DWORD slot = (DWORD)log & (SLOTS-1); + EnterCriticalSection(&s_critsect[slot]); + *lockedhandle = (HLOCKEDLOG)slot; + + // SEARCH FOR AN EXISTING LOG RECORD + LOGPTR *nextptr = &s_loghead[slot]; + LOGPTR currptr; + while ((currptr = *nextptr) != NULL) + if (currptr->log == log) + return currptr; + else + nextptr = &currptr->next; + + // IF WE DIDN'T FIND ONE, CREATE A NEW RECORD + if (!createifnecessary) { + LeaveCriticalSection(&s_critsect[slot]); + *lockedhandle = (HLOCKEDLOG)0xFFFFFFFF; + return NULL; + } + currptr = *nextptr = (LOGPTR)VirtualAlloc(NULL,sizeof(LOG),MEM_COMMIT,PAGE_READWRITE); + currptr->log = log; + currptr->next = NULL; + currptr->file = INVALID_HANDLE_VALUE; + currptr->bufferused = 0; + currptr->pendpoint = 0; + return currptr; + +} + +//=========================================================================== +static void OutputReturn (LOGPTR logptr) { + CopyMemory(logptr->buffer+logptr->bufferused,"\r\n",3); + logptr->bufferused += 2; +} + +//=========================================================================== +static void OutputTime (LOGPTR logptr, BOOL show) { + + // GENERATE A NEW TIME STRING IF NECESSARY + static char timestr[64] = ""; + static DWORD timestrlen = 0; + static DWORD lasttime = 0; + DWORD currtime = GetTickCount(); + if (currtime != lasttime) { + lasttime = currtime; + SYSTEMTIME systime; + GetLocalTime(&systime); + wsprintf(timestr, + "%u/%u %02u:%02u:%02u.%03u ", + systime.wMonth, + systime.wDay, + systime.wHour, + systime.wMinute, + systime.wSecond, + systime.wMilliseconds); + timestrlen = SStrLen(timestr); + } + + // COPY THE TIME STRING TO THE OUTPUT BUFFER + if (show) + CopyMemory(logptr->buffer+logptr->bufferused,timestr,timestrlen+1); + else { + FillMemory(logptr->buffer+logptr->bufferused,timestrlen,' '); + logptr->buffer[logptr->bufferused+timestrlen] = 0; + } + logptr->bufferused += timestrlen; + +} + +//=========================================================================== +static void UnlockDeleteLog (LOGPTR logptr, HLOCKEDLOG lockedhandle) { + DWORD slot = (DWORD)lockedhandle; + LOGPTR *nextptr = &s_loghead[slot]; + LOGPTR currptr; + while ((currptr = *nextptr) != NULL) + if (currptr == logptr) { + *nextptr = currptr->next; + VirtualFree(currptr,0,MEM_RELEASE); + break; + } + else + nextptr = &currptr->next; + LeaveCriticalSection(&s_critsect[slot]); +} + +//=========================================================================== +static void UnlockLog (HLOCKEDLOG lockedhandle) { + DWORD slot = (DWORD)lockedhandle; + LeaveCriticalSection(&s_critsect[slot]); +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +void APIENTRY SLogClose (HSLOG log) { + + // LOCK THE LOG RECORD + HLOCKEDLOG lockedhandle; + LOGPTR logptr = LockLog(log,&lockedhandle,FALSE); + if (!logptr) + return; + + // FLUSH THE LOG RECORD AND CLOSE THE FILE + FlushLog(logptr); + CloseHandle(logptr->file); + + // UNLOCK THE LOG RECORD + UnlockDeleteLog(logptr,lockedhandle); + +} + +//=========================================================================== +BOOL APIENTRY SLogCreate (LPCTSTR filename, + DWORD flags, + HSLOG *log) { + VALIDATEBEGIN; + VALIDATE(filename); + VALIDATE(*filename); + VALIDATEANDBLANK(log); + VALIDATEEND; + + // OPEN THE FILE + HANDLE file = CreateFile(filename, + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (file == INVALID_HANDLE_VALUE) + return FALSE; + + // CREATE THE LOG RECORD + *log = s_sequence = (HSLOG)(((DWORD)s_sequence)+1); + HLOCKEDLOG lockedhandle; + LOGPTR logptr = LockLog(*log,&lockedhandle,TRUE); + logptr->file = file; + UnlockLog(lockedhandle); + + return TRUE; +} + +//=========================================================================== +void APIENTRY SLogDestroy () { + SLogFlushAll(); + for (DWORD slot = 0; slot < SLOTS; ++slot) { + EnterCriticalSection(&s_critsect[slot]); + while (s_loghead[slot]) { + SLogClose(s_loghead[slot]->log); + REPORTRESOURCELEAK(HSLOG); + } + LeaveCriticalSection(&s_critsect[slot]); + DeleteCriticalSection(&s_critsect[slot]); + } +} + +//=========================================================================== +void APIENTRY SLogDump (HSLOG log, + LPCVOID data, + DWORD bytes) { + + // LOCK THE LOG RECORD + HLOCKEDLOG lockedhandle; + LOGPTR logptr = LockLog(log,&lockedhandle,FALSE); + if (!logptr) + return; + +#define SPRINTFTOBUFFER(fmt,val) \ + do { \ + wsprintf(logptr->buffer+logptr->bufferused,(fmt),(val)); \ + logptr->bufferused += SStrLen(logptr->buffer+logptr->bufferused); \ + } while (0) +#define STRCPYTOBUFFER(str) \ + logptr->bufferused += SStrCopy(logptr->buffer+logptr->bufferused,(str)) + + // OUTPUT THE DATA TO THE LOG IN HEX FORMAT, EIGHT BYTES PER LINE + DWORD offset = 0; + while (offset < bytes) { + OutputTime(logptr,FALSE); + SPRINTFTOBUFFER("%04x ",offset); + DWORD loop; + for (loop = offset; loop < offset+8; ++loop) { + if (loop < bytes) + SPRINTFTOBUFFER("%02x ",(unsigned)*((LPBYTE)data+loop)); + else + STRCPYTOBUFFER(" "); + if ((loop & 3) == 3) + STRCPYTOBUFFER(" "); + } + for (loop = offset; loop < offset+8; ++loop) { + char value = (loop < bytes) ? *((char *)data+loop) : 0; + if ((value >= 32) && (value <= 126)) + SPRINTFTOBUFFER("%c",value); + else + STRCPYTOBUFFER(value ? "." : " "); + if ((loop & 7) == 3) + STRCPYTOBUFFER(" "); + } + OutputReturn(logptr); + offset += 8; + } + +#undef STRCPYTOBUFFER +#undef SPRINTFTOBUFFER + + // ADVANCE THE PENDING POINT + logptr->pendpoint = logptr->bufferused; + + // IF THE BUFFER IS GETTING FULL, FLUSH IT + if (logptr->bufferused >= FLUSHMARK) + FlushLog(logptr); + + // UNLOCK THE LOG RECORD + UnlockLog(lockedhandle); + +} + +//=========================================================================== +void APIENTRY SLogFlush (HSLOG log) { + + // LOCK THE LOG RECORD + HLOCKEDLOG lockedhandle; + LOGPTR logptr = LockLog(log,&lockedhandle,FALSE); + if (!logptr) + return; + + // FLUSH THE LOG + FlushLog(logptr); + + // UNLOCK THE LOG RECORD + UnlockLog(lockedhandle); + +} + +//=========================================================================== +void APIENTRY SLogFlushAll () { + for (DWORD slot = 0; slot < SLOTS; ++slot) { + EnterCriticalSection(&s_critsect[slot]); + LOGPTR curr = s_loghead[slot]; + while (curr) { + FlushLog(curr); + curr = curr->next; + } + LeaveCriticalSection(&s_critsect[slot]); + } +} + +//=========================================================================== +void APIENTRY SLogInitialize () { + for (DWORD slot = 0; slot < SLOTS; ++slot) + InitializeCriticalSection(&s_critsect[slot]); +} + +//=========================================================================== +void __cdecl SLogPend (HSLOG log, + LPCTSTR format, + ...) { + + // LOCK THE LOG RECORD + HLOCKEDLOG lockedhandle; + LOGPTR logptr = LockLog(log,&lockedhandle,FALSE); + if (!logptr) + return; + + // RESET THE OUTPUT LOCATION TO THE PENDING POINT + logptr->bufferused = logptr->pendpoint; + + // OUTPUT THE CURRENT TIME TO THE LOG + OutputTime(logptr,TRUE); + + // OUTPUT THE ARGUMENT STRING TO THE LOG + va_list arglist; + va_start(arglist,format); + vsprintf(logptr->buffer+logptr->bufferused, + format, + arglist); + va_end(arglist); + logptr->bufferused += SStrLen(logptr->buffer+logptr->bufferused); + + // OUTPUT A CARRIAGE RETURN TO THE LOG + OutputReturn(logptr); + + // UNLOCK THE LOG RECORD + UnlockLog(lockedhandle); + +} + +//=========================================================================== +void __cdecl SLogWrite (HSLOG log, + LPCTSTR format, + ...) { + + // LOCK THE LOG RECORD + HLOCKEDLOG lockedhandle; + LOGPTR logptr = LockLog(log,&lockedhandle,FALSE); + if (!logptr) + return; + + // OUTPUT THE CURRENT TIME TO THE LOG + OutputTime(logptr,TRUE); + + // OUTPUT THE ARGUMENT STRING TO THE LOG + va_list arglist; + va_start(arglist,format); + vsprintf(logptr->buffer+logptr->bufferused, + format, + arglist); + va_end(arglist); + logptr->bufferused += SStrLen(logptr->buffer+logptr->bufferused); + + // OUTPUT A CARRIAGE RETURN TO THE LOG + OutputReturn(logptr); + + // ADVANCE THE PENDING POINT + logptr->pendpoint = logptr->bufferused; + + // IF THE BUFFER IS GETTING FULL, FLUSH IT + if (logptr->bufferused >= FLUSHMARK) + FlushLog(logptr); + + // UNLOCK THE LOG RECORD + UnlockLog(lockedhandle); + +} diff --git a/src/Storm/SOURCE/SMEM.CPP b/src/Storm/SOURCE/SMEM.CPP new file mode 100644 index 0000000..a686906 --- /dev/null +++ b/src/Storm/SOURCE/SMEM.CPP @@ -0,0 +1,1316 @@ +/**************************************************************************** +* +* SMEM.CPP +* Storm memory manager +* +* By Michael O'Brien (3/18/97) +* +* This module cannot use constructors or destructors, because it is called +* by the runtime library startup code prior to construction and after +* destruction. +* +* The allocation functions implemented in this module are guaranteed not +* to return NULL. Storm always displays a fatal error if an allocation +* can not succeed, so that the application does not have to have failure +* code paths for each allocation. However, Storm does not display errors +* for failures to free memory unless debug mode is enabled. +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define FIRSTUSERHEAP 0x80000000 // must be a power of two +#define MAXALLOCSIZE (0xFFFF-(sizeof(HEAP)+MAX_PATH+sizeof(BLOCK)+2*sizeof(DWORD))) +#define MAXFREEMAINT 4 +#define MAXHEAPSIZE 0x7FFFFFFF +#define MINBLOCKSIZE (sizeof(BLOCK)+2*sizeof(DWORD)) +#define PAGESIZE 0x1000 // must be a power of two +#define RESERVESIZE 0x10000 +#define SIGNATURE1 0x6F6D +#define SIGNATURE2 0xB112 +#define TABLESIZE 256 // must be a power of two + +#define REGKEY "Internal" +#define REGVAL_DEBUG "Debug Memory" +#define REGVAL_GUARD "Protect Memory" +#define REGVAL_TRACEFILE "SMem Trace File" + +#define BF_BOUNDINGSIG 0x01 +#define BF_FREEBLOCK 0x02 +#define BF_LARGEALLOC 0x04 +#define BF_OUTSIDEHEAP 0x08 +#define BF_PRESERVE 0x80 + +typedef struct _BLOCK { + WORD bytes; + BYTE padding; + BYTE flags; + WORD heapaddr; + WORD signature1; +} BLOCK, *BLOCKPTR; + +typedef struct _FASTBLOCK { + WORD bytes; + BYTE padding; + BYTE flags; + DWORD addrsig; +} FASTBLOCK, *FASTBLOCKPTR; + +typedef struct _FREEBLOCK { + WORD bytes; + BYTE padding; + BYTE flags; + _FREEBLOCK *next; +} FREEBLOCK, *FREEBLOCKPTR; + +typedef struct _HEAP { + _HEAP *next; + HSHEAP handle; + DWORD slot; + DWORD addrsig; + BOOL active; + DWORD allocatedblocks; + BLOCKPTR firstblock; + BLOCKPTR termblock; + FREEBLOCKPTR firstfreeblock; + DWORD maintainfreelist; + DWORD chunksize; + DWORD committedbytes; + DWORD reservedbytes; + int linenumber; + char filename[1]; +} HEAP, *HEAPPTR; + +DECLARE_STRICT_HANDLE(HLOCKEDHEAP); + +static BOOL s_emptyheap[TABLESIZE]; +static CRITICAL_SECTION s_critsect[TABLESIZE]; +static BOOL s_debugmode; +static BOOL s_guardmode; +static HEAPPTR s_heaphead[TABLESIZE]; +static BOOL s_initialized; +static HEAPPTR s_lastemptyheap; +static DWORD s_pagesize; + +/**************************************************************************** +* +* TRACING FUNCTIONS +* +***/ + +#ifdef _DEBUG + +static CSLog s_log(REGKEY,REGVAL_TRACEFILE); + +//=========================================================================== +static inline void Trace (LPVOID ptr, + LPCTSTR funcname, + LPCTSTR filename, + int linenumber) { + if (!s_log.GetHandle()) + return; + SLogWrite(s_log.GetHandle(), + "[0x%08x] %-20s %s (%d)", + ptr, + funcname, + filename ? filename : "", + linenumber); +} + +#define TRACE Trace + +#else + +#define TRACE + +#endif + +/**************************************************************************** +* +* SYNCHRONIZATION AND CONVERSION FUNCTIONS +* +***/ + +//=========================================================================== +static inline BOOL CheckInitialized () { +#ifdef STATICLIB + if (!s_initialized) + SMemInitialize(); +#endif + return s_initialized; +} + +//=========================================================================== +static void FatalError (DWORD errorcode, + LPCSTR filename, + int linenumber) { + SErrDisplayError(errorcode, + filename, + linenumber, + NULL, + FALSE); + ExitProcess(1); +} + +//=========================================================================== +static inline BLOCKPTR GetBlockPtrByPtr (LPVOID ptr) { + if (!ptr) + return NULL; + BLOCKPTR blockptr = (BLOCKPTR)ptr-1; + if (blockptr->flags & BF_OUTSIDEHEAP) + blockptr = *(BLOCKPTR *)((LPBYTE)blockptr-sizeof(BLOCKPTR)); + return blockptr; +} + +//=========================================================================== +static inline HSHEAP GetHandleByBlockPtr (BLOCKPTR blockptr) { + HEAPPTR heapptr = (HEAPPTR)((DWORD)(blockptr->heapaddr) << 16); + return heapptr->handle; +} + +//=========================================================================== +static inline HSHEAP GetHandleByCaller (LPCSTR filename, + int linenumber) { + static BOOL cacheenabled = TRUE; + static DWORD lastchars = 0; + static int lastline = 0; + static LPCSTR lastptr = NULL; + static HSHEAP lasthandle = (HSHEAP)0; + + // IF CACHING IS ENABLED AND THIS CALLER MATCHES THE PREVIOUS ONE, + // RETURN THE PREVIOUSLY COMPUTED HANDLE + DWORD filenamechars = *(LPDWORD)filename; + if (cacheenabled && + (filename == lastptr) && + (linenumber == lastline)) { + + // VERIFY THAT THE CALLER IS NOT JUST CHANGING FILENAMES WITHIN A + // STATIC BUFFER BY CHECKING THE FIRST FOUR CHARACTERS. IF THEY + // ARE DIFFERENT FROM WHAT WE EXPECT, DISABLE CACHING. + if (filenamechars != lastchars) + cacheenabled = FALSE; + else + return lasthandle; + + } + + // OTHERWISE, COMPUTE THE HANDLE FOR THIS CALLER + DWORD hashval = SStrHash(filename, + TRUE, + (DWORD)linenumber); + HSHEAP handle = (HSHEAP)(hashval & (FIRSTUSERHEAP-1)); + if (!handle) + handle = (HSHEAP)1; + + // SAVE IT IN THE CACHE + lastchars = filenamechars; + lastptr = filename; + lastline = linenumber; + lasthandle = handle; + + return handle; +} + +//=========================================================================== +static inline LPVOID GetPtrByBlockPtr (BLOCKPTR blockptr) { + if (!blockptr) + return NULL; + LPVOID ptr = blockptr+1; + if (blockptr->flags & BF_LARGEALLOC) + ptr = *(LPVOID *)ptr; + return ptr; +} + +//=========================================================================== +static inline DWORD GetSlotByHandle (HSHEAP handle) { + return (DWORD)handle & (TABLESIZE-1); +} + +//=========================================================================== +static inline HEAPPTR LockHeapByBlockPtr (BLOCKPTR blockptr, + HLOCKEDHEAP *lockedhandle) { + + // CONVERT THE COMPACT FORM OF THE HEAP ADDRESS TO A FULL ADDRESS + HEAPPTR heapptr = (HEAPPTR)((DWORD)(blockptr->heapaddr) << 16); + + // LOCK THE HEAP'S CRITICAL SECTION + EnterCriticalSection(&s_critsect[heapptr->slot]); + *lockedhandle = (HLOCKEDHEAP)heapptr->slot; + + return heapptr; +} + +//=========================================================================== +static inline HEAPPTR LockHeapByHandle (HSHEAP handle, + HLOCKEDHEAP *lockedhandle, + BOOL heapmustexist) { + + // LOCK THE HEAP'S CRITICAL SECTION + DWORD slot = GetSlotByHandle(handle); + EnterCriticalSection(&s_critsect[slot]); + *lockedhandle = (HLOCKEDHEAP)slot; + + // FIND AND RETURN THE HEAP HEADER + HEAPPTR heapptr = s_heaphead[slot]; + while (heapptr) + if (heapptr->handle == handle) + return heapptr; + else + heapptr = heapptr->next; + + // IF WE DIDN'T FIND THE HEAP AND THE CALLER REQUIRES THAT THE HEAP + // EXIST, UNLOCK THE CRITICAL SECTION + if (heapmustexist) { + LeaveCriticalSection(&s_critsect[slot]); + *lockedhandle = (HLOCKEDHEAP)INVALID_HANDLE_VALUE; + } + + return NULL; +} + +//=========================================================================== +static void Warning (DWORD errorcode, + LPCSTR filename, + int linenumber) { + SErrSetLastError(errorcode); + if (s_debugmode) + SErrDisplayError(errorcode, + filename, + linenumber, + NULL, + TRUE); +} + +//=========================================================================== +static inline void UnlockHeap (HLOCKEDHEAP lockedhandle) { + DWORD slot = (DWORD)lockedhandle; + LeaveCriticalSection(&s_critsect[slot]); +} + +/**************************************************************************** +* +* BLOCK ALLOCATION/DEALLOCATION FUNCTIONS +* +***/ + +static void CombineFreeBlocks (HEAPPTR heapptr); +static void ComputePageSize (); +static void FreeHeap (HEAPPTR *nextptr); +static BOOL FreeHeapBlock (HEAPPTR heapptr, + BLOCKPTR block); + +//=========================================================================== +static HEAPPTR AllocateHeap (LPCSTR filename, + int linenumber, + HSHEAP handle, + DWORD slot, + DWORD chunksize, + DWORD commitsize, + DWORD reservesize) { + + // RESERVE MEMORY FOR THE NEW HEAP + HEAPPTR newheap = (HEAPPTR)VirtualAlloc(NULL, + reservesize, + MEM_RESERVE, + PAGE_NOACCESS); + + if (!newheap) + FatalError(ERROR_NOT_ENOUGH_MEMORY, + filename, + linenumber); + if (!VirtualAlloc(newheap, + commitsize, + MEM_COMMIT, + PAGE_READWRITE)) + FatalError(ERROR_NOT_ENOUGH_MEMORY, + filename, + linenumber); + + // DETERMINE THE SIZE OF THE NEW HEAP HEADER + DWORD filenamebytes = (filename ? SStrLen(filename) : 0)+1; + DWORD headerbytes = sizeof(HEAP)+filenamebytes-1; + if (headerbytes & 3) + headerbytes += 4-(headerbytes & 3); + + // FILL IN THE NEW HEAP HEADER + newheap->handle = handle; + newheap->next = s_heaphead[slot]; + newheap->slot = slot; + newheap->active = TRUE; + newheap->firstblock = (BLOCKPTR)((LPBYTE)newheap+headerbytes); + newheap->termblock = (BLOCKPTR)((LPBYTE)newheap+headerbytes); + newheap->firstfreeblock = NULL; + newheap->maintainfreelist = MAXFREEMAINT; + newheap->chunksize = chunksize; + newheap->committedbytes = commitsize; + newheap->reservedbytes = reservesize; + newheap->linenumber = linenumber; + + // FILL IN THE HEAP'S FILENAME + if (filename) + CopyMemory(newheap->filename,filename,filenamebytes); + else + newheap->filename[0] = 0; + + // FILL IN THE HEAP'S ADDRESS AND SIGNATURE OPTIMIZED DWORD + { + BLOCK block; + block.heapaddr = (WORD)((DWORD)newheap >> 16); + block.signature1 = SIGNATURE1; + FASTBLOCKPTR fastblockptr = (FASTBLOCKPTR)█ + newheap->addrsig = fastblockptr->addrsig; + } + + // ADD THE HEAP TO THE LIST OF HEAPS + s_heaphead[slot] = newheap; + + return newheap; +} + +//=========================================================================== +static LPVOID AllocateHeapBlock (HEAPPTR heapptr, + DWORD bytes, + BYTE baseflags) { + + // DETERMINE THE BLOCK SIZE REQUIRED TO SATISFY THIS ALLOCATION REQUEST + BOOL largealloc = s_guardmode || (bytes > MAXALLOCSIZE); + BOOL boundingsig = s_debugmode && !largealloc; + DWORD reqblocksize; + { + DWORD userbytes = largealloc ? sizeof(LPVOID) : bytes; + DWORD overhead = sizeof(BLOCK)+(boundingsig ? sizeof(WORD) : 0); + reqblocksize = userbytes+overhead; + } + DWORD blocksize = reqblocksize; + if (blocksize & 7) + blocksize += 8-(blocksize & 7); + + // REBUILD THIS HEAP'S FREE LIST IF NECESSARY + if (heapptr->firstfreeblock && + !heapptr->maintainfreelist) + CombineFreeBlocks(heapptr); + heapptr->maintainfreelist = MAXFREEMAINT; + + // SEARCH THIS HEAP FOR THE CLOSEST MATCHING FREE BLOCK WHICH IS + // LARGE ENOUGH TO SATISFY THE REQUEST + DWORD bestdelta = LONG_MAX; + FREEBLOCKPTR *bestfreeblock = NULL; + { + FREEBLOCKPTR *nextfreeblock = &heapptr->firstfreeblock; + while (*nextfreeblock) { + DWORD delta = (*nextfreeblock)->bytes-blocksize; + if (delta < bestdelta) { + bestdelta = delta; + bestfreeblock = nextfreeblock; + if (delta < MINBLOCKSIZE) + break; + } + nextfreeblock = &(*nextfreeblock)->next; + } + } + + // IF WE FOUND A FREE BLOCK THAT CAN SATISFY THE REQUEST, SUBDIVIDE IT + // AS NECESSARY AND USE IT + BLOCKPTR newblock; + if (bestfreeblock) { + newblock = (BLOCKPTR)*bestfreeblock; + if (bestdelta >= MINBLOCKSIZE) { + FREEBLOCKPTR newfreeblock = (FREEBLOCKPTR)((LPBYTE)newblock+blocksize); + newfreeblock->bytes = (WORD)bestdelta; + newfreeblock->padding = 0; + newfreeblock->flags = BF_FREEBLOCK; + newfreeblock->next = (*bestfreeblock)->next; + newblock->bytes = (WORD)blocksize; + *bestfreeblock = newfreeblock; + } + else + *bestfreeblock = (*bestfreeblock)->next; + } + + // OTHERWISE, ALLOCATE A NEW BLOCK ON THE END OF THE HEAP + else { + DWORD newheapsize = ((LPBYTE)heapptr->termblock-(LPBYTE)heapptr)+blocksize; + + // IF THIS NEW BLOCK WON'T FIT IN THE SPACE WE HAVE RESERVED FOR THIS + // HEAP, CREATE A NEW HEAP AND SET IT AS THE ACTIVE HEAP + if (newheapsize > heapptr->reservedbytes) { + DWORD newreservesize = (heapptr->reservedbytes < 0x10000000) + ? heapptr->reservedbytes*2 + : heapptr->reservedbytes; + DWORD newchunksize = newreservesize >> 3; + HEAPPTR newheapptr = AllocateHeap(heapptr->filename, + heapptr->linenumber, + heapptr->handle, + heapptr->slot, + newchunksize, + newchunksize, + newreservesize); + if (!newheapptr) + return NULL; + heapptr->active = FALSE; + heapptr = newheapptr; + newheapsize = ((LPBYTE)heapptr->termblock-(LPBYTE)heapptr)+blocksize; + } + + // IF WE HAVEN'T YET COMMITTED THE MEMORY THAT WILL BE NEEDED FOR THIS + // NEW BLOCK, DO SO NOW + if (newheapsize > heapptr->committedbytes) { + DWORD commitsize = newheapsize-heapptr->committedbytes; + if (commitsize & (heapptr->chunksize-1)) + commitsize += heapptr->chunksize-(commitsize & (heapptr->chunksize-1)); + if (heapptr->committedbytes+commitsize > heapptr->reservedbytes) + commitsize = heapptr->reservedbytes-heapptr->committedbytes; + VirtualAlloc((LPBYTE)heapptr+heapptr->committedbytes, + commitsize, + MEM_COMMIT, + PAGE_READWRITE); + heapptr->committedbytes += commitsize; + } + + // DETERMINE THE LOCATION AND SIZE OF THE NEW BLOCK + newblock = heapptr->termblock; + newblock->bytes = (WORD)blocksize; + + // CREATE A NEW TERMINATOR BLOCK + heapptr->termblock = (BLOCKPTR)((LPBYTE)newblock+blocksize); + + } + + // FILL IN THE NEW BLOCK'S HEADER + newblock->padding = (BYTE)(newblock->bytes-reqblocksize); + newblock->flags = baseflags | (largealloc ? BF_LARGEALLOC : 0); + ((FASTBLOCKPTR)newblock)->addrsig = heapptr->addrsig; + ++heapptr->allocatedblocks; + + // IF REQUESTED, ADD A SECOND SIGNATURE TO BOUND THE BLOCK + if (boundingsig) { + newblock->flags |= BF_BOUNDINGSIG; + *(LPWORD)((LPBYTE)newblock+reqblocksize-sizeof(WORD)) = SIGNATURE2; + } + + // IF THIS IS A LARGE ALLOCATION, THEN ALLOCATE A BLOCK OF USER MEMORY + // OUTSIDE THE HEAP, AND MAKE THE BLOCK INSIDE THE HEAP POINT TO THE + // EXTERNAL BLOCK. SAVE A POINTER TO THE USER PORTION OF THE EXTERNAL + // BLOCK. + LPVOID result; + if (largealloc) { + if (!s_pagesize) + ComputePageSize(); + DWORD largeallocbytes = sizeof(BLOCKPTR)+sizeof(BLOCK)+bytes; + DWORD largeallocoffset = 0; + + // IF WE ARE IN DEBUG MODE, ALIGN THE ALLOCATION AT THE END OF A PAGE, + // SO THAT IF THE APPLICATION OVERWRITES THE ALLOCATION IT WILL TRIGGER + // AN EXCEPTION. (HOWEVER, KEEP THE ALLOCATION ALIGNED ON A DWORD + // BOUNDARY.) + LPBYTE largeallocptr = NULL; + if (s_debugmode || s_guardmode) { + largeallocoffset = s_pagesize-(largeallocbytes & (s_pagesize-1)); + if (s_guardmode) + largeallocoffset &= (s_pagesize-1); + else + largeallocoffset &= (s_pagesize-4); + if (s_guardmode) + largeallocptr = (LPBYTE)VirtualAlloc(NULL, + largeallocbytes+largeallocoffset+4, + MEM_RESERVE, + PAGE_NOACCESS); + } + + largeallocptr = (LPBYTE)VirtualAlloc(largeallocptr, + largeallocbytes+largeallocoffset, + MEM_COMMIT, + PAGE_READWRITE); + if (!largeallocptr) { + FreeHeapBlock(heapptr,newblock); + return NULL; + } + largeallocptr = (LPBYTE)largeallocptr+largeallocoffset; + *(BLOCKPTR *)largeallocptr = newblock; + BLOCKPTR largeallocblock = (BLOCKPTR)((LPBYTE)largeallocptr+sizeof(BLOCKPTR)); + largeallocblock->bytes = (WORD)((bytes+0xFFFF) >> 16); + largeallocblock->padding = 0; + largeallocblock->flags = BF_LARGEALLOC | BF_OUTSIDEHEAP; + ((FASTBLOCKPTR)largeallocblock)->addrsig = heapptr->addrsig; + result = largeallocblock+1; + *(LPVOID *)(newblock+1) = result; + } + + // OTHERWISE, SAVE A POINTER TO THE USER PORTION OF THE HEAP BLOCK + else + result = newblock+1; + + return result; +} + +//=========================================================================== +static BOOL CheckValidBlock (LPVOID ptr, + BOOL displayerror, + LPCSTR filename, + int linenumber) { + + // VERIFY THAT THIS ISN'T A NULL POINTER + if (!ptr) { + if (displayerror) + Warning(STORM_ERROR_MEMORY_NULL_POINTER, + filename, + linenumber); + return FALSE; + } + + // VERIFY THAT THIS IS A VALID HEAP BLOCK + BLOCKPTR block = (BLOCKPTR)ptr-1; + if (block->signature1 != SIGNATURE1) { + if (displayerror) + Warning(STORM_ERROR_MEMORY_INVALID_BLOCK, + filename, + linenumber); + return FALSE; + } + + // VERIFY THAT THIS BLOCK IS ALLOCATED + if (block->flags & BF_FREEBLOCK) { + if (displayerror) + Warning(STORM_ERROR_MEMORY_ALREADY_FREED, + filename, + linenumber); + return FALSE; + } + + // IF THIS BLOCK HAS A BOUNDING SIGNATURE, VERIFY THAT IT IS INTACT + if ((block->flags & BF_BOUNDINGSIG) && + (*(LPWORD)((LPBYTE)block+block->bytes-block->padding-sizeof(WORD)) != SIGNATURE2) && + displayerror) + Warning(STORM_ERROR_MEMORY_CORRUPT, + filename, + linenumber); + + return TRUE; +} + +//=========================================================================== +static void CombineFreeBlocks (HEAPPTR heapptr) { + + // RESET THE LIST OF FREE BLOCKS + FREEBLOCKPTR prevfreeblock = NULL; + FREEBLOCKPTR *nextfreeblock = &heapptr->firstfreeblock; + + // SEARCH THE ENTIRE HEAP FOR FREE BLOCKS + for (BLOCKPTR blockptr = heapptr->firstblock; + blockptr != heapptr->termblock; + blockptr = (BLOCKPTR)((LPBYTE)blockptr+blockptr->bytes)) + if (blockptr->flags & BF_FREEBLOCK) { + FREEBLOCKPTR freeblockptr = (FREEBLOCKPTR)blockptr; + freeblockptr->next = NULL; + + // IF THIS FREE BLOCK IS ADJACENT TO THE PREVIOUS ONE, COMBINE THEM + if (prevfreeblock && + (freeblockptr == (FREEBLOCKPTR)((LPBYTE)prevfreeblock+prevfreeblock->bytes)) && + ((DWORD)freeblockptr->bytes+(DWORD)prevfreeblock->bytes <= 0xFFFF)) + prevfreeblock->bytes += freeblockptr->bytes; + + // OTHERWISE, ADD THIS FREE BLOCK TO THE LIST + else { + *nextfreeblock = freeblockptr; + nextfreeblock = &freeblockptr->next; + prevfreeblock = freeblockptr; + } + + } + + // TERMINATE THE LIST OF FREE BLOCKS + *nextfreeblock = NULL; + +} + +//=========================================================================== +static void ComputePageSize () { + + // GET THE SYSTEM'S PAGE SIZE + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + + // FORCE THE PAGE SIZE TO BE A POWER OF TWO (JUST IN CASE IT ISN'T ALREADY) + s_pagesize = 1; + while (s_pagesize < sysinfo.dwPageSize) + s_pagesize <<= 1; + +} + +//=========================================================================== +static HEAPPTR * DestroyHeap (HEAPPTR *nextptr) { + BOOL preserve = FALSE; + + // IF THERE ARE ANY ALLOCATED BLOCKS IN THIS HEAP WHICH AREN'T MARKED + // PRESERVE-ON-DESTROY, DISPLAY A WARNING AND DELETE THEM + BLOCKPTR blockptr = (*nextptr)->firstblock; + while (blockptr != (*nextptr)->termblock) + if (blockptr->flags & (BF_FREEBLOCK | BF_PRESERVE)) { + preserve |= (blockptr->flags & BF_PRESERVE); + blockptr = (BLOCKPTR)((LPBYTE)blockptr+blockptr->bytes); + } + else { + Warning(STORM_ERROR_MEMORY_NEVER_RELEASED, + (*nextptr)->filename, + (*nextptr)->linenumber); + FreeHeapBlock(*nextptr,blockptr); + blockptr = (*nextptr)->firstblock; + } + + // IF THERE WERE NO PRESERVE-ON-DESTROY BLOCKS, FREE THE HEAP + if (!preserve) { + FreeHeap(nextptr); + return nextptr; + } + else + return &(*nextptr)->next; + +} + +//=========================================================================== +static void FreeEmptyHeaps () { + s_lastemptyheap = NULL; + for (DWORD slot = 0; slot < TABLESIZE; ++slot) + if (s_emptyheap[slot]) { + EnterCriticalSection(&s_critsect[slot]); + s_emptyheap[slot] = FALSE; + HEAPPTR *nextheap = &s_heaphead[slot]; + while (*nextheap) + if ((!(*nextheap)->allocatedblocks) && + ((DWORD)((*nextheap)->handle) < FIRSTUSERHEAP)) + FreeHeap(nextheap); + else + nextheap = &(*nextheap)->next; + LeaveCriticalSection(&s_critsect[slot]); + } +} + +//=========================================================================== +static void FreeHeap (HEAPPTR *nextptr) { + + // UNLINK THE HEAP + HEAPPTR heapptr = *nextptr; + *nextptr = heapptr->next; + + // FREE THE HEAP + VirtualFree(heapptr,0,MEM_RELEASE); + +} + +//=========================================================================== +static BOOL FreeHeapBlock (HEAPPTR heapptr, + BLOCKPTR block) { + + // MARK THE BLOCK AS FREE + FREEBLOCKPTR freeblock = (FREEBLOCKPTR)block; + freeblock->flags = BF_FREEBLOCK; + freeblock->padding = 0; + freeblock->next = NULL; + + // IF WE ARE MAINTAING A FULLY COMBINED AND SORTED FREE LIST, THE COMBINE + // THIS BLOCK WITH CONTIGUOUS FREE BLOCKS AND ADD FIND THE CORRECT LOCATION + // FOR IT IN THE FREE LIST. OTHERWISE, JUST DO MINIMAL PROCESSING FOR NOW, + // DELAYING THE COMBINING AND SORTING OPERATIONS UNTIL THE NEXT BLOCK + // ALLOCATION ON THIS HEAP. + FREEBLOCKPTR endblock = (FREEBLOCKPTR)((LPBYTE)freeblock+freeblock->bytes); + FREEBLOCKPTR *nextfreeblock = &heapptr->firstfreeblock; + FREEBLOCKPTR currfreeblock; + if (heapptr->maintainfreelist) { + --heapptr->maintainfreelist; + for (;;) { + currfreeblock = *nextfreeblock; + if ((!currfreeblock) || (currfreeblock > endblock)) + break; + BOOL unlink = FALSE; + if ((DWORD)freeblock->bytes+(DWORD)currfreeblock->bytes <= 0xFFFF) + if (currfreeblock == endblock) { + freeblock->bytes += currfreeblock->bytes; + endblock = (FREEBLOCKPTR)((LPBYTE)block+block->bytes); + unlink = TRUE; + } + else if (((FREEBLOCKPTR)((LPBYTE)currfreeblock+currfreeblock->bytes)) == freeblock) { + currfreeblock->bytes += freeblock->bytes; + freeblock = currfreeblock; + unlink = TRUE; + } + if (unlink) + *nextfreeblock = currfreeblock->next; + else + nextfreeblock = &currfreeblock->next; + } + } + + // IF THIS BLOCK IS AT THE END OF THE HEAP, SHRINK THE HEAP + if (heapptr->termblock == (BLOCKPTR)endblock) + heapptr->termblock = (BLOCKPTR)freeblock; + + // OTHERWISE, ADD THIS BLOCK TO THE LINKED LIST OF FREE BLOCKS + else { + freeblock->next = currfreeblock; + *nextfreeblock = freeblock; + } + + // IF THIS HEAP IS NOW EMPTY, SET OURSELVES A REMINDER TO REMOVE IT DURING + // THE NEXT CLEANUP + --heapptr->allocatedblocks; + if ((!heapptr->allocatedblocks) && + ((DWORD)(heapptr->handle) < FIRSTUSERHEAP)) { + s_emptyheap[heapptr->slot] = TRUE; + s_lastemptyheap = heapptr; + } + + return TRUE; +} + +//=========================================================================== +static inline LPVOID SatisfyAllocRequest (HLOCKEDHEAP lockedhandle, + HEAPPTR heapptr, + DWORD flags, + DWORD bytes) { + + // ALLOCATE THE REQUESTED BLOCK OF MEMORY FROM THE CALLER'S HEAP + LPVOID result = NULL; + if (heapptr) { + BYTE baseflags = 0; + if (flags & SMEM_FLAG_PRESERVEONDESTROY) + baseflags |= BF_PRESERVE; + result = AllocateHeapBlock(heapptr, + bytes, + baseflags); + } + + // IF THERE IS AN EMPTY HEAP WAITING TO BE CLEANED UP, AND WE DIDN'T + // JUST ALLOCATE A BLOCK IN IT, THEN PERFORM THE CLEANUP + if (s_lastemptyheap && (s_lastemptyheap != heapptr)) + FreeEmptyHeaps(); + + // UNLOCK THE HEAP + UnlockHeap(lockedhandle); + + // IF THE ALLOCATION FAILED, DISPLAY A FATAL ERROR + if (!result) + if (heapptr->filename[0]) + FatalError(ERROR_NOT_ENOUGH_MEMORY, + heapptr->filename, + heapptr->linenumber); + else + FatalError(ERROR_NOT_ENOUGH_MEMORY, + "SMemHeapAlloc()", + SERR_LINECODE_FUNCTION); + + // FILL THE NEW BLOCK WITH ITS REQUIRED STARTING VALUE + if (flags & SMEM_FLAG_ZEROMEMORY) + ZeroMemory(result,bytes); + else if (s_debugmode) + FillMemory(result,bytes,0xEE); + + return result; +} + +//=========================================================================== +static inline BOOL SatisfyFreeRequest (HLOCKEDHEAP lockedhandle, + HEAPPTR heapptr, + LPVOID ptr, + BLOCKPTR blockptr) { + + // IF THIS IS A LARGE BLOCK ALLOCATED OUTSIDE OF A HEAP, FREE IT + if (blockptr->flags & BF_LARGEALLOC) { + LPVOID largeallocptr = (LPBYTE)ptr-sizeof(BLOCK)-sizeof(BLOCKPTR); + largeallocptr = (LPVOID)((DWORD)largeallocptr & ~(s_pagesize-1)); + VirtualFree(largeallocptr,0,MEM_RELEASE); + } + + // IF DEBUG MODE IS ENABLED AND THIS IS NOT A LARGE BLOCK ALLOCATED + // OUTSIDE THE HEAP, WIPE OUT THE USER PORTION OF THE DATA + else if (s_debugmode) { + DWORD userbytes = blockptr->bytes + -blockptr->padding + -sizeof(BLOCK) + -((blockptr->flags & BF_BOUNDINGSIG) ? sizeof(WORD) : 0); + FillMemory(ptr,userbytes,0xDD); + } + + // FREE THIS BLOCK FROM THE HEAP + BOOL success = FALSE; + if (heapptr) + success = FreeHeapBlock(heapptr,blockptr); + + // UNLOCK THE HEAP + UnlockHeap(lockedhandle); + + return success; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +#define CHECKINITIALIZED(name,errortype,retval) \ + do \ + if (!CheckInitialized()) { \ + errortype(STORM_ERROR_MEMORY_MANAGER_INACTIVE, \ + name, \ + SERR_LINECODE_FUNCTION); \ + return retval; \ + } \ + while (0) + +//=========================================================================== +LPVOID APIENTRY SMemAlloc (DWORD bytes, + LPCSTR filename, + int linenumber, + DWORD flags) { + CHECKINITIALIZED("SMemAlloc()",FatalError,NULL); + + // DETERMINE THE HEAP THAT WILL BE USED FOR THIS ALLOCATION + HSHEAP handle = GetHandleByCaller(filename, + linenumber); + + // LOCK THE HEAP + HLOCKEDHEAP lockedhandle; + HEAPPTR heapptr = LockHeapByHandle(handle, + &lockedhandle, + FALSE); + + // IF THE HEAP DOES NOT EXIST, ALLOCATE ONE. THE SLOT CONTAINING + // THE HEAP IS STILL LOCKED AFTER THE CALL TO LOCKHEAPBYHANDLE(). + if (!heapptr) + heapptr = AllocateHeap(filename, + linenumber, + handle, + GetSlotByHandle(handle), + PAGESIZE, + PAGESIZE, + RESERVESIZE); + + // ALLOCATE MEMORY AND UNLOCK THE HEAP + LPVOID result = SatisfyAllocRequest(lockedhandle, + heapptr, + flags, + bytes); + + // TRACE THE ALLOCATION IF NECESSARY + TRACE(result,"SMemAlloc()",filename,linenumber); + + return result; + +} + +//=========================================================================== +BOOL APIENTRY SMemDestroy () { + if (!s_initialized) + return TRUE; + s_initialized = FALSE; + + // REMOVE ALL EMPTY HEAPS, AND ALL CRITICAL SECTIONS + for (DWORD loop = 0; loop < TABLESIZE; ++loop) { + EnterCriticalSection(&s_critsect[loop]); + s_emptyheap[loop] = FALSE; + HEAPPTR *nextheap = &s_heaphead[loop]; + while (*nextheap) + if ((*nextheap)->allocatedblocks) + nextheap = DestroyHeap(nextheap); + else { + if ((*nextheap)->active && + ((DWORD)((*nextheap)->handle) >= FIRSTUSERHEAP)) + REPORTRESOURCELEAK(HSHEAP); + FreeHeap(nextheap); + } + LeaveCriticalSection(&s_critsect[loop]); + DeleteCriticalSection(&s_critsect[loop]); + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SMemFindNextBlock (HSHEAP heap, + LPVOID prevblock, + LPVOID *nextblock, + LPSMEMBLOCKDETAILS details) { + CHECKINITIALIZED("SMemFindNextBlock()",Warning,FALSE); + + VALIDATEBEGIN; + VALIDATE(heap); + VALIDATE(nextblock); + VALIDATE(details); + VALIDATE(details->size == sizeof(SMEMBLOCKDETAILS)); + VALIDATEEND; + + // BLANK OUT THE BLOCK DETAILS STRUCTURE + ZeroMemory((LPBYTE)details+sizeof(DWORD), + details->size-sizeof(DWORD)); + + // CLAIM THE CRITICAL SECTION FOR THE SLOT THAT CONTAINS THIS HEAP + DWORD slot = GetSlotByHandle(heap); + EnterCriticalSection(&s_critsect[slot]); + + // GENERATE A POINTER TO THE BLOCK HEADER OF THE PREVIOUS BLOCK + BLOCKPTR prevblockptr = GetBlockPtrByPtr(prevblock); + + // SEARCH ALL REGIONS OF THIS HEAP FOR THE NEXT BLOCK. SEARCH REGIONS + // IN REVERSE ORDER SO THAT BLOCKS WHICH WERE ALLOCATED FIRST WILL TEND + // TO BE LISTED FIRST. + BLOCKPTR lastblockptr = NULL; + BLOCKPTR blockptr = NULL; + BOOL found = FALSE; + HEAPPTR heapptr = s_heaphead[slot]; + while (heapptr && heapptr->next) + heapptr = heapptr->next; + while (heapptr && !found) { + + // IF THIS REGION IS PART OF THE HEAP, SEARCH ALL OF ITS BLOCKS + if (heapptr->handle == heap) { + blockptr = heapptr->firstblock; + while (blockptr != heapptr->termblock) { + if (lastblockptr == prevblockptr) { + found = TRUE; + break; + } + lastblockptr = blockptr; + blockptr = (BLOCKPTR)((LPBYTE)blockptr+blockptr->bytes); + } + } + + // MOVE TO THE PREVIOUS REGION + if (heapptr == s_heaphead[slot]) + break; + HEAPPTR lastheapptr = heapptr; + heapptr = s_heaphead[slot]; + while (heapptr->next != lastheapptr) + heapptr = heapptr->next; + + } + + // IF WE DIDN'T FIND ONE, RETURN FALSE TO INDICATE THE ITERATION IS + // COMPLETE + if (!found) { + *nextblock = NULL; + LeaveCriticalSection(&s_critsect[slot]); + return FALSE; + } + + // FILL IN INFORMATION ABOUT THE BLOCK + LPVOID ptr = GetPtrByBlockPtr(blockptr); + *nextblock = ptr; + details->ptr = ptr; + details->allocated = !(blockptr->flags & BF_FREEBLOCK); + details->valid = CheckValidBlock(ptr, + FALSE, + NULL, + 0); + if (blockptr->flags & BF_LARGEALLOC) { + BLOCKPTR largeblockptr = (BLOCKPTR)ptr-1; + DWORD largeblockoverhead = sizeof(BLOCKPTR)+sizeof(BLOCK); + MEMORY_BASIC_INFORMATION info; + VirtualQuery((LPBYTE)ptr-largeblockoverhead, + &info, + sizeof(MEMORY_BASIC_INFORMATION)); + details->bytes = info.RegionSize-largeblockoverhead; + details->overhead = sizeof(BLOCK)+sizeof(LPVOID)+blockptr->padding + +largeblockoverhead; + } + else { + details->overhead = sizeof(BLOCK)+blockptr->padding; + details->bytes = blockptr->bytes-details->overhead; + } + + // LEAVE THE CRITICAL SECTION + LeaveCriticalSection(&s_critsect[slot]); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SMemFindNextHeap (HSHEAP prevheap, + HSHEAP *nextheap, + LPSMEMHEAPDETAILS details) { + CHECKINITIALIZED("SMemFindNextHeap()",Warning,FALSE); + + VALIDATEBEGIN; + VALIDATE(nextheap); + VALIDATE(details); + VALIDATE(details->size == sizeof(SMEMHEAPDETAILS)); + VALIDATEEND; + + // BLANK OUT THE HEAP DETAILS STRUCTURE + ZeroMemory((LPBYTE)details+sizeof(DWORD), + details->size-sizeof(DWORD)); + + // DETERMINE THE FIRST SLOT TO CHECK + DWORD slot = 0; + if (prevheap) + slot = GetSlotByHandle(prevheap); + + // FIND THE NEXT HEAP + HSHEAP lastheap = (HSHEAP)0; + HEAPPTR heapptr = NULL; + for (; slot < TABLESIZE; ++slot) { + EnterCriticalSection(&s_critsect[slot]); + heapptr = s_heaphead[slot]; + while (heapptr) { + if (heapptr->active) { + if (lastheap == prevheap) + break; + lastheap = heapptr->handle; + } + heapptr = heapptr->next; + } + if (heapptr) + break; + LeaveCriticalSection(&s_critsect[slot]); + } + + // IF WE DIDN'T FIND ONE, RETURN FALSE TO INDICATE THE ITERATION IS + // COMPLETE + if (!heapptr) { + *nextheap = NULL; + return FALSE; + } + + // FILL IN INFORMATION ABOUT THE HEAP + *nextheap = heapptr->handle; + details->handle = heapptr->handle; + details->linenumber = heapptr->linenumber; + details->maximumsize = MAXHEAPSIZE; // note: change this + SStrCopy(details->filename,heapptr->filename,MAX_PATH); + + // SUM THE ALLOCATION STATISTICS FOR EACH REGION THAT MAKES UP THE HEAP + while (heapptr) { + CombineFreeBlocks(heapptr); + if (heapptr->handle == *nextheap) { + details->committedbytes += heapptr->committedbytes; + details->reservedbytes += heapptr->reservedbytes; + details->allocatedblocks += heapptr->allocatedblocks; + } + heapptr = heapptr->next; + } + + // LEAVE THE CRITICAL SECTION + LeaveCriticalSection(&s_critsect[slot]); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SMemFree (LPVOID ptr, + LPCSTR filename, + int linenumber, + DWORD flags) { + CHECKINITIALIZED("SMemFree()",Warning,FALSE); + + // TRACE THE DEALLOCATION IF NECESSARY + TRACE(ptr,"SMemFree()",filename,linenumber); + + // VERIFY THAT THIS BLOCK IS VALID AND ALLOCATED + if (!CheckValidBlock(ptr, + TRUE, + filename, + linenumber)) + return FALSE; + + // LOCK THE HEAP WHICH CONTAINS THE BLOCK + BLOCKPTR blockptr = GetBlockPtrByPtr(ptr); + HLOCKEDHEAP lockedhandle; + HEAPPTR heapptr = LockHeapByBlockPtr(blockptr,&lockedhandle); + + // FREE THIS MEMORY BLOCK AND UNLOCK THE HEAP + return SatisfyFreeRequest(lockedhandle, + heapptr, + ptr, + blockptr); +} + +//=========================================================================== +HSHEAP APIENTRY SMemGetHeapByCaller (LPCSTR filename, + int linenumber) { + CHECKINITIALIZED("SMemGetHeapByCaller()",Warning,(HSHEAP)0); + + return GetHandleByCaller(filename,linenumber); +} + +//=========================================================================== +HSHEAP APIENTRY SMemGetHeapByPtr (LPVOID ptr) { + CHECKINITIALIZED("SMemGetHeapByPtr()",Warning,(HSHEAP)0); + + BLOCKPTR blockptr = GetBlockPtrByPtr(ptr); + if (CheckValidBlock(blockptr, + FALSE, + NULL, + 0)) + return GetHandleByBlockPtr(blockptr); + else + return (HSHEAP)0; +} + +//=========================================================================== +LPVOID APIENTRY SMemHeapAlloc (HSHEAP handle, + DWORD flags, + DWORD bytes) { + CHECKINITIALIZED("SMemHeapAlloc()",FatalError,NULL); + + // LOCK THE HEAP + HLOCKEDHEAP lockedhandle; + HEAPPTR heapptr = LockHeapByHandle(handle, + &lockedhandle, + TRUE); + if (!heapptr) + FatalError(ERROR_INVALID_HANDLE, + "SMemHeapAlloc()", + SERR_LINECODE_FUNCTION); + + // ALLOCATE MEMORY AND UNLOCK THE HEAP + LPVOID result = SatisfyAllocRequest(lockedhandle, + heapptr, + flags, + bytes); + + // TRACE THE ALLOCATION IF NECESSARY + TRACE(result,"SMemHeapAlloc()",NULL,0); + + return result; +} + +//=========================================================================== +HSHEAP APIENTRY SMemHeapCreate (DWORD options, + DWORD initialsize, + DWORD maximumsize) { + CHECKINITIALIZED("SMemHeapCreate()",Warning,(HSHEAP)0); + + // VERIFY THAT THE RESERVED OPTIONS PARAMETER IS NOT BEING USED + if (options) { + Warning(ERROR_INVALID_PARAMETER, + "SMemHeapCreate()", + SERR_LINECODE_FUNCTION); + return FALSE; + } + + // ROUND THE REQUESTED INITIAL SIZE UP TO THE NEXT PAGE BOUNDARY + if (initialsize & (PAGESIZE-1)) + initialsize += PAGESIZE-(initialsize & (PAGESIZE-1)); + initialsize = max(initialsize,PAGESIZE); + maximumsize = max(maximumsize,initialsize); + + // FIND AN UNUSED HANDLE FOR THIS HEAP + static HSHEAP handle = (HSHEAP)FIRSTUSERHEAP; + for (;;) { + + // INCREMENT THE HANDLE SEQUENCE + handle = (HSHEAP)((DWORD)handle+1); + if (!handle) + handle = (HSHEAP)FIRSTUSERHEAP; + + // CHECK TO SEE IF THIS HANDLE IS IN USE + HLOCKEDHEAP lockedhandle = (HLOCKEDHEAP)INVALID_HANDLE_VALUE; + if (LockHeapByHandle(handle, + &lockedhandle, + TRUE)) + UnlockHeap(lockedhandle); + else + break; + + } + + // ALLOCATE THE HEAP + DWORD slot = GetSlotByHandle(handle); + EnterCriticalSection(&s_critsect[slot]); + AllocateHeap(NULL, + 0, + handle, + slot, + PAGESIZE, + initialsize, + RESERVESIZE); + LeaveCriticalSection(&s_critsect[slot]); + if (!handle) + Warning(ERROR_NOT_ENOUGH_MEMORY, + "SMemHeapCreate()", + SERR_LINECODE_FUNCTION); + + // RETURN THE HEAP HANDLE + return handle; +} + +//=========================================================================== +BOOL APIENTRY SMemHeapDestroy (HSHEAP handle) { + CHECKINITIALIZED("SMemHeapDestroy()",Warning,FALSE); + + // LOCK THE HEAP'S CRITICAL SECTION + DWORD slot = GetSlotByHandle(handle); + EnterCriticalSection(&s_critsect[slot]); + + // DESTROY ALL REGIONS OF THE HEAP + BOOL found = FALSE; + HEAPPTR *nextptr = &s_heaphead[slot]; + while (*nextptr) + if ((*nextptr)->handle == handle) { + found = TRUE; + nextptr = DestroyHeap(nextptr); + } + else + nextptr = &(*nextptr)->next; + + // UNLOCK THE CRITICAL SECTION + LeaveCriticalSection(&s_critsect[slot]); + + return found; +} + +//=========================================================================== +BOOL APIENTRY SMemHeapFree (HSHEAP handle, + DWORD flags, + LPVOID ptr) { + CHECKINITIALIZED("SMemHeapFree()",Warning,FALSE); + + // TRACE THE DEALLOCATION IF NECESSARY + TRACE(ptr,"SMemHeapFree()",NULL,0); + + // VERIFY THAT THIS BLOCK IS VALID AND ALLOCATED + if (!CheckValidBlock(ptr, + TRUE, + NULL, + 0)) + return FALSE; + + // VERIFY THAT THE HEAP HANDLE IS CORRECT + BLOCKPTR blockptr = GetBlockPtrByPtr(ptr); + if (GetHandleByBlockPtr(blockptr) != handle) + return FALSE; + + // LOCK THE HEAP WHICH CONTAINS THE BLOCK + HLOCKEDHEAP lockedhandle; + HEAPPTR heapptr = LockHeapByBlockPtr(blockptr,&lockedhandle); + + // FREE THIS MEMORY BLOCK AND UNLOCK THE HEAP + return SatisfyFreeRequest(lockedhandle, + heapptr, + ptr, + blockptr); +} + +//=========================================================================== +void APIENTRY SMemInitialize () { + if (s_initialized) + return; + + // DETERMINE WHETHER TO PERFORM HEAP CHECKS +#ifdef _DEBUG + s_debugmode = TRUE; +#endif + SRegLoadValue(REGKEY,REGVAL_DEBUG,0,(LPDWORD)&s_debugmode); + SRegLoadValue(REGKEY,REGVAL_GUARD,0,(LPDWORD)&s_guardmode); +#ifdef _DEBUG + SRegSaveValue(REGKEY,REGVAL_DEBUG,0,(DWORD)s_debugmode); + SRegSaveValue(REGKEY,REGVAL_GUARD,0,(DWORD)s_guardmode); + s_debugmode = TRUE; +#endif + + // INITIALIZE CRITICAL SECTIONS + for (DWORD loop = 0; loop < TABLESIZE; ++loop) + InitializeCriticalSection(&s_critsect[loop]); + + s_initialized = TRUE; +} diff --git a/src/Storm/SOURCE/SMSG.CPP b/src/Storm/SOURCE/SMSG.CPP new file mode 100644 index 0000000..613c98a --- /dev/null +++ b/src/Storm/SOURCE/SMSG.CPP @@ -0,0 +1,247 @@ +/**************************************************************************** +* +* SMSG.CPP +* Storm message processing and dispatching functions +* +* By Michael O'Brien (3/5/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define REGISTERTYPE_BASE 'SMSG' +#define REGISTERTYPE_MESSAGE (REGISTERTYPE_BASE+0) +#define REGISTERTYPE_COMMAND (REGISTERTYPE_BASE+1) +#define REGISTERTYPE_KEYDOWN (REGISTERTYPE_BASE+2) +#define REGISTERTYPE_KEYUP (REGISTERTYPE_BASE+3) + +NODEDECL(WNDREC) { + HWND window; +} *WNDPTR; + +static LIST(WNDREC) s_wndlist; + +//=========================================================================== +static void AddWindow (HWND window) { + s_wndlist.NewNode()->window = window; +} + +//=========================================================================== +static WNDPTR FindWindow (HWND window) { + ITERATELIST(WNDREC,s_wndlist,curr) + if (curr->window == window) + return curr; + return NULL; +} + +//=========================================================================== +static void DeleteWindow (HWND window) { + WNDPTR ptr = FindWindow(window); + if (ptr) { + SEvtUnregisterType(REGISTERTYPE_MESSAGE,(DWORD)window); + SEvtUnregisterType(REGISTERTYPE_COMMAND,(DWORD)window); + SEvtUnregisterType(REGISTERTYPE_KEYUP ,(DWORD)window); + SEvtUnregisterType(REGISTERTYPE_KEYDOWN,(DWORD)window); + s_wndlist.DeleteNode(ptr); + } +} + +//=========================================================================== +static BOOL InternalRegister (DWORD type, + HWND window, + DWORD id, + SMSGHANDLER handler) { + VALIDATEBEGIN; + VALIDATE(handler); + VALIDATEEND; + + // FIND THE WINDOW + if (!window) + SDrawGetFrameWindow(&window); + if (!FindWindow(window)) + AddWindow(window); + + // REGISTER THE MESSAGE + return SEvtRegisterHandler(type,(DWORD)window,id,0,(SEVTHANDLER)handler); +} + +//=========================================================================== +static BOOL InternalUnregister (DWORD type, + HWND window, + DWORD id, + SMSGHANDLER handler) { + VALIDATEBEGIN; + VALIDATE(handler); + VALIDATEEND; + + // FIND THE WINDOW + if (!window) + SDrawGetFrameWindow(&window); + if (!FindWindow(window)) + AddWindow(window); + + // UNREGISTER THE MESSAGE + return SEvtUnregisterHandler(type,(DWORD)window,id,(SEVTHANDLER)handler); +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SMsgBreakHandlerChain (LPPARAMS params) { + return SEvtBreakHandlerChain(params); +} + +//=========================================================================== +BOOL APIENTRY SMsgDestroy () { + while (!s_wndlist.IsEmpty()) + DeleteWindow(s_wndlist.Head()->window); + return 1; +} + +//=========================================================================== +BOOL APIENTRY SMsgDispatchMessage (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL *useresult, + LRESULT *result) { + if (useresult) + *useresult = 0; + if (result) + *result = 0; + + // CREATE A PARAMETER RECORD TO PASS TO THE HANDLER FUNCTION + PARAMS params; + params.window = window; + params.message = message; + params.wparam = wparam; + params.lparam = lparam; + params.notifycode = (message == WM_COMMAND) ? HIWORD(wparam) : 0; + params.useresult = 0; + params.result = 0; + + // DISPATCH THE MESSAGE + SEvtDispatch(REGISTERTYPE_MESSAGE,(DWORD)window,message,¶ms); + if (message == WM_COMMAND) + SEvtDispatch(REGISTERTYPE_COMMAND,(DWORD)window,LOWORD(wparam),¶ms); + else if (message == WM_KEYDOWN) + SEvtDispatch(REGISTERTYPE_KEYDOWN,(DWORD)window,wparam,¶ms); + else if (message == WM_KEYUP) + SEvtDispatch(REGISTERTYPE_KEYUP,(DWORD)window,wparam,¶ms); + + // IF THIS MESSAGE IS WM_NCDESTROY, DEALLOCATE THIS WINDOW'S RECORD + if (message == WM_NCDESTROY) + DeleteWindow(window); + + // RETURN THE DISPATCHING RESULTS + if (useresult) + *useresult = params.useresult; + if (result) + *result = params.result; + + return 1; +} + +//=========================================================================== +BOOL APIENTRY SMsgDoMessageLoop (SMSGIDLEPROC idleproc, + BOOL cleanuponquit) { + DWORD count = 0; + MSG message; + for (;;) + if (PeekMessage(&message,(HWND)0,0,0,PM_NOREMOVE) || + !(idleproc && idleproc(count++))) { + count = 0; + if (!GetMessage(&message,(HWND)0,0,0)) + break; + TranslateMessage(&message); + DispatchMessage(&message); + } +#ifndef STATICLIB + if (cleanuponquit) + StormDestroy(); +#endif + return message.wParam; +} + +//=========================================================================== +BOOL APIENTRY SMsgPopRegisterState (HWND window) { + if (!window) + SDrawGetFrameWindow(&window); + SEvtPopState(REGISTERTYPE_COMMAND,(DWORD)window); + SEvtPopState(REGISTERTYPE_KEYDOWN,(DWORD)window); + SEvtPopState(REGISTERTYPE_KEYUP ,(DWORD)window); + SEvtPopState(REGISTERTYPE_MESSAGE,(DWORD)window); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SMsgPushRegisterState (HWND window) { + if (!window) + SDrawGetFrameWindow(&window); + SEvtPushState(REGISTERTYPE_COMMAND,(DWORD)window); + SEvtPushState(REGISTERTYPE_KEYDOWN,(DWORD)window); + SEvtPushState(REGISTERTYPE_KEYUP ,(DWORD)window); + SEvtPushState(REGISTERTYPE_MESSAGE,(DWORD)window); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SMsgRegisterCommand (HWND window, + UINT id, + SMSGHANDLER handler) { + return InternalRegister(REGISTERTYPE_COMMAND,window,id,handler); +} + +//=========================================================================== +BOOL APIENTRY SMsgRegisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler) { + return InternalRegister(REGISTERTYPE_KEYDOWN,window,id,handler); +} + +//=========================================================================== +BOOL APIENTRY SMsgRegisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler) { + return InternalRegister(REGISTERTYPE_KEYUP,window,id,handler); +} + +//=========================================================================== +BOOL APIENTRY SMsgRegisterMessage (HWND window, + UINT id, + SMSGHANDLER handler) { + return InternalRegister(REGISTERTYPE_MESSAGE,window,id,handler); +} + +//=========================================================================== +BOOL APIENTRY SMsgUnregisterCommand (HWND window, + UINT id, + SMSGHANDLER handler) { + return InternalUnregister(REGISTERTYPE_COMMAND,window,id,handler); +} + +//=========================================================================== +BOOL APIENTRY SMsgUnregisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler) { + return InternalUnregister(REGISTERTYPE_KEYDOWN,window,id,handler); +} + +//=========================================================================== +BOOL APIENTRY SMsgUnregisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler) { + return InternalUnregister(REGISTERTYPE_KEYUP,window,id,handler); +} + +//=========================================================================== +BOOL APIENTRY SMsgUnregisterMessage (HWND window, + UINT id, + SMSGHANDLER handler) { + return InternalUnregister(REGISTERTYPE_MESSAGE,window,id,handler); +} diff --git a/src/Storm/SOURCE/SNET.CPP b/src/Storm/SOURCE/SNET.CPP new file mode 100644 index 0000000..0a76695 --- /dev/null +++ b/src/Storm/SOURCE/SNET.CPP @@ -0,0 +1,5261 @@ +/**************************************************************************** +* +* SNET.CPP +* Storm networking functions +* +* By Michael O'Brien (4/19/96) +* +* SNet implements multiple independent communication streams between each +* player. It guarantees delivery of all messages, using different +* techniques depending on the message type. +* +***/ + +#include "pch.h" +#pragma hdrstop + +#ifdef _DEBUG +#define TRACING +#define UNSIGNEDSNPS +#endif + +#pragma warning(disable:4200) // don't warn about zero-sized arrays + +#define MF_ACK 0x01 +#define MF_RESENDREQUEST 0x02 +#define MF_FORWARDED 0x04 + +#define PF_JOINING 0x00000004 +#define PF_LEAVING 0x00000008 + +#define NOPLAYER 0xFF + +#define ESTIMATEDPACKETOVERHEAD 64 +#define DELETECONNTIME 50000 +#define MINSPISIZE (20*sizeof(DWORD)) +#define PINGFREQUENCY 20000 + +#define REGISTERTYPE 'SNET' +#define REGISTERSUBTYPE_SNETEVENT 1 +#define REGISTERSUBTYPE_SYSEVENT 2 + +#define SENDBUFSIZE 8192 + +#define SNET_NETWORKVERSION 1 + +#define SYS_UNUSED 0 +#define SYS_INITIALCONTACT 1 +#define SYS_CIRCUITCHECK 2 +#define SYS_CIRCUITCHECKRESPONSE 3 +#define SYS_PING 4 +#define SYS_PINGRESPONSE 5 +#define SYS_PLAYERINFO 6 +#define SYS_PLAYERJOIN 7 +#define SYS_PLAYERJOIN_ACCEPTSTART 8 +#define SYS_PLAYERJOIN_ACCEPTDONE 9 +#define SYS_PLAYERJOIN_REJECT 10 +#define SYS_PLAYERLEAVE 11 +#define SYS_DROPPLAYER 12 +#define SYS_NEWGAMEOWNER 13 +#define SYSMSGS 14 + +#define TYPE_SYSTEM 0 +#define TYPE_MESSAGE 1 +#define TYPE_TURN 2 +#define TYPES 3 + +typedef struct _CLIENTDATA { + DWORD bytes; + DWORD numplayers; + DWORD maxplayers; +} CLIENTDATA, *CLIENTDATAPTR; + +typedef struct _HEADER { + WORD checksum; // checksum must be first field + WORD bytes; // bytes including header + WORD sequence; + WORD acksequence; + BYTE type; + BYTE subtype; + BYTE playerid; + BYTE flags; +} HEADER, *HEADERPTR; + +typedef struct _PACKET { + HEADER header; + BYTE data[0]; +} PACKET, *PACKETPTR; + +NODEDECL(MESSAGE) { + SNETADDRPTR addr; + PACKETPTR data; + DWORD databytes; + BOOL local; + DWORD sendtime; + DWORD resendtime; +} *MESSAGEPTR; + +NODEDECL(CONNREC) { + char name[SNETSPI_MAXSTRINGLENGTH]; + char desc[SNETSPI_MAXSTRINGLENGTH]; + SNETADDR addr; + DWORD flags; + DWORD lastreceivetime; // last time any packet was received + DWORD lastrequesttime; // last time we requested a turn + DWORD lastpingtime; // last time we sent a ping + DWORD latency; + DWORD peaklatency; + LIST(MESSAGE) outgoingqueue[TYPES]; // already sent; waiting for ack + LIST(MESSAGE) incomingqueue[TYPES]; // waiting to be processed + LIST(MESSAGE) processing[TYPES]; // given to app; valid until next call + LIST(MESSAGE) oldturns; // old turns from this player + WORD outgoingsequence[TYPES]; // (in case we need to send them + WORD incomingsequence[TYPES]; // to another player) + WORD lastprocessedturn; // last turn ack from this player + WORD availablesequence[TYPES]; // highest available incoming sequence + WORD acksequence[TYPES]; // last message we acked + DWORD acktime[TYPES]; // time of unacked message processing + BOOL gameowner; + BOOL establishing; + DWORD exitcode; + WORD finalsequence; + BYTE playerid; +} *CONNPTR; + +typedef struct _PERFDATAREC { + DWORD value; + DWORD type; + LONG scale; + BOOL providerspecific; +} PERFDATAREC, *PERFDATAPTR; + +NODEDECL(PROVIDERINFO) { + char filename[MAX_PATH]; + DWORD index; + DWORD id; + char desc[SNETSPI_MAXSTRINGLENGTH]; + char req[SNETSPI_MAXSTRINGLENGTH]; + SNETCAPS caps; +} *PROVIDERINFOPTR; + +typedef struct _UIPARAMS { + SNETCAPSPTR mincaps; + SNETPROGRAMDATAPTR programdata; + SNETPLAYERDATAPTR playerdata; + SNETUIDATAPTR interfacedata; + SNETVERSIONDATAPTR versiondata; +} UIPARAMS, *UIPARAMSPTR; + +NODEDECL(USEREVENT) { + SNETEVENT event; +} *USEREVENTPTR; + +typedef struct _SYSEVENT { + SNETADDRPTR senderaddr; + LPVOID data; + DWORD databytes; + BYTE senderplayerid; + BYTE eventid; +} SYSEVENT, *SYSEVENTPTR; + +typedef struct _SYSEVENTDATA_DROPPLAYER { + DWORD playerid; + DWORD finalsequence; + DWORD exitcode; +} SYSEVENTDATA_DROPPLAYER, *SYSEVENTDATA_DROPPLAYERPTR; + +typedef struct _SYSEVENTDATA_PLAYERJOIN { + char namedescpass[3*SNETSPI_MAXSTRINGLENGTH]; +} SYSEVENTDATA_PLAYERJOIN, *SYSEVENTDATA_PLAYERJOINPTR; + +typedef struct _SYSEVENTDATA_PLAYERJOIN_ACCEPTSTART { + DWORD playerid; + DWORD playersallowed; + DWORD nextturn; + DWORD gamemode; + DWORD runningtime; + char namedescpass[3*SNETSPI_MAXSTRINGLENGTH]; +} SYSEVENTDATA_PLAYERJOIN_ACCEPTSTART, *SYSEVENTDATA_PLAYERJOIN_ACCEPTSTARTPTR; + +typedef struct _SYSEVENTDATA_PLAYERINFO { + DWORD bytes; + DWORD playerid; + BOOL gameowner; + DWORD flags; + DWORD startingturn; + SNETADDR addr; + char namedesc[SNETSPI_MAXSTRINGLENGTH*2]; +} SYSEVENTDATA_PLAYERINFO, *SYSEVENTDATA_PLAYERINFOPTR; + +typedef struct _SYSEVENTDATA_PLAYERLEAVE { + DWORD finalsequence; + DWORD exitcode; +} SYSEVENTDATA_PLAYERLEAVE, *SYSEVENTDATA_PLAYERLEAVEPTR; + +typedef void (CALLBACK *SYSEVENTPROC)(SYSEVENTPTR); + +static CCritSect s_api_critsect; +static DWORD s_api_playeroffset = 0; + +static CONNPTR inline ConnFindByAddr (SNETADDRPTR addr); +static CONNPTR inline ConnFindLocal (); +static void ConnSetCurrentMessage (CONNPTR conn, BYTE type, MESSAGEPTR message); +static void RecvProcessExternalMessages (); +static void RecvProcessIncomingPackets (); +static void SysQueueUserEvent (DWORD eventid, + DWORD playerid, + LPVOID data, + DWORD databytes); +static void UiGetProgramDescription (LPCSTR programname, + SNETVERSIONDATAPTR versionptr, + LPSTR buffer, + DWORD buffersize); + +/**************************************************************************** +* +* TRACE FUNCTIONS +* +***/ + +#ifdef TRACING + +static CSLog s_trace_log("Internal","SNet Trace File"); + +//=========================================================================== +static void TraceDumpAddr (HSLOG log, + LPCSTR addrname, + SNETADDRPTR addr, + BYTE playerid) { + char outstr[80]; + wsprintf(outstr," %s=",addrname); + for (unsigned loop = 0; loop < sizeof(SNETADDR); ++loop) + wsprintf(outstr+SStrLen(outstr),"%02x",(DWORD)*((LPBYTE)addr+loop)); + wsprintf(outstr+SStrLen(outstr)," (%x)",(DWORD)playerid); + SLogWrite(log,outstr); +} + +//=========================================================================== +static void TraceDumpDataBlocks (HSLOG log, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + if (programdata && (programdata->size >= sizeof(SNETPROGRAMDATA))) { + SLogWrite(log," programdata.size = %u" ,programdata->size); + SLogWrite(log," programdata.programname = \"%s\"",programdata->programname); + SLogWrite(log," programdata.programdescription = \"%s\"",programdata->programdescription); + SLogWrite(log," programdata.programid = 0x%08x",programdata->programid); + SLogWrite(log," programdata.versionid = 0x%08x",programdata->versionid); + SLogWrite(log," programdata.reserved1 = %u" ,programdata->reserved1); + SLogWrite(log," programdata.maxplayers = %u" ,programdata->maxplayers); + SLogWrite(log," programdata.initdata = 0x%08x",programdata->initdata); + SLogWrite(log," programdata.initdatabytes = %u" ,programdata->initdatabytes); + SLogWrite(log," programdata.reserved2 = 0x%08x",programdata->reserved2); + SLogWrite(log," programdata.optcategorybits = 0x%08x",programdata->optcategorybits); + } + if (playerdata && (playerdata->size >= sizeof(SNETPLAYERDATA))) { + SLogWrite(log," playerdata.size = %u" ,playerdata->size); + SLogWrite(log," playerdata.playername = \"%s\"",playerdata->playername); + SLogWrite(log," playerdata.playerdescription = \"%s\"",playerdata->playerdescription); + } + if (interfacedata && (interfacedata->size >= sizeof(SNETUIDATA))) { + SLogWrite(log," interfacedata.size = %u" ,interfacedata->size); + SLogWrite(log," interfacedata.uiflags = 0x%08x",interfacedata->uiflags); + SLogWrite(log," interfacedata.parentwindow = 0x%08x",interfacedata->parentwindow); + SLogWrite(log," interfacedata.artcallback = 0x%08x",interfacedata->artcallback); + SLogWrite(log," interfacedata.authcallback = 0x%08x",interfacedata->authcallback); + SLogWrite(log," interfacedata.createcallback = 0x%08x",interfacedata->createcallback); + SLogWrite(log," interfacedata.drawdesccallback = 0x%08x",interfacedata->drawdesccallback); + SLogWrite(log," interfacedata.selectedcallback = 0x%08x",interfacedata->selectedcallback); + SLogWrite(log," interfacedata.messageboxcallback = 0x%08x",interfacedata->messageboxcallback); + SLogWrite(log," interfacedata.soundcallback = 0x%08x",interfacedata->soundcallback); + SLogWrite(log," interfacedata.statuscallback = 0x%08x",interfacedata->statuscallback); + SLogWrite(log," interfacedata.getdatacallback = 0x%08x",interfacedata->getdatacallback); + SLogWrite(log," interfacedata.categorycallback = 0x%08x",interfacedata->categorycallback); + } + if (versiondata && (versiondata->size >= sizeof(SNETVERSIONDATA))) { + SLogWrite(log," versiondata.size = %u" ,versiondata->size); + SLogWrite(log," versiondata.versionstring = \"%s\"",versiondata->versionstring); + SLogWrite(log," versiondata.executablefile = \"%s\"",versiondata->executablefile); + SLogWrite(log," versiondata.originalarchivefile = \"%s\"",versiondata->originalarchivefile); + SLogWrite(log," versiondata.patcharchivefile = \"%s\"",versiondata->patcharchivefile); + } +} + +//=========================================================================== +static void TraceDumpMsg (HSLOG log, + DWORD playerid, + DWORD sequence, + LPVOID data, + DWORD databytes) { + + // DUMP THE PLAYER ID + if (playerid != 0xFFFFFFFF) + SLogWrite(log, + "(from player %u, sequence=%u)\n", + playerid+s_api_playeroffset,sequence); + else if (sequence != 0xFFFFFFFF) + SLogWrite(log, + "(sequence=%u)\n",sequence); + + // DUMP THE DATA + SLogDump(log,data,databytes); + +} + +#define TRACEDUMP SLogDump +#define TRACEDUMPADDR TraceDumpAddr +#define TRACEDUMPDATABLOCKS TraceDumpDataBlocks +#define TRACEDUMPMSG TraceDumpMsg +#define TRACEHANDLE s_trace_log.GetHandle() +#define TRACEOUT SLogWrite +#define TRACEPEND SLogPend + +#else + +#define TRACEDUMP +#define TRACEDUMPADDR +#define TRACEDUMPDATABLOCKS +#define TRACEDUMPMSG +#define TRACEHANDLE 0 +#define TRACEOUT +#define TRACEPEND + +#endif + +/**************************************************************************** +* +* PERFORMANCE FUNCTIONS +* +***/ + +static PERFDATAREC s_perf_data[SNET_PERFIDNUM] + = {{0,0 , 0,0}, // unused + {0,SNET_PERFTYPE_RAWCOUNT,-1,0}, // SNET_PERFID_TURN + {0,0 , 0,0}, // unused + {0,0 , 0,0}, // unused + {0,SNET_PERFTYPE_COUNTER ,-1,0}, // SNET_PERFID_TURNSSENT + {0,SNET_PERFTYPE_COUNTER ,-1,0}, // SNET_PERFID_TURNSRECV + {0,SNET_PERFTYPE_COUNTER ,-1,0}, // SNET_PERFID_MSGSENT + {0,SNET_PERFTYPE_COUNTER ,-1,0}, // SNET_PERFID_MSGRECV + {0,SNET_PERFTYPE_COUNTER ,-4,0}, // SNET_PERFID_USERBYTESSENT + {0,SNET_PERFTYPE_COUNTER ,-4,0}, // SNET_PERFID_USERBYTESRECV + {0,SNET_PERFTYPE_COUNTER ,-4,0}, // SNET_PERFID_TOTALBYTESSENT + {0,SNET_PERFTYPE_COUNTER ,-4,0}, // SNET_PERFID_TOTALBYTESRECV + {0,SNET_PERFTYPE_COUNTER ,-1,1}, // SNET_PERFID_PKTSENTONWIRE + {0,SNET_PERFTYPE_COUNTER ,-1,1}, // SNET_PERFID_PKTRECVONWIRE + {0,SNET_PERFTYPE_COUNTER ,-4,1}, // SNET_PERFID_BYTESSENTONWIRE + {0,SNET_PERFTYPE_COUNTER ,-4,1}}; // SNET_PERFID_BYTESRECVONWIRE + +//=========================================================================== +static void inline PerfAdd (DWORD id, DWORD value) { + VALIDATEBEGIN; + VALIDATE(id < SNET_PERFIDNUM); + VALIDATEENDVOID; + + s_perf_data[id].value += value; +} + +//=========================================================================== +static void inline PerfDecrement (DWORD id) { + VALIDATEBEGIN; + VALIDATE(id < SNET_PERFIDNUM); + VALIDATEENDVOID; + + InterlockedDecrement((LONG *)&s_perf_data[id].value); +} + +//=========================================================================== +static void inline PerfIncrement (DWORD id) { + VALIDATEBEGIN; + VALIDATE(id < SNET_PERFIDNUM); + VALIDATEENDVOID; + + InterlockedIncrement((LONG *)&s_perf_data[id].value); +} + +//=========================================================================== +static void inline PerfSet (DWORD id, DWORD value) { + VALIDATEBEGIN; + VALIDATE(id < SNET_PERFIDNUM); + VALIDATEENDVOID; + + s_perf_data[id].value = value; +} + +/**************************************************************************** +* +* SERVICE PROVIDER MANAGEMENT FUNCTIONS +* +***/ + +static SNETSPIPTR s_spi = NULL; +static HINSTANCE s_spi_lib = (HINSTANCE)0; +static DWORD s_spi_outgoingtime = 0; +static LIST(PROVIDERINFO) s_spi_providerlist; +static PROVIDERINFOPTR s_spi_providerptr = NULL; +static BOOL s_spi_providersfound = FALSE; +static LPVOID s_spi_sendbuffer = NULL; +static DWORD s_spi_timetoackturn = 250; +static DWORD s_spi_timetoblock = 5000; +static DWORD s_spi_timetogiveup = 1000; +static DWORD s_spi_timetorequest = 25; +static DWORD s_spi_timetoresend = 50; + +static LPVOID SpiLoadCapsSignature (LPCSTR filename); + +//=========================================================================== +static LPVOID inline SpiExtractCaps (LPVOID capssig, + DWORD *id, + LPCSTR *desc, + LPCSTR *req, + SNETCAPSPTR *caps) { + VALIDATEBEGIN; + VALIDATE(capssig); + VALIDATEEND; + + DWORD bytes = *(LPDWORD)capssig; + LPCSTR start = (LPCSTR)capssig+sizeof(DWORD); + LPCSTR curr = start; + *id = *(LPDWORD)curr; + curr += sizeof(DWORD); + *desc = curr; + curr += SStrLen(curr)+1; + *req = curr; + curr += SStrLen(curr)+1; + *caps = (SNETCAPSPTR)curr; + curr += ((SNETCAPSPTR)curr)->size; + if ((DWORD)(curr-start) != bytes) + return NULL; + + return (LPVOID)curr; +} + +//=========================================================================== +static int inline SpiCheckProviderOrder (PROVIDERINFOPTR first, + PROVIDERINFOPTR second) { + + // CHECK WHETHER ONE OR BOTH OF THE PROVIDERS IN IN OUR PREFERRED LIST +#define BASENUM 6 + static const DWORD baseorder[BASENUM] = {'BNET','IPXN','IPXW','MODM','SCBL','MSDP'}; + int firstindex = 0x7FFFFFFF; + int secondindex = 0x7FFFFFFF; + for (int loop = 0; loop < BASENUM; ++loop) { + if (first->id == baseorder[loop]) + firstindex = loop; + if (second->id == baseorder[loop]) + secondindex = loop; + } +#undef BASENUM + + // IF SO, SORT BASED ON THE ORDER IN THE LIST + if ((firstindex != 0x7FFFFFFF) || (secondindex != 0x7FFFFFFF)) + return secondindex-firstindex; + + // OTHERWISE, SORT ON ALPHABETICAL ORDER + else + return _stricmp(first->desc,second->desc); + +} + +//=========================================================================== +static void SpiDestroy (BOOL clearproviderlist) { + + // CALL THE PROVIDER'S DESTROY FUNCTION + if (s_spi_lib && s_spi) { + TRACEOUT(TRACEHANDLE," spiDestroy()"); + s_spi->Destroy(); + } + + // UNBIND FROM THE CURRENT PROVIDER + if (s_spi_lib) { + FreeLibrary(s_spi_lib); + s_spi_lib = (HINSTANCE)0; + } + if (s_spi) { + DEL(s_spi); + s_spi = NULL; + } + + // FREE THE SEND BUFFER + if (s_spi_sendbuffer) { + VirtualUnlock(s_spi_sendbuffer,SENDBUFSIZE); + VirtualFree(s_spi_sendbuffer,0,MEM_RELEASE); + s_spi_sendbuffer = NULL; + } + + // DESTROY THE LIST OF PROVIDERS + if (clearproviderlist) { + s_spi_providerlist.Clear(); + s_spi_providersfound = FALSE; + } + +} + +//=========================================================================== +static void SpiFindAllProviders () { + + // MAKE SURE THIS FUNCTION IS NOT CALLED MORE THAN ONCE + if (s_spi_providersfound) + return; + else + s_spi_providersfound = TRUE; + + // CREATE THE SEARCH SPECIFICATION + char basepath[MAX_PATH] = ""; + GetModuleFileName((HMODULE)StormGetInstance(),basepath,MAX_PATH); + { + LPTSTR curr = basepath; + while (SStrChr(curr,'\\')) + curr = SStrChr(curr,'\\')+1; + *curr = 0; + } + char filespec[MAX_PATH] = ""; + wsprintf(filespec,"%s*.snp",basepath); + + // SEARCH FOR PROVIDER LIBRARIES + WIN32_FIND_DATA finddata; + HANDLE findhandle = FindFirstFile(filespec,&finddata); + if (findhandle == INVALID_HANDLE_VALUE) + return; + do { + + // BUILD THE COMPLETE FILENAME + char filename[MAX_PATH]; + wsprintf(filename,"%s%s",basepath,finddata.cFileName); + + // LOAD THE CAPABILITIES SIGNATURE BLOCK FOR THE NEXT LIBRARY + LPVOID capssig = NULL; +#ifndef UNSIGNEDSNPS + capssig = SpiLoadCapsSignature(filename); + if (!capssig) + continue; +#endif + + // LOAD THE NEXT LIBRARY + HINSTANCE lib = LoadLibrary(filename); + if (!lib) { + if (capssig) + FREE(capssig); + continue; + } + + // GET THE ADDRESS OF THE QUERY FUNCTION + SNETSPIQUERY query = (SNETSPIQUERY)GetProcAddress(lib,"SnpQuery"); + if (!query) { + if (capssig) + FREE(capssig); + FreeLibrary(lib); + continue; + } + + // QUERY ALL PROVIDER INTERFACES CONTAINED IN THIS LIBRARY + LPVOID currcapssig = capssig; + DWORD index = 0; + for (;;) { + + // QUERY THE PROVIDER'S CAPABILITIES TO DETERMINE WHETHER IT RETURNS + // SUCCESS OR FAILURE; HOWEVER, DON'T USE THE CAPABILITIES IT RETURNS, + // BECAUSE THEY'RE TOO EASY TO HACK +#ifndef UNSIGNEDSNPS + { +#endif + DWORD id; + LPCSTR desc; + LPCSTR req; + SNETCAPSPTR caps = NULL; + if (!query(index,&id,&desc,&req,&caps)) + break; + if (!(caps && (caps->size >= sizeof(SNETCAPS)))) + break; +#ifdef _DEBUG + if (caps->flags & SNET_CAPS_RETAILONLY) + break; +#else + if (caps->flags & SNET_CAPS_DEBUGONLY) + break; +#endif +#ifndef UNSIGNEDSNPS + } + + // RETRIEVE THE REAL CAPABILITIES FROM THE SIGNATURE DATA + DWORD id; + LPCSTR desc; + LPCSTR req; + SNETCAPSPTR caps = NULL; + currcapssig = SpiExtractCaps(currcapssig,&id,&desc,&req,&caps); + if (!currcapssig) + break; + if (!(caps && (caps->size >= sizeof(SNETCAPS)))) + break; +#endif + + // ALLOCATE A NEW PROVIDER STRUCTURE + PROVIDERINFOPTR info = s_spi_providerlist.NewNode(LIST_UNLINKED); + + // FILL OUT THE PROVIDER INFORMATION STRUCTURE + SStrCopy(info->filename,filename,MAX_PATH); + info->index = index; + info->id = id; + if (desc) + SStrCopy(info->desc,desc,SNETSPI_MAXSTRINGLENGTH); + if (req) + SStrCopy(info->req,req,SNETSPI_MAXSTRINGLENGTH); + CopyMemory(&info->caps,caps,sizeof(SNETCAPS)); + info->caps.maxmessagesize -= (sizeof(HEADER)+sizeof(DWORD)); + + // ADD IT TO THE LIST IN SORTED ORDER + PROVIDERINFOPTR curr = s_spi_providerlist.Head(); + while (curr && (SpiCheckProviderOrder(curr,info) <= 0)) + curr = curr->Next(); + s_spi_providerlist.LinkNode(info,LIST_LINK_BEFORE,curr); + + ++index; + } + + // FREE THE LIBRARY + FreeLibrary(lib); + + // FREE THE CAPABILITIES SIGNATURE + if (capssig) + FREE(capssig); + + } while (FindNextFile(findhandle,&finddata)); + FindClose(findhandle); +} + +//=========================================================================== +static BOOL SpiInitialize (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + HANDLE recvevent) { + + // DESTROY THE EXISTING PROVIDER IF ONE IS INITIALIZED + SpiDestroy(FALSE); + + // BUILD A LIST OF PROVIDERS IF WE DON'T ALREADY HAVE ONE + SpiFindAllProviders(); + + // FIND THE DESIRED PROVIDER + s_spi_providerptr = s_spi_providerlist.Head(); + while (s_spi_providerptr && (s_spi_providerptr->id != providerid)) + s_spi_providerptr = s_spi_providerptr->Next(); + if (!s_spi_providerptr) { + SpiDestroy(FALSE); + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + return FALSE; + } + + // DETERMINE TIMEOUTS BASED ON THE LATENCY OF THIS PROVIDER + s_spi_timetoackturn = max( 250, 5*s_spi_providerptr->caps.latencyms); + s_spi_timetoblock = max(5000,12*s_spi_providerptr->caps.latencyms); + s_spi_timetogiveup = max(1000, 4*s_spi_providerptr->caps.latencyms); + s_spi_timetorequest = max( 25,s_spi_providerptr->caps.latencyms/2); + s_spi_timetoresend = max( 50,s_spi_providerptr->caps.latencyms); + + // IF THIS PROVIDER REQUIRES PACKETS TO BE IN PAGE-LOCKED MEMORY, ALLOCATE + // A SEND BUFFER + if (s_spi_providerptr->caps.flags & SNET_CAPS_PAGELOCKEDBUFFERS) { + s_spi_sendbuffer = VirtualAlloc(NULL,SENDBUFSIZE,MEM_COMMIT,PAGE_READWRITE); + if (s_spi_sendbuffer) + VirtualLock(s_spi_sendbuffer,SENDBUFSIZE); + else { + SpiDestroy(FALSE); + SErrSetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + } + + // LOAD THE LIBRARY CONTAINING THE PROVIDER + s_spi_lib = LoadLibrary(s_spi_providerptr->filename); + if (!s_spi_lib) { + SpiDestroy(FALSE); + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + return FALSE; + } + + // GET A POINTER TO THE BIND FUNCTION + SNETSPIBIND bind = (SNETSPIBIND)GetProcAddress(s_spi_lib,"SnpBind"); + if (!bind) { + SpiDestroy(FALSE); + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + return FALSE; + } + + // BIND TO THE PROVIDER + SNETSPIPTR returnedspi = NULL; + bind(s_spi_providerptr->index,&returnedspi); + if ((!returnedspi) || (returnedspi->size < MINSPISIZE)) { + SpiDestroy(FALSE); + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + return FALSE; + } + + // SAVE THE PROVIDER INTERFACE POINTERS + if (!s_spi) + s_spi = NEW(SNETSPI); + ZeroMemory(s_spi,sizeof(SNETSPI)); + CopyMemory(s_spi,returnedspi,min(returnedspi->size,sizeof(SNETSPI))); + + // CALL THE PROVIDER'S INITIALIZE FUNCTION + TRACEOUT(TRACEHANDLE, + " spiInitialize(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x)", + programdata,playerdata,interfacedata,versiondata,recvevent); + if (!s_spi->Initialize(programdata, + playerdata, + interfacedata, + versiondata, + recvevent)) { + DWORD lasterror = SErrGetLastError(); + SpiDestroy(FALSE); + SErrSetLastError(lasterror); + return FALSE; + } + + return TRUE; +} + +//=========================================================================== +static LPVOID SpiLoadCapsSignature (LPCSTR filename) { + HSARCHIVE archive = (HSARCHIVE)0; + LPVOID buffer = NULL; + HSFILE file = (HSFILE)0; + TRY { + + // OPEN THE MPQ ARCHIVE EMBEDDED IN THE FILE + if (!SFileOpenArchive(filename,0,0,&archive)) + LEAVE; + + // AUTHENTICATE THE ARCHIVE + { + DWORD authtype; + SFileAuthenticateArchive(archive,&authtype); + if ((authtype != SFILE_AUTH_UNABLETOAUTHENTICATE) && + (authtype < SFILE_AUTH_FIRSTAUTHENTIC)) + LEAVE; + } + + // OPEN THE CAPABILITIES DATA FROM THE ARCHIVE + if (!SFileOpenFileEx(archive,"caps.dat",0,&file)) + LEAVE; + + // CREATE A BUFFER FOR THE CAPABILITIES DATA + DWORD bytes = SFileGetFileSize(file,NULL); + buffer = ALLOC(bytes); + + // READ THE CAPABILITIES DATA + { + DWORD bytesread; + SFileReadFile(file,buffer,bytes,&bytesread,NULL); + } + + } + FINALLY { + if (file) + SFileCloseFile(file); + if (archive) + SFileCloseArchive(archive); + } + return buffer; +} + +//=========================================================================== +static BOOL SpiMeetsMinimumCaps (SNETCAPSPTR curr, SNETCAPSPTR mincaps) { + if (!(curr && mincaps)) + return TRUE; + return (((mincaps->flags & curr->flags) == mincaps->flags) && + (mincaps->maxmessagesize <= curr->maxmessagesize) && + (mincaps->maxqueuesize <= curr->maxqueuesize ) && + (mincaps->maxplayers <= curr->maxplayers ) && + (mincaps->bytessec <= curr->bytessec ) && + ((!mincaps->latencyms) || + (mincaps->latencyms >= curr->latencyms))); +} + +//=========================================================================== +static BOOL SpiNormalizeDataBlocks (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + SNETPROGRAMDATAPTR modprogramdata, + SNETPLAYERDATAPTR modplayerdata, + SNETUIDATAPTR modinterfacedata, + SNETVERSIONDATAPTR modversiondata) { + + // NORMALIZE THE PROGRAM DATA + ZeroMemory(modprogramdata,sizeof(SNETPROGRAMDATA)); + if (programdata) + CopyMemory(modprogramdata,programdata,min(sizeof(SNETPROGRAMDATA),programdata->size)); + modprogramdata->size = sizeof(SNETPROGRAMDATA); + if (!modprogramdata->programname) + modprogramdata->programname = ""; + char generateddescription[256] = ""; + if (!modprogramdata->programdescription) { + UiGetProgramDescription(modprogramdata->programname, + versiondata, + generateddescription, + 256); + modprogramdata->programdescription = generateddescription; + } + + // NORMALIZE THE PLAYER DATA + ZeroMemory(modplayerdata,sizeof(SNETPLAYERDATA)); + if (playerdata) + CopyMemory(modplayerdata,playerdata,min(sizeof(SNETPLAYERDATA),playerdata->size)); + modplayerdata->size = sizeof(SNETPLAYERDATA); + if (!modplayerdata->playername) + modplayerdata->playername = ""; + if (!modplayerdata->playerdescription) + modplayerdata->playerdescription = ""; + + // NORMALIZE THE INTERFACE DATA + ZeroMemory(modinterfacedata,sizeof(SNETUIDATA)); + if (interfacedata) + CopyMemory(modinterfacedata,interfacedata,min(sizeof(SNETUIDATA),interfacedata->size)); + modinterfacedata->size = sizeof(SNETUIDATA); + if (!modinterfacedata->parentwindow) + modinterfacedata->parentwindow = SDrawGetFrameWindow(); + if (!modinterfacedata->messageboxcallback) + modinterfacedata->messageboxcallback = MessageBoxA; + + // NORMALIZE THE VERSION DATA + ZeroMemory(modversiondata,sizeof(SNETVERSIONDATA)); + if (versiondata) + CopyMemory(modversiondata,versiondata,min(sizeof(SNETVERSIONDATA),versiondata->size)); + modversiondata->size = sizeof(SNETVERSIONDATA); + + return TRUE; +} + +//=========================================================================== +static BOOL SpiSend (DWORD addresses, + SNETADDRPTR *addrlist, + LPVOID data, + DWORD databytes) { + if (!s_spi) + return FALSE; + + // UPDATE OUR ESTIMATE OF HOW LONG IT WILL TAKE TO SEND ALL THE OUTGOING + // DATA THAT WE HAVE QUEUED + { + DWORD currtime = GetTickCount(); + if (currtime-s_spi_outgoingtime < 0x7FFFFFFF) + s_spi_outgoingtime = currtime; + s_spi_outgoingtime += (addresses*(databytes+ESTIMATEDPACKETOVERHEAD)) + *1000 + /s_spi_providerptr->caps.bytessec; + } + + // IF THIS SERVICE PROVIDER REQUIRES ITS DATA TO BE PAGE LOCKED, MOVE + // THE ADDRESSES AND DATA INTO A PAGE LOCKED BUFFER + if (s_spi_sendbuffer) { + DWORD ptrbytes = 16*sizeof(SNETADDRPTR); + DWORD addrbytes = 16*sizeof(SNETADDR); + if ((addresses > 16) || (databytes > SENDBUFSIZE-addrbytes)) + return FALSE; + DWORD loop; + for (loop = 0; loop < addresses; ++loop) + *((SNETADDRPTR *)s_spi_sendbuffer+loop) = (SNETADDRPTR)((LPBYTE)s_spi_sendbuffer+ptrbytes+loop*sizeof(SNETADDR)); + for (loop = 0; loop < addresses; ++loop) + CopyMemory((LPBYTE)s_spi_sendbuffer+ptrbytes+loop*sizeof(SNETADDR),*(addrlist+loop),sizeof(SNETADDR)); + CopyMemory((LPBYTE)s_spi_sendbuffer+ptrbytes+addrbytes,data,databytes); + data = (LPBYTE)s_spi_sendbuffer+ptrbytes+addrbytes; + } + + // IF WE ARE IN DEBUG MODE, DUMP THE ADDRESSES AND PACKET DATA +#ifdef TRACING + TRACEOUT(TRACEHANDLE, + " spiSend(%u,*addrlist,0x%08x,%u)", + addresses,data,databytes); + for (DWORD loop = 0; loop < addresses; ++loop) { + CONNPTR targetconn = ConnFindByAddr(*(addrlist+loop)); + TRACEDUMPADDR(TRACEHANDLE, + "target", + *(addrlist+loop), + targetconn ? targetconn->playerid : NOPLAYER); + } + PACKETPTR pkt = (PACKETPTR)data; + TRACEDUMP(TRACEHANDLE,&pkt->header,min(databytes,sizeof(HEADER))); + if (databytes > sizeof(HEADER)) + TRACEDUMP(TRACEHANDLE,&pkt->data[0],databytes-sizeof(HEADER)); +#endif + + PerfAdd(SNET_PERFID_TOTALBYTESSENT,databytes); + return s_spi->Send(addresses,addrlist,data,databytes); +} + +/**************************************************************************** +* +* PACKET UTILITY FUNCTIONS +* +***/ + +//=========================================================================== +static void PktAllocateLocalMessage (SNETADDRPTR *addr, + LPVOID *data, + DWORD databytes) { + *addr = NEW(SNETADDR); + databytes += 4-(databytes & 3); + *data = ALLOC(max(4,databytes)); +} + +//=========================================================================== +static WORD PktComputeChecksum (LPVOID data, + DWORD databytes) { + DWORD checkval1 = 0; + DWORD checkval2 = 0; + LPBYTE ptr = ((LPBYTE)data)+databytes-1; + while (databytes--) { + checkval1 += *ptr--; + if (checkval1 >= 0xFF) + checkval1 -= 0xFF; + checkval2 += checkval1; + } + checkval2 %= 255; + return MAKEWORD((checkval2 & 0xFF),(checkval1 & 0xFF)); +} + +//=========================================================================== +static void PktFreeLocalMessage (SNETADDRPTR addr, + LPVOID data, + DWORD databytes) { + if (addr) + DEL(addr); + if (data) + FREE(data); +} + +//=========================================================================== +static WORD PktGenerateChecksum (PACKETPTR pkt) { + + // COMPUTE THE CURRENT CHECKSUM FOR THE MESSAGE + WORD checksum = PktComputeChecksum(((LPBYTE)pkt)+sizeof(WORD), + pkt->header.bytes-sizeof(WORD)); + + // COMPUTE A NEW VALUE FOR THE CHECKSUM FIELD THAT WILL MAKE THE NEW + // CHECKSUM OF THE ENTIRE MESSAGE ZERO + BYTE hibyte = 0xFF-((checksum >> 8)+(checksum & 0xFF)) % 0xFF; + BYTE lobyte = 0xFF-((checksum >> 8)+hibyte) % 0xFF; + return MAKEWORD(lobyte,hibyte); +} + +/**************************************************************************** +* +* CONNECTION MANAGEMENT FUNCTIONS +* +***/ + +static LIST(CONNREC) s_conn_connlist; +static LIST(CONNREC) s_conn_local; + +static void ConnFree (CONNPTR conn); +static BOOL ConnResendMessage (CONNPTR conn, + LPVOID data, + DWORD databytes); +static void ConnSendPacket (CONNPTR conn, + PACKETPTR pkt); +static MESSAGEPTR ConnSendMessage (CONNPTR target, + BYTE type, + BYTE subtype, + LPVOID data, + DWORD databytes); + +//=========================================================================== +static CONNPTR ConnAddRec (LISTPTR(CONNREC) list, SNETADDRPTR addr) { + TRACEDUMPADDR(TRACEHANDLE, + " ConnAddRec() addr", + addr,NOPLAYER); + CONNPTR newconn = list->NewNode(); + CopyMemory(&newconn->addr,addr,sizeof(SNETADDR)); + newconn->playerid = NOPLAYER; + newconn->lastreceivetime = GetTickCount(); + return newconn; +} + +//=========================================================================== +static void ConnClearOldTurns (CONNPTR onlyconn) { + CONNPTR localptr = ConnFindLocal(); + if (!localptr) + return; + + // DETERMINE THE SEQUENCE OF THE NEXT TURN WE WILL PROCESS + WORD sequence = localptr->incomingsequence[TYPE_TURN]; + + // DETERMINE THE EARLIEST POSSIBLE SEQUENCE FOR WHICH WE MAY STILL NEED + // TURN DATA FOR THE PURPOSES OF RESENDING TURNS ON BEHALF OF UNRESPONSIVE + // CLIENTS + WORD acksequence = sequence; + { + CONNPTR conn = s_conn_connlist.Head(); + while (conn) { + if ((WORD)(acksequence-conn->lastprocessedturn) < 0x7FFF) + acksequence = conn->lastprocessedturn; + conn = conn->Next(); + } + } + + // ITERATE THROUGH ALL CONNECTIONS + { + for (int local = 0; local <= 1; ++local) { + CONNPTR conn = local ? localptr : s_conn_connlist.Head(); + while (conn) { + if ((!onlyconn) || (conn == onlyconn)) { + + // IF THERE ARE ANY TURNS ON THIS CONNECTION'S INCOMING QUEUE + // WITH SEQUENCE NUMBERS PRIOR TO THE CURRENT SEQUENCE NUMBER, + // MOVE THEM TO THE OLD TURNS QUEUE + while ((!conn->incomingqueue[TYPE_TURN].IsEmpty()) && + ((WORD)(sequence-conn->incomingqueue[TYPE_TURN].Head()->data->header.sequence) > 0) && + ((WORD)(sequence-conn->incomingqueue[TYPE_TURN].Head()->data->header.sequence) <= 0x7FFF)) { + MESSAGEPTR message = conn->incomingqueue[TYPE_TURN].Head(); + conn->incomingqueue[TYPE_TURN].UnlinkNode(message); + ConnSetCurrentMessage(conn,TYPE_TURN,message); + } + + // IF THERE ARE ANY TURNS ON THIS CONNECTION'S OLD TURNS QUEUE + // WITH SEQUENCE NUMBERS PRIOR TO THE EARLIEST POSSIBLE NEEDED + // SEQUENCE, FREE THEM + while ((!conn->oldturns.IsEmpty()) && + ((WORD)(acksequence-conn->oldturns.Head()->data->header.sequence) > 0) && + ((WORD)(acksequence-conn->oldturns.Head()->data->header.sequence) <= 0x7FFF)) { + MESSAGEPTR message = conn->oldturns.Head(); + if (local) + PktFreeLocalMessage(message->addr,message->data,message->databytes); + else { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [all acks above turn sequence (%u>%u)]", + message->addr,message->data,message->databytes,acksequence,message->data->header.sequence); + s_spi->Free(message->addr,message->data,message->databytes); + } + conn->oldturns.DeleteNode(message); + } + + } + conn = conn->Next(); + } + } + } + +} + +//=========================================================================== +static void ConnDestroy () { + for (BOOL local = FALSE; local <= TRUE; ++local) { + LISTPTR(CONNREC) list = local ? &s_conn_local + : &s_conn_connlist; + CONNPTR currconn; + while ((currconn = list->Head()) != NULL) + ConnFree(currconn); + } +} + +//=========================================================================== +static void ConnDestroyQueue (LISTPTR(MESSAGE) queue) { + MESSAGEPTR currmsg; + while ((currmsg = queue->Head()) != NULL) { + if (currmsg->local) + PktFreeLocalMessage(currmsg->addr,currmsg->data,currmsg->databytes); + else if (s_spi) { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [closing connection]", + currmsg->addr,currmsg->data,currmsg->databytes); + s_spi->Free(currmsg->addr,currmsg->data,currmsg->databytes); + } + queue->DeleteNode(currmsg); + } +} + +//=========================================================================== +static CONNPTR inline ConnFindByAddr (SNETADDRPTR addr) { + CONNPTR curr = s_conn_connlist.Head(); + while (curr && memcmp(&curr->addr,addr,sizeof(SNETADDR))) + curr = curr->Next(); + if (!curr) + curr = ConnAddRec(&s_conn_connlist,addr); + return curr; +} + +//=========================================================================== +static CONNPTR inline ConnFindByPlayerId (DWORD playerid) { + if (playerid == NOPLAYER) + return NULL; + for (BOOL local = TRUE; local >= FALSE; --local) { + LISTPTR(CONNREC) list = local ? &s_conn_local + : &s_conn_connlist; + CONNPTR curr = list->Head(); + while (curr) + if (curr->playerid == (BYTE)playerid) + return curr; + else + curr = curr->Next(); + } + return NULL; +} + +//=========================================================================== +static CONNPTR inline ConnFindLocal () { + if (!s_conn_local.IsEmpty()) + return s_conn_local.Head(); + else { + SNETADDR addr; + ZeroMemory(&addr,sizeof(SNETADDR)); + return ConnAddRec(&s_conn_local,&addr); + } +} + +//=========================================================================== +static void ConnFree (CONNPTR conn) { + TRACEDUMPADDR(TRACEHANDLE, + " ConnFree() addr", + &conn->addr,conn->playerid); + for (int type = 0; type < TYPES; ++type) { + ConnDestroyQueue(&conn->outgoingqueue[type]); + ConnDestroyQueue(&conn->incomingqueue[type]); + ConnDestroyQueue(&conn->processing[type]); + } + ConnDestroyQueue(&conn->oldturns); + if (conn == s_conn_local.Head()) + s_conn_local.DeleteNode(conn); + else + s_conn_connlist.DeleteNode(conn); +} + +//=========================================================================== +static DWORD ConnMaintainConnections () { + DWORD currtime = GetTickCount(); + DWORD wait = INFINITE; + CONNPTR local = ConnFindLocal(); + CONNPTR conn = s_conn_connlist.Head(); + if (!(conn && local)) + return wait; + CONNPTR next; + do { + next = conn->Next(); + + // DELETE ANY CONNECTION WHICH WE HAVEN'T HEARD FROM IN FIFTY SECONDS + if ((conn->playerid == NOPLAYER) && + (currtime-conn->lastreceivetime >= DELETECONNTIME)) { + TRACEOUT(TRACEHANDLE, + " deleting unresponsive connection: player=%x", + conn->playerid); + ConnFree(conn); + continue; + } + + // DON'T SEND CONNECTION MAINTENANCE PACKETS TO PLAYERS WHO AREN'T + // IN THE GAME + if ((conn->playerid == NOPLAYER) && !conn->establishing) + continue; + + // PING EACH ESTABLISHED CONNECTION ONCE EVERY TWENTY SECONDS + if ((currtime-conn->lastpingtime >= PINGFREQUENCY) && + !conn->establishing) { + TRACEOUT(TRACEHANDLE, + " pinging: player=%x", + conn->playerid); + conn->lastpingtime = currtime; + ConnSendMessage(conn,TYPE_SYSTEM,SYS_PING,NULL,0); + } + + // SEND OUT RESEND REQUESTS AS NECESSARY + { + for (int type = 0; type < TYPES; ++type) { + WORD lastsequence = conn->incomingsequence[type]-1; + MESSAGEPTR message = conn->incomingqueue[type].Head(); + while (message) { + if (message->data->header.sequence-lastsequence > 1) { + if (message->resendtime && + ((LONG)(message->resendtime+s_spi_timetoresend-currtime) > 0)) + wait = min(wait,message->resendtime+s_spi_timetoresend-currtime); + else { + TRACEOUT(TRACEHANDLE, + " requesting resend: type=%u sequence=%04x player=%x", + type,lastsequence+1,conn->playerid); + message->resendtime = currtime; + PACKET pkt; + pkt.header.checksum = 0; + pkt.header.bytes = sizeof(HEADER); + pkt.header.sequence = lastsequence+1; + pkt.header.acksequence = conn->availablesequence[type]; + pkt.header.type = type; + pkt.header.subtype = 0; + pkt.header.playerid = local->playerid; + pkt.header.flags = MF_RESENDREQUEST; + pkt.header.checksum = PktGenerateChecksum(&pkt); + ConnSendPacket(conn,&pkt); + } + break; + } + lastsequence = message->data->header.sequence; + message = message->Next(); + } + } + } + + // AUTOMATICALLY RESEND UNACKNOWLEDGED SYSTEM MESSAGES AND USER + // ASYNCHRONOUS MESSAGES + // (THESE TYPES OF MESSAGES ARE NOT EXPECTED BY THE RECIPIENT, SO + // WE CAN'T RELY ON HIM TO REQUEST A RESEND) + { + for (int type = 0; type < TYPES; ++type) + if ((!conn->outgoingqueue[type].IsEmpty()) && + (type != TYPE_TURN)) { + + // DETERMINE HOW QUICKLY WE SHOULD EXPECT A RESPONSE TO THIS + // MESSAGE, BASED ON BOTH LATENCY AND BANDWIDTH + MESSAGEPTR message = conn->outgoingqueue[type].Head(); + DWORD bandwidth = s_spi_providerptr->caps.bytessec; + DWORD maxpacket = s_spi_providerptr->caps.maxmessagesize; + DWORD totaldata = message->databytes + +maxpacket + +2*ESTIMATEDPACKETOVERHEAD; + DWORD responsetime = 2*s_spi_timetoresend + +totaldata*1000/bandwidth + +200; + + // IF WE HAVEN'T RECEIVED A RESPONSE IN THE EXPECTED AMOUNT + // OF TIME, RESEND THE MESSAGE + if (message->resendtime && + ((LONG)(message->resendtime+responsetime-currtime) > 0)) + wait = min(wait,message->resendtime+responsetime-currtime); + else { + TRACEOUT(TRACEHANDLE, + " auto-resending: type=%u sequence=%04x player=%x", + type,message->data->header.sequence,conn->playerid); + message->resendtime = currtime; + ConnResendMessage(conn,message->data,message->databytes); + } + + } + } + + // SEND OUT EXPLICIT ACKNOWLEDGEMENT PACKETS TO THIS CONNECTION IF + // WE HAVEN'T SENT ANY EXPLICIT OR PIGGY-BACKED ACKNOWLEDGEMENTS RECENTLY + { + for (int type = 0; type < TYPES; ++type) { + DWORD acktime = (type == TYPE_TURN) ? s_spi_timetoackturn + : s_spi_timetorequest; + if ((conn->acksequence[type] != conn->availablesequence[type]) && + conn->acktime[type]) + if ((LONG)(conn->acktime[type]+acktime-currtime) > 0) + wait = min(wait,conn->acktime[type]+acktime-currtime); + else { + TRACEOUT(TRACEHANDLE, + " sending explicit ack: type=%u sequence=%04x player=%x", + type,conn->availablesequence[type],conn->playerid); + PACKET pkt; + pkt.header.checksum = 0; + pkt.header.bytes = sizeof(HEADER); + pkt.header.sequence = conn->availablesequence[type]; + pkt.header.acksequence = conn->availablesequence[type]; + pkt.header.type = type; + pkt.header.subtype = 0; + pkt.header.playerid = local->playerid; + pkt.header.flags = MF_ACK; + pkt.header.checksum = PktGenerateChecksum(&pkt); + SNETADDRPTR addr = &conn->addr; + ConnSendPacket(conn,&pkt); + } + } + } + + } while ((conn = next) != NULL); + return wait; +} + +//=========================================================================== +static void ConnProcessAck (CONNPTR conn, BYTE type, WORD acksequence) { + + // REMOVE ACKNOWLEDGED MESSAGES FROM THE OUTGOING QUEUE + BOOL found = FALSE; + while ((!conn->outgoingqueue[type].IsEmpty()) && + ((WORD)(acksequence-conn->outgoingqueue[type].Head()->data->header.sequence) > 0) && + ((WORD)(acksequence-conn->outgoingqueue[type].Head()->data->header.sequence) <= 0x7FFF)) { + found = TRUE; + MESSAGEPTR message = conn->outgoingqueue[type].Head(); + if (message->local) + PktFreeLocalMessage(message->addr,message->data,message->databytes); + else { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [acknowledged]", + message->addr, + message->data, + message->databytes); + s_spi->Free(message->addr,message->data,message->databytes); + } + conn->outgoingqueue[type].DeleteNode(message); + } + + // SAVE THE SEQUENCE OF THE LAST PROCESSED TURN + if (type == TYPE_TURN) + conn->lastprocessedturn = acksequence; + + // RESET THE TIME STAMP OF THE MESSAGE THAT IS NOW AT THE HEAD OF THE + // OUTGOING QUEUE, SO WE DON'T IMMEDIATELY RESEND IT + if (found && !conn->outgoingqueue[type].IsEmpty()) { + DWORD currtime = GetTickCount(); + if (currtime-conn->outgoingqueue[type].Head()->resendtime < 0x7FFFFFFF) + conn->outgoingqueue[type].Head()->resendtime = currtime; + } + +} + +//=========================================================================== +static BOOL ConnResendMessage (CONNPTR conn, + LPVOID data, + DWORD databytes) { + + // MAKE A COPY OF THE MESSAGE + PACKETPTR localpkt = (PACKETPTR)ALLOC(databytes); + CopyMemory(localpkt,data,databytes); + + // FILL IN THE CURRENT ACKNOWLEDGEMENT SEQUENCE + localpkt->header.acksequence = conn->availablesequence[localpkt->header.type]; + + // FILL IN THE NEW CHECKSUM + localpkt->header.checksum = PktGenerateChecksum(localpkt); + + // SEND THE MESSAGE + ConnSendPacket(conn,localpkt); + + // FREE THE COPY + FREE(localpkt); + + return TRUE; +} + +//=========================================================================== +static void ConnSendPacket (CONNPTR conn, + PACKETPTR pkt) { + SNETADDRPTR addr = &conn->addr; + SpiSend(1,&addr,pkt,pkt->header.bytes); + conn->acksequence[pkt->header.type] = pkt->header.acksequence; + conn->acktime[pkt->header.type] = 0; +} + +//=========================================================================== +static MESSAGEPTR ConnSendMessage (CONNPTR target, + BYTE type, + BYTE subtype, + LPVOID data, + DWORD databytes) { + + // GET A POINTER TO THE LOCAL PLAYER + CONNPTR local = ConnFindLocal(); + if (!local) + return NULL; + + // ALLOCATE MEMORY TO HOLD THE ADDRESS AND MESSAGE DATA + SNETADDRPTR pktaddr = NULL; + LPVOID pktdata = NULL; + DWORD pktdatabytes = sizeof(HEADER)+databytes; + PktAllocateLocalMessage(&pktaddr,&pktdata,pktdatabytes); + + // FILL IN THE ADDRESS + CopyMemory(pktaddr,&target->addr,sizeof(SNETADDR)); + + // FILL IN THE HEADER + PACKETPTR pkt = (PACKETPTR)pktdata; + pkt->header.bytes = (WORD)pktdatabytes; + pkt->header.acksequence = target->availablesequence[type]; + pkt->header.type = type; + pkt->header.subtype = subtype; + pkt->header.playerid = local->playerid; + pkt->header.flags = 0; + + // FILL IN THE SEQUENCE NUMBER FOR THIS MESSAGE + if ((type == TYPE_SYSTEM) && (subtype == SYS_INITIALCONTACT)) + pkt->header.sequence = 0; + else + pkt->header.sequence = target->outgoingsequence[type]++; + + // FILL IN THE DATA + if (data && databytes) + CopyMemory((LPBYTE)pktdata+sizeof(HEADER),data,databytes); + + // FILL IN THE CHECKSUM + pkt->header.checksum = PktGenerateChecksum(pkt); + + // ALLOCATE A MESSAGE RECORD + MESSAGEPTR msg; + if (target == local) + msg = target->incomingqueue[type].NewNode(); + else + msg = target->outgoingqueue[type].NewNode(); + + // FILL IN THE MESSAGE RECORD + msg->addr = pktaddr; + msg->data = (PACKETPTR)pktdata; + msg->databytes = pktdatabytes; + msg->local = TRUE; + msg->sendtime = GetTickCount(); + + // SEND THE MESSAGE + if (target != local) { + ConnSendPacket(target,pkt); + PerfAdd(SNET_PERFID_USERBYTESSENT,databytes); + } + + // INITIALIZE THE MESSAGE'S RESEND TIMER TO THE ESTIMATED TIME THAT + // THE COMPLETE MESSAGE WILL HIT THE WIRE + msg->resendtime = s_spi_outgoingtime; + + return msg; +} + +//=========================================================================== +static void ConnSetCurrentMessage (CONNPTR conn, BYTE type, MESSAGEPTR message) { + // message must be unlinked upon entry to this function + if (type == TYPE_TURN) + conn->oldturns.LinkNode(message,LIST_TAIL,NULL); + else { + if (!conn->processing[type].IsEmpty()) { + MESSAGEPTR processing = conn->processing[type].Head(); + if (processing->local) + PktFreeLocalMessage(processing->addr, + processing->data, + processing->databytes); + else { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [processed]", + processing->addr, + processing->data, + processing->databytes); + s_spi->Free(processing->addr, + processing->data, + processing->databytes); + } + conn->processing[type].DeleteNode(processing); + } + conn->processing[type].LinkNode(message,LIST_TAIL,NULL); + } +} + +/**************************************************************************** +* +* GAME/PLAYER MANAGEMENT FUNCTIONS +* +***/ + +static DWORD s_game_categorybits = 0; +static DWORD s_game_creationtime = 0; +static LPVOID s_game_initdata = NULL; +static DWORD s_game_initdatabytes = 0; +static char s_game_gamedesc[SNETSPI_MAXSTRINGLENGTH] = ""; +static DWORD s_game_gamemode = 0; +static char s_game_gamename[SNETSPI_MAXSTRINGLENGTH] = ""; +static char s_game_gamepass[SNETSPI_MAXSTRINGLENGTH] = ""; +static BOOL s_game_joining = FALSE; +static DWORD s_game_optcategorybits = 0; +static BYTE s_game_playerid = NOPLAYER; +static DWORD s_game_playersallowed = 0; + +//=========================================================================== +static void GameBuildClientData (LPVOID buffer, + DWORD *bytes) { + CLIENTDATAPTR ptr = (CLIENTDATAPTR)buffer; + ptr->bytes = sizeof(CLIENTDATA); + SNetGetNumPlayers(NULL,NULL,&ptr->numplayers); + ptr->maxplayers = s_game_playersallowed; + *bytes = ptr->bytes; +} + +//=========================================================================== +static void GameBuildGameData (SNETGAMEPTR dest, + SNETSPI_GAMELISTPTR source) { + ZeroMemory(dest,sizeof(SNETGAME)); + dest->size = sizeof(SNETGAMEPTR); + dest->id = source->gameid; + dest->gamename = source->gamename; + dest->gamedescription = source->gamedescription; + dest->categorybits = source->gamecategorybits; + CLIENTDATAPTR clientdata = (CLIENTDATAPTR)(source->clientdata); + if (clientdata) { + dest->numplayers = clientdata->numplayers; + dest->maxplayers = clientdata->maxplayers; + } +} + +//=========================================================================== +static void GameCopyGameList (DWORD categorybits, + DWORD categorymask, + SNETSPI_GAMELISTPTR *gamearray, + DWORD *games, + DWORD *hintnextcall) { + *games = 0; + + // LOCK THE GAME LIST + SNETSPI_GAMELISTPTR head; + TRACEOUT(TRACEHANDLE, + " spiLockGameList(0x%08x,0x%08x,*gamelist)", + categorybits,categorymask); + if (!s_spi->LockGameList(categorybits,categorymask,&head)) + return; + + // DETERMINE THE NUMBER OF MATCHING GAMES + *games = 0; + { + SNETSPI_GAMELISTPTR curr = head; + while (curr) { + if (!(curr->gamemode & SNET_GM_UNLISTEDMASK)) + ++*games; + curr = curr->next; + } + } + + // ALLOCATE AN ARRAY TO HOLD THE GAMES + if (*games) { + *gamearray = (SNETSPI_GAMELISTPTR)ALLOC((*games)*(sizeof(SNETSPI_GAMELIST)+SNETSPI_MAXCLIENTDATA)); + + // COPY THE GAMES + SNETSPI_GAMELISTPTR source = head; + LPBYTE dest = (LPBYTE)*gamearray; + SNETSPI_GAMELISTPTR lastdest = NULL; + while (source) { + if (!(source->gamemode & SNET_GM_UNLISTEDMASK)) { + + // LINK THE LAST RECORD TO THIS ONE + if (lastdest) + lastdest->next = (SNETSPI_GAMELISTPTR)dest; + lastdest = (SNETSPI_GAMELISTPTR)dest; + + // COPY THIS RECORD + CopyMemory(dest,source,sizeof(SNETSPI_GAMELIST)); + dest += sizeof(SNETSPI_GAMELIST); + + // COPY THE CLIENT DATA FOR THIS RECORD + if (source->clientdata) { + CopyMemory(dest,source->clientdata,source->clientdatabytes); + lastdest->clientdata = dest; + dest += source->clientdatabytes; + } + + } + source = source->next; + } + + } + + // UNLOCK THE GAME LIST + TRACEOUT(TRACEHANDLE, + " spiUnlockGameList(0x%08x,*hintnextcall)", + head); + s_spi->UnlockGameList(head,hintnextcall); + +} + +//=========================================================================== +static void GameDestroy () { + + // FREE THE GAME INITIALIZATION DATA + if (s_game_initdata) { + FREE(s_game_initdata); + s_game_initdata = NULL; + s_game_initdatabytes = 0; + } + + // RESET THE GAME INFORMATION + s_game_gamename[0] = 0; + s_game_gamedesc[0] = 0; + s_game_gamepass[0] = 0; + s_game_gamemode = 0; + + // RESET THE PLAYER INFORMATION + s_game_playerid = NOPLAYER; + s_game_playersallowed = 0; + + // DESTROY ALL CONNECTION RECORDS + ConnDestroy(); + +} + +//=========================================================================== +static void GameProcessLeavingPlayers () { + CONNPTR conn = s_conn_connlist.Head(); + CONNPTR local = ConnFindLocal(); + if (!local) + return; + while (conn) { + if ((conn->flags & PF_LEAVING) && + (conn->playerid != NOPLAYER)) { + + // IF WE HAVE PROCESSED THE FINAL TURN FOR THIS PLAYER, REMOVE HIM + if ((WORD)(conn->incomingsequence[TYPE_TURN]-conn->finalsequence) <= 0x7FFF) { + + // QUEUE A USER-LEVEL EVENT + SysQueueUserEvent(SNET_EVENT_PLAYERLEAVE,conn->playerid,&conn->exitcode,sizeof(DWORD)); + + // MARK THE PLAYER SLOT AS UNUSED + conn->flags = 0; + conn->playerid = NOPLAYER; + + // IF THE GAME OWNER JUST LEFT AND WE ARE NOW THE LOWEST NUMBERED + // PLAYER, TAKE OWNERSHIP OF THE GAME + if ((s_game_playerid != NOPLAYER) && + !local->gameowner) { + + // FIND THE LOWEST NUMBERED PLAYED BESIDES THE LOCAL PLAYER WHICH + // IS STILL IN THE GAME + DWORD lowestplayerid = 0xFFFFFFFF; + CONNPTR checkconn = s_conn_connlist.Head(); + while (checkconn) { + if (checkconn->playerid != NOPLAYER) { + if (checkconn->gameowner) + lowestplayerid = 0; + else if (checkconn->playerid < lowestplayerid) + lowestplayerid = checkconn->playerid; + } + checkconn = checkconn->Next(); + } + + // IF OUR PLAYER NUMBER IS LOWER, TAKE OWNERSHIP + if (s_game_playerid < lowestplayerid) { + + // LOG IT + TRACEOUT(TRACEHANDLE," taking ownership"); + + // MARK THE LOCAL PLAYER AS THE OWNER + local->gameowner = TRUE; + + // SEND MESSAGES TO ALL OTHER PLAYERS NOTIFYING THEM OF THE + // TRANSFER OF GAME OWNERSHIP + { + CONNPTR checkconn = s_conn_connlist.Head(); + while (checkconn) { + if (checkconn->playerid != NOPLAYER) { + DWORD playerid = s_game_playerid; + ConnSendMessage(checkconn, + TYPE_SYSTEM, + SYS_NEWGAMEOWNER, + &playerid, + sizeof(DWORD)); + } + checkconn = checkconn->Next(); + } + } + + } + } + + // IF THE GAME IS NO LONGER FULL, NOTIFY THE NETWORK PROVIDER BY + // CHANGING THE GAME MODE + { + CONNPTR local = ConnFindLocal(); + if (local && local->gameowner) { + DWORD activeplayers = 0; + SNetGetNumPlayers(NULL,NULL,&activeplayers); + if (activeplayers < s_game_playersallowed) + s_game_gamemode &= ~SNET_GM_FULL; + } + } + + // UPDATE THE SERVER WITH THE NEW GAME MODE, FULL VS NOT FULL, + // NUMBER OF PLAYERS, ETC. + SNetSetGameMode(s_game_gamemode); + + } + + } + conn = conn->Next(); + } +} + +/**************************************************************************** +* +* SYSTEM MESSAGE FUNCTIONS +* +***/ + +static LIST(USEREVENT) s_sys_usereventlist; +static BOOL s_sys_event[SYSMSGS]; + +//=========================================================================== +static DWORD SysBuildPlayerInfo (SYSEVENTDATA_PLAYERINFOPTR data, + CONNPTR conn, + DWORD startingturn) { + data->playerid = conn->playerid; + data->gameowner = conn->gameowner; + data->flags = conn->flags; + data->startingturn = startingturn; + CopyMemory(&data->addr,&conn->addr,sizeof(SNETADDR)); + LPTSTR curr = data->namedesc; + curr += SStrCopy(curr,conn->name,SNETSPI_MAXSTRINGLENGTH)+1; + curr += SStrCopy(curr,conn->desc,SNETSPI_MAXSTRINGLENGTH)+1; + data->bytes = (LPBYTE)curr-(LPBYTE)data; + return data->bytes; +} + +//=========================================================================== +static void SysDestroy () { + USEREVENTPTR curr; + while ((curr = s_sys_usereventlist.Head()) != NULL) { + if (curr->event.data) + FREE(curr->event.data); + s_sys_usereventlist.DeleteNode(curr); + } +} + +//=========================================================================== +static void SysDispatchUserEvents () { + USEREVENTPTR curr; + while ((curr = s_sys_usereventlist.Head()) != NULL) { + USEREVENT event; + CopyMemory(&event,curr,sizeof(USEREVENT)); + s_sys_usereventlist.DeleteNode(curr); + event.event.playerid += s_api_playeroffset; + TRACEOUT(TRACEHANDLE, + " dispatch event=%u player=%u data=0x%08x databytes=%u", + event.event.eventid,event.event.playerid,event.event.data,event.event.databytes); + SEvtDispatch(REGISTERTYPE, + REGISTERSUBTYPE_SNETEVENT, + event.event.eventid, + &event.event); + if (event.event.data) + FREE(event.event.data); + } +} + +//=========================================================================== +static void CALLBACK SysOnCircuitCheck (SYSEVENTPTR event) { + if ((event->databytes == sizeof(DWORD)) && + (*(LPDWORD)event->data == SNET_NETWORKVERSION)) + ConnSendMessage(ConnFindByAddr(event->senderaddr), + TYPE_SYSTEM, + SYS_CIRCUITCHECKRESPONSE, + event->data, + event->databytes); +} + +//=========================================================================== +static void CALLBACK SysOnDropPlayer (SYSEVENTPTR event) { + SYSEVENTDATA_DROPPLAYERPTR eventdataptr = (SYSEVENTDATA_DROPPLAYERPTR)event->data; + + // MARK THE PLAYER AS LEAVING. WE DON'T ACTUALLY REMOVE HIM FROM THE + // GAME, OR SEND A USER-LEVEL NOTIFICATION, UNTIL THE APPLICATION HAS + // PROCESSED ALL REMAINING MESSAGES FROM THIS PLAYER. + CONNPTR conn = ConnFindByPlayerId(eventdataptr->playerid); + if (conn && (conn->playerid != NOPLAYER)) { + conn->flags |= PF_LEAVING; + conn->finalsequence = (WORD)eventdataptr->finalsequence; + conn->exitcode = eventdataptr->exitcode; + } + +} + +//=========================================================================== +static void CALLBACK SysOnNewGameOwner (SYSEVENTPTR event) { + + // REMOVE OWNERSHIP FROM THE EXISTING GAME OWNER + for (BOOL local = TRUE; local >= FALSE; --local) { + LISTPTR(CONNREC) list = local ? &s_conn_local + : &s_conn_connlist; + ITERATELISTPTR(CONNREC,list,curr) + curr->gameowner = FALSE; + } + + // MAKE THE SENDER THE NEW GAME OWNER + DWORD playerid = *(LPDWORD)event->data; + CONNPTR conn = ConnFindByPlayerId(playerid); + if (conn) + conn->gameowner = TRUE; + +} + +//=========================================================================== +static void CALLBACK SysOnPing (SYSEVENTPTR event) { + ConnSendMessage(ConnFindByAddr(event->senderaddr), + TYPE_SYSTEM, + SYS_PINGRESPONSE, + event->data, + event->databytes); +} + +//=========================================================================== +static void CALLBACK SysOnPingResponse (SYSEVENTPTR event) { + CONNPTR conn = ConnFindByAddr(event->senderaddr); + DWORD currtime = GetTickCount(); + if (conn) { + conn->latency = currtime-conn->lastpingtime; + conn->peaklatency = max(conn->peaklatency,conn->latency); + } +} + +//=========================================================================== +static void CALLBACK SysOnPlayerInfo (SYSEVENTPTR event) { + SYSEVENTDATA_PLAYERINFOPTR eventdataptr = (SYSEVENTDATA_PLAYERINFOPTR)event->data; + SNETADDRPTR addr = &eventdataptr->addr; + + // IF THIS IS THE PLAYER INFO FOR THE SYSTEM SENDING THE PACKET, USE THE + // PACKET'S ORIGIN ADDRESS RATHER THAN THE ONE IN THE PLAYER INFORMATION, + // BECAUSE THE SENDER PRESUMABLY DOESN'T KNOW HIS OWN ADDRESS. + if (eventdataptr->playerid == event->senderplayerid) + addr = event->senderaddr; + + // OTHERWISE, IF THIS IS THE PLAYER INFO FOR A THIRD PARTY SYSTEM, THEN + // RESET THE CONNECTION RECORD FOR THAT SYSTEM. + else + ConnFree(ConnFindByAddr(addr)); + + // UPDATE THE PLAYER INFORMATION + CONNPTR conn = ConnFindByAddr(addr); + CONNPTR local = ConnFindLocal(); + if (conn && local) { + conn->flags = eventdataptr->flags; + conn->playerid = (BYTE)eventdataptr->playerid; + conn->gameowner = eventdataptr->gameowner; + conn->incomingsequence[TYPE_TURN] = (WORD)eventdataptr->startingturn; + conn->availablesequence[TYPE_TURN] = (WORD)eventdataptr->startingturn; + conn->outgoingsequence[TYPE_TURN] = local->outgoingsequence[TYPE_TURN]; + if ((conn->incomingsequence[TYPE_TURN] != local->incomingsequence[TYPE_TURN]) && + ((WORD)(conn->incomingsequence[TYPE_TURN]-local->incomingsequence[TYPE_TURN]) < 0x7FFF)) + conn->flags |= PF_JOINING; + CopyMemory(&conn->addr,addr,sizeof(SNETADDR)); + SStrCopy(conn->name, + eventdataptr->namedesc, + SNETSPI_MAXSTRINGLENGTH); + SStrCopy(conn->desc, + eventdataptr->namedesc+SStrLen(eventdataptr->namedesc)+1, + SNETSPI_MAXSTRINGLENGTH); + } + + // IF THIS IS A NEW PLAYER, SEND HIM ALL OF OUR TURNS FROM HIS STARTING + // TURN NUMBER + { + MESSAGEPTR currmsg; + currmsg = local->oldturns.Head(); + while (currmsg) { + if ((WORD)(currmsg->data->header.sequence-eventdataptr->startingturn) <= 0x7FFF) + ConnResendMessage(conn,currmsg->data,currmsg->databytes); + currmsg = currmsg->Next(); + } + currmsg = local->incomingqueue[TYPE_TURN].Head(); + while (currmsg) { + if ((WORD)(currmsg->data->header.sequence-eventdataptr->startingturn) <= 0x7FFF) + ConnResendMessage(conn,currmsg->data,currmsg->databytes); + currmsg = currmsg->Next(); + } + } + + // QUEUE A USER-LEVEL EVENT + if ((s_game_playerid != NOPLAYER) && + conn && + (!(conn->flags & PF_JOINING))) + SysQueueUserEvent(SNET_EVENT_PLAYERJOIN, + eventdataptr->playerid, + NULL, + 0); + +} + +//=========================================================================== +static void CALLBACK SysOnPlayerJoin (SYSEVENTPTR event) { + SYSEVENTDATA_PLAYERJOINPTR eventdataptr = (SYSEVENTDATA_PLAYERJOINPTR)event->data; + + // IF THE GAME IS FULL OR NOT JOINABLE, SEND BACK A REJECTION NOTICE + { + DWORD activeplayers = 0; + SNetGetNumPlayers(NULL,NULL,&activeplayers); + if ((activeplayers >= s_game_playersallowed) || + (s_game_gamemode & SNET_GM_UNJOINABLE)) { + ConnSendMessage(ConnFindByAddr(event->senderaddr), + TYPE_SYSTEM, + SYS_PLAYERJOIN_REJECT, + NULL, + 0); + return; + } + } + + // BREAK OUT THE NAME, DESCRIPTION, AND PASSWORD + LPCSTR playername = eventdataptr->namedescpass; + LPCSTR playerdesc = playername+SStrLen(playername)+1; + LPCSTR gamepass = playerdesc+SStrLen(playerdesc)+1; + + // IF THE PASSWORD IS WRONG, SEND BACK A REJECTION NOTICE + if (s_game_gamepass[0] && _stricmp(s_game_gamepass,gamepass)) { + ConnSendMessage(ConnFindByAddr(event->senderaddr), + TYPE_SYSTEM, + SYS_PLAYERJOIN_REJECT, + NULL, + 0); + return; + } + + // DETERMINE THE PLAYER'S ID + BYTE playerid = 0; + do { + if (!ConnFindByPlayerId(playerid)) + break; + } while (++playerid != NOPLAYER); + if ((playerid == NOPLAYER) || (playerid >= s_game_playersallowed)) { + ConnSendMessage(ConnFindByAddr(event->senderaddr), + TYPE_SYSTEM, + SYS_PLAYERJOIN_REJECT, + NULL, + 0); + return; + } + + // ADD THE PLAYER + CONNPTR local = ConnFindLocal(); + CONNPTR conn = ConnFindByAddr(event->senderaddr); + if (!(conn && local)) + return; + { + conn->flags = 0; + conn->playerid = playerid; + conn->establishing = FALSE; + SStrCopy(conn->name,playername,SNETSPI_MAXSTRINGLENGTH); + SStrCopy(conn->desc,playerdesc,SNETSPI_MAXSTRINGLENGTH); + conn->incomingsequence[TYPE_TURN] = local->outgoingsequence[TYPE_TURN]; + conn->availablesequence[TYPE_TURN] = local->outgoingsequence[TYPE_TURN]; + conn->outgoingsequence[TYPE_TURN] = local->outgoingsequence[TYPE_TURN]; + if ((conn->incomingsequence[TYPE_TURN] != local->incomingsequence[TYPE_TURN]) && + ((WORD)(conn->incomingsequence[TYPE_TURN]-local->incomingsequence[TYPE_TURN]) < 0x7FFF)) + conn->flags |= PF_JOINING; + } + + // NOTIFY THE NETWORK PROVIDER OF THE NEW NUMBER OF PLAYERS IN THE GAME + { + DWORD activeplayers = 0; + SNetGetNumPlayers(NULL,NULL,&activeplayers); + DWORD gamemode = s_game_gamemode; + if (activeplayers >= s_game_playersallowed) + gamemode |= SNET_GM_FULL; + SNetSetGameMode(gamemode); + } + + // SEND BACK AN ACCEPT START NOTICE + DWORD startingturn = local->outgoingsequence[TYPE_TURN]; + { + SYSEVENTDATA_PLAYERJOIN_ACCEPTSTART data; + data.playerid = playerid; + data.playersallowed = s_game_playersallowed; + data.nextturn = startingturn; + data.gamemode = s_game_gamemode; + data.runningtime = (GetTickCount()-s_game_creationtime)/1000; + LPSTR currptr = data.namedescpass; + currptr += SStrCopy(currptr,s_game_gamename,SNETSPI_MAXSTRINGLENGTH)+1; + currptr += SStrCopy(currptr,s_game_gamedesc,SNETSPI_MAXSTRINGLENGTH)+1; + currptr += SStrCopy(currptr,s_game_gamepass,SNETSPI_MAXSTRINGLENGTH)+1; + ConnSendMessage(conn, + TYPE_SYSTEM, + SYS_PLAYERJOIN_ACCEPTSTART, + &data, + (LPBYTE)currptr-(LPBYTE)&data); + } + + // SEND BACK INFORMATION ABOUT THE LOCAL PLAYER + { + SYSEVENTDATA_PLAYERINFO data; + DWORD databytes = SysBuildPlayerInfo(&data,local,startingturn); + ConnSendMessage(conn, + TYPE_SYSTEM, + SYS_PLAYERINFO, + &data, + databytes); + } + + // SEND BACK INFORMATION FOR EACH OTHER PLAYER IN THE GAME + { + CONNPTR sendconn = s_conn_connlist.Head(); + while (sendconn) { + if ((sendconn != conn) && (sendconn->playerid != NOPLAYER)) { + SYSEVENTDATA_PLAYERINFO data; + DWORD databytes = SysBuildPlayerInfo(&data,sendconn,startingturn); + ConnSendMessage(conn, + TYPE_SYSTEM, + SYS_PLAYERINFO, + &data, + databytes); + } + sendconn = sendconn->Next(); + } + } + + // SEND BACK AN ACCEPT DONE NOTICE + ConnSendMessage(conn, + TYPE_SYSTEM, + SYS_PLAYERJOIN_ACCEPTDONE, + s_game_initdata, + s_game_initdatabytes); + + // SEND AN UPDATE MESSAGE TO ALL OTHER PLAYERS IN THE GAME + { + CONNPTR destconn = s_conn_connlist.Head(); + while (destconn) { + if ((destconn != conn) && (destconn->playerid != NOPLAYER)) { + SYSEVENTDATA_PLAYERINFO data; + DWORD databytes = SysBuildPlayerInfo(&data,conn,startingturn); + ConnSendMessage(destconn, + TYPE_SYSTEM, + SYS_PLAYERINFO, + &data, + databytes); + } + destconn = destconn->Next(); + } + } + + // SEND THE NEW PLAYER A COPY OF ALL OUR UNPROCESSED TURNS + { + MESSAGEPTR currmsg = local->incomingqueue[TYPE_TURN].Head(); + while (currmsg) { + ConnResendMessage(conn,currmsg->data,currmsg->databytes); + currmsg = currmsg->Next(); + } + } + + // QUEUE A USER-LEVEL EVENT + if (!(conn->flags & PF_JOINING)) + SysQueueUserEvent(SNET_EVENT_PLAYERJOIN,playerid,NULL,0); + +} + +//=========================================================================== +static void CALLBACK SysOnPlayerJoinAcceptStart (SYSEVENTPTR event) { + SYSEVENTDATA_PLAYERJOIN_ACCEPTSTARTPTR eventdataptr + = (SYSEVENTDATA_PLAYERJOIN_ACCEPTSTARTPTR)event->data; + CONNPTR conn = ConnFindLocal(); + if (conn) { + conn->playerid = (BYTE)eventdataptr->playerid; + conn->incomingsequence[TYPE_TURN] = (WORD)eventdataptr->nextturn; + conn->availablesequence[TYPE_TURN] = (WORD)eventdataptr->nextturn; + conn->outgoingsequence[TYPE_TURN] = (WORD)eventdataptr->nextturn; + PerfSet(SNET_PERFID_TURN,eventdataptr->nextturn); + } + s_game_playersallowed = eventdataptr->playersallowed; + s_game_gamemode = eventdataptr->gamemode; + s_game_creationtime = GetTickCount()-eventdataptr->runningtime*1000; + LPCSTR currptr = eventdataptr->namedescpass; + currptr += SStrCopy(s_game_gamename,currptr,SNETSPI_MAXSTRINGLENGTH)+1; + currptr += SStrCopy(s_game_gamedesc,currptr,SNETSPI_MAXSTRINGLENGTH)+1; + currptr += SStrCopy(s_game_gamepass,currptr,SNETSPI_MAXSTRINGLENGTH)+1; +} + +//=========================================================================== +static void CALLBACK SysOnPlayerJoinAcceptDone (SYSEVENTPTR event) { + CONNPTR conn = ConnFindLocal(); + if (conn) + s_game_playerid = conn->playerid; + if (s_game_initdata) { + FREE(s_game_initdata); + s_game_initdata = NULL; + } + s_game_initdatabytes = 0; + if (event->data && event->databytes) { + s_game_initdata = ALLOC(event->databytes); + s_game_initdatabytes = event->databytes; + CopyMemory(s_game_initdata,event->data,s_game_initdatabytes); + SysQueueUserEvent(SNET_EVENT_INITDATA, + s_game_playerid, + s_game_initdata, + s_game_initdatabytes); + } +} + +//=========================================================================== +static void CALLBACK SysOnPlayerJoinReject (SYSEVENTPTR event) { +} + +//=========================================================================== +static void CALLBACK SysOnPlayerLeave (SYSEVENTPTR event) { + SYSEVENTDATA_PLAYERLEAVEPTR eventdataptr = + (SYSEVENTDATA_PLAYERLEAVEPTR)event->data; + + // MARK THE PLAYER AS LEAVING. WE DON'T ACTUALLY REMOVE HIM FROM THE + // GAME, OR SEND A USER-LEVEL NOTIFICATION, UNTIL THE APPLICATION HAS + // PROCESSED ALL REMAINING TURNS FROM THIS PLAYER. + CONNPTR conn = ConnFindByAddr(event->senderaddr); + if (conn && (conn->playerid != NOPLAYER)) { + conn->flags |= PF_LEAVING; + conn->finalsequence = (WORD)eventdataptr->finalsequence; + conn->exitcode = eventdataptr->exitcode; + } + +} + +//=========================================================================== +static void SysProcessIncomingMessages (CONNPTR conn) { + while ((!conn->incomingqueue[TYPE_SYSTEM].IsEmpty()) && + (conn->incomingqueue[TYPE_SYSTEM].Head()->data->header.sequence + == conn->incomingsequence[TYPE_SYSTEM])) { + MESSAGEPTR message = conn->incomingqueue[TYPE_SYSTEM].Head(); + PACKETPTR pkt = (PACKETPTR)message->data; + TRACEOUT(TRACEHANDLE, + " processing system message: sequence=%04x event=%u player=%x", + pkt->header.sequence,pkt->header.subtype,pkt->header.playerid); + + // SIGNAL THE EVENT + if (pkt->header.subtype < SYSMSGS) + s_sys_event[pkt->header.subtype] = TRUE; + + // CALL INTERNAL THE SYSTEM EVENT HANDLER FOR THIS EVENT TYPE + { + SYSEVENT eventdata; + eventdata.senderplayerid = pkt->header.playerid; + eventdata.senderaddr = message->addr; + eventdata.eventid = pkt->header.subtype; + eventdata.data = pkt->data; + eventdata.databytes = pkt->header.bytes-sizeof(HEADER); + SEvtDispatch(REGISTERTYPE, + REGISTERSUBTYPE_SYSEVENT, + eventdata.eventid, + &eventdata); + } + + // ADJUST THE INCOMING SEQUENCE NUMBER + ++(conn->incomingsequence[TYPE_SYSTEM]); + + // FREE THE MESSAGE DATA + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [system message]", + message->addr,message->data,message->databytes); + s_spi->Free(message->addr,message->data,message->databytes); + + // FREE THE MESSAGE RECORD + conn->incomingqueue[TYPE_SYSTEM].DeleteNode(message); + + } +} + +//=========================================================================== +static void SysQueueUserEvent (DWORD eventid, + DWORD playerid, + LPVOID data, + DWORD databytes) { + USEREVENTPTR userevent = s_sys_usereventlist.NewNode(); + userevent->event.eventid = eventid; + userevent->event.playerid = playerid; + if (data && databytes) { + userevent->event.data = ALLOC(databytes); + CopyMemory(userevent->event.data,data,databytes); + userevent->event.databytes = databytes; + } +} + +//=========================================================================== +static BOOL SysWaitForMultipleEvents (DWORD numevents, + LPDWORD eventlist, + BOOL waitforall, + DWORD timeout) { + + // BLANK OUT THE RECEIVED EVENT ARRAY + ZeroMemory(s_sys_event,SYSMSGS*sizeof(BOOL)); + + // LOOP UNTIL THE CONDITIONS ARE SATISFIED OR THE TIMEOUT HAS ELAPSED + DWORD starttime = GetTickCount(); + BOOL firstiter = TRUE; + do { + + // IF THIS IS NOT THE FIRST ITERATION, SLEEP FOR A CLOCK TICK + if (!firstiter) + Sleep(10); + firstiter = FALSE; + + // PROCESS INCOMING PACKETS + RecvProcessExternalMessages(); + RecvProcessIncomingPackets(); + + // MAINTAIN CONNECTIONS + ConnMaintainConnections(); + + // IF THE CONDITIONS HAVE BEEN SATISFIED, RETURN SUCCESS + { + DWORD signalled = 0; + for (DWORD loop = 0; loop < numevents; ++loop) + if ((*(eventlist+loop) < SYSMSGS) && + s_sys_event[*(eventlist+loop)]) + ++signalled; + if ((signalled >= numevents) || + (signalled && !waitforall)) + return TRUE; + } + + } while ((timeout == INFINITE) || + (GetTickCount()-starttime < timeout)); + + return FALSE; +} + +/**************************************************************************** +* +* RECEIVING THREAD +* +***/ + +static HANDLE s_recv_event = (HANDLE)0; +static BOOL s_recv_shutdown = FALSE; +static HANDLE s_recv_thread = (HANDLE)0; + +static DWORD CALLBACK RecvThreadProc (LPVOID param); + +//=========================================================================== +static void RecvDestroy () { + if (s_recv_event && s_recv_thread) { + s_recv_shutdown = TRUE; + SetEvent(s_recv_event); + WaitForSingleObject(s_recv_thread,INFINITE); + s_recv_shutdown = FALSE; + CloseHandle(s_recv_event); + CloseHandle(s_recv_thread); + s_recv_event = (HANDLE)0; + s_recv_thread = (HANDLE)0; + } +} + +//=========================================================================== +static BOOL RecvInitialize (HANDLE *eventptr) { + + // CREATE THE EVENT + if (!s_recv_event) + s_recv_event = CreateEvent((LPSECURITY_ATTRIBUTES)NULL, + 0, + 0, + NULL); + + // CREATE THE THREAD + if (!s_recv_thread) { + s_recv_shutdown = FALSE; + DWORD threadid; + s_recv_thread = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + RecvThreadProc, + NULL, + 0, + &threadid); + SetThreadPriority(s_recv_thread,THREAD_PRIORITY_HIGHEST); + } + + // RETURN A HANDLE TO THE EVENT + if (eventptr) + *eventptr = s_recv_event; + + return (s_recv_event && s_recv_thread); +} + +//=========================================================================== +static void RecvProcessExternalMessages () { + for (;;) { + LPCSTR senderpath = NULL; + LPCSTR sendername = NULL; + LPCSTR message = NULL; + TRACEOUT(TRACEHANDLE, + " spiReceiveExternalMessage(*senderpath,*sendername,*message)"); + if (!s_spi->ReceiveExternalMessage(&senderpath,&sendername,&message)) + break; + if (!(senderpath && sendername && message)) + break; + + if ((!*senderpath) && (!*sendername)) + SysQueueUserEvent(SNET_EVENT_SERVERMESSAGE, + SNET_BROADCASTPLAYERID, + (LPVOID)message, + SStrLen(message)+1); + + TRACEOUT(TRACEHANDLE, + " spiFreeExternalMessage(0x%08x,0x%08x,0x%08x)", + senderpath,sendername,message); + s_spi->FreeExternalMessage(senderpath,sendername,message); + } +} + +//=========================================================================== +static void RecvProcessIncomingPackets () { + for (;;) { + SNETADDRPTR addr = NULL; + LPVOID data = NULL; + DWORD databytes = 0; + TRACEOUT(TRACEHANDLE," spiReceive(*addr,*data,*databytes)"); +/* note: restore this + if (!s_spi->Receive(&addr,&data,&databytes)) + break; +*/ +if (!s_spi->Receive(&data,&databytes,&addr)) +break; + if (!(addr && data)) + break; + PACKETPTR pkt = (PACKETPTR)data; + + // IF WE ARE IN DEBUG MODE, PRINT TRACE INFO FOR THE MESSAGE +#ifdef TRACING + TRACEOUT(TRACEHANDLE, + " addr=0x%08x data=0x%08x databytes=%u", + addr,data,databytes); + TRACEDUMPADDR(TRACEHANDLE, + "sender", + addr, + (databytes >= sizeof(HEADER)) ? pkt->header.playerid : NOPLAYER); + TRACEDUMP(TRACEHANDLE,&pkt->header,min(databytes,sizeof(HEADER))); + if (databytes > sizeof(HEADER)) + TRACEDUMP(TRACEHANDLE,&pkt->data[0],databytes-sizeof(HEADER)); +#endif + PerfAdd(SNET_PERFID_TOTALBYTESRECV,databytes); + + // FIND THE CONNECTION RECORD FOR THE SENDER OF THIS MESSAGE + CONNPTR local = ConnFindLocal(); + CONNPTR conn = (pkt->header.flags & MF_FORWARDED) + ? ConnFindByPlayerId(pkt->header.playerid) + : ConnFindByAddr(addr); + if (!(conn && local)) { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [no connection]", + addr,data,databytes); + s_spi->Free(addr,data,databytes); + continue; + } + + // CONFIRM THAT THIS IS A VALID MESSAGE. WE PERFORM THE FOLLOWING + // CHECKS: + // - CHECK FOR MINIMUM PACKET SIZE + // - COMPARE LENGTH IN HEADER TO SIZE OF PACKET + // - CHECK FOR VALID MESSAGE TYPE + // - CHECK PLAYER NUMBER + // - COMPUTE CHECKSUM + // - COMPARE SENDER ADDRESS TO ADDRESS OF THE PLAYER NUMBER IN HEADER + if ((databytes < sizeof(HEADER)) || + (databytes < pkt->header.bytes) || + (pkt->header.type >= TYPES) || + PktComputeChecksum(data,pkt->header.bytes)) { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [invalid message: corrupt]", + addr,data,databytes); + s_spi->Free(addr,data,databytes); + continue; + } + if ((!s_game_joining) && + (pkt->header.playerid != NOPLAYER) && + (!(pkt->header.flags & MF_FORWARDED)) && + (ConnFindByPlayerId(pkt->header.playerid) != conn)) { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [invalid message: bad sender]", + addr,data,databytes); + s_spi->Free(addr,data,databytes); + continue; + } + + // IF THIS IS AN INITIAL CONTACT MESSAGE, RESET THE SENDER'S CONNECTION + // RECORD AND INITIATE A CIRCUIT CHECK + if ((pkt->header.type == TYPE_SYSTEM) && + (pkt->header.subtype == SYS_INITIALCONTACT)) { + ConnFree(ConnFindByAddr(addr)); + if ((pkt->header.bytes == sizeof(HEADER)+sizeof(DWORD)) && + (*(LPDWORD)&pkt->data[0] == SNET_NETWORKVERSION)) { + CONNPTR conn = ConnFindByAddr(addr); + if (conn) { + conn->establishing = TRUE; + conn->incomingsequence[TYPE_SYSTEM] = 1; + conn->availablesequence[TYPE_SYSTEM] = 1; + conn->outgoingsequence[TYPE_SYSTEM] = 1; + DWORD networkversion = SNET_NETWORKVERSION; + ConnSendMessage(conn, + TYPE_SYSTEM, + SYS_CIRCUITCHECK, + &networkversion, + sizeof(DWORD)); + } + } + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [initial contact]", + addr,data,databytes); + s_spi->Free(addr,data,databytes); + continue; + } + + // IF THIS MESSAGE WAS NOT FORWARDED THEN RESET THE "LAST HEARD FROM" + // TIME STAMP OF THE PLAYER WHO SENT IT + if (!(pkt->header.flags & MF_FORWARDED)) + conn->lastreceivetime = GetTickCount(); + + // IF THIS MESSAGE CONTAINS A PIGGY-BACKED ACKNOWLEDGEMENT THEN + // FREE MESSAGES THAT WE SENT TO THE OTHER COMPUTER UP TO THE + // ACKNOWLEDGEMENT SEQUENCE + if (!(pkt->header.flags & MF_FORWARDED)) + ConnProcessAck(conn,pkt->header.type,pkt->header.acksequence); + + // IF THIS MESSAGE CONTAINS ONLY AN ACKNOWLEDGEMENT, AND NO ACTUAL + // DATA, THEN FREE IT + if (pkt->header.flags & MF_ACK) { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [ack only]", + addr,data,databytes); + s_spi->Free(addr,data,databytes); + continue; + } + + // IF THIS MESSAGE IS A RESEND REQUEST THEN FIND AND RESEND THE + // REQUESTED MESSAGE + if (pkt->header.flags & MF_RESENDREQUEST) { + MESSAGEPTR currmsg = NULL; + + // PROCESS REQUESTS TO RESEND ONE OF OUR OWN MESSAGES OR TURNS + if ((pkt->header.bytes == sizeof(HEADER)) || + (pkt->data[0] == (s_game_playerid & 0xFF))) + if (pkt->header.type == TYPE_TURN) { + currmsg = local->incomingqueue[TYPE_TURN].Head(); + while (currmsg && (currmsg->data->header.sequence != pkt->header.sequence)) + currmsg = currmsg->Next(); + if (!currmsg) { + currmsg = local->oldturns.Head(); + while (currmsg && (currmsg->data->header.sequence != pkt->header.sequence)) + currmsg = currmsg->Next(); + } + } + else { + currmsg = conn->outgoingqueue[pkt->header.type].Head(); + while (currmsg && (currmsg->data->header.sequence != pkt->header.sequence)) + currmsg = currmsg->Next(); + } + + // PROCESS REQUESTS TO FORWARD A TURN FROM ANOTHER PLAYER + else if (pkt->header.type == TYPE_TURN) { + CONNPTR findconn = ConnFindByPlayerId(pkt->data[0]); + if (findconn) { + currmsg = findconn->incomingqueue[TYPE_TURN].Head(); + while (currmsg && (currmsg->data->header.sequence != pkt->header.sequence)) + currmsg = currmsg->Next(); + if (!currmsg) { + currmsg = findconn->oldturns.Head(); + while (currmsg && (currmsg->data->header.sequence != pkt->header.sequence)) + currmsg = currmsg->Next(); + } + } + if (currmsg) { + currmsg->data->header.checksum = 0; + currmsg->data->header.flags |= MF_FORWARDED; + currmsg->data->header.checksum = PktGenerateChecksum(currmsg->data); + } + } + + // IF WE FOUND THE REQUESTED DATA, RESEND IT + if (currmsg) + ConnResendMessage(conn,currmsg->data,currmsg->databytes); + + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [resend request]", + addr,data,databytes); + s_spi->Free(addr,data,databytes); + continue; + } + + // IF THIS MESSAGE HAS ALREADY BEEN PROCESSED, IGNORE IT AND MARK THIS + // CONNECTION AS REQUIRING ANOTHER EXPLICIT ACK + if (((WORD)(conn->incomingsequence[pkt->header.type]-pkt->header.sequence) > 0) && + ((WORD)(conn->incomingsequence[pkt->header.type]-pkt->header.sequence) < 0x7FFF)) { + if (pkt->header.type != TYPE_TURN) { + conn->acksequence[pkt->header.type] = conn->availablesequence[pkt->header.type]-1; + conn->acktime[pkt->header.type] = GetTickCount(); + } + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [already processed]", + addr,data,databytes); + s_spi->Free(addr,data,databytes); + continue; + } + + // CREATE A MESSAGE RECORD FOR THIS PACKET + MESSAGEPTR message = conn->incomingqueue[pkt->header.type].NewNode(LIST_UNLINKED); + message->addr = addr; + message->data = (PACKETPTR)data; + message->databytes = databytes; + message->sendtime = GetTickCount(); + message->resendtime = message->sendtime+s_spi_timetorequest-s_spi_timetoresend; + PerfAdd(SNET_PERFID_USERBYTESRECV,databytes-sizeof(HEADER)); + + // ADD THE MESSAGE TO THE APPROPRIATE INCOMING QUEUE IN SEQUENCE ORDER + { + MESSAGEPTR curr = conn->incomingqueue[pkt->header.type].Head(); + while (curr && + ((WORD)(pkt->header.sequence-curr->data->header.sequence) > 0) && + ((WORD)(pkt->header.sequence-curr->data->header.sequence) < 0x7FFF)) + curr = curr->Next(); + + // IF WE FOUND ANOTHER PACKET IN THE QUEUE WITH THE SAME SEQUENCE + // NUMBER, FREE THIS PACKET + if (curr && (pkt->header.sequence == curr->data->header.sequence)) { + TRACEOUT(TRACEHANDLE, + " spiFree(0x%08x,0x%08x,%u) [already received]", + addr,data,databytes); + conn->incomingqueue[pkt->header.type].DeleteNode(message); + s_spi->Free(addr,data,databytes); + continue; + } + + // OTHERWISE, LINK THIS PACKET INTO THE QUEUE + else + conn->incomingqueue[pkt->header.type].LinkNode(message,LIST_LINK_BEFORE,curr); + } + + // UPDATE THE AVAILABLE SEQUENCE NUMBER FOR THIS MESSAGE TYPE. + // IF THE AVAILABLE SEQUENCE NUMBER HAS CHANGED AND WE ARE NOT CURRENTLY + // SET TO SEND AN EXPLICIT ACKNOWLEDGEMENT, SET THE EXPLICIT ACK TIMER. + if (pkt->header.type != TYPE_TURN) { + WORD oldavailablesequence = conn->availablesequence[pkt->header.type]; + conn->availablesequence[pkt->header.type] = conn->incomingsequence[pkt->header.type]; + MESSAGEPTR curr = conn->incomingqueue[pkt->header.type].Head(); + while (curr && + (curr->data->header.sequence == conn->availablesequence[pkt->header.type])) { + conn->availablesequence[pkt->header.type]++; + curr = curr->Next(); + } + if ((conn->availablesequence[pkt->header.type] != oldavailablesequence) && + (!conn->acktime[pkt->header.type])) + conn->acktime[pkt->header.type] = GetTickCount(); + } + else { + + // FOR TURNS, WE DON'T ACKNOWLEDGE A TURN FROM ONE CONNECTION UNTIL + // WE HAVE RECEIVED IT FROM ALL CONNECTIONS. THAT WAY, OTHER COMPUTERS + // KEEP OLD TURNS AROUND SO THAT THEY CAN RESEND THEM ON BEHALF OF + // UNRESPONSIVE SYSTEMS. + WORD curravailablesequence = conn->availablesequence[pkt->header.type]; + { + BOOL receivedany; + BOOL receivedall; + do { + receivedany = FALSE; + receivedall = TRUE; + CONNPTR currconn = s_conn_connlist.Head(); + while (currconn) { + if ((currconn->playerid != NOPLAYER) && + ((!(currconn->flags & PF_JOINING)) || + ((LONG)(curravailablesequence-currconn->incomingsequence[TYPE_TURN]) >= 0))) { + MESSAGEPTR currmsg = currconn->incomingqueue[TYPE_TURN].Head(); + while (currmsg && + (currmsg->data->header.sequence != curravailablesequence)) + currmsg = currmsg->Next(); + if (currmsg) + receivedany = TRUE; + else + receivedall = FALSE; + } + currconn = currconn->Next(); + } + if (receivedany && receivedall) + ++curravailablesequence; + } while (receivedany && receivedall); + } + + // IF THE AVAILABLE SEQUENCE FOR TURNS HAS CHANGED, UPDATE ALL + // CONNECTIONS AND MARK EACH AS REQUIRING AN EXPLICIT ACKNOWLEDGEMENT. + { + CONNPTR currconn = s_conn_connlist.Head(); + while (currconn) { + if ((curravailablesequence != currconn->availablesequence[TYPE_TURN]) && + (currconn->playerid != NOPLAYER) && + ((!(currconn->flags & PF_JOINING)) || + ((LONG)(curravailablesequence-currconn->incomingsequence[TYPE_TURN]) >= 0))) { + currconn->availablesequence[TYPE_TURN] = curravailablesequence; + if (!currconn->acktime[TYPE_TURN]) + currconn->acktime[TYPE_TURN] = GetTickCount(); + } + currconn = currconn->Next(); + } + } + + } + + // IF THIS IS A SYSTEM MESSAGE, PROCESS SYSTEM MESSAGES IN ORDER + // FOR THIS CONNECTION + if (pkt->header.type == TYPE_SYSTEM) + SysProcessIncomingMessages(conn); + + } + +} + +//=========================================================================== +static DWORD CALLBACK RecvThreadProc (LPVOID param) { + DWORD wait = INFINITE; + for (;;) { + + // WAIT FOR AT LEAST ONE PACKET TO BE RECEIVED AND QUEUED + if (s_recv_shutdown) { + _endthreadex(0); + return 0; + } + BOOL msgwaiting = (WaitForSingleObject(s_recv_event,wait) == WAIT_OBJECT_0); + if (s_recv_shutdown) { + _endthreadex(0); + return 0; + } + + // ENTER THE API LOCK + s_api_critsect.Enter(); + if (!s_spi) { + s_api_critsect.Leave(); + _endthreadex(0); + return 0; + } + + // PROCESS ALL OUTSTANDING RECEIVED PACKETS + if (msgwaiting) { + TRACEOUT(TRACEHANDLE,"Background thread processing incoming packets:"); + RecvProcessExternalMessages(); + RecvProcessIncomingPackets(); + } + else + TRACEOUT(TRACEHANDLE,"Background thread maintaining connections:"); + + // MAINTAIN CONNECTIONS + wait = ConnMaintainConnections(); + + // LEAVE THE API LOCK + s_api_critsect.Leave(); + TRACEOUT(TRACEHANDLE," done"); + + } +} + +/**************************************************************************** +* +* USER INTERFACE FUNCTIONS +* +***/ + +//=========================================================================== +static PROVIDERINFOPTR UiFindProvider (LPCSTR desc) { + PROVIDERINFOPTR curr = s_spi_providerlist.Head(); + while (curr) + if (!strcmp(curr->desc,desc)) + return curr; + else + curr = curr->Next(); + return NULL; +} + +//=========================================================================== +static void UiGetProgramDescription (LPCSTR programname, + SNETVERSIONDATAPTR versionptr, + LPSTR buffer, + DWORD buffersize) { + + // ADD THE NAME OF THE PROGRAM + SStrCopy(buffer,programname,buffersize-2); + strcat(buffer," "); + + // DETERMINE THE NAME OF THIS PROGRAM'S EXE FILE + char programfilename[MAX_PATH] = ""; + GetModuleFileName((HMODULE)0,programfilename,MAX_PATH); + + // IF WE WERE GIVEN A HUMAN READABLE VERSION STRING, ADD THAT + if (versionptr && versionptr->versionstring && *versionptr->versionstring) + SStrPack(buffer,versionptr->versionstring,buffersize); + + // OTHERWISE, ADD THE HUMAN READABLE VERSION STRING FROM THE EXE FILE'S + // VERSION RESOURCE + else if (programfilename[0]) { + DWORD handle; + DWORD versioninfosize = GetFileVersionInfoSize((char *)programfilename,&handle); + LPVOID versioninfo = ALLOC(versioninfosize); + if (GetFileVersionInfo((char *)programfilename,handle,versioninfosize,versioninfo)) { + LPCTSTR info = NULL; + UINT bytes = 0; + if (VerQueryValueA(versioninfo, + "\\StringFileInfo\\040904b0\\ProductVersion", + (LPVOID *)&info, + &bytes) && + info && *info) + SStrPack(buffer,info,buffersize); + } + FREE(versioninfo); + } + +} + +//=========================================================================== +static BOOL UiLoadArtwork (SNETGETARTPROC artcallback, + DWORD providerid, + DWORD artid, + BOOL setpalette, + LPBYTE *data, + SIZE *size) { + *data = 0; + size->cx = 0; + size->cy = 0; + + // VERIFY THAT THE APPLICATION HAS REGISTERED AN ARTWORK CALLBACK + if (!artcallback) + return FALSE; + + // CALL THE ARTWORK CALLBACK TO DETERMINE THE IMAGE DIMENSIONS + int width; + int height; + int bitdepth; + if (!artcallback(providerid, + artid, + NULL, + NULL, + 0, + &width, + &height, + &bitdepth)) + return FALSE; + if (size) { + size->cx = width; + size->cy = height; + } + + // ALLOCATE MEMORY FOR THE IMAGE + DWORD bytes = width*height*bitdepth/8; + *data = (LPBYTE)ALLOC(bytes); + + // LOAD THE IMAGE + PALETTEENTRY pe[256]; + if (!artcallback(providerid, + artid, + &pe[0], + *data, + bytes, + &width, + &height, + &bitdepth)) { + FREE(*data); + *data = NULL; + return FALSE; + } + + // IF REQUESTED, UPDATE THE SYSTEM PALETTE + if (setpalette) + SDrawUpdatePalette(1,254,&pe[1]); + + return TRUE; +} + +//=========================================================================== +static BOOL CALLBACK UiSelectProviderDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + static LPBYTE background = NULL; + static LPBYTE buttontexture = NULL; + static UIPARAMSPTR uiparams = NULL; + switch (message) { + + case WM_COMMAND: + + // IF THE USER CLICKED THE CANCEL BUTTON, RETURN ZERO + if (LOWORD(wparam) == IDCANCEL) + SDlgEndDialog(window,0); + + // IF THE USER CLICKED THE CONNECT BUTTON, INITIALIZE THE SELECTED + // PROVIDER AND RETURNS ITS PROVIDER ID + else if (LOWORD(wparam) == IDOK) { + char buffer[256] = ""; + int cursel = SendDlgItemMessage(window,IDC_PROVIDERLIST,LB_GETCURSEL,0,0); + SendDlgItemMessageA(window,IDC_PROVIDERLIST,LB_GETTEXT,cursel,(LPARAM)(LPSTR)buffer); + PROVIDERINFOPTR ptr = UiFindProvider(buffer); + if (ptr) { + + // SAVE THIS AS THE NEW PREFERRED PROVIDER + SRegSaveValue("Network Providers","Preferred Provider",0,ptr->id); + + // BUILD A NEW INTERFACE DATA STRUCTURE CONTAINING OUR WINDOW + // HANDLE + SNETUIDATA interfacedata; + ZeroMemory(&interfacedata,sizeof(SNETUIDATA)); + if (uiparams->interfacedata) + CopyMemory(&interfacedata,uiparams->interfacedata,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = window; + + // CALL THE SELECTED CALLBACK IF AVAILABLE + if (uiparams->interfacedata && uiparams->interfacedata->selectedcallback) + if (!uiparams->interfacedata->selectedcallback(ptr->id, + &ptr->caps, + &interfacedata, + uiparams->versiondata)) + break; + + // INITIALIZE THE PROVIDER + if (SNetInitializeProvider(ptr->id, + uiparams->programdata, + uiparams->playerdata, + &interfacedata, + uiparams->versiondata)) + SDlgEndDialog(window,ptr->id); + + } + } + + // IF THE USER HIGHLIGHTED A NEW LISTBOX ITEM, UPDATE + // THE STATIC TEXT. IF THE USER DOUBLE-CLICKED AN ITEM, + // POST AN 'OK' COMMAND. + else if (LOWORD(wparam) == IDC_PROVIDERLIST) + if (HIWORD(wparam) == LBN_SELCHANGE) + PostMessage(window,WM_USER,0,0); + else if (HIWORD(wparam) == LBN_DBLCLK) + PostMessage(window,WM_COMMAND,MAKELONG(IDOK,BN_CLICKED),(LPARAM)GetDlgItem(window,IDOK)); + + break; + + case WM_DESTROY: + if (background) { + FREE(background); + background = NULL; + } + if (buttontexture) { + FREE(buttontexture); + buttontexture = NULL; + } + break; + + case WM_INITDIALOG: + + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + uiparams = (UIPARAMSPTR)lparam; + + // LOAD THE ARTWORK FOR THIS DIALOG + { + SIZE size; + if (UiLoadArtwork(uiparams->interfacedata->artcallback, + 0, + SNET_ART_BACKGROUND, + 1, + &background, + &size)) { + SDlgSetBitmap(window, + NULL, + "", + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + background, + NULL, + size.cx, + size.cy); + int controllist[3] = {IDC_MAXPLAYERS,IDC_REQUIREMENTS,0}; + SDlgSetControlBitmaps(window, + &controllist[0], + NULL, + background, + &size, + SDLG_ADJUST_CONTROLPOS); + } + if (UiLoadArtwork(uiparams->interfacedata->artcallback, + 0, + SNET_ART_BUTTONTEXTURE, + 0, + &buttontexture, + &size)) { + int controllist[3] = {IDOK,IDCANCEL,0}; + SDlgSetControlBitmaps(window, + &controllist[0], + NULL, + buttontexture, + &size, + SDLG_ADJUST_VERTICAL); + } + } + + // FILL IN THE LIST BOX WITH THE LIST OF PROVIDERS + { + DWORD selectid = 0; + PROVIDERINFOPTR selectptr = NULL; + PROVIDERINFOPTR curr = s_spi_providerlist.Head(); + SRegLoadValue("Network Providers","Preferred Provider",0,&selectid); + while (curr) { + if (curr->id && + SpiMeetsMinimumCaps(&curr->caps,uiparams->mincaps)) { + SendDlgItemMessageA(window,IDC_PROVIDERLIST,LB_ADDSTRING,0,(LPARAM)(LPCSTR)curr->desc); + if (curr->id == selectid) + selectptr = curr; + } + curr = curr->Next(); + } + WPARAM selectindex = 0; + if (selectptr) + selectindex = (WPARAM)SendDlgItemMessage(window,IDC_PROVIDERLIST,LB_FINDSTRINGEXACT,(WPARAM)-1,(LPARAM)selectptr->desc); + SendDlgItemMessage(window,IDC_PROVIDERLIST,LB_SETCURSEL,selectindex,0); + } + + // FILL IN THE PROGRAM DESCRIPTION + { + char buffer[256] = ""; + UiGetProgramDescription(uiparams->programdata->programname, + uiparams->versiondata, + buffer, + 256); + SetDlgItemTextA(window,IDC_PROGRAMDESCRIPTION,buffer); + } + + // UPDATE THE PLAYERS SUPPORTED AND REQUIREMENTS TEXT + PostMessage(window,WM_USER,0,0); + + return 1; + + case WM_USER: + { + + // FIND THE HIGHLIGHTED PROVIDER + char buffer[256] = ""; + int cursel = SendDlgItemMessage(window,IDC_PROVIDERLIST,LB_GETCURSEL,0,0); + SendDlgItemMessageA(window,IDC_PROVIDERLIST,LB_GETTEXT,cursel,(LPARAM)(LPSTR)buffer); + PROVIDERINFOPTR ptr = UiFindProvider(buffer); + if (!ptr) + break; + + // DISPLAY THE MAXIMUM NUMBER OF PLAYERS + { + char buffer[64]; + GetDlgItemTextA(window,IDC_MAXPLAYERS,buffer,63); + if (SStrChr(buffer,':')) + wsprintf(SStrChr(buffer,':')+1, + " %u", + min(uiparams->programdata->maxplayers,ptr->caps.maxplayers)); + SetDlgItemTextA(window,IDC_MAXPLAYERS,buffer); + } + + // DISPLAY THE REQUIREMENTS + { + char buffer[256]; + GetDlgItemTextA(window,IDC_REQUIREMENTS,buffer,255); + if (SStrChr(buffer,':')) + wsprintf(SStrChr(buffer,':')+1, + "\n%s", + ptr->req); + SetDlgItemTextA(window,IDC_REQUIREMENTS,buffer); + } + + } + break; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +#define ENTER_APILOCK_READ s_api_critsect.Enter() +#define ENTER_APILOCK_WRITE s_api_critsect.Enter() +#define FAILOUT_APILOCK_READ do { \ + TRACEOUT(TRACEHANDLE, \ + " [fail: %08x]", \ + SErrGetLastError()); \ + s_api_critsect.Leave(); \ + return FALSE; \ + } while (FALSE) +#define FAILOUT_APILOCK_WRITE do { \ + TRACEOUT(TRACEHANDLE, \ + " [fail: %08x]", \ + SErrGetLastError()); \ + s_api_critsect.Leave(); \ + return FALSE; \ + } while (FALSE) +#define LEAVE_APILOCK_READ s_api_critsect.Leave() +#define LEAVE_APILOCK_WRITE s_api_critsect.Leave() + +//=========================================================================== +BOOL APIENTRY SNetCreateGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamecategorybits, + LPVOID initdata, + DWORD initdatabytes, + DWORD maxplayers, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid) { + + // VALIDATE PARAMETERS + if (playerid) + *playerid = SNET_INVALIDPLAYERID+s_api_playeroffset; + + VALIDATEBEGIN; + VALIDATE(gamename); + VALIDATE(*gamename); + VALIDATE(maxplayers); + VALIDATE(playerid); + VALIDATEEND; + + // LOG THE CALL + ENTER_APILOCK_WRITE; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if (!gamepassword) + gamepassword = ""; + if (!gamedescription) + gamedescription = ""; + if (!playername) + playername = ""; + if (!playerdescription) + playerdescription = ""; + TRACEOUT(TRACEHANDLE, + "SNetCreateGame(\"%s\",\"%s\",\"%s\",0x%08x,0x%08x,%u,%u,\"%s\",\"%s\",*playerid)", + gamename,gamepassword,gamedescription,gamecategorybits,initdata,initdatabytes,maxplayers,playername,playerdescription); + + // IF NO PLAYER NAME WAS PROVIDED, AND THE CURRENT NETWORK PROVIDER + // IS CAPABLE OF PROVIDING IT, THEN GET THE NAME OF THE LOGGED ON + // USER FROM THE NETWORK PROVIDER + char localplayername[SNETSPI_MAXSTRINGLENGTH] = ""; + char localplayerdesc[SNETSPI_MAXSTRINGLENGTH] = ""; + if ((!*playername) && s_spi->GetLocalPlayerName) { + s_spi->GetLocalPlayerName(localplayername, + SNETSPI_MAXSTRINGLENGTH, + localplayerdesc, + SNETSPI_MAXSTRINGLENGTH); + playername = localplayername; + playerdescription = localplayerdesc; + } + if (!*playername) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + return FALSE; + } + + // IF WE ARE ALREADY IN A GAME, LEAVE IT + if (s_game_playerid != NOPLAYER) + SNetLeaveGame(SNET_EXIT_AUTO_NEWGAME); + + // RESET THE CONNECTION TABLE + ConnDestroy(); + + // SET THE MAXIMUM NUMBER OF PLAYERS ALLOWED + s_game_playersallowed = maxplayers; + + // SAVE THE GAME NAME AND DESCRIPTION + SStrCopy(s_game_gamename,gamename,SNETSPI_MAXSTRINGLENGTH); + SStrCopy(s_game_gamedesc,gamedescription,SNETSPI_MAXSTRINGLENGTH); + SStrCopy(s_game_gamepass,gamepassword,SNETSPI_MAXSTRINGLENGTH); + s_game_creationtime = GetTickCount(); + s_game_categorybits = gamecategorybits; + + // SET THE GAME MODE + s_game_gamemode = 0; + if (*gamepassword) + s_game_gamemode |= SNET_GM_PRIVATE; + if (s_game_playersallowed <= 1) + s_game_gamemode |= SNET_GM_FULL; + + // SAVE THE INITIALIZATION DATA + if (s_game_initdata) + FREE(s_game_initdata); + s_game_initdata = ALLOC(initdatabytes); + s_game_initdatabytes = initdatabytes; + CopyMemory(s_game_initdata,initdata,initdatabytes); + + // ASSIGN THE LOCAL PLAYER A PLAYER ID, AND MARK HIM AS THE GAME OWNER + s_game_playerid = 0; + CONNPTR conn = ConnFindLocal(); + if (conn) { + conn->flags = 0; + conn->playerid = s_game_playerid; + conn->gameowner = TRUE; + SStrCopy(conn->name,playername ,SNETSPI_MAXSTRINGLENGTH); + SStrCopy(conn->desc,playerdescription,SNETSPI_MAXSTRINGLENGTH); + } + if (playerid) + *playerid = s_game_playerid+s_api_playeroffset; + + // BUILD THE CLIENT DATA BLOCK + BYTE clientdata[SNETSPI_MAXCLIENTDATA]; + DWORD clientdatabytes; + GameBuildClientData(clientdata, + &clientdatabytes); + + // START ADVERTISING THE GAME SO THAT OTHERS CAN JOIN IT + TRACEOUT(TRACEHANDLE, + " spiStartAdvertisingGame(\"%s\",\"%s\",\"%s\",%u,%u,0x%08x,0x%08x,0x%08x,%u)", + s_game_gamename, + s_game_gamepass, + s_game_gamedesc, + s_game_gamemode, + 0, + s_game_categorybits, + s_game_optcategorybits, + clientdata, + clientdatabytes); + if (!s_spi->StartAdvertisingGame(s_game_gamename, + s_game_gamepass, + s_game_gamedesc, + s_game_gamemode, + 0, + s_game_categorybits, + s_game_optcategorybits, + clientdata, + clientdatabytes)) { + // SERVICE PROVIDER IS RESPONSIBLE FOR CALLING SETLASTERROR() + DWORD lasterror = SErrGetLastError(); + SNetLeaveGame(SNET_EXIT_AUTO_JOINING); + SErrSetLastError(lasterror); + FAILOUT_APILOCK_WRITE; + } + + // MARK THE GAME AS ADVERTISED + s_game_gamemode |= SNET_GM_ADVERTISED; + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetDestroy () { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE,"SNetDestroy()"); + + // IF WE ARE IN A GAME, LEAVE IT + if (s_game_playerid != NOPLAYER) + SNetLeaveGame(SNET_EXIT_AUTO_SHUTDOWN); + + // TERMINATE THE RECEIVE THREAD + LEAVE_APILOCK_WRITE; + RecvDestroy(); + ENTER_APILOCK_WRITE; + + // REMOVE ALL MESSAGES FROM THE SYSTEM MESSAGE QUEUE + SysDestroy(); + + // UNREGISTER ALL EVENT HANDLERS + SEvtUnregisterType(REGISTERTYPE,REGISTERSUBTYPE_SNETEVENT); + SEvtUnregisterType(REGISTERTYPE,REGISTERSUBTYPE_SYSEVENT); + + // DESTROY ALL CONNECTIONS + ConnDestroy(); + + // UNBIND FROM THE SERVICE PROVIDER AND CLEAR THE PROVIDER LIST + SpiDestroy(TRUE); + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetDropPlayer (DWORD playerid, DWORD exitcode) { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetDropPlayer(%u,0x%08x)", + playerid,exitcode); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if ((playerid == NOPLAYER) || + (playerid == s_game_playerid)) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + FAILOUT_APILOCK_WRITE; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + + // FIND THE REFERENCED PLAYER + CONNPTR conn = ConnFindByPlayerId(playerid); + if (!conn) { + SErrSetLastError(SNET_ERROR_INVALID_PLAYER); + FAILOUT_APILOCK_WRITE; + } + + // MARK THE PLAYER AS LEAVING + conn->flags |= PF_LEAVING; + conn->finalsequence = conn->incomingsequence[TYPE_TURN]; + conn->exitcode = exitcode; + + // SEND A DROP PLAYER MESSAGE TO ALL OTHER PLAYERS + { + CONNPTR checkconn = s_conn_connlist.Head(); + while (checkconn) { + if ((checkconn != conn) && + (checkconn->playerid != NOPLAYER)) { + SYSEVENTDATA_DROPPLAYER eventdata; + eventdata.playerid = playerid; + eventdata.finalsequence = conn->incomingsequence[TYPE_TURN]; + eventdata.exitcode = exitcode; + ConnSendMessage(checkconn, + TYPE_SYSTEM, + SYS_DROPPLAYER, + &eventdata, + sizeof(SYSEVENTDATA_DROPPLAYER)); + } + checkconn = checkconn->Next(); + } + } + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetEnumDevices (SNETENUMDEVICESPROC callback) { + VALIDATEBEGIN; + VALIDATE(callback); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetEnumDevices(0x%08x)", + callback); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + + // MAKE A LOCAL COPY OF ALL DEVICES + SNETSPI_DEVICELISTPTR devicearray = NULL; + DWORD devices = 0; + { + + // LOCK THE DEVICE LIST + SNETSPI_DEVICELISTPTR head; + TRACEOUT(TRACEHANDLE," spiLockDeviceList(*devicelist)"); + if (!s_spi->LockDeviceList(&head)) { + // SERVICE PROVIDER IS RESPONSIBLE FOR CALLING SETLASTERROR() + FAILOUT_APILOCK_READ; + } + + // DETERMINE THE TOTAL NUMBER OF DEVICES + { + SNETSPI_DEVICELISTPTR curr = head; + while (curr) { + ++devices; + curr = curr->next; + } + } + + // ALLOCATE AN ARRAY TO HOLD THE DEVICES + if (devices) { + devicearray = (SNETSPI_DEVICELISTPTR)ALLOC(devices*sizeof(SNETSPI_DEVICELIST)); + + // COPY THE DEVICES + SNETSPI_DEVICELISTPTR source = head; + SNETSPI_DEVICELISTPTR dest = devicearray; + while (source) { + CopyMemory(dest,source,sizeof(SNETSPI_DEVICELIST)); + dest->next = dest+1; + dest = dest->next; + source = source->next; + } + + } + + // UNLOCK THE DEVICE LIST + TRACEOUT(TRACEHANDLE, + " spiUnlockDeviceList(0x%08x)", + head); + s_spi->UnlockDeviceList(head); + + } + + // LEAVE THE API LOCK + LEAVE_APILOCK_READ; + + // IF THERE WERE NO DEVICES, RETURN NOW + if (!(devices && devicearray)) + return TRUE; + + // CALL THE ENUMERATION FUNCTION ONCE FOR EACH DEVICE + { + SNETSPI_DEVICELISTPTR curr = devicearray; + while (devices--) { + TRACEOUT(TRACEHANDLE, + " callback(0x%08x,\"%s\",\"%s\")", + curr->deviceid,curr->devicename,curr->devicedescription); + if (callback(curr->deviceid,curr->devicename,curr->devicedescription)) + curr = curr->next; + else + devices = 0; + } + } + + // FREE THE LOCAL COPY + FREE(devicearray); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetEnumGames (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESPROC callback, + DWORD *hintnextcall) { + VALIDATEBEGIN; + VALIDATE(callback); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetEnumGames(0x%08x,0x%08x,0x%08x,*hintnextcall)", + categorybits,categorymask,callback); + + // VALIDATE PARAMETERS + if (hintnextcall) + *hintnextcall = 0; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + + // MAKE A LOCAL COPY OF ALL MATCHING GAMES + SNETSPI_GAMELISTPTR gamearray = NULL; + DWORD games = 0; + GameCopyGameList(categorybits, + categorymask, + &gamearray, + &games, + hintnextcall); + + // LEAVE THE API LOCK + LEAVE_APILOCK_READ; + + // CALL THE ENUMERATION FUNCTION ONCE FOR EACH GAME + { + SNETSPI_GAMELISTPTR curr = gamearray; + while (games--) { + TRACEOUT(TRACEHANDLE, + " callback(0x%08x,\"%s\",\"%s\")", + curr->gameid,curr->gamename,curr->gamedescription); + TRACEDUMP(TRACEHANDLE,&curr->owner,sizeof(SNETADDR)); + if (callback(curr->gameid,curr->gamename,curr->gamedescription)) + curr = curr->next; + else + games = 0; + } + } + + // FREE THE LOCAL COPY + FREEIFUSED(gamearray); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetEnumGamesEx (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESEXPROC callback, + DWORD *hintnextcall) { + VALIDATEBEGIN; + VALIDATE(callback); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetEnumGamesEx(0x%08x,0x%08x,0x%08x,*hintnextcall)", + categorybits,categorymask,callback); + + // VALIDATE PARAMETERS + if (hintnextcall) + *hintnextcall = 0; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + + // MAKE A LOCAL COPY OF ALL MATCHING GAMES + SNETSPI_GAMELISTPTR gamearray = NULL; + DWORD games = 0; + GameCopyGameList(categorybits, + categorymask, + &gamearray, + &games, + hintnextcall); + + // LEAVE THE API LOCK + LEAVE_APILOCK_READ; + + // CALL THE ENUMERATION FUNCTION ONCE FOR EACH GAME + { + SNETSPI_GAMELISTPTR curr = gamearray; + SNETGAME gamedata; + while (games--) { + GameBuildGameData(&gamedata,curr); + TRACEOUT(TRACEHANDLE, + " callback(0x%08x)", + &gamedata); + TRACEDUMP(TRACEHANDLE,&curr->owner,sizeof(SNETADDR)); + if (callback(&gamedata)) + curr = curr->next; + else + games = 0; + } + } + + // FREE THE LOCAL COPY + FREEIFUSED(gamearray); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetEnumProviders (SNETCAPSPTR mincaps, + SNETENUMPROVIDERSPROC callback) { + VALIDATEBEGIN; + VALIDATE(callback); + VALIDATE((!mincaps) || (mincaps->size == sizeof(SNETCAPS))); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetEnumProviders(mincaps,0x%08x)", + callback); + + // BUILD A LIST OF PROVIDERS IF WE DON'T ALREADY HAVE ONE + SpiFindAllProviders(); + + // CALL THE CALLBACK FUNCTION ONCE FOR EACH PROVIDER IN THE LIST + // WHICH MEETS THE MINIMUM CAPABILITIES + PROVIDERINFOPTR curr = s_spi_providerlist.Head(); + while (curr) { + if (curr->id && curr->desc && *curr->desc && + SpiMeetsMinimumCaps(&curr->caps,mincaps)) { + TRACEOUT(TRACEHANDLE, + " callback(0x%08x,\"%s\",\"%s\",caps)", + curr->id,curr->desc,curr->req); + if (!callback(curr->id,curr->desc,curr->req,&curr->caps)) + curr = NULL; + } + if (s_spi_providersfound && (!s_spi_providerlist.IsEmpty()) && curr) + curr = curr->Next(); + else + curr = NULL; + } + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetGameInfo (DWORD index, + LPVOID buffer, + DWORD buffersize, + DWORD *byteswritten) { + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetGetGameInfo(%u,0x%08x,%u,*byteswritten)", + index,buffer,buffersize); + + // VALIDATE PARAMETERS + if (buffer && buffersize) + ZeroMemory(buffer,buffersize); + if (byteswritten) + *byteswritten = NULL; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_READ; + } + + // FIND THE REQUESTED INFORMATION + LPVOID info = NULL; + DWORD infobytes = 0; + BOOL nullterm = FALSE; + switch (index) { + + case SNET_INFO_GAMENAME: + info = s_game_gamename; + infobytes = SStrLen(s_game_gamename)+1; + nullterm = TRUE; + break; + + case SNET_INFO_GAMEPASSWORD: + info = s_game_gamepass; + infobytes = SStrLen(s_game_gamepass)+1; + nullterm = TRUE; + break; + + case SNET_INFO_GAMEDESCRIPTION: + info = s_game_gamedesc; + infobytes = SStrLen(s_game_gamedesc)+1; + nullterm = TRUE; + break; + + case SNET_INFO_GAMEMODE: + info = &s_game_gamemode; + infobytes = sizeof(s_game_gamemode); + break; + + case SNET_INFO_INITDATA: + info = s_game_initdata; + infobytes = s_game_initdatabytes; + break; + + case SNET_INFO_MAXPLAYERS: + info = &s_game_playersallowed; + infobytes = sizeof(s_game_playersallowed); + break; + + } + if (!info) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + FAILOUT_APILOCK_READ; + } + + // IF THE USER DIDN'T PASS A BUFFER, SIMPLY RETURN THE NUMBER OF BYTES + // OF INFORMATION WE HAVE AVAILABLE + if (!(buffer && buffersize)) { + if (byteswritten) + *byteswritten = infobytes; + } + + // OTHERWISE, COPY THE INFORMATION INTO THE USER'S BUFFER + else { + CopyMemory(buffer,info,min(buffersize,infobytes)); + if (byteswritten) + *byteswritten = min(buffersize,infobytes); + if (nullterm) + *((LPSTR)buffer+buffersize-1) = 0; + } + + LEAVE_APILOCK_READ; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetNetworkLatency (DWORD measurementtype, + DWORD *result) { + VALIDATEBEGIN; + VALIDATE(result); + VALIDATE(measurementtype >= SNET_LMT_EXPECTED); + VALIDATE(measurementtype <= SNET_LMT_PEAK); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetGetNetworkLatency(%u,*result)", + measurementtype); + + // VALIDATE PARAMETERS + if (result) + *result = 0; + if (!(s_spi && s_spi_providerptr)) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + + // RETURN THE LATENCY + switch (measurementtype) { + + case SNET_LMT_EXPECTED: + *result = s_spi_providerptr->caps.latencyms; + break; + + case SNET_LMT_CURRENT: + case SNET_LMT_PEAK: + { + CONNPTR conn = s_conn_connlist.Head(); + while (conn) { + if (conn->playerid != NOPLAYER) { + DWORD latency = 0; + if (measurementtype == SNET_LMT_CURRENT) + latency = conn->peaklatency; + if (latency < conn->latency) + latency = conn->latency; + if (latency > *result) + *result = latency; + } + conn = conn->Next(); + } + } + break; + + default: + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + FAILOUT_APILOCK_READ; + + } + + LEAVE_APILOCK_READ; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetNumPlayers (DWORD *firstplayerid, + DWORD *lastplayerid, + DWORD *activeplayers) { + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetGetNumPlayers(*firstplayerid,*lastplayerid,*activeplayers)"); + + // VALIDATE PARAMETERS + if (firstplayerid) + *firstplayerid = SNET_INVALIDPLAYERID+s_api_playeroffset; + if (lastplayerid) + *lastplayerid = SNET_INVALIDPLAYERID+s_api_playeroffset; + if (activeplayers) + *activeplayers = 0; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_READ; + } + + // START WITH THE LOCAL PLAYER + if (firstplayerid) + *firstplayerid = s_game_playerid+s_api_playeroffset; + if (lastplayerid) + *lastplayerid = s_game_playerid+s_api_playeroffset; + if (activeplayers) + *activeplayers = 1; + + // TAKE INTO ACCOUNT ALL OTHER ACTIVE PLAYERS + { + CONNPTR conn = s_conn_connlist.Head(); + while (conn) { + if (conn->playerid != NOPLAYER) { + if (firstplayerid) + *firstplayerid = min(conn->playerid+s_api_playeroffset,*firstplayerid); + if (lastplayerid) + *lastplayerid = max(conn->playerid+s_api_playeroffset,*lastplayerid); + if (activeplayers) + ++*activeplayers; + } + conn = conn->Next(); + } + } + + // LOG THE RETURNED INFORMATION + if (firstplayerid) + TRACEOUT(TRACEHANDLE," firstplayerid=%u",*firstplayerid); + if (lastplayerid) + TRACEOUT(TRACEHANDLE," lastplayerid=%u",*lastplayerid); + if (activeplayers) + TRACEOUT(TRACEHANDLE," activeplayers=%u",*activeplayers); + + LEAVE_APILOCK_READ; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetOwnerId (DWORD *playerid) { + VALIDATEBEGIN; + VALIDATE(playerid); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEPEND(TRACEHANDLE,"SNetGetOwnerId(*playerid)"); + + // VALIDATE PARAMETERS + *playerid = SNET_INVALIDPLAYERID+s_api_playeroffset; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + + // CHECK FOR TRANSFER OF OWNERSHIP + if (s_game_playerid != NOPLAYER) + GameProcessLeavingPlayers(); + + // FIND THE GAME OWNER + CONNPTR local = ConnFindLocal(); + if (!local) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + CONNPTR conn = local; + if (!(conn && conn->gameowner)) { + conn = s_conn_connlist.Head(); + while (conn && !conn->gameowner) + conn = conn->Next(); + } + if (!(conn && conn->gameowner)) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + + // RETURN THE GAME OWNER'S PLAYER ID + *playerid = conn->playerid+s_api_playeroffset; + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetOwnerTurnsWaiting (DWORD *turns) { + VALIDATEBEGIN; + VALIDATE(turns); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEPEND(TRACEHANDLE,"SNetGetOwnerTurnsWaiting(*turns)"); + *turns = 0; + + // GET THE PLAYER ID OF THE GAME OWNER + DWORD playerid; + if (!SNetGetOwnerId(&playerid)) { + // SNETGETOWNERID() IS RESPONSIBLE FOR CALLING SETLASTERROR() + FAILOUT_APILOCK_WRITE; + } + playerid -= s_api_playeroffset; + + // FIND THE CONNECTION RECORD ASSOCIATED WITH THE GAME OWNER + CONNPTR conn = ConnFindByPlayerId(playerid); + if (!(conn && conn->gameowner)) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + + // CLEAR OUT ANY UNNEEDED OR ALREADY PROCESSED TURNS FROM THE GAME OWNER + ConnClearOldTurns(conn); + + // DETERMINE THE NUMBER OF TURNS WE STILL HAVE QUEUED FROM THE GAME OWNER + MESSAGEPTR message = conn->incomingqueue[TYPE_TURN].Head(); + while (message) { + ++*turns; + message = message->Next(); + } + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetPerformanceData (DWORD counterid, + DWORD *countervalue, + DWORD *countertype, + LONG *counterscale, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq) { + VALIDATEBEGIN; + VALIDATE(counterid); + VALIDATE(counterid < SNET_PERFIDNUM); + VALIDATE(countervalue); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetGetPerformanceData(%u,*countervalue,*countertype,*counterscale,*measurementtime,*measurementfreq)", + counterid); + + // SET THE VALUES BASED ON OUR INTERNAL PERFORMANCE DATA + *countervalue = s_perf_data[counterid].value; + if (countertype) + *countertype = s_perf_data[counterid].type; + if (counterscale) + *counterscale = s_perf_data[counterid].scale; + if (measurementtime) { + SYSTEMTIME systime; + GetSystemTime(&systime); + SystemTimeToFileTime(&systime,(FILETIME *)measurementtime); + } + if (measurementfreq) { + measurementfreq->LowPart = 10000000; + measurementfreq->HighPart = 0; + } + + // IF THIS COUNTER IS PROVIDER SPECIFIC, ALLOW THE CURRENT PROVIDER TO + // OVERWRITE OUR RESULTS + if (s_perf_data[counterid].providerspecific && s_spi) { + LARGE_INTEGER localtime; + LARGE_INTEGER localfreq; + if (!measurementtime) + measurementtime = &localtime; + if (!measurementfreq) + measurementfreq = &localfreq; + TRACEOUT(TRACEHANDLE, + " spiGetPerformanceData(%u,*countervalue,*measurementtime,*measurementfreq)", + counterid); + s_spi->GetPerformanceData(counterid,countervalue,measurementtime,measurementfreq); + } + + LEAVE_APILOCK_READ; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetPlayerCaps (DWORD playerid, + SNETCAPSPTR caps) { + VALIDATEBEGIN; + VALIDATE(caps); + VALIDATE(caps->size == sizeof(SNETCAPS)); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetGetPlayerCaps(%u,*caps)", + playerid); + + // VALIDATE PARAMETERS + ZeroMemory(((LPDWORD)caps)+1,sizeof(SNETCAPS)-sizeof(DWORD)); + if (!(s_spi && s_spi_providerptr)) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_READ; + } + + // FIND THE REQUESTED PLAYER + CONNPTR conn = ConnFindByPlayerId(playerid-s_api_playeroffset); + if (!conn) { + SErrSetLastError(SNET_ERROR_INVALID_PLAYER); + FAILOUT_APILOCK_READ; + } + + // COPY THE PROVIDER CAPS + CopyMemory(caps,&s_spi_providerptr->caps,sizeof(SNETCAPS)); + + // ADD THE USER'S LATENCY + if (conn->latency) + caps->latencyms = conn->latency; + + LEAVE_APILOCK_READ; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetPlayerName (DWORD playerid, + LPSTR buffer, + DWORD buffersize) { + VALIDATEBEGIN; + VALIDATE(buffer); + VALIDATE(buffersize); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetGetPlayerName(%u,0x%08x,%u)", + playerid,buffer,buffersize); + + // VALIDATE PARAMETERS + *buffer = 0; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_READ; + } + + // FIND THE REQUESTED PLAYER + CONNPTR conn = ConnFindByPlayerId(playerid-s_api_playeroffset); + if ((!conn) || (conn->flags & PF_JOINING)) { + SErrSetLastError(SNET_ERROR_INVALID_PLAYER); + FAILOUT_APILOCK_READ; + } + + // RETURN THE PLAYER'S NAME + SStrCopy(buffer,conn->name,buffersize); + + LEAVE_APILOCK_READ; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetProviderCaps (SNETCAPSPTR caps) { + VALIDATEBEGIN; + VALIDATE(caps); + VALIDATE(caps->size == sizeof(SNETCAPS)); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEOUT(TRACEHANDLE, + "SNetGetProviderCaps(*caps)"); + + // VALIDATE PARAMETERS + ZeroMemory(((LPDWORD)caps)+1,sizeof(SNETCAPS)-sizeof(DWORD)); + if (!(s_spi && s_spi_providerptr)) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + + // COPY THE PROVIDER CAPS + CopyMemory(caps,&s_spi_providerptr->caps,sizeof(SNETCAPS)); + + LEAVE_APILOCK_READ; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetGetTurnsInTransit (DWORD *turns) { + VALIDATEBEGIN; + VALIDATE(turns); + VALIDATEEND; + + ENTER_APILOCK_READ; + TRACEPEND(TRACEHANDLE,"SNetGetTurnsInTransit(*turns)"); + + // VALIDATE PARAMETERS + *turns = 0; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_READ; + } + + // FIND OUR PLAYER RECORD + CONNPTR conn = ConnFindLocal(); + if (!conn) { + SErrSetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + FAILOUT_APILOCK_READ; + } + + // DETERMINE THE NUMBER OF TURNS WE HAVE SENT OUT BEYOND WHAT WE HAVE + // PROCESSED + *turns = conn->outgoingsequence[TYPE_TURN] + -conn->incomingsequence[TYPE_TURN]; + + LEAVE_APILOCK_READ; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetInitializeDevice(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x)", + deviceid,programdata,playerdata,interfacedata,versiondata); + TRACEDUMPDATABLOCKS(TRACEHANDLE, + programdata,playerdata,interfacedata,versiondata); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_READ; + } + SNETPROGRAMDATA modprogramdata; + SNETPLAYERDATA modplayerdata; + SNETUIDATA modinterfacedata; + SNETVERSIONDATA modversiondata; + if (!SpiNormalizeDataBlocks(programdata,playerdata,interfacedata,versiondata, + &modprogramdata,&modplayerdata,&modinterfacedata,&modversiondata)) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + FAILOUT_APILOCK_WRITE; + } + + // INITIALIZE THE DEVICE + if (!s_spi->InitializeDevice(deviceid, + &modprogramdata, + &modplayerdata, + &modinterfacedata, + &modversiondata)) { + // SERVICE PROVIDER IS RESPONSIBLE FOR CALLING SETLASTERROR() + FAILOUT_APILOCK_WRITE; + } + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetInitializeProvider (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "(using Storm build " __DATE__ " " __TIME__ ")"); + TRACEOUT(TRACEHANDLE, + "SNetInitializeProvider(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x)", + providerid,programdata,playerdata,interfacedata,versiondata); + TRACEDUMPDATABLOCKS(TRACEHANDLE, + programdata,playerdata,interfacedata,versiondata); + + // VALIDATE PARAMETERS + SNETPROGRAMDATA modprogramdata; + SNETPLAYERDATA modplayerdata; + SNETUIDATA modinterfacedata; + SNETVERSIONDATA modversiondata; + if (!SpiNormalizeDataBlocks(programdata,playerdata,interfacedata,versiondata, + &modprogramdata,&modplayerdata,&modinterfacedata,&modversiondata)) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + FAILOUT_APILOCK_WRITE; + } + + // UNREGISTER ALL EXISTING EVENT HANDLERS + SEvtUnregisterType(REGISTERTYPE,REGISTERSUBTYPE_SNETEVENT); + SEvtUnregisterType(REGISTERTYPE,REGISTERSUBTYPE_SYSEVENT); + + // REGISTER DEFAULT EVENT HANDLERS +#define REGISTER(a,b) SEvtRegisterHandler(REGISTERTYPE, \ + REGISTERSUBTYPE_SYSEVENT, \ + (a), \ + 0, \ + (SEVTHANDLER)(b)) + REGISTER(SYS_CIRCUITCHECK ,SysOnCircuitCheck); + REGISTER(SYS_DROPPLAYER ,SysOnDropPlayer); + REGISTER(SYS_NEWGAMEOWNER ,SysOnNewGameOwner); + REGISTER(SYS_PING ,SysOnPing); + REGISTER(SYS_PINGRESPONSE ,SysOnPingResponse); + REGISTER(SYS_PLAYERINFO ,SysOnPlayerInfo); + REGISTER(SYS_PLAYERJOIN ,SysOnPlayerJoin); + REGISTER(SYS_PLAYERJOIN_ACCEPTSTART,SysOnPlayerJoinAcceptStart); + REGISTER(SYS_PLAYERJOIN_ACCEPTDONE ,SysOnPlayerJoinAcceptDone); + REGISTER(SYS_PLAYERJOIN_REJECT ,SysOnPlayerJoinReject); + REGISTER(SYS_PLAYERLEAVE ,SysOnPlayerLeave); +#undef REGISTER + + // INITIALIZE THE RECEIVING THREAD + HANDLE event = (HANDLE)0; + if (!RecvInitialize(&event)) { + SErrSetLastError(SNET_ERROR_MAX_THRDS_REACHED); + FAILOUT_APILOCK_WRITE; + } + + // INITIALIZE THE PROVIDER + if (!SpiInitialize(providerid, + &modprogramdata, + &modplayerdata, + &modinterfacedata, + &modversiondata, + event)) { + // EITHER SPIINITIALIZE() OR THE SERVICE PROVIDER IS RESPONSIBLE + // FOR CALLING SETLASTERROR() + FAILOUT_APILOCK_WRITE; + } + + // SAVE THE CATEGORY OPTIMIZATION HINT + s_game_optcategorybits = modprogramdata.optcategorybits; + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetJoinGame (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid) { + if (playerid) + *playerid = SNET_INVALIDPLAYERID+s_api_playeroffset; + + VALIDATEBEGIN; + VALIDATE(playerid); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetJoinGame(0x%08x,\"%s\",\"%s\",\"%s\",\"%s\",*playerid)", + gameid,gamename,gamepassword,playername,playerdescription); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if (!gamename) + gamename = ""; + if (!gamepassword) + gamepassword = ""; + if (!playername) + playername = ""; + if (!playerdescription) + playerdescription = ""; + + // IF NO PLAYER NAME WAS PROVIDED, AND THE CURRENT NETWORK PROVIDER + // IS CAPABLE OF PROVIDING IT, THEN GET THE NAME OF THE LOGGED ON + // USER FROM THE NETWORK PROVIDER + char localplayername[SNETSPI_MAXSTRINGLENGTH] = ""; + char localplayerdesc[SNETSPI_MAXSTRINGLENGTH] = ""; + if ((!*playername) && s_spi->GetLocalPlayerName) { + s_spi->GetLocalPlayerName(localplayername, + SNETSPI_MAXSTRINGLENGTH, + localplayerdesc, + SNETSPI_MAXSTRINGLENGTH); + playername = localplayername; + playerdescription = localplayerdesc; + } + if (!*playername) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + return FALSE; + } + + // IF WE ARE ALREADY IN A GAME, LEAVE IT + if (s_game_playerid != NOPLAYER) + SNetLeaveGame(SNET_EXIT_AUTO_NEWGAME); + + // RESET THE CONNECTION TABLE + ConnDestroy(); + + // GET THE ADDRESS OF THE GAME OWNER + SNETSPI_GAMELIST gameinfo; + TRACEOUT(TRACEHANDLE, + " spiGetGameInfo(0x%08x,\"%s\",\"%s\",*gameinfo)", + gameid,gamename,gamepassword); + if (!s_spi->GetGameInfo(gameid,gamename,gamepassword,&gameinfo)) { + // SERVICE PROVIDER IS RESPONSIBLE FOR CALLING SETLASTERROR() + FAILOUT_APILOCK_WRITE; + } + + // CREATE A CONNECTION RECORD FOR THE GAME OWNER AND SEND HIM AN + // INITIAL CONTACT MESSAGE + s_game_joining = TRUE; + CONNPTR ownerconn = ConnFindByAddr(&gameinfo.owner); + if (!ownerconn) { + s_game_joining = FALSE; + TRACEOUT(TRACEHANDLE," out of memory"); + SNetLeaveGame(SNET_EXIT_AUTO_JOINING); + SErrSetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + FAILOUT_APILOCK_WRITE; + } + ownerconn->establishing = TRUE; + ownerconn->incomingsequence[TYPE_SYSTEM] = 1; + ownerconn->availablesequence[TYPE_SYSTEM] = 1; + ownerconn->outgoingsequence[TYPE_SYSTEM] = 1; + { + DWORD netversion = SNET_NETWORKVERSION; + MESSAGEPTR msg = ConnSendMessage(ownerconn, + TYPE_SYSTEM, + SYS_INITIALCONTACT, + &netversion, + sizeof(DWORD)); + if (msg) { + ConnResendMessage(ownerconn,msg->data,msg->databytes); + ConnResendMessage(ownerconn,msg->data,msg->databytes); + } + ConnProcessAck(ownerconn,TYPE_SYSTEM,1); + } + + // WAIT FOR THE CIRCUIT CHECK MESSAGE FROM THE GAME OWNER + { + DWORD events[1] = {SYS_CIRCUITCHECK}; + if (!SysWaitForMultipleEvents(1,events,0,s_spi_timetoblock)) { + s_game_joining = FALSE; + TRACEOUT(TRACEHANDLE," host unreachable"); + SNetLeaveGame(SNET_EXIT_AUTO_JOINING); + SErrSetLastError(SNET_ERROR_HOST_UNREACHABLE); + FAILOUT_APILOCK_WRITE; + } + } + + // SEND A REQUEST TO JOIN + { + SYSEVENTDATA_PLAYERJOIN data; + LPSTR currptr = data.namedescpass; + currptr += SStrCopy(currptr,playername,SNETSPI_MAXSTRINGLENGTH)+1; + currptr += SStrCopy(currptr,playerdescription,SNETSPI_MAXSTRINGLENGTH)+1; + currptr += SStrCopy(currptr,gamepassword,SNETSPI_MAXSTRINGLENGTH)+1; + ConnSendMessage(ConnFindByAddr(&gameinfo.owner), + TYPE_SYSTEM, + SYS_PLAYERJOIN, + &data, + (LPBYTE)currptr-(LPBYTE)&data); + } + + // WAIT FOR AN ACCEPT OR REJECT MESSAGE FROM THE OWNER + { + DWORD events[2] = {SYS_PLAYERJOIN_ACCEPTDONE, + SYS_PLAYERJOIN_REJECT}; + if (!SysWaitForMultipleEvents(2,events,0,s_spi_timetoblock)) { + ownerconn->establishing = FALSE; + s_game_joining = FALSE; + TRACEOUT(TRACEHANDLE," host unreachable"); + SNetLeaveGame(SNET_EXIT_AUTO_JOINING); + SErrSetLastError(SNET_ERROR_HOST_UNREACHABLE); + FAILOUT_APILOCK_WRITE; + } + } + + // IF WE WERE REJECTED, RETURN FAILURE + if (s_game_playerid == NOPLAYER) { + ownerconn->establishing = FALSE; + s_game_joining = FALSE; + TRACEOUT(TRACEHANDLE," rejected"); + SNetLeaveGame(SNET_EXIT_AUTO_JOINING); + SErrSetLastError(SNET_ERROR_GAME_FULL); + FAILOUT_APILOCK_WRITE; + } + + // OTHERWISE, SAVE THE GAME CATEGORY + s_game_categorybits = gameinfo.gamecategorybits; + + // SET OUR PLAYER INFORMATION + CONNPTR conn = ConnFindLocal(); + if (conn) { + conn->playerid = s_game_playerid; + SStrCopy(conn->name,playername,SNETSPI_MAXSTRINGLENGTH); + SStrCopy(conn->desc,playerdescription,SNETSPI_MAXSTRINGLENGTH); + } + *playerid = s_game_playerid+s_api_playeroffset; + TRACEOUT(TRACEHANDLE," joined as player %u",*playerid); + + // DISPATCH ANY PENDING EVENTS + LEAVE_APILOCK_WRITE; + SysDispatchUserEvents(); + ENTER_APILOCK_WRITE; + + // COMPLETE THE JOIN PROCESS + ownerconn->establishing = FALSE; + s_game_joining = FALSE; + + // MAKE SURE WE ARE STILL IN A GAME + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_GAME_TERMINATED); + FAILOUT_APILOCK_WRITE; + } + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetLeaveGame (DWORD exitcode) { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetLeaveGame(0x%08x)", + exitcode); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + + // FIND OUR PLAYER RECORD + CONNPTR conn = ConnFindLocal(); + if (!conn) { + SErrSetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + FAILOUT_APILOCK_WRITE; + } + + // IF WE ARE THE GAME OWNER, STOP ADVERTISING THE GAME + if (conn->gameowner) { + TRACEOUT(TRACEHANDLE," spiStopAdvertisingGame()"); + s_spi->StopAdvertisingGame(); + } + + // SEND MESSAGES TO ALL OTHER PLAYERS INFORMING THEM THAT WE'RE DROPPING + // OUT OF THE GAME + { + CONNPTR checkconn = s_conn_connlist.Head(); + while (checkconn) { + if (checkconn->playerid != NOPLAYER) { + SYSEVENTDATA_PLAYERLEAVE data; + data.finalsequence = checkconn->outgoingsequence[TYPE_TURN]; + data.exitcode = exitcode; + MESSAGEPTR msg = ConnSendMessage(checkconn, + TYPE_SYSTEM, + SYS_PLAYERLEAVE, + &data, + sizeof(SYSEVENTDATA_PLAYERLEAVE)); + if (msg) { + ConnResendMessage(checkconn,msg->data,msg->databytes); + ConnResendMessage(checkconn,msg->data,msg->databytes); + } + } + checkconn = checkconn->Next(); + } + } + + // DESTROY THE GAME LOCALLY + GameDestroy(); + + // LEAVE THE API LOCK + LEAVE_APILOCK_WRITE; + + // DELAY A FRACTION OF A SECOND TO GIVE THE BACKGROUND THREAD TIME TO + // FINISH ANY PACKETS IT'S PROCESSING + Sleep(s_spi_timetoresend); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetPerformUpgrade (DWORD *upgradestatus) { + VALIDATEBEGIN; + VALIDATE(upgradestatus); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE,"SNetPerformUpgrade(*upgradestatus)"); + + // VERIFY THAT THERE IS AT LEAST ONE PATCH READY TO BE INSTALLED + char buffer[1024] = ""; + if (!SRegLoadData("Patch","Patches",SREG_FLAG_BATTLENET,buffer,1023,NULL)) { + *upgradestatus = SNET_UPGRADE_NOT_NEEDED; + FAILOUT_APILOCK_WRITE; + } + buffer[1022] = 0; + buffer[1023] = 0; + + // DETERMINE THE PROGRAM DIRECTORY + char directory[MAX_PATH] = ""; + GetModuleFileName((HMODULE)0,directory,MAX_PATH); + directory[MAX_PATH-1] = 0; + { + LPSTR curr = directory; + while (*curr && SStrChr(curr+1,'\\')) + curr = SStrChr(curr+1,'\\'); + *curr = 0; + } + + // CREATE A LIST OF FILES TO EXECUTE + char execute[1024] = ""; + LPSTR currexec = execute; + + // PREPROCESS EACH PATCH + { + LPSTR curr = buffer; + while (*curr) { + + // OPEN THE PATCH + HSARCHIVE archive; + if (!SFileOpenArchive(curr,0,0,&archive)) { + *upgradestatus = (DWORD)SNET_UPGRADE_FAILED; + FAILOUT_APILOCK_WRITE; + } + + // VERIFY ITS AUTHENTICITY + { + DWORD authtype; + SFileAuthenticateArchive(archive,&authtype); + if ((authtype != SFILE_AUTH_UNABLETOAUTHENTICATE) && + (authtype < SFILE_AUTH_FIRSTAUTHENTIC)) { + SFileCloseArchive(archive); + *upgradestatus = (DWORD)SNET_UPGRADE_FAILED; + FAILOUT_APILOCK_WRITE; + } + } + + // LOOK FOR A FILE CALLED 'PREPATCH.LST' INSIDE THE PATCH FILE + { + HSFILE listfile; + if (SFileOpenFileEx(archive,"Prepatch.lst",0,&listfile)) { + + // IF WE FOUND ONE, READ IT INTO MEMORY + DWORD bytes = SFileGetFileSize(listfile); + LPSTR buffer = (LPSTR)ALLOC(bytes); + if (SFileReadFile(listfile,buffer,bytes,NULL,NULL)) { + LPCSTR curr = buffer; + while ((DWORD)(curr-buffer) < bytes) { + + // EXTRACT THE NEXT LINE + char line[256] = ""; + { + LPSTR currout = line; + while (((DWORD)(curr-buffer) < bytes) && + (currout-line < 255) && + *curr && (*curr != '\r') && (*curr != '\n')) { + *currout++ = *curr++; + *currout = 0; + } + } + while (((DWORD)(curr-buffer) < bytes) && + ((*curr == '\r') || (*curr == '\n'))) + ++curr; + + // IF THIS LINE HAS A FILENAME ARGUMENT, TURN IT INTO A FULLY + // QUALIFIED FILENAME + char relpath[MAX_PATH] = ""; + char abspath[MAX_PATH] = ""; + if (SStrChr(line,' ')) { + LPCSTR currline = SStrChr(line,' ')+1; + while (*currline == ' ') + ++currline; + SStrCopy(relpath,currline,MAX_PATH); + wsprintf(abspath,"%s\\%s",directory,currline); + } + + // IF THIS LINE CONTAINS A DELETE COMMAND, DELETE THE FILE + if (!_strnicmp(line,"delete ",7)) + DeleteFile(abspath); + + // IF THIS LINE CONTAINS AN EXTRACT COMMAND, EXTRACT THE FILE + if (!_strnicmp(line,"extract ",8)) { + HSFILE extractfile; + if (SFileOpenFileEx(archive,relpath,0,&extractfile)) { + DWORD extractbytes = SFileGetFileSize(extractfile); + LPVOID extractbuffer = ALLOC(extractbytes); + if (SFileReadFile(extractfile,extractbuffer,extractbytes,NULL,NULL)) { + HANDLE outfile = CreateFile(abspath, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (outfile != INVALID_HANDLE_VALUE) { + DWORD byteswritten; + WriteFile(outfile,extractbuffer,extractbytes,&byteswritten,NULL); + CloseHandle(outfile); + } + } + FREE(extractbuffer); + SFileCloseFile(extractfile); + } + } + + // IF THIS LINE CONTAINS AN EXECUTE COMMAND, ADD THE PROGRAM + // TO OUR LIST OF PROGRAMS TO EXECUTE + if (!_strnicmp(line,"execute ",8)) + currexec += SStrCopy(currexec,abspath)+1; + + } + + } + FREE(buffer); + + SFileCloseFile(listfile); + } + } + + // CLOSE THE PATCH + SFileCloseArchive(archive); + + curr += SStrLen(curr)+1; + } + } + + // IF THE EXECUTE LIST IS BLANK, ADD 'BNUPDATE' + if (currexec == execute) { + wsprintf(currexec,"%s\\bnupdate.exe",directory); + currexec += SStrLen(currexec)+1; + } + *currexec = 0; + + // RUN ALL OF THE PROGRAMS ON THE EXECUTE LIST + currexec = execute; + while (*currexec) { + STARTUPINFO startupinfo; + PROCESS_INFORMATION processinfo; + ZeroMemory(&startupinfo,sizeof(STARTUPINFO)); + startupinfo.cb = sizeof(STARTUPINFO); + if (CreateProcess(currexec, + NULL, + NULL, + NULL, + 0, + NORMAL_PRIORITY_CLASS, + NULL, + directory, + &startupinfo, + &processinfo)) { + CloseHandle(processinfo.hThread); + CloseHandle(processinfo.hProcess); + } + else { + *upgradestatus = (DWORD)SNET_UPGRADE_FAILED; + FAILOUT_APILOCK_WRITE; + } + currexec += SStrLen(currexec)+1; + } + + LEAVE_APILOCK_WRITE; + *upgradestatus = SNET_UPGRADING_TERMINATE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetReceiveMessage (DWORD *senderplayerid, + LPVOID *data, + DWORD *databytes) { + if (senderplayerid) + *senderplayerid = SNET_INVALIDPLAYERID+s_api_playeroffset; + if (data) + *data = NULL; + if (databytes) + *databytes = 0; + + VALIDATEBEGIN; + VALIDATE(data); + VALIDATE(databytes); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEPEND(TRACEHANDLE,"SNetReceiveMessage(*senderplayerid,*data,*databytes)"); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + + // CHECK FOR TRANSFER OF GAME OWNERSHIP + if (s_game_playerid != NOPLAYER) + GameProcessLeavingPlayers(); + + // DISPATCH ANY PENDING EVENTS + LEAVE_APILOCK_WRITE; + SysDispatchUserEvents(); + ENTER_APILOCK_WRITE; + + // MAKE SURE WE ARE STILL IN A GAME + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_GAME_TERMINATED); + FAILOUT_APILOCK_WRITE; + } + + // FIND A VALID MESSAGE THAT IS THE NEXT IN SEQUENCE FROM ITS SENDER. + // IF THERE IS MORE THAN ONE MESSAGE AVAILABLE, USE THE ONE THAT WAS + // RECEIVED EARLIEST. + { + DWORD currtime = GetTickCount(); + DWORD earliesttime = 0; + CONNPTR earliestconn = NULL; + for (int local = FALSE; local <= TRUE; ++local) { + CONNPTR conn = local ? ConnFindLocal() + : s_conn_connlist.Head(); + while (conn) { + if ((conn->playerid != NOPLAYER) && + (!conn->incomingqueue[TYPE_MESSAGE].IsEmpty()) && + (conn->incomingqueue[TYPE_MESSAGE].Head()->data->header.sequence + == conn->incomingsequence[TYPE_MESSAGE])) { + + // DETERMINE THE TIME STAMP OF THIS MESSAGE + MESSAGEPTR curr = conn->incomingqueue[TYPE_MESSAGE].Head(); + DWORD timestamp = curr->sendtime; + + // IF THIS MESSAGE'S TIME STAMP IS GREATER THAN ANY MESSAGES + // THAT WERE SENT LATER BY THE SAME PLAYER, UPDATE IT TO BE + // EARLIER + while (curr->Next()) { + curr = curr->Next(); + if (timestamp-curr->sendtime < 0x7FFFFFFF) + timestamp = curr->sendtime-1; + } + + // IF THIS MESSAGE IS NOW THE EARLIEST WE HAVE SEEN, MARK THIS + // CONNECTION AS THE NEW EARLIEST CONNECTION + if (currtime-timestamp >= earliesttime) { + earliesttime = currtime-timestamp; + earliestconn = conn; + } + + } + conn = conn->Next(); + } + } + + // RETURN THE NEXT MESSAGE IN SEQUENCE FROM THE EARLIEST CONNECTION + // TO THE USER + if (earliestconn) { + MESSAGEPTR message = earliestconn->incomingqueue[TYPE_MESSAGE].Head(); + earliestconn->incomingqueue[TYPE_MESSAGE].UnlinkNode(message); + ++(earliestconn->incomingsequence[TYPE_MESSAGE]); + ConnSetCurrentMessage(earliestconn,TYPE_MESSAGE,message); + if (senderplayerid) + *senderplayerid = earliestconn->playerid+s_api_playeroffset; + *data = message->data->data; + *databytes = message->data->header.bytes-sizeof(HEADER); + PerfIncrement(SNET_PERFID_MSGRECV); + TRACEDUMPMSG(TRACEHANDLE, + earliestconn->playerid, + message->data->header.sequence, + message->data->data, + message->data->header.bytes-sizeof(HEADER)); + LEAVE_APILOCK_WRITE; + return TRUE; + } + + } + + LEAVE_APILOCK_WRITE; + SErrSetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return FALSE; +} + +//=========================================================================== +BOOL APIENTRY SNetReceiveTurns (DWORD firstplayerid, + DWORD arraysize, + LPVOID *arraydata, + LPDWORD arraydatabytes, + LPDWORD arrayplayerstatus) { + if (arraysize && arraydata) + ZeroMemory(arraydata,arraysize*sizeof(LPVOID)); + if (arraysize && arraydatabytes) + ZeroMemory(arraydatabytes,arraysize*sizeof(DWORD)); + if (arraysize && arrayplayerstatus) + ZeroMemory(arrayplayerstatus,arraysize*sizeof(DWORD)); + + VALIDATEBEGIN; + VALIDATE(arraysize); + VALIDATE(arraydata); + VALIDATE(arraydatabytes); + VALIDATE(arrayplayerstatus); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetReceiveTurns(%u,%u,*arraydata,*arraydatabytes,*arrayplayerstatus)", + firstplayerid,arraysize); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + firstplayerid -= s_api_playeroffset; + + // CHECK FOR TRANSFER OF GAME OWNERSHIP + if (s_game_playerid != NOPLAYER) + GameProcessLeavingPlayers(); + + // DETERMINE THE SEQUENCE NUMBER TO RECEIVE + CONNPTR local = ConnFindLocal(); + if (!local) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + WORD sequence = local->incomingsequence[TYPE_TURN]; + + // CHECK ALL PLAYERS THAT ARE IN A JOINING STATE, MEANING THAT WE HAVEN'T + // CAUGHT UP TO THEIR FIRST EVER TURN, TO SEE IF THEY ARE READY TO SWITCH + // OVER TO ACTIVE STATE + { + CONNPTR conn = s_conn_connlist.Head(); + while (conn) { + if ((conn->flags & PF_JOINING) && + (conn->incomingsequence[TYPE_TURN] == sequence)) { + conn->flags &= ~PF_JOINING; + SysQueueUserEvent(SNET_EVENT_PLAYERJOIN, + conn->playerid, + NULL, + 0); + } + conn = conn->Next(); + } + } + + // DISPATCH ANY PENDING EVENTS + LEAVE_APILOCK_WRITE; + SysDispatchUserEvents(); + ENTER_APILOCK_WRITE; + + // MAKE SURE WE ARE STILL IN A GAME + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_GAME_TERMINATED); + FAILOUT_APILOCK_WRITE; + } + + // CLEAR OUT ANY UNNEEDED OR ALREADY PROCESSED TURNS + ConnClearOldTurns(NULL); + + // FILL IN THE PLAYER STATUS ARRAY + DWORD currtime = GetTickCount(); + BOOL ready = TRUE; +#ifdef TRACING + char outstr[256]; + wsprintf(outstr,"%u ",sequence); +#endif + { + for (DWORD playerid = firstplayerid; playerid < firstplayerid+arraysize; ++playerid) { + + // FIND THE CONNECTION RECORD FOR THIS PLAYER + CONNPTR conn; + if (playerid == s_game_playerid) + conn = local; + else + conn = ConnFindByPlayerId((BYTE)playerid); + + // IF THE PLAYER IS ACTIVE AND HAS COMPLETED JOINING THE GAME, FILL + // IN HIS STATUS FLAGS + DWORD statusflags = 0; + if (conn && !(conn->flags & PF_JOINING)) { + statusflags |= SNET_PSF_ACTIVE; + if ((!conn->incomingqueue[TYPE_TURN].IsEmpty()) && + (conn->incomingqueue[TYPE_TURN].Head()->data->header.sequence == sequence)) + statusflags |= SNET_PSF_TURNAVAILABLE; + else + ready = FALSE; + if ((playerid == s_game_playerid) || + (currtime-conn->lastreceivetime < s_spi_timetogiveup) || + ((conn->flags & PF_LEAVING) && (statusflags & SNET_PSF_TURNAVAILABLE))) + statusflags |= SNET_PSF_RESPONDING; + + // IF THIS IS A TRACING BUILD, LOG EACH PLAYER'S STATUS +#ifdef TRACING + char buffer[16]; + wsprintf(buffer,"%u?%u ",playerid,conn->incomingsequence[TYPE_TURN]); + if (statusflags & SNET_PSF_TURNAVAILABLE) + buffer[1] = '='; + else if (statusflags & SNET_PSF_RESPONDING) + buffer[1] = 'W'; + else + buffer[1] = 'X'; + SStrPack(outstr,buffer,256); +#endif + + } + *(arrayplayerstatus+playerid-firstplayerid) = statusflags; + } + } +#ifdef TRACING + TRACEOUT(TRACEHANDLE,outstr); +#endif + + // MAINTAIN ACTIVE CONNECTIONS + { + for (DWORD playerid = firstplayerid; playerid < firstplayerid+arraysize; ++playerid) + if (*(arrayplayerstatus+playerid-firstplayerid) & SNET_PSF_ACTIVE) { + + // FIND THE PLAYER RECORD + CONNPTR conn = NULL; + if (playerid != s_game_playerid) + conn = ConnFindByPlayerId((BYTE)playerid); + if (!conn) + continue; + + // IF WE ARE STILL WAITING FOR THIS PLAYER'S TURN AND MORE THAN THE + // RESEND TIME HAS ELAPSED, REQUEST A RESEND OF THIS TURN FROM ALL + // PLAYERS + if ((!((*(arrayplayerstatus+playerid-firstplayerid)) & SNET_PSF_TURNAVAILABLE)) && + ((!conn->lastrequesttime) || + ((currtime-conn->lastrequesttime >= s_spi_timetoresend) && + (currtime-conn->lastrequesttime <= 0x7FFFFFFF)))) { + PACKETPTR pkt = (PACKETPTR)ALLOC(sizeof(PACKET)+1); + conn->lastrequesttime = currtime; + CONNPTR otherconn = s_conn_connlist.Head(); + while (otherconn) { + if ((otherconn->playerid != NOPLAYER) && + ((conn->playerid != NOPLAYER) || (otherconn == conn))) { + TRACEOUT(TRACEHANDLE, + " requesting resend: type=%u sequence=%04x player=%x", + TYPE_TURN,conn->incomingsequence[TYPE_TURN],conn->playerid); + pkt->header.checksum = 0; + pkt->header.bytes = sizeof(HEADER); + pkt->header.sequence = conn->incomingsequence[TYPE_TURN]; + pkt->header.acksequence = otherconn->availablesequence[TYPE_TURN]; + pkt->header.type = TYPE_TURN; + pkt->header.subtype = 0; + pkt->header.playerid = local->playerid; + pkt->header.flags = MF_RESENDREQUEST; + if (otherconn != conn) { + pkt->header.bytes++; + pkt->data[0] = conn->playerid; + } + pkt->header.checksum = PktGenerateChecksum(pkt); + ConnSendPacket(otherconn,pkt); + } + otherconn = otherconn->Next(); + } + FREE(pkt); + } + + // IF WE'RE IN DANGER OF GIVING UP ON THIS PLAYER, SEND A PING + // REQUEST TO SEE IF HE'S STILL ALIVE. (OPTIMIZATION: IF THIS + // PLAYER ALREADY HAS UNACKNOWLEDGED SYSTEM MESSAGES THEN HE'S + // NOT GOING TO RESPOND TO A PING UNTIL HE PROCESSES THOSE, SO + // DON'T BOTHER TO SEND ONE.) + if ((conn->outgoingqueue[TYPE_SYSTEM].IsEmpty()) && + (currtime-conn->lastreceivetime >= s_spi_timetogiveup/2) && + (currtime-conn->lastpingtime >= s_spi_timetogiveup/2)) { + conn->lastpingtime = currtime; + ConnSendMessage(conn,TYPE_SYSTEM,SYS_PING,NULL,0); + } + + } + } + + // EXIT IF WE DON'T HAVE TURN DATA FOR ALL PLAYERS + if (!ready) { + SErrSetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + LEAVE_APILOCK_WRITE; + return FALSE; + } + + // FILL IN THE TURN DATA ARRAYS + { + for (DWORD playerid = firstplayerid; playerid < firstplayerid+arraysize; ++playerid) { + CONNPTR conn; + if (playerid == s_game_playerid) + conn = local; + else + conn = ConnFindByPlayerId((BYTE)playerid); + if (conn && + (*(arrayplayerstatus+playerid-firstplayerid) & SNET_PSF_TURNAVAILABLE)) { + MESSAGEPTR message = conn->incomingqueue[TYPE_TURN].Head(); + conn->incomingqueue[TYPE_TURN].UnlinkNode(message); + conn->incomingsequence[TYPE_TURN] = (WORD)(sequence+1); + ConnSetCurrentMessage(conn,TYPE_TURN,message); + *(arraydata +playerid-firstplayerid) = message->data->data; + *(arraydatabytes+playerid-firstplayerid) = message->data->header.bytes-sizeof(HEADER); + TRACEDUMPMSG(TRACEHANDLE, + conn->playerid, + message->data->header.sequence, + message->data->data, + message->data->header.bytes-sizeof(HEADER)); + } + else { + *(arraydata +playerid-firstplayerid) = NULL; + *(arraydatabytes+playerid-firstplayerid) = 0; + } + } + } + + // INCREMENT THE SEQUENCE NUMBER + local->incomingsequence[TYPE_TURN] = (WORD)(sequence+1); + PerfSet(SNET_PERFID_TURN,local->incomingsequence[TYPE_TURN]); + PerfIncrement(SNET_PERFID_TURNSRECV); + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetRegisterEventHandler (DWORD eventid, + SNETEVENTPROC callback) { + VALIDATEBEGIN; + VALIDATE(callback); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetRegisterEventHandler(%u,0x%08x)", + eventid,callback); + + // REGISTER THE EVENT HANDLER + BOOL success = SEvtRegisterHandler(REGISTERTYPE, + REGISTERSUBTYPE_SNETEVENT, + eventid, + 0, + (SEVTHANDLER)callback); + + LEAVE_APILOCK_WRITE; + if (!success) + SErrSetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return success; +} + +//=========================================================================== +BOOL APIENTRY SNetResetLatencyMeasurements () { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetResetLatencyMeasurements()"); + + CONNPTR conn = s_conn_connlist.Head(); + while (conn) { + conn->latency = 0; + conn->peaklatency = 0; + conn->lastpingtime = 0; + conn = conn->Next(); + } + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetSelectGame(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,*playerid)", + flags,programdata,playerdata,interfacedata,versiondata); + TRACEDUMPDATABLOCKS(TRACEHANDLE, + programdata,playerdata,interfacedata,versiondata); + + // VALIDATE PARAMETERS + if (playerid) + *playerid = 0; + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + SNETPROGRAMDATA modprogramdata; + SNETPLAYERDATA modplayerdata; + SNETUIDATA modinterfacedata; + SNETVERSIONDATA modversiondata; + if (!SpiNormalizeDataBlocks(programdata,playerdata,interfacedata,versiondata, + &modprogramdata,&modplayerdata,&modinterfacedata,&modversiondata)) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + FAILOUT_APILOCK_WRITE; + } + + // SAVE A POINTER TO THE SELECT GAME FUNCTION AND LEAVE THE API LOCK + BOOL (CALLBACK *selectfunc)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,DWORD *); + selectfunc = s_spi->SelectGame; + LEAVE_APILOCK_WRITE; + + // CALL THE SELECT GAME FUNCTION + TRACEOUT(TRACEHANDLE, + " spiSelectGame(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,*playerid)", + flags,&modprogramdata,&modplayerdata,&modinterfacedata,&modversiondata); + BOOL success = selectfunc(flags, + &modprogramdata, + &modplayerdata, + &modinterfacedata, + &modversiondata, + playerid); + + TRACEOUT(TRACEHANDLE," spiSelectGame() returns %u",success); + return success; +} + +//=========================================================================== +BOOL APIENTRY SNetSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid) { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetSelectProvider(0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,*providerid)", + mincaps,programdata,playerdata,interfacedata,versiondata); + TRACEDUMPDATABLOCKS(TRACEHANDLE, + programdata,playerdata,interfacedata,versiondata); + + // VALIDATE PARAMETERS + if (providerid) + *providerid = 0; + SNETPROGRAMDATA modprogramdata; + SNETPLAYERDATA modplayerdata; + SNETUIDATA modinterfacedata; + SNETVERSIONDATA modversiondata; + if (!SpiNormalizeDataBlocks(programdata,playerdata,interfacedata,versiondata, + &modprogramdata,&modplayerdata,&modinterfacedata,&modversiondata)) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + FAILOUT_APILOCK_WRITE; + } + + // BUILD A LIST OF PROVIDERS IF WE DON'T ALREADY HAVE ONE + SpiFindAllProviders(); + + // BUILD A USER INTERFACE PARAMETERS BLOCK + UIPARAMS uiparams; + ZeroMemory(&uiparams,sizeof(UIPARAMS)); + uiparams.mincaps = mincaps; + uiparams.programdata = &modprogramdata; + uiparams.playerdata = &modplayerdata; + uiparams.interfacedata = &modinterfacedata; + uiparams.versiondata = &modversiondata; + + // DISPLAY THE DIALOG BOX + DWORD result = (DWORD)SDlgDialogBoxParam(StormGetInstance(), + "SELECTPROVIDER_DIALOG", + SDrawGetFrameWindow(), + UiSelectProviderDialogProc, + (LPARAM)&uiparams); + if (providerid) + *providerid = result; + + LEAVE_APILOCK_WRITE; + return (result && (result != 0xFFFFFFFF)); +} + +//=========================================================================== +BOOL APIENTRY SNetSendMessage (DWORD targetplayerid, + LPVOID data, + DWORD databytes) { + VALIDATEBEGIN; + VALIDATE(data); + VALIDATE(databytes); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetSendMessage(%u,0x%08x,%u)", + targetplayerid,data,databytes); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + if ((targetplayerid != SNET_BROADCASTNONLOCALPLAYERID) && + (targetplayerid != SNET_BROADCASTPLAYERID)) + targetplayerid -= s_api_playeroffset; + + // IF THIS IS A BROADCAST, SEND IT TO ALL PLAYERS IN THE GAME, + // INCLUDING THE LOCAL PLAYER + if ((targetplayerid == SNET_BROADCASTNONLOCALPLAYERID) || + (targetplayerid == SNET_BROADCASTPLAYERID)) { + CONNPTR conn = s_conn_connlist.Head(); + while (conn) { + if (conn->playerid != NOPLAYER) { + TRACEDUMPMSG(TRACEHANDLE, + 0xFFFFFFFF, + conn->outgoingsequence[TYPE_MESSAGE], + data, + databytes); + ConnSendMessage(conn, + TYPE_MESSAGE, + 0, + data, + databytes); + } + conn = conn->Next(); + } + if (targetplayerid == SNET_BROADCASTPLAYERID) { + conn = ConnFindLocal(); + if (conn) { + TRACEDUMPMSG(TRACEHANDLE, + 0xFFFFFFFF, + conn->outgoingsequence[TYPE_MESSAGE], + data, + databytes); + ConnSendMessage(conn, + TYPE_MESSAGE, + 0, + data, + databytes); + } + } + } + + // OTHERWISE, SEND IT TO JUST THE REQUESTED PLAYER + else { + CONNPTR conn = ConnFindByPlayerId(targetplayerid); + if (conn) { + TRACEDUMPMSG(TRACEHANDLE, + 0xFFFFFFFF, + conn->outgoingsequence[TYPE_MESSAGE], + data, + databytes); + ConnSendMessage(conn, + TYPE_MESSAGE, + 0, + data, + databytes); + } + else { + SErrSetLastError(SNET_ERROR_INVALID_PLAYER); + FAILOUT_APILOCK_WRITE; + } + } + + PerfIncrement(SNET_PERFID_MSGSENT); + LEAVE_APILOCK_WRITE; + + // TRIGGER THE BACKGROUND RECEIVE THREAD SO IT WILL MAINTAIN CONNECTIONS + SetEvent(s_recv_event); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetSendServerChatCommand (LPCSTR command) { + VALIDATEBEGIN; + VALIDATE(command); + VALIDATE(*command); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetSetServerChatCommand(0x%08x)", + command); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + CONNPTR local = ConnFindLocal(); + if (!local) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + + // SEND THE MESSAGE TO THE SERVER + char senderpath[SNETSPI_MAXSTRINGLENGTH+16]; + wsprintf(senderpath,"\\\\.\\game\\%s",s_game_gamename); + BOOL result = s_spi->SendExternalMessage(senderpath, + local->name, + "", + "", + command); + + LEAVE_APILOCK_WRITE; + return result; +} + +//=========================================================================== +BOOL APIENTRY SNetSendTurn (LPVOID data, + DWORD databytes) { + VALIDATEBEGIN; + VALIDATE(data); + VALIDATE(databytes); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetSendTurn(0x%08x,%u)", + data,databytes); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_BAD_PROVIDER); + FAILOUT_APILOCK_WRITE; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + CONNPTR local = ConnFindLocal(); + if (!local) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + + // SEND THE TURN TO ALL PLAYERS IN THE GAME, INCLUDING THE LOCAL PLAYER + { + CONNPTR conn = s_conn_connlist.Head(); + while (conn) { + if ((conn->playerid != NOPLAYER) && + (conn->outgoingsequence[TYPE_TURN] == local->outgoingsequence[TYPE_TURN])) { + TRACEDUMPMSG(TRACEHANDLE, + 0xFFFFFFFF, + conn->outgoingsequence[TYPE_TURN], + data, + databytes); + ConnSendMessage(conn, + TYPE_TURN, + 0, + data, + databytes); + } + conn = conn->Next(); + } + TRACEDUMPMSG(TRACEHANDLE, + 0xFFFFFFFF, + local->outgoingsequence[TYPE_TURN], + data, + databytes); + ConnSendMessage(local, + TYPE_TURN, + 0, + data, + databytes); + } + + PerfIncrement(SNET_PERFID_TURNSSENT); + LEAVE_APILOCK_WRITE; + + // TRIGGER THE BACKGROUND RECEIVE THREAD SO IT WILL MAINTAIN CONNECTIONS + SetEvent(s_recv_event); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetSetBasePlayer (DWORD playerid) { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetSetBasePlayer(%u)", + playerid); + + s_api_playeroffset = playerid; + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetSetGameMode (DWORD modeflags) { + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetSetGameMode(0x%08x)", + modeflags); + + // VALIDATE PARAMETERS + if (!s_spi) { + SErrSetLastError(SNET_ERROR_INVALID_PARAMETER); + FAILOUT_APILOCK_WRITE; + } + if (s_game_playerid == NOPLAYER) { + SErrSetLastError(SNET_ERROR_NOT_IN_GAME); + FAILOUT_APILOCK_WRITE; + } + + // IF WE ARE NOT THE GAME OWNER, RETURN FAILURE + { + CONNPTR local = ConnFindLocal(); + if (!(local && local->gameowner)) { + SErrSetLastError(SNET_ERROR_NOT_OWNER); + FAILOUT_APILOCK_WRITE; + } + } + + // SET THE NEW GAME MODE + s_game_gamemode = modeflags; + + // BUILD THE CLIENT DATA BLOCK + BYTE clientdata[SNETSPI_MAXCLIENTDATA]; + DWORD clientdatabytes; + GameBuildClientData(clientdata, + &clientdatabytes); + + // START ADVERTISING WITH THE NEW MODE + DWORD gameage = (GetTickCount()-s_game_creationtime)/1000; + TRACEOUT(TRACEHANDLE, + " spiStartAdvertisingGame(\"%s\",\"%s\",\"%s\",%u,%u,0x%08x,0x%08x,0x%08x,%u)", + s_game_gamename, + s_game_gamepass, + s_game_gamedesc, + s_game_gamemode, + gameage, + s_game_categorybits, + s_game_optcategorybits, + clientdata, + clientdatabytes); + if (!s_spi->StartAdvertisingGame(s_game_gamename, + s_game_gamepass, + s_game_gamedesc, + s_game_gamemode, + gameage, + s_game_categorybits, + s_game_optcategorybits, + clientdata, + clientdatabytes)) + FAILOUT_APILOCK_WRITE; + + // note: broadcast the new mode to other players + + LEAVE_APILOCK_WRITE; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SNetUnregisterEventHandler (DWORD eventid, + SNETEVENTPROC callback) { + VALIDATEBEGIN; + VALIDATE(callback); + VALIDATEEND; + + ENTER_APILOCK_WRITE; + TRACEOUT(TRACEHANDLE, + "SNetUnregisterEventHandler(%u,0x%08x)", + eventid,callback); + + // UNREGISTER THE EVENT HANDLER + BOOL success = SEvtUnregisterHandler(REGISTERTYPE, + REGISTERSUBTYPE_SNETEVENT, + eventid, + (SEVTHANDLER)callback); + + LEAVE_APILOCK_WRITE; + if (!success) + SErrSetLastError(SNET_ERROR_NOT_REGISTERED); + return success; +} diff --git a/src/Storm/SOURCE/SREG.CPP b/src/Storm/SOURCE/SREG.CPP new file mode 100644 index 0000000..d2fe106 --- /dev/null +++ b/src/Storm/SOURCE/SREG.CPP @@ -0,0 +1,289 @@ +/**************************************************************************** +* +* SREG.CPP +* Storm registry functions +* +* By Michael O'Brien (9/28/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define BASEKEY "Software\\Blizzard Entertainment\\" +#define BATTLENETKEY "Software\\Battle.net\\" + +//=========================================================================== +static BOOL InternalLoadEntry (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *datatype, + LPVOID buffer, + DWORD bytes, + DWORD *bytesread) { + *bytesread = 0; + BOOL success = 0; + { + char fullkeyname[MAX_PATH]; + SRegGetBaseKey(flags,fullkeyname,MAX_PATH); + SStrPack(fullkeyname,keyname,MAX_PATH); + HKEY keyhandle; + if (!RegOpenKeyEx((flags & SREG_FLAG_USERSPECIFIC) + ? HKEY_CURRENT_USER + : HKEY_LOCAL_MACHINE, + fullkeyname, + 0, + KEY_READ, + &keyhandle)) { + *bytesread = bytes; + success = !RegQueryValueEx(keyhandle, + valuename, + 0, + datatype, + (LPBYTE)buffer, + bytesread); + RegCloseKey(keyhandle); + } + } + return success; +} + +//=========================================================================== +static BOOL InternalSaveEntry (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD datatype, + LPCVOID buffer, + DWORD bytes) { + BOOL success = 0; + { + char fullkeyname[MAX_PATH]; + if (flags & SREG_FLAG_BATTLENET) + SStrCopy(fullkeyname,BATTLENETKEY,MAX_PATH); + else + SStrCopy(fullkeyname,BASEKEY,MAX_PATH); + SStrPack(fullkeyname,keyname,MAX_PATH); + HKEY keyhandle; + DWORD disposition; + if (!RegCreateKeyEx((flags & SREG_FLAG_USERSPECIFIC) + ? HKEY_CURRENT_USER + : HKEY_LOCAL_MACHINE, + fullkeyname, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_WRITE, + (LPSECURITY_ATTRIBUTES)NULL, + &keyhandle, + &disposition)) { + success = !RegSetValueEx(keyhandle, + valuename, + 0, + datatype, + (const BYTE *)buffer, + bytes); + if (flags & SREG_FLAG_FLUSHTODISK) + RegFlushKey(keyhandle); + RegCloseKey(keyhandle); + } + } + return success; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SRegGetBaseKey (DWORD flags, + LPSTR buffer, + DWORD buffersize) { + VALIDATEBEGIN; + VALIDATE(buffer); + VALIDATE(buffersize); + VALIDATEEND; + + if (flags & SREG_FLAG_BATTLENET) + SStrCopy(buffer,BATTLENETKEY,buffersize); + else + SStrCopy(buffer,BASEKEY,buffersize); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SRegLoadData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID buffer, + DWORD buffersize, + DWORD *bytesread) { + VALIDATEBEGIN; + VALIDATE(keyname); + VALIDATE(*keyname); + VALIDATE(valuename); + VALIDATE(*valuename); + VALIDATEEND; + + DWORD datatype; + DWORD localbytesread; + if (!bytesread) + bytesread = &localbytesread; + return InternalLoadEntry(keyname, + valuename, + flags, + &datatype, + buffer, + buffersize, + bytesread); +} + +//=========================================================================== +BOOL APIENTRY SRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars) { + VALIDATEBEGIN; + VALIDATE(keyname); + VALIDATE(*keyname); + VALIDATE(valuename); + VALIDATE(*valuename); + VALIDATE(buffer); + VALIDATE(bufferchars); + VALIDATEEND; + + DWORD datatype; + DWORD bytesread; + if (!InternalLoadEntry(keyname, + valuename, + flags, + &datatype, + buffer, + bufferchars, + &bytesread)) + return FALSE; + + switch (datatype) { + + case REG_DWORD: + { + DWORD value = *(LPDWORD)buffer; + wsprintf(buffer,"%u",value); + } + break; + + case REG_SZ: + *(buffer+min(bufferchars-1,bytesread)) = 0; + break; + + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SRegLoadValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *value) { + VALIDATEBEGIN; + VALIDATE(keyname); + VALIDATE(*keyname); + VALIDATE(valuename); + VALIDATE(*valuename); + VALIDATE(value); + VALIDATEEND; + + DWORD datatype; + char buffer[256] = ""; + DWORD bytesread; + if (!InternalLoadEntry(keyname, + valuename, + flags, + &datatype, + buffer, + 256, + &bytesread)) + return FALSE; + + switch (datatype) { + + case REG_DWORD: + *value = *(LPDWORD)buffer; + break; + + case REG_SZ: + *value = strtoul(buffer,NULL,0); + break; + + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SRegSaveData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID data, + DWORD databytes) { + VALIDATEBEGIN; + VALIDATE(keyname); + VALIDATE(*keyname); + VALIDATE(valuename); + VALIDATE(*valuename); + VALIDATEEND; + + return InternalSaveEntry(keyname, + valuename, + flags, + (flags & SREG_FLAG_MULTISZ) + ? REG_MULTI_SZ + : REG_BINARY, + data ? data : "", + databytes); +} + +//=========================================================================== +BOOL APIENTRY SRegSaveString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPCTSTR string) { + VALIDATEBEGIN; + VALIDATE(keyname); + VALIDATE(*keyname); + VALIDATE(valuename); + VALIDATE(*valuename); + VALIDATE(string); + VALIDATEEND; + + return InternalSaveEntry(keyname, + valuename, + flags, + REG_SZ, + string, + SStrLen(string)+1); +} + +//=========================================================================== +BOOL APIENTRY SRegSaveValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD value) { + VALIDATEBEGIN; + VALIDATE(keyname); + VALIDATE(*keyname); + VALIDATE(valuename); + VALIDATE(*valuename); + VALIDATEEND; + + return InternalSaveEntry(keyname, + valuename, + flags, + REG_DWORD, + &value, + sizeof(DWORD)); +} diff --git a/src/Storm/SOURCE/SRGN.CPP b/src/Storm/SOURCE/SRGN.CPP new file mode 100644 index 0000000..a50f0a7 --- /dev/null +++ b/src/Storm/SOURCE/SRGN.CPP @@ -0,0 +1,765 @@ +/**************************************************************************** +* +* SRGN.CPP +* Storm region manager +* +* By Michael O'Brien (9/3/97) +* +***/ + +#include "pch.h" +#pragma hdrstop + +DECLARE_STRICT_HANDLE(HLOCKEDRGN); + +#define SF_ADDING 0x00000001 +#define SF_OVERLAPS 0x00000002 +#define SF_TEMPMASK 0x00000003 +#define SF_PARAMONLY 0x00010000 + +typedef struct _SOURCE { + RECT rect; + LPVOID param; + int sequence; + DWORD flags; +} SOURCE, *SOURCEPTR; + +typedef struct _FOUNDPARAM { + LPVOID param; + int sequence; +} FOUNDPARAM, *FOUNDPARAMPTR; + +EXPORTOBJECTDECL(RGN) { + ARRAY(SOURCE) source; + ARRAY(RECT) combined; + ARRAY(FOUNDPARAM) foundparams; + RECT foundparamsrect; + int sequence; + BOOL dirty; +} *RGNPTR; + +typedef EXPORTTABLEREUSE(RGN,HSRGN,HLOCKEDRGN,SYNC_ALWAYS) RGNTABLE; + +static RGNTABLE s_rgntable; + +static inline void DeleteCombinedRect (ARRAYPTR(RECT) combinedarray, + DWORD index); +static inline void DeleteRect (LPRECT rect); +static inline BOOL IsNullRect (LPCRECT rect); +static int __cdecl SortFoundParamsCallback (const void *elem1, + const void *elem2); +static int __cdecl SortRectCallback (const void *elem1, + const void *elem2); + +//=========================================================================== +static inline void AddCombinedRect (ARRAYPTR(RECT) combinedarray, + LPCRECT rect) { + LPRECT newrect = combinedarray->NewElement(); + CopyMemory(newrect,rect,sizeof(RECT)); +} + +//=========================================================================== +static inline void AddSourceRect (ARRAYPTR(SOURCE) sourcearray, + LPCRECT rect, + LPVOID param, + int sequence, + DWORD flags) { + SOURCEPTR newptr = sourcearray->NewElement(); + CopyMemory(&newptr->rect,rect,sizeof(RECT)); + newptr->param = param; + newptr->sequence = sequence; + newptr->flags = flags; +} + +//=========================================================================== +static inline BOOL CheckForIntersection (LPCRECT sourcerect, + LPCRECT targetrect) { + return (sourcerect->left < targetrect->right) && + (sourcerect->top < targetrect->bottom) && + (sourcerect->right > targetrect->left) && + (sourcerect->bottom > targetrect->top); +} + +//=========================================================================== +static void ClearRegion (RGNPTR rgnptr) { + rgnptr->source.SetNumElements(0); + rgnptr->combined.SetNumElements(0); + rgnptr->foundparams.SetNumElements(0); + DeleteRect(&rgnptr->foundparamsrect); + rgnptr->sequence = 0; + rgnptr->dirty = FALSE; +} + +//=========================================================================== +static void CombineRectangles (ARRAYPTR(RECT) combinedarray) { + for (DWORD loop0 = 1; loop0 < combinedarray->NumElements(); ++loop0) + for (DWORD loop1 = 0; loop1 < loop0; ++loop1) { + LPRECT rect[2] = {&(*combinedarray)[loop0], + &(*combinedarray)[loop1]}; + + // IF THESE TWO RECTANGLES ARE VERTICALLY ADJACENT AND LINE UP + // HORIZONTALLY, COMBINE THEM + if ((rect[0]->left == rect[1]->left) && + (rect[0]->right == rect[1]->right) && + ((rect[0]->top == rect[1]->bottom) || + (rect[1]->top == rect[0]->bottom))) { + rect[0]->top = min(rect[0]->top ,rect[1]->top); + rect[0]->bottom = max(rect[0]->bottom,rect[1]->bottom); + DeleteRect(rect[1]); + break; + } + + // IF THESE TWO RECTANGLES ARE NOT HORIZONTALLY ADJACENT, GO TO + // THE NEXT PAIR + if ((rect[0]->left != rect[1]->right) && + (rect[1]->left != rect[0]->right)) + continue; + + // IF THESE TWO RECTANGLES LINE UP VERTICALLY, COMBINE THEM + if ((rect[0]->top == rect[1]->top) && + (rect[0]->bottom == rect[1]->bottom)) { + rect[0]->left = min(rect[0]->left ,rect[1]->left); + rect[0]->right = max(rect[0]->right,rect[1]->right); + DeleteRect(rect[1]); + break; + } + + // OTHERWISE, IF THEY DON'T LINE UP BUT DO AT LEAST TOUCH EACH OTHER, + // THEN SPLIT THEM AS NECESSARY TO CREATE ONE WIDE RECTANGLE + else if ((rect[0]->top < rect[1]->bottom) && + (rect[1]->top < rect[0]->bottom)) { + RECT newrect[5] = {{rect[0]->left, + rect[0]->top, + rect[0]->right, + rect[1]->top}, + {rect[1]->left, + rect[1]->top, + rect[1]->right, + rect[0]->top}, + {rect[0]->left, + rect[1]->bottom, + rect[0]->right, + rect[0]->bottom}, + {rect[1]->left, + rect[0]->bottom, + rect[1]->right, + rect[1]->bottom}, + {min(rect[0]->left ,rect[1]->left), + max(rect[0]->top ,rect[1]->top), + max(rect[0]->right ,rect[1]->right), + min(rect[0]->bottom,rect[1]->bottom)}}; + for (DWORD loop = 0; loop < 5; ++loop) + if (!IsNullRect(&newrect[loop])) + AddCombinedRect(combinedarray, + &newrect[loop]); + DeleteCombinedRect(combinedarray, + loop0); + DeleteCombinedRect(combinedarray, + loop1); + break; + } + + } +} + +//=========================================================================== +static inline BOOL CompareRects (LPCRECT rect1, + LPCRECT rect2) { + return !memcmp(rect1,rect2,sizeof(RECT)); +} + +//=========================================================================== +static inline void DeleteCombinedRect (ARRAYPTR(RECT) combinedarray, + DWORD index) { + LPRECT rect = &(*combinedarray)[index]; + DeleteRect(rect); +} + +//=========================================================================== +static inline void DeleteRect (LPRECT rect) { + rect->left = INT_MAX; + rect->top = INT_MAX; + rect->right = INT_MAX; + rect->bottom = INT_MAX; +} + +//=========================================================================== +static inline void DeleteSourceRect (ARRAYPTR(SOURCE) sourcearray, + DWORD index) { + SOURCEPTR sourceptr = &(*sourcearray)[index]; + DeleteRect(&sourceptr->rect); + sourceptr->param = NULL; + sourceptr->sequence = -1; + sourceptr->flags = 0; +} + +//=========================================================================== +static void FindSourceParams (RGNPTR rgnptr, + LPCRECT rect) { + + // IF THE RESULTS FOR THIS SEARCH ARE ALREADY CACHED, JUST RETURN + if (CompareRects(rect,&rgnptr->foundparamsrect)) + return; + + // OTHERWISE, RESET THE SEARCH RESULTS + rgnptr->foundparams.SetNumElements(0); + + // FIND ALL SOURCE PARAMETERS WHICH MATCH THE GIVEN RECTANGLE + DWORD sourcerects = rgnptr->source.NumElements(); + DWORD params = 0; + for (DWORD loop1 = 0; loop1 < sourcerects; ++loop1) + if (CheckForIntersection(rect,&rgnptr->source[loop1].rect)) { + int sequence = rgnptr->source[loop1].sequence; + BOOL found = FALSE; + for (DWORD loop2 = 0; loop2 < params; ++loop2) { + FOUNDPARAMPTR checkptr = &rgnptr->foundparams[loop2]; + if (checkptr->sequence == sequence) { + found = TRUE; + break; + } + } + if (!found) { + FOUNDPARAMPTR newptr = rgnptr->foundparams.NewElement(); + newptr->param = rgnptr->source[loop1].param; + newptr->sequence = sequence; + ++params; + } + } + + // SORT THE PARAMETERS + qsort(rgnptr->foundparams.Ptr(), + rgnptr->foundparams.NumElements(), + sizeof(FOUNDPARAM), + SortFoundParamsCallback); + + // SAVE THIS RECTANGLE AS THE RECTANGLE TO WHICH THE CACHE NOW APPLIES + CopyMemory(&rgnptr->foundparamsrect, + rect, + sizeof(RECT)); + +} + +//=========================================================================== +static void FragmentCombinedRectangles (ARRAYPTR(RECT) combinedarray, + DWORD firstindex, + DWORD lastindex, + LPCRECT rect) { + for (DWORD index = firstindex; index < lastindex; ++index) { + LPCRECT checkrect = &(*combinedarray)[index]; + if (CheckForIntersection(rect,checkrect)) { + RECT newrect[4] = {{rect->left, + rect->top, + rect->right, + checkrect->top}, + {rect->left, + checkrect->bottom, + rect->right, + rect->bottom}, + {rect->left, + max(rect->top,checkrect->top), + checkrect->left, + min(rect->bottom,checkrect->bottom)}, + {checkrect->right, + max(rect->top,checkrect->top), + rect->right, + min(rect->bottom,checkrect->bottom)}}; + for (DWORD loop = 0; loop < 4; ++loop) + if (!IsNullRect(&newrect[loop])) + FragmentCombinedRectangles(combinedarray, + index+1, + lastindex, + &newrect[loop]); + return; + } + } + AddCombinedRect(combinedarray, + rect); +} + +//=========================================================================== +static void FragmentSourceRectangles (ARRAYPTR(SOURCE) sourcearray, + DWORD firstindex, + DWORD lastindex, + BOOL previousoverlap, + LPCRECT rect, + LPVOID param, + int sequence) { + + // IF THIS RECTANGLE INTERSECTS ANY OTHER RECTANGLE IN THE ARRAY, + // BREAK UP EITHER OR BOTH OF THE RECTANGLES TO ELIMINATE OVERLAP, + // AND CALL THIS FUNCTION RECURSIVELY WITH EACH PIECE. + BOOL overlapsexisting = previousoverlap; + for (DWORD index = firstindex; index < lastindex; ++index) { + LPCRECT checkrect = &(*sourcearray)[index].rect; + if (CheckForIntersection(rect,checkrect)) { + + // IF THE TWO RECTANGLES ARE IDENTICAL, DON'T TREAT THIS AS AN + // INTERSECTION + if (CompareRects(rect,checkrect)) { + (*sourcearray)[index].flags |= SF_OVERLAPS; + overlapsexisting = TRUE; + continue; + } + + // OTHERWISE, BUILD NEW RECTANGLES WHICH EACH EITHER COMPLETELY + // OVERLAP OR DON'T OVERLAP AT ALL + LPCRECT overlaprect[2] = {rect,checkrect}; + int minleft = (int)(overlaprect[0]->left > overlaprect[1]->left); + int maxleft = (int)(overlaprect[1]->left > overlaprect[0]->left); + int mintop = (int)(overlaprect[0]->top > overlaprect[1]->top); + int maxtop = (int)(overlaprect[1]->top > overlaprect[0]->top); + int minright = (int)(overlaprect[0]->right > overlaprect[1]->right); + int maxright = (int)(overlaprect[1]->right > overlaprect[0]->right); + int minbottom = (int)(overlaprect[0]->bottom > overlaprect[1]->bottom); + int maxbottom = (int)(overlaprect[1]->bottom > overlaprect[0]->bottom); + RECT newrect[5] = {{overlaprect[mintop]->left, + overlaprect[mintop]->top, + overlaprect[mintop]->right, + overlaprect[maxtop]->top}, + {overlaprect[maxbottom]->left, + overlaprect[minbottom]->bottom, + overlaprect[maxbottom]->right, + overlaprect[maxbottom]->bottom}, + {overlaprect[minleft]->left, + overlaprect[maxtop]->top, + overlaprect[maxleft]->left, + overlaprect[minbottom]->bottom}, + {overlaprect[minright]->right, + overlaprect[maxtop]->top, + overlaprect[maxright]->right, + overlaprect[minbottom]->bottom}, + {overlaprect[maxleft]->left, + overlaprect[maxtop]->top, + overlaprect[minright]->right, + overlaprect[minbottom]->bottom}}; + + // DETERMINE WHICH NEW RECTANGLES OVERLAP WHICH OF THE ORIGINAL + // RECTANGLES + BOOL overlaps[5][2]; + { + for (DWORD loop1 = 0; loop1 < 5; ++loop1) + if (IsNullRect(&newrect[loop1])) + overlaps[loop1][0] = overlaps[loop1][1] = FALSE; + else + for (DWORD loop2 = 0; loop2 < 2; ++loop2) + overlaps[loop1][loop2] = CheckForIntersection(&newrect[loop1], + overlaprect[loop2]); + } + + // ADD THE NEW RECTANGLES TO THE ARRAY. (OUR POINTERS TO THE SOURCE + // RECTANGLES BECOME INVALID AT THIS POINT BECAUSE THE ARRAY MAY BE + // RESIZED, CAUSING IT TO MOVE IN MEMORY.) + for (DWORD loop = 0; loop < 5; ++loop) { + if (overlaps[loop][0]) + FragmentSourceRectangles(sourcearray, + index+1, + lastindex, + overlapsexisting || overlaps[loop][1], + &newrect[loop], + param, + sequence); + if (overlaps[loop][1]) + AddSourceRect(sourcearray, + &newrect[loop], + (*sourcearray)[index].param, + (*sourcearray)[index].sequence, + ((*sourcearray)[index].flags & ~SF_TEMPMASK) + | (overlaps[loop][0] ? SF_OVERLAPS : 0)); + } + + // REMOVE THE ORIGINAL RECTANGLES FROM THE ARRAY AND RETURN + DeleteSourceRect(sourcearray,index); + return; + + } + } + + // IF THIS RECTANGLE DIDN'T PARTIALLY OVERLAP ANY OTHER RECTANGLE, + // ADD IT TO THE ARRAY, KEEPING TRACK OF WHETHER OR NOT IT FULLY + // OVERLAPPED ANY OTHER RECTANGLE. + AddSourceRect(sourcearray, + rect, + param, + sequence, + SF_ADDING | (overlapsexisting ? SF_OVERLAPS : 0)); + +} + +//=========================================================================== +static inline BOOL IsNullRect (LPCRECT rect) { + return ((rect->left >= rect->right) || + (rect->top >= rect->bottom)); +} + +//=========================================================================== +static void OptimizeSource (ARRAYPTR(SOURCE) sourcearray) { + + // REMOVE NULL RECTANGLES + DWORD index = 0; + DWORD numelements; + while (index < (numelements = sourcearray->NumElements())) + if (IsNullRect(&(*sourcearray)[index].rect)) { + CopyMemory(&(*sourcearray)[index], + &(*sourcearray)[numelements-1], + sizeof(SOURCE)); + sourcearray->SetNumElements(numelements-1); + } + else + ++index; + +} + +//=========================================================================== +static void ProcessBooleanOperation (ARRAYPTR(SOURCE) sourcearray, + LPCRECT rect, + int combinemode) { + for (DWORD index = 0; index < sourcearray->NumElements(); ++index) { + SOURCEPTR sourceptr = &(*sourcearray)[index]; + BOOL remove = FALSE; + switch (combinemode) { + + case SRGN_AND: + remove = !(sourceptr->flags & SF_OVERLAPS); + break; + + case SRGN_COPY: + remove = (sourceptr->flags & SF_ADDING); + break; + + case SRGN_DIFF: + remove = (sourceptr->flags & (SF_ADDING | SF_OVERLAPS)); + break; + + case SRGN_XOR: + remove = (sourceptr->flags & SF_OVERLAPS); + break; + + } + if (remove) + DeleteSourceRect(sourcearray,index); + sourceptr->flags = 0; + } +} + +//=========================================================================== +static void ProduceCombinedRectangles (RGNPTR rgnptr) { + DWORD sourcerects = rgnptr->source.NumElements(); + rgnptr->combined.SetNumElements(0); + + // FRAGMENT THE SOURCE RECTANGLES INTO SMALLER NON-OVERLAPPING RECTANGLES + { + SOURCEPTR sourcearray = rgnptr->source.Ptr(); + for (DWORD loop = 0; loop < sourcerects; ++loop) + if (!(sourcearray[loop].flags & SF_PARAMONLY)) + FragmentCombinedRectangles(&rgnptr->combined, + 0, + rgnptr->combined.NumElements(), + &sourcearray[loop].rect); + } + + // RECOMBINE ADJACENT RECTANGLES + CombineRectangles(&rgnptr->combined); + + // SORT THE RECTANGLES VERTICALLY + qsort(rgnptr->combined.Ptr(), + rgnptr->combined.NumElements(), + sizeof(RECT), + SortRectCallback); + + // REMOVE ANY DELETED RECTANGLES (WHICH WILL HAVE BEEN SORTED TO THE + // BOTTOM OF THE ARRAY) + DWORD numrects; + while ((numrects = rgnptr->combined.NumElements()) != 0) + if (IsNullRect(&rgnptr->combined[--numrects])) + rgnptr->combined.SetNumElements(numrects); + else + break; + +} + +//=========================================================================== +static int __cdecl SortFoundParamsCallback (const void *elem1, + const void *elem2) { + FOUNDPARAMPTR ptr1 = (FOUNDPARAMPTR)elem1; + FOUNDPARAMPTR ptr2 = (FOUNDPARAMPTR)elem2; + return (ptr1->sequence-ptr2->sequence); +} + +//=========================================================================== +static int __cdecl SortRectCallback (const void *elem1, + const void *elem2) { + LPRECT rect1 = (LPRECT)elem1; + LPRECT rect2 = (LPRECT)elem2; + if (rect1->top == rect2->top) + return rect1->left-rect2->left; + else + return rect1->top-rect2->top; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +void APIENTRY SRgnClear (HSRGN handle) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATEENDVOID; + + // LOCK THE REGION + HLOCKEDRGN lockedhandle; + RGNPTR rgnptr = s_rgntable.Lock(handle,&lockedhandle); + if (!rgnptr) + return; + + // CLEAR THE REGION + ClearRegion(rgnptr); + + // UNLOCK THE REGION + s_rgntable.Unlock(lockedhandle); + +} + +//=========================================================================== +void APIENTRY SRgnCombineRect (HSRGN handle, + LPCRECT rect, + LPVOID param, + int combinemode) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATE(rect); + VALIDATE(combinemode >= SRGN_MIN); + VALIDATE(combinemode <= SRGN_MAX); + VALIDATEENDVOID; + + // LOCK THE REGION + HLOCKEDRGN lockedhandle; + RGNPTR rgnptr = s_rgntable.Lock(handle,&lockedhandle); + if (!rgnptr) + return; + + // IF THIS IS A SIMPLE 'OR' OPERATION, SKIP THE ITERSECTION STEP AND JUST + // ADD THE RECTANGLE TO THE REGION + if ((combinemode == SRGN_OR) || + (combinemode == SRGN_PARAMONLY)) { + if (!IsNullRect(rect)) + AddSourceRect(&rgnptr->source, + rect, + param, + ++rgnptr->sequence, + (combinemode == SRGN_PARAMONLY) + ? SF_PARAMONLY + : 0); + } + + // OTHERWISE, PERFORM AN INTERSECTION, PROCESS THE BOOLEAN OPERATOR ON + // THE RESULTING SOURCE ELEMENTS, AND ADD OR REMOVE THEM AS NECESSARY + else { + if (!IsNullRect(rect)) + FragmentSourceRectangles(&rgnptr->source, + 0, + rgnptr->source.NumElements(), + FALSE, + rect, + param, + ++rgnptr->sequence); + ProcessBooleanOperation(&rgnptr->source, + rect, + combinemode); + OptimizeSource(&rgnptr->source); + } + + // MARK THE REGION AS DIRTY + rgnptr->dirty = TRUE; + + // INVALIDATE THE CACHE OF FOUND PARAMETERS + DeleteRect(&rgnptr->foundparamsrect); + + // UNLOCK THE REGION + s_rgntable.Unlock(lockedhandle); + +} + +//=========================================================================== +void APIENTRY SRgnCreate (HSRGN *handle, + DWORD reserved) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATE(!reserved); + VALIDATEENDVOID; + + HLOCKEDRGN lockedhandle; + RGNPTR rgnptr = s_rgntable.NewLock(handle,&lockedhandle); + ClearRegion(rgnptr); + s_rgntable.Unlock(lockedhandle); +} + +//=========================================================================== +void APIENTRY SRgnDelete (HSRGN handle) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATEENDVOID; + + s_rgntable.Delete(handle); +} + +//=========================================================================== +void APIENTRY SRgnDestroy () { + s_rgntable.Destroy(); +} + +//=========================================================================== +void APIENTRY SRgnDuplicate (HSRGN orighandle, + HSRGN *handle, + DWORD reserved) { + VALIDATEBEGIN; + VALIDATEANDBLANK(handle); + VALIDATE(orighandle); + VALIDATE(!reserved); + VALIDATEENDVOID; + + HLOCKEDRGN origlockedhandle; + RGNPTR origrgnptr = s_rgntable.Lock(orighandle,&origlockedhandle); + if (!origrgnptr) + return; + + HLOCKEDRGN lockedhandle; + RGNPTR rgnptr = s_rgntable.NewLock(handle,&lockedhandle); + *rgnptr = *origrgnptr; + s_rgntable.Unlock(lockedhandle); + s_rgntable.Unlock(origlockedhandle); +} + +//=========================================================================== +void APIENTRY SRgnGetBoundingRect (HSRGN handle, + LPRECT rect) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATE(rect); + VALIDATEENDVOID; + + rect->left = INT_MAX; + rect->top = INT_MAX; + rect->right = INT_MIN; + rect->bottom = INT_MIN; + + // LOCK THE REGION + HLOCKEDRGN lockedhandle; + RGNPTR rgnptr = s_rgntable.Lock(handle,&lockedhandle); + if (!rgnptr) + return; + + // ADJUST THE BOUNDING RECTANGLE FOR EACH SOURCE RECTANGLE IN THE REGION + SOURCEPTR sourcearray = rgnptr->source.Ptr(); + DWORD sourcerects = rgnptr->source.NumElements(); + for (DWORD loop = 0; loop < sourcerects; ++loop) + if (!(sourcearray[loop].flags & SF_PARAMONLY)) { + rect->left = min(rect->left ,sourcearray[loop].rect.left ); + rect->top = min(rect->top ,sourcearray[loop].rect.top ); + rect->right = max(rect->right ,sourcearray[loop].rect.right ); + rect->bottom = max(rect->bottom,sourcearray[loop].rect.bottom); + } + + // UNLOCK THE REGION + s_rgntable.Unlock(lockedhandle); + + // IF THE BOUNDING RECTANGLE IS EMPTY, SET IT TO A NORMALIZED EMPTY + // RECTANGLE + if (IsNullRect(rect)) + ZeroMemory(rect,sizeof(RECT)); + +} + +//=========================================================================== +void APIENTRY SRgnGetRectParams (HSRGN handle, + LPCRECT rect, + DWORD *numparams, + LPVOID *buffer) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATE(rect); + VALIDATE(numparams); + VALIDATEENDVOID; + + // VERIFY THAT THE RECTANGLE IS VALID + if (IsNullRect(rect)) { + *numparams = 0; + return; + } + + // LOCK THE REGION + HLOCKEDRGN lockedhandle; + RGNPTR rgnptr = s_rgntable.Lock(handle,&lockedhandle); + if (!rgnptr) { + *numparams = 0; + return; + } + + // COMBINE THE SOURCE ELEMENTS INTO AN ARRAY OF NONOVERLAPPING RECTANGLES + if (rgnptr->dirty) { + ProduceCombinedRectangles(rgnptr); + rgnptr->dirty = FALSE; + } + + // FIND ALL SOURCE PARAMETERS WHICH OVERLAP THE GIVEN RECTANGLE + FindSourceParams(rgnptr,rect); + + // DETERMINE THE NUMBER OF SOURCE PARAMETERS TO COPY + if (buffer) + *numparams = min(*numparams,rgnptr->foundparams.NumElements()); + else + *numparams = rgnptr->foundparams.NumElements(); + + // COPY THE SOURCE PARAMETERS + if (buffer) { + FOUNDPARAMPTR foundarray = rgnptr->foundparams.Ptr(); + for (DWORD loop = 0; loop < *numparams; ++loop) + *buffer++ = (foundarray++)->param; + } + + // UNLOCK THE REGION + s_rgntable.Unlock(lockedhandle); + +} + +//=========================================================================== +void APIENTRY SRgnGetRects (HSRGN handle, + DWORD *numrects, + LPRECT buffer) { + VALIDATEBEGIN; + VALIDATE(handle); + VALIDATE(numrects); + VALIDATEENDVOID; + + // LOCK THE REGION + HLOCKEDRGN lockedhandle; + RGNPTR rgnptr = s_rgntable.Lock(handle,&lockedhandle); + if (!rgnptr) { + *numrects = 0; + return; + } + + // COMBINE THE SOURCE ELEMENTS INTO AN ARRAY OF NONOVERLAPPING RECTANGLES + if (rgnptr->dirty) { + ProduceCombinedRectangles(rgnptr); + rgnptr->dirty = FALSE; + } + + // DETERMINE THE NUMBER OF RECTANGLES TO COPY + if (buffer) + *numrects = min(*numrects,rgnptr->combined.NumElements()); + else + *numrects = rgnptr->combined.NumElements(); + + // COPY THE RECTANGLES + if (buffer) + CopyMemory(buffer, + rgnptr->combined.Ptr(), + (*numrects)*sizeof(RECT)); + + // UNLOCK THE REGION + s_rgntable.Unlock(lockedhandle); + +} diff --git a/src/Storm/SOURCE/SRTL.CPP b/src/Storm/SOURCE/SRTL.CPP new file mode 100644 index 0000000..660348a --- /dev/null +++ b/src/Storm/SOURCE/SRTL.CPP @@ -0,0 +1,168 @@ +/**************************************************************************** +* +* SRTL.CPP +* Replacements for select C runtime library functions +* +* By Michael O'Brien (3/6/97) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#ifndef STATICLIB +#define REPLACESTARTUP 1 +#define REPLACETYPEINFO 1 +#endif + +/**************************************************************************** +* +* STARTUP AND SHUTDOWN FUNCTIONS +* +***/ + +#if REPLACESTARTUP + +typedef void (__cdecl *_PVFV)(void); + +#pragma data_seg(".CRT$XIA") +_PVFV __xi_a[] = { NULL }; // C initializers (begin) +#pragma data_seg(".CRT$XIZ") +_PVFV __xi_z[] = { NULL }; // C initializers (end) +#pragma data_seg(".CRT$XCA") +_PVFV __xc_a[] = { NULL }; // C++ initializers (begin) +#pragma data_seg(".CRT$XCZ") +_PVFV __xc_z[] = { NULL }; // C++ initializers (end) +#pragma data_seg() + +static CRITICAL_SECTION s_critsect; +static DWORD s_termalloc = 0; +static _PVFV *s_termlist = NULL; +static DWORD s_termused = 0; + +extern BOOL APIENTRY DllMain (HINSTANCE, DWORD, LPVOID); + +//=========================================================================== +static void CallInitList (_PVFV *begin, _PVFV *end) { + while (begin < end) { + if (*begin) + (**begin)(); + ++begin; + } +} + +//=========================================================================== +static void RtlDestroy () { + + // CALL REGISTERED EXIT PROCEDURES (INCLUDING DESTRUCTORS FOR STATIC + // OBJECTS) IN LIFO ORDER + while (s_termused) + (**(s_termlist+(--s_termused)))(); + + // CLEAR THE LIST OF EXIT PROCEDURES + VirtualFree(s_termlist,0,MEM_RELEASE); + s_termalloc = 0; + s_termlist = NULL; + + // DESTROY LOW-LEVEL MODULES. THESE ARE DESTROYED NOW RATHER THAN DURING + // DLLMAIN() SO THAT THEY CAN BE USED BY DESTRUCTORS. + SMemDestroy(); + SErrDestroy(); + SLogDestroy(); + + // DELETE OUR CRITICAL SECTION + DeleteCriticalSection(&s_critsect); + +} + +//=========================================================================== +static void RtlInitialize () { + + // INITIALIZE OUR CRITICAL SECTION + InitializeCriticalSection(&s_critsect); + + // INITIALIZE STORM'S LOG AND MEMORY MANAGERS, SO THAT THEY CAN BE USED BY + // CLASS CONSTRUCTORS + SLogInitialize(); + SMemInitialize(); + + // CALL C/C++ INITIALIZERS (INCLUDING CONSTRUCTORS FOR STATIC OBJECTS) + CallInitList(__xi_a,__xi_z); + CallInitList(__xc_a,__xc_z); + +} + +//=========================================================================== +extern "C" BOOL APIENTRY _DllMainCRTStartup (HINSTANCE instance, + DWORD reason, + LPVOID reserved) { + if (reason == DLL_PROCESS_ATTACH) + RtlInitialize(); + BOOL result = DllMain(instance,reason,reserved); + if ((reason == DLL_PROCESS_DETACH) || + ((reason == DLL_PROCESS_ATTACH) && !result)) + RtlDestroy(); + return result; +} + +#endif // if REPLACESTARTUP + +/**************************************************************************** +* +* EXPORTED STARTUP/SHUTDOWN FUNCTIONS +* +***/ + +#if REPLACESTARTUP + +//=========================================================================== +int __cdecl atexit (_PVFV func) { + EnterCriticalSection(&s_critsect); + + // GROW THE TERMINATOR LIST IF NECESSARY + if (s_termused >= s_termalloc) { + DWORD newalloc = s_termalloc+1024; + _PVFV *newlist = (_PVFV *)VirtualAlloc(NULL,newalloc*sizeof(_PVFV),MEM_COMMIT,PAGE_READWRITE); + if (!newlist) { + LeaveCriticalSection(&s_critsect); + return EXIT_FAILURE; + } + if (s_termlist) { + CopyMemory(newlist,s_termlist,s_termalloc*sizeof(_PVFV)); + VirtualFree(s_termlist,0,MEM_RELEASE); + } + s_termalloc = newalloc; + s_termlist = newlist; + } + + // ADD THIS ENTRY TO THE TERMINATOR LIST + *(s_termlist+s_termused++) = func; + + LeaveCriticalSection(&s_critsect); + return EXIT_SUCCESS; +} + +#endif // if REPLACESTARTUP + +/**************************************************************************** +* +* EXPORTED TYPEINFO FUNCTIONS +* +***/ + +#if REPLACETYPEINFO + +//=========================================================================== +type_info::type_info (const type_info& rhs) { +} + +//=========================================================================== +type_info::~type_info() { +} + +//=========================================================================== +type_info& type_info::operator= (const type_info& rhs) { + return *this; +} + +#endif // if REPLACETYPEINFO diff --git a/src/Storm/SOURCE/SSTR.CPP b/src/Storm/SOURCE/SSTR.CPP new file mode 100644 index 0000000..1d0d5b1 --- /dev/null +++ b/src/Storm/SOURCE/SSTR.CPP @@ -0,0 +1,396 @@ +/**************************************************************************** +* +* SSTR.CPP +* String manipulation functions +* +* By Michael O'Brien (5/29/97) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define QUOTECHAR '\"' + +typedef union _PACKED { + DWORD dword; + BYTE byte[4]; +} PACKED, *PACKEDPTR; + +static const DWORD s_hashtable[16] = {0x486e26ee,0xdcaa16b3,0xe1918eef,0x202dafdb, + 0x341c7dc7,0x1c365303,0x40ef2d37,0x65fd5e49, + 0xd6057177,0x904ece93,0x1c38024f,0x98fd323b, + 0xe3061ae7,0xa39b0fa1,0x9797f25f,0xe4444563}; + +/**************************************************************************** +* +* MACROS +* +* These macros implement routines to copy strings either a byte or dword at +* at time, and to search for null terminators either a byte or dword at a +* time. +* +* To check a dword for a null terminator, the macros add the 32-bit +* constant 0x7EFEFEFF to the dword value. This causes an overflow in each +* byte in the dword unless that byte is zero. The macros then xor the +* result with the original to see which bits have changed, in order to +* determine whether there were any bytes that didn't overflow. This test is +* fast (it executes in three clock cycles on an Intel system) and 100% +* accurate in identifying null terminators where they exist. There is one +* case (0x80010101) where it falsely identifies a null terminator where none +* exists, so the code in the macros that is executed in response to a +* positive result has to test all four bytes for a null terminator, not just +* three. +* +* These macros are designed to give good performance on all systems, but are +* especially tweaked for MSVC on Intel systems, where they generate code +* that is the same as the most efficient possible assembly language +* implementation of the algorithm. This tweaking adds some complexity to +* the code, as follows: +* +* - The code to handle a dword with a null terminator in it is placed +* in a separate loop from the code that handles non-terminating dwords, +* rather than a separate "if" statement in the same loop, because +* Microsoft's compiler always generates an unconditional jump rather +* than a conditional one to a target address that can be reached from +* two or more jump statements. +* +* - The code that tests for overflows in the byte components of a dword +* tricks the compiler into thinking that the result of the test is used +* for more than just the conditional jump, so that the compiler will +* generate an "and" rather than a "test" instruction, because "and" is +* fully pairable on a Pentium processor while "test" with an immediate +* is not. +* +* - The code that checks for null bytes in a dword also emulates a "not" +* instruction by subtracting the value from 0xFFFFFFFF. Subtracting a +* value from a register and then restoring the contents of that register +* requires a total of one clock cycle on a Pentium, which is the same as +* a "not" instruction; however, it increases the opportunities for the +* compiler to reshuffle code in order to avoid delays caused by data +* dependence, and that makes a critical speed difference in this case. +* +* - The same code also tricks the compiler into thinking that the constant +* 0xFFFFFFFF might be changed at some point, so that it will store it +* in a register rather than using it as an immediate value, because +* otherwise MSVC generates code to load the immediate value into a +* register once for each iteration of the loop. +* +* Most of these tweaks are separated out in an Intel-specific macro, so that +* a more straightforward implementation of the algorithm gets used on non- +* Intel systems. +* +***/ + +//=========================================================================== +#ifdef _X86_ + static DWORD s_check_markresultused; + #define INITDWORDOPERATIONS \ + DWORD check_modnum; \ + DWORD check_notnum = 0xFFFFFFFF + #define CHECKFORNULLBYTES(num) \ + (check_modnum = (num)+0x7EFEFEFF, \ + check_notnum -= (num), \ + check_modnum ^= check_notnum, \ + check_notnum |= (num), \ + check_modnum &= 0x81010101) + #define CHECK_ENDLOOP \ + s_check_markresultused = check_modnum +#else + #define INITDWORDOPERATIONS + #define CHECKFORNULLBYTES(num) \ + (((((num)+0x7EFEFEFF) ^ (num)) & 0x81010100) != 0x81010100) + #define CHECK_ENDLOOP +#endif + +//=========================================================================== +#ifdef _X86_ + #define CHECKFORNULLBYTE0(packed) (!packed.byte[0]) + #define CHECKFORNULLBYTE1(packed) (!packed.byte[1]) + #define CHECKFORNULLBYTE2(packed) (!(packed.dword & 0x00FF0000)) + #define CHECKFORNULLBYTE3(packed) (!(packed.dword & 0xFF000000)) +#else + #define CHECKFORNULLBYTE0(packed) (!packed.byte[0]) + #define CHECKFORNULLBYTE1(packed) (!packed.byte[1]) + #define CHECKFORNULLBYTE2(packed) (!packed.byte[2]) + #define CHECKFORNULLBYTE3(packed) (!packed.byte[3]) +#endif + +//=========================================================================== +#define BEGINSKIP + +//=========================================================================== +#define SKIPLEADINGBYTES \ + for (; \ + (DWORD)currdest & 3; \ + ++currdest) \ + if (!*currdest) \ + goto endskip + +//=========================================================================== +#define SKIPALIGNEDDWORDS \ + do { \ + PACKED packed = *(PACKEDPTR)currdest; \ + currdest += sizeof(PACKED); \ + if (!CHECKFORNULLBYTES(packed.dword)) \ + continue; \ + if (CHECKFORNULLBYTE0(packed)) { \ + currdest -= 4; \ + goto endskip; \ + } \ + if (CHECKFORNULLBYTE1(packed)) { \ + currdest -= 3; \ + goto endskip; \ + } \ + if (CHECKFORNULLBYTE2(packed)) { \ + currdest -= 2; \ + goto endskip; \ + } \ + if (CHECKFORNULLBYTE3(packed)) { \ + currdest -= 1; \ + goto endskip; \ + } \ + CHECK_ENDLOOP; \ + } while (1) + +//=========================================================================== +#define ENDSKIP \ + endskip: + +//=========================================================================== +#define BEGINCOPY \ + DWORD negoffset = (DWORD)-(int)(destsize-(currdest-dest)) + +//=========================================================================== +#define COPYLEADINGBYTES \ + while (((DWORD)source & 3) && negoffset) \ + if (!(*(enddest+negoffset++) = *source++)) \ + goto endcopy; + +//=========================================================================== +#define COPYALIGNEDDWORDS \ + if ((int)(negoffset += 3) < 0) { \ + enddest -= 3; \ + \ + PACKED packed = *(PACKEDPTR)source; \ + source += sizeof(PACKED); \ + while (!CHECKFORNULLBYTES(packed.dword)) { \ + *(PACKEDPTR)(enddest+negoffset) = packed; \ + if ((int)(negoffset += 4) >= 0) \ + goto donealigned; \ + packed = *(PACKEDPTR)source; \ + source += sizeof(PACKED); \ + } \ + for (;;) { \ + if (CHECKFORNULLBYTE0(packed)) { \ + *(enddest+negoffset) = packed.byte[0]; \ + negoffset += 1; \ + goto endcopy; \ + } \ + if (CHECKFORNULLBYTE1(packed)) { \ + *(LPWORD)(enddest+negoffset) = (WORD)(packed.dword); \ + negoffset += 2; \ + goto endcopy; \ + } \ + if (CHECKFORNULLBYTE2(packed)) { \ + *(LPWORD)(enddest+negoffset) = (WORD)(packed.dword); \ + *(enddest+negoffset+2) = 0; \ + negoffset += 3; \ + goto endcopy; \ + } \ + *(PACKEDPTR)(enddest+negoffset) = packed; \ + negoffset += sizeof(PACKED); \ + if (CHECKFORNULLBYTE3(packed)) \ + goto endcopy; \ + CHECK_ENDLOOP; \ + if ((int)negoffset >= 0) \ + goto donealigned; \ + packed = *(PACKEDPTR)source; \ + source += sizeof(PACKED); \ + } \ + \ + donealigned: \ + enddest += 3; \ + } \ + negoffset -= 3 + +//=========================================================================== +#define COPYTRAILINGBYTES \ + while (negoffset) \ + if (!(*(enddest+negoffset++) = *source++)) \ + goto endcopy; \ + *enddest = 0 + +//=========================================================================== +#define ENDCOPY \ + endcopy: \ + currdest = enddest+(negoffset-1); + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +LPTSTR APIENTRY SStrChr (LPCTSTR string, + char ch, + BOOL reverse) { + LPTSTR last = NULL; + if (reverse) { + for (LPCTSTR curr = string; *curr; ++curr) + if (*curr == ch) + last = (LPTSTR)curr; + } + else { + for (LPCTSTR curr = string; *curr; ++curr) + if (*curr == ch) + return (LPTSTR)curr; + } + return last; +} + +//=========================================================================== +DWORD APIENTRY SStrCopy (LPTSTR dest, + LPCTSTR source, + DWORD destsize) { + if (!destsize--) + return 0; + + INITDWORDOPERATIONS; + LPTSTR currdest = dest; + LPTSTR enddest = dest+destsize; + + BEGINCOPY; + COPYLEADINGBYTES; + COPYALIGNEDDWORDS; + COPYTRAILINGBYTES; + ENDCOPY; + + return currdest-dest; +} + +//=========================================================================== +DWORD APIENTRY SStrHash (LPCTSTR string, + DWORD flags, + DWORD seed) { + DWORD result = seed ? seed : 0x7FED7FED; + DWORD adjust = 0xEEEEEEEE; + DWORD ch; + if (flags & SSTR_HASH_CASESENSITIVE) + while ((ch = (DWORD)(BYTE)*(string++)) != 0) { + result = (result+adjust) ^ (s_hashtable[ch >> 4] - s_hashtable[ch & 0x0F]); + adjust += ch+result+(adjust << 5)+3; + } + else + while ((ch = (DWORD)(BYTE)*(string++)) != 0) { + if ((ch >= (DWORD)'a') && (ch <= (DWORD)'z')) + ch = ch+(DWORD)'A'-(DWORD)'a'; + if (ch == (DWORD)'/') + ch = (DWORD)'\\'; + result = (result+adjust) ^ (s_hashtable[ch >> 4] - s_hashtable[ch & 0x0F]); + adjust += ch+result+(adjust << 5)+3; + } + if (!result) + ++result; + return result; +} + +//=========================================================================== +DWORD APIENTRY SStrLen (LPCTSTR string) { + + INITDWORDOPERATIONS; + LPCTSTR currdest = string; + + BEGINSKIP; + SKIPLEADINGBYTES; + SKIPALIGNEDDWORDS; + ENDSKIP; + + return currdest-string; +} + +//=========================================================================== +void APIENTRY SStrPack (LPTSTR dest, + LPCTSTR source, + DWORD destsize) { + if (!destsize--) + return; + + INITDWORDOPERATIONS; + LPTSTR currdest = dest; + LPTSTR enddest = dest+destsize; + + // FORCE THE DESTINATION BUFFER TO BE NULL TERMINATED + if (destsize != SSTR_UNBOUNDED) + *enddest = 0; + + BEGINSKIP; + SKIPLEADINGBYTES; + SKIPALIGNEDDWORDS; + ENDSKIP; + + BEGINCOPY; + COPYLEADINGBYTES; + COPYALIGNEDDWORDS; + COPYTRAILINGBYTES; + ENDCOPY; + +} + +//=========================================================================== +void APIENTRY SStrTokenize (LPCTSTR *string, + LPTSTR buffer, + DWORD bufferchars, + LPCTSTR whitespace, + BOOL *quoted) { + BOOL checkquotes = (SStrChr(whitespace,QUOTECHAR) != NULL); + BOOL inquotes = FALSE; + BOOL usedquotes = FALSE; + LPCTSTR currsource = *string; + + // SKIP PAST ALL LEADING WHITESPACE + while ((*currsource) && SStrChr(whitespace,*currsource)) { + if (checkquotes && (*currsource == QUOTECHAR)) { + usedquotes = TRUE; + inquotes = !inquotes; + } + ++currsource; + } + + // COPY THE TOKEN + DWORD destchars = 0; + char ch; + while ((ch = *currsource) != 0) + if (checkquotes && (ch == QUOTECHAR)) { + if (destchars && !inquotes) + break; + usedquotes = TRUE; + inquotes = !inquotes; + ++currsource; + if (!inquotes) + break; + } + else if (inquotes || !SStrChr(whitespace,ch)) { + if (destchars+1 < bufferchars) + buffer[destchars++] = ch; + ++currsource; + } + else { + ++currsource; + break; + } + + // NULL TERMINATE THE BUFFER + if (destchars < bufferchars) + buffer[destchars] = 0; + + // RETURN AN UPDATED POINTER INTO THE SOURCE STRING + *string = currsource; + + // RETURN TO THE APPLICATION A BOOLEAN TELLING WHETHER THIS TOKEN + // WAS IN QUOTES + if (quoted) + *quoted = usedquotes; + +} diff --git a/src/Storm/SOURCE/STANDARD/CAPS.DAT b/src/Storm/SOURCE/STANDARD/CAPS.DAT new file mode 100644 index 0000000..b65b837 Binary files /dev/null and b/src/Storm/SOURCE/STANDARD/CAPS.DAT differ diff --git a/src/Storm/SOURCE/STANDARD/CAPS.MPQ b/src/Storm/SOURCE/STANDARD/CAPS.MPQ new file mode 100644 index 0000000..b19306e Binary files /dev/null and b/src/Storm/SOURCE/STANDARD/CAPS.MPQ differ diff --git a/src/Storm/SOURCE/STANDARD/IPX.CPP b/src/Storm/SOURCE/STANDARD/IPX.CPP new file mode 100644 index 0000000..95ea837 --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/IPX.CPP @@ -0,0 +1,1374 @@ +/**************************************************************************** +* +* IPX.CPP +* IPX network provider +* +* By Michael O'Brien (4/22/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define ADVPORT 6111 +#define MAINPORT 6112 +#define MAXMESSAGESIZE 504 +#define MAXPLAYERS 256 +#define PROVIDERID 'IPXN' +#define RECVDATATHREADS 2 + +#define ADTYPE_GAMEINFO 0 +#define ADTYPE_REMOVE 1 +#define ADTYPE_REQUEST 2 + +typedef struct _ADVHEADER { + WORD checksum; // must be first field + WORD length; + WORD type; + WORD reserved; + DWORD programid; + DWORD versionid; + DWORD gamemode; +} ADVHEADER, *ADVHEADERPTR; + +typedef struct _ADVPACKET { + ADVHEADER header; + char strings[SNETSPI_MAXSTRINGLENGTH*2]; + BYTE clientdatabuffer[SNETSPI_MAXCLIENTDATA]; +} ADVPACKET, *ADVPACKETPTR; + +typedef struct _PACKET { + SNETADDR addr; // must be first field in structure + BYTE data[MAXMESSAGESIZE]; + DWORD databytes; + _PACKET *next; +} PACKET, *PACKETPTR; + +typedef struct _UIPARAMS { + DWORD flags; + SNETPROGRAMDATAPTR programdata; + SNETPLAYERDATAPTR playerdata; + SNETUIDATAPTR interfacedata; + SNETVERSIONDATAPTR versiondata; + LPDWORD playeridptr; +} UIPARAMS, *UIPARAMSPTR; + +typedef struct _THREAD { + unsigned id; + HANDLE handle; + _THREAD *next; +} THREAD, *THREADPTR; + +typedef struct _WINSOCKAPI { + int (APIENTRY *bind )(SOCKET,const sockaddr *,int); + int (APIENTRY *closesocket)(SOCKET); + u_short (APIENTRY *htons )(u_short); + int (APIENTRY *recvfrom )(SOCKET,char *,int,int,sockaddr *,int *); + int (APIENTRY *sendto )(SOCKET,const char *,int,int,const sockaddr *,int); + int (APIENTRY *setsockopt )(SOCKET,int,int,const char *,int); + SOCKET (APIENTRY *socket )(int,int,int); + int (APIENTRY *WSAStartup )(WORD,LPWSADATA); + int (APIENTRY *WSACleanup )(); +} WINSOCKAPI, *WINSOCKAPIPTR; + +static ADVPACKETPTR ipx_advgameinfo = NULL; +static SOCKET ipx_advsocket = (SOCKET)0; +static SOCKADDR_IPX ipx_broadcastaddr = {0}; +static CCritSect ipx_critsect; +static SNETSPI_GAMELISTPTR ipx_gamehead = NULL; +static SOCKADDR_IPX ipx_localaddr = {0}; +static DWORD ipx_nextgameid = 0; +static SOCKET ipx_mainsocket = (SOCKET)0; +static DWORD ipx_maxplayers = MAXPLAYERS; +static PACKETPTR ipx_packethead = NULL; +static PACKETPTR ipx_pendingreadpkt[RECVDATATHREADS] = {NULL,NULL}; +static DWORD ipx_programid = 0; +static HANDLE ipx_recvevent = NULL; +static BOOL ipx_shutdown = 0; +static THREADPTR ipx_threadhead = NULL; +static DWORD ipx_versionid = 0; +static WINSOCKAPIPTR ipx_winsockapi = NULL; +static HINSTANCE ipx_winsocklib = (HINSTANCE)0; + +static void SendAdvertisement (SOCKADDR_IPX *addr); +static void SendRequest (); +static void TrimGameList (DWORD timeout); +static void UpdateGameList (HWND dialog, HWND listbox); +BOOL CALLBACK IpxCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude); +BOOL CALLBACK IpxStopAdvertisingGame (); + +//=========================================================================== +static BOOL inline BindToWinsock () { + + // LOAD THE WINSOCK LIBRARY + if (!ipx_winsocklib) { + ipx_winsocklib = LoadLibrary(TEXT("wsock32.dll")); + if (!ipx_winsocklib) + return 0; + } + + // ALLOCATE AN API STRUCTURE + if (!ipx_winsockapi) { + ipx_winsockapi = NEW(WINSOCKAPI); + if (!ipx_winsockapi) + return 0; + } + + // BIND TO THE INDIVIDUAL FUNCTIONS + BOOL success = 1; +#define BIND(a,b) *(void **)&ipx_winsockapi->##a \ + = GetProcAddress(ipx_winsocklib,(LPCSTR)MAKELONG((b),0)); \ + if (!ipx_winsockapi->##a) \ + success = 0; + BIND(bind ,2); + BIND(closesocket,3); + BIND(htons ,9); + BIND(recvfrom ,17); + BIND(sendto ,20); + BIND(setsockopt ,21); + BIND(socket ,23); + BIND(WSAStartup ,115); + BIND(WSACleanup ,116); +#undef BIND + return success; +} + +//=========================================================================== +static WORD ComputeChecksum (LPVOID data, DWORD databytes) { + DWORD checkval1 = 0; + DWORD checkval2 = 0; + LPBYTE ptr = ((LPBYTE)data)+databytes-1; + while (databytes--) { + checkval1 += *ptr--; + if (checkval1 >= 0xFF) + checkval1 -= 0xFF; + checkval2 += checkval1; + } + checkval2 %= 255; + return MAKEWORD((checkval2 & 0xFF),(checkval1 & 0xFF)); +} + +//=========================================================================== +static WORD GenerateChecksum (LPVOID packet, DWORD bytes) { + + // COMPUTE THE CURRENT CHECKSUM FOR THE MESSAGE + WORD checksum = ComputeChecksum(((LPBYTE)packet)+sizeof(WORD), + bytes-sizeof(WORD)); + + // COMPUTE A NEW VALUE FOR THE CHECKSUM FIELD THAT WILL MAKE THE NEW + // CHECKSUM OF THE ENTIRE MESSAGE ZERO + BYTE hibyte = 0xFF-((checksum >> 8)+(checksum & 0xFF)) % 0xFF; + BYTE lobyte = 0xFF-((checksum >> 8)+hibyte) % 0xFF; + return MAKEWORD(lobyte,hibyte); +} + +//=========================================================================== +static BOOL LoadArtwork (SNETGETARTPROC artcallback, + DWORD providerid, + DWORD artid, + BOOL setpalette, + LPBYTE *data, + SIZE *size) { + *data = 0; + size->cx = 0; + size->cy = 0; + + // VERIFY THAT THE APPLICATION HAS REGISTERED AN ARTWORK CALLBACK + if (!artcallback) + return 0; + + // CALL THE ARTWORK CALLBACK TO DETERMINE THE IMAGE DIMENSIONS + int width; + int height; + int bitdepth; + if (!artcallback(providerid, + artid, + NULL, + NULL, + 0, + &width, + &height, + &bitdepth)) + return 0; + if (size) { + size->cx = width; + size->cy = height; + } + + // ALLOCATE MEMORY FOR THE IMAGE + DWORD bytes = width*height*bitdepth/8; + if (!(*data = (LPBYTE)ALLOC(bytes))) + return 0; + + // LOAD THE IMAGE + PALETTEENTRY pe[256]; + if (!artcallback(providerid, + artid, + &pe[0], + *data, + bytes, + &width, + &height, + &bitdepth)) { + FREE(*data); + *data = NULL; + return 0; + } + + // IF REQUESTED, UPDATE THE SYSTEM PALETTE + if (setpalette) + SDrawUpdatePalette(1,254,&pe[1]); + + return 1; +} + +//=========================================================================== +static void ProcessIncomingAd (SOCKADDR_IPX *incomingaddr, + ADVPACKETPTR incomingad, + BOOL remove) { + + // FIX THE INCOMING ADDRESS SO IT POINTS TO THE MAIN PORT, + // NOT THE ADVERTISING PORT + if (ipx_winsockapi && ipx_winsockapi->htons) + incomingaddr->sa_socket = ipx_winsockapi->htons(MAINPORT); + + // ENTER THE CRITICAL SECTION + ipx_critsect.Enter(); + + // DELETE ALL GAMES IN OUR LIST FROM THIS ADDRESS + DWORD gameid = 0; + { + SNETSPI_GAMELISTPTR curr = ipx_gamehead; + while (curr) + if (!memcmp(&curr->owner,incomingaddr,sizeof(SOCKADDR_IPX))) { + gameid = curr->gameid; + SNETSPI_GAMELISTPTR next = curr->next; + FREEIFUSED(curr->clientdata); + LISTFREE(&ipx_gamehead,curr); + curr = next; + } + else + curr = curr->next; + } + + // IF THIS GAME WAS NOT ALREADY IN THE LIST, ADD A NEW ID FOR IT. + // MAKE SURE WE NEVER ASSIGN AN ID OF ZERO. + if (!gameid) + gameid = ++ipx_nextgameid; + if (!gameid) + gameid = ++ipx_nextgameid; + + // IF THIS GAME MATCHES OUR PROGRAM ID AND VERSION ID, AND WE'RE NOT + // REMOVING, THEN ADD IT TO THE LIST + if ((incomingad->header.programid == ipx_programid) && + (incomingad->header.versionid == ipx_versionid) && + !remove) { + SNETSPI_GAMELIST game; + ZeroMemory(&game,sizeof(SNETSPI_GAMELIST)); + game.gameid = gameid; + game.gamemode = incomingad->header.gamemode; + CopyMemory(&game.owner,incomingaddr,sizeof(SOCKADDR_IPX)); + game.ownerlatency = 50; + game.ownerlasttime = GetTickCount(); + LPSTR currptr = incomingad->strings; + strncpy(game.gamename, + currptr, + SNETSPI_MAXSTRINGLENGTH); + currptr += strlen(currptr)+1; + strncpy(game.gamedescription, + currptr, + SNETSPI_MAXSTRINGLENGTH); + currptr += strlen(currptr)+1; + game.clientdatabytes = (incomingad->header.length-(currptr-(LPSTR)incomingad)); + game.clientdata = ALLOC(game.clientdatabytes); + CopyMemory(game.clientdata,currptr,game.clientdatabytes); + LISTADD(&ipx_gamehead,&game); + } + + // LEAVE THE CRITICAL SECTION + ipx_critsect.Leave(); + +} + +//=========================================================================== +static unsigned CALLBACK RecvAdThreadProc (LPVOID param) { + if (!(ipx_winsockapi && ipx_winsockapi->recvfrom)) { + _endthreadex(0); + return 0; + } + + // SEND OUT A REQUEST FOR ADVERTISEMENTS + SendRequest(); + + ADVPACKET incomingad; + while (ipx_advsocket && !ipx_shutdown) { + + // PROCESS ALL INCOMING ADVERTISEMENTS + SOCKADDR_IPX incomingaddr; + int addrsize = sizeof(SOCKADDR_IPX); + int bytesread = 0; + bytesread = ipx_winsockapi->recvfrom(ipx_advsocket, + (char *)&incomingad, + sizeof(ADVPACKET), + 0, + (sockaddr *)&incomingaddr, + &addrsize); + PerfIncrement(PERF_PKTRECV); + PerfAdd(PERF_BYTESRECV,bytesread); + if ((bytesread >= sizeof(ADVHEADER)) && + (incomingad.header.length == bytesread) && + !ComputeChecksum(&incomingad,incomingad.header.length)) + switch (incomingad.header.type) { + + case ADTYPE_GAMEINFO: + case ADTYPE_REMOVE: + ProcessIncomingAd(&incomingaddr, + &incomingad, + (incomingad.header.type == ADTYPE_REMOVE)); + break; + + case ADTYPE_REQUEST: + SendAdvertisement(&incomingaddr); + break; + + } + + } + + // FREE THE LIST OF GAMES + { + SNETSPI_GAMELISTPTR curr; + while ((curr = ipx_gamehead) != NULL) { + FREEIFUSED(curr->clientdata); + LISTFREE(&ipx_gamehead,curr); + } + } + + _endthreadex(0); + return 0; +} + +//=========================================================================== +static unsigned CALLBACK RecvDataThreadProc (LPVOID param) { + if (!(ipx_winsockapi && ipx_winsockapi->recvfrom)) { + _endthreadex(0); + return 0; + } + while (ipx_mainsocket && !ipx_shutdown) { + + // ALLOCATE MEMORY FOR THE NEXT INCOMING PACKET + PACKETPTR pkt = NEW(PACKET); + int loop; + ipx_critsect.Enter(); + for (loop = 0; loop < RECVDATATHREADS; ++loop) + if (!ipx_pendingreadpkt[loop]) { + ipx_pendingreadpkt[loop] = pkt; + break; + } + ipx_critsect.Leave(); + + // RECEIVE A PACKET, BLOCKING IF ONE IS NOT AVAILABLE YET. WHEN THE + // NETWORK DRIVER HAS INCOMING DATA ON A PORT, IT WILL COPY IT DIRECTLY + // TO THE APPLICATION'S ADDRESS SPACE IF THE APPLICATION IS BLOCKING ON + // A READ. FOR THIS REASON, WE TRY TO ALWAYS HAVE AT LEAST ONE READ + // PENDING. + int addrsize = sizeof(SOCKADDR_IPX); + int bytesread = 0; + bytesread = ipx_winsockapi->recvfrom(ipx_mainsocket, + (char *)&pkt->data, + MAXMESSAGESIZE, + 0, + (sockaddr *)&pkt->addr, + &addrsize); + PerfIncrement(PERF_PKTRECV); + PerfAdd(PERF_BYTESRECV,bytesread); + pkt->databytes = bytesread; + ZeroMemory(((LPBYTE)&pkt->addr)+addrsize,sizeof(SNETADDR)-addrsize); + + // ON A SUCCESSFUL READ, QUEUE THE PACKET. SINCE WE DON'T TIME OUT ON + // READS, THE ONLY WAY A READ CAN FAIL IS IF THE SOCKET WAS CLOSED. + // IN THIS CASE, SHUT DOWN THE THREAD. + ipx_critsect.Enter(); + for (loop = 0; loop < RECVDATATHREADS; ++loop) + if (ipx_pendingreadpkt[loop] == pkt) { + ipx_pendingreadpkt[loop] = NULL; + break; + } + BOOL success = (bytesread >= 0) && !ipx_shutdown; + if (success) + LISTADDPTREND(&ipx_packethead,pkt); + else + FREE(pkt); + ipx_critsect.Leave(); + + if (success) + SetEvent(ipx_recvevent); + else { + _endthreadex(0); + return 0; + } + + + } + return 0; +} + +//=========================================================================== +static BOOL CALLBACK SelectGameDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + static LPBYTE background = NULL; + static LPBYTE buttontexture = NULL; + static UIPARAMSPTR uiparams = NULL; + switch (message) { + + case WM_COMMAND: + + // IF THE USER CLICKED 'JOIN GAME', TRY TO JOIN THE SELECTED GAME + if (LOWORD(wparam) == IDOK) { + LPARAM cursel = SendDlgItemMessage(window,IDC_GAMELIST,LB_GETCURSEL,0,0); + if (cursel != LB_ERR) { + char fullname[2*SNETSPI_MAXSTRINGLENGTH] = ""; + SendDlgItemMessage(window,IDC_GAMELIST,LB_GETTEXT,cursel,(LPARAM)fullname); + if (fullname[0]) { + if (strchr(fullname,'\t')) + *strchr(fullname,'\t') = 0; + if (SNetJoinGame(0, + fullname, + NULL, + uiparams->playerdata->playername, + uiparams->playerdata->playerdescription, + uiparams->playeridptr)) { + KillTimer(window,1); + SDlgEndDialog(window,1); + } + else + uiparams->interfacedata->messageboxcallback(window, + "Unable to connect.", + uiparams->programdata->programname, + 0); + } + } + } + + // IF THE USER CLICKED 'CREATE GAME', CALL THE CREATE GAME CALLBACK + else if ((LOWORD(wparam) == IDC_CREATEGAME) && + uiparams->interfacedata->createcallback) { + + // BUILD A NEW INTERFACE DATA STRUCTURE CONTAINING OUR WINDOW HANDLE + SNETUIDATA interfacedata; + CopyMemory(&interfacedata,uiparams->interfacedata,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = window; + + // BUILD A CREATION DATA STRUCTURE + SNETCREATEDATA createdata; + ZeroMemory(&createdata,sizeof(SNETCREATEDATA)); + createdata.size = sizeof(SNETCREATEDATA); + createdata.providerid = PROVIDERID; + createdata.maxplayers = ipx_maxplayers; + createdata.createflags = 0; + + // CALL THE CREATE GAME CALLBACK + if (uiparams->interfacedata->createcallback(&createdata, + uiparams->programdata, + uiparams->playerdata, + &interfacedata, + uiparams->versiondata, + uiparams->playeridptr)) { + KillTimer(window,1); + SDlgEndDialog(window,1); + } + + } + + // IF THE USER CLICKED 'DISCONNECT', END THE DIALOG + else if (LOWORD(wparam) == IDCANCEL) { + KillTimer(window,1); + SDlgEndDialog(window,0); + } + + // IF THE USER SELECTED A NEW LIST BOX ITEM, UPDATE THE GAME + // DESCRIPTION + else if ((LOWORD(wparam) == IDC_GAMELIST) && + (HIWORD(wparam) == LBN_SELCHANGE)) + InvalidateRect(GetDlgItem(window,IDC_GAMEDESCRIPTION),NULL,1); + + // IF THE USER DOUBLE-CLICKED A LIST BOX ITEM, POST AN 'OK' COMMAND + else if ((LOWORD(wparam) == IDC_GAMELIST) && + (HIWORD(wparam) == LBN_DBLCLK)) + PostMessage(window,WM_COMMAND,MAKELONG(IDOK,BN_CLICKED),(LPARAM)GetDlgItem(window,IDOK)); + + break; + + case WM_DESTROY: + if (background) { + FREE(background); + background = NULL; + } + if (buttontexture) { + FREE(buttontexture); + buttontexture = NULL; + } + uiparams = NULL; + break; + + case WM_DRAWITEM: + if (wparam == IDC_GAMEDESCRIPTION) { + + // GET THE GAME NAME AND DESCRIPTION + char name[256] = ""; + { + LRESULT sel = SendDlgItemMessage(window,IDC_GAMELIST,LB_GETCURSEL,0,0); + if (sel != LB_ERR) + SendDlgItemMessage(window,IDC_GAMELIST,LB_GETTEXT,sel,(LPARAM)name); + } + LPSTR description = ""; + if (strchr(name,'\t')) { + description = strchr(name,'\t'); + *description++ = 0; + } + + // UPDATE THE DESCRIPTION IN THE STATIC TEXT CONTROL + { + char buffer[256] = ""; + GetDlgItemText(window,IDC_GAMEDESCRIPTION,buffer,256); + buffer[255] = 0; + if (strcmp(buffer,description)) + SetDlgItemText(window,IDC_GAMEDESCRIPTION,description); + } + + // IF THE APPLICATION HAS REGISTERED A DRAW DESCRIPTION CALLBACK, + // LET IT DRAW THE DESCRIPTION + if (uiparams->interfacedata->drawdesccallback) + return uiparams->interfacedata->drawdesccallback(PROVIDERID, + SNET_DRAWTYPE_GAME, + name, + description, + 0, + 0, + SNET_DDF_MULTILINE, + (LPDRAWITEMSTRUCT)lparam); + + // OTHERWISE, LET THE DEFAULT DIALOG BOX PROCEDURE DRAW THE + // DESCRIPTION FROM THE STATIC TEXT + else + return 0; + + } + break; + + case WM_INITDIALOG: + + // SAVE A POINTER TO THE USER INTERFACE PARAMETERS + uiparams = (UIPARAMSPTR)lparam; + + // LOAD THE ARTWORK FOR THIS DIALOG + { + SIZE size; + if (LoadArtwork(uiparams->interfacedata->artcallback, + PROVIDERID, + SNET_ART_BACKGROUND, + 1, + &background, + &size)) { + SDlgSetBitmap(window, + NULL, + "", + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + background, + NULL, + size.cx, + size.cy); + int controllist[2] = {IDC_GAMEDESCRIPTION,0}; + SDlgSetControlBitmaps(window, + &controllist[0], + NULL, + background, + &size, + SDLG_ADJUST_CONTROLPOS); + } + if (LoadArtwork(uiparams->interfacedata->artcallback, + PROVIDERID, + SNET_ART_BUTTONTEXTURE, + 0, + &buttontexture, + &size)) { + int controllist[4] = {IDC_CREATEGAME,IDOK,IDCANCEL,0}; + SDlgSetControlBitmaps(window, + &controllist[0], + NULL, + buttontexture, + &size, + SDLG_ADJUST_VERTICAL); + } + } + + // DRAW THE PROGRAM DESCRIPTION + SetDlgItemTextA(window,IDC_PROGRAMDESCRIPTION,uiparams->programdata->programdescription); + + // SET THE FIRST TAB STOP FOR THE GAME LIST TO WIDER THAN THE LIST BOX, + // TO HIDE ALL TABBED TEXT + { + RECT rect; + GetClientRect(GetDlgItem(window,IDC_GAMELIST),&rect); + SendDlgItemMessage(window,IDC_GAMELIST,LB_SETTABSTOPS,1,(LPARAM)&rect.right); + } + + PostMessage(window,WM_USER,0,0); + SetTimer(window,1,500,NULL); + return 1; + + case WM_TIMER: + case WM_USER: + SendRequest(); + TrimGameList(3000); + UpdateGameList(window,GetDlgItem(window,IDC_GAMELIST)); + break; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//=========================================================================== +static void SendAdvertisement (SOCKADDR_IPX *addr) { + ipx_critsect.Enter(); + if (ipx_advgameinfo && ipx_winsockapi && ipx_winsockapi->sendto) { + ipx_winsockapi->sendto(ipx_advsocket, + (const char *)ipx_advgameinfo, + ipx_advgameinfo->header.length, + 0, + (const sockaddr *)(addr ? addr : &ipx_broadcastaddr), + sizeof(SOCKADDR_IPX)); + PerfIncrement(PERF_PKTSENT); + PerfAdd(PERF_BYTESSENT,ipx_advgameinfo->header.length); + } + ipx_critsect.Leave(); +} + +//=========================================================================== +static void SendRequest () { + ADVHEADER request; + ZeroMemory(&request,sizeof(ADVHEADER)); + request.length = sizeof(ADVHEADER); + request.type = ADTYPE_REQUEST; + request.programid = ipx_programid; + request.versionid = ipx_versionid; + request.checksum = GenerateChecksum(&request,sizeof(ADVHEADER)); + if (ipx_winsockapi && ipx_winsockapi->sendto) + ipx_winsockapi->sendto(ipx_advsocket, + (const char *)&request, + request.length, + 0, + (const sockaddr *)&ipx_broadcastaddr, + sizeof(SOCKADDR_IPX)); + PerfIncrement(PERF_PKTSENT); + PerfAdd(PERF_BYTESSENT,request.length); +} + +//=========================================================================== +static void TrimGameList (DWORD timeout) { + ipx_critsect.Enter(); + { + DWORD currtime = GetTickCount(); + SNETSPI_GAMELISTPTR *next = &ipx_gamehead; + while (*next) + if (currtime-(*next)->ownerlasttime > timeout) { + SNETSPI_GAMELISTPTR freeptr = *next; + *next = (*next)->next; + FREEIFUSED(freeptr->clientdata); + FREE(freeptr); + } + else + next = &(*next)->next; + } + ipx_critsect.Leave(); +} + +//=========================================================================== +static void UpdateGameList (HWND dialog, HWND listbox) { + ipx_critsect.Enter(); + + // MAKE SURE ALL GAMES IN THE LINKED LIST ARE REPRESENTED IN THE LIST BOX + { + SNETSPI_GAMELISTPTR curr = ipx_gamehead; + while (curr) { + if (!(curr->gamemode & SNET_GM_UNLISTEDMASK)) { + char fullstring[2*SNETSPI_MAXSTRINGLENGTH]; + sprintf(fullstring,"%s\t%s",curr->gamename,curr->gamedescription); + if (SendMessage(listbox,LB_FINDSTRINGEXACT,(WPARAM)-1,(LPARAM)fullstring) == LB_ERR) { + SendMessage(listbox,LB_ADDSTRING,0,(LPARAM)fullstring); + EnableWindow(GetDlgItem(dialog,IDOK),1); + if (SendMessage(listbox,LB_GETCURSEL,0,0) == LB_ERR) { + SendMessage(listbox,LB_SETCURSEL,0,0); + SendMessage(dialog,WM_COMMAND,MAKELONG(IDC_GAMELIST,LBN_SELCHANGE),(LPARAM)listbox); + } + } + } + curr = curr->next; + } + } + + // MAKE SURE THERE ARE NO GAME IN THE LIST BOX THAT AREN'T IN THE LINKED LIST + { + char liststring[2*SNETSPI_MAXSTRINGLENGTH]; + WPARAM index = 0; + while (SendMessage(listbox,LB_GETTEXT,index,(LPARAM)liststring) != LB_ERR) { + SNETSPI_GAMELISTPTR curr = ipx_gamehead; + while (curr) { + if (!(curr->gamemode & SNET_GM_UNLISTEDMASK)) { + char fullstring[2*SNETSPI_MAXSTRINGLENGTH]; + sprintf(fullstring,"%s\t%s",curr->gamename,curr->gamedescription); + if (!strcmp(fullstring,liststring)) + break; + } + curr = curr->next; + } + if (!curr) { + if (SendMessage(listbox,LB_GETCURSEL,0,0) == (LRESULT)index) { + SendMessage(listbox,LB_SETCURSEL,index-1,0); + SendMessage(dialog,WM_COMMAND,MAKELONG(IDC_GAMELIST,LBN_SELCHANGE),(LPARAM)listbox); + } + if (!SendMessage(listbox,LB_DELETESTRING,index,0)) + EnableWindow(GetDlgItem(dialog,IDOK),0); + } + else + ++index; + } + } + + ipx_critsect.Leave(); +} + +/**************************************************************************** +* +* SERVICE PROVIDER INTERFACE FUNCTIONS +* +***/ + +//=========================================================================== +BOOL CALLBACK IpxCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude) { + if (diffmagnitude) + *diffmagnitude = 0; + if (!(addr1 && addr2 && diffmagnitude)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // COMPARE THE ADDRESSES, AND RETURN: + // 2 IF THEY ARE ON DIFFERENT NETWORKS + // 1 IF THEY ARE DIFFERENT ADDRESSES ON THE SAME NETWORK + // 0 IF THEY ARE THE SAME ADDRESS + SOCKADDR_IPX *ipxaddr1 = (SOCKADDR_IPX *)addr1; + SOCKADDR_IPX *ipxaddr2 = (SOCKADDR_IPX *)addr2; + if ((*(DWORD *)&ipxaddr1->sa_netnum) != + (*(DWORD *)&ipxaddr2->sa_netnum)) + *diffmagnitude = 2; + else if (memcmp(ipxaddr1,ipxaddr2,sizeof(SOCKADDR_IPX))) + *diffmagnitude = 1; + else + *diffmagnitude = 0; + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxDestroy () { + + // START THE SHUTDOWN PROCESS + ipx_shutdown = TRUE; + + // SEND DATA TO THE RECEIVE THREADS TO WAKE THEM UP + { + SOCKADDR_IPX sendaddr; + CopyMemory(&sendaddr,&ipx_broadcastaddr,sizeof(SOCKADDR_IPX)); + BYTE buffer[8] = {0x08,0xEF,0x08,0x00,0x00,0x00,0x00,0x00}; + if (ipx_winsockapi && ipx_winsockapi->htons) + sendaddr.sa_socket = ipx_winsockapi->htons(ADVPORT); + if (ipx_winsockapi && ipx_winsockapi->sendto) + ipx_winsockapi->sendto(ipx_advsocket,(const char *)&buffer[0],8,0,(const sockaddr *)&sendaddr,sizeof(SOCKADDR_IPX)); + if (ipx_winsockapi && ipx_winsockapi->htons) + sendaddr.sa_socket = ipx_winsockapi->htons(MAINPORT); + if (ipx_winsockapi && ipx_winsockapi->sendto) + for (int loop = 0; loop < RECVDATATHREADS; ++loop) + ipx_winsockapi->sendto(ipx_mainsocket,(const char *)&buffer[0],8,0,(sockaddr *)&sendaddr,sizeof(SOCKADDR_IPX)); + } + + // WAIT FOR ALL THREADS TO TERMINATE + while (ipx_threadhead) { + WaitForSingleObject(ipx_threadhead->handle,100); + CloseHandle(ipx_threadhead->handle); + LISTFREE(&ipx_threadhead,ipx_threadhead); + } + + // CLOSE THE SOCKETS + if (ipx_mainsocket) { + if (ipx_winsockapi && ipx_winsockapi->closesocket) + ipx_winsockapi->closesocket(ipx_mainsocket); + ipx_mainsocket = (SOCKET)0; + } + if (ipx_advsocket) { + if (ipx_winsockapi && ipx_winsockapi->closesocket) + ipx_winsockapi->closesocket(ipx_advsocket); + ipx_advsocket = (SOCKET)0; + } + + // TAKE CONTROL OF THE CRITICAL SECTION + ipx_critsect.Enter(); + + // FREE THE GAME INFO + IpxStopAdvertisingGame(); + { + SNETSPI_GAMELISTPTR curr; + while ((curr = ipx_gamehead) != NULL) { + FREEIFUSED(curr->clientdata); + LISTFREE(&ipx_gamehead,curr); + } + } + + // FREE ALL UNPROCESSED PACKETS + LISTCLEAR(&ipx_packethead); + for (int loop = 0; loop < RECVDATATHREADS; ++loop) + if (ipx_pendingreadpkt[loop]) + FREE(ipx_pendingreadpkt[loop]); + + // CLEAN UP WINDOWS SOCKETS + if (ipx_winsockapi && ipx_winsockapi->WSACleanup) + ipx_winsockapi->WSACleanup(); + if (ipx_winsockapi) { + FREE(ipx_winsockapi); + ipx_winsockapi = NULL; + } + if (ipx_winsocklib) { + FreeLibrary(ipx_winsocklib); + ipx_winsocklib = (HINSTANCE)0; + } + + // LEAVE THE CRITICAL SECTION + ipx_critsect.Leave(); + + // FINISH THE SHUTDOWN PROCESS + ipx_shutdown = 0; + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxFree (SNETADDRPTR addr, + LPVOID data, + DWORD databytes) { + if (!(addr && data)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + FREE(addr); + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxFreeExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR mesage) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxGetGameInfo (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + SNETSPI_GAMELIST *gameinfo) { + if (gameinfo) + ZeroMemory(gameinfo,sizeof(SNETSPI_GAMELIST)); + if (!(gamename && gameinfo && (gameid || *gamename))) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // SEARCH FOR A GAME IN THE GAME LIST MATCHING THE QUERY PARAMETERS + ipx_critsect.Enter(); + { + SNETSPI_GAMELISTPTR curr = ipx_gamehead; + while (curr) + if (((!gameid) || (gameid == curr->gameid)) && + ((!*gamename) || !_stricmp(gamename,curr->gamename))) { + CopyMemory(gameinfo,curr,sizeof(SNETSPI_GAMELIST)); + break; + } + else + curr = curr->next; + } + ipx_critsect.Leave(); + + if (gameinfo->gameid) + return 1; + else { + SetLastError(SNET_ERROR_GAME_NOT_FOUND); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK IpxGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq) { + return PerfGetPerformanceData(counterid, + countervalue, + measurementtime, + measurementfreq); +} + +//=========================================================================== +BOOL CALLBACK IpxInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + HANDLE event) { + + // SAVE THE PROGRAM AND VERSION IDS AND THE RECEIVE EVENT HANDLE + ipx_programid = programdata->programid; + ipx_versionid = programdata->versionid; + ipx_maxplayers = min(programdata->maxplayers,MAXPLAYERS); + ipx_recvevent = event; + + // RESET PERFORMANCE DATA + PerfReset(); + + // BIND TO WINSOCK + if (!BindToWinsock()) + return 0; + + // INITIALIZE WINDOWS SOCKETS + { + WSADATA data; + if (ipx_winsockapi->WSAStartup(MAKEWORD(1,1),&data)) { + IpxDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + } + + // CREATE TWO SOCKETS: ONE FOR APPLICATION DATA AND ONE FOR ADVERTISING + ipx_advsocket = ipx_winsockapi->socket(PF_NS,SOCK_DGRAM,NSPROTO_IPX); + ipx_mainsocket = ipx_winsockapi->socket(PF_NS,SOCK_DGRAM,NSPROTO_IPX); + if (!(ipx_advsocket && ipx_mainsocket)) { + IpxDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + + // DETERMINE THE BROADCAST ADDRESS + { + ZeroMemory(&ipx_broadcastaddr,sizeof(SOCKADDR_IPX)); + for (int loop = 0; loop < 6; ++loop) + ipx_broadcastaddr.sa_nodenum[loop] = (BYTE)0xFF; + ipx_broadcastaddr.sa_family = AF_IPX; + ipx_broadcastaddr.sa_socket = ipx_winsockapi->htons(ADVPORT); + } + + // BIND TO THE MAIN SOCKET, DETERMINING OUR LOCAL ADDRESS + ZeroMemory(&ipx_localaddr,sizeof(SOCKADDR_IPX)); + ipx_localaddr.sa_family = AF_IPX; + ipx_localaddr.sa_socket = ipx_winsockapi->htons(MAINPORT); + if (ipx_winsockapi->bind(ipx_mainsocket, + (const struct sockaddr *)&ipx_localaddr, + sizeof(SOCKADDR_IPX))) { + IpxDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + + // BIND TO THE ADVERTISING SOCKET + { + SOCKADDR_IPX advaddr; + CopyMemory(&advaddr,&ipx_localaddr,sizeof(SOCKADDR_IPX)); + advaddr.sa_socket = ipx_winsockapi->htons(ADVPORT); + if (ipx_winsockapi->bind(ipx_advsocket, + (const struct sockaddr *)&advaddr, + sizeof(SOCKADDR_IPX))) { + IpxDestroy(); + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + } + + // ALLOW BROADCASTS TO BE SENT ON THE SOCKETS (DUE TO A BUG IN WINDOWS 95, + // THIS OPTION IS ALSO REQUIRED FOR RECEIVING BROADCASTS) + { + BOOL value = 1; + ipx_winsockapi->setsockopt(ipx_advsocket, + SOL_SOCKET, + SO_BROADCAST, + (const char *)&value, + sizeof(BOOL)); + ipx_winsockapi->setsockopt(ipx_mainsocket, + SOL_SOCKET, + SO_BROADCAST, + (const char *)&value, + sizeof(BOOL)); + } + + // CREATE A THREAD TO RECEIVE PACKETS ON THE ADVERTISING SOCKET + { + THREAD thread; + thread.handle = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + RecvAdThreadProc, + NULL, + 0, + &thread.id); + if (thread.handle) { + SetThreadPriority(thread.handle,THREAD_PRIORITY_ABOVE_NORMAL); + LISTADD(&ipx_threadhead,&thread); + } + } + + // CREATE THREADS TO READ PACKETS FROM THE MAIN SOCKET + { + BOOL win95 = GetVersion() & 0x80000000; + int threads = win95 ? 1 : RECVDATATHREADS; + for (int loop = 0; loop < threads; ++loop) { + THREAD thread; + thread.handle = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES)NULL, + 0, + RecvDataThreadProc, + NULL, + 0, + &thread.id); + if (thread.handle) { + SetThreadPriority(thread.handle,THREAD_PRIORITY_HIGHEST); + LISTADD(&ipx_threadhead,&thread); + } + } + } + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + + // WE NEVER RETURN ANY DEVICES, SO THIS FUNCTION SHOULD NEVER BE CALLED + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxLockDeviceList (SNETSPI_DEVICELISTPTR *devicelist) { + *devicelist = NULL; + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxLockGameList (DWORD categorybits, + DWORD categorymask, + SNETSPI_GAMELISTPTR *gamelist) { + if (!gamelist) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // TRIM ANY GAMES THAT WE HAVEN'T HEARD FROM IN A WHILE + { + static DWORD lasttime = GetTickCount(); + DWORD currtime = GetTickCount(); + TrimGameList(max(3000,2*(currtime-lasttime))); + } + + // LOCK THE GAME LIST + ipx_critsect.Enter(); + *gamelist = ipx_gamehead; + + return 1; +} + +//=========================================================================== +/* +BOOL CALLBACK IpxReceive (SNETADDRPTR *addr, + LPVOID *data, + DWORD *databytes) { +*/ +BOOL CALLBACK IpxReceive (LPVOID *data, + DWORD *databytes, + SNETADDRPTR *addr) { + if (addr) + *addr = NULL; + if (data) + *data = NULL; + if (databytes) + *databytes = NULL; + if (!(addr && data && databytes && ipx_mainsocket)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // IF THERE IS A PACKET QUEUED, REMOVE IT FROM THE QUEUE AND RETURN + // POINTERS TO THE CALLER. NOTE THAT WE UNLINK THE PACKET BUT DON'T + // FREE IT FROM MEMORY; IT IS THE CALLER'S RESPONSIBILITY TO CALL + // OUR FREE FUNCTION WHEN IT IS DONE WITH THE PACKET. + if (ipx_packethead) { + ipx_critsect.Enter(); + *addr = &ipx_packethead->addr; + *data = ipx_packethead->data; + *databytes = ipx_packethead->databytes; + ipx_packethead = ipx_packethead->next; + ipx_critsect.Leave(); + return 1; + } + else { + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK IpxReceiveExternalMessage (LPCSTR *senderpath, + LPCSTR *sendername, + LPCSTR *message) { + if (senderpath) + *senderpath = NULL; + if (sendername) + *sendername = NULL; + if (message) + *message = NULL; + + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + + // BUILD A USER INTERFACE DATA BLOCK + UIPARAMS uiparams; + ZeroMemory(&uiparams,sizeof(UIPARAMS)); + uiparams.flags = flags; + uiparams.programdata = programdata; + uiparams.playerdata = playerdata; + uiparams.interfacedata = interfacedata; + uiparams.versiondata = versiondata; + uiparams.playeridptr = playerid; + + // DISPLAY THE DIALOG BOX + DWORD result = (DWORD)SDlgDialogBoxParam(global_instance, + "IPXSELECTGAME_DIALOG", + interfacedata ? interfacedata->parentwindow + : SDrawGetFrameWindow(), + SelectGameDialogProc, + (LPARAM)&uiparams); + + return (result && (result != 0xFFFFFFFF)); +} + +//=========================================================================== +BOOL CALLBACK IpxSend (DWORD addresses, + SNETADDRPTR *addrlist, + LPVOID data, + DWORD databytes) { + if (!(addresses && addrlist && data && databytes && ipx_mainsocket)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // SEND THE PACKET + if (ipx_winsockapi && ipx_winsockapi->sendto) + while (addresses--) { + ipx_winsockapi->sendto(ipx_mainsocket, + (const char *)data, + databytes, + 0, + (const sockaddr *)*(addrlist+addresses), + sizeof(SOCKADDR_IPX)); + PerfIncrement(PERF_PKTSENT); + PerfAdd(PERF_BYTESSENT,databytes); + } + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxSendExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR targetpath, + LPCSTR targetname, + LPCSTR message) { + return 0; +} + +//=========================================================================== +BOOL CALLBACK IpxStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD gameage, + DWORD gamecategorybits, + DWORD optcategorybits, + LPCVOID clientdata, + DWORD clientdatabytes) { + if (!(gamename && gamedescription)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // CREATE A STRUCTURE TO CONTAIN THE DATA WE NEED TO ADVERTISE + ipx_critsect.Enter(); + if (!ipx_advgameinfo) { + ipx_advgameinfo = NEW(ADVPACKET); + if (!ipx_advgameinfo) { + ipx_critsect.Leave(); + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + ZeroMemory(ipx_advgameinfo,sizeof(ADVPACKET)); + ipx_advgameinfo->header.checksum = 0; + ipx_advgameinfo->header.length = sizeof(ADVHEADER) + +strlen(gamename) + +strlen(gamedescription) + +2 + +clientdatabytes; + ipx_advgameinfo->header.type = ADTYPE_GAMEINFO; + ipx_advgameinfo->header.reserved = 0; + ipx_advgameinfo->header.programid = ipx_programid; + ipx_advgameinfo->header.versionid = ipx_versionid; + ipx_advgameinfo->header.gamemode = gamemode; + LPSTR currptr = ipx_advgameinfo->strings; + SStrCopy(currptr, + gamename, + SNETSPI_MAXSTRINGLENGTH); + currptr += strlen(currptr)+1; + SStrCopy(currptr, + gamedescription, + SNETSPI_MAXSTRINGLENGTH); + currptr += strlen(currptr)+1; + CopyMemory(currptr, + clientdata, + clientdatabytes); + ipx_advgameinfo->header.checksum = GenerateChecksum(ipx_advgameinfo, + ipx_advgameinfo->header.length); + ipx_critsect.Leave(); + + // SEND THE FIRST ADVERTISEMENT + SendAdvertisement(NULL); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxStopAdvertisingGame () { + + // DELETE THE ADVERTISEMENT DATA AND SEND OUT A REMOVE GAME MESSAGE + ipx_critsect.Enter(); + if (ipx_advgameinfo) { + ipx_advgameinfo->header.checksum = 0; + ipx_advgameinfo->header.type = ADTYPE_REMOVE; + ipx_advgameinfo->header.checksum = GenerateChecksum(ipx_advgameinfo, + ipx_advgameinfo->header.length); + if (ipx_winsockapi && ipx_winsockapi->sendto) + ipx_winsockapi->sendto(ipx_advsocket, + (const char *)ipx_advgameinfo, + ipx_advgameinfo->header.length, + 0, + (const sockaddr *)&ipx_broadcastaddr, + sizeof(SOCKADDR_IPX)); + PerfIncrement(PERF_PKTSENT); + PerfAdd(PERF_BYTESSENT,ipx_advgameinfo->header.length); + FREE(ipx_advgameinfo); + ipx_advgameinfo = NULL; + } + ipx_critsect.Leave(); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxUnlockDeviceList (SNETSPI_DEVICELISTPTR devicelist) { + return 1; +} + +//=========================================================================== +BOOL CALLBACK IpxUnlockGameList (SNETSPI_GAMELISTPTR gamelist, + DWORD *hintnextcall) { + if (gamelist != ipx_gamehead) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // UNLOCK THE GAME LIST + ipx_critsect.Leave(); + if (hintnextcall) + *hintnextcall = 500; + + // SEND OUT A REQUEST FOR ADVERTISEMENTS, SO WE WILL HAVE UPDATED DATA + // THE NEXT TIME IT IS REQUESTED + { + static DWORD lasttime = 0; + DWORD currtime = GetTickCount(); + if (currtime-lasttime > 400) { + lasttime = currtime; + SendRequest(); + } + } + + return 1; +} + +/**************************************************************************** +* +* EXPORTED STRUCTURES +* +***/ + +DWORD ipx_id = PROVIDERID; +LPCSTR ipx_desc = "Local Area Network (IPX)"; +LPCSTR ipx_req = "All computers must be connected to an IPX-compatible network."; +SNETCAPS ipx_caps = {sizeof(SNETCAPS), // size + SNET_CAPS_PAGELOCKEDBUFFERS // flags + | SNET_CAPS_BASICINTERFACE +#ifdef _DEBUG + | SNET_CAPS_DEBUGONLY, +#else + | SNET_CAPS_RETAILONLY, +#endif + MAXMESSAGESIZE, // max message size + 16, // max queue size, + MAXPLAYERS, // max players, + 100000, // bytes per second + 50, // latency (ms) + 8, // default turns per second + 2}; // default turns in transit +SNETSPI ipx_spi = {sizeof(SNETSPI), + IpxCompareNetAddresses, + IpxDestroy, + IpxFree, + IpxFreeExternalMessage, + IpxGetGameInfo, + IpxGetPerformanceData, + IpxInitialize, + IpxInitializeDevice, + IpxLockDeviceList, + IpxLockGameList, + IpxReceive, + IpxReceiveExternalMessage, + IpxSelectGame, + IpxSend, + IpxSendExternalMessage, + IpxStartAdvertisingGame, + IpxStopAdvertisingGame, + IpxUnlockDeviceList, + IpxUnlockGameList}; diff --git a/src/Storm/SOURCE/STANDARD/MODEM.CPP b/src/Storm/SOURCE/STANDARD/MODEM.CPP new file mode 100644 index 0000000..70fe7cc --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/MODEM.CPP @@ -0,0 +1,2216 @@ +/**************************************************************************** +* +* MODEM.CPP +* Modem provider +* +* By Jeff Strain (11/21/96) +* +* File History: +* 11/28/96 1.00 (js) Initial version +* 02/03/97 1.10 (js) Fixes for shitty non-error correcting modems +* and noisy lines +* (js) Now returning unique busy status +* (js) Full packet signatures +* (js) Pulse dialing +* +***/ + +#include "pch.h" + +// This is just so that functions will show up in the globals list in +// MSDEV Studio. +#define STATIC static + +// Prevents compilation of internal UI code +#define PROVIDERUI + +// CATCHES INTERNAL TEST VERSIONS +// EXPIRES MARCH 01, 1997 +// #define EXPIRATION {1997, 3, 0, 1} // YEAR, MONTH, NULL, DAY + +// Need this when compiling under NT4 - otherwise does not generate +// a Win95 compatible TAPI version, This *must* be included before +// tapi.h! +#define TAPI_CURRENT_VERSION 0x00010004 +#include + +#include + +// MAX TIME (MS) BETWEEN CLIENT AND HOST CONNECTION NOTIFICATIONS +#define MAX_CONNECT_DIFFERENTIAL 10000 + +#define HANDSHAKE_TIMEOUT 5000 +#define ANSWERTIMEOUT INFINITE + +// Time in ms to wait for game info after connection +#define FINDGAMETIMEOUT MAX_CONNECT_DIFFERENTIAL + HANDSHAKE_TIMEOUT + +#define READTIMEOUT 25 // in ms + +#define MAXMESSAGESIZE 180 // BE CAREFUL NOT TO FALL BELOW THE APP MIN +#define MAXPLAYERS 2 +#define PORTS 1 +#define PROVIDERID 'MODM' +#define READBUFFERSIZE 64 +#define HEADER_KEY_SEQ {'N','R','M','L'} +#define HEADER_KEYS 4 + +#define STATE_NOGAME 0 +#define STATE_SHUTDOWN 1 + +#define TAPISTATE_SHUTDOWN 0 +#define TAPISTATE_ACTIVE 1 + +#define TYPE_USERDATA 0 +#define TYPE_SYSTEMDATA 1 +#define TYPE_LASTDATA 1 + +#define SYS_UNUSED 0 +#define SYS_QUERYID 1 +#define SYS_ASSERTID 2 +#define SYS_QUERYGAME 9 +#define SYS_GAMEINFO 10 +#define SYS_REMOVE 11 + +// SYSTEM MESSAGE SYMBOLS FOR 2-WAY HANDSHAKE. THIS IS NECCESSARY +// SINCE THERE CAN BE A DIFFERENTIAL IN CONNECTION NOTIFICATION +// BETWEEN CALLER AND HOST OF UP TO 5 SECONDS AND THE QUERY +// GAME CAN BE LOST. NOTE THAT A 3-WAY HANDSHAKE IS NOT NECCESSARY +// SINCE WE DO NOT NEED TO TEST THE LINE, JUST THE STARTUP OF THE +// REMOTE SYSEM. +#define SYS_QUERYLINE 3 +#define SYS_ASSERTLINE 4 + +// Possible return error for resynchronization functions. +#define WAITERR_WAITABORTED 1 +#define WAITERR_WAITTIMEDOUT 2 + +// LOCAL DATA TYPES + +typedef struct _UIPARAMS { + DWORD flags; + SNETPROGRAMDATAPTR programdata; + SNETPLAYERDATAPTR playerdata; + SNETUIDATAPTR interfacedata; + SNETVERSIONDATAPTR versiondata; + LPDWORD playeridptr; +} UIPARAMS, *UIPARAMSPTR; + +typedef struct _ADVREC { + DWORD networkid; + DWORD programid; + DWORD versionid; + char strings[SNETSPI_MAXSTRINGLENGTH*2]; + DWORD bytes; +} ADVREC, *ADVPTR; + +typedef struct _PACKETHEADER { + BYTE key_sequence[HEADER_KEYS]; // must be first field + BYTE sizedwords; // must be second field + BYTE startbyte_type; + BYTE targetmask; + union { + struct { + BYTE fromid:4; + BYTE timetolive:4; + }; + struct { + BYTE sysmsgtype:4; + BYTE timetolive:4; + }; + }; +} PACKETHEADER, *PACKETHEADERPTR; + +typedef struct _MESSAGEREC { + SNETADDR addr; // must be first field + PACKETHEADER header; // must immediately precede data + BYTE data[MAXMESSAGESIZE]; + DWORD bytesneeded; + DWORD bytesread; + DWORD inport; + _MESSAGEREC *next; +} MESSAGEREC, *MESSAGEPTR; + +typedef struct _MESSAGEDATAREC { + PACKETHEADER header; // must immediately precede data + BYTE data[MAXMESSAGESIZE]; +} MESSAGEDATAREC, *MESSAGEDATAPTR; + +typedef struct _PORTREC { + HANDLE handle; + OVERLAPPED overlapped; + BYTE readbuffer[READBUFFERSIZE]; + DWORD bytesread; + MESSAGEPTR partialmessage; + BYTE networkids; +} PORTREC, *PORTPTR; + +typedef BOOL (CALLBACK *DEVENUMPROC)(LPLINEDEVCAPS, DWORD, LPARAM); +typedef BOOL (CALLBACK *LOCENUMPROC)(LPLINETRANSLATECAPS, + LPLINELOCATIONENTRY, LPARAM); +typedef BOOL (CALLBACK *COUNTRYENUMPROC)(LPLINECOUNTRYLIST, + LPLINECOUNTRYENTRY, LPARAM); + +// GLOBAL STATIC VARIABLES + +static BYTE gs_arrHeaderKeys[HEADER_KEYS] = HEADER_KEY_SEQ; +#ifdef EXPIRATION +static SYSTEMTIME sg_expDate = EXPIRATION; +#endif +static CCritSect modem_critsect; +static HANDLE modem_event[PORTS] = {0}; +static ADVPTR modem_gameadvinfo = NULL; +static SNETSPI_GAMELISTPTR modem_gamelist = NULL; +static DWORD modem_maxplayers = MAXPLAYERS; +static MESSAGEPTR modem_messagehead = NULL; +static BOOL modem_lineconfirmed = 0; +static BOOL modem_lineestablished = 0; +static BYTE modem_networkid = 0; +static BOOL modem_networkidlocked = 0; +static PORTPTR modem_port[PORTS] = {0}; +static DWORD modem_programid = 0; +static HANDLE modem_recvevent = NULL; +static HANDLE modem_TAPIHangupEvent = NULL; +static HANDLE modem_TAPIHangupNotify = NULL; +static HANDLE modem_TAPIAnswerEvent = NULL; +static HANDLE modem_TAPIEvent = NULL; +static HANDLE modem_TAPINotifyEvent = NULL; +static HANDLE modem_TAPICallStateEvent = NULL; +static HANDLE modem_TAPITerminateEvent = NULL; +static HANDLE modem_TAPILineReplyEvent = NULL; +static DWORD modem_routeloopcheck = 0; +static DWORD modem_state = STATE_NOGAME; +static DWORD modem_tapistate = TAPISTATE_SHUTDOWN; +static HANDLE modem_readthread = NULL; +static HANDLE modem_tapithread = NULL; +static HANDLE modem_tapianswerthread = NULL; +static HANDLE modem_tapihangupthread = NULL; +static DWORD modem_versionid = 0; +static BOOL modem_versionmismatch = 0; +static DWORD modem_callstatus = NO_ERROR; +static SNETSTATUSPROC modem_status = NULL; + +// TAPI GLOBALS + +static HLINEAPP g_hLineApp = NULL; +static HCALL g_hCall = NULL; +static HLINE g_hLine = NULL; +static DWORD g_dwNumDevices = 0; +static DWORD g_dwDeviceID = 0; + +static LONG g_lRequestedID; +static LONG g_lAsyncReply; +static DWORD g_dwCallState; +static DWORD g_dwDesiredCallState; + +// FORWARD DECLARATIONS + +static BOOL StartCom(); +static void StopCom(); +static BOOL HangupCall(); +static BOOL SendDataMessage (BYTE sysmsgtype, + BYTE targetmask, + LPVOID data, + DWORD databytes); +BOOL CALLBACK ModemDestroy(); +BOOL CALLBACK ModemStopAdvertisingGame(); +static LONG WaitForReply(LONG lRequestedID); +static LONG WaitForCallState(DWORD dwDesiredCallState, DWORD dwWaitTime); +static BOOL TakeCall(); +static void InsertHeaderKey(PACKETHEADERPTR header); + +//=========================================================================== +static DWORD PickRandomNumber () { + // RETURN A DWORD-SIZED RANDOM NUMBER. IT IS IMPORTANT THAT WE DON'T + // USE THE RUNTIME LIBRARY RANDOM GENERATOR, BECAUSE WE DON'T WANT TO + // INTERFERE WITH THE APPLICATION'S RANDOM SEQUENCE. + LARGE_INTEGER perfcount; + POINT pos; + QueryPerformanceCounter(&perfcount); + GetCursorPos(&pos); + + static DWORD seed = 0x100001; + seed ^= perfcount.LowPart ^ GetTickCount() ^ pos.x ^ pos.y; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand1 = seed & 0xFFFF; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand2 = seed & 0xFFFF; + return (rand1 << 16) | rand2; +} + +//=========================================================================== +static BOOL FindNetworkId () { + DWORD timeout = 16; + while (timeout--) { + + // PICK A RANDOM NUMBER WHICH WE CAN USE TO RECOGNIZE AND DISCARD OUR + // OWN PACKETS IN THE CASE OF A ROUTING LOOP. MAKE SURE THE NUMBER IS + // NOT ZERO, BECAUSE COMPUTERS WITH ESTABLISHED NETWORK IDS WILL USE ZERO. + modem_routeloopcheck = 0; + while (!modem_routeloopcheck) + modem_routeloopcheck = PickRandomNumber(); + + // PICK A NETWORK ID AT RANDOM, AND SEND OUT A QUERY TO SEE IF ANYONE + // ELSE IS USING IT. IF WE ARE THE GAME OWNER WE CANNOT QUERY SINCE WE + // HAVE ALREADY RETURNED A NETWORK ID IN ModemStartAdvertisingGame(). + if (!modem_networkidlocked) { + modem_critsect.Enter(); + modem_networkid = 0; + while (!modem_networkid) + modem_networkid = (BYTE)((PickRandomNumber() % MAXPLAYERS) + 1); + modem_critsect.Leave(); + DWORD messagedata[2] = {modem_networkid,modem_routeloopcheck}; + TraceOut("Snd: SYS_QUERYID"); + SendDataMessage(SYS_QUERYID,0xFF,&messagedata[0],2*sizeof(DWORD)); + + // WAIT 1000 MILLISECONDS FOR A RESPONSE. IF ANY OTHER COMPUTER ASSERTS + // THAT IT IS USING THE ID WE PICKED, OR IF ANY OTHER COMPUTER QUERIES + // FOR THE SAME ID, THEN GIVE UP THAT ID AND PICK A NEW ONE. + DWORD starttime = GetTickCount(); + while (modem_networkid && (GetTickCount()-starttime < 1000)) + Sleep(10); + + // IF SOMEONE CONTESTED OUR ID, DUMP IT AND TRY AGAIN. + if (!modem_networkid) + continue; + } + + // NO OTHER COMPUTER CONTESTED OUR NETWORK ID. LOCK IT DOWN, ASSERT IT + // ON THE NETWORK, AND RETURN SUCCESS. + modem_critsect.Enter(); + modem_networkidlocked = 1; + modem_routeloopcheck = 0; + modem_critsect.Leave(); + TraceOut("Snd: SYS_ASSERTID %d", modem_networkid); + SendDataMessage(SYS_ASSERTID,0xFF,&modem_networkid,sizeof(DWORD)); + return 1; + } // while (timeout--) + return 0; +} + +//=========================================================================== +static void SendFormedMessage (MESSAGEDATAPTR messageptr, + DWORD exceptport, + BOOL wait) { + BOOL systemmessage = (messageptr->header.startbyte_type == TYPE_SYSTEMDATA); + + // IF THIS IS A SYSTEM MESSAGE, WRITE IT OUT ON ALL ACTIVE PORTS. + // OTHERWISE, WRITE IT OUT ON ALL PORTS WHICH LEAD TO ANY OF THE + // DESIRED NETWORK IDS. + HANDLE event[PORTS]; + OVERLAPPED overlapped[PORTS]; + DWORD byteswritten[PORTS]; + DWORD numsends = 0; + BOOL bIOResult; + ZeroMemory(&event[0],PORTS*sizeof(HANDLE)); + + for (DWORD port = 0; port < PORTS; ++port) { + if ((port != exceptport) && modem_port[port] && + (modem_port[port]->handle != INVALID_HANDLE_VALUE) && + (systemmessage || + (modem_port[port]->networkids & messageptr->header.targetmask))) { + ZeroMemory(&overlapped[numsends],sizeof(OVERLAPPED)); + + if (wait) + event[numsends] = CreateEvent(NULL,0,0,NULL); + ASSERT(event[numsends]); + if (!event[numsends]) + return; + + overlapped[numsends].hEvent = event[numsends]; + bIOResult = WriteFile(modem_port[port]->handle, + messageptr, + messageptr->header.sizedwords*sizeof(DWORD), + &byteswritten[numsends], + &overlapped[numsends]); + + TraceDumpAddr("write data", messageptr, messageptr->header.sizedwords*sizeof(DWORD)); + // If WriteFile() sets the last error to something other than + // ERROR_IO_PENDING we probably have a bad file handle, which + // means that the remote party dropped the line. In this case + // we do not want to wait on the event, so don't increment numsends + if (bIOResult || GetLastError() == ERROR_IO_PENDING) { + PerfIncrement(PERF_PKTSENT); + PerfAdd(PERF_BYTESSENT,messageptr->header.sizedwords*sizeof(DWORD)); + ++numsends; + } + else if (wait && event[numsends]) + CloseHandle(event[numsends]); + } // if ((port != exceptport) && modem_port[port] && ... + } // for (DWORD port = 0; port < PORTS; ++port) + if (numsends && wait) { + // WAIT FOR ALL WRITES TO COMPLETE + WaitForMultipleObjects(numsends,&event[0],1,INFINITE); + } + while (numsends--) + CloseHandle(event[numsends]); +} + +//=========================================================================== +static BOOL SendDataMessage (BYTE sysmsgtype, + BYTE targetmask, + LPVOID data, + DWORD databytes) { + BOOL systemmessage = (sysmsgtype != SYS_UNUSED); + if (systemmessage) + targetmask = 0xFF; + + // DON'T SEND DATA WITHOUT A VALID CONNECTION + if (!modem_lineestablished) + return 0; + + // REFUSE TO SEND A NON-SYSTEM MESSAGE IF WE DON'T HAVE A VALID NETWORK ID + if ((sysmsgtype == SYS_UNUSED) && (!(modem_networkid && modem_networkidlocked))) + return 0; + + // CREATE A FULLY-FORMED MESSAGE + MESSAGEDATAREC messagedata; + ZeroMemory(&messagedata,sizeof(MESSAGEDATAREC)); + InsertHeaderKey(&messagedata.header); + messagedata.header.startbyte_type = (sysmsgtype == SYS_UNUSED) ? TYPE_USERDATA : TYPE_SYSTEMDATA; + messagedata.header.sizedwords = (sizeof(PACKETHEADER)+databytes+sizeof(DWORD)-1)/sizeof(DWORD); + messagedata.header.timetolive = MAXPLAYERS; + messagedata.header.targetmask = targetmask; + if (systemmessage) + messagedata.header.sysmsgtype = sysmsgtype; + else + messagedata.header.fromid = modem_networkid; + if (data && databytes) + CopyMemory(&messagedata.data[0],data,databytes); + + // SEND IT + SendFormedMessage(&messagedata,0xFFFFFFFF,1); + + return 1; +} + +//=========================================================================== +static void ProcessIncomingMessage (DWORD port, MESSAGEPTR messageptr) { + BOOL systemmessage = (messageptr->header.startbyte_type == TYPE_SYSTEMDATA); + BYTE origtargetmask = messageptr->header.targetmask; + + TraceOut("ProcessIncomingMessage()"); + PerfIncrement(PERF_PKTRECV); + PerfAdd(PERF_BYTESRECV,messageptr->bytesread); + + // VALIDATE THE PORT NUMBER + if (port >= PORTS) { + FREE(messageptr); + return; + } + + // VERIFY THAT WE ARE A RECIPIENT OF THIS MESSAGE, AND NOT THE SENDER + if (modem_networkid && modem_networkidlocked && + ((!(origtargetmask & (1 << modem_networkid))) || + ((!systemmessage) && + (messageptr->header.fromid == modem_networkid)))) { + FREE(messageptr); + return; + } + + // PROCESS USER MESSAGES + if (!systemmessage) { + TraceOut("USER MESSAGE"); + if (modem_networkid && modem_networkidlocked) { + *(LPBYTE)&messageptr->addr = messageptr->header.fromid; + LISTADDPTREND(&modem_messagehead,messageptr); + if (modem_recvevent) + SetEvent(modem_recvevent); + } + else + FREE(messageptr); + } + + // PROCESS SYSTEM MESSAGES + else { + TraceOut("SYSTEM MESSAGE"); + switch (messageptr->header.sysmsgtype) { + + case SYS_QUERYLINE: + TraceOut("Rcv: SYS_QUERYLINE"); + TraceOut("Snd: SYS_ASSERTLINE"); + SendDataMessage(SYS_ASSERTLINE,0xFF,NULL,0); + modem_critsect.Enter(); + modem_lineconfirmed = 1; + modem_critsect.Leave(); + break; + + case SYS_ASSERTLINE: + TraceOut("Rcv: SYS_ASSERTLINE"); + modem_critsect.Enter(); + modem_lineconfirmed = 1; + modem_critsect.Leave(); + break; + + case SYS_QUERYID: + TraceOut("Rcv: SYS_QUERYID"); + if (messageptr->bytesread >= sizeof(PACKETHEADER)+2*sizeof(DWORD)) { + DWORD networkid = *(LPDWORD)&messageptr->data[0]; + DWORD routeloopcheck = *(LPDWORD)&messageptr->data[sizeof(DWORD)]; + if (routeloopcheck != modem_routeloopcheck) { + if (modem_networkidlocked) { + TraceOut("Snd: SYS_ASSERTID"); + SendDataMessage(SYS_ASSERTID,0xFF,&modem_networkid,sizeof(DWORD)); + } + else if (networkid == modem_networkid) + modem_networkid = 0; + } + } + break; + + case SYS_ASSERTID: + TraceOut("Rcv: SYS_ASSERTID"); + if (messageptr->bytesread >= sizeof(PACKETHEADER)+sizeof(DWORD)) { + DWORD networkid = *(LPDWORD)&messageptr->data[0]; + modem_port[port]->networkids |= (1 << networkid); + if ((!modem_networkidlocked) && (networkid == modem_networkid)) + modem_networkid = 0; + } + break; + + case SYS_QUERYGAME: + TraceOut("Rcv: SYS_QUERYGAME"); + if (modem_gameadvinfo) { + TraceOut("Snd: SYS_GAMEINFO"); + SendDataMessage(SYS_GAMEINFO,0xFF,modem_gameadvinfo,modem_gameadvinfo->bytes); + } + break; + + case SYS_GAMEINFO: + TraceOut("Rcv: SYS_GAMEINFO"); + { + modem_critsect.Enter(); + ADVPTR advinfo = (ADVPTR)&messageptr->data[0]; + if ((advinfo->programid == modem_programid) && + (advinfo->versionid == modem_versionid)) { + if (!modem_gamelist) { + modem_gamelist = NEW(SNETSPI_GAMELIST); + ASSERT(modem_gamelist); + if (!modem_gamelist) + break; + ZeroMemory(modem_gamelist,sizeof(SNETSPI_GAMELIST)); + } + *(LPBYTE)&modem_gamelist->owner = (BYTE)advinfo->networkid; + modem_gamelist->gameid = 1; + strcpy(modem_gamelist->gamename,advinfo->strings); + strcpy(modem_gamelist->gamedescription,advinfo->strings+strlen(advinfo->strings)+1); + } + else + modem_versionmismatch = 1; + modem_critsect.Leave(); + } + break; + + case SYS_REMOVE: + TraceOut("Rcv: SYS_REMOVE"); + modem_critsect.Enter(); + ADVPTR advinfo = (ADVPTR)&messageptr->data[0]; + if (modem_networkid != advinfo->networkid && modem_gamelist) { + FREE(modem_gamelist); + modem_gamelist = NULL; + } + modem_critsect.Leave(); + break; + } + FREE(messageptr); + } +} + +//=========================================================================== +BOOL CALLBACK CancelCall() +{ + modem_critsect.Enter(); + modem_callstatus = SNET_ERROR_CANCELLED; + modem_critsect.Leave(); + TraceOut("CancelCall()"); + SetEvent(modem_TAPIHangupEvent); + return 1; +} + +//=========================================================================== +static void UpdateCallStatus(DWORD dwStringResource) +{ + char buf[SNETSPI_MAXSTRINGLENGTH]; + if (!modem_status) + return; + int ret = LoadString(global_instance, dwStringResource, buf, + SNETSPI_MAXSTRINGLENGTH); + ASSERT(ret); + if (!ret) + return; + modem_status(buf, 0, 0, 0, CancelCall); +} + +//=========================================================================== +static void HandleLineCallState( + DWORD dwDevice, DWORD dwMessage, DWORD dwCallbackInstance, + DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) +{ + // dwParam1 is the specific CALLSTATE change that is occurring. + g_dwCallState = dwParam1; + if (g_dwCallState == g_dwDesiredCallState) + SetEvent(modem_TAPICallStateEvent); + TraceOut("LINE_CALLSTATE: %d", g_dwCallState); + switch (dwParam1) + { + // ANSWER NEW CALL + case LINECALLSTATE_OFFERING: + modem_critsect.Enter(); + g_hCall = (HCALL)dwDevice; + modem_critsect.Leave(); + SetEvent(modem_TAPIAnswerEvent); + break; + + case LINECALLSTATE_IDLE: + TraceOut("LINECALLSTATE_IDLE"); + break; + + case LINECALLSTATE_BUSY: + TraceOut("LINECALLSTATE_BUSY"); + break; + + case LINECALLSTATE_DISCONNECTED: + switch (dwParam2) + { + case LINEDISCONNECTMODE_NORMAL: + TraceOut("LINEDISCONNECTMODE_NORMAL"); + break; + + case LINEDISCONNECTMODE_BUSY: + modem_critsect.Enter(); + modem_callstatus = SNET_ERROR_NETWORK_BUSY; + modem_critsect.Leave(); + break; + + case LINEDISCONNECTMODE_NOANSWER: + modem_critsect.Enter(); + modem_callstatus = SNET_ERROR_NOT_CONNECTED; + modem_critsect.Leave(); + break; + + case LINEDISCONNECTMODE_NODIALTONE: + modem_critsect.Enter(); + modem_callstatus = SNET_ERROR_NO_NETWORK; + modem_critsect.Leave(); + break; + + case LINEDISCONNECTMODE_BADADDRESS: + case LINEDISCONNECTMODE_UNREACHABLE: + case LINEDISCONNECTMODE_CONGESTION: + case LINEDISCONNECTMODE_INCOMPATIBLE: + case LINEDISCONNECTMODE_UNAVAIL: + case LINEDISCONNECTMODE_UNKNOWN: + case LINEDISCONNECTMODE_REJECT: + case LINEDISCONNECTMODE_PICKUP: + case LINEDISCONNECTMODE_FORWARDED: + default: + break; + } + // THERE ARE 3 CASES HERE: + // 1) WE WERE THE ORIGINAL GAME OWNER, AND THE CALLER DROPPED + // THE LINE. IN THIS CASE WE WILL RECONFIGURE THE LINE TO + // ACCEPT CALLS + // 2) WE ARE THE CALLER, AND THE SERVER DROPPED. WE HAVE + // RECEIVED THIS ASYNC MESSAGE BEFORE SPISTARTADVERTISE. + // IN THIS CASE WE DO NOT CONFIGURE FOR CALL RECEIPT SINCE + // WE DO NOT TECHNICALLY KNOW WE ARE NOW THE GAME OWNER, I.E. + // THERE IS NO VALID ADVINFO RECORD. SPISTARTADVERTISE WILL + // DO THIS ON FINDING TAPI SHUTDOWN AFTER OUR HANGUP CALL. + // 3) AS ABOVE, BUT WE ARE HERE AFTER THE SPISTARTADVERTISE. + // THE MODEM WAS NOT CONFIGURED THERE SINCE TAPI WAS STILL + // RUNNING, SO WE NEED TO START IT UP! + + SetEvent(modem_TAPIHangupEvent); + break; + + case LINECALLSTATE_CONNECTED: + TraceOut("LINECALLSTATE_CONNECTED"); + StartCom(); + UpdateCallStatus(IDS_CONNECTING); + break; + + case LINECALLSTATE_DIALING: + UpdateCallStatus(IDS_DIALING); + break; + + case LINECALLSTATE_RINGBACK: + UpdateCallStatus(IDS_RINGING); + break; + + case LINECALLSTATE_PROCEEDING: + UpdateCallStatus(IDS_PROCEEDING); + break; + + case LINECALLSTATE_DIALTONE: + UpdateCallStatus(IDS_DIALTONE); + break; + + case LINECALLSTATE_SPECIALINFO: + default: + break; + } +} + +//=========================================================================== +static void CALLBACK TAPIEventCallback ( + DWORD hDevice, + DWORD dwMsg, + DWORD dwCallbackInstance, + DWORD dwParam1, + DWORD dwParam2, + DWORD dwParam3 + ) +{ + + // Handle the line messages. + switch(dwMsg) + { + case LINE_CALLSTATE: + HandleLineCallState(hDevice, dwMsg, dwCallbackInstance, + dwParam1, dwParam2, dwParam3); + break; + + case LINE_CLOSE: + TraceOut("LINE_CLOSE"); + // Line has been shut down. + break; + + case LINE_REPLY: + TraceOut("LINE_REPLY"); + modem_critsect.Enter(); + if (g_lRequestedID == (LONG)dwParam1) { + g_lAsyncReply = (LONG)dwParam2; + SetEvent(modem_TAPILineReplyEvent); + } + modem_critsect.Leave(); + break; + + case LINE_CREATE: + default: + break; + } + return; +} + +//=========================================================================== +static DWORD CALLBACK TAPIProc(LPVOID) { + + HANDLE events[] = {modem_TAPITerminateEvent, modem_TAPIEvent}; + DWORD dwEvent; + MSG msg; + + modem_critsect.Enter(); + LONG result = lineInitialize(&g_hLineApp, global_instance, + TAPIEventCallback, NULL, &g_dwNumDevices); + modem_critsect.Leave(); + ASSERT(!result); + // NOTIFY OF INIT COMPLETION + SetEvent(modem_TAPINotifyEvent); + + while (1) { + if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ResetEvent(modem_TAPIEvent); + dwEvent = MsgWaitForMultipleObjects(2, events, FALSE, INFINITE, QS_ALLINPUT); + TraceOut("TAPIProc awake"); + if (dwEvent == WAIT_FAILED || !(dwEvent - WAIT_OBJECT_0)) + break; + } + ExitThread(0); + return 0; +} + +//=========================================================================== +static DWORD CALLBACK TAPIAnswerProc(LPVOID) { + HANDLE events[] = {modem_TAPITerminateEvent, modem_TAPIAnswerEvent}; + DWORD dwEvent; + LONG lResult; + + while (1) { + ResetEvent(modem_TAPIAnswerEvent); + dwEvent = WaitForMultipleObjects(2, events, FALSE, INFINITE); + if (dwEvent == WAIT_FAILED || !(dwEvent - WAIT_OBJECT_0)) + break; + + lResult = WaitForReply(lineAnswer(g_hCall, NULL, 0)); + if (lResult) + continue; + + // THIS MAY NOT BE NECESSARY, BUT IT MIGHT BE NICE TO DETECT IF + // THE CALLER IS RUNNING DIABLO AND HAGUP IF NOT, SO GO AHEAD + // AND LEAVE THIS AS A SEPARATE THREAD +#if 0 + // TIMEOUT IF THE CALLER HUNG UP + lResult = WaitForCallState(LINECALLSTATE_CONNECTED, ANSWERTIMEOUT); + if (lResult) + continue; +#endif + } + ExitThread(0); + return 0; +} + +//=========================================================================== +static DWORD CALLBACK TAPIHangupProc(LPVOID) { + HANDLE events[] = {modem_TAPITerminateEvent, modem_TAPIHangupEvent}; + DWORD dwEvent; + while (1) { + ResetEvent(modem_TAPIHangupEvent); + dwEvent = WaitForMultipleObjects(2, events, FALSE, INFINITE); + if (dwEvent == WAIT_FAILED || !(dwEvent - WAIT_OBJECT_0)) + break; + HangupCall(); + SetEvent(modem_TAPIHangupNotify); + if (modem_gameadvinfo) + TakeCall(); + } + ExitThread(0); + return 0; +} + +//=========================================================================== +static void InsertHeaderKey(PACKETHEADERPTR header) +{ + ASSERT(header); + if (!header) + return; + CopyMemory(header->key_sequence, gs_arrHeaderKeys, HEADER_KEYS); +} + +//=========================================================================== +static BOOL ScanForHeader(LPDWORD bytesleft, LPBYTE *dataptr) +{ + ASSERT(bytesleft && *dataptr); + if (!(bytesleft && *dataptr)) + return FALSE; + + static int matchlevel = 0; + while (*bytesleft && matchlevel < HEADER_KEYS) { + if (**dataptr == gs_arrHeaderKeys[matchlevel]) + matchlevel++; + else if (matchlevel) { + matchlevel = 0; + TraceOut("Reset Match"); + continue; + } + (*bytesleft)--; + (*dataptr)++; + } + if (matchlevel == HEADER_KEYS) { + matchlevel = 0; + return TRUE; + } + return FALSE; +} + +//=========================================================================== +unsigned CALLBACK ThreadProc (LPVOID) { + while (modem_state != STATE_SHUTDOWN) { + TraceOut("Read Thread Awake"); + modem_critsect.Enter(); + for (DWORD port = 0; port < PORTS; ++port) { + + if (modem_port[port]->handle == INVALID_HANDLE_VALUE) + continue; + + // CHECK TO SEE IF AN I/O OPERATION HAS COMPLETED ON THIS PORT + if (!GetOverlappedResult(modem_port[port]->handle, + &modem_port[port]->overlapped, + &modem_port[port]->bytesread, + 0)) { + if (GetLastError() == ERROR_OPERATION_ABORTED) + ResetEvent(modem_event[port]); + continue; + } + + // IF SO, PARSE THE INCOMING DATA + DWORD bytesleft = modem_port[port]->bytesread; + LPBYTE dataptr = &modem_port[port]->readbuffer[0]; + TraceDumpAddr("read data", dataptr, bytesleft); + + MESSAGEPTR messageptr; + while (bytesleft) { + messageptr = NULL; + if (modem_port[port]->partialmessage) { + TraceOut("Partial Message"); + messageptr = modem_port[port]->partialmessage; + } + else if (ScanForHeader(&bytesleft, &dataptr)) { + // ALLOCATE NEW RECORD + messageptr = NEW(MESSAGEREC); + ASSERT(messageptr); + if (!messageptr) { + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + TraceOut("NEW(MESSAGEREC)"); + ZeroMemory(messageptr, sizeof(MESSAGEREC)); + messageptr->inport = port; + + // INSERT MULTIBYTE HEADER KEY + InsertHeaderKey(&messageptr->header); + messageptr->bytesread = HEADER_KEYS; + modem_port[port]->partialmessage = messageptr; + } + + // PROCESS NEW AND PARTIAL PACKETS + if (!bytesleft) + continue; + + if (!messageptr->bytesneeded) { + messageptr->bytesneeded = (*dataptr) * sizeof(DWORD); + if (messageptr->bytesneeded > sizeof(PACKETHEADER) + MAXMESSAGESIZE) { + TraceOut("Bogus Packet"); + FREE(messageptr); + modem_port[port]->partialmessage = NULL; + continue; + } + } + LPBYTE writeptr = (LPBYTE)&messageptr->header; + DWORD bytestocopy = + min(bytesleft, messageptr->bytesneeded - messageptr->bytesread); + CopyMemory(writeptr + messageptr->bytesread, dataptr, bytestocopy); + messageptr->bytesread += bytestocopy; + dataptr += bytestocopy; + bytesleft -= bytestocopy; + if (!(messageptr->bytesread < messageptr->bytesneeded)) { + ProcessIncomingMessage(port, messageptr); + modem_port[port]->partialmessage = NULL; + } + } // while (bytesleft) + + // RETURN THIS PORT'S EVENT TO A NONSIGNALED STATE + ResetEvent(modem_event[port]); + + // POST ANOTHER OVERLAPPED READ FOR THIS PORT + ReadFile(modem_port[port]->handle, + modem_port[port]->readbuffer, + READBUFFERSIZE, + &modem_port[port]->bytesread, + &modem_port[port]->overlapped); + } // for (DWORD port = 0; port < PORTS; ++port) + modem_critsect.Leave(); + WaitForMultipleObjects(PORTS,&modem_event[0],0,INFINITE); + } // while (modem_state != STATE_SHUTDOWN) + modem_state = STATE_NOGAME; + _endthreadex(0); + return 0; +} + +//=========================================================================== +static void CleanupEvents() +{ + // CLEANUP EVENTS + if (modem_TAPITerminateEvent) { + CloseHandle(modem_TAPITerminateEvent); + modem_TAPITerminateEvent = NULL; + } + if (modem_TAPIEvent) { + CloseHandle(modem_TAPIEvent); + modem_TAPIEvent = NULL; + } + if (modem_TAPINotifyEvent) { + CloseHandle(modem_TAPINotifyEvent); + modem_TAPINotifyEvent = NULL; + } + if (modem_TAPIHangupEvent) { + CloseHandle(modem_TAPIHangupEvent); + modem_TAPIHangupEvent = NULL; + } + if (modem_TAPIHangupNotify) { + CloseHandle(modem_TAPIHangupNotify); + modem_TAPIHangupNotify = NULL; + } + if (modem_TAPIAnswerEvent) { + CloseHandle(modem_TAPIAnswerEvent); + modem_TAPIAnswerEvent = NULL; + } + if (modem_TAPICallStateEvent) { + CloseHandle(modem_TAPICallStateEvent); + modem_TAPICallStateEvent = NULL; + } + if (modem_TAPILineReplyEvent) { + CloseHandle(modem_TAPILineReplyEvent); + modem_TAPILineReplyEvent = NULL; + } +} + +//=========================================================================== +static BOOL ShutdownTAPI() +{ + long lReturn; + + // If we aren't initialized, then Shutdown is unnecessary. + if (!g_hLineApp) + return TRUE; + + // POST HANGUP AND SHUTDOWN THREADS. HANGUPPROC WILL ALWAYS GIVE + // PREFERENCE TO HANGUP EVENTS OVER DESTROY EVENTS, SO WE KNOW THE + // LINE IS CLEAN AFTER THE WAIT. + + SetEvent(modem_TAPIHangupEvent); + ResetEvent(modem_TAPIHangupNotify); + WaitForSingleObject(modem_TAPIHangupNotify, 2000); + + SetEvent(modem_TAPITerminateEvent); + HANDLE hHarray[] = {modem_tapithread, modem_tapianswerthread, + modem_tapihangupthread}; + WaitForMultipleObjects(3, hHarray, TRUE, 2000); + modem_tapithread = NULL; + modem_tapianswerthread = NULL; + modem_tapihangupthread = NULL; + + CleanupEvents(); + + // SHUTDOWN TAPI INTERFACE + if (g_hLineApp) { + lReturn = lineShutdown(g_hLineApp); + g_hLineApp = NULL; + } + + return TRUE; +} + +//=========================================================================== +static BOOL StartupTAPI() +{ + // If we aren initialized, then Startup is unnecessary. + if (g_hLineApp) + return TRUE; + + modem_TAPITerminateEvent = CreateEvent(NULL, 1, 0, NULL); + modem_TAPIEvent = CreateEvent(NULL, 1, 0, NULL); + modem_TAPINotifyEvent = CreateEvent(NULL, 1, 0, NULL); + modem_TAPIAnswerEvent = CreateEvent(NULL, 1, 0, NULL); + modem_TAPIHangupEvent = CreateEvent(NULL, 1, 0, NULL); + modem_TAPIHangupNotify = CreateEvent(NULL, 1, 0, NULL); + modem_TAPICallStateEvent = CreateEvent(NULL, 1, 0, NULL); + modem_TAPILineReplyEvent = CreateEvent(NULL, 1, 0, NULL); + + // CREATE A THREAD TO HANDLE TAPI MESSAGES. THIS IS NECESSARY + // SINCE MANY SPI FUNCTIONS REQUIRE BLOCKING, AND THIS BRAIN DEAD + // VERSION OF TAPI USES A MESSAGE LOOP FOR STATUS. + ResetEvent(modem_TAPINotifyEvent); + if (modem_TAPIEvent && !modem_tapithread) { + DWORD threadid; + modem_tapithread = CreateThread(NULL, 0, TAPIProc, + NULL, 0, &threadid); + ASSERT(modem_tapithread); + if (!modem_tapithread) { + SetEvent(modem_TAPITerminateEvent); + modem_tapithread = NULL; + SetLastError(SNET_ERROR_MAX_THRDS_REACHED); + return 0; + } + } + WaitForSingleObject(modem_TAPINotifyEvent, INFINITE); + if (!g_hLineApp) { + SetEvent(modem_TAPITerminateEvent); + WaitForSingleObject(modem_tapithread, INFINITE); + modem_tapithread = NULL; + CleanupEvents(); + return 0; + } + + // CREATE THE ANSWER THREAD + if (modem_TAPIAnswerEvent && !modem_tapianswerthread) { + DWORD threadid; + modem_tapianswerthread = CreateThread(NULL, 0, TAPIAnswerProc, + NULL, 0, &threadid); + ASSERT(modem_tapianswerthread); + if (!modem_tapianswerthread) { + SetEvent(modem_TAPITerminateEvent); + modem_tapianswerthread = NULL; + SetLastError(SNET_ERROR_MAX_THRDS_REACHED); + return 0; + } + } + + // CREATE THE HANGUP THREAD + if (modem_TAPIHangupEvent && modem_TAPIHangupNotify && + !modem_tapihangupthread) { + DWORD threadid; + modem_tapihangupthread = CreateThread(NULL, 0, TAPIHangupProc, + NULL, 0, &threadid); + ASSERT(modem_tapihangupthread); + if (!modem_tapihangupthread) { + SetEvent(modem_TAPITerminateEvent); + modem_tapihangupthread = NULL; + SetLastError(SNET_ERROR_MAX_THRDS_REACHED); + return 0; + } + } + + return 1; +} + +//=========================================================================== +static LONG WaitForReply(LONG lRequestedID) +{ + if (!(lRequestedID > 0)) + return lRequestedID; + + modem_critsect.Enter(); + g_lRequestedID = lRequestedID; + g_lAsyncReply = lRequestedID; + ResetEvent(modem_TAPILineReplyEvent); + modem_critsect.Leave(); + WaitForSingleObject(modem_TAPILineReplyEvent, INFINITE); + + return g_lAsyncReply; +} + +//=========================================================================== +static LONG WaitForCallState(DWORD dwDesiredCallState, DWORD dwWaitTime) +{ + modem_critsect.Enter(); + g_dwDesiredCallState = dwDesiredCallState; + ResetEvent(modem_TAPICallStateEvent); + modem_critsect.Leave(); + DWORD dwRes = WaitForSingleObject(modem_TAPICallStateEvent, dwWaitTime); + + if (dwRes == WAIT_TIMEOUT) + return WAITERR_WAITTIMEDOUT; + if (g_dwDesiredCallState != dwDesiredCallState) + return WAITERR_WAITABORTED; + + return 0; +} + +//=========================================================================== +static BOOL HangupCall() +{ + LPLINECALLSTATUS pLineCallStatus = NULL; + long lReturn; + + TraceOut("HangupCall()"); + + StopCom(); + + // SET WAIT EVENTS SO THAT ANY THREAD WAITING ON TAPI EVENTS WILL + // TERMINATE CLEANLY + modem_critsect.Enter(); + g_dwDesiredCallState = LINECALLSTATE_DISCONNECTED; + SetEvent(modem_TAPICallStateEvent); + SetEvent(modem_TAPILineReplyEvent); + modem_critsect.Leave(); + + // If there is a call in progress, drop and deallocate it. + if (g_hCall) { + + pLineCallStatus = (LPLINECALLSTATUS)LocalAlloc(LPTR, sizeof(LINECALLSTATUS)); + ASSERT(pLineCallStatus); + if (!pLineCallStatus) + return FALSE; + lReturn = lineGetCallStatus(g_hCall, pLineCallStatus); + + // Only drop the call when the line is not IDLE. + if (!((pLineCallStatus->dwCallState) & LINECALLSTATE_IDLE)) { + lReturn = WaitForReply(lineDrop(g_hCall, NULL, 0)); + ASSERT(!lReturn); + if (lReturn) + return FALSE; + } + + // Need to free buffer returned from lineGetCallStatus + if (pLineCallStatus) + LocalFree(pLineCallStatus); + + modem_critsect.Enter(); + lReturn = lineDeallocateCall(g_hCall); + ASSERT(!lReturn); + if (lReturn) { + modem_critsect.Leave(); + return FALSE; + } + g_hCall = NULL; + modem_critsect.Leave(); + } + + // if we have a line open, close it. + if (g_hLine) { + modem_critsect.Enter(); + lReturn = lineClose(g_hLine); + ASSERT(!lReturn); + if (lReturn) { + modem_critsect.Leave(); + return FALSE; + } + g_hLine = NULL; + modem_critsect.Leave(); + } + + if (modem_gamelist) { + modem_critsect.Enter(); + FREE(modem_gamelist); + modem_gamelist = NULL; + modem_critsect.Leave(); + } + return TRUE; +} + +//=========================================================================== +static BOOL GetDeviceAPIVersion(DWORD id, LPDWORD lpdwTAPIVersion) +{ + LINEEXTENSIONID lineExtId; + + ASSERT(g_hLineApp && g_dwNumDevices); + LONG lReturn = lineNegotiateAPIVersion(g_hLineApp, id, + TAPI_CURRENT_VERSION, + TAPI_CURRENT_VERSION, + lpdwTAPIVersion, + &lineExtId); + return (!lReturn); +} + +//=========================================================================== +static LPLINEDEVCAPS GetDeviceCaps(DWORD id, DWORD dwTAPIVersion) +{ + LINEDEVCAPS tmpLineDevCaps; + LPLINEDEVCAPS lpLineDevCaps; + LONG lReturn; + + ASSERT(g_hLineApp && g_dwNumDevices); + + tmpLineDevCaps.dwTotalSize = sizeof(tmpLineDevCaps); + lReturn = lineGetDevCaps(g_hLineApp, id, dwTAPIVersion, 0, &tmpLineDevCaps); + if (lReturn) { + return NULL; + } + + lpLineDevCaps = (LPLINEDEVCAPS)LocalAlloc(LPTR, tmpLineDevCaps.dwNeededSize); + ASSERT(lpLineDevCaps); + if (!lpLineDevCaps) { + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + lpLineDevCaps->dwTotalSize = tmpLineDevCaps.dwNeededSize; + lReturn = lineGetDevCaps(g_hLineApp, id, dwTAPIVersion, 0, lpLineDevCaps); + if (lReturn) { + LocalFree(lpLineDevCaps); + return NULL; + } + return lpLineDevCaps; +} + +//=========================================================================== +static LPLINECALLPARAMS CreateCallParams(LPCSTR szAddress) +{ + LPLINECALLPARAMS lpCallParams = NULL; + DWORD dwAddressSize; + + ASSERT(szAddress && *szAddress); + + dwAddressSize = strlen(szAddress) + 1; + + lpCallParams = (LPLINECALLPARAMS)LocalAlloc(LPTR, sizeof(LINECALLPARAMS) + + dwAddressSize); + ASSERT(lpCallParams); + if (!lpCallParams) { + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + + lpCallParams->dwTotalSize = sizeof(LINECALLPARAMS) + dwAddressSize; + // This is where we configure the line. + lpCallParams->dwBearerMode = LINEBEARERMODE_VOICE; + lpCallParams->dwMediaMode = LINEMEDIAMODE_DATAMODEM; + + // This specifies that we want to use only IDLE calls and + // don't want to cut into a call that might not be IDLE (ie, in use). + lpCallParams->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE; + + // if there are multiple addresses on line, use first anyway. + // It will take a more complex application than a simple tty app + // to use multiple addresses on a line anyway. + lpCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID; + + // Address we are dialing. + lpCallParams->dwDisplayableAddressOffset = sizeof(LINECALLPARAMS); + lpCallParams->dwDisplayableAddressSize = dwAddressSize; + strcpy((LPSTR)lpCallParams + sizeof(LINECALLPARAMS), szAddress); + + return lpCallParams; +} + +//=========================================================================== +static LPLINETRANSLATEOUTPUT TranslateAddress( + DWORD id, DWORD dwTAPIVersion, LPCTSTR szAddress) +{ + LPLINETRANSLATEOUTPUT lpOutput = NULL; + DWORD dwSize; + LONG lReturn; + + ASSERT(g_hLineApp && g_dwNumDevices); + + // LOOP UNTIL WE HAVE ALLOCATED A STRUCTURE LARGE ENOUGH TO + // HOLD THE ENTIRE ADDRESS INFORMATION BLOCK + dwSize = sizeof(LINETRANSLATEOUTPUT); + do { + if (lpOutput) { + dwSize = lpOutput->dwNeededSize; + LocalFree(lpOutput); + } + lpOutput = (LPLINETRANSLATEOUTPUT)LocalAlloc(LPTR, dwSize); + ASSERT(lpOutput); + if (!lpOutput) { + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + lpOutput->dwTotalSize = dwSize; + + lReturn = lineTranslateAddress(g_hLineApp, id, dwTAPIVersion, + szAddress, 0, 0, lpOutput); + ASSERT(!lReturn); + if (lReturn) { + LocalFree(lpOutput); + return NULL; + } + } while (lpOutput->dwTotalSize < lpOutput->dwNeededSize); + + return lpOutput; +} + +//=========================================================================== +static BOOL MakeCall(LPCSTR szAddress) +{ + BOOL bVal; + DWORD dwTAPIVersion; + LPLINEDEVCAPS lpLineDevCaps = NULL; + LPLINECALLPARAMS lpCallParams = NULL; + LPLINETRANSLATEOUTPUT lpOutput = NULL; + LPCTSTR lpDialString = NULL; + LONG lResult; + + TraceOut("MakeCall()"); + + // MAKE SURE LINE SUPPORTS DIAL-OUT + bVal = GetDeviceAPIVersion(g_dwDeviceID, &dwTAPIVersion); + ASSERT(bVal); + if (!bVal) + return 0; + + lpLineDevCaps = GetDeviceCaps(g_dwDeviceID, dwTAPIVersion); + ASSERT(lpLineDevCaps); + if (!lpLineDevCaps) + return 0; + + if (!(lpLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL)) + return 0; + + if (lpLineDevCaps) + LocalFree(lpLineDevCaps); + + modem_critsect.Enter(); + lResult = lineOpen(g_hLineApp, g_dwDeviceID, &g_hLine, dwTAPIVersion, 0, 0, + LINECALLPRIVILEGE_NONE, LINEMEDIAMODE_DATAMODEM, NULL); + modem_critsect.Leave(); + ASSERT(!lResult); + if (lResult == LINEERR_ALLOCATED) + return 0; + if (lResult) + return 0; + + lpCallParams = CreateCallParams(szAddress); + ASSERT(lpCallParams); + if (!lpCallParams) + return 0; + + // CALL TRANSLATE ADDRESS TO CAPTURE ANY LINE PROPERITES SUCH + // AS PULSE DIALING. NOTE THAT COUNTRY AND AREA CODES ARE NOT + // HANDLED - IT IS UP TO THE USER TO ENTER A FULLY QUALIFIED + // DIALING STRING + lpOutput = TranslateAddress(g_dwDeviceID, dwTAPIVersion, szAddress); + ASSERT(lpOutput); + if (!lpOutput) + return 0; + lpDialString = (LPCTSTR)lpOutput + lpOutput->dwDialableStringOffset; + TraceOut("Dialing %s", lpDialString); + + lResult = WaitForReply(lineMakeCall(g_hLine, &g_hCall, lpDialString, + 0, lpCallParams)); + + if (lpCallParams) + LocalFree(lpCallParams); + if (lpOutput) + LocalFree(lpOutput); + + return (!lResult); +} + +//=========================================================================== +static BOOL TakeCall() +{ + BOOL bVal; + DWORD dwTAPIVersion; + LONG lResult; + + TraceOut("TakeCall()"); + bVal = GetDeviceAPIVersion(g_dwDeviceID, &dwTAPIVersion); + if (!bVal) + return 0; + + modem_critsect.Enter(); + lResult = lineOpen(g_hLineApp, g_dwDeviceID, &g_hLine, dwTAPIVersion, 0, 0, + LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_DATAMODEM, NULL); + modem_critsect.Leave(); + ASSERT(!lResult); + if (lResult) + return 0; + + return 1; +} + +//=========================================================================== +static LPVARSTRING GetVarString() +{ + VARSTRING tmpVarString; + LPVARSTRING lpVarString = NULL; + long lReturn; + + ASSERT(g_hCall); + if (!g_hCall) + return NULL; + + tmpVarString.dwTotalSize = sizeof(tmpVarString); + lReturn = lineGetID(0, 0, g_hCall, LINECALLSELECT_CALL, &tmpVarString, + "comm/datamodem"); + ASSERT(!lReturn); + if (lReturn) + return NULL; + + lpVarString = (LPVARSTRING)LocalAlloc(LPTR, tmpVarString.dwNeededSize); + ASSERT(lpVarString); + if (!lpVarString) + return NULL; + + lpVarString->dwTotalSize = tmpVarString.dwNeededSize; + lReturn = lineGetID(0, 0, g_hCall, LINECALLSELECT_CALL, lpVarString, + "comm/datamodem"); + ASSERT(!lReturn); + if (lReturn) { + LocalFree(lpVarString); + return NULL; + } + return lpVarString; +} + +//=========================================================================== +static BOOL InitializePort (DWORD port) { + + // ALLOCATE MEMORY FOR THE PORT RECORD + ASSERT(!modem_port[port]); + if (!modem_port[port]) { + modem_port[port] = NEW(PORTREC); + ASSERT(modem_port[port]); + if (!modem_port[port]) + return 0; + ZeroMemory(modem_port[port],sizeof(PORTREC)); + TraceOut("Allocated port %d", port); + } + + // CREATE AN EVENT FOR OVERLAPPED I/O + ASSERT(!modem_event[port]); + if (!modem_event[port]) { + modem_event[port] = CreateEvent(NULL,1,0,NULL); + if (!modem_event[port]) + return 0; + modem_port[port]->overlapped.hEvent = modem_event[port]; + } + + // Get the handle to the comm port from the driver so we can start + // communicating. This is returned in a LPVARSTRING structure. + LPVARSTRING lpVarString = GetVarString(); + ASSERT(lpVarString); + if (!lpVarString) + return 0; + + // Again, the handle to the comm port is contained in a + // LPVARSTRING structure. Thus, the handle is the very first + // thing after the end of the structure. Note that the name of + // the comm port is right after the handle, but I don't want it. + modem_port[port]->handle = *((LPHANDLE)((LPBYTE)lpVarString + + lpVarString->dwStringOffset)); + ASSERT(modem_port[port]->handle); + + if (lpVarString) + LocalFree(lpVarString); + + // IF WE COULDN'T OPEN THE PORT THEN IT IS PROBABLY UNCONFIGURED OR IN + // USE BY ANOTHER APPLICATION. RETURN SUCCESS BECAUSE THIS ISN'T A FATAL + // ERROR; WE WILL JUST NOT USE THIS PARTICULAR PORT. + if (modem_port[port]->handle == INVALID_HANDLE_VALUE) + return 1; + + // SET THE COMMUNICATIONS TIMEOUT VALUES + { + COMMTIMEOUTS timeouts; + ZeroMemory(&timeouts,sizeof(COMMTIMEOUTS)); + timeouts.ReadIntervalTimeout = READTIMEOUT; + SetCommTimeouts(modem_port[port]->handle, &timeouts); + } + + // fAbortOnError is the only DCB dependancy in TapiComm. + // Can't guarentee that the SP will set this to what we expect. + { + DCB dcb; + GetCommState(modem_port[port]->handle, &dcb); + dcb.fAbortOnError = FALSE; + SetCommState(modem_port[port]->handle, &dcb); + } + + // EXECUTE AN OVERLAPPED READ + ReadFile(modem_port[port]->handle, + modem_port[port]->readbuffer, + READBUFFERSIZE, + &modem_port[port]->bytesread, + &modem_port[port]->overlapped); + + return 1; +} + +//=========================================================================== +static void StopCom() +{ + DWORD port; + + TraceOut("StopCom()"); + // TERMINATE THE READ THREAD + if (!modem_lineestablished) + return; + + modem_state = STATE_SHUTDOWN; + for (port = 0; port < PORTS; ++port) + if (modem_port[port] && modem_port[port]->handle != INVALID_HANDLE_VALUE) + SetEvent(modem_port[port]->overlapped.hEvent); + WaitForSingleObject(modem_readthread,INFINITE); + modem_readthread = NULL; + + // CLOSE AND FREE ALL PORTS + for (port = 0; port < PORTS; ++port) { + if (modem_event[port]) { + CloseHandle(modem_event[port]); + modem_event[port] = NULL; + } + if (modem_port[port]) { + if (modem_port[port]->handle != INVALID_HANDLE_VALUE) + CloseHandle(modem_port[port]->handle); + if (modem_port[port]->partialmessage) + FREE(modem_port[port]->partialmessage); + FREE(modem_port[port]); + modem_port[port] = NULL; + } + } + modem_lineconfirmed = 0; + modem_lineestablished = 0; +} + +//=========================================================================== +static BOOL StartCom() +{ + // Very first, make sure this isn't a duplicated message. + // A CALLSTATE message can be sent whenever there is a + // change to the capabilities of a line, meaning that it is + // possible to receive multiple CONNECTED messages per call. + // The CONNECTED CALLSTATE message is the only one in TapiComm + // where it would cause problems if it where sent more + // than once. + + TraceOut("StartCom()"); + if (modem_lineestablished) + return 1; + + modem_critsect.Enter(); + // INITIALIZE THE SERIAL PORTS + for (DWORD loop = 0; loop < PORTS; ++loop) + if (!InitializePort(loop)) { + // Free the previously allocated port memory + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + SetEvent(modem_TAPIHangupEvent); + return 0; + } + + // CREATE A THREAD TO PROCESS INCOMING PACKETS + ASSERT(!modem_readthread); + if (!modem_readthread) { + unsigned threadid; + modem_readthread = (HANDLE)_beginthreadex(NULL, + 0, + ThreadProc, + NULL, + 0, + &threadid); + ASSERT(modem_readthread); + if (!modem_readthread) { + SetEvent(modem_TAPIHangupEvent); + SetLastError(SNET_ERROR_MAX_THRDS_REACHED); + return 0; + } + SetThreadPriority(modem_readthread,THREAD_PRIORITY_HIGHEST); + } + modem_critsect.Leave(); + + modem_lineestablished = 1; + SendDataMessage(SYS_QUERYLINE,0xFF,NULL,0); + DWORD starttime = GetTickCount(); + while (!modem_lineconfirmed && (GetTickCount() - starttime < MAX_CONNECT_DIFFERENTIAL)) + Sleep(10); + if (!modem_lineconfirmed) + return 0; + + // FIND AN UNUSED NETWORK ID + TraceOut("Finding ID"); + if (!FindNetworkId()) { + TraceOut("Finding ID: Failed!"); + SetEvent(modem_TAPIHangupEvent); + SetLastError(SNET_ERROR_TOO_MANY_NAMES); + return 0; + } + + // SEND OUT A QUERY FOR ACTIVE GAMES + TraceOut("Sending SYS_QUERYGAME"); + SendDataMessage(SYS_QUERYGAME,0xFF,NULL,0); + return 1; +} + +//=========================================================================== +static BOOL CALLBACK DevFillDeviceList(LPLINEDEVCAPS lpLineDevCaps, DWORD dwDevID, + LPARAM appData) +{ + SNETSPI_DEVICELISTPTR *devicelist = (SNETSPI_DEVICELISTPTR*)appData; + SNETSPI_DEVICELIST device; + + strncpy(device.devicename, + ((LPCTSTR)lpLineDevCaps) + lpLineDevCaps->dwLineNameOffset, + SNETSPI_MAXSTRINGLENGTH); + device.deviceid = dwDevID; + LISTADD(devicelist, &device); + return 1; +} + +//=========================================================================== +static void EnumerateDevices(DEVENUMPROC func, LPARAM appData) +{ + LPLINEDEVCAPS lpLineDevCaps = NULL; + DWORD dwTAPIVersion; + DWORD i; + BOOL bVal; + + ASSERT(func); + if (!func) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return; + } + + for (i = 0; i < g_dwNumDevices; i++) { + // Check that we can talk to this TAPI version + bVal = GetDeviceAPIVersion(i, &dwTAPIVersion); + if (!bVal) + continue; + + lpLineDevCaps = GetDeviceCaps(i, dwTAPIVersion); + if (!lpLineDevCaps) + continue; + if (func && !func(lpLineDevCaps, i, appData)) + break; + if (lpLineDevCaps) + LocalFree(lpLineDevCaps); + } +} + +//=========================================================================== +static void EnumerateLocations(LOCENUMPROC func, LPARAM appData) +{ + LINETRANSLATECAPS tmpTranslateCaps; + LPLINETRANSLATECAPS lpTranslateCaps = NULL; + long lReturn; + DWORD dwCounter; + LPLINELOCATIONENTRY lpLocationEntry = NULL; + + // First, get the TRANSLATECAPS + ZeroMemory(&tmpTranslateCaps, sizeof(tmpTranslateCaps)); + tmpTranslateCaps.dwTotalSize = sizeof(tmpTranslateCaps); + lReturn = lineGetTranslateCaps(g_hLineApp, TAPI_CURRENT_VERSION, + &tmpTranslateCaps); + ASSERT(!(lReturn < 0)); + if(lReturn < 0) + return; + lpTranslateCaps = (LPLINETRANSLATECAPS) + LocalAlloc(0, tmpTranslateCaps.dwNeededSize); + ASSERT(lpTranslateCaps); + if(!lpTranslateCaps) + return; + ZeroMemory(lpTranslateCaps, tmpTranslateCaps.dwNeededSize); + lpTranslateCaps->dwTotalSize = tmpTranslateCaps.dwNeededSize; + lReturn = lineGetTranslateCaps(g_hLineApp, TAPI_CURRENT_VERSION, + lpTranslateCaps); + ASSERT(!(lReturn < 0)); + if(lReturn < 0) { + if (lpTranslateCaps) + LocalFree(lpTranslateCaps); + return; + } + + // Find the location information in the TRANSLATECAPS + lpLocationEntry = (LPLINELOCATIONENTRY) + (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset); + + // enumerate all the locations + for (dwCounter = 0; dwCounter < lpTranslateCaps->dwNumLocations; + dwCounter++) { + if (func && !func(lpTranslateCaps, lpLocationEntry + dwCounter, appData)) + break; + } +} + +//=========================================================================== +static void EnumerateCountries(DWORD dwCountryID, COUNTRYENUMPROC func, + LPARAM appData) +{ + LINECOUNTRYLIST tmpLineCountryList; + LPLINECOUNTRYLIST lpLineCountryList = NULL; + DWORD dwSizeofCountryList = sizeof(LINECOUNTRYLIST); + long lReturn; + LPLINECOUNTRYENTRY lpLineCountryEntries = NULL; + DWORD dwCountry; + + // Get the country information stored in TAPI + ZeroMemory(&tmpLineCountryList, sizeof(tmpLineCountryList)); + tmpLineCountryList.dwTotalSize = sizeof(tmpLineCountryList); + lReturn = lineGetCountry (dwCountryID, TAPI_CURRENT_VERSION, + &tmpLineCountryList); + ASSERT(!(lReturn < 0)); + if(lReturn < 0) + return; + lpLineCountryList = (LPLINECOUNTRYLIST) + LocalAlloc(0, tmpLineCountryList.dwNeededSize); + ASSERT(lpLineCountryList); + if(!lpLineCountryList) + return; + ZeroMemory(lpLineCountryList, tmpLineCountryList.dwNeededSize); + lpLineCountryList->dwTotalSize = tmpLineCountryList.dwNeededSize; + lReturn = lineGetCountry (dwCountryID, TAPI_CURRENT_VERSION, + lpLineCountryList); + ASSERT(!(lReturn < 0)); + if(lReturn < 0) { + if (lpLineCountryList) + LocalFree(lpLineCountryList); + return; + } + + lpLineCountryEntries = (LPLINECOUNTRYENTRY)(((LPBYTE)lpLineCountryList) + + lpLineCountryList->dwCountryListOffset); + + // Now enumerate through all the countries + for (dwCountry = 0; dwCountry < lpLineCountryList->dwNumCountries; + dwCountry++) { + if (func && !func(lpLineCountryList, lpLineCountryEntries + dwCountry, + appData)) + break; + } +} + +/**************************************************************************** +* +* SERVICE PROVIDER INTERFACE FUNCTIONS +* +***/ + +//=========================================================================== +BOOL CALLBACK ModemCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude) { + if (diffmagnitude) + *diffmagnitude = 0; + if (!(addr1 && addr2)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + *diffmagnitude = (memcmp(addr1,addr2,sizeof(SNETADDR)) != 0); + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemDestroy() { + + TraceOut("ModemDestroy()"); + // STOP ADVERTISING GAMES + ModemStopAdvertisingGame(); + + // KILL ALL TAPI RELATED THREADS + ShutdownTAPI(); + + // FREE ALL MESSAGES + LISTCLEAR(&modem_messagehead); + + // FREE THE GAME LIST + if (modem_gamelist) { + FREE(modem_gamelist); + modem_gamelist = NULL; + } + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemFree (SNETADDRPTR addr, + LPVOID data, + DWORD databytes) { + if (!(addr && data)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + FREE(addr); + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemFreeExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR mesage) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; +} + +//=========================================================================== +BOOL CALLBACK ModemGetGameInfo (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + SNETSPI_GAMELIST *gameinfo) { + LONG lResult; + + if (!(gamename && gameinfo && (gameid || *gamename))) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + if (gameinfo) + ZeroMemory(gameinfo,sizeof(SNETSPI_GAMELIST)); + + if (!modem_lineestablished) { + modem_networkidlocked = 0; + if (!MakeCall(gamename)) { + SetEvent(modem_TAPIHangupEvent); + SetLastError(SNET_ERROR_BAD_PROVIDER); + return 0; + } + + lResult = WaitForCallState(LINECALLSTATE_CONNECTED, INFINITE); + if (lResult) { + SetLastError(modem_callstatus); + return 0; + } + + // Wait up to FINDGAMETIMEOUT milliseconds for a game + DWORD starttime = GetTickCount(); + while (!modem_gamelist && (GetTickCount() - starttime < FINDGAMETIMEOUT)) + Sleep(10); + } + + if (modem_versionmismatch) { + SetLastError(SNET_ERROR_VERSION_MISMATCH); + return 0; + } + + // IF THE GAME IN THE GAME LIST MATCHES THE QUERY PARAMETERS, RETURN + // ITS INFORMATION + modem_critsect.Enter(); + if (modem_gamelist) + CopyMemory(gameinfo,modem_gamelist,sizeof(SNETSPI_GAMELIST)); + modem_critsect.Leave(); + + if (!gameinfo->gameid) { + SetEvent(modem_TAPIHangupEvent); + SetLastError(SNET_ERROR_GAME_NOT_FOUND); + return 0; + } + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq) { + return PerfGetPerformanceData(counterid, + countervalue, + measurementtime, + measurementfreq); +} + +//=========================================================================== +BOOL CALLBACK ModemInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + HANDLE event) { + +#ifdef EXPIRATION + SYSTEMTIME sysTime; + GetLocalTime(&sysTime); + if (sysTime.wYear > sg_expDate.wYear || + (sysTime.wYear == sg_expDate.wYear && sysTime.wMonth > sg_expDate.wMonth) || + (sysTime.wYear == sg_expDate.wYear && sysTime.wMonth == sg_expDate.wMonth && + !(sysTime.wDay < sg_expDate.wDay))) { + char buf[256]; + LoadString(global_instance, IDS_EXPIRATION, buf, 256); + SDrawMessageBox(buf, "Version Error", MB_ICONEXCLAMATION); + return 0; + } +#endif + + // SAVE THE PROGRAM AND VERSION IDS AND THE RECEIVE EVENT HANDLE + modem_programid = programdata->programid; + modem_versionid = programdata->versionid; + modem_maxplayers = min(programdata->maxplayers,MAXPLAYERS); + modem_recvevent = event; + + // RESET PERFORMANCE DATA + PerfReset(); + + return StartupTAPI(); +} + +//=========================================================================== +BOOL CALLBACK ModemInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + BOOL bVal; + LPLINEDEVCAPS lpLineDevCaps; + DWORD dwTAPIVersion; + + ASSERT(g_hLineApp && g_dwNumDevices); + + ASSERT(interfacedata->statuscallback); + modem_critsect.Enter(); + modem_status = interfacedata->statuscallback; + modem_critsect.Leave(); + + // Make sure that the line is available and supports data capabilities + bVal = GetDeviceAPIVersion(deviceid, &dwTAPIVersion); + if (!bVal) + return 0; + + lpLineDevCaps = GetDeviceCaps(deviceid, dwTAPIVersion); + if (!lpLineDevCaps) + return 0; + if (!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM)) { + SetLastError(SNET_ERROR_BAD_PROVIDER); + return 0; + } + if (lpLineDevCaps) + LocalFree(lpLineDevCaps); + + modem_critsect.Enter(); + g_dwDeviceID = deviceid; + modem_critsect.Leave(); + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemLockDeviceList (SNETSPI_DEVICELISTPTR *devicelist) { + ASSERT(devicelist); + if (!devicelist) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + *devicelist = NULL; + EnumerateDevices(DevFillDeviceList, (LPARAM)devicelist); + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemLockGameList (DWORD categorybits, + DWORD categorymask, + SNETSPI_GAMELISTPTR *gamelist) { + if (!gamelist) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + // IF WE ARE NOT CURRENTLY CONNECTED RETURN FAIL SO THAT THE + // PROVIDER KNOWS TO BYPASS THE GAME SELECTION SCREEN AND + // DISPLAY THE PHONEBOOK IF AVAILABLE + if (!modem_lineestablished) { + SetLastError(SNET_ERROR_NO_NETWORK); + *gamelist = NULL; + return 0; + } + modem_critsect.Enter(); + *gamelist = modem_gamelist; + return 1; +} + +//=========================================================================== +/* +BOOL CALLBACK ModemReceive (SNETADDRPTR *addr, + LPVOID *data, + DWORD *databytes) { +*/ +BOOL CALLBACK ModemReceive (LPVOID *data, + DWORD *databytes, + SNETADDRPTR *addr) { + if (addr) + *addr = NULL; + if (data) + *data = NULL; + if (databytes) + *databytes = NULL; + if (!(addr && data && databytes)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + if (modem_messagehead) { + modem_critsect.Enter(); + *addr = &modem_messagehead->addr; + *data = &modem_messagehead->data[0]; + *databytes = modem_messagehead->bytesread-sizeof(PACKETHEADER); + LISTFREEPTR(&modem_messagehead,modem_messagehead); + modem_critsect.Leave(); + return 1; + } + else { + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK ModemReceiveExternalMessage (LPCSTR *senderpath, + LPCSTR *sendername, + LPCSTR *message) { + if (senderpath) + *senderpath = NULL; + if (sendername) + *sendername = NULL; + if (message) + *message = NULL; + + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; +} + +//=========================================================================== +BOOL CALLBACK ModemSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { +#ifdef PROVIDERUI + return 0; + +#else + + // BUILD A USER INTERFACE DATA BLOCK + UIPARAMS uiparams; + ZeroMemory(&uiparams,sizeof(UIPARAMS)); + uiparams.flags = flags; + uiparams.programdata = programdata; + uiparams.playerdata = playerdata; + uiparams.interfacedata = interfacedata; + uiparams.versiondata = versiondata; + uiparams.playeridptr = playerid; + + // DISPLAY THE DIALOG BOX + DWORD result = (DWORD)SDlgDialogBoxParam(global_instance, + "MODEM_DIALOG", + interfacedata ? + interfacedata->parentwindow : + SDrawGetFrameWindow(), + ModemDialogProc, + (LPARAM)&uiparams); + result = + ASSERT(!(result == -1)); + if (result == -1) + return 0; + + if (result == IDCANCEL) + return 0; + + // Add capabilities checking here! + + if (result == IDC_MODEMCREATE) { + ASSERT(interfacedata && interfacedata->createcallback); + if (!(interfacedata && interfacedata->createcallback)) + return 0; + // return ModemCreateGame(interfacedata->createcallback); + return 1; + } + return (!(result == -1)); +#endif +} + +//=========================================================================== +BOOL CALLBACK ModemSend (DWORD addresses, + SNETADDRPTR *addrlist, + LPVOID data, + DWORD databytes) { + if (!(addresses && addrlist && data && databytes)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // BUILD A TARGET MASK OUT OF THE LIST OF ADDRESSES + BYTE targetmask = 0; + while (addresses--) + targetmask |= (1 << *(LPBYTE)*(addrlist+addresses)); + + // SEND THE MESSAGE + return SendDataMessage(SYS_UNUSED,targetmask,data,databytes); +} + +//=========================================================================== +BOOL CALLBACK ModemSendExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR targetpath, + LPCSTR targetname, + LPCSTR message) { + return 0; +} + +//=========================================================================== +BOOL CALLBACK ModemStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD gameage, + DWORD gamecategorybits, + DWORD optcategorybits, + LPCVOID clientdata, + DWORD clientdatabytes) { + TraceOut("ModemStartAdvertisingGame()"); + if (!(gamename && gamedescription)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // STOP ADVERTISING ANY GAME WE ARE CURRENTLY ADVERTISING + if (modem_gameadvinfo) + ModemStopAdvertisingGame(); + + modem_critsect.Enter(); + // CREATE RECORDS TO ADVERTISE THE GAME + modem_gameadvinfo = NEW(ADVREC); + ASSERT(modem_gameadvinfo); + if (!modem_gameadvinfo) { + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + modem_critsect.Leave(); + return 0; + } + ZeroMemory(modem_gameadvinfo,sizeof(ADVREC)); + + // PICK AN INITIAL ID. THIS WILL NOT BE NEGOTIABLE FOR THE RECEIVING + // MACHINE SINCE WE NEED IT FOR SPISTARTADVERTISINGGAME(). DO NOT INIT + // THIS TO 0 IF WE ARE STARTING TO ADVERTIZE ON AN EXISTING + // CONNECTION + if (!modem_lineestablished) { + modem_networkid = 0; + while (!modem_networkid) + modem_networkid = (BYTE)((PickRandomNumber() % MAXPLAYERS) + 1); + modem_networkidlocked = 1; + } + + // FILL IN THE ADVERTISING INFORMATION + modem_gameadvinfo->networkid = modem_networkid; + modem_gameadvinfo->programid = modem_programid; + modem_gameadvinfo->versionid = modem_versionid; + strcpy(modem_gameadvinfo->strings,gamename); + strcpy(modem_gameadvinfo->strings+strlen(gamename)+1,gamedescription); + modem_gameadvinfo->bytes = 2*sizeof(DWORD)+strlen(gamename)+strlen(gamedescription)+2; + + modem_critsect.Leave(); + + // IF WE ARE TRYING TO TAKE OVER A GAME FROM A DROPPED SERVER, + // WE WILL CONFIGURE THE LINE TO RECEIVE CALLS IN THE UPCOMING + // LINESTATUS_DISCONNECT + if (!modem_lineestablished) { + if (!TakeCall()) { + SetLastError(SNET_ERROR_NO_NETWORK); + return 0; + } + } + else + SendDataMessage(SYS_GAMEINFO,0xFF,modem_gameadvinfo,modem_gameadvinfo->bytes); + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemStopAdvertisingGame () { + TraceOut("ModemStopAdvertisingGame enter"); + if (!modem_gameadvinfo) { + SetLastError(SNET_ERROR_NOT_OWNER); + return 0; + } + SendDataMessage(SYS_REMOVE,0xFF,modem_gameadvinfo,modem_gameadvinfo->bytes); + modem_critsect.Enter(); + if (modem_gameadvinfo) { + FREE(modem_gameadvinfo); + modem_gameadvinfo = NULL; + } + modem_critsect.Leave(); + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemUnlockDeviceList (SNETSPI_DEVICELISTPTR devicelist) { + if (devicelist) + LISTCLEAR(&devicelist); + return 1; +} + +//=========================================================================== +BOOL CALLBACK ModemUnlockGameList (SNETSPI_GAMELISTPTR gamelist, + DWORD *hintnextcall) { + modem_critsect.Leave(); + if (hintnextcall) + *hintnextcall = 1000; + SendDataMessage(SYS_QUERYGAME,0xFF,NULL,0); + return 1; +} + +/**************************************************************************** +* +* EXPORTED STRUCTURES +* +***/ + +DWORD modem_id = PROVIDERID; +LPCSTR modem_desc = "Modem"; +LPCSTR modem_req = "Two computers, each with its own modem and phone line."; +SNETCAPS modem_caps = {sizeof(SNETCAPS), // size +#ifdef _DEBUG + SNET_CAPS_DEBUGONLY, +#else + SNET_CAPS_RETAILONLY, +#endif + MAXMESSAGESIZE, // max message size + 16, // max queue size, + MAXPLAYERS, // max players, + 1000, // bytes per second + 250, // latency (ms) + 4, // default turns per second + 2}; // default turns in transit +SNETSPI modem_spi = {sizeof(SNETSPI), + ModemCompareNetAddresses, + ModemDestroy, + ModemFree, + ModemFreeExternalMessage, + ModemGetGameInfo, + ModemGetPerformanceData, + ModemInitialize, + ModemInitializeDevice, + ModemLockDeviceList, + ModemLockGameList, + ModemReceive, + ModemReceiveExternalMessage, + ModemSelectGame, + ModemSend, + ModemSendExternalMessage, + ModemStartAdvertisingGame, + ModemStopAdvertisingGame, + ModemUnlockDeviceList, + ModemUnlockGameList}; diff --git a/src/Storm/SOURCE/STANDARD/NULL.CPP b/src/Storm/SOURCE/STANDARD/NULL.CPP new file mode 100644 index 0000000..aeffe0b --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/NULL.CPP @@ -0,0 +1,261 @@ +/**************************************************************************** +* +* NULL.CPP +* Null provider +* +* By Michael O'Brien (6/27/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define MAXMESSAGESIZE 512 + +/**************************************************************************** +* +* SERVICE PROVIDER INTERFACE FUNCTIONS +* +***/ + +//=========================================================================== +BOOL CALLBACK NullCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude) { + if (diffmagnitude) + *diffmagnitude = 0; + if (!(addr1 && addr2)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + if (diffmagnitude) + *diffmagnitude = !memcmp(addr1,addr2,sizeof(SNETADDR)); + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullDestroy () { + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullFree (SNETADDRPTR addr, + LPVOID data, + DWORD databytes) { + if (!(addr && data)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullFreeExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR mesage) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; +} + +//=========================================================================== +BOOL CALLBACK NullGetGameInfo (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + SNETSPI_GAMELIST *gameinfo) { + SetLastError(SNET_ERROR_GAME_NOT_FOUND); + return 0; +} + +//=========================================================================== +BOOL CALLBACK NullGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq) { + return PerfGetPerformanceData(counterid, + countervalue, + measurementtime, + measurementfreq); +} + +//=========================================================================== +BOOL CALLBACK NullInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + HANDLE event) { + PerfReset(); + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + + // WE NEVER RETURN ANY DEVICES, SO THIS FUNCTION SHOULD NEVER BE CALLED + return 0; +} + +//=========================================================================== +BOOL CALLBACK NullLockDeviceList (SNETSPI_DEVICELISTPTR *devicelist) { + *devicelist = NULL; + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullLockGameList (DWORD categorybits, + DWORD categorymask, + SNETSPI_GAMELISTPTR *gamelist) { + if (gamelist) + *gamelist = NULL; + if (!gamelist) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + return 1; +} + +//=========================================================================== +/* +BOOL CALLBACK NullReceive (SNETADDRPTR *addr, + LPVOID *data, + DWORD *databytes) { +*/ +BOOL CALLBACK NullReceive (LPVOID *data, + DWORD *databytes, + SNETADDRPTR *addr) { + if (addr) + *addr = NULL; + if (data) + *data = NULL; + if (databytes) + *databytes = NULL; + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; +} + +//=========================================================================== +BOOL CALLBACK NullReceiveExternalMessage (LPCSTR *senderpath, + LPCSTR *sendername, + LPCSTR *message) { + if (senderpath) + *senderpath = NULL; + if (sendername) + *sendername = NULL; + if (message) + *message = NULL; + + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; +} + +//=========================================================================== +BOOL CALLBACK NullSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + return 0; +} + +//=========================================================================== +BOOL CALLBACK NullSend (DWORD addresses, + SNETADDRPTR *addrlist, + LPVOID data, + DWORD databytes) { + if (!(addresses && addrlist && data && databytes)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullSendExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR targetpath, + LPCSTR targetname, + LPCSTR message) { + return 0; +} + +//=========================================================================== +BOOL CALLBACK NullStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD gameage, + DWORD gamecategorybits, + DWORD optcategorybits, + LPCVOID clientdata, + DWORD clientdatabytes) { + if (!(gamename && gamedescription)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullStopAdvertisingGame () { + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullUnlockDeviceList (SNETSPI_DEVICELISTPTR devicelist) { + return 1; +} + +//=========================================================================== +BOOL CALLBACK NullUnlockGameList (SNETSPI_GAMELISTPTR gamelist, + DWORD *hintnextcall) { + if (hintnextcall) + *hintnextcall = 0; + return 1; +} + +/**************************************************************************** +* +* EXPORTED STRUCTURES +* +***/ + +DWORD null_id = 0; +LPCSTR null_desc = ""; +LPCSTR null_req = ""; +SNETCAPS null_caps = {sizeof(SNETCAPS), // size +#ifdef _DEBUG + SNET_CAPS_DEBUGONLY, +#else + SNET_CAPS_RETAILONLY, +#endif + MAXMESSAGESIZE, // max message size + 16, // max queue size, + 1, // max players, + 0x300000, // bytes per second + 0, // latency (ms) + 30, // default turns per second + 0}; // default turns in transit +SNETSPI null_spi = {sizeof(SNETSPI), + NullCompareNetAddresses, + NullDestroy, + NullFree, + NullFreeExternalMessage, + NullGetGameInfo, + NullGetPerformanceData, + NullInitialize, + NullInitializeDevice, + NullLockDeviceList, + NullLockGameList, + NullReceive, + NullReceiveExternalMessage, + NullSelectGame, + NullSend, + NullSendExternalMessage, + NullStartAdvertisingGame, + NullStopAdvertisingGame, + NullUnlockDeviceList, + NullUnlockGameList}; diff --git a/src/Storm/SOURCE/STANDARD/PCH.H b/src/Storm/SOURCE/STANDARD/PCH.H new file mode 100644 index 0000000..88ce73b --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/PCH.H @@ -0,0 +1,9 @@ +#define STRICT +#include +#include +#include +#include +#include +#include "standard.h" +#include "trace.h" +#include "resource.h" diff --git a/src/Storm/SOURCE/STANDARD/PERF.CPP b/src/Storm/SOURCE/STANDARD/PERF.CPP new file mode 100644 index 0000000..9c2a041 --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/PERF.CPP @@ -0,0 +1,63 @@ +/**************************************************************************** +* +* PERF.CPP +* Common performance monitoring functions +* +* By Michael O'Brien (12/1/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +static DWORD perfdata[PERFNUM] = {0}; + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +void PerfAdd (DWORD id, DWORD value) { + if (id < PERFNUM) + perfdata[id] += value; +} + +//=========================================================================== +BOOL PerfGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq) { + switch (counterid) { + + case SNET_PERFID_PKTSENTONWIRE: + *countervalue = perfdata[PERF_PKTSENT]; + return 1; + + case SNET_PERFID_PKTRECVONWIRE: + *countervalue = perfdata[PERF_PKTRECV]; + return 1; + + case SNET_PERFID_BYTESSENTONWIRE: + *countervalue = perfdata[PERF_BYTESSENT]; + return 1; + + case SNET_PERFID_BYTESRECVONWIRE: + *countervalue = perfdata[PERF_BYTESRECV]; + return 1; + + } + return 0; +} + +//=========================================================================== +void PerfIncrement (DWORD id) { + if (id < PERFNUM) + InterlockedIncrement((LONG *)&perfdata[id]); +} + +//=========================================================================== +void PerfReset () { + ZeroMemory(&perfdata[0],PERFNUM*sizeof(DWORD)); +} diff --git a/src/Storm/SOURCE/STANDARD/RESOURCE.H b/src/Storm/SOURCE/STANDARD/RESOURCE.H new file mode 100644 index 0000000..5d81a3a --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/RESOURCE.H @@ -0,0 +1,59 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by standard.RC +// +#define IDS_PBADD 1 +#define IDS_PBEDIT 2 +#define IDC_CREATEGAME 3 +#define IDC_MODEMJOIN 3 +#define IDS_NODEVICES 3 +#define IDS_NOLOCATIONS 4 +#define IDS_DIALING 5 +#define IDS_RINGING 6 +#define IDS_CONNECTING 7 +#define IDS_PROCEEDING 8 +#define IDS_DIALTONE 9 +#define IDC_GAMEDESCRIPTION 103 +#define IDC_PROGRAMDESCRIPTION 104 +#define IDD_DIALOG1 104 +#define IDD_DIALOG2 105 +#define IDC_GAMELIST 1001 +#define IDC_EDIT1 1002 +#define IDC_LIST1 1003 +#define IDC_LOCATION 1003 +#define IDC_PHONEBOOK 1003 +#define IDC_EDIT2 1004 +#define IDC_LIST2 1005 +#define IDC_COMBO1 1006 +#define IDC_COUNTRYCODE 1006 +#define IDC_CALL 1008 +#define IDC_CANCEL 1009 +#define IDC_CHECK1 1010 +#define IDC_MODEMCREATE 1011 +#define IDC_DEVICELIST 1013 +#define IDC_CALLINGCARD 1014 +#define IDC_CHANGELOCATION 1015 +#define IDC_CHANGEMODEM 1016 +#define IDC_PHONEBOOKADD 1017 +#define IDC_PHONEBOOKREMOVE 1018 +#define IDC_CURRENTMODEM 1019 +#define IDC_CURRENTLOCATION 1020 +#define IDC_PHONEBOOKEDIT 1021 +#define IDC_PBNAME 1021 +#define IDC_AREACODE 1022 +#define IDC_PBNUMBER 1023 +#define IDC_PBOPERATION 1025 +#define IDC_LOCLIST 1026 +#define IDC_COUNTRY 1026 +#define IDC_CHANGECOUNTRY 1027 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 106 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1028 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Storm/SOURCE/STANDARD/SERIAL.CPP b/src/Storm/SOURCE/STANDARD/SERIAL.CPP new file mode 100644 index 0000000..17abcd6 --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/SERIAL.CPP @@ -0,0 +1,1053 @@ +/**************************************************************************** +* +* SERIAL.CPP +* Serial provider +* +* By Michael O'Brien (8/29/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define MAXMESSAGESIZE 512 +#define MAXPLAYERS 4 +#define PORTS 8 +#define PROVIDERID 'SCBL' +#define READBUFFERSIZE 64 +#define STARTBYTE 0xFE + +#define STATE_NOGAME 0 +#define STATE_FOUNDGAME 1 +#define STATE_INGAME 2 +#define STATE_SHUTDOWN 3 + +#define TYPE_USERDATA 0 +#define TYPE_SYSTEMDATA 1 + +#define SYS_UNUSED 0 +#define SYS_QUERYID 1 +#define SYS_ASSERTID 2 +#define SYS_QUERYGAME 9 +#define SYS_GAMEINFO 10 + +typedef struct _ADVREC { + DWORD networkid; + DWORD programid; + DWORD versionid; + char strings[SNETSPI_MAXSTRINGLENGTH*2]; + DWORD bytes; +} ADVREC, *ADVPTR; + +typedef struct _PACKETHEADER { + BYTE startbyte_type; // must be first field + BYTE sizedwords; // must be second field + BYTE targetmask; + union { + struct { + BYTE fromid:4; + BYTE timetolive:4; + }; + struct { + BYTE sysmsgtype:4; + BYTE timetolive:4; + }; + }; +} PACKETHEADER, *PACKETHEADERPTR; + +typedef struct _MESSAGEREC { + SNETADDR addr; // must be first field + PACKETHEADER header; // must immediately precede data + BYTE data[MAXMESSAGESIZE]; + DWORD bytesneeded; + DWORD bytesread; + DWORD inport; + _MESSAGEREC *next; +} MESSAGEREC, *MESSAGEPTR; + +typedef struct _MESSAGEDATAREC { + PACKETHEADER header; // must immediately precede data + BYTE data[MAXMESSAGESIZE]; +} MESSAGEDATAREC, *MESSAGEDATAPTR; + +typedef struct _PORTREC { + HANDLE handle; + OVERLAPPED overlapped; + BYTE readbuffer[READBUFFERSIZE]; + DWORD bytesread; + MESSAGEPTR partialmessage; + BYTE networkids; +} PORTREC, *PORTPTR; + +static CCritSect serial_critsect; +static HANDLE serial_event[PORTS] = {0}; +static ADVPTR serial_gameadvinfo = NULL; +static SNETSPI_GAMELISTPTR serial_gamelist = NULL; +static DWORD serial_maxplayers = MAXPLAYERS; +static MESSAGEPTR serial_messagehead = NULL; +static BYTE serial_networkid = 0; +static BOOL serial_networkidlocked = 0; +static PORTPTR serial_port[PORTS] = {0}; +static DWORD serial_programid = 0; +static HANDLE serial_recvevent = NULL; +static DWORD serial_routeloopcheck = 0; +static DWORD serial_state = STATE_NOGAME; +static HANDLE serial_thread = NULL; +static DWORD serial_versionid = 0; +static BOOL serial_versionmismatch = 0; + +static DWORD PickRandomNumber (); +static void SendFormedMessage (MESSAGEDATAPTR messageptr, + DWORD exceptport, + BOOL wait); +static BOOL SendMessage (BYTE sysmsgtype, + BYTE targetmask, + LPVOID data, + DWORD databytes); +BOOL CALLBACK SerialStopAdvertisingGame (); + +//=========================================================================== +static BOOL FindNetworkId () { + DWORD timeout = 16; + while (timeout--) { + + // PICK A RANDOM NUMBER WHICH WE CAN USE TO RECOGNIZE AND DISCARD OUR + // OWN PACKETS IN THE CASE OF A ROUTING LOOP. MAKE SURE THE NUMBER IS + // NOT ZERO, BECAUSE COMPUTERS WITH ESTABLISHED NETWORK IDS WILL USE ZERO. + serial_routeloopcheck = 0; + while (!serial_routeloopcheck) + serial_routeloopcheck = PickRandomNumber(); + + // PICK A NETWORK ID AT RANDOM, AND SEND OUT A QUERY TO SEE IF ANYONE + // ELSE IS USING IT. + serial_networkid = 0; + while (!serial_networkid) + serial_networkid = (BYTE)(PickRandomNumber() & 7); + DWORD messagedata[2] = {serial_networkid,serial_routeloopcheck}; + SendMessage(SYS_QUERYID,0xFF,&messagedata[0],2*sizeof(DWORD)); + + // WAIT 500 MILLISECONDS FOR A RESPONSE. IF ANY OTHER COMPUTER ASSERTS + // THAT IT IS USING THE ID WE PICKED, OR IF ANY OTHER COMPUTER QUERIES + // FOR THE SAME ID, THEN GIVE UP THAT ID AND PICK A NEW ONE. + DWORD starttime = GetTickCount(); + while (serial_networkid && (GetTickCount()-starttime < 500)) + Sleep(1); + if (!serial_networkid) + continue; + + // NO OTHER COMPUTER CONTESTED OUR NETWORK ID. LOCK IT DOWN, ASSERT IT + // ON THE NETWORK, AND RETURN SUCCESS. + serial_networkidlocked = 1; + serial_routeloopcheck = 0; + SendMessage(SYS_ASSERTID,0xFF,&serial_networkid,sizeof(DWORD)); + return 1; + + } + return 0; +} + +//=========================================================================== +static BOOL InitializePort (DWORD port) { + + // ALLOCATE MEMORY FOR THE PORT RECORD + if (!serial_port[port]) { + serial_port[port] = NEW(PORTREC); + if (serial_port[port]) + ZeroMemory(serial_port[port],sizeof(PORTREC)); + else + return 0; + } + + // CREATE AN EVENT FOR OVERLAPPED I/O + if (!serial_event[port]) { + serial_event[port] = CreateEvent(NULL,1,0,NULL); + if (serial_event[port]) + serial_port[port]->overlapped.hEvent = serial_event[port]; + else + return 0; + } + + // OPEN THE COMMUNICATIONS PORT + { + TCHAR portname[16]; + wsprintf(portname,TEXT("\\\\.\\COM%u"),(port+1)); + serial_port[port]->handle = CreateFile(portname, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + } + + // IF WE COULDN'T OPEN THE PORT THEN IT IS PROBABLY UNCONFIGURED OR IN + // USE BY ANOTHER APPLICATION. RETURN SUCCESS BECAUSE THIS ISN'T A FATAL + // ERROR; WE WILL JUST NOT USE THIS PARTICULAR PORT. + if (serial_port[port]->handle == INVALID_HANDLE_VALUE) + return 1; + + // SET THE COMMUNICATIONS STATE + // (WE DO THIS THE HARD WAY BECAUSE BUILDCOMMDCB() DOESN'T WORK RIGHT + // ON WINDOWS 95) + { + DCB dcb; + ZeroMemory(&dcb,sizeof(DCB)); + dcb.DCBlength = sizeof(DCB); + dcb.BaudRate = CBR_56000; + SRegLoadValue("Network Providers\\Serial","Baud Rate",0,&dcb.BaudRate); + dcb.fBinary = 1; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.ByteSize = 8; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + dcb.ErrorChar = 63; + dcb.EofChar = 26; + SetCommState(serial_port[port]->handle,&dcb); + } + + // SET THE COMMUNICATIONS TIMEOUT VALUES + { + COMMTIMEOUTS timeouts; + ZeroMemory(&timeouts,sizeof(COMMTIMEOUTS)); + timeouts.ReadIntervalTimeout = 5; + SetCommTimeouts(serial_port[port]->handle,&timeouts); + } + + // EXECUTE AN OVERLAPPED READ + ReadFile(serial_port[port]->handle, + serial_port[port]->readbuffer, + READBUFFERSIZE, + &serial_port[port]->bytesread, + &serial_port[port]->overlapped); + + return 1; +} + +//=========================================================================== +static DWORD PickRandomNumber () { + // RETURN A DWORD-SIZED RANDOM NUMBER. IT IS IMPORTANT THAT WE DON'T + // USE THE RUNTIME LIBRARY RANDOM GENERATOR, BECAUSE WE DON'T WANT TO + // INTERFERE WITH THE APPLICATION'S RANDOM SEQUENCE. + LARGE_INTEGER perfcount; + POINT pos; + QueryPerformanceCounter(&perfcount); + GetCursorPos(&pos); + + static DWORD seed = 0x100001; + seed ^= perfcount.LowPart ^ GetTickCount() ^ pos.x ^ pos.y; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand1 = seed & 0xFFFF; + seed = (seed*0x7D+3) % 0x2AAAAB; + DWORD rand2 = seed & 0xFFFF; + return (rand1 << 16) | rand2; +} + +//=========================================================================== +static void ProcessIncomingMessage (DWORD port, MESSAGEPTR messageptr) { + PerfIncrement(PERF_PKTRECV); + PerfAdd(PERF_BYTESRECV,messageptr->bytesread); + BOOL systemmessage = (messageptr->header.startbyte_type-STARTBYTE == TYPE_SYSTEMDATA); + + // VALIDATE THE PORT NUMBER + if (port >= PORTS) { + FREE(messageptr); + return; + } + + // IF THIS MESSAGE HAS A NON-ZERO TIME TO LIVE AND HAS ADDITIONAL + // RECIPIENTS, SEND IT OUT ON ALL ACTIVE PORTS WHICH LEAD TO THE + // OTHER TARGET RECIPIENTS, EXCEPT THE PORT THE MESSAGE CAME IN ON + BYTE origtargetmask = messageptr->header.targetmask; + if (messageptr->header.timetolive--) { + if (serial_networkid && serial_networkidlocked) + messageptr->header.targetmask &= ~(1 << serial_networkid); + if (messageptr->header.targetmask) + SendFormedMessage((MESSAGEDATAPTR)&messageptr->header, + port, + 1); + } + + // VERIFY THAT WE ARE A RECIPIENT OF THIS MESSAGE, AND NOT THE SENDER + if (serial_networkid && serial_networkidlocked && + ((!(origtargetmask & (1 << serial_networkid))) || + ((!systemmessage) && + (messageptr->header.fromid == serial_networkid)))) { + FREE(messageptr); + return; + } + + // PROCESS USER MESSAGES + if (!systemmessage) + if (serial_networkid && serial_networkidlocked) { + *(LPBYTE)&messageptr->addr = messageptr->header.fromid; + LISTADDPTREND(&serial_messagehead,messageptr); + if (serial_recvevent) + SetEvent(serial_recvevent); + } + else + FREE(messageptr); + + // PROCESS SYSTEM MESSAGES + else { + switch (messageptr->header.sysmsgtype) { + + case SYS_QUERYID: + if (messageptr->bytesread >= sizeof(PACKETHEADER)+2*sizeof(DWORD)) { + DWORD networkid = *(LPDWORD)&messageptr->data[0]; + DWORD routeloopcheck = *(LPDWORD)&messageptr->data[sizeof(DWORD)]; + if (routeloopcheck != serial_routeloopcheck) + if (serial_networkidlocked) + SendMessage(SYS_ASSERTID,0xFF,&serial_networkid,sizeof(DWORD)); + else if (networkid == serial_networkid) + serial_networkid = 0; + } + break; + + case SYS_ASSERTID: + if (messageptr->bytesread >= sizeof(PACKETHEADER)+sizeof(DWORD)) { + DWORD networkid = *(LPDWORD)&messageptr->data[0]; + serial_port[port]->networkids |= (1 << networkid); + if ((!serial_networkidlocked) && (networkid == serial_networkid)) + serial_networkid = 0; + } + break; + + case SYS_QUERYGAME: + if (serial_gameadvinfo) + SendMessage(SYS_GAMEINFO,0xFF,serial_gameadvinfo,serial_gameadvinfo->bytes); + break; + + case SYS_GAMEINFO: + { + ADVPTR advinfo = (ADVPTR)&messageptr->data[0]; + if ((advinfo->programid == serial_programid) && + (advinfo->versionid == serial_versionid)) { + if (!serial_gamelist) { + serial_gamelist = NEW(SNETSPI_GAMELIST); + ZeroMemory(serial_gamelist,sizeof(SNETSPI_GAMELIST)); + } + if (serial_gamelist) { + *(LPBYTE)&serial_gamelist->owner = (BYTE)advinfo->networkid; + serial_gamelist->gameid = 1; + strcpy(serial_gamelist->gamename,advinfo->strings); + strcpy(serial_gamelist->gamedescription,advinfo->strings+strlen(advinfo->strings)+1); + } + } + else + serial_versionmismatch = 1; + } + break; + + } + FREE(messageptr); + } + +} + +//=========================================================================== +static void SendFormedMessage (MESSAGEDATAPTR messageptr, + DWORD exceptport, + BOOL wait) { + BOOL systemmessage = (messageptr->header.startbyte_type == STARTBYTE+TYPE_SYSTEMDATA); + + // IF THIS IS A SYSTEM MESSAGE, WRITE IT OUT ON ALL ACTIVE PORTS. + // OTHERWISE, WRITE IT OUT ON ALL PORTS WHICH LEAD TO ANY OF THE + // DESIRED NETWORK IDS. + HANDLE event[PORTS]; + OVERLAPPED overlapped[PORTS]; + DWORD byteswritten[PORTS]; + DWORD numsends = 0; + { + for (DWORD port = 0; port < PORTS; ++port) + if ((port != exceptport) && + (serial_port[port]->handle != INVALID_HANDLE_VALUE) && + (systemmessage || + (serial_port[port]->networkids & messageptr->header.targetmask))) { + ZeroMemory(&overlapped[numsends],sizeof(OVERLAPPED)); + if (wait) + event[numsends] = CreateEvent(NULL,0,0,NULL); + overlapped[numsends].hEvent = event[numsends]; + WriteFile(serial_port[port]->handle, + messageptr, + messageptr->header.sizedwords*sizeof(DWORD), + &byteswritten[numsends], + &overlapped[numsends]); + ++numsends; + PerfIncrement(PERF_PKTSENT); + PerfAdd(PERF_BYTESSENT,messageptr->header.sizedwords*sizeof(DWORD)); + } + } + + // WAIT FOR ALL WRITES TO COMPLETE + if (numsends && wait) { + WaitForMultipleObjects(numsends,&event[0],1,INFINITE); + while (numsends--) + CloseHandle(event[numsends]); + } + +} + +//=========================================================================== +static BOOL SendMessage (BYTE sysmsgtype, + BYTE targetmask, + LPVOID data, + DWORD databytes) { + BOOL systemmessage = (sysmsgtype != SYS_UNUSED); + if (systemmessage) + targetmask = 0xFF; + + // REFUSE TO SEND A NON-SYSTEM MESSAGE IF WE DON'T HAVE A VALID NETWORK ID + if ((sysmsgtype == SYS_UNUSED) && (!(serial_networkid && serial_networkidlocked))) + return 0; + + // CREATE A FULLY-FORMED MESSAGE + MESSAGEDATAREC messagedata; + ZeroMemory(&messagedata,sizeof(MESSAGEDATAREC)); + messagedata.header.startbyte_type = STARTBYTE+((sysmsgtype == SYS_UNUSED) ? TYPE_USERDATA : TYPE_SYSTEMDATA); + messagedata.header.sizedwords = (sizeof(PACKETHEADER)+databytes+sizeof(DWORD)-1)/sizeof(DWORD); + messagedata.header.timetolive = MAXPLAYERS; + messagedata.header.targetmask = targetmask; + if (systemmessage) + messagedata.header.sysmsgtype = sysmsgtype; + else + messagedata.header.fromid = serial_networkid; + if (data && databytes) + CopyMemory(&messagedata.data[0],data,databytes); + + // SEND IT + SendFormedMessage(&messagedata,0xFFFFFFFF,1); + + return 1; +} + +//=========================================================================== +static unsigned CALLBACK ThreadProc (LPVOID) { + while (serial_state != STATE_SHUTDOWN) { + serial_critsect.Enter(); + for (DWORD port = 0; port < PORTS; ++port) + if (serial_port[port]->handle != INVALID_HANDLE_VALUE) { + + // CHECK TO SEE IF AN I/O OPERATION HAS COMPLETED ON THIS PORT + if (GetOverlappedResult(serial_port[port]->handle, + &serial_port[port]->overlapped, + &serial_port[port]->bytesread, + 0)) { + + // IF SO, PARSE THE INCOMING DATA + DWORD bytesleft = serial_port[port]->bytesread; + LPBYTE dataptr = &serial_port[port]->readbuffer[0]; + while (bytesleft) { + + // IF WE HAVE A PARTIAL MESSAGE WAITING, TRY TO COMPLETE THE + // MESSAGE + if (serial_port[port]->partialmessage) { + if (!serial_port[port]->partialmessage->bytesneeded) + serial_port[port]->partialmessage->bytesneeded + = min(sizeof(PACKETHEADER)+MAXMESSAGESIZE, + (*dataptr)*sizeof(DWORD)); + LPBYTE writeptr = (LPBYTE)&serial_port[port]->partialmessage->header; + DWORD bytestocopy = min(bytesleft, + serial_port[port]->partialmessage->bytesneeded + -serial_port[port]->partialmessage->bytesread); + CopyMemory(writeptr+serial_port[port]->partialmessage->bytesread, + dataptr, + bytestocopy); + serial_port[port]->partialmessage->bytesread += bytestocopy; + dataptr += bytestocopy; + bytesleft -= bytestocopy; + if (serial_port[port]->partialmessage->bytesread >= serial_port[port]->partialmessage->bytesneeded) { + ProcessIncomingMessage(port,serial_port[port]->partialmessage); + serial_port[port]->partialmessage = NULL; + } + } + + // SCAN TO THE BEGINNING OF THE NEXT MESSAGE + while (bytesleft && (*dataptr < STARTBYTE)) { + ++dataptr; + --bytesleft; + } + + // IF A MESSAGE IS AVAILABLE, CREATE A NEW MESSAGE RECORD TO + // HOLD IT + if (bytesleft) { + MESSAGEPTR messageptr = NEW(MESSAGEREC); + if (messageptr) { + ZeroMemory(messageptr,sizeof(MESSAGEREC)); + messageptr->inport = port; + messageptr->bytesneeded = (bytesleft >= 2) ? (*(dataptr+1))*sizeof(DWORD) + : 0; + if (messageptr->bytesneeded > sizeof(PACKETHEADER)+MAXMESSAGESIZE) + messageptr->bytesneeded = sizeof(PACKETHEADER)+MAXMESSAGESIZE; + DWORD bytestocopy = messageptr->bytesneeded ? min(bytesleft,messageptr->bytesneeded) + : 1; + LPBYTE writeptr = (LPBYTE)&messageptr->header; + CopyMemory(writeptr,dataptr,bytestocopy); + dataptr += bytestocopy; + bytesleft -= bytestocopy; + messageptr->bytesread = bytestocopy; + if (messageptr->bytesneeded && + (messageptr->bytesread >= messageptr->bytesneeded)) + ProcessIncomingMessage(port,messageptr); + else + serial_port[port]->partialmessage = messageptr; + } + else + bytesleft = 0; + } + + } + + // RETURN THIS PORT'S EVENT TO A NONSIGNALED STATE + ResetEvent(serial_event[port]); + + // POST ANOTHER OVERLAPPED READ FOR THIS PORT + ReadFile(serial_port[port]->handle, + serial_port[port]->readbuffer, + READBUFFERSIZE, + &serial_port[port]->bytesread, + &serial_port[port]->overlapped); + + } + + } + serial_critsect.Leave(); + WaitForMultipleObjects(PORTS,&serial_event[0],0,INFINITE); + } + serial_state = STATE_NOGAME; + _endthreadex(0); + return 0; +} + +/**************************************************************************** +* +* SERVICE PROVIDER INTERFACE FUNCTIONS +* +***/ + +//=========================================================================== +BOOL CALLBACK SerialCompareNetAddresses (SNETADDRPTR addr1, + SNETADDRPTR addr2, + DWORD *diffmagnitude) { + if (diffmagnitude) + *diffmagnitude = 0; + if (!(addr1 && addr2)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + *diffmagnitude = (memcmp(addr1,addr2,sizeof(SNETADDR)) != 0); + return 1; +} + +//=========================================================================== +BOOL CALLBACK SerialDestroy () { + + // TERMINATE THE READ THREAD + if (serial_thread) { + serial_state = STATE_SHUTDOWN; + for (DWORD port = 0; port < PORTS; ++port) + if (serial_port[port]->handle != INVALID_HANDLE_VALUE) + SetEvent(serial_port[port]->overlapped.hEvent); + WaitForSingleObject(serial_thread,INFINITE); + serial_thread = NULL; + } + + // WRITE A FINAL CR/LF TO EVERY PORT WE OPENED, TO PUT ANY MODEMS WE MAY + // HAVE SENT GARBAGE TO DURING THE AUTO-DETECTION PROCESS BACK INTO A + // KNOWN STATE + { + HANDLE event[PORTS]; + OVERLAPPED overlapped[PORTS]; + DWORD byteswritten[PORTS]; + DWORD numsends = 0; + { + for (DWORD port = 0; port < PORTS; ++port) + if (serial_port[port]->handle != INVALID_HANDLE_VALUE) { + ZeroMemory(&overlapped[numsends],sizeof(OVERLAPPED)); + event[numsends] = CreateEvent(NULL,0,0,NULL); + overlapped[numsends].hEvent = event[numsends]; + WriteFile(serial_port[port]->handle, + "\n", + 2, + &byteswritten[numsends], + &overlapped[numsends]); + ++numsends; + PerfIncrement(PERF_PKTSENT); + PerfAdd(PERF_BYTESSENT,2); + } + } + if (numsends) { + WaitForMultipleObjects(numsends,&event[0],1,INFINITE); + while (numsends--) + CloseHandle(event[numsends]); + } + } + + // CLOSE AND FREE ALL PORTS + for (DWORD port = 0; port < PORTS; ++port) { + CloseHandle(serial_event[port]); + if (serial_port[port]->handle != INVALID_HANDLE_VALUE) + CloseHandle(serial_port[port]->handle); + if (serial_port[port]->partialmessage) + FREE(serial_port[port]->partialmessage); + FREE(serial_port[port]); + serial_port[port] = NULL; + } + + // STOP ADVERTISING GAMES + SerialStopAdvertisingGame(); + + // FREE ALL MESSAGES + LISTCLEAR(&serial_messagehead); + + // FREE THE GAME LIST + if (serial_gamelist) { + FREE(serial_gamelist); + serial_gamelist = NULL; + } + + // RESET OUR NETWORK ID + serial_networkid = 0; + serial_networkidlocked = 0; + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SerialFree (SNETADDRPTR addr, + LPVOID data, + DWORD databytes) { + if (!(addr && data)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + FREE(addr); + return 1; +} + +//=========================================================================== +BOOL CALLBACK SerialFreeExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR mesage) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; +} + +//=========================================================================== +BOOL CALLBACK SerialGetGameInfo (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + SNETSPI_GAMELIST *gameinfo) { + if (gameinfo) + ZeroMemory(gameinfo,sizeof(SNETSPI_GAMELIST)); + if (!(gamename && gameinfo && (gameid || *gamename))) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // IF THE GAME IN THE GAME LIST MATCHES THE QUERY PARAMETERS, RETURN + // ITS INFORMATION + serial_critsect.Enter(); + if (serial_gamelist && + ((!gameid) || (gameid == serial_gamelist->gameid)) && + ((!*gamename) || !_stricmp(gamename,serial_gamelist->gamename))) + CopyMemory(gameinfo,serial_gamelist,sizeof(SNETSPI_GAMELIST)); + serial_critsect.Leave(); + + if (gameinfo->gameid) + return 1; + else { + SetLastError(SNET_ERROR_GAME_NOT_FOUND); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK SerialGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq) { + return PerfGetPerformanceData(counterid, + countervalue, + measurementtime, + measurementfreq); +} + +//=========================================================================== +BOOL CALLBACK SerialInitialize (SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + HANDLE event) { + + // SAVE THE PROGRAM AND VERSION IDS AND THE RECEIVE EVENT HANDLE + serial_programid = programdata->programid; + serial_versionid = programdata->versionid; + serial_maxplayers = min(programdata->maxplayers,MAXPLAYERS); + serial_recvevent = event; + + // RESET PERFORMANCE DATA + PerfReset(); + + // INITIALIZE THE SERIAL PORTS + { + for (DWORD loop = 0; loop < PORTS; ++loop) + if (!InitializePort(loop)) { + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + } + + // CREATE A THREAD TO PROCESS INCOMING PACKETS + if (!serial_thread) { + unsigned threadid; + serial_thread = (HANDLE)_beginthreadex(NULL, + 0, + ThreadProc, + NULL, + 0, + &threadid); + if (serial_thread) + SetThreadPriority(serial_thread,THREAD_PRIORITY_HIGHEST); + else { + SerialDestroy(); + SetLastError(SNET_ERROR_MAX_THRDS_REACHED); + return 0; + } + } + + // FIND AN UNUSED NETWORK ID + if (!FindNetworkId()) { + SetLastError(SNET_ERROR_TOO_MANY_NAMES); + return 0; + } + + // SEND OUT A QUERY FOR ACTIVE GAMES + SendMessage(SYS_QUERYGAME,0xFF,NULL,0); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SerialInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + + // WE NEVER RETURN ANY DEVICES, SO THIS FUNCTION SHOULD NEVER BE CALLED + return 0; +} + +//=========================================================================== +BOOL CALLBACK SerialLockDeviceList (SNETSPI_DEVICELISTPTR *devicelist) { + if (!devicelist) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + *devicelist = NULL; + return 1; +} + +//=========================================================================== +BOOL CALLBACK SerialLockGameList (DWORD categorybits, + DWORD categorymask, + SNETSPI_GAMELISTPTR *gamelist) { + if (!gamelist) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + if (serial_versionmismatch) { + SetLastError(SNET_ERROR_VERSION_MISMATCH); + return 0; + } + serial_critsect.Enter(); + *gamelist = serial_gamelist; + return 1; +} + +//=========================================================================== +/* +BOOL CALLBACK SerialReceive (SNETADDRPTR *addr, + LPVOID *data, + DWORD *databytes) { +*/ +BOOL CALLBACK SerialReceive (LPVOID *data, + DWORD *databytes, + SNETADDRPTR *addr) { + if (addr) + *addr = NULL; + if (data) + *data = NULL; + if (databytes) + *databytes = NULL; + if (!(addr && data && databytes)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + if (serial_messagehead) { + serial_critsect.Enter(); + *addr = &serial_messagehead->addr; + *data = &serial_messagehead->data[0]; + *databytes = serial_messagehead->bytesread-sizeof(PACKETHEADER); + LISTFREEPTR(&serial_messagehead,serial_messagehead); + serial_critsect.Leave(); + return 1; + } + else { + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; + } +} + +//=========================================================================== +BOOL CALLBACK SerialReceiveExternalMessage (LPCSTR *senderpath, + LPCSTR *sendername, + LPCSTR *message) { + if (senderpath) + *senderpath = NULL; + if (sendername) + *sendername = NULL; + if (message) + *message = NULL; + + SetLastError(SNET_ERROR_NO_MESSAGES_WAITING); + return 0; +} + +//=========================================================================== +BOOL CALLBACK SerialSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + + // IF WE DON'T YET KNOW OF ANY GAMES, WAIT A REASONABLE AMOUNT OF TIME + // FOR ADVERTISEMENTS TO COME IN + if (!serial_gamelist) + Sleep(500); + + // GET THE GAME INFORMATION FROM THE FIRST (AND ONLY) GAME IN THE + // GAME LIST + SNETSPI_GAMELIST gameinfo; + serial_critsect.Enter(); + if (serial_gamelist) + CopyMemory(&gameinfo,serial_gamelist,sizeof(SNETSPI_GAMELIST)); + else + ZeroMemory(&gameinfo,sizeof(SNETSPI_GAMELIST)); + serial_critsect.Leave(); + + // IF THERE IS A COMPATIBLE GAME IN THE GAME LIST, JOIN IT + if (serial_gamelist) + return SNetJoinGame(gameinfo.gameid, + gameinfo.gamename, + NULL, + playerdata->playername, + playerdata->playerdescription, + playerid); + + // OTHERWISE, CALL THE CREATE GAME CALLBACK TO CREATE A NEW ONE + else if (interfacedata && interfacedata->createcallback) { + SNETCREATEDATA createdata; + ZeroMemory(&createdata,sizeof(SNETCREATEDATA)); + createdata.size = sizeof(SNETCREATEDATA); + createdata.providerid = PROVIDERID; + createdata.maxplayers = serial_maxplayers; + createdata.createflags = 0; + return interfacedata->createcallback(&createdata, + programdata, + playerdata, + interfacedata, + versiondata, + playerid); + } + else + return 0; + +} + +//=========================================================================== +BOOL CALLBACK SerialSend (DWORD addresses, + SNETADDRPTR *addrlist, + LPVOID data, + DWORD databytes) { + if (!(addresses && addrlist && data && databytes)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // BUILD A TARGET MASK OUT OF THE LIST OF ADDRESSES + BYTE targetmask = 0; + while (addresses--) + targetmask |= (1 << *(LPBYTE)*(addrlist+addresses)); + + // SEND THE MESSAGE + return SendMessage(SYS_UNUSED,targetmask,data,databytes); +} + +//=========================================================================== +BOOL CALLBACK SerialSendExternalMessage (LPCSTR senderpath, + LPCSTR sendername, + LPCSTR targetpath, + LPCSTR targetname, + LPCSTR message) { + return 0; +} + +//=========================================================================== +BOOL CALLBACK SerialStartAdvertisingGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamemode, + DWORD gameage, + DWORD gamecategorybits, + DWORD optcategorybits, + LPCVOID clientdata, + DWORD clientdatabytes) { + if (!(gamename && gamedescription)) { + SetLastError(SNET_ERROR_INVALID_PARAMETER); + return 0; + } + + // STOP ADVERTISING ANY GAME WE ARE CURRENTLY ADVERTISING + if (serial_gameadvinfo) + SerialStopAdvertisingGame(); + + // REFUSE TO ADVERTISE A NEW GAME IF ANY OTHER GAME IS BEING + // ADVERTISED ON THIS SERIAL NETWORK + if (serial_gamelist) + if (gamemode & SNET_GM_ADVERTISED) { + FREE(serial_gamelist); + serial_gamelist = NULL; + } + else { + SetLastError(SNET_ERROR_TOO_MANY_NAMES); + return 0; + } + + // CREATE RECORDS TO ADVERTISE THE GAME + serial_gameadvinfo = NEW(ADVREC); + serial_gamelist = NEW(SNETSPI_GAMELIST); + if (serial_gameadvinfo && serial_gamelist) { + ZeroMemory(serial_gameadvinfo,sizeof(ADVREC)); + ZeroMemory(serial_gamelist ,sizeof(SNETSPI_GAMELIST)); + } + else { + if (serial_gameadvinfo) { + FREE(serial_gameadvinfo); + serial_gameadvinfo = NULL; + } + if (serial_gamelist) { + FREE(serial_gamelist); + serial_gamelist = NULL; + } + SetLastError(SNET_ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + // FILL IN THE ADVERTISING INFORMATION + serial_critsect.Enter(); + serial_gameadvinfo->networkid = serial_networkid; + serial_gameadvinfo->programid = serial_programid; + serial_gameadvinfo->versionid = serial_versionid; + strcpy(serial_gameadvinfo->strings,gamename); + strcpy(serial_gameadvinfo->strings+strlen(gamename)+1,gamedescription); + serial_gameadvinfo->bytes = 2*sizeof(DWORD)+strlen(gamename)+strlen(gamedescription)+2; + + // FILL IN THE GAME LIST + serial_gamelist->gameid = 1; + *(LPBYTE)&serial_gamelist->owner = serial_networkid; + strcpy(serial_gamelist->gamename,gamename); + strcpy(serial_gamelist->gamedescription,gamedescription); + serial_critsect.Leave(); + + // SEND OUT THE GAME INFORMATION + SendMessage(SYS_GAMEINFO,0xFF,serial_gameadvinfo,serial_gameadvinfo->bytes); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SerialStopAdvertisingGame () { + if (!serial_gameadvinfo) { + SetLastError(SNET_ERROR_NOT_OWNER); + return 0; + } + + // STOP ADVERTISING THE GAME + serial_critsect.Enter(); + if (serial_gameadvinfo) { + FREE(serial_gameadvinfo); + serial_gameadvinfo = NULL; + } + if (serial_gamelist) { + FREE(serial_gamelist); + serial_gamelist = NULL; + } + serial_critsect.Leave(); + + // SEND OUT A NEW QUERY + Sleep(500); + SendMessage(SYS_QUERYGAME,0xFF,NULL,0); + + return 1; +} + +//=========================================================================== +BOOL CALLBACK SerialUnlockDeviceList (SNETSPI_DEVICELISTPTR devicelist) { + return 1; +} + +//=========================================================================== +BOOL CALLBACK SerialUnlockGameList (SNETSPI_GAMELISTPTR gamelist, + DWORD *hintnextcall) { + serial_critsect.Leave(); + if (hintnextcall) + *hintnextcall = gamelist ? 0 : 500; + return 1; +} + +/**************************************************************************** +* +* EXPORTED STRUCTURES +* +***/ + +DWORD serial_id = PROVIDERID; +LPCSTR serial_desc = "Direct Cable Connection"; +LPCSTR serial_req = "Two or more computers connected together with serial cables and null-modems."; +SNETCAPS serial_caps = {sizeof(SNETCAPS), // size +#ifdef _DEBUG + SNET_CAPS_DEBUGONLY, +#else + SNET_CAPS_RETAILONLY, +#endif + MAXMESSAGESIZE, // max message size + 16, // max queue size, + MAXPLAYERS, // max players, + 1500, // bytes per second + 500, // latency (ms) + 4, // default turns per second + 2}; // default turns in transit +SNETSPI serial_spi = {sizeof(SNETSPI), + SerialCompareNetAddresses, + SerialDestroy, + SerialFree, + SerialFreeExternalMessage, + SerialGetGameInfo, + SerialGetPerformanceData, + SerialInitialize, + SerialInitializeDevice, + SerialLockDeviceList, + SerialLockGameList, + SerialReceive, + SerialReceiveExternalMessage, + SerialSelectGame, + SerialSend, + SerialSendExternalMessage, + SerialStartAdvertisingGame, + SerialStopAdvertisingGame, + SerialUnlockDeviceList, + SerialUnlockGameList}; diff --git a/src/Storm/SOURCE/STANDARD/STANDARD.CPP b/src/Storm/SOURCE/STANDARD/STANDARD.CPP new file mode 100644 index 0000000..15fad8c --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/STANDARD.CPP @@ -0,0 +1,94 @@ +/**************************************************************************** +* +* STANDARD.CPP +* Standard storm network providers +* +* By Michael O'Brien (4/22/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +HINSTANCE global_instance = (HINSTANCE)0; + +//=========================================================================== +extern "C" BOOL APIENTRY SnpQuery (DWORD index, + DWORD *id, + LPCSTR *description, + LPCSTR *requirements, + SNETCAPSPTR *caps) { + if (!(id && description && requirements && caps)) + return 0; + switch (index) { + + case 0: + *id = ipx_id; + *description = ipx_desc; + *requirements = ipx_req; + *caps = &ipx_caps; + return 1; + + case 1: + *id = serial_id; + *description = serial_desc; + *requirements = serial_req; + *caps = &serial_caps; + return 1; + + case 2: + *id = null_id; + *description = null_desc; + *requirements = null_req; + *caps = &null_caps; + return 1; + + case 3: + *id = modem_id; + *description = modem_desc; + *requirements = modem_req; + *caps = &modem_caps; + return 1; + + default: + return 0; + + } +} + +//=========================================================================== +extern "C" BOOL APIENTRY SnpBind (DWORD index, + SNETSPIPTR *spi) { + if (!spi) + return 0; + + switch (index) { + + case 0: + *spi = &ipx_spi; + return 1; + + case 1: + *spi = &serial_spi; + return 1; + + case 2: + *spi = &null_spi; + return 1; + + case 3: + *spi = &modem_spi; + return 1; + + default: + return 0; + + } +} + +//=========================================================================== +extern "C" BOOL APIENTRY DllMain (HINSTANCE passinstance, DWORD reason, LPVOID) { + if (reason == DLL_PROCESS_ATTACH) + global_instance = passinstance; + return 1; +} diff --git a/src/Storm/SOURCE/STANDARD/STANDARD.CS b/src/Storm/SOURCE/STANDARD/STANDARD.CS new file mode 100644 index 0000000..7cfdb47 --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/STANDARD.CS @@ -0,0 +1,18 @@ +#include +#include +set deffile=standard.def +set extralib=wsock32.lib tapi32.lib +set linkopt=%linkopt% -base:0x18000000 + +// DETERMINE THE PROJECT NAME +if %debug% set project=%project%d +set outfile=%project%.snp + +// ADD THE CAPS SIGNATURE TO THE END OF THE FILE +!copy /b %project%.dll+caps.mpq > NUL: + +// RENAME IT TO .SNP AND COPY IT TO THE OUTPUT DIRECTORY +!if exist %outfile% del %outfile% +!rename %project%.dll %outfile% +!copy %outfile% ..\..\bin > NUL: +!if exist *.bak del *.bak diff --git a/src/Storm/SOURCE/STANDARD/STANDARD.DEF b/src/Storm/SOURCE/STANDARD/STANDARD.DEF new file mode 100644 index 0000000..e2987e5 --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/STANDARD.DEF @@ -0,0 +1,3 @@ +EXPORTS +SnpBind +SnpQuery diff --git a/src/Storm/SOURCE/STANDARD/STANDARD.H b/src/Storm/SOURCE/STANDARD/STANDARD.H new file mode 100644 index 0000000..16364ff --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/STANDARD.H @@ -0,0 +1,57 @@ +/**************************************************************************** +* +* GLOBAL VARIABLES +* +***/ + +extern HINSTANCE global_instance; + +/**************************************************************************** +* +* EXPORTED STRUCTURES +* +***/ + +extern DWORD ipx_id; +extern LPCSTR ipx_desc; +extern LPCSTR ipx_req; +extern SNETCAPS ipx_caps; +extern SNETSPI ipx_spi; + +extern DWORD modem_id; +extern LPCSTR modem_desc; +extern LPCSTR modem_req; +extern SNETCAPS modem_caps; +extern SNETSPI modem_spi; + +extern DWORD serial_id; +extern LPCSTR serial_desc; +extern LPCSTR serial_req; +extern SNETCAPS serial_caps; +extern SNETSPI serial_spi; + +extern DWORD null_id; +extern LPCSTR null_desc; +extern LPCSTR null_req; +extern SNETCAPS null_caps; +extern SNETSPI null_spi; + +/**************************************************************************** +* +* COMMON PERFORMANCE MONITORING FUNCTIONS +* +***/ + +#define PERF_PKTSENT 0 +#define PERF_PKTRECV 1 +#define PERF_BYTESSENT 2 +#define PERF_BYTESRECV 3 +#define PERFNUM 4 + +void PerfAdd (DWORD id, DWORD value); +BOOL PerfGetPerformanceData (DWORD counterid, + DWORD *countervalue, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +void PerfIncrement (DWORD id); +void PerfReset (); diff --git a/src/Storm/SOURCE/STANDARD/STANDARD.RC b/src/Storm/SOURCE/STANDARD/STANDARD.RC new file mode 100644 index 0000000..fadf8b6 --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/STANDARD.RC @@ -0,0 +1,271 @@ +//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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IPXSELECTGAME_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE DS_3DLOOK | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman Bold", 0, 0, 0x1 +BEGIN + LTEXT "IPX Games Available",IDC_STATIC,10,62,124,10,0, + WS_EX_TRANSPARENT + LISTBOX IDC_GAMELIST,10,74,124,80,LBS_SORT | LBS_USETABSTOPS | + WS_VSCROLL | WS_TABSTOP + LTEXT "Description:",IDC_STATIC,10,152,124,10,0, + WS_EX_TRANSPARENT + LTEXT "",IDC_GAMEDESCRIPTION,10,162,124,30 + LTEXT "",IDC_PROGRAMDESCRIPTION,10,192,124,9,0, + WS_EX_TRANSPARENT + DEFPUSHBUTTON "&Join Game",IDOK,160,147,90,12,WS_DISABLED + PUSHBUTTON "&Create Game",IDC_CREATEGAME,160,161,90,12 + PUSHBUTTON "&Disconnect",IDCANCEL,160,175,90,12 +END + +TAPI_DEV_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE DS_3DLOOK | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman Bold", 0, 0, 0x1 +BEGIN + LISTBOX IDC_DEVICELIST,8,55,181,83,LBS_SORT | LBS_USETABSTOPS | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "&OK",IDOK,155,163,90,12,WS_DISABLED,WS_EX_TRANSPARENT + PUSHBUTTON "Cancel",IDCANCEL,155,178,90,12,0,WS_EX_TRANSPARENT + LTEXT "Modem Devices Available",IDC_STATIC,8,44,113,8,0, + WS_EX_TRANSPARENT +END + +TAPI_LOC_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE DS_3DLOOK | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman Bold", 0, 0, 0x1 +BEGIN + LISTBOX IDC_LOCLIST,8,55,181,83,LBS_SORT | LBS_USETABSTOPS | + WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "&OK",IDOK,155,163,90,12,WS_DISABLED,WS_EX_TRANSPARENT + PUSHBUTTON "Cancel",IDCANCEL,155,178,90,12,0,WS_EX_TRANSPARENT + LTEXT "Select Location",IDC_STATIC,8,44,113,8,0, + WS_EX_TRANSPARENT +END + +MODEM_ADDNUM_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE DS_3DLOOK | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman Bold", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_PBNAME,62,35,182,12,ES_AUTOHSCROLL + EDITTEXT IDC_AREACODE,62,87,48,12,ES_AUTOHSCROLL, + WS_EX_TRANSPARENT + EDITTEXT IDC_PBNUMBER,62,113,100,12,ES_AUTOHSCROLL, + WS_EX_TRANSPARENT + DEFPUSHBUTTON "&OK",IDOK,153,158,90,12,WS_DISABLED,WS_EX_TRANSPARENT + PUSHBUTTON "Cancel",IDCANCEL,153,177,90,12,0,WS_EX_TRANSPARENT + RTEXT "Area Code:",IDC_STATIC,6,90,48,8,0,WS_EX_TRANSPARENT + RTEXT "Number:",IDC_STATIC,6,116,48,8,0,WS_EX_TRANSPARENT + RTEXT "Country Code:",IDC_STATIC,6,64,48,8,0,WS_EX_TRANSPARENT + RTEXT "Name:",IDC_STATIC,6,38,48,8,0,WS_EX_TRANSPARENT + LTEXT "",IDC_PBOPERATION,13,16,137,8,0,WS_EX_TRANSPARENT + LTEXT "United States of America",IDC_COUNTRY,62,64,103,8,0, + WS_EX_TRANSPARENT + PUSHBUTTON "Change &Country...",IDC_CHANGECOUNTRY,178,60,66,15 +END + +MODEM_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_BORDER +FONT 13, "Times New Roman Bold" +BEGIN + DEFPUSHBUTTON "&Create Game",IDC_MODEMCREATE,148,139,90,12,WS_DISABLED, + WS_EX_TRANSPARENT + LISTBOX IDC_PHONEBOOK,14,102,121,67,LBS_SORT | WS_VSCROLL | + WS_TABSTOP + PUSHBUTTON "&Join Game",IDC_MODEMJOIN,148,157,90,12,WS_DISABLED, + WS_EX_TRANSPARENT + PUSHBUTTON "Cancel",IDCANCEL,148,175,90,12 + PUSHBUTTON "Change &Modem...",IDC_CHANGEMODEM,172,26,66,15 + PUSHBUTTON "Change &Location...",IDC_CHANGELOCATION,172,64,66,15 + PUSHBUTTON "&Add...",IDC_PHONEBOOKADD,14,173,34,15 + PUSHBUTTON "&Edit",IDC_PHONEBOOKEDIT,57,173,34,15,WS_DISABLED + PUSHBUTTON "&Remove",IDC_PHONEBOOKREMOVE,100,173,34,15,WS_DISABLED + LTEXT "Current Modem:",IDC_STATIC,14,15,65,8,0, + WS_EX_TRANSPARENT + LTEXT "Current Location:",IDC_STATIC,14,54,65,8,0, + WS_EX_TRANSPARENT + LTEXT "",IDC_CURRENTLOCATION,14,67,151,8,0,WS_EX_TRANSPARENT + LTEXT "",IDC_CURRENTMODEM,14,29,151,8,0,WS_EX_TRANSPARENT + LTEXT "Phonebook Entries",IDC_STATIC,14,88,62,8,0, + WS_EX_TRANSPARENT +END + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 +END + +IDD_DIALOG2 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "MODEM_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END + + IDD_DIALOG2, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_PBADD "Add New Phonebook Entry" + IDS_PBEDIT "Edit Phonebook Entry" + IDS_NODEVICES "No Modem Devices Configured" + IDS_NOLOCATIONS "No Locations Defined" + IDS_DIALING "Dialing number..." + IDS_RINGING "Ringing..." + IDS_CONNECTING "Establishing connection..." + IDS_PROCEEDING "Contacting remote computer..." + IDS_DIALTONE "Dialtone..." +END + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1997,3,29,1 + PRODUCTVERSION 1997,3,29,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Blizzard Entertainment\0" + VALUE "FileDescription", "Standard.snp\0" + VALUE "FileVersion", "1.03\0" + VALUE "InternalName", "Standard.snp\0" + VALUE "LegalCopyright", "Copyright © 1997, Blizzard Entertainment\0" + VALUE "OriginalFilename", "Standard.snp\0" + VALUE "ProductName", "Standard.snp\0" + VALUE "ProductVersion", "1.03\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200, 0x409, 1200 + END +END + +#endif // !_MAC + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SOURCE/STANDARD/TRACE.CPP b/src/Storm/SOURCE/STANDARD/TRACE.CPP new file mode 100644 index 0000000..526a24b --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/TRACE.CPP @@ -0,0 +1,118 @@ +/**************************************************************************** +* +* TRACE.CPP +* Modem trace functions +* +* Written by Mike O'Brien +* Modified by Jeff Strain (1/9/97) +* +***/ + +#include "pch.h" +#pragma hdrstop +#include "trace.h" + +// DEFAULT DATA FILE FOR ALL TRACE COMMANDS +#define TRACEFILE "c:\\mdmtrace.txt" + +/**************************************************************************** +* +* TRACE FUNCTIONS +* +***/ + +static CCritSect trace_critsect; +static FILE *trace_file = NULL; +static DWORD trace_init = 0; +static DWORD trace_pendcount = 0; +static char trace_pending[256] = ""; + +//=========================================================================== +void TraceBegin (BOOL writepending) { +#ifdef _DEBUG + + // OPEN THE FILE + if (!trace_file) { + trace_file = fopen(TRACEFILE,trace_init ? "at" : "wt"); + if (!trace_file) + return; + else if (!trace_init) + trace_init = GetTickCount(); + } + + // WRITE AND CLEAR ANY PENDING LINES + if (trace_pending[0]) { + if (trace_pendcount > 1) + fprintf(trace_file," [...]\n"); + if (writepending) + fprintf(trace_file,"%s",trace_pending); + trace_pendcount = 0; + trace_pending[0] = 0; + } + +#endif +} + +//=========================================================================== +void TraceDestroy () { +#ifdef _DEBUG + trace_critsect.Enter(); + if (trace_file) { + fclose(trace_file); + trace_file = NULL; + } + trace_critsect.Leave(); +#endif +} + +//=========================================================================== +void TraceDumpAddr (LPCSTR addrname, LPVOID addr, unsigned size) { +#ifdef _DEBUG +#define LINESIZE 80 + char outstr[LINESIZE + 1]; + sprintf(outstr," %s=", addrname); + size = min(size, (LINESIZE - strlen(outstr)) / 2); + for (unsigned loop = 0; loop < size; ++loop) + sprintf(outstr+strlen(outstr),"%02x",(DWORD)*((LPBYTE)addr+loop)); + TraceOut(outstr); +#endif +} + +//=========================================================================== +void __cdecl TraceOut (const char *format, ...) { +#ifdef _DEBUG + trace_critsect.Enter(); + TraceBegin((strlen(format) > 1) && (format[0] == ' ')); + + // WRITE THE LINE + DWORD eventtime = GetTickCount()-trace_init; + fprintf(trace_file,"%4u.%02u ",eventtime/1000,(eventtime % 1000)/10); + va_list arglist; + va_start(arglist,format); + vfprintf(trace_file,format,arglist); + va_end(arglist); + fprintf(trace_file,"\n"); + fflush(trace_file); + + trace_critsect.Leave(); +#endif +} + +//=========================================================================== +void __cdecl TracePend (const char *format, ...) { +#ifdef _DEBUG + trace_critsect.Enter(); + + // SAVE THE LINE + ++trace_pendcount; + DWORD eventtime = GetTickCount()-trace_init; + sprintf(trace_pending,"%4u.%02u ",eventtime/1000,(eventtime % 1000)/10); + va_list arglist; + va_start(arglist,format); + vsprintf(trace_pending+strlen(trace_pending),format,arglist); + va_end(arglist); + strcat(trace_pending,"\n"); + + trace_critsect.Leave(); +#endif +} diff --git a/src/Storm/SOURCE/STANDARD/TRACE.H b/src/Storm/SOURCE/STANDARD/TRACE.H new file mode 100644 index 0000000..0936aa9 --- /dev/null +++ b/src/Storm/SOURCE/STANDARD/TRACE.H @@ -0,0 +1,14 @@ +/**************************************************************************** +* +* TRACE.H +* Modem trace public interface +* +* Written by Jeff Strain (1/9/97) +* +***/ + +void TraceBegin (BOOL writepending); +void TraceDestroy (); +void TraceDumpAddr (LPCSTR addrname, LPVOID addr, unsigned size); +void __cdecl TraceOut (const char *format, ...); +void __cdecl TracePend (const char *format, ...); diff --git a/src/Storm/SOURCE/STORM.APS b/src/Storm/SOURCE/STORM.APS new file mode 100644 index 0000000..bed0fad Binary files /dev/null and b/src/Storm/SOURCE/STORM.APS differ diff --git a/src/Storm/SOURCE/STORM.CPP b/src/Storm/SOURCE/STORM.CPP new file mode 100644 index 0000000..4e25098 --- /dev/null +++ b/src/Storm/SOURCE/STORM.CPP @@ -0,0 +1,92 @@ +/**************************************************************************** +* +* STORM.CPP +* Storm main module +* +* By Michael O'Brien (2/8/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +static HINSTANCE s_instance = (HINSTANCE)0; +static LPTOP_LEVEL_EXCEPTION_FILTER s_oldfilter = NULL; + +LONG CALLBACK ExceptionFilter (EXCEPTION_POINTERS *exceptinfo); + +//=========================================================================== +#ifndef STATICLIB +extern "C" BOOL APIENTRY DllMain (HINSTANCE instance, + DWORD reason, + LPVOID) { + if (reason == DLL_PROCESS_ATTACH) { + s_instance = instance; + s_oldfilter = SetUnhandledExceptionFilter(ExceptionFilter); + } + else if (reason == DLL_PROCESS_DETACH) { + SetUnhandledExceptionFilter(s_oldfilter); + StormDestroy(); + } + return TRUE; +} +#endif + +//=========================================================================== +LONG CALLBACK ExceptionFilter (EXCEPTION_POINTERS *exceptinfo) { + SErrSuppressErrors(TRUE); + SLogFlushAll(); + if (s_oldfilter) + s_oldfilter(exceptinfo); + return EXCEPTION_CONTINUE_SEARCH; +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +#ifndef STATICLIB +BOOL APIENTRY StormDestroy () { + + // DESTROY MODULES WHICH DEPEND ON SDRAW + SDlgDestroy(); + SGdiDestroy(); + SVidDestroy(); + SDrawDestroy(); + + // DESTROY MODULES WHICH DEPEND ON SRGN + SRgnDestroy(); + + // DESTROY MODULES WHICH DEPEND ON SEVT + SMsgDestroy(); + SNetDestroy(); + SEvtDestroy(); + + // DESTROY MODULES WHICH DEPEND ON SCODE + SBltDestroy(); + SCodeDestroy(); + + // DESTROY OTHER HIGH LEVEL MODULES + SCmdDestroy(); + SFileDestroy(); + STransDestroy(); + + // THE MEMORY MANAGER, ERROR HANDLER, AND LOGGING MODULE ARE NOT + // DESTROYED UNTIL AFTER ALL DESTRUCTORS HAVE BEEN CALLED BY THE + // RUNTIME LIBRARY CLEANUP CODE + + return TRUE; +} +#endif + +//=========================================================================== +HINSTANCE StormGetInstance () { +#ifdef STATICLIB + return (HINSTANCE)GetModuleHandle(NULL); +#else + return s_instance; +#endif +} diff --git a/src/Storm/SOURCE/STORM.CS b/src/Storm/SOURCE/STORM.CS new file mode 100644 index 0000000..dbc6db5 --- /dev/null +++ b/src/Storm/SOURCE/STORM.CS @@ -0,0 +1,15 @@ +#include +set crtlib=crtdll.lib +set deffile=exports.def +set extralib=comdlg32.lib implode.lib version.lib +set linkopt=%linkopt% -base:0x15000000 +set .obj=.dll + +// DETERMINE THE PROJECT NAME +if %debug% set project=%project%d + +// COPY THE FILES TO THE OUTPUT DIRECTORIES +!copy %project%.lib ..\lib > NUL: +!copy %project%.dll ..\bin > NUL: +!if exist *.bak del *.bak +!if exist %project%.dll del %project%.dll diff --git a/src/Storm/SOURCE/STORM.RC b/src/Storm/SOURCE/STORM.RC new file mode 100644 index 0000000..9151a6e --- /dev/null +++ b/src/Storm/SOURCE/STORM.RC @@ -0,0 +1,184 @@ +//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 + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Message Table +// + +1 MESSAGETABLE MSG00001.bin + +///////////////////////////////////////////////////////////////////////////// +// +// 256 +// + +BLIZZARDKEY 256 MOVEABLE PURE "blizzard.key" +SYSTEMPALETTE 256 MOVEABLE PURE "syspal.pcx" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +SELECTPROVIDER_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE DS_3DLOOK | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + LTEXT "Select Connection Method",IDC_STATIC,10,62,124,10,0, + WS_EX_TRANSPARENT + LISTBOX IDC_PROVIDERLIST,10,74,124,60,LBS_SORT | WS_VSCROLL | + WS_TABSTOP + LTEXT "Players supported: ",IDC_MAXPLAYERS,10,134,124,9 + LTEXT "Requirements: ",IDC_REQUIREMENTS,10,143,124,50 + LTEXT "",IDC_PROGRAMDESCRIPTION,10,192,124,9,0, + WS_EX_TRANSPARENT + DEFPUSHBUTTON "&Connect",IDOK,160,147,90,12 + PUSHBUTTON "&Previous Menu",IDCANCEL,160,161,90,12 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "SELECTPROVIDER_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 250 + TOPMARGIN, 7 + END +END +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +#ifndef STATICLIB +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1997,9,7,1 + PRODUCTVERSION 1997,9,7,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Author", "Mike O'Brien\0" + VALUE "CompanyName", "Blizzard Entertainment\0" + VALUE "FileDescription", "Storm Library\0" + VALUE "FileVersion", "1.05\0" + VALUE "LegalCopyright", "Copyright © 1997, Blizzard Entertainment\0" + VALUE "OriginalFilename", "Storm.dll\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !STATICLIB +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_ERROR "ERROR #%u (0x%08x)" + IDS_HEADER "This application has encountered a critical error:\n\n%s\n" + IDS_PROGRAM "Program:\t%s\n" + IDS_FILELINE "File:\t%s\nLine:\t%d\n" + IDS_FUNCTION "Function:\t%s\n" + IDS_OBJECT "Object:\t%s\n" + IDS_HANDLE "Handle:\t%s\n" + IDS_EXPRESSION "Expr:\t%s\n\n" + IDS_DESCRIPTION "\n%s\n\n" + IDS_TERMINATE "Press OK to terminate the application." + IDS_RECOVERABLE "Do you wish to terminate the application?" + IDS_FILE "File:\t%s\n" + IDS_BADARGUMENT "Invalid argument: %s" + IDS_NOTENOUGHARGUMENTS "The syntax of the command is incorrect." + IDS_OPENFAILED "Unable to open response file: %s" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Storm/SOURCE/STORMERR.MC b/src/Storm/SOURCE/STORMERR.MC new file mode 100644 index 0000000..3de1084 --- /dev/null +++ b/src/Storm/SOURCE/STORMERR.MC @@ -0,0 +1,678 @@ +FacilityNames=(STORM=0x510 DDERR=0x876 DSERR=0x878) +SeverityNames=(Success=0 Informational=1 Warning=2 Error=3) + +MessageId=0 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_ASSERTION Language=English +ASSERTION! +. + +MessageId=101 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_BAD_ARGUMENT Language=English +STORM_ERROR_BAD_ARGUMENT +. + +MessageId=102 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_GAME_ALREADY_STARTED Language=English +STORM_ERROR_GAME_ALREADY_STARTED +. + +MessageId=103 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_GAME_FULL Language=English +STORM_ERROR_GAME_FULL +. + +MessageId=104 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_GAME_NOT_FOUND Language=English +STORM_ERROR_GAME_NOT_FOUND +. + +MessageId=105 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_GAME_TERMINATED Language=English +STORM_ERROR_GAME_TERMINATED +. + +MessageId=106 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_INVALID_PLAYER Language=English +STORM_ERROR_INVALID_PLAYER +. + +MessageId=107 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NO_MESSAGES_WAITING Language=English +STORM_ERROR_NO_MESSAGES_WAITING +. + +MessageId=108 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NOT_ARCHIVE Language=English +STORM_ERROR_NOT_ARCHIVE +. + +MessageId=109 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NOT_ENOUGH_ARGUMENTS Language=English +STORM_ERROR_NOT_ENOUGH_ARGUMENTS +. + +MessageId=110 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NOT_IMPLEMENTED Language=English +STORM_ERROR_NOT_IMPLEMENTED +. + +MessageId=111 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NOT_IN_ARCHIVE Language=English +STORM_ERROR_NOT_IN_ARCHIVE +. + +MessageId=112 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NOT_IN_GAME Language=English +STORM_ERROR_NOT_IN_GAME +. + +MessageId=113 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NOT_INITIALIZED Language=English +STORM_ERROR_NOT_INITIALIZED +. + +MessageId=114 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NOT_PLAYING Language=English +STORM_ERROR_NOT_PLAYING +. + +MessageId=115 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_NOT_REGISTERED Language=English +STORM_ERROR_NOT_REGISTERED +. + +MessageId=116 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_REQUIRES_CODEC Language=English +STORM_ERROR_REQUIRES_CODEC +. + +MessageId=117 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_REQUIRES_DDRAW Language=English +STORM_ERROR_REQUIRES_CODEC +. + +MessageId=118 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_REQUIRES_DSOUND Language=English +STORM_ERROR_REQUIRES_CODEC +. + +MessageId=119 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_REQUIRES_UPGRADE Language=English +STORM_ERROR_REQUIRES_UPGRADE +. + +MessageId=120 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_STILL_ACTIVE Language=English +STORM_ERROR_STILL_ACTIVE +. + +MessageId=121 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_VERSION_MISMATCH Language=English +STORM_ERROR_VERSION_MISMATCH +. + +MessageId=122 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_MEMORY_ALREADY_FREED Language=English +Attempt to free a memory block which is not currently allocated. +. + +MessageId=123 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_MEMORY_CORRUPT Language=English +This memory block has been corrupted by an out-of-bounds memory write. +. + +MessageId=124 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_MEMORY_INVALID_BLOCK Language=English +Attempt to free an invalid memory block. +. + +MessageId=125 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_MEMORY_MANAGER_INACTIVE Language=English +This function call is invalid because the memory manager is not currently initialized. +. + +MessageId=126 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_MEMORY_NEVER_RELEASED Language=English +A block of memory was allocated but never freed. +. + +MessageId=127 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_HANDLE_NEVER_RELEASED Language=English +A resource handle was obtained but never released. +. + +MessageId=128 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_ACCESS_OUT_OF_BOUNDS Language=English +Attempt to access beyond the bounds of an array. +. + +MessageId=129 Severity=Warning Facility=STORM +SymbolicName=STORM_ERROR_MEMORY_NULL_POINTER Language=English +Attempt to free a NULL pointer. +. + +MessageId=5 Severity=Warning Facility=DDERR +SymbolicName=DDERR_ALREADYINITIALIZED Language=English +DDERR_ALREADYINITIALIZED +. + +MessageId=10 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CANNOTATTACHSURFACE Language=English +DDERR_CANNOTATTACHSURFACE +. + +MessageId=20 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CANNOTDETACHSURFACE Language=English +DDERR_CANNOTDETACHSURFACE +. + +MessageId=40 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CURRENTLYNOTAVAIL Language=English +DDERR_CURRENTLYNOTAVAIL +. + +MessageId=55 Severity=Warning Facility=DDERR +SymbolicName=DDERR_EXCEPTION Language=English +DDERR_EXCEPTION +. + +MessageId=90 Severity=Warning Facility=DDERR +SymbolicName=DDERR_HEIGHTALIGN Language=English +DDERR_HEIGHTALIGN +. + +MessageId=95 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INCOMPATIBLEPRIMARY Language=English +DDERR_INCOMPATIBLEPRIMARY +. + +MessageId=100 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDCAPS Language=English +DDERR_INVALIDCAPS +. + +MessageId=110 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDCLIPLIST Language=English +DDERR_INVALIDCLIPLIST +. + +MessageId=120 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDMODE Language=English +DDERR_INVALIDMODE +. + +MessageId=130 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDOBJECT Language=English +DDERR_INVALIDOBJECT +. + +MessageId=145 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDPIXELFORMAT Language=English +DDERR_INVALIDPIXELFORMAT +. + +MessageId=150 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDRECT Language=English +DDERR_INVALIDRECT +. + +MessageId=160 Severity=Warning Facility=DDERR +SymbolicName=DDERR_LOCKEDSURFACES Language=English +DDERR_LOCKEDSURFACES +. + +MessageId=170 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NO3D Language=English +DDERR_NO3D +. + +MessageId=180 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOALPHAHW Language=English +DDERR_NOALPHAHW +. + +MessageId=205 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOCLIPLIST Language=English +DDERR_NOCLIPLIST +. + +MessageId=210 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOCOLORCONVHW Language=English +DDERR_NOCOLORCONVHW +. + +MessageId=212 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOCOOPERATIVELEVELSET Language=English +DDERR_NOCOOPERATIVELEVELSET +. + +MessageId=215 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOCOLORKEY Language=English +DDERR_NOCOLORKEY +. + +MessageId=220 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOCOLORKEYHW Language=English +DDERR_NOCOLORKEYHW +. + +MessageId=222 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NODIRECTDRAWSUPPORT Language=English +DDERR_NODIRECTDRAWSUPPORT +. + +MessageId=225 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOEXCLUSIVEMODE Language=English +DDERR_NOEXCLUSIVEMODE +. + +MessageId=230 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOFLIPHW Language=English +DDERR_NOFLIPHW +. + +MessageId=240 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOGDI Language=English +DDERR_NOGDI +. + +MessageId=250 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOMIRRORHW Language=English +DDERR_NOMIRRORHW +. + +MessageId=255 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOTFOUND Language=English +DDERR_NOTFOUND +. + +MessageId=260 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOOVERLAYHW Language=English +DDERR_NOOVERLAYHW +. + +MessageId=280 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NORASTEROPHW Language=English +DDERR_NORASTEROPHW +. + +MessageId=290 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOROTATIONHW Language=English +DDERR_NOROTATIONHW +. + +MessageId=310 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOSTRETCHHW Language=English +DDERR_NOSTRETCHHW +. + +MessageId=316 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOT4BITCOLOR Language=English +DDERR_NOT4BITCOLOR +. + +MessageId=317 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOT4BITCOLORINDEX Language=English +DDERR_NOT4BITCOLORINDEX +. + +MessageId=320 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOT8BITCOLOR Language=English +DDERR_NOT8BITCOLOR +. + +MessageId=330 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOTEXTUREHW Language=English +DDERR_NOTEXTUREHW +. + +MessageId=335 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOVSYNCHW Language=English +DDERR_NOVSYNCHW +. + +MessageId=340 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOZBUFFERHW Language=English +DDERR_NOZBUFFERHW +. + +MessageId=350 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOZOVERLAYHW Language=English +DDERR_NOZOVERLAYHW +. + +MessageId=360 Severity=Warning Facility=DDERR +SymbolicName=DDERR_OUTOFCAPS Language=English +DDERR_OUTOFCAPS +. + +MessageId=380 Severity=Warning Facility=DDERR +SymbolicName=DDERR_OUTOFVIDEOMEMORY Language=English +DDERR_OUTOFVIDEOMEMORY +. + +MessageId=382 Severity=Warning Facility=DDERR +SymbolicName=DDERR_OVERLAYCANTCLIP Language=English +DDERR_OVERLAYCANTCLIP +. + +MessageId=384 Severity=Warning Facility=DDERR +SymbolicName=DDERR_OVERLAYCOLORKEYONLYONEACTIVE Language=English +DDERR_OVERLAYCOLORKEYONLYONEACTIVE +. + +MessageId=387 Severity=Warning Facility=DDERR +SymbolicName=DDERR_PALETTEBUSY Language=English +DDERR_PALETTEBUSY +. + +MessageId=400 Severity=Warning Facility=DDERR +SymbolicName=DDERR_COLORKEYNOTSET Language=English +DDERR_COLORKEYNOTSET +. + +MessageId=410 Severity=Warning Facility=DDERR +SymbolicName=DDERR_SURFACEALREADYATTACHED Language=English +DDERR_SURFACEALREADYATTACHED +. + +MessageId=420 Severity=Warning Facility=DDERR +SymbolicName=DDERR_SURFACEALREADYDEPENDENT Language=English +DDERR_SURFACEALREADYDEPENDENT +. + +MessageId=430 Severity=Warning Facility=DDERR +SymbolicName=DDERR_SURFACEBUSY Language=English +DDERR_SURFACEBUSY +. + +MessageId=435 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CANTLOCKSURFACE Language=English +DDERR_CANTLOCKSURFACE +. + +MessageId=440 Severity=Warning Facility=DDERR +SymbolicName=DDERR_SURFACEISOBSCURED Language=English +DDERR_SURFACEISOBSCURED +. + +MessageId=450 Severity=Warning Facility=DDERR +SymbolicName=DDERR_SURFACELOST Language=English +DDERR_SURFACELOST +. + +MessageId=460 Severity=Warning Facility=DDERR +SymbolicName=DDERR_SURFACENOTATTACHED Language=English +DDERR_SURFACENOTATTACHED +. + +MessageId=470 Severity=Warning Facility=DDERR +SymbolicName=DDERR_TOOBIGHEIGHT Language=English +DDERR_TOOBIGHEIGHT +. + +MessageId=480 Severity=Warning Facility=DDERR +SymbolicName=DDERR_TOOBIGSIZE Language=English +DDERR_TOOBIGSIZE +. + +MessageId=490 Severity=Warning Facility=DDERR +SymbolicName=DDERR_TOOBIGWIDTH Language=English +DDERR_TOOBIGWIDTH +. + +MessageId=510 Severity=Warning Facility=DDERR +SymbolicName=DDERR_UNSUPPORTEDFORMAT Language=English +DDERR_UNSUPPORTEDFORMAT +. + +MessageId=520 Severity=Warning Facility=DDERR +SymbolicName=DDERR_UNSUPPORTEDMASK Language=English +DDERR_UNSUPPORTEDMASK +. + +MessageId=537 Severity=Warning Facility=DDERR +SymbolicName=DDERR_VERTICALBLANKINPROGRESS Language=English +DDERR_VERTICALBLANKINPROGRESS +. + +MessageId=540 Severity=Warning Facility=DDERR +SymbolicName=DDERR_WASSTILLDRAWING Language=English +DDERR_WASSTILLDRAWING +. + +MessageId=560 Severity=Warning Facility=DDERR +SymbolicName=DDERR_XALIGN Language=English +DDERR_XALIGN +. + +MessageId=561 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDDIRECTDRAWGUID Language=English +DDERR_INVALIDDIRECTDRAWGUID +. + +MessageId=562 Severity=Warning Facility=DDERR +SymbolicName=DDERR_DIRECTDRAWALREADYCREATED Language=English +DDERR_DIRECTDRAWALREADYCREATED +. + +MessageId=563 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NODIRECTDRAWHW Language=English +DDERR_NODIRECTDRAWHW +. + +MessageId=564 Severity=Warning Facility=DDERR +SymbolicName=DDERR_PRIMARYSURFACEALREADYEXISTS Language=English +DDERR_PRIMARYSURFACEALREADYEXISTS +. + +MessageId=565 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOEMULATION Language=English +DDERR_NOEMULATION +. + +MessageId=566 Severity=Warning Facility=DDERR +SymbolicName=DDERR_REGIONTOOSMALL Language=English +DDERR_REGIONTOOSMALL +. + +MessageId=567 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CLIPPERISUSINGHWND Language=English +DDERR_CLIPPERISUSINGHWND +. + +MessageId=568 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOCLIPPERATTACHED Language=English +DDERR_NOCLIPPERATTACHED +. + +MessageId=569 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOHWND Language=English +DDERR_NOHWND +. + +MessageId=570 Severity=Warning Facility=DDERR +SymbolicName=DDERR_HWNDSUBCLASSED Language=English +DDERR_HWNDSUBCLASSED +. + +MessageId=571 Severity=Warning Facility=DDERR +SymbolicName=DDERR_HWNDALREADYSET Language=English +DDERR_HWNDALREADYSET +. + +MessageId=572 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOPALETTEATTACHED Language=English +DDERR_NOPALETTEATTACHED +. + +MessageId=573 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOPALETTEHW Language=English +DDERR_NOPALETTEHW +. + +MessageId=574 Severity=Warning Facility=DDERR +SymbolicName=DDERR_BLTFASTCANTCLIP Language=English +DDERR_BLTFASTCANTCLIP +. + +MessageId=575 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOBLTHW Language=English +DDERR_NOBLTHW +. + +MessageId=576 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NODDROPSHW Language=English +DDERR_NODDROPSHW +. + +MessageId=577 Severity=Warning Facility=DDERR +SymbolicName=DDERR_OVERLAYNOTVISIBLE Language=English +DDERR_OVERLAYNOTVISIBLE +. + +MessageId=578 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOOVERLAYDEST Language=English +DDERR_NOOVERLAYDEST +. + +MessageId=579 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDPOSITION Language=English +DDERR_INVALIDPOSITION +. + +MessageId=580 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOTAOVERLAYSURFACE Language=English +DDERR_NOTAOVERLAYSURFACE +. + +MessageId=581 Severity=Warning Facility=DDERR +SymbolicName=DDERR_EXCLUSIVEMODEALREADYSET Language=English +DDERR_EXCLUSIVEMODEALREADYSET +. + +MessageId=582 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOTFLIPPABLE Language=English +DDERR_NOTFLIPPABLE +. + +MessageId=583 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CANTDUPLICATE Language=English +DDERR_CANTDUPLICATE +. + +MessageId=584 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOTLOCKED Language=English +DDERR_NOTLOCKED +. + +MessageId=585 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CANTCREATEDC Language=English +DDERR_CANTCREATEDC +. + +MessageId=586 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NODC Language=English +DDERR_NODC +. + +MessageId=587 Severity=Warning Facility=DDERR +SymbolicName=DDERR_WRONGMODE Language=English +DDERR_WRONGMODE +. + +MessageId=588 Severity=Warning Facility=DDERR +SymbolicName=DDERR_IMPLICITLYCREATED Language=English +DDERR_IMPLICITLYCREATED +. + +MessageId=589 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOTPALETTIZED Language=English +DDERR_NOTPALETTIZED +. + +MessageId=590 Severity=Warning Facility=DDERR +SymbolicName=DDERR_UNSUPPORTEDMODE Language=English +DDERR_UNSUPPORTEDMODE +. + +MessageId=591 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOMIPMAPHW Language=English +DDERR_NOMIPMAPHW +. + +MessageId=592 Severity=Warning Facility=DDERR +SymbolicName=DDERR_INVALIDSURFACETYPE Language=English +DDERR_INVALIDSURFACETYPE +. + +MessageId=620 Severity=Warning Facility=DDERR +SymbolicName=DDERR_DCALREADYCREATED Language=English +DDERR_DCALREADYCREATED +. + +MessageId=640 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CANTPAGELOCK Language=English +DDERR_CANTPAGELOCK +. + +MessageId=660 Severity=Warning Facility=DDERR +SymbolicName=DDERR_CANTPAGEUNLOCK Language=English +DDERR_CANTPAGEUNLOCK +. + +MessageId=680 Severity=Warning Facility=DDERR +SymbolicName=DDERR_NOTPAGELOCKED Language=English +DDERR_NOTPAGELOCKED +. + +MessageId=10 Severity=Warning Facility=DSERR +SymbolicName=DSERR_ALLOCATED Language=English +DSERR_ALLOCATED +. + +MessageId=30 Severity=Warning Facility=DSERR +SymbolicName=DSERR_CONTROLUNAVAIL Language=English +DSERR_CONTROLUNAVAIL +. + +MessageId=50 Severity=Warning Facility=DSERR +SymbolicName=DSERR_INVALIDCALL Language=English +DSERR_INVALIDCALL +. + +MessageId=70 Severity=Warning Facility=DSERR +SymbolicName=DSERR_PRIOLEVELNEEDED Language=English +DSERR_PRIOLEVELNEEDED +. + +MessageId=100 Severity=Warning Facility=DSERR +SymbolicName=DSERR_BADFORMAT Language=English +DSERR_BADFORMAT +. + +MessageId=120 Severity=Warning Facility=DSERR +SymbolicName=DSERR_NODRIVER Language=English +DSERR_NODRIVER +. + +MessageId=130 Severity=Warning Facility=DSERR +SymbolicName=DSERR_ALREADYINITIALIZED Language=English +DSERR_ALREADYINITIALIZED +. + +MessageId=150 Severity=Warning Facility=DSERR +SymbolicName=DSERR_BUFFERLOST Language=English +DSERR_BUFFERLOST +. + +MessageId=160 Severity=Warning Facility=DSERR +SymbolicName=DSERR_OTHERAPPHASPRIO Language=English +DSERR_OTHERAPPHASPRIO +. + +MessageId=170 Severity=Warning Facility=DSERR +SymbolicName=DSERR_UNINITIALIZED Language=English +DSERR_UNINITIALIZED +. + diff --git a/src/Storm/SOURCE/STORMST.CS b/src/Storm/SOURCE/STORMST.CS new file mode 100644 index 0000000..bde95a3 --- /dev/null +++ b/src/Storm/SOURCE/STORMST.CS @@ -0,0 +1,11 @@ +#include +if %debug% set clopt=-DSTATICLIB -D_DEBUG -Zi +if not %debug% set clopt=-DSTATICLIB -DNDEBUG -O1 -GBFry +set extralib=implode.lib +set .def= +set .obj=.lib +!copy %project%.lib ..\lib > NUL: +!copy storm.res ..\lib\stormst.res > NUL: +!if exist *.bak del *.bak +!if exist *.res del *.res +!if exist %project%.lib del %project%.lib \ No newline at end of file diff --git a/src/Storm/SOURCE/STRANS.CPP b/src/Storm/SOURCE/STRANS.CPP new file mode 100644 index 0000000..4c4710a --- /dev/null +++ b/src/Storm/SOURCE/STRANS.CPP @@ -0,0 +1,1350 @@ +/**************************************************************************** +* +* STRANS.CPP +* Storm transparency functions +* +* By Michael O'Brien (6/19/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define COPY 0 +#define SKIP 1 +#define MAXSPANLENGTH 0xFC + +typedef struct _BUFFER { + LPBYTE data; + DWORD bytesalloc; + DWORD bytesused; + DWORD chunksize; +} BUFFER, *BUFFERPTR; + +typedef union _INSTPTR { + LPBYTE byteptr; + LPWORD wordptr; +} INSTPTR; + +typedef union _SPANPAIR { + BYTE span[2]; + WORD pair; +} SPANPAIR; + +NODEDECL(TRANS) { + LPBYTE data; + DWORD dataalloc; + DWORD databytes; + DWORD instructionoffset; + int width; + int height; + RECT boundrect; +} *TRANSPTR; + +static LPDWORD s_dirtyoffset = NULL; +static SIZE s_dirtysize = {40,30}; +static int s_dirtyxshift = 4; +static int s_dirtyxsize = 16; +static int s_dirtyyshift = 4; +static int s_dirtyysize = 16; +static LPBYTE s_savedata = NULL; +static int s_savedataalloc = 0; +static LIST(TRANS) s_translist; + +//=========================================================================== +static inline void BufferCreate (BUFFERPTR buffer) { + buffer->chunksize = 4096; + buffer->bytesused = 0; + if (s_savedata) { + buffer->data = s_savedata; + buffer->bytesalloc = s_savedataalloc; + s_savedata = NULL; + s_savedataalloc = 0; + } + else { + buffer->bytesalloc = 4096; + buffer->data = (LPBYTE)ALLOC(buffer->bytesalloc); + } +} + +//=========================================================================== +static inline void BufferReserve (BUFFERPTR buffer, + DWORD bytes, + LPBYTE *adjptr1, + LPBYTE *adjptr2) { + DWORD newalloc = buffer->bytesalloc; + while ((buffer->bytesused+bytes) > newalloc) + newalloc += buffer->chunksize; + if (newalloc != buffer->bytesalloc) { + LPBYTE newdata = (LPBYTE)ALLOC(newalloc); + CopyMemory(newdata,buffer->data,buffer->bytesused); + FREE(buffer->data); + if (adjptr1 && *adjptr1) + *adjptr1 = newdata+((*adjptr1)-buffer->data); + if (adjptr2 && *adjptr2) + *adjptr2 = newdata+((*adjptr2)-buffer->data); + buffer->bytesalloc = newalloc; + buffer->data = newdata; + } +} + +//=========================================================================== +static void ConvertBitmapToTransparency (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + LPRECT boundrect, + BYTE colorkey, + BOOL maskonly, + LPBYTE data, + DWORD *databytes, + DWORD *instructionoffset) { + DWORD size = 0; + + // DETERMINE THE SOURCE BITMAP LOCATION AND EXTENTS + LPBYTE start = bits+(rect ? rect->top*width+rect->left : 0); + int cx = rect ? rect->right-rect->left : width; + int cy = rect ? rect->bottom-rect->top : height; + int adjust = width-cx; + + // INITIALIZE THE BOUNDING RECTANGLE + boundrect->left = INT_MAX; + boundrect->top = INT_MAX; + boundrect->right = 0; + boundrect->bottom = 0; + + // STORE ALL OF THE NON-TRANSPARENT BITMAP BITS IN THE BUFFER + if (!maskonly) { + LPBYTE source = start; + for (int y = 0; y < cy; ++y) { + BOOL found = 0; + for (int x = 0; x < cx; ++x) { + if (*source != colorkey) { + ++size; + if (data) + *(data++) = *source; + if (x < boundrect->left) + boundrect->left = x; + if (x >= boundrect->right) + boundrect->right = x+1; + found = 1; + } + ++source; + } + if (found) { + if (y < boundrect->top) + boundrect->top = y; + if (y >= boundrect->bottom) + boundrect->bottom = y+1; + } + source += adjust; + } + } + if (boundrect->left > boundrect->right) + boundrect->left = boundrect->right; + if (boundrect->top > boundrect->bottom) + boundrect->top = boundrect->bottom; + + // SAVE THE OFFSET TO THE INSTRUCTION STREAM + if (size & 3) { + if (data) + data += 4-(size & 3); + size += 4-(size & 3); + } + if (instructionoffset) + *instructionoffset = size; + + // CREATE THE INSTRUCTION STREAM. EACH INSTRUCTION CONSISTS OF A BYTE + // SPECIFYING THE NUMBER OF BYTES TO COPY, FOLLOWED BY A BYTE SPECIFYING + // THE NUMBER OF BYTES TO SKIP. A PAIR OF ZEROES IS USED TO INDICATE THE + // END OF THE CURRENT SCAN LINE. + { + LPBYTE source = start; + int y = cy; + while (y--) { + BYTE copybytes = 0; + BYTE skipbytes = 0; + BOOL copymode = TRUE; + int x = cx; + while (x--) { + BOOL output = FALSE; + if ((*(source++) != colorkey) == copymode) + if (copymode) + ++copybytes; + else + ++skipbytes; + else + if (copymode) { + copymode = FALSE; + ++skipbytes; + } + else { + output = TRUE; + --source; + ++x; + } + if (output || + (copybytes == MAXSPANLENGTH) || + (skipbytes == MAXSPANLENGTH) || + !x) { + size += 2; + if (data) { + *(data++) = copybytes; + *(data++) = skipbytes; + } + copybytes = 0; + skipbytes = 0; + copymode = TRUE; + } + } + size += 2; + if (data) { + *(data++) = 0; + *(data++) = 0; + } + source += adjust; + } + } + + // RETURN THE NUMBER OF BYTES WRITTEN + if (databytes) + *databytes = size; +} + +//=========================================================================== +static DWORD ConvertColorRefToColorData (COLORREF colorref, int bitdepth) { + if (colorref & 0x01000000) + return (colorref & 0x00FFFFFF); + + return 0; +} + +//=========================================================================== +static TRANSPTR CreateTransparencyRecord (TRANSPTR baseptr) { + TRANSPTR transptr = s_translist.NewNode(); + if (baseptr) { + transptr->dataalloc = baseptr->dataalloc; + transptr->databytes = baseptr->databytes; + transptr->instructionoffset = baseptr->instructionoffset; + transptr->width = baseptr->width; + transptr->height = baseptr->height; + transptr->boundrect = baseptr->boundrect; + } + return transptr; +} + +//=========================================================================== +static BOOL DetermineShift (int value, int *shift) { + int bits = 0; + int curr = 1; + while (curr < value) { + ++bits; + curr <<= 1; + } + *shift = bits; + return (curr == value); +} + +//=========================================================================== +static BOOL InternalCreateTransparency (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + BOOL maskonly, + HSTRANS *handle) { + + // STORM CURRENTLY ONLY SUPPORTS 256-COLOR MODE, SO FOR THE TIME BEING, + // REJECT ALL BIT DEPTHS EXCEPT 8BPP + if (bitdepth != 8) + return FALSE; + BYTE paletteindex = (BYTE)ConvertColorRefToColorData(colorkey,bitdepth); + + // DETERMINE THE SIZE OF THE TRANSPARENCY DATA + DWORD transbytes = 0; + DWORD instructionoffset = 0; + RECT boundrect; + ConvertBitmapToTransparency(bits,width,height,bitdepth,rect,&boundrect,paletteindex, + maskonly,NULL,&transbytes,&instructionoffset); + + // ALLOCATE MEMORY FOR THE TRANSPARENCY DATA + LPBYTE transdata = (LPBYTE)ALLOC(transbytes); + + // GENERATE THE TRANSPARENCY DATA + ConvertBitmapToTransparency(bits,width,height,bitdepth,rect,&boundrect,paletteindex, + maskonly,transdata,NULL,NULL); + + // CREATE A RECORD FOR THE TRANSPARENCY + TRANSPTR newptr = CreateTransparencyRecord(NULL); + CopyMemory(&newptr->boundrect,&boundrect,sizeof(RECT)); + newptr->data = transdata; + newptr->dataalloc = transbytes; + newptr->databytes = transbytes; + newptr->instructionoffset = instructionoffset; + newptr->width = rect ? rect->right-rect->left : width; + newptr->height = rect ? rect->bottom-rect->top : height; + + // RETURN A HANDLE TO THE TRANSPARENCY + *handle = (HSTRANS)newptr; + + return TRUE; +} + +//=========================================================================== +static void inline InternalDrawTransparency (TRANSPTR trans, + LPBYTE dest, + int destadjust) { + LPBYTE sourcedata = trans->data; + LPBYTE sourceinst = trans->data+trans->instructionoffset; + int cy = trans->height; +#ifdef _X86_ + __asm { + + // SETUP REGISTERS + mov edx,[cy] + mov ebx,[sourceinst] + mov esi,[sourcedata] + mov edi,[dest] + xor eax,eax + xor ecx,ecx + test edx,edx + jz dt_done + jmp dt_nextinst + + // PERFORM THE COPY + dt_copy: cmp al,3 + jbe dt_done4 + + // IF NECESSARY, MOVE A SINGLE BYTE TO WORD-ALIGN THE + // DESTINATION + test edi,1 + jz dt_aligned2 + mov cl,[esi] + inc esi + mov [edi],cl + inc edi + dec al + dt_aligned2: + + // IF NECESSARY, MOVE A SINGLE WORD TO DWORD-ALIGN THE + // DESTINATION + test edi,2 + jz dt_aligned4 + mov cx,[esi] + add esi,2 + mov [edi],cx + add edi,2 + sub al,2 + dt_aligned4: + + // MOVE AS MANY ALIGNED DWORDS AS POSSIBLE + mov ecx,eax + and ecx,0FCh + shr ecx,2 + rep movsd + dt_done4: + + // MOVE ONE MORE WORD IF NECESSARY + test al,2 + jz dt_done2 + mov cx,[esi] + add esi,2 + mov [edi],cx + add edi,2 + dt_done2: + + // MOVE ONE MORE BYTE IF NECESSARY + test al,1 + jz dt_done1 + mov cl,[esi] + inc esi + mov [edi],cl + inc edi + dt_done1: + + // PERFORM THE SKIP + xor ecx,ecx + mov cl,ah + add edi,ecx + + // LOAD IN THE NEXT SET OF COPY/SKIP LENGTHS + dt_nextinst: xor eax,eax + mov ax,[ebx] + add ebx,2 + test eax,eax + jnz dt_copy + + // IF THIS LINE IS COMPLETE, MOVE TO THE NEXT LINE + add edi,[destadjust] + dec edx + jnz dt_nextinst + + dt_done: + } +#else + + // DRAW EACH LINE AS DEFINED IN THE INSTRUCTION STREAM + while (cy--) { + BYTE copybytes = *(sourceinst++); + BYTE skipbytes = *(sourceinst++); + while (copybytes || skipbytes) { + + // IF WE ARE COPYING AT LEAST SEVEN BYTES, ARRANGE THE BLT SO WE CAN + // DO AS MANY ALIGNED DWORD MOVES AS POSSIBLE + if (copybytes >= 7) { + while ((DWORD)dest & 3) { + *(dest++) = *(sourcedata++); + --copybytes; + } + while (copybytes >= 4) { + *(LPDWORD)dest = *(LPDWORD)sourcedata; + dest += 4; + sourcedata += 4; + copybytes -= 4; + } + } + + // OTHERWISE, JUST DO BYTE MOVES + while (copybytes) { + *(dest++) = *(sourcedata++); + --copybytes; + } + + // SKIP PAST THE NEXT TRANSPARENCY SPAN + dest += skipbytes; + + // LOAD IN THE NEXT SPAN DATA + copybytes = *(sourceinst++); + skipbytes = *(sourceinst++); + + } + dest += destadjust; + } + +#endif +} + +//=========================================================================== +static void inline InternalDrawTransparencyFromSource (TRANSPTR trans, + LPBYTE dest, + LPBYTE source, + int destadjust, + int sourceadjust) { + LPBYTE sourceinst = trans->data+trans->instructionoffset; + int cy = trans->height; +#ifdef _X86_ + __asm { + + // SETUP REGISTERS + mov edx,[cy] + mov ebx,[sourceinst] + mov esi,[source] + mov edi,[dest] + xor eax,eax + xor ecx,ecx + test edx,edx + jz dt_done + jmp dt_nextinst + + // PERFORM THE COPY + dt_copy: cmp al,3 + jbe dt_done4 + + // IF NECESSARY, MOVE A SINGLE BYTE TO WORD-ALIGN THE + // DESTINATION + test edi,1 + jz dt_aligned2 + mov cl,[esi] + inc esi + mov [edi],cl + inc edi + dec al + dt_aligned2: + + // IF NECESSARY, MOVE A SINGLE WORD TO DWORD-ALIGN THE + // DESTINATION + test edi,2 + jz dt_aligned4 + mov cx,[esi] + add esi,2 + mov [edi],cx + add edi,2 + sub al,2 + dt_aligned4: + + // MOVE AS MANY ALIGNED DWORDS AS POSSIBLE + mov ecx,eax + and ecx,0FCh + shr ecx,2 + rep movsd + dt_done4: + + // MOVE ONE MORE WORD IF NECESSARY + test al,2 + jz dt_done2 + mov cx,[esi] + add esi,2 + mov [edi],cx + add edi,2 + dt_done2: + + // MOVE ONE MORE BYTE IF NECESSARY + test al,1 + jz dt_done1 + mov cl,[esi] + inc esi + mov [edi],cl + inc edi + dt_done1: + + // PERFORM THE SKIP + xor ecx,ecx + mov cl,ah + add esi,ecx + add edi,ecx + + // LOAD IN THE NEXT SET OF COPY/SKIP LENGTHS + dt_nextinst: xor eax,eax + mov ax,[ebx] + add ebx,2 + test eax,eax + jnz dt_copy + + // IF THIS LINE IS COMPLETE, MOVE TO THE NEXT LINE + add edi,[destadjust] + add esi,[sourceadjust] + dec edx + jnz dt_nextinst + + dt_done: + } +#else + + // DRAW EACH LINE AS DEFINED IN THE INSTRUCTION STREAM + while (cy--) { + BYTE copybytes = *(sourceinst++); + BYTE skipbytes = *(sourceinst++); + while (copybytes || skipbytes) { + + // IF WE ARE COPYING AT LEAST SEVEN BYTES, ARRANGE THE BLT SO WE CAN + // DO AS MANY ALIGNED DWORD MOVES AS POSSIBLE + if (copybytes >= 7) { + while ((DWORD)dest & 3) { + *(dest++) = *(source++); + --copybytes; + } + while (copybytes >= 4) { + *(LPDWORD)dest = *(LPDWORD)source; + dest += 4; + source += 4; + copybytes -= 4; + } + } + + // OTHERWISE, JUST DO BYTE MOVES + while (copybytes) { + *(dest++) = *(source++); + --copybytes; + } + + // SKIP PAST THE NEXT TRANSPARENCY SPAN + dest += skipbytes; + source += skipbytes; + + // LOAD IN THE NEXT SPAN DATA + copybytes = *(sourceinst++); + skipbytes = *(sourceinst++); + + } + dest += destadjust; + source += sourceadjust; + } + +#endif +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY STransBlt (LPBYTE dest, + int destx, + int desty, + int destpitch, + HSTRANS transparency) { + // to minimize function call overhead for this time critical function, + // we use assert instead of validate so that the retail version has + // no parameter checking code + ASSERT(dest); + ASSERT(destpitch > 0); + ASSERT(transparency); + + TRANSPTR transptr = (TRANSPTR)transparency; + ASSERT(transptr->instructionoffset); + + // COMPUTE THE DESTINATION X ADJUSTMENT FOR EACH SCAN LINE + int xadjust = destpitch-transptr->width; + + // DRAW THE TRANSPARENCY + InternalDrawTransparency(transptr, + dest+(desty*destpitch)+destx, + xadjust); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransBltUsingMask (LPBYTE dest, + LPBYTE source, + int destpitch, + int sourcepitch, + HSTRANS mask) { + // to minimize function call overhead for this time critical function, + // we use assert instead of validate so that the retail version has + // no parameter checking code + ASSERT(dest); + ASSERT(source); + ASSERT(destpitch > 0); + ASSERT(mask); + + TRANSPTR transptr = (TRANSPTR)mask; + + // COMPUTE THE X ADJUSTMENTS FOR EACH SCAN LINE + int destadjust = destpitch-transptr->width; + int sourceadjust = sourcepitch ? sourcepitch-transptr->width : 0; + + // DRAW USING THE TRANSPARENCY MASK + InternalDrawTransparencyFromSource(transptr, + dest, + source, + destadjust, + sourceadjust); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransCreateE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle) { + if (handle) + *handle = (HSTRANS)0; + + VALIDATEBEGIN; + VALIDATE(bits); + VALIDATE(width); + VALIDATE(height); + VALIDATE(handle); + VALIDATEEND; + + return InternalCreateTransparency(bits, + width, + height, + bitdepth, + rect, + colorkey, + FALSE, + handle); +} + +//=========================================================================== +BOOL APIENTRY STransCreateI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle) { + RECT exclrect; + LPRECT exclrectptr = rect; + if (rect) { + exclrect.left = rect->left; + exclrect.top = rect->top; + exclrect.right = rect->right+1; + exclrect.bottom = rect->bottom+1; + exclrectptr = &exclrect; + } + return STransCreateE(bits, + width, + height, + bitdepth, + exclrectptr, + colorkey, + handle); +} + +//=========================================================================== +BOOL APIENTRY STransCreateMaskE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle) { + if (handle) + *handle = (HSTRANS)0; + + VALIDATEBEGIN; + VALIDATE(bits); + VALIDATE(width); + VALIDATE(height); + VALIDATE(handle); + VALIDATEEND; + + return InternalCreateTransparency(bits, + width, + height, + bitdepth, + rect, + colorkey, + TRUE, + handle); +} + +//=========================================================================== +BOOL APIENTRY STransCreateMaskI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle) { + RECT exclrect; + LPRECT exclrectptr = rect; + if (rect) { + exclrect.left = rect->left; + exclrect.top = rect->top; + exclrect.right = rect->right+1; + exclrect.bottom = rect->bottom+1; + exclrectptr = &exclrect; + } + return STransCreateMaskI(bits, + width, + height, + bitdepth, + exclrectptr, + colorkey, + handle); +} + +//=========================================================================== +BOOL APIENTRY STransDelete (HSTRANS handle) { + TRANSPTR transptr = (TRANSPTR)handle; + if (transptr->data) { + if (s_savedata) + FREE(s_savedata); + s_savedata = transptr->data; + s_savedataalloc = transptr->dataalloc; + transptr->data = NULL; + transptr->dataalloc = 0; + } + s_translist.DeleteNode(transptr); + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransDestroy () { + TRANSPTR curr; + while ((curr = s_translist.Head()) != NULL) { + REPORTRESOURCELEAK(HSTRANS); + STransDelete((HSTRANS)curr); + } + if (s_dirtyoffset) { + FREE(s_dirtyoffset); + s_dirtyoffset = NULL; + } + if (s_savedata) { + FREE(s_savedata); + s_savedata = NULL; + s_savedataalloc = 0; + } + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransDuplicate (HSTRANS source, + HSTRANS *handle) { + if (handle) + *handle = (HSTRANS)0; + + VALIDATEBEGIN; + VALIDATE(source); + VALIDATE(handle); + VALIDATEEND; + + TRANSPTR sourceptr = (TRANSPTR)source; + LPBYTE data = (LPBYTE)ALLOC(sourceptr->dataalloc); + CopyMemory(data,sourceptr->data,sourceptr->databytes); + TRANSPTR newptr = CreateTransparencyRecord(sourceptr); + newptr->data = data; + *handle = (HSTRANS)newptr; + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransInvertMask (HSTRANS sourcemask, + HSTRANS *handle) { + if (handle) + *handle = (HSTRANS)0; + + VALIDATEBEGIN; + VALIDATE(sourcemask); + VALIDATE(handle); + VALIDATEEND; + + TRANSPTR sourceptr = (TRANSPTR)sourcemask; + + // ALLOCATE MEMORY FOR THE NEW MASK DATA + DWORD dataalloc = (sourceptr->databytes-sourceptr->instructionoffset) + +2*sourceptr->height; + LPBYTE data = (LPBYTE)ALLOC(dataalloc); + + // COPY THE SOURCE MASK DATA, INVERTED, INTO THE DESTINATION BUFFER + DWORD bytes = 0; + { + LPBYTE source = sourceptr->data+sourceptr->instructionoffset; + LPBYTE dest = data; + int cy = sourceptr->height; + while (cy--) { + BYTE copybytes = 0; + BYTE skipbytes = 0; + do { + skipbytes = *(source++); + if (copybytes || skipbytes) { + *(dest++) = copybytes; + *(dest++) = skipbytes; + bytes += 2; + } + copybytes = *(source++); + } while (copybytes || skipbytes); + *(dest++) = 0; + *(dest++) = 0; + bytes += 2; + } + } + + // CREATE A RECORD FOR THE TRANSPARENCY + TRANSPTR newptr = CreateTransparencyRecord(sourceptr); + newptr->data = data; + newptr->dataalloc = dataalloc; + newptr->databytes = bytes; + newptr->instructionoffset = 0; + + // RETURN A HANDLE TO THE TRANSPARENCY + *handle = (HSTRANS)newptr; + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransIntersectDirtyArray (HSTRANS sourcemask, + LPBYTE dirtyarray, + BYTE dirtyarraymask, + HSTRANS *handle) { + if (handle) + *handle = (HSTRANS)0; + + VALIDATEBEGIN; + VALIDATE(sourcemask); + VALIDATE(dirtyarray); + VALIDATE(dirtyarraymask); + VALIDATE(handle); + VALIDATEEND; + + if (!s_dirtyoffset) + return FALSE; + TRANSPTR sourceptr = (TRANSPTR)sourcemask; + + // ALLOCATE MEMORY FOR THE RESULT + BUFFER buffer; + BufferCreate(&buffer); + + // PERFORM THE INTERSECTION + { + LPBYTE source = sourceptr->data+sourceptr->instructionoffset; + LPBYTE dest = buffer.data; + LPBYTE lastsource = source; + LPBYTE lastdest = dest; + int y = 0; + while (y < sourceptr->height) { + + // MAKE SURE THERE IS ENOUGH MEMORY IN THE DESTINATION BUFFER FOR + // THE LINE + BufferReserve(&buffer, + sourceptr->width*2+2, + &dest, + &lastdest); + + // IF THIS LINE MATCHES THE PREVIOUS ONE, JUST COPY THE RESULT + if ((y & (s_dirtyysize-1)) && + (*(LPDWORD)source == *(LPDWORD)lastsource) && + !memcmp(source+4,lastsource+4,source-lastsource-4)) { + DWORD sourcebytes = source-lastsource; + DWORD destbytes = dest-lastdest; + CopyMemory(dest,lastdest,destbytes); + lastsource = source; + lastdest = dest; + source += sourcebytes; + dest += destbytes; + buffer.bytesused += destbytes; + } + + // OTHERWISE, EXAMINE EACH SPAN FOR THIS LINE, SPLITTING COPY SPANS + // AND TURNING PORTIONS OF THEM INTO SKIP SPANS AS NECESSARY + else { + lastsource = source; + lastdest = dest; + LPBYTE dirty = dirtyarray+*(s_dirtyoffset+(y >> s_dirtyyshift)); + DWORD xoffset = 0; + BYTE copybytes; + BYTE skipbytes; + do { + copybytes = *(source++); + skipbytes = *(source++); + if (copybytes) { + BYTE bytesleft = copybytes; + BYTE length = 0; + BOOL copymode = TRUE; + while (bytesleft || length) + if (bytesleft && (((*dirty & dirtyarraymask) != 0) == copymode)) { + DWORD cellleft = s_dirtyxsize-xoffset; + if (bytesleft < cellleft) { + length += bytesleft; + xoffset += bytesleft; + bytesleft = 0; + } + else { + length += (BYTE)cellleft; + bytesleft -= (BYTE)cellleft; + xoffset = 0; + ++dirty; + } + } + else { + *(dest++) = length; + buffer.bytesused++; + length = 0; + copymode = !copymode; + } + if (skipbytes || !copymode) { + if (copymode) { + *(dest++) = 0; + buffer.bytesused++; + } + *(dest++) = skipbytes; + buffer.bytesused++; + } + } + else { + *(dest++) = 0; + *(dest++) = skipbytes; + buffer.bytesused += 2; + } + if (skipbytes) { + xoffset += skipbytes; + dirty += (xoffset >> s_dirtyxshift); + xoffset &= (s_dirtyxsize-1); + } + } while (copybytes || skipbytes); + } + + ++y; + } + } + + // CREATE A RECORD FOR THE TRANSPARENCY + TRANSPTR newptr = CreateTransparencyRecord(sourceptr); + newptr->data = buffer.data; + newptr->dataalloc = buffer.bytesalloc; + newptr->databytes = buffer.bytesused; + newptr->instructionoffset = 0; + + // RETURN A HANDLE TO THE TRANSPARENCY + *handle = (HSTRANS)newptr; + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransCombineMasks (HSTRANS basemask, + HSTRANS secondmask, + int offsetx, + int offsety, + DWORD flags, + HSTRANS *handle) { + if (handle) + *handle = (HSTRANS)0; + + VALIDATEBEGIN; + VALIDATE(basemask); + VALIDATE(secondmask); + VALIDATE(handle); + VALIDATEEND; + + // PARSE THE FLAGS + BOOL intersect = ((flags & 0x00000001) != 0); + BOOL invertsecond = ((flags & 0x00000002) != 0); + + // GENERATE A TRUTH TABLE TO DEFINE WHICH SOURCE SPANS WILL BE COMBINED INTO WHICH + // OUTPUT SPANS + BOOL usespan[2][2][2]; + { + for (int spantype0 = COPY; spantype0 <= SKIP; ++spantype0) + for (int spantypedest = COPY; spantypedest <= SKIP; ++spantypedest) + if (intersect) { + usespan[spantype0][spantypedest][invertsecond ? SKIP : COPY] = (spantype0 == spantypedest); + usespan[spantype0][spantypedest][invertsecond ? COPY : SKIP] = (spantypedest == SKIP); + } + else { + usespan[spantype0][spantypedest][invertsecond ? SKIP : COPY] = (spantypedest == COPY); + usespan[spantype0][spantypedest][invertsecond ? COPY : SKIP] = (spantype0 == spantypedest); + } + } + + // GET POINTERS TO THE SOURCE TRANSPARENCY INFORMATION + TRANSPTR sourceptr[2] = {(TRANSPTR)basemask, + (TRANSPTR)secondmask}; + INSTPTR instptr[2]; + instptr[0].byteptr = sourceptr[0]->data+sourceptr[0]->instructionoffset; + instptr[1].byteptr = sourceptr[1]->data+sourceptr[1]->instructionoffset; + + // SKIP PAST ANY SCAN LINES IN THE SECOND MASK WHICH ARE ABOVE THE TOP + // OF THE BASE MASK + if (offsety < 0) + for (int line = offsety; line < 0; ++line) + while (*instptr[1].wordptr++) + ; + + // ALLOCATE MEMORY FOR THE RESULT + BUFFER buffer; + BufferCreate(&buffer); + INSTPTR dest; + dest.byteptr = buffer.data; + + // PROCESS EACH SCAN LINE + for (int line = 0; line < sourceptr[0]->height; ++line) { + + // MAKE SURE THERE IS ENOUGH MEMORY IN THE DESTINATION BUFFER FOR + // THE LINE + BufferReserve(&buffer, + sourceptr[0]->width*2+2, + &dest.byteptr, + NULL); + + // IF THIS LINE IS NOT WITHIN THE RANGE THAT THE SECOND MASK INTERSECTS, + // THEN GENERATE A COMPLETE DUPLICATE OR A COMPLETE INTERSECTION OF THE + // BASE MASK + if ((line < offsety) || + (line > offsety+sourceptr[1]->height-1)) + if (intersect == invertsecond) { + do + buffer.bytesused += 2; + while ((*dest.wordptr++ = *instptr[0].wordptr++) != 0); + } + else { + int width = sourceptr[0]->width; + while (width) { + int skipspan = min(MAXSPANLENGTH,width); + *dest.byteptr++ = 0; + *dest.byteptr++ = (BYTE)skipspan; + buffer.bytesused += 2; + width -= skipspan; + } + *dest.wordptr++ = 0; + buffer.bytesused += 2; + while (*instptr[0].wordptr++) + ; + } + + // OTHERWISE, BUILD NEW INSTRUCTIONS FOR THIS SCAN LINE BY COMBINING THE + // INSTRUCTIONS FROM THE BASE AND SECOND MASKS + else { + int span[2][2] = {{0,0},{0,max(0,offsetx)}}; + BOOL hitend = FALSE; + + // SKIP PAST ANY PORTIONS OF THE SECOND MASK WHICH ARE ENTIRELY + // TO THE LEFT OF THE BASE MASK + if (offsetx < 0) { + int bytesleft = -offsetx; + while (bytesleft) { + span[1][COPY] = *instptr[1].byteptr++; + span[1][SKIP] = *instptr[1].byteptr++; + if (!(span[1][COPY] || span[1][SKIP])) { + span[1][SKIP] = INT_MAX; + hitend = TRUE; + break; + } + for (int adjustremaining = COPY; adjustremaining <= SKIP; ++adjustremaining) { + int adjustment = min(bytesleft,span[1][adjustremaining]); + span[1][adjustremaining] -= adjustment; + bytesleft -= adjustment; + } + } + } + + + // COMBINE THE BASE AND SECOND MASKS UNTIL THE BASE MASK IS EXHAUSTED + for (;;) { + + // LOAD THE NEXT COPY/SKIP PAIR FROM THE FIRST MASK + span[0][COPY] = *instptr[0].byteptr++; + span[0][SKIP] = *instptr[0].byteptr++; + if (!(span[0][COPY] || span[0][SKIP])) { + *dest.wordptr++ = 0; + buffer.bytesused += 2; + break; + } + + // COMBINE IT WITH INFORMATION FROM THE SECOND MASK STARTING + // AT THE CURRENT COPY/SKIP POSITION + for (int spantype0 = COPY; spantype0 <= SKIP; ++spantype0) + while (span[0][spantype0]) { + + // IF WE'VE USED UP THE CURRENT SET OF SPANS FROM THE SECOND MASK, + // LOAD THE NEXT SET + if (!(span[1][COPY] || span[1][SKIP])) { + span[1][COPY] = *instptr[1].byteptr++; + span[1][SKIP] = *instptr[1].byteptr++; + if (!(span[1][COPY] || span[1][SKIP])) { + span[1][SKIP] = INT_MAX; + hitend = TRUE; + } + } + + // GENERATE A NEW COPY SPAN AND A NEW SKIP SPAN + SPANPAIR inst; + for (int spantypedest = COPY; spantypedest <= SKIP; ++spantypedest) { + int spanlength = 0; + if (usespan[spantype0][spantypedest][COPY]) + spanlength = span[1][COPY]; + if (usespan[spantype0][spantypedest][SKIP] && + (usespan[spantype0][spantypedest][COPY] || !span[1][COPY])) + spanlength += span[1][SKIP]; + spanlength = min(spanlength,span[0][spantype0]); + inst.span[spantypedest] = (BYTE)spanlength; + span[0][spantype0] -= spanlength; + for (int adjustremaining = COPY; adjustremaining <= SKIP; ++adjustremaining) + if (usespan[adjustremaining]) { + int adjustment = min(spanlength,span[1][adjustremaining]); + span[1][adjustremaining] -= adjustment; + spanlength -= adjustment; + } + } + if (inst.pair) { + *dest.wordptr++ = inst.pair; + buffer.bytesused += 2; + } + + } + + } + if (!hitend) + while (*instptr[1].wordptr++) + ; + } + + } + + // CREATE A RECORD FOR THE TRANSPARENCY + TRANSPTR newptr = CreateTransparencyRecord(sourceptr[0]); + newptr->data = buffer.data; + newptr->dataalloc = buffer.bytesalloc; + newptr->databytes = buffer.bytesused; + newptr->instructionoffset = 0; + + // RETURN A HANDLE TO THE TRANSPARENCY + *handle = (HSTRANS)newptr; + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransIsPixelInMask (HSTRANS mask, + int offsetx, + int offsety) { + VALIDATEBEGIN; + VALIDATE(mask); + VALIDATEEND; + + // MAKE SURE THAT THE OFFSETS ARE WITHIN THE BOUNDS OF THE TRANSPARENCY + TRANSPTR transptr = (TRANSPTR)mask; + if ((offsetx < 0) || + (offsety < 0) || + (offsetx >= transptr->width) || + (offsety >= transptr->height)) + return FALSE; + + // SKIP TO THE CORRECT SCAN LINE + LPWORD instwordptr = (LPWORD)(transptr->data+transptr->instructionoffset); + while (offsety--) + while (*instwordptr++) + ; + + // SKIP TO THE CORRECT PIXEL + LPBYTE instbyteptr = (LPBYTE)instwordptr; + for (;;) { + BYTE copybytes = *instbyteptr++; + BYTE skipbytes = *instbyteptr++; + + // IF WE HIT THE END OF THE SCAN LINE, RETURN FALSE + if (!(copybytes || skipbytes)) + return FALSE; + + // IF THE REQUESTED PIXEL FALLS WITHIN A COPY SPAN, RETURN TRUE + if (copybytes > offsetx) + return TRUE; + offsetx -= copybytes; + + // IF THE REQUESTED PIXEL FALLS WITHIN A SKIP SPAN, RETURN FALSE + if (skipbytes > offsetx) + return FALSE; + offsetx -= skipbytes; + + } + +} + +//=========================================================================== +BOOL APIENTRY STransLoadE (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle) { + if (handle) + *handle = (HSTRANS)0; + + VALIDATEBEGIN; + VALIDATE(filename); + VALIDATE(*filename); + VALIDATE(handle); + VALIDATEEND; + + // DETERMINE THE SIZE OF THE BITMAP FILE + int width = 0; + int height = 0; + if (!SBmpLoadImage(filename,NULL,NULL,0,&width,&height)) + return FALSE; + + // READ THE BITMAP BITS + LPBYTE buffer = (LPBYTE)ALLOC(width*height); + if (!SBmpLoadImage(filename,NULL,buffer,width*height)) + return FALSE; + + // CREATE THE TRANSPARENCY + STransCreate(buffer, + width, + height, + 8, + rect, + colorkey, + handle); + + // FREE THE BITMAP BITS + FREE(buffer); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransLoadI (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle) { + RECT exclrect; + LPRECT exclrectptr = rect; + if (rect) { + exclrect.left = rect->left; + exclrect.top = rect->top; + exclrect.right = rect->right+1; + exclrect.bottom = rect->bottom+1; + exclrectptr = &exclrect; + } + return STransLoadE(filename, + exclrectptr, + colorkey, + handle); +} + +//=========================================================================== +BOOL APIENTRY STransSetDirtyArrayInfo (int screencx, + int screency, + int cellcx, + int cellcy) { + + // FREE THE OLD DIRTY ARRAY OFFSET TABLE + if (s_dirtyoffset) { + FREE(s_dirtyoffset); + s_dirtyoffset = NULL; + } + + // SAVE THE NEW CELL SIZES AND SHIFT VALUES + if (!DetermineShift(cellcx,&s_dirtyxshift)) + return 0; + if (!DetermineShift(cellcy,&s_dirtyyshift)) + return 0; + s_dirtysize.cx = (screencx+(1 << s_dirtyxshift)-1) >> s_dirtyxshift; + s_dirtysize.cy = (screency+(1 << s_dirtyyshift)-1) >> s_dirtyyshift; + s_dirtyxsize = cellcx; + s_dirtyysize = cellcy; + + // CREATE A NEW DIRTY ARRAY OFFSET TABLE + s_dirtyoffset = (LPDWORD)ALLOC(s_dirtysize.cy*sizeof(DWORD)); + DWORD offset = 0; + for (int loop = 0; loop < s_dirtysize.cy; ++loop) { + *(s_dirtyoffset+loop) = offset; + offset += s_dirtysize.cx; + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY STransUpdateDirtyArray (LPBYTE dirtyarray, + BYTE dirtyvalue, + int destx, + int desty, + HSTRANS transparency, + BOOL tracecontour) { + VALIDATEBEGIN; + VALIDATE(dirtyarray); + VALIDATE(dirtyvalue); + VALIDATE(transparency); + VALIDATEEND; + + if (!s_dirtyoffset) + return FALSE; + TRANSPTR transptr = (TRANSPTR)transparency; + if (!((transptr->width > 0) && (transptr->height > 0))) + return FALSE; + + // IF WE HAVE BEEN ASKED TO TRACE THE CONTOUR, THEN ONLY UPDATE THE VALUES + // OF THOSE CELLS THAT ARE TOUCHED BY A NON-TRANSPARENT PORTION OF THE + // TRANSPARENCY + if (tracecontour) { + // note: write this + return FALSE; + } + + // OTHERWISE, UPDATE THE WHOLE RECTANGLE CONTAINING THE TRANSPARENCY + else { + int lastx = (destx+transptr->boundrect.right) >> s_dirtyxshift; + int lasty = (desty+transptr->boundrect.bottom) >> s_dirtyyshift; + destx = (destx+transptr->boundrect.left) >> s_dirtyxshift; + desty = (desty+transptr->boundrect.top) >> s_dirtyyshift; + for (int y = desty; y < lasty; ++y) { + LPBYTE dirty = dirtyarray+*(s_dirtyoffset+y)+destx; + for (int x = destx; x < lastx; ++x) + *(dirty++) |= dirtyvalue; + } + } + + return TRUE; +} diff --git a/src/Storm/SOURCE/SVID.CPP b/src/Storm/SOURCE/SVID.CPP new file mode 100644 index 0000000..3a7ff33 --- /dev/null +++ b/src/Storm/SOURCE/SVID.CPP @@ -0,0 +1,1012 @@ +/**************************************************************************** +* +* SVID.CPP +* Storm video playback functions +* +* By Michael O'Brien (3/28/96) +* +***/ + +#include "pch.h" +#pragma hdrstop + +#define BENCHMARKVERSION 3 +#define MAXSOURCEWIDTH 320 +#define TOLERANCE 768 + +#define COL_RED 0 +#define COL_GREEN 1 +#define COL_BLUE 2 + +#define REGKEY "Video Player" +#define REGVALUE_MODE "Mode" + +typedef struct _COLORNODE { + _COLORNODE *next; + BYTE color; +} COLORNODE, *COLORNODEPTR; + +typedef struct _SCODE { + HSCODESTREAM horizontalinterpolate; + HSCODESTREAM verticalinterpolate; + HSCODESTREAM pixeldouble; +} SCODEREC, *SCODEPTR; + +typedef struct _SMACKERAPI { + void (RADEXPLINK *SmackBufferClose)(SmackBuf *); + void (RADEXPLINK *SmackBufferNewPalette)(SmackBuf *,void *,u32); + SmackBuf * (RADEXPLINK *SmackBufferOpen)(HWND,u32,u32,u32,u32,u32); + void (RADEXPLINK *SmackClose)(Smack *); + u32 (RADEXPLINK *SmackDoFrame)(Smack *); + void (RADEXPLINK *SmackGoto)(Smack *,u32); + void (RADEXPLINK *SmackNextFrame)(Smack *); + Smack * (RADEXPLINK *SmackOpen)(char *,u32,u32); + u8 (RADEXPLINK *SmackSoundUseDirectSound)(LPVOID); + void (RADEXPLINK *SmackToBuffer)(Smack *,u32,u32,u32,u32,void *,u32); + u32 (RADEXPLINK *SmackToBufferRect)(Smack *,u32); + void (RADEXPLINK *SmackVolumePan)(Smack *,u32,u32,u32); + u32 (RADEXPLINK *SmackWait)(Smack *); +} SMACKERAPI, *SMACKERAPIPTR; + +typedef struct _SMACKERDATA { + SmackBuf *buffer; + Smack *file; + int top; +} SMACKERDATA, *SMACKERDATAPTR; + +NODEDECL(VIDEOREC) { + HANDLE filehandle; + SCODEEXECUTEDATA executedata; + LPBYTE interptable; + DWORD palettefirstentry; + DWORD palettenumentries; + SMACKERDATAPTR smackerdata; + LPBYTE destbuffer; + RECT destrect; + LPCRECT ddrect; + SIZE destsize; + LPBYTE lockedbuffer; + DWORD flags; + BOOL vertzoom; + BOOL vertinterp; + int altline; + CSRgn rgn[2]; + DWORD allocrects; + DWORD numrects; + LPRECT rect; +} *VIDEOPTR; + +static SCODEPTR s_scode = NULL; +static SMACKERAPIPTR s_smackerapi = NULL; +static HINSTANCE s_smackerlib = (HINSTANCE)0; +static LIST(VIDEOREC) s_videolist; + +static void UnlockBuffer (VIDEOPTR video); + +//=========================================================================== +static void AdjustGamma (LPPALETTEENTRY pe, double gamma) { + for (int loop = 0; loop < 256; ++loop) { + double red = 256.0*pow(((double)(pe+loop)->peRed )/256.0,gamma); + double green = 256.0*pow(((double)(pe+loop)->peGreen)/256.0,gamma); + double blue = 256.0*pow(((double)(pe+loop)->peBlue )/256.0,gamma); + (pe+loop)->peRed = (red > 255.0) ? 255 : (BYTE)red; + (pe+loop)->peGreen = (green > 255.0) ? 255 : (BYTE)green; + (pe+loop)->peBlue = (blue > 255.0) ? 255 : (BYTE)blue; + } +} + +//=========================================================================== +static BOOL inline BindToSmacker () { + + // LOAD THE SMACKER LIBRARY + if (!s_smackerlib) { + s_smackerlib = LoadLibrary("smackw32.dll"); + if (!s_smackerlib) + return FALSE; + } + + // ALLOCATE AN API STRUCTURE + if (!s_smackerapi) + s_smackerapi = NEW(SMACKERAPI); + + // BIND TO THE INDIVIDUAL FUNCTIONS + BOOL success = TRUE; +#define BIND(a,b) *(void **)&s_smackerapi->##a \ + = GetProcAddress(s_smackerlib,b); \ + if (!s_smackerapi->##a) \ + success = FALSE; + BIND(SmackBufferClose ,"_SmackBufferClose@4"); + BIND(SmackBufferNewPalette ,"_SmackBufferNewPalette@12"); + BIND(SmackBufferOpen ,"_SmackBufferOpen@24"); + BIND(SmackClose ,"_SmackClose@4"); + BIND(SmackDoFrame ,"_SmackDoFrame@4"); + BIND(SmackGoto ,"_SmackGoto@8"); + BIND(SmackNextFrame ,"_SmackNextFrame@4"); + BIND(SmackOpen ,"_SmackOpen@12"); + BIND(SmackSoundUseDirectSound,"_SmackSoundUseDirectSound@4"); + BIND(SmackToBuffer ,"_SmackToBuffer@28"); + BIND(SmackToBufferRect ,"_SmackToBufferRect@8"); + BIND(SmackVolumePan ,"_SmackVolumePan@16"); + BIND(SmackWait ,"_SmackWait@4"); +#undef BIND + return success; +} + +//=========================================================================== +static BOOL CreateLinearInterpolationTable (VIDEOPTR video, LPPALETTEENTRY pe) { + + // ALLOCATE 64K FOR THE INTERPOLATION TABLE IF IT'S NOT ALREADY ALLOCATED + if (!video->interptable) { + video->interptable = (LPBYTE)ALLOC(0x10000); + video->executedata.table = video->interptable; + } + + // BUILD A SQUARE TABLE + static DWORD squaretable[511]; + static BOOL squareinit = FALSE; + if (!squareinit) { + squareinit = TRUE; + for (int loop = -255; loop <= 255; ++loop) + squaretable[loop+255] = (DWORD)(loop*loop); + } + + // BUILD A SET OF POINTERS INTO THE SQUARE TABLE FOR EACH PALETTE ENTRY + LPBYTE palcolor[3][256]; + DWORD loop; + for (loop = 0; loop < 256; ++loop) { + palcolor[COL_RED ][loop] = (LPBYTE)&squaretable[255+(pe+loop)->peRed]; + palcolor[COL_GREEN][loop] = (LPBYTE)&squaretable[255+(pe+loop)->peGreen]; + palcolor[COL_BLUE ][loop] = (LPBYTE)&squaretable[255+(pe+loop)->peBlue]; + } + + // FILL IN THE COLOR MATCHING TABLE + COLORNODEPTR interpcolortable[18][18][18]; + COLORNODE interpnode[256]; + ZeroMemory(&interpcolortable,18*18*18*sizeof(COLORNODEPTR)); + for (loop = 0; loop < 256; ++loop) { + if (loop && + ((pe+loop)->peRed == (pe+loop-1)->peRed) && + ((pe+loop)->peGreen == (pe+loop-1)->peGreen) && + ((pe+loop)->peBlue == (pe+loop-1)->peBlue)) + continue; + DWORD red = ((DWORD)(pe+loop)->peRed >> 4)+1; + DWORD green = ((DWORD)(pe+loop)->peGreen >> 4)+1; + DWORD blue = ((DWORD)(pe+loop)->peBlue >> 4)+1; + interpnode[loop].color = (BYTE)loop; + interpnode[loop].next = interpcolortable[red][green][blue]; + interpcolortable[red][green][blue] = &interpnode[loop]; + } + + // BUILD THE INTERPOLATION TABLE. FOR EVERY PAIR OF COLORS, WE LOOK + // FOR A COLOR THAT IS AS CLOSE AS POSSIBLE TO EQUIDISTANT BETWEEN THE + // TWO COLORS. + for (DWORD loop1 = 0; loop1 < 256; ++loop1) { + for (DWORD loop2 = 0; loop2 < loop1; ++loop2) { + BYTE minnum = (BYTE)max(loop1,loop2); + DWORD mindist = UINT_MAX; + + // FIND THE DESIRED COLOR + DWORD red = ((DWORD)(pe+loop1)->peRed +(DWORD)(pe+loop2)->peRed ) >> 1; + DWORD green = ((DWORD)(pe+loop1)->peGreen+(DWORD)(pe+loop2)->peGreen) >> 1; + DWORD blue = ((DWORD)(pe+loop1)->peBlue +(DWORD)(pe+loop2)->peBlue ) >> 1; + + // FIND THE SLOT IN THE COLOR MATCHING TABLE WHICH WOULD CONTAIN + // THE DESIRED COLOR + DWORD redslot = (red >> 4)+1; + DWORD greenslot = (green >> 4)+1; + DWORD blueslot = (blue >> 4)+1; + + // ADJUST THE COLOR VALUES OF THE DESIRED COLOR SO THEY CAN BE + // USED AS BYTE POINTERS + red <<= 2; + green <<= 2; + blue <<= 2; + + // IF THERE IS AT LEAST ONE COLOR IN THE COLOR MATCHING TABLE + // FOR THE TARGET AREA, USE ONLY COLORS FROM THAT AREA. + COLORNODEPTR curr = interpcolortable[redslot][greenslot][blueslot]; + if (curr) + if (curr->next) + while (curr) { + DWORD dist = *(LPDWORD)(palcolor[COL_RED][curr->color]-red) + +*(LPDWORD)(palcolor[COL_GREEN][curr->color]-green) + +*(LPDWORD)(palcolor[COL_BLUE][curr->color]-blue); + if (dist < mindist) { + mindist = dist; + minnum = curr->color; + } + curr = curr->next; + } + else + minnum = curr->color; + + // OTHERWISE, SEARCH A 3X3X3 GRID IN THE COLOR MATCHING TABLE. + else { + static const int offs[26][3] = {{-1,0,0},{0,-1,0},{0,0,-1}, + {1,0,0},{0,1,0},{0,0,1}, + {-1,1,0},{-1,0,1}, + {1,-1,0},{0,-1,1}, + {1,0,-1},{0,1,-1}, + {-1,-1,0},{-1,0,-1},{0,-1,-1}, + {1,1,0},{1,0,1},{0,1,1}, + {-1,-1,1},{-1,1,-1},{1,-1,-1}, + {1,1,-1},{1,-1,1},{-1,1,1}, + {-1,-1,-1},{1,1,1}}; + for (BYTE loop = 0; (loop < 26) && (mindist > TOLERANCE); ++loop) { + curr = interpcolortable[redslot +offs[loop][0]] + [greenslot+offs[loop][1]] + [blueslot +offs[loop][2]]; + while (curr) { + DWORD dist = *(LPDWORD)(palcolor[COL_RED][curr->color]-red) + +*(LPDWORD)(palcolor[COL_GREEN][curr->color]-green) + +*(LPDWORD)(palcolor[COL_BLUE][curr->color]-blue); + if (dist < mindist) { + mindist = dist; + minnum = curr->color; + } + curr = curr->next; + } + } + } + + *(video->interptable+(loop1 << 8)+loop2) = (BYTE)minnum; + *(video->interptable+(loop2 << 8)+loop1) = (BYTE)minnum; + } + *(video->interptable+(loop1 << 8)+loop1) = (BYTE)loop1; + } + + return TRUE; +} + +//=========================================================================== +static inline void ExtractRects (VIDEOPTR videoptr, + CSRgn *rgn) { + rgn->GetRects(&videoptr->numrects,NULL); + if (videoptr->numrects > videoptr->allocrects) { + FREEIFUSED(videoptr->rect); + videoptr->allocrects = videoptr->numrects; + videoptr->rect = (LPRECT)ALLOC(videoptr->allocrects*sizeof(RECT)); + } + rgn->GetRects(&videoptr->numrects,videoptr->rect); +} + +//=========================================================================== +static BOOL IsValidVideoHandle (HSVIDEO handle) { + ITERATELIST(VIDEOREC,s_videolist,currvideo) + if (currvideo == (VIDEOPTR)handle) + return TRUE; + return FALSE; +} + +//=========================================================================== +static BOOL LockBuffer (VIDEOPTR video, LPBYTE *buffer, LPSIZE size) { + if (video->flags & SVID_FLAG_TOSCREEN) { + size->cx = 640; + size->cy = 480; + SDrawGetScreenSize((int *)&size->cx,(int *)&size->cy); + BOOL result = SDrawLockSurface(SDRAW_SURFACE_FRONT, + video->ddrect, + &video->lockedbuffer, + (int *)&size->cx); + *buffer = video->lockedbuffer+video->smackerdata->top*size->cx; + if ((!video->ddrect) && (video->flags & SVID_FLAG_1XSIZE)) + *buffer += (min(640,size->cx)-video->smackerdata->file->Width) >> 1; + return result; + } + else { + *buffer = video->destbuffer + +(video->destrect.top*video->destsize.cx) + +video->destrect.left; + size->cx = video->destsize.cx; + size->cy = video->destsize.cy; + return TRUE; + } +} + +//=========================================================================== +static BOOL ProcessFrameDirect (VIDEOPTR videoptr) { + BOOL skip = TRUE; + LPBYTE videobuffer; + SIZE videosize; + if (LockBuffer(videoptr,&videobuffer,&videosize)) { + s_smackerapi->SmackToBuffer(videoptr->smackerdata->file, + 0, + 0, + videosize.cx, + videosize.cy, + videobuffer, + 0); + skip = s_smackerapi->SmackDoFrame(videoptr->smackerdata->file); + UnlockBuffer(videoptr); + } + return skip; +} + +//=========================================================================== +static void ProcessFrameEffects (VIDEOPTR videoptr) { + + // SAVE POINTERS TO COMMONLY ACCESSED DATA STRUCTURES + SCODEEXECUTEDATA *exec = &videoptr->executedata; + LPBYTE source = (LPBYTE)videoptr->smackerdata->buffer->Buffer; + SIZE sourcesz = {videoptr->smackerdata->buffer->Width, + videoptr->smackerdata->buffer->Height}; + BOOL vertzoom = videoptr->vertzoom; + BOOL vertinterp = videoptr->vertinterp; + BOOL horzinterp = ((videoptr->flags & SVID_FLAG_INTERPOLATE) != 0); + BOOL skip = vertzoom && !(videoptr->flags & SVID_FLAG_DOUBLESCANS); + BOOL interlace = (videoptr->flags & SVID_FLAG_INTERLACE) && !skip; + + // IF WE ARE INTERLACING, ALTERNATE THE SCAN LINE ADJUSTMENT + if (interlace) + videoptr->altline = !videoptr->altline; + int altline = videoptr->altline; + + // UNCOMPRESS THE FRAME INTO THE OFFSCREEN BUFFER, AND BUILD A REGION + // CONTAINING ALL OF THE RECTANGLES THAT WERE MODIFIED DURING THE + // DECOMPRESSION PROCESS + videoptr->rgn[altline].Clear(); + while (s_smackerapi->SmackToBufferRect(videoptr->smackerdata->file, + SMACKSURFACEFAST)) { + RECT rect = {videoptr->smackerdata->file->LastRectx, + videoptr->smackerdata->file->LastRecty, + videoptr->smackerdata->file->LastRectx + +videoptr->smackerdata->file->LastRectw, + videoptr->smackerdata->file->LastRecty + +videoptr->smackerdata->file->LastRecth}; + videoptr->rgn[altline].AddRect(&rect,NULL); + } + + // IF WE ARE INTERLACING, THEN ADD ALL THE RECTANGLES FROM THE PREVIOUS + // FRAME + CSRgn *rgn; + if (interlace) { + rgn = new CSRgn(videoptr->rgn[altline]); + ExtractRects(videoptr,&videoptr->rgn[!altline]); + for (DWORD num = 0; num < videoptr->numrects; ++num) + rgn->AddRect(&videoptr->rect[num],NULL); + } + else + rgn = &videoptr->rgn[altline]; + + // EXTRACT AN ARRAY OF RECTANGLES FROM THE REGION + ExtractRects(videoptr,rgn); + if (interlace) + delete rgn; + + // LOCK THE VIDEO BUFFER + LPBYTE dest; + SIZE destsz; + if (!LockBuffer(videoptr,&dest,&destsz)) + return; + + // PROCESS EACH RECTANGLE + for (DWORD num = 0; num < videoptr->numrects; ++num) { + POINT pos = {videoptr->rect[num].left, + videoptr->rect[num].top}; + SIZE sz = {videoptr->rect[num].right-videoptr->rect[num].left, + videoptr->rect[num].bottom-videoptr->rect[num].top}; + if ((sz.cx < 2) || (sz.cy < 2)) + continue; + + // PERFORM VERTICAL INTERPOLATION IF NECESSARY + if (vertinterp) { + exec->xiterations = sz.cx; + exec->yiterations = sz.cy-1; + exec->source = source+(pos.y*sourcesz.cx)+pos.x; + exec->dest = source+(pos.y*sourcesz.cx)+pos.x+(sourcesz.cx/2); + exec->adjustsource = sourcesz.cx-sz.cx; + exec->adjustdest = sourcesz.cx-sz.cx; + exec->c = sourcesz.cx; + if (pos.y) { + exec->yiterations++; + exec->source = (LPBYTE)exec->source-sourcesz.cx; + exec->dest = (LPBYTE)exec->dest-sourcesz.cx; + } + SCodeExecute(s_scode->verticalinterpolate,exec); + } + + // SETUP THE OPERATION TO BLT THE OFFSCREEN BUFFER ONTO THE SCREEN + exec->xiterations = sz.cx; + exec->yiterations = sz.cy; + exec->source = source+pos.y*sourcesz.cx+pos.x; + exec->dest = dest+pos.y*destsz.cx+pos.x*2; + exec->adjustsource = sourcesz.cx-sz.cx; + exec->adjustdest = destsz.cx-sz.cx*2; + + // ADJUST THE OPERATION FOR HORIZONTAL INTERPOLATION + exec->xiterations -= horzinterp; + + // ADJUST THE OPERATION FOR VERTICAL ZOOMING + if (vertzoom) { + exec->dest = (LPBYTE)exec->dest+pos.y*destsz.cx; + exec->yiterations *= 2; + } + + // ADJUST THE OPERATION FOR VERTICAL INTERPOLATION + if (vertinterp) { + exec->adjustsource -= sourcesz.cx/2; + if (interlace && altline && (pos.y >= 2)) { + exec->yiterations += 2; + exec->source = (LPBYTE)exec->source-sourcesz.cx; + exec->dest = (LPBYTE)exec->dest-destsz.cx*2; + } + else if ((!interlace) && pos.y) { + exec->yiterations++; + exec->source = (LPBYTE)exec->source-sourcesz.cx/2; + exec->dest = (LPBYTE)exec->dest-destsz.cx; + } + } + + // ADJUST THE OPERATION FOR SCAN LINE SKIPPING + if (skip) { + exec->yiterations /= 2; + exec->adjustdest += destsz.cx; + } + + // ADJUST THE OPERATION FOR INTERLACING + if (interlace) { + exec->yiterations /= 2; + exec->adjustdest += destsz.cx; + if (altline && (vertinterp || !vertzoom)) + exec->source = (LPBYTE)exec->source+(sourcesz.cx >> vertinterp); + if (altline) + exec->dest = (LPBYTE)exec->dest+destsz.cx; + if (vertinterp) + exec->adjustsource += sourcesz.cx/2; + else if (!vertzoom) + exec->adjustsource += sourcesz.cx; + } + + // ADJUST THE OPERATION FOR LINE DOUBLING + exec->adjustsourcealt = exec->adjustsource; + exec->adjustdestalt = exec->adjustdest; + if (vertzoom && !(vertinterp || skip || interlace)) + exec->adjustsource = -sz.cx; + + // PERFORM THE BLT + SCodeExecute(horzinterp + ? s_scode->horizontalinterpolate + : s_scode->pixeldouble, + exec); + + + } + + // UNLOCK THE VIDEO BUFFER + UnlockBuffer(videoptr); + +} + +//=========================================================================== +static void UnlockBuffer (VIDEOPTR video) { + if (video->flags & SVID_FLAG_TOSCREEN) { + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,video->lockedbuffer); + video->lockedbuffer = NULL; + } +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY SVidDestroy () { + + // CLOSE ALL ACTIVE VIDEOS + VIDEOPTR curr; + while ((curr = s_videolist.Head()) != NULL) { + REPORTRESOURCELEAK(HSVIDEO); + SVidPlayEnd((HSVIDEO)curr); + } + + // DELETE S-CODE STREAMS + if (s_scode) { + SCodeDelete(s_scode->horizontalinterpolate); + SCodeDelete(s_scode->verticalinterpolate); + SCodeDelete(s_scode->pixeldouble); + FREE(s_scode); + s_scode = NULL; + } + + // UNBIND FROM SMACKER + if (s_smackerapi) { + FREE(s_smackerapi); + s_smackerapi = NULL; + } + if (s_smackerlib) { + FreeLibrary(s_smackerlib); + s_smackerlib = (HINSTANCE)0; + } + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SVidGetSize (HSVIDEO video, + int *width, + int *height, + int *bitdepth) { + if (width) + *width = 0; + if (height) + *height = 0; + if (bitdepth) + *bitdepth = 8; + + VALIDATEBEGIN; + VALIDATE(video); + VALIDATEEND; + + if (!IsValidVideoHandle(video)) + return FALSE; + VIDEOPTR videoptr = (VIDEOPTR)video; + if (width) + *width = videoptr->smackerdata->file->Width; + if (height) + *height = videoptr->smackerdata->file->Height; + return (width || height || bitdepth); +} + +//=========================================================================== +BOOL APIENTRY SVidInitialize (LPVOID directsound) { + + // BIND TO SMACKER + if (!BindToSmacker()) + return FALSE; + + // CREATE S-CODE STREAMS FOR THE INNER LOOPS + if (!s_scode) { + s_scode = NEW(SCODEREC); + SCodeCompile("1 W2=S W1=W2 2 D=W","1 W1=W2 W2=S W1=TW 2 D=W",NULL, + MAXSOURCEWIDTH, + 0, + &s_scode->horizontalinterpolate); + SCodeCompile(NULL,"1 W1=S W2=SC D=TW",NULL, + MAXSOURCEWIDTH, + 0, + &s_scode->verticalinterpolate); + SCodeCompile(NULL,"1 W1=S W2=W1 2 D=W",NULL, + MAXSOURCEWIDTH, + SCODE_CF_USESALTADJUSTS, + &s_scode->pixeldouble); + } + if (!(s_scode->horizontalinterpolate && + s_scode->verticalinterpolate && + s_scode->pixeldouble)) + return FALSE; + + // INITIALIZE SOUND + s_smackerapi->SmackSoundUseDirectSound(directsound); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SVidPlayBegin (LPCTSTR filename, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle) { + if (handle) + *handle = (HSVIDEO)0; + + VALIDATEBEGIN; + VALIDATE(filename); + VALIDATE(handle); + VALIDATE(destbuffer || !(flags & SVID_FLAG_TOBUFFER)); + VALIDATE(destsize || !destbuffer); + VALIDATE((!paletteuse) || (paletteuse->size == sizeof(SVIDPALETTEUSE))); + VALIDATEEND; + + // DETERMINE THE SCREEN SIZE, WHICH IS NEEDED BY MANY OF THE SIZING AND + // POSITIONING CALCULATIONS PERFORMED BY THIS FUNCTION + int screencx, screency; + SDrawGetScreenSize(&screencx,&screency); + + // IF THE AUTOSIZE OR AUTOQUALITY FLAGS ARE SET, READ THE CURRENT VIDEO + // MODE OUT OF THE REGISTRY, OR DEFAULT TO HIGH QUALITY MODE + if (flags & (SVID_FLAG_AUTOSIZE | SVID_FLAG_AUTOQUALITY)) { + + // LOAD THE BASE SETTING FROM THE REGISTRY + DWORD newflags = 0; + SRegLoadValue(REGKEY,REGVALUE_MODE,0,&newflags); + + // ADJUST IT TO THE DEFAULT QUALITY LEVEL + if (!(newflags & SVID_FLAG_1XSIZE)) + newflags = SVID_QUALITY_HIGH; + + // ADJUST THE FLAGS + if (flags & SVID_FLAG_AUTOSIZE) { + flags &= ~(SVID_FLAG_1XSIZE | SVID_FLAG_2XSIZE); + flags |= (newflags & (SVID_FLAG_1XSIZE | SVID_FLAG_2XSIZE)); + } + if (flags & SVID_FLAG_AUTOQUALITY) { + flags &= ~(SVID_FLAG_DOUBLESCANS | SVID_FLAG_INTERPOLATE | SVID_FLAG_INTERLACE); + flags |= (newflags & (SVID_FLAG_DOUBLESCANS | SVID_FLAG_INTERPOLATE | SVID_FLAG_INTERLACE)); + } + + } + + // INITIALIZE THIS MODULE IF NECESSARY + if (!(s_smackerlib && s_smackerapi && s_scode)) + if (!SVidInitialize(NULL)) + return FALSE; + + // ALLOCATE A NEW VIDEO RECORD + VIDEOPTR videoptr = s_videolist.NewNode(); + videoptr->filehandle = INVALID_HANDLE_VALUE; + + // PERFORM INITIAL PROCESSING ON THE FLAGS + flags = (flags & ~SVID_FLAG_TOSCREEN) + | ((flags & SVID_FLAG_TOBUFFER) ? 0 : SVID_FLAG_TOSCREEN); + if (flags & SVID_FLAG_TOBUFFER) + flags &= ~SVID_FLAG_FULLSCREEN; + if (flags & SVID_FLAG_TOSCREEN) + destbuffer = NULL; + + // PROCESS AND SAVE THE DESTINATION + videoptr->destbuffer = (LPBYTE)destbuffer; + if (destrect) { + CopyMemory(&videoptr->destrect,destrect,sizeof(RECT)); + videoptr->ddrect = &videoptr->destrect; + } + if (destsize) + CopyMemory(&videoptr->destsize,destsize,sizeof(SIZE)); + + // PROCESS AND SAVE THE PALETTE INFORMATION + if (paletteuse) { + videoptr->palettefirstentry = paletteuse->firstentry; + videoptr->palettenumentries = paletteuse->numentries; + } + else { + videoptr->palettefirstentry = 1; + videoptr->palettenumentries = 254; + } + + // ALLOCATE A SMACKER DATA RECORD + videoptr->smackerdata = NEWZERO(SMACKERDATA); + + // OPEN THE FILE + { + DWORD smackerflags = SMACKFILEHANDLE | SMACKTRACKS; + HANDLE filehandle = INVALID_HANDLE_VALUE; + if (flags & SVID_FLAG_PRELOAD) + smackerflags |= SMACKPRELOADALL; + if (flags & SVID_FLAG_NOSKIP) + smackerflags |= SMACKNOSKIP; + if (flags & SVID_FLAG_NEEDPAN) + smackerflags |= SMACKNEEDPAN; + if (flags & SVID_FLAG_NEEDVOLUME) + smackerflags |= SMACKNEEDVOLUME; + if (flags & SVID_FLAG_FILEHANDLE) + filehandle = (HANDLE)filename; + else if (SFileOpenFileWin32(filename,&filehandle)) + videoptr->filehandle = filehandle; + else { + SVidPlayEnd((HSVIDEO)videoptr); + return FALSE; + } + if (!(videoptr->smackerdata->file = s_smackerapi->SmackOpen((char *)filehandle, + smackerflags, + SMACKAUTOEXTRA))) { + SVidPlayEnd((HSVIDEO)videoptr); + return FALSE; + } + } + + // COMPARE THE VIDEO SIZE TO THE SCREEN SIZE, AND FORCE OFF VERTICAL ZOOMING + // AND/OR HORIZONTAL ZOOMING AS NECESSARY TO FIT THE VIDEO ON THE SCREEN + if ((int)videoptr->smackerdata->file->Width*2 > screencx) + flags &= ~SVID_FLAG_2XSIZE; + videoptr->vertzoom = ((flags & SVID_FLAG_2XSIZE) != 0); + if ((int)videoptr->smackerdata->file->Height*2 > screency) + videoptr->vertzoom = FALSE; + + // DETERMINE THE TOP OUTPUT SCAN LINE + if (flags & SVID_FLAG_FULLSCREEN) + videoptr->smackerdata->top = (screency-(videoptr->smackerdata->file->Height*(videoptr->vertzoom+1)))/2; + else + videoptr->smackerdata->top = 0; + + // CREATE A SMACKER OFFSCREEN BUFFER + if (flags & SVID_FLAG_2XSIZE) { + videoptr->vertinterp = videoptr->vertzoom && + (flags & SVID_FLAG_DOUBLESCANS) && + (flags & SVID_FLAG_INTERPOLATE); + if (!(videoptr->smackerdata->buffer = + s_smackerapi->SmackBufferOpen((HWND)0, + SMACKSTANDARDBLIT, + videoptr->smackerdata->file->Width*(videoptr->vertinterp+1), + videoptr->smackerdata->file->Height, + videoptr->smackerdata->file->Width*(videoptr->vertinterp+1), + videoptr->smackerdata->file->Height))) { + SVidPlayEnd((HSVIDEO)videoptr); + return FALSE; + } + s_smackerapi->SmackToBuffer(videoptr->smackerdata->file, + 0, + 0, + videoptr->smackerdata->file->Width*(videoptr->vertinterp+1), + videoptr->smackerdata->file->Height, + videoptr->smackerdata->buffer->Buffer, + 0); + } + else + videoptr->vertinterp = FALSE; + + // PROCESS AND SAVE THE FINAL FLAGS + flags = (flags & ~SVID_FLAG_1XSIZE) + | ((flags & SVID_FLAG_2XSIZE) ? 0 : SVID_FLAG_1XSIZE); + if (flags & SVID_FLAG_1XSIZE) + flags &= ~(SVID_FLAG_DOUBLESCANS | SVID_FLAG_INTERPOLATE | SVID_FLAG_INTERLACE); + videoptr->flags = flags; + + // IF WE HAVE BEEN ASKED TO LINEAR INTERPOLATE BUT HAVE NOT BEEN GIVEN + // AUTHORITY TO MODIFY THE PALETTE, THEN CREATE A LINEAR INTERPOLATION + // TABLE BASED ON THE CURRENT PALETTE + if ((flags & (SVID_FLAG_INTERPOLATE | SVID_FLAG_USECURRENTPALETTE)) + == (SVID_FLAG_INTERPOLATE | SVID_FLAG_USECURRENTPALETTE) && + SDrawGetFrameWindow()) { + HDC dc = GetDC(SDrawGetFrameWindow()); + PALETTEENTRY pe[256]; + GetSystemPaletteEntries(dc,0,256,&pe[0]); + ReleaseDC(SDrawGetFrameWindow(),dc); + CreateLinearInterpolationTable(videoptr,&pe[0]); + } + + // INITIALIZE THE EXECUTE DATA + videoptr->executedata.size = sizeof(SCODEEXECUTEDATA); + + // RETURN A HANDLE TO THE VIDEO + *handle = (HSVIDEO)videoptr; + + // CLEAR THE VIDEO SURFACE + if (flags & SVID_FLAG_CLEARSCREEN) + SDrawClearSurface(SDRAW_SURFACE_FRONT); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SVidPlayBeginFromMemory (LPVOID sourceptr, + DWORD sourcebytes, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle) { + if (handle) + *handle = (HSVIDEO)0; + + VALIDATEBEGIN; + VALIDATE(sourceptr); + VALIDATE(sourcebytes); + VALIDATE(destbuffer || !(flags & SVID_FLAG_TOBUFFER)); + VALIDATE(destsize || !destbuffer); + VALIDATE((!paletteuse) || (paletteuse->size == sizeof(SVIDPALETTEUSE))); + VALIDATEEND; + + // SMACKER DOESN'T HAVE THE CAPABILITY TO PLAY FROM MEMORY, SO WE + // SAVE THE DATA TO A TEMPORARY FILE ON DISK AND THEN ASK SMACKER + // TO PLAY THAT. + char temppath[MAX_PATH] = "."; + char tempfilename[MAX_PATH] = ""; + GetTempPath(MAX_PATH,temppath); + GetTempFileName(temppath,"Vid",0,tempfilename); + HANDLE tempfile = CreateFile(tempfilename, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + if (tempfile == INVALID_HANDLE_VALUE) + return FALSE; + DWORD byteswritten; + WriteFile(tempfile,sourceptr,sourcebytes,&byteswritten,NULL); + SetFilePointer(tempfile,0,NULL,FILE_BEGIN); + BOOL result = SVidPlayBegin((LPCTSTR)tempfile, + destbuffer, + destrect, + destsize, + paletteuse, + flags | SVID_FLAG_FILEHANDLE | SVID_FLAG_PRELOAD, + handle); + CloseHandle(tempfile); + DeleteFile(tempfilename); + + return result; +} + +//=========================================================================== +BOOL APIENTRY SVidPlayContinue () { + BOOL moreframes = FALSE; + VIDEOPTR currvideo = s_videolist.Head(); + while (currvideo) { + VIDEOPTR nextvideo = currvideo->Next(); + if (SVidPlayContinueSingle((HSVIDEO)currvideo,0,NULL)) + moreframes = TRUE; + currvideo = nextvideo; + } + return moreframes; +} + +//=========================================================================== +BOOL APIENTRY SVidPlayContinueSingle (HSVIDEO video, + BOOL forceupdate, + BOOL *updated) { + if (updated) + *updated = 0; + + VALIDATEBEGIN; + VALIDATE(video); + VALIDATEEND; + + if (!IsValidVideoHandle(video)) + return FALSE; + VIDEOPTR videoptr = (VIDEOPTR)video; + if (!(videoptr->smackerdata && videoptr->smackerdata->file)) + return FALSE; + + // UNLESS THE FORCE UPDATE FLAG IS ON, DO NOT PLAY THE NEXT FRAME + // UNTIL THE REQUIRED DELAY HAS ELAPSED + if ((!forceupdate) && + s_smackerapi->SmackWait(videoptr->smackerdata->file)) + return TRUE; + + // IF THE PALETTE HAS CHANGED, PROCESS THE NEW PALETTE + LPPALETTEENTRY newpalette = NULL; + if (videoptr->smackerdata->file->NewPalette && + !(videoptr->flags & SVID_FLAG_USECURRENTPALETTE)) { + if (videoptr->smackerdata->buffer) + s_smackerapi->SmackBufferNewPalette(videoptr->smackerdata->buffer, + videoptr->smackerdata->file->Palette, + 0); + PALETTEENTRY pe[256]; + int index = 0; + for (int loop = 0; loop < 256; ++loop) { + pe[loop].peRed = videoptr->smackerdata->file->Palette[index++]; + pe[loop].peGreen = videoptr->smackerdata->file->Palette[index++]; + pe[loop].peBlue = videoptr->smackerdata->file->Palette[index++]; + } + newpalette = &pe[0]; + if (videoptr->flags & SVID_FLAG_CLEARSCREEN) + SDrawClearSurface(SDRAW_SURFACE_FRONT); + if ((videoptr->flags & (SVID_FLAG_2XSIZE | SVID_FLAG_DOUBLESCANS)) == SVID_FLAG_2XSIZE) + AdjustGamma(newpalette,0.8); + if (videoptr->flags & SVID_FLAG_INTERPOLATE) + CreateLinearInterpolationTable(videoptr,newpalette); + } + + // UNCOMPRESS THE FRAME AND SET ITS PALETTE + BOOL skip; + if (videoptr->flags & SVID_FLAG_2XSIZE) { + skip = s_smackerapi->SmackDoFrame(videoptr->smackerdata->file); + if (newpalette) + SDrawUpdatePalette(videoptr->palettefirstentry, + videoptr->palettenumentries, + newpalette+videoptr->palettefirstentry); + } + else { + if (newpalette) + SDrawUpdatePalette(videoptr->palettefirstentry, + videoptr->palettenumentries, + newpalette+videoptr->palettefirstentry); + skip = ProcessFrameDirect(videoptr); + } + if (updated && !skip) + *updated = TRUE; + + // IF WE JUST SKIPPED A FRAME AND STORM IS IN CHARGE OF SETTING THE + // QUALITY, DEGRADE THE CURRENT QUALITY SETTING + if (skip) + if (videoptr->flags & SVID_FLAG_INTERPOLATE) { + videoptr->flags &= ~SVID_FLAG_INTERPOLATE; + videoptr->vertinterp = FALSE; + } + else + videoptr->flags |= SVID_FLAG_INTERLACE; + + // IF THIS FRAME WAS NOT SKIPPED AND WAS NOT UNCOMPRESSED DIRECTLY + // ONTO THE SCREEN, UPDATE THE SCREEN + if ((videoptr->flags & SVID_FLAG_2XSIZE) && !skip) + ProcessFrameEffects(videoptr); + + // STEP TO THE NEXT FRAME, AND RETURN A BOOLEAN TELLING WHETHER THERE + // ARE MORE FRAMES TO BE PROCESSED + if ((videoptr->smackerdata->file->FrameNum+1 < videoptr->smackerdata->file->Frames) || + (videoptr->flags & SVID_FLAG_LOOP)) { + s_smackerapi->SmackNextFrame(videoptr->smackerdata->file); + return TRUE; + } + else { + SVidPlayEnd((HSVIDEO)videoptr); + return FALSE; + } +} + +//=========================================================================== +BOOL APIENTRY SVidPlayEnd (HSVIDEO video) { + VALIDATEBEGIN; + VALIDATE(video); + VALIDATEEND; + + if (!IsValidVideoHandle(video)) + return FALSE; + VIDEOPTR videoptr = (VIDEOPTR)video; + if (!videoptr->smackerdata) + return FALSE; + + // CLOSE THE FILE + if (videoptr->smackerdata->buffer) + s_smackerapi->SmackBufferClose(videoptr->smackerdata->buffer); + if (videoptr->smackerdata->file) + s_smackerapi->SmackClose(videoptr->smackerdata->file); + FREE(videoptr->smackerdata); + videoptr->smackerdata = NULL; + if (videoptr->filehandle != INVALID_HANDLE_VALUE) { + CloseHandle(videoptr->filehandle); + videoptr->filehandle = INVALID_HANDLE_VALUE; + } + + // DELETE THE INTERPOLATION TABLE + if (videoptr->interptable) { + FREE(videoptr->interptable); + videoptr->interptable = NULL; + videoptr->executedata.table = NULL; + } + + // DELETE THE ARRAY OF RECTANGLES + FREEIFUSED(videoptr->rect); + + // REMOVE THE VIDEO RECORD FROM OUR LIST + s_videolist.DeleteNode(videoptr); + + return TRUE; +} + +//=========================================================================== +BOOL APIENTRY SVidSetVolume (HSVIDEO video, + LONG volume, + LONG pan, + DWORD track) { + VALIDATEBEGIN; + VALIDATE(video); + VALIDATEEND; + + if (!IsValidVideoHandle(video)) + return FALSE; + VIDEOPTR videoptr = (VIDEOPTR)video; + if (!videoptr->smackerdata) + return FALSE; + + // CONVERT THE VOLUME AND PAN PARAMETERS TO SMACKER FORMAT + DWORD smackervolume = (DWORD)(volume+10000)*65536/20000; + DWORD smackerpan = (DWORD)(pan +10000)*65536/20000; + + // CONVERT THE TRACK PARAMETER TO SMACKER FORMAT + DWORD smackertracks; + switch (track) { + case 1: smackertracks = SMACKTRACK1; break; + case 2: smackertracks = SMACKTRACK2; break; + case 3: smackertracks = SMACKTRACK3; break; + case 4: smackertracks = SMACKTRACK4; break; + case 5: smackertracks = SMACKTRACK5; break; + case 6: smackertracks = SMACKTRACK6; break; + case 7: smackertracks = SMACKTRACK7; break; + default: smackertracks = SMACKTRACKS; break; + } + + // CALL SMACKER TO SET THE VOLUME AND PAN FOR THE REQUESTED TRACK(S) + s_smackerapi->SmackVolumePan(videoptr->smackerdata->file, + smackertracks, + smackervolume, + smackerpan); + + return TRUE; +} diff --git a/src/Storm/SOURCE/SYSPAL.PCX b/src/Storm/SOURCE/SYSPAL.PCX new file mode 100644 index 0000000..fe66a80 Binary files /dev/null and b/src/Storm/SOURCE/SYSPAL.PCX differ diff --git a/src/Storm/SOURCE/WIN32.CS b/src/Storm/SOURCE/WIN32.CS new file mode 100644 index 0000000..a72e225 --- /dev/null +++ b/src/Storm/SOURCE/WIN32.CS @@ -0,0 +1,46 @@ +// IF THE USER TRIES TO RUN THIS SCRIPT DIRECTLY, INSTEAD OF USING THIS +// SCRIPT BY INCLUDING IT FROM ANOTHER ONE, DISPLAY AN ERROR +if not %project%==win32 goto start +echo You must specify a project script. +echo Type "C /?" for help. +halt +:start + +// SET UP AUTO-DEPENDENCY CHECKING +set -autodependencies =.c;.cpp;.h;.hpp +set -ignoredependencies=windows.h;windowsx.h;ole2.h;rpc.h;ddraw.h;dsound.h + +// SET THE DEFAULT COMMAND LINE OPTIONS FOR THE COMPILER AND LINKER +if %debug% set clopt=-D_DEBUG -Zi +if %debug% set linkopt=-debug -debugtype:cv -pdb:none +if %debug% set crtlib=libcmtd.lib +if %debug% set debugchar=d +if not %debug% set clopt=-DNDEBUG -Ox -GBFry +if not %debug% set crtlib=libcmt.lib +if not %debug% set debugchar= +set mlopt=-Cx +set subsystem=windows +set baselib=%baselib% kernel32.lib user32.lib gdi32.lib advapi32.lib + +// CREATE A TEMPORARY DIRECTORY TO USE FOR PRECOMPILED HEADERS +if not exist %temp%\pch\. md %temp%\pch +if not exist %temp%\pch\%username%\. md %temp%\pch\%username% +set precompileddir=%temp%\pch\%username% + +// SET THE DEFAULT BUILD RULES +set .asm=.obj +set .c =.obj +set .cpp=.obj +set .def=.exp +set .rc =.res +if exist %project%.def set .obj=.dll +if exist %project%.def set deffile=%project%.def +if not exist %project%.def set .obj=.exe +set .asm.obj=ml -nologo -c -coff %mlopt% %file% +set .c.obj =cl -nologo -c -D_X86_ -D_MT -DWIN32 %clopt% -W3 -Fp%precompileddir%\%project%.pch -YX %file% +set .cpp.obj=cl -nologo -c -D_X86_ -D_MT -DWIN32 %clopt% -W3 -Fp%precompileddir%\%project%.pch -YX %file% +set .def.exp=lib -nologo -machine:i386 -def:%deffile% -name:%project%.dll -out:%project%.lib *.obj +set .rc.res =rc -r %rcopt% %file% +set .obj.lib=lib -nologo -machine:i386 -out:%project%.lib *.obj *.res %extralib% +set .obj.dll=link -nologo -machine:i386 -subsystem:%subsystem% %linkopt% -map -dll -out:%project%.dll *.obj *.res %project%.exp %extraobj% -nod %crtlib% %baselib% %extralib% +set .obj.exe=link -nologo -machine:i386 -subsystem:%subsystem% %linkopt% -map -out:%project%.exe *.obj *.res %extraobj% -nod %crtlib% %baselib% %extralib% diff --git a/src/Storm/STORM.DSW b/src/Storm/STORM.DSW new file mode 100644 index 0000000..785a776 --- /dev/null +++ b/src/Storm/STORM.DSW @@ -0,0 +1,17 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/Storm/STORM.NCB b/src/Storm/STORM.NCB new file mode 100644 index 0000000..d948343 Binary files /dev/null and b/src/Storm/STORM.NCB differ diff --git a/src/Storm/STORM.OPT b/src/Storm/STORM.OPT new file mode 100644 index 0000000..7dbba8f Binary files /dev/null and b/src/Storm/STORM.OPT differ diff --git a/src/Storm/STORMDLL.DSP b/src/Storm/STORMDLL.DSP new file mode 100644 index 0000000..27ce4ce --- /dev/null +++ b/src/Storm/STORMDLL.DSP @@ -0,0 +1,270 @@ +# Microsoft Developer Studio Project File - Name="stormdll" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=stormdll - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "stormdll.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "stormdll.mak" CFG="stormdll - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "stormdll - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "stormdll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "stormdll - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "h" /I "smacker\h" /I "pkware\h" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib comdlg32.lib version.lib implode.lib oldnames.lib msvcrtd.lib /nologo /subsystem:windows /dll /machine:I386 /nodefaultlib:"crtdll.lib" /nodefaultlib /libpath:"source" /libpath:"pkware\lib" + +!ELSEIF "$(CFG)" == "stormdll - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /GR /GX /Zi /Od /I "h" /I "smacker\h" /I "pkware\h" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"./debug/" /Fp"./debug/stormdll.pch" /YX /Fo"./debug/" /Fd"./debug/" /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /fo"../windebug/Storm.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /o"../windebug/stormdll.bsc" +# SUBTRACT BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib comdlg32.lib version.lib implode.lib oldnames.lib msvcrtd.lib /nologo /base:"0x15000000" /subsystem:windows /dll /incremental:no /pdb:"../windebug/storm.pdb" /map:"../windebug/storm.map" /debug /machine:I386 /nodefaultlib:"crtdll.lib" /nodefaultlib /def:".\Source\Exports.def" /out:"../windebug/storm.dll" /implib:"../windebug/storm.lib" /pdbtype:sept /libpath:"source" /libpath:"pkware\lib" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "stormdll - Win32 Release" +# Name "stormdll - Win32 Debug" +# Begin Group "source" + +# PROP Default_Filter ".cpp" +# Begin Source File + +SOURCE=.\Source\Exports.def + +!IF "$(CFG)" == "stormdll - Win32 Release" + +!ELSEIF "$(CFG)" == "stormdll - Win32 Debug" + +# PROP Exclude_From_Build 1 + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\Source\Sblt.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Sbmp.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Scmd.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Scode.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Scomp.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Sdlg.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Sdraw.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Serr.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Sevt.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Sfile.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Sgdi.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Slog.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Smem.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\SMsg.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Snet.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Sreg.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Srgn.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Srtl.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Sstr.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Storm.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Storm.rc +# End Source File +# Begin Source File + +SOURCE=.\Source\STrans.cpp +# End Source File +# Begin Source File + +SOURCE=.\Source\Svid.cpp +# End Source File +# End Group +# Begin Group "include" + +# PROP Default_Filter "*.h" +# Begin Source File + +SOURCE=.\Source\Pch.h +# End Source File +# Begin Source File + +SOURCE=.\Source\Resource.h +# End Source File +# Begin Source File + +SOURCE=.\Source\SIntern.h +# End Source File +# End Group +# Begin Group "h" + +# PROP Default_Filter "*.h" +# Begin Source File + +SOURCE=.\H\Bnetart.h +# End Source File +# Begin Source File + +SOURCE=.\H\Storm.h +# End Source File +# End Group +# Begin Group "pkware" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\pkware\Obj\Crc32.obj +# End Source File +# Begin Source File + +SOURCE=.\pkware\Obj\Crcfast.obj +# End Source File +# Begin Source File + +SOURCE=.\pkware\Obj\Crcstd.obj +# End Source File +# Begin Source File + +SOURCE=.\pkware\Obj\Expfast.obj +# End Source File +# Begin Source File + +SOURCE=.\pkware\Obj\Explode.obj +# End Source File +# Begin Source File + +SOURCE=.\pkware\Obj\Expstd.obj +# End Source File +# Begin Source File + +SOURCE=.\pkware\Obj\Impfast.obj +# End Source File +# Begin Source File + +SOURCE=.\pkware\Obj\Implode.obj +# End Source File +# Begin Source File + +SOURCE=.\pkware\Obj\Impstd.obj +# End Source File +# End Group +# End Target +# End Project diff --git a/src/Storm/STORMDLL.DSW b/src/Storm/STORMDLL.DSW new file mode 100644 index 0000000..a1f89cf --- /dev/null +++ b/src/Storm/STORMDLL.DSW @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "stormdll"=.\stormdll.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/Storm/STORMDLL.NCB b/src/Storm/STORMDLL.NCB new file mode 100644 index 0000000..5f1bede Binary files /dev/null and b/src/Storm/STORMDLL.NCB differ diff --git a/src/Storm/STORMDLL.OPT b/src/Storm/STORMDLL.OPT new file mode 100644 index 0000000..c1ca1e7 Binary files /dev/null and b/src/Storm/STORMDLL.OPT differ diff --git a/src/Storm/TESTAPP.DSP b/src/Storm/TESTAPP.DSP new file mode 100644 index 0000000..0d0e475 --- /dev/null +++ b/src/Storm/TESTAPP.DSP @@ -0,0 +1,88 @@ +# Microsoft Developer Studio Project File - Name="testapp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=testapp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testapp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testapp.mak" CFG="testapp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testapp - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "testapp - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "testapp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "testapp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "testapp_" +# PROP BASE Intermediate_Dir "testapp_" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "testapp_" +# PROP Intermediate_Dir "testapp_" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "testapp - Win32 Release" +# Name "testapp - Win32 Debug" +# End Target +# End Project diff --git a/src/Storm/TESTAPP_/TESTAPP.PCH b/src/Storm/TESTAPP_/TESTAPP.PCH new file mode 100644 index 0000000..8047c7d Binary files /dev/null and b/src/Storm/TESTAPP_/TESTAPP.PCH differ diff --git a/src/Storm/TESTAPP_/VC50.IDB b/src/Storm/TESTAPP_/VC50.IDB new file mode 100644 index 0000000..1647f6c Binary files /dev/null and b/src/Storm/TESTAPP_/VC50.IDB differ diff --git a/src/Storm/UPDATE.BAT b/src/Storm/UPDATE.BAT new file mode 100644 index 0000000..6e7d727 --- /dev/null +++ b/src/Storm/UPDATE.BAT @@ -0,0 +1,13 @@ +@echo off +copy o:\h\*.h p:\dev\h\ /v +del o:\source\*.exp +c /ads o:\source\battle\battle.cs +c /aos o:\source\battle\battle.cs +c /ads o:\source\standard\standard.cs +c /aos o:\source\standard\standard.cs +c /aos o:\source\stormst.cs +c /ads o:\source\storm.cs +c /aos o:\source\storm.cs +ss checkin -i- -k -r $/Storm +copy o:\lib\*.lib p:\dev\lib\ /v +copy o:\lib\*.res p:\dev\lib\ /v diff --git a/src/Storm/VC50.PCH b/src/Storm/VC50.PCH new file mode 100644 index 0000000..ba1a064 Binary files /dev/null and b/src/Storm/VC50.PCH differ diff --git a/src/TEXTDAT.CPP b/src/TEXTDAT.CPP new file mode 100644 index 0000000..eb27594 --- /dev/null +++ b/src/TEXTDAT.CPP @@ -0,0 +1,2243 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Miniquest Text file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "minitext.h" +#include "textdat.h" +#include "effects.h" + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Skeleton King Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char King1[] = " Ahh, the story of our King, is it? The tragic fall of " +"Leoric was a harsh blow to this land. The people always loved the King, " +"and now they live in mortal fear of him. The question that I keep asking " +"myself is how he could have fallen so far from the Light, as Leoric had " +"always been the holiest of men. Only the vilest powers of Hell could so " +"utterly destroy a man from within... |"; + +//quest init +static char King2[] = "The village needs your help, good master! Some months " +"ago King Leoric's son, Prince Albrecht, was kidnapped. The King went into " +"a rage and scoured the village for his missing child. With each passing " +"day, Leoric seemed to slip deeper into madness. He sought to blame " +"innocent townsfolk for the boy's disappearance and had them brutally " +"executed. Less than half of us survived his insanity...\n \n" +"The King's Knights and Priests tried to placate him, but he turned " +"against them and sadly, they were forced to kill him. With his dying " +"breath the King called down a terrible curse upon his former followers. " +"He vowed that they would serve him in darkness forever...\n \n" +"This is where things take an even darker twist than I thought possible! " +"Our former King has risen from his eternal sleep and now commands a legion " +"of undead minions within the Labyrinth. His body was buried in a tomb " +"three levels beneath the Cathedral. Please, good master, put his soul " +"at ease by destroying his now cursed form... |"; + +//If the hero returns before completing the quest +static char King3[] = "As I told you, good master, the King was entombed " +"three levels below. He's down there, waiting in the putrid darkness " +"for his chance to destroy this land... |"; + +//If the hero returns after completing the quest +static char King4[] = "The curse of our King has passed, but I fear that it " +"was only part of a greater evil at work. However, we may yet be saved " +"from the darkness that consumes our land, for your victory is a good " +"omen. May Light guide you on your way, good master. |"; + +static char King5[] = "The loss of his son was too much for King Leoric. I " +"did what I could to ease his madness, but in the end it overcame him. " +"A black curse has hung over this kingdom from that day forward, but " +"perhaps if you were to free his spirit from his earthly prison, the " +"curse would be lifted... |"; + +static char King6[] = "I don't like to think about how the King died. I " +"like to remember him for the kind and just ruler that he was. His death " +"was so sad and seemed very wrong, somehow. |"; + +static char King7[] = "I made many of the weapons and most of the armor " +"that King Leoric used to outfit his knights. I even crafted a huge " +"two-handed sword of the finest mithril for him, as well as a field " +"crown to match. I still cannot believe how he died, but it must have " +"been some sinister force that drove him insane! |"; + +static char King8[] = "I don't care about that. Listen, no skeleton is gonna " +"be MY king. Leoric is King. King, so you hear me? HAIL TO THE KING! |"; + +static char King9[] = "The dead who walk among the living follow the cursed " +"King. He holds the power to raise yet more warriors for an ever growing " +"army of the undead. If you do not stop his reign, he will surely march " +"across this land and slay all who still live here. |"; + +static char King10[] = "Look, I'm running a business here. I don't sell " +"information, and I don't care about some King that's been dead longer " +"than I've been alive. If you need something to use against this King " +"of the undead, then I can help you out... |"; + +//When the hero enters the Skeleton King Chamber +static char King11[] = "The warmth of life has entered my tomb. Prepare " +"yourself, mortal, to serve my Master for eternity! |"; +#endif + +/*-----------------------------------------------------------------------** +** Banner of Light Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Banner1[] = "I see that this strange behavior puzzles you as " +"well. I would surmise that since many demons fear the light of the sun " +"and believe that it holds great power, it may be that the rising sun " +"depicted on the sign you speak of has led them to believe that it too holds " +"some arcane powers. Hmm, perhaps they are not all as smart as we had " +"feared... |"; + +//quest init +static char Banner2[] = "Master, I have a strange experience to relate. " +"I know that you have a great knowledge of those monstrosities that " +"inhabit the labyrinth, and this is something that I cannot understand " +"for the very life of me... " +"I was awakened during the night by a scraping sound just outside of " +"my tavern. When I looked out from my bedroom, I saw the shapes of " +"small demon-like creatures in the inn yard. After a short time, " +"they ran off, but not before stealing the sign to my inn. I don't " +"know why the demons would steal my sign but leave my family " +"in peace... 'tis strange, no? |"; + +//If hero returns the sign to the tavern +static char Banner3[] = "Oh, you didn't have to bring back my sign, but I " +"suppose that it does save me the expense of having another one made. Well, let me see, " +"what could I give you as a fee for finding it? Hmmm, what have we " +"here... ah, yes! This cap was left in one of the rooms by a magician " +"who stayed here some time ago. Perhaps it may be of some value to you. |"; + +static char Banner4[] = "My goodness, demons running about the village at " +"night, pillaging our homes - is nothing sacred? I hope that Ogden and " +"Garda are all right. I suppose that they would come to see me if they " +"were hurt... |"; + +static char Banner5[] = "Oh my! Is that where the sign went? My " +"Grandmother and I must have slept right through the whole thing. Thank " +"the Light that those monsters didn't attack the inn. |"; + +static char Banner6[] = "Demons stole Ogden's sign, you say? That doesn't " +"sound much like the atrocities I've heard of - or seen. \n \n" +"Demons are " +"concerned with ripping out your heart, not your signpost. |"; + +static char Banner7[] = "You know what I think? Somebody took that sign, " +"and they gonna want lots of money for it. If I was Ogden... and I'm not, " +"but if I was... I'd just buy a new sign with some pretty drawing on it. " +"Maybe a nice mug of ale or a piece of cheese... |"; + +static char Banner8[] = "No mortal can truly understand the mind of the demon. \n \n" +"Never let their erratic actions confuse you, as that too may be their " +"plan. |"; + +static char Banner9[] = "What - is he saying I took that? I suppose that " +"Griswold is on his side, too. \n \n" +"Look, I got over simple sign stealing " +"months ago. You can't turn a profit on a piece of wood. |"; + +//Within the labyrinth +static char Banner10[] = "Hey - You that one that kill all! You get me " +"Magic Banner or we attack! You no leave with life! You kill big uglies " +"and give back Magic. Go past corner and door, find uglies. You give, " +"you go! |"; + +//If hero returns empty-handed +static char Banner11[] = "You kill uglies, get banner. You bring to me, " +"or else... |"; + +//If hero returns with sign +static char Banner12[] = "You give! Yes, good! Go now, we strong. We kill " +"all with big Magic! |"; +#endif + +/*-----------------------------------------------------------------------** +** Vile Betrayer Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +// quest init +static char Vile1[] = "This does not bode well, for it confirms my " +"darkest fears. While I did not allow myself to believe the ancient " +"legends, I cannot deny them now. Perhaps the time has come to reveal " +"who I am.\n \n" +"My true name is Deckard Cain the Elder, and I am the last descendant " +"of an ancient Brotherhood that was dedicated to safeguarding the secrets " +"of a timeless evil. An evil that quite obviously has now been released.\n \n" +"The Archbishop Lazarus, once King Leoric's most trusted advisor, led a " +"party of simple townsfolk into the Labyrinth to find the King's missing " +"son, Albrecht. Quite some time passed before they returned, and only a " +"few of them escaped with their lives.\n \n" +"Curse me for a fool! I should have suspected his veiled treachery then. " +"It must have been Lazarus himself who kidnapped Albrecht and has since " +"hidden him within the Labyrinth. I do not understand why the Archbishop " +"turned to the darkness, or what his interest is in the child, unless he " +"means to sacrifice him to his dark masters!\n \n" +"That must be what he has planned! The survivors of his 'rescue party' " +"say that Lazarus was last seen running into the deepest bowels of the " +"labyrinth. You must hurry and save the prince from the sacrificial blade " +"of this demented fiend! |"; + +// quest not done +static char Vile2[] = "You must hurry and rescue Albrecht from the hands " +"of Lazarus. The prince and the people of this kingdom are counting on you! |"; + +// quest done +static char Vile3[] = "Your story is quite grim, my friend. Lazarus will " +"surely burn in Hell for his horrific deed. The boy that you describe is " +"not our prince, but I believe that Albrecht may yet be in danger. The " +"symbol of power that you speak of must be a portal in the very heart of " +"the labyrinth.\n \n" +"Know this, my friend - The evil that you move against is the dark Lord " +"of Terror. He is known to mortal men as Diablo. It was he who was " +"imprisoned within the Labyrinth many centuries ago and I fear that he " +"seeks to once again sow chaos in the realm of mankind. You must venture " +"through the portal and destroy Diablo before it is too late! |"; + +static char Vile4[] = "Lazarus was the Archbishop who led many of the " +"townspeople into the labyrinth. I lost many good friends that day, " +"and Lazarus never returned. I suppose he was killed along with most " +"of the others. If you would do me a favor, good master - please do " +"not talk to Farnham about that day. |"; + +static char Vile5[] = "|"; + +static char Vile6[] = "|"; + +static char Vile7[] = "I was shocked when I heard of what the townspeople " +"were planning to do that night. I thought that of all people, Lazarus " +"would have had more sense than that. He was an Archbishop, and always " +"seemed to care so much for the townsfolk of Tristram. So many were " +"injured, I could not save them all... |"; + +static char Vile8[] = "I remember Lazarus as being a very kind and giving " +"man. He spoke at my mother's funeral, and was supportive of my " +"grandmother and myself in a very troubled time. I pray every night " +"that somehow, he is still alive and safe. |"; + +static char Vile9[] = "I was there when Lazarus led us into the labyrinth. " +"He spoke of holy retribution, but when we started fighting those " +"hellspawn, he did not so much as lift his mace against them. He just " +"ran deeper into the dim, endless chambers that were filled with the " +"servants of darkness! |"; + +static char Vile10[] = "They stab, then bite, then they're all around you. " +"Liar! LIAR! They're all dead! Dead! Do you hear me? They just keep " +"falling and falling... their blood spilling out all over the floor... " +"all his fault... |"; + +static char Vile11[] = "I did not know this Lazarus of whom you speak, but " +"I do sense a great conflict within his being. He poses a great danger, " +"and will stop at nothing to serve the powers of darkness which have " +"claimed him as theirs. |"; + +static char Vile12[] = "Yes, the righteous Lazarus, who was sooo effective " +"against those monsters down there. Didn't help save my leg, did it? " +"Look, I'll give you a free piece of advice. Ask Farnham, he was there. |"; + +//If the hero meets Lazarus after the sacrifice +static char Vile13[] = "Abandon your foolish quest. All that awaits you " +"is the wrath of my Master! You are too late to save the child. Now you will " +"join him in Hell! |"; + +//deleted +static char Vile14[] = " |"; +#endif + +/*-----------------------------------------------------------------------** +** Poisoned Water Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Poison1[] = "Hmm, I don't know what I can really tell you about " +"this that will be of any help. The water that fills our wells comes " +"from an underground spring. I have heard of a tunnel that leads to a " +"great lake - perhaps they are one and the same. Unfortunately, I do not " +"know what would cause our water supply to be tainted. |"; + +static char Poison2[] = "I have always tried to keep a large supply of " +"foodstuffs and drink in our storage cellar, but with the entire town " +"having no source of fresh water, even our stores will soon run dry. \n \n" +"Please, do what you can or I don't know what we will do. |"; + +static char Poison3[] = "I'm glad I caught up to you in time! Our wells " +"have become brackish and stagnant and some of the townspeople have " +"become ill drinking from them. Our reserves of fresh water are " +"quickly running dry. I believe that there is a passage that leads to " +"the springs that serve our town. Please find what has caused this " +"calamity, or we all will surely perish. |"; + +//If the hero returns before completing the quest +static char Poison4[] = "Please, you must hurry. Every hour that passes " +"brings us closer to having no water to drink. \n \n" +"We cannot survive for " +"long without your help. |"; + +//If the hero completes the quest +static char Poison5[] = "What's that you say - the mere presence of the " +"demons had caused the water to become tainted? Oh, truly a great evil " +"lurks beneath our town, but your perseverance and courage gives us " +"hope. Please take this ring - perhaps it will aid you in the " +"destruction of such vile creatures. |"; + +static char Poison6[] = "My grandmother is very weak, and Garda says " +"that we cannot drink the water from the wells. Please, can you do something " +"to help us? |"; + +static char Poison7[] = "Pepin has told you the truth. We will need fresh " +"water badly, and soon. I have tried to clear one of the smaller wells, " +"but it reeks of stagnant filth. It must be getting clogged at the source. |"; + +static char Poison8[] = "You drink water? |"; + +static char Poison9[] = "The people of Tristram will die if you cannot " +"restore fresh water to their wells. \n \n" +"Know this - demons are at the heart " +"of this matter, but they remain ignorant of what they have spawned. |"; + +static char Poison10[] = "For once, I'm with you. My business runs dry - so " +"to speak - if I have no market to sell to. You better find out what is " +"going on, and soon! |"; +#endif + +/*-----------------------------------------------------------------------** +** The Chamber of Bone Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Bone1[] = "A book that speaks of a chamber of human bones? Well, " +"a Chamber of Bone is mentioned in certain archaic writings that I " +"studied in the libraries of the East. These tomes inferred that when " +"the Lords of the underworld desired to protect great treasures, they " +"would create domains where those who died in the attempt to steal that " +"treasure would be forever bound to defend it. A twisted, but strangely " +"fitting, end? |"; + +static char Bone2[] = "I am afraid that I don't know anything about that, " +"good master. Cain has many books that may be of some help. |"; + +static char Bone3[] = "This sounds like a very dangerous place. If you " +"venture there, please take great care. |"; + +static char Bone4[] = "I am afraid that I haven't heard anything about " +"that. Perhaps Cain the Storyteller could be of some help. |"; + +static char Bone5[] = "I know nothing of this place, but you may try " +"asking Cain. He talks about many things, and it would not surprise " +"me if he had some answers to your question. |"; + +static char Bone6[] = "Okay, so listen. There's this chamber of wood, " +"see. And his wife, you know - her - tells the tree... cause you gotta " +"wait. Then I says, that might work against him, but if you think I'm " +"gonna PAY for this... you... uh... yeah. |"; + +static char Bone7[] = "You will become an eternal servant of the dark " +"lords should you perish within this cursed domain. \n \n" +"Enter the Chamber " +"of Bone at your own peril. |"; + +static char Bone8[] = "A vast and mysterious treasure, you say? Maybe I " +"could be interested in picking up a few things from you... or better " +"yet, don't you need some rare and expensive supplies to get you through " +"this ordeal? |"; +#endif + +/*-----------------------------------------------------------------------** +** The Butcher Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Butch1[] = "It seems that the Archbishop Lazarus goaded many " +"of the townsmen into venturing into the Labyrinth to find the King's " +"missing son. He played upon their fears and whipped them into a " +"frenzied mob. None of them were prepared for what lay within the cold " +"earth... Lazarus abandoned them down there - left in the clutches of " +"unspeakable horrors - to die. |"; + +static char Butch2[] = "Yes, Farnham has mumbled something about a hulking " +"brute who wielded a fierce weapon. I believe he called him a butcher. |"; + +static char Butch3[] = "By the Light, I know of this vile demon. There were " +"many that bore the scars of his wrath upon their bodies when the few " +"survivors of the charge led by Lazarus crawled from the Cathedral. I " +"don't know what he used to slice open his victims, but it could not " +"have been of this world. It left wounds festering with disease and " +"even I found them almost impossible to treat. Beware if you plan to " +"battle this fiend... |"; + +static char Butch4[] = "When Farnham said something about a butcher killing " +"people, I immediately discounted it. But since you brought it up, maybe " +"it is true. |"; + +static char Butch5[] = "I saw what Farnham calls the Butcher as it swathed " +"a path through the bodies of my friends. He swung a cleaver as large " +"as an axe, hewing limbs and cutting down brave men where they stood. I " +"was separated from the fray by a host of small screeching demons and " +"somehow found the stairway leading out. I never saw that hideous beast " +"again, but his blood-stained visage haunts me to this day. |"; + +static char Butch6[] = "Big! Big cleaver killing all my friends. Couldn't " +"stop him, had to run away, couldn't save them. Trapped in a room with " +"so many bodies... so many friends... NOOOOOOOOOO! |"; + +static char Butch7[] = "The Butcher is a sadistic creature that delights " +"in the torture and pain of others. You have seen his handiwork in the " +"drunkard Farnham. His destruction will do much to ensure the safety of " +"this village. |"; + +static char Butch8[] = "I know more than you'd think about that grisly " +"fiend. His little friends got a hold of me and managed to get my leg " +"before Griswold pulled me out of that hole. \n \n" +"I'll put it bluntly - " +"kill him before he kills you and adds your corpse to his collection. |"; + +//wounded townsman +static char Butch9[] = "Please, listen to me. The Archbishop " +"Lazarus, he led us down here to find the lost prince. The bastard " +"led us into a trap! Now everyone is dead... killed by a demon he " +"called the Butcher. Avenge us! Find this Butcher and slay him so " +"that our souls may finally rest... |"; + +//butcher +static char Butch10[] = " |"; +#endif + +/*-----------------------------------------------------------------------** +** Halls of the Blind Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Blind1[] = "You recite an interesting rhyme written in a style " +"that reminds me of other works. Let me think now - what was it?\n \n" +"...Darkness shrouds the Hidden. Eyes glowing unseen with only the " +"sounds of razor claws briefly scraping to torment those poor souls who " +"have been made sightless for all eternity. The prison for those so " +"damned is named the Halls of the Blind... |"; + +static char Blind2[] = "I never much cared for poetry. Occasionally, I had " +"cause to hire minstrels when the inn was doing well, but that seems " +"like such a long time ago now. \n \n" +"What? Oh, yes... uh, well, I suppose you " +"could see what someone else knows. |"; + +static char Blind3[] = "This does seem familiar, somehow. I seem to recall " +"reading something very much like that poem while researching the " +"history of demonic afflictions. It spoke of a place of great evil " +"that... wait - you're not going there are you? |"; + +static char Blind4[] = "If you have questions about blindness, you should " +"talk to Pepin. I know that he gave my grandmother a potion that helped " +"clear her vision, so maybe he can help you, too. |"; + +static char Blind5[] = "I am afraid that I have neither heard nor seen a " +"place that matches your vivid description, my friend. Perhaps Cain " +"the Storyteller could be of some help. |"; + +static char Blind6[] = "Look here... that's pretty funny, huh? " +"Get it? Blind - look here? |"; + +static char Blind7[] = "This is a place of great anguish and terror, and " +"so serves its master well. \n \n" +"Tread carefully or you may yourself " +"be staying much longer than you had anticipated. |"; + +static char Blind8[] = "Lets see, am I selling you something? No. Are you " +"giving me money to tell you about this? No. Are you now leaving and " +"going to talk to the storyteller who lives for this kind of thing? " +"Yes. |"; +#endif + +/*-----------------------------------------------------------------------** +** Veil of Steel Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Veil1[] = "You claim to have spoken with Lachdanan? He was a " +"great hero during his life. Lachdanan was an honorable and just man " +"who served his King faithfully for years. But of course, you already " +"know that.\n \n" +"Of those who were caught within the grasp of the King's " +"Curse, Lachdanan would be the least likely to submit to the darkness " +"without a fight, so I suppose that your story could be true. If I were " +"in your place, my friend, I would find a way to release him from his " +"torture. |"; + +static char Veil2[] = "You speak of a brave warrior long dead! I'll have " +"no such talk of speaking with departed souls in my inn yard, thank you " +"very much. |"; + +static char Veil3[] = "A golden elixir, you say. I have never concocted a " +"potion of that color before, so I can't tell you how it would effect " +"you if you were to try to drink it. As your healer, I strongly advise " +"that should you find such an elixir, do as Lachdanan asks and " +"DO NOT try to use it. |"; + +static char Veil4[] = "I've never heard of a Lachdanan before. I'm sorry, but " +"I don't think that I can be of much help to you. |"; + +static char Veil5[] = "If it is actually Lachdanan that you have met, then " +"I would advise that you aid him. I dealt with him on several occasions " +"and found him to be honest and loyal in nature. The curse that fell " +"upon the followers of King Leoric would fall especially hard upon him. |"; + +static char Veil6[] = " Lachdanan is dead. Everybody knows that, and you " +"can't fool me into thinking any other way. You can't talk to the dead. " +"I know! |"; + +static char Veil7[] = "You may meet people who are trapped within the " +"Labyrinth, such as Lachdanan. \n \n" +"I sense in him honor and great guilt. " +"Aid him, and you aid all of Tristram. |"; + +static char Veil8[] = "Wait, let me guess. Cain was swallowed up in a " +"gigantic fissure that opened beneath him. He was incinerated in a ball " +"of hellfire, and can't answer your questions anymore. Oh, that isn't " +"what happened? Then I guess you'll be buying something or you'll be " +"on your way. |"; + +//upon meeting the captain +static char Veil9[] = "Please, don't kill me, just hear me out. I was once " +"Captain of King Leoric's Knights, upholding the laws of this land with " +"justice and honor. Then his dark Curse fell upon us for the role we " +"played in his tragic death. As my fellow Knights succumbed to their " +"twisted fate, I fled from the King's burial chamber, searching for " +"some way to free myself from the Curse. I failed...\n \n" +"I have heard of a Golden Elixir that could lift the Curse and allow " +"my soul to rest, but I have been unable to find it. My strength now " +"wanes, and with it the last of my humanity as well. Please aid me and " +"find the Elixir. I will repay your efforts - I swear upon my honor. |"; + +//If the hero returns without the Elixir +static char Veil10[] = "You have not found the Golden Elixir. I fear that " +"I am doomed for eternity. Please, keep trying... |"; + +//If the hero returns with the Elixir +static char Veil11[] = "You have saved my soul from damnation, and for " +"that I am in your debt. If there is ever a way that I can repay you " +"from beyond the grave I will find it, but for now - take my helm. On " +"the journey I am about to take I will have little use for it. May it " +"protect you against the dark powers below. Go with the Light, my " +"friend... |"; +#endif + +/*-----------------------------------------------------------------------** +** The Anvil of Fury Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Anvil1[] = "Griswold speaks of The Anvil of Fury - a legendary " +"artifact long searched for, but never found. Crafted from the metallic " +"bones of the Razor Pit demons, the Anvil of Fury was smelt around the " +"skulls of the five most powerful magi of the underworld. Carved with " +"runes of power and chaos, any weapon or armor forged upon this Anvil " +"will be immersed into the realm of Chaos, imbedding it with magical " +"properties. It is said that the unpredictable nature of Chaos makes " +"it difficult to know what the outcome of this smithing will be... |"; + +static char Anvil2[] = "Don't you think that Griswold would be a better " +"person to ask about this? He's quite handy, you know. |"; + +static char Anvil3[] = "If you had been looking for information on the " +"Pestle of Curing or the Silver Chalice of Purification, I could have " +"assisted you, my friend. However, in this matter, you would be better " +"served to speak to either Griswold or Cain. |"; + +static char Anvil4[] = "Griswold's father used to tell some of us when we " +"were growing up about a giant anvil that was used to make mighty " +"weapons. He said that when a hammer was struck upon this anvil, the " +"ground would shake with a great fury. Whenever the earth moves, I " +"always remember that story. |"; + +static char Anvil5[] = "Greetings! It's always a pleasure to see one of " +"my best customers! I know that you have been venturing deeper into " +"the Labyrinth, and there is a story I was told that you may find worth " +"the time to listen to...\n \n" +"One of the men who returned from the Labyrinth told me about a mystic " +"anvil that he came across during his escape. His description reminded " +"me of legends I had heard in my youth about the burning Hellforge where " +"powerful weapons of magic are crafted. The legend had it that deep " +"within the Hellforge rested the Anvil of Fury! This Anvil contained " +"within it the very essence of the demonic underworld...\n \n" +"It is said that any weapon crafted upon the burning Anvil is imbued " +"with great power. If this anvil is indeed the Anvil of Fury, I may " +"be able to make you a weapon capable of defeating even the darkest " +"lord of Hell! \n \n" +"Find the Anvil for me, and I'll get to work! |"; + +//If the hero returns without the Anvil +static char Anvil6[] = "Nothing yet, eh? Well, keep searching. A weapon " +"forged upon the Anvil could be your best hope, and I am sure that I " +"can make you one of legendary proportions. |"; + +//If the hero returns with the Anvil +static char Anvil7[] = "I can hardly believe it! This is the Anvil of Fury " +"- good work, my friend. Now we'll show those bastards that there are " +"no weapons in Hell more deadly than those made by men! Take this and " +"may Light protect you. |"; + +static char Anvil8[] = "Griswold can't sell his anvil. What will he do " +"then? And I'd be angry too if someone took my anvil! |"; + +static char Anvil9[] = "There are many artifacts within the Labyrinth " +"that hold powers beyond the comprehension of mortals. Some of these " +"hold fantastic power that can be used by either the Light or the " +"Darkness. Securing the Anvil from below could shift the course of " +"the Sin War towards the Light. |"; + +static char Anvil10[] = "If you were to find this artifact for Griswold, " +"it could put a serious damper on my business here. Awwww, you'll never " +"find it. |"; +#endif + +/*-----------------------------------------------------------------------** +** Stones of Blood Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Blood1[] = "The Gateway of Blood and the Halls of Fire are " +"landmarks of mystic origin. Wherever this book you read from resides it is " +"surely a place of great power.\n \n" +"Legends speak of a pedestal that is carved from obsidian stone and " +"has a pool of boiling blood atop its bone encrusted surface. There " +"are also allusions to Stones of Blood that will open a door that " +"guards an ancient treasure...\n \n" +"The nature of this treasure is shrouded in speculation, my friend, " +"but it is said that the ancient hero Arkaine placed the holy armor " +"Valor in a secret vault. Arkaine was the first mortal to turn the " +"tide of the Sin War and chase the legions of darkness back to the " +"Burning Hells.\n \n" +"Just before Arkaine died, his armor was hidden away " +"in a secret vault. It is said that when this holy armor is again " +"needed, a hero will arise to don Valor once more. Perhaps you are " +"that hero... |"; + +static char Blood2[] = "Every child hears the story of the warrior Arkaine " +"and his mystic armor known as Valor. If you could find its resting " +"place, you would be well protected against the evil in the " +"Labyrinth. |"; + +static char Blood3[] = "Hmm... it sounds like something I should remember, " +"but I've been so busy learning new cures and creating better elixirs " +"that I must have forgotten. Sorry... |"; + +static char Blood4[] = "The story of the magic armor called Valor is " +"something I often heard the boys talk about. You had better ask one " +"of the men in the village. |"; + +static char Blood5[] = "The armor known as Valor could be what tips the " +"scales in your favor. I will tell you that many have looked for it - " +"including myself. Arkaine hid it well, my friend, and it will take " +"more than a bit of luck to unlock the secrets that have kept it " +"concealed oh, lo these many years. |"; + +static char Blood6[] = "Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz... |"; + +static char Blood7[] = "Should you find these Stones of Blood, use them " +"carefully. \n \n" +"The way is fraught with danger and your only hope rests " +"within your self trust. |"; + +static char Blood8[] = "You intend to find the armor known as Valor? \n \n" +"No " +"one has ever figured out where Arkaine stashed the stuff, and if my " +"contacts couldn't find it, I seriously doubt you ever will either. |"; +#endif + +/*-----------------------------------------------------------------------** +** Warlord of Blood Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Warlrd1[] = "I know of only one legend that speaks of such a " +"warrior as you describe. His story is found within the ancient " +"chronicles of the Sin War...\n \n" +"Stained by a thousand years of war, blood and death, the Warlord of " +"Blood stands upon a mountain of his tattered victims. His dark blade " +"screams a black curse to the living; a tortured invitation to any who " +"would stand before this Executioner of Hell.\n \n" +"It is also written that " +"although he was once a mortal who fought beside the Legion of Darkness " +"during the Sin War, he lost his humanity to his insatiable hunger for " +"blood. |"; + +static char Warlrd2[] = "I am afraid that I haven't heard anything about " +"such a vicious warrior, good master. I hope that you do not have to fight " +"him, for he sounds extremely dangerous. |"; + +static char Warlrd3[] = "Cain would be able to tell you much more about " +"something like this than I would ever wish to know. |"; + +static char Warlrd4[] = "If you are to battle such a fierce opponent, may " +"Light be your guide and your defender. I will keep you in my thoughts. |"; + +static char Warlrd5[] = "Dark and wicked legends surrounds the one Warlord " +"of Blood. Be well prepared, my friend, for he shows no mercy or quarter. |"; + +static char Warlrd6[] = "Always you gotta talk about Blood? What about " +"flowers, and sunshine, and that pretty girl that brings the drinks. " +"Listen here, friend - you're obsessive, you know that? |"; + +static char Warlrd7[] = "His prowess with the blade is awesome, and he " +"has lived for thousands of years knowing only warfare. I am sorry... " +"I can not see if you will defeat him. |"; + +static char Warlrd8[] = "I haven't ever dealt with this Warlord you speak " +"of, but he sounds like he's going through a lot of swords. Wouldn't mind " +"supplying his armies... |"; + +static char Warlrd9[] = "My blade sings for your blood, mortal, and by my " +"dark masters it shall not be denied. |"; +#endif + +/*-----------------------------------------------------------------------** +** Ring of Infravision Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Infra1[] = "Griswold speaks of the Heaven Stone that was " +"destined for the enclave located in the east. It was being taken " +"there for further study. This stone glowed with an energy that " +"somehow granted vision beyond that which a normal man could possess. " +"I do not know what secrets it holds, my friend, but finding this " +"stone would certainly prove most valuable. |"; + +static char Infra2[] = "The caravan stopped here to take on some supplies " +"for their journey to the east. I sold them quite an array of fresh " +"fruits and some excellent sweetbreads that Garda has just finished " +"baking. Shame what happened to them... |"; + +static char Infra3[] = "I don't know what it is that they thought they " +"could see with that rock, but I will say this. If rocks are falling " +"from the sky, you had better be careful! |"; + +static char Infra4[] = "Well, a caravan of some very important people did " +"stop here, but that was quite a while ago. They had strange accents " +"and were starting on a long journey, as I recall. \n \n" +"I don't see how you " +"could hope to find anything that they would have been carrying. |"; + +static char Infra5[] = "Stay for a moment - I have a story you might find " +"interesting. A caravan that was bound for the eastern kingdoms passed " +"through here some time ago. It was supposedly carrying a piece of the " +"heavens that had fallen to earth! The caravan was ambushed by cloaked " +"riders just north of here along the roadway. I searched the wreckage " +"for this sky rock, but it was nowhere to be found. If you should find " +"it, I believe that I can fashion something useful from it. |"; + +//If the hero returns before completing the quest +static char Infra6[] = "I am still waiting for you to bring me that stone " +"from the heavens. I know that I can make something powerful out of it. |"; + +//If the hero returns before completing the quest +static char Infra7[] = "Let me see that - aye... aye, it is as I believed. Give me " +"a moment...\n \n" +"Ah, Here you are. I arranged pieces of the stone within a silver ring " +"that my father left me. I hope it serves you well. |"; + +static char Infra8[] = "I used to have a nice ring; it was a really " +"expensive one, with blue and green and red and silver. Don't remember " +"what happened to it, though. I really miss that ring... |"; + +static char Infra9[] = "The Heaven Stone is very powerful, and were it " +"any but Griswold who bid you find it, I would prevent it. He will " +"harness its powers and its use will be for the good of us all. |"; + +static char Infra10[] = "If anyone can make something out of that rock, " +"Griswold can. He knows what he is doing, and as much as I try to " +"steal his customers, I respect the quality of his work. |"; +#endif + +/*-----------------------------------------------------------------------** +** Black Mushroom Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Mush1[] = "The witch Adria seeks a black mushroom? I know as " +"much about Black Mushrooms as I do about Red Herrings. Perhaps " +"Pepin the Healer could tell you more, but this is something that " +"cannot be found in any of my stories or books. |"; + +//Tavern guy +static char Mush2[] = "Let me just say this. Both Garda and I would never, " +"EVER serve black mushrooms to our honored guests. If Adria wants some " +"mushrooms in her stew, then that is her business, but I can't help you " +"find any. Black mushrooms... disgusting! |"; + +//If the hero goes to the healer without the brain +static char Mush3[] = "The witch told me that you were searching for the " +"brain of a demon to assist me in creating my elixir. It should be of " +"great value to the many who are injured by those foul beasts, if I can " +"just unlock the secrets I suspect that its alchemy holds. If you can " +"remove the brain of a demon when you kill it, I would be grateful if " +"you could bring it to me. |"; + +//If the hero brings a brain to the healer +static char Mush4[] = "Excellent, this is just what I had in mind. I was " +"able to finish the elixir without this, but it can't hurt to have this " +"to study. Would you please carry this to the witch? I believe that she " +"is expecting it. |"; + +static char Mush5[] = "I think Ogden might have some mushrooms in the " +"storage cellar. Why don't you ask him? |"; + +static char Mush6[] = "If Adria doesn't have one of these, you can bet " +"that's a rare thing indeed. I can offer you no more help than that, " +"but it sounds like... a huge, gargantuan, swollen, bloated mushroom! " +"Well, good hunting, I suppose. |"; + +static char Mush7[] = "Ogden mixes a MEAN black mushroom, but I get sick " +"if I drink that. Listen, listen... here's the secret - moderation is " +"the key! |"; + +//If hero brings the Fungal Tome to the Witch +static char Mush8[] = "What do we have here? Interesting, it looks like a " +"book of reagents. Keep your eyes open for a black mushroom. It should " +"be fairly large and easy to identify. If you find it, bring it to me, " +"won't you? |"; + +//If hero returns without the mushroom +static char Mush9[] = "It's a big, black mushroom that I need. Now run off " +"and get it for me so that I can use it for a special concoction that " +"I am working on. |"; + +//If hero brings the mushroom to the witch +static char Mush10[] = "Yes, this will be perfect for a brew that I am " +"creating. By the way, the healer is looking for the brain of some " +"demon or another so he can treat those who have been afflicted by " +"their poisonous venom. I believe that he intends to make an elixir " +"from it. If you help him find what he needs, please see if you can " +"get a sample of the elixir for me. |"; + +//If hero brings the brain to the witch +static char Mush11[] = "Why have you brought that here? I have no need " +"for a demon's brain at this time. I do need some of the elixir that " +"the Healer is working on. He needs that grotesque organ that you " +"are holding, and then bring me the elixir. Simple when you think about " +"it, isn't it? |"; + +//If the hero takes the elixir to the witch +static char Mush12[] = "What? Now you bring me that elixir from the healer? " +"I was able to finish my brew without it. Why don't you just keep it... |"; + +static char Mush13[] = "I don't have any mushrooms of any size or color " +"for sale. How about something a bit more useful? |"; +#endif + +/*-----------------------------------------------------------------------** +** Map of Doom Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Doom1[] = "So, the legend of the Map is real. Even I never " +"truly believed any of it! I suppose it is time that I told you the " +"truth about who I am, my friend. You see, I am not all that I seem...\n \n" +"My true name is Deckard Cain the Elder, and I am the last descendant " +"of an ancient Brotherhood that was dedicated to keeping and safeguarding " +"the secrets of a timeless evil. An evil that quite obviously has now " +"been released...\n \n" +"The evil that you move against is the dark Lord of Terror - known to " +"mortal men as Diablo. It was he who was imprisoned within the Labyrinth " +"many centuries ago. The Map that you hold now was created ages ago to " +"mark the time when Diablo would rise again from his imprisonment. When " +"the two stars on that map align, Diablo will be at the height of his " +"power. He will be all but invincible...\n \n" +"You are now in a race against time, my friend! Find Diablo and destroy " +"him before the stars align, for we may never have a chance to rid the " +"world of his evil again! |"; + +//If the hero returns before the stars align and Diablo is Alive +static char Doom2[] = "Our time is running short! I sense his dark power " +"building and only you can stop him from attaining his full might. |"; + +//If the hero returns after the stars align and Diablo is Alive +static char Doom3[] = "I am sure that you tried your best, but I fear that " +"even your strength and will may not be enough. Diablo is now at the " +"height of his earthly power, and you will need all your courage and " +"strength to defeat him. May the Light protect and guide you, my friend. " +"I will help in any way that I am able. |"; + +static char Doom4[] = "If the witch can't help you and suggests you see Cain, " +"what makes you think that I would know anything? It sounds like this is a " +"very serious matter. You should hurry along and see the storyteller as " +"Adria suggests. |"; + +static char Doom5[] = "I can't make much of the writing on this map, but " +"perhaps Adria or Cain could help you decipher what this refers to. \n \n" +"I can see that it is a map of the stars in our sky, but any more than " +"that is beyond my talents. |"; + +static char Doom6[] = "The best person to ask about that sort of thing " +"would be our storyteller. \n \n" +"Cain is very knowledgeable about ancient " +"writings, and that is easily the oldest looking piece of paper that " +"I have ever seen. |"; + +static char Doom7[] = "I have never seen a map of this sort before. Where'd you get it? " +"Although I have no idea how to read this, Cain or Adria may be able " +"to provide the answers that you seek. |"; + +static char Doom8[] = "Listen here, come close. I don't know if you know " +"what I know, but you have really got somethin' here. That's a map. |"; + +static char Doom9[] = "Oh, I'm afraid this does not bode well at all. This map " +"of the stars portends great disaster, but its secrets are not mine to " +"tell. The time has come for you to have a very serious conversation " +"with the Storyteller... |"; + +static char Doom10[] = "I've been looking for a map, but that certainly " +"isn't it. You should show that to Adria - she can probably tell you " +"what it is. I'll say one thing; it looks old, and old usually means " +"valuable. |"; +#endif + +/*-----------------------------------------------------------------------** +** Garbud the Weak Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +//Gharbad the Weak Encounter +static char Garbud1[] = "Pleeeease, no hurt. No Kill. Keep alive and next " +"time good bring to you. |"; + +//When the hero finds Gharbad again +static char Garbud2[] = "Something for you I am making. Again, not kill " +"Gharbad. Live and give good. \n \n" +"You take this as proof I keep word... |"; + +//When the hero finds Gharbad again +static char Garbud3[] = "Nothing yet! Almost done. \n \n" +"Very powerful, very " +"strong. Live! Live! \n \n" +"No pain and promise I keep! |"; + +//When the hero finds Gharbad again +static char Garbud4[] = "This too good for you. Very Powerful! You want - " +"you take! |"; +#endif + +/*-----------------------------------------------------------------------** +** Zhar the Mad Quest +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +//Zhar the Mad Encounter +static char Zhar1[] = "What?! Why are you here? All these interruptions " +"are enough to make one insane. Here, take this and leave me to my work. " +"Trouble me no more! |"; + +//If the hero bothers him again +static char Zhar2[] = "Arrrrgh! Your curiosity will be the death of you!!! |"; +#endif + +/*-----------------------------------------------------------------------** +// TOWNSPEOPLE'S NONQUEST +**-----------------------------------------------------------------------*/ +// Deckard Cain +static char Story1[] = "Hello, my friend. Stay awhile and listen... |"; + +#if !IS_VERSION(SHAREWARE) +static char Story2[] = "While you are venturing deeper into the Labyrinth " +"you may find tomes of great knowledge hidden there. \n \n" +"Read them carefully " +"for they can tell you things that even I cannot. |"; + +static char Story3[] = "I know of many myths and legends that may contain " +"answers to questions that may arise in your journeys into the Labyrinth. " +"If you come across challenges and questions to which you seek knowledge, " +"seek me out and I will tell you what I can. |"; + +static char Story4[] = "Griswold - a man of great action and great courage. " +"I bet he never told you about the time he went into the Labyrinth to " +"save Wirt, did he? He knows his fair share of the dangers to be found " +"there, but then again - so do you. He is a skilled craftsman, and if " +"he claims to be able to help you in any way, you can count on his " +"honesty and his skill. |"; + +static char Story5[] = "Ogden has owned and run the Rising Sun Inn and " +"Tavern for almost four years now. He purchased it just a few short " +"months before everything here went to hell. He and his wife Garda do " +"not have the money to leave as they invested all they had in making " +"a life for themselves here. He is a good man with a deep sense of " +"responsibility. |"; + + +static char Story6[] = "Poor Farnham. He is a disquieting reminder of the " +"doomed assembly that entered into the Cathedral with Lazarus on that " +"dark day. He escaped with his life, but his courage and much of his " +"sanity were left in some dark pit. He finds comfort only at the bottom " +"of his tankard nowadays, but there are occasional bits of truth buried " +"within his constant ramblings. |"; + +static char Story7[] = "The witch, Adria, is an anomaly here in Tristram. " +"She arrived shortly after the Cathedral was desecrated while most " +"everyone else was fleeing. She had a small hut constructed at the " +"edge of town, seemingly overnight, and has access to many strange " +"and arcane artifacts and tomes of knowledge that even I have never " +"seen before. |"; + +static char Story9[] = "The story of Wirt is a frightening and tragic one. " +"He was taken from the arms of his mother " +"and dragged into the labyrinth by the small, foul demons that wield " +"wicked spears. There were many other children taken that day, including " +"the son of King Leoric. The Knights of the palace went below, but " +"never returned. The Blacksmith found the boy, but only after the foul " +"beasts had begun to torture him for their sadistic pleasures. |"; + +static char Story10[] = "Ah, Pepin. I count him as a true friend - perhaps " +"the closest I have here. He is a bit addled at times, but never a more " +"caring or considerate soul has existed. His knowledge and skills are " +"equaled by few, and his door is always open. |"; + +static char Story11[] = "Gillian is a fine woman. Much adored for her high " +"spirits and her quick laugh, she holds a special place in my heart. She " +"stays on at the tavern to support her elderly grandmother who is too " +"sick to travel. I sometimes fear for her safety, but I know that any man " +"in the village would rather die than see her harmed. |"; +#endif + +// Ogden +static char Ogden1[] = "Greetings, good master. Welcome to the Tavern of " +"the Rising Sun! |"; + +#if !IS_VERSION(SHAREWARE) +static char Ogden2[] = "Many adventurers have graced the tables of my tavern, " +"and ten times as many stories have been told over as much ale. The only " +"thing that I ever heard any of them agree on was this old axiom. Perhaps " +"it will help you. " +"You can cut the flesh, but you must crush the bone. |"; + +static char Ogden3[] = "Griswold the blacksmith is extremely knowledgeable " +"about weapons and armor. If you ever need work done on your gear, he is " +"definitely the man to see. |"; + +static char Ogden4[] = "Farnham spends far too much time here, drowning his " +"sorrows in cheap ale. I would make him leave, but he did suffer so during " +"his time in the Labyrinth. |"; + +static char Ogden5[] = "Adria is wise beyond her years, but I must admit - " +"she frightens me a little. \n \n" +"Well, no matter. If you ever have need to " +"trade in items of sorcery, she maintains a strangely well-stocked hut " +"just across the river. |"; + +static char Ogden6[] = "If you want to know more about the history of our " +"village, the storyteller Cain knows quite a bit about the past. |"; + +static char Ogden8[] = "Wirt is a rapscallion and a little scoundrel. He " +"was always getting into trouble, and it's no surprise what happened to " +"him. \n \n" +"He probably went fooling about someplace that he shouldn't have " +"been. I feel sorry for the boy, but I don't abide the company that he keeps. |"; + +static char Ogden9[] = "Pepin is a good man - and certainly the most " +"generous in the village. He is always attending to the needs of others, " +"but trouble of some sort or another does seem to follow him wherever he " +"goes... |"; + +static char Ogden10[] = "Gillian, my Barmaid? If it were not for her sense " +"of duty to her grand-dam, she would have fled from here long ago. \n \n" +"Goodness knows I begged her to leave, telling her that I would watch " +"after the old woman, but she is too sweet and caring to have done so. |"; +#endif + +// Pepin +static char Pepin1[] = "What ails you, my friend? |"; + +#if !IS_VERSION(SHAREWARE) +static char Pepin2[] = "I have made a very interesting discovery. Unlike " +"us, the creatures in the Labyrinth can heal themselves without the aid " +"of potions or magic. If you hurt one of the monsters, make sure it is " +"dead or it very well may regenerate itself. |"; + +static char Pepin3[] = "Before it was taken over by, well, whatever lurks " +"below, the Cathedral was a place of great learning. There are many " +"books to be found there. If you find any, you should read them all, " +"for some may hold secrets to the workings of the Labyrinth. |"; + +static char Pepin4[] = "Griswold knows as much about the art of war as I " +"do about the art of healing. He is a shrewd merchant, but his work is " +"second to none. Oh, I suppose that may be because he is the only " +"blacksmith left here. |"; + +static char Pepin5[] = "Cain is a true friend and a wise sage. He maintains " +"a vast library and has an innate ability to discern the true nature of " +"many things. If you ever have any questions, he is the person to go to. |"; + +static char Pepin6[] = "Even my skills have been unable to fully heal " +"Farnham. Oh, I have been able to mend his body, but his mind and spirit " +"are beyond anything I can do. |"; + +static char Pepin7[] = "While I use some limited forms of magic to create " +"the potions and elixirs I store here, Adria is a true sorceress. She " +"never seems to sleep, and she always has access to many mystic tomes " +"and artifacts. I believe her hut may be much more than the hovel " +"it appears to be, but I can never seem to get inside the place. |"; + +static char Pepin9[] = "Poor Wirt. I did all that was possible for the " +"child, but I know he despises that wooden peg that I was forced to " +"attach to his leg. His wounds were hideous. No one - and especially " +"such a young child - should have to suffer the way he did. |"; + +static char Pepin10[] = "I really don't understand why Ogden stays here " +"in Tristram. He suffers from a slight nervous condition, but he is an " +"intelligent and industrious man who would do very well wherever he " +"went. I suppose it may be the fear of the many murders that happen in " +"the surrounding countryside, or perhaps the wishes of his wife that " +"keep him and his family where they are. |"; + +static char Pepin11[] = "Ogden's barmaid is a sweet girl. Her grandmother " +"is quite ill, and suffers from delusions. \n \n" +"She claims that they are " +"visions, but I have no proof of that one way or the other. |"; +#endif + +// Gillian +static char Gillian1[] = "Good day! How may I serve you? |"; + +#if !IS_VERSION(SHAREWARE) +static char Gillian2[] = "My grandmother had a dream that you would come " +"and talk to me. She has visions, you know and can see into the future. |"; + +static char Gillian3[] = "The woman at the edge of town is a witch! She " +"seems nice enough, and her name, Adria, is very pleasing to the ear, " +"but I am very afraid of her. \n \n" +"It would take someone quite brave, like " +"you, to see what she is doing out there. |"; + +static char Gillian4[] = "Our Blacksmith is a point of pride to the people " +"of Tristram. Not only is he a master craftsman who has won many " +"contests within his guild, but he received praises from our King " +"Leoric himself - may his soul rest in peace. Griswold is also a great hero; just " +"ask Cain. |"; + +static char Gillian5[] = "Cain has been the storyteller of Tristram for " +"as long as I can remember. He knows so much, and can tell you just " +"about anything about almost everything. |"; + +static char Gillian6[] = "Farnham is a drunkard who fills his belly with " +"ale and everyone else's ears with nonsense. \n \n" +"I know that both Pepin " +"and Ogden feel sympathy for him, but I get so frustrated watching him " +"slip farther and farther into a befuddled stupor every night. |"; + +static char Gillian7[] = "Pepin saved my grandmother's life, and I know " +"that I can never repay him for that. His ability to heal any sickness " +"is more powerful than the mightiest sword and more mysterious than any spell you " +"can name. If you ever are in need of healing, Pepin can help you. |"; + +static char Gillian9[] = "I grew up with Wirt's mother, Canace. Although " +"she was only slightly hurt when those hideous creatures stole him, " +"she never recovered. I think she died of a broken heart. Wirt has " +"become a mean-spirited youngster, looking only to profit from the " +"sweat of others. I know that he suffered and has seen horrors that " +"I cannot even imagine, but some of that darkness hangs over him still. |"; + +static char Gillian10[] = "Ogden and his wife have taken me and my " +"grandmother into their home and have even let me earn a few gold " +"pieces by working at the inn. I owe so much to them, and hope one " +"day to leave this place and help them start a grand hotel in the east. |"; +#endif + +// Griswold +static char Griswold1[] = "Well, what can I do for ya? |"; + +#if !IS_VERSION(SHAREWARE) +static char Griswold2[] = "If you're looking for a good weapon, let me show " +"this to you. Take your basic blunt weapon, such as a mace. Works like " +"a charm against most of those undying horrors down there, and there's " +"nothing better to shatter skinny little skeletons! |"; + +static char Griswold3[] = "The axe? Aye, that's a good weapon, balanced against any " +"foe. Look how it cleaves the air, and then imagine a nice fat demon " +"head in its path. Keep in mind, however, that it is slow to swing - " +"but talk about dealing a heavy blow! |"; + +static char Griswold4[] = "Look at that edge, that balance. A sword in " +"the right hands, and against the right foe, is the master of all " +"weapons. Its keen blade finds little to hack or pierce on the undead, " +"but against a living, breathing enemy, a sword will better slice their " +"flesh! |"; + +static char Griswold5[] = "Your weapons and armor will show the signs of " +"your struggles against the Darkness. If you bring them to me, with a " +"bit of work and a hot forge, I can restore them to top fighting form. |"; + +static char Griswold6[] = "While I have to practically smuggle in the " +"metals and tools I need from caravans that skirt the edges of our " +"damned town, that witch, Adria, always seems to get whatever she needs. " +"If I knew even the smallest bit about how to harness magic as she did, " +"I could make some truly incredible things. |"; + +static char Griswold7[] = "Gillian is a nice lass. Shame that her gammer " +"is in such poor health or I would arrange to get both of them out of " +"here on one of the trading caravans. |"; + +static char Griswold8[] = "Sometimes I think that Cain talks too much, " +"but I guess that is his calling in life. If I could bend steel as " +"well as he can bend your ear, I could make a suit of court plate " +"good enough for an Emperor! |"; + +static char Griswold9[] = "I was with Farnham that night that Lazarus " +"led us into Labyrinth. I never saw the Archbishop again, and I may " +"not have survived if Farnham was not at my side. I fear that the " +"attack left his soul as crippled as, well, another did my leg. I " +"cannot fight this battle for him now, but I would if I could. |"; + +static char Griswold10[] = "A good man who puts the needs of others above " +"his own. You won't find anyone left in Tristram - or anywhere else " +"for that matter - who has a bad thing to say about the healer. |"; + +static char Griswold12[] = "That lad is going to get himself into serious " +"trouble... or I guess I should say, again. I've tried to interest him " +"in working here and learning an honest trade, but he prefers the high " +"profits of dealing in goods of dubious origin. I cannot hold that " +"against him after what happened to him, but I do wish he would at " +"least be careful. |"; + +static char Griswold13[] = "The Innkeeper has little business and no real " +"way of turning a profit. He manages to make ends meet by providing " +"food and lodging for those who occasionally drift through the " +"village, but they are as likely to sneak off into the night as they " +"are to pay him. If it weren't for the stores of grains and dried " +"meats he kept in his cellar, why, most of us would have starved during " +"that first year when the entire countryside was overrun by demons. |"; +#endif + +// Farnham +static char Farnham1[] = "Can't a fella drink in peace? |"; + +#if !IS_VERSION(SHAREWARE) +static char Farnham2[] = "The gal who brings the drinks? Oh, yeah, what a " +"pretty lady. So nice, too. |"; + +static char Farnham3[] = "Why don't that old crone do somethin' for a " +"change. Sure, sure, she's got stuff, but you listen to me... she's " +"unnatural. I ain't never seen her eat or drink - and you can't trust " +"somebody who doesn't drink at least a little. |"; + +static char Farnham4[] = "Cain isn't what he says he is. Sure, sure, he " +"talks a good story... some of 'em are real scary or funny... but I think " +"he knows more than he knows he knows. |"; + +static char Farnham5[] = "Griswold? Good old Griswold. I love him like " +"a brother! We fought together, you know, back when... we... Lazarus... " +" Lazarus... Lazarus!!! |"; + +static char Farnham6[] = "Hehehe, I like Pepin. He really tries, you know. " +"Listen here, you should make sure you get to know him. Good fella like " +"that with people always wantin' help. Hey, I guess that would be kinda " +"like you, huh hero? I was a hero too... |"; + +static char Farnham8[] = "Wirt is a kid with more problems than even me, " +"and I know all about problems. Listen here - that kid is gotta sweet " +"deal, but he's been there, you know? Lost a leg! Gotta walk around on " +"a piece of wood. So sad, so sad... |"; + +static char Farnham9[] = "Ogden is the best man in town. I don't think his " +"wife likes me much, but as long as she keeps tappin' kegs, I'll like " +"her just fine. Seems like I been spendin' more time with Ogden than " +"most, but he's so good to me... |"; + +static char Farnham10[] = "I wanna tell ya sumthin', 'cause I know all about this " +"stuff. It's my specialty. This here is " +"the best... theeeee best! That other ale ain't no good since " +"those stupid dogs... |"; + +static char Farnham11[] = "No one ever lis... listens to me. Somewhere - " +"I ain't too sure - but somewhere under the church is a whole pile o' " +"gold. Gleamin' and shinin' and just waitin' for someone to get it. |"; + +static char Farnham12[] = "I know you gots your own ideas, and I know you're " +"not gonna believe this, but that weapon you got there - it just ain't " +"no good against those big brutes! Oh, I don't care what Griswold " +"says, they can't make anything like they used to in the old days... |"; + +static char Farnham13[] = "If I was you... and I ain't... but if I was, I'd " +"sell all that stuff you got and get out of here. That boy out there... " +"He's always got somethin good, but you gotta give him some gold or " +"he won't even show you what he's got. |"; +#endif + +// Adria +static char Adria1[] = "I sense a soul in search of answers... |"; + +#if !IS_VERSION(SHAREWARE) +static char Adria2[] = "Wisdom is earned, not given. If you discover a " +"tome of knowledge, devour its words. Should you already have knowledge " +"of the arcane mysteries scribed within a book, remember - that level of " +"mastery can always increase. |"; + +static char Adria3[] = "The greatest power is often the shortest lived. " +"You may find ancient words of power written upon scrolls of parchment. " +"The strength of these scrolls lies in the ability of either apprentice " +"or adept to cast them with equal ability. Their weakness is that they " +"must first be read aloud and can never be kept at the ready in your " +"mind. Know also that these scrolls can be read but once, so use them " +"with care. |"; + +static char Adria4[] = "Though the heat of the sun is beyond measure, the " +"mere flame of a candle is of greater danger. No energies, no matter how " +"great, can be used without the proper focus. For many spells, " +"ensorcelled Staves may be charged with magical energies many times " +"over. I have the ability to restore their power - but know that nothing " +"is done without a price. |"; + +static char Adria5[] = "The sum of our knowledge is in the sum of its " +"people. Should you find a book or scroll that you cannot decipher, do " +"not hesitate to bring it to me. If I can make sense of it I will share " +"what I find. |"; + +static char Adria6[] = "To a man who only knows Iron, there is no greater " +"magic than Steel. The blacksmith Griswold is more of a sorcerer than " +"he knows. His ability to meld fire and metal is unequaled in this land. |"; + +static char Adria7[] = "Corruption has the strength of deceit, but innocence " +"holds the power of purity. The young woman Gillian has a pure heart, " +"placing the needs of her matriarch over her own. She fears me, but it is " +"only because she does not understand me. |"; + +static char Adria8[] = "A chest opened in darkness holds no greater treasure " +"than when it is opened in the light. The storyteller Cain is an enigma, " +"but only to those who do not look. His knowledge of what lies beneath " +"the cathedral is far greater than even he allows himself to realize. |"; + +static char Adria9[] = "The higher you place your faith in one man, the " +"farther it has to fall. Farnham has lost his soul, but not to any demon. " +"It was lost when he saw his fellow townspeople betrayed by the " +"Archbishop Lazarus. He has knowledge to be gleaned, but you must " +"separate fact from fantasy. |"; + +static char Adria10[] = "The hand, the heart and the mind can perform " +"miracles when they are in perfect harmony. The healer Pepin sees into " +"the body in a way that even I cannot. His ability to restore the sick " +"and injured is magnified by his understanding of the creation of " +"elixirs and potions. He is as great an ally as you have in Tristram. |"; + +static char Adria12[] = "There is much about the future we cannot see, but " +"when it comes it will be the children who wield it. The boy Wirt has " +"a blackness upon his soul, but he poses no threat to the town or its " +"people. His secretive dealings with the urchins and unspoken guilds " +"of nearby towns gain him access to many devices that cannot be easily " +"found in Tristram. While his methods may be reproachful, Wirt can " +"provide assistance for your battle against the encroaching Darkness. |"; + +static char Adria13[] = "Earthen walls and thatched canopy do not a home " +"create. The innkeeper Ogden serves more of a purpose in this town than " +"many understand. He provides shelter for Gillian and her matriarch, " +"maintains what life Farnham has left to him, and provides an anchor " +"for all who are left in the town to what Tristram once was. His tavern, " +"and the simple pleasures that can still be found there, provide a " +"glimpse of a life that the people here remember. It is that memory " +"that continues to feed their hopes for your success. |"; +#endif + +// Wirt +static char Wirt1[] = "Pssst... over here... |"; + +#if !IS_VERSION(SHAREWARE) +static char Wirt2[] = "Not everyone in Tristram has a use - or a market - " +"for everything you will find in the labyrinth. Not even me, as hard " +"as that is to believe. \n \n" +"Sometimes, only you will be able to find a " +"purpose for some things. |"; + +static char Wirt3[] = "Don't trust everything the drunk says. Too many " +"ales have fogged his vision and his good sense. |"; + +static char Wirt4[] = "In case you haven't noticed, I don't buy anything " +"from Tristram. I am an importer of quality goods. If you want to " +"peddle junk, you'll have to see Griswold, Pepin or that witch, " +"Adria. I'm sure that they will snap up whatever you can bring them... |"; + +static char Wirt5[] = "I guess I owe the blacksmith my life - what there " +"is of it. Sure, Griswold offered me an apprenticeship at the smithy, " +"and he is a nice enough guy, but I'll never get enough money to... " +"well, let's just say that I have definite plans that require a large " +"amount of gold. |"; + +static char Wirt6[] = "If I were a few years older, I would shower her " +"with whatever riches I could muster, and let me assure you I can get " +"my hands on some very nice stuff. Gillian is a beautiful girl who " +"should get out of Tristram as soon as it is safe. Hmmm... maybe I'll " +"take her with me when I go... |"; + +static char Wirt7[] = "Cain knows too much. He scares the life out of me " +"- even more than that woman across the river. He keeps telling me " +"about how lucky I am to be alive, and how my story is foretold in " +"legend. I think he's off his crock. |"; + +static char Wirt8[] = "Farnham - now there is a man with serious problems, " +"and I know all about how serious problems can be. He trusted too much " +"in the integrity of one man, and Lazarus led him into the very jaws of " +"death. Oh, I know what it's like down there, so don't even start " +"telling me about your plans to destroy the evil that dwells in that " +"Labyrinth. Just watch your legs... |"; + +static char Wirt9[] = "As long as you don't need anything reattached, " +"old Pepin is as good as they come. \n \n" +"If I'd have had some of those " +"potions he brews, I might still have my leg... |"; + +static char Wirt11[] = "Adria truly bothers me. Sure, Cain is creepy in " +"what he can tell you about the past, but that witch can see into " +"your past. She always has some way to get whatever she needs, too. " +"Adria gets her hands on more merchandise than I've seen pass through " +"the gates of the King's Bazaar during High Festival. |"; + +static char Wirt12[] = "Ogden is a fool for staying here. I could get " +"him out of town for a very reasonable price, but he insists on trying " +"to make a go of it with that stupid tavern. I guess at the least he " +"gives Gillian a place to work, and his wife Garda does make a superb " +"Shepherd's pie... |"; +#endif + +/*-----------------------------------------------------------------------** +// BOOKS and SCROLLS as read by the heroes +**-----------------------------------------------------------------------*/ + +static char Cow1[] = " |"; + +/*-----------------------------------------------------------------------** +// BOOKS and SCROLLS as read by the heroes +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +// Warrior, Sorceror, Rogue +//SKELETAL TOME (TRIGGERS THE QUEST): +static char Boner[] = "Beyond the Hall of Heroes lies the Chamber of " +"Bone. Eternal death awaits any who would seek to steal the treasures " +"secured within this room. So speaks the Lord of Terror, and so it is " +"written. |"; + +//BOOK OF BLOOD: +static char Bloody[] = "...and so, locked beyond the Gateway of Blood and " +"past the Hall of Fire, Valor awaits for the Hero of Light to awaken... |"; + +//BOOK OF THE BLIND (TRIGGERS QUEST): +static char Blinding[] = "I can see what you see not.\n" +"Vision milky then eyes rot.\n" +"When you turn they will be gone,\n" +"Whispering their hidden song.\n" +"Then you see what cannot be,\n" +"Shadows move where light should be.\n" +"Out of darkness, out of mind,\n" +"Cast down into the Halls of the Blind. |\n"; + +//STEEL TOME (TRIGGERS QUEST): +static char Bloodwar[] = "The armories of Hell are home to the Warlord of " +"Blood. In his wake lay the mutilated bodies of thousands. Angels and " +"man alike have been cut down to fulfill his endless sacrifices to the " +"Dark ones who scream for one thing - blood. |"; +#endif + +/*-----------------------------------------------------------------------** +** The Librium of the Horadrim (White Books) +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Book11[] = "Take heed and bear witness to the truths that lie herein, for they are the " +"last legacy of the Horadrim. There is a war that rages on even now, beyond the fields that " +"we know - between the utopian kingdoms of the High Heavens and the chaotic pits of the " +"Burning Hells. This war is known as the Great Conflict, and it has raged and burned " +"longer than any of the stars in the sky. Neither side ever gains sway for long as the " +"forces of Light and Darkness constantly vie for control over all creation. |"; + +static char Book12[] = "Take heed and bear witness to the truths that lie herein, for they are the " +"last legacy of the Horadrim. When the Eternal Conflict between the High Heavens and the " +"Burning Hells falls upon mortal soil, it is called the Sin War. Angels and Demons walk " +"amongst humanity in disguise, fighting in secret, away from the prying eyes of mortals. " +"Some daring, powerful mortals have even allied themselves with either side, and helped " +"to dictate the course of the Sin War. |"; + +static char Book13[] = "Take heed and bear witness to the truths that lie herein, for they are the " +"last legacy of the Horadrim. Nearly three hundred years ago, it came to be known that the " +"Three Prime Evils of the Burning Hells had mysteriously come to our world. The Three " +"Brothers ravaged the lands of the east for decades, while humanity was left trembling " +"in their wake. Our Order - the Horadrim - was founded by a group of secretive magi to " +"hunt down and capture the Three Evils once and for all.\n \n" +"The original Horadrim captured two of the Three within powerful artifacts known as " +"Soulstones and buried them deep beneath the desolate eastern sands. The third Evil " +"escaped capture and fled to the west with many of the Horadrim in pursuit. The Third " +"Evil - known as Diablo, the Lord of Terror - was eventually captured, his essence set " +"in a Soulstone and buried within this Labyrinth.\n \n" +"Be warned that the soulstone must be kept from discovery by those not of the faith. If " +"Diablo were to be released, he would seek a body that is easily controlled as he would " +"be very weak - perhaps that of an old man or a child. |"; +#endif + +/*-----------------------------------------------------------------------** +** Grimoire of the Burning Hells (Red Books) +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Book21[] = "So it came to be that there was a great revolution within the Burning " +"Hells known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils and banished " +"their spirit forms to the mortal realm. The demons Belial (the Lord of Lies) and " +"Azmodan (the Lord of Sin) fought to claim rulership of Hell during the absence of " +"the Three Brothers. All of Hell polarized between the factions of Belial and Azmodan " +"while the forces of the High Heavens continually battered upon the very Gates of Hell. |"; + +static char Book22[] = "Many demons traveled to the mortal realm in search of the " +"Three Brothers. These " +"demons were followed to the mortal plane by Angels who hunted them throughout the vast " +"cities of the East. The Angels allied themselves with a secretive Order of mortal magi " +"named the Horadrim, who quickly became adept at hunting demons. They also made many dark " +"enemies in the underworlds. |"; + +static char Book23[] = "So it came to be that the Three Prime Evils were banished in spirit form " +"to the mortal realm and after sewing chaos across the East for decades, they were " +"hunted down by the cursed Order of the mortal Horadrim. The Horadrim used artifacts " +"called Soulstones to contain the essence of Mephisto, the Lord of Hatred and his " +"brother Baal, the Lord of Destruction. The youngest brother - Diablo, the Lord of " +"Terror - escaped to the west.\n \n" +"Eventually the Horadrim captured Diablo within a Soulstone as well, and buried him " +"under an ancient, forgotten Cathedral. There, the Lord of Terror sleeps and awaits the " +"time of his rebirth. Know ye that he will seek a body of youth and power to possess - " +"one that is innocent and easily controlled. He will then arise to free his Brothers " +"and once more fan the flames of the Sin War... |"; +#endif + +/*-----------------------------------------------------------------------** +** The Journals of Lazarus the Betrayer (Normal Book Color) +**-----------------------------------------------------------------------*/ +#if !IS_VERSION(SHAREWARE) +static char Book31[] = "All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. " +"When he awakened from his long slumber, my Lord and Master spoke to me of secrets " +"that few mortals know. He told me the kingdoms of the High Heavens and the pits of " +"the Burning Hells engage in an eternal war. He revealed the powers that have brought " +"this discord to the realms of man. My lord has named the battle for this world and " +"all who exist here the Sin War. |"; + +static char Book32[] = "Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. " +"My Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished to this " +"world long ago. My Lord wishes to bide his time and harness his awesome power so that " +"he may free his captive brothers from their tombs beneath the sands of the east. Once " +"my Lord releases his Brothers, the Sin War will once again know the fury of the Three. |"; + +static char Book33[] = "Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. " +"When I awoke my Master from his sleep, he attempted to possess a mortal's form. Diablo " +"attempted to claim the body of King Leoric, but my Master was too weak from his " +"imprisonment. My Lord required a simple and innocent anchor to this world, and so " +"found the boy Albrecht to be perfect for the task. While the good King Leoric was " +"left maddened by Diablo's unsuccessful possession, I kidnapped his son Albrecht " +"and brought him before my Master. I now await Diablo's call and pray that I will " +"be rewarded when he at last emerges as the Lord of this world. |"; +#endif + +static char Intro[] = "Thank goodness you've returned!\n" +"Much has changed since you lived here, my friend. " +"All was peaceful until the dark riders came and destroyed " +"our village. Many were cut down where they stood, and those who " +"took up arms were slain or dragged away to become slaves - or worse. " +"The church at the edge of town has been desecrated and is being used " +"for dark rituals. The screams that echo in the night are inhuman, but " +"some of our townsfolk may yet survive. Follow the path that lies " +"between my tavern and the blacksmith shop to find the church and " +"save who you can. \n \n" +"Perhaps I can tell you more if we speak again. Good luck.|"; + +// JKEQUEST Place text here + +static char CryptMap1[] = "Maintain your quest. Finding a treasure that is lost is not " +"easy. Finding a treasure that is hidden less so. I will leave you with this. Do not " +"let the sands of time confuse your search.|"; + +static char CryptMap2[] = "A what?! This is foolishness. There's no treasure buried " +"here in Tristram. Let me see that!! Ah, Look these drawings are inaccurate. They " +"don't match our town at all. I'd keep my mind on what lies below the cathedral and not " +"what lies below our topsoil.|"; + +static char CryptMap3[] = "I really don't have time to discuss some map you are looking " +"for. I have many sick people that require my help and yours as well.|"; + +static char CryptMap4[] = "The once proud Iswall is trapped deep beneath the surface of " +"this world. His honor stripped and his visage altered. He is trapped in immortal " +"torment. Charged to conceal the very thing that could free him.|"; + +static char CryptMap5[] = "I'll bet that Wirt saw you coming and put on an act just so " +"he could laugh at you later when you were running around the town with your nose in the " +"dirt. I'd ignore it.|"; + +static char CryptMap6[] = "There was a time when this town was a frequent stop for " +"travelers from far and wide. Much has changed since then. But hidden caves and buried " +"treasure are common fantasies of any child. Wirt seldom indulges in youthful games. " +"So it may just be his imagination.|"; + +static char CryptMap7[] = "Listen here. Come close. I don't know if you know what I " +"know, but you've have really got something here. That's a map.|"; + +static char CryptMap8[] = "My grandmother often tells me stories about the strange forces " +"that inhabit the graveyard outside of the church. And it may well interest you to hear " +"one of them. She said that if you were to leave the proper offering in the cemetary, " +"enter the cathedral to pray for the dead, and then return, the offering would be altered " +"in some strange way. I don't know if this is just the talk of an old sick woman, but " +"anything seems possible these days.|"; + +static char CryptMap9[] = "Hmmm. A vast and mysterious treasure you say. Mmmm. " +"Maybe I could be interested in picking up a few things from you. Or better yet, don't " +"you need some rare and expensive supplies to get you through this ordeal?|"; + + +static char Cowsuit1[] = "Moo.|"; + +static char Cowsuit2[] = "I said, Moo.|"; + +static char Cowsuit3[] = "Look I'm just a cow, OK?|"; + +static char Cowsuit4[] = "All right, all right. I'm not really a cow. I don't normally go " +"around like this; but, I was sitting at home minding my own business and all of a sudden " +"these bugs & vines & bulbs & stuff started coming out of the floor... it was horrible! " +"If only I had something normal to wear, it wouldn't be so bad. Hey! Could you go back to " +"my place and get my suit for me? The brown one, not the gray one, that's for evening wear. " +"I'd do it myself, but I don't want anyone seeing me like this. Here, take this, you " +"might need it... to kill those things that have overgrown everything. You can't miss my " +"house, it's just south of the fork in the river... you know... the one with the overgrown " +"vegetable garden.|"; + +static char Cowsuit4A[] = "All right, I'll cut the bull. I didn't mean to steer you wrong. " +"I was sitting at home, feeling moo-dy, when things got really un-stable; a whole stampede " +"of monsters came out of the floor! I just cowed. I just happened to be wearing this Jersey " +"when I ran out the door, and now I look udderly ridiculous. If only I had something normal " +"to wear, it wouldn't be so bad. Hey! Can you go back to my place and get my suit for me? " +"The brown one, not the gray one, that's for evening wear. I'd do it myself, but I don't " +"want anyone seeing me like this. Here, take this, you might need it... to kill those things " +"that have overgrown everything. You can't miss my house, it's just south of the fork in " +"the river... you know... the one with the overgrown vegetable garden.|"; + +static char Cowsuit5[] = "What are you wasting time for? Go get my suit! And hurry! That Holstein " +"over there keeps winking at me! |"; + +static char Cowsuit6[] = "Hey, have you got my suit there? Quick, pass it over! These ears " +"itch like you wouldn't believe!|"; + +static char Cowsuit7[] = "No no no no! This is my GRAY suit! It's for evening wear! " +"Formal occasions! I can't wear THIS. What are you, some kind of weirdo? I need the " +"BROWN suit.|"; + +static char Cowsuit8[] = "Ahh, that's MUCH better. Whew! At last, some dignity! Are my " +"antlers on straight? Good. Look, thanks a lot for helping me out. Here, take this as a " +"gift; and, you know... a little fashion tip... you could use a little... you could use a " +"new... yknowwhatImean? The whole adventurer motif is just so... retro. Just a word of " +"advice, eh? Ciao.|"; + +static char Cowsuit9[] = "Look. I'm a cow. And you, you're monster bait. " +"Get some experience under your belt! We'll talk...|"; + +static char Cowsuit10[] = "Me, I'm a self-made cow. Make something of " +"yourself, and... then we'll talk.|"; + +static char Cowsuit11[] = "I don't have to explain myself to every tourist " +"that walks by! Don't you have some monsters to kill? Maybe we'll talk " +"later. If you live...|"; + +static char Cowsuit12[] = "Quit bugging me. I'm looking for someone really " +"heroic. And you're not it. I can't trust you, you're going to get eaten " +"by monsters any day now... I need someone who's an experienced hero.|"; + +static char Cornerstone1[] = "And in the year of the Golden Light, it was so decreed " +"that a great Cathedral be raised. The cornerstone of this holy place was to be " +"carved from the translucent stone Antyrael, named for the Angel who shared his power " +"with the Horadrim. \n \nIn the Year of Drawing Shadows, the ground shook and the Cathedral " +"shattered and fell. As the building of catacombs and castles began and man stood " +"against the ravages of the Sin War, the ruins were scavenged for their stones. And " +"so it was that the cornerstone vanished from the eyes of man. \n \nThe stone was of this " +"world -- and of all worlds -- as the Light is both within all things and beyond all " +"things. Light and unity are the products of this holy foundation, a unity of purpose " +"and a unity of possession.|"; + +/*"And in the year of Golden Light, it was so " +"decreed that a great cathedral should be raised, for the glory of Heaven. " +"And for the cornerstone was brought from the Holy Land a block of " +"translucent stone. And the stone was of this world, and of all worlds, as " +"the spirit of Light is both within and beyond us, in all things. " +"The stone brought all it touched to all the worlds, uniting them in Light. " +"In the Year of the Drawing Shadows, the ground shook, and the cathedral " +"tumbled and shattered. And in the time that followed, of the building of " +"catacombs and castles against the ravages of the Sin War, the ruins were " +"taken for their stones. And so it was that the Cornerstone vanished from " +"the eyes of man, lost, perhaps forever.|";*/ + + +static char Theo1[] = "Waaaah! (sniff) Waaaah! (sniff)|"; + +static char Theo2[] = "I lost Theo! I lost my best friend! We were playing over by the " +"river, and Theo said he wanted to go look at the big green thing. I said we " +"shouldn't, but we snuck over there, and then suddenly this BUG came out! We ran away but " +"Theo fell down and the bug GRABBED him and took him away!|"; + +static char Theo3[] = "Didja find him? You gotta find Theodore, please! " +"He's just little. He can't take care of himself! Please!|"; + +static char Theo4[] = "You found him! You found him! Thank you! Oh Theo, " +"did those nasty bugs scare you? Hey! Ugh! There's something stuck to " +"your fur! Ick! Come on, Theo, let's go home! Thanks again, hero person!|"; + +static char Farmer1[] = "So, you're the hero everyone's been talking " +"about. Perhaps you could help a poor, simple farmer out of a terrible " +"mess? At the edge of my orchard, just south of here, there's a horrible " +"thing swelling out of the ground! I can't get to my crops or my bales " +"of hay, and my poor cows will starve. The witch gave this to me and " +"said that it would blast that thing out of my field. If you could " +"destroy it, I would be forever grateful. I'd do it myself, but someone " +"has to stay here with the cows...|"; + +/*"Here, you're that hero everyone's talking about! " +"You're just the type to help a poor farmer out of a terrible fix! You " +"see, right at the border of my orchard, just south of here, there's a " +"horrible thing swelling out of the ground! I daren't go near me own " +"land! So I got an alchemist to make a magic doo-hickey that'll " +"blast that thing. All you gotta do is take it over and drop it in. " +"I'd do it myself, but my leg's acting up, my lumbago, old war wounds, " +"you know. |";*/ + +static char Farmer2[] = "I knew that it couldn't be as simple as that " +"witch made it sound. It's a sad world when you can't even trust your " +"neighbors.|"; + +/*"You ain't done that measly little thing for me " +"yet? You're young! Never a thought for a poor common peasant... " +"it's a sad world.|";*/ + +static char Farmer2a[] = "It must truly be a fearsome task I've set " +"before you. If there was just some way that I could... would a flagon " +"of some nice, fresh milk help?|"; + +/*"Please, can you get that snarkfarbin' thing outta " +"myfield? It's blockin' the path to me privy!|";*/ + +static char Farmer3[] = "Is it gone? Did you send it back to the dark " +"recesses of Hades that spawned it? You what? Oh, don't tell me you lost " +"it! Those things don't come cheap, you know. You've got to find it, " +"and then blast that horror out of our town.|"; + +/*"You don't have that doo-hickey no more, but I " +"didn't hear any kaboom! Don't tell me you lost it! Those things don't " +"come cheap! You gotta find it, and blast that slimy-lookin' thing outta " +"there!|";*/ + +static char Farmer4[] = "I heard the explosion from here! Many thanks " +"to you, kind stranger. What with all these things comin' out of the " +"ground, monsters taking over the church, and so forth, these are trying " +"times. I am but a poor farmer, but here -- take this with my great " +"thanks.|"; + +/*"You blasted the sucker, eh? Many thanks to you, you're so kind, " +"many thanks. I don't know, things comin' out of the ground, monsters taking over the church, " +"these are hard times... I'm a poor man, I ain't got much, but... take this, take this with my" +" great thanks.|";*/ + +static char Farmer5[] = "Oh, such a trouble I have...maybe...No, I " +"couldn't impose on you, what with all the other troubles. Maybe after " +"you've cleansed the church of some of those creatures you could come " +"back... and spare a little time to help a poor farmer?|"; + +/*"Oh, such a trouble I have... maybe... Nah, you're just a kid, " +"still wet behind the ears! I can't ask you to do this. If only you were a little better " +"prepared.|";*/ + +static char Farmer6[] = "Oh, I could use your help, but perhaps after " +"you've saved the catacombs from the desecration of those beasts.|"; + +/*"Off with you! What I need done would take a real hero... maybe " +"someday you'll qualify.|";*/ + +static char Farmer7[] = "I need something done, but I couldn't impose " +"on a perfect stranger. Perhaps after you've been here a while I might " +"feel more comfortable asking a favor.|"; + +/*"I need something done, but how do I know you won't just skip town " +"on me? Make a name for yourself, kid, and then come find me.|";*/ + +static char Farmer8[] = "I see in you the potential for greatness. " +"Perhaps sometime while you are fulfilling your destiny, you could " +"stop by and do a little favor for me?|"; + +/*"Talk of the town is that you show real promise! Maybe if you live " +"up to the rumors... someday, I might have a little job for you.|";*/ + +static char Farmer9[] = "I think you could probably help me, but perhaps " +"after you've gotten a little more powerful. I wouldn't want to injure " +"the village's only chance to destroy the menace in the church!|"; + +/*"Busy fighting evil, huh? Well, if you live long enough to know " +"what you're doing, look me up, I got a little job you might be interested in.|";*/ + +static char Skulljrnl1[] = "Cloudy and cooler today. Casting the nets of necromancy across " +"the void landed two new subspecies of flying horror; a good day's work. Must remember to " +"order some more bat guano and black candles from Adria; I'm running a bit low.|"; + +static char Skulljrnl2[] = "I have tried spells, threats, abjuration and bargaining with " +"this foul creature -- to no avail. My methods of enslaving lesser demons seem to have no " +"effect on this fearsome beast.|"; + +/*"I have tried spells, threats, abjuration and bargaining with " +"the new creature. My means which have enslaved many lesser demons have no effect on this " +"fearsome beast; it only leers at me in a most unpleasant fashion. |";*/ + +static char Skulljrnl3[] = "My home is slowly becoming corrupted by the vileness of this " +"unwanted prisoner. The crypts are full of shadows that move just beyond the corners of " +"my vision. The faint scrabble of claws dances at the edges of my hearing. They are " +"searching, I think, for this journal.|"; + +/*"The trapped creature's howls of fury keep me from sleep-- it " +"rages and curses the name of the one who sent it to the void, and against myself, for " +"trapping it here. Its words fill my heart with terror, yet I cannot block out its voice.|";*/ + +static char Skulljrnl4[] = "In its ranting, the creature has let slip its name -- " +"Na-Krul. I have attempted to research the name, but the smaller demons have somehow " +"destroyed my library. Na-Krul... The name fills me with a cold dread. I prefer to " +"think of it only as The Creature rather than ponder its true name.|"; + +/*"My home is coming alive, corrupted by the darkness of my " +"unwanted prisoner... The crypts are full of shadows... I see things at the corners of my " +"vision, hear the sounds of claws, and of searching. Searching, I think, for me. For " +"this journal. They must not learn the secret! The creature must not be released!|";*/ + +static char Skulljrnl5[] = "The entrapped creature's howls of fury keep me from gaining " +"much needed sleep. It rages against the one who sent it to the Void, and it " +"calls foul curses upon me for trapping it here. Its words fill my heart with terror, " +"and yet I cannot block out its voice.|"; + +/*"In its ranting, the creature has let slip its name. It calls " +"itself Na-Krul. The name is familiar to me... I wish I could research it, but the smaller " +"horrors have destroyed my library in their endless searching. Still, the syllables fill " +"me with a cold dread... I prefer to think of it only as the creature rather than ponder " +"its true name.|";*/ + +static char Skulljrnl6[] = "My time is quickly running out. I must record the ways to " +"weaken the demon, and then conceal that text, lest his minions find some way to use " +"my knowledge to free their lord. I hope that whoever finds this journal will seek the " +"knowledge.|"; + +/*"Time is running out. With my last entry I must reveal the way " +"to defeat the demon, then conceal that text, lest the demon-creatures find some way to " +"use my knowledge to free their lord. I have kept my athame, at least; when all is lost " +"I would rather meet my death at the end of a dagger, than at the claws of a demon.|";*/ + +static char Skulljrnl7[] = "Whoever finds this scroll is charged with stopping the demonic " +"creature that lies within these walls. My time is over. Even now, its hellish minions " +"claw at the frail door behind which I hide. \n \nI have hobbled the demon with arcane " +"magic and encased it within great walls, but I fear that will not be enough. " +"\n \nThe spells found in my three grimoires will provide you protected entrance to his " +"domain, but only if cast in their proper sequence. The levers at the entryway " +"will remove the barriers and free the demon; touch them not! Use only these spells to " +"gain entry or his power may be too great for you to defeat.|"; + +/*"Whoever finds this, you must stop this demon creature. It is " +"too late for me now; its hellish minions are clawing at this last door behind which I " +"cower. I have hobbled the creature by powerful spells and encased it behind thick walls, " +"yet it will not be enough. You will need the power of the spells in my three grimoires, " +"cast only in their proper sequence. The levers at the entry will remove the barriers and " +"free the demon; touch them not! Use only the spells! The spells in the correct sequence " +"will open the magical doorways, and allow you to face the demon and, I hope, defeat it. " +"May the Heavens have mercy on us all.|";*/ + +static char Defiler1[] = "Ahh, mammal, welcome. Such a... tasty planet you have. My Nest shall spread " +"across this land, and you and your species shall serve as food for our colony. I'm sure " +"our meeting will be quite... delicious. |"; + +static char Defiler2[] = "Have you been enjoying yourself, little mammal? How pathetic. " +"Your little world will be no challenge at all.|"; + +static char Defiler3[] = "Come closer, morsel...come find me, the Defiler. I have waited " +"thousands of years...do not try my patience any further. |"; + +static char Defiler4[] = "Ah, I can smell you...you are close! Close! Ssss...the scent " +"of blood and fear...how enticing...|"; + +static char Defiler6[] = "We have long lain dormant, and the time to " +"awaken has come. After our long sleep, we are filled with great hunger. " +"Soon, now, we shall feed...|"; + +static char Defiler7[] = "These lands shall be defiled, and our brood " +"shall overrun the fields that men call home. Our tendrils shall envelop " +"this world, and we will feast on the flesh of its denizens. Man shall " +"become our chattel and sustenance.|"; + +static char Defiler8[] = "Come closer, morsel! I smell your terror, " +"and I hunger.|"; + +static char Trader1[] = "|"; + +static char Spell1[] = "In Spiritu Sanctum. |"; + +static char Spell2[] = "Praedictum Otium. |"; + +static char Spell3[] = "Efficio Obitus Ut Inimicus. |"; + +#if IS_VERSION(SHAREWARE) +static char szShareware[] = "Nice try... "; +#endif + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// QST() --> quest in retail version ONLY +// sQST() --> quest in retail or shareware version -- most greetings +#if IS_VERSION(SHAREWARE) + // make regular quest text into "fake" text + #define QST(a,b,c,d) { &szShareware[0], FALSE, FALSE, TSFX_TAVERN36 } + #define sQST(a,b,c,d) { a,b,c,d } +#else + #define QST(a,b,c,d) { a,b,c,d } + #define sQST(a,b,c,d) { a,b,c,d } +#endif + +// * NOTE * Quest text scrolling rate 1 = slowest, 5 = normal, 9 = fastest + +const TextDataStruct alltext[] = { + QST( &King1[0], TRUE, 5, TSFX_STORY1 ), // 0 + QST( &King2[0], TRUE, 5, TSFX_TAVERN21 ), // 1 + QST( &King3[0], TRUE, 6, TSFX_TAVERN22 ), // 2 + QST( &King4[0], TRUE, 5, TSFX_TAVERN23 ), // 3 + QST( &King5[0], TRUE, 5, TSFX_HEALER1 ), // 4 + QST( &King6[0], TRUE, 6, TSFX_BMAID1 ), // 5 + QST( &King7[0], TRUE, 5, TSFX_SMITH1 ), // 6 + QST( &King8[0], TRUE, 5, TSFX_DRUNK1 ), // 7 + QST( &King9[0], TRUE, 5, TSFX_WITCH1 ), // 8 + QST( &King10[0], TRUE, 5, TSFX_PEGBOY1 ), // 9 + QST( &King11[0], FALSE, 5, USFX_SKING1 ), // 10 + QST( &Banner1[0], TRUE, 5, TSFX_STORY2 ), // 11 + QST( &Banner2[0], TRUE, 5, TSFX_TAVERN24 ), // 12 + QST( &Banner3[0], TRUE, 5, TSFX_TAVERN25 ), // 13 + QST( &Banner4[0], TRUE, 5, TSFX_HEALER2 ), // 14 + QST( &Banner5[0], TRUE, 6, TSFX_BMAID2 ), // 15 + QST( &Banner6[0], TRUE, 6, TSFX_SMITH2 ), // 16 + QST( &Banner7[0], TRUE, 5, TSFX_DRUNK2 ), // 17 + QST( &Banner8[0], TRUE, 6, TSFX_WITCH2 ), // 18 + QST( &Banner9[0], TRUE, 6, TSFX_PEGBOY2 ), // 19 + QST( &Banner10[0], TRUE, 5, USFX_SNOT1 ), // 20 + QST( &Banner11[0], TRUE, 6, USFX_SNOT2 ), // 21 + QST( &Banner12[0], TRUE, 6, USFX_SNOT3 ), // 22 + QST( &Vile1[0], TRUE, 3, TSFX_STORY36 ), // 23 + QST( &Vile2[0], TRUE, 5, TSFX_STORY37 ), // 24 + QST( &Vile3[0], TRUE, 5, TSFX_STORY38 ), // 25 + QST( &Vile4[0], TRUE, 6, TSFX_TAVERN1 ), // 26 + QST( &Vile5[0], TRUE, 5, TSFX_STORY38 ), // 27 not in + QST( &Vile6[0], TRUE, 5, TSFX_STORY38 ), // 28 not in + QST( &Vile7[0], TRUE, 5, TSFX_HEALER3 ), // 29 + QST( &Vile8[0], TRUE, 5, TSFX_BMAID3 ), // 30 + QST( &Vile9[0], TRUE, 5, TSFX_SMITH3 ), // 31 + QST( &Vile10[0], TRUE, 5, TSFX_DRUNK3 ), // 32 + QST( &Vile11[0], TRUE, 5, TSFX_WITCH3 ), // 33 + QST( &Vile12[0], TRUE, 5, TSFX_PEGBOY3 ), // 34 + QST( &Vile13[0], FALSE, 5, USFX_LAZ1 ), // 35 + QST( &Vile14[0], FALSE, 5, USFX_LAZ1 ), // 36 + QST( &Poison1[0], TRUE, 5, TSFX_STORY4 ), // 37 + QST( &Poison2[0], TRUE, 6, TSFX_TAVERN2 ), // 38 + QST( &Poison3[0], TRUE, 5, TSFX_HEALER20 ), // 39 + QST( &Poison4[0], TRUE, 6, TSFX_HEALER21 ), // 40 + QST( &Poison5[0], TRUE, 5, TSFX_HEALER22 ), // 41 + QST( &Poison6[0], TRUE, 6, TSFX_BMAID4 ), // 42 + QST( &Poison7[0], TRUE, 5, TSFX_SMITH4 ), // 43 + QST( &Poison8[0], TRUE, 8, TSFX_DRUNK4 ), // 44 + QST( &Poison9[0], TRUE, 6, TSFX_WITCH4 ), // 45 + QST( &Poison10[0], TRUE, 6, TSFX_PEGBOY4 ), // 46 + QST( &Bone1[0], TRUE, 4, TSFX_STORY7 ), // 47 + QST( &Bone2[0], TRUE, 6, TSFX_TAVERN5 ), // 48 + QST( &Bone3[0], TRUE, 6, TSFX_HEALER5 ), // 49 + QST( &Bone4[0], TRUE, 6, TSFX_BMAID6 ), // 50 + QST( &Bone5[0], TRUE, 6, TSFX_SMITH7 ), // 51 + QST( &Bone6[0], TRUE, 5, TSFX_DRUNK7 ), // 52 + QST( &Bone7[0], TRUE, 6, TSFX_WITCH7 ), // 53 + QST( &Bone8[0], TRUE, 5, TSFX_PEGBOY7 ), // 54 + QST( &Butch1[0], TRUE, 5, TSFX_STORY10 ), // 55 + QST( &Butch2[0], TRUE, 6, TSFX_TAVERN8 ), // 56 + QST( &Butch3[0], TRUE, 5, TSFX_HEALER8 ), // 57 + QST( &Butch4[0], TRUE, 6, TSFX_BMAID8 ), // 58 + QST( &Butch5[0], TRUE, 5, TSFX_SMITH10 ), // 59 + QST( &Butch6[0], TRUE, 5, TSFX_DRUNK10 ), // 60 + QST( &Butch7[0], TRUE, 5, TSFX_WITCH10 ), // 61 + QST( &Butch8[0], TRUE, 6, TSFX_PEGBOY10 ), // 62 + QST( &Butch9[0], TRUE, 5, TSFX_WOUND ), // 63 + QST( &Butch10[0], TRUE, 5, USFX_CLEAVER ), // 64 + QST( &Blind1[0], TRUE, 5, TSFX_STORY12 ), // 65 + QST( &Blind2[0], TRUE, 6, TSFX_TAVERN10 ), // 66 + QST( &Blind3[0], TRUE, 5, TSFX_HEALER10 ), // 67 + QST( &Blind4[0], TRUE, 6, TSFX_BMAID10 ), // 68 + QST( &Blind5[0], TRUE, 6, TSFX_SMITH12 ), // 69 + QST( &Blind6[0], TRUE, 6, TSFX_DRUNK12 ), // 70 + QST( &Blind7[0], TRUE, 6, TSFX_WITCH12 ), // 71 + QST( &Blind8[0], TRUE, 5, TSFX_PEGBOY11 ), // 72 + QST( &Veil1[0], TRUE, 5, TSFX_STORY13 ), // 73 + QST( &Veil2[0], TRUE, 6, TSFX_TAVERN11 ), // 74 + QST( &Veil3[0], TRUE, 5, TSFX_HEALER11 ), // 75 + QST( &Veil4[0], TRUE, 7, TSFX_BMAID11 ), // 76 + QST( &Veil5[0], TRUE, 5, TSFX_SMITH13 ), // 77 + QST( &Veil6[0], TRUE, 5, TSFX_DRUNK13 ), // 78 + QST( &Veil7[0], TRUE, 6, TSFX_WITCH13 ), // 79 + QST( &Veil8[0], TRUE, 5, TSFX_PEGBOY12 ), // 80 + QST( &Veil9[0], TRUE, 3, USFX_LACH1 ), // 81 + QST( &Veil10[0], TRUE, 6, USFX_LACH2 ), // 82 + QST( &Veil11[0], TRUE, 4, USFX_LACH3 ), // 83 + QST( &Anvil1[0], TRUE, 4, TSFX_STORY14 ), // 84 + QST( &Anvil2[0], TRUE, 7, TSFX_TAVERN12 ), // 85 + QST( &Anvil3[0], TRUE, 6, TSFX_HEALER12 ), // 86 + QST( &Anvil4[0], TRUE, 5, TSFX_BMAID12 ), // 87 + QST( &Anvil5[0], TRUE, 5, TSFX_SMITH21 ), // 88 + QST( &Anvil6[0], TRUE, 5, TSFX_SMITH22 ), // 89 + QST( &Anvil7[0], TRUE, 5, TSFX_SMITH23 ), // 90 + QST( &Anvil8[0], TRUE, 6, TSFX_DRUNK14 ), // 91 + QST( &Anvil9[0], TRUE, 5, TSFX_WITCH14 ), // 92 + QST( &Anvil10[0], TRUE, 6, TSFX_PEGBOY13 ), // 93 + QST( &Blood1[0], TRUE, 3, TSFX_STORY15 ), // 94 + QST( &Blood2[0], TRUE, 6, TSFX_TAVERN13 ), // 95 + QST( &Blood3[0], TRUE, 6, TSFX_HEALER13 ), // 96 + QST( &Blood4[0], TRUE, 6, TSFX_BMAID13 ), // 97 + QST( &Blood5[0], TRUE, 5, TSFX_SMITH14 ), // 98 + QST( &Blood6[0], TRUE, 7, TSFX_DRUNK15 ), // 99 + QST( &Blood7[0], TRUE, 6, TSFX_WITCH15 ), // 100 + QST( &Blood8[0], TRUE, 6, TSFX_PEGBOY14 ), // 101 + QST( &Warlrd1[0], TRUE, 5, TSFX_STORY18 ), // 102 + QST( &Warlrd2[0], TRUE, 6, TSFX_TAVERN16 ), // 103 + QST( &Warlrd3[0], TRUE, 7, TSFX_HEALER16 ), // 104 + QST( &Warlrd4[0], TRUE, 6, TSFX_BMAID16 ), // 105 + QST( &Warlrd5[0], TRUE, 6, TSFX_SMITH17 ), // 106 + QST( &Warlrd6[0], TRUE, 5, TSFX_DRUNK17 ), // 107 + QST( &Warlrd7[0], TRUE, 5, TSFX_WITCH18 ), // 108 + QST( &Warlrd8[0], TRUE, 6, TSFX_PEGBOY17 ), // 109 + QST( &Warlrd9[0], FALSE, 6, USFX_WARLRD1 ), // 110 + QST( &Infra1[0], TRUE, 5, TSFX_STORY20 ), // 111 + QST( &Infra2[0], TRUE, 6, TSFX_TAVERN18 ), // 112 + QST( &Infra3[0], TRUE, 6, TSFX_HEALER18 ), // 113 + QST( &Infra4[0], TRUE, 6, TSFX_BMAID18 ), // 114 + QST( &Infra5[0], TRUE, 5, TSFX_SMITH24 ), // 115 + QST( &Infra6[0], TRUE, 6, TSFX_SMITH25 ), // 116 + QST( &Infra7[0], TRUE, 5, TSFX_SMITH26 ), // 117 + QST( &Infra8[0], TRUE, 5, TSFX_DRUNK19 ), // 118 + QST( &Infra9[0], TRUE, 5, TSFX_WITCH20 ), // 119 + QST( &Infra10[0], TRUE, 6, TSFX_PEGBOY18 ), // 120 + QST( &Mush1[0], TRUE, 5, TSFX_STORY21 ), // 121 + QST( &Mush2[0], TRUE, 5, TSFX_TAVERN19 ), // 122 + QST( &Mush3[0], TRUE, 5, TSFX_HEALER26 ), // 123 + QST( &Mush4[0], TRUE, 5, TSFX_HEALER27 ), // 124 + QST( &Mush5[0], TRUE, 7, TSFX_BMAID19 ), // 125 + QST( &Mush6[0], TRUE, 5, TSFX_SMITH19 ), // 126 + QST( &Mush7[0], TRUE, 5, TSFX_DRUNK20 ), // 127 + QST( &Mush8[0], TRUE, 5, TSFX_WITCH22 ), // 128 + QST( &Mush9[0], TRUE, 6, TSFX_WITCH23 ), // 129 + QST( &Mush10[0], TRUE, 5, TSFX_WITCH24 ), // 130 + QST( &Mush11[0], TRUE, 5, TSFX_WITCH25 ), // 131 + QST( &Mush12[0], TRUE, 6, TSFX_WITCH26 ), // 132 + QST( &Mush13[0], TRUE, 6, TSFX_PEGBOY19 ), // 133 + QST( &Doom1[0], TRUE, 2, TSFX_STORY22 ), // 134 + QST( &Doom2[0], TRUE, 6, TSFX_STORY23 ), // 135 + QST( &Doom3[0], TRUE, 5, TSFX_STORY24 ), // 136 + QST( &Doom4[0], TRUE, 6, TSFX_TAVERN20 ), // 137 + QST( &Doom5[0], TRUE, 6, TSFX_HEALER19 ), // 138 + QST( &Doom6[0], TRUE, 6, TSFX_BMAID20 ), // 139 + QST( &Doom7[0], TRUE, 6, TSFX_SMITH20 ), // 140 + QST( &Doom8[0], TRUE, 5, TSFX_DRUNK21 ), // 141 + QST( &Doom9[0], TRUE, 5, TSFX_WITCH21 ), // 142 + QST( &Doom10[0], TRUE, 5, TSFX_PEGBOY20 ), // 143 + QST( &Garbud1[0], TRUE, 6, USFX_GARBUD1 ), // 144 + QST( &Garbud2[0], TRUE, 6, USFX_GARBUD2 ), // 145 + QST( &Garbud3[0], TRUE, 6, USFX_GARBUD3 ), // 146 + QST( &Garbud4[0], TRUE, 6, USFX_GARBUD4 ), // 147 + QST( &Zhar1[0], TRUE, 6, USFX_ZHAR1 ), // 148 + QST( &Zhar2[0], TRUE, 7, USFX_ZHAR2 ), // 149 + sQST( &Story1[0], FALSE, 5, TSFX_STORY25 ), // 150 + QST( &Story2[0], TRUE, 6, TSFX_STORY26 ), // 151 + QST( &Story3[0], TRUE, 5, TSFX_STORY27 ), // 152 + QST( &Story4[0], TRUE, 5, TSFX_STORY28 ), // 153 + QST( &Story5[0], TRUE, 5, TSFX_STORY29 ), // 154 + QST( &Story6[0], TRUE, 5, TSFX_STORY30 ), // 155 + QST( &Story7[0], TRUE, 5, TSFX_STORY31 ), // 156 + QST( &Story9[0], TRUE, 5, TSFX_STORY33 ), // 157 + QST( &Story10[0], TRUE, 5, TSFX_STORY34 ), // 158 + QST( &Story11[0], TRUE, 5, TSFX_STORY35 ), // 159 + sQST( &Ogden1[0], FALSE, 5, TSFX_TAVERN36 ), // 160 + QST( &Ogden2[0], TRUE, 5, TSFX_TAVERN37 ), // 161 + QST( &Ogden3[0], TRUE, 6, TSFX_TAVERN38 ), // 162 + QST( &Ogden4[0], TRUE, 6, TSFX_TAVERN39 ), // 163 + QST( &Ogden5[0], TRUE, 6, TSFX_TAVERN40 ), // 164 + QST( &Ogden6[0], TRUE, 6, TSFX_TAVERN41 ), // 165 + QST( &Ogden8[0], TRUE, 6, TSFX_TAVERN43 ), // 166 + QST( &Ogden9[0], TRUE, 6, TSFX_TAVERN44 ), // 167 + QST( &Ogden10[0], TRUE, 6, TSFX_TAVERN45 ), // 168 + sQST( &Pepin1[0], FALSE, 5, TSFX_HEALER37 ), // 169 + QST( &Pepin2[0], TRUE, 5, TSFX_HEALER38 ), // 170 + QST( &Pepin3[0], TRUE, 5, TSFX_HEALER39 ), // 171 + QST( &Pepin4[0], TRUE, 5, TSFX_HEALER40 ), // 172 + QST( &Pepin5[0], TRUE, 5, TSFX_HEALER41 ), // 173 + QST( &Pepin6[0], TRUE, 5, TSFX_HEALER42 ), // 174 + QST( &Pepin7[0], TRUE, 5, TSFX_HEALER43 ), // 175 + QST( &Pepin9[0], TRUE, 5, TSFX_HEALER45 ), // 176 + QST( &Pepin10[0], TRUE, 5, TSFX_HEALER46 ), // 177 + QST( &Pepin11[0], TRUE, 6, TSFX_HEALER47 ), // 178 + sQST( &Gillian1[0], FALSE, 5, TSFX_BMAID31 ), // 179 + QST( &Gillian2[0], TRUE, 6, TSFX_BMAID32 ), // 180 + QST( &Gillian3[0], TRUE, 6, TSFX_BMAID33 ), // 181 + QST( &Gillian4[0], TRUE, 5, TSFX_BMAID34 ), // 182 + QST( &Gillian5[0], TRUE, 6, TSFX_BMAID35 ), // 183 + QST( &Gillian6[0], TRUE, 6, TSFX_BMAID36 ), // 184 + QST( &Gillian7[0], TRUE, 5, TSFX_BMAID37 ), // 185 + QST( &Gillian9[0], TRUE, 5, TSFX_BMAID39 ), // 186 + QST( &Gillian10[0], TRUE, 5, TSFX_BMAID40 ), // 187 + sQST( &Griswold1[0], FALSE, 5, TSFX_SMITH44 ), // 188 + QST( &Griswold2[0], TRUE, 5, TSFX_SMITH45 ), // 189 + QST( &Griswold3[0], TRUE, 5, TSFX_SMITH46 ), // 190 + QST( &Griswold4[0], TRUE, 5, TSFX_SMITH47 ), // 191 + QST( &Griswold5[0], TRUE, 6, TSFX_SMITH48 ), // 192 + QST( &Griswold6[0], TRUE, 5, TSFX_SMITH49 ), // 193 + QST( &Griswold7[0], TRUE, 6, TSFX_SMITH50 ), // 194 + QST( &Griswold8[0], TRUE, 5, TSFX_SMITH51 ), // 195 + QST( &Griswold9[0], TRUE, 5, TSFX_SMITH52 ), // 196 + QST( &Griswold10[0], TRUE, 6, TSFX_SMITH53 ), // 197 + QST( &Griswold12[0], TRUE, 5, TSFX_SMITH55 ), // 198 + QST( &Griswold13[0], TRUE, 5, TSFX_SMITH56 ), // 199 + sQST( &Farnham1[0], FALSE, 5, TSFX_DRUNK27 ), // 200 + QST( &Farnham2[0], TRUE, 6, TSFX_DRUNK28 ), // 201 + QST( &Farnham3[0], TRUE, 5, TSFX_DRUNK29 ), // 202 + QST( &Farnham4[0], TRUE, 5, TSFX_DRUNK30 ), // 203 + QST( &Farnham5[0], TRUE, 5, TSFX_DRUNK31 ), // 204 + QST( &Farnham6[0], TRUE, 5, TSFX_DRUNK32 ), // 205 + QST( &Farnham8[0], TRUE, 5, TSFX_DRUNK34 ), // 206 + QST( &Farnham9[0], TRUE, 5, TSFX_DRUNK35 ), // 207 + QST( &Farnham10[0], TRUE, 5, TSFX_DRUNK23 ), // 208 + QST( &Farnham11[0], TRUE, 5, TSFX_DRUNK24 ), // 209 + QST( &Farnham12[0], TRUE, 5, TSFX_DRUNK25 ), // 210 + QST( &Farnham13[0], TRUE, 5, TSFX_DRUNK26 ), // 211 + sQST( &Adria1[0], FALSE, 5, TSFX_WITCH38 ), // 212 + QST( &Adria2[0], TRUE, 5, TSFX_WITCH39 ), // 213 + QST( &Adria3[0], TRUE, 5, TSFX_WITCH40 ), // 214 + QST( &Adria4[0], TRUE, 5, TSFX_WITCH41 ), // 215 + QST( &Adria5[0], TRUE, 5, TSFX_WITCH42 ), // 216 + QST( &Adria6[0], TRUE, 5, TSFX_WITCH43 ), // 217 + QST( &Adria7[0], TRUE, 5, TSFX_WITCH44 ), // 218 + QST( &Adria8[0], TRUE, 5, TSFX_WITCH45 ), // 219 + QST( &Adria9[0], TRUE, 5, TSFX_WITCH46 ), // 220 + QST( &Adria10[0], TRUE, 5, TSFX_WITCH47 ), // 221 + QST( &Adria12[0], TRUE, 4, TSFX_WITCH49 ), // 222 + QST( &Adria13[0], TRUE, 4, TSFX_WITCH50 ), // 223 + sQST( &Wirt1[0], FALSE, 5, TSFX_PEGBOY32 ), // 224 + QST( &Wirt2[0], TRUE, 6, TSFX_PEGBOY33 ), // 225 + QST( &Wirt3[0], TRUE, 6, TSFX_PEGBOY34 ), // 226 + QST( &Wirt4[0], TRUE, 5, TSFX_PEGBOY35 ), // 227 + QST( &Wirt5[0], TRUE, 5, TSFX_PEGBOY36 ), // 228 + QST( &Wirt6[0], TRUE, 5, TSFX_PEGBOY37 ), // 229 + QST( &Wirt7[0], TRUE, 5, TSFX_PEGBOY38 ), // 230 + QST( &Wirt8[0], TRUE, 5, TSFX_PEGBOY39 ), // 231 + QST( &Wirt9[0], TRUE, 6, TSFX_PEGBOY40 ), // 232 + QST( &Wirt11[0], TRUE, 5, TSFX_PEGBOY42 ), // 233 + QST( &Wirt12[0], TRUE, 5, TSFX_PEGBOY43 ), // 234 + QST( &Boner[0], TRUE, 5, PS_WARR1 ), // 235 + QST( &Bloody[0], TRUE, 6, PS_WARR10 ), // 236 + QST( &Blinding[0], TRUE, 5, PS_WARR11 ), // 237 + QST( &Bloodwar[0], TRUE, 5, PS_WARR12 ), // 238 + QST( &Boner[0], TRUE, 5, PS_MAGE1 ), // 239 + QST( &Bloody[0], TRUE, 6, PS_MAGE10 ), // 240 + QST( &Blinding[0], TRUE, 4, PS_MAGE11 ), // 241 + QST( &Bloodwar[0], TRUE, 5, PS_MAGE12 ), // 242 + QST( &Boner[0], TRUE, 5, PS_ROGUE1 ), // 243 + QST( &Bloody[0], TRUE, 5, PS_ROGUE10 ), // 244 + QST( &Blinding[0], TRUE, 5, PS_ROGUE11 ), // 245 + QST( &Bloodwar[0], TRUE, 5, PS_ROGUE12 ), // 246 + sQST( &Cow1[0], FALSE, 5, TSFX_COW1 ), // 247 + sQST( &Cow1[0], FALSE, 5, TSFX_COW2 ), // 248 + QST( &Book11[0], TRUE, 5, PS_NAR1 ), // 249 + QST( &Book12[0], TRUE, 4, PS_NAR2 ), // 250 + QST( &Book13[0], TRUE, 3, PS_NAR3 ), // 251 + QST( &Book21[0], TRUE, 4, PS_NAR4 ), // 252 + QST( &Book22[0], TRUE, 5, PS_NAR5 ), // 253 + QST( &Book23[0], TRUE, 3, PS_NAR6 ), // 254 + QST( &Book31[0], TRUE, 4, PS_NAR7 ), // 255 + QST( &Book32[0], TRUE, 4, PS_NAR8 ), // 256 + QST( &Book33[0], TRUE, 3, PS_NAR9 ), // 257 + sQST( &Intro[0], TRUE, 5, TSFX_TAVERN0 ), // 258 + QST( &Boner[0], TRUE, 5, PS_MONK1 ), // 259 + QST( &Bloody[0], TRUE, 5, PS_MONK10 ), // 260 + QST( &Blinding[0], TRUE, 5, PS_MONK11 ), // 261 + QST( &Bloodwar[0], TRUE, 5, PS_MONK12 ), // 262 + QST( &Boner[0], TRUE, 5, PS_BARD1 ), // 263 + QST( &Bloody[0], TRUE, 5, PS_BARD10 ), // 264 + QST( &Blinding[0], TRUE, 5, PS_BARD11 ), // 265 + +// Link Text and Sound here JKEQUEST + QST( &Bloodwar[0], TRUE, 5, PS_BARD12 ), // 266 + QST( &CryptMap1[0], TRUE, 5, TSFX_WITCH19 ), // 267 + QST( &CryptMap2[0], TRUE, 5, TSFX_SMITH18 ), // 268 + QST( &CryptMap3[0], TRUE, 5, TSFX_HEALER17 ), // 269 + QST( &CryptMap4[0], TRUE, 5, TSFX_WITCH9 ), // 270 + QST( &CryptMap5[0], TRUE, 5, TSFX_TAVERN17 ), // 271 + QST( &CryptMap6[0], TRUE, 5, TSFX_STORY19 ), // 272 + QST( &CryptMap7[0], TRUE, 5, TSFX_DRUNK21 ), // 273 + QST( &CryptMap8[0], TRUE, 5, TSFX_BMAID27 ), // 274 + QST( &CryptMap9[0], TRUE, 5, TSFX_PEGBOY7 ), // 275 + QST( &CryptMap4[0], TRUE, 5, TSFX_WITCH9 ), // 276 + + QST( &Farmer1[0], TRUE, 3, HSFX_FARMER1 ), // 277 + QST( &Farmer2[0], TRUE, 5, HSFX_FARMER2 ), // 278 + QST( &Farmer3[0], TRUE, 5, HSFX_FARMER3 ), // 279 + QST( &Farmer4[0], TRUE, 5, HSFX_FARMER4 ), // 280 + QST( &Farmer5[0], TRUE, 5, HSFX_FARMER5 ), // 281 + + QST( &Theo1[0], TRUE, 5, HSFX_THEO1 ), // 282 + QST( &Theo2[0], TRUE, 5, HSFX_THEO2 ), // 283 + QST( &Theo3[0], TRUE, 5, HSFX_THEO3 ), // 284 + QST( &Theo4[0], TRUE, 5, HSFX_THEO4 ), // 285 + + QST( &Defiler6[0], TRUE, 5, HSFX_DEFILER6 ), // 286 + QST( &Defiler2[0], TRUE, 5, HSFX_DEFILER2 ), // 287 + QST( &Defiler7[0], TRUE, 5, HSFX_DEFILER7 ), // 288 + QST( &Defiler4[0], TRUE, 5, HSFX_DEFILER4 ), // 289 + QST( &Cow1[0], TRUE, 5, HSFX_DEFILER5 ), // 290 + + QST( &Cow1[0], TRUE, 5, HSFX_NA_KRUL1 ), // 291 + QST( &Cow1[0], TRUE, 5, HSFX_NA_KRUL2 ), // 292 + QST( &Cow1[0], TRUE, 5, HSFX_NA_KRUL3 ), // 293 + QST( &Cow1[0], TRUE, 5, HSFX_NA_KRUL4 ), // 294 + QST( &Cow1[0], TRUE, 5, HSFX_NA_KRUL5 ), // 295 + + QST( &Cornerstone1[0], TRUE, 2, HSFX_CORNERSTONE1), // 296 + + QST( &Cowsuit1[0], TRUE, 5, HSFX_COWSUIT1 ), // 297 + QST( &Cowsuit2[0], TRUE, 5, HSFX_COWSUIT2 ), // 298 + QST( &Cowsuit3[0], TRUE, 5, HSFX_COWSUIT3 ), // 299 + QST( &Cowsuit4[0], TRUE, 5, HSFX_COWSUIT4 ), // 300 + QST( &Cowsuit5[0], TRUE, 5, HSFX_COWSUIT5 ), // 301 + QST( &Cowsuit6[0], TRUE, 5, HSFX_COWSUIT6 ), // 302 + QST( &Cowsuit7[0], TRUE, 5, HSFX_COWSUIT7 ), // 303 + QST( &Cowsuit8[0], TRUE, 5, HSFX_COWSUIT8 ), // 304 + QST( &Cowsuit9[0], TRUE, 5, HSFX_COWSUIT9 ), // 305 + + QST( &Trader1[0], TRUE, 5, HSFX_TRADER1 ), // 306 + + QST( &Farmer2a[0], TRUE, 5, HSFX_FARMER2A ), // 307 + QST( &Farmer6[0], TRUE, 5, HSFX_FARMER6 ), // 308 + QST( &Farmer7[0], TRUE, 5, HSFX_FARMER7 ), // 309 + QST( &Farmer8[0], TRUE, 5, HSFX_FARMER8 ), // 310 + QST( &Farmer9[0], TRUE, 5, HSFX_FARMER9 ), // 311 + + QST( &Cowsuit10[0], TRUE, 5, HSFX_COWSUIT10 ), // 312 + QST( &Cowsuit11[0], TRUE, 5, HSFX_COWSUIT11 ), // 313 + QST( &Cowsuit12[0], TRUE, 5, HSFX_COWSUIT12 ), // 314 + QST( &Cowsuit4A[0], TRUE, 5, HSFX_COWSUIT4A ), // 315 + + QST( &Skulljrnl1[0], TRUE, 5, HSFX_SKULLJRNL1 ), // 316 + QST( &Skulljrnl2[0], TRUE, 5, HSFX_SKULLJRNL2 ), // 317 + QST( &Skulljrnl3[0], TRUE, 5, HSFX_SKULLJRNL3 ), // 318 + QST( &Skulljrnl4[0], TRUE, 5, HSFX_SKULLJRNL4 ), // 319 + QST( &Skulljrnl5[0], TRUE, 5, HSFX_SKULLJRNL5 ), // 320 + QST( &Skulljrnl6[0], TRUE, 5, HSFX_SKULLJRNL6 ), // 321 + QST( &Skulljrnl7[0], TRUE, 2, HSFX_SKULLJRNL7 ), // 322 + + QST( &Spell1[0], TRUE, 5, PS_WARR54 ), // 323 + QST( &Spell2[0], TRUE, 5, PS_WARR55 ), // 324 + QST( &Spell3[0], TRUE, 5, PS_WARR56 ), // 325 + + QST( &Spell1[0], TRUE, 5, PS_MONK54 ), // 323 + QST( &Spell2[0], TRUE, 5, PS_MONK55 ), // 324 + QST( &Spell3[0], TRUE, 5, PS_MONK56 ), // 325 + + QST( &Spell1[0], TRUE, 5, PS_MAGE54 ), // 323 + QST( &Spell2[0], TRUE, 5, PS_MAGE55 ), // 324 + QST( &Spell3[0], TRUE, 5, PS_MAGE56 ), // 325 + + QST( &Spell1[0], TRUE, 5, PS_ROGUE54 ), // 323 + QST( &Spell2[0], TRUE, 5, PS_ROGUE55 ), // 324 + QST( &Spell3[0], TRUE, 5, PS_ROGUE56 ), // 325 + + QST( &Spell1[0], TRUE, 5, PS_BARD54 ), // 323 + QST( &Spell2[0], TRUE, 5, PS_BARD55 ), // 324 + QST( &Spell3[0], TRUE, 5, PS_BARD56 ), // 325 + +}; + +const DWORD gdwAllTextEntries = sizeof(alltext) / sizeof(alltext[0]); diff --git a/src/TEXTDAT.H b/src/TEXTDAT.H new file mode 100644 index 0000000..21ad435 --- /dev/null +++ b/src/TEXTDAT.H @@ -0,0 +1,536 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ +// STORYTELLER ST +// TAVERN OWNER TO +// PRIEST P +// HEALER H +// BARMAID BM +// BLACKSMITH BS +// TOWN DRUNK TD +// WITCH W +// PEG-LEGGED BOY PB +/*-----------------------------------------------------------------------** +// QUESTS +**-----------------------------------------------------------------------*/ +// Skeleton King Quest +#define TXT_KINGST1 0 // ST +#define TXT_KINGTO1 1 // TO quest init +#define TXT_KINGTO2 2 // TO return before end +#define TXT_KINGTO3 3 // TO return upon completion +// P +#define TXT_KINGH1 4 // H +#define TXT_KINGBM1 5 // BM +#define TXT_KINGBS1 6 // BS +#define TXT_KINGTD1 7 // TD +#define TXT_KINGW1 8 // W +#define TXT_KINGPB1 9 // PB + +#define TXT_KING1 10 // Skeleton King + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Banner of Light Quest +#define TXT_BOLST1 11 // ST +#define TXT_BOLTO1 12 // TO quest init +#define TXT_BOLTO2 13 // TO return sign +// P +#define TXT_BOLH1 14 // H +#define TXT_BOLBM1 15 // BM +#define TXT_BOLBS1 16 // BS +#define TXT_BOLTD1 17 // TD +#define TXT_BOLW1 18 // W +#define TXT_BOLPB1 19 // PB + +#define TXT_BOL1 20 // Snotspil first time +#define TXT_BOL2 21 // Snotspil empty handed +#define TXT_BOL3 22 // Snotspil with sign + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Vile Betrayer Quest +#define TXT_VBST1 23 // ST quest not done +#define TXT_VBST2 24 // ST quest init +#define TXT_VBST3 25 // ST quest done +#define TXT_VBTO1 26 // TO +#define TXT_VBP3 27 // not in +#define TXT_VBP4 28 // not in +#define TXT_VBH1 29 // H +#define TXT_VBBM1 30 // BM +#define TXT_VBBS1 31 // BS +#define TXT_VBTD1 32 // TD +#define TXT_VBW1 33 // W +#define TXT_VBPB1 34 // PB + +#define TXT_VB1 35 // Lazurus before sacrafice +#define TXT_VB2 36 // Lazurus after sacrafice + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Poisoned Water Quest +#define TXT_PWST1 37 // ST +#define TXT_PWTO1 38 // TO +// P +#define TXT_PWH1 39 // H quest init +#define TXT_PWH2 40 // H return before done +#define TXT_PWH3 41 // H quest done +#define TXT_PWBM1 42 // BM +#define TXT_PWBS1 43 // BS +#define TXT_PWTD1 44 // TD +#define TXT_PWW1 45 // W +#define TXT_PWPB1 46 // PB + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// The Chamber of Bone Quest +#define TXT_BONEST1 47 // ST +#define TXT_BONETO1 48 // TO +// P +#define TXT_BONEH1 49 // H +#define TXT_BONEBM1 50 // BM +#define TXT_BONEBS1 51 // BS +#define TXT_BONETD1 52 // TD +#define TXT_BONEW1 53 // W +#define TXT_BONEPB1 54 // PB + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// The Butcher Quest +#define TXT_BUTCHST1 55 // ST +#define TXT_BUTCHTO1 56 // TO +// P +#define TXT_BUTCHH1 57 // H +#define TXT_BUTCHBM1 58 // BM +#define TXT_BUTCHBS1 59 // BS +#define TXT_BUTCHTD1 60 // TD +#define TXT_BUTCHW1 61 // W +#define TXT_BUTCHPB1 62 // PB + +#define TXT_BUTCH1 63 // Wounded Townsman +#define TXT_BUTCH2 64 // Butcher + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Halls of the Blind Quest +#define TXT_BLINDST1 65 // ST +#define TXT_BLINDTO1 66 // TO +// P +#define TXT_BLINDH1 67 // H +#define TXT_BLINDBM1 68 // BM +#define TXT_BLINDBS1 69 // BS +#define TXT_BLINDTD1 70 // TD +#define TXT_BLINDW1 71 // W +#define TXT_BLINDPB1 72 // PB + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Veil of Steel Quest +#define TXT_VEILST1 73 // ST +#define TXT_VEILTO1 74 // TO +// P +#define TXT_VEILH1 75 // H +#define TXT_VEILBM1 76 // BM +#define TXT_VEILBS1 77 // BS +#define TXT_VEILTD1 78 // TD +#define TXT_VEILW1 79 // W +#define TXT_VEILPB1 80 // PB + +#define TXT_VEIL1 81 // Lachdanan first time +#define TXT_VEIL2 82 // Lachdanan without elixir +#define TXT_VEIL3 83 // Lachdanan with elixir + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// The Anvil of Fury Quest +#define TXT_ANVILST1 84 // ST +#define TXT_ANVILTO1 85 // TO +// P +#define TXT_ANVILH1 86 // H +#define TXT_ANVILBM1 87 // BM +#define TXT_ANVILBS1 88 // BS +#define TXT_ANVILBS2 89 // BS +#define TXT_ANVILBS3 90 // BS +#define TXT_ANVILTD1 91 // TD +#define TXT_ANVILW1 92 // W +#define TXT_ANVILPB1 93 // PB + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Stones of Blood Quest +#define TXT_BLOODST1 94 // ST +#define TXT_BLOODTO1 95 // TO +// P +#define TXT_BLOODH1 96 // H +#define TXT_BLOODBM1 97 // BM +#define TXT_BLOODBS1 98 // BS +#define TXT_BLOODTD1 99 // TD +#define TXT_BLOODW1 100 // W +#define TXT_BLOODPB1 101 // PB + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Warlord of Blood Quest +#define TXT_WARLRDST1 102 // ST +#define TXT_WARLRDTO1 103 // TO +// P +#define TXT_WARLRDH1 104 // H +#define TXT_WARLRDBM1 105 // BM +#define TXT_WARLRDBS1 106 // BS +#define TXT_WARLRDTD1 107 // TD +#define TXT_WARLRDW1 108 // W +#define TXT_WARLRDPB1 109 // PB + +#define TXT_WARLRD1 110 // Warlord of the Blood + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Ring of Infravision Quest +#define TXT_INFRAST1 111 // ST +#define TXT_INFRATO1 112 // TO +// P +#define TXT_INFRAH1 113 // H +#define TXT_INFRABM1 114 // BM +#define TXT_INFRABS1 115 // BS +#define TXT_INFRABS2 116 // BS +#define TXT_INFRABS3 117 // BS +#define TXT_INFRATD1 118 // TD +#define TXT_INFRAW1 119 // W +#define TXT_INFRAPB1 120 // PB + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Black Mushroom Quest +#define TXT_BLKMST1 121 // ST +#define TXT_BLKMTO1 122 // TO +// P +#define TXT_BLKMH1 123 // H no brain +#define TXT_BLKMH2 124 // H with brain +#define TXT_BLKMBM1 125 // BM +#define TXT_BLKMBS1 126 // BS +#define TXT_BLKMTD1 127 // TD +#define TXT_BLKMW1 128 // W +#define TXT_BLKMW2 129 // W +#define TXT_BLKMW3 130 // W +#define TXT_BLKMW4 131 // W +#define TXT_BLKMW5 132 // W +#define TXT_BLKMPB1 133 // PB + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Map of Doom Quest +#define TXT_MODST1 134 // ST quest init +#define TXT_MODST2 135 // ST return before stars align and Diablo alive +#define TXT_MODST3 136 // ST return after stars align and Diablo alive +#define TXT_MODTO1 137 // TO +// P +#define TXT_MODH1 138 // H +#define TXT_MODBM1 139 // BM +#define TXT_MODBS1 140 // BS +#define TXT_MODTD1 141 // TD +#define TXT_MODW1 142 // W +#define TXT_MODPB1 143 // PB + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Garbud the Weak Quest + +#define TXT_GARB1 144 // Garbud first time +#define TXT_GARB2 145 // Garbud 2nd time +#define TXT_GARB3 146 // Garbud 3rd time +#define TXT_GARB4 147 // Garbud 4th time + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Zhar the Mad Quest + +#define TXT_ZHAR1 148 // Zhar 1st time +#define TXT_ZHAR2 149 // Zhar 2nd time + + +/*-----------------------------------------------------------------------** +// TOWNSPEOPLE'S NONQUEST +**-----------------------------------------------------------------------*/ +// Deckard Cain +#define TXT_STORY1 150 +#define TXT_STORY2 151 +#define TXT_STORY3 152 +#define TXT_STORY4 153 +#define TXT_STORY5 154 +#define TXT_STORY6 155 +#define TXT_STORY7 156 +#define TXT_STORY9 157 +#define TXT_STORY10 158 +#define TXT_STORY11 159 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Ogden +#define TXT_OGDEN1 160 +#define TXT_OGDEN2 161 +#define TXT_OGDEN3 162 +#define TXT_OGDEN4 163 +#define TXT_OGDEN5 164 +#define TXT_OGDEN6 165 +#define TXT_OGDEN8 166 +#define TXT_OGDEN9 167 +#define TXT_OGDEN10 168 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Pepin +#define TXT_PEPIN1 169 +#define TXT_PEPIN2 170 +#define TXT_PEPIN3 171 +#define TXT_PEPIN4 172 +#define TXT_PEPIN5 173 +#define TXT_PEPIN6 174 +#define TXT_PEPIN7 175 +#define TXT_PEPIN9 176 +#define TXT_PEPIN10 177 +#define TXT_PEPIN11 178 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Gillian +#define TXT_GILIAN1 179 +#define TXT_GILIAN2 180 +#define TXT_GILIAN3 181 +#define TXT_GILIAN4 182 +#define TXT_GILIAN5 183 +#define TXT_GILIAN6 184 +#define TXT_GILIAN7 185 +#define TXT_GILIAN9 186 +#define TXT_GILIAN10 187 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Griswold +#define TXT_GRIS1 188 +#define TXT_GRIS2 189 +#define TXT_GRIS3 190 +#define TXT_GRIS4 191 +#define TXT_GRIS5 192 +#define TXT_GRIS6 193 +#define TXT_GRIS7 194 +#define TXT_GRIS8 195 +#define TXT_GRIS9 196 +#define TXT_GRIS10 197 +#define TXT_GRIS12 198 +#define TXT_GRIS13 199 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Farnham +#define TXT_FARN1 200 +#define TXT_FARN2 201 +#define TXT_FARN3 202 +#define TXT_FARN4 203 +#define TXT_FARN5 204 +#define TXT_FARN6 205 +#define TXT_FARN8 206 +#define TXT_FARN9 207 +#define TXT_FARN10 208 +#define TXT_FARN11 209 +#define TXT_FARN12 210 +#define TXT_FARN13 211 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Adria +#define TXT_ADRIA1 212 +#define TXT_ADRIA2 213 +#define TXT_ADRIA3 214 +#define TXT_ADRIA4 215 +#define TXT_ADRIA5 216 +#define TXT_ADRIA6 217 +#define TXT_ADRIA7 218 +#define TXT_ADRIA8 219 +#define TXT_ADRIA9 220 +#define TXT_ADRIA10 221 +#define TXT_ADRIA12 222 +#define TXT_ADRIA13 223 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// Wirt +#define TXT_WIRT1 224 +#define TXT_WIRT2 225 +#define TXT_WIRT3 226 +#define TXT_WIRT4 227 +#define TXT_WIRT5 228 +#define TXT_WIRT6 229 +#define TXT_WIRT7 230 +#define TXT_WIRT8 231 +#define TXT_WIRT9 232 +#define TXT_WIRT11 233 +#define TXT_WIRT12 234 + + +/*-----------------------------------------------------------------------** +// BOOKS and SCROLLS as read by the heroes +**-----------------------------------------------------------------------*/ +// Warrior +#define TXT_WARBONE 235 // Skeletal Tome +#define TXT_WARBLOOD 236 // Book of Blood +#define TXT_WARBLIND 237 // Book of the Blind +#define TXT_WARLORD 238 // Steel Tome + +// Sorcerer +#define TXT_SORBONE 239 // Skeletal Tome +#define TXT_SORBLOOD 240 // Book of Blood +#define TXT_SORBLIND 241 // Book of the Blind +#define TXT_SORLORD 242 // Steel Tome + +// Rogue +#define TXT_ROGBONE 243 // Skeletal Tome +#define TXT_ROGBLOOD 244 // Book of Blood +#define TXT_ROGBLIND 245 // Book of the Blind +#define TXT_ROGLORD 246 // Steel Tome + +// Monk +// GWP Fix these if new quests are added. +#define TXT_MNKBONE 259 // Skeletal Tome +#define TXT_MNKBLOOD 260 // Book of Blood +#define TXT_MNKBLIND 261 // Book of the Blind +#define TXT_MNKLORD 262 // Steel Tome + +// Bard +#define TXT_BRDBONE 263 // Skeletal Tome +#define TXT_BRDBLOOD 264 // Book of Blood +#define TXT_BRDBLIND 265 // Book of the Blind +#define TXT_BRDLORD 266 // Steel Tome + +// Barbarian +#define TXT_BARBONE TXT_WARBONE +#define TXT_BARBLOOD TXT_WARBLOOD +#define TXT_BARBLIND TXT_WARBLIND +#define TXT_BARLORD TXT_WARLORD + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define TXT_COW1 247 // Cow1 +#define TXT_COW2 248 // Cow2 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +#define TXT_BOOK11 249 // Story Book Set 1, Book 1 +#define TXT_BOOK12 250 // Story Book Set 1, Book 2 +#define TXT_BOOK13 251 // Story Book Set 1, Book 3 +#define TXT_BOOK21 252 // Story Book Set 2, Book 1 +#define TXT_BOOK22 253 // Story Book Set 2, Book 2 +#define TXT_BOOK23 254 // Story Book Set 2, Book 3 +#define TXT_BOOK31 255 // Story Book Set 3, Book 1 +#define TXT_BOOK32 256 // Story Book Set 3, Book 2 +#define TXT_BOOK33 257 // Story Book Set 3, Book 3 + +#define TXT_INTRO 258 // Tavern owner intro + + +//----------------------------------------------------------------------- +// START OUR QUEST TEXT DEFINES HERE - JKEQUEST +//----------------------------------------------------------------------- +#define TXT_CRYPTMAP1 267 // Init text for crypt quest JKE +#define TXT_CRYPTMAP2 268 +#define TXT_CRYPTMAP3 269 +#define TXT_CRYPTMAP4 270 +#define TXT_CRYPTMAP5 271 +#define TXT_CRYPTMAP6 272 +#define TXT_CRYPTMAP7 273 +#define TXT_CRYPTMAP8 274 +#define TXT_CRYPTMAP9 275 +#define TXT_CRYPTMAP10 276 + +#define TXT_FARMER1 277 // Farmer explosion thing JKE +#define TXT_FARMER2 278 +#define TXT_FARMER3 279 +#define TXT_FARMER4 280 +#define TXT_FARMER5 281 +#define TXT_FARMER2A 307 +#define TXT_FARMER6 308 +#define TXT_FARMER7 309 +#define TXT_FARMER8 310 +#define TXT_FARMER9 311 + + +#define TXT_THEO1 282 // Theo the teddy bear +#define TXT_THEO2 283 +#define TXT_THEO3 284 +#define TXT_THEO4 285 + +#define TXT_DEFILER1 286 // The Defiler +#define TXT_DEFILER2 287 +#define TXT_DEFILER3 288 +#define TXT_DEFILER4 289 +#define TXT_DEFILER5 290 + +#define TXT_NA_KRUL1 291 // Na-Krul +#define TXT_NA_KRUL2 292 +#define TXT_NA_KRUL3 293 +#define TXT_NA_KRUL4 294 +#define TXT_NA_KRUL5 295 + +#define TXT_CORNERSTONE1 296 // Cornerstone of the world + +#define TXT_COWSUIT1 297 // Cow suit guy +#define TXT_COWSUIT2 298 +#define TXT_COWSUIT3 299 +#define TXT_COWSUIT4 300 +#define TXT_COWSUIT4A 315 +#define TXT_COWSUIT5 301 +#define TXT_COWSUIT6 302 +#define TXT_COWSUIT7 303 +#define TXT_COWSUIT8 304 +#define TXT_COWSUIT9 305 +#define TXT_COWSUIT10 312 +#define TXT_COWSUIT11 313 +#define TXT_COWSUIT12 314 + +#define TXT_TRADER1 306 + +#define TXT_SKULLJRNL1 316 +#define TXT_SKULLJRNL2 317 +#define TXT_SKULLJRNL3 318 +#define TXT_SKULLJRNL4 319 +#define TXT_SKULLJRNL5 320 +#define TXT_SKULLJRNL6 321 +#define TXT_SKULLJRNL7 322 + +#define TXT_SPELL1 323 +#define TXT_SPELL2 324 +#define TXT_SPELL3 325 + +#define TXT_M_SPELL1 326 +#define TXT_M_SPELL2 327 +#define TXT_M_SPELL3 328 + +#define TXT_S_SPELL1 329 +#define TXT_S_SPELL2 330 +#define TXT_S_SPELL3 331 + +#define TXT_R_SPELL1 332 +#define TXT_R_SPELL2 333 +#define TXT_R_SPELL3 334 + +#define TXT_B_SPELL1 335 +#define TXT_B_SPELL2 336 +#define TXT_B_SPELL3 337 + +#define TXT_C_SPELL1 TXT_SPELL1 +#define TXT_C_SPELL2 TXT_SPELL2 +#define TXT_C_SPELL3 TXT_SPELL3 + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ +extern const TextDataStruct alltext[]; +extern const DWORD gdwAllTextEntries; diff --git a/src/THEMES.CPP b/src/THEMES.CPP new file mode 100644 index 0000000..61cffb4 --- /dev/null +++ b/src/THEMES.CPP @@ -0,0 +1,1063 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Thematic rooms file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/THEMES.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "themes.h" +#include "gendung.h" +#include "engine.h" + +#include "objects.h" +#include "objdat.h" +#include "monster.h" +#include "monstdat.h" +#include "items.h" +#include "quests.h" +#include "trigs.h" + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +#define TOTAL_THEMES 17 + +#define THEME_NONE -1 +#define THEME_BARREL 0 +#define THEME_SHRINE 1 +#define THEME_MONSTPIT 2 +#define THEME_SKELRM 3 +#define THEME_TREASURE 4 +#define THEME_LIBRARY 5 +#define THEME_TORTURE 6 +#define THEME_BLOODFTN 7 +#define THEME_DECAP 8 +#define THEME_PURIFYINGFTN 9 +#define THEME_ARMORSTAND 10 +#define THEME_GOATSHRINE 11 +#define THEME_CAULDRON 12 +#define THEME_MURKYFTN 13 +#define THEME_TEARFTN 14 +#define THEME_BRNCROSS 15 +#define THEME_WEAPONRACK 16 + +/*-----------------------------------------------------------------------** +** Global variables +**-----------------------------------------------------------------------*/ + +ThemeStruct theme[MAXTHEMES]; +int numthemes; +int zharlib; + +int themex, themey; +int themeVar1; + +//Theme flags +BOOL armorFlag; +BOOL bFountainFlag; +BOOL cauldronFlag; +BOOL mFountainFlag; +BOOL pFountainFlag; +BOOL tFountainFlag; +BOOL treasureFlag; +BOOL bCrossFlag; +BOOL weaponFlag; + +/*-----------------------------------------------------------------------*/ +// List of themes that it trys to fit first + +#define THEME_NUMGOOD 4 + +int ThemeGood[THEME_NUMGOOD] = { + THEME_GOATSHRINE, + THEME_SHRINE, + THEME_SKELRM, + THEME_LIBRARY, +}; + +BOOL ThemeGoodIn[THEME_NUMGOOD]; + +/*-----------------------------------------------------------------------*/ + +// 5x5 area offsets +int trm5x[] = { -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2 }; +int trm5y[] = { -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 }; + +// 3x3 area offsets +int trm3x[] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 }; +int trm3y[] = { -1, -1, -1, 0, 0, 0, 1, 1, 1 }; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL TFit_Shrine(int i) +{ + int xp, yp, found; + + app_assert((DWORD)i < MAXTHEMES); + xp = 0; + yp = 0; + found = 0; + while (!found) { + if (dTransVal[xp][yp] == theme[i].ttval) { + if ((nTrapTable[dPiece[xp][yp-1]]) && + (!nSolidTable[dPiece[xp-1][yp]]) && + (!nSolidTable[dPiece[xp+1][yp]]) && + (dTransVal[xp-1][yp] == theme[i].ttval) && + (dTransVal[xp+1][yp] == theme[i].ttval) && + (dObject[xp-1][yp-1] == 0) && + (dObject[xp+1][yp-1] == 0)) found = 1; + if (!found) { + if ((nTrapTable[dPiece[xp-1][yp]]) && + (!nSolidTable[dPiece[xp][yp-1]]) && + (!nSolidTable[dPiece[xp][yp+1]]) && + (dTransVal[xp][yp-1] == theme[i].ttval) && + (dTransVal[xp][yp+1] == theme[i].ttval) && + (dObject[xp-1][yp-1] == 0) && + (dObject[xp-1][yp+1] == 0)) found = 2; + } + } + if (!found) { + xp++; + if (xp == DMAXX) { + xp = 0; + yp++; + if (yp == DMAXY) return(FALSE); + } + } + } + themex = xp; + themey = yp; + themeVar1 = found; + return(TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL TFit_Obj5(int t) +{ + int xp, yp; + int i, r, rs; + BOOL found; + + app_assert((DWORD)t < MAXTHEMES); + xp = 0; + yp = 0; + r = random(0, 5) + 1; + rs = r; + while (r > 0) { + found = FALSE; + if ((dTransVal[xp][yp] == theme[t].ttval) && (!nSolidTable[dPiece[xp][yp]])) { + found = TRUE; + for (i = 0; (found && (i < 25)); i++) { + if (nSolidTable[dPiece[xp+trm5x[i]][yp+trm5y[i]]]) found = FALSE; + if (dTransVal[xp+trm5x[i]][yp+trm5y[i]] != theme[t].ttval) found = FALSE; + } + } + if (!found) { + xp++; + if (xp == DMAXX) { + xp = 0; + yp++; + if (yp == DMAXY) { + if (r == rs) return(FALSE); + else yp = 0; + } + } + } else r--; + } + themex = xp; + themey = yp; + return(TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL TFit_SkelRoom(int t) +{ + int i; + + if (leveltype == 1 || leveltype == 2) + { + for (i = 0; i < nummtypes; i++) { + if (IsSkel(Monsters[i].mtype)) { + //Initialize themeVar1 to monster type skeleton + themeVar1 = i; + return TFit_Obj5(t); + } + } + } + + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL TFit_GoatShrine(int t) +{ + int i; + + for (i = 0; i < nummtypes; i++) { + if (IsGoat(Monsters[i].mtype)) { + //Initialize themeVar1 to monster type goat + themeVar1 = i; + return TFit_Obj5(t); + } + } + + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL CheckThemeObj3(int xp, int yp, int t, int f) +{ + app_assert((DWORD)t < MAXTHEMES); + for (int i = 0; i < 9; i++) { + if (xp+trm3x[i] < 0 || yp+trm3y[i] < 0) + return FALSE; + if (nSolidTable[dPiece[xp+trm3x[i]][yp+trm3y[i]]]) + return FALSE; + if (dTransVal[xp+trm3x[i]][yp+trm3y[i]] != theme[t].ttval) + return FALSE; + if (dObject[xp+trm3x[i]][yp+trm3y[i]] != 0) + return FALSE; + if (f != -1 && random(0, f) == 0) + return FALSE; + } + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL TFit_Obj3(int t) +{ + int xp, yp; + char objrnd[4] = { 4, 4, 3, 5 }; + + for (yp = 1; yp < DMAXY-1; yp++) { + for (xp = 1; xp < DMAXX-1; xp++) { + if (CheckThemeObj3(xp, yp, t, objrnd[leveltype-1])) { + themex = xp; + themey = yp; + return TRUE; + } + } + } + return FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL CheckThemeReqs(int t) +/*-----------------------------------------------------------------------** +** Description: Checks theme room requirements, such as themes for specific +** levels or themes which can only be used once per level. +** Input: None +** Return: TRUE = All requirements met +**-----------------------------------------------------------------------*/ +{ + BOOL rv = TRUE; + + switch(t) { + case THEME_SHRINE: + case THEME_LIBRARY: + if (leveltype == 3 || leveltype == 4) rv = FALSE; + break; + case THEME_SKELRM: + if (leveltype == 3 || leveltype == 4) rv = FALSE; + break; + case THEME_BLOODFTN: + if (!bFountainFlag) rv = FALSE; + break; + case THEME_PURIFYINGFTN: + if (!pFountainFlag) rv = FALSE; + break; + case THEME_MURKYFTN: + if (!mFountainFlag) rv = FALSE; + break; + case THEME_TEARFTN: + if (!tFountainFlag) rv = FALSE; + break; + case THEME_ARMORSTAND: + case THEME_WEAPONRACK: + if (leveltype == 1) rv = FALSE; + break; + case THEME_CAULDRON: + if ((leveltype != 4) || (!cauldronFlag)) rv = FALSE; + break; + } + + return rv; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL SpecialThemeFit(int i, int t) +{ + BOOL rv = TRUE; + + rv = CheckThemeReqs(t); + + switch(t) { + case THEME_SHRINE: + case THEME_LIBRARY: + if (rv) rv = TFit_Shrine(i); + break; + case THEME_SKELRM: + if (rv) rv = TFit_SkelRoom(i); + break; + case THEME_BLOODFTN: + if (rv) rv = TFit_Obj5(i); + //This is set so we only get one blood fountain per level + if (rv) bFountainFlag = FALSE; + break; + case THEME_PURIFYINGFTN: + if (rv) rv = TFit_Obj5(i); + //This is set so we only get one purifying fountain per level + if (rv) pFountainFlag = FALSE; + break; + case THEME_MURKYFTN: + if (rv) rv = TFit_Obj5(i); + //This is set so we only get one murky fountain per level + if (rv) mFountainFlag = FALSE; + break; + case THEME_TEARFTN: + if (rv) rv = TFit_Obj5(i); + //This is set so we only get one tear fountain per level + if (rv) tFountainFlag = FALSE; + break; + case THEME_CAULDRON: + if (rv) rv = TFit_Obj5(i); + //This is set so we only get one cauldron room per level + if (rv) cauldronFlag = FALSE; + break; + case THEME_GOATSHRINE: + if (rv) rv = TFit_GoatShrine(i); + break; + case THEME_DECAP: + case THEME_TORTURE: + case THEME_ARMORSTAND: + case THEME_BRNCROSS: + case THEME_WEAPONRACK: + if (rv) rv = TFit_Obj3(i); + break; + case THEME_TREASURE: + rv = treasureFlag; + //This is set so we only get one treasure room per level + if (rv) treasureFlag = FALSE; + break; + } + + return(rv); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL CheckThemeRoom(int tv) +{ + int i, j; + int tarea; + + for (i = 0; i < numtrigs; i++) { + if (dTransVal[trigs[i]._tx][trigs[i]._ty] == tv) return(FALSE); + } + + // Check area requirements + tarea = 0; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dTransVal[i][j] == tv) { + if (dFlags[i][j] & BFLAG_SETPC) return(FALSE); + tarea++; + } + } + } + + if (leveltype == 1) { + if ((tarea < 9) || (tarea > 100)) return(FALSE); + } + + // Make sure it is a solid room + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if ((dTransVal[i][j] == tv) && (!nSolidTable[dPiece[i][j]])) { + if ((dTransVal[i-1][j] != tv) && (!nSolidTable[dPiece[i-1][j]])) return(FALSE); + if ((dTransVal[i+1][j] != tv) && (!nSolidTable[dPiece[i+1][j]])) return(FALSE); + if ((dTransVal[i][j-1] != tv) && (!nSolidTable[dPiece[i][j-1]])) return(FALSE); + if ((dTransVal[i][j+1] != tv) && (!nSolidTable[dPiece[i][j+1]])) return(FALSE); + } + } + } + return(TRUE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitThemes() +{ + int i, t; + + numthemes = 0; + zharlib = -1; + //Initialize theme flags + armorFlag = TRUE; + bFountainFlag = TRUE; + cauldronFlag = TRUE; + mFountainFlag = TRUE; + pFountainFlag = TRUE; + tFountainFlag = TRUE; + treasureFlag = TRUE; + bCrossFlag = FALSE; + weaponFlag = TRUE; + + if (currlevel == 16) return; + + //Find L1 theme room types + if (leveltype == 1) { + for (i = 0; i < THEME_NUMGOOD; i++) ThemeGoodIn[i] = FALSE; + for (i = 0; (i < 256) && (numthemes < MAXTHEMES); i++) { + if (CheckThemeRoom(i)) { + theme[numthemes].ttval = i; + t = ThemeGood[random(0, THEME_NUMGOOD)]; // Normal + while (!SpecialThemeFit(numthemes, t)) t = random(0, TOTAL_THEMES); + theme[numthemes].ttype = t; + numthemes++; + } + } + } + + //Find L2, L3, L4 theme room types + if (leveltype == 2 || leveltype == 3 || leveltype == 4) + { + //Initialize theme room types + app_assert((DWORD)themeCount < MAXTHEMES); + for (i = 0; i < themeCount; i++) { + theme[i].ttype = THEME_NONE; + } + + //Special Quest + if (QuestStatus(Q_ZHAR)) { + for (i = 0; i < themeCount; i++) { + theme[i].ttval = themeLoc[i].ttval; + if (SpecialThemeFit(i, THEME_LIBRARY)) { + theme[i].ttype = THEME_LIBRARY; + zharlib = i; + break; + } + } + } + + //Add themeLoc array to general theme array + for (i = 0; i < themeCount; i++) { + if (theme[i].ttype == THEME_NONE) { + theme[i].ttval = themeLoc[i].ttval; + t = ThemeGood[random(0, THEME_NUMGOOD)]; + while (!SpecialThemeFit(i, t)) t = random(0, TOTAL_THEMES); + theme[i].ttype = t; + } + } + //Add L2 theme count to general theme count + numthemes += themeCount; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void HoldThemeRooms() +{ + int i, x, y; + char tv; + + if (currlevel == 16) return; + + app_assert((DWORD)numthemes < MAXTHEMES); + if (leveltype == 1) { + for (i = 0; i < numthemes; i++) { + tv = theme[i].ttval; + for (y = 0; y < DMAXY; y++) { + for (x = 0; x < DMAXX; x++) { + if (dTransVal[x][y] == tv) dFlags[x][y] |= BFLAG_SETPC; + } + } + } + } else { + //Hold L2,L3,L4 + DRLG_HoldThemeRooms(); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PlaceThemeMonsts(int t, int f) +{ + int xp, yp, mtype; + int scattertypes[LASTMT]; + int numscattypes = 0; + int i; + + app_assert((DWORD)t < MAXTHEMES); + for (i = 0; i < nummtypes; i++) + { + if (Monsters[i].mPlaceFlags & MPFLAG_SCATTER) + scattertypes[numscattypes++] = i; + } + mtype = scattertypes[random(0, numscattypes)]; + + for (yp = 0; yp < DMAXY; yp++) { + for (xp = 0; xp < DMAXX; xp++) { + if ((dTransVal[xp][yp] == theme[t].ttval) && + (!nSolidTable[dPiece[xp][yp]]) && + (dItem[xp][yp] == 0) && + (dObject[xp][yp] == 0)) { + if (random(0, f) == 0) AddMonster(xp, yp, random(0, 8), mtype, TRUE); + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void PlaceSpecificThemeMonsts(int t, int f, int mtype) +{ + int xp, yp; + + app_assert((DWORD)t < MAXTHEMES); + for (yp = 0; yp < DMAXY; yp++) { + for (xp = 0; xp < DMAXX; xp++) { + if ((dTransVal[xp][yp] == theme[t].ttval) && + (!nSolidTable[dPiece[xp][yp]]) && + (dItem[xp][yp] == 0) && + (dObject[xp][yp] == 0)) { + if (random(0, f) == 0) AddMonster(xp, yp, random(0, 8), mtype, TRUE); + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_Barrel(int t) +{ + int xp, yp, r; + char barrnd[4] = { 2, 6, 4, 8 }; + char monstrnd[4] = { 5, 7, 3, 9 }; + + app_assert((DWORD)t < MAXTHEMES); + for (yp = 0; yp < DMAXY; yp++) { + for (xp = 0; xp < DMAXX; xp++) { + if ((dTransVal[xp][yp] == theme[t].ttval) && (!nSolidTable[dPiece[xp][yp]])) { + if (!random(0, barrnd[leveltype-1])) { + if (!random(0, barrnd[leveltype-1])) r = OBJ_BARREL; + else r = OBJ_BARRELEX; + AddObject(r, xp, yp); + } + } + } + } + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_Shrine(int t) +{ + char monstrnd[4] = { 6, 6, 3, 9 }; + + TFit_Shrine(t); + if (themeVar1 == 1) { + AddObject(OBJ_CANDLE2, themex-1, themey); + AddObject(OBJ_SHRINER, themex, themey); + AddObject(OBJ_CANDLE2, themex+1, themey); + } else { + AddObject(OBJ_CANDLE2, themex, themey-1); + AddObject(OBJ_SHRINEL, themex, themey); + AddObject(OBJ_CANDLE2, themex, themey+1); + } + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_MonstPit(int t) +{ + int r, ixp, iyp; + char monstrnd[4] = { 6, 7, 3, 9 }; + + app_assert((DWORD)t < MAXTHEMES); + r = random(0, 100)+1; + ixp = 0; + iyp = 0; + while (r > 0) { + if ((dTransVal[ixp][iyp] == theme[t].ttval) && (!nSolidTable[dPiece[ixp][iyp]])) r--; + if (r > 0) { + ixp++; + if (ixp == DMAXX) { + ixp = 0; + iyp++; + if (iyp == DMAXY) iyp = 0; + } + } + } + CreateRndItem(ixp, iyp, TRUE, FALSE, TRUE); // Create a good item + ItemNoFlippy(); + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_SkelRoom(int t) +{ + int mt; + int xp, yp; + int ii; + char monstrnd[4] = { 6, 7, 3, 9 }; + + TFit_SkelRoom(t); + mt = themeVar1; + xp = themex; + yp = themey; + + AddObject(OBJ_SKFIRE, xp, yp); + if (random(0, monstrnd[leveltype-1])) { + ii = PreSpawnSkeleton(); + SpawnSkeleton(ii, xp-1, yp-1); + } else AddObject(OBJ_BANNERL, xp-1, yp-1); + ii = PreSpawnSkeleton(); + SpawnSkeleton(ii, xp, yp-1); + if (random(0, monstrnd[leveltype-1])) { + ii = PreSpawnSkeleton(); + SpawnSkeleton(ii, xp+1, yp-1); + } else AddObject(OBJ_BANNERR, xp+1, yp-1); + if (random(0, monstrnd[leveltype-1])) { + ii = PreSpawnSkeleton(); + SpawnSkeleton(ii, xp-1, yp); + } else AddObject(OBJ_BANNERM, xp-1, yp); + if (random(0, monstrnd[leveltype-1])) { + ii = PreSpawnSkeleton(); + SpawnSkeleton(ii, xp+1, yp); + } else AddObject(OBJ_BANNERM, xp+1, yp); + if (random(0, monstrnd[leveltype-1])) { + ii = PreSpawnSkeleton(); + SpawnSkeleton(ii, xp-1, yp+1); + } else AddObject(OBJ_BANNERR, xp-1, yp+1); + ii = PreSpawnSkeleton(); + SpawnSkeleton(ii, xp, yp+1); + if (random(0, monstrnd[leveltype-1])) { + ii = PreSpawnSkeleton(); + SpawnSkeleton(ii, xp+1, yp+1); + } else AddObject(OBJ_BANNERL, xp+1, yp+1); + + if (dObject[xp][yp-3] == 0) AddObject(OBJ_SKELBOOK, xp, yp-2); + if (dObject[xp][yp+3] == 0) AddObject(OBJ_SKELBOOK, xp, yp+2); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_Treasure(int t) +{ + int xp, yp, i; + char treasrnd[4] = { 4, 9, 7, 10 }; + char monstrnd[4] = { 6, 8, 3, 7 }; + + app_assert((DWORD)t < MAXTHEMES); + int rs = GetRndSeed(); + for (yp = 0; yp < DMAXY; yp++) + { + for (xp = 0; xp < DMAXX; xp++) + { + if ((dTransVal[xp][yp] == theme[t].ttval) && + (!nSolidTable[dPiece[xp][yp]])) + { + int rv = random(0, treasrnd[leveltype-1]); + if (!(random(0, treasrnd[leveltype-1])*2)) { + CreateTypeItem(xp, yp, FALSE, IT_GOLD, 0, FALSE, TRUE); + ItemNoFlippy(); + } + if (rv == 0) { + CreateRndItem(xp, yp, FALSE, FALSE, TRUE); + ItemNoFlippy(); + } + if ((rv == 0) || (rv >= (treasrnd[leveltype-1]-2))) { + i = ItemNoFlippy(); + if (rv >= (treasrnd[leveltype-1]-2) && leveltype != 1) + item[i]._ivalue = item[i]._ivalue >> 1; + } + } + } + } + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_Library(int t) +{ + int xp, yp, oi; + char librnd[4] = { 1, 2, 2, 5 }; + char monstrnd[4] = { 5, 7, 3, 9 }; + + TFit_Shrine(t); + if (themeVar1 == 1) { + AddObject(OBJ_BOOKCANDLE, themex-1, themey); + AddObject(OBJ_BOOKCASER, themex, themey); + AddObject(OBJ_BOOKCANDLE, themex+1, themey); + } else { + AddObject(OBJ_BOOKCANDLE, themex, themey-1); + AddObject(OBJ_BOOKCASEL, themex, themey); + AddObject(OBJ_BOOKCANDLE, themex, themey+1); + } + + for (yp = 1; yp < DMAXY-1; yp++) { + for (xp = 1; xp < DMAXX-1; xp++) { + if (CheckThemeObj3(xp, yp, t, -1) && + (dMonster[xp][yp] == 0) && // Zhar the mad fix + (!random(0, librnd[leveltype-1]))) { + AddObject(OBJ_BOOKSTAND, xp, yp); + // Pre used? + if (random(0, (librnd[leveltype-1] << 1))) { + oi = dObject[xp][yp]-1; + object[oi]._oSelFlag = OSEL_NONE; + object[oi]._oAnimFrame += 2; + } + } + } + } + + //special quest + if (QuestStatus(Q_ZHAR)) { + if (t != zharlib) PlaceThemeMonsts(t, monstrnd[leveltype]); + } + else PlaceThemeMonsts(t, monstrnd[leveltype]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_Torture(int t) +{ + int xp, yp; + char tortrnd[4] = { 6, 8, 3, 8 }; + char monstrnd[4] = { 6, 8, 3, 9 }; + + app_assert((DWORD)t < MAXTHEMES); + //Add tortured body + for (yp = 1; yp < DMAXY-1; yp++) { + for (xp = 1; xp < DMAXX-1; xp++) { + if ((dTransVal[xp][yp] == theme[t].ttval) && (!nSolidTable[dPiece[xp][yp]])) { + if (CheckThemeObj3(xp, yp, t, -1) && (!random(0, tortrnd[leveltype-1]))) + AddObject(OBJ_TNUDEM2, xp, yp); + } + } + } + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_BloodFountain(int t) +{ + char monstrnd[4] = { 6, 8, 3, 9 }; + + TFit_Obj5(t); + AddObject(OBJ_BLOODFTN, themex, themey); + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_Decap(int t) +{ + int xp, yp; + char decaprnd[4] = { 6, 8, 3, 8 }; + char monstrnd[4] = { 6, 8, 3, 9 }; + + app_assert((DWORD)t < MAXTHEMES); + //Add decapitated body + for (yp = 1; yp < DMAXY-1; yp++) { + for (xp = 1; xp < DMAXX-1; xp++) { + if ((dTransVal[xp][yp] == theme[t].ttval) && (!nSolidTable[dPiece[xp][yp]])) { + if (CheckThemeObj3(xp, yp, t, -1) && (!random(0, decaprnd[leveltype-1]))) + AddObject(OBJ_DECAP, xp, yp); + } + } + } + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_PurifyingFountain(int t) +{ + char monstrnd[4] = { 6, 7, 3, 9 }; + + TFit_Obj5(t); + AddObject(OBJ_PURIFYINGFTN, themex, themey); + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_ArmorStand(int t) +{ + int xp, yp; + char armorrnd[4] = { 6, 8, 3, 8 }; + char monstrnd[4] = { 6, 7, 3, 9 }; + + app_assert((DWORD)t < MAXTHEMES); + //Add functional stand w/ armor + if(armorFlag) { + TFit_Obj3(t); + AddObject(OBJ_ARMORSTAND, themex, themey); + } + //Add stand only + for (yp = 0; yp < DMAXY; yp++) { + for (xp = 0; xp < DMAXX; xp++) { + if ((dTransVal[xp][yp] == theme[t].ttval) && (!nSolidTable[dPiece[xp][yp]])) { + if (CheckThemeObj3(xp, yp, t, -1) && (!random(0, armorrnd[leveltype-1]))) + AddObject(OBJ_ARMORSTANDN, xp, yp); + } + } + } + PlaceThemeMonsts(t, monstrnd[leveltype-1]); + //This is set so we only get one functional armor stand per level + armorFlag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_GoatShrine(int t) +{ + int xx, yy; + + app_assert((DWORD)t < MAXTHEMES); + TFit_GoatShrine(t); + AddObject(OBJ_GOATSHRINE, themex, themey); + //Add goat monsters around shrine + for (yy = themey-1; yy <= themey+1; yy++) { + for (xx = themex-1; xx <= themex+1; xx++) { + if ((dTransVal[xx][yy] == theme[t].ttval) && + (!nSolidTable[dPiece[xx][yy]])) { + //Skip center monster since shrine is in the center + if (xx == themex && yy == themey) continue; + else AddMonster(xx, yy, 1, themeVar1, TRUE); + } + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_Cauldron(int t) +{ + char monstrnd[4] = { 6, 7, 3, 9 }; + + TFit_Obj5(t); + AddObject(OBJ_CAULDRON, themex, themey); + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_MurkyFountain(int t) +{ + char monstrnd[4] = { 6, 7, 3, 9 }; + + TFit_Obj5(t); + AddObject(OBJ_MURKYFTN, themex, themey); + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_TearFountain(int t) +{ + char monstrnd[4] = { 6, 7, 3, 9 }; + + TFit_Obj5(t); + AddObject(OBJ_TEARFTN, themex, themey); + PlaceThemeMonsts(t, monstrnd[leveltype-1]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_BrnCross(int t) +{ + int xp, yp; + + char monstrnd[4] = { 6, 8, 3, 9 }; + char bcrossrnd[4] = { 5, 7, 3, 8 }; + + app_assert((DWORD)t < MAXTHEMES); + for (yp = 0; yp < DMAXY; yp++) { + for (xp = 0; xp < DMAXX; xp++) { + if ((dTransVal[xp][yp] == theme[t].ttval) && (!nSolidTable[dPiece[xp][yp]])) { + if (CheckThemeObj3(xp, yp, t, -1) && (!random(0, bcrossrnd[leveltype-1]))) + AddObject(OBJ_TBCROSS, xp, yp); + } + } + } + PlaceThemeMonsts(t, monstrnd[leveltype-1]); + //Set so we know a burning cross theme room has been created on the level. + bCrossFlag = TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void Theme_WeaponRack(int t) +{ + int xp, yp; + char weaponrnd[4] = { 6, 8, 5, 8 }; + char monstrnd[4] = { 6, 7, 3, 9 }; + + app_assert((DWORD)t < MAXTHEMES); + //Add functional rack w/ weapon + if(weaponFlag) { + TFit_Obj3(t); + AddObject(OBJ_WEAPONRACK, themex, themey); + } + //Add rack only + for (yp = 0; yp < DMAXY; yp++) { + for (xp = 0; xp < DMAXX; xp++) { + if ((dTransVal[xp][yp] == theme[t].ttval) && (!nSolidTable[dPiece[xp][yp]])) { + if (CheckThemeObj3(xp, yp, t, -1) && (!random(0, weaponrnd[leveltype-1]))) + AddObject(OBJ_WEAPONRACKN, xp, yp); + } + } + } + PlaceThemeMonsts(t, monstrnd[leveltype-1]); + //This is set so we only get one functional weapon rack per level + weaponFlag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void UpdateL4Trans() +{ + int i, j; + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dTransVal[i][j] != 0) + dTransVal[i][j] = 1; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CreateThemeRooms() +{ + int i; + + if (currlevel == 16) return; + + InitObjFlag = TRUE; + app_assert((DWORD)numthemes < MAXTHEMES); + for (i = 0; i < numthemes; i++) { + themex = 0; + themey = 0; + switch(theme[i].ttype) { + case THEME_BARREL: + Theme_Barrel(i); + break; + case THEME_SHRINE: + Theme_Shrine(i); + break; + case THEME_MONSTPIT: + Theme_MonstPit(i); + break; + case THEME_SKELRM: + Theme_SkelRoom(i); + break; + case THEME_TREASURE: + Theme_Treasure(i); + break; + case THEME_LIBRARY: + Theme_Library(i); + break; + case THEME_TORTURE: + Theme_Torture(i); + break; + case THEME_BLOODFTN: + Theme_BloodFountain(i); + break; + case THEME_DECAP: + Theme_Decap(i); + break; + case THEME_PURIFYINGFTN: + Theme_PurifyingFountain(i); + break; + case THEME_ARMORSTAND: + Theme_ArmorStand(i); + break; + case THEME_GOATSHRINE: + Theme_GoatShrine(i); + break; + case THEME_CAULDRON: + Theme_Cauldron(i); + break; + case THEME_TEARFTN: + Theme_TearFountain(i); + break; + case THEME_MURKYFTN: + Theme_MurkyFountain(i); + break; + case THEME_BRNCROSS: + Theme_BrnCross(i); + break; + case THEME_WEAPONRACK: + Theme_WeaponRack(i); + break; + } + } + InitObjFlag = FALSE; + + //Update L4 trans values to get rid of blinking + if (leveltype == 4 && themeCount > 0) UpdateL4Trans(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + + diff --git a/src/THEMES.H b/src/THEMES.H new file mode 100644 index 0000000..2cb039e --- /dev/null +++ b/src/THEMES.H @@ -0,0 +1,43 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/THEMES.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAXTHEMES 50 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + char ttype; + int ttval; +} ThemeStruct; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern ThemeStruct theme[MAXTHEMES]; +extern int numthemes; +extern int zharlib; +extern BOOL armorFlag; +extern BOOL bCrossFlag; +extern BOOL weaponFlag; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitThemes(); +void HoldThemeRooms(); +void CreateThemeRooms(); diff --git a/src/TMSG.CPP b/src/TMSG.CPP new file mode 100644 index 0000000..ef95bdc --- /dev/null +++ b/src/TMSG.CPP @@ -0,0 +1,88 @@ +//****************************************************************** +// tmsg.cpp +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "engine.h" + + +//****************************************************************** +// timed messages +//****************************************************************** +typedef struct TTimedMsg { + struct TTimedMsg * pNext; + long lTime; + BYTE bLen; + BYTE bData[1]; +} TTimedMsg; + +#define TIMED_MSG_DELAY 500 // ticks +static TTimedMsg * sgpTimedMsgHead; + + +//****************************************************************** +//****************************************************************** +DWORD tmsg_get(BYTE * pbMsg,DWORD dwMaxLen) { + app_assert(pbMsg); + + // any msgs? + if (! sgpTimedMsgHead) return 0; + + // is it time to get this msg? + if (sgpTimedMsgHead->lTime - (long) GetTickCount() >= 0) return 0; + + // dequeue msg + TTimedMsg * ptMsg = sgpTimedMsgHead; + sgpTimedMsgHead = sgpTimedMsgHead->pNext; + + // get msg data + BYTE bLen = ptMsg->bLen; + app_assert(bLen); + app_assert(bLen <= dwMaxLen); + CopyMemory(pbMsg,ptMsg->bData,bLen); + + // free msg + DiabloFreePtr(ptMsg); + + return bLen; +} + + +//****************************************************************** +//****************************************************************** +void tmsg_add(const BYTE * pbMsg,BYTE bLen) { + app_assert(pbMsg); + app_assert(bLen); + + // allocate a new message buffer for this message + TTimedMsg * ptMsg = (TTimedMsg *) DiabloAllocPtrSig(sizeof(TTimedMsg) + bLen,'TMSG'); + ptMsg->pNext = NULL; + ptMsg->lTime = (long) GetTickCount() + TIMED_MSG_DELAY; + ptMsg->bLen = bLen; + CopyMemory(ptMsg->bData,pbMsg,bLen); + + // add to tail of list + TTimedMsg ** ppMsg = &sgpTimedMsgHead; + while (*ppMsg) ppMsg = &(*ppMsg)->pNext; + *ppMsg = ptMsg; +} + + +//****************************************************************** +//****************************************************************** +void tmsg_init() { + app_assert(! sgpTimedMsgHead); +} + + +//****************************************************************** +//****************************************************************** +void tmsg_free() { + while (sgpTimedMsgHead) { + TTimedMsg * pNext = sgpTimedMsgHead->pNext; + DiabloFreePtr(sgpTimedMsgHead); + sgpTimedMsgHead = pNext; + } +} diff --git a/src/TOWN.CPP b/src/TOWN.CPP new file mode 100644 index 0000000..461bca0 --- /dev/null +++ b/src/TOWN.CPP @@ -0,0 +1,1808 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Town file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/TOWN.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "engine.h" +#include "scrollrt.h" +#include "scrlasm.h" +#include "gendung.h" + +#include "items.h" +#include "cursor.h" +#include "trigs.h" +#include "control.h" +#include "gamemenu.h" + +#include "player.h" +#include "monster.h" + +#include "town.h" +#include "towners.h" +#include "inv.h" +#include "quests.h" +#include "minitext.h" +#include "stores.h" +#include "effects.h" + +#include "automap.h" +#include "help.h" +#include "error.h" +#include "doom.h" +#include "multi.h" + +#define T_POUTC 165 + +// #define TESTINGCRYPT // JKE set this to keep the crypt open + +#if RLE_DRAW +void DrawUnit (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawUnitClipped (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawUnitOutline(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +void DrawUnitOutlineClipped(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +#endif + +static void T_DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag); +static void T_DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, int yp, BOOL chflag); +static void T_DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, int yp, BOOL chflag); +void plrmsg_draw(); + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TDrawBlankMini(BYTE *pDecodeTo) +{ + app_assert(gpBuffer); + __asm { + mov edi,dword ptr [pDecodeTo] // Dest + + mov edx,30 + mov ebx,1 + xor eax,eax + //mov eax,0d3d3d3d3h +_BLp1: cmp edi,dword ptr [glClipY] + jb _Done + add edi,edx + mov ecx,ebx + rep stosd + add edi,edx + sub edi,NBUFFW64 + or edx,edx + jz _Bb + sub edx,2 + inc ebx + jmp _BLp1 + +_Bb: mov edx,2 + mov ebx,15 +_BLp2: cmp edi,dword ptr [glClipY] + jb _Done + add edi,edx + mov ecx,ebx + rep stosd + add edi,edx + sub edi,NBUFFW64 + dec ebx + add edx,2 + cmp edx,32 + jnz _BLp2 +_Done: nop + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TCDrawBlankMini(BYTE *pDecodeTo) +{ + app_assert(gpBuffer); + __asm { + mov edi,dword ptr [pDecodeTo] // Dest + + mov edx,30 + mov ebx,1 + xor eax,eax + //mov eax,0d3d3d3d3h +_BLp1: cmp edi,dword ptr [glClipY] + jb _C1 + add edi,64 + jmp _C2 +_C1: add edi,edx + mov ecx,ebx + rep stosd + add edi,edx +_C2: sub edi,NBUFFW64 + or edx,edx + jz _Bb + sub edx,2 + inc ebx + jmp _BLp1 + +_Bb: mov edx,2 + mov ebx,15 +_BLp2: cmp edi,dword ptr [glClipY] + jb _C3 + add edi,64 + jmp _C4 +_C3: add edi,edx + mov ecx,ebx + rep stosd + add edi,edx +_C4: sub edi,NBUFFW64 + dec ebx + add edx,2 + cmp edx,32 + jnz _BLp2 + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_CDrawSpecial(BYTE *pTo, long nCel) +{ +/* + long RLELen; + long nBufferW; + app_assert(gpBuffer); + __asm { + mov ebx,dword ptr [pSpecialCels] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] + sub eax,dword ptr [ebx] + mov dword ptr [RLELen],eax + mov esi,dword ptr [pSpecialCels] + add esi,dword ptr [ebx] + + mov edi,dword ptr [pTo] // Dest + + mov eax,832 // Increase width + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [RLELen] + add ebx,esi + +_T1Lp1: mov edx,64 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [glClipY] + jb _T1C1 + add esi,eax + add edi,eax + jmp _T1x +_T1C1: mov ecx,eax + shr ecx,1 + jnc _T1w + movsb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + movsw + jecxz _T1x +_T1Lp3: rep movsd +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 + } +*/ +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_DrawSpecial(BYTE *pTo, int nCel) +{ +/* + long RLELen; + long nBufferW; + app_assert(gpBuffer); + __asm { + mov ebx,dword ptr [pSpecialCels] + mov eax,dword ptr [nCel] + shl eax,2 + add ebx,eax + mov eax,dword ptr [ebx+4] + sub eax,dword ptr [ebx] + mov dword ptr [RLELen],eax + mov esi,dword ptr [pSpecialCels] + add esi,dword ptr [ebx] + + mov edi,dword ptr [pTo] // Dest + + mov eax,832 // Increase width + mov dword ptr [nBufferW],eax + + mov ebx,dword ptr [RLELen] + add ebx,esi + +_T1Lp1: mov edx,64 + +_T1Lp2: xor eax,eax // Load control byte + lodsb + or al,al + js _T1J + + sub edx,eax + cmp edi,dword ptr [glClipY] + jb _Done + mov ecx,eax + shr ecx,1 + jnc _T1w + movsb + jecxz _T1x +_T1w: shr ecx,1 + jnc _T1Lp3 + movsw + jecxz _T1x +_T1Lp3: rep movsd +_T1x: or edx,edx + jz _T1Nxt + jmp _T1Lp2 + +_T1J: neg al // Do jump + add edi,eax + sub edx,eax + jnz _T1Lp2 +_T1Nxt: sub edi,dword ptr [nBufferW] + cmp ebx,esi + jnz _T1Lp1 +_Done: nop + } +*/ +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_DrawEFlag1(BYTE *pTo2, int sx, int sy, int xp, int yp) +{ + BYTE *pTo; + int t; + WORD *mt; + + pTo = pTo2; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + for(t = 0; t < 12; t += 2) + { + if (gdwPNum = mt[t]) DrawMTileClipBottom (pTo); + if (gdwPNum = mt[t+1]) DrawMTileClipBottom (pTo+32); + pTo -= NBUFFWSL5; + } + + T_DrawHTLXsub (pTo2, sx, sy, xp, yp, FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void T_DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag) +{ + int pxp,pyp; + char bv; + int mi; + + app_assert(gpBuffer); + pTo = gpBuffer + nBuffWTbl[yp] + xp; + if (dItem[sx][sy] != 0) { + bv = dItem[sx][sy] - 1; + pxp = xp - item[bv]._iAnimWidth2; + if (bv == cursitem) COutlineSlabCel(181, pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, 8); + CDrawSlabCel(pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, 8); + } + if ((dFlags[sx][sy] & BFLAG_MONSTLR) != 0) { + mi = -(dMonster[sx][sy-1] + 1); + pxp = xp - towner[mi]._tAnimWidth2; + pyp = yp; + if (mi == cursmonst) COutlineSlabCel(166, pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, 8); + CDrawSlabCel(pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, 8); + } + if (dMonster[sx][sy] > 0) { + mi = dMonster[sx][sy] - 1; + pxp = xp - towner[mi]._tAnimWidth2; + pyp = yp; + if (mi == cursmonst) COutlineSlabCel(166, pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, 8); + CDrawSlabCel(pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, 8); + } + if ((dFlags[sx][sy] & BFLAG_PLRLR) != 0) { + bv = -(dPlayer[sx][sy-1] + 1); + pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; + pyp = plr[bv]._pyoff + yp; + + #if RLE_DRAW + if (bv == cursplr) DrawUnitOutlineClipped(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); + DrawUnitClipped(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); + #else + if (bv == cursplr) COutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); + CDrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); + #endif + + if (chflag) + { +// if (plr[bv]._peflag == 2) T_DrawEFlag1(pTo-NBUFFWSL4+96, sx-2, sy+1, xp-96, yp-16); + if (plr[bv]._peflag != 0) T_DrawEFlag1(pTo-64, sx-1, sy+1, xp-64, yp); + } + } + if (dFlags[sx][sy] & BFLAG_DEADPLR) + DrawDeadPlr(sx, sy, xp, yp, 0, 8, TRUE); + if (dPlayer[sx][sy] > 0) { + bv = dPlayer[sx][sy] - 1; + pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; + pyp = plr[bv]._pyoff + yp; + + #if RLE_DRAW + if (bv == cursplr) DrawUnitOutlineClipped(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); + DrawUnitClipped(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); + #else + if (bv == cursplr) COutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); + CDrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); + #endif + + if (chflag) + { +// if (plr[bv]._peflag == 2) T_DrawEFlag1(pTo-NBUFFWSL4+96, sx-2, sy+1, xp-96, yp-16); + if (plr[bv]._peflag != 0) T_DrawEFlag1(pTo-64, sx-1, sy+1, xp-64, yp); + } + } + if ((dFlags[sx][sy] & BFLAG_MISSILE) != 0) CDrawMissile(sx, sy, xp, yp, 0, 8, FALSE); + if (dSpecial[sx][sy]) T_CDrawSpecial(pTo, dSpecial[sx][sy]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_DrawHTileLineX (int sx, int sy, int xp, int yp, int nd, int halfflag) +{ + int i; + BYTE *pTo; + int t; + WORD *mt; + + app_assert(gpBuffer); + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + if (gdwPNum = dPiece[sx][sy]) { + pTo = gpBuffer + nBuffWTbl[yp] + xp + 32; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 1; t < 17; t += 2) + { + if (gdwPNum = mt[t]) DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + } + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + T_DrawHTLXsub (pTo, sx, sy, xp, yp, FALSE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + sx++; + sy--; + xp += 64; + } + + nd -= halfflag; + for (i = 0; i < nd; i++) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gdwPNum = dPiece[sx][sy]; + if (gdwPNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 0; t < 16; t+= 2) + { + if (gdwPNum = mt[t]) DrawMTileClipBottom (pTo); + if (gdwPNum = mt[t+1]) DrawMTileClipBottom (pTo+32); + pTo -= NBUFFWSL5; + } + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + T_DrawHTLXsub (pTo, sx, sy, xp, yp, TRUE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + sx++; + sy--; + xp += 64; + } + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gdwPNum = dPiece[sx][sy]; + if (gdwPNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 0; t < 16; t+= 2) + { + if (gdwPNum = mt[t]) DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + } + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + T_DrawHTLXsub (pTo, sx, sy, xp, yp, FALSE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_DrawEFlag2(BYTE *pTo2, int sx, int sy, int sv, int sv2, int xp, int yp) +{ + BYTE *pTo; + int t; + WORD *mt; + + if (sv == 0) pTo = pTo2; + else + pTo = pTo2 + (NBUFFWSL5 * sv); + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 0; t < 6; t++) + { + if (sv <= t) { + if (gdwPNum = mt[2*t+2]) DrawMTileClipBottom (pTo); + if (gdwPNum = mt[2*t+3]) DrawMTileClipBottom (pTo+32); + } + pTo -= NBUFFWSL5; + } + + if (sv2 < 8) { + T_DrawHTLXsub2 (pTo2, sx, sy, sv, sv2, xp, yp, FALSE); + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void T_DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, int yp, BOOL chflag) +{ + int pxp,pyp; + char bv; + int mi; + + if (dItem[sx][sy] != 0) { + bv = dItem[sx][sy] - 1; + pxp = xp - item[bv]._iAnimWidth2; + if (bv == cursitem) COutlineSlabCel(181, pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, sv2, 8); + CDrawSlabCel(pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, sv2, 8); + } + if ((dFlags[sx][sy] & BFLAG_MONSTLR) != 0) { + mi = -(dMonster[sx][sy-1] + 1); + pxp = xp - towner[mi]._tAnimWidth2; + pyp = yp; + if (mi == cursmonst) COutlineSlabCel(166, pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, sv2, 8); + CDrawSlabCel(pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, sv2, 8); + } + if (dMonster[sx][sy] > 0) { + mi = dMonster[sx][sy] - 1; + pxp = xp - towner[mi]._tAnimWidth2; + pyp = yp; + if (mi == cursmonst) COutlineSlabCel(166, pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, sv2, 8); + CDrawSlabCel(pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, sv2, 8); + } + if ((dFlags[sx][sy] & BFLAG_PLRLR) != 0) { + bv = -(dPlayer[sx][sy-1] + 1); + pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; + pyp = plr[bv]._pyoff + yp; + + #if RLE_DRAW + if (bv == cursplr) DrawUnitOutlineClipped(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); + DrawUnitClipped(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); + #else + if (bv == cursplr) COutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); + CDrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); + #endif + + if (chflag) + { +// if (plr[bv]._peflag == 2) T_DrawEFlag2(pTo-NBUFFWSL4+96, sx-2, sy+1, sv, sv2, xp-96, yp-16); + if (plr[bv]._peflag != 0) T_DrawEFlag2(pTo-64, sx-1, sy+1, sv, sv2, xp-64, yp); + } + } + if (dFlags[sx][sy] & BFLAG_DEADPLR) + DrawDeadPlr(sx, sy, xp, yp, sv2, 8, TRUE); + if (dPlayer[sx][sy] > 0) { + bv = dPlayer[sx][sy] - 1; + pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; + pyp = plr[bv]._pyoff + yp; + + #if RLE_DRAW + if (bv == cursplr) DrawUnitOutlineClipped(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); + DrawUnitClipped(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); + #else + if (bv == cursplr) COutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); + CDrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); + #endif + + if (chflag) + { +// if (plr[bv]._peflag == 2) T_DrawEFlag2(pTo-NBUFFWSL4+96, sx-2, sy+1, sv, sv2, xp-96, yp-16); + if (plr[bv]._peflag != 0) T_DrawEFlag2(pTo-64, sx-1, sy+1, sv, sv2, xp-64, yp); + } + } + if ((dFlags[sx][sy] & BFLAG_MISSILE) != 0) CDrawMissile(sx, sy, xp, yp, sv2, 8, FALSE); + if (dSpecial[sx][sy]) T_CDrawSpecial(pTo+nBuffWTbl[sv2<<4], dSpecial[sx][sy]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_DrawHTLX2 (int sx, int sy, int xp, int yp, int nd, int sv, int halfflag) +{ + int i; + BYTE *pTo; + int sv2; + int t; + WORD *mt; + + app_assert(gpBuffer); + sv2 = (sv + 1) << 1; + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + if (gdwPNum = dPiece[sx][sy]) { + pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5 + 32; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 0; t < 7; t++) + { + if ((sv <= t) && (gdwPNum = mt[2*t+3])) DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + } + + if (sv2 < 8) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + T_DrawHTLXsub2 (pTo, sx, sy, sv, sv2, xp, yp, FALSE); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + sx++; + sy--; + xp += 64; + } + + nd -= halfflag; + for (i = 0; i < nd; i++) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gdwPNum = dPiece[sx][sy]; + if (gdwPNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + for(t = 0; t < 7; t++) + { + if (sv <= t) { + if (gdwPNum = mt[2*t+2]) DrawMTileClipBottom (pTo); + if (gdwPNum = mt[2*t+3]) DrawMTileClipBottom (pTo+32); + } + pTo -= NBUFFWSL5; + } + + if (sv2 < 8) { + pTo = gpBuffer + nBuffWTbl[yp] + xp - (sv2 * NBUFFWSL4); + T_DrawHTLXsub2 (pTo, sx, sy, sv, sv2, xp, yp, TRUE); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + sx++; + sy--; + xp += 64; + } + + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gdwPNum = dPiece[sx][sy]; + if (gdwPNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 0; t < 7; t++) + { + if ((sv <= t) && (gdwPNum = mt[2*t+2])) DrawMTileClipBottom (pTo); + pTo -= NBUFFWSL5; + } + + if (sv2 < 8) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + T_DrawHTLXsub2 (pTo, sx, sy, sv, sv2, xp, yp, FALSE); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TCDrawBlankMini(pTo); + } + } + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_DrawEFlag3(BYTE *pTo2, int sx, int sy, int ev, int ev2, int xp, int yp) +{ + BYTE *pTo; + int t; + WORD *mt; + + pTo = pTo2; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 0; t < 7; t++) + { + if (ev >= t) { + if (gdwPNum = mt[2*t]) DrawMTileClipTop (pTo); + if (gdwPNum = mt[2*t+1]) DrawMTileClipTop (pTo+32); + } + pTo -= NBUFFWSL5; + } + + T_DrawHTLXsub3 (pTo2, sx, sy, ev, ev2, xp, yp, FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void T_DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, int yp, BOOL chflag) +{ + int pxp,pyp; + char bv; + int mi; + + if (dItem[sx][sy] != 0) { + bv = dItem[sx][sy] - 1; + pxp = xp - item[bv]._iAnimWidth2; + if (bv == cursitem) OutlineSlabCel(181, pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, ev2); + app_assert(item[bv]._iAnimData); + DrawSlabCel(pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, ev2); + } + if ((dFlags[sx][sy] & BFLAG_MONSTLR) != 0) { + mi = -(dMonster[sx][sy-1] + 1); + pxp = xp - towner[mi]._tAnimWidth2; + pyp = yp; + if (mi == cursmonst) OutlineSlabCel(166, pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, ev2); + app_assert(towner[mi]._tAnimData); + DrawSlabCel(pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, ev2); + } + if (dMonster[sx][sy] > 0) { + mi = dMonster[sx][sy] - 1; + pxp = xp - towner[mi]._tAnimWidth2; + pyp = yp; + if (mi == cursmonst) OutlineSlabCel(166, pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, ev2); + app_assert(towner[mi]._tAnimData); + DrawSlabCel(pxp, pyp, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, ev2); + } + if ((dFlags[sx][sy] & BFLAG_PLRLR) != 0) { + bv = -(dPlayer[sx][sy-1] + 1); + pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; + pyp = plr[bv]._pyoff + yp; + + #if RLE_DRAW + if (bv == cursplr) DrawUnitOutline(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); + app_assert(plr[bv]._pAnimData); + DrawUnit(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); + #else + if (bv == cursplr) OutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); + app_assert(plr[bv]._pAnimData); + DrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); + #endif + + if (chflag) + { +// if (plr[bv]._peflag == 2) T_DrawEFlag3(pTo-NBUFFWSL4-96, sx-2, sy+1, ev, ev2, xp-96, yp-16); + if (plr[bv]._peflag != 0) T_DrawEFlag3(pTo-64, sx-1, sy+1, ev, ev2, xp-64, yp); + } + } + if (dFlags[sx][sy] & BFLAG_DEADPLR) + DrawDeadPlr(sx, sy, xp, yp, 0, ev2, FALSE); + if (dPlayer[sx][sy] > 0) { + bv = dPlayer[sx][sy] - 1; + pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; + pyp = plr[bv]._pyoff + yp; + + #if RLE_DRAW + if (bv == cursplr) DrawUnitOutline(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); + app_assert(plr[bv]._pAnimData); + DrawUnit(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); + #else + if (bv == cursplr) OutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); + app_assert(plr[bv]._pAnimData); + DrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); + #endif + + if (chflag) + { +// if (plr[bv]._peflag == 2) T_DrawEFlag3(pTo-NBUFFWSL4-96, sx-2, sy+1, ev, ev2, xp-96, yp-16); + if (plr[bv]._peflag != 0) T_DrawEFlag3(pTo-64, sx-1, sy+1, ev, ev2, xp-64, yp); + } + } + if ((dFlags[sx][sy] & BFLAG_MISSILE) != 0) DrawMissile(sx, sy, xp, yp, 0, ev2, FALSE); + if (dSpecial[sx][sy]) T_DrawSpecial(pTo, dSpecial[sx][sy]); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_DrawHTLX3 (int sx, int sy, int xp, int yp, int nd, int ev, int halfflag) +{ + int i; + BYTE *pTo; + int ev2; + int t; + WORD *mt; + + app_assert(gpBuffer); + ev2 = (ev + 1) << 1; + if (ev2 > 8) ev2 = 8; + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + if (gdwPNum = dPiece[sx][sy]) { + pTo = gpBuffer + nBuffWTbl[yp] + xp + 32; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 0; t < 7; t++) + { + if ((ev >= t) && (gdwPNum = mt[2*t+1])) DrawMTileClipTop (pTo); + pTo -= NBUFFWSL5; + } + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + T_DrawHTLXsub3 (pTo, sx, sy, ev, ev2, xp, yp, FALSE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TDrawBlankMini(pTo); + } + sx++; + sy--; + xp += 64; + } + + nd -= halfflag; + for (i = 0; i < nd; i++) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gdwPNum = dPiece[sx][sy]; + if (gdwPNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + for(t = 0; t < 7; t++) + { + if (ev >= t) { + if (gdwPNum = mt[2*t]) DrawMTileClipTop (pTo); + if (gdwPNum = mt[2*t+1]) DrawMTileClipTop (pTo+32); + } + pTo -= NBUFFWSL5; + } + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + T_DrawHTLXsub3 (pTo, sx, sy, ev, ev2, xp, yp, TRUE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TDrawBlankMini(pTo); + } + sx++; + sy--; + xp += 64; + } + + if (halfflag != 0) { + if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { + gdwPNum = dPiece[sx][sy]; + if (gdwPNum != 0) { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + mt = &dMT2[CalcRot(sx,sy)].mt[0]; + + for(t = 0; t < 7; t++) + { + if ((ev >= t) && (gdwPNum = mt[2*t])) DrawMTileClipTop (pTo); + pTo -= NBUFFWSL5; + } + + pTo = gpBuffer + nBuffWTbl[yp] + xp; + T_DrawHTLXsub3 (pTo, sx, sy, ev, ev2, xp, yp, FALSE); + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TDrawBlankMini(pTo); + } + } else { + pTo = gpBuffer + nBuffWTbl[yp] + xp; + TDrawBlankMini(pTo); + } + } + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_SVGADrawView (int StartX, int StartY) +{ + int xpos, ypos; + int i; + int width,height; + + ViewDX = 640; + ViewDY = 352; + ViewBX = 10; + ViewBY = 11; + + xpos = 64 + ScrollInfo._sxoff; + ypos = 175 + ScrollInfo._syoff; + StartX -= 10; + StartY -= 1; + width = 10; + height = 5; + + if (chrflag || questlog) { + StartX += 2; + StartY -= 2; + xpos += 288; + width = 6; + } + if (invflag || sbookflag) { + StartX += 2; + StartY -= 2; + xpos -= 32; + width = 6; + } + + switch (ScrollInfo._sdir) { + case SCRL_NONE : + break; + case SCRL_U : + ypos -= 32; + StartX--; + StartY--; + height++; + break; + case SCRL_UR : + ypos -= 32; + StartX--; + StartY--; + width++; + height++; + break; + case SCRL_R : + width++; + break; + case SCRL_DR : + width++; + height++; + break; + case SCRL_D : + height++; + break; + case SCRL_DL : + xpos -= 64; + StartX--; + StartY++; + width++; + height++; + break; + case SCRL_L : + xpos -= 64; + StartX--; + StartY++; + width++; + break; + case SCRL_UL : + xpos -= 64; + ypos -= 32; + StartX -= 2; + width++; + height++; + break; + } + + app_assert(gpBuffer); + glClipY = (long)gpBuffer + nBuffWTbl[160]; + for (i = 0; i < 7; i++) { + T_DrawHTLX3(StartX, StartY, xpos, ypos, width, i, 0); + StartY++; + xpos -= 32; + ypos += 16; + T_DrawHTLX3(StartX, StartY, xpos, ypos, width, i, 1); + StartX++; + xpos += 32; + ypos += 16; + } + app_assert(gpBuffer); + glClipY = (long)gpBuffer + nBuffWTbl[512]; + for (i = 0; i < height; i++) { + T_DrawHTileLineX(StartX, StartY, xpos, ypos, width, 0); + StartY++; + xpos -= 32; + ypos += 16; + T_DrawHTileLineX(StartX, StartY, xpos, ypos, width, 1); + StartX++; + xpos += 32; + ypos += 16; + } + for (i = 0; i < 7; i++) { + T_DrawHTLX2(StartX, StartY, xpos, ypos, width, i, 0); + StartY++; + xpos -= 32; + ypos += 16; + T_DrawHTLX2(StartX, StartY, xpos, ypos, width, i, 1); + StartX++; + xpos += 32; + ypos += 16; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_VGADrawView (int StartX, int StartY) +{ + int xpos, ypos; + int i; + int width,height; + long csrc, cdest, cw; + + ViewDX = 384; + ViewDY = 192; + ViewBX = 6; + ViewBY = 6; + + xpos = 64 + ScrollInfo._sxoff; + ypos = 143 + ScrollInfo._syoff; + StartX -= 6; + StartY -= 1; + width = 6; + height = 0; + + switch (ScrollInfo._sdir) { + case SCRL_NONE : + break; + case SCRL_U : + ypos -= 32; + StartX--; + StartY--; + height++; + break; + case SCRL_UR : + ypos -= 32; + StartX--; + StartY--; + width++; + height++; + break; + case SCRL_R : + width++; + break; + case SCRL_DR : + width++; + height++; + break; + case SCRL_D : + height++; + break; + case SCRL_DL : + xpos -= 64; + StartX--; + StartY++; + width++; + height++; + break; + case SCRL_L : + xpos -= 64; + StartX--; + StartY++; + width++; + break; + case SCRL_UL : + xpos -= 64; + ypos -= 32; + StartX -= 2; + width++; + height++; + break; + } + + app_assert(gpBuffer); + glClipY = (long)gpBuffer + nBuffWTbl[143]; + for (i = 0; i < 7; i++) { + T_DrawHTLX3(StartX, StartY, xpos, ypos, width, i, 0); + StartY++; + xpos -= 32; + ypos += 16; + T_DrawHTLX3(StartX, StartY, xpos, ypos, width, i, 1); + StartX++; + xpos += 32; + ypos += 16; + } + app_assert(gpBuffer); + glClipY = (long)gpBuffer + nBuffWTbl[320]; + for (i = 0; i < height; i++) { + T_DrawHTileLineX(StartX, StartY, xpos, ypos, width, 0); + StartY++; + xpos -= 32; + ypos += 16; + T_DrawHTileLineX(StartX, StartY, xpos, ypos, width, 1); + StartX++; + xpos += 32; + ypos += 16; + } + for (i = 0; i < 7; i++) { + T_DrawHTLX2(StartX, StartY, xpos, ypos, width, i, 0); + StartY++; + xpos -= 32; + ypos += 16; + T_DrawHTLX2(StartX, StartY, xpos, ypos, width, i, 1); + StartX++; + xpos += 32; + ypos += 16; + } + + if (chrflag || questlog) { + csrc = 245168; + cdest = 392064; + cw = 160; + } else { + if (invflag || sbookflag) { + csrc = 245168; + cdest = 391744; + cw = 160; + } else { + csrc = 245088; + cdest = 391744; + cw = 320; + } + } + // Double res copy + app_assert(gpBuffer); + __asm { + mov esi,[gpBuffer] + mov edx,[cdest] + mov edi,esi + mov ecx,[csrc] + add edi,edx + add esi,ecx + mov ebx,edi + add ebx,768 + + mov edx,176 +_YLp: + mov ecx,[cw] +_XLp: + mov al,[esi] + inc esi + mov ah,al + mov [edi],ax + mov [ebx],ax + add edi,2 + add ebx,2 + dec ecx + jnz _XLp + mov eax,768 + add eax,[cw] + sub esi,eax + add eax,eax + sub ebx,eax + sub edi,eax + dec edx + jnz _YLp + } +/* // Double res copy (Old) + app_assert(gpBuffer); + __asm { + mov esi,dword ptr [gpBuffer] + mov edi,esi + add esi,dword ptr [csrc] + add edi,dword ptr [cdest] + mov ebx,edi + add ebx,768 + + mov edx,176 +_YLp: mov ecx,dword ptr [cw] +_XLp: lodsb + mov ah,al + stosw + mov word ptr [ebx],ax + add ebx,2 + loop _XLp + mov eax,768 + add eax,dword ptr [cw] + sub esi,eax + add eax,eax + sub ebx,eax + sub edi,eax + dec edx + jnz _YLp + }*/ +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_DrawView (int StartX, int StartY) +{ +/* __asm { + mov edi,dword ptr [gpBuffer] + add edi,122944 + + mov edx,352 + mov eax,092929292h // yellow + //xor eax,eax // black +_YLp: mov ecx,160 + rep stosd + add edi,128 + dec edx + jnz _YLp + }*/ + + // Non-town draw routines use nLVal and nTrans as global params, + // but in town all tiles are fully lit, and there are no transparent + // walls, so we set them here once for the whole screen + nLVal = 0; + nTrans = 0; + + if (svgamode) T_SVGADrawView (StartX, StartY); + else T_VGADrawView (StartX, StartY); + if (automapflag) DrawAutomap(); + if ((stextflag) && (!qtextflag)) DrawSText(); + if (invflag) DrawInv(); + else if (sbookflag) DrawSpellBook(); + + DrawDurIcon(); + + if (chrflag) DrawChr(); + else if (questlog) DrawQuestLog(); + else if ((plr[myplr]._pStatPts != 0) && (!spselflag)) DrawLevelUpIcon(); + + if (uitemflag) DrawUniqueInfo(); + if (qtextflag) DrawQText(); + if (spselflag) DrawSpellList(); + if (dropGoldFlag) DrawGoldBox(dropGoldValue); + if (helpflag) DrawHelp(); + if (msgflag) DrawDiabloMsg(); + if (PauseMode && !deathflag) DrawPause(); + + plrmsg_draw(); + + gmenu_draw(); + + DrawMapOfDoom(); + + DrawInfoBox(); + DrawHealthTop(); + DrawManaTop(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_SetDungeonMicros() +{ + int wv; + int i,j; + int t; + WORD *mtsource; + WORD *mt; + + // Init the light values for each piece + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + wv = dPiece[i][j]; + mt = &dMT2[CalcRot(i,j)].mt[0]; + if (wv != 0) { + wv--; + mtsource = (WORD *)(pMiniTiles + 32*wv); + for(t = 0; t < 16; t++) + // MiniTiles array uses opposite y direction + // hence wierd index on next line + mt[t] = mtsource[14-(t&0xe)+(t&1)]; + } else { + for(t = 0; t < 16; t++) + mt[t] = 0; + } + } + } + +#if 0 + int xmp,ymp,nPNum; + int s; + WORD tempmt[16]; + + // Zero micro tile values for each piece + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + mt = &dMT2[CalcRot(i,j)].mt[0]; + for(t = 0; t < 16; t++) + tempmt[t] = 0; + + nPNum = mt[0]; + if (((nPNum & 0x7000) == 0x4000) && (nPNum)) tempmt[0] = 1; + nPNum = mt[1]; + if (((nPNum & 0x7000) == 0x5000) && (nPNum != 0)) tempmt[1] = 1; + + for(t = 2; t < 16; t++) + { + nPNum = mt[t]; + if (((nPNum & 0x7000) == 0) && nPNum) + { + tempmt[t] = 1; + xmp = i; + ymp = j; + for(s = t-2; s >= 0 && xmp > 0 && ymp > 0; s -= 2) + { + xmp--; + ymp--; + dMT2[CalcRot(xmp,ymp)].mt[s] = 0; + } + } + } + + for(t = 0; t < 13; t += 2) + { + if(tempmt[t] && tempmt[t+2]) + { + xmp = i-1; + ymp = j; + for(s = t+1; s >= 0 && xmp >= 0 && ymp >= 0; s -= 2) + { + dMT2[CalcRot(xmp,ymp)].mt[s] = 0; + xmp--; + ymp--; + } + } + } + for(t = 1; t < 14; t += 2) + { + if(tempmt[t] && tempmt[t+2]) + { + xmp = i; + ymp = j-1; + for(s = t+1; s >= 0 && xmp >= 0 && ymp >= 0; s -= 2) + { + dMT2[CalcRot(xmp,ymp)].mt[s] = 0; + xmp--; + ymp--; + } + } + } + + } + } +#endif + + if (svgamode) { + ViewDX = 640; + ViewDY = 352; + ViewBX = 10; + ViewBY = 11; + } else { + ViewDX = 384; + ViewDY = 224; + ViewBX = 6; + ViewBY = 7; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_FillSector (BYTE *P3Tiles, BYTE *pSector, int xi, int yi, int w, int h) +{ + int i,j,xx,yy; + long v1,v2,v3,v4,ii; + + // Convert dungeon mega tiles to mini tiles + ii = 4; + yy = yi; + for (j = 0; j < h; j++) { + xx = xi; + for (i = 0; i < w; i++) { + __asm { + mov esi,dword ptr [pSector] + mov eax,dword ptr [ii] + add esi,eax + xor eax,eax + lodsw + or eax,eax + jz _Zero + dec eax + mov esi,dword ptr [P3Tiles] + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + jmp _Done +_Zero: mov dword ptr [v1],eax + mov dword ptr [v2],eax + mov dword ptr [v3],eax + mov dword ptr [v4],eax +_Done: nop + } + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; + xx += 2; + ii += 2; + } + yy += 2; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void T_FillTile(BYTE *P3Tiles, int xx, int yy, int t) +{ + long v1,v2,v3,v4; + + // Convert dungeon mega tiles to mini tiles + __asm { + mov eax,dword ptr [t] + dec eax + mov esi,dword ptr [P3Tiles] + shl eax,3 + add esi,eax + xor eax,eax + lodsw + inc eax + mov dword ptr [v1],eax + lodsw + inc eax + mov dword ptr [v2],eax + lodsw + inc eax + mov dword ptr [v3],eax + lodsw + inc eax + mov dword ptr [v4],eax + jmp _Done + mov dword ptr [v1],eax + mov dword ptr [v2],eax + mov dword ptr [v3],eax + mov dword ptr [v4],eax +_Done: nop + } + dPiece[xx][yy] = (int) v1; + dPiece[xx+1][yy] = (int) v2; + dPiece[xx][yy+1] = (int) v3; + dPiece[xx+1][yy+1] = (int) v4; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void OpenNest() +{ + dPiece[78][60] = 1162; // shadow at fork + dPiece[79][60] = 1163; + dPiece[78][61] = 1164; + dPiece[79][61] = 1294; + + dPiece[78][62] = 1262; // bridge + dPiece[78][63] = 1264; + dPiece[79][62] = 1296; + dPiece[79][63] = 1297; + + dPiece[79][64] = 1298; // second shadow + dPiece[78][64] = 282; + dPiece[78][65] = 284; + dPiece[79][65] = 285; + + dPiece[80][60] = 1299; // start tile of thing + dPiece[80][61] = 1301; + dPiece[81][61] = 1302; + + dPiece[82][60] = 1303; // second tile of thing + dPiece[83][60] = 1304; + dPiece[82][61] = 1305; + dPiece[83][61] = 1306; + + dPiece[80][62] = 1307; // third tile of thing + dPiece[81][62] = 1308; + dPiece[80][63] = 1309; + dPiece[81][63] = 1310; + + dPiece[80][64] = 1311; // forth tile of thing + dPiece[81][64] = 1312; + dPiece[80][65] = 1313; + dPiece[81][65] = 1314; + + dPiece[82][64] = 1319; // fifth tile of thing + dPiece[83][64] = 1320; + dPiece[82][65] = 1321; + dPiece[83][65] = 1322; + + dPiece[82][62] = 1315; // sixth tile of thing + dPiece[83][62] = 1316; + dPiece[82][63] = 1317; + dPiece[83][63] = 1318; + + dPiece[84][61] = 280; // remove tree + dPiece[84][62] = 280; + dPiece[84][63] = 280; +// dPiece[85][59] = 11; + dPiece[85][60] = 280; + dPiece[85][61] = 280; + dPiece[85][62] = 8; + dPiece[85][63] = 8; + dPiece[85][64] = 8; + dPiece[86][60] = 217; + dPiece[86][61] = 24; + dPiece[85][62] = 19; +// dPiece[86][62] = 11; +// dPiece[86][63] = 11; +// dPiece[86][64] = 11; + dPiece[84][64] = 280; +// dPiece[86][65] = 11; + T_SetDungeonMicros(); +} +void CloseNest() +{ + dPiece[78][60] = 1162; // shadow at fork + dPiece[79][60] = 1259; + dPiece[78][61] = 1260; + dPiece[79][61] = 1261; + + dPiece[78][62] = 1262; // bridge + dPiece[79][62] = 1263; + dPiece[78][63] = 1264; + dPiece[79][63] = 1265; + + dPiece[78][64] = 1266; // second shadow + dPiece[79][64] = 1267; + dPiece[78][65] = 1268; + + dPiece[80][60] = 1269; // start tile of thing + dPiece[81][60] = 1270; + dPiece[80][61] = 1271; + dPiece[81][61] = 1272; + + dPiece[82][60] = 1273; // second tile of thing + dPiece[83][60] = 1274; + dPiece[82][61] = 1275; + dPiece[83][61] = 1276; + + dPiece[80][62] = 1277; // third tile of thing + dPiece[81][62] = 1278; + dPiece[80][63] = 1279; + dPiece[81][63] = 1280; + + dPiece[80][64] = 1281; // forth tile of thing + dPiece[81][64] = 1282; + dPiece[80][65] = 1283; + dPiece[81][65] = 1284; + + dPiece[82][64] = 1289; // fifth tile of thing + dPiece[83][64] = 1290; + dPiece[82][65] = 1291; + dPiece[83][65] = 1292; + + dPiece[82][62] = 1285; // sixth tile of thing + dPiece[83][62] = 1286; + dPiece[82][63] = 1287; + dPiece[83][63] = 1288; + + dPiece[84][61] = 280; // remove tree + dPiece[84][62] = 280; + dPiece[84][63] = 280; +// dPiece[85][59] = 11; + dPiece[85][60] = 280; + dPiece[85][61] = 280; + dPiece[85][62] = 8; + dPiece[85][63] = 8; + dPiece[85][64] = 8; + dPiece[86][60] = 217; + dPiece[86][61] = 24; + dPiece[85][62] = 19; +// dPiece[86][62] = 11; +// dPiece[86][63] = 11; +// dPiece[86][64] = 11; + dPiece[84][64] = 280; +// dPiece[86][65] = 11; + T_SetDungeonMicros(); +} + +void CloseCrypt() +{ + dPiece[36][21] = 1323; + dPiece[37][21] = 1324; + dPiece[36][22] = 1325; + dPiece[37][22] = 1326; + + dPiece[36][23] = 1327; + dPiece[37][23] = 1328; + dPiece[36][24] = 1329; + dPiece[37][24] = 1330; + + dPiece[35][21] = 1339; + dPiece[34][21] = 1340; +// dPiece[34][22] = 1341; +// dPiece[35][22] = 1342; + + + T_SetDungeonMicros(); +} + +void OpenCrypt() +{ + dPiece[36][21] = 1331; + dPiece[37][21] = 1332; + dPiece[36][22] = 1333; + dPiece[37][22] = 1334; + + dPiece[36][23] = 1335; + dPiece[37][23] = 1336; + dPiece[36][24] = 1337; + dPiece[37][24] = 1338; + + dPiece[35][21] = 1339; + dPiece[34][21] = 1340; +// dPiece[34][22] = 1341; +// dPiece[35][22] = 1342; + + + T_SetDungeonMicros(); +} + +void T_Pass3() +{ + BYTE *P3Tiles; + BYTE *pSector; + int xx,yy; + + // Init Dungeon to blank + for (yy = 0; yy < DMAXY; yy+=2) { + for (xx = 0; xx < DMAXX; xx+=2) { + dPiece[xx][yy] = 0; + dPiece[xx+1][yy] = 0; + dPiece[xx][yy+1] = 0; + dPiece[xx+1][yy+1] = 0; + } + } + + // Load convertion tiles + P3Tiles = LoadFileInMemSig("Levels\\TownData\\Town.TIL",NULL,'TOWN'); + + // Load map sector + pSector = LoadFileInMemSig("Levels\\TownData\\Sector1s.DUN",NULL,'TOWN'); + T_FillSector(P3Tiles, pSector, 46, 46, 25, 25); + DiabloFreePtr(pSector); + + pSector = LoadFileInMemSig("Levels\\TownData\\Sector2s.DUN",NULL,'TOWN'); + T_FillSector(P3Tiles, pSector, 46, 0, 25, 23); + DiabloFreePtr(pSector); + + pSector = LoadFileInMemSig("Levels\\TownData\\Sector3s.DUN",NULL,'TOWN'); + T_FillSector(P3Tiles, pSector, 0, 46, 23, 25); + DiabloFreePtr(pSector); + + pSector = LoadFileInMemSig("Levels\\TownData\\Sector4s.DUN",NULL,'TOWN'); + T_FillSector(P3Tiles, pSector, 0, 0, 23, 23); + DiabloFreePtr(pSector); + +#ifdef TESTINGCRYPT + quests[Q_CRYPTMAP]._qactive = QUEST_DONE; +#endif + + +#if IS_VERSION(SHAREWARE) + // Close Maus shortcut + T_FillTile(P3Tiles, 48, 20, 320); + // Close cave shortcut + T_FillTile(P3Tiles, 16, 68, 332); + T_FillTile(P3Tiles, 16, 70, 331); + // Close crev shortcut + for (xx = 36; xx < 46; xx++) T_FillTile(P3Tiles, xx, 78, random(0,4)+1); +#else + if (gbMaxPlayers == 1) { + if ((quests[Q_FARMER]._qactive == QUEST_DONE) || (quests[Q_FARMER]._qactive == QUEST_REALLYDONE) + || (quests[Q_COWSUIT]._qactive == QUEST_DONE) || (quests[Q_COWSUIT]._qactive == QUEST_REALLYDONE)) + { + OpenNest(); + } + else + { + CloseNest(); + } + + if ((quests[Q_CRYPTMAP]._qactive != QUEST_DONE) && (!plr[myplr]._pLvlVisited[CRYPTSTART])) + CloseCrypt(); + else + OpenCrypt(); + + + // Close Maus shortcut + if (!((plr[myplr].pTownWarps & 0x01) || plr[myplr]._pLevel >= 10)) + T_FillTile(P3Tiles, 48, 20, 320); + // Close cave shortcut + if (!((plr[myplr].pTownWarps & 0x02) || plr[myplr]._pLevel >= 15)) + { + T_FillTile(P3Tiles, 16, 68, 332); + T_FillTile(P3Tiles, 16, 70, 331); + } + // Close crev shortcut or open or close or whatever is asked today + if (!((plr[myplr].pTownWarps & 0x04) || plr[myplr]._pLevel >= 20)) +// if (!(plr[myplr].pTownWarps & 0x04)) + { + for (xx = 36; xx < 46; xx++) + T_FillTile(P3Tiles, xx, 78, random(0,4)+1); + } + } + else + { + if ((quests[Q_FARMER]._qactive == QUEST_DONE) || (quests[Q_FARMER]._qactive == QUEST_REALLYDONE) + || (quests[Q_COWSUIT]._qactive == QUEST_DONE) || (quests[Q_COWSUIT]._qactive == QUEST_REALLYDONE)) + { + OpenNest(); + } + else + { + CloseNest(); + } + + if ((quests[Q_CRYPTMAP]._qactive != QUEST_DONE) && (!plr[myplr]._pLvlVisited[CRYPTSTART])) + CloseCrypt(); + else + OpenCrypt(); + } + +#endif + + if ((quests[Q_PWATER]._qactive == QUEST_DONE) || (quests[Q_PWATER]._qactive == QUEST_NOTAVAIL)) + T_FillTile(P3Tiles, 60, 70, 71); + else + T_FillTile(P3Tiles, 60, 70, 342); + + DiabloFreePtr(P3Tiles); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +extern int TWarpFrom; + +void CreateTown(int entry) +{ + int i,j; + + dminx = 10; + dminy = 10; + dmaxx = 84; + dmaxy = 84; + + if (entry == LVL_DOWN) { + ViewX = 75; // Your house + ViewY = 68; + } else { + if (entry == LVL_UP) { + ViewX = 25; // Near church + ViewY = 31; + } else { + if (entry == LVL_TWARPUP) { + if (TWarpFrom == 5) { + ViewX = 49; // Maus warp + ViewY = 22; + } + if (TWarpFrom == 9) { + ViewX = 18; // Cave warp + ViewY = 69; + } + if (TWarpFrom == 13) { + ViewX = 41; // Hell warp + ViewY = 81; + }// JKE add level up here. + if (TWarpFrom == CRYPTSTART) { + ViewX = 36; + ViewY = 25; + } + if (TWarpFrom == HIVESTART) { + ViewX = 79; + ViewY = 62; + } + } + } + } + + T_Pass3(); + + // Init the light values for each piece + ZeroMemory(dLight,sizeof(dLight)); + ZeroMemory(dFlags,sizeof(dFlags)); + ZeroMemory(dPlayer,sizeof(dPlayer)); + ZeroMemory(dMonster,sizeof(dMonster)); + ZeroMemory(dObject,sizeof(dObject)); + ZeroMemory(dItem,sizeof(dItem)); + ZeroMemory(dSpecial,sizeof(dSpecial)); + + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + int nPiece = dPiece[i][j]; + if (nPiece == 360) dSpecial[i][j] = 1; + else if (nPiece == 358) dSpecial[i][j] = 2; + else if (nPiece == 129) dSpecial[i][j] = 6; + else if (nPiece == 130) dSpecial[i][j] = 7; + else if (nPiece == 128) dSpecial[i][j] = 8; + else if (nPiece == 117) dSpecial[i][j] = 9; + else if (nPiece == 157) dSpecial[i][j] = 10; + else if (nPiece == 158) dSpecial[i][j] = 11; + else if (nPiece == 156) dSpecial[i][j] = 12; + else if (nPiece == 162) dSpecial[i][j] = 13; + else if (nPiece == 160) dSpecial[i][j] = 14; + else if (nPiece == 214) dSpecial[i][j] = 15; + else if (nPiece == 212) dSpecial[i][j] = 16; + else if (nPiece == 217) dSpecial[i][j] = 17; + else if (nPiece == 216) dSpecial[i][j] = 18; + } + } + + T_SetDungeonMicros(); +} diff --git a/src/TOWN.H b/src/TOWN.H new file mode 100644 index 0000000..817b8a6 --- /dev/null +++ b/src/TOWN.H @@ -0,0 +1,17 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/TOWN.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void CreateTown(int); + +void T_DrawView(int, int); diff --git a/src/TOWNERS.CPP b/src/TOWNERS.CPP new file mode 100644 index 0000000..19862cf --- /dev/null +++ b/src/TOWNERS.CPP @@ -0,0 +1,1458 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Town file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/TOWNERS.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "sound.h" +#include "engine.h" +#include "gendung.h" +#include "palette.h" + +#include "items.h" +#include "itemdat.h" +#include "inv.h" + +#include "player.h" +#include "monster.h" + +#include "town.h" +#include "quests.h" +#include "towners.h" +#include "minitext.h" +#include "textdat.h" +#include "stores.h" +#include "effects.h" +#include "multi.h" + +#include "cursor.h" +#include "msg.h" + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void SpawnSomething(int, int, int); +TownerStruct towner[MAX_TOWNERS]; +int numtowners; +BOOL storeflag; +BOOL boyloadflag; +BOOL bannerflag; + +char AnimOrder[6][148] = { +{ 5,6,7,8,9,10,11,12,13,14,14,13,12,11,10,9,8,7,6,5,5,6,7,8,9,10,11,12,13,14,14,13,12,11,10,9,8,7,6,5,5,6,7,8,9,10,11,12,13,14,14,13,12,11,10,9,8,7,6,5,5,6,7,8,9,10,11,12,13,14,14,13,12,11,10,9,8,7,6,5,5,6,7,8,9,10,11,12,13,14,14,13,12,11,10,9,8,7,6,5,5,6,7,8,9,10,11,12,13,14,15,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,-1 }, // Blacksmith +{ 1,2,3,3,2,1,20,19,19,20,1,2,3,3,2,1,20,19,19,20,1,2,3,3,2,1,20,19,19,20,1,2,3,3,2,1,20,19,19,20,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,15,14,13,12,11,10,9,8,7,6,5,4,5,6,7,8,9,10,11,12,13,14,15,16,15,14,13,12,11,10,9,8,7,6,5,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,-1 }, // Healer +{ 1,1,25,25,24,23,22,21,20,19,18,17,16,15,16,17,18,19,20,21,22,23,24,25,25,25,1,1,1,25,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,-1 }, // Storyteller +{ 1,2,3,3,2,1,16,15,14,14,16,1,2,3,3,2,1,16,15,14,14,15,16,1,2,3,3,2,1,16,15,14,14,15,16,1,2,3,3,2,1,16,15,14,14,15,16,1,2,3,3,2,1,16,15,14,14,15,16,1,2,3,3,2,1,16,15,14,14,15,16,1,2,3,3,2,1,16,15,14,14,15,16,1,2,3,2,1,16,15,14,14,15,16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,-1 }, // Innkeeper +{ 1,1,1,2,3,4,5,6,7,8,9,10,11,11,11,11,12,13,14,15,16,17,18,18,1,1,1,18,17,16,15,14,13,12,11,10,11,12,13,14,15,16,17,18,1,2,3,4,5,5,5,4,3,2,-1 }, // Towndrunk +{ 4,4,4,5,6,6,6,5,4,15,14,13,13,13,14,15,4,5,6,6,6,5,4,4,4,5,6,6,6,5,4,15,14,13,13,13,14,15,4,5,6,6,6,5,4,4,4,5,6,6,6,5,4,15,14,13,13,13,14,15,4,5,6,6,6,5,4,3,2,1,19,18,19,1,2,1,19,18,19,1,2,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,15,14,13,13,13,13,14,15,15,15,14,13,12,12,12,11,10,10,10,9,8,9,10,10,11,12,13,14,15,16,17,18,19,1,2,1,19,18,19,1,2,1,2,3,-1 } // Witch +}; + +/*-----------------------------------------------------------------------*/ + +#define TOWN_NUMCOWS 3 + + +#define COW // turns off cow quest JKECOW + +BYTE *pCowCels; +int TownCowX[] = { 58, 56, 59 }; +int TownCowY[] = { 16, 14, 20 }; +int TownCowDir[] = { DIR_DL, DIR_UL, DIR_U }; + +int cowoffx[8] = { -1, 0, -1, -1, -1, 0, -1, -1 }; +int cowoffy[8] = { -1, -1, -1, 0, -1, -1, -1, 0 }; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +int Qtalklist[14][MAXQUESTS] = { +// Q_ROCK Q_BKMUSHRM Q_GARBUD Q_ZHAR Q_VEIL Q_DIABLO Q_BUTCHER Q_LTBANNER Q_BLIND Q_BLOOD Q_ANVIL Q_WARLORD Q_SKELKING Q_PWATER Q_SCHAMB Q_BETRAYER Q_CRYPTMAP Q_FARMER Q_THEO Q_TRADER Q_DEFILER Q_NA_KRUL Q_CORNERSTONE Q_COWSUIT + { TXT_INFRABS2, TXT_BLKMBS1, -1, -1, TXT_VEILBS1, -1, TXT_BUTCHBS1, TXT_BOLBS1, TXT_BLINDBS1, TXT_BLOODBS1, TXT_ANVILBS2, TXT_WARLRDBS1, TXT_KINGBS1, TXT_PWBS1, TXT_BONEBS1, TXT_VBBS1, TXT_CRYPTMAP2, -1, -1, -1, -1, -1, -1, -1 }, // black smith + { TXT_INFRAH1, -1, -1, -1, TXT_VEILH1, -1, TXT_BUTCHH1, TXT_BOLH1, TXT_BLINDH1, TXT_BLOODH1, TXT_ANVILH1, TXT_WARLRDH1, TXT_KINGH1, TXT_PWH2, TXT_BONEH1, TXT_VBH1, TXT_CRYPTMAP3, -1, -1, -1, -1, -1, -1, -1 }, // healer + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // dead guy + { TXT_INFRATO1, TXT_BLKMTO1, -1, -1, TXT_VEILTO1, -1, TXT_BUTCHTO1, -1, TXT_BLINDTO1, TXT_BLOODTO1, TXT_ANVILTO1, TXT_WARLRDTO1, TXT_KINGTO2, TXT_PWTO1, TXT_BONETO1, TXT_VBTO1, TXT_CRYPTMAP5, -1, -1, -1, -1, -1, -1, -1 }, // tavern owner + { TXT_INFRAST1, TXT_BLKMST1, -1, -1, TXT_VEILST1, TXT_VBST3, TXT_BUTCHST1, TXT_BOLST1, TXT_BLINDST1, TXT_BLOODST1, TXT_ANVILST1, TXT_WARLRDST1, TXT_KINGST1, TXT_PWST1, TXT_BONEST1, TXT_VBST2, TXT_CRYPTMAP6, -1, -1, -1, -1, -1, -1, -1 }, // storyteller + { TXT_INFRATD1, TXT_BLKMTD1, -1, -1, TXT_VEILTD1, -1, TXT_BUTCHTD1, TXT_BOLTD1, TXT_BLINDTD1, TXT_BLOODTD1, TXT_ANVILTD1, TXT_WARLRDTD1, TXT_KINGTD1, TXT_PWTD1, TXT_BONETD1, TXT_VBTD1, TXT_CRYPTMAP7, -1, -1, -1, -1, -1, -1, -1 }, // town drunk + { TXT_INFRAW1, TXT_BLKMW2, -1, -1, TXT_VEILW1, -1, TXT_BUTCHW1, TXT_BOLW1, TXT_BLINDW1, TXT_BLOODW1, TXT_ANVILW1, TXT_WARLRDW1, TXT_KINGW1, TXT_PWW1, TXT_BONEW1, TXT_VBW1, TXT_CRYPTMAP1, -1, -1, -1, -1, -1, -1, -1 }, // witch + { TXT_INFRABM1, TXT_BLKMBM1, -1, -1, TXT_VEILBM1, -1, TXT_BUTCHBM1, TXT_BOLBM1, TXT_BLINDBM1, TXT_BLOODBM1, TXT_ANVILBM1, TXT_WARLRDBM1, TXT_KINGBM1, TXT_PWBM1, TXT_BONEBM1, TXT_VBBM1, TXT_CRYPTMAP8, -1, -1, -1, -1, -1, -1, -1 }, // barmaid + { TXT_INFRAPB1, TXT_BLKMPB1, -1, -1, TXT_VEILPB1, -1, TXT_BUTCHPB1, TXT_BOLPB1, TXT_BLINDPB1, TXT_BLOODPB1, TXT_ANVILPB1, TXT_WARLRDPB1, TXT_KINGPB1, TXT_PWPB1, TXT_BONEPB1, TXT_VBPB1, TXT_CRYPTMAP9, -1, -1, -1, -1, -1, -1, -1 }, // peg-legged boy + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // cow + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Farmer + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // Little Girl + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // cow suit guy + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // traveling salesman +}; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +int GetActiveTowner(int t) { + for (int i = 0; i < numtowners; i++) { + if (towner[i]._ttype == t) return(i); + } + return(-1); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void SetTownerGPtrs(BYTE *pData, BYTE *pAnim[]) { + BYTE *p; + int i; + + for (i = 0; i < 8; i++) { + p = pData; + __asm { + mov eax,dword ptr [p] + mov ebx,eax + mov edx,dword ptr [i] + shl edx,2 + add ebx,edx + mov edx,dword ptr [ebx] + add eax,edx + mov dword ptr [p],eax + } + pAnim[i] = p; + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void NewTownerAnim(int tnum, BYTE *pAnim, int numFrames, int Delay) +{ + app_assert(pAnim); + towner[tnum]._tAnimData = pAnim; + towner[tnum]._tAnimLen = numFrames; + towner[tnum]._tAnimFrame = 1; + towner[tnum]._tAnimCnt = 0; + towner[tnum]._tAnimDelay = Delay; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void InitTownerInfo(int i, long w, BOOL sel, int t, int x, int y, char ao, int tp) +{ + ZeroMemory(&towner[i],sizeof(TownerStruct)); + towner[i]._tSelFlag = sel; + towner[i]._tAnimWidth = w; + towner[i]._tAnimWidth2 = (w - 64) >> 1; + towner[i]._tMsgSaid = FALSE; + towner[i]._ttype = t; + towner[i]._tx = x; + towner[i]._ty = y; + dMonster[x][y] = i + 1; + towner[i]._tAnimOrder = ao; + towner[i]._tTenPer = tp; + towner[i]._tSeed = GetRndSeed(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitQstSnds(int i) +{ + int j = i; + + if (boyloadflag) j = i+1; + for (int quest = 0; quest < MAXQUESTS; quest++) { + towner[i].qsts[quest]._qsttype = quests[quest]._qtype; + towner[i].qsts[quest]._qstmsg = Qtalklist[j][quest]; + if (Qtalklist[j][quest] != -1) towner[i].qsts[quest]._qstmsgact = QSTMSG_AVAIL; + else towner[i].qsts[quest]._qstmsgact = QSTMSG_NOTAVAIL; + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitSmith() +{ + InitTownerInfo(numtowners, 96, TRUE, TWN_BLKSMITH, 62, 63, 0, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Smith\\SmithN.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 16; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_DL], towner[numtowners]._tNFrames, 3); + strcpy(towner[numtowners]._tName, "Griswold the Blacksmith"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitBarOwner() +{ + bannerflag = FALSE; + InitTownerInfo(numtowners, 96, TRUE, TWN_BAROWNER, 55, 62, 3, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\TwnF\\TwnFN.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 16; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_DL], towner[numtowners]._tNFrames, 3); + strcpy(towner[numtowners]._tName, "Ogden the Tavern owner"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitTownDead() { + InitTownerInfo(numtowners, 96, TRUE, TWN_DEAD, 24, 32, -1, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Butch\\Deadguy.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 8; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_U], towner[numtowners]._tNFrames, 6); + strcpy(towner[numtowners]._tName, "Wounded Townsman"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitWitch() { + InitTownerInfo(numtowners, 96, TRUE, TWN_WITCH, 80, 20, 5, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\TownWmn1\\Witch.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 19; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_D], towner[numtowners]._tNFrames, 6); + strcpy(towner[numtowners]._tName, "Adria the Witch"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitBarmaid() { + InitTownerInfo(numtowners, 96, TRUE, TWN_BARMAID, 43, 66, -1, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\TownWmn1\\WmnN.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 18; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_D], towner[numtowners]._tNFrames, 6); + strcpy(towner[numtowners]._tName, "Gillian the Barmaid"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitBoy() { + boyloadflag = TRUE; + InitTownerInfo(numtowners, 96, TRUE, TWN_BOY, 11, 53, -1, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\TownBoy\\PegKid1.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 20; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_D], towner[numtowners]._tNFrames, 6); + strcpy(towner[numtowners]._tName, "Wirt the Peg-legged boy"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitHealer() { + InitTownerInfo(numtowners, 96, TRUE, TWN_HEALER, 55, 79, 1, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Healer\\Healer.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 20; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_DR], towner[numtowners]._tNFrames, 6); + strcpy(towner[numtowners]._tName, "Pepin the Healer"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitTeller() +{ + InitTownerInfo(numtowners, 96, TRUE, TWN_TELLER, 62, 71, 2, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Strytell\\Strytell.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 25; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_D], towner[numtowners]._tNFrames, 3); + strcpy(towner[numtowners]._tName, "Cain the Elder"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitDrunk() { + InitTownerInfo(numtowners, 96, TRUE, TWN_DRUNK, 71, 84, 4, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Drunk\\TwnDrunk.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 18; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_D], towner[numtowners]._tNFrames, 3); + strcpy(towner[numtowners]._tName, "Farnham the Drunk"); + numtowners++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void InitCows() +{ + int i, x, y, d, x2, y2; + + app_assert(! pCowCels); + pCowCels = LoadFileInMemSig("Towners\\Animals\\Cow.CEL",NULL,'TOWN'); + + for (i = 0; i < TOWN_NUMCOWS; i++) { + x = TownCowX[i]; + y = TownCowY[i]; + d = TownCowDir[i]; + InitTownerInfo(numtowners, 128, FALSE, TWN_COW, x, y, -1, 10); + towner[numtowners]._tNData = pCowCels; + SetTownerGPtrs(towner[numtowners]._tNData, towner[numtowners]._tNAnim); + towner[numtowners]._tNFrames = 12; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[d], towner[numtowners]._tNFrames, 3); + towner[numtowners]._tAnimFrame = random(0,11) + 1; + towner[numtowners]._tSelFlag = TRUE; + strcpy(towner[numtowners]._tName, "Cow"); + x2 = x + cowoffx[d]; + y2 = y + cowoffy[d]; + if (dMonster[x][y2] == 0) dMonster[x][y2] = -(numtowners + 1); + if (dMonster[x2][y] == 0) dMonster[x2][y] = -(numtowners + 1); + if (dMonster[x2][y2] == 0) dMonster[x2][y2] = -(numtowners + 1); + numtowners++; + } +} + +// JKENEWTOWNER INIT INFO HERE +void InitFarmer() +{ + InitTownerInfo(numtowners, 96, TRUE, TWN_FARMER, 62, 16, -1, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Farmer\\Farmrn2.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 15; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_D], towner[numtowners]._tNFrames, 3); + strcpy(towner[numtowners]._tName, "Lester the farmer"); + numtowners++; +} +void InitCowsuit() +{ + InitTownerInfo(numtowners, 96, TRUE, TWN_COWSUIT, 61, 22, -1, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + if(quests[Q_COWSUIT]._qactive != QUEST_DONE) + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Farmer\\cfrmrn2.CEL",NULL,'TOWN'); + else + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Farmer\\mfrmrn2.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 15; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_DL], towner[numtowners]._tNFrames, 3); + strcpy(towner[numtowners]._tName, "Complete Nut"); + numtowners++; + +} +void InitGirl() +{ + InitTownerInfo(numtowners, 96, TRUE, TWN_GIRL, 77, 43, -1, 10); + app_assert(! towner[numtowners]._tNData); + InitQstSnds(numtowners); + if (quests[Q_THEO]._qactive != QUEST_DONE) + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Girl\\Girlw1.CEL",NULL,'TOWN'); + else + towner[numtowners]._tNData = LoadFileInMemSig("Towners\\Girl\\Girls1.CEL",NULL,'TOWN'); + for (int i = 0; i < 8; i++) towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData; + towner[numtowners]._tNFrames = 20; + NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_D], towner[numtowners]._tNFrames, 6); + strcpy(towner[numtowners]._tName, "Celia"); + numtowners++; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitTowners() //when adding any towners add the init in order of the defines +{ + numtowners = 0; + boyloadflag = FALSE; + InitSmith(); + InitHealer(); + if (quests[Q_BUTCHER]._qactive != QUEST_NOTAVAIL && quests[Q_BUTCHER]._qactive != QUEST_DONE) + InitTownDead(); + InitBarOwner(); + InitTeller(); + InitDrunk(); + InitWitch(); + InitBarmaid(); + InitBoy(); + // From here down, not controled, only animated + InitCows(); + // HELLFIRE INIT JKENEWTOWNERS + + if (gbCowsuit) + { + InitCowsuit(); + } + else + { + if (quests[Q_FARMER]._qactive != QUEST_REALLYDONE) + InitFarmer(); + } + + if (gbTheo) + if (plr[0]._pLvlVisited[HIVESTART]) + InitGirl(); + +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void FreeTownerGFX() { + int i; + + for (i = 0; i < MAX_TOWNERS; i++) { + if (towner[i]._tNData == pCowCels) { + // don't free + towner[i]._tNData = NULL; + } + else if (towner[i]._tNData) { + DiabloFreePtr(towner[i]._tNData); + } + } + + // now free cow cels + DiabloFreePtr(pCowCels); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownCtrlMsg(int i) +{ + if (towner[i]._tbtcnt != 0) { + int const p = towner[i]._tVar1; + int const dx = abs(towner[i]._tx - plr[p]._px); + int const dy = abs(towner[i]._ty - plr[p]._py); + if ((dx >= 2) || (dy >= 2)) + { + towner[i]._tbtcnt = 0; + qtextflag = FALSE; + stream_stop(); + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownBlackSmith() +{ + int const tidx = GetActiveTowner(TWN_BLKSMITH); + TownCtrlMsg(tidx); +#if 0 + if ((!qtextflag) && quests[Q_ROCK]._qactive == QUEST_DONE) { + int const x = towner[tidx]._tx; + int const y = towner[tidx]._ty + 1; + if (dPlayer[x][y] > 0) x++; + } +#endif +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownBarOwner() +{ + int const tidx = GetActiveTowner(TWN_BAROWNER); + TownCtrlMsg(tidx); +#if 0 + if ((!qtextflag) && (quests[Q_LTBANNER]._qactive == QUEST_DONE) && (bannerflag)) { + int const x = towner[tidx]._tx; + int const y = towner[tidx]._ty + 1; + if (dPlayer[x][y] > 0) x++; + } +#endif +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownDead() +{ + int const tidx = GetActiveTowner(TWN_DEAD); + TownCtrlMsg(tidx); + if (!qtextflag) { + if ((quests[Q_BUTCHER]._qactive == QUEST_NOTDONE) && (!quests[Q_BUTCHER]._qlog)) return; + if (quests[Q_BUTCHER]._qactive != QUEST_NOTACTIVE) { + towner[tidx]._tAnimDelay = 1000; + towner[tidx]._tAnimFrame = 1; + strcpy(towner[tidx]._tName, "Slain Townsman"); + } + } + if (quests[Q_BUTCHER]._qactive != QUEST_NOTACTIVE) towner[tidx]._tAnimCnt = 0; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownHealer() +{ + int const tidx = GetActiveTowner(TWN_HEALER); + TownCtrlMsg(tidx); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownStory() +{ + + int const tidx = GetActiveTowner(TWN_TELLER); + TownCtrlMsg(tidx); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownDrunk() +{ + + int const tidx = GetActiveTowner(TWN_DRUNK); + TownCtrlMsg(tidx); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownBoy() +{ + + int const tidx = GetActiveTowner(TWN_BOY); + TownCtrlMsg(tidx); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownWitch() +{ + + int const tidx = GetActiveTowner(TWN_WITCH); + TownCtrlMsg(tidx); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownBarMaid() +{ + int const tidx = GetActiveTowner(TWN_BARMAID); + TownCtrlMsg(tidx); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void TownCow() +{ + + int const tidx = GetActiveTowner(TWN_COW); + TownCtrlMsg(tidx); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +// add helfire characters here + +void Farmer() +{ + int const tidx = GetActiveTowner(TWN_FARMER); + TownCtrlMsg(tidx); +} + +void Cowsuit() +{ + int const tidx = GetActiveTowner(TWN_COWSUIT); + TownCtrlMsg(tidx); +} + +void Girl() +{ + int const tidx = GetActiveTowner(TWN_GIRL); + TownCtrlMsg(tidx); +} + + +void ProcessTowners() +{ + int i; + + for (i = 0; i < MAX_TOWNERS; ++i) { + switch (towner[i]._ttype) { + case TWN_BLKSMITH : + TownBlackSmith(); + break; + case TWN_HEALER : + TownHealer(); + break; + case TWN_DEAD : + TownDead(); + break; + case TWN_BAROWNER : + TownBarOwner(); + break; + case TWN_TELLER : + TownStory(); + break; + case TWN_DRUNK : + TownDrunk(); + break; + case TWN_BOY : + TownBoy(); + break; + case TWN_WITCH : + TownWitch(); + break; + case TWN_BARMAID : + TownBarMaid(); + break; + case TWN_COW : + TownCow(); + break; + case TWN_FARMER: + Farmer(); + break; + case TWN_GIRL: + Girl(); + break; + case TWN_COWSUIT: + Cowsuit(); + break; + } + + // Animate Towner + ++towner[i]._tAnimCnt; + if (towner[i]._tAnimCnt >= towner[i]._tAnimDelay) { + towner[i]._tAnimCnt = 0; + if (towner[i]._tAnimOrder >= 0) { + int const ao = towner[i]._tAnimOrder; + ++towner[i]._tAnimFrameCnt; + if (AnimOrder[ao][towner[i]._tAnimFrameCnt] == -1) towner[i]._tAnimFrameCnt = 0; + towner[i]._tAnimFrame = AnimOrder[ao][towner[i]._tAnimFrameCnt]; + } else { + ++towner[i]._tAnimFrame; + if (towner[i]._tAnimFrame > towner[i]._tAnimLen) towner[i]._tAnimFrame = 1; + } + } + } +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +ItemStruct *PlrHasItem(int pnum, int item, int &i) +{ + for (i = 0; i < plr[pnum]._pNumInv; ++i) { + if (plr[pnum].InvList[i].IDidx == item) + return &plr[pnum].InvList[i]; + } + return FALSE; +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +static DWORD sgdwCowClicks; +static int sgnCowMsg; +static void CowSFX(int pnum) { + #if !IS_VERSION(SHAREWARE) + #define NUM_COW_SFX 3 + static const int snSFX[NUM_COW_SFX][NUM_CLASSES] = { + { PS_WARR52, PS_ROGUE52, PS_MAGE52, PS_MONK52, PS_BARD52 }, // yup, that's a cow + { PS_WARR49, PS_ROGUE49, PS_MAGE49, PS_MONK49, PS_BARD49 }, // I'm not thirsty + { PS_WARR50, PS_ROGUE50, PS_MAGE50, PS_MONK50, PS_BARD50 }, // I'm no milkmaid + }; + #endif + + // make sure we're not still playing the last cow SFX + static int snLastCowSFX = -1; + BOOL effect_is_playing(int nSFX); + if (snLastCowSFX != -1 && effect_is_playing(snLastCowSFX)) + return; + + // next cow sound + sgdwCowClicks++; + #if !IS_VERSION(SHAREWARE) + if (sgdwCowClicks >= 8) { + // play cow in background + PlaySfxLoc(TSFX_COW1, plr[pnum]._px, plr[pnum]._py + 5); + + // reset cow counter + sgdwCowClicks = 4; + + // choose player cow sfx + snLastCowSFX = snSFX[sgnCowMsg][plr[pnum]._pClass]; + if (++sgnCowMsg >= NUM_COW_SFX) sgnCowMsg = 0; + } + else + #endif + if (sgdwCowClicks == 4) { + #if IS_VERSION(SHAREWARE) + sgdwCowClicks = 0; + #endif + snLastCowSFX = TSFX_COW2; + } + else { + snLastCowSFX = TSFX_COW1; + } + + PlaySfxLoc(snLastCowSFX,plr[pnum]._px,plr[pnum]._py); +} + + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ +void TownerTalk(int first, int t) +{ + // reset cow counter + sgdwCowClicks = 0; + sgnCowMsg = 0; + + storeflag = TRUE; + InitQTextMsg(first); +} + +/*-----------------------------------------------------------------------* +**-----------------------------------------------------------------------*/ + +void TalkToTowner(int p, int t) +{ + int i; + int dx, dy; + int r3, r4, r5; + ItemStruct *Item; + + r3 = random(6, 3); + r4 = random(6, 4); + r5 = random(6, 5); + dx = abs(plr[p]._px - towner[t]._tx); + dy = abs(plr[p]._py - towner[t]._ty); +#if CHEATS + if ((!davedebug) && ((dx >= 2) || (dy >= 2))) return; +#else + if ((dx >= 2) || (dy >= 2)) return; +#endif + if (qtextflag) return; + towner[t]._tMsgSaid = FALSE; + + //Does player have item in hand? If so, drop it before talking to town person. + if (curs >= ICSTART) { + if(!DropItemBeforeTrig()) return; + } + +/*-----Tavern Owner------------------------------------------------------*/ + if (t == GetActiveTowner(TWN_BAROWNER)) { + if (!(plr[p]._pLvlVisited[0]) && !(towner[t]._tMsgSaid)) { + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_INTRO); + towner[t]._tMsgSaid = TRUE; + } + if ((plr[p]._pLvlVisited[2] || plr[p]._pLvlVisited[4]) && (quests[Q_SKELKING]._qactive != QUEST_NOTAVAIL)) { + // skel king init + if ((quests[Q_SKELKING]._qactive != QUEST_NOTAVAIL) && (quests[Q_SKELKING]._qvar2 == 0) && (!towner[t]._tMsgSaid)) { + quests[Q_SKELKING]._qvar2 = 1; + quests[Q_SKELKING]._qlog = TRUE; + if (quests[Q_SKELKING]._qactive == QUEST_NOTACTIVE) { + quests[Q_SKELKING]._qactive = QUEST_NOTDONE; + quests[Q_SKELKING]._qvar1 = 1; // state of quest + } + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_KINGTO1); + towner[t]._tMsgSaid = TRUE; + NetSendCmdQuest(TRUE, Q_SKELKING); + } + // skel king finished + if ((quests[Q_SKELKING]._qactive == QUEST_DONE) && (quests[Q_SKELKING]._qvar2 == 1) && (!towner[t]._tMsgSaid)) { + quests[Q_SKELKING]._qvar2 = 2; + quests[Q_SKELKING]._qvar1 = 2; // state of quest + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_KINGTO3); + towner[t]._tMsgSaid = TRUE; + NetSendCmdQuest(TRUE, Q_SKELKING); + } + } + + if (gbMaxPlayers == 1) { + // banner of light init + if ((plr[p]._pLvlVisited[3]) && (quests[Q_LTBANNER]._qactive != QUEST_NOTAVAIL)) { + if ((quests[Q_LTBANNER]._qactive == QUEST_NOTACTIVE) || (quests[Q_LTBANNER]._qactive == QUEST_NOTDONE)) { + if ((quests[Q_LTBANNER]._qvar2 == 0) && (!towner[t]._tMsgSaid)) { + quests[Q_LTBANNER]._qvar2 = 1; + if (quests[Q_LTBANNER]._qactive == QUEST_NOTACTIVE) { + quests[Q_LTBANNER]._qvar1 = 1; // state of quest + quests[Q_LTBANNER]._qactive = QUEST_NOTDONE; + } + quests[Q_LTBANNER]._qlog = TRUE; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_BOLTO1); + towner[t]._tMsgSaid = TRUE; + } + } + } + // banner of light finished + if ((!towner[t]._tMsgSaid) && PlrHasItem(p, IDI_BANNER, i)) { + quests[Q_LTBANNER]._qactive = QUEST_DONE; + quests[Q_LTBANNER]._qvar1 = 3; + RemoveInvItem(p, i); + CreateItem(UID_HARCREST, towner[t]._tx, towner[t]._ty + 1); // Harlequin Crest + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_BOLTO2); + towner[t]._tMsgSaid = TRUE; + } + } + if (!qtextflag) { + TownerTalk(TXT_OGDEN1, t); + if(storeflag) StartStore(STORE_TAVERN); + } + } + +/*-----Nearly dead guy---------------------------------------------------*/ + else if (t == GetActiveTowner(TWN_DEAD)) { + if ((quests[Q_BUTCHER]._qactive == QUEST_NOTDONE) && (quests[Q_BUTCHER]._qvar1 == 1)) { + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + quests[Q_BUTCHER]._qvar1 = 1; + #if !IS_VERSION(SHAREWARE) + BOOL effect_is_playing(int nSFX); + if ((plr[p]._pClass == CLASS_WARRIOR) && !effect_is_playing(PS_WARR8)) PlaySFX(PS_WARR8); + else if ((plr[p]._pClass == CLASS_ROGUE) && !effect_is_playing(PS_ROGUE8)) PlaySFX(PS_ROGUE8); + else if ((plr[p]._pClass == CLASS_SORCEROR) && !effect_is_playing(PS_MAGE8)) PlaySFX(PS_MAGE8); + else if ((plr[p]._pClass == CLASS_MONK) && !effect_is_playing(PS_MONK8)) PlaySFX(PS_MONK8); + else if ((plr[p]._pClass == CLASS_BARD) && !effect_is_playing(PS_BARD8)) PlaySFX(PS_BARD8); + else if ((plr[p]._pClass == CLASS_BARBARIAN) && !effect_is_playing(PS_BARBARIAN8)) PlaySFX(PS_BARBARIAN8); + #endif + towner[t]._tMsgSaid = TRUE; + } + else if ((quests[Q_BUTCHER]._qactive == QUEST_DONE) && (quests[Q_BUTCHER]._qvar1 == 1)) { + /* #if !IS_VERSION(SHAREWARE) + BOOL effect_is_playing(int nSFX); + if ((plr[p]._pClass == CLASS_WARRIOR) && !effect_is_playing(PS_WARR9)) PlaySFX(PS_WARR9); + else if ((plr[p]._pClass == CLASS_ROGUE) && !effect_is_playing(PS_ROGUE9)) PlaySFX(PS_ROGUE9); + else if ((plr[p]._pClass == CLASS_SORCEROR) && !effect_is_playing(PS_MAGE9)) PlaySFX(PS_MAGE9); + else if ((plr[p]._pClass == CLASS_MONK) && !effect_is_playing(PS_MONK9)) PlaySFX(PS_MONK9); + else if ((plr[p]._pClass == CLASS_BARD) && !effect_is_playing(PS_BARD9)) PlaySFX(PS_BARD9); + else if ((plr[p]._pClass == CLASS_BARBARIAN) && !effect_is_playing(PS_BARBARIAN9)) PlaySFX(PS_BARBARIAN9); + #endif + */ + //InitQTextMsg(5); + quests[Q_BUTCHER]._qvar1 = 1; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + towner[t]._tMsgSaid = TRUE; + } + + else if ((quests[Q_BUTCHER]._qactive == QUEST_NOTACTIVE) || + ((quests[Q_BUTCHER]._qactive == QUEST_NOTDONE) && (!quests[Q_BUTCHER]._qvar1))) { + quests[Q_BUTCHER]._qactive = QUEST_NOTDONE; + quests[Q_BUTCHER]._qlog = TRUE; + quests[Q_BUTCHER]._qmsg = TXT_BUTCH1; + quests[Q_BUTCHER]._qvar1 = 1; + towner[t]._tbtcnt = 50; + towner[t]._tVar1 = p; + towner[t]._tVar2 = 3; + InitQTextMsg(TXT_BUTCH1); + towner[t]._tMsgSaid = TRUE; + NetSendCmdQuest(TRUE, Q_BUTCHER); + } + } +/*-----Blacksmith-------------------------------------------------------*/ + else if (t == GetActiveTowner(TWN_BLKSMITH)) { + if (gbMaxPlayers == 1) { + // magic rock init + if ((plr[p]._pLvlVisited[4]) && (quests[Q_ROCK]._qactive != QUEST_NOTAVAIL)) { + if ((quests[Q_ROCK]._qactive != QUEST_NOTAVAIL) && (quests[Q_ROCK]._qvar2 == 0)) { + quests[Q_ROCK]._qvar2 = 1; + quests[Q_ROCK]._qlog = TRUE; + if (quests[Q_ROCK]._qactive == QUEST_NOTACTIVE) { + quests[Q_ROCK]._qactive = QUEST_NOTDONE; + quests[Q_ROCK]._qvar1 = 1; // state + } + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_INFRABS1); + towner[t]._tMsgSaid = TRUE; + } + } + // magic rock finished + if ((!towner[t]._tMsgSaid) && PlrHasItem(p, IDI_ROCK, i)) + { + quests[Q_ROCK]._qactive = QUEST_DONE; + quests[Q_ROCK]._qvar2 = 2; + quests[Q_ROCK]._qvar1 = 2; + RemoveInvItem(p, i); + CreateItem(UID_INFRARING, towner[t]._tx, towner[t]._ty + 1); // Ring of Infravision + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_INFRABS3); + towner[t]._tMsgSaid = TRUE; + } + + // anvil init + if ((plr[p]._pLvlVisited[9]) && (quests[Q_ANVIL]._qactive != QUEST_NOTAVAIL)) { + if ((quests[Q_ANVIL]._qactive == QUEST_NOTACTIVE) || (quests[Q_ANVIL]._qactive == QUEST_NOTDONE)) { + if ((quests[Q_ANVIL]._qvar2 == 0) && (!towner[t]._tMsgSaid)) { + if ((quests[Q_ROCK]._qvar2 == 2) + || ((quests[Q_ROCK]._qactive == QUEST_NOTDONE) && (quests[Q_ROCK]._qvar2 == 1))) { + quests[Q_ANVIL]._qvar2 = 1; + quests[Q_ANVIL]._qlog = TRUE; + if (quests[Q_ANVIL]._qactive == QUEST_NOTACTIVE) { + quests[Q_ANVIL]._qactive = QUEST_NOTDONE; + quests[Q_ANVIL]._qvar1 = 1; + } + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_ANVILBS1); + towner[t]._tMsgSaid = TRUE; + } + } + } + } + // anvil finished + if ((!towner[t]._tMsgSaid) && PlrHasItem(p, IDI_ANVIL, i)) { + quests[Q_ANVIL]._qactive = QUEST_DONE; + quests[Q_ANVIL]._qvar2 = 2; + quests[Q_ANVIL]._qvar1 = 2; + RemoveInvItem(p, i); + CreateItem(UID_GRISWOLD, towner[t]._tx, towner[t]._ty + 1); // Griswolds edge + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_ANVILBS3); + towner[t]._tMsgSaid = TRUE; + } + } + if (!qtextflag) { + TownerTalk(TXT_GRIS1, t); + if(storeflag) StartStore(STORE_SMITH); + } + } + +/*-----Witch-------------------------------------------------------------*/ + else if (t == GetActiveTowner(TWN_WITCH)) { + if (quests[Q_BKMUSHRM]._qactive == QUEST_NOTACTIVE + && PlrHasItem(p, IDI_FUNGALTM, i)) { + // got fungal tome + RemoveInvItem(p, i); + quests[Q_BKMUSHRM]._qactive = QUEST_NOTDONE; + quests[Q_BKMUSHRM]._qlog = TRUE; + quests[Q_BKMUSHRM]._qvar1 = QS_TOMEGIVEN; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_BLKMW1); + towner[t]._tMsgSaid = TRUE; + } else if (quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE) { + if (quests[Q_BKMUSHRM]._qvar1 >= QS_TOMEGIVEN + && quests[Q_BKMUSHRM]._qvar1 <= QS_MUSHPICKED) { + // waiting for mushroom + if (PlrHasItem(p, IDI_MUSHROOM, i)) { + RemoveInvItem(p, i); + quests[Q_BKMUSHRM]._qvar1 = QS_MUSHGIVEN; + Qtalklist[TWN_HEALER][Q_BKMUSHRM] = TXT_BLKMH1; + Qtalklist[TWN_WITCH][Q_BKMUSHRM] = -1; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + quests[Q_BKMUSHRM]._qmsg = TXT_BLKMW3; + InitQTextMsg(TXT_BLKMW3); + towner[t]._tMsgSaid = TRUE; + } + else if (quests[Q_BKMUSHRM]._qmsg != TXT_BLKMW2) { + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + quests[Q_BKMUSHRM]._qmsg = TXT_BLKMW2; + InitQTextMsg(TXT_BLKMW2); + towner[t]._tMsgSaid = TRUE; + } + } + else { + // waiting for elixir + if (Item = PlrHasItem(p, IDI_SPECELIX, i)) { + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_BLKMW5); + quests[Q_BKMUSHRM]._qactive = QUEST_DONE; + towner[t]._tMsgSaid = TRUE; + AllItemsList[Item->IDidx].iUsable = TRUE; + } + else if (PlrHasItem(p, IDI_BRAIN, i) + && quests[Q_BKMUSHRM]._qvar2 != TXT_BLKMW4) { + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + quests[Q_BKMUSHRM]._qvar2 = TXT_BLKMW4; + InitQTextMsg(TXT_BLKMW4); + towner[t]._tMsgSaid = TRUE; + } + } + } + if (!qtextflag) { + TownerTalk(TXT_ADRIA1, t); + if(storeflag) StartStore(STORE_WITCH); + } + } + +/*-----BarMaid-------------------------------------------------------------*/ + else if (t == GetActiveTowner(TWN_BARMAID)) { + if ((!plr[p]._pLvlVisited[CRYPTSTART]) && (PlrHasItem(p, IDI_MAPOFDOOM, i))) + { + quests[Q_CRYPTMAP]._qactive = QUEST_NOTDONE; + quests[Q_CRYPTMAP]._qlog = TRUE; + quests[Q_CRYPTMAP]._qmsg = TXT_CRYPTMAP8; + InitQTextMsg(TXT_CRYPTMAP8); + towner[t]._tMsgSaid = TRUE; + } + if (!qtextflag) { + TownerTalk(TXT_GILIAN1, t); + if(storeflag) StartStore(STORE_BARMAID); + } + } +/*-----Drunk-------------------------------------------------------------*/ + else if (t == GetActiveTowner(TWN_DRUNK)) { + if (!qtextflag) { + TownerTalk(TXT_FARN1, t); + if(storeflag) StartStore(STORE_DRUNK); + } + } +/*-----Healer------------------------------------------------------------*/ + else if (t == GetActiveTowner(TWN_HEALER)) { + if (gbMaxPlayers == 1) { + if (plr[p]._pLvlVisited[1] || plr[p]._pLvlVisited[5]) { + if (!towner[t]._tMsgSaid) { + if (quests[Q_PWATER]._qactive == QUEST_NOTACTIVE) { + quests[Q_PWATER]._qactive = QUEST_NOTDONE; + quests[Q_PWATER]._qlog = TRUE; + quests[Q_PWATER]._qmsg = TXT_PWH1; + quests[Q_PWATER]._qvar1 = 1; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_PWH1); + towner[t]._tMsgSaid = TRUE; + } + else if ((quests[Q_PWATER]._qactive == QUEST_DONE) && (quests[Q_PWATER]._qvar1 != 2)) { + quests[Q_PWATER]._qvar1 = 2; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_PWH3); + CreateItem(UID_TRING, towner[t]._tx, towner[t]._ty + 1); // Ring of truth + towner[t]._tMsgSaid = TRUE; + } + } + } + if (quests[Q_BKMUSHRM]._qactive == QUEST_NOTDONE + && quests[Q_BKMUSHRM]._qmsg == TXT_BLKMW3) { + if (PlrHasItem(p, IDI_BRAIN, i)) { + RemoveInvItem(p, i); + // pop out spectral elixir + SpawnQuestItem(IDI_SPECELIX, towner[t]._tx, towner[t]._ty + 1, FALSE, ISEL_NONE); + InitQTextMsg(TXT_BLKMH2); + quests[Q_BKMUSHRM]._qvar1 = QS_BRAINGIVEN; + Qtalklist[TWN_HEALER][Q_BKMUSHRM] = -1; + } + } + } + if (!qtextflag) { + TownerTalk(TXT_PEPIN1, t); + if(storeflag) StartStore(STORE_HEALER); + } + } +/*-----Peg-legged Boy----------------------------------------------------*/ + else if (t == GetActiveTowner(TWN_BOY)) { + if (!qtextflag) { + TownerTalk(TXT_WIRT1, t); + if(storeflag) StartStore(STORE_BOY); + } + } +/*-----Story Teller------------------------------------------------------*/ + else if (t == GetActiveTowner(TWN_TELLER)) { + if (gbMaxPlayers == 1) { + if ((quests[Q_BETRAYER]._qactive == QUEST_NOTACTIVE) && (PlrHasItem(p, IDI_LAZSTAFF, i))) { + RemoveInvItem(p, i); + quests[Q_BETRAYER]._qvar1 = 2; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_VBST1); + towner[t]._tMsgSaid = TRUE; + quests[Q_BETRAYER]._qactive = QUEST_NOTDONE; + quests[Q_BETRAYER]._qlog = TRUE; + } + else if ((quests[Q_BETRAYER]._qactive == QUEST_DONE) && (quests[Q_BETRAYER]._qvar1 == 7)) { + quests[Q_BETRAYER]._qvar1 = 8; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_VBST3); + towner[t]._tMsgSaid = TRUE; + quests[Q_DIABLO]._qlog = TRUE; + } + } + if (gbMaxPlayers != 1) { + if ((quests[Q_BETRAYER]._qactive == QUEST_NOTDONE) && (quests[Q_BETRAYER]._qlog == FALSE)) { + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_VBST1); + towner[t]._tMsgSaid = TRUE; + quests[Q_BETRAYER]._qlog = TRUE; + NetSendCmdQuest(TRUE, Q_BETRAYER); + } + else if ((quests[Q_BETRAYER]._qactive == QUEST_DONE) && (quests[Q_BETRAYER]._qvar1 == 7)) { + quests[Q_BETRAYER]._qvar1 = 8; + towner[t]._tbtcnt = 150; + towner[t]._tVar1 = p; + InitQTextMsg(TXT_VBST3); + towner[t]._tMsgSaid = TRUE; + NetSendCmdQuest(TRUE, Q_BETRAYER); + quests[Q_DIABLO]._qlog = TRUE; + NetSendCmdQuest(TRUE, Q_DIABLO); + } + } + if (!qtextflag) { + TownerTalk(TXT_STORY1, t); + if(storeflag) StartStore(STORE_STORYTLR); + } + } +/*-----Cow-------------------------------------------------------------------------*/ + + else if (towner[t]._ttype == TWN_COW) { + if (! qtextflag) CowSFX(p); + } +/*-------------N E W T O W N E R S JKENEWTOWNER -------------------------------- */ + + else if (towner[t]._ttype == TWN_FARMER) + { + if (! qtextflag) + { + int message = TXT_FARMER1; +// int textflag = FALSE; + int textflag = TRUE; + switch (quests[Q_FARMER]._qactive) + { + case QUEST_NOTAVAIL: + if (PlrHasItem(p, IDI_RUNEBOMB, i)) + { + message = TXT_FARMER2; + quests[Q_FARMER]._qactive = QUEST_NOTDONE; + quests[Q_FARMER]._qvar1 = 1; + quests[Q_FARMER]._qlog = TRUE; + quests[Q_FARMER]._qmsg = TXT_FARMER1; + break; + } + else + if (!(plr[myplr]._pLvlVisited[9] || + plr[myplr]._pLevel >= 15)) + { + message = TXT_FARMER7; + if (plr[myplr]._pLvlVisited[2]) + message = TXT_FARMER5; + if (plr[myplr]._pLvlVisited[5]) + message = TXT_FARMER6; + if (plr[myplr]._pLvlVisited[7]) + message = TXT_FARMER8; + + +/* int respond; + respond = random(0,5) + 5; + switch (respond) + { + case 5: + message = TXT_FARMER5; + break; + case 6: + message = TXT_FARMER6; + break; + case 7: + message = TXT_FARMER7; + break; + case 8: + message = TXT_FARMER8; + break; + default: + message = TXT_FARMER9; + }*/ + } + else + { + message = TXT_FARMER1; + quests[Q_FARMER]._qactive = QUEST_NOTDONE; + quests[Q_FARMER]._qvar1 = 1; + quests[Q_FARMER]._qlog = TRUE; + quests[Q_FARMER]._qmsg = TXT_FARMER1; + SpawnBomb(towner[t]._tx + 1, towner[t]._ty); + textflag = TRUE; + break; + } + case QUEST_NOTDONE: + if(PlrHasItem(p, IDI_RUNEBOMB, i)) + message = TXT_FARMER2; + else + message = TXT_FARMER3; + break; + case QUEST_NOTACTIVE: + if (PlrHasItem(p, IDI_RUNEBOMB, i)) + { + message = TXT_FARMER2; + quests[Q_FARMER]._qactive = QUEST_NOTDONE; + quests[Q_FARMER]._qvar1 = 1; + quests[Q_FARMER]._qmsg = TXT_FARMER1; + quests[Q_FARMER]._qlog = TRUE; + break; + } + else if (!(plr[myplr]._pLvlVisited[9] || + plr[myplr]._pLevel >= 15)) + { + + message = TXT_FARMER7; + if (plr[myplr]._pLvlVisited[2]) + message = TXT_FARMER5; + if (plr[myplr]._pLvlVisited[5]) + message = TXT_FARMER6; + if (plr[myplr]._pLvlVisited[7]) + message = TXT_FARMER8; + +/* int respond; + respond = random(0,5) + 5; + switch (respond) + { + case 5: + message = TXT_FARMER5; + break; + case 6: + message = TXT_FARMER6; + break; + case 7: + message = TXT_FARMER7; + break; + case 8: + message = TXT_FARMER8; + break; + default: + message = TXT_FARMER9; + }*/ + break; + } + else + { + message = TXT_FARMER1; + quests[Q_FARMER]._qactive = QUEST_NOTDONE; + quests[Q_FARMER]._qvar1 = 1; + quests[Q_FARMER]._qlog = TRUE; + quests[Q_FARMER]._qmsg = TXT_FARMER1; + SpawnBomb(towner[t]._tx + 1, towner[t]._ty); + textflag = TRUE; + break; + } + case QUEST_DONE: + message = TXT_FARMER4; + //SpawnUnique(UID_INFRARING, towner[t]._tx, towner[t]._ty + 1); + SpawnSomething(IDI_AURIC, towner[t]._tx + 1, towner[t]._ty); + quests[Q_FARMER]._qactive = QUEST_REALLYDONE; + quests[Q_FARMER]._qlog = FALSE; + textflag = TRUE; + break; + case QUEST_REALLYDONE: + message = -1; + break; + default: + message = TXT_FARMER4; + quests[Q_FARMER]._qactive = QUEST_NOTAVAIL; + + + } + + if (message != -1) + { + if (textflag) + InitQTextMsg(message); + else + PlaySFX(alltext[message].sfxnr); + } + if (gbMaxPlayers != 1) + NetSendCmdQuest(TRUE, Q_FARMER); + + } // JKENEWTOWNER + } + + else if (towner[t]._ttype == TWN_COWSUIT) + { + if (! qtextflag) + { + int message = TXT_COWSUIT1; + int textflag = TRUE; + if (PlrHasItem(p, IDI_SUITGREY, i)) + { + message = TXT_COWSUIT7; + RemoveInvItem(p, i); + } + else if (PlrHasItem(p, IDI_SUITBRWN, i)) + { + CreateItem(UID_ARMRCOW,towner[t]._tx + 1, towner[t]._ty); + RemoveInvItem(p, i); + message = TXT_COWSUIT8; + quests[Q_COWSUIT]._qactive = QUEST_DONE; + } + else if (PlrHasItem(p, IDI_RUNEBOMB, i)) + { + message = TXT_COWSUIT5; + quests[Q_COWSUIT]._qactive = QUEST_NOTDONE; + quests[Q_COWSUIT]._qvar1 = 1; + quests[Q_COWSUIT]._qmsg = TXT_COWSUIT4; + quests[Q_COWSUIT]._qlog = TRUE; + } + else + { + switch (quests[Q_COWSUIT]._qactive) + { + case QUEST_NOTAVAIL: + message = TXT_COWSUIT1; + quests[Q_COWSUIT]._qactive = QUEST_PASS1; + break; + case QUEST_PASS1: + message = TXT_COWSUIT2; + quests[Q_COWSUIT]._qactive = QUEST_PASS2; + break; + case QUEST_PASS2: + message = TXT_COWSUIT3; + quests[Q_COWSUIT]._qactive = QUEST_PASS3; + break; + case QUEST_PASS3: + if (!(plr[myplr]._pLvlVisited[9] || plr[myplr]._pLevel >= 15)) + { + int respond; + respond = random(0,4) + 9; + switch (respond) + { + case 9: + message = TXT_COWSUIT9; + break; + case 10: + message = TXT_COWSUIT10; + break; + case 11: + message = TXT_COWSUIT11; + break; + default: + message = TXT_COWSUIT12; + } + break; + } + else + { + message = TXT_COWSUIT4; + quests[Q_COWSUIT]._qactive = QUEST_NOTDONE; + quests[Q_COWSUIT]._qvar1 = 1; + quests[Q_COWSUIT]._qmsg = TXT_COWSUIT4; + quests[Q_COWSUIT]._qlog = TRUE; + SpawnBomb(towner[t]._tx + 1, towner[t]._ty); + textflag = TRUE; + break; + } + case QUEST_NOTDONE: + message = TXT_COWSUIT5; + break; + case QUEST_DONE: + message = TXT_COWSUIT1; + break; + case QUEST_NOTACTIVE: + message = TXT_COWSUIT1; + quests[Q_COWSUIT]._qactive = QUEST_PASS1; + break; + default: + message = TXT_COWSUIT5; + quests[Q_COWSUIT]._qactive = QUEST_NOTAVAIL; + + + } + } + + if (message != -1) + { + if (textflag) + InitQTextMsg(message); + else + PlaySFX(alltext[message].sfxnr); + } + if (gbMaxPlayers != 1) + NetSendCmdQuest(TRUE, Q_COWSUIT); + + } // borrow this JKENEWTOWNER + } + else if (towner[t]._ttype == TWN_GIRL) + { + if (! qtextflag) + { + int message = TXT_THEO1; + int textflag = FALSE; + if((PlrHasItem(p, IDI_THEODORE, i)) && (quests[Q_THEO]._qactive != QUEST_DONE)) + { + message = TXT_THEO4; + RemoveInvItem(p, i); + //SpawnSomething(IDI_AURIC, towner[t]._tx, towner[t]._ty + 1); + CreateAmulet(towner[t]._tx, towner[t]._ty, 13, FALSE, TRUE); + quests[Q_THEO]._qactive = QUEST_DONE; + quests[Q_THEO]._qlog = FALSE; + textflag = TRUE; + } + else + switch (quests[Q_THEO]._qactive) + { + case QUEST_NOTAVAIL: + message = TXT_THEO2; + quests[Q_THEO]._qactive = QUEST_NOTDONE; + quests[Q_THEO]._qvar1 = 1; + quests[Q_THEO]._qlog = TRUE; + quests[Q_THEO]._qmsg = TXT_THEO2; + textflag = TRUE; + break; + case QUEST_NOTDONE: + message = TXT_THEO3; + textflag = TRUE; + break; + case QUEST_DONE: + message = -1; + break; + case QUEST_NOTACTIVE: + message = TXT_THEO2; + quests[Q_THEO]._qvar1 = 1; + quests[Q_THEO]._qlog = TRUE; + quests[Q_THEO]._qmsg = TXT_THEO2; + quests[Q_THEO]._qactive = QUEST_NOTDONE; + textflag = TRUE; + break; + default: + message = TXT_THEO1; + quests[Q_THEO]._qactive = QUEST_NOTAVAIL; + + + } + + if (message != -1) + { + if (textflag) + InitQTextMsg(message); + else + PlaySFX(alltext[message].sfxnr); + } + if (gbMaxPlayers != 1) + NetSendCmdQuest(TRUE, Q_THEO); + + + } // JKENEWTOWNER + } +} + diff --git a/src/TOWNERS.H b/src/TOWNERS.H new file mode 100644 index 0000000..d85ce0c --- /dev/null +++ b/src/TOWNERS.H @@ -0,0 +1,130 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/TOWNERS.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +#include "quests.h" + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +#define MAX_TOWNERS 16 + +//#define TALKQUESTS 17 + +// These are interactive people in town, so @ beginning of towner list +#define TWN_BLKSMITH 0 +#define TWN_HEALER 1 +#define TWN_DEAD 2 +#define TWN_BAROWNER 3 +#define TWN_TELLER 4 +#define TWN_DRUNK 5 +#define TWN_WITCH 6 +#define TWN_BARMAID 7 +#define TWN_BOY 8 +#define TWN_COW 9 +#define TWN_FARMER 10 +#define TWN_GIRL 11 +#define TWN_COWSUIT 12 + +#define QSTMSG_NOTAVAIL 0 +#define QSTMSG_AVAIL 1 +#define QSTMSG_SAID 2 +#define QSTMSG_NOTSAID 3 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + byte _qsttype; // Quest type + byte _qstmsg; // Quest message + byte _qstmsgact; // Quest message flag +} TNQ; + +typedef struct { + int _tmode; // towners current mode + int _ttype; // towner type + int _tx; // plr map x + int _ty; // plr map y + long _txoff; // offset x from left of map tile + long _tyoff; // offset y from bottom of map tile + long _txvel; // current x rate + long _tyvel; // current y rate + int _tdir; // current towner direction + BYTE *_tAnimData; // Data pointer to anim tables + int _tAnimDelay; // anim delay amount + int _tAnimCnt; // current anim delay value + int _tAnimLen; // number of anim frames + int _tAnimFrame; // current anim frame + int _tAnimFrameCnt; // current anim frame count into AnimOrder + char _tAnimOrder; // Animation order or not + long _tAnimWidth; // width of anim frames + long _tAnimWidth2; // (width - 64) / 2 of towner for drawing + int _tTenPer; // Ten percent of time (special message said) + int _teflag; // draw extra tile to left for walk fix (flag) + int _tbtcnt; // Big text count + BOOL _tSelFlag; // Is the town person selectable? + BOOL _tMsgSaid; // Has the towner given his talk this trip to town? + TNQ qsts[MAXQUESTS];// quest struct for talking about quests + + int _tSeed; + + long _tVar1; // scratch var 1 + long _tVar2; // scratch var 2 + long _tVar3; // scratch var 3 + long _tVar4; // scratch var 4 + + char _tName[32]; // Towners name + + BYTE *_tNAnim[8]; // Neutral anims + int _tNFrames; // Number of neutral frames + + // Anything below this will not be saved or sent during a sync + BYTE *_tNData; // Neutral anim memory +} TownerStruct; + + +typedef struct { + int _qinfra; // Infravision + int _qblkm; // Black Mushroom + int _qgarb; + int _qzhar; + int _qveil; // Veil of Steel + int _qmod; // Map of Doom + int _qbutch; // Butcher + int _qbol; // Banner of Light + int _qblind; // Halls of Blind + int _qblood; // Stones of Blood + int _qanvil; // Anvil of Fury + int _qwarlrd; // Warlord of Blood + int _qking; // Skeleton King + int _qpw; // Poison Water + int _qbone; // Chamber of Bone + int _qvb; // Vile Betrayer +} QuestTalkData; + + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern TownerStruct towner[MAX_TOWNERS]; +extern int Qtalklist[14][MAXQUESTS]; // use define JKENEWTOWNERS +extern void SpawnBomb(int,int); + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void InitTowners(); +void FreeTownerGFX(); +void ProcessTowners(); +void TalkToTowner(int, int); +ItemStruct *PlrHasItem(int pnum, int item, int &i); diff --git a/src/TRACK.CPP b/src/TRACK.CPP new file mode 100644 index 0000000..2a32cd1 --- /dev/null +++ b/src/TRACK.CPP @@ -0,0 +1,115 @@ +//****************************************************************** +// track.cpp +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "msg.h" +#include "items.h" +#include "gendung.h" +#include "player.h" +#include "cursor.h" + + +//****************************************************************** +// compiler constants +//****************************************************************** +#define STOP_ON_MOUSEUP 0 // 0 in final +#define TRACKING_CURSOR 0 // 1 in final + + +//****************************************************************** +// private +//****************************************************************** + // track state on/off + static BOOL sgbMouseDown; + static BYTE sgbTrackMode; + + // time tracking last performed + #define TRACK_START_DELAY 250 // milliseconds + #define TRACK_LOOP_DELAY 300 // milliseconds + static long sglTrackTime; + + +//****************************************************************** +//****************************************************************** +void TrackMouse() { + // don't track if the mouse isn't down + if (! sgbMouseDown) return; + + // don't track if the cursor is out of range + if (cursmx < 0) return; + if (cursmx >= DMAXX - 1) return; + if (cursmy < 0) return; + if (cursmy >= DMAXY - 1) return; + + // don't track if the player isn't in a stand state or late walk + if (plr[myplr]._pVar8 <= 6 && plr[myplr]._pmode != PM_STAND) return; + + // don't track if mouse still on same target + if (cursmx == plr[myplr]._ptargx && cursmy == plr[myplr]._ptargy) return; + + // don't track if it hasn't been long enough since we last tracked + long lCurrTime = (long) GetTickCount(); + long lDelta = lCurrTime - sglTrackTime; + if (lDelta < TRACK_LOOP_DELAY) return; + sglTrackTime = lCurrTime; + + // track! + NetSendCmdLoc(TRUE,CMD_WALKXY,cursmx,cursmy); + + if (! sgbTrackMode) { + sgbTrackMode = TRUE; + #if TRACKING_CURSOR + if (curs == GLOVE_CURS) SetCursor(TARGET_CURS); + #endif + } +} + + +//****************************************************************** +//****************************************************************** +void TrackInit(BOOL bMouseDown) { + // are we already in desired state? + if (sgbMouseDown == bMouseDown) return; + sgbMouseDown = bMouseDown; + + if (sgbMouseDown) { + // indicate we haven't moved from click mode to track mode yet + sgbTrackMode = FALSE; + + // make next track time occur after TRACK_START_DELAY + // instead of TRACK_LOOP_DELAY + sglTrackTime = (long) GetTickCount(); + sglTrackTime += TRACK_START_DELAY; + sglTrackTime -= TRACK_LOOP_DELAY; + + // start tracking immediately by pumping a command into queue + NetSendCmdLoc(TRUE,CMD_WALKXY,cursmx,cursmy); + } + else if (sgbTrackMode) { + // turn off track mode + sgbTrackMode = FALSE; + + #if STOP_ON_MOUSEUP + // the user clicked on a map coordinate and held the mouse down + // long enough to indicate tracking rather than clicking, so + // since the mouse is up, stop the player at current coordinate + NetSendCmdLoc(TRUE,CMD_WALKXY,plr[myplr]._pfutx,plr[myplr]._pfuty); + #endif + + // restore cursor + #if TRACKING_CURSOR + if (curs == TARGET_CURS) SetCursor(GLOVE_CURS); + #endif + } +} + + +//****************************************************************** +//****************************************************************** +BOOL IsTracking() { + return sgbTrackMode; +} \ No newline at end of file diff --git a/src/TRIGS.CPP b/src/TRIGS.CPP new file mode 100644 index 0000000..612a314 --- /dev/null +++ b/src/TRIGS.CPP @@ -0,0 +1,1102 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Triggers file +** +** (C)1995 Condor, Inc. All rights reserved. +** +**-----------------------------------------------------------------------** +** $Header: /Diablo/TRIGS.CPP 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------** +** +** File Routines +**-----------------------------------------------------------------------*/ + +#include "diablo.h" +#pragma hdrstop +#include "trigs.h" +#include "palette.h" +#include "gendung.h" +#include "items.h" +#include "player.h" +#include "quests.h" +#include "cursor.h" +#include "control.h" +#include "effects.h" +#include "msg.h" +#include "multi.h" +#include "error.h" +#include "inv.h" +#include "setmaps.h" + +//#define JIM + + +/*-----------------------------------------------------------------------* +** Global Variables +**-----------------------------------------------------------------------*/ + +TriggerStruct trigs[MAXTRIGGERS]; +int numtrigs; +int TWarpFrom; + +int TownDownList[] = { 716, 715, 719, 720, 721, 723, 724, 725, 726, 727, -1 }; +int TownWarp1List[] = { 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1181, 1183, 1185, -1 }; + +//HellFire patch JKE +int TownCryptList[] = { 1331,1332,1333,1334,1335,1336,1337,1338, -1}; // Tag for info box +int TownHiveList[] = { 1307,1308,1309,1310, -1}; +//end of patch JKE + +int L1UpList[] = { 127, 129, 130, 131, 132, 133, 135, 137, 138, 139, 140, -1 }; +int L1DownList[] = { 106, 107, 108, 109, 110, 112, 114, 115, 118, -1 }; +int L2UpList[] = { 266, 267, -1 }; +int L2DownList[] = { 269, 270, 271, 272, -1 }; +int L2TWarpUpList[] = { 558, 559, -1 }; +int L3UpList[] = { 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, -1 }; +int L3DownList[] = { 162, 163, 164, 165, 166, 167, 168, 169, -1 }; +int L3TWarpUpList[] = { 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, -1 }; +//int L4UpList[] = { 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -1 }; +//int L4DownList[] = { 118, 120, 126, 127, 131, 132, 133, 134, 135, 137, 139, 140, 142, -1 }; +//int L4TWarpUpList[] = { 425, 427, 429, 430, 431, 432, 433, 434, 435, 439, -1 }; +int L4UpList[] = { 82, 83, 90, -1 }; +int L4DownList[] = { 120, 130, 131, 132, 133, -1 }; +int L4TWarpUpList[] = { 421, 422, 429, -1 }; +int L4PentaList[] = { 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, -1 }; + +// JKE new warp list for L5 CRYPT +int L5TWarpUpList[] = {172,173,174,175,176,177,178,179,184,-1}; +//int L5UpList[] = {159,-1}; +int L5UpList[] = {149,150,151,152,153,154,155,157,158,159,-1}; +//int L5DownList[] = {125,126,129,130,131,132,135,136,140,142,-1}; +int L5DownList[] = {125, 126, 129, 131, 132, 135, 136, 140, 142,-1}; + +// JKE new warp list for L6 +int L6TWarpUpList[] = {79,80,81,82,83,84,85,86,87,88,89,90,91,92,-1}; +int L6UpList[] = {65,66,67,68,69,70,71,72,73,74,75,76,77,78,-1}; +int L6DownList[] = {57,58,59,60,61,62,63,64,-1}; + +BOOL trigflag; +BOOL townwarps[3]; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitNoTriggers() +{ + numtrigs = 0; + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitTownTriggers() +{ + trigs[0]._tx = 25; + trigs[0]._ty = 29; + trigs[0]._tmsg = WM_DIABNEXTLVL; + numtrigs = 1; +#if IS_VERSION(SHAREWARE) + for (int i = 0; i < (MAX_PLRS - 1); i++) townwarps[i] = FALSE; + trigflag = FALSE; + return; +#endif + if (gbMaxPlayers == MAX_PLRS) { + for (int i = 0; i < 3; i++) townwarps[i] = TRUE; + trigs[1]._tx = 49; + trigs[1]._ty = 21; + trigs[1]._tmsg = WM_DIABTOWNWARP; + trigs[1]._tlvl = 5; +#if CHEATS + extern BOOL trigdebug; + if (trigdebug) + trigs[1]._tlvl = trigdebug; +#endif + numtrigs++; + trigs[2]._tx = 17; + trigs[2]._ty = 69; + trigs[2]._tmsg = WM_DIABTOWNWARP; + trigs[2]._tlvl = 9; + numtrigs++; + trigs[3]._tx = 41; + trigs[3]._ty = 80; + trigs[3]._tmsg = WM_DIABTOWNWARP; + trigs[3]._tlvl = 13; + numtrigs++; + trigs[4]._tx = 36; + trigs[4]._ty = 24; + trigs[4]._tmsg = WM_DIABTOWNWARP; + trigs[4]._tlvl = CRYPTSTART; + numtrigs++; + trigs[5]._tx = 80; + trigs[5]._ty = 62; + trigs[5]._tmsg = WM_DIABTOWNWARP; + trigs[5]._tlvl = HIVESTART; + numtrigs++; + } else { + for (int i = 0; i < (MAX_PLRS - 1); i++) townwarps[i] = FALSE; + if (plr[myplr].pTownWarps & 0x01 || plr[myplr]._pLevel >= 10) { + trigs[numtrigs]._tx = 49; + trigs[numtrigs]._ty = 21; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = 5; + numtrigs++; + townwarps[0] = TRUE; + } + if (plr[myplr].pTownWarps & 0x02 || plr[myplr]._pLevel >= 15) { + trigs[numtrigs]._tx = 17; + trigs[numtrigs]._ty = 69; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = 9; + numtrigs++; + townwarps[1] = TRUE; + } + if (plr[myplr].pTownWarps & 0x04 || plr[myplr]._pLevel >= 20) { + trigs[numtrigs]._tx = 41; + trigs[numtrigs]._ty = 80; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = 13; + numtrigs++; + townwarps[2] = TRUE; + } +// This will all have to be ifed with whatever we want to trigger with. + // for now I've assumed it is last and always active. JKE + + if (quests[Q_CRYPTMAP]._qactive == QUEST_DONE) + { + trigs[numtrigs]._tx = 36; + trigs[numtrigs]._ty = 24; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = CRYPTSTART; + ++numtrigs; + } + + trigs[numtrigs]._tx = 80; + trigs[numtrigs]._ty = 62; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = HIVESTART; + ++numtrigs; + } + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitL1Triggers() +{ + int i,j; + + numtrigs = 0; + if (currlevel < HIVESTART) + { + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + // if ((dPiece[i][j] == 129) && (currlevel == CRYPTSTART)) { // cheat to add level up for crypt very temporary JKE + // trigs[numtrigs]._tx = i; + // trigs[numtrigs]._ty = j; + // trigs[numtrigs]._tmsg = WM_DIABTWARPUP; + // trigs[numtrigs]._tlvl = 0; + // numtrigs++; + // } else { + if (dPiece[i][j] == 129) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABPREVLVL; + numtrigs++; + } + // } + if (dPiece[i][j] == 115) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; + } + } + } + } + else + { + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 184) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABTWARPUP; + trigs[numtrigs]._tlvl = 0; + numtrigs++; + } + if (dPiece[i][j] == 158) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABPREVLVL; + numtrigs++; + } + + if (dPiece[i][j] == 126) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; + } + } + } + } + + + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitL2Triggers() +{ + int i,j; + + numtrigs = 0; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 267) { + if ((i != quests[Q_SCHAMB]._qtx) || (j != quests[Q_SCHAMB]._qty)) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABPREVLVL; + numtrigs++; + } + } + if (dPiece[i][j] == 559) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABTWARPUP; + trigs[numtrigs]._tlvl = 0; + numtrigs++; + } + if (dPiece[i][j] == 271) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; + } + } + } + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitL3Triggers() +{ + int i,j; + + if (currlevel < HIVESTART) + { + numtrigs = 0; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 171) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABPREVLVL; + numtrigs++; + } + if (dPiece[i][j] == 168) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; + } + if (dPiece[i][j] == 549) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABTWARPUP; + numtrigs++; + } + } + } + } + else + { + numtrigs = 0; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 66) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABPREVLVL; + numtrigs++; + } + if (dPiece[i][j] == 63) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; + } + if (dPiece[i][j] == 80) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABTWARPUP; + numtrigs++; + } + } + } + } + + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitL4Triggers() +{ + int i,j; + + numtrigs = 0; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 83) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABPREVLVL; + numtrigs++; + } + if (dPiece[i][j] == 422) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABTWARPUP; + trigs[numtrigs]._tlvl = 0; + numtrigs++; + } + if (dPiece[i][j] == 120) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; + } + } + } + // this will ensure that the first trigger is not the trigger down to 16 + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if (dPiece[i][j] == 370) { + if (quests[Q_BETRAYER]._qactive == QUEST_DONE) { + trigs[numtrigs]._tx = i; + trigs[numtrigs]._ty = j; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; + } + } + } + } + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitSKingTriggers() +{ + numtrigs = 1; + trigs[0]._tx = 82; + trigs[0]._ty = 42; + trigs[0]._tmsg = WM_DIABRTNLVL; + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitSChambTriggers() +{ + numtrigs = 1; + trigs[0]._tx = 70; + trigs[0]._ty = 39; + trigs[0]._tmsg = WM_DIABRTNLVL; + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitPWaterTriggers() +{ + numtrigs = 1; + trigs[0]._tx = 30; + trigs[0]._ty = 83; + trigs[0]._tmsg = WM_DIABRTNLVL; + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void InitVPTriggers() +{ + numtrigs = 1; + trigs[0]._tx = 35; + trigs[0]._ty = 32; + trigs[0]._tmsg = WM_DIABRTNLVL; + trigflag = FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL ForceTownTrig() +{ + int i; +#ifdef JIM // debug only + char mystr[10]; +#endif + +// HellFire patch JKE + for (i = 0; TownCryptList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == TownCryptList[i]) { + strcpy(infostr, "Down to Crypt"); +#ifdef JIM // debug only + _itoa(dPiece[cursmx][cursmy],mystr,10); + strcat(infostr,mystr); + +#endif // END + cursmx = 36; + cursmy = 24; + return(TRUE); + } + } + for (i = 0; TownHiveList [i] != -1; i++) { + if (dPiece[cursmx][cursmy] == TownHiveList[i]) { + strcpy(infostr, "Down to Hive"); + cursmx = 80; + cursmy = 62; + return(TRUE); + } + } +// end patch JKE + + for (i = 0; TownDownList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == TownDownList[i]) { + strcpy(infostr, "Down to dungeon"); + + // JIM info bit +#ifdef JIM + _itoa(dPiece[cursmx][cursmy],mystr,10); + strcat(infostr,mystr); +#endif + // END + cursmx = 25; + cursmy = 29; + return(TRUE); + } + } + if (townwarps[0]) { + for (i = 0; TownWarp1List[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == TownWarp1List[i]) { + strcpy(infostr, "Down to catacombs"); + // JIM info bit +#ifdef JIM + _itoa(dPiece[cursmx][cursmy],mystr,10); + strcat(infostr,mystr); +#endif + // END + cursmx = 49; + cursmy = 21; + return(TRUE); + } + } + } + if (townwarps[1]) { + for (i = 1199; i <= 1220; i++) { + if (dPiece[cursmx][cursmy] == i) { + strcpy(infostr, "Down to caves"); + // JIM info bit +#ifdef JIM + _itoa(dPiece[cursmx][cursmy],mystr,10); + strcat(infostr,mystr); +#endif + // END + cursmx = 17; + cursmy = 69; + return(TRUE); + } + } + } + if (townwarps[2]) { + for (i = 1240; i <= 1255; i++) { + if (dPiece[cursmx][cursmy] == i) { + strcpy(infostr, "Down to hell"); + // JIM info bit +#ifdef JIM + _itoa(dPiece[cursmx][cursmy],mystr,10); + strcat(infostr,mystr); +#endif + // END + cursmx = 41; + cursmy = 80; + return(TRUE); + } + } + } + // JIM info bit +#ifdef JIM + sprintf(infostr,"X: %d, Y: %d, dPiece: %d", cursmx, cursmy,dPiece[cursmx][cursmy]); + return (TRUE); +#endif + // END + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +BOOL ForceL1Trig() { + int i, j, dx, dy; + + if (currlevel < HIVESTART) + { + for (i = 0; L1UpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L1UpList[i]) { + if (currlevel > 1) sprintf(infostr, "Up to level %i",currlevel - 1); + else strcpy(infostr, "Up to town"); +// Total hack up just cause I aint got art. JKE +// if (currlevel == 17) { +// strcpy(infostr, "Warp to town"); +// if (trigs[j]._tmsg == WM_DIABTWARPUP) { +// cursmx = trigs[j]._tx; +// cursmy = trigs[j]._ty; +// return(TRUE); +// } +// } +// end of hack + + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABPREVLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + + for (i = 0; L1DownList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L1DownList[i]) { + sprintf(infostr, "Down to level %i", currlevel + 1); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABNEXTLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + else + { + for (i = 0; L5UpList[i] != -1; i++) + { + if (dPiece[cursmx][cursmy] == L5UpList[i]) + { + sprintf(infostr, "Up to Crypt level %i", currlevel - 21); + for (j = 0; j < numtrigs; j++) + { + if (trigs[j]._tmsg == WM_DIABPREVLVL) + { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + if (dPiece[cursmx][cursmy] == 317) // cornerstone + { + strcpy (infostr, "Cornerstone of the World"); + return(TRUE); + } + for (i = 0; L5DownList[i] != -1; i++) + { + if (dPiece[cursmx][cursmy] == L5DownList[i]) + { + sprintf(infostr, "Down to Crypt level %i", currlevel - 19); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABNEXTLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + + if (currlevel == CRYPTSTART) { + for (i = 0; L5TWarpUpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L5TWarpUpList[i]) { + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABTWARPUP) { + dx = abs(trigs[j]._tx - cursmx); + dy = abs(trigs[j]._ty - cursmy); + if ((dx < 4) && (dy < 4)) { + strcpy(infostr, "Up to town"); + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + } + } + // JIM info bit +#ifdef JIM + sprintf(infostr,"X: %d, Y: %d, dPiece: %d", cursmx, cursmy,dPiece[cursmx][cursmy]); + return (TRUE); +#endif + // END + return(FALSE); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL ForceL2Trig() +{ + int i, j, dx, dy; + + for (i = 0; L2UpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L2UpList[i]) { + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABPREVLVL) { + dx = abs(trigs[j]._tx - cursmx); + dy = abs(trigs[j]._ty - cursmy); + if ((dx < 4) && (dy < 4)) { + sprintf(infostr, "Up to level %i", currlevel - 1); + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + for (i = 0; L2DownList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L2DownList[i]) { + sprintf(infostr, "Down to level %i", currlevel + 1); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABNEXTLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + if (currlevel == 5) { + for (i = 0; L2TWarpUpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L2TWarpUpList[i]) { + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABTWARPUP) { + dx = abs(trigs[j]._tx - cursmx); + dy = abs(trigs[j]._ty - cursmy); + if ((dx < 4) && (dy < 4)) { + strcpy(infostr, "Up to town"); + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL ForceL3Trig() +{ + int i, j, dx, dy; + +// JKE level 6 stuff + if (currlevel < HIVESTART) + { + for (i = 0; L3UpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L3UpList[i]) { + sprintf(infostr, "Up to level %i", currlevel - 1); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABPREVLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + for (i = 0; L3DownList[i] != -1; i++) { + if ((dPiece[cursmx][cursmy] == L3DownList[i]) || + (dPiece[cursmx+1][cursmy] == L3DownList[i]) || + (dPiece[cursmx+2][cursmy] == L3DownList[i])) { + sprintf(infostr, "Down to level %i", currlevel + 1); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABNEXTLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + else + { + for (i = 0; L6UpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L6UpList[i]) { + sprintf(infostr, "Up to Nest level %i", currlevel - 17); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABPREVLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + for (i = 0; L6DownList[i] != -1; i++) { + if ((dPiece[cursmx][cursmy] == L6DownList[i]) || + (dPiece[cursmx+1][cursmy] == L6DownList[i]) || + (dPiece[cursmx+2][cursmy] == L6DownList[i])) { + sprintf(infostr, "Down to level %i", currlevel - 15); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABNEXTLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + + if (currlevel == 9) { + for (i = 0; L3TWarpUpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L3TWarpUpList[i]) { + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABTWARPUP) { + dx = abs(trigs[j]._tx - cursmx); + dy = abs(trigs[j]._ty - cursmy); + if ((dx < 4) && (dy < 4)) { + strcpy(infostr, "Up to town"); + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + } + if (currlevel == HIVESTART) { + for (i = 0; L6TWarpUpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L6TWarpUpList[i]) { + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABTWARPUP) { + dx = abs(trigs[j]._tx - cursmx); + dy = abs(trigs[j]._ty - cursmy); + if ((dx < 4) && (dy < 4)) { + strcpy(infostr, "Up to town"); + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL ForceL4Trig() +{ + int i, j, dx, dy; + + for (i = 0; L4UpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L4UpList[i]) { + sprintf(infostr, "Up to level %i", currlevel - 1); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABPREVLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + for (i = 0; L4DownList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L4DownList[i]) { + sprintf(infostr, "Down to level %i", currlevel + 1); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABNEXTLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + if (currlevel == 13) { + for (i = 0; L4TWarpUpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L4TWarpUpList[i]) { + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABTWARPUP) { + dx = abs(trigs[j]._tx - cursmx); + dy = abs(trigs[j]._ty - cursmy); + if ((dx < 4) && (dy < 4)) { + strcpy(infostr, "Up to town"); + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + } + if (currlevel == 15) { + for (i = 0; L4PentaList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L4PentaList[i]) { + strcpy(infostr, "Down to Diablo"); + for (j = 0; j < numtrigs; j++) { + if (trigs[j]._tmsg == WM_DIABNEXTLVL) { + cursmx = trigs[j]._tx; + cursmy = trigs[j]._ty; + return(TRUE); + } + } + } + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void Freeupstairs() +{ + int j, tx, ty, xx, yy; + + for (j = 0; j < numtrigs; j++) { + tx = trigs[j]._tx; + ty = trigs[j]._ty; + for (yy = -2; yy <= 2; yy++) { + for (xx = -2; xx <= 2; xx++) + dFlags[tx+xx][ty+yy] |= BFLAG_SETPC; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL ForceSKingTrig() +{ + int i; + + for (i = 0; L1UpList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L1UpList[i]) { + sprintf(infostr, "Back to Level %i", quests[Q_SKELKING]._qlevel); + cursmx = trigs[0]._tx; + cursmy = trigs[0]._ty; + return(TRUE); + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL ForceSChambTrig() +{ + int i; + + for (i = 0; L2DownList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L2DownList[i]) { + sprintf(infostr, "Back to Level %i", quests[Q_SCHAMB]._qlevel); + cursmx = trigs[0]._tx; + cursmy = trigs[0]._ty; + return(TRUE); + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +BOOL ForcePWaterTrig() +{ + int i; + + for (i = 0; L3DownList[i] != -1; i++) { + if (dPiece[cursmx][cursmy] == L3DownList[i]) { + sprintf(infostr, "Back to Level %i", quests[Q_PWATER]._qlevel); + cursmx = trigs[0]._tx; + cursmy = trigs[0]._ty; + return(TRUE); + } + } + return(FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +void CheckTrigForce() +{ + trigflag = FALSE; + if (MouseY > 351) return; + if (!setlevel) { + switch (leveltype) { + case 0: + trigflag = ForceTownTrig(); + break; + case 1: + trigflag = ForceL1Trig(); + break; + case 2: + trigflag = ForceL2Trig(); + break; + case 3: + trigflag = ForceL3Trig(); + break; + case 4: + trigflag = ForceL4Trig(); + break; + } + if (leveltype && !trigflag) + trigflag = ForceQuests(); + } else { + switch (setlvlnum) { + case SL_SKELKING: + trigflag = ForceSKingTrig(); + break; + case SL_BONECHAMB: + trigflag = ForceSChambTrig(); + break; + case SL_POISONWATER: + trigflag = ForcePWaterTrig(); + break; +/* case SL_VILEBETRAYER: + trigflag = ForceVBetTrig(); + break;*/ + } + } + if (trigflag) ClearPanel(); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void CheckTriggers() { + + // player can only work triggers in stand mode + if (plr[myplr]._pmode != PM_STAND) + return; + + for (int i = 0; i < numtrigs; i++) { + if (plr[myplr]._px != trigs[i]._tx) continue; + if (plr[myplr]._py != trigs[i]._ty) continue; + + switch (trigs[i]._tmsg) { + case WM_DIABNEXTLVL: + #if IS_VERSION(SHAREWARE) + if (currlevel >= 2) { + NetSendCmdLoc(TRUE,CMD_WALKXY,plr[myplr]._px,plr[myplr]._py+1); + PlaySFX(PS_WARR18); // "no way" + InitDiabloMsg(MSG_SHAREWARE); + break; + } + #endif + //Does player have item in hand? If so, drop it before going down level. + if (curs >= ICSTART) { + if(DropItemBeforeTrig()) return; + } + StartNewLvl(myplr,trigs[i]._tmsg,currlevel + 1); + break; + + case WM_DIABPREVLVL: + //Does player have item in hand? If so, drop it before going up level. + if (curs >= ICSTART) { + if(DropItemBeforeTrig()) return; + } + StartNewLvl(myplr,trigs[i]._tmsg,currlevel - 1); + break; + + case WM_DIABTOWNWARP: + if (gbMaxPlayers != 1) { + BOOL abortflag = FALSE; + int dx,dy; + char m; + if ((trigs[i]._tlvl == 5) && (plr[myplr]._pLevel < 8)) { + abortflag = TRUE; + dx = plr[myplr]._px; + dy = plr[myplr]._py+1; + m = MSG_TRIG1; + } + if ((trigs[i]._tlvl == 9) && (plr[myplr]._pLevel < 13)) { + abortflag = TRUE; + dx = plr[myplr]._px+1; + dy = plr[myplr]._py; + m = MSG_TRIG2; + } + if ((trigs[i]._tlvl == 13) && (plr[myplr]._pLevel < 17)) { + abortflag = TRUE; + dx = plr[myplr]._px; + dy = plr[myplr]._py+1; + m = MSG_TRIG3; + } + if (abortflag) { + if (plr[myplr]._pClass == CLASS_WARRIOR) PlaySFX(PS_WARR43); + #if !IS_VERSION(SHAREWARE) + else if (plr[myplr]._pClass == CLASS_ROGUE) PlaySFX(PS_ROGUE43); + else if (plr[myplr]._pClass == CLASS_SORCEROR) PlaySFX(PS_MAGE43); + else if (plr[myplr]._pClass == CLASS_MONK) PlaySFX(PS_MONK43); + else if (plr[myplr]._pClass == CLASS_BARD) PlaySFX(PS_BARD43); + else if (plr[myplr]._pClass == CLASS_BARBARIAN) PlaySFX(PS_BARBARIAN43); + #endif + InitDiabloMsg(m); + NetSendCmdLoc(TRUE,CMD_WALKXY,dx,dy); + return; + } + } + StartNewLvl(myplr,trigs[i]._tmsg,trigs[i]._tlvl); + break; + + case WM_DIABTWARPUP: + TWarpFrom = currlevel; + StartNewLvl(myplr,trigs[i]._tmsg,0); + break; + + case WM_DIABRTNLVL: + // doesn't work for multiplayer + app_assert(gbMaxPlayers == 1); + StartNewLvl(myplr,trigs[i]._tmsg,ReturnLvl); + break; + + default: + app_fatal("Unknown trigger msg"); + break; + } + } + +} + \ No newline at end of file diff --git a/src/TRIGS.H b/src/TRIGS.H new file mode 100644 index 0000000..16f416c --- /dev/null +++ b/src/TRIGS.H @@ -0,0 +1,63 @@ +/*-----------------------------------------------------------------------** +** Diablo +** +** Constants and Variables +** +** (C)1995 Condor, Inc. All rights reserved. +**-----------------------------------------------------------------------** +** $Header: /Diablo/TRIGS.H 2 1/23/97 12:21p Jmorin $ +**-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------** +** Defines +**-----------------------------------------------------------------------*/ + +//#define MAXTRIGGERS 5 +#define MAXTRIGGERS 7 // to add crypt and hive JKE + +#define LVL_DOWN 0 +#define LVL_UP 1 +#define LVL_SET 2 +#define LVL_RTN 3 +#define LVL_NODIR 4 +#define LVL_WARP 5 +#define LVL_TWARPDN 6 +#define LVL_TWARPUP 7 + +/*-----------------------------------------------------------------------** +** Structures +**-----------------------------------------------------------------------*/ + +typedef struct { + int _tx; + int _ty; + unsigned int _tmsg; + int _tlvl; +} TriggerStruct; + +/*-----------------------------------------------------------------------** +** Externs +**-----------------------------------------------------------------------*/ + +extern BOOL trigflag; +extern TriggerStruct trigs[MAXTRIGGERS]; +extern int numtrigs; + +/*-----------------------------------------------------------------------** +** Prototypes +**-----------------------------------------------------------------------*/ + +void CheckTriggers(); +void InitTownTriggers(); +void InitL1Triggers(); +void InitL2Triggers(); +void InitL3Triggers(); +void InitL4Triggers(); +void InitSKingTriggers(); +void InitSChambTriggers(); +void InitPWaterTriggers(); +void InitNoTriggers(); +void InitVPTriggers(); + +void CheckTrigForce(); +void Freeupstairs(); \ No newline at end of file diff --git a/src/UNIQUES.TXT b/src/UNIQUES.TXT new file mode 100644 index 0000000..9e8a078 --- /dev/null +++ b/src/UNIQUES.TXT @@ -0,0 +1,13 @@ +------------Donald------------ + +Re: Mr. Tsang Could you Please... from Donald Tsang (donaldtsang), Wed Jan 28 15:47:19 US/Pacific 1998 In-reply-to To Mister Tsang. + +(please call me Donald; "Mr. Tsang" makes me feel old. :) + +Okay, so the random item generator has determined that you may deserve a random unique of a certain type (say, rings). + +Now it goes through the list of uniques, and sees if there are any that you're allowed to have on that dungeon level (plus a few if you're getting this from a unique critter) that you haven't already found this session. + +It then takes the last one of those it finds (which is, presumably, the highest-level-and-therefore-best), and gives it to you. + +Me, I would've made that last step just a random pick from the list (perhaps weighted toward the highest-level one), but what do I know? \ No newline at end of file diff --git a/src/Uisrc/BATTLE/BNETART.H b/src/Uisrc/BATTLE/BNETART.H new file mode 100644 index 0000000..cba8b17 --- /dev/null +++ b/src/Uisrc/BATTLE/BNETART.H @@ -0,0 +1,30 @@ +/**************************************************************************** +* +* bnetart.h +* +* This file should be included by an application that wants to provide +* battle.net-specific artwork in its art callback. +* +***/ + +enum _BATTLENET_ART { + SNET_ART_BATTLE_BTNS = 0x80000000, + SNET_ART_BATTLE_CHAT_BKG, + SNET_ART_BATTLE_GREENLAG, + SNET_ART_BATTLE_YELLOWLAG, + SNET_ART_BATTLE_REDLAG, + SNET_ART_BATTLE_CONNECT_BKG, + SNET_ART_BATTLE_SELECT_CHNL_BKG, + SNET_ART_BATTLE_LOGIN_BKG, + + SNET_ART_BATTLE_BADCONNECTION, + SNET_ART_BATTLE_WELCOME_AD, + + SNET_ART_BATTLE_LRG_EDIT_POPUP_BKG, +}; + + +enum _BATTLENET_DATA { + SNET_DATA_BATTLE_LOGODELAY = 0x80000000, // (DWORD) delay between frames +}; + diff --git a/src/Uisrc/BATTLE/DEBUG/BATTLE.LIB b/src/Uisrc/BATTLE/DEBUG/BATTLE.LIB new file mode 100644 index 0000000..d2a90c7 Binary files /dev/null and b/src/Uisrc/BATTLE/DEBUG/BATTLE.LIB differ diff --git a/src/Uisrc/BATTLE/RELEASE/BATTLE.LIB b/src/Uisrc/BATTLE/RELEASE/BATTLE.LIB new file mode 100644 index 0000000..d2a90c7 Binary files /dev/null and b/src/Uisrc/BATTLE/RELEASE/BATTLE.LIB differ diff --git a/src/Uisrc/BIN/BATTLE.SNP b/src/Uisrc/BIN/BATTLE.SNP new file mode 100644 index 0000000..6030771 Binary files /dev/null and b/src/Uisrc/BIN/BATTLE.SNP differ diff --git a/src/Uisrc/BIN/BNCACHE.DAT b/src/Uisrc/BIN/BNCACHE.DAT new file mode 100644 index 0000000..a70a34d Binary files /dev/null and b/src/Uisrc/BIN/BNCACHE.DAT differ diff --git a/src/Uisrc/BIN/DIABLOUI.EXE b/src/Uisrc/BIN/DIABLOUI.EXE new file mode 100644 index 0000000..e60c77d Binary files /dev/null and b/src/Uisrc/BIN/DIABLOUI.EXE differ diff --git a/src/Uisrc/BIN/SMACKW32.DLL b/src/Uisrc/BIN/SMACKW32.DLL new file mode 100644 index 0000000..e756b2f Binary files /dev/null and b/src/Uisrc/BIN/SMACKW32.DLL differ diff --git a/src/Uisrc/BIN/STORM.DLL b/src/Uisrc/BIN/STORM.DLL new file mode 100644 index 0000000..b80dff6 Binary files /dev/null and b/src/Uisrc/BIN/STORM.DLL differ diff --git a/src/Uisrc/BIN/STORM.SAV b/src/Uisrc/BIN/STORM.SAV new file mode 100644 index 0000000..3a77cd0 Binary files /dev/null and b/src/Uisrc/BIN/STORM.SAV differ diff --git a/src/Uisrc/DEBUG/DIABLOUI.PCH b/src/Uisrc/DEBUG/DIABLOUI.PCH new file mode 100644 index 0000000..405420d Binary files /dev/null and b/src/Uisrc/DEBUG/DIABLOUI.PCH differ diff --git a/src/Uisrc/DEBUG/TESTUI.SBR b/src/Uisrc/DEBUG/TESTUI.SBR new file mode 100644 index 0000000..e69de29 diff --git a/src/Uisrc/DEBUG/VC50.IDB b/src/Uisrc/DEBUG/VC50.IDB new file mode 100644 index 0000000..1369c6e Binary files /dev/null and b/src/Uisrc/DEBUG/VC50.IDB differ diff --git a/src/Uisrc/DIABLOUI.BAK b/src/Uisrc/DIABLOUI.BAK new file mode 100644 index 0000000..4e25fd7 --- /dev/null +++ b/src/Uisrc/DIABLOUI.BAK @@ -0,0 +1,2751 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +!IF "$(CFG)" == "" +CFG=Standard - Win32 Debug +!MESSAGE No configuration specified. Defaulting to Standard - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "DiabloUI - Win32 Release" && "$(CFG)" !=\ + "DiabloUI - Win32 Debug" && "$(CFG)" != "ui - Win32 Release" && "$(CFG)" !=\ + "ui - Win32 Debug" && "$(CFG)" != "battle - Win32 Release" && "$(CFG)" !=\ + "battle - Win32 Debug" && "$(CFG)" != "Standard - Win32 Release" && "$(CFG)" !=\ + "Standard - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Diabloui.mak" CFG="Standard - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "DiabloUI - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "DiabloUI - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "ui - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ui - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "battle - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "battle - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Standard - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Standard - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Standard - Win32 Debug" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "Standard - Win32 Release" "battle - Win32 Release" "ui - Win32 Release"\ + ".\bin\DiabloUI.exe" + +CLEAN : + -@erase "$(INTDIR)\Testui.obj" + -@erase "$(OUTDIR)\DiabloUI.map" + -@erase ".\bin\DiabloUI.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /G5 /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/Diabloui.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/Diabloui.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib ui\release\diabloui.lib battle\release\battle.lib standard\release\standard.lib /nologo /subsystem:windows /map /machine:I386 /out:"bin/DiabloUI.exe" +# SUBTRACT LINK32 /incremental:yes +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib\ + wsock32.lib storm.lib ui\release\diabloui.lib battle\release\battle.lib\ + standard\release\standard.lib /nologo /subsystem:windows /incremental:no\ + /pdb:"$(OUTDIR)/DiabloUI.pdb" /map:"$(INTDIR)/DiabloUI.map" /machine:I386\ + /out:"bin/DiabloUI.exe" +LINK32_OBJS= \ + "$(INTDIR)\Testui.obj" \ + ".\battle\Release\battle.lib" \ + ".\Standard\Release\Standard.lib" \ + ".\STORM.LIB" \ + ".\ui\Release\diabloui.lib" + +".\bin\DiabloUI.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "Standard - Win32 Debug" "battle - Win32 Debug" "ui - Win32 Debug"\ + ".\bin\DiabloUI.exe" + +CLEAN : + -@erase "$(INTDIR)\Testui.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\DiabloUI.map" + -@erase "$(OUTDIR)\DiabloUI.pdb" + -@erase ".\bin\DiabloUI.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/Diabloui.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/Diabloui.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib ui\debug\diabloui.lib battle\debug\battle.lib standard\debug\standard.lib /nologo /subsystem:windows /incremental:no /map /debug /machine:I386 /out:"bin/DiabloUI.exe" +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib\ + wsock32.lib storm.lib ui\debug\diabloui.lib battle\debug\battle.lib\ + standard\debug\standard.lib /nologo /subsystem:windows /incremental:no\ + /pdb:"$(OUTDIR)/DiabloUI.pdb" /map:"$(INTDIR)/DiabloUI.map" /debug\ + /machine:I386 /out:"bin/DiabloUI.exe" +LINK32_OBJS= \ + "$(INTDIR)\Testui.obj" \ + ".\battle\debug\battle.lib" \ + ".\Standard\Debug\Standard.lib" \ + ".\STORM.LIB" \ + ".\ui\Debug\diabloui.lib" + +".\bin\DiabloUI.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ui - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ui\Release" +# PROP BASE Intermediate_Dir "ui\Release" +# PROP BASE Target_Dir "ui" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ui\Release" +# PROP Intermediate_Dir "ui\Release" +# PROP Target_Dir "ui" +OUTDIR=.\ui\Release +INTDIR=.\ui\Release + +ALL : ".\bin\diabloui.dll" + +CLEAN : + -@erase "$(INTDIR)\artfont.obj" + -@erase "$(INTDIR)\connect.obj" + -@erase "$(INTDIR)\CopyProt.obj" + -@erase "$(INTDIR)\cr8game.obj" + -@erase "$(INTDIR)\CreaDung.obj" + -@erase "$(INTDIR)\CreaHero.obj" + -@erase "$(INTDIR)\credits.obj" + -@erase "$(INTDIR)\DiabEdit.obj" + -@erase "$(INTDIR)\Diabloui.obj" + -@erase "$(INTDIR)\DiabloUI.res" + -@erase "$(INTDIR)\DirLink.obj" + -@erase "$(INTDIR)\disclaim.obj" + -@erase "$(INTDIR)\Doom.obj" + -@erase "$(INTDIR)\EntrDial.obj" + -@erase "$(INTDIR)\EntrName.obj" + -@erase "$(INTDIR)\Fade.obj" + -@erase "$(INTDIR)\Focus.obj" + -@erase "$(INTDIR)\local.obj" + -@erase "$(INTDIR)\Logon.obj" + -@erase "$(INTDIR)\MainMenu.obj" + -@erase "$(INTDIR)\Modem.obj" + -@erase "$(INTDIR)\ModmStat.obj" + -@erase "$(INTDIR)\OkCancel.obj" + -@erase "$(INTDIR)\Progress.obj" + -@erase "$(INTDIR)\Sbar.obj" + -@erase "$(INTDIR)\SelClass.obj" + -@erase "$(INTDIR)\SelConn.obj" + -@erase "$(INTDIR)\SelDial.obj" + -@erase "$(INTDIR)\SelGame.obj" + -@erase "$(INTDIR)\SelHero.obj" + -@erase "$(INTDIR)\SelIPX.obj" + -@erase "$(INTDIR)\SelList.obj" + -@erase "$(INTDIR)\SelLoad.obj" + -@erase "$(INTDIR)\SelModem.obj" + -@erase "$(INTDIR)\SelYesNo.obj" + -@erase "$(INTDIR)\Title.obj" + -@erase "$(INTDIR)\UiSnd.obj" + -@erase "$(OUTDIR)\diabloui.exp" + -@erase "$(OUTDIR)\diabloui.lib" + -@erase "$(OUTDIR)\diabloui.map" + -@erase ".\bin\diabloui.dll" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /G5Fry /c +CPP_PROJ=/nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/ui.pch" /YX /Fo"$(INTDIR)/" /G5Fry /c +CPP_OBJS=.\ui\Release/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/DiabloUI.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/ui.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x20000000 /subsystem:windows /dll /map /machine:I386 /out:"bin/diabloui.dll" +# SUBTRACT LINK32 /incremental:yes +LINK32_FLAGS=tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib\ + shell32.lib wsock32.lib storm.lib /nologo /base:0x20000000 /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)/diabloui.pdb"\ + /map:"$(INTDIR)/diabloui.map" /machine:I386 /def:".\Ui\Diabloui.def"\ + /out:"bin/diabloui.dll" /implib:"$(OUTDIR)/diabloui.lib" +DEF_FILE= \ + ".\Ui\Diabloui.def" +LINK32_OBJS= \ + "$(INTDIR)\artfont.obj" \ + "$(INTDIR)\connect.obj" \ + "$(INTDIR)\CopyProt.obj" \ + "$(INTDIR)\cr8game.obj" \ + "$(INTDIR)\CreaDung.obj" \ + "$(INTDIR)\CreaHero.obj" \ + "$(INTDIR)\credits.obj" \ + "$(INTDIR)\DiabEdit.obj" \ + "$(INTDIR)\Diabloui.obj" \ + "$(INTDIR)\DiabloUI.res" \ + "$(INTDIR)\DirLink.obj" \ + "$(INTDIR)\disclaim.obj" \ + "$(INTDIR)\Doom.obj" \ + "$(INTDIR)\EntrDial.obj" \ + "$(INTDIR)\EntrName.obj" \ + "$(INTDIR)\Fade.obj" \ + "$(INTDIR)\Focus.obj" \ + "$(INTDIR)\local.obj" \ + "$(INTDIR)\Logon.obj" \ + "$(INTDIR)\MainMenu.obj" \ + "$(INTDIR)\Modem.obj" \ + "$(INTDIR)\ModmStat.obj" \ + "$(INTDIR)\OkCancel.obj" \ + "$(INTDIR)\Progress.obj" \ + "$(INTDIR)\Sbar.obj" \ + "$(INTDIR)\SelClass.obj" \ + "$(INTDIR)\SelConn.obj" \ + "$(INTDIR)\SelDial.obj" \ + "$(INTDIR)\SelGame.obj" \ + "$(INTDIR)\SelHero.obj" \ + "$(INTDIR)\SelIPX.obj" \ + "$(INTDIR)\SelList.obj" \ + "$(INTDIR)\SelLoad.obj" \ + "$(INTDIR)\SelModem.obj" \ + "$(INTDIR)\SelYesNo.obj" \ + "$(INTDIR)\Title.obj" \ + "$(INTDIR)\UiSnd.obj" \ + ".\STORM.LIB" + +".\bin\diabloui.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ui\ui___Win" +# PROP BASE Intermediate_Dir "ui\ui___Win" +# PROP BASE Target_Dir "ui" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "ui\Debug" +# PROP Intermediate_Dir "ui\Debug" +# PROP Target_Dir "ui" +OUTDIR=.\ui\Debug +INTDIR=.\ui\Debug + +ALL : ".\bin\diabloui.dll" + +CLEAN : + -@erase "$(INTDIR)\artfont.obj" + -@erase "$(INTDIR)\connect.obj" + -@erase "$(INTDIR)\CopyProt.obj" + -@erase "$(INTDIR)\cr8game.obj" + -@erase "$(INTDIR)\CreaDung.obj" + -@erase "$(INTDIR)\CreaHero.obj" + -@erase "$(INTDIR)\credits.obj" + -@erase "$(INTDIR)\DiabEdit.obj" + -@erase "$(INTDIR)\Diabloui.obj" + -@erase "$(INTDIR)\DiabloUI.res" + -@erase "$(INTDIR)\DirLink.obj" + -@erase "$(INTDIR)\disclaim.obj" + -@erase "$(INTDIR)\Doom.obj" + -@erase "$(INTDIR)\EntrDial.obj" + -@erase "$(INTDIR)\EntrName.obj" + -@erase "$(INTDIR)\Fade.obj" + -@erase "$(INTDIR)\Focus.obj" + -@erase "$(INTDIR)\local.obj" + -@erase "$(INTDIR)\Logon.obj" + -@erase "$(INTDIR)\MainMenu.obj" + -@erase "$(INTDIR)\Modem.obj" + -@erase "$(INTDIR)\ModmStat.obj" + -@erase "$(INTDIR)\OkCancel.obj" + -@erase "$(INTDIR)\Progress.obj" + -@erase "$(INTDIR)\Sbar.obj" + -@erase "$(INTDIR)\SelClass.obj" + -@erase "$(INTDIR)\SelConn.obj" + -@erase "$(INTDIR)\SelDial.obj" + -@erase "$(INTDIR)\SelGame.obj" + -@erase "$(INTDIR)\SelHero.obj" + -@erase "$(INTDIR)\SelIPX.obj" + -@erase "$(INTDIR)\SelList.obj" + -@erase "$(INTDIR)\SelLoad.obj" + -@erase "$(INTDIR)\SelModem.obj" + -@erase "$(INTDIR)\SelYesNo.obj" + -@erase "$(INTDIR)\Title.obj" + -@erase "$(INTDIR)\UiSnd.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\diabloui.exp" + -@erase "$(OUTDIR)\diabloui.lib" + -@erase "$(OUTDIR)\diabloui.map" + -@erase "$(OUTDIR)\diabloui.pdb" + -@erase ".\bin\diabloui.dll" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/ui.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\ui\Debug/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/DiabloUI.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/ui.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x20000000 /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"bin/diabloui.dll" +LINK32_FLAGS=tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib\ + shell32.lib wsock32.lib storm.lib /nologo /base:0x20000000 /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)/diabloui.pdb"\ + /map:"$(INTDIR)/diabloui.map" /debug /machine:I386 /def:".\Ui\Diabloui.def"\ + /out:"bin/diabloui.dll" /implib:"$(OUTDIR)/diabloui.lib" +DEF_FILE= \ + ".\Ui\Diabloui.def" +LINK32_OBJS= \ + "$(INTDIR)\artfont.obj" \ + "$(INTDIR)\connect.obj" \ + "$(INTDIR)\CopyProt.obj" \ + "$(INTDIR)\cr8game.obj" \ + "$(INTDIR)\CreaDung.obj" \ + "$(INTDIR)\CreaHero.obj" \ + "$(INTDIR)\credits.obj" \ + "$(INTDIR)\DiabEdit.obj" \ + "$(INTDIR)\Diabloui.obj" \ + "$(INTDIR)\DiabloUI.res" \ + "$(INTDIR)\DirLink.obj" \ + "$(INTDIR)\disclaim.obj" \ + "$(INTDIR)\Doom.obj" \ + "$(INTDIR)\EntrDial.obj" \ + "$(INTDIR)\EntrName.obj" \ + "$(INTDIR)\Fade.obj" \ + "$(INTDIR)\Focus.obj" \ + "$(INTDIR)\local.obj" \ + "$(INTDIR)\Logon.obj" \ + "$(INTDIR)\MainMenu.obj" \ + "$(INTDIR)\Modem.obj" \ + "$(INTDIR)\ModmStat.obj" \ + "$(INTDIR)\OkCancel.obj" \ + "$(INTDIR)\Progress.obj" \ + "$(INTDIR)\Sbar.obj" \ + "$(INTDIR)\SelClass.obj" \ + "$(INTDIR)\SelConn.obj" \ + "$(INTDIR)\SelDial.obj" \ + "$(INTDIR)\SelGame.obj" \ + "$(INTDIR)\SelHero.obj" \ + "$(INTDIR)\SelIPX.obj" \ + "$(INTDIR)\SelList.obj" \ + "$(INTDIR)\SelLoad.obj" \ + "$(INTDIR)\SelModem.obj" \ + "$(INTDIR)\SelYesNo.obj" \ + "$(INTDIR)\Title.obj" \ + "$(INTDIR)\UiSnd.obj" \ + ".\STORM.LIB" + +".\bin\diabloui.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "battle - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "battle\Release" +# PROP BASE Intermediate_Dir "battle\Release" +# PROP BASE Target_Dir "battle" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "battle\Release" +# PROP Intermediate_Dir "battle\Release" +# PROP Target_Dir "battle" +OUTDIR=.\battle\Release +INTDIR=.\battle\Release + +ALL : ".\bin\battle.snp" + +CLEAN : + -@erase "$(INTDIR)\ad.obj" + -@erase "$(INTDIR)\Battle.obj" + -@erase "$(INTDIR)\Battle.res" + -@erase "$(INTDIR)\bnetlogo.obj" + -@erase "$(INTDIR)\Cache.obj" + -@erase "$(INTDIR)\cancel.obj" + -@erase "$(INTDIR)\chatchnl.obj" + -@erase "$(INTDIR)\Chatroom.obj" + -@erase "$(INTDIR)\clrpref.obj" + -@erase "$(INTDIR)\connect.obj" + -@erase "$(INTDIR)\disconn.obj" + -@erase "$(INTDIR)\getpass.obj" + -@erase "$(INTDIR)\Joingame.obj" + -@erase "$(INTDIR)\logon.obj" + -@erase "$(INTDIR)\message.obj" + -@erase "$(INTDIR)\Progress.obj" + -@erase "$(INTDIR)\rasmgr.obj" + -@erase "$(INTDIR)\scrllbar.obj" + -@erase "$(INTDIR)\setpass.obj" + -@erase "$(INTDIR)\Spi.obj" + -@erase "$(INTDIR)\Srv.obj" + -@erase "$(INTDIR)\Ui.obj" + -@erase "$(OUTDIR)\battle.exp" + -@erase "$(OUTDIR)\battle.lib" + -@erase "$(OUTDIR)\battle.map" + -@erase ".\bin\battle.snp" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /G5Fry /c +CPP_PROJ=/nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/battle.pch" /YX /Fo"$(INTDIR)/" /G5Fry /c +CPP_OBJS=.\battle\Release/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /i "u:\diabloui" /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Battle.res" /i "u:\diabloui" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/battle.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x19000000 /subsystem:windows /dll /map /machine:I386 /out:"bin\battle.snp" +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib\ + wsock32.lib storm.lib /nologo /base:0x19000000 /subsystem:windows /dll\ + /incremental:no /pdb:"$(OUTDIR)/battle.pdb" /map:"$(INTDIR)/battle.map"\ + /machine:I386 /def:".\battle\Battle.def" /out:"bin\battle.snp"\ + /implib:"$(OUTDIR)/battle.lib" +DEF_FILE= \ + ".\battle\Battle.def" +LINK32_OBJS= \ + "$(INTDIR)\ad.obj" \ + "$(INTDIR)\Battle.obj" \ + "$(INTDIR)\Battle.res" \ + "$(INTDIR)\bnetlogo.obj" \ + "$(INTDIR)\Cache.obj" \ + "$(INTDIR)\cancel.obj" \ + "$(INTDIR)\chatchnl.obj" \ + "$(INTDIR)\Chatroom.obj" \ + "$(INTDIR)\clrpref.obj" \ + "$(INTDIR)\connect.obj" \ + "$(INTDIR)\disconn.obj" \ + "$(INTDIR)\getpass.obj" \ + "$(INTDIR)\Joingame.obj" \ + "$(INTDIR)\logon.obj" \ + "$(INTDIR)\message.obj" \ + "$(INTDIR)\Progress.obj" \ + "$(INTDIR)\rasmgr.obj" \ + "$(INTDIR)\scrllbar.obj" \ + "$(INTDIR)\setpass.obj" \ + "$(INTDIR)\Spi.obj" \ + "$(INTDIR)\Srv.obj" \ + "$(INTDIR)\Ui.obj" \ + ".\STORM.LIB" + +".\bin\battle.snp" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "battle\battle__" +# PROP BASE Intermediate_Dir "battle\battle__" +# PROP BASE Target_Dir "battle" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "battle\debug" +# PROP Intermediate_Dir "battle\debug" +# PROP Target_Dir "battle" +OUTDIR=.\battle\debug +INTDIR=.\battle\debug + +ALL : ".\bin\battle.snp" + +CLEAN : + -@erase "$(INTDIR)\ad.obj" + -@erase "$(INTDIR)\Battle.obj" + -@erase "$(INTDIR)\Battle.res" + -@erase "$(INTDIR)\bnetlogo.obj" + -@erase "$(INTDIR)\Cache.obj" + -@erase "$(INTDIR)\cancel.obj" + -@erase "$(INTDIR)\chatchnl.obj" + -@erase "$(INTDIR)\Chatroom.obj" + -@erase "$(INTDIR)\clrpref.obj" + -@erase "$(INTDIR)\connect.obj" + -@erase "$(INTDIR)\disconn.obj" + -@erase "$(INTDIR)\getpass.obj" + -@erase "$(INTDIR)\Joingame.obj" + -@erase "$(INTDIR)\logon.obj" + -@erase "$(INTDIR)\message.obj" + -@erase "$(INTDIR)\Progress.obj" + -@erase "$(INTDIR)\rasmgr.obj" + -@erase "$(INTDIR)\scrllbar.obj" + -@erase "$(INTDIR)\setpass.obj" + -@erase "$(INTDIR)\Spi.obj" + -@erase "$(INTDIR)\Srv.obj" + -@erase "$(INTDIR)\Ui.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\battle.exp" + -@erase "$(OUTDIR)\battle.lib" + -@erase "$(OUTDIR)\battle.map" + -@erase "$(OUTDIR)\battle.pdb" + -@erase ".\bin\battle.ilk" + -@erase ".\bin\battle.snp" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/battle.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\battle\debug/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /i "u:\diabloui" /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Battle.res" /i "u:\diabloui" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/battle.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x19000000 /subsystem:windows /dll /map /debug /machine:I386 /out:"bin\battle.snp" +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib\ + wsock32.lib storm.lib /nologo /base:0x19000000 /subsystem:windows /dll\ + /incremental:yes /pdb:"$(OUTDIR)/battle.pdb" /map:"$(INTDIR)/battle.map" /debug\ + /machine:I386 /def:".\battle\Battle.def" /out:"bin\battle.snp"\ + /implib:"$(OUTDIR)/battle.lib" +DEF_FILE= \ + ".\battle\Battle.def" +LINK32_OBJS= \ + "$(INTDIR)\ad.obj" \ + "$(INTDIR)\Battle.obj" \ + "$(INTDIR)\Battle.res" \ + "$(INTDIR)\bnetlogo.obj" \ + "$(INTDIR)\Cache.obj" \ + "$(INTDIR)\cancel.obj" \ + "$(INTDIR)\chatchnl.obj" \ + "$(INTDIR)\Chatroom.obj" \ + "$(INTDIR)\clrpref.obj" \ + "$(INTDIR)\connect.obj" \ + "$(INTDIR)\disconn.obj" \ + "$(INTDIR)\getpass.obj" \ + "$(INTDIR)\Joingame.obj" \ + "$(INTDIR)\logon.obj" \ + "$(INTDIR)\message.obj" \ + "$(INTDIR)\Progress.obj" \ + "$(INTDIR)\rasmgr.obj" \ + "$(INTDIR)\scrllbar.obj" \ + "$(INTDIR)\setpass.obj" \ + "$(INTDIR)\Spi.obj" \ + "$(INTDIR)\Srv.obj" \ + "$(INTDIR)\Ui.obj" \ + ".\STORM.LIB" + +".\bin\battle.snp" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Standard - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Standard\Release" +# PROP BASE Intermediate_Dir "Standard\Release" +# PROP BASE Target_Dir "Standard" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Standard\Release" +# PROP Intermediate_Dir "Standard\Release" +# PROP Target_Dir "Standard" +OUTDIR=.\Standard\Release +INTDIR=.\Standard\Release + +ALL : ".\bin\Standard.snp" + +CLEAN : + -@erase "$(INTDIR)\IPX.OBJ" + -@erase "$(INTDIR)\MODEM.OBJ" + -@erase "$(INTDIR)\NULL.OBJ" + -@erase "$(INTDIR)\PERF.OBJ" + -@erase "$(INTDIR)\SERIAL.OBJ" + -@erase "$(INTDIR)\STANDARD.OBJ" + -@erase "$(INTDIR)\STANDARD.res" + -@erase "$(INTDIR)\Trace.obj" + -@erase "$(OUTDIR)\Standard.exp" + -@erase "$(OUTDIR)\Standard.lib" + -@erase "$(OUTDIR)\Standard.map" + -@erase ".\bin\Standard.snp" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /G5Fry /c +CPP_PROJ=/nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/Standard.pch" /YX /Fo"$(INTDIR)/" /G5Fry /c +CPP_OBJS=.\Standard\Release/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/STANDARD.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/Standard.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x18000000 /subsystem:windows /dll /map /machine:I386 /out:"bin\Standard.snp" +LINK32_FLAGS=tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib\ + shell32.lib wsock32.lib storm.lib /nologo /base:0x18000000 /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)/Standard.pdb"\ + /map:"$(INTDIR)/Standard.map" /machine:I386 /def:".\Standard\STANDARD.DEF"\ + /out:"bin\Standard.snp" /implib:"$(OUTDIR)/Standard.lib" +DEF_FILE= \ + ".\Standard\STANDARD.DEF" +LINK32_OBJS= \ + "$(INTDIR)\IPX.OBJ" \ + "$(INTDIR)\MODEM.OBJ" \ + "$(INTDIR)\NULL.OBJ" \ + "$(INTDIR)\PERF.OBJ" \ + "$(INTDIR)\SERIAL.OBJ" \ + "$(INTDIR)\STANDARD.OBJ" \ + "$(INTDIR)\STANDARD.res" \ + "$(INTDIR)\Trace.obj" \ + ".\STORM.LIB" + +".\bin\Standard.snp" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Standard\Debug" +# PROP BASE Intermediate_Dir "Standard\Debug" +# PROP BASE Target_Dir "Standard" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Standard\Debug" +# PROP Intermediate_Dir "Standard\Debug" +# PROP Target_Dir "Standard" +OUTDIR=.\Standard\Debug +INTDIR=.\Standard\Debug + +ALL : ".\bin\Standard.snp" + +CLEAN : + -@erase "$(INTDIR)\IPX.OBJ" + -@erase "$(INTDIR)\MODEM.OBJ" + -@erase "$(INTDIR)\NULL.OBJ" + -@erase "$(INTDIR)\PERF.OBJ" + -@erase "$(INTDIR)\SERIAL.OBJ" + -@erase "$(INTDIR)\STANDARD.OBJ" + -@erase "$(INTDIR)\STANDARD.res" + -@erase "$(INTDIR)\Trace.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\Standard.exp" + -@erase "$(OUTDIR)\Standard.lib" + -@erase "$(OUTDIR)\Standard.map" + -@erase "$(OUTDIR)\Standard.pdb" + -@erase ".\bin\Standard.ilk" + -@erase ".\bin\Standard.snp" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/Standard.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Standard\Debug/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/STANDARD.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/Standard.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x18000000 /subsystem:windows /dll /map /debug /machine:I386 /out:"bin\Standard.snp" +LINK32_FLAGS=tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib\ + shell32.lib wsock32.lib storm.lib /nologo /base:0x18000000 /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)/Standard.pdb"\ + /map:"$(INTDIR)/Standard.map" /debug /machine:I386\ + /def:".\Standard\STANDARD.DEF" /out:"bin\Standard.snp"\ + /implib:"$(OUTDIR)/Standard.lib" +DEF_FILE= \ + ".\Standard\STANDARD.DEF" +LINK32_OBJS= \ + "$(INTDIR)\IPX.OBJ" \ + "$(INTDIR)\MODEM.OBJ" \ + "$(INTDIR)\NULL.OBJ" \ + "$(INTDIR)\PERF.OBJ" \ + "$(INTDIR)\SERIAL.OBJ" \ + "$(INTDIR)\STANDARD.OBJ" \ + "$(INTDIR)\STANDARD.res" \ + "$(INTDIR)\Trace.obj" \ + ".\STORM.LIB" + +".\bin\Standard.snp" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +################################################################################ +# Begin Target + +# Name "DiabloUI - Win32 Release" +# Name "DiabloUI - Win32 Debug" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Project Dependency + +# Project_Dep_Name "ui" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +"ui - Win32 Release" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="ui - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +"ui - Win32 Debug" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="ui - Win32 Debug" + +!ENDIF + +# End Project Dependency +################################################################################ +# Begin Source File + +SOURCE=.\Testui.cpp +DEP_CPP_TESTU=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\Diabloui.h"\ + + +"$(INTDIR)\Testui.obj" : $(SOURCE) $(DEP_CPP_TESTU) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STORM.LIB + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Project Dependency + +# Project_Dep_Name "battle" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +"battle - Win32 Release" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="battle - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +"battle - Win32 Debug" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="battle - Win32 Debug" + +!ENDIF + +# End Project Dependency +################################################################################ +# Begin Project Dependency + +# Project_Dep_Name "Standard" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +"Standard - Win32 Release" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="Standard - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +"Standard - Win32 Debug" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="Standard - Win32 Debug" + +!ENDIF + +# End Project Dependency +# End Target +################################################################################ +# Begin Target + +# Name "ui - Win32 Release" +# Name "ui - Win32 Debug" + +!IF "$(CFG)" == "ui - Win32 Release" + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Title.cpp +DEP_CPP_TITLE=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Title.obj" : $(SOURCE) $(DEP_CPP_TITLE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\DiabloUI.rc +DEP_RSC_DIABL=\ + ".\Ui\arrow.cur"\ + ".\Ui\But_sml.raw"\ + ".\Ui\Credits.txt"\ + ".\Ui\Frank.rc"\ + ".\Ui\ibeam.cur"\ + ".\Ui\link.cur"\ + ".\Ui\Mike.rc"\ + ".\Ui\Srpopup.pal"\ + ".\Ui\Srpopup.raw"\ + + +!IF "$(CFG)" == "ui - Win32 Release" + + +"$(INTDIR)\DiabloUI.res" : $(SOURCE) $(DEP_RSC_DIABL) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/DiabloUI.res" /i "Ui" /d "NDEBUG" $(SOURCE) + + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + + +"$(INTDIR)\DiabloUI.res" : $(SOURCE) $(DEP_RSC_DIABL) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/DiabloUI.res" /i "Ui" /d "_DEBUG" $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\local.cpp +DEP_CPP_LOCAL=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\local.obj" : $(SOURCE) $(DEP_CPP_LOCAL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Diabloui.cpp +DEP_CPP_DIABLO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\Diabloui.obj" : $(SOURCE) $(DEP_CPP_DIABLO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Diabloui.def + +!IF "$(CFG)" == "ui - Win32 Release" + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\MainMenu.cpp +DEP_CPP_MAINM=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\MainMenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\credits.cpp +DEP_CPP_CREDI=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\credits.obj" : $(SOURCE) $(DEP_CPP_CREDI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\cr8game.cpp +DEP_CPP_CR8GA=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\cr8game.obj" : $(SOURCE) $(DEP_CPP_CR8GA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelHero.cpp +DEP_CPP_SELHE=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelHero.obj" : $(SOURCE) $(DEP_CPP_SELHE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\OkCancel.cpp +DEP_CPP_OKCAN=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\OkCancel.obj" : $(SOURCE) $(DEP_CPP_OKCAN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Logon.cpp +DEP_CPP_LOGON=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Logon.obj" : $(SOURCE) $(DEP_CPP_LOGON) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Progress.cpp +DEP_CPP_PROGR=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Progress.obj" : $(SOURCE) $(DEP_CPP_PROGR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\connect.cpp +DEP_CPP_CONNE=\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\connect.obj" : $(SOURCE) $(DEP_CPP_CONNE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\disclaim.cpp +DEP_CPP_DISCL=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\disclaim.obj" : $(SOURCE) $(DEP_CPP_DISCL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\artfont.cpp +DEP_CPP_ARTFO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\artfont.obj" : $(SOURCE) $(DEP_CPP_ARTFO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Focus.cpp +DEP_CPP_FOCUS=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\Focus.obj" : $(SOURCE) $(DEP_CPP_FOCUS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STORM.LIB + +!IF "$(CFG)" == "ui - Win32 Release" + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelClass.cpp +DEP_CPP_SELCL=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelClass.obj" : $(SOURCE) $(DEP_CPP_SELCL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelList.cpp +DEP_CPP_SELLI=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelList.obj" : $(SOURCE) $(DEP_CPP_SELLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\EntrName.cpp +DEP_CPP_ENTRN=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\EntrName.obj" : $(SOURCE) $(DEP_CPP_ENTRN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\UiSnd.cpp +DEP_CPP_UISND=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\UiSnd.obj" : $(SOURCE) $(DEP_CPP_UISND) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelYesNo.cpp +DEP_CPP_SELYE=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelYesNo.obj" : $(SOURCE) $(DEP_CPP_SELYE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelConn.cpp +DEP_CPP_SELCO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelConn.obj" : $(SOURCE) $(DEP_CPP_SELCO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\CreaHero.cpp +DEP_CPP_CREAH=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\CreaHero.obj" : $(SOURCE) $(DEP_CPP_CREAH) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\DiabEdit.cpp +DEP_CPP_DIABE=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\DiabEdit.obj" : $(SOURCE) $(DEP_CPP_DIABE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Doom.cpp +DEP_CPP_DOOM_=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Fade.cpp +DEP_CPP_FADE_=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Fade.obj" : $(SOURCE) $(DEP_CPP_FADE_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelIPX.cpp +DEP_CPP_SELIP=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelIPX.obj" : $(SOURCE) $(DEP_CPP_SELIP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelGame.cpp +DEP_CPP_SELGA=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\SelGame.obj" : $(SOURCE) $(DEP_CPP_SELGA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\CreaDung.cpp +DEP_CPP_CREAD=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\CreaDung.obj" : $(SOURCE) $(DEP_CPP_CREAD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\DirLink.cpp +DEP_CPP_DIRLI=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\DirLink.obj" : $(SOURCE) $(DEP_CPP_DIRLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Sbar.cpp +DEP_CPP_SBAR_=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Sbar.obj" : $(SOURCE) $(DEP_CPP_SBAR_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelLoad.cpp +DEP_CPP_SELLO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelLoad.obj" : $(SOURCE) $(DEP_CPP_SELLO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\CopyProt.cpp +DEP_CPP_COPYP=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\CopyProt.obj" : $(SOURCE) $(DEP_CPP_COPYP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Modem.cpp +DEP_CPP_MODEM=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\Modem.obj" : $(SOURCE) $(DEP_CPP_MODEM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelModem.cpp +DEP_CPP_SELMO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelModem.obj" : $(SOURCE) $(DEP_CPP_SELMO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\EntrDial.cpp +DEP_CPP_ENTRD=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\EntrDial.obj" : $(SOURCE) $(DEP_CPP_ENTRD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelDial.cpp +DEP_CPP_SELDI=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelDial.obj" : $(SOURCE) $(DEP_CPP_SELDI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\ModmStat.cpp +DEP_CPP_MODMS=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\ModmStat.obj" : $(SOURCE) $(DEP_CPP_MODMS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "battle - Win32 Release" +# Name "battle - Win32 Debug" + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\battle\Ui.cpp +DEP_CPP_UI_CP=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Ui.obj" : $(SOURCE) $(DEP_CPP_UI_CP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Battle.h + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Battle.rc +DEP_RSC_BATTL=\ + ".\battle\Chathelp.txt"\ + + +!IF "$(CFG)" == "battle - Win32 Release" + + +"$(INTDIR)\Battle.res" : $(SOURCE) $(DEP_RSC_BATTL) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/Battle.res" /i "u:\diabloui" /i "battle" /d\ + "NDEBUG" $(SOURCE) + + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + + +"$(INTDIR)\Battle.res" : $(SOURCE) $(DEP_RSC_BATTL) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/Battle.res" /i "u:\diabloui" /i "battle" /d\ + "_DEBUG" $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\bnetart.h + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Chatroom.cpp +DEP_CPP_CHATR=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Chatroom.obj" : $(SOURCE) $(DEP_CPP_CHATR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Joingame.cpp +DEP_CPP_JOING=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Joingame.obj" : $(SOURCE) $(DEP_CPP_JOING) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Pch.h + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Resource.h + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Spi.cpp +DEP_CPP_SPI_C=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Spi.obj" : $(SOURCE) $(DEP_CPP_SPI_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Srv.cpp +DEP_CPP_SRV_C=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Srv.obj" : $(SOURCE) $(DEP_CPP_SRV_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Battle.cpp +DEP_CPP_BATTLE=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Battle.obj" : $(SOURCE) $(DEP_CPP_BATTLE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STORM.LIB + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Battle.def + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\connect.cpp +DEP_CPP_CONNE=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\connect.obj" : $(SOURCE) $(DEP_CPP_CONNE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\logon.cpp +DEP_CPP_LOGON_=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\logon.obj" : $(SOURCE) $(DEP_CPP_LOGON_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Progress.cpp +DEP_CPP_PROGR=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Progress.obj" : $(SOURCE) $(DEP_CPP_PROGR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\bnetlogo.cpp +DEP_CPP_BNETL=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\bnetlogo.obj" : $(SOURCE) $(DEP_CPP_BNETL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\cancel.cpp +DEP_CPP_CANCE=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\cancel.obj" : $(SOURCE) $(DEP_CPP_CANCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Cache.cpp +DEP_CPP_CACHE=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Cache.obj" : $(SOURCE) $(DEP_CPP_CACHE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\clrpref.cpp +DEP_CPP_CLRPR=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\clrpref.obj" : $(SOURCE) $(DEP_CPP_CLRPR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\ad.cpp +DEP_CPP_AD_CP=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\ad.obj" : $(SOURCE) $(DEP_CPP_AD_CP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\rasmgr.cpp +DEP_CPP_RASMG=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\rasmgr.obj" : $(SOURCE) $(DEP_CPP_RASMG) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\disconn.cpp +DEP_CPP_DISCO=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\disconn.obj" : $(SOURCE) $(DEP_CPP_DISCO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\chatchnl.cpp +DEP_CPP_CHATC=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\chatchnl.obj" : $(SOURCE) $(DEP_CPP_CHATC) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\scrllbar.cpp +DEP_CPP_SCRLL=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\scrllbar.obj" : $(SOURCE) $(DEP_CPP_SCRLL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\message.cpp +DEP_CPP_MESSA=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\message.obj" : $(SOURCE) $(DEP_CPP_MESSA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\setpass.cpp +DEP_CPP_SETPA=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\setpass.obj" : $(SOURCE) $(DEP_CPP_SETPA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\getpass.cpp +DEP_CPP_GETPA=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\getpass.obj" : $(SOURCE) $(DEP_CPP_GETPA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "Standard - Win32 Release" +# Name "Standard - Win32 Debug" + +!IF "$(CFG)" == "Standard - Win32 Release" + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\Standard\STANDARD.RC + +!IF "$(CFG)" == "Standard - Win32 Release" + + +"$(INTDIR)\STANDARD.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/STANDARD.res" /i "Standard" /d "NDEBUG"\ + $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + + +"$(INTDIR)\STANDARD.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/STANDARD.res" /i "Standard" /d "_DEBUG"\ + $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\MODEM.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_MODEM=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\MODEM.OBJ" : $(SOURCE) $(DEP_CPP_MODEM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_MODEM=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\MODEM.OBJ" : $(SOURCE) $(DEP_CPP_MODEM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\NULL.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_NULL_=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\NULL.OBJ" : $(SOURCE) $(DEP_CPP_NULL_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_NULL_=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\NULL.OBJ" : $(SOURCE) $(DEP_CPP_NULL_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\PERF.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_PERF_=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\PERF.OBJ" : $(SOURCE) $(DEP_CPP_PERF_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_PERF_=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\PERF.OBJ" : $(SOURCE) $(DEP_CPP_PERF_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\SERIAL.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_SERIA=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\SERIAL.OBJ" : $(SOURCE) $(DEP_CPP_SERIA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_SERIA=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\SERIAL.OBJ" : $(SOURCE) $(DEP_CPP_SERIA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\STANDARD.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_STAND=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\STANDARD.OBJ" : $(SOURCE) $(DEP_CPP_STAND) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_STAND=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\STANDARD.OBJ" : $(SOURCE) $(DEP_CPP_STAND) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\IPX.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_IPX_C=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\IPX.OBJ" : $(SOURCE) $(DEP_CPP_IPX_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_IPX_C=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\IPX.OBJ" : $(SOURCE) $(DEP_CPP_IPX_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STORM.LIB + +!IF "$(CFG)" == "Standard - Win32 Release" + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\STANDARD.DEF + +!IF "$(CFG)" == "Standard - Win32 Release" + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\Trace.cpp +DEP_CPP_TRACE=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Standard\Trace.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Trace.obj" : $(SOURCE) $(DEP_CPP_TRACE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/src/Uisrc/DIABLOUI.DSP b/src/Uisrc/DIABLOUI.DSP new file mode 100644 index 0000000..c05eab2 --- /dev/null +++ b/src/Uisrc/DIABLOUI.DSP @@ -0,0 +1,120 @@ +# Microsoft Developer Studio Project File - Name="DiabloUI" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=DiabloUI - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Diabloui.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Diabloui.mak" CFG="DiabloUI - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "DiabloUI - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "DiabloUI - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib ui\release\hellfrui.lib battle\release\battle.lib standard\release\standard.lib /nologo /subsystem:windows /map /machine:I386 /out:".\bin\DiabloUI.exe" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\Debug" +# PROP BASE Intermediate_Dir ".\Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\Debug" +# PROP Intermediate_Dir ".\Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib ui\debug\hellfrui.lib battle\debug\battle.lib standard\debug\standard.lib /nologo /subsystem:windows /incremental:no /map /debug /machine:I386 /out:".\bin\DiabloUI.exe" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "DiabloUI - Win32 Release" +# Name "DiabloUI - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\STORM.LIB +# End Source File +# Begin Source File + +SOURCE=.\Testui.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\Sclass.h +# End Source File +# Begin Source File + +SOURCE=.\storm.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/src/Uisrc/DIABLOUI.DSW b/src/Uisrc/DIABLOUI.DSW new file mode 100644 index 0000000..2430495 --- /dev/null +++ b/src/Uisrc/DIABLOUI.DSW @@ -0,0 +1,74 @@ +Microsoft Developer Studio Workspace File, Format Version 5.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "DiabloUI"=.\Diabloui.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ui + End Project Dependency + Begin Project Dependency + Project_Dep_Name battle + End Project Dependency + Begin Project Dependency + Project_Dep_Name Standard + End Project Dependency +}}} + +############################################################################### + +Project: "Standard"=.\Standard\Standard.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "battle"=.\battle\battle.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ui"=.\ui\ui.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/Uisrc/DIABLOUI.MAK b/src/Uisrc/DIABLOUI.MAK new file mode 100644 index 0000000..4e25fd7 --- /dev/null +++ b/src/Uisrc/DIABLOUI.MAK @@ -0,0 +1,2751 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +!IF "$(CFG)" == "" +CFG=Standard - Win32 Debug +!MESSAGE No configuration specified. Defaulting to Standard - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "DiabloUI - Win32 Release" && "$(CFG)" !=\ + "DiabloUI - Win32 Debug" && "$(CFG)" != "ui - Win32 Release" && "$(CFG)" !=\ + "ui - Win32 Debug" && "$(CFG)" != "battle - Win32 Release" && "$(CFG)" !=\ + "battle - Win32 Debug" && "$(CFG)" != "Standard - Win32 Release" && "$(CFG)" !=\ + "Standard - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Diabloui.mak" CFG="Standard - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "DiabloUI - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "DiabloUI - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE "ui - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ui - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "battle - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "battle - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Standard - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Standard - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "Standard - Win32 Debug" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "Standard - Win32 Release" "battle - Win32 Release" "ui - Win32 Release"\ + ".\bin\DiabloUI.exe" + +CLEAN : + -@erase "$(INTDIR)\Testui.obj" + -@erase "$(OUTDIR)\DiabloUI.map" + -@erase ".\bin\DiabloUI.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /G5 /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /G5 /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/Diabloui.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/Diabloui.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib ui\release\diabloui.lib battle\release\battle.lib standard\release\standard.lib /nologo /subsystem:windows /map /machine:I386 /out:"bin/DiabloUI.exe" +# SUBTRACT LINK32 /incremental:yes +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib\ + wsock32.lib storm.lib ui\release\diabloui.lib battle\release\battle.lib\ + standard\release\standard.lib /nologo /subsystem:windows /incremental:no\ + /pdb:"$(OUTDIR)/DiabloUI.pdb" /map:"$(INTDIR)/DiabloUI.map" /machine:I386\ + /out:"bin/DiabloUI.exe" +LINK32_OBJS= \ + "$(INTDIR)\Testui.obj" \ + ".\battle\Release\battle.lib" \ + ".\Standard\Release\Standard.lib" \ + ".\STORM.LIB" \ + ".\ui\Release\diabloui.lib" + +".\bin\DiabloUI.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "Standard - Win32 Debug" "battle - Win32 Debug" "ui - Win32 Debug"\ + ".\bin\DiabloUI.exe" + +CLEAN : + -@erase "$(INTDIR)\Testui.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\DiabloUI.map" + -@erase "$(OUTDIR)\DiabloUI.pdb" + -@erase ".\bin\DiabloUI.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/Diabloui.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/Diabloui.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib ui\debug\diabloui.lib battle\debug\battle.lib standard\debug\standard.lib /nologo /subsystem:windows /incremental:no /map /debug /machine:I386 /out:"bin/DiabloUI.exe" +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib\ + wsock32.lib storm.lib ui\debug\diabloui.lib battle\debug\battle.lib\ + standard\debug\standard.lib /nologo /subsystem:windows /incremental:no\ + /pdb:"$(OUTDIR)/DiabloUI.pdb" /map:"$(INTDIR)/DiabloUI.map" /debug\ + /machine:I386 /out:"bin/DiabloUI.exe" +LINK32_OBJS= \ + "$(INTDIR)\Testui.obj" \ + ".\battle\debug\battle.lib" \ + ".\Standard\Debug\Standard.lib" \ + ".\STORM.LIB" \ + ".\ui\Debug\diabloui.lib" + +".\bin\DiabloUI.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ui - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ui\Release" +# PROP BASE Intermediate_Dir "ui\Release" +# PROP BASE Target_Dir "ui" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ui\Release" +# PROP Intermediate_Dir "ui\Release" +# PROP Target_Dir "ui" +OUTDIR=.\ui\Release +INTDIR=.\ui\Release + +ALL : ".\bin\diabloui.dll" + +CLEAN : + -@erase "$(INTDIR)\artfont.obj" + -@erase "$(INTDIR)\connect.obj" + -@erase "$(INTDIR)\CopyProt.obj" + -@erase "$(INTDIR)\cr8game.obj" + -@erase "$(INTDIR)\CreaDung.obj" + -@erase "$(INTDIR)\CreaHero.obj" + -@erase "$(INTDIR)\credits.obj" + -@erase "$(INTDIR)\DiabEdit.obj" + -@erase "$(INTDIR)\Diabloui.obj" + -@erase "$(INTDIR)\DiabloUI.res" + -@erase "$(INTDIR)\DirLink.obj" + -@erase "$(INTDIR)\disclaim.obj" + -@erase "$(INTDIR)\Doom.obj" + -@erase "$(INTDIR)\EntrDial.obj" + -@erase "$(INTDIR)\EntrName.obj" + -@erase "$(INTDIR)\Fade.obj" + -@erase "$(INTDIR)\Focus.obj" + -@erase "$(INTDIR)\local.obj" + -@erase "$(INTDIR)\Logon.obj" + -@erase "$(INTDIR)\MainMenu.obj" + -@erase "$(INTDIR)\Modem.obj" + -@erase "$(INTDIR)\ModmStat.obj" + -@erase "$(INTDIR)\OkCancel.obj" + -@erase "$(INTDIR)\Progress.obj" + -@erase "$(INTDIR)\Sbar.obj" + -@erase "$(INTDIR)\SelClass.obj" + -@erase "$(INTDIR)\SelConn.obj" + -@erase "$(INTDIR)\SelDial.obj" + -@erase "$(INTDIR)\SelGame.obj" + -@erase "$(INTDIR)\SelHero.obj" + -@erase "$(INTDIR)\SelIPX.obj" + -@erase "$(INTDIR)\SelList.obj" + -@erase "$(INTDIR)\SelLoad.obj" + -@erase "$(INTDIR)\SelModem.obj" + -@erase "$(INTDIR)\SelYesNo.obj" + -@erase "$(INTDIR)\Title.obj" + -@erase "$(INTDIR)\UiSnd.obj" + -@erase "$(OUTDIR)\diabloui.exp" + -@erase "$(OUTDIR)\diabloui.lib" + -@erase "$(OUTDIR)\diabloui.map" + -@erase ".\bin\diabloui.dll" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /G5Fry /c +CPP_PROJ=/nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/ui.pch" /YX /Fo"$(INTDIR)/" /G5Fry /c +CPP_OBJS=.\ui\Release/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/DiabloUI.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/ui.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x20000000 /subsystem:windows /dll /map /machine:I386 /out:"bin/diabloui.dll" +# SUBTRACT LINK32 /incremental:yes +LINK32_FLAGS=tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib\ + shell32.lib wsock32.lib storm.lib /nologo /base:0x20000000 /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)/diabloui.pdb"\ + /map:"$(INTDIR)/diabloui.map" /machine:I386 /def:".\Ui\Diabloui.def"\ + /out:"bin/diabloui.dll" /implib:"$(OUTDIR)/diabloui.lib" +DEF_FILE= \ + ".\Ui\Diabloui.def" +LINK32_OBJS= \ + "$(INTDIR)\artfont.obj" \ + "$(INTDIR)\connect.obj" \ + "$(INTDIR)\CopyProt.obj" \ + "$(INTDIR)\cr8game.obj" \ + "$(INTDIR)\CreaDung.obj" \ + "$(INTDIR)\CreaHero.obj" \ + "$(INTDIR)\credits.obj" \ + "$(INTDIR)\DiabEdit.obj" \ + "$(INTDIR)\Diabloui.obj" \ + "$(INTDIR)\DiabloUI.res" \ + "$(INTDIR)\DirLink.obj" \ + "$(INTDIR)\disclaim.obj" \ + "$(INTDIR)\Doom.obj" \ + "$(INTDIR)\EntrDial.obj" \ + "$(INTDIR)\EntrName.obj" \ + "$(INTDIR)\Fade.obj" \ + "$(INTDIR)\Focus.obj" \ + "$(INTDIR)\local.obj" \ + "$(INTDIR)\Logon.obj" \ + "$(INTDIR)\MainMenu.obj" \ + "$(INTDIR)\Modem.obj" \ + "$(INTDIR)\ModmStat.obj" \ + "$(INTDIR)\OkCancel.obj" \ + "$(INTDIR)\Progress.obj" \ + "$(INTDIR)\Sbar.obj" \ + "$(INTDIR)\SelClass.obj" \ + "$(INTDIR)\SelConn.obj" \ + "$(INTDIR)\SelDial.obj" \ + "$(INTDIR)\SelGame.obj" \ + "$(INTDIR)\SelHero.obj" \ + "$(INTDIR)\SelIPX.obj" \ + "$(INTDIR)\SelList.obj" \ + "$(INTDIR)\SelLoad.obj" \ + "$(INTDIR)\SelModem.obj" \ + "$(INTDIR)\SelYesNo.obj" \ + "$(INTDIR)\Title.obj" \ + "$(INTDIR)\UiSnd.obj" \ + ".\STORM.LIB" + +".\bin\diabloui.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ui\ui___Win" +# PROP BASE Intermediate_Dir "ui\ui___Win" +# PROP BASE Target_Dir "ui" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "ui\Debug" +# PROP Intermediate_Dir "ui\Debug" +# PROP Target_Dir "ui" +OUTDIR=.\ui\Debug +INTDIR=.\ui\Debug + +ALL : ".\bin\diabloui.dll" + +CLEAN : + -@erase "$(INTDIR)\artfont.obj" + -@erase "$(INTDIR)\connect.obj" + -@erase "$(INTDIR)\CopyProt.obj" + -@erase "$(INTDIR)\cr8game.obj" + -@erase "$(INTDIR)\CreaDung.obj" + -@erase "$(INTDIR)\CreaHero.obj" + -@erase "$(INTDIR)\credits.obj" + -@erase "$(INTDIR)\DiabEdit.obj" + -@erase "$(INTDIR)\Diabloui.obj" + -@erase "$(INTDIR)\DiabloUI.res" + -@erase "$(INTDIR)\DirLink.obj" + -@erase "$(INTDIR)\disclaim.obj" + -@erase "$(INTDIR)\Doom.obj" + -@erase "$(INTDIR)\EntrDial.obj" + -@erase "$(INTDIR)\EntrName.obj" + -@erase "$(INTDIR)\Fade.obj" + -@erase "$(INTDIR)\Focus.obj" + -@erase "$(INTDIR)\local.obj" + -@erase "$(INTDIR)\Logon.obj" + -@erase "$(INTDIR)\MainMenu.obj" + -@erase "$(INTDIR)\Modem.obj" + -@erase "$(INTDIR)\ModmStat.obj" + -@erase "$(INTDIR)\OkCancel.obj" + -@erase "$(INTDIR)\Progress.obj" + -@erase "$(INTDIR)\Sbar.obj" + -@erase "$(INTDIR)\SelClass.obj" + -@erase "$(INTDIR)\SelConn.obj" + -@erase "$(INTDIR)\SelDial.obj" + -@erase "$(INTDIR)\SelGame.obj" + -@erase "$(INTDIR)\SelHero.obj" + -@erase "$(INTDIR)\SelIPX.obj" + -@erase "$(INTDIR)\SelList.obj" + -@erase "$(INTDIR)\SelLoad.obj" + -@erase "$(INTDIR)\SelModem.obj" + -@erase "$(INTDIR)\SelYesNo.obj" + -@erase "$(INTDIR)\Title.obj" + -@erase "$(INTDIR)\UiSnd.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\diabloui.exp" + -@erase "$(OUTDIR)\diabloui.lib" + -@erase "$(OUTDIR)\diabloui.map" + -@erase "$(OUTDIR)\diabloui.pdb" + -@erase ".\bin\diabloui.dll" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/ui.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\ui\Debug/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/DiabloUI.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/ui.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x20000000 /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"bin/diabloui.dll" +LINK32_FLAGS=tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib\ + shell32.lib wsock32.lib storm.lib /nologo /base:0x20000000 /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)/diabloui.pdb"\ + /map:"$(INTDIR)/diabloui.map" /debug /machine:I386 /def:".\Ui\Diabloui.def"\ + /out:"bin/diabloui.dll" /implib:"$(OUTDIR)/diabloui.lib" +DEF_FILE= \ + ".\Ui\Diabloui.def" +LINK32_OBJS= \ + "$(INTDIR)\artfont.obj" \ + "$(INTDIR)\connect.obj" \ + "$(INTDIR)\CopyProt.obj" \ + "$(INTDIR)\cr8game.obj" \ + "$(INTDIR)\CreaDung.obj" \ + "$(INTDIR)\CreaHero.obj" \ + "$(INTDIR)\credits.obj" \ + "$(INTDIR)\DiabEdit.obj" \ + "$(INTDIR)\Diabloui.obj" \ + "$(INTDIR)\DiabloUI.res" \ + "$(INTDIR)\DirLink.obj" \ + "$(INTDIR)\disclaim.obj" \ + "$(INTDIR)\Doom.obj" \ + "$(INTDIR)\EntrDial.obj" \ + "$(INTDIR)\EntrName.obj" \ + "$(INTDIR)\Fade.obj" \ + "$(INTDIR)\Focus.obj" \ + "$(INTDIR)\local.obj" \ + "$(INTDIR)\Logon.obj" \ + "$(INTDIR)\MainMenu.obj" \ + "$(INTDIR)\Modem.obj" \ + "$(INTDIR)\ModmStat.obj" \ + "$(INTDIR)\OkCancel.obj" \ + "$(INTDIR)\Progress.obj" \ + "$(INTDIR)\Sbar.obj" \ + "$(INTDIR)\SelClass.obj" \ + "$(INTDIR)\SelConn.obj" \ + "$(INTDIR)\SelDial.obj" \ + "$(INTDIR)\SelGame.obj" \ + "$(INTDIR)\SelHero.obj" \ + "$(INTDIR)\SelIPX.obj" \ + "$(INTDIR)\SelList.obj" \ + "$(INTDIR)\SelLoad.obj" \ + "$(INTDIR)\SelModem.obj" \ + "$(INTDIR)\SelYesNo.obj" \ + "$(INTDIR)\Title.obj" \ + "$(INTDIR)\UiSnd.obj" \ + ".\STORM.LIB" + +".\bin\diabloui.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "battle - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "battle\Release" +# PROP BASE Intermediate_Dir "battle\Release" +# PROP BASE Target_Dir "battle" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "battle\Release" +# PROP Intermediate_Dir "battle\Release" +# PROP Target_Dir "battle" +OUTDIR=.\battle\Release +INTDIR=.\battle\Release + +ALL : ".\bin\battle.snp" + +CLEAN : + -@erase "$(INTDIR)\ad.obj" + -@erase "$(INTDIR)\Battle.obj" + -@erase "$(INTDIR)\Battle.res" + -@erase "$(INTDIR)\bnetlogo.obj" + -@erase "$(INTDIR)\Cache.obj" + -@erase "$(INTDIR)\cancel.obj" + -@erase "$(INTDIR)\chatchnl.obj" + -@erase "$(INTDIR)\Chatroom.obj" + -@erase "$(INTDIR)\clrpref.obj" + -@erase "$(INTDIR)\connect.obj" + -@erase "$(INTDIR)\disconn.obj" + -@erase "$(INTDIR)\getpass.obj" + -@erase "$(INTDIR)\Joingame.obj" + -@erase "$(INTDIR)\logon.obj" + -@erase "$(INTDIR)\message.obj" + -@erase "$(INTDIR)\Progress.obj" + -@erase "$(INTDIR)\rasmgr.obj" + -@erase "$(INTDIR)\scrllbar.obj" + -@erase "$(INTDIR)\setpass.obj" + -@erase "$(INTDIR)\Spi.obj" + -@erase "$(INTDIR)\Srv.obj" + -@erase "$(INTDIR)\Ui.obj" + -@erase "$(OUTDIR)\battle.exp" + -@erase "$(OUTDIR)\battle.lib" + -@erase "$(OUTDIR)\battle.map" + -@erase ".\bin\battle.snp" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /G5Fry /c +CPP_PROJ=/nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/battle.pch" /YX /Fo"$(INTDIR)/" /G5Fry /c +CPP_OBJS=.\battle\Release/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /i "u:\diabloui" /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Battle.res" /i "u:\diabloui" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/battle.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x19000000 /subsystem:windows /dll /map /machine:I386 /out:"bin\battle.snp" +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib\ + wsock32.lib storm.lib /nologo /base:0x19000000 /subsystem:windows /dll\ + /incremental:no /pdb:"$(OUTDIR)/battle.pdb" /map:"$(INTDIR)/battle.map"\ + /machine:I386 /def:".\battle\Battle.def" /out:"bin\battle.snp"\ + /implib:"$(OUTDIR)/battle.lib" +DEF_FILE= \ + ".\battle\Battle.def" +LINK32_OBJS= \ + "$(INTDIR)\ad.obj" \ + "$(INTDIR)\Battle.obj" \ + "$(INTDIR)\Battle.res" \ + "$(INTDIR)\bnetlogo.obj" \ + "$(INTDIR)\Cache.obj" \ + "$(INTDIR)\cancel.obj" \ + "$(INTDIR)\chatchnl.obj" \ + "$(INTDIR)\Chatroom.obj" \ + "$(INTDIR)\clrpref.obj" \ + "$(INTDIR)\connect.obj" \ + "$(INTDIR)\disconn.obj" \ + "$(INTDIR)\getpass.obj" \ + "$(INTDIR)\Joingame.obj" \ + "$(INTDIR)\logon.obj" \ + "$(INTDIR)\message.obj" \ + "$(INTDIR)\Progress.obj" \ + "$(INTDIR)\rasmgr.obj" \ + "$(INTDIR)\scrllbar.obj" \ + "$(INTDIR)\setpass.obj" \ + "$(INTDIR)\Spi.obj" \ + "$(INTDIR)\Srv.obj" \ + "$(INTDIR)\Ui.obj" \ + ".\STORM.LIB" + +".\bin\battle.snp" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "battle\battle__" +# PROP BASE Intermediate_Dir "battle\battle__" +# PROP BASE Target_Dir "battle" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "battle\debug" +# PROP Intermediate_Dir "battle\debug" +# PROP Target_Dir "battle" +OUTDIR=.\battle\debug +INTDIR=.\battle\debug + +ALL : ".\bin\battle.snp" + +CLEAN : + -@erase "$(INTDIR)\ad.obj" + -@erase "$(INTDIR)\Battle.obj" + -@erase "$(INTDIR)\Battle.res" + -@erase "$(INTDIR)\bnetlogo.obj" + -@erase "$(INTDIR)\Cache.obj" + -@erase "$(INTDIR)\cancel.obj" + -@erase "$(INTDIR)\chatchnl.obj" + -@erase "$(INTDIR)\Chatroom.obj" + -@erase "$(INTDIR)\clrpref.obj" + -@erase "$(INTDIR)\connect.obj" + -@erase "$(INTDIR)\disconn.obj" + -@erase "$(INTDIR)\getpass.obj" + -@erase "$(INTDIR)\Joingame.obj" + -@erase "$(INTDIR)\logon.obj" + -@erase "$(INTDIR)\message.obj" + -@erase "$(INTDIR)\Progress.obj" + -@erase "$(INTDIR)\rasmgr.obj" + -@erase "$(INTDIR)\scrllbar.obj" + -@erase "$(INTDIR)\setpass.obj" + -@erase "$(INTDIR)\Spi.obj" + -@erase "$(INTDIR)\Srv.obj" + -@erase "$(INTDIR)\Ui.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\battle.exp" + -@erase "$(OUTDIR)\battle.lib" + -@erase "$(OUTDIR)\battle.map" + -@erase "$(OUTDIR)\battle.pdb" + -@erase ".\bin\battle.ilk" + -@erase ".\bin\battle.snp" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/battle.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\battle\debug/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /i "u:\diabloui" /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/Battle.res" /i "u:\diabloui" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/battle.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x19000000 /subsystem:windows /dll /map /debug /machine:I386 /out:"bin\battle.snp" +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib\ + wsock32.lib storm.lib /nologo /base:0x19000000 /subsystem:windows /dll\ + /incremental:yes /pdb:"$(OUTDIR)/battle.pdb" /map:"$(INTDIR)/battle.map" /debug\ + /machine:I386 /def:".\battle\Battle.def" /out:"bin\battle.snp"\ + /implib:"$(OUTDIR)/battle.lib" +DEF_FILE= \ + ".\battle\Battle.def" +LINK32_OBJS= \ + "$(INTDIR)\ad.obj" \ + "$(INTDIR)\Battle.obj" \ + "$(INTDIR)\Battle.res" \ + "$(INTDIR)\bnetlogo.obj" \ + "$(INTDIR)\Cache.obj" \ + "$(INTDIR)\cancel.obj" \ + "$(INTDIR)\chatchnl.obj" \ + "$(INTDIR)\Chatroom.obj" \ + "$(INTDIR)\clrpref.obj" \ + "$(INTDIR)\connect.obj" \ + "$(INTDIR)\disconn.obj" \ + "$(INTDIR)\getpass.obj" \ + "$(INTDIR)\Joingame.obj" \ + "$(INTDIR)\logon.obj" \ + "$(INTDIR)\message.obj" \ + "$(INTDIR)\Progress.obj" \ + "$(INTDIR)\rasmgr.obj" \ + "$(INTDIR)\scrllbar.obj" \ + "$(INTDIR)\setpass.obj" \ + "$(INTDIR)\Spi.obj" \ + "$(INTDIR)\Srv.obj" \ + "$(INTDIR)\Ui.obj" \ + ".\STORM.LIB" + +".\bin\battle.snp" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Standard - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Standard\Release" +# PROP BASE Intermediate_Dir "Standard\Release" +# PROP BASE Target_Dir "Standard" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Standard\Release" +# PROP Intermediate_Dir "Standard\Release" +# PROP Target_Dir "Standard" +OUTDIR=.\Standard\Release +INTDIR=.\Standard\Release + +ALL : ".\bin\Standard.snp" + +CLEAN : + -@erase "$(INTDIR)\IPX.OBJ" + -@erase "$(INTDIR)\MODEM.OBJ" + -@erase "$(INTDIR)\NULL.OBJ" + -@erase "$(INTDIR)\PERF.OBJ" + -@erase "$(INTDIR)\SERIAL.OBJ" + -@erase "$(INTDIR)\STANDARD.OBJ" + -@erase "$(INTDIR)\STANDARD.res" + -@erase "$(INTDIR)\Trace.obj" + -@erase "$(OUTDIR)\Standard.exp" + -@erase "$(OUTDIR)\Standard.lib" + -@erase "$(OUTDIR)\Standard.map" + -@erase ".\bin\Standard.snp" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /G5Fry /c +CPP_PROJ=/nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/Standard.pch" /YX /Fo"$(INTDIR)/" /G5Fry /c +CPP_OBJS=.\Standard\Release/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/STANDARD.res" /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/Standard.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x18000000 /subsystem:windows /dll /map /machine:I386 /out:"bin\Standard.snp" +LINK32_FLAGS=tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib\ + shell32.lib wsock32.lib storm.lib /nologo /base:0x18000000 /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)/Standard.pdb"\ + /map:"$(INTDIR)/Standard.map" /machine:I386 /def:".\Standard\STANDARD.DEF"\ + /out:"bin\Standard.snp" /implib:"$(OUTDIR)/Standard.lib" +DEF_FILE= \ + ".\Standard\STANDARD.DEF" +LINK32_OBJS= \ + "$(INTDIR)\IPX.OBJ" \ + "$(INTDIR)\MODEM.OBJ" \ + "$(INTDIR)\NULL.OBJ" \ + "$(INTDIR)\PERF.OBJ" \ + "$(INTDIR)\SERIAL.OBJ" \ + "$(INTDIR)\STANDARD.OBJ" \ + "$(INTDIR)\STANDARD.res" \ + "$(INTDIR)\Trace.obj" \ + ".\STORM.LIB" + +".\bin\Standard.snp" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Standard\Debug" +# PROP BASE Intermediate_Dir "Standard\Debug" +# PROP BASE Target_Dir "Standard" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Standard\Debug" +# PROP Intermediate_Dir "Standard\Debug" +# PROP Target_Dir "Standard" +OUTDIR=.\Standard\Debug +INTDIR=.\Standard\Debug + +ALL : ".\bin\Standard.snp" + +CLEAN : + -@erase "$(INTDIR)\IPX.OBJ" + -@erase "$(INTDIR)\MODEM.OBJ" + -@erase "$(INTDIR)\NULL.OBJ" + -@erase "$(INTDIR)\PERF.OBJ" + -@erase "$(INTDIR)\SERIAL.OBJ" + -@erase "$(INTDIR)\STANDARD.OBJ" + -@erase "$(INTDIR)\STANDARD.res" + -@erase "$(INTDIR)\Trace.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\Standard.exp" + -@erase "$(OUTDIR)\Standard.lib" + -@erase "$(OUTDIR)\Standard.map" + -@erase "$(OUTDIR)\Standard.pdb" + -@erase ".\bin\Standard.ilk" + -@erase ".\bin\Standard.snp" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/Standard.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Standard\Debug/ +CPP_SBRS=.\. + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +MTL=mktyplib.exe +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +RSC_PROJ=/l 0x409 /fo"$(INTDIR)/STANDARD.res" /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/Standard.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:0x18000000 /subsystem:windows /dll /map /debug /machine:I386 /out:"bin\Standard.snp" +LINK32_FLAGS=tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib\ + shell32.lib wsock32.lib storm.lib /nologo /base:0x18000000 /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)/Standard.pdb"\ + /map:"$(INTDIR)/Standard.map" /debug /machine:I386\ + /def:".\Standard\STANDARD.DEF" /out:"bin\Standard.snp"\ + /implib:"$(OUTDIR)/Standard.lib" +DEF_FILE= \ + ".\Standard\STANDARD.DEF" +LINK32_OBJS= \ + "$(INTDIR)\IPX.OBJ" \ + "$(INTDIR)\MODEM.OBJ" \ + "$(INTDIR)\NULL.OBJ" \ + "$(INTDIR)\PERF.OBJ" \ + "$(INTDIR)\SERIAL.OBJ" \ + "$(INTDIR)\STANDARD.OBJ" \ + "$(INTDIR)\STANDARD.res" \ + "$(INTDIR)\Trace.obj" \ + ".\STORM.LIB" + +".\bin\Standard.snp" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +################################################################################ +# Begin Target + +# Name "DiabloUI - Win32 Release" +# Name "DiabloUI - Win32 Debug" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Project Dependency + +# Project_Dep_Name "ui" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +"ui - Win32 Release" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="ui - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +"ui - Win32 Debug" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="ui - Win32 Debug" + +!ENDIF + +# End Project Dependency +################################################################################ +# Begin Source File + +SOURCE=.\Testui.cpp +DEP_CPP_TESTU=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\Diabloui.h"\ + + +"$(INTDIR)\Testui.obj" : $(SOURCE) $(DEP_CPP_TESTU) "$(INTDIR)" + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STORM.LIB + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Project Dependency + +# Project_Dep_Name "battle" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +"battle - Win32 Release" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="battle - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +"battle - Win32 Debug" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="battle - Win32 Debug" + +!ENDIF + +# End Project Dependency +################################################################################ +# Begin Project Dependency + +# Project_Dep_Name "Standard" + +!IF "$(CFG)" == "DiabloUI - Win32 Release" + +"Standard - Win32 Release" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="Standard - Win32 Release" + +!ELSEIF "$(CFG)" == "DiabloUI - Win32 Debug" + +"Standard - Win32 Debug" : + $(MAKE) /$(MAKEFLAGS) /F ".\Diabloui.mak" CFG="Standard - Win32 Debug" + +!ENDIF + +# End Project Dependency +# End Target +################################################################################ +# Begin Target + +# Name "ui - Win32 Release" +# Name "ui - Win32 Debug" + +!IF "$(CFG)" == "ui - Win32 Release" + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Title.cpp +DEP_CPP_TITLE=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Title.obj" : $(SOURCE) $(DEP_CPP_TITLE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\DiabloUI.rc +DEP_RSC_DIABL=\ + ".\Ui\arrow.cur"\ + ".\Ui\But_sml.raw"\ + ".\Ui\Credits.txt"\ + ".\Ui\Frank.rc"\ + ".\Ui\ibeam.cur"\ + ".\Ui\link.cur"\ + ".\Ui\Mike.rc"\ + ".\Ui\Srpopup.pal"\ + ".\Ui\Srpopup.raw"\ + + +!IF "$(CFG)" == "ui - Win32 Release" + + +"$(INTDIR)\DiabloUI.res" : $(SOURCE) $(DEP_RSC_DIABL) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/DiabloUI.res" /i "Ui" /d "NDEBUG" $(SOURCE) + + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + + +"$(INTDIR)\DiabloUI.res" : $(SOURCE) $(DEP_RSC_DIABL) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/DiabloUI.res" /i "Ui" /d "_DEBUG" $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\local.cpp +DEP_CPP_LOCAL=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\local.obj" : $(SOURCE) $(DEP_CPP_LOCAL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Diabloui.cpp +DEP_CPP_DIABLO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\Diabloui.obj" : $(SOURCE) $(DEP_CPP_DIABLO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Diabloui.def + +!IF "$(CFG)" == "ui - Win32 Release" + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\MainMenu.cpp +DEP_CPP_MAINM=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\MainMenu.obj" : $(SOURCE) $(DEP_CPP_MAINM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\credits.cpp +DEP_CPP_CREDI=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\credits.obj" : $(SOURCE) $(DEP_CPP_CREDI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\cr8game.cpp +DEP_CPP_CR8GA=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\cr8game.obj" : $(SOURCE) $(DEP_CPP_CR8GA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelHero.cpp +DEP_CPP_SELHE=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelHero.obj" : $(SOURCE) $(DEP_CPP_SELHE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\OkCancel.cpp +DEP_CPP_OKCAN=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\OkCancel.obj" : $(SOURCE) $(DEP_CPP_OKCAN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Logon.cpp +DEP_CPP_LOGON=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Logon.obj" : $(SOURCE) $(DEP_CPP_LOGON) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Progress.cpp +DEP_CPP_PROGR=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Progress.obj" : $(SOURCE) $(DEP_CPP_PROGR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\connect.cpp +DEP_CPP_CONNE=\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\connect.obj" : $(SOURCE) $(DEP_CPP_CONNE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\disclaim.cpp +DEP_CPP_DISCL=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\disclaim.obj" : $(SOURCE) $(DEP_CPP_DISCL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\artfont.cpp +DEP_CPP_ARTFO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\artfont.obj" : $(SOURCE) $(DEP_CPP_ARTFO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Focus.cpp +DEP_CPP_FOCUS=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\Focus.obj" : $(SOURCE) $(DEP_CPP_FOCUS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STORM.LIB + +!IF "$(CFG)" == "ui - Win32 Release" + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelClass.cpp +DEP_CPP_SELCL=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelClass.obj" : $(SOURCE) $(DEP_CPP_SELCL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelList.cpp +DEP_CPP_SELLI=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelList.obj" : $(SOURCE) $(DEP_CPP_SELLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\EntrName.cpp +DEP_CPP_ENTRN=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\EntrName.obj" : $(SOURCE) $(DEP_CPP_ENTRN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\UiSnd.cpp +DEP_CPP_UISND=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\UiSnd.obj" : $(SOURCE) $(DEP_CPP_UISND) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelYesNo.cpp +DEP_CPP_SELYE=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelYesNo.obj" : $(SOURCE) $(DEP_CPP_SELYE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelConn.cpp +DEP_CPP_SELCO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelConn.obj" : $(SOURCE) $(DEP_CPP_SELCO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\CreaHero.cpp +DEP_CPP_CREAH=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\CreaHero.obj" : $(SOURCE) $(DEP_CPP_CREAH) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\DiabEdit.cpp +DEP_CPP_DIABE=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\DiabEdit.obj" : $(SOURCE) $(DEP_CPP_DIABE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Doom.cpp +DEP_CPP_DOOM_=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Doom.obj" : $(SOURCE) $(DEP_CPP_DOOM_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Fade.cpp +DEP_CPP_FADE_=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Fade.obj" : $(SOURCE) $(DEP_CPP_FADE_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelIPX.cpp +DEP_CPP_SELIP=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelIPX.obj" : $(SOURCE) $(DEP_CPP_SELIP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelGame.cpp +DEP_CPP_SELGA=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\SelGame.obj" : $(SOURCE) $(DEP_CPP_SELGA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\CreaDung.cpp +DEP_CPP_CREAD=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\CreaDung.obj" : $(SOURCE) $(DEP_CPP_CREAD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\DirLink.cpp +DEP_CPP_DIRLI=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\DirLink.obj" : $(SOURCE) $(DEP_CPP_DIRLI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Sbar.cpp +DEP_CPP_SBAR_=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + + +"$(INTDIR)\Sbar.obj" : $(SOURCE) $(DEP_CPP_SBAR_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelLoad.cpp +DEP_CPP_SELLO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelLoad.obj" : $(SOURCE) $(DEP_CPP_SELLO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\CopyProt.cpp +DEP_CPP_COPYP=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\CopyProt.obj" : $(SOURCE) $(DEP_CPP_COPYP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\Modem.cpp +DEP_CPP_MODEM=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\Modem.obj" : $(SOURCE) $(DEP_CPP_MODEM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelModem.cpp +DEP_CPP_SELMO=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelModem.obj" : $(SOURCE) $(DEP_CPP_SELMO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\EntrDial.cpp +DEP_CPP_ENTRD=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\EntrDial.obj" : $(SOURCE) $(DEP_CPP_ENTRD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\SelDial.cpp +DEP_CPP_SELDI=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\SelDial.obj" : $(SOURCE) $(DEP_CPP_SELDI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Ui\ModmStat.cpp +DEP_CPP_MODMS=\ + ".\Sclass.h"\ + ".\Ui\..\storm.h"\ + ".\Ui\artfont.h"\ + ".\Ui\DiabEdit.h"\ + ".\Ui\Diabloui.h"\ + ".\Ui\Doom.h"\ + ".\Ui\Fade.h"\ + ".\Ui\local.h"\ + ".\Ui\Pch.h"\ + ".\Ui\Sbar.h"\ + ".\Ui\UiSnd.h"\ + + +"$(INTDIR)\ModmStat.obj" : $(SOURCE) $(DEP_CPP_MODMS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "battle - Win32 Release" +# Name "battle - Win32 Debug" + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\battle\Ui.cpp +DEP_CPP_UI_CP=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Ui.obj" : $(SOURCE) $(DEP_CPP_UI_CP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Battle.h + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Battle.rc +DEP_RSC_BATTL=\ + ".\battle\Chathelp.txt"\ + + +!IF "$(CFG)" == "battle - Win32 Release" + + +"$(INTDIR)\Battle.res" : $(SOURCE) $(DEP_RSC_BATTL) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/Battle.res" /i "u:\diabloui" /i "battle" /d\ + "NDEBUG" $(SOURCE) + + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + + +"$(INTDIR)\Battle.res" : $(SOURCE) $(DEP_RSC_BATTL) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/Battle.res" /i "u:\diabloui" /i "battle" /d\ + "_DEBUG" $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\bnetart.h + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Chatroom.cpp +DEP_CPP_CHATR=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Chatroom.obj" : $(SOURCE) $(DEP_CPP_CHATR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Joingame.cpp +DEP_CPP_JOING=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Joingame.obj" : $(SOURCE) $(DEP_CPP_JOING) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Pch.h + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Resource.h + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Spi.cpp +DEP_CPP_SPI_C=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Spi.obj" : $(SOURCE) $(DEP_CPP_SPI_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Srv.cpp +DEP_CPP_SRV_C=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Srv.obj" : $(SOURCE) $(DEP_CPP_SRV_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Battle.cpp +DEP_CPP_BATTLE=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Battle.obj" : $(SOURCE) $(DEP_CPP_BATTLE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STORM.LIB + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Battle.def + +!IF "$(CFG)" == "battle - Win32 Release" + +!ELSEIF "$(CFG)" == "battle - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\connect.cpp +DEP_CPP_CONNE=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\connect.obj" : $(SOURCE) $(DEP_CPP_CONNE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\logon.cpp +DEP_CPP_LOGON_=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\logon.obj" : $(SOURCE) $(DEP_CPP_LOGON_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Progress.cpp +DEP_CPP_PROGR=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Progress.obj" : $(SOURCE) $(DEP_CPP_PROGR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\bnetlogo.cpp +DEP_CPP_BNETL=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\bnetlogo.obj" : $(SOURCE) $(DEP_CPP_BNETL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\cancel.cpp +DEP_CPP_CANCE=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\cancel.obj" : $(SOURCE) $(DEP_CPP_CANCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\Cache.cpp +DEP_CPP_CACHE=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Cache.obj" : $(SOURCE) $(DEP_CPP_CACHE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\clrpref.cpp +DEP_CPP_CLRPR=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\clrpref.obj" : $(SOURCE) $(DEP_CPP_CLRPR) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\ad.cpp +DEP_CPP_AD_CP=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\ad.obj" : $(SOURCE) $(DEP_CPP_AD_CP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\rasmgr.cpp +DEP_CPP_RASMG=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\rasmgr.obj" : $(SOURCE) $(DEP_CPP_RASMG) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\disconn.cpp +DEP_CPP_DISCO=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\disconn.obj" : $(SOURCE) $(DEP_CPP_DISCO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\chatchnl.cpp +DEP_CPP_CHATC=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\chatchnl.obj" : $(SOURCE) $(DEP_CPP_CHATC) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\scrllbar.cpp +DEP_CPP_SCRLL=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\scrllbar.obj" : $(SOURCE) $(DEP_CPP_SCRLL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\message.cpp +DEP_CPP_MESSA=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Sclass.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\message.obj" : $(SOURCE) $(DEP_CPP_MESSA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\setpass.cpp +DEP_CPP_SETPA=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\setpass.obj" : $(SOURCE) $(DEP_CPP_SETPA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\battle\getpass.cpp +DEP_CPP_GETPA=\ + ".\battle\Battle.h"\ + ".\battle\chat.h"\ + ".\battle\Pch.h"\ + ".\battle\rasmgr.h"\ + ".\Ui\..\battle\bnetart.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\getpass.obj" : $(SOURCE) $(DEP_CPP_GETPA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +################################################################################ +# Begin Target + +# Name "Standard - Win32 Release" +# Name "Standard - Win32 Debug" + +!IF "$(CFG)" == "Standard - Win32 Release" + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\Standard\STANDARD.RC + +!IF "$(CFG)" == "Standard - Win32 Release" + + +"$(INTDIR)\STANDARD.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/STANDARD.res" /i "Standard" /d "NDEBUG"\ + $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + + +"$(INTDIR)\STANDARD.res" : $(SOURCE) "$(INTDIR)" + $(RSC) /l 0x409 /fo"$(INTDIR)/STANDARD.res" /i "Standard" /d "_DEBUG"\ + $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\MODEM.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_MODEM=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\MODEM.OBJ" : $(SOURCE) $(DEP_CPP_MODEM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_MODEM=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\MODEM.OBJ" : $(SOURCE) $(DEP_CPP_MODEM) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\NULL.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_NULL_=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\NULL.OBJ" : $(SOURCE) $(DEP_CPP_NULL_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_NULL_=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\NULL.OBJ" : $(SOURCE) $(DEP_CPP_NULL_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\PERF.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_PERF_=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\PERF.OBJ" : $(SOURCE) $(DEP_CPP_PERF_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_PERF_=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\PERF.OBJ" : $(SOURCE) $(DEP_CPP_PERF_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\SERIAL.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_SERIA=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\SERIAL.OBJ" : $(SOURCE) $(DEP_CPP_SERIA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_SERIA=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\SERIAL.OBJ" : $(SOURCE) $(DEP_CPP_SERIA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\STANDARD.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_STAND=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\STANDARD.OBJ" : $(SOURCE) $(DEP_CPP_STAND) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_STAND=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\STANDARD.OBJ" : $(SOURCE) $(DEP_CPP_STAND) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\IPX.CPP + +!IF "$(CFG)" == "Standard - Win32 Release" + +DEP_CPP_IPX_C=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + + +"$(INTDIR)\IPX.OBJ" : $(SOURCE) $(DEP_CPP_IPX_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +DEP_CPP_IPX_C=\ + ".\Sclass.h"\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\IPX.OBJ" : $(SOURCE) $(DEP_CPP_IPX_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\STORM.LIB + +!IF "$(CFG)" == "Standard - Win32 Release" + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\STANDARD.DEF + +!IF "$(CFG)" == "Standard - Win32 Release" + +!ELSEIF "$(CFG)" == "Standard - Win32 Debug" + +!ENDIF + +# End Source File +################################################################################ +# Begin Source File + +SOURCE=.\Standard\Trace.cpp +DEP_CPP_TRACE=\ + ".\Standard\Pch.h"\ + ".\Standard\Standard.h"\ + ".\Standard\Trace.h"\ + ".\Ui\..\storm.h"\ + + +"$(INTDIR)\Trace.obj" : $(SOURCE) $(DEP_CPP_TRACE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/src/Uisrc/DIABLOUI.MDP b/src/Uisrc/DIABLOUI.MDP new file mode 100644 index 0000000..3b901a4 Binary files /dev/null and b/src/Uisrc/DIABLOUI.MDP differ diff --git a/src/Uisrc/DIABLOUI.NCB b/src/Uisrc/DIABLOUI.NCB new file mode 100644 index 0000000..55e1e5a Binary files /dev/null and b/src/Uisrc/DIABLOUI.NCB differ diff --git a/src/Uisrc/DIABLOUI.OPT b/src/Uisrc/DIABLOUI.OPT new file mode 100644 index 0000000..1a2d257 Binary files /dev/null and b/src/Uisrc/DIABLOUI.OPT differ diff --git a/src/Uisrc/DIABLOUI.PLG b/src/Uisrc/DIABLOUI.PLG new file mode 100644 index 0000000..7da553c --- /dev/null +++ b/src/Uisrc/DIABLOUI.PLG @@ -0,0 +1,31 @@ +--------------------Configuration: DiabloUI - Win32 Debug-------------------- +Begining build with project "C:\hellfire\diabloui\Diabloui.dsp", at root. +Active configuration is Win32 (x86) Application (based on Win32 (x86) Application) + +Project's tools are: + "32-bit C/C++ Compiler for 80x86" with flags "/nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR".\Debug/" /Fp".\Debug/Diabloui.pch" /YX /Fo".\Debug/" /Fd".\Debug/" /FD /c " + "OLE Type Library Maker" with flags "/nologo /D "_DEBUG" /mktyplib203 /win32 " + "Win32 Resource Compiler" with flags "/l 0x409 /d "_DEBUG" " + "Browser Database Maker" with flags "/nologo /o".\Debug/Diabloui.bsc" " + "COFF Linker for 80x86" with flags "kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib ui\debug\diabloui.lib battle\debug\battle.lib standard\debug\standard.lib /nologo /subsystem:windows /incremental:no /pdb:".\Debug/DiabloUI.pdb" /map:".\Debug/DiabloUI.map" /debug /machine:I386 /out:".\bin\DiabloUI.exe" " + "Custom Build" with flags "" + "" with flags "" + +Creating temp file "C:\WINDOWS\TEMP\RSP40A3.TMP" with contents +Creating command line "cl.exe @C:\WINDOWS\TEMP\RSP40A3.TMP" +Compiling... +Testui.cpp +Creating temp file "C:\WINDOWS\TEMP\RSP41B4.TMP" with contents +Creating command line "link.exe @C:\WINDOWS\TEMP\RSP41B4.TMP" +Linking... +Creating command line "bscmake.exe /nologo /o".\Debug/Diabloui.bsc" .\Debug\Testui.sbr" +Creating browse info file... + + + +DiabloUI.exe - 0 error(s), 0 warning(s) diff --git a/src/Uisrc/MSSCCPRJ.SCC b/src/Uisrc/MSSCCPRJ.SCC new file mode 100644 index 0000000..f37e866 --- /dev/null +++ b/src/Uisrc/MSSCCPRJ.SCC @@ -0,0 +1,4 @@ +SCC = This is a Source Code Control file + +[DIABLOUI.MAK] +SCC_Project_Name = "$/UiSrc", RJAAAAAA diff --git a/src/Uisrc/NEWSTM/STORM.H b/src/Uisrc/NEWSTM/STORM.H new file mode 100644 index 0000000..7916c00 --- /dev/null +++ b/src/Uisrc/NEWSTM/STORM.H @@ -0,0 +1,3331 @@ +#ifndef _STORM_H_ +#define _STORM_H_ + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import on +#endif + + +//#########################################################################// +//#########################################################################// +// // +// // +// STANDARD PROGRAMMING INTERFACE // +// // +// // +//#########################################################################// +//#########################################################################// + + +#define DECLARE_STRICT_HANDLE(name) typedef struct name##__ { int unused; } *name +#define DECLARE_DERIVED_HANDLE(name,base) typedef struct name##__ : public base##__ { int unused; } *name + + +/**************************************************************************** +* +* Error codes +* (Error text is defined in Stormerr.mc) +* +***/ + +#define STORMFAC 0x510 +#define STORMERROR(code) (0x80000000 | (STORMFAC << 16) | ((code) & 0xFFFF)) + +#define STORM_ERROR_ASSERTION STORMERROR(0) +#define STORM_ERROR_BAD_ARGUMENT STORMERROR(101) +#define STORM_ERROR_GAME_ALREADY_STARTED STORMERROR(102) +#define STORM_ERROR_GAME_FULL STORMERROR(103) +#define STORM_ERROR_GAME_NOT_FOUND STORMERROR(104) +#define STORM_ERROR_GAME_TERMINATED STORMERROR(105) +#define STORM_ERROR_INVALID_PLAYER STORMERROR(106) +#define STORM_ERROR_NO_MESSAGES_WAITING STORMERROR(107) +#define STORM_ERROR_NOT_ARCHIVE STORMERROR(108) +#define STORM_ERROR_NOT_ENOUGH_ARGUMENTS STORMERROR(109) +#define STORM_ERROR_NOT_IMPLEMENTED STORMERROR(110) +#define STORM_ERROR_NOT_IN_ARCHIVE STORMERROR(111) +#define STORM_ERROR_NOT_IN_GAME STORMERROR(112) +#define STORM_ERROR_NOT_INITIALIZED STORMERROR(113) +#define STORM_ERROR_NOT_PLAYING STORMERROR(114) +#define STORM_ERROR_NOT_REGISTERED STORMERROR(115) +#define STORM_ERROR_REQUIRES_CODEC STORMERROR(116) +#define STORM_ERROR_REQUIRES_DDRAW STORMERROR(117) +#define STORM_ERROR_REQUIRES_DSOUND STORMERROR(118) +#define STORM_ERROR_REQUIRES_UPGRADE STORMERROR(119) +#define STORM_ERROR_STILL_ACTIVE STORMERROR(120) +#define STORM_ERROR_VERSION_MISMATCH STORMERROR(121) +#define STORM_ERROR_MEMORY_ALREADY_FREED STORMERROR(122) +#define STORM_ERROR_MEMORY_CORRUPT STORMERROR(123) +#define STORM_ERROR_MEMORY_INVALID_BLOCK STORMERROR(124) +#define STORM_ERROR_MEMORY_MANAGER_INACTIVE STORMERROR(125) +#define STORM_ERROR_MEMORY_NEVER_RELEASED STORMERROR(126) +#define STORM_ERROR_HANDLE_NEVER_RELEASED STORMERROR(127) +#define STORM_ERROR_ACCESS_OUT_OF_BOUNDS STORMERROR(128) +#define STORM_ERROR_MEMORY_NULL_POINTER STORMERROR(129) + + +/**************************************************************************** +* +* BitBlt functions +* +***/ + +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SBltDestroy (); +#endif +extern "C" BOOL APIENTRY SBltGetSCode (DWORD rop3, + LPSTR buffer, + DWORD buffersize, + BOOL optimize = 1); +extern "C" BOOL APIENTRY SBltROP3 (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Clipped (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Tiled (LPBYTE dest, + LPRECT destrect, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3); + + +/**************************************************************************** +* +* Bitmap functions +* +***/ + +#define SBMP_IMAGETYPE_AUTO 0 +#define SBMP_IMAGETYPE_BMP 1 +#define SBMP_IMAGETYPE_PCX 2 + +typedef LPVOID (APIENTRY *SBMPALLOCPROC)(DWORD); + +extern "C" BOOL APIENTRY SBmpAllocLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE *returnedbuffer, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL, + int requestedbitdepth = 0, + SBMPALLOCPROC allocproc = NULL); +extern "C" BOOL APIENTRY SBmpDecodeImage (DWORD imagetype, + LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpSaveImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height, + int bitdepth); + + +/**************************************************************************** +* +* Command line parsing functions +* +***/ + +#define SCMD_ARG_FLAGGED (0 << 24) +#define SCMD_ARG_OPTIONAL (1 << 24) +#define SCMD_ARG_REQUIRED (2 << 24) +#define SCMD_ARG_MASK (SCMD_ARG_FLAGGED | SCMD_ARG_OPTIONAL | SCMD_ARG_REQUIRED) + +#define SCMD_BOOL_SET 0 +#define SCMD_BOOL_CLEAR 1 +#define SCMD_BOOL_MASK (SCMD_BOOL_CLEAR | SCMD_BOOL_SET) + +#define SCMD_CASESENSITIVE (0x01 << 8) + +#define SCMD_NUM_UNSIGNED 0 +#define SCMD_NUM_SIGNED 1 +#define SCMD_NUM_MASK (SCMD_NUM_UNSIGNED | SCMD_NUM_SIGNED) + +#define SCMD_TYPE_BOOL (0 << 16) +#define SCMD_TYPE_NUMERIC (1 << 16) +#define SCMD_TYPE_STRING (2 << 16) +#define SCMD_TYPE_MASK (SCMD_TYPE_BOOL | SCMD_TYPE_NUMERIC | SCMD_TYPE_STRING) + +#define SCMD_ERROR_BAD_ARGUMENT STORM_ERROR_BAD_ARGUMENT +#define SCMD_ERROR_NOT_ENOUGH_ARGUMENTS STORM_ERROR_NOT_ENOUGH_ARGUMENTS +#define SCMD_ERROR_OPEN_FAILED ERROR_OPEN_FAILED + +typedef struct _CMDERROR { + DWORD errorcode; + LPCTSTR itemstr; + LPCTSTR errorstr; +} CMDERROR, *CMDERRORPTR; + +typedef struct _CMDPARAMS { + DWORD flags; + DWORD id; + LPCTSTR name; + LPVOID variable; + DWORD setvalue; + DWORD setmask; + union { + BOOL boolvalue; + LONG signedvalue; + DWORD unsignedvalue; + LPCTSTR stringvalue; + }; +} CMDPARAMS, *CMDPARAMSPTR; + +typedef BOOL (CALLBACK *SCMDCALLBACK)(CMDPARAMSPTR,LPCTSTR); +typedef void (CALLBACK *SCMDERRORCALLBACK)(CMDERRORPTR); +typedef BOOL (CALLBACK *SCMDEXTRACALLBACK)(LPCTSTR); + +typedef struct _ARGLIST { + DWORD flags; + DWORD id; + LPCTSTR name; + SCMDCALLBACK callback; +} ARGLIST, *ARGLISTPTR; + +extern "C" BOOL APIENTRY SCmdCheckId (DWORD id); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SCmdDestroy (); +#endif +extern "C" BOOL APIENTRY SCmdGetBool (DWORD id); +extern "C" DWORD APIENTRY SCmdGetNum (DWORD id); +extern "C" BOOL APIENTRY SCmdGetString (DWORD id, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SCmdProcess (LPCTSTR cmdline, + BOOL skipprogname, + SCMDEXTRACALLBACK extracallback, + SCMDERRORCALLBACK errorcallback); +extern "C" BOOL APIENTRY SCmdRegisterArgList (const ARGLIST *listptr, + DWORD numargs); +extern "C" BOOL APIENTRY SCmdRegisterArgument (DWORD flags, + DWORD id, + LPCTSTR name, + LPVOID variableptr = NULL, + DWORD variablebytes = 0, + DWORD setvalue = TRUE, + DWORD setmask = 0xFFFFFFFF, + SCMDCALLBACK callback = NULL); + +#define SCmdProcessCommandLine(ext,err) SCmdProcess(GetCommandLine(),TRUE,(ext),(err)) + +#define ARGBOOL(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),TRUE,0xFFFFFFFF,callback) +#define ARGFLAG(flags,name,var,valuecallback) SCmdRegisterArgument(SCMD_TYPE_BOOL | (flags),0xFFFFFFFF,name,var,sizeof(var),value,value,callback) +#define ARGNUMBER(flags,name,var,callback) SCmdRegisterArgument(SCMD_TYPE_NUMERIC | (flags),0xFFFFFFFF,name,var,sizeof(var),0,0,callback) +#define ARGSTRING(flags,name,buffer,chars,callback) SCmdRegisterArgument(SCMD_TYPE_STRING | (flags),0xFFFFFFFF,name,buffer,(chars),0,0,callback) + + +/**************************************************************************** +* +* S-Code functions +* +***/ + +#define SCODE_CF_AUTOALIGNDWORD 0x00040000 +#define SCODE_CF_USESALTADJUSTS 0x04000000 + +DECLARE_STRICT_HANDLE(HSCODESTREAM); + +typedef struct _SCODEEXECUTEDATA { + DWORD size; + DWORD flags; + int xiterations; + int yiterations; + int adjustdest; + int adjustsource; + LPVOID dest; + LPVOID source; + LPVOID table; + DWORD a; + DWORD b; + DWORD c; + int adjustdestalt; + int adjustsourcealt; + DWORD reserved[2]; +} SCODEEXECUTEDATA, *SCODEEXECUTEDATAPTR; + +extern "C" BOOL APIENTRY SCodeCompile (LPCSTR prologstring, + LPCSTR loopstring, + LPCSTR *firsterror, + DWORD maxiterations, + DWORD flags, + HSCODESTREAM *handle); +extern "C" BOOL APIENTRY SCodeDelete (HSCODESTREAM handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SCodeDestroy (); +#endif +extern "C" BOOL APIENTRY SCodeExecute (HSCODESTREAM handle, + SCODEEXECUTEDATAPTR executedata); +extern "C" BOOL APIENTRY SCodeGetJumpTable (HSCODESTREAM handle, + LPBYTE **jumptableptr, + LPDWORD *prologpatchlocation, + LPDWORD *looppatchlocation, + LPDWORD *epilogpatchlocation); +extern "C" BOOL APIENTRY SCodeGetPseudocode (LPCSTR scodestring, + LPSTR buffer, + DWORD buffersize); + + +/**************************************************************************** +* +* Compression functions +* +***/ + +#define SCOMP_HINT_NONE 0 +#define SCOMP_HINT_BINARY 1 +#define SCOMP_HINT_TEXT 2 +#define SCOMP_HINT_EXECUTABLE 3 +#define SCOMP_HINT_ADPCM4 4 +#define SCOMP_HINT_ADPCM6 5 +#define SCOMP_HINTS 6 + +#define SCOMP_OPT_DEFAULT 0 +#define SCOMP_OPT_COMPRESSION 1 +#define SCOMP_OPT_SPEED 2 +#define SCOMP_OPT_QUALITY 3 + +#define SCOMP_TYPE_HUFFMAN 0x01 +#define SCOMP_TYPE_PKWARE 0x08 +#define SCOMP_TYPE_LOSSY_ADPCM_MONO 0x10 +#define SCOMP_TYPE_LOSSY_ADPCM_STEREO 0x20 + +extern "C" BOOL APIENTRY SCompCompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize, + DWORD compressiontypes, + DWORD hint, + DWORD optimization); +extern "C" BOOL APIENTRY SCompDecompress (LPVOID dest, + DWORD *destsize, + LPCVOID source, + DWORD sourcesize); + + +/**************************************************************************** +* +* Dialog box functions +* +***/ + +#define SDLG_ADJUST_NONE 0 +#define SDLG_ADJUST_VERTICAL 1 +#define SDLG_ADJUST_CONTROLPOS 2 + +#define SDLG_DBF_TILE 0x00000001 +#define SDLG_DBF_VCENTER 0x00000002 + +#define SDLG_STYLE_ANY 0xFFFFFFFF +#define SDLG_STYLE_ANYPUSHBUTTON 0x00010001 + +#define SDLG_USAGE_BACKGROUND 0x00000001 +#define SDLG_USAGE_NORMAL_UNFOCUSED 0x00000010 +#define SDLG_USAGE_NORMAL_FOCUSED 0x00000020 +#define SDLG_USAGE_NORMAL (SDLG_USAGE_NORMAL_UNFOCUSED | SDLG_USAGE_NORMAL_FOCUSED) +#define SDLG_USAGE_SELECTED_UNFOCUSED 0x00000040 +#define SDLG_USAGE_SELECTED_FOCUSED 0x00000080 +#define SDLG_USAGE_SELECTED (SDLG_USAGE_SELECTED_UNFOCUSED | SDLG_USAGE_SELECTED_FOCUSED) +#define SDLG_USAGE_NORMAL_GRAYED 0x00000100 +#define SDLG_USAGE_SELECTED_GRAYED 0x00000400 +#define SDLG_USAGE_GRAYED (SDLG_USAGE_NORMAL_GRAYED | SDLG_USAGE_SELECTED_GRAYED) +#define SDLG_USAGE_CURSORMASK 0x00001000 +#define SDLG_USAGE_CURSORIMAGE 0x00002000 + +extern "C" HDC APIENTRY SDlgBeginPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgBltToWindowE (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgBltToWindowI (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgCheckTimers (); +extern "C" HWND APIENTRY SDlgCreateDialogIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" HWND APIENTRY SDlgCreateDialogParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDefDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SDlgDestroy (); +#endif +extern "C" int APIENTRY SDlgDialogBoxIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" int APIENTRY SDlgDialogBoxParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDrawBitmap (HWND window, + DWORD usage, + HRGN region, + int offsetx = 0, + int offsety = 0, + LPRECT boundingoffset = NULL, + DWORD flags = 0); +extern "C" BOOL APIENTRY SDlgEndDialog (HWND window, + int result); +extern "C" BOOL APIENTRY SDlgEndPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgKillTimer (HWND window, + UINT event); +extern "C" BOOL APIENTRY SDlgSetBaseFont (int pointsize, + int weight, + DWORD flags, + DWORD family, + LPCTSTR face); +extern "C" BOOL APIENTRY SDlgSetBitmapE (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetBitmapI (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetControlBitmaps (HWND parentwindow, + LPINT controllist, + LPDWORD usagelist, + LPBYTE bitmapbits, + LPSIZE bitmapsize, + DWORD adjusttype, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetCursor (HWND window, + HCURSOR cursor, + DWORD id, + HCURSOR *oldcursor); +extern "C" BOOL APIENTRY SDlgSetSystemCursor (LPBYTE maskbitmap, + LPBYTE imagebitmap, + LPSIZE size, + DWORD id = 32512); +extern "C" BOOL APIENTRY SDlgSetTimer (HWND window, + UINT event, + UINT elapse, + TIMERPROC timerfunc); +extern "C" BOOL APIENTRY SDlgUpdateCursor (); + +#define SDlgCreateDialog(ins,tpl,wnd,prc) SDlgCreateDialogParam(ins,tpl,wnd,prc,0) +#define SDlgCreateDialogIndirect(ins,tpl,wnd,prc) SDlgCreateDialogIndirectParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBox(ins,tpl,wnd,prc) SDlgDialogBoxParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBoxIndirect(ins,tpl,wnd,prc) SDlgDialogBoxIndirectParam(ins,tpl,wnd,prc,0) + +#ifdef SDLG_USE_INCLUSIVE_RECTS +#define SDlgBltToWindow SDlgBltToWindowI +#define SDlgSetBitmap SDlgSetBitmapI +#else +#define SDlgBltToWindow SDlgBltToWindowE +#define SDlgSetBitmap SDlgSetBitmapE +#endif + +/**************************************************************************** +* +* DirectDraw functions +* +***/ + +#define SDRAW_SERVICE_BASIC 1 +#define SDRAW_SERVICE_PAGEFLIP 2 +#define SDRAW_SERVICE_DOUBLEBUFFER 3 +#define SDRAW_SERVICE_MAX 3 + +#define SDRAW_SURFACE_FRONT 0 +#define SDRAW_SURFACE_BACK 1 +#define SDRAW_SURFACE_SYSTEM 2 +#define SDRAW_SURFACE_TEMPORARY 3 + +#ifndef MAC +extern "C" BOOL APIENTRY SDrawAutoInitialize (HINSTANCE instance, + LPCTSTR classname, + LPCTSTR title, + WNDPROC wndproc = NULL, + int servicelevel = SDRAW_SERVICE_BASIC, + int width = 640, + int height = 480, + int bitdepth = 8); +extern "C" BOOL APIENTRY SDrawCaptureScreen (LPCTSTR filename = NULL); +#endif +extern "C" BOOL APIENTRY SDrawClearSurface (int surfacenumber); +extern "C" BOOL APIENTRY SDrawDestroy (); +extern "C" BOOL APIENTRY SDrawFlipPage (); +extern "C" HWND APIENTRY SDrawGetFrameWindow (HWND *window = NULL); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawGetObjects (LPDIRECTDRAW *directdraw, + LPDIRECTDRAWSURFACE *frontbuffer, + LPDIRECTDRAWSURFACE *backbuffer, + LPDIRECTDRAWSURFACE *systembuffer, + LPDIRECTDRAWSURFACE *temporarybuffer, + LPDIRECTDRAWPALETTE *palette, + HPALETTE *gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawGetScreenSize (int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SDrawGetServiceLevel (int *servicelevel = NULL); +extern "C" BOOL APIENTRY SDrawLockSurface (int surfacenumber, + LPCRECT rect, + LPBYTE *ptr, + int *pitch = NULL, + DWORD flags = 0); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawManualInitialize (HWND framewindow, + LPDIRECTDRAW directdraw, + LPDIRECTDRAWSURFACE frontbuffer, + LPDIRECTDRAWSURFACE backbuffer, + LPDIRECTDRAWSURFACE systembuffer, + LPDIRECTDRAWSURFACE temporarybuffer, + LPDIRECTDRAWPALETTE palette, + HPALETTE gdipalette); +#endif +extern "C" int APIENTRY SDrawMessageBox (LPCTSTR text, + LPCTSTR title, + UINT flags); +extern "C" BOOL APIENTRY SDrawPostClose (); +extern "C" BOOL APIENTRY SDrawRealizePalette (); +#ifndef MAC +extern "C" BOOL APIENTRY SDrawSelectGdiSurface (BOOL select, BOOL copy); +#endif +extern "C" BOOL APIENTRY SDrawUnlockSurface (int surfacenumber, + LPBYTE ptr, + DWORD numrects = 0, + LPCRECT rectarray = NULL); +extern "C" BOOL APIENTRY SDrawUpdatePalette (DWORD firstentry, + DWORD numentries, + LPPALETTEENTRY entries, + BOOL reservedentries = FALSE); +extern "C" BOOL APIENTRY SDrawUpdateScreen (LPCRECT rect); +#ifdef MAC +extern "C" BOOL APIENTRY SDrawVidDriverInitialize (HWND framewindow, + int servicelevel); +#endif + + +/**************************************************************************** +* +* Error handling functions +* +***/ + +#define SERR_LINECODE_FUNCTION -1 +#define SERR_LINECODE_OBJECT -2 +#define SERR_LINECODE_HANDLE -3 +#define SERR_LINECODE_FILE -4 + +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SErrDestroy (); +#endif +extern "C" BOOL APIENTRY SErrDisplayError (DWORD errorcode, + LPCTSTR filename, + int linenumber, + LPCTSTR description, + BOOL recoverable, + UINT exitcode = 1); +extern "C" BOOL APIENTRY SErrGetErrorStr (DWORD errorcode, + LPTSTR buffer, + DWORD bufferchars); +extern "C" DWORD APIENTRY SErrGetLastError (); +extern "C" BOOL APIENTRY SErrRegisterMessageSource (WORD facility, + HMODULE module, + LPVOID reserved = NULL); +extern "C" void APIENTRY SErrReportResourceLeak (LPCTSTR handlename); +extern "C" void APIENTRY SErrSetLastError (DWORD errorcode); +extern "C" void APIENTRY SErrSuppressErrors (BOOL suppress); + +#define SErrGetLastErrorStr(buf,len) SErrGetErrorStr(SErrGetLastError(),buf,len) +#define FATALRESULT(str) SErrDisplayError(SErrGetLastError(),str,SERR_LINECODE_FUNCTION,NULL,FALSE) +#define REPORTRESOURCELEAK(handle) SErrReportResourceLeak(#handle) + +#ifdef _DEBUG +#define ASSERT(a) if (!(a)) \ + SErrDisplayError(STORM_ERROR_ASSERTION, \ + __FILE__, \ + __LINE__, \ + #a, \ + FALSE) +#define VALIDATEBEGIN do { +#define VALIDATE(a) ASSERT(a) +#define VALIDATEANDBLANK(a) do { \ + ASSERT(a); \ + *(a) = 0; \ + } while (0) +#define VALIDATEEND } while (0) +#define VALIDATEENDVOID } while (0) +#else +#define ASSERT(a) +#define VALIDATEBEGIN do { \ + int intrn_valresult = -1 +#define VALIDATE(a) intrn_valresult &= (a) ? -1 : 0 +#define VALIDATEANDBLANK(a) if (a) \ + *a = 0; \ + else \ + intrn_valresult = 0 +#define VALIDATEEND if (!intrn_valresult) { \ + SErrSetLastError( \ + ERROR_INVALID_PARAMETER); \ + return 0; \ + } \ + } while (0) +#define VALIDATEENDVOID if (!intrn_valresult) { \ + SErrSetLastError( \ + ERROR_INVALID_PARAMETER); \ + return; \ + } \ + } while (0) +#endif + + +/**************************************************************************** +* +* Event dispatching functions +* +***/ + +typedef void (CALLBACK *SEVTHANDLER)(LPVOID); + +extern "C" BOOL APIENTRY SEvtBreakHandlerChain (LPVOID data); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SEvtDestroy (); +#endif +extern "C" BOOL APIENTRY SEvtDispatch (DWORD type, + DWORD subtype, + DWORD id, + LPVOID data); +extern "C" BOOL APIENTRY SEvtPopState (DWORD type, + DWORD subtype); +extern "C" BOOL APIENTRY SEvtPushState (DWORD type, + DWORD subtype); +extern "C" BOOL APIENTRY SEvtRegisterHandler (DWORD type, + DWORD subtype, + DWORD id, + DWORD flags, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterHandler (DWORD type, + DWORD subtype, + DWORD id, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterType (DWORD type, + DWORD subtype); + + +/**************************************************************************** +* +* File I/O functions +* +***/ + +#define SFILE_AUTH_UNABLETOAUTHENTICATE 0 +#define SFILE_AUTH_NOSIGNATURE 1 +#define SFILE_AUTH_BADSIGNATURE 2 +#define SFILE_AUTH_UNKNOWNSIGNATURE 3 +#define SFILE_AUTH_FIRSTAUTHENTIC 5 +#define SFILE_AUTH_AUTHENTICBLIZZARD 5 + +#define SFILE_DDA_LOOP 0x00040000 + +#define SFILE_ERROR_BAD_FORMAT ERROR_BAD_FORMAT +#define SFILE_ERROR_BAD_PATHNAME ERROR_BAD_PATHNAME +#define SFILE_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED +#define SFILE_ERROR_FILE_INVALID ERROR_FILE_INVALID +#define SFILE_ERROR_FILE_NOT_FOUND ERROR_FILE_NOT_FOUND +#define SFILE_ERROR_HANDLE_EOF ERROR_HANDLE_EOF +#define SFILE_ERROR_INVALID_DATA ERROR_INVALID_DATA +#define SFILE_ERROR_INVALID_DRIVE ERROR_INVALID_DRIVE +#define SFILE_ERROR_INVALID_HANDLE ERROR_INVALID_HANDLE +#define SFILE_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SFILE_ERROR_NOT_ARCHIVE STORM_ERROR_NOT_ARCHIVE +#define SFILE_ERROR_NOT_AUTHENTICATED ERROR_NOT_AUTHENTICATED +#define SFILE_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SFILE_ERROR_NOT_IN_ARCHIVE STORM_ERROR_NOT_IN_ARCHIVE +#define SFILE_ERROR_NOT_INITIALIZED STORM_ERROR_NOT_INITIALIZED +#define SFILE_ERROR_NOT_PLAYING STORM_ERROR_NOT_PLAYING + +#define SFILE_ERRORMODE_RETURNCODE 0 +#define SFILE_ERRORMODE_CUSTOM 1 +#define SFILE_ERRORMODE_FATAL 2 + +#define SFILE_FIND_FILES 0x00000001 +#define SFILE_FIND_DIRECTORIES 0x00000002 + +DECLARE_STRICT_HANDLE(HSARCHIVE); +DECLARE_STRICT_HANDLE(HSFILE); + +typedef BOOL (CALLBACK *SFILEERRORPROC)(LPCTSTR,DWORD); + +extern "C" BOOL APIENTRY SFileAuthenticateArchive (HSARCHIVE archive, + DWORD *extendedresult); +extern "C" BOOL APIENTRY SFileCloseArchive (HSARCHIVE handle); +extern "C" BOOL APIENTRY SFileCloseFile (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaBegin (HSFILE handle, + DWORD buffersize, + DWORD flags); +extern "C" BOOL APIENTRY SFileDdaBeginEx (HSFILE handle, + DWORD buffersize, + DWORD flags, + DWORD offset, + LONG volume, + LONG pan, + LPVOID reserved); +extern "C" BOOL APIENTRY SFileDdaDestroy (); +extern "C" BOOL APIENTRY SFileDdaEnd (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaGetPos (HSFILE handle, + DWORD *position, + DWORD *maxposition); +extern "C" BOOL APIENTRY SFileDdaGetVolume (HSFILE handle, + LONG *volume, + LONG *pan); +#ifdef __DSOUND_INCLUDED__ +extern "C" BOOL APIENTRY SFileDdaInitialize (LPDIRECTSOUND directsound); +#endif +extern "C" BOOL APIENTRY SFileDdaSetVolume (HSFILE handle, + LONG volume, + LONG pan); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SFileDestroy (); +#endif +extern "C" BOOL APIENTRY SFileEnableDirectAccess (BOOL enable); +extern "C" BOOL APIENTRY SFileGetArchiveInfo (HSARCHIVE archive, + int *priority, + BOOL *cdrom); +extern "C" BOOL APIENTRY SFileGetArchiveName (HSARCHIVE archive, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SFileGetBasePath (LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SFileGetFileArchive (HSFILE file, + HSARCHIVE *archive); +extern "C" BOOL APIENTRY SFileGetFileName (HSFILE file, + LPTSTR buffer, + DWORD bufferchars); +extern "C" DWORD APIENTRY SFileGetFileSize (HSFILE handle, + LPDWORD filesizehigh = NULL); +extern "C" BOOL APIENTRY SFileOpenArchive (LPCTSTR archivename, + int priority, + BOOL cdonly, + HSARCHIVE *handle); +extern "C" BOOL APIENTRY SFileOpenFile (LPCTSTR filename, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileEx (HSARCHIVE archivehandle, + LPCTSTR filename, + DWORD flags, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileReadFile (HSFILE handle, + LPVOID buffer, + DWORD bytestoread, + LPDWORD bytesread = NULL, + LPOVERLAPPED overlapped = NULL); +extern "C" BOOL APIENTRY SFileSetBasePath (LPCTSTR path); +extern "C" DWORD APIENTRY SFileSetFilePointer (HSFILE handle, + LONG distancetomove, + PLONG distancetomovehigh, + DWORD movemethod); +extern "C" BOOL APIENTRY SFileSetIoErrorMode (DWORD errormode, + SFILEERRORPROC errorproc = NULL); +extern "C" BOOL APIENTRY SFileSetLocale (LCID lcid); + + +/**************************************************************************** +* +* GDI functions +* +***/ + +#define ETO_TEXT_TRANSPARENT 0 +#define ETO_TEXT_COLOR 1 +#define ETO_TEXT_BLACK 2 +#define ETO_TEXT_WHITE 3 +#define ETO_BKG_TRANSPARENT 0 +#define ETO_BKG_COLOR 1 +#define ETO_BKG_BLACK 2 +#define ETO_BKG_WHITE 3 + +DECLARE_STRICT_HANDLE(HSGDIOBJ); +DECLARE_DERIVED_HANDLE(HSGDIFONT,HSGDIOBJ); + +extern "C" BOOL APIENTRY SGdiBitBlt (LPBYTE videobuffer, + int destx, + int desty, + LPBYTE sourcedata, + LPRECT sourcerect, + int sourcecx, + int sourcecy, + COLORREF color = 0, + DWORD rop = SRCCOPY); +extern "C" BOOL APIENTRY SGdiCreateFont (LPBYTE bits, + int width, + int height, + int bitdepth, + int filecharwidth, + int filecharheight, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiDeleteObject (HSGDIOBJ handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SGdiDestroy (); +#endif +extern "C" BOOL APIENTRY SGdiExtTextOut (LPBYTE videobuffer, + int x, + int y, + LPRECT rect, + COLORREF color, + int textcoloruse, + int bkgcoloruse, + LPCTSTR string, + int chars = -1); +extern "C" BOOL APIENTRY SGdiGetTextExtent (LPCTSTR string, + int chars, + LPSIZE size); +extern "C" BOOL APIENTRY SGdiImportFont (HFONT windowsfont, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiLoadFont (LPCTSTR filename, + int filecharwidth, + int filecharheight, + int basecharwidth, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiRectangle (LPBYTE videobuffer, + int left, + int top, + int right, + int bottom, + COLORREF color); +extern "C" BOOL APIENTRY SGdiSelectObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiSetPitch (int pitch); +extern "C" BOOL APIENTRY SGdiSetTargetDimensions (int width, + int height, + int bitdepth, + int pitch); +extern "C" BOOL APIENTRY SGdiTextOut (LPBYTE videobuffer, + int x, + int y, + COLORREF color, + LPCTSTR string, + int chars = -1); + + +/**************************************************************************** +* +* Logging functions +* +***/ + +DECLARE_STRICT_HANDLE(HSLOG); + +extern "C" void APIENTRY SLogClose (HSLOG log); +extern "C" BOOL APIENTRY SLogCreate (LPCTSTR filename, + DWORD flags, + HSLOG *log); +#ifdef STORMSTATIC +extern "C" void APIENTRY SLogDestroy (); +#endif +extern "C" void APIENTRY SLogDump (HSLOG log, + LPCVOID data, + DWORD bytes); +extern "C" void APIENTRY SLogFlush (HSLOG log); +extern "C" void APIENTRY SLogFlushAll (); +#ifdef STORMSTATIC +extern "C" void APIENTRY SLogInitialize (); +#endif +extern "C" void __cdecl SLogPend (HSLOG log, + LPCTSTR format, + ...); +extern "C" void __cdecl SLogWrite (HSLOG log, + LPCTSTR format, + ...); + + +/**************************************************************************** +* +* Memory allocation functions +* +***/ + +#define SMEM_FLAG_ZEROMEMORY 0x00000008 +#define SMEM_FLAG_PRESERVEONDESTROY 0x08000000 + +DECLARE_STRICT_HANDLE(HSHEAP); + +typedef struct _SMEMBLOCKDETAILS { + DWORD size; + LPVOID ptr; + BOOL allocated; + BOOL valid; + DWORD bytes; + DWORD overhead; +} SMEMBLOCKDETAILS, *LPSMEMBLOCKDETAILS; + +typedef struct _SMEMHEAPDETAILS { + DWORD size; + HSHEAP handle; + char filename[MAX_PATH]; + int linenumber; + DWORD regions; + DWORD committedbytes; + DWORD reservedbytes; + DWORD maximumsize; + DWORD allocatedblocks; +} SMEMHEAPDETAILS, *LPSMEMHEAPDETAILS; + +extern "C" LPVOID APIENTRY SMemAlloc (DWORD bytes, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SMemDestroy (); +#endif +extern "C" BOOL APIENTRY SMemFindNextBlock (HSHEAP heap, + LPVOID prevblock, + LPVOID *nextblock, + LPSMEMBLOCKDETAILS details); +extern "C" BOOL APIENTRY SMemFindNextHeap (HSHEAP prevheap, + HSHEAP *nextheap, + LPSMEMHEAPDETAILS details); +extern "C" BOOL APIENTRY SMemFree (LPVOID ptr, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" HSHEAP APIENTRY SMemGetHeapByCaller (LPCSTR filename, + int linenumber); +extern "C" HSHEAP APIENTRY SMemGetHeapByPtr (LPVOID ptr); +extern "C" LPVOID APIENTRY SMemHeapAlloc (HSHEAP handle, + DWORD flags, + DWORD bytes); +extern "C" HSHEAP APIENTRY SMemHeapCreate (DWORD options, + DWORD initialsize, + DWORD maximumsize); +extern "C" BOOL APIENTRY SMemHeapDestroy (HSHEAP handle); +extern "C" BOOL APIENTRY SMemHeapFree (HSHEAP handle, + DWORD flags, + LPVOID ptr); +#ifdef STORMSTATIC +extern "C" void APIENTRY SMemInitialize (); +#endif + +inline void __cdecl operator delete (void *ptr) { + if (ptr) + SMemFree(ptr,__FILE__,__LINE__,0); +} + +inline void * __cdecl operator new (size_t bytes) { + return SMemAlloc(bytes,__FILE__,__LINE__,0); +} + +#ifndef __ICL +#ifndef __MWERKS__ +inline void __cdecl operator delete[] (void *ptr) { + if (ptr) + SMemFree(ptr,__FILE__,__LINE__,0); +} + +inline void * __cdecl operator new[] (size_t bytes) { + return SMemAlloc(bytes,__FILE__,__LINE__,0); +} +#endif +#endif + +#ifndef __PLACEMENT_NEW_INLINE +#define __PLACEMENT_NEW_INLINE +inline void * __cdecl operator new (size_t, void *ptr) { + return (ptr); +} + +inline void * __cdecl operator new[] (size_t, void *ptr) { + return (ptr); +} +#endif + +#define ALLOC(bytes) SMemAlloc(bytes,__FILE__,__LINE__,0) +#define ALLOCZERO(bytes) SMemAlloc(bytes,__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) +#define DEL(ptr) delete(ptr) +#define DELIFUSED(ptr) delete(ptr) +#define FREE(ptr) SMemFree(ptr,__FILE__,__LINE__,0) +#define FREEIFUSED(ptr) do if (ptr) SMemFree(ptr,__FILE__,__LINE__,0); while (0) +#define NEW(struct) (new(SMemAlloc(sizeof(struct),__FILE__,__LINE__,0)) struct) +#define NEWZERO(struct) (new(SMemAlloc(sizeof(struct),__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY)) struct) + + +/**************************************************************************** +* +* Message functions +* +***/ + +typedef struct _PARAMS { + HWND window; + UINT message; + WPARAM wparam; + LPARAM lparam; + UINT notifycode; + LPVOID extra; + BOOL useresult; + LRESULT result; +} PARAMS, *PARAMSPTR, *LPPARAMS; + +typedef BOOL (CALLBACK *SMSGIDLEPROC)(DWORD); +typedef void (CALLBACK *SMSGHANDLER)(LPPARAMS); + +extern "C" BOOL APIENTRY SMsgBreakHandlerChain (LPPARAMS params); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY SMsgDestroy (); +#endif +extern "C" BOOL APIENTRY SMsgDispatchMessage (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL *useresult, + LRESULT *result); +extern "C" BOOL APIENTRY SMsgDoMessageLoop (SMSGIDLEPROC idleproc = NULL, + BOOL cleanuponquit = TRUE); +extern "C" BOOL APIENTRY SMsgPopRegisterState (HWND window); +extern "C" BOOL APIENTRY SMsgPushRegisterState (HWND window); +extern "C" BOOL APIENTRY SMsgRegisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgUnregisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); + + +/**************************************************************************** +* +* Networking functions +* +***/ + +#define SNET_ART_BACKGROUND 0 +#define SNET_ART_BUTTONTEXTURE 1 +#define SNET_ART_JOINBACKGROUND 2 +#define SNET_ART_HELPBACKGROUND 3 +#define SNET_ART_POPUPBACKGROUND 4 +#define SNET_ART_BUTTON_XSML 5 +#define SNET_ART_BUTTON_SML 6 +#define SNET_ART_BUTTON_MED 7 +#define SNET_ART_BUTTON_LRG 8 +#define SNET_ART_APP_LOGO_SML 9 +#define SNET_ART_PROGRESS_BACKGROUND 10 +#define SNET_ART_PROGRESS_FILLER 11 +#define SNET_ART_POPUPBACKGROUND_SML 12 +#define SNET_ART_SCROLLBARARROWS 13 +#define SNET_ART_SCROLLTHUMB 14 +#define SNET_ART_SCROLLBAR 15 +#define SNET_ART_COMBOLEFT 16 +#define SNET_ART_COMBOMIDDLE 17 +#define SNET_ART_COMBORIGHT 18 + +#define SNET_AUTHTYPE_CHANNEL 1 +#define SNET_AUTHTYPE_GAME 2 + +#define SNET_BROADCASTNONLOCALPLAYERID 0xFFFFFFFE +#define SNET_BROADCASTPLAYERID 0xFFFFFFFF +#define SNET_INVALIDPLAYERID 0xFFFFFFFF + +#define SNET_CAPS_PAGELOCKEDBUFFERS 0x00000001 +#define SNET_CAPS_BASICINTERFACE 0x00000002 +#define SNET_CAPS_DEBUGONLY 0x10000000 +#define SNET_CAPS_RETAILONLY 0x20000000 + +#define SNET_CF_ALLOWPRIVATEGAMES 0x00000001 + +#define SNET_DATA_SYSCOLORS 1 +#define SNET_DATA_CURSORLINK 2 +#define SNET_DATA_CURSORARROW 3 +#define SNET_DATA_CURSORIBEAM 4 + +#define SNET_DDF_INCLUDENAME 0x00000001 +#define SNET_DDF_MULTILINE 0x00000002 + +#define SNET_DDPF_BLIZZARD 0x00000001 +#define SNET_DDPF_MODERATOR 0x00000002 +#define SNET_DDPF_SPEAKER 0x00000004 +#define SNET_DDPF_SYSOP 0x00000008 +#define SNET_DDPF_SQUELCHED 0x00000020 + +#define SNET_DRAWTYPE_GAME 1 +#define SNET_DRAWTYPE_PLAYER 2 + +#define SNET_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS +#define SNET_ERROR_BAD_PROVIDER ERROR_BAD_PROVIDER +#define SNET_ERROR_CANCELLED ERROR_CANCELLED +#define SNET_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SNET_ERROR_INVALID_PLAYER STORM_ERROR_INVALID_PLAYER +#define SNET_ERROR_GAME_ALREADY_STARTED STORM_ERROR_GAME_ALREADY_STARTED +#define SNET_ERROR_GAME_FULL STORM_ERROR_GAME_FULL +#define SNET_ERROR_GAME_NOT_FOUND STORM_ERROR_GAME_NOT_FOUND +#define SNET_ERROR_GAME_TERMINATED STORM_ERROR_GAME_TERMINATED +#define SNET_ERROR_HOST_UNREACHABLE ERROR_HOST_UNREACHABLE +#define SNET_ERROR_MAX_THRDS_REACHED ERROR_MAX_THRDS_REACHED +#define SNET_ERROR_NETWORK_BUSY ERROR_NETWORK_BUSY +#define SNET_ERROR_NO_MESSAGES_WAITING STORM_ERROR_NO_MESSAGES_WAITING +#define SNET_ERROR_NO_NETWORK ERROR_NO_NETWORK +#define SNET_ERROR_NOT_CONNECTED ERROR_NOT_CONNECTED +#define SNET_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SNET_ERROR_NOT_IMPLEMENTED STORM_ERROR_NOT_IMPLEMENTED +#define SNET_ERROR_NOT_IN_GAME STORM_ERROR_NOT_IN_GAME +#define SNET_ERROR_NOT_OWNER ERROR_NOT_OWNER +#define SNET_ERROR_NOT_REGISTERED STORM_ERROR_NOT_REGISTERED +#define SNET_ERROR_REQUIRES_UPGRADE STORM_ERROR_REQUIRES_UPGRADE +#define SNET_ERROR_STILL_ACTIVE STORM_ERROR_STILL_ACTIVE +#define SNET_ERROR_TOO_MANY_NAMES ERROR_TOO_MANY_NAMES +#define SNET_ERROR_VERSION_MISMATCH STORM_ERROR_VERSION_MISMATCH + +#define SNET_EVENT_INITDATA 1 +#define SNET_EVENT_PLAYERJOIN 2 +#define SNET_EVENT_PLAYERLEAVE 3 +#define SNET_EVENT_SERVERMESSAGE 4 + +#define SNET_EXIT_AUTO_JOINING 0x00000001 +#define SNET_EXIT_AUTO_NEWGAME 0x00000002 +#define SNET_EXIT_AUTO_SHUTDOWN 0x00000003 +#define SNET_EXIT_PLAYERQUIT 0x40000001 +#define SNET_EXIT_PLAYERKILLED 0x40000002 +#define SNET_EXIT_PLAYERWON 0x40000004 +#define SNET_EXIT_GAMEOVER 0x40000005 +#define SNET_EXIT_NOTRESPONDING 0x40000006 + +#define SNET_GM_PRIVATE 0x00000001 +#define SNET_GM_FULL 0x00000002 +#define SNET_GM_ADVERTISED 0x00000004 +#define SNET_GM_UNJOINABLE 0x00000008 +#define SNET_GM_UNLISTEDMASK (SNET_GM_PRIVATE | SNET_GM_FULL | SNET_GM_UNJOINABLE) + +#define SNET_INFO_GAMENAME 1 +#define SNET_INFO_GAMEPASSWORD 2 +#define SNET_INFO_GAMEDESCRIPTION 3 +#define SNET_INFO_GAMEMODE 4 +#define SNET_INFO_INITDATA 5 +#define SNET_INFO_MAXPLAYERS 6 + +#define SNET_LMT_EXPECTED 1 +#define SNET_LMT_CURRENT 2 +#define SNET_LMT_PEAK 4 + +#define SNET_PERFID_TURN 1 +#define SNET_PERFID_TURNSSENT 4 +#define SNET_PERFID_TURNSRECV 5 +#define SNET_PERFID_MSGSENT 6 +#define SNET_PERFID_MSGRECV 7 +#define SNET_PERFID_USERBYTESSENT 8 +#define SNET_PERFID_USERBYTESRECV 9 +#define SNET_PERFID_TOTALBYTESSENT 10 +#define SNET_PERFID_TOTALBYTESRECV 11 +#define SNET_PERFID_PKTSENTONWIRE 12 +#define SNET_PERFID_PKTRECVONWIRE 13 +#define SNET_PERFID_BYTESSENTONWIRE 14 +#define SNET_PERFID_BYTESRECVONWIRE 15 +#define SNET_PERFIDNUM 16 + +#define SNET_PERFTYPE_COUNTER 0x10410400 +#define SNET_PERFTYPE_RAWCOUNT 0x00010000 + +#define SNET_PSF_ACTIVE 0x00010000 +#define SNET_PSF_TURNAVAILABLE 0x00020000 +#define SNET_PSF_RESPONDING 0x00040000 + +#define SNET_SF_ALLOWCREATE 0x00000001 + +#define SNET_SND_CHANGEFOCUS 0 +#define SNET_SND_SELECTITEM 1 + +#define SNET_UPGRADE_FAILED -1 +#define SNET_UPGRADE_NOT_NEEDED 0 +#define SNET_UPGRADE_SUCCEEDED 1 +#define SNET_UPGRADING_TERMINATE 2 + +#define SNET_MAXNAMELENGTH 128 +#define SNET_MAXDESCLENGTH 128 + +typedef struct _SNETCAPS { + DWORD size; + DWORD flags; + DWORD maxmessagesize; + DWORD maxqueuesize; + DWORD maxplayers; + DWORD bytessec; + DWORD latencyms; + DWORD defaultturnssec; + DWORD defaultturnsintransit; +} SNETCAPS, *SNETCAPSPTR; + +typedef struct _SNETCREATEDATA { + DWORD size; + DWORD providerid; + DWORD maxplayers; + DWORD createflags; +} SNETCREATEDATA, *SNETCREATEDATAPTR; + +typedef struct _SNET_DATA_SYSCOLORTABLE { + DWORD syscolor; + COLORREF rgb; +} SNET_DATA_SYSCOLORTABLE, *SNET_DATA_SYSCOLORTABLEPTR; + +typedef struct _SNETEVENT { + DWORD eventid; + DWORD playerid; + LPVOID data; + DWORD databytes; +} SNETEVENT, *SNETEVENTPTR; + +typedef struct _SNETGAME { + DWORD size; + DWORD id; + LPCSTR gamename; + LPCSTR gamedescription; + DWORD categorybits; + DWORD numplayers; + DWORD maxplayers; +} SNETGAME, *SNETGAMEPTR; + +struct _SNETPROGRAMDATA; +struct _SNETPLAYERDATA; +struct _SNETUIDATA; +struct _SNETVERSIONDATA; + +typedef BOOL (CALLBACK *SNETABORTPROC )(); +typedef void (CALLBACK *SNETADDCATEGORYPROC )(LPCSTR,DWORD,DWORD); +typedef void (CALLBACK *SNETCATEGORYLISTPROC )(_SNETPLAYERDATA *,SNETADDCATEGORYPROC); +typedef BOOL (CALLBACK *SNETCATEGORYPROC )(BOOL,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *,DWORD *); +typedef BOOL (CALLBACK *SNETCHECKAUTHPROC )(DWORD,LPCSTR,LPCSTR,DWORD,LPCSTR,LPSTR,DWORD); +typedef BOOL (CALLBACK *SNETCREATEPROC )(SNETCREATEDATAPTR,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *); +typedef BOOL (CALLBACK *SNETDRAWDESCPROC )(DWORD,DWORD,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,LPDRAWITEMSTRUCT); +typedef BOOL (CALLBACK *SNETENUMDEVICESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMGAMESEXPROC )(SNETGAMEPTR); +typedef BOOL (CALLBACK *SNETENUMGAMESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMPROVIDERSPROC)(DWORD,LPCSTR,LPCSTR,SNETCAPSPTR); +typedef void (CALLBACK *SNETEVENTPROC )(SNETEVENTPTR); +typedef BOOL (CALLBACK *SNETGETARTPROC )(DWORD,DWORD,LPPALETTEENTRY,LPBYTE,DWORD,int *,int *,int *); +typedef BOOL (CALLBACK *SNETGETDATAPROC )(DWORD,DWORD,LPVOID,DWORD,DWORD *); +typedef int (CALLBACK *SNETMESSAGEBOXPROC )(HWND,LPCSTR,LPCSTR,UINT); +typedef BOOL (CALLBACK *SNETPLAYSOUNDPROC )(DWORD,DWORD,DWORD); +typedef BOOL (CALLBACK *SNETSELECTEDPROC )(DWORD,SNETCAPSPTR,_SNETUIDATA *,_SNETVERSIONDATA *); +typedef BOOL (CALLBACK *SNETSTATUSPROC )(LPCSTR,DWORD,DWORD,DWORD,SNETABORTPROC); +typedef BOOL (CALLBACK *SNETPROFILEPROC )(); // tbd -- include callback to save info +typedef BOOL (CALLBACK *SNETNEWACCOUNTPROC )(); // tbd -- include callback to try to create + +typedef struct _SNETPLAYERDATA { + DWORD size; + LPCSTR playername; + LPCSTR playerdescription; + // new for 1.05: + LPCSTR displayedfields; +} SNETPLAYERDATA, *SNETPLAYERDATAPTR; + +typedef struct _SNETPROGRAMDATA { + DWORD size; + LPCSTR programname; + LPCSTR programdescription; + DWORD programid; + DWORD versionid; + DWORD reserved1; + DWORD maxplayers; + LPVOID initdata; + DWORD initdatabytes; + LPVOID reserved2; + DWORD optcategorybits; +} SNETPROGRAMDATA, *SNETPROGRAMDATAPTR; + +typedef struct _SNETUIDATA { + DWORD size; + DWORD uiflags; + HWND parentwindow; + SNETGETARTPROC artcallback; + SNETCHECKAUTHPROC authcallback; + SNETCREATEPROC createcallback; + SNETDRAWDESCPROC drawdesccallback; + SNETSELECTEDPROC selectedcallback; + SNETMESSAGEBOXPROC messageboxcallback; + SNETPLAYSOUNDPROC soundcallback; + SNETSTATUSPROC statuscallback; + SNETGETDATAPROC getdatacallback; + SNETCATEGORYPROC categorycallback; + // new for 1.05: + SNETCATEGORYLISTPROC categorylistcallback; + SNETNEWACCOUNTPROC newaccountcallback; + SNETPROFILEPROC profilecallback; +} SNETUIDATA, *SNETUIDATAPTR; + +typedef struct _SNETVERSIONDATA { + DWORD size; + LPCSTR versionstring; + LPCSTR executablefile; + LPCSTR originalarchivefile; + LPCSTR patcharchivefile; +} SNETVERSIONDATA, *SNETVERSIONDATAPTR; + +extern "C" BOOL APIENTRY SNetCreateGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamecategorybits, + LPVOID initdata, + DWORD initdatabytes, + DWORD maxplayers, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetDestroy (); +extern "C" BOOL APIENTRY SNetDropPlayer (DWORD playerid, DWORD exitcode); +extern "C" BOOL APIENTRY SNetEnumDevices (SNETENUMDEVICESPROC callback); +extern "C" BOOL APIENTRY SNetEnumGames (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumGamesEx (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESEXPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumProviders (SNETCAPSPTR mincaps, + SNETENUMPROVIDERSPROC callback); +extern "C" BOOL APIENTRY SNetGetGameInfo (DWORD index, + LPVOID buffer, + DWORD buffersize, + DWORD *byteswritten); +extern "C" BOOL APIENTRY SNetGetNetworkLatency (DWORD measurementtype, + DWORD *result); +extern "C" BOOL APIENTRY SNetGetNumPlayers (DWORD *firstplayerid, + DWORD *lastplayerid, + DWORD *activeplayers); +extern "C" BOOL APIENTRY SNetGetOwnerId (DWORD *playerid); +extern "C" BOOL APIENTRY SNetGetOwnerTurnsWaiting (DWORD *turns); +extern "C" BOOL APIENTRY SNetGetPerformanceData (DWORD counterid, + DWORD *countervalue, + DWORD *countertype, + LONG *counterscale, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +extern "C" BOOL APIENTRY SNetGetPlayerCaps (DWORD playerid, + SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetPlayerName (DWORD playerid, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SNetGetProviderCaps (SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetTurnsInTransit (DWORD *turns); +extern "C" BOOL APIENTRY SNetInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetInitializeProvider (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetJoinGame (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetLeaveGame (DWORD exitcode); +extern "C" BOOL APIENTRY SNetPerformUpgrade (DWORD *upgradestatus); +extern "C" BOOL APIENTRY SNetReceiveMessage (DWORD *senderplayerid, + LPVOID *data, + DWORD *databytes); +extern "C" BOOL APIENTRY SNetReceiveTurns (DWORD firstplayerid, + DWORD arraysize, + LPVOID *arraydata, + LPDWORD arraydatabytes, + LPDWORD arrayplayerstatus); +extern "C" BOOL APIENTRY SNetRegisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); +extern "C" BOOL APIENTRY SNetResetLatencyMeasurements (); +extern "C" BOOL APIENTRY SNetSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY SNetSendMessage (DWORD targetplayerid, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSendServerChatCommand (LPCSTR command); +extern "C" BOOL APIENTRY SNetSendTurn (LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSetBasePlayer (DWORD playerid); +extern "C" BOOL APIENTRY SNetSetGameMode (DWORD modeflags); +extern "C" BOOL APIENTRY SNetUnregisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); + + +/**************************************************************************** +* +* Networking service provider interface +* +***/ + +#define SNETSPI_MAXCLIENTDATA 256 +#define SNETSPI_MAXSTRINGLENGTH 128 + +typedef struct _SNETADDR { + BYTE address[16]; +} SNETADDR, *SNETADDRPTR; + +typedef struct _SNETSPI_DEVICELIST { + DWORD deviceid; + SNETCAPS devicecaps; + char devicename[SNETSPI_MAXSTRINGLENGTH]; + char devicedescription[SNETSPI_MAXSTRINGLENGTH]; + DWORD reserved; + _SNETSPI_DEVICELIST *next; +} SNETSPI_DEVICELIST, *SNETSPI_DEVICELISTPTR; + +typedef struct _SNETSPI_GAMELIST { + DWORD gameid; + DWORD gamemode; + DWORD creationtime; + SNETADDR owner; + DWORD ownerlatency; + DWORD ownerlasttime; + DWORD gamecategorybits; + char gamename[SNETSPI_MAXSTRINGLENGTH]; + char gamedescription[SNETSPI_MAXSTRINGLENGTH]; + _SNETSPI_GAMELIST *next; + // new for 1.05: + LPVOID clientdata; + DWORD clientdatabytes; +} SNETSPI_GAMELIST, *SNETSPI_GAMELISTPTR; + +typedef struct _SNETSPI { + DWORD size; + BOOL (CALLBACK *CompareNetAddresses)(SNETADDRPTR,SNETADDRPTR,DWORD *); + BOOL (CALLBACK *Destroy)(); + BOOL (CALLBACK *Free)(SNETADDRPTR,LPVOID,DWORD); + BOOL (CALLBACK *FreeExternalMessage)(LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *GetGameInfo)(DWORD,LPCSTR,LPCSTR,SNETSPI_GAMELIST *); + BOOL (CALLBACK *GetPerformanceData)(DWORD,DWORD *,LARGE_INTEGER *,LARGE_INTEGER *); + BOOL (CALLBACK *Initialize)(SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,HANDLE); + BOOL (CALLBACK *InitializeDevice)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR); + BOOL (CALLBACK *LockDeviceList)(SNETSPI_DEVICELISTPTR *); + BOOL (CALLBACK *LockGameList)(DWORD,DWORD,SNETSPI_GAMELISTPTR *); + +/* note: this is the way that the Receive call should look... + + BOOL (CALLBACK *Receive)(SNETADDRPTR *,LPVOID *,DWORD *); + + below is the receive call with two parameters switched around + to make it incompatible with older .snp's during the beta... */ + + BOOL (CALLBACK *Receive)(LPVOID *,DWORD *,SNETADDRPTR *); + + BOOL (CALLBACK *ReceiveExternalMessage)(LPCSTR *,LPCSTR *,LPCSTR *); + BOOL (CALLBACK *SelectGame)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,DWORD *); + BOOL (CALLBACK *Send)(DWORD,SNETADDRPTR *,LPVOID,DWORD); + BOOL (CALLBACK *SendExternalMessage)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *StartAdvertisingGame)(LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,DWORD,LPCVOID,DWORD); + BOOL (CALLBACK *StopAdvertisingGame)(); + BOOL (CALLBACK *UnlockDeviceList)(SNETSPI_DEVICELISTPTR); + BOOL (CALLBACK *UnlockGameList)(SNETSPI_GAMELISTPTR,DWORD *); + // new for 1.05: + BOOL (CALLBACK *GetLocalPlayerName)(LPSTR,DWORD,LPSTR,DWORD); +} SNETSPI, *SNETSPIPTR; + +typedef BOOL (APIENTRY *SNETSPIBIND )(DWORD,SNETSPIPTR *); +typedef BOOL (APIENTRY *SNETSPIQUERY)(DWORD,DWORD *,LPCSTR *,LPCSTR *,SNETCAPSPTR *); + + +/**************************************************************************** +* +* Registry functions +* +***/ + +#define SREG_FLAG_USERSPECIFIC 0x00000001 +#define SREG_FLAG_BATTLENET 0x00000002 +#define SREG_FLAG_FLUSHTODISK 0x00000008 +#define SREG_FLAG_MULTISZ 0x00000080 + +extern "C" BOOL APIENTRY SRegGetBaseKey (DWORD flags, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SRegLoadData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID buffer, + DWORD buffersize, + DWORD *bytesread); +extern "C" BOOL APIENTRY SRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SRegLoadValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *value); +extern "C" BOOL APIENTRY SRegSaveData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SRegSaveString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPCTSTR string); +extern "C" BOOL APIENTRY SRegSaveValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD value); + + +/**************************************************************************** +* +* Region manager functions +* +***/ + +#define SRGN_AND RGN_AND +#define SRGN_COPY RGN_COPY +#define SRGN_DIFF RGN_DIFF +#define SRGN_OR RGN_OR +#define SRGN_XOR RGN_XOR +#define SRGN_PARAMONLY 6 +#define SRGN_MIN 1 +#define SRGN_MAX 6 + +DECLARE_STRICT_HANDLE(HSRGN); + +extern "C" void APIENTRY SRgnClear (HSRGN handle); +extern "C" void APIENTRY SRgnCombineRect (HSRGN handle, + LPCRECT rect, + LPVOID param, + int combinemode); +extern "C" void APIENTRY SRgnCreate (HSRGN *handle, + DWORD reserved = 0); +extern "C" void APIENTRY SRgnDelete (HSRGN handle); +#ifdef STORMSTATIC +extern "C" void APIENTRY SRgnDestroy (); +#endif +extern "C" void APIENTRY SRgnDuplicate (HSRGN orighandle, + HSRGN *handle, + DWORD reserved = 0); +extern "C" void APIENTRY SRgnGetBoundingRect (HSRGN handle, + LPRECT rect); +extern "C" void APIENTRY SRgnGetRectParams (HSRGN handle, + LPCRECT rect, + DWORD *numparams, + LPVOID *buffer); +extern "C" void APIENTRY SRgnGetRects (HSRGN handle, + DWORD *numrects, + LPRECT buffer); + +#define SRgnAddParam(handle,rect,param) SRgnCombineRect(handle,rect,param,SRGN_PARAMONLY); +#define SRgnAddRect(handle,rect,param) SRgnCombineRect(handle,rect,param,SRGN_OR) + + +/**************************************************************************** +* +* Run-time library functions +* +***/ + +#define ONCE ONCEEXPAND(__FILE__##__##__LINE__##__once) +#define ONCEEXPAND(a) BOOL a = TRUE; a; a = FALSE + +#define TRY goto trylabel; trylabel: +#define LEAVE goto finallylabel +#define FINALLY goto finallylabel; finallylabel: + + +/**************************************************************************** +* +* String functions +* +***/ + +#define SSTR_HASH_CASESENSITIVE 0x00000001 + +#define SSTR_UNBOUNDED 0x7FFFFFFF + +extern "C" LPTSTR APIENTRY SStrChr (LPCTSTR string, + char ch, + BOOL reverse = FALSE); +extern "C" DWORD APIENTRY SStrCopy (LPTSTR dest, + LPCTSTR source, + DWORD destsize = SSTR_UNBOUNDED); +extern "C" DWORD APIENTRY SStrHash (LPCTSTR string, + DWORD flags = 0, + DWORD seed = 0); +extern "C" DWORD APIENTRY SStrLen (LPCTSTR string); +extern "C" void APIENTRY SStrPack (LPTSTR dest, + LPCTSTR source, + DWORD destsize = SSTR_UNBOUNDED); +extern "C" void APIENTRY SStrTokenize (LPCTSTR *string, + LPTSTR buffer, + DWORD bufferchars, + LPCTSTR whitespace, + BOOL *quoted = NULL); + + +/**************************************************************************** +* +* Transparency functions +* +***/ + +#define STRANS_CF_INTERSECT 0x00000001 +#define STRANS_CF_INVERTSECOND 0x00000002 +#define STRANS_CF_SUBTRACT (STRANS_CF_INTERSECT | STRANS_CF_INVERTSECOND) + +DECLARE_STRICT_HANDLE(HSTRANS); +typedef HSTRANS HTRANS; + +extern "C" BOOL APIENTRY STransBlt (LPBYTE dest, + int destx, + int desty, + int destpitch, + HSTRANS transparency); +extern "C" BOOL APIENTRY STransBltUsingMask (LPBYTE dest, + LPBYTE source, + int destpitch, + int sourcepitch, + HSTRANS mask); +extern "C" BOOL APIENTRY STransCombineMasks (HSTRANS basemask, + HSTRANS secondmask, + int offsetx, + int offsety, + DWORD flags, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateMaskE (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransCreateMaskI (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransDelete (HSTRANS handle); +#ifdef STORMSTATIC +extern "C" BOOL APIENTRY STransDestroy (); +#endif +extern "C" BOOL APIENTRY STransDuplicate (HSTRANS source, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIntersectDirtyArray (HSTRANS sourcemask, + LPBYTE dirtyarray, + BYTE dirtyarraymask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransInvertMask (HSTRANS sourcemask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIsPixelInMask (HSTRANS mask, + int offsetx, + int offsety); +extern "C" BOOL APIENTRY STransLoadE (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransLoadI (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransSetDirtyArrayInfo (int screencx, + int screency, + int cellcx, + int cellcy); +extern "C" BOOL APIENTRY STransUpdateDirtyArray (LPBYTE dirtyarray, + BYTE dirtyvalue, + int destx, + int desty, + HSTRANS transparency, + BOOL tracecontour); + +#ifdef STRANS_USE_INCLUSIVE_RECTS +#define STransCreate STransCreateI +#define STransCreateMask STransCreateMaskI +#define STransLoad STransLoadI +#else +#define STransCreate STransCreateE +#define STransCreateMask STransCreateMaskE +#define STransLoad STransLoadE +#endif + + +/**************************************************************************** +* +* Video functions +* +***/ + +#define SVID_FLAG_DOUBLESCANS 0x00000001 +#define SVID_FLAG_INTERPOLATE 0x00000002 +#define SVID_FLAG_INTERLACE 0x00000004 +#define SVID_FLAG_AUTOQUALITY 0x00000008 +#define SVID_FLAG_1XSIZE 0x00000100 +#define SVID_FLAG_2XSIZE 0x00000200 +#define SVID_FLAG_AUTOSIZE 0x00000800 +#define SVID_FLAG_FILEHANDLE 0x00010000 +#define SVID_FLAG_PRELOAD 0x00020000 +#define SVID_FLAG_LOOP 0x00040000 +#define SVID_FLAG_FULLSCREEN 0x00080000 +#define SVID_FLAG_USECURRENTPALETTE 0x00100000 +#define SVID_FLAG_CLEARSCREEN 0x00200000 +#define SVID_FLAG_NOSKIP 0x00400000 +#define SVID_FLAG_NEEDPAN 0x02000000 +#define SVID_FLAG_NEEDVOLUME 0x04000000 +#define SVID_FLAG_TOSCREEN 0x10000000 +#define SVID_FLAG_TOBUFFER 0x20000000 + +#define SVID_CUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_2XSIZE) +#define SVID_AUTOCUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_AUTOSIZE | SVID_FLAG_AUTOQUALITY) + +#define SVID_QUALITY_LOW_SKIPSCANS SVID_FLAG_2XSIZE +#define SVID_QUALITY_LOW (SVID_FLAG_2XSIZE | SVID_FLAG_DOUBLESCANS) +#define SVID_QUALITY_HIGH_SKIPSCANS (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE) +#define SVID_QUALITY_HIGH (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE | SVID_FLAG_DOUBLESCANS) + +DECLARE_STRICT_HANDLE(HSVIDEO); + +typedef struct _SVIDPALETTEUSE { + DWORD size; + DWORD firstentry; + DWORD numentries; +} SVIDPALETTEUSE, *SVIDPALETTEUSEPTR; + +extern "C" BOOL APIENTRY SVidDestroy (); +extern "C" BOOL APIENTRY SVidGetPerformanceData (HSVIDEO video, + BOOL averageframems, + DWORD *framems, + BOOL averagepalettems, + DWORD *palettems); +extern "C" BOOL APIENTRY SVidGetSize (HSVIDEO video, + int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SVidInitialize (LPVOID directsound); +extern "C" BOOL APIENTRY SVidPlayBegin (LPCTSTR filename, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayBeginFromMemory (LPVOID sourceptr, + DWORD sourcebytes, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayContinue (); +extern "C" BOOL APIENTRY SVidPlayContinueSingle (HSVIDEO video, + BOOL forceupdate, + BOOL *updated); +extern "C" BOOL APIENTRY SVidPlayEnd (HSVIDEO video); +extern "C" BOOL APIENTRY SVidSetVolume (HSVIDEO video, + LONG volume, + LONG pan, + DWORD track = 0); + + +/**************************************************************************** +* +* Storm global functions +* +***/ + +extern "C" BOOL APIENTRY StormDestroy (); + +#ifdef MAC +extern "C" void StormStartup(); +extern "C" void StormShutdown(); +#endif + + +//#########################################################################// +//#########################################################################// +// // +// // +// CLASS-BASED PROGRAMMING INTERFACE // +// (under construction) // +// // +// // +//#########################################################################// +//#########################################################################// + + +/**************************************************************************** +* +* CSLog +* +***/ + +class CSLog { + + private: + HSLOG m_handle; + + public: + + //======================================================================= + CSLog (LPCTSTR filename) { + SLogCreate(filename,0,&m_handle); + } + + //======================================================================= + CSLog (LPCTSTR keyname, + LPCTSTR valuename) { + char filename[MAX_PATH] = ""; + SRegLoadString(keyname,valuename,0,filename,MAX_PATH); +#ifdef _DEBUG + SRegSaveString(keyname,valuename,0,filename); +#endif + if (filename[0]) + SLogCreate(filename,0,&m_handle); + } + + //======================================================================= + ~CSLog () { + SLogClose(m_handle); + } + + //======================================================================= + void Dump (LPCVOID data, + DWORD bytes) { + SLogDump(m_handle, + data, + bytes); + } + + //======================================================================= + void Flush () { + SLogFlush(m_handle); + } + + //======================================================================= + HSLOG GetHandle () { + return m_handle; + } + + //======================================================================= + void Pend (LPCSTR string) { + SLogPend(m_handle, + string); + } + + //======================================================================= + void Write (LPCSTR string) { + SLogWrite(m_handle, + string); + } + +}; + + +/**************************************************************************** +* +* CSRgn +* +***/ + +class CSRgn { + + private: + HSRGN m_handle; + + //======================================================================= + void CopyConstructor (const CSRgn & source) { + SRgnDuplicate(source.m_handle, + &m_handle); + } + + public: + + //======================================================================= + CSRgn () { + SRgnCreate(&m_handle); + } + + //======================================================================= + CSRgn (const CSRgn & source) { + CopyConstructor(source); + } + + //======================================================================= + ~CSRgn () { + SRgnDelete(m_handle); + } + + //======================================================================= + CSRgn & operator= (const CSRgn &source) { + if (this != &source) { + this->~CSRgn(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + void AddParam (LPCRECT rect, + LPVOID param) { + SRgnAddParam(m_handle, + rect, + param); + } + + //======================================================================= + void AddRect (LPCRECT rect, + LPVOID param) { + SRgnAddRect(m_handle, + rect, + param); + } + + //======================================================================= + void Clear () { + SRgnClear(m_handle); + } + + //======================================================================= + void CombineRect (LPCRECT rect, + LPVOID param, + int combinemode) { + SRgnCombineRect(m_handle, + rect, + param, + combinemode); + } + + //======================================================================= + void GetBoundingRect (LPRECT rect) { + SRgnGetBoundingRect(m_handle, + rect); + } + + //======================================================================= + void GetRects (DWORD *numrects, + LPRECT buffer) { + SRgnGetRects(m_handle, + numrects, + buffer); + } + + //======================================================================= + void GetRectParams (LPCRECT rect, + DWORD *numparams, + LPVOID *buffer) { + SRgnGetRectParams(m_handle, + rect, + numparams, + buffer); + } + +}; + + +//#########################################################################// +//#########################################################################// +// // +// // +// UTILITY CLASSES AND TEMPLATES // +// // +// // +//#########################################################################// +//#########################################################################// + + +/**************************************************************************** +* +* CCritSect -- Critical section class +* +* Methods: +* +* void Enter () +* void Leave () +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void Enter () { EnterCriticalSection(&m_critsect); } + void Enter (BOOL) { EnterCriticalSection(&m_critsect); } + void Leave () { LeaveCriticalSection(&m_critsect); } + void Leave (BOOL) { LeaveCriticalSection(&m_critsect); } +}; + + +/**************************************************************************** +* +* CLock -- Reader/writer lock class +* +* Methods: +* +* void Enter (BOOL forwriting) +* void Leave (BOOL fromwriting) +* +***/ + +class CLock { + + private: + + HANDLE m_mutexevent; + HANDLE m_readerevent; + LONG m_readercount; + + public: + + //======================================================================= + CLock () { + m_mutexevent = CreateEvent(NULL,FALSE,TRUE,NULL); + m_readerevent = CreateEvent(NULL,TRUE,FALSE,NULL); + m_readercount = -1; + } + + //======================================================================= + ~CLock () { + CloseHandle(m_readerevent); + CloseHandle(m_mutexevent); + } + + //======================================================================= + void Enter (BOOL forwriting) { + if (forwriting) + WaitForSingleObject(m_mutexevent,INFINITE); + else if (!InterlockedIncrement(&m_readercount)) { + WaitForSingleObject(m_mutexevent,INFINITE); + SetEvent(m_readerevent); + } + else + WaitForSingleObject(m_readerevent,INFINITE); + } + + //======================================================================= + void Leave (BOOL fromwriting) { + if (fromwriting) + SetEvent(m_mutexevent); + else if (InterlockedDecrement(&m_readercount) < 0) { + ResetEvent(m_readerevent); + SetEvent(m_mutexevent); + } + } + +}; + + +/**************************************************************************** +* +* CNullSync -- Null synchronization class +* +* (used for templates that take a synchronization class as a parameter) +* +***/ + +class CNullSync { + public: + void Enter (BOOL) { } + void Leave (BOOL) { } +}; + + +/**************************************************************************** +* +* type_info +* +* (used by templates to obtain the name of an object) +* +***/ + +#ifdef _MSC_VER + #ifdef _INC_TYPEINFO + #define INTERNALRAWNAME raw_name + #else + #define INTERNALRAWNAME internal_raw_name + class type_info { + public: + virtual ~type_info (); + const char * internal_raw_name () const { return _m_d_name; }; + private: + void *_m_data; + char _m_d_name[1]; + type_info (const type_info& rhs); + type_info& operator= (const type_info& rhs); + }; + #endif +#else + #if defined(MAC) && !defined(__typeinfo__) + #include + #endif + #define INTERNALRAWNAME name +#endif + + +/**************************************************************************** +* +* ARRAY -- Dynamically allocated array template +* +* Types: +* +* ARRAY(structname) -- dynamically sized array of struct +* +* Pointers to types: +* +* ARRAYPTR(structname) +* +* Array methods: +* +* void AddDiscontiguousElements (DWORD count, +* int stride, +* const *newelements); +* void AddElement (const *newelement); +* void AddElements (DWORD count, +* const *newelements); +* DWORD NumElements (); +* * NewElement (); +* * Ptr (); +* void ReserveSpace (DWORD count); +* void SetNumElements (DWORD totalcount); +* +***/ + +template +class TSArray { + + private: + DWORD m_allocchunksize; + T *m_data; + DWORD m_elements; + DWORD m_elementsalloc; + + //======================================================================= + BOOL CheckSpace (DWORD count) { + return (m_elements+count <= m_elementsalloc); + } + + //======================================================================= + void Constructor () { + m_allocchunksize = max(16,256/sizeof(T)); + m_data = NULL; + m_elements = 0; + m_elementsalloc = 0; + } + + //======================================================================= + void CopyConstructor (const TSArray & source) { + Constructor(); + m_allocchunksize = source.m_allocchunksize; + ReserveSpace(source.m_elementsalloc); + AddElements(source.m_elements, + source.m_data); + } + + public: + + //======================================================================= + TSArray () { + Constructor(); + } + + //======================================================================= + TSArray (const TSArray & source) { + CopyConstructor(source); + } + + //======================================================================= + ~TSArray () { + if (m_data) { + while (m_elements) { + --m_elements; + m_data[m_elements].~T(); + } + SMemFree(m_data,__FILE__,__LINE__,0); + m_data = NULL; + } + } + + //======================================================================= + TSArray & operator= (const TSArray &source) { + if (this != &source) { + this->~TSArray(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + T & operator[] (DWORD num) { + if (num >= m_elements) + SErrDisplayError(STORM_ERROR_ACCESS_OUT_OF_BOUNDS, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + NULL, + TRUE); + return m_data[num]; + } + + //======================================================================= + void AddDiscontiguousElements (DWORD count, + int stride, + const T *newelements) { + if (!CheckSpace(count)) + ReserveSpace(count); + if (stride == sizeof(T)) + AddElements(count,newelements); + else + for (DWORD loop = 0; loop < count; ++loop) { + new(m_data+m_elements++) T(*newelements); + newelements = (const T *)((LPBYTE)newelements+stride); + } + } + + //======================================================================= + void AddElement (const T *newelement) { + if (!CheckSpace(1)) + ReserveSpace(1); + new(m_data+m_elements++) T(*newelement); + } + + //======================================================================= + void AddElements (DWORD count, + const T *newelements) { + if (!CheckSpace(count)) + ReserveSpace(count); + for (DWORD loop = 0; loop < count; ++loop) + new(m_data+m_elements++) T(newelements[loop]); + } + + //======================================================================= + DWORD NumElements () { + return m_elements; + } + + //======================================================================= + T * NewElement () { + if (!CheckSpace(1)) + ReserveSpace(1); + return new(m_data+m_elements++) T; + } + + //======================================================================= + T * Ptr () { + if (!m_data) + ReserveSpace(1); + return m_data; + } + + //======================================================================= + void ReserveSpace (DWORD count) { + if (CheckSpace(count)) + return; + + // DETERMINE THE NUMBER OF NEW ELEMENTS TO ALLOCATE + DWORD newelements = m_elements+count; + DWORD partialchunk = newelements & (m_allocchunksize-1); + if (partialchunk) + newelements += m_allocchunksize-partialchunk; + + // ALLOCATE THE NEW ARRAY AND COPY DATA FROM THE OLD ARRAY + T *newdata = (T *)ALLOC(newelements*sizeof(T)); + if (m_data) { + for (DWORD loop = 0; loop < m_elements; ++loop) + new(newdata+loop) T(m_data[loop]); + FREE(m_data); + } + m_data = newdata; + m_elementsalloc = newelements; + + } + + //======================================================================= + void SetNumElements (DWORD totalcount) { + if (totalcount > m_elements) { + ReserveSpace(totalcount-m_elements); + for (DWORD loop = m_elements; loop < totalcount; ++loop) + new(m_data+loop) T; + } + else if (totalcount < m_elements) { + for (DWORD loop = totalcount; loop < m_elements; ++loop) + m_data[loop].~T(); + } + m_elements = totalcount; + } + +}; + +#define ARRAY(structname) TSArray< structname > +#define ARRAYDECL(structname,varname) TSArray< structname > varname +#define ARRAYPTR(structname) TSArray< structname > * + + +/**************************************************************************** +* +* NODE/LIST -- Linked list template +* +* Types: +* +* LINKEX(structname) -- explicit link field +* LIST(structname) -- linked list of implicitly linked nodes +* LISTEX(structname,linkname) -- linked list of explicitly linked nodes +* LISTEXDYN(structname) -- linked list of explicitly linked nodes, +* where the link field to be used by +* this list is not known at compile time +* NODEDECL(structname) -- implicitly linked node +* NODEDECLEX(structname) -- explicitly linked node (must contain one +* or more LINKEX fields) +* +* Pointers to types: +* +* LISTPTR(structname) +* LISTPTREX(structname) +* +* Link methods: +* +* * Next (); +* * Prev (); +* void Unlink (); +* +* Explicitly linked node methods: +* +* None. Use link methods for the link you want to manipulate. +* +* Implicitly linked node methods: +* +* * Next (); +* * Prev (); +* void Unlink (); +* +* List methods: +* +* void Clear (); +* * DeleteNode ( *ptr); +* * Head () const; +* BOOL IsEmpty () const; +* void LinkNode ( *ptr, +* DWORD linktype = LIST_TAIL, +* *existingptr = NULL); +* * NewNode (DWORD location = LIST_TAIL, +* DWORD extrabytes = 0, +* DWORD flags = 0); +* * Next (const *ptr) const; +* * Prev (const *ptr) const; +* * Tail () const; +* void UnlinkAll (); +* void UnlinkNode ( *ptr); +* +* Constants for use with LinkNode() and NewNode(): +* +* LIST_UNLINKED +* LIST_LINK_AFTER +* LIST_LINK_BEFORE +* LIST_HEAD +* LIST_TAIL +* +* Macros: +* +* LISTEXSETLINK(structname,listname,linkname) +* ITERATELIST(structname,listname,ptrname) +* ITERATELISTPTR(structname,listname,ptrname) +* ITERATEPARTIALLIST(structname,listname,start,ptrname) +* ITERATEPARTIALLISTPTR(structname,listname,start,ptrname) +* ITERATELISTREVERSE(structname,listname,ptrname) +* ITERATELISTREVERSEPTR(structname,listname,ptrname) +* ITERATEPARTIALLISTREVERSE(structname,listname,start,ptrname) +* ITERATEPARTIALLISTREVERSEPTR(structname,listname,start,ptrname) +* ITERATE_DELETE +* ITERATE_DELETEANDBREAK +* +***/ + +#define LIST_UNLINKED 0 +#define LIST_LINK_AFTER 1 +#define LIST_LINK_BEFORE 2 +#define LIST_HEAD LIST_LINK_AFTER +#define LIST_TAIL LIST_LINK_BEFORE + +template +class TSList; + +template +class TSLink { + friend class TSList; + friend class TSList; + + private: + TSLink *m_prevlink; + T *m_next; + + //======================================================================= + void Constructor () { + m_prevlink = NULL; + m_next = NULL; + } + + //======================================================================= + void CopyConstructor (const TSLink &) { + Constructor(); + } + + //======================================================================= + TSLink *NextLink () const { + + // IF THE NEXT NODE IS A TERMINATOR, ITS LINK POINTER IS THE SAME AS + // ITS NODE POINTER. + if ((int)m_next < 0) + return (TSLink *)~(DWORD)m_next; + + // OTHERWISE, COMPUTE THE LINK ADDRESS BY USING THE OFFSET OF THIS + // NODE'S LINK AND POINTER ADDRESSES. (THIS NODE MUST NOT BE A + // TERMINATOR.) + else { + DWORD linkoffset = (DWORD)this-(DWORD)(m_prevlink->m_next); + return (TSLink *)(linkoffset+(DWORD)m_next); + } + + } + + protected: + + //======================================================================= + T *NextThroughTerminator () const { + return ((int)m_next > 0) ? m_next : (T *)~(DWORD)m_next; + } + + public: + + //======================================================================= + TSLink () { + Constructor(); + } + + //======================================================================= + TSLink (const TSLink & source) { + CopyConstructor(source); + } + + //======================================================================= + ~TSLink () { + Unlink(); + } + + //======================================================================= + TSLink & operator= (const TSLink &) { + // LEAVE THE DESTINATION NODE LINKED INTO ITS CURRENT LIST + return *this; + } + + //======================================================================= + T * Next () const { + return ((int)m_next > 0) ? m_next : NULL; + } + + //======================================================================= + T * Prev () const { + return m_prevlink->m_prevlink->Next(); + } + + //======================================================================= + void Unlink () { + if (!m_prevlink) + return; + NextLink()->m_prevlink = m_prevlink; + m_prevlink->m_next = m_next; + m_prevlink = NULL; + m_next = NULL; + } + +}; + +template +class TSBaseNode { + public: + + //======================================================================= + inline void * __cdecl operator new (size_t bytes, + size_t extra, + DWORD flags) { + void *ptr = SMemAlloc(bytes+extra, + typeid(T).INTERNALRAWNAME(), + SERR_LINECODE_OBJECT, + flags | SMEM_FLAG_ZEROMEMORY); + return ptr; + } + +}; + +template +class TSExplicitNode : public TSBaseNode { + friend class TSList; + + private: + + //======================================================================= + TSLink *Link (BOOL explicitlink, int linkoffset) const { + ASSERT(explicitlink); + explicitlink; + return (TSLink *)((LPBYTE)this+linkoffset); + } + +}; + +template +class TSLinkedNode : public TSBaseNode { + friend class TSList; + + private: + TSLink m_link; + + //======================================================================= + TSLink *Link (BOOL explicitlink, int linkoffset) const { + if (explicitlink) + return (TSLink *)((LPBYTE)this+linkoffset); + else + return (TSLink *)&m_link; + } + + public: + + //======================================================================= + ~TSLinkedNode () { + Unlink(); + } + + //======================================================================= + T * Next () const { + return m_link.Next(); + } + + //======================================================================= + T * Prev () const { + return m_link.Prev(); + } + + //======================================================================= + void Unlink () { + m_link.Unlink(); + } + +}; + +template +class TSList { + + private: + int m_linkoffset; + TSLink m_terminator; + + //======================================================================= + void Constructor () { + m_linkoffset = 0; + InitializeTerminator(); + } + + //======================================================================= + void CopyConstructor (const TSList & source) { + m_linkoffset = source.m_linkoffset; + InitializeTerminator(); + } + + //======================================================================= + void InitializeTerminator () { + m_terminator.m_prevlink = &m_terminator; + m_terminator.m_next = (T *)~(DWORD)&m_terminator; + } + + //======================================================================= + TSLink *Link (const T *ptr) const { + // THIS FUNCTION CALLS THE LINK METHOD IN EITHER THE NODE OR THE LINK + // TO WHICH THIS LIST REFERS. IF THIS FUNCTION WON'T COMPILE, IT'S + // BECAUSE A NODE WITH EXPLICIT LINKS WAS DEFINED WITH NODEDECL() + // INSTEAD OF NODEDECLEX(). + return ptr->Link(explicitlink,m_linkoffset); + } + + protected: + + //======================================================================= + void SetLinkOffset (int linkoffset) { + m_linkoffset = linkoffset; + InitializeTerminator(); + } + + public: + + //======================================================================= + TSList () { + Constructor(); + }; + + //======================================================================= + TSList (const TSList &source) { + CopyConstructor(source); + }; + + //======================================================================= + TSList (int linkoffset) { + m_linkoffset = linkoffset; + InitializeTerminator(); + }; + + //======================================================================= + ~TSList () { + UnlinkAll(); + } + + //======================================================================= + TSList & operator= (const TSList &source) { + if (this != &source) { + this->~TSList(); + CopyConstructor(source); + } + return *this; + } + + //======================================================================= + void ChangeLinkOffset (int linkoffset) { + UnlinkAll(); + SetLinkOffset(linkoffset); + } + + //======================================================================= + void Clear () { + T *curr; + while ((curr = Head()) != NULL) + delete curr; + } + + //======================================================================= + T * DeleteNode (T *ptr) { + T *nextptr = Next(ptr); + delete ptr; + return nextptr; + } + + //======================================================================= + T * Head () const { + return m_terminator.Next(); + } + + //======================================================================= + BOOL IsEmpty () const { + return !m_terminator.Next(); + } + + //======================================================================= + T * Iterate_RawNext (const T *ptr) const { + return Link(ptr)->m_next; + } + + //======================================================================= + void LinkNode (T *ptr, + DWORD linktype = LIST_TAIL, + T *existingptr = NULL) { + TSLink *link = Link(ptr); + + // IF THIS NODE IS ALREADY LINKED INTO THE LIST, UNLINK IT + if (link->m_prevlink) + link->Unlink(); + + // FIND THE NODE THAT WE WILL LINK BEFORE OR AFTER. USE THE + // TERMINATOR NODE IF WE'RE LINKING ONTO THE HEAD OR TAIL. + TSLink *existinglink; + if (existingptr) + existinglink = Link(existingptr); + else + existinglink = &m_terminator; + + // LINK THIS NODE INTO THE LIST + switch (linktype) { + + case LIST_LINK_AFTER: + { + link->m_prevlink = existinglink; + link->m_next = existinglink->m_next; + Link(existinglink->NextThroughTerminator())->m_prevlink = link; + existinglink->m_next = ptr; + } + break; + + case LIST_LINK_BEFORE: + { + TSLink *prevlink = existinglink->m_prevlink; + link->m_prevlink = prevlink; + link->m_next = prevlink->m_next; + prevlink->m_next = ptr; + existinglink->m_prevlink = link; + } + break; + + } + } + + //======================================================================= + T * NewNode (DWORD location = LIST_TAIL, + DWORD extrabytes = 0, + DWORD flags = 0) { + T *ptr = new(extrabytes,flags) T; + if (location != LIST_UNLINKED) + LinkNode(ptr,location); + return ptr; + } + + //======================================================================= + T * Next (const T *ptr) const { + return Link(ptr)->Next(); + } + + //======================================================================= + T * Prev (const T *ptr) const { + return Link(ptr)->Prev(); + } + + //======================================================================= + T * Tail () const { + return m_terminator.Prev(); + } + + //======================================================================= + void UnlinkAll () { + T *curr; + while ((curr = Head()) != NULL) + UnlinkNode(curr); + } + + //======================================================================= + void UnlinkNode (T *ptr) { + Link(ptr)->Unlink(); + } + +}; + +template +class TSExplicitList : public TSList { + public: + + //======================================================================= + TSExplicitList () { + SetLinkOffset(linkoffset); + } + +}; + + +#define LINKEX(structname) TSLink< structname > +#define LINKDECLEX(structname,varname) TSLink< structname > varname +#define LIST(structname) TSList< structname ,FALSE> +#define LISTDECL(structname,varname) TSList< structname ,FALSE> varname +#define LISTPTR(structname) TSList< structname ,FALSE> * +#define LISTPTREX(structname) TSList< structname ,TRUE> * +#define NODEDECL(structname) typedef struct structname : public TSLinkedNode< structname > +#define NODEDECLEX(structname) typedef struct structname : public TSExplicitNode< structname > + +#define LISTEX(structname,linkname) \ + TSExplicitList< structname ,(int)&(((structname *)0)->linkname)> + +#define LISTEXDYN(structname) \ + TSExplicitList< structname ,(int)0xDDDDDDDD> + +#define LISTEXSETLINK(structname,listname,linkname) \ + listname.ChangeLinkOffset((int)&(((structname *)0)->linkname)); + +#define LISTDECLEX(structname,linkname,varname) \ + TSExplicitList< structname ,(int)&(((structname *)0)->linkname)> varname + +#define ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,op) \ + for (structname *ptrname = start, \ + *iterate_delete = NULL; \ + (int)ptrname > 0; \ + iterate_delete \ + ? (ptrname = (listname)##op##DeleteNode(ptrname), \ + ptrname = ((int)iterate_delete > 0) ? ptrname : NULL, \ + iterate_delete = NULL, \ + ptrname) \ + : ptrname = (listname)##op##Iterate_RawNext(ptrname)) + +#define ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,op) \ + for (structname *ptrname = start, \ + *iterate_delete = NULL, \ + *iterate_delete_temp = NULL; \ + ptrname; \ + iterate_delete \ + ? (iterate_delete_temp = ((int)iterate_delete > 0) \ + ? (listname)##op##Prev(ptrname) \ + : NULL, \ + (listname)##op##DeleteNode(ptrname), \ + iterate_delete = NULL, \ + ptrname = iterate_delete_temp) \ + : ptrname = (listname)##op##Prev(ptrname)) + +#define ITERATELIST(structname,listname,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,(listname).Head(),ptrname,.) + +#define ITERATELISTPTR(structname,listname,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,(listname)->Head(),ptrname,->) + +#define ITERATEPARTIALLIST(structname,listname,start,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,.) + +#define ITERATEPARTIALLISTPTR(structname,listname,start,ptrname) \ + ITERATEFORWARDTEMPLATE(structname,listname,start,ptrname,->) + +#define ITERATELISTREVERSE(structname,listname,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,(listname).Tail(),ptrname,.) + +#define ITERATELISTREVERSEPTR(structname,listname,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,(listname)->Tail(),ptrname,->) + +#define ITERATEPARTIALLISTREVERSE(structname,listname,start,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,.) + +#define ITERATEPARTIALLISTREVERSEPTR(structname,listname,start,ptrname) \ + ITERATEREVERSETEMPLATE(structname,listname,start,ptrname,->) + +#define ITERATE_DELETE \ + { \ + ++iterate_delete; \ + continue; \ + } + +#define ITERATE_DELETEANDBREAK \ + { \ + --iterate_delete; \ + continue; \ + } + + +/**************************************************************************** +* +* EXPORTOBJECT/EXPORTTABLE -- Export manager template +* +* Types: +* +* DECLARE_STRICT_HANDLE(handle) -- handle to object +* DECLARE_STRICT_HANDLE(lockedhandle) -- handle to locked object +* EXPORTOBJECTDECL(structname) -- object to be exported +* EXPORTTABLE(structname,handlename,lockedhandlename,synctype) +* EXPORTTABLEREUSE(structname,handlename,lockedhandlename,synctype) +* +* Export table methods: +* +* void Delete ( handle); +* void DeleteUnlock ( *ptr, +* lockedhandle); +* void Destroy (); +* * Lock ( handle, +* *lockedhandle, +* BOOL forwriting = FALSE); +* void New ( *handle); +* * NewLock ( *handle, +* *lockedhandle); +* void Unlock ( lockedhandle); +* +* Synchronization types for use with EXPORTTABLE(): +* +* SYNC_NONE -- use no synchronization +* SYNC_READWRITE -- use a reader/writer lock +* SYNC_ALWAYS -- use a critical section +* +***/ + +template +class TSExportTableBase { + + protected: + + //======================================================================= + T * BaseFindByHandle (LISTPTREX(T) list, unsigned handle) { + ITERATELISTPTR(T,list,curr) + if (curr->m_handle == handle) + return curr; + return NULL; + } + + //======================================================================= + T * BaseFindByHandleEx (LISTPTREX(T) list, unsigned handle, unsigned *count) { + *count = 0; + ITERATELISTPTR(T,list,curr) + if (curr->m_handle == handle) + return curr; + else + ++*count; + return NULL; + } + + //======================================================================= + unsigned BaseGetHandle (const T *ptr) { + return ptr->m_handle; + } + + //======================================================================= + int BaseGetLinkOffset () { + return (int)&(((T *)0)->m_linktoslot); + } + + //======================================================================= + void BaseSetHandle (T *ptr, unsigned handle) { + ptr->m_handle = handle; + } + +}; + +template +class TSExportTable : public TSExportTableBase { + + private: + ARRAY(LISTEXDYN(T)) m_listarray; + LISTEXDYN(T) m_reuselist; + H m_sequence; + unsigned m_slotmask; + SYNC m_sync; + + //======================================================================= + unsigned ComputeSlot (H handle) { + return (unsigned)handle & m_slotmask; + } + + //======================================================================= + H GenerateUniqueHandle () { + unsigned count; + for (;;) { + m_sequence = (H)((unsigned)m_sequence+1); + if (!BaseFindByHandleEx(&m_listarray[ComputeSlot(m_sequence)], + (unsigned)m_sequence, + &count)) + break; + } + if (count >= 4) + GrowListArray(); + return m_sequence; + } + + //======================================================================= + void GrowListArray () { +return; // note: out for testing + if (m_slotmask >= 1023) + return; + + // DETERMINE THE NEW ARRAY SIZE + unsigned oldarraysize = m_slotmask+1; + unsigned newarraysize = oldarraysize*2; + + // GROW THE ARRAY + { + m_listarray.SetNumElements(newarraysize); + int linkoffset = BaseGetLinkOffset(); + for (unsigned slot = oldarraysize; slot < newarraysize; ++slot) + m_listarray[slot].ChangeLinkOffset(linkoffset); + } + + // MOVE ALL RECORDS FROM THE OLD LISTS TO THE NEW LISTS + m_slotmask = newarraysize-1; + { + for (unsigned slot = 0; slot < oldarraysize; ++slot) { + T *currptr = m_listarray[slot].Head(); + while (currptr) { + T *nextptr = m_listarray[slot].Next(currptr); + unsigned newslot = ComputeSlot((H)BaseGetHandle(currptr)); + if (newslot != slot) { + m_listarray[slot].UnlinkNode(currptr); + m_listarray[newslot].LinkNode(currptr); + } + currptr = nextptr; + } + } + } + + } + + //======================================================================= + BOOL IsForWriting (LH lockedhandle) { + return (lockedhandle == (LH)1); + } + + //======================================================================= + void SyncEnterLock (LH *lockedhandle, BOOL forwriting) { + m_sync.Enter(forwriting); + *lockedhandle = (LH)(forwriting ? 1 : -1); + } + + //======================================================================= + void SyncLeaveLock (LH lockedhandle) { + if (lockedhandle) + m_sync.Leave(IsForWriting(lockedhandle)); + } + + public: + + //======================================================================= + TSExportTable () { + m_sequence = (H)0; + m_slotmask = 3; + m_listarray.SetNumElements(m_slotmask+1); + int linkoffset = BaseGetLinkOffset(); + for (unsigned slot = 0; slot <= m_slotmask; ++slot) + m_listarray[slot].ChangeLinkOffset(linkoffset); + m_reuselist.ChangeLinkOffset(linkoffset); + } + + //======================================================================= + ~TSExportTable () { + Destroy(); + } + + //======================================================================= + void Delete (H handle) { + LH lockedhandle; + T *ptr = Lock(handle,&lockedhandle,TRUE); + DeleteUnlock(ptr,lockedhandle); + } + + //======================================================================= + void DeleteUnlock (T *ptr, + LH lockedhandle) { + if (ptr) + if (REUSE) + m_reuselist.LinkNode(ptr); + else + delete ptr; + Unlock(lockedhandle); + } + + //======================================================================= + void Destroy () { + LH lockedhandle; + SyncEnterLock(&lockedhandle,TRUE); + for (unsigned slot = 0; slot <= m_slotmask; ++slot) { + T *curr; + while ((curr = m_listarray[slot].Head()) != NULL) { + delete curr; + SErrReportResourceLeak(typeid(H).INTERNALRAWNAME()); + } + } + m_reuselist.Clear(); + SyncLeaveLock(lockedhandle); + } + + //======================================================================= + T * Lock (H handle, + LH *lockedhandle, + BOOL forwriting = FALSE) { + SyncEnterLock(lockedhandle,forwriting); + T *result = BaseFindByHandle(&m_listarray[ComputeSlot(handle)], + (unsigned)handle); + if (!result) { + SyncLeaveLock(*lockedhandle); + *lockedhandle = (LH)0; + } + return result; + } + + //======================================================================= + void New (H *handle) { + LH lockedhandle; + NewLock(handle,&lockedhandle); + Unlock(lockedhandle); + } + + //======================================================================= + T * NewLock (H *handle, LH *lockedhandle) { + SyncEnterLock(lockedhandle,TRUE); + H newhandle = GenerateUniqueHandle(); + T *ptr = NULL; + if (REUSE) { + ptr = m_reuselist.Head(); + if (ptr) + m_listarray[ComputeSlot(newhandle)].LinkNode(ptr); + } + if (!ptr) + ptr = m_listarray[ComputeSlot(newhandle)].NewNode(); + BaseSetHandle(ptr,(unsigned)newhandle); + *handle = newhandle; + return ptr; + } + + //======================================================================= + void Unlock (LH lockedhandle) { + SyncLeaveLock(lockedhandle); + } + +}; + +template +class TSExportObject : public TSExplicitNode { + friend class TSExportTableBase; + + private: + unsigned m_handle; + LINKEX(T) m_linktoslot; + + public: + + //======================================================================= + TSExportObject () { + } + + //======================================================================= + TSExportObject (const TSExportObject &source) { + } + + //======================================================================= + TSExportObject & operator= (const TSExportObject &source) { + // COPY THE OBJECT DATA, BUT DON'T OVERWRITE THE DESTINATION OBJECT'S + // HANDLE OR LINK + return *this; + } + +}; + +#define SYNC_NONE CNullSync +#define SYNC_READWRITE CLock +#define SYNC_ALWAYS CCritSect + +#define EXPORTOBJECTDECL(structname) \ + typedef struct structname : public TSExportObject< structname > + +#define EXPORTTABLE(structname,handlename,lockedhandlename,synctype) \ + TSExportTable + +#define EXPORTTABLEREUSE(structname,handlename,lockedhandlename,synctype) \ + TSExportTable + + +/**************************************************************************** +* +* SWAP -- Swap template +* +* Macros: +* +* SWAP(a,b) +* +***/ + +//=========================================================================== +template +void inline TSSwap (T &a, T &b) { + T temp = a; + a = b; + b = temp; +} +#define SWAP(a,b) TSSwap(a,b) + + +/**************************************************************************** +* +* Old TList Template -- Obsolete!! +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return FALSE; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return FALSE; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return TRUE; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return FALSE; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return FALSE; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return TRUE; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return FALSE; + + ptr->next = *head; + *head = ptr; + return TRUE; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return FALSE; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return TRUE; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return FALSE; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber,0); + *head = next; + } + return TRUE; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return FALSE; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber,0); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return FALSE; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + + +#if PRAGMA_IMPORT_SUPPORTED +#pragma import off +#endif + +#endif // ifndef _STORM_H_ diff --git a/src/Uisrc/OLD/STORM.H b/src/Uisrc/OLD/STORM.H new file mode 100644 index 0000000..0561112 --- /dev/null +++ b/src/Uisrc/OLD/STORM.H @@ -0,0 +1,1342 @@ +#ifndef _STORM_H_ +#define _STORM_H_ + +/**************************************************************************** +* +* BitBlt functions +* +***/ + +extern "C" BOOL APIENTRY SBltDestroy (); +extern "C" BOOL APIENTRY SBltGetSCode (DWORD rop3, + LPSTR buffer, + DWORD buffersize, + BOOL optimize = 1); +extern "C" BOOL APIENTRY SBltROP3 (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Clipped (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Tiled (LPBYTE dest, + LPRECT destrect, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3); + +/**************************************************************************** +* +* Bitmap functions +* +***/ + +#define SBMP_IMAGETYPE_BMP 1 +#define SBMP_IMAGETYPE_PCX 2 + +extern "C" BOOL APIENTRY SBmpDecodeImage (DWORD imagetype, + LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width, + int *height, + int *bitdepth); +extern "C" BOOL APIENTRY SBmpDestroy (); +extern "C" BOOL APIENTRY SBmpLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpSaveImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height, + int bitdepth); + +/**************************************************************************** +* +* S-Code functions +* +***/ + +#define SCODE_CF_AUTOALIGNDWORD 0x00040000 +#define SCODE_CF_USESALTADJUSTS 0x04000000 + +typedef struct _HSCODESTREAM { int unused; } *HSCODESTREAM; + +typedef struct _SCODEEXECUTEDATA { + DWORD size; + DWORD flags; + int xiterations; + int yiterations; + int adjustdest; + int adjustsource; + LPVOID dest; + LPVOID source; + LPVOID table; + DWORD a; + DWORD b; + DWORD c; + int adjustdestalt; + int adjustsourcealt; + DWORD reserved[2]; +} SCODEEXECUTEDATA, *SCODEEXECUTEDATAPTR; + +extern "C" BOOL APIENTRY SCodeCompile (LPCSTR prologstring, + LPCSTR loopstring, + LPCSTR *firsterror, + DWORD maxiterations, + DWORD flags, + HSCODESTREAM *handle); +extern "C" BOOL APIENTRY SCodeDelete (HSCODESTREAM handle); +extern "C" BOOL APIENTRY SCodeDestroy (); +extern "C" BOOL APIENTRY SCodeExecute (HSCODESTREAM handle, + SCODEEXECUTEDATAPTR executedata); +extern "C" BOOL APIENTRY SCodeGetJumpTable (HSCODESTREAM handle, + LPBYTE **jumptableptr, + LPDWORD *prologpatchlocation, + LPDWORD *looppatchlocation, + LPDWORD *epilogpatchlocation); +extern "C" BOOL APIENTRY SCodeGetPseudocode (LPCSTR scodestring, + LPSTR buffer, + DWORD buffersize); + +/**************************************************************************** +* +* Dialog box functions +* +***/ + +#define SDLG_ADJUST_NONE 0 +#define SDLG_ADJUST_VERTICAL 1 +#define SDLG_ADJUST_CONTROLPOS 2 + +#define SDLG_DBF_TILE 0x00000001 +#define SDLG_DBF_VCENTER 0x00000002 + +#define SDLG_STYLE_ANY 0xFFFFFFFF +#define SDLG_STYLE_ANYPUSHBUTTON 0x00010001 + +#define SDLG_USAGE_BACKGROUND 0x00000001 +#define SDLG_USAGE_NORMAL_UNFOCUSED 0x00000010 +#define SDLG_USAGE_NORMAL_FOCUSED 0x00000020 +#define SDLG_USAGE_NORMAL (SDLG_USAGE_NORMAL_UNFOCUSED | SDLG_USAGE_NORMAL_FOCUSED) +#define SDLG_USAGE_SELECTED_UNFOCUSED 0x00000040 +#define SDLG_USAGE_SELECTED_FOCUSED 0x00000080 +#define SDLG_USAGE_SELECTED (SDLG_USAGE_SELECTED_UNFOCUSED | SDLG_USAGE_SELECTED_FOCUSED) +#define SDLG_USAGE_NORMAL_GRAYED 0x00000100 +#define SDLG_USAGE_SELECTED_GRAYED 0x00000400 +#define SDLG_USAGE_GRAYED (SDLG_USAGE_NORMAL_GRAYED | SDLG_USAGE_SELECTED_GRAYED) +#define SDLG_USAGE_CURSORMASK 0x00001000 +#define SDLG_USAGE_CURSORIMAGE 0x00002000 + +extern "C" HDC APIENTRY SDlgBeginPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgBltToWindow (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgCheckTimers (); +extern "C" HWND APIENTRY SDlgCreateDialogIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" HWND APIENTRY SDlgCreateDialogParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDefDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +extern "C" BOOL APIENTRY SDlgDestroy (); +extern "C" int APIENTRY SDlgDialogBoxIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" int APIENTRY SDlgDialogBoxParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDrawBitmap (HWND window, + DWORD usage, + HRGN region, + int offsetx = 0, + int offsety = 0, + LPRECT boundingoffset = NULL, + DWORD flags = 0); +extern "C" BOOL APIENTRY SDlgEndDialog (HWND window, + int result); +extern "C" BOOL APIENTRY SDlgEndPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgKillTimer (HWND window, + UINT event); +extern "C" BOOL APIENTRY SDlgSetBaseFont (int pointsize, + int weight, + DWORD flags, + DWORD family, + LPCTSTR face); +extern "C" BOOL APIENTRY SDlgSetBitmap (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetControlBitmaps (HWND parentwindow, + LPINT controllist, + LPDWORD usagelist, + LPBYTE bitmapbits, + LPSIZE bitmapsize, + DWORD adjusttype, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetCursor (HWND window, + HCURSOR cursor, + DWORD id, + HCURSOR *oldcursor); +extern "C" BOOL APIENTRY SDlgSetSystemCursor (LPBYTE maskbitmap, + LPBYTE imagebitmap, + LPSIZE size, + DWORD id = 32512); +extern "C" BOOL APIENTRY SDlgSetTimer (HWND window, + UINT event, + UINT elapse, + TIMERPROC timerfunc); +extern "C" BOOL APIENTRY SDlgUpdateCursor (); + +#define SDlgCreateDialog(ins,tpl,wnd,prc) SDlgCreateDialogParam(ins,tpl,wnd,prc,0) +#define SDlgCreateDialogIndirect(ins,tpl,wnd,prc) SDlgCreateDialogIndirectParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBox(ins,tpl,wnd,prc) SDlgDialogBoxParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBoxIndirect(ins,tpl,wnd,prc) SDlgDialogBoxIndirectParam(ins,tpl,wnd,prc,0) + +/**************************************************************************** +* +* DirectDraw functions +* +***/ + +#define SDRAW_SERVICE_BASIC 1 +#define SDRAW_SERVICE_PAGEFLIP 2 +#define SDRAW_SERVICE_DOUBLEBUFFER 3 +#define SDRAW_SERVICE_MAX 3 + +#define SDRAW_SURFACE_FRONT 0 +#define SDRAW_SURFACE_BACK 1 +#define SDRAW_SURFACE_SYSTEM 2 +#define SDRAW_SURFACE_TEMPORARY 3 + +extern "C" BOOL APIENTRY SDrawAutoInitialize (HINSTANCE instance, + LPCTSTR classname, + LPCTSTR title, + WNDPROC wndproc = NULL, + int servicelevel = SDRAW_SERVICE_BASIC, + int width = 640, + int height = 480, + int bitdepth = 8); +extern "C" BOOL APIENTRY SDrawCaptureScreen (LPCTSTR filename = NULL); +extern "C" BOOL APIENTRY SDrawClearSurface (int surfacenumber); +extern "C" BOOL APIENTRY SDrawDestroy (); +extern "C" BOOL APIENTRY SDrawFlipPage (); +extern "C" HWND APIENTRY SDrawGetFrameWindow (HWND *window = NULL); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawGetObjects (LPDIRECTDRAW *directdraw, + LPDIRECTDRAWSURFACE *frontbuffer, + LPDIRECTDRAWSURFACE *backbuffer, + LPDIRECTDRAWSURFACE *systembuffer, + LPDIRECTDRAWSURFACE *temporarybuffer, + LPDIRECTDRAWPALETTE *palette, + HPALETTE *gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawGetScreenSize (int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SDrawGetServiceLevel (int *servicelevel = NULL); +extern "C" BOOL APIENTRY SDrawLockSurface (int surfacenumber, + LPCRECT rect, + LPBYTE *ptr, + int *pitch = NULL, + DWORD flags = 0); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawManualInitialize (HWND framewindow, + LPDIRECTDRAW directdraw, + LPDIRECTDRAWSURFACE frontbuffer, + LPDIRECTDRAWSURFACE backbuffer, + LPDIRECTDRAWSURFACE systembuffer, + LPDIRECTDRAWSURFACE temporarybuffer, + LPDIRECTDRAWPALETTE palette, + HPALETTE gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawMessageBox (LPCTSTR text, + LPCTSTR title, + UINT flags); +extern "C" BOOL APIENTRY SDrawPostClose (); +extern "C" BOOL APIENTRY SDrawRealizePalette (); +extern "C" BOOL APIENTRY SDrawSelectGdiSurface (BOOL select, BOOL copy); +extern "C" BOOL APIENTRY SDrawUnlockSurface (int surfacenumber, + LPBYTE ptr, + DWORD numrects = 0, + LPCRECT rectarray = NULL); +extern "C" BOOL APIENTRY SDrawUpdatePalette (DWORD firstentry, + DWORD numentries, + LPPALETTEENTRY entries, + BOOL reservedentries = 0); +extern "C" BOOL APIENTRY SDrawUpdateScreen (LPCRECT rect); + +/**************************************************************************** +* +* Event dispatching functions +* +***/ + +typedef void (CALLBACK *SEVTHANDLER)(LPVOID); + +extern "C" BOOL APIENTRY SEvtDestroy (); +extern "C" BOOL APIENTRY SEvtDispatch (DWORD type, + DWORD subtype, + DWORD id, + LPVOID data); +extern "C" BOOL APIENTRY SEvtRegisterHandler (DWORD type, + DWORD subtype, + DWORD id, + DWORD flags, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterHandler (DWORD type, + DWORD subtype, + DWORD id, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterType (DWORD type, + DWORD subtype); + +/**************************************************************************** +* +* File I/O functions +* +***/ + +#define SFILE_AUTH_UNABLETOAUTHENTICATE 0 +#define SFILE_AUTH_NOSIGNATURE 1 +#define SFILE_AUTH_BADSIGNATURE 2 +#define SFILE_AUTH_UNKNOWNSIGNATURE 3 +#define SFILE_AUTH_FIRSTAUTHENTIC 5 +#define SFILE_AUTH_AUTHENTICBLIZZARD 5 + +#define SFILE_DDA_LOOP 0x00040000 + +#define SFILE_ERROR_BASE 0x21030000 +#define SFILE_ERROR_BAD_FORMAT ERROR_BAD_FORMAT +#define SFILE_ERROR_BAD_PATHNAME ERROR_BAD_PATHNAME +#define SFILE_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED +#define SFILE_ERROR_FILE_INVALID ERROR_FILE_INVALID +#define SFILE_ERROR_FILE_NOT_FOUND ERROR_FILE_NOT_FOUND +#define SFILE_ERROR_HANDLE_EOF ERROR_HANDLE_EOF +#define SFILE_ERROR_INVALID_DATA ERROR_INVALID_DATA +#define SFILE_ERROR_INVALID_DRIVE ERROR_INVALID_DRIVE +#define SFILE_ERROR_INVALID_HANDLE ERROR_INVALID_HANDLE +#define SFILE_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SFILE_ERROR_NOT_ARCHIVE (SFILE_ERROR_BASE+1) +#define SFILE_ERROR_NOT_AUTHENTICATED ERROR_NOT_AUTHENTICATED +#define SFILE_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SFILE_ERROR_NOT_IN_ARCHIVE (SFILE_ERROR_BASE+2) +#define SFILE_ERROR_NOT_PLAYING (SFILE_ERROR_BASE+3) + +#define SFILE_FIND_FILES 0x00000001 +#define SFILE_FIND_DIRECTORIES 0x00000002 + +typedef struct _HSARCHIVE { int unused; } *HSARCHIVE; +typedef struct _HSFILE { int unused; } *HSFILE; +typedef struct _HSFINDFILE { int unused; } *HSFINDFILE; + +extern "C" BOOL APIENTRY SFileAuthenticateArchive (HSARCHIVE archive, + DWORD *extendedresult); +extern "C" BOOL APIENTRY SFileCloseArchive (HSARCHIVE handle); +extern "C" BOOL APIENTRY SFileCloseFile (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaBegin (HSFILE handle, + DWORD buffersize, + DWORD flags); +extern "C" BOOL APIENTRY SFileDdaBeginEx (HSFILE handle, + DWORD buffersize, + DWORD flags, + DWORD offset, + LONG volume, + LONG pan, + LPVOID reserved); +extern "C" BOOL APIENTRY SFileDdaDestroy (); +extern "C" BOOL APIENTRY SFileDdaEnd (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaGetPos (HSFILE handle, + DWORD *position, + DWORD *maxposition); +extern "C" BOOL APIENTRY SFileDdaGetVolume (HSFILE handle, + LONG *volume, + LONG *pan); +#ifdef __DSOUND_INCLUDED__ +extern "C" BOOL APIENTRY SFileDdaInitialize (LPDIRECTSOUND directsound); +#endif +extern "C" BOOL APIENTRY SFileDdaSetVolume (HSFILE handle, + LONG volume, + LONG pan); +extern "C" BOOL APIENTRY SFileDestroy (); +extern "C" BOOL APIENTRY SFileEnableDirectAccess (BOOL enable); +extern "C" BOOL APIENTRY SFileGetFileArchive (HSFILE file, + HSARCHIVE *archive); +extern "C" DWORD APIENTRY SFileGetFileSize (HSFILE handle, + LPDWORD filesizehigh = NULL); +extern "C" BOOL APIENTRY SFileOpenArchive (LPCTSTR archivename, + int priority, + BOOL cdonly, + HSARCHIVE *handle); +extern "C" BOOL APIENTRY SFileOpenFile (LPCTSTR filename, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileEx (HSARCHIVE archivehandle, + LPCTSTR filename, + DWORD flags, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileWin32 (LPCTSTR filename, + HANDLE *handle); +extern "C" BOOL APIENTRY SFileReadFile (HSFILE handle, + LPVOID buffer, + DWORD bytestoread, + LPDWORD bytesread = NULL, + LPVOID reserved = NULL); +extern "C" BOOL APIENTRY SFileSetBasePath (LPCTSTR path); +extern "C" DWORD APIENTRY SFileSetFilePointer (HSFILE handle, + LONG distancetomove, + PLONG distancetomovehigh, + DWORD movemethod); +extern "C" BOOL APIENTRY SFileSetLocale (LCID lcid); + +/**************************************************************************** +* +* GDI functions +* +***/ + +#define ETO_TEXT_TRANSPARENT 0 +#define ETO_TEXT_COLOR 1 +#define ETO_TEXT_BLACK 2 +#define ETO_TEXT_WHITE 3 +#define ETO_BKG_TRANSPARENT 0 +#define ETO_BKG_COLOR 1 +#define ETO_BKG_BLACK 2 +#define ETO_BKG_WHITE 3 + +typedef struct _HSGDIOBJ { int unused; } *HSGDIOBJ; +typedef struct _HSGDIFONT : public _HSGDIOBJ { int unused; } *HSGDIFONT; + +extern "C" BOOL APIENTRY SGdiBitBlt (LPBYTE videobuffer, + int destx, + int desty, + LPBYTE sourcedata, + LPRECT sourcerect, + int sourcecx, + int sourcecy, + COLORREF color = 0, + DWORD rop = SRCCOPY); +extern "C" BOOL APIENTRY SGdiCreateFont (LPBYTE bits, + int width, + int height, + int bitdepth, + int filecharwidth, + int filecharheight, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiDeleteObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiDestroy (); +extern "C" BOOL APIENTRY SGdiExtTextOut (LPBYTE videobuffer, + int x, + int y, + LPRECT rect, + COLORREF color, + int textcoloruse, + int bkgcoloruse, + LPCTSTR string, + int chars = -1); +extern "C" BOOL APIENTRY SGdiImportFont (HFONT windowsfont, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiLoadFont (LPCTSTR filename, + int filecharwidth, + int filecharheight, + int basecharwidth, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiRectangle (LPBYTE videobuffer, + int left, + int top, + int right, + int bottom, + COLORREF color); +extern "C" BOOL APIENTRY SGdiSelectObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiSetPitch (int pitch); +extern "C" BOOL APIENTRY SGdiTextOut (LPBYTE videobuffer, + int x, + int y, + COLORREF color, + LPCTSTR string, + int chars = -1); + +/**************************************************************************** +* +* Memory allocation functions +* +***/ + +#define SMEM_FLAG_ZEROMEMORY 0x00000008 + +extern "C" LPVOID APIENTRY SMemAlloc (DWORD bytes, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" BOOL APIENTRY SMemDestroy (); +extern "C" BOOL APIENTRY SMemFree (LPVOID ptr, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" void APIENTRY SMemInitialize (); + +#define ALLOC(bytes) SMemAlloc(bytes,__FILE__,__LINE__,0) +#define ALLOCZERO(bytes) SMemAlloc(bytes,__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) +#define FREE(ptr) SMemFree(ptr,__FILE__,__LINE__,0) +#define NEW(struct) (struct *)SMemAlloc(sizeof(struct),__FILE__,__LINE__,0) +#define NEWZERO(struct) (struct *)SMemAlloc(sizeof(struct),__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) + +/**************************************************************************** +* +* Message functions +* +***/ + +typedef struct _PARAMS { + HWND window; + UINT message; + WPARAM wparam; + LPARAM lparam; + UINT notifycode; + LPVOID extra; + BOOL useresult; + LRESULT result; +} PARAMS, *PARAMSPTR, *LPPARAMS; + +typedef BOOL (CALLBACK *SMSGIDLEPROC)(DWORD); +typedef void (CALLBACK *SMSGHANDLER)(LPPARAMS); + +extern "C" BOOL APIENTRY SMsgDestroy (); +extern "C" BOOL APIENTRY SMsgDispatchMessage (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL *useresult, + LRESULT *result); +extern "C" BOOL APIENTRY SMsgDoMessageLoop (SMSGIDLEPROC idleproc = NULL, + BOOL cleanuponquit = 1); +extern "C" BOOL APIENTRY SMsgRegisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); + +/**************************************************************************** +* +* Networking functions +* +***/ + +#define SNET_ART_BACKGROUND 0 +#define SNET_ART_BUTTONTEXTURE 1 +#define SNET_ART_JOINBACKGROUND 2 +#define SNET_ART_HELPBACKGROUND 3 +#define SNET_ART_POPUPBACKGROUND 4 +#define SNET_ART_BUTTON_XSML 5 +#define SNET_ART_BUTTON_SML 6 +#define SNET_ART_BUTTON_MED 7 +#define SNET_ART_BUTTON_LRG 8 +#define SNET_ART_APP_LOGO_SML 9 +#define SNET_ART_PROGRESS_BACKGROUND 10 +#define SNET_ART_PROGRESS_FILLER 11 +#define SNET_ART_POPUPBACKGROUND_SML 12 +#define SNET_ART_SCROLLBARARROWS 13 +#define SNET_ART_SCROLLTHUMB 14 +#define SNET_ART_SCROLLBAR 15 + +#define SNET_AUTHTYPE_CHANNEL 1 +#define SNET_AUTHTYPE_GAME 2 + +#define SNET_BROADCASTNONLOCALPLAYERID 0xFFFFFFFE +#define SNET_BROADCASTPLAYERID 0xFFFFFFFF +#define SNET_INVALIDPLAYERID 0xFFFFFFFF + +#define SNET_CAPS_PAGELOCKEDBUFFERS 0x00000001 +#define SNET_CAPS_BASICINTERFACE 0x00000002 + +#define SNET_CF_ALLOWPRIVATEGAMES 0x00000001 + +#define SNET_DATA_SYSCOLORS 1 +#define SNET_DATA_CURSORLINK 2 +#define SNET_DATA_CURSORARROW 3 +#define SNET_DATA_CURSORIBEAM 4 + +#define SNET_DDF_INCLUDENAME 0x00000001 +#define SNET_DDF_MULTILINE 0x00000002 + +#define SNET_DDPF_BLIZZARD 0x00000001 +#define SNET_DDPF_MODERATOR 0x00000002 +#define SNET_DDPF_SPEAKER 0x00000004 +#define SNET_DDPF_SYSOP 0x00000008 +#define SNET_DDPF_SQUELCHED 0x00000020 + +#define SNET_DRAWTYPE_GAME 1 +#define SNET_DRAWTYPE_PLAYER 2 + +#define SNET_ERROR_BASE 0x21050000 +#define SNET_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS +#define SNET_ERROR_BAD_PROVIDER ERROR_BAD_PROVIDER +#define SNET_ERROR_CANCELLED ERROR_CANCELLED +#define SNET_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SNET_ERROR_INVALID_PLAYER (SNET_ERROR_BASE+1) +#define SNET_ERROR_GAME_ALREADY_STARTED (SNET_ERROR_BASE+2) +#define SNET_ERROR_GAME_FULL (SNET_ERROR_BASE+3) +#define SNET_ERROR_GAME_NOT_FOUND (SNET_ERROR_BASE+4) +#define SNET_ERROR_GAME_TERMINATED (SNET_ERROR_BASE+5) +#define SNET_ERROR_HOST_UNREACHABLE ERROR_HOST_UNREACHABLE +#define SNET_ERROR_MAX_THRDS_REACHED ERROR_MAX_THRDS_REACHED +#define SNET_ERROR_NETWORK_BUSY ERROR_NETWORK_BUSY +#define SNET_ERROR_NO_MESSAGES_WAITING (SNET_ERROR_BASE+6) +#define SNET_ERROR_NO_NETWORK ERROR_NO_NETWORK +#define SNET_ERROR_NOT_CONNECTED ERROR_NOT_CONNECTED +#define SNET_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SNET_ERROR_NOT_IMPLEMENTED (SNET_ERROR_BASE+7) +#define SNET_ERROR_NOT_IN_GAME (SNET_ERROR_BASE+8) +#define SNET_ERROR_NOT_OWNER ERROR_NOT_OWNER +#define SNET_ERROR_NOT_REGISTERED (SNET_ERROR_BASE+9) +#define SNET_ERROR_REQUIRES_UPGRADE (SNET_ERROR_BASE+10) +#define SNET_ERROR_STILL_ACTIVE (SNET_ERROR_BASE+11) +#define SNET_ERROR_TOO_MANY_NAMES ERROR_TOO_MANY_NAMES +#define SNET_ERROR_VERSION_MISMATCH (SNET_ERROR_BASE+12) + +#define SNET_EVENT_INITDATA 1 +#define SNET_EVENT_PLAYERJOIN 2 +#define SNET_EVENT_PLAYERLEAVE 3 +#define SNET_EVENT_SERVERMESSAGE 4 + +#define SNET_EXIT_AUTO_JOINING 0x00000001 +#define SNET_EXIT_AUTO_NEWGAME 0x00000002 +#define SNET_EXIT_AUTO_SHUTDOWN 0x00000003 +#define SNET_EXIT_PLAYERQUIT 0x40000001 +#define SNET_EXIT_PLAYERKILLED 0x40000002 +#define SNET_EXIT_PLAYERWON 0x40000004 +#define SNET_EXIT_GAMEOVER 0x40000005 +#define SNET_EXIT_NOTRESPONDING 0x40000006 + +#define SNET_GM_PRIVATE 0x00000001 +#define SNET_GM_FULL 0x00000002 +#define SNET_GM_ADVERTISED 0x00000004 + +#define SNET_INFO_GAMENAME 1 +#define SNET_INFO_GAMEPASSWORD 2 +#define SNET_INFO_GAMEDESCRIPTION 3 +#define SNET_INFO_GAMEMODE 4 +#define SNET_INFO_INITDATA 5 +#define SNET_INFO_MAXPLAYERS 6 + +#define SNET_LMT_EXPECTED 1 +#define SNET_LMT_CURRENT 2 +#define SNET_LMT_PEAK 4 + +#define SNET_PERFID_TURN 1 +#define SNET_PERFID_TURNSSENT 4 +#define SNET_PERFID_TURNSRECV 5 +#define SNET_PERFID_MSGSENT 6 +#define SNET_PERFID_MSGRECV 7 +#define SNET_PERFID_USERBYTESSENT 8 +#define SNET_PERFID_USERBYTESRECV 9 +#define SNET_PERFID_TOTALBYTESSENT 10 +#define SNET_PERFID_TOTALBYTESRECV 11 +#define SNET_PERFID_PKTSENTONWIRE 12 +#define SNET_PERFID_PKTRECVONWIRE 13 +#define SNET_PERFID_BYTESSENTONWIRE 14 +#define SNET_PERFID_BYTESRECVONWIRE 15 +#define SNET_PERFIDNUM 16 + +#define SNET_PERFTYPE_COUNTER 0x10410400 +#define SNET_PERFTYPE_RAWCOUNT 0x00010000 + +#define SNET_PSF_ACTIVE 0x00010000 +#define SNET_PSF_TURNAVAILABLE 0x00020000 +#define SNET_PSF_RESPONDING 0x00040000 + +#define SNET_SF_ALLOWCREATE 0x00000001 + +#define SNET_SND_CHANGEFOCUS 0 +#define SNET_SND_SELECTITEM 1 + +#define SNET_UPGRADE_FAILED -1 +#define SNET_UPGRADE_NOT_NEEDED 0 +#define SNET_UPGRADE_SUCCEEDED 1 +#define SNET_UPGRADING_TERMINATE 2 + +#define SNET_MAXNAMELENGTH 128 +#define SNET_MAXDESCLENGTH 128 + +typedef struct _SNETCAPS { + DWORD size; + DWORD flags; + DWORD maxmessagesize; + DWORD maxqueuesize; + DWORD maxplayers; + DWORD bytessec; + DWORD latencyms; + DWORD defaultturnssec; + DWORD defaultturnsintransit; +} SNETCAPS, *SNETCAPSPTR; + +typedef struct _SNETCREATEDATA { + DWORD size; + DWORD providerid; + DWORD maxplayers; + DWORD createflags; +} SNETCREATEDATA, *SNETCREATEDATAPTR; + +typedef struct _SNET_DATA_SYSCOLORTABLE { + DWORD syscolor; + COLORREF rgb; +} SNET_DATA_SYSCOLORTABLE, *SNET_DATA_SYSCOLORTABLEPTR; + +typedef struct _SNETEVENT { + DWORD eventid; + DWORD playerid; + LPVOID data; + DWORD databytes; +} SNETEVENT, *SNETEVENTPTR; + +struct _SNETPROGRAMDATA; +struct _SNETPLAYERDATA; +struct _SNETUIDATA; +struct _SNETVERSIONDATA; + +typedef BOOL (CALLBACK *SNETABORTPROC )(); +typedef BOOL (CALLBACK *SNETCATEGORYPROC )(BOOL,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *,DWORD *); +typedef BOOL (CALLBACK *SNETCHECKAUTHPROC )(DWORD,LPCSTR,LPCSTR,DWORD,LPCSTR,LPSTR,DWORD); +typedef BOOL (CALLBACK *SNETCREATEPROC )(SNETCREATEDATAPTR,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *); +typedef BOOL (CALLBACK *SNETDRAWDESCPROC )(DWORD,DWORD,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,LPDRAWITEMSTRUCT); +typedef BOOL (CALLBACK *SNETENUMDEVICESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMGAMESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMPROVIDERSPROC)(DWORD,LPCSTR,LPCSTR,SNETCAPSPTR); +typedef void (CALLBACK *SNETEVENTPROC )(SNETEVENTPTR); +typedef BOOL (CALLBACK *SNETGETARTPROC )(DWORD,DWORD,LPPALETTEENTRY,LPBYTE,DWORD,int *,int *,int *); +typedef BOOL (CALLBACK *SNETGETDATAPROC )(DWORD,DWORD,LPVOID,DWORD,DWORD *); +typedef int (CALLBACK *SNETMESSAGEBOXPROC )(HWND,LPCSTR,LPCSTR,UINT); +typedef BOOL (CALLBACK *SNETPLAYSOUNDPROC )(DWORD,DWORD,DWORD); +typedef BOOL (CALLBACK *SNETSELECTEDPROC )(DWORD,SNETCAPSPTR,_SNETUIDATA *,_SNETVERSIONDATA *); +typedef BOOL (CALLBACK *SNETSTATUSPROC )(LPCSTR,DWORD,DWORD,DWORD,SNETABORTPROC); + +typedef struct _SNETPLAYERDATA { + DWORD size; + LPCSTR playername; + LPCSTR playerdescription; +} SNETPLAYERDATA, *SNETPLAYERDATAPTR; + +typedef struct _SNETPROGRAMDATA { + DWORD size; + LPCSTR programname; + LPCSTR programdescription; + DWORD programid; + DWORD versionid; + DWORD reserved1; + DWORD maxplayers; + LPVOID initdata; + DWORD initdatabytes; + LPVOID reserved2; + DWORD optcategorybits; +} SNETPROGRAMDATA, *SNETPROGRAMDATAPTR; + +typedef struct _SNETUIDATA { + DWORD size; + DWORD uiflags; + HWND parentwindow; + SNETGETARTPROC artcallback; + SNETCHECKAUTHPROC authcallback; + SNETCREATEPROC createcallback; + SNETDRAWDESCPROC drawdesccallback; + SNETSELECTEDPROC selectedcallback; + SNETMESSAGEBOXPROC messageboxcallback; + SNETPLAYSOUNDPROC soundcallback; + SNETSTATUSPROC statuscallback; + SNETGETDATAPROC getdatacallback; + SNETCATEGORYPROC categorycallback; +} SNETUIDATA, *SNETUIDATAPTR; + +typedef struct _SNETVERSIONDATA { + DWORD size; + LPCSTR versionstring; + LPCSTR executablefile; + LPCSTR originalarchivefile; + LPCSTR patcharchivefile; +} SNETVERSIONDATA, *SNETVERSIONDATAPTR; + +extern "C" BOOL APIENTRY SNetCreateGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamecategorybits, + LPVOID initdata, + DWORD initdatabytes, + DWORD maxplayers, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetDestroy (); +extern "C" BOOL APIENTRY SNetDropPlayer (DWORD playerid, DWORD exitcode); +extern "C" BOOL APIENTRY SNetEnumDevices (SNETENUMDEVICESPROC callback); +extern "C" BOOL APIENTRY SNetEnumGames (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumProviders (SNETCAPSPTR mincaps, + SNETENUMPROVIDERSPROC callback); +extern "C" BOOL APIENTRY SNetGetGameInfo (DWORD index, + LPVOID buffer, + DWORD buffersize, + DWORD *byteswritten); +extern "C" BOOL APIENTRY SNetGetNetworkLatency (DWORD measurementtype, + DWORD *result); +extern "C" BOOL APIENTRY SNetGetNumPlayers (DWORD *firstplayerid, + DWORD *lastplayerid, + DWORD *activeplayers); +extern "C" BOOL APIENTRY SNetGetOwnerTurnsWaiting (DWORD *turns); +extern "C" BOOL APIENTRY SNetGetPerformanceData (DWORD counterid, + DWORD *countervalue, + DWORD *countertype, + LONG *counterscale, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +extern "C" BOOL APIENTRY SNetGetPlayerCaps (DWORD playerid, + SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetPlayerName (DWORD playerid, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SNetGetProviderCaps (SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetTurnsInTransit (DWORD *turns); +extern "C" BOOL APIENTRY SNetInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetInitializeProvider (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetJoinGame (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetLeaveGame (DWORD exitcode); +extern "C" BOOL APIENTRY SNetPerformUpgrade (DWORD *upgradestatus); +extern "C" BOOL APIENTRY SNetReceiveMessage (DWORD *senderplayerid, + LPVOID *data, + DWORD *databytes); +extern "C" BOOL APIENTRY SNetReceiveTurns (DWORD firstplayerid, + DWORD arraysize, + LPVOID *arraydata, + LPDWORD arraydatabytes, + LPDWORD arrayplayerstatus); +extern "C" BOOL APIENTRY SNetRegisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); +extern "C" BOOL APIENTRY SNetResetLatencyMeasurements (); +extern "C" BOOL APIENTRY SNetSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY SNetSendMessage (DWORD targetplayerid, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSendTurn (LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSetBasePlayer (DWORD playerid); +extern "C" BOOL APIENTRY SNetSetGameMode (DWORD modeflags); +extern "C" BOOL APIENTRY SNetUnregisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); + +/**************************************************************************** +* +* Networking service provider interface +* +***/ + +#define SNETSPI_MAXSTRINGLENGTH 128 + +typedef struct _SNETADDR { + BYTE address[16]; +} SNETADDR, *SNETADDRPTR; + +typedef struct _SNETSPI_DEVICELIST { + DWORD deviceid; + SNETCAPS devicecaps; + char devicename[SNETSPI_MAXSTRINGLENGTH]; + char devicedescription[SNETSPI_MAXSTRINGLENGTH]; + DWORD reserved; + _SNETSPI_DEVICELIST *next; +} SNETSPI_DEVICELIST, *SNETSPI_DEVICELISTPTR; + +typedef struct _SNETSPI_GAMELIST { + DWORD gameid; + DWORD gamemode; + DWORD creationtime; + SNETADDR owner; + DWORD ownerlatency; + DWORD ownerlasttime; + DWORD gamecategorybits; + char gamename[SNETSPI_MAXSTRINGLENGTH]; + char gamedescription[SNETSPI_MAXSTRINGLENGTH]; + _SNETSPI_GAMELIST *next; +} SNETSPI_GAMELIST, *SNETSPI_GAMELISTPTR; + +typedef struct _SNETSPI { + DWORD size; + BOOL (CALLBACK *CompareNetAddresses)(SNETADDRPTR,SNETADDRPTR,DWORD *); + BOOL (CALLBACK *Destroy)(); + BOOL (CALLBACK *Free)(SNETADDRPTR,LPVOID,DWORD); + BOOL (CALLBACK *FreeExternalMessage)(LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *GetGameInfo)(DWORD,LPCSTR,LPCSTR,SNETSPI_GAMELIST *); + BOOL (CALLBACK *GetPerformanceData)(DWORD,DWORD *,LARGE_INTEGER *,LARGE_INTEGER *); + BOOL (CALLBACK *Initialize)(SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,HANDLE); + BOOL (CALLBACK *InitializeDevice)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR); + BOOL (CALLBACK *LockDeviceList)(SNETSPI_DEVICELISTPTR *); + BOOL (CALLBACK *LockGameList)(DWORD,DWORD,SNETSPI_GAMELISTPTR *); + BOOL (CALLBACK *Receive)(SNETADDRPTR *,LPVOID *,DWORD *); + BOOL (CALLBACK *ReceiveExternalMessage)(LPCSTR *,LPCSTR *,LPCSTR *); + BOOL (CALLBACK *SelectGame)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,DWORD *); + BOOL (CALLBACK *Send)(DWORD,SNETADDRPTR *,LPVOID,DWORD); + BOOL (CALLBACK *SendExternalMessage)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *StartAdvertisingGame)(LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,DWORD); + BOOL (CALLBACK *StopAdvertisingGame)(); + BOOL (CALLBACK *UnlockDeviceList)(SNETSPI_DEVICELISTPTR); + BOOL (CALLBACK *UnlockGameList)(SNETSPI_GAMELISTPTR,DWORD *); +} SNETSPI, *SNETSPIPTR; + +typedef BOOL (APIENTRY *SNETSPIBIND )(DWORD,SNETSPIPTR *); +typedef BOOL (APIENTRY *SNETSPIQUERY)(DWORD,DWORD *,LPCSTR *,LPCSTR *,SNETCAPSPTR *); + +/**************************************************************************** +* +* Registry functions +* +***/ + +#define SREG_FLAG_USERSPECIFIC 0x00000001 +#define SREG_FLAG_BATTLENET 0x00000002 +#define SREG_FLAG_FLUSHTODISK 0x00000008 +#define SREG_FLAG_MULTISZ 0x00000080 + +extern "C" BOOL APIENTRY SRegLoadData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID buffer, + DWORD buffersize, + DWORD *bytesread); +extern "C" BOOL APIENTRY SRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SRegLoadValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *value); +extern "C" BOOL APIENTRY SRegSaveData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SRegSaveString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPCTSTR string); +extern "C" BOOL APIENTRY SRegSaveValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD value); + +/**************************************************************************** +* +* Run-time library functions +* +***/ + +#define TRY goto trylabel; trylabel: +#define LEAVE goto finallylabel +#define FINALLY goto finallylabel; finallylabel: + +/**************************************************************************** +* +* Transparency functions +* +***/ + +typedef struct _HSTRANS { int unused; } *HSTRANS; +typedef HSTRANS HTRANS; + +extern "C" BOOL APIENTRY STransBlt (LPBYTE dest, + int destx, + int desty, + int destpitch, + HSTRANS transparency); +extern "C" BOOL APIENTRY STransBltUsingMask (LPBYTE dest, + LPBYTE source, + int destpitch, + int sourcepitch, + HSTRANS mask); +extern "C" BOOL APIENTRY STransCreate (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransDelete (HSTRANS handle); +extern "C" BOOL APIENTRY STransDestroy (); +extern "C" BOOL APIENTRY STransDuplicate (HSTRANS source, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIntersectDirtyArray (HSTRANS sourcemask, + LPBYTE dirtyarray, + BYTE dirtyarraymask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransInvertMask (HSTRANS sourcemask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransLoad (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransSetDirtyArrayInfo (int screencx, + int screency, + int cellcx, + int cellcy); +extern "C" BOOL APIENTRY STransUpdateDirtyArray (LPBYTE dirtyarray, + BYTE dirtyvalue, + int destx, + int desty, + HSTRANS transparency, + BOOL tracecontour); + +/**************************************************************************** +* +* Video functions +* +***/ + +#define SVID_FLAG_DOUBLESCANS 0x00000001 +#define SVID_FLAG_INTERPOLATE 0x00000002 +#define SVID_FLAG_AUTOQUALITY 0x00000008 +#define SVID_FLAG_1XSIZE 0x00000100 +#define SVID_FLAG_2XSIZE 0x00000200 +#define SVID_FLAG_AUTOSIZE 0x00000800 +#define SVID_FLAG_FILEHANDLE 0x00010000 +#define SVID_FLAG_PRELOAD 0x00020000 +#define SVID_FLAG_LOOP 0x00040000 +#define SVID_FLAG_FULLSCREEN 0x00080000 +#define SVID_FLAG_USECURRENTPALETTE 0x00100000 +#define SVID_FLAG_CLEARSCREEN 0x00200000 +#define SVID_FLAG_TOSCREEN 0x10000000 +#define SVID_FLAG_TOBUFFER 0x20000000 + +#define SVID_CUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_2XSIZE) +#define SVID_AUTOCUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_AUTOSIZE | SVID_FLAG_AUTOQUALITY) + +#define SVID_QUALITY_LOW_SKIPSCANS SVID_FLAG_2XSIZE +#define SVID_QUALITY_LOW (SVID_FLAG_2XSIZE | SVID_FLAG_DOUBLESCANS) +#define SVID_QUALITY_HIGH_SKIPSCANS (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE) +#define SVID_QUALITY_HIGH (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE | SVID_FLAG_DOUBLESCANS) + +typedef struct _HSVIDEO { int unused; } *HSVIDEO; + +typedef struct _SVIDPALETTEUSE { + DWORD size; + DWORD firstentry; + DWORD numentries; +} SVIDPALETTEUSE, *SVIDPALETTEUSEPTR; + +extern "C" BOOL APIENTRY SVidDestroy (); +extern "C" BOOL APIENTRY SVidGetPerformanceData (HSVIDEO video, + BOOL averageframems, + DWORD *framems, + BOOL averagepalettems, + DWORD *palettems); +extern "C" BOOL APIENTRY SVidGetSize (HSVIDEO video, + int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SVidInitialize (LPVOID directsound); +extern "C" BOOL APIENTRY SVidPlayBegin (LPCTSTR filename, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayBeginFromMemory (LPVOID sourceptr, + DWORD sourcebytes, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayContinue (); +extern "C" BOOL APIENTRY SVidPlayContinueSingle (HSVIDEO video, + BOOL forceupdate, + BOOL *updated); +extern "C" BOOL APIENTRY SVidPlayEnd (HSVIDEO video); + +/**************************************************************************** +* +* Storm global functions +* +***/ + +extern "C" BOOL APIENTRY StormDestroy (); + +/**************************************************************************** +* +* C++ Utility Classes and Templates +* +***/ + +#ifndef __cplusplus +extern "C++" +#endif + +/**************************************************************************** +* +* CCRITSECT -- Critical section class +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void inline Enter () { EnterCriticalSection(&m_critsect); } + void inline Leave () { LeaveCriticalSection(&m_critsect); } +}; + +/**************************************************************************** +* +* CLOCK -- Lock class +* +***/ + +class CLock { + + private: + + HANDLE m_mutexevent; + HANDLE m_readerevent; + LONG m_readercount; + + public: + + CLock () { + m_mutexevent = CreateEvent(NULL,FALSE,TRUE,NULL); + m_readerevent = CreateEvent(NULL,TRUE,FALSE,NULL); + m_readercount = -1; + } + + ~CLock () { + CloseHandle(m_readerevent); + CloseHandle(m_mutexevent); + } + + void inline Enter (BOOL forwriting) { + if (forwriting) + WaitForSingleObject(m_mutexevent,INFINITE); + else if (!InterlockedIncrement(&m_readercount)) { + WaitForSingleObject(m_mutexevent,INFINITE); + SetEvent(m_readerevent); + } + else + WaitForSingleObject(m_readerevent,INFINITE); + } + + void inline Leave (BOOL fromwriting) { + if (fromwriting) + SetEvent(m_mutexevent); + else if (InterlockedDecrement(&m_readercount) < 0) { + ResetEvent(m_readerevent); + SetEvent(m_mutexevent); + } + } + +}; + +/**************************************************************************** +* +* TLIST -- Linked list function templates +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return 1; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return 1; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = *head; + *head = ptr; + return 1; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return 1; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return 0; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber,0); + *head = next; + } + return 1; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber,0); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + +#ifndef __cplusplus +} // extern "C++" +#endif + +#endif // ifndef _STORM_H_ diff --git a/src/Uisrc/OLD/STORM.LIB b/src/Uisrc/OLD/STORM.LIB new file mode 100644 index 0000000..67499fd Binary files /dev/null and b/src/Uisrc/OLD/STORM.LIB differ diff --git a/src/Uisrc/RELEASE/DIABLOUI.PCH b/src/Uisrc/RELEASE/DIABLOUI.PCH new file mode 100644 index 0000000..c805464 Binary files /dev/null and b/src/Uisrc/RELEASE/DIABLOUI.PCH differ diff --git a/src/Uisrc/RELEASE/STANDARD.LIB b/src/Uisrc/RELEASE/STANDARD.LIB new file mode 100644 index 0000000..7d6fc5f Binary files /dev/null and b/src/Uisrc/RELEASE/STANDARD.LIB differ diff --git a/src/Uisrc/RELEASE/VC50.IDB b/src/Uisrc/RELEASE/VC50.IDB new file mode 100644 index 0000000..e49812d Binary files /dev/null and b/src/Uisrc/RELEASE/VC50.IDB differ diff --git a/src/Uisrc/SCLASS.H b/src/Uisrc/SCLASS.H new file mode 100644 index 0000000..0e1c039 --- /dev/null +++ b/src/Uisrc/SCLASS.H @@ -0,0 +1,158 @@ +#ifndef _STORM_SCLASS_H_ +#define _STORM_SCLASS_H_ + +extern "C++" { + +/**************************************************************************** +* +* CCRITSECT -- Critical section class +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void inline Enter () { EnterCriticalSection(&m_critsect); } + void inline Leave () { LeaveCriticalSection(&m_critsect); } +}; + +/**************************************************************************** +* +* CLOCK -- Lock class +* +***/ + +class CLock { + private: + SSYNCLOCK m_lock; + public: + CLock () { SSyncInitializeLock(&m_lock); } + ~CLock () { SSyncDeleteLock(&m_lock); } + void inline Enter (BOOL forwriting) { SSyncEnterLock(&m_lock,forwriting); } + void inline Leave (BOOL fromwriting) { SSyncLeaveLock(&m_lock,fromwriting); } +}; + +/**************************************************************************** +* +* TLIST -- Linked list function templates +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return 1; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return 1; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = *head; + *head = ptr; + return 1; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return 1; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return 0; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber); + *head = next; + } + return 1; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + +} // extern "C++" +#endif // ifndef _STORM_SCLASS_H_ diff --git a/src/Uisrc/STANDARD/DEBUG/STANDARD.LIB b/src/Uisrc/STANDARD/DEBUG/STANDARD.LIB new file mode 100644 index 0000000..7d6fc5f Binary files /dev/null and b/src/Uisrc/STANDARD/DEBUG/STANDARD.LIB differ diff --git a/src/Uisrc/STANDARD/RELEASE/STANDARD.LIB b/src/Uisrc/STANDARD/RELEASE/STANDARD.LIB new file mode 100644 index 0000000..7d6fc5f Binary files /dev/null and b/src/Uisrc/STANDARD/RELEASE/STANDARD.LIB differ diff --git a/src/Uisrc/STORM.H b/src/Uisrc/STORM.H new file mode 100644 index 0000000..0561112 --- /dev/null +++ b/src/Uisrc/STORM.H @@ -0,0 +1,1342 @@ +#ifndef _STORM_H_ +#define _STORM_H_ + +/**************************************************************************** +* +* BitBlt functions +* +***/ + +extern "C" BOOL APIENTRY SBltDestroy (); +extern "C" BOOL APIENTRY SBltGetSCode (DWORD rop3, + LPSTR buffer, + DWORD buffersize, + BOOL optimize = 1); +extern "C" BOOL APIENTRY SBltROP3 (LPBYTE dest, + LPBYTE source, + int width, + int height, + int destcx, + int sourcecx, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Clipped (LPBYTE dest, + LPRECT destrect, + LPSIZE destsize, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + LPSIZE sourcesize, + int sourcepitch, + DWORD pattern, + DWORD rop3); +extern "C" BOOL APIENTRY SBltROP3Tiled (LPBYTE dest, + LPRECT destrect, + int destpitch, + LPBYTE source, + LPRECT sourcerect, + int sourcepitch, + int sourceoffsetx, + int sourceoffsety, + DWORD pattern, + DWORD rop3); + +/**************************************************************************** +* +* Bitmap functions +* +***/ + +#define SBMP_IMAGETYPE_BMP 1 +#define SBMP_IMAGETYPE_PCX 2 + +extern "C" BOOL APIENTRY SBmpDecodeImage (DWORD imagetype, + LPBYTE imagedata, + DWORD imagebytes, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width, + int *height, + int *bitdepth); +extern "C" BOOL APIENTRY SBmpDestroy (); +extern "C" BOOL APIENTRY SBmpLoadImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + DWORD buffersize, + int *width = NULL, + int *height = NULL, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SBmpSaveImage (LPCTSTR filename, + LPPALETTEENTRY paletteentries, + LPBYTE bitmapbits, + int width, + int height, + int bitdepth); + +/**************************************************************************** +* +* S-Code functions +* +***/ + +#define SCODE_CF_AUTOALIGNDWORD 0x00040000 +#define SCODE_CF_USESALTADJUSTS 0x04000000 + +typedef struct _HSCODESTREAM { int unused; } *HSCODESTREAM; + +typedef struct _SCODEEXECUTEDATA { + DWORD size; + DWORD flags; + int xiterations; + int yiterations; + int adjustdest; + int adjustsource; + LPVOID dest; + LPVOID source; + LPVOID table; + DWORD a; + DWORD b; + DWORD c; + int adjustdestalt; + int adjustsourcealt; + DWORD reserved[2]; +} SCODEEXECUTEDATA, *SCODEEXECUTEDATAPTR; + +extern "C" BOOL APIENTRY SCodeCompile (LPCSTR prologstring, + LPCSTR loopstring, + LPCSTR *firsterror, + DWORD maxiterations, + DWORD flags, + HSCODESTREAM *handle); +extern "C" BOOL APIENTRY SCodeDelete (HSCODESTREAM handle); +extern "C" BOOL APIENTRY SCodeDestroy (); +extern "C" BOOL APIENTRY SCodeExecute (HSCODESTREAM handle, + SCODEEXECUTEDATAPTR executedata); +extern "C" BOOL APIENTRY SCodeGetJumpTable (HSCODESTREAM handle, + LPBYTE **jumptableptr, + LPDWORD *prologpatchlocation, + LPDWORD *looppatchlocation, + LPDWORD *epilogpatchlocation); +extern "C" BOOL APIENTRY SCodeGetPseudocode (LPCSTR scodestring, + LPSTR buffer, + DWORD buffersize); + +/**************************************************************************** +* +* Dialog box functions +* +***/ + +#define SDLG_ADJUST_NONE 0 +#define SDLG_ADJUST_VERTICAL 1 +#define SDLG_ADJUST_CONTROLPOS 2 + +#define SDLG_DBF_TILE 0x00000001 +#define SDLG_DBF_VCENTER 0x00000002 + +#define SDLG_STYLE_ANY 0xFFFFFFFF +#define SDLG_STYLE_ANYPUSHBUTTON 0x00010001 + +#define SDLG_USAGE_BACKGROUND 0x00000001 +#define SDLG_USAGE_NORMAL_UNFOCUSED 0x00000010 +#define SDLG_USAGE_NORMAL_FOCUSED 0x00000020 +#define SDLG_USAGE_NORMAL (SDLG_USAGE_NORMAL_UNFOCUSED | SDLG_USAGE_NORMAL_FOCUSED) +#define SDLG_USAGE_SELECTED_UNFOCUSED 0x00000040 +#define SDLG_USAGE_SELECTED_FOCUSED 0x00000080 +#define SDLG_USAGE_SELECTED (SDLG_USAGE_SELECTED_UNFOCUSED | SDLG_USAGE_SELECTED_FOCUSED) +#define SDLG_USAGE_NORMAL_GRAYED 0x00000100 +#define SDLG_USAGE_SELECTED_GRAYED 0x00000400 +#define SDLG_USAGE_GRAYED (SDLG_USAGE_NORMAL_GRAYED | SDLG_USAGE_SELECTED_GRAYED) +#define SDLG_USAGE_CURSORMASK 0x00001000 +#define SDLG_USAGE_CURSORIMAGE 0x00002000 + +extern "C" HDC APIENTRY SDlgBeginPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgBltToWindow (HWND window, + HRGN region, + int x, + int y, + LPBYTE bitmapbits, + LPRECT bitmaprect, + LPSIZE bitmapsize, + DWORD colorkey = 0xFFFFFFFF, + DWORD pattern = 0, + DWORD rop3 = SRCCOPY); +extern "C" BOOL APIENTRY SDlgCheckTimers (); +extern "C" HWND APIENTRY SDlgCreateDialogIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" HWND APIENTRY SDlgCreateDialogParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDefDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam); +extern "C" BOOL APIENTRY SDlgDestroy (); +extern "C" int APIENTRY SDlgDialogBoxIndirectParam (HINSTANCE instance, + LPCDLGTEMPLATE templatedata, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" int APIENTRY SDlgDialogBoxParam (HINSTANCE instance, + LPCTSTR templatename, + HWND parentwindow, + DLGPROC dialogproc, + LPARAM initparam); +extern "C" BOOL APIENTRY SDlgDrawBitmap (HWND window, + DWORD usage, + HRGN region, + int offsetx = 0, + int offsety = 0, + LPRECT boundingoffset = NULL, + DWORD flags = 0); +extern "C" BOOL APIENTRY SDlgEndDialog (HWND window, + int result); +extern "C" BOOL APIENTRY SDlgEndPaint (HWND window, LPPAINTSTRUCT ps); +extern "C" BOOL APIENTRY SDlgKillTimer (HWND window, + UINT event); +extern "C" BOOL APIENTRY SDlgSetBaseFont (int pointsize, + int weight, + DWORD flags, + DWORD family, + LPCTSTR face); +extern "C" BOOL APIENTRY SDlgSetBitmap (HWND window, + HWND parentwindow, + LPCTSTR controltype, + DWORD controlstyle, + DWORD usage, + LPBYTE bitmapbits, + LPRECT rect, + int width, + int height, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetControlBitmaps (HWND parentwindow, + LPINT controllist, + LPDWORD usagelist, + LPBYTE bitmapbits, + LPSIZE bitmapsize, + DWORD adjusttype, + COLORREF colorkey = 0xFFFFFFFF); +extern "C" BOOL APIENTRY SDlgSetCursor (HWND window, + HCURSOR cursor, + DWORD id, + HCURSOR *oldcursor); +extern "C" BOOL APIENTRY SDlgSetSystemCursor (LPBYTE maskbitmap, + LPBYTE imagebitmap, + LPSIZE size, + DWORD id = 32512); +extern "C" BOOL APIENTRY SDlgSetTimer (HWND window, + UINT event, + UINT elapse, + TIMERPROC timerfunc); +extern "C" BOOL APIENTRY SDlgUpdateCursor (); + +#define SDlgCreateDialog(ins,tpl,wnd,prc) SDlgCreateDialogParam(ins,tpl,wnd,prc,0) +#define SDlgCreateDialogIndirect(ins,tpl,wnd,prc) SDlgCreateDialogIndirectParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBox(ins,tpl,wnd,prc) SDlgDialogBoxParam(ins,tpl,wnd,prc,0) +#define SDlgDialogBoxIndirect(ins,tpl,wnd,prc) SDlgDialogBoxIndirectParam(ins,tpl,wnd,prc,0) + +/**************************************************************************** +* +* DirectDraw functions +* +***/ + +#define SDRAW_SERVICE_BASIC 1 +#define SDRAW_SERVICE_PAGEFLIP 2 +#define SDRAW_SERVICE_DOUBLEBUFFER 3 +#define SDRAW_SERVICE_MAX 3 + +#define SDRAW_SURFACE_FRONT 0 +#define SDRAW_SURFACE_BACK 1 +#define SDRAW_SURFACE_SYSTEM 2 +#define SDRAW_SURFACE_TEMPORARY 3 + +extern "C" BOOL APIENTRY SDrawAutoInitialize (HINSTANCE instance, + LPCTSTR classname, + LPCTSTR title, + WNDPROC wndproc = NULL, + int servicelevel = SDRAW_SERVICE_BASIC, + int width = 640, + int height = 480, + int bitdepth = 8); +extern "C" BOOL APIENTRY SDrawCaptureScreen (LPCTSTR filename = NULL); +extern "C" BOOL APIENTRY SDrawClearSurface (int surfacenumber); +extern "C" BOOL APIENTRY SDrawDestroy (); +extern "C" BOOL APIENTRY SDrawFlipPage (); +extern "C" HWND APIENTRY SDrawGetFrameWindow (HWND *window = NULL); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawGetObjects (LPDIRECTDRAW *directdraw, + LPDIRECTDRAWSURFACE *frontbuffer, + LPDIRECTDRAWSURFACE *backbuffer, + LPDIRECTDRAWSURFACE *systembuffer, + LPDIRECTDRAWSURFACE *temporarybuffer, + LPDIRECTDRAWPALETTE *palette, + HPALETTE *gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawGetScreenSize (int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SDrawGetServiceLevel (int *servicelevel = NULL); +extern "C" BOOL APIENTRY SDrawLockSurface (int surfacenumber, + LPCRECT rect, + LPBYTE *ptr, + int *pitch = NULL, + DWORD flags = 0); +#ifdef __DDRAW_INCLUDED__ +extern "C" BOOL APIENTRY SDrawManualInitialize (HWND framewindow, + LPDIRECTDRAW directdraw, + LPDIRECTDRAWSURFACE frontbuffer, + LPDIRECTDRAWSURFACE backbuffer, + LPDIRECTDRAWSURFACE systembuffer, + LPDIRECTDRAWSURFACE temporarybuffer, + LPDIRECTDRAWPALETTE palette, + HPALETTE gdipalette); +#endif +extern "C" BOOL APIENTRY SDrawMessageBox (LPCTSTR text, + LPCTSTR title, + UINT flags); +extern "C" BOOL APIENTRY SDrawPostClose (); +extern "C" BOOL APIENTRY SDrawRealizePalette (); +extern "C" BOOL APIENTRY SDrawSelectGdiSurface (BOOL select, BOOL copy); +extern "C" BOOL APIENTRY SDrawUnlockSurface (int surfacenumber, + LPBYTE ptr, + DWORD numrects = 0, + LPCRECT rectarray = NULL); +extern "C" BOOL APIENTRY SDrawUpdatePalette (DWORD firstentry, + DWORD numentries, + LPPALETTEENTRY entries, + BOOL reservedentries = 0); +extern "C" BOOL APIENTRY SDrawUpdateScreen (LPCRECT rect); + +/**************************************************************************** +* +* Event dispatching functions +* +***/ + +typedef void (CALLBACK *SEVTHANDLER)(LPVOID); + +extern "C" BOOL APIENTRY SEvtDestroy (); +extern "C" BOOL APIENTRY SEvtDispatch (DWORD type, + DWORD subtype, + DWORD id, + LPVOID data); +extern "C" BOOL APIENTRY SEvtRegisterHandler (DWORD type, + DWORD subtype, + DWORD id, + DWORD flags, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterHandler (DWORD type, + DWORD subtype, + DWORD id, + SEVTHANDLER handler); +extern "C" BOOL APIENTRY SEvtUnregisterType (DWORD type, + DWORD subtype); + +/**************************************************************************** +* +* File I/O functions +* +***/ + +#define SFILE_AUTH_UNABLETOAUTHENTICATE 0 +#define SFILE_AUTH_NOSIGNATURE 1 +#define SFILE_AUTH_BADSIGNATURE 2 +#define SFILE_AUTH_UNKNOWNSIGNATURE 3 +#define SFILE_AUTH_FIRSTAUTHENTIC 5 +#define SFILE_AUTH_AUTHENTICBLIZZARD 5 + +#define SFILE_DDA_LOOP 0x00040000 + +#define SFILE_ERROR_BASE 0x21030000 +#define SFILE_ERROR_BAD_FORMAT ERROR_BAD_FORMAT +#define SFILE_ERROR_BAD_PATHNAME ERROR_BAD_PATHNAME +#define SFILE_ERROR_CALL_NOT_IMPLEMENTED ERROR_CALL_NOT_IMPLEMENTED +#define SFILE_ERROR_FILE_INVALID ERROR_FILE_INVALID +#define SFILE_ERROR_FILE_NOT_FOUND ERROR_FILE_NOT_FOUND +#define SFILE_ERROR_HANDLE_EOF ERROR_HANDLE_EOF +#define SFILE_ERROR_INVALID_DATA ERROR_INVALID_DATA +#define SFILE_ERROR_INVALID_DRIVE ERROR_INVALID_DRIVE +#define SFILE_ERROR_INVALID_HANDLE ERROR_INVALID_HANDLE +#define SFILE_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SFILE_ERROR_NOT_ARCHIVE (SFILE_ERROR_BASE+1) +#define SFILE_ERROR_NOT_AUTHENTICATED ERROR_NOT_AUTHENTICATED +#define SFILE_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SFILE_ERROR_NOT_IN_ARCHIVE (SFILE_ERROR_BASE+2) +#define SFILE_ERROR_NOT_PLAYING (SFILE_ERROR_BASE+3) + +#define SFILE_FIND_FILES 0x00000001 +#define SFILE_FIND_DIRECTORIES 0x00000002 + +typedef struct _HSARCHIVE { int unused; } *HSARCHIVE; +typedef struct _HSFILE { int unused; } *HSFILE; +typedef struct _HSFINDFILE { int unused; } *HSFINDFILE; + +extern "C" BOOL APIENTRY SFileAuthenticateArchive (HSARCHIVE archive, + DWORD *extendedresult); +extern "C" BOOL APIENTRY SFileCloseArchive (HSARCHIVE handle); +extern "C" BOOL APIENTRY SFileCloseFile (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaBegin (HSFILE handle, + DWORD buffersize, + DWORD flags); +extern "C" BOOL APIENTRY SFileDdaBeginEx (HSFILE handle, + DWORD buffersize, + DWORD flags, + DWORD offset, + LONG volume, + LONG pan, + LPVOID reserved); +extern "C" BOOL APIENTRY SFileDdaDestroy (); +extern "C" BOOL APIENTRY SFileDdaEnd (HSFILE handle); +extern "C" BOOL APIENTRY SFileDdaGetPos (HSFILE handle, + DWORD *position, + DWORD *maxposition); +extern "C" BOOL APIENTRY SFileDdaGetVolume (HSFILE handle, + LONG *volume, + LONG *pan); +#ifdef __DSOUND_INCLUDED__ +extern "C" BOOL APIENTRY SFileDdaInitialize (LPDIRECTSOUND directsound); +#endif +extern "C" BOOL APIENTRY SFileDdaSetVolume (HSFILE handle, + LONG volume, + LONG pan); +extern "C" BOOL APIENTRY SFileDestroy (); +extern "C" BOOL APIENTRY SFileEnableDirectAccess (BOOL enable); +extern "C" BOOL APIENTRY SFileGetFileArchive (HSFILE file, + HSARCHIVE *archive); +extern "C" DWORD APIENTRY SFileGetFileSize (HSFILE handle, + LPDWORD filesizehigh = NULL); +extern "C" BOOL APIENTRY SFileOpenArchive (LPCTSTR archivename, + int priority, + BOOL cdonly, + HSARCHIVE *handle); +extern "C" BOOL APIENTRY SFileOpenFile (LPCTSTR filename, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileEx (HSARCHIVE archivehandle, + LPCTSTR filename, + DWORD flags, + HSFILE *handle); +extern "C" BOOL APIENTRY SFileOpenFileWin32 (LPCTSTR filename, + HANDLE *handle); +extern "C" BOOL APIENTRY SFileReadFile (HSFILE handle, + LPVOID buffer, + DWORD bytestoread, + LPDWORD bytesread = NULL, + LPVOID reserved = NULL); +extern "C" BOOL APIENTRY SFileSetBasePath (LPCTSTR path); +extern "C" DWORD APIENTRY SFileSetFilePointer (HSFILE handle, + LONG distancetomove, + PLONG distancetomovehigh, + DWORD movemethod); +extern "C" BOOL APIENTRY SFileSetLocale (LCID lcid); + +/**************************************************************************** +* +* GDI functions +* +***/ + +#define ETO_TEXT_TRANSPARENT 0 +#define ETO_TEXT_COLOR 1 +#define ETO_TEXT_BLACK 2 +#define ETO_TEXT_WHITE 3 +#define ETO_BKG_TRANSPARENT 0 +#define ETO_BKG_COLOR 1 +#define ETO_BKG_BLACK 2 +#define ETO_BKG_WHITE 3 + +typedef struct _HSGDIOBJ { int unused; } *HSGDIOBJ; +typedef struct _HSGDIFONT : public _HSGDIOBJ { int unused; } *HSGDIFONT; + +extern "C" BOOL APIENTRY SGdiBitBlt (LPBYTE videobuffer, + int destx, + int desty, + LPBYTE sourcedata, + LPRECT sourcerect, + int sourcecx, + int sourcecy, + COLORREF color = 0, + DWORD rop = SRCCOPY); +extern "C" BOOL APIENTRY SGdiCreateFont (LPBYTE bits, + int width, + int height, + int bitdepth, + int filecharwidth, + int filecharheight, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiDeleteObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiDestroy (); +extern "C" BOOL APIENTRY SGdiExtTextOut (LPBYTE videobuffer, + int x, + int y, + LPRECT rect, + COLORREF color, + int textcoloruse, + int bkgcoloruse, + LPCTSTR string, + int chars = -1); +extern "C" BOOL APIENTRY SGdiImportFont (HFONT windowsfont, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiLoadFont (LPCTSTR filename, + int filecharwidth, + int filecharheight, + int basecharwidth, + LPSIZE charsizetable, + HSGDIFONT *handle); +extern "C" BOOL APIENTRY SGdiRectangle (LPBYTE videobuffer, + int left, + int top, + int right, + int bottom, + COLORREF color); +extern "C" BOOL APIENTRY SGdiSelectObject (HSGDIOBJ handle); +extern "C" BOOL APIENTRY SGdiSetPitch (int pitch); +extern "C" BOOL APIENTRY SGdiTextOut (LPBYTE videobuffer, + int x, + int y, + COLORREF color, + LPCTSTR string, + int chars = -1); + +/**************************************************************************** +* +* Memory allocation functions +* +***/ + +#define SMEM_FLAG_ZEROMEMORY 0x00000008 + +extern "C" LPVOID APIENTRY SMemAlloc (DWORD bytes, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" BOOL APIENTRY SMemDestroy (); +extern "C" BOOL APIENTRY SMemFree (LPVOID ptr, + LPCSTR filename = NULL, + int linenumber = 0, + DWORD flags = 0); +extern "C" void APIENTRY SMemInitialize (); + +#define ALLOC(bytes) SMemAlloc(bytes,__FILE__,__LINE__,0) +#define ALLOCZERO(bytes) SMemAlloc(bytes,__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) +#define FREE(ptr) SMemFree(ptr,__FILE__,__LINE__,0) +#define NEW(struct) (struct *)SMemAlloc(sizeof(struct),__FILE__,__LINE__,0) +#define NEWZERO(struct) (struct *)SMemAlloc(sizeof(struct),__FILE__,__LINE__,SMEM_FLAG_ZEROMEMORY) + +/**************************************************************************** +* +* Message functions +* +***/ + +typedef struct _PARAMS { + HWND window; + UINT message; + WPARAM wparam; + LPARAM lparam; + UINT notifycode; + LPVOID extra; + BOOL useresult; + LRESULT result; +} PARAMS, *PARAMSPTR, *LPPARAMS; + +typedef BOOL (CALLBACK *SMSGIDLEPROC)(DWORD); +typedef void (CALLBACK *SMSGHANDLER)(LPPARAMS); + +extern "C" BOOL APIENTRY SMsgDestroy (); +extern "C" BOOL APIENTRY SMsgDispatchMessage (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam, + BOOL *useresult, + LRESULT *result); +extern "C" BOOL APIENTRY SMsgDoMessageLoop (SMSGIDLEPROC idleproc = NULL, + BOOL cleanuponquit = 1); +extern "C" BOOL APIENTRY SMsgRegisterCommand (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyDown (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterKeyUp (HWND window, + UINT id, + SMSGHANDLER handler); +extern "C" BOOL APIENTRY SMsgRegisterMessage (HWND window, + UINT id, + SMSGHANDLER handler); + +/**************************************************************************** +* +* Networking functions +* +***/ + +#define SNET_ART_BACKGROUND 0 +#define SNET_ART_BUTTONTEXTURE 1 +#define SNET_ART_JOINBACKGROUND 2 +#define SNET_ART_HELPBACKGROUND 3 +#define SNET_ART_POPUPBACKGROUND 4 +#define SNET_ART_BUTTON_XSML 5 +#define SNET_ART_BUTTON_SML 6 +#define SNET_ART_BUTTON_MED 7 +#define SNET_ART_BUTTON_LRG 8 +#define SNET_ART_APP_LOGO_SML 9 +#define SNET_ART_PROGRESS_BACKGROUND 10 +#define SNET_ART_PROGRESS_FILLER 11 +#define SNET_ART_POPUPBACKGROUND_SML 12 +#define SNET_ART_SCROLLBARARROWS 13 +#define SNET_ART_SCROLLTHUMB 14 +#define SNET_ART_SCROLLBAR 15 + +#define SNET_AUTHTYPE_CHANNEL 1 +#define SNET_AUTHTYPE_GAME 2 + +#define SNET_BROADCASTNONLOCALPLAYERID 0xFFFFFFFE +#define SNET_BROADCASTPLAYERID 0xFFFFFFFF +#define SNET_INVALIDPLAYERID 0xFFFFFFFF + +#define SNET_CAPS_PAGELOCKEDBUFFERS 0x00000001 +#define SNET_CAPS_BASICINTERFACE 0x00000002 + +#define SNET_CF_ALLOWPRIVATEGAMES 0x00000001 + +#define SNET_DATA_SYSCOLORS 1 +#define SNET_DATA_CURSORLINK 2 +#define SNET_DATA_CURSORARROW 3 +#define SNET_DATA_CURSORIBEAM 4 + +#define SNET_DDF_INCLUDENAME 0x00000001 +#define SNET_DDF_MULTILINE 0x00000002 + +#define SNET_DDPF_BLIZZARD 0x00000001 +#define SNET_DDPF_MODERATOR 0x00000002 +#define SNET_DDPF_SPEAKER 0x00000004 +#define SNET_DDPF_SYSOP 0x00000008 +#define SNET_DDPF_SQUELCHED 0x00000020 + +#define SNET_DRAWTYPE_GAME 1 +#define SNET_DRAWTYPE_PLAYER 2 + +#define SNET_ERROR_BASE 0x21050000 +#define SNET_ERROR_ALREADY_EXISTS ERROR_ALREADY_EXISTS +#define SNET_ERROR_BAD_PROVIDER ERROR_BAD_PROVIDER +#define SNET_ERROR_CANCELLED ERROR_CANCELLED +#define SNET_ERROR_INVALID_PARAMETER ERROR_INVALID_PARAMETER +#define SNET_ERROR_INVALID_PLAYER (SNET_ERROR_BASE+1) +#define SNET_ERROR_GAME_ALREADY_STARTED (SNET_ERROR_BASE+2) +#define SNET_ERROR_GAME_FULL (SNET_ERROR_BASE+3) +#define SNET_ERROR_GAME_NOT_FOUND (SNET_ERROR_BASE+4) +#define SNET_ERROR_GAME_TERMINATED (SNET_ERROR_BASE+5) +#define SNET_ERROR_HOST_UNREACHABLE ERROR_HOST_UNREACHABLE +#define SNET_ERROR_MAX_THRDS_REACHED ERROR_MAX_THRDS_REACHED +#define SNET_ERROR_NETWORK_BUSY ERROR_NETWORK_BUSY +#define SNET_ERROR_NO_MESSAGES_WAITING (SNET_ERROR_BASE+6) +#define SNET_ERROR_NO_NETWORK ERROR_NO_NETWORK +#define SNET_ERROR_NOT_CONNECTED ERROR_NOT_CONNECTED +#define SNET_ERROR_NOT_ENOUGH_MEMORY ERROR_NOT_ENOUGH_MEMORY +#define SNET_ERROR_NOT_IMPLEMENTED (SNET_ERROR_BASE+7) +#define SNET_ERROR_NOT_IN_GAME (SNET_ERROR_BASE+8) +#define SNET_ERROR_NOT_OWNER ERROR_NOT_OWNER +#define SNET_ERROR_NOT_REGISTERED (SNET_ERROR_BASE+9) +#define SNET_ERROR_REQUIRES_UPGRADE (SNET_ERROR_BASE+10) +#define SNET_ERROR_STILL_ACTIVE (SNET_ERROR_BASE+11) +#define SNET_ERROR_TOO_MANY_NAMES ERROR_TOO_MANY_NAMES +#define SNET_ERROR_VERSION_MISMATCH (SNET_ERROR_BASE+12) + +#define SNET_EVENT_INITDATA 1 +#define SNET_EVENT_PLAYERJOIN 2 +#define SNET_EVENT_PLAYERLEAVE 3 +#define SNET_EVENT_SERVERMESSAGE 4 + +#define SNET_EXIT_AUTO_JOINING 0x00000001 +#define SNET_EXIT_AUTO_NEWGAME 0x00000002 +#define SNET_EXIT_AUTO_SHUTDOWN 0x00000003 +#define SNET_EXIT_PLAYERQUIT 0x40000001 +#define SNET_EXIT_PLAYERKILLED 0x40000002 +#define SNET_EXIT_PLAYERWON 0x40000004 +#define SNET_EXIT_GAMEOVER 0x40000005 +#define SNET_EXIT_NOTRESPONDING 0x40000006 + +#define SNET_GM_PRIVATE 0x00000001 +#define SNET_GM_FULL 0x00000002 +#define SNET_GM_ADVERTISED 0x00000004 + +#define SNET_INFO_GAMENAME 1 +#define SNET_INFO_GAMEPASSWORD 2 +#define SNET_INFO_GAMEDESCRIPTION 3 +#define SNET_INFO_GAMEMODE 4 +#define SNET_INFO_INITDATA 5 +#define SNET_INFO_MAXPLAYERS 6 + +#define SNET_LMT_EXPECTED 1 +#define SNET_LMT_CURRENT 2 +#define SNET_LMT_PEAK 4 + +#define SNET_PERFID_TURN 1 +#define SNET_PERFID_TURNSSENT 4 +#define SNET_PERFID_TURNSRECV 5 +#define SNET_PERFID_MSGSENT 6 +#define SNET_PERFID_MSGRECV 7 +#define SNET_PERFID_USERBYTESSENT 8 +#define SNET_PERFID_USERBYTESRECV 9 +#define SNET_PERFID_TOTALBYTESSENT 10 +#define SNET_PERFID_TOTALBYTESRECV 11 +#define SNET_PERFID_PKTSENTONWIRE 12 +#define SNET_PERFID_PKTRECVONWIRE 13 +#define SNET_PERFID_BYTESSENTONWIRE 14 +#define SNET_PERFID_BYTESRECVONWIRE 15 +#define SNET_PERFIDNUM 16 + +#define SNET_PERFTYPE_COUNTER 0x10410400 +#define SNET_PERFTYPE_RAWCOUNT 0x00010000 + +#define SNET_PSF_ACTIVE 0x00010000 +#define SNET_PSF_TURNAVAILABLE 0x00020000 +#define SNET_PSF_RESPONDING 0x00040000 + +#define SNET_SF_ALLOWCREATE 0x00000001 + +#define SNET_SND_CHANGEFOCUS 0 +#define SNET_SND_SELECTITEM 1 + +#define SNET_UPGRADE_FAILED -1 +#define SNET_UPGRADE_NOT_NEEDED 0 +#define SNET_UPGRADE_SUCCEEDED 1 +#define SNET_UPGRADING_TERMINATE 2 + +#define SNET_MAXNAMELENGTH 128 +#define SNET_MAXDESCLENGTH 128 + +typedef struct _SNETCAPS { + DWORD size; + DWORD flags; + DWORD maxmessagesize; + DWORD maxqueuesize; + DWORD maxplayers; + DWORD bytessec; + DWORD latencyms; + DWORD defaultturnssec; + DWORD defaultturnsintransit; +} SNETCAPS, *SNETCAPSPTR; + +typedef struct _SNETCREATEDATA { + DWORD size; + DWORD providerid; + DWORD maxplayers; + DWORD createflags; +} SNETCREATEDATA, *SNETCREATEDATAPTR; + +typedef struct _SNET_DATA_SYSCOLORTABLE { + DWORD syscolor; + COLORREF rgb; +} SNET_DATA_SYSCOLORTABLE, *SNET_DATA_SYSCOLORTABLEPTR; + +typedef struct _SNETEVENT { + DWORD eventid; + DWORD playerid; + LPVOID data; + DWORD databytes; +} SNETEVENT, *SNETEVENTPTR; + +struct _SNETPROGRAMDATA; +struct _SNETPLAYERDATA; +struct _SNETUIDATA; +struct _SNETVERSIONDATA; + +typedef BOOL (CALLBACK *SNETABORTPROC )(); +typedef BOOL (CALLBACK *SNETCATEGORYPROC )(BOOL,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *,DWORD *); +typedef BOOL (CALLBACK *SNETCHECKAUTHPROC )(DWORD,LPCSTR,LPCSTR,DWORD,LPCSTR,LPSTR,DWORD); +typedef BOOL (CALLBACK *SNETCREATEPROC )(SNETCREATEDATAPTR,_SNETPROGRAMDATA *,_SNETPLAYERDATA *,_SNETUIDATA *,_SNETVERSIONDATA *,DWORD *); +typedef BOOL (CALLBACK *SNETDRAWDESCPROC )(DWORD,DWORD,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,LPDRAWITEMSTRUCT); +typedef BOOL (CALLBACK *SNETENUMDEVICESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMGAMESPROC )(DWORD,LPCSTR,LPCSTR); +typedef BOOL (CALLBACK *SNETENUMPROVIDERSPROC)(DWORD,LPCSTR,LPCSTR,SNETCAPSPTR); +typedef void (CALLBACK *SNETEVENTPROC )(SNETEVENTPTR); +typedef BOOL (CALLBACK *SNETGETARTPROC )(DWORD,DWORD,LPPALETTEENTRY,LPBYTE,DWORD,int *,int *,int *); +typedef BOOL (CALLBACK *SNETGETDATAPROC )(DWORD,DWORD,LPVOID,DWORD,DWORD *); +typedef int (CALLBACK *SNETMESSAGEBOXPROC )(HWND,LPCSTR,LPCSTR,UINT); +typedef BOOL (CALLBACK *SNETPLAYSOUNDPROC )(DWORD,DWORD,DWORD); +typedef BOOL (CALLBACK *SNETSELECTEDPROC )(DWORD,SNETCAPSPTR,_SNETUIDATA *,_SNETVERSIONDATA *); +typedef BOOL (CALLBACK *SNETSTATUSPROC )(LPCSTR,DWORD,DWORD,DWORD,SNETABORTPROC); + +typedef struct _SNETPLAYERDATA { + DWORD size; + LPCSTR playername; + LPCSTR playerdescription; +} SNETPLAYERDATA, *SNETPLAYERDATAPTR; + +typedef struct _SNETPROGRAMDATA { + DWORD size; + LPCSTR programname; + LPCSTR programdescription; + DWORD programid; + DWORD versionid; + DWORD reserved1; + DWORD maxplayers; + LPVOID initdata; + DWORD initdatabytes; + LPVOID reserved2; + DWORD optcategorybits; +} SNETPROGRAMDATA, *SNETPROGRAMDATAPTR; + +typedef struct _SNETUIDATA { + DWORD size; + DWORD uiflags; + HWND parentwindow; + SNETGETARTPROC artcallback; + SNETCHECKAUTHPROC authcallback; + SNETCREATEPROC createcallback; + SNETDRAWDESCPROC drawdesccallback; + SNETSELECTEDPROC selectedcallback; + SNETMESSAGEBOXPROC messageboxcallback; + SNETPLAYSOUNDPROC soundcallback; + SNETSTATUSPROC statuscallback; + SNETGETDATAPROC getdatacallback; + SNETCATEGORYPROC categorycallback; +} SNETUIDATA, *SNETUIDATAPTR; + +typedef struct _SNETVERSIONDATA { + DWORD size; + LPCSTR versionstring; + LPCSTR executablefile; + LPCSTR originalarchivefile; + LPCSTR patcharchivefile; +} SNETVERSIONDATA, *SNETVERSIONDATAPTR; + +extern "C" BOOL APIENTRY SNetCreateGame (LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR gamedescription, + DWORD gamecategorybits, + LPVOID initdata, + DWORD initdatabytes, + DWORD maxplayers, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetDestroy (); +extern "C" BOOL APIENTRY SNetDropPlayer (DWORD playerid, DWORD exitcode); +extern "C" BOOL APIENTRY SNetEnumDevices (SNETENUMDEVICESPROC callback); +extern "C" BOOL APIENTRY SNetEnumGames (DWORD categorybits, + DWORD categorymask, + SNETENUMGAMESPROC callback, + DWORD *hintnextcall); +extern "C" BOOL APIENTRY SNetEnumProviders (SNETCAPSPTR mincaps, + SNETENUMPROVIDERSPROC callback); +extern "C" BOOL APIENTRY SNetGetGameInfo (DWORD index, + LPVOID buffer, + DWORD buffersize, + DWORD *byteswritten); +extern "C" BOOL APIENTRY SNetGetNetworkLatency (DWORD measurementtype, + DWORD *result); +extern "C" BOOL APIENTRY SNetGetNumPlayers (DWORD *firstplayerid, + DWORD *lastplayerid, + DWORD *activeplayers); +extern "C" BOOL APIENTRY SNetGetOwnerTurnsWaiting (DWORD *turns); +extern "C" BOOL APIENTRY SNetGetPerformanceData (DWORD counterid, + DWORD *countervalue, + DWORD *countertype, + LONG *counterscale, + LARGE_INTEGER *measurementtime, + LARGE_INTEGER *measurementfreq); +extern "C" BOOL APIENTRY SNetGetPlayerCaps (DWORD playerid, + SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetPlayerName (DWORD playerid, + LPSTR buffer, + DWORD buffersize); +extern "C" BOOL APIENTRY SNetGetProviderCaps (SNETCAPSPTR caps); +extern "C" BOOL APIENTRY SNetGetTurnsInTransit (DWORD *turns); +extern "C" BOOL APIENTRY SNetInitializeDevice (DWORD deviceid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetInitializeProvider (DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata); +extern "C" BOOL APIENTRY SNetJoinGame (DWORD gameid, + LPCSTR gamename, + LPCSTR gamepassword, + LPCSTR playername, + LPCSTR playerdescription, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetLeaveGame (DWORD exitcode); +extern "C" BOOL APIENTRY SNetPerformUpgrade (DWORD *upgradestatus); +extern "C" BOOL APIENTRY SNetReceiveMessage (DWORD *senderplayerid, + LPVOID *data, + DWORD *databytes); +extern "C" BOOL APIENTRY SNetReceiveTurns (DWORD firstplayerid, + DWORD arraysize, + LPVOID *arraydata, + LPDWORD arraydatabytes, + LPDWORD arrayplayerstatus); +extern "C" BOOL APIENTRY SNetRegisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); +extern "C" BOOL APIENTRY SNetResetLatencyMeasurements (); +extern "C" BOOL APIENTRY SNetSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern "C" BOOL APIENTRY SNetSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY SNetSendMessage (DWORD targetplayerid, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSendTurn (LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SNetSetBasePlayer (DWORD playerid); +extern "C" BOOL APIENTRY SNetSetGameMode (DWORD modeflags); +extern "C" BOOL APIENTRY SNetUnregisterEventHandler (DWORD eventid, + SNETEVENTPROC callback); + +/**************************************************************************** +* +* Networking service provider interface +* +***/ + +#define SNETSPI_MAXSTRINGLENGTH 128 + +typedef struct _SNETADDR { + BYTE address[16]; +} SNETADDR, *SNETADDRPTR; + +typedef struct _SNETSPI_DEVICELIST { + DWORD deviceid; + SNETCAPS devicecaps; + char devicename[SNETSPI_MAXSTRINGLENGTH]; + char devicedescription[SNETSPI_MAXSTRINGLENGTH]; + DWORD reserved; + _SNETSPI_DEVICELIST *next; +} SNETSPI_DEVICELIST, *SNETSPI_DEVICELISTPTR; + +typedef struct _SNETSPI_GAMELIST { + DWORD gameid; + DWORD gamemode; + DWORD creationtime; + SNETADDR owner; + DWORD ownerlatency; + DWORD ownerlasttime; + DWORD gamecategorybits; + char gamename[SNETSPI_MAXSTRINGLENGTH]; + char gamedescription[SNETSPI_MAXSTRINGLENGTH]; + _SNETSPI_GAMELIST *next; +} SNETSPI_GAMELIST, *SNETSPI_GAMELISTPTR; + +typedef struct _SNETSPI { + DWORD size; + BOOL (CALLBACK *CompareNetAddresses)(SNETADDRPTR,SNETADDRPTR,DWORD *); + BOOL (CALLBACK *Destroy)(); + BOOL (CALLBACK *Free)(SNETADDRPTR,LPVOID,DWORD); + BOOL (CALLBACK *FreeExternalMessage)(LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *GetGameInfo)(DWORD,LPCSTR,LPCSTR,SNETSPI_GAMELIST *); + BOOL (CALLBACK *GetPerformanceData)(DWORD,DWORD *,LARGE_INTEGER *,LARGE_INTEGER *); + BOOL (CALLBACK *Initialize)(SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,HANDLE); + BOOL (CALLBACK *InitializeDevice)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR); + BOOL (CALLBACK *LockDeviceList)(SNETSPI_DEVICELISTPTR *); + BOOL (CALLBACK *LockGameList)(DWORD,DWORD,SNETSPI_GAMELISTPTR *); + BOOL (CALLBACK *Receive)(SNETADDRPTR *,LPVOID *,DWORD *); + BOOL (CALLBACK *ReceiveExternalMessage)(LPCSTR *,LPCSTR *,LPCSTR *); + BOOL (CALLBACK *SelectGame)(DWORD,SNETPROGRAMDATAPTR,SNETPLAYERDATAPTR,SNETUIDATAPTR,SNETVERSIONDATAPTR,DWORD *); + BOOL (CALLBACK *Send)(DWORD,SNETADDRPTR *,LPVOID,DWORD); + BOOL (CALLBACK *SendExternalMessage)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPCSTR); + BOOL (CALLBACK *StartAdvertisingGame)(LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD,DWORD,DWORD); + BOOL (CALLBACK *StopAdvertisingGame)(); + BOOL (CALLBACK *UnlockDeviceList)(SNETSPI_DEVICELISTPTR); + BOOL (CALLBACK *UnlockGameList)(SNETSPI_GAMELISTPTR,DWORD *); +} SNETSPI, *SNETSPIPTR; + +typedef BOOL (APIENTRY *SNETSPIBIND )(DWORD,SNETSPIPTR *); +typedef BOOL (APIENTRY *SNETSPIQUERY)(DWORD,DWORD *,LPCSTR *,LPCSTR *,SNETCAPSPTR *); + +/**************************************************************************** +* +* Registry functions +* +***/ + +#define SREG_FLAG_USERSPECIFIC 0x00000001 +#define SREG_FLAG_BATTLENET 0x00000002 +#define SREG_FLAG_FLUSHTODISK 0x00000008 +#define SREG_FLAG_MULTISZ 0x00000080 + +extern "C" BOOL APIENTRY SRegLoadData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID buffer, + DWORD buffersize, + DWORD *bytesread); +extern "C" BOOL APIENTRY SRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars); +extern "C" BOOL APIENTRY SRegLoadValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD *value); +extern "C" BOOL APIENTRY SRegSaveData (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPVOID data, + DWORD databytes); +extern "C" BOOL APIENTRY SRegSaveString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPCTSTR string); +extern "C" BOOL APIENTRY SRegSaveValue (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + DWORD value); + +/**************************************************************************** +* +* Run-time library functions +* +***/ + +#define TRY goto trylabel; trylabel: +#define LEAVE goto finallylabel +#define FINALLY goto finallylabel; finallylabel: + +/**************************************************************************** +* +* Transparency functions +* +***/ + +typedef struct _HSTRANS { int unused; } *HSTRANS; +typedef HSTRANS HTRANS; + +extern "C" BOOL APIENTRY STransBlt (LPBYTE dest, + int destx, + int desty, + int destpitch, + HSTRANS transparency); +extern "C" BOOL APIENTRY STransBltUsingMask (LPBYTE dest, + LPBYTE source, + int destpitch, + int sourcepitch, + HSTRANS mask); +extern "C" BOOL APIENTRY STransCreate (LPBYTE bits, + int width, + int height, + int bitdepth, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransDelete (HSTRANS handle); +extern "C" BOOL APIENTRY STransDestroy (); +extern "C" BOOL APIENTRY STransDuplicate (HSTRANS source, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransIntersectDirtyArray (HSTRANS sourcemask, + LPBYTE dirtyarray, + BYTE dirtyarraymask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransInvertMask (HSTRANS sourcemask, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransLoad (LPCTSTR filename, + LPRECT rect, + COLORREF colorkey, + HSTRANS *handle); +extern "C" BOOL APIENTRY STransSetDirtyArrayInfo (int screencx, + int screency, + int cellcx, + int cellcy); +extern "C" BOOL APIENTRY STransUpdateDirtyArray (LPBYTE dirtyarray, + BYTE dirtyvalue, + int destx, + int desty, + HSTRANS transparency, + BOOL tracecontour); + +/**************************************************************************** +* +* Video functions +* +***/ + +#define SVID_FLAG_DOUBLESCANS 0x00000001 +#define SVID_FLAG_INTERPOLATE 0x00000002 +#define SVID_FLAG_AUTOQUALITY 0x00000008 +#define SVID_FLAG_1XSIZE 0x00000100 +#define SVID_FLAG_2XSIZE 0x00000200 +#define SVID_FLAG_AUTOSIZE 0x00000800 +#define SVID_FLAG_FILEHANDLE 0x00010000 +#define SVID_FLAG_PRELOAD 0x00020000 +#define SVID_FLAG_LOOP 0x00040000 +#define SVID_FLAG_FULLSCREEN 0x00080000 +#define SVID_FLAG_USECURRENTPALETTE 0x00100000 +#define SVID_FLAG_CLEARSCREEN 0x00200000 +#define SVID_FLAG_TOSCREEN 0x10000000 +#define SVID_FLAG_TOBUFFER 0x20000000 + +#define SVID_CUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_2XSIZE) +#define SVID_AUTOCUTSCENE (SVID_FLAG_TOSCREEN | SVID_FLAG_FULLSCREEN | SVID_FLAG_CLEARSCREEN | SVID_FLAG_AUTOSIZE | SVID_FLAG_AUTOQUALITY) + +#define SVID_QUALITY_LOW_SKIPSCANS SVID_FLAG_2XSIZE +#define SVID_QUALITY_LOW (SVID_FLAG_2XSIZE | SVID_FLAG_DOUBLESCANS) +#define SVID_QUALITY_HIGH_SKIPSCANS (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE) +#define SVID_QUALITY_HIGH (SVID_FLAG_2XSIZE | SVID_FLAG_INTERPOLATE | SVID_FLAG_DOUBLESCANS) + +typedef struct _HSVIDEO { int unused; } *HSVIDEO; + +typedef struct _SVIDPALETTEUSE { + DWORD size; + DWORD firstentry; + DWORD numentries; +} SVIDPALETTEUSE, *SVIDPALETTEUSEPTR; + +extern "C" BOOL APIENTRY SVidDestroy (); +extern "C" BOOL APIENTRY SVidGetPerformanceData (HSVIDEO video, + BOOL averageframems, + DWORD *framems, + BOOL averagepalettems, + DWORD *palettems); +extern "C" BOOL APIENTRY SVidGetSize (HSVIDEO video, + int *width, + int *height, + int *bitdepth = NULL); +extern "C" BOOL APIENTRY SVidInitialize (LPVOID directsound); +extern "C" BOOL APIENTRY SVidPlayBegin (LPCTSTR filename, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayBeginFromMemory (LPVOID sourceptr, + DWORD sourcebytes, + LPVOID destbuffer, + LPCRECT destrect, + LPSIZE destsize, + SVIDPALETTEUSEPTR paletteuse, + DWORD flags, + HSVIDEO *handle); +extern "C" BOOL APIENTRY SVidPlayContinue (); +extern "C" BOOL APIENTRY SVidPlayContinueSingle (HSVIDEO video, + BOOL forceupdate, + BOOL *updated); +extern "C" BOOL APIENTRY SVidPlayEnd (HSVIDEO video); + +/**************************************************************************** +* +* Storm global functions +* +***/ + +extern "C" BOOL APIENTRY StormDestroy (); + +/**************************************************************************** +* +* C++ Utility Classes and Templates +* +***/ + +#ifndef __cplusplus +extern "C++" +#endif + +/**************************************************************************** +* +* CCRITSECT -- Critical section class +* +***/ + +class CCritSect { + private: + CRITICAL_SECTION m_critsect; + public: + CCritSect () { InitializeCriticalSection(&m_critsect); } + ~CCritSect () { DeleteCriticalSection(&m_critsect); } + void inline Enter () { EnterCriticalSection(&m_critsect); } + void inline Leave () { LeaveCriticalSection(&m_critsect); } +}; + +/**************************************************************************** +* +* CLOCK -- Lock class +* +***/ + +class CLock { + + private: + + HANDLE m_mutexevent; + HANDLE m_readerevent; + LONG m_readercount; + + public: + + CLock () { + m_mutexevent = CreateEvent(NULL,FALSE,TRUE,NULL); + m_readerevent = CreateEvent(NULL,TRUE,FALSE,NULL); + m_readercount = -1; + } + + ~CLock () { + CloseHandle(m_readerevent); + CloseHandle(m_mutexevent); + } + + void inline Enter (BOOL forwriting) { + if (forwriting) + WaitForSingleObject(m_mutexevent,INFINITE); + else if (!InterlockedIncrement(&m_readercount)) { + WaitForSingleObject(m_mutexevent,INFINITE); + SetEvent(m_readerevent); + } + else + WaitForSingleObject(m_readerevent,INFINITE); + } + + void inline Leave (BOOL fromwriting) { + if (fromwriting) + SetEvent(m_mutexevent); + else if (InterlockedDecrement(&m_readercount) < 0) { + ResetEvent(m_readerevent); + SetEvent(m_mutexevent); + } + } + +}; + +/**************************************************************************** +* +* TLIST -- Linked list function templates +* +***/ + +//=========================================================================== +template +BOOL inline TListAdd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = *head; + *head = newptr; + return 1; +} +#define LISTADD(a,b) TListAdd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddEnd (T **head, T *rec, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && rec)) + return 0; + + T *newptr = (T *)SMemAlloc(sizeof(T),filename,linenumber,0); + if (!newptr) + return 0; + CopyMemory(newptr,rec,sizeof(T)); + newptr->next = NULL; + + T **next = head; + while (*next) + next = &(*next)->next; + *next = newptr; + + return 1; +} +#define LISTADDEND(a,b) TListAddEnd(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListAddPtr (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = *head; + *head = ptr; + return 1; +} +#define LISTADDPTR(a,b) TListAddPtr(a,b) + +//=========================================================================== +template +BOOL inline TListAddPtrEnd (T **head, T *ptr) { + if (!(head && ptr)) + return 0; + + ptr->next = NULL; + T **next = head; + while (*next) + next = &(*next)->next; + *next = ptr; + + return 1; +} +#define LISTADDPTREND(a,b) TListAddPtrEnd(a,b) + +//=========================================================================== +template +BOOL inline TListClear (T **head, LPCSTR filename = NULL, int linenumber = 0) { + if (!head) + return 0; + + while (*head) { + T *next = (*head)->next; + SMemFree(*head,filename,linenumber,0); + *head = next; + } + return 1; +} +#define LISTCLEAR(a) TListClear(a,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFree (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + SMemFree(ptr,filename,linenumber,0); + return (*next != NULL); +} +#define LISTFREE(a,b) TListFree(a,b,(LPCSTR)__FILE__,__LINE__) + +//=========================================================================== +template +BOOL inline TListFreePtr (T **head, T *ptr, LPCSTR filename = NULL, int linenumber = 0) { + if (!(head && ptr)) + return 0; + + T **next = head; + while (*next && (*next != ptr)) + next = &(*next)->next; + if (*next) + *next = (*next)->next; + + return (*next != NULL); +} +#define LISTFREEPTR(a,b) TListFreePtr(a,b,(LPCSTR)__FILE__,__LINE__) + +#ifndef __cplusplus +} // extern "C++" +#endif + +#endif // ifndef _STORM_H_ diff --git a/src/Uisrc/STORM.HLP b/src/Uisrc/STORM.HLP new file mode 100644 index 0000000..3a09005 Binary files /dev/null and b/src/Uisrc/STORM.HLP differ diff --git a/src/Uisrc/STORM.LIB b/src/Uisrc/STORM.LIB new file mode 100644 index 0000000..67499fd Binary files /dev/null and b/src/Uisrc/STORM.LIB differ diff --git a/src/Uisrc/TESTUI.CPP b/src/Uisrc/TESTUI.CPP new file mode 100644 index 0000000..8f9b309 --- /dev/null +++ b/src/Uisrc/TESTUI.CPP @@ -0,0 +1,151 @@ +//**************************************************************************** +// +// TESTUI.CPP +// Diablo UI test program +// +// By Michael O'Brien (9/12/96) +// +//**************************************************************************** + +#include +#include "storm.h" +#include "ui\diabloui.h" + +//**************************************************************************** +//**************************************************************************** +#define CLASS TEXT("TESTUICLASS") +#define TITLE TEXT("Diablo UI Test") +#define PROGRAMID 'DTST' +#define VERSIONID 1 +#define MAXPLAYERS 4 + +char szName[MAX_COMPUTERNAME_LENGTH+1] = "TestUI"; + + +//**************************************************************************** +//**************************************************************************** +BOOL Initialize (HINSTANCE instance) { + + // FOR DEBUG VERSIONS OF THE PROGRAM, SETUP STORM'S MOPAQ ARCHIVE SUPPORT + // SO THAT IT CAN READ FILES DIRECTLY FROM THE DISK (RATHER THAN ONLY FROM + // MOPAQ FILES) AND SO THAT FILE ACCESS IS BASED IN THE CURRENT DIRECTORY + // RATHER THAN THE EXECUTABLE DIRECTORY + { + TCHAR directory[MAX_PATH] = TEXT(""); + GetCurrentDirectory(MAX_PATH,directory); + SFileSetBasePath(directory); + SFileEnableDirectAccess(1); + } + + // INITIALIZE DIRECTDRAW + if (!SDrawAutoInitialize(instance,CLASS,TITLE)) { + SDrawMessageBox("Unable to initialize DirectDraw.",TITLE,0); + return 1; + } + + // REGISTER MESSAGE HANDLERS FOR THOSE MESSAGES THAT WILL BE HANDLED + // BY THE FRAME WINDOW + SMsgRegisterMessage(NULL,WM_PAINT,UiOnPaint); + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY Connect (SNETPROGRAMDATAPTR programdata, SNETPLAYERDATAPTR playerdata, DWORD *pdwLocalPlayer) { + // BUILD AN INTERFACE DATA RECORD + SNETUIDATA Interfacedata; + + ZeroMemory(&Interfacedata,sizeof(SNETUIDATA)); + Interfacedata.size = sizeof(SNETUIDATA); + Interfacedata.parentwindow = SDrawGetFrameWindow(); + Interfacedata.artcallback = UiArtCallback; + Interfacedata.createcallback = UiCreateGameCallback; + Interfacedata.drawdesccallback = UiDrawDescCallback; + Interfacedata.messageboxcallback = UiMessageBoxCallback; + Interfacedata.soundcallback = UiSoundCallback; + Interfacedata.authcallback = UiAuthCallback; + Interfacedata.getdatacallback = UiGetDataCallback; + Interfacedata.categorycallback = UiCategoryCallback; + + + // SELECT A NETWORK PROVIDER + while (UiSelectProvider(NULL, + programdata, + playerdata, + &Interfacedata, + NULL, + NULL)) { + + // SELECT A GAME + if (SNetSelectGame(SNET_SF_ALLOWCREATE, + programdata, + playerdata, + &Interfacedata, + NULL, + pdwLocalPlayer)) { + MessageBox(SDrawGetFrameWindow(), "Test", "Test", MB_OK); + return 1; + } + + } + + return 0; +} + + +//**************************************************************************** +//**************************************************************************** +int APIENTRY WinMain (HINSTANCE instance, HINSTANCE, LPSTR, int) { + + DWORD dwLocalPlayer; + char szDesc[256]; + TUIHEROINFO HeroInfo; + + + ShowCursor(FALSE); + + ZeroMemory(&HeroInfo, sizeof(HeroInfo)); + HeroInfo.level = 5; + HeroInfo.herorank = 3; + + if (!Initialize(instance)) { + ShowCursor(TRUE); + return 1; + } + + + // Must be called after storm is initialized + UiInitialize(); + + // BUILD A PROGRAM DATA RECORD + SNETPROGRAMDATA programdata; + ZeroMemory(&programdata,sizeof(SNETPROGRAMDATA)); + programdata.size = sizeof(SNETPROGRAMDATA); + programdata.programname = TITLE; + programdata.programid = PROGRAMID; + programdata.versionid = VERSIONID; + programdata.maxplayers = MAXPLAYERS; + programdata.initdata = NULL; + programdata.initdatabytes = 0; + + + // BUILD A PLAYER DATA RECORD + SNETPLAYERDATA playerdata; + ZeroMemory(&playerdata,sizeof(SNETPLAYERDATA)); + playerdata.size = sizeof(SNETPLAYERDATA); + playerdata.playername = szName; + playerdata.playerdescription = (LPSTR)szDesc; + + // Create player description string + UiCreatePlayerDescription(&HeroInfo, PROGRAMID, (LPSTR)szDesc); + + Connect(&programdata, &playerdata, &dwLocalPlayer); + + UiDestroy(); + StormDestroy(); + + ShowCursor(TRUE); + return 0; +} diff --git a/src/Uisrc/UI/ARROW.CUR b/src/Uisrc/UI/ARROW.CUR new file mode 100644 index 0000000..348f576 Binary files /dev/null and b/src/Uisrc/UI/ARROW.CUR differ diff --git a/src/Uisrc/UI/ARTFONT.CPP b/src/Uisrc/UI/ARTFONT.CPP new file mode 100644 index 0000000..8d26ec8 --- /dev/null +++ b/src/Uisrc/UI/ARTFONT.CPP @@ -0,0 +1,343 @@ +//**************************************************************************** +// artfont.cpp +// created 10.15.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" + + +//**************************************************************************** +//**************************************************************************** + + static TARTFONT sgHugeFont; + static TARTFONT sgHugeFontGray; + static TARTFONT sgBigFont; + static TARTFONT sgBigFontGray; + static TARTFONT sgMedFont; + static TARTFONT sgMedFontGray; + static TARTFONT sgSmallFont; + static TARTFONT sgSmallFontGray; + static TPARTFONT sgpCurrFont; + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSetHuge(void) { + sgpCurrFont = &sgHugeFont; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSetHugeGray(void) { + sgpCurrFont = &sgHugeFontGray; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSetBig(void) { + sgpCurrFont = &sgBigFont; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSetBigGray(void) { + sgpCurrFont = &sgBigFontGray; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSetMed(void) { + sgpCurrFont = &sgMedFont; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSetMedGray(void) { + sgpCurrFont = &sgMedFontGray; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSetSmall(void) { + sgpCurrFont = &sgSmallFont; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSetSmallGray(void) { + sgpCurrFont = &sgSmallFontGray; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontSet(int fontnum) { + switch (fontnum) { + case AF_HUGE: + ArtFontSetHuge(); + break; + case AF_HUGEGRAY: + ArtFontSetHugeGray(); + break; + case AF_BIG: + ArtFontSetBig(); + break; + case AF_BIGGRAY: + ArtFontSetBigGray(); + break; + case AF_MED: + ArtFontSetMed(); + break; + case AF_MEDGRAY: + ArtFontSetMedGray(); + break; + case AF_SMALL: + ArtFontSetSmall(); + break; + case AF_SMALLGRAY: + default: + ArtFontSetSmallGray(); + break; + } +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontInit(void) { + sgHugeFont.bValid = FALSE; + sgHugeFontGray.bValid = FALSE; + sgBigFont.bValid = FALSE; + sgBigFontGray.bValid = FALSE; + sgMedFont.bValid = FALSE; + sgMedFontGray.bValid = FALSE; + sgSmallFont.bValid = FALSE; + sgSmallFontGray.bValid = FALSE; + sgpCurrFont = NULL; +} + + +//**************************************************************************** +//**************************************************************************** +static void ArtFontDestroyFont(TPARTFONT pFont) { + if (! pFont->bValid) return; + + for (int index = 0; index < MAX_CHARS; index++) { + if (pFont->pCharData[index]) { + STransDelete(pFont->pCharData[index]); + pFont->pCharData[index] = NULL; + } + } + + pFont->bValid = FALSE; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontDestroy(void) { + ArtFontDestroyFont(&sgHugeFont); + ArtFontDestroyFont(&sgHugeFontGray); + ArtFontDestroyFont(&sgBigFont); + ArtFontDestroyFont(&sgBigFontGray); + ArtFontDestroyFont(&sgMedFont); + ArtFontDestroyFont(&sgMedFontGray); + ArtFontDestroyFont(&sgSmallFont); + ArtFontDestroyFont(&sgSmallFontGray); + + sgpCurrFont = NULL; +} + + +//**************************************************************************** +//**************************************************************************** +static void ArtFontLoadFont(TPARTFONT pFont, LPCSTR datafile, LPCSTR artfile) { + HSFILE file; + LPBYTE pFontBmp; + SIZE BmpSize; + + if (pFont->bValid) return; + + // load the font specs for the font + if (! SFileOpenFile(datafile, &file)) + return; + if (! SFileReadFile(file, &pFont->tFontSpecs, SFileGetFileSize(file))) { + SFileCloseFile(file); + return; + } + SFileCloseFile(file); + + // load the artwork for the font + UiLoadBmpFile(artfile, &pFontBmp, &BmpSize); + + memset(pFont->pCharData, 0, sizeof(sgBigFont.pCharData)); + if (pFontBmp) { + RECT rect; + // create an HTRANS for each character in the font + for (int index = 0; index <= MAX_CHARS; index++) { + if (! pFont->tFontSpecs.bCharWidths[index]) continue; + + rect.left = 0; + rect.right = pFont->tFontSpecs.bCharWidths[index]; + rect.top = index * pFont->tFontSpecs.bCharHeight; + rect.bottom = rect.top + pFont->tFontSpecs.bCharHeight - 1; + + STransCreate( + pFontBmp, + BmpSize.cx, + BmpSize.cy, + 8, + &rect, + PALETTEINDEX(32), + &pFont->pCharData[index] + ); + } + + pFont->bValid = TRUE; + FREE(pFontBmp); + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL ArtFontLoad(void) { + ArtFontLoadFont(&sgBigFont, "ui_art\\font30.bin", "ui_art\\font30g.pcx"); + ArtFontLoadFont(&sgBigFontGray, "ui_art\\font30.bin", "ui_art\\font30s.pcx"); + ArtFontLoadFont(&sgMedFont, "ui_art\\font24.bin", "ui_art\\font24g.pcx"); + ArtFontLoadFont(&sgMedFontGray, "ui_art\\font24.bin", "ui_art\\font24s.pcx"); + ArtFontLoadFont(&sgSmallFont, "ui_art\\font16.bin", "ui_art\\font16g.pcx"); + ArtFontLoadFont(&sgSmallFontGray, "ui_art\\font16.bin", "ui_art\\font16s.pcx"); + ArtFontLoadFont(&sgHugeFont, "ui_art\\font42.bin", "ui_art\\font42g.pcx"); + ArtFontLoadFont(&sgHugeFontGray, "ui_art\\font42.bin", "ui_art\\font42y.pcx"); + + return 1; +} + + +//**************************************************************************** +// return the height of the current font +//**************************************************************************** +int ArtFontHeight(void) { + if (! sgpCurrFont) return 0; + if (! sgpCurrFont->bValid) return 0; + return sgpCurrFont->tFontSpecs.bCharHeight; +} + + +//**************************************************************************** +//**************************************************************************** +int ArtFontGridWidth(void) { + if (! sgpCurrFont) return 0; + if (! sgpCurrFont->bValid) return 0; + + return sgpCurrFont->tFontSpecs.bCharWidth; +} + + +//**************************************************************************** +// calculate the witdth of the given string +//**************************************************************************** +int ArtFontPixelWidth(LPCTSTR text) { + unsigned char c; + int len = 0; + + if (! sgpCurrFont) return 0; + if (! sgpCurrFont->bValid) return 0; + + while (0 != (c = *text)) { + if (! sgpCurrFont->tFontSpecs.bCharWidths[c]) + len += sgpCurrFont->tFontSpecs.bCharWidth; + else + len += sgpCurrFont->tFontSpecs.bCharWidths[c]; + text++; + } + + return len; +} + + +//**************************************************************************** +//**************************************************************************** +int ArtFontWordLen(LPCTSTR text) { + unsigned char c; + int len = 0; + + if (! sgpCurrFont) return 0; + if (! sgpCurrFont->bValid) return 0; + + while (0 != (c = *text)) { + switch (c) { + case ' ': + case '\n': + return len; + + default: + if (! sgpCurrFont->tFontSpecs.bCharWidths[c]) + return len; + else + len += sgpCurrFont->tFontSpecs.bCharWidths[c]; + break; + } + text++; + } + return len; +} + + +//**************************************************************************** +//**************************************************************************** +void ArtFontDraw(LPCTSTR text, TPBMP dest, int x, int y) { + unsigned char c; + if (! dest) return; + if (! dest->data) return; + if (! sgpCurrFont) return; + if (! sgpCurrFont->bValid) return; + + if (x < 0) x = 0; + if (y < 0) y = 0; + + while (0 != (c = *text)) { + + // check for vertical overflow + if ((y + sgpCurrFont->tFontSpecs.bCharHeight) > dest->datasize.cy) + break; + + if (c == '\n') { + x = 0; + y += sgpCurrFont->tFontSpecs.bCharHeight; + text++; + } + else if (! sgpCurrFont->tFontSpecs.bCharWidths[c]) { // word break + if ((x + sgpCurrFont->tFontSpecs.bCharWidth + ArtFontWordLen(text+1)) >= dest->datasize.cx) { // line overrun + x = 0; + y += sgpCurrFont->tFontSpecs.bCharHeight; + } + else { + x += sgpCurrFont->tFontSpecs.bCharWidth; + } + text++; + } + else if (sgpCurrFont->pCharData[c]) { + if ((x + sgpCurrFont->tFontSpecs.bCharWidths[c]) > dest->datasize.cx) { + x = 0; + y += sgpCurrFont->tFontSpecs.bCharHeight; + continue; + } + + STransBlt(dest->data, x, y, dest->datasize.cx, sgpCurrFont->pCharData[c]); + x += sgpCurrFont->tFontSpecs.bCharWidths[c]; + // advance char + text++; + } + } +} \ No newline at end of file diff --git a/src/Uisrc/UI/ARTFONT.H b/src/Uisrc/UI/ARTFONT.H new file mode 100644 index 0000000..91f2fa5 --- /dev/null +++ b/src/Uisrc/UI/ARTFONT.H @@ -0,0 +1,52 @@ +//**************************************************************************** +// artfont.h +// created 10.15.96 +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** + #define MAX_CHARS 256 + + enum _artfonts { + AF_SMALL, + AF_SMALLGRAY, + AF_MED, + AF_MEDGRAY, + AF_BIG, + AF_BIGGRAY, + AF_HUGE, + AF_HUGEGRAY + }; + + typedef struct _fontspecs { + BYTE bCharWidth; // max char width + BYTE bCharHeight; // max char height + BYTE bCharWidths[MAX_CHARS]; // actual char widths + } TFONTSPECS, * TPFONTSPECS; + + typedef struct _artfont { + TFONTSPECS tFontSpecs; + HTRANS pCharData[MAX_CHARS]; + BOOL bValid; + } TARTFONT, * TPARTFONT; + + +//**************************************************************************** +//**************************************************************************** + void ArtFontInit(void); + void ArtFontDestroy(void); + BOOL ArtFontLoad(void); + + void ArtFontSetBig(void); + void ArtFontSetBigGray(void); + void ArtFontSetMed(void); + void ArtFontSetMedGray(void); + void ArtFontSetSmall(void); + void ArtFontSetSmallGray(void); + void ArtFontSet(int fontnum); + + void ArtFontDraw(LPCSTR text, TPBMP dest, int x, int y); + int ArtFontGridWidth(void); + int ArtFontPixelWidth(LPCSTR text); + int ArtFontHeight(void); diff --git a/src/Uisrc/UI/BNET.H b/src/Uisrc/UI/BNET.H new file mode 100644 index 0000000..bc76501 --- /dev/null +++ b/src/Uisrc/UI/BNET.H @@ -0,0 +1,33 @@ +/**************************************************************************** +* +* bnet.h +* BattleNet Chat Room +* +* By Michael Morhaime +* +***/ + + +#define PROVIDERID 'BATL' +#define BATTLENET_MAXPLAYERS 256 +typedef struct _UIPARAMS { + DWORD flags; + SNETPROGRAMDATAPTR programdata; + SNETPLAYERDATAPTR playerdata; + SNETUIDATAPTR interfacedata; + SNETVERSIONDATAPTR versiondata; + LPDWORD playeridptr; +} UIPARAMS, *UIPARAMSPTR; + + + +BOOL DoLoadArtwork (SNETGETARTPROC artcallback, + HWND hWnd, + HWND hWndParent, + DWORD artid, + LPCTSTR controltype, + DWORD controlstyle, + LONG usageflags, + BOOL setpalette, + LPBYTE *data, + SIZE *size); diff --git a/src/Uisrc/UI/BUT_SML.RAW b/src/Uisrc/UI/BUT_SML.RAW new file mode 100644 index 0000000..73e89ea --- /dev/null +++ b/src/Uisrc/UI/BUT_SML.RAW @@ -0,0 +1 @@ +·¸¸ºººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººº¸¸·ÿÿ¸²°³´³³´³°°°°°°°°°°°°±²²²±°°°°°°°°²²²²²²²²²²²²²²²²²²²²²²²°°°°²°°°°°°°°°°°±±°°°³³´³°°°°°°°°°°°°±²²²±°°°°³´³±°²¸ÿÿ¸°¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿°¸ÿÿº°¿·¹ºººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººº¹·¿°ºÿÿº±¿»¸¸ºº¹ºººººº¹¹¹¹ººº¹¹ºººº¹¹ººººº¹¹¹ººººººº¹¹¹ººººººº¹ºº¹ºººººº¹ººº¹¹¹¹ºº¹¹¹ººº¹ºººººº¹¹¹¹ººº¹¹ºººº¹¹º¸¸¼¿±ºÿÿº³¿»¼º·¶¶µµ´´´´±±³³µ¶¶¶¶¶¶µ¶·¸¸¸¸¸·¸¹¸··¸¸¸¹·¸¹¸¶¸¸¸¹·¹··¶¶µµ¶¶¶···¸··¸¹¸¹¸¸·¸··¶¶µµ´´´´±±³³µ¶¶¶¶¶¶µ¶·¸·º¼½¿³ºÿÿ·´¿¼½½····¶µ´¶µ³´´µµµ¶·¸¶¶¶·¸¸¹¸¸º¸¸¸····¶¸··¶¶·¸·¸¸¸¸¸¹¹··¶··¸·¸¸¸¸¹¹¸¹¹¸¸¸··¸····¶µ´¶µ³´´µµµ¶·¸¶¶¶···¸¼½¼¿´ºÿÿ¶µ¿»½½·¶¶¶¶µµµ´´µµµµ¶··¸¸¸¸·¸¹¹¸¸¸¸¸¸¶¶µµµµ·¶´µ·µ¶··¸¸¸¸¸¸¸···¸¸¸¸¸¸¹·¹¸¹¸·¸·¸··¶¶¶¶µµµ´´µµµµ¶··¸¸¸¸··¸·½½½¿³¸ÿÿ¶µ¿»½½·¶¶¶¶µµµ´´µµµµ¶··¸¸¸¸·¸¹¹¸¸·¶¸¶·¶µµµµ¶¶´µ¶¶··¸¸¸·¸·¸·····¸¸¸¸¸¹·¹¸¹¸·¸·¸··¶¶¶¶µµµ´´µµµµ¶··¸¸¸¸··¸·½½½¿³¸ÿÿ¸³¿¼½½··¶¶¸¶¶µ´´¶¶´µ¶¶¶¶·¸¸¸¸¸¸····¸¸¸···¶µ´µ¶µ´µ¶¶¶¶·¸··¸¸¸····¹º¹¸¸¸¸·¸¸··¶¶¸··¶¶¸¶¶µ´´¶¶´µ¶¶¶¶·¸¸¸¶¶¸½½½¿±¸ÿÿ¸³¿½½½¸¸··¶¶µµ´¶·¶¸·¸¸¸¸·¸·¸·¶¶µµµ¶¶··¶··¸¸·¶¶···¶¶¶µµ¶¶····¶¶·¸¸¸¸··¸¹¹¸···¶¸¸¸··¶¶¶µµ¶¸¸¹·¶¸·¸¸¸¸··¶·¸½½½¿°¹ÿÿ·³¿¼½¼¸¹¸¶·¶µ´µµ¶¶···¸······µ¶·¶¶¶µ·¸¸·······¶¶¶µ¶¶¶¶¶¶µµ··¶¶¶¶···¸·¸¸¸¸···¸¶·¸¸¸¸¶¶¶·¶¶··¸¸·····¸¸·¶···¼½½¿°ºÿÿ·³¿¼½½¹¹¹¸··¸¶µ¶¶¶··¶µ··¸···¶¶¶µ¶¶µ·¶·¸·¶··¶¶µµµ¶·¶¶¶¶¶¶¶¶¶µµµ¶········¸¸·····¶¸·¸·µ··¶·µ¶¶¸·¶¶··¸¸··¸¸·½½½¿°ºÿÿ¶³¿»½½···¸¹···¶¶·¸¸·¶··¸¸¸¸····¶¶··¶¶¶¶¶¶¶¶·µµµµ¶¶µ¶¶´µ´µµµ¶¶¶····¶¶¶¶¶¶·········¸¶µ¶¶·µµ··¸····¸···¸·¸¹¼½¼¿±ºÿÿ·³¿¼½½·¶¶·¸····¶¶¶·······¸···¶·¶¶µ····¶·¶·¶¶¶¶¶¶¶¶·¶µ¶´´´´¶·¶¶·¶···¶¶¶¶¶¶··¸¸·¶·¸¸·¶·¸··¶¶···¸··¸¸¸¸·¸·¸½½½¿±¸ÿÿº´¿½½½··¶·¸¸¸¸¶······¶·¸····¶¶·¶µ¶µ····¶¶·¶¶··¶····¶¶¶¶¶µ¶µµ¶¶¶¶¶¶µµµ¶¶¶¶·····¶····¸········¸···¸···¸···½½½¿°¹ÿÿ¸µ¿¼½¼¸¸··¶¸·¸¸¶··¸···¸¸·¶¶¶¶¶¶¶¶¶µ¶¶·¶¶¶···¶··¸····¶µ¶·¶¶·¶¶¶¶µ¶µ¶µµµµ¶µµ·¸¸¶¶·¸¸···¸¸·¶·¸···¸¸··¶·¸··µ½½½¿°ºÿÿ¸³¿½½½¸¹¸¶¶¸¸¸···¸·¸¸¶·¶·¶¶¶¶¶·¶¶¶¶··¶¶¶µµ¶¶··¶·····µ¶¶¶¶¶¶¶·¶¶¶¶¶¶¶·¶¶¶µµ¶·¸···¸¸¸¸···¶·····¸·¸··¶¶¶¶¶·¼¼½¿°ºÿÿ¸³¿½½½¹¹¹·¶····¸¸¸¸¸¸·¶¶¶µ´µ¶··¶·¸·¸¶¶¶µ´µ¶····¸¸·¶µµ¶¶¶¶¶¶¶¶¶¶¸··¶¶¶··¶µµ¶¶·¶··¸¸·¸·¶·µ··¸¹¸¸¶·¶¶¶µµ¶¶¶¼¼½¿°ºÿÿ¸³¿½½½¶···¸·¶··¸¸¸·¶······¸·¶¶¶¶¶·¶··¸¸¸¶··¸¸¸··¶¶¶¶·¶···¶····¸¸¶····¸¸·¸¸¸¸¸··¶¶¶¶¶¶¶¶¶¶¶¶¶¶µ·¶µ³³´µ¶¶¸¼¼½¿²ºÿÿ¸³¿½½½¶····¸¶····¸¸·¸¹¸¹¸··¶¶¶¶¶¶¶¶····¸¶····¸¸·¶¶¶¶·¶···¶····¸¸¶····¸¸·¸¸¸¸¸··¶¶¶¶¶¶¶¶¶¶¶¶¶¶µµµ³³´´µ¶¶¸¼¼½¿°ºÿÿº²¿»½½¶¶¶¶¶¶··¹·¹¸¸·¸¹¹¹¹¹¸¹¸¸·¶¶¶¶¶¶¶¶¶··¹·¹¸¸·¶¶µµµµµµ¶·¶¹¶··µ··¹·¹¸¸·¸¹¹¹¹¹¸¹¸¸·¶¶¶¶¶¶¶¶¶µµµ³´´µµµ¶¶¶¼¼½¿°ºÿÿº±¾¼½½ºº»»¹¸¹»¹ºº¹¹¹¹º¹º¹º¹º¹¸¹¹¹º¹»¹¸»¹¸¹¹¹»¹¹¸··¸·¹··¹·º¸¸¸¸¹¸¹·¸¸¸¸¸¹¸¹¸··¶··¸¸¸¹¹»¹¸¸¹¹¹»¹¹»¹¸¹¹¹¹¹¹½¼½¿³»ÿÿº´¾»¼½½½¼¼¼½½½¼½½½½½½½½¼½½½½½½½¼½¼½½½½½½½½½¼½¼½½¼½¼½½½½½½½½½¼½¼½½½½¼½¼½½½½½½½¼½¼½½½½½¼½¼½½¼¼¼½½½½¼¼¼½¼½½¼½½¿´µÿÿ¹²¾½½¼½½¼¼¼½½½¼½½½½½½½½¼½½½½½½½¼½¼½½½½½½½½½¼½¼½½¼½¼½½½½½½½½½¼½¼½½½½¼½¼½½½½½½½¼½¼½½½½½¼½¼½½¼¼¼½½½½¼¼¼½¼½½¼½½¿²¶ÿÿ¸°¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿°¸ÿÿ¸²°°±³´³°°°±±°°°°°°°°°°°²°°°°²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²°°°°°°°°±²²²±°°°°°°°°°°°°°³´³±°°²¸ÿÿ·¸¸ºººº¸¹ººººººººººººººººººº¹¸···¸¸···¸¸¸¹ºº¹¸····¸¸···¸¸¸¹ºº¹¸¸¸¹ºº¹¸···¸¸¸¹ºº¹¸··¸¸ºººº¸¸ººººººººººº¸ºººº¸¸·ÿÿ·¸¸ºººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººº¸¸·ÿÿ¸²°³´³³´³°°°°°°°°°°°°±²²²±°°°°°°°°²²²²²²²²²²²²²²²²²²²²²²²°°°°²°°°°°°°°°°°±±°°°³³´³°°°°°°°°°°°°±²²²±°°°°³´³±°²¸ÿÿ¸°¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾°¸ÿÿº°¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾°ºÿÿº±¾¾¹º»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»º¹±ºÿÿº³¾¾»ºº»»º»»»»»»ºººº»»»ºº»»»»ºº»»»»»ººº»»»»»»»ººº»»»»»»»º»»º»»»»»»º»»»ºººº»»ººº»»»º»»»»»»ºººº»»»ºº»»»»ºº»ºº¼³ºÿÿ·´¾¾»¼»¹¸¸¸¸····µµ··¸¸¸¸¸¸¸¸¸¹ººººº¹ººº¹¹ºººº¹ººº¸ºººº¹º¹¹¸¸¸¸¸¸¸¹¹¹º¹¹ºººººº¹º¹¹¸¸¸¸····µµ··¸¸¸¸¸¸¸¸¸¹º¹»¼½´ºÿÿ¶µ¾¾¼½½¹¹¹¹¸¸·¸¸···¸¸¸¸¹º¸¸¸¹ººººº»ººº¹¹¹¹¸º¹¹¸¸¹º¹ººººººº¹¹¸¹¹º¹ºººººººººººº¹¹º¹¹¹¹¸¸·¸¸···¸¸¸¸¹º¸¸¸¹¹¹º¼½¼³¸ÿÿ¶µ¾¾»½½¹¸¸¸¸¸¸¸··¸¸¸¸¸¹¹ºººº¹ººººººººº¸¸¸¸¸¸¹¸·¸¹¸¸¹¹ººººººº¹¹¹ººººººº¹ºººº¹º¹º¹¹¸¸¸¸¸¸¸··¸¸¸¸¸¹¹ºººº¹¹º¹½½½³¸ÿÿ¸³¾¾»½½¹¸¸¸¸¸¸¸··¸¸¸¸¸¹¹ºººº¹ººººº¹¸º¸¹¸¸¸¸¸¸¸·¸¸¸¹¹ººº¹º¹º¹¹¹¹¹ºººººº¹ºººº¹º¹º¹¹¸¸¸¸¸¸¸··¸¸¸¸¸¹¹ºººº¹¹º¹½½½±¸ÿÿ¸³¾¾¼½½¹¹¸¸º¸¸¸··¸¸·¸¸¸¸¸¹ºººººº¹¹¹¹ººº¹¹¹¸¸·¸¸¸·¸¸¸¸¸¹º¹¹ººº¹¹¹¹º»ººººº¹ºº¹¹¸¸º¹¹¸¸º¸¸¸··¸¸·¸¸¸¸¸¹ººº¸¸º½½½°¹ÿÿ·³¾¾½½½ºº¹¹¸¸¸¸·¸¹¸º¹ºººº¹º¹º¹¸¸¸¸¸¸¸¹¹¸¹¹ºº¹¸¸¹¹¹¸¸¸¸¸¸¸¹¹¹¹¸¸¹ºººº¹¹ºººº¹¹¹¸ººº¹¹¸¸¸¸¸¸ººº¹¸º¹ºººº¹¹¸¹º½½½°ºÿÿ·³¾¾¼½¼ººº¸¹¸¸·¸¸¸¸¹¹¹º¹¹¹¹¹¹¸¸¹¸¸¸¸¹ºº¹¹¹¹¹¹¹¸¸¸¸¸¸¸¸¸¸¸¸¹¹¸¸¸¸¹¹¹º¹ºººº¹¹¹º¸¹ºººº¸¸¸¹¸¸¹¹ºº¹¹¹¹¹ºº¹¸¹¹¹¼½½°ºÿÿ¶³¾¾¼½½ºººº¹¹º¸¸¸¸¸¹¹¸¸¹¹º¹¹¹¸¸¸¸¸¸¸¹¸¹º¹¸¹¹¸¸¸¸¸¸¹¸¸¸¸¸¸¸¸¸¸¸¸¸¹¹¹¹¹¹¹¹ºº¹¹¹¹¹¸º¹º¹¸¹¹¸¹¸¸¸º¹¸¸¹¹ºº¹¹ºº¹½½½±ºÿÿ·³¾¾»½½¹¹¹ºº¹¹¹¸¸¹ºº¹¸¹¹ºººº¹¹¹¹¸¸¹¹¸¸¸¸¸¸¸¸¹¸¸¸¸¸¸¸¸¸·¸·¸¸¸¸¸¸¹¹¹¹¸¸¸¸¸¸¹¹¹¹¹¹¹¹¹º¸¸¸¸¹¸¸¹¹º¹¹¹¹º¹¹¹º¹ºº¼½¼±¸ÿÿº´¾¾¼½½¹¸¸¹º¹¹¹¹¸¸¸¹¹¹¹¹¹¹º¹¹¹¸¹¸¸¸¹¹¹¹¸¹¸¹¸¸¸¸¸¸¸¸¹¸¸¸····¸¹¸¸¹¸¹¹¹¸¸¸¸¸¸¹¹ºº¹¸¹ºº¹¸¹º¹¹¸¸¹¹¹º¹¹ºººº¹º¹º½½½°¹ÿÿ¸µ¾¾½½½¹¹¸¹ºººº¸¹¹¹¹¹¹¸¹º¹¹¹¹¸¸¹¸¸¸¸¹¹¹¹¸¸¹¸¸¹¹¸¹¹¹¹¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¹¹¹¹¹¸¹¹¹¹º¹¹¹¹¹¹¹¹º¹¹¹º¹¹¹º¹¹¹½½½°ºÿÿ¸³¾¾¼½¼ºº¹¹¸º¹ºº¸¹¹º¹¹¹ºº¹¸¸¸¸¸¸¸¸¸¸¸¸¹¸¸¸¹¹¹¸¹¹º¹¹¹¹¸¸¸¹¸¸¹¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¹ºº¸¸¹ºº¹¹¹ºº¹¸¹º¹¹¹ºº¹¹¸¹º¹¹¸½½½°ºÿÿ¸³¾¾½½½ººº¸¸ººº¹¹¹º¹ºº¸¹¸¹¸¸¸¸¸¹¸¸¸¸¹¹¸¸¸¸¸¸¸¹¹¸¹¹¹¹¹¸¸¸¸¸¸¸¸¹¸¸¸¸¸¸¸¹¸¸¸¸¸¸¹º¹¹¹ºººº¹¹¹¸¹¹¹¹¹º¹º¹¹¸¸¸¸¸¹¼¼½°ºÿÿ¸³¾¾½½½ººº¹¸¹¹¹¹ºººººº¹¸¸¸¸·¸¸¹¹¸¹º¹º¸¸¸¸·¸¸¹¹¹¹ºº¹¸¸¸¸¸¸¸¸¸¸¸¸¸º¹¹¸¸¸¹¹¸¸¸¸¸¹¸¹¹ºº¹º¹¸¹¸¹¹ºººº¸¹¸¸¸¸¸¸¸¸¼¼½²ºÿÿ¸³¾¾½½½¸¹¹¹º¹¸¹¹ººº¹¸¹¹¹¹¹¹º¹¸¸¸¸¸¹¸¹¹ººº¸¹¹ººº¹¹¸¸¸¸¹¸¹¹¹¸¹¹¹¹ºº¸¹¹¹¹ºº¹ººººº¹¹¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¹¸¸···¸¸¸º¼¼½°ºÿÿº²¾¾½½½¸¹¹¹¹º¸¹¹¹¹ºº¹ººººº¹¹¸¸¸¸¸¸¸¸¹¹¹¹º¸¹¹¹¹ºº¹¸¸¸¸¹¸¹¹¹¸¹¹¹¹ºº¸¹¹¹¹ºº¹ººººº¹¹¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸····¸¸¸º¼¼½°ºÿÿº±¾¾»½½¸¸¸¸¸¸¹¹º¹ººº¹ºººººººººº¹¸¸¸¸¸¸¸¸¸¹¹º¹ººº¹¸¸¸¸¸¸¸¸¸¹¸º¸¹¹¸¹¹º¹ººº¹ºººººººººº¹¸¸¸¸¸¸¸¸¸¸¸¸···¸¸¸¸¸¸¼¼½³»ÿÿº´¾¾¼½½»»»»ººº»º»»ºººº»º»º»º»ººººº»º»ºº»ººººº»ººº¹¹º¹º¹¹º¹»ººººººº¹ººººººººº¹¹¸¹¹ººººº»ºººººº»ºº»ºººººººº½¼½´µÿÿ¹²¾¾»¼½½½¼¼¼½½½¼½½½½½½½½¼½½½½½½½¼½¼½½½½½½½½½¼½¼½½¼½¼½½½½½½½½½¼½¼½½½½¼½¼½½½½½½½¼½¼½½½½½¼½¼½½¼¼¼½½½½¼¼¼½¼½½¼½½²¶ÿÿ¸°¾¾½½¼½½¼¼¼½½½¼½½½½½½½½¼½½½½½½½¼½¼½½½½½½½½½¼½¼½½¼½¼½½½½½½½½½¼½¼½½½½¼½¼½½½½½½½¼½¼½½½½½¼½¼½½¼¼¼½½½½¼¼¼½¼½½¼½½°¸ÿÿ¸²°°±³´³°°°±±°°°°°°°°°°°²°°°°²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²°°°°°°°°±²²²±°°°°°°°°°°°°°³´³±°°²¸ÿÿ·¸¸ºººº¸¹ººººººººººººººººººº¹¸···¸¸···¸¸¸¹ºº¹¸····¸¸···¸¸¸¹ºº¹¸¸¸¹ºº¹¸···¸¸¸¹ºº¹¸··¸¸ºººº¸¸ººººººººººº¸ºººº¸¸·ÿÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ÿÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ÿÿ€€¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿€€ÿÿ€€¿·¹ºººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººº¹·¿€€ÿÿ€€¿»¸¸ºº¹ºººººº¹¹¹¹ººº¹¹ºººº¹¹ººººº¹¹¹ººººººº¹¹¹ººººººº¹ºº¹ºººººº¹ººº¹¹¹¹ºº¹¹¹ººº¹ºººººº¹¹¹¹ººº¹¹ºººº¹¹º¸¸¼¿€€ÿÿ€€¿»¼º·¶¶µµ´´´´±±³³µ¶¶¶¶¶¶µ¶·¸¸¸¸¸·¸¹¸··¸¸¸¹·¸¹¸¶¸¸¸¹·¹··¶¶µµ¶¶¶···¸··¸¹¸¹¸¸·¸··¶¶µµ´´´´±±³³µ¶¶¶¶¶¶µ¶·¸·º¼½¿€€ÿÿ€€¿¼½½····¶µ´¶µ³´´µµµ¶·¸¶¶¶·¸¸¹¸¸º¸¸¸····¶¸··¶¶·¸·¸¸¸¸¸¹¹··¶··¸·¸¸¸¸¹¹¸¹¹¸¸¸··¸····¶µ´¶µ³´´µµµ¶·¸¶¶¶···¸¼½¼¿€€ÿÿ€€¿»½½·¶¶¶¶µµµ´´µµµµ¶··¸¸¸¸·¸¹¹¸¸¸¸¸¸¶¶µµµµ·¶´µ·µ¶··¸¸¸¸¸¸¸···¸¸¸¸¸¸¹·¹¸¹¸·¸·¸··¶¶¶¶µµµ´´µµµµ¶··¸¸¸¸··¸·½½½¿€€ÿÿ€€¿»½½·¶¶¶¶µµµ´´µµµµ¶··¸¸¸¸·¸¹¹¸¸·¶¸¶·¶µµµµ¶¶´µ¶¶··¸¸¸·¸·¸·····¸¸¸¸¸¹·¹¸¹¸·¸·¸··¶¶¶¶µµµ´´µµµµ¶··¸¸¸¸··¸·½½½¿€€ÿÿ€€¿¼½½··¶¶¸¶¶µ´´¶¶´µ¶¶¶¶·¸¸¸¸¸¸····¸¸¸···¶µ´µ¶µ´µ¶¶¶¶·¸··¸¸¸····¹º¹¸¸¸¸·¸¸··¶¶¸··¶¶¸¶¶µ´´¶¶´µ¶¶¶¶·¸¸¸¶¶¸½½½¿€€ÿÿ€€¿½½½¸¸··¶¶µµ´¶·¶¸·¸¸¸¸·¸·¸·¶¶µµµ¶¶··¶··¸¸·¶¶···¶¶¶µµ¶¶····¶¶·¸¸¸¸··¸¹¹¸···¶¸¸¸··¶¶¶µµ¶¸¸¹·¶¸·¸¸¸¸··¶·¸½½½¿€€ÿÿ€€¿¼½¼¸¹¸¶·¶µ´µµ¶¶···¸······µ¶·¶¶¶µ·¸¸·······¶¶¶µ¶¶¶¶¶¶µµ··¶¶¶¶···¸·¸¸¸¸···¸¶·¸¸¸¸¶¶¶·¶¶··¸¸·····¸¸·¶···¼½½¿€€ÿÿ€€¿¼½½¹¹¹¸··¸¶µ¶¶¶··¶µ··¸···¶¶¶µ¶¶µ·¶·¸·¶··¶¶µµµ¶·¶¶¶¶¶¶¶¶¶µµµ¶········¸¸·····¶¸·¸·µ··¶·µ¶¶¸·¶¶··¸¸··¸¸·½½½¿€€ÿÿ€€¿»½½···¸¹···¶¶·¸¸·¶··¸¸¸¸····¶¶··¶¶¶¶¶¶¶¶·µµµµ¶¶µ¶¶´µ´µµµ¶¶¶····¶¶¶¶¶¶·········¸¶µ¶¶·µµ··¸····¸···¸·¸¹¼½¼¿€€ÿÿ€€¿¼½½·¶¶·¸····¶¶¶·······¸···¶·¶¶µ····¶·¶·¶¶¶¶¶¶¶¶·¶µ¶´´´´¶·¶¶·¶···¶¶¶¶¶¶··¸¸·¶·¸¸·¶·¸··¶¶···¸··¸¸¸¸·¸·¸½½½¿€€ÿÿ€€¿½½½··¶·¸¸¸¸¶······¶·¸····¶¶·¶µ¶µ····¶¶·¶¶··¶····¶¶¶¶¶µ¶µµ¶¶¶¶¶¶µµµ¶¶¶¶·····¶····¸········¸···¸···¸···½½½¿€€ÿÿ€€¿¼½¼¸¸··¶¸·¸¸¶··¸···¸¸·¶¶¶¶¶¶¶¶¶µ¶¶·¶¶¶···¶··¸····¶µ¶·¶¶·¶¶¶¶µ¶µ¶µµµµ¶µµ·¸¸¶¶·¸¸···¸¸·¶·¸···¸¸··¶·¸··µ½½½¿€€öÿ€€¿½½½¸¹¸¶¶¸¸¸···¸·¸¸¶·¶·¶¶¶¶¶·¶¶¶¶··¶¶¶µµ¶¶··¶·····µ¶¶¶¶¶¶¶·¶¶¶¶¶¶¶·¶¶¶µµ¶·¸···¸¸¸¸···¶·····¸·¸··¶¶¶¶¶·¼¼½¿€€öÿ€€¿½½½¹¹¹·¶····¸¸¸¸¸¸·¶¶¶µ´µ¶··¶·¸·¸¶¶¶µ´µ¶····¸¸·¶µµ¶¶¶¶¶¶¶¶¶¶¸··¶¶¶··¶µµ¶¶·¶··¸¸·¸·¶·µ··¸¹¸¸¶·¶¶¶µµ¶¶¶¼¼½¿€€öÿ€€¿½½½¶···¸·¶··¸¸¸·¶······¸·¶¶¶¶¶·¶··¸¸¸¶··¸¸¸··¶¶¶¶·¶···¶····¸¸¶····¸¸·¸¸¸¸¸··¶¶¶¶¶¶¶¶¶¶¶¶¶¶µ·¶µ³³´µ¶¶¸¼¼½¿€€öÿ€€¿½½½¶····¸¶····¸¸·¸¹¸¹¸··¶¶¶¶¶¶¶¶····¸¶····¸¸·¶¶¶¶·¶···¶····¸¸¶····¸¸·¸¸¸¸¸··¶¶¶¶¶¶¶¶¶¶¶¶¶¶µµµ³³´´µ¶¶¸¼¼½¿€€öÿ€€¿»½½¶¶¶¶¶¶··¹·¹¸¸·¸¹¹¹¹¹¸¹¸¸·¶¶¶¶¶¶¶¶¶··¹·¹¸¸·¶¶µµµµµµ¶·¶¹¶··µ··¹·¹¸¸·¸¹¹¹¹¹¸¹¸¸·¶¶¶¶¶¶¶¶¶µµµ³´´µµµ¶¶¶¼¼½¿€€öÿ€€¾¼½½ºº»»¹¸¹»¹ºº¹¹¹¹º¹º¹º¹º¹¸¹¹¹º¹»¹¸»¹¸¹¹¹»¹¹¸··¸·¹··¹·º¸¸¸¸¹¸¹·¸¸¸¸¸¹¸¹¸··¶··¸¸¸¹¹»¹¸¸¹¹¹»¹¹»¹¸¹¹¹¹¹¹½¼½¿€€öÿ€€¾»¼½½½¼¼¼½½½¼½½½½½½½½¼½½½½½½½¼½¼½½½½½½½½½¼½¼½½¼½¼½½½½½½½½½¼½¼½½½½¼½¼½½½½½½½¼½¼½½½½½¼½¼½½¼¼¼½½½½¼¼¼½¼½½¼½½¿€€öÿ€€¾½½¼½½¼¼¼½½½¼½½½½½½½½¼½½½½½½½¼½¼½½½½½½½½½¼½¼½½¼½¼½½½½½½½½½¼½¼½½½½¼½¼½½½½½½½¼½¼½½½½½¼½¼½½¼¼¼½½½½¼¼¼½¼½½¼½½¿€€öÿ€€¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿€€öÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€öÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€öÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€öÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€öÿ€€¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾€€öÿ€€¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾¾€€öÿ€€¾¾¹º»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»º¹€€öÿ€€¾¾»ºº»»º»»»»»»ºººº»»»ºº»»»»ºº»»»»»ººº»»»»»»»ººº»»»»»»»º»»º»»»»»»º»»»ºººº»»ººº»»»º»»»»»»ºººº»»»ºº»»»»ºº»ºº¼€€öÿ€€¾¾»¼»¹¸¸¸¸····µµ··¸¸¸¸¸¸¸¸¸¹ººººº¹ººº¹¹ºººº¹ººº¸ºººº¹º¹¹¸¸¸¸¸¸¸¹¹¹º¹¹ºººººº¹º¹¹¸¸¸¸····µµ··¸¸¸¸¸¸¸¸¸¹º¹»¼½€€öÿ€€¾¾¼½½¹¹¹¹¸¸·¸¸···¸¸¸¸¹º¸¸¸¹ººººº»ººº¹¹¹¹¸º¹¹¸¸¹º¹ººººººº¹¹¸¹¹º¹ºººººººººººº¹¹º¹¹¹¹¸¸·¸¸···¸¸¸¸¹º¸¸¸¹¹¹º¼½¼€€öÿ€€¾¾»½½¹¸¸¸¸¸¸¸··¸¸¸¸¸¹¹ºººº¹ººººººººº¸¸¸¸¸¸¹¸·¸¹¸¸¹¹ººººººº¹¹¹ººººººº¹ºººº¹º¹º¹¹¸¸¸¸¸¸¸··¸¸¸¸¸¹¹ºººº¹¹º¹½½½€€öÿ€€¾¾»½½¹¸¸¸¸¸¸¸··¸¸¸¸¸¹¹ºººº¹ººººº¹¸º¸¹¸¸¸¸¸¸¸·¸¸¸¹¹ººº¹º¹º¹¹¹¹¹ºººººº¹ºººº¹º¹º¹¹¸¸¸¸¸¸¸··¸¸¸¸¸¹¹ºººº¹¹º¹½½½€€öÿ€€¾¾¼½½¹¹¸¸º¸¸¸··¸¸·¸¸¸¸¸¹ºººººº¹¹¹¹ººº¹¹¹¸¸·¸¸¸·¸¸¸¸¸¹º¹¹ººº¹¹¹¹º»ººººº¹ºº¹¹¸¸º¹¹¸¸º¸¸¸··¸¸·¸¸¸¸¸¹ººº¸¸º½½½€€öÿ€€¾¾½½½ºº¹¹¸¸¸¸·¸¹¸º¹ºººº¹º¹º¹¸¸¸¸¸¸¸¹¹¸¹¹ºº¹¸¸¹¹¹¸¸¸¸¸¸¸¹¹¹¹¸¸¹ºººº¹¹ºººº¹¹¹¸ººº¹¹¸¸¸¸¸¸ººº¹¸º¹ºººº¹¹¸¹º½½½€€öÿ€€¾¾¼½¼ººº¸¹¸¸·¸¸¸¸¹¹¹º¹¹¹¹¹¹¸¸¹¸¸¸¸¹ºº¹¹¹¹¹¹¹¸¸¸¸¸¸¸¸¸¸¸¸¹¹¸¸¸¸¹¹¹º¹ºººº¹¹¹º¸¹ºººº¸¸¸¹¸¸¹¹ºº¹¹¹¹¹ºº¹¸¹¹¹¼½½€€öÿ€€¾¾¼½½ºººº¹¹º¸¸¸¸¸¹¹¸¸¹¹º¹¹¹¸¸¸¸¸¸¸¹¸¹º¹¸¹¹¸¸¸¸¸¸¹¸¸¸¸¸¸¸¸¸¸¸¸¸¹¹¹¹¹¹¹¹ºº¹¹¹¹¹¸º¹º¹¸¹¹¸¹¸¸¸º¹¸¸¹¹ºº¹¹ºº¹½½½€€öÿ€€¾¾»½½¹¹¹ºº¹¹¹¸¸¹ºº¹¸¹¹ºººº¹¹¹¹¸¸¹¹¸¸¸¸¸¸¸¸¹¸¸¸¸¸¸¸¸¸·¸·¸¸¸¸¸¸¹¹¹¹¸¸¸¸¸¸¹¹¹¹¹¹¹¹¹º¸¸¸¸¹¸¸¹¹º¹¹¹¹º¹¹¹º¹ºº¼½¼€€öÿ€€¾¾¼½½¹¸¸¹º¹¹¹¹¸¸¸¹¹¹¹¹¹¹º¹¹¹¸¹¸¸¸¹¹¹¹¸¹¸¹¸¸¸¸¸¸¸¸¹¸¸¸····¸¹¸¸¹¸¹¹¹¸¸¸¸¸¸¹¹ºº¹¸¹ºº¹¸¹º¹¹¸¸¹¹¹º¹¹ºººº¹º¹º½½½€€öÿ€€¾¾½½½¹¹¸¹ºººº¸¹¹¹¹¹¹¸¹º¹¹¹¹¸¸¹¸¸¸¸¹¹¹¹¸¸¹¸¸¹¹¸¹¹¹¹¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¹¹¹¹¹¸¹¹¹¹º¹¹¹¹¹¹¹¹º¹¹¹º¹¹¹º¹¹¹½½½€€öÿ€€¾¾¼½¼ºº¹¹¸º¹ºº¸¹¹º¹¹¹ºº¹¸¸¸¸¸¸¸¸¸¸¸¸¹¸¸¸¹¹¹¸¹¹º¹¹¹¹¸¸¸¹¸¸¹¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¹ºº¸¸¹ºº¹¹¹ºº¹¸¹º¹¹¹ºº¹¹¸¹º¹¹¸½½½€€öÿ€€¾¾½½½ººº¸¸ººº¹¹¹º¹ºº¸¹¸¹¸¸¸¸¸¹¸¸¸¸¹¹¸¸¸¸¸¸¸¹¹¸¹¹¹¹¹¸¸¸¸¸¸¸¸¹¸¸¸¸¸¸¸¹¸¸¸¸¸¸¹º¹¹¹ºººº¹¹¹¸¹¹¹¹¹º¹º¹¹¸¸¸¸¸¹¼¼½€€öÿ€€¾¾½½½ººº¹¸¹¹¹¹ºººººº¹¸¸¸¸·¸¸¹¹¸¹º¹º¸¸¸¸·¸¸¹¹¹¹ºº¹¸¸¸¸¸¸¸¸¸¸¸¸¸º¹¹¸¸¸¹¹¸¸¸¸¸¹¸¹¹ºº¹º¹¸¹¸¹¹ºººº¸¹¸¸¸¸¸¸¸¸¼¼½€€öÿ€€¾¾½½½¸¹¹¹º¹¸¹¹ººº¹¸¹¹¹¹¹¹º¹¸¸¸¸¸¹¸¹¹ººº¸¹¹ººº¹¹¸¸¸¸¹¸¹¹¹¸¹¹¹¹ºº¸¹¹¹¹ºº¹ººººº¹¹¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¹¸¸···¸¸¸º¼¼½€€öÿ€€¾¾½½½¸¹¹¹¹º¸¹¹¹¹ºº¹ººººº¹¹¸¸¸¸¸¸¸¸¹¹¹¹º¸¹¹¹¹ºº¹¸¸¸¸¹¸¹¹¹¸¹¹¹¹ºº¸¹¹¹¹ºº¹ººººº¹¹¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸¸····¸¸¸º¼¼½€€öÿ€€¾¾»½½¸¸¸¸¸¸¹¹º¹ººº¹ºººººººººº¹¸¸¸¸¸¸¸¸¸¹¹º¹ººº¹¸¸¸¸¸¸¸¸¸¹¸º¸¹¹¸¹¹º¹ººº¹ºººººººººº¹¸¸¸¸¸¸¸¸¸¸¸¸···¸¸¸¸¸¸¼¼½€€öÿ€€¾¾¼½½»»»»ººº»º»»ºººº»º»º»º»ººººº»º»ºº»ººººº»ººº¹¹º¹º¹¹º¹»ººººººº¹ººººººººº¹¹¸¹¹ººººº»ºººººº»ºº»ºººººººº½¼½€€öÿ€€¾¾»¼½½½¼¼¼½½½¼½½½½½½½½¼½½½½½½½¼½¼½½½½½½½½½¼½¼½½¼½¼½½½½½½½½½¼½¼½½½½¼½¼½½½½½½½¼½¼½½½½½¼½¼½½¼¼¼½½½½¼¼¼½¼½½¼½½€€öÿ€€¾¾½½¼½½¼¼¼½½½¼½½½½½½½½¼½½½½½½½¼½¼½½½½½½½½½¼½¼½½¼½¼½½½½½½½½½¼½¼½½½½¼½¼½½½½½½½¼½¼½½½½½¼½¼½½¼¼¼½½½½¼¼¼½¼½½¼½½€€öÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€öÿ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€öÿæççééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééççæöÿçáöââââööööööööööööàáááàööööööööáááááááááááááááááááááááööööáöööööööööööààöööâââööööööööööööàáááàööööââàöáçöÿçöîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîöçöÿéöîæèééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééèæîöéöÿéàîêççééèééééééèèèèéééèèééééèèéééééèèèéééééééèèèéééééééèééèééééééèéééèèèèééèèèéééèééééééèèèèéééèèééééèèéççëîàéöÿéâîêëéæååääààââäååååååäåæçççççæçèçææçççèæçèçåçççèæèææååääåååæææçææçèçèççæçææååääààââäååååååäåæçæéëìîâéöÿæîëììææææåäåäâäääåæçåååæççèççéçççææææåçææååæçæçççççèèææåææçæççççèèçèèçççææçææææåäåäâäääåæçåååæææçëìëîéöÿåäîêììæååååäääääääåææççççæçèèççççççååääääæåäæäåææçççççççæææççççççèæèçèçæçæçææååååäääääääåææççççææçæìììîâçöÿåäîêììæååååäääääääåææççççæçèèççæåçåæåääääååäååææçççæçæçæææææçççççèæèçèçæçæçææååååäääääääåææççççææçæìììîâçöÿçâîëììææååçååäååäååååæççççççææææçççæææåääåääååååæçææçççææææèéèççççæççææååçææååçååäååäååååæçççååçìììîàçöÿçâîìììççææååääåæåçæççççæçæçæååäääååææåææççæååæææåååääååææææååæççççææçèèçæææåçççææåååääåççèæåçæççççææåæçìììîöèöÿæâîëìëçèçåæåäääååæææçææææææäåæåååäæççæææææææåååäååååååääææååååæææçæççççæææçåæççççåååæååææççæææææççæåæææëììîöéöÿæâîëììèèèçææçåäåååææåäææçæææåååäååäæåæçæåææååäääåæåååååååååäääåææææææææççæææææåçæçæäææåæäååçæååææççææççæìììîöéöÿåâîêììæææçèæææååæççæåææççççææææååææååååååååæääääååäååääääåååææææååååååæææææææææçåäååæääææçææææçæææçæçèëìëîàéöÿæâîëììæååæçææææåååæææææææçæææåæååäææææåæåæååååååååæåäååæååæåæææååååååææççæåæççæåæçææååæææçææççççæçæçìììîàçöÿéîìììææåæççççåææææææåæçææææååæåäåäææææååæååææåææææåååååäåääååååååäääååååæææææåææææçææææææææçæææçæææçæææìììîöèöÿçäîëìëççææåçæççåææçæææççæåååååååååäååæåååæææåææçææææåäåæååæååååäåäåääääåääæççååæççæææççæåæçæææççææåæçææäìììîöéöÿçâîìììçèçååçççæææçæççåæåæåååååæååååææåååääååææåæææææäåååååååæåååååååæåååääåæçæææççççæææåæææææçæçææåååååæëëìîöéöÿçâîìììèèèæåææææççççççæåååääåææåæçæçåååääåææææççæåääååååååååååçææåååææåääååæåææççæçæåæäææçèççåæåååääåååëëìîöéöÿçâîìììåæææçæåææçççæåææææææçæåååååæåææçççåææçççææååååæåæææåææææççåææææççæçççççææååååååååååååååäæåäââäååçëëìîáéöÿçâîìììåææææçåææææççæçèçèçææååååååååææææçåææææççæååååæåæææåææææççåææææççæçççççææååååååååååååååäääââäååçëëìîöéöÿéáîêììååååååææèæèççæçèèèèèçèççæåååååååååææèæèççæååääääääåæåèåææäææèæèççæçèèèèèçèççæåååååååååäääâäääåååëëìîöéöÿéàíëììééêêèçèêèééèèèèéèéèéèéèçèèèéèêèçêèçèèèêèèçææçæèææèæéççççèçèæçççççèçèçææåææçççèèêèççèèèêèèêèçèèèèèèìëìîâêöÿéíêëìììëëëìììëììììììììëìììììììëìëìììììììììëìëììëìëìììììììììëìëììììëìëìììììììëìëìììììëìëììëëëììììëëëìëììëììîäöÿèáíììëììëëëìììëììììììììëìììììììëìëìììììììììëìëììëìëìììììììììëìëììììëìëìììììììëìëìììììëìëììëëëììììëëëìëììëììîáåöÿçöîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîîöçöÿçáööàââöööààöööööööööööáööööáááááááááááááááááááááááááááááááááááááááááááááááööööööööàáááàöööööööööööööââàööáçöÿæççééééçèéééééééééééééééééééèçæææççæææçççèééèçææææççæææçççèééèçççèééèçæææçççèééèçææççééééççéééééééééééçééééççæöÿ \ No newline at end of file diff --git a/src/Uisrc/UI/CHATHELP.TXT b/src/Uisrc/UI/CHATHELP.TXT new file mode 100644 index 0000000..d9546be --- /dev/null +++ b/src/Uisrc/UI/CHATHELP.TXT @@ -0,0 +1,10 @@ +Press CREATE to create a new game. + +Press JOIN to join a game currently in progress. + +Press HELP to display this help screen. + +Press QUIT to leave the chatroom without joining a game. + + +For additional help, get Bill Roper or someone to write something. diff --git a/src/Uisrc/UI/CLAW.BMP b/src/Uisrc/UI/CLAW.BMP new file mode 100644 index 0000000..0395034 Binary files /dev/null and b/src/Uisrc/UI/CLAW.BMP differ diff --git a/src/Uisrc/UI/CONNECT.CPP b/src/Uisrc/UI/CONNECT.CPP new file mode 100644 index 0000000..25626b2 --- /dev/null +++ b/src/Uisrc/UI/CONNECT.CPP @@ -0,0 +1,1096 @@ +//**************************************************************************** +// +// connect.CPP +// Diablo UI +// +// By Michael Morhaime +// +//**************************************************************************** + +#include "pch.h" +#include "stdio.h" +#include "..\battle\bnetart.h" +#include "uisnd.h" +#include + + +#define MAX_SHORT_STRING_LEN 128 +#define MAX_STRING_LEN 256 + +#define DIABLO_RETAIL_ID 'DRET' +#define DIABLO_SHARE_ID 'DSHR' + +#define PROGRAMID 'HRTL' + +#define MIN_SPACING 2 +#define NUM_PORTS (3*4) +#define PORTRAIT_HEIGHT 14 + +#define HERO_PORT_X 0 + + +#define HERO_LEVEL_X1 14 +#define HERO_LEVEL_X2 20 +#define HERO_LEVEL_Y 5 + +#define COLOR_BG_HILITE (RGB(0x80,0x80,0x80)) + + +BOOL Txt2HeroInfo(char *szDesc, TUIHEROINFO *pHeroInfo); +void HeroInfo2Txt(TUIHEROINFO *pHeroInfo, char *szDesc); +DWORD GetPlayerCategory(const char *szDesc); //### MM Diablo Patch #2 3/21/97 + +extern int UiOkCancelDialog(HWND parent, LPCSTR okcanceltext, BOOL bErrFlag); +extern int UiBigOkCancelDialog(HWND parent, LPCSTR okcanceltext, LPCSTR title, BOOL bErrFlag); +extern int UiBigOkDialog(HWND parent, LPCSTR oktext, LPCSTR title, BOOL errorflag); +extern int UiOkDialog(HWND parent, LPCSTR okcanceltext, BOOL bErrFlag); + +static LPBYTE gBmpHeroPort = NULL; +static LPBYTE gBmpSpawnedPort = NULL; +static LPBYTE gBmpSpecial = NULL; +static LPBYTE gBmpScratchPort = NULL; +static HTRANS sgTransNum[10] = { 0 }; + +static SIZE gSizeHeroPort; +static SIZE gSizeHeroNum; +static SIZE gSizeSpecial; + +static int gHeroNumHgt; // Height of individual numbers/portraits +static int gHeroPortHgt; +static int gSpecialHgt; +static int gnPortBytesSize; // Precalulated bytes per Portrait and Digit image (for easy calculations) +static int gnDigitBytesSize; + +static DWORD sgMyProgramId = 0; // This is saved during call to CreatePlayerDesc() + +enum _special_icons { + eSPECIAL_BLIZZARD, + eSPECIAL_SYSOP_BATTLENET, + eSPECIAL_MODERATOR, + eSPECIAL_SPEAKER, + eSPECIAL_SYSOP, + eSPECIAL_SQUELCHED, +NUM_SPECIAL_ICONS + +}; + + +// Game Description Fields +// "%d\r%s\r%s", bDiff, szPlayerName, szPlayerDesc +// +// Player Description Fields +// "%c%c%c%c %d %d %d %d %d %d %d %d", PROGRAMID, wLevel, bHeroClass, bStrength, bMagic, bDexterity, bVitality, dwGold, bSpawned +enum _description_fields { + eGAMEDESC_DIFFICULTY, + eGAMEDESC_CREATOR_NAME, + + // These are from the Player Description + eGAMEDESC_PROGRAMID, + eGAMEDESC_CREATOR_LEVEL, + eGAMEDESC_CREATOR_CLASS, + eGAMEDESC_CREATOR_STRENGTH, + eGAMEDESC_CREATOR_MAGIC, + eGAMEDESC_CREATOR_DEXTERITY, + eGAMEDESC_CREATOR_VITALITY, + eGAMEDESC_CREATOR_GOLD, + eGAMEDESC_CREATOR_SPAWNED +}; + + + +//=========================================================================== +//=========================================================================== +// DATA Used in GetDataCallback + +// speed to play diablo logo +#define SML_LOGO_DELAY 54 + +SNET_DATA_SYSCOLORTABLE sgSysColorTbl[] = { + { COLOR_HIGHLIGHT, RGB(0x80, 0x80, 0x80) }, + { COLOR_HIGHLIGHTTEXT, RGB(0xff, 0xff, 0xff) }, +}; + + +//=========================================================================== + +//=========================================================================== +void FreeGlobalHeroArt(void) { + if (gBmpHeroPort) { + FREE(gBmpHeroPort); + gBmpHeroPort = NULL; + } + + if (gBmpSpawnedPort) { + FREE(gBmpSpawnedPort); + gBmpSpawnedPort = NULL; + } + + for (int i=0; i<10; i++) { + if (sgTransNum[i]) { + STransDelete(sgTransNum[i]); + sgTransNum[i] = NULL; + } + } + + if (gBmpSpecial) { + FREE(gBmpSpecial); + gBmpSpecial = NULL; + } + + if (gBmpScratchPort) { + FREE(gBmpScratchPort); + gBmpScratchPort = NULL; + } +} + +//=========================================================================== +BOOL LoadGlobalHeroArt(void) { + LPBYTE bmpHeroNum = NULL; + RECT rect; + + // Make sure this doesn't get loaded twice + if (gBmpHeroPort || sgTransNum[0]) { + return 1; + } + + UiLoadBmpFile( + TEXT("ui_art\\heroport.pcx"), + &gBmpHeroPort, + &gSizeHeroPort + ); + + UiLoadBmpFile( + TEXT("ui_art\\spwnport.pcx"), + &gBmpSpawnedPort, + NULL + ); + + UiLoadBmpFile( + TEXT("ui_art\\heronum.pcx"), + &bmpHeroNum, + &gSizeHeroNum + ); + + UiLoadBmpFile( + TEXT("ui_art\\special.pcx"), + &gBmpSpecial, + &gSizeSpecial // Special 'chat' icons + ); + + gHeroNumHgt = gSizeHeroNum.cy/10; + gHeroPortHgt = PORTRAIT_HEIGHT; + gSpecialHgt = gSizeSpecial.cy/NUM_SPECIAL_ICONS; + + gnDigitBytesSize = gSizeHeroNum.cx * gHeroNumHgt; + gnPortBytesSize = gSizeHeroPort.cx * gHeroPortHgt; + + + // Allocate space offscreen to build portraits + gBmpScratchPort = (LPBYTE)ALLOC(gHeroPortHgt * gSizeHeroPort.cx); + if (!gBmpScratchPort) { + return 0; + } + + + // Build Transparencies for numbers + memset(sgTransNum, 0, sizeof(sgTransNum)); + if (bmpHeroNum) { + // create an HTRANS for each number + for (int index = 0; index < 10; index++) { + + rect.left = 0; + rect.right = gSizeHeroNum.cx - 1; + rect.top = index * gHeroNumHgt; + rect.bottom = rect.top + gHeroNumHgt - 1; + + STransCreate( + bmpHeroNum, + gSizeHeroNum.cx, + gHeroNumHgt, + 8, + &rect, + PALETTEINDEX(239), + &sgTransNum[index] + ); + } + FREE(bmpHeroNum); + } + + return 1; +} + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK UiArtCallback (DWORD providerid, + DWORD artid, + LPPALETTEENTRY pe, + LPBYTE buffer, + DWORD buffersize, + int *width, + int *height, + int *bitdepth) { + + char filename[MAX_PATH] = ""; + + if (providerid == 'BNET') { + // Check for battlenet specific art + switch (artid) { + case SNET_ART_BACKGROUND: strcpy(filename,"ui_art\\bn_bkg.pcx"); break; + + case SNET_ART_JOINBACKGROUND: strcpy(filename, "ui_art\\bnjoinbg.pcx"); break; + case SNET_ART_HELPBACKGROUND: strcpy(filename, "ui_art\\hpopup.pcx"); break; + + case SNET_ART_BATTLE_LOGIN_BKG: strcpy(filename, "ui_art\\epopup.pcx"); break; + case SNET_ART_BATTLE_CONNECT_BKG: strcpy(filename, "ui_art\\bnconnbg.pcx"); break; + + case SNET_ART_BATTLE_CHAT_BKG: strcpy(filename, "ui_art\\chat_bkg.pcx"); break; + case SNET_ART_BATTLE_BTNS: strcpy(filename, "ui_art\\bnbuttns.pcx"); break; + case SNET_ART_BATTLE_SELECT_CHNL_BKG: strcpy(filename, "ui_art\\bnselchn.pcx"); break; + case SNET_ART_BATTLE_REDLAG: strcpy(filename, "ui_art\\redlag.pcx"); break; + case SNET_ART_BATTLE_YELLOWLAG: strcpy(filename, "ui_art\\yellolag.pcx"); break; + case SNET_ART_BATTLE_GREENLAG: strcpy(filename, "ui_art\\greenlag.pcx"); break; + + case SNET_ART_BUTTON_XSML: strcpy(filename,"ui_art\\but_xsm.pcx"); break; + case SNET_ART_BUTTON_SML: strcpy(filename,"ui_art\\but_sml.pcx"); break; + case SNET_ART_BUTTON_MED: strcpy(filename,"ui_art\\but_med.pcx"); break; + case SNET_ART_BUTTON_LRG: strcpy(filename,"ui_art\\but_lrg.pcx"); break; + + case SNET_ART_BATTLE_BADCONNECTION: strcpy(filename,"ui_art\\badconn.pcx"); break; + case SNET_ART_BATTLE_WELCOME_AD: strcpy(filename,"ui_art\\welcome.pcx"); break; + + case SNET_ART_BATTLE_LRG_EDIT_POPUP_BKG: strcpy(filename,"ui_art\\lepopup.pcx"); break; + } + + } + else if (providerid == 'IPXN') { + switch (artid) { + case SNET_ART_BACKGROUND: strcpy(filename, "ui_art\\ipx_bkg.pcx"); break; + } + } + else if (providerid == 0) { + switch (artid) { + case SNET_ART_BACKGROUND: strcpy(filename, "ui_art\\connect.pcx"); break; + } + } + + if (!filename[0]) { + // Check for generic artwork + switch (artid) { + case SNET_ART_JOINBACKGROUND: // fall through + case SNET_ART_BACKGROUND: strcpy(filename,"ui_art\\menu.pcx"); break; + case SNET_ART_BUTTONTEXTURE: strcpy(filename,"ui_art\\but_lrg.pcx"); break; + + case SNET_ART_POPUPBACKGROUND: strcpy(filename,"ui_art\\lpopup.pcx"); break; + case SNET_ART_HELPBACKGROUND: strcpy(filename,"ui_art\\lpopup.pcx"); break; + + case SNET_ART_APP_LOGO_SML: strcpy(filename, "ui_art\\xsmlogo.pcx"); break; + + case SNET_ART_BUTTON_XSML: strcpy(filename,"ui_art\\but_xsm.pcx"); break; + case SNET_ART_BUTTON_SML: strcpy(filename,"ui_art\\but_sml.pcx"); break; + case SNET_ART_BUTTON_MED: strcpy(filename,"ui_art\\but_med.pcx"); break; + case SNET_ART_BUTTON_LRG: strcpy(filename,"ui_art\\but_lrg.pcx"); break; + + case SNET_ART_PROGRESS_BACKGROUND: strcpy(filename, "ui_art\\prog_bg.pcx"); break; + case SNET_ART_PROGRESS_FILLER: strcpy(filename, "ui_art\\prog_fil.pcx"); break; + case SNET_ART_POPUPBACKGROUND_SML: strcpy(filename,"ui_art\\spopup.pcx"); break; + + case SNET_ART_SCROLLBARARROWS: strcpy(filename, "ui_art\\scrlarrw.pcx"); break; + case SNET_ART_SCROLLTHUMB: strcpy(filename, "ui_art\\scrlthmb.pcx"); break; + case SNET_ART_SCROLLBAR: strcpy(filename, "ui_art\\scrlbar.pcx"); break; + + } + } + + if (filename[0]) + return SBmpLoadImage(filename,pe,buffer,buffersize,width,height,bitdepth); + + return 0; +} + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK UiGetDataCallback(DWORD providerid, DWORD dataid, LPVOID buffer, DWORD buffersize, DWORD *bytesused) { + DWORD dwSize = 0; + + if (providerid == 'BNET') { + switch (dataid) { + case SNET_DATA_BATTLE_LOGODELAY: + dwSize = sizeof(DWORD); + if (buffer) { + DWORD *pdword; + + if (buffersize >= dwSize) { + pdword = (DWORD *)buffer; + *pdword = SML_LOGO_DELAY; + } + else return 0; + } + break; + } + } + + + if (!dwSize) { // Have we filled the data in yet? + switch (dataid) { // No... so move on to snp nonspecific constants + case SNET_DATA_SYSCOLORS: + dwSize = sizeof(sgSysColorTbl); + if (buffer) { + if (buffersize >= dwSize) + memcpy((LPBYTE)buffer, (LPBYTE)sgSysColorTbl, dwSize); + else return 0; + } + break; + + case SNET_DATA_CURSORARROW: + dwSize = sizeof(HCURSOR); + + if (buffer) { + if (buffersize >= dwSize) { + HCURSOR *phCursor; + + phCursor = (HCURSOR *)buffer; + *phCursor = LoadCursor(global_hinstance, "DIABLO_ARROWCURSOR"); + + if (*phCursor == NULL) + return 0; + } + else return 0; + } + break; + + case SNET_DATA_CURSORIBEAM: + dwSize = sizeof(HCURSOR); + + if (buffer) { + if (buffersize >= dwSize) { + HCURSOR *phCursor; + + phCursor = (HCURSOR *)buffer; + *phCursor = LoadCursor(global_hinstance, "DIABLOIBEAM"); + + if (*phCursor == NULL) + return 0; + } + else return 0; + } + break; + + case SNET_DATA_CURSORLINK: + dwSize = sizeof(HCURSOR); + + if (buffer) { + if (buffersize >= dwSize) { + HCURSOR *phCursor; + + phCursor = (HCURSOR *)buffer; + *phCursor = LoadCursor(global_hinstance, "DIABLO_LINKCURSOR"); + + if (*phCursor == NULL) + return 0; + } + else return 0; + } + break; + + } + } + + + if (bytesused) + *bytesused = dwSize; + + if (dwSize) + return 1; + + return 0; +} + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK UiSoundCallback(DWORD providerid, DWORD soundid, DWORD flags) { + switch (soundid) { + case SNET_SND_SELECTITEM: + UiSndPlayEnter(); + break; + + case SNET_SND_CHANGEFOCUS: + UiSndPlayClick(); + break; + } + + return 0; +} + +typedef BOOL (CALLBACK *SNETCHECKAUTHPROC )(DWORD,LPCSTR,LPCSTR,DWORD,LPCSTR,LPSTR,DWORD); + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK UiAuthCallback(DWORD dwItemType, LPCSTR szName, LPCSTR szDesc, DWORD dwUserFlags, LPCSTR szItem, LPSTR szErrorBuf, DWORD dwErrorBufSize) { + TUIHEROINFO heroInfo; + char szString[256]; + char szFmt[256]; + BOOL bAuth = FALSE; // we are not authorized unless we find a reason to be + char *p; + char szDescCopy[SNETSPI_MAXSTRINGLENGTH*2]; // trashable copy of description string + char szItemCopy[SNETSPI_MAXSTRINGLENGTH*2]; // trashable copy of item string + int nDescLen; + int nItemLen; + + + // Default to NULL error string + if (dwErrorBufSize) + szErrorBuf[0] = 0; + + // First make trashable copies of description and item strings + nDescLen = strlen(szDesc) + 1; + nItemLen = strlen(szItem) + 1; + if (nDescLen > sizeof(szDescCopy) || nItemLen > sizeof(szItemCopy)) { + if (szErrorBuf) + LoadString(global_hinstance, IDS_AUTH_STRTOOLONG, szErrorBuf, dwErrorBufSize); + return 0; + } + memcpy(szDescCopy, szDesc, nDescLen); + memcpy(szItemCopy, szItem, nItemLen); + + // Put data into our heroinfo struct so we can understand it. + if (!Txt2HeroInfo(szDescCopy, &heroInfo)) { + if (szErrorBuf) + LoadString(global_hinstance, IDS_AUTH_BADHERODESC, szErrorBuf, dwErrorBufSize); + return 0; + } + + if (dwItemType == SNET_AUTHTYPE_CHANNEL) { + // Blizzard employees and Sysop can go anywhere + if ((dwUserFlags & SNET_DDPF_BLIZZARD) || (dwUserFlags & SNET_DDPF_SYSOP)) + return 1; + + for (int i=0; i= nMinLevel) + return TRUE; + } + + // ok, bAuth contains our answer at this point + if (bAuth) + return TRUE; + // fall through to Unauthorized + +CHANNEL_UNAUTHORIZED: + if (szErrorBuf) { + int nLen; + + // Generate error string + LoadString(global_hinstance, IDS_AUTH_CHANNELRESTRICTED, szFmt, sizeof(szFmt)); + nLen = 1+sprintf(szString, szFmt, szItemCopy); + if ((int)dwErrorBufSize < nLen) { + memcpy(szErrorBuf, szString, dwErrorBufSize); + szErrorBuf[dwErrorBufSize-1] = 0; + } + else + memcpy(szErrorBuf, szString, nLen); + } + + return 0; + } + else { // SNET_AUTHTYPE_GAME + TGAMEDATA GameData; + + // Sysop can join any game + if (dwUserFlags & SNET_DDPF_SYSOP) + return 1; + + Txt2GameData((char *)szItemCopy, &GameData, NULL, NULL); + if (GameData.bDiff == DIFF_NIGHTMARE && heroInfo.level < 20) { + if (szErrorBuf) + LoadString(global_hinstance, IDS_NIGHTMARE_MINREQ, szErrorBuf, dwErrorBufSize); + return 0; + } + + if (GameData.bDiff == DIFF_HELL && heroInfo.level < 30) { + if (szErrorBuf) + LoadString(global_hinstance, IDS_HELL_MINREQ, szErrorBuf, dwErrorBufSize); + return 0; + } + + return 1; + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK UiDrawDescCallback (DWORD providerid, + DWORD itemtype, + LPCSTR itemname, + LPCSTR itemdescription, + DWORD itemflags, + DWORD drawflags, + DWORD time, + LPDRAWITEMSTRUCT lpdis) { + + char szItemDescCopy[SNETSPI_MAXSTRINGLENGTH*2]; + char szDiff[MAX_SHORT_STRING_LEN] = ""; + BOOL bSelected = lpdis->itemState & ODS_SELECTED; + COLORREF oldTextColor, oldBkColor; + static sbDrawingGameDesc = FALSE; + int nDescLen; + + // Make a trashable copy of the item description + nDescLen = strlen(itemdescription)+1; + if (nDescLen > sizeof(szItemDescCopy)) + return 0; + memcpy(szItemDescCopy, itemdescription, nDescLen); + + // First check if this is a game or player description + if (itemtype == SNET_DRAWTYPE_GAME) { + char szString[128]; + char szFmt[32]; + TGAMEDATA gameData; + LPSTR pszPlayerName = NULL; // Used to describe player who created the games + LPSTR pszPlayerDesc = NULL; + + // Put data into our gamedata struct so we can understand it. + if (!Txt2GameData(szItemDescCopy, &gameData, &pszPlayerName, &pszPlayerDesc)) + return 0; + + // Now display whatever we need to display + oldTextColor = SetTextColor(lpdis->hDC, RGB(0xff, 0xff, 0xff)); // white text + oldBkColor = SetBkColor(lpdis->hDC, (bSelected) ? COLOR_BG_HILITE : RGB(0, 0, 0)); + + // get format string and create text description + if (drawflags & SNET_DDF_INCLUDENAME) { + // Just print game name only + ExtTextOut( + lpdis->hDC, + lpdis->rcItem.left, + lpdis->rcItem.top, + ETO_CLIPPED | ETO_OPAQUE, + &lpdis->rcItem, + itemname, + strlen(itemname), + NULL); + } + else { + BOOL bHaveCreatorInfo; + + bHaveCreatorInfo = ((pszPlayerName != NULL) && (pszPlayerDesc != NULL)); + + // Build string for display + if ((unsigned char)gameData.bDiff < NUM_DIFFICULTIES) + LoadString(global_hinstance, IDS_DIFF_NORMAL+gameData.bDiff, szDiff, sizeof(szDiff)); + + + if ((drawflags & SNET_DDF_MULTILINE) && bHaveCreatorInfo) { + DRAWITEMSTRUCT disCopy; + POINT oldPos; + int nSaveAlignMode; + int nLineHgt; + TEXTMETRIC tm; + + // Get font height information + GetTextMetrics(lpdis->hDC, &tm); + nLineHgt = tm.tmHeight + tm.tmExternalLeading; + + // Print game description on first line + MoveToEx(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, &oldPos); + nSaveAlignMode = SetTextAlign(lpdis->hDC, TA_UPDATECP); + + TextOut(lpdis->hDC, 0, 0, szDiff, strlen(szDiff)); + + LoadString(global_hinstance, IDS_CREATOR, szString, sizeof(szString)); + MoveToEx(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top+nLineHgt, NULL); + TextOut(lpdis->hDC, 0, 0, szString, strlen(szString)); + + + // make a copy of the draw item struct so we can modify the draw rect location + disCopy = *lpdis; + + // Use Current Position as top-left of draw rect for player desc. + GetCurrentPositionEx(lpdis->hDC, (POINT *)&disCopy.rcItem.left); + SetTextAlign(lpdis->hDC, TA_NOUPDATECP); + + // Draw creator description on first second line + sbDrawingGameDesc = TRUE; + UiDrawDescCallback( + providerid, + SNET_DRAWTYPE_PLAYER, + pszPlayerName, + pszPlayerDesc, + 0, // No player flags + SNET_DDF_INCLUDENAME, + 0, // No time stamp + &disCopy); + sbDrawingGameDesc = FALSE; + + if (time) { + struct tm *newtime; + char szTime[32]; + char szAmPm[10]; + BOOL bAfternoon; + + SetTextAlign(lpdis->hDC, TA_UPDATECP); + + // Display Creation Time info + LoadString(global_hinstance, IDS_CREATIONTIME_FMT, szFmt, sizeof(szFmt)); + LoadString(global_hinstance, IDS_TIME, szTime, sizeof(szTime)); + + newtime = localtime((time_t *)&time ); /* Convert to local time. */ + + if (newtime) { //### BUG FIX MM 1/13/97 Protect against time out of range + bAfternoon = (newtime->tm_hour > 12); + LoadString(global_hinstance, IDS_AM + bAfternoon, szAmPm, sizeof(szAmPm)); + if( newtime->tm_hour > 12 ) /* Convert from 24-hour */ + newtime->tm_hour -= 12; /* to 12-hour clock. */ + if( newtime->tm_hour == 0 ) /* Set hour to 12 if midnight. */ + newtime->tm_hour = 12; + sprintf(szString, szFmt, szTime, newtime->tm_hour, newtime->tm_min, szAmPm); + + MoveToEx(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top+2*nLineHgt, NULL); + TextOut(lpdis->hDC, 0, 0, szString, strlen(szString)); + } + } + + MoveToEx(lpdis->hDC, oldPos.x, oldPos.y, NULL); + SetTextAlign(lpdis->hDC, nSaveAlignMode); + } + else { + // For single line, don't worry about creator info + TextOut(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, szDiff, strlen(szDiff)); + } + } + + // Restore colors to hdc + SetTextColor(lpdis->hDC, oldTextColor); + SetBkColor(lpdis->hDC, oldBkColor); + return 1; + } + else { // if (itemtype == SNET_DRAWTYPE_PLAYER) { + TUIHEROINFO heroInfo; + RECT srcRect; + int digit; + int nLineHgt; + int nPortOffset; + TEXTMETRIC tm; + + // Get font height information for centering of portrait on line + GetTextMetrics(lpdis->hDC, &tm); + nLineHgt = tm.tmHeight; // don't include tm.tmExternalLeading for centering purposes + nPortOffset = (nLineHgt - gHeroPortHgt)/2 + 1; + + + if (!sbDrawingGameDesc) { + oldTextColor = SetTextColor(lpdis->hDC, RGB(0xff, 0xff, 0)); // yellow text + oldBkColor = SetBkColor(lpdis->hDC, (bSelected) ? COLOR_BG_HILITE : RGB(0, 0, 0)); + } + + if (drawflags & SNET_DDF_INCLUDENAME) { + // Draw username + ExtTextOut( + lpdis->hDC, + lpdis->rcItem.left + HERO_PORT_X + gSizeHeroPort.cx + MIN_SPACING, + lpdis->rcItem.top, + ETO_CLIPPED | ETO_OPAQUE, + &lpdis->rcItem, + itemname, + strlen(itemname), + NULL); + } + + // Handle special user types, if necessary + int nIcon = -1; + if (itemflags) { + + // User is special, so display a special icon instead of a character class + if (itemflags & SNET_DDPF_SQUELCHED) { + nIcon = eSPECIAL_SQUELCHED; + } + else if (itemflags & SNET_DDPF_BLIZZARD) { + nIcon = eSPECIAL_BLIZZARD; + } + else if (itemflags & SNET_DDPF_MODERATOR) { + nIcon = eSPECIAL_MODERATOR; + } + else if (itemflags & SNET_DDPF_SPEAKER) { + nIcon = eSPECIAL_SPEAKER; + } + else if (itemflags & SNET_DDPF_SYSOP) { + if (providerid == 'BNET') + nIcon = eSPECIAL_SYSOP_BATTLENET; + else + nIcon = eSPECIAL_SYSOP; + } + } + + if (nIcon >= 0 && gBmpSpecial) { + SetRect(&srcRect, 0, 0, gSizeSpecial.cx - 1, gSpecialHgt - 1); + OffsetRect(&srcRect, 0, gSpecialHgt * nIcon); + + // Now draw icon in place of the hero icon + SDlgBltToWindow( + lpdis->hwndItem, + NULL, + lpdis->rcItem.left + HERO_PORT_X, + lpdis->rcItem.top + nPortOffset, + gBmpSpecial, + &srcRect, + &gSizeSpecial); + } + else { + // Player is not a special player type. + // Make sure that he/she is playing diablo before drawing + // hero information. + if (Txt2HeroInfo(szItemDescCopy, &heroInfo)) { + // compose portrait in offscreen portrait buffer. + // That way we don't have to clip on each blit. + + // Check for spawned here... + if (heroInfo.spawned) { + if (gBmpScratchPort && gBmpSpawnedPort) + SBltROP3( + gBmpScratchPort, + gBmpSpawnedPort, // Only one class in spawned version + gSizeHeroPort.cx, + gHeroPortHgt, + gSizeHeroPort.cx, + gSizeHeroPort.cx, + NULL, + SRCCOPY); + } + else { + if (gBmpScratchPort && gBmpHeroPort) + SBltROP3( + gBmpScratchPort, + gBmpHeroPort + (gnPortBytesSize*(heroInfo.heroclass + (heroInfo.herorank*UI_NUM_CLASSES))), + gSizeHeroPort.cx, + gHeroPortHgt, + gSizeHeroPort.cx, + gSizeHeroPort.cx, + NULL, + SRCCOPY); + } + + // Draw level number + + // Draw 10's digit + digit = heroInfo.level/10; + if (digit && gBmpScratchPort) { + STransBlt( + gBmpScratchPort + (gSizeHeroPort.cx*HERO_LEVEL_Y) + HERO_LEVEL_X1, + 0, 0, + gSizeHeroPort.cx, + sgTransNum[digit]); + } + + // Draw 1's digit + digit = heroInfo.level % 10; + + if (gBmpScratchPort) + STransBlt( + gBmpScratchPort + (gSizeHeroPort.cx*HERO_LEVEL_Y) + HERO_LEVEL_X2, + 0, 0, + gSizeHeroPort.cx, + sgTransNum[digit]); + + // Now copy portrait to the screen + // init source rect + SetRect(&srcRect, 0, 0, gSizeHeroPort.cx - 1, gHeroPortHgt -1); + + if (gBmpScratchPort) + SDlgBltToWindow( + lpdis->hwndItem, + NULL, + lpdis->rcItem.left + HERO_PORT_X, + lpdis->rcItem.top + nPortOffset, + gBmpScratchPort, + &srcRect, + &gSizeHeroPort); + } + } + + // Restore colors to hdc + if (!sbDrawingGameDesc) { + SetTextColor(lpdis->hDC, oldTextColor); + SetBkColor(lpdis->hDC, oldBkColor); + } + return 1; + } +} + + +//### MM Diablo Patch #2 3/21/97 BEGIN +#define DIABLO_CATEGORY_MASK 0xffff // Directs Battle.net to match on all category bits. +//=========================================================================== +// UiSelectCategory() +// +//=========================================================================== +BOOL CALLBACK UiCategoryCallback ( + BOOL userinitiated, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD * categorybits, + DWORD * categorymask) { + + *categorymask = DIABLO_CATEGORY_MASK; + *categorybits = GetPlayerCategory(playerdata->playerdescription); + return TRUE; +} + + + +//=========================================================================== +// +//=========================================================================== +DWORD GetPlayerCategory(const char *szDesc) { + TUIHEROINFO HeroInfo; + TCHAR szDescCopy[512]; + DWORD dwCategory = 0; + int nLevel; + + + // First make a trashable copy of the player description string + strcpy(szDescCopy, szDesc); + + if (!Txt2HeroInfo(szDescCopy, &HeroInfo)) + return 0; + + nLevel = HeroInfo.level; + if (nLevel == 1) // Level 1 + return dwCategory; + + dwCategory++; + if (nLevel < 4) // Level 2-3 + return dwCategory; + + dwCategory++; + if (nLevel < 6) // Level 4-5 + return dwCategory; + + dwCategory++; + if (nLevel < 8) // Level 6-7 + return dwCategory; + + dwCategory++; + if (nLevel < 10) // Level 8-9 + return dwCategory; + + dwCategory++; + if (nLevel < 13) // Level 10-12 + return dwCategory; + + dwCategory++; + if (nLevel < 17) // Level 13-16 + return dwCategory; + + dwCategory++; + if (nLevel < 20) // Level 17-19 + return dwCategory; + + dwCategory++; + if (nLevel < 25) // Level 20-24 + return dwCategory; + + dwCategory++; + if (nLevel < 30) // Level 25-29 + return dwCategory; + + dwCategory++; + if (nLevel < 35) // Level 30-34 + return dwCategory; + + dwCategory++; + if (nLevel < 40) // Level 35-39 + return dwCategory; + + dwCategory++; + if (nLevel < 48) // Level 40-47 + return dwCategory; + + dwCategory++; // Level 48+ + return dwCategory; +} +//### MM Diablo Patch #2 3/21/97 END + + +//=========================================================================== +// These routines will translate to and from the game description string that storm uses. +// +// The game description format is as follows: +// "%d\r%s\r%s", bDiff, szPlayerName, szPlayerDesc +// +// NOTE: if this format changes, update CreateGameCriteria(), and enum _description_fields +//=========================================================================== +BOOL Txt2GameData(char *szDesc, TGAMEDATA *pGameData, LPSTR *ppszPlayerName, LPSTR *ppszPlayerDesc) { + LPSTR p; + + if (szDesc[0] == 0) + return 0; + + pGameData->bDiff = atoi(szDesc); + if ((unsigned int)pGameData->bDiff >= NUM_DIFFICULTIES) + return 0; + + // Find player name + p = strchr(szDesc, '\r'); + if (p == NULL) + return 1; + *p++ = 0; + if (ppszPlayerName) + *ppszPlayerName = p; + + // Find player description + p = strchr(p, '\r'); + if (p == NULL) + return 1; + *p++ = 0; + if (ppszPlayerDesc) + *ppszPlayerDesc = p; + + return 1; + +} + +//=========================================================================== +void GameData2Txt(TGAMEDATA *pGameData, LPCSTR szPlayerName, LPCSTR szPlayerDesc, LPSTR szDesc, int nMaxLength) { + + // fill string with game info text, including creator's player info if it will fit. + if (nMaxLength > (int)(strlen(szPlayerName)+strlen(szPlayerDesc)+5)) + sprintf(szDesc, "%d\r%s\r%s", pGameData->bDiff, szPlayerName, szPlayerDesc); + else + itoa(pGameData->bDiff, szDesc, 10); +} + +//=========================================================================== +// These routines will translate to and from the hero description string that storm uses. +// +// The game description format is as follows: +// "%d %d %d %d %d %d %d", wLevel, bHeroClass, bStrength, bMagic, bDexterity, bVitality, dwGold +// +// NOTE: if this format changes, update CreatGameCriteria(), and enum _description_fields +//=========================================================================== + +BOOL Txt2HeroInfo(char *szDesc, TUIHEROINFO *pHeroInfo) { + int nLevel, nHeroClass, nHeroRank, nStrength, nMagic, nDexterity, nVitality, nGold, nSpawned; + DWORD *pdwProgramId = (DWORD *)szDesc; + + // Reset everything, in case this routine fails + ZeroMemory(pHeroInfo, sizeof(TUIHEROINFO)); + + // Only parse the hero info string if it was built by a user game with a programid we recognize. + if (szDesc[0] == 0 || *pdwProgramId != PROGRAMID) + return 0; + + + // If item count changes, change if constant + if (9 != sscanf(&szDesc[4], "%d %d %d %d %d %d %d %d %d", + &nLevel, + &nHeroClass, + &nHeroRank, + &nStrength, + &nMagic, + &nDexterity, + &nVitality, + &nGold, + &nSpawned)) { + return 0; + } + + + // Validate some of the data + if (*pdwProgramId == PROGRAMID && nSpawned) + return 0; + + //if ((*pdwProgramId == 'DSHR') && !nSpawned) + // return 0; + + + //### BUG FIX MM 2/3/97 Character Level 0 is invalid also. + if (nLevel == 0) + return 0; + //### END + + if ((unsigned long)nLevel > 99) + return 0; + + if ((unsigned long)nHeroClass >= UI_NUM_CLASSES) + return 0; + + if ((unsigned long)nHeroRank > NUM_DIFFICULTIES) + return 0; + + if (nStrength < 0 || nMagic < 0 || nDexterity < 0 || nVitality < 0) + return 0; + + // Now write values into hero info struct + pHeroInfo->level = (WORD) nLevel; + pHeroInfo->heroclass = (BYTE) nHeroClass; + pHeroInfo->herorank = (BYTE) nHeroRank; + pHeroInfo->strength = (BYTE) nStrength; + pHeroInfo->magic = (BYTE) nMagic; + pHeroInfo->dexterity = (BYTE) nDexterity; + pHeroInfo->vitality = (BYTE) nVitality; + pHeroInfo->gold = (DWORD) nGold; + pHeroInfo->spawned = (BOOL) nSpawned; + + return 1; +} + +//=========================================================================== +void HeroInfo2Txt(TUIHEROINFO *pHeroInfo, char *szDesc) { + DWORD *pdword; + + // fill string with hero info text + pdword = (DWORD *)szDesc; + *pdword = sgMyProgramId; + + sprintf(&szDesc[4], " %d %d %d %d %d %d %d %d %d", + pHeroInfo->level, + pHeroInfo->heroclass, + pHeroInfo->herorank, + pHeroInfo->strength, + pHeroInfo->magic, + pHeroInfo->dexterity, + pHeroInfo->vitality, + pHeroInfo->gold, + pHeroInfo->spawned); +} + + +//=========================================================================== +// UiCreateGameCriteria() +// +// This routine directs the Battle.net server how to prioritize games in the join game list. +// If the game description string changes, this must change as well. +//=========================================================================== +int APIENTRY UiCreateGameCriteria(TPUIHEROINFO pHeroInfo, char *szCriteria) { + return sprintf(szCriteria, "#%d?%d", eGAMEDESC_CREATOR_LEVEL, pHeroInfo->level); +} + +//*************************************************************************** +//*************************************************************************** +BOOL APIENTRY UiCreatePlayerDescription(TPUIHEROINFO pHeroInfo, DWORD dwProgramId, LPSTR pPlayerDesc) { + sgMyProgramId = dwProgramId; + HeroInfo2Txt(pHeroInfo, pPlayerDesc); + return 1; +} + + diff --git a/src/Uisrc/UI/COPYPROT.CPP b/src/Uisrc/UI/COPYPROT.CPP new file mode 100644 index 0000000..62c39db --- /dev/null +++ b/src/Uisrc/UI/COPYPROT.CPP @@ -0,0 +1,185 @@ +//**************************************************************************** +// CopyProt.cpp +// Diablo UI copy protection dialog +// +// By Frank Pearce +// created 11.18.96 +//**************************************************************************** + +#include "pch.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + static HGLOBAL sghBgRes; + static HGLOBAL sghBtnRes; + static HGLOBAL sghPalRes; + + +//**************************************************************************** +//**************************************************************************** +static void CopyProtDestroy(HWND window) { + + // free the art resources + if (sghPalRes) { + FreeResource(sghPalRes); + sghPalRes = NULL; + } + if (sghBtnRes) { + FreeResource(sghBtnRes); + sghBtnRes = NULL; + } + if (sghBgRes) { + FreeResource(sghBgRes); + sghBgRes = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CopyProtInit(HWND window, LPCSTR copyprottext) { + LPBYTE BgBmp; + LPBYTE BtnBmp; + PALETTEENTRY * BgPal; + PALETTEENTRY LoadedPal[PALETTE_REGISTERS]; + SIZE BgSize = { 284, 148 }; + SIZE BtnSize = { 112, 140 }; + + int BtnIDs[] = { IDC_OK, IDCANCEL, 0 }; + LPCTSTR srpopup = TEXT("ui_art\\srpopup.pcx"); + HWND child; + + // load the art resources + sghBgRes = LoadResource( + global_hinstance, + FindResource(global_hinstance, TEXT("IDR_POPUPART"), TEXT("ART_FILES")) + ); + sghBtnRes = LoadResource( + global_hinstance, + FindResource(global_hinstance, TEXT("IDR_BTNART"), TEXT("ART_FILES")) + ); + sghPalRes = LoadResource( + global_hinstance, + FindResource(global_hinstance, TEXT("IDR_ARTPAL"), TEXT("ART_FILES")) + ); + + // lock the loaded resources + BgBmp = (LPBYTE) LockResource(sghBgRes); + BtnBmp = (LPBYTE) LockResource(sghBtnRes); + BgPal = (PALETTEENTRY *) LockResource(sghPalRes); + + // register the images + if (BgBmp) { + SDlgSetBitmap( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + BgBmp, + NULL, + BgSize.cx, + BgSize.cy + ); + } + + ShowCursor(TRUE); + UiAltFadeInit(window); + + if (BtnBmp) + UiSetButtonBitmaps(window, BtnIDs, BtnBmp, &BtnSize); + + // load the palette + if (BgPal) { + memcpy(LoadedPal, BgPal, sizeof(PALETTEENTRY) * PALETTE_REGISTERS); + SDrawUpdatePalette(0, PALETTE_REGISTERS, LoadedPal, TRUE); + } + + child = GetDlgItem(window, IDC_OKCANCEL_TEXT); + SetWindowText(child, copyprottext); + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static void CopyProtAbort(HWND window, int retval) { + ShowCursor(FALSE); + SDlgEndDialog(window, retval); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK CopyProtDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_DESTROY: + CopyProtDestroy(window); + UiVidFadeOut(DEFAULT_STEPS*2); + break; + + case WM_INITDIALOG: + CopyProtInit(window, (LPCSTR)lparam); + return 1; + + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: + switch (GetWindowLong(GetFocus(), GWL_ID)) { + case IDC_OK: + CopyProtAbort(window, IDOK); + break; + default: + CopyProtAbort(window, IDCANCEL); + break; + } + break; + case IDC_OK: + CopyProtAbort(window, IDOK); + break; + case IDCANCEL: + CopyProtAbort(window, IDCANCEL); + break; + } + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiCopyProtError(DWORD *result) { + TCHAR copyproterror[128]; + DWORD dwResult; + + if (! UiIsSpawned()) + LoadString(global_hinstance, IDS_COPYPROT_ERR, copyproterror, 127); + else + LoadString(global_hinstance, IDS_SPAWNDATA_ERR, copyproterror, 127); + + dwResult = SDlgDialogBoxParam( + global_hinstance, + TEXT("OKCANCEL_DIALOG"), + SDrawGetFrameWindow(), + CopyProtDialogProc, + (LPARAM)copyproterror + ); + + if (result) + *result = dwResult; + + return 1; +} \ No newline at end of file diff --git a/src/Uisrc/UI/CR8GAME.CPP b/src/Uisrc/UI/CR8GAME.CPP new file mode 100644 index 0000000..20b178f --- /dev/null +++ b/src/Uisrc/UI/CR8GAME.CPP @@ -0,0 +1,522 @@ +/**************************************************************************** +* +* cr8game.CPP +* BattleNet Chat Room +* +* By Michael Morhaime +* +***/ + +#include "pch.h" +#include "stdio.h" +#include "uisnd.h" + +#define MAX_STRING_LEN 256 +#define NUM_DIFF_SETTINGS 3 +#define NUM_DIFF_BTN_POSITIONS 2 + + +//**************************************************************************** +// Private Data +//**************************************************************************** +static LPBYTE sgBackgroundBmp = NULL; +static LPBYTE sgButtonBmp = NULL; +static LPBYTE sgDiffBtnBmp = NULL; + +static SIZE sgDiffBtnSize; // Holds size of individual button in pixels + +static TGAMEDATA sgGameData; // Holds game initialization data +static TGAMEINFO sgGameInfo; // Holds game name and password + +static LONG sglPrivate; +static LONG sglDifficulty; +static LONG sglRestricted; + +extern int UiOkDialog(HWND parent, LPCSTR oktext, BOOL bErrFlag); + +extern BOOL IsNastyName(LPCTSTR name); +extern BOOL InvalidChars(LPCTSTR name, LPCTSTR additionalbad); +extern DWORD GetPlayerCategory(const char *szDesc); //### MM Diablo Patch #2 3/21/97 + +typedef struct _create_params { + SNETCREATEDATAPTR createdata; + SNETPROGRAMDATAPTR programdata; + SNETPLAYERDATAPTR playerdata; + SNETUIDATAPTR interfacedata; + SNETVERSIONDATAPTR versiondata; + DWORD *playerid; +} TCREATEPARAMS, PTCREATEPARAMS; + +static TCREATEPARAMS sgCreateParams; + +//=========================================================================== +static void DestroyArtwork (HWND window) { + if (sgBackgroundBmp) { + FREE(sgBackgroundBmp); + sgBackgroundBmp = NULL; + } + + if (sgButtonBmp) { + FREE(sgButtonBmp); + sgButtonBmp = NULL; + } + + if (sgDiffBtnBmp) { + FREE(sgDiffBtnBmp); + sgDiffBtnBmp = NULL; + } +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window) { + int btn_ids[] = { + IDOK, + IDCANCEL, + 0 + }; + + int diff_btn_ids[] = { + IDC_RADIO_NORMAL, + IDC_RADIO_NIGHTMARE, + IDC_RADIO_HELL, + 0 + }; + + + SIZE btnbmpsize; + SIZE bgSize; + + // For the background bitmap, "Dialog" is specified as the controltype to prevent + // LoadArtFile() from loading a palette, which would be done if we simply specified "". + LoadArtFile( + window, + NULL, + TEXT("Dialog"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\creat_bg.pcx"), + &sgBackgroundBmp, + &bgSize); + + + UiLoadBmpFile( + TEXT("ui_art\\but_xsm.pcx"), + &sgButtonBmp, + &btnbmpsize + ); + SDlgSetControlBitmaps (window, btn_ids, NULL, sgButtonBmp, &btnbmpsize, SDLG_ADJUST_VERTICAL); + + UiLoadBmpFile( + TEXT("ui_art\\diffbtns.pcx"), + &sgDiffBtnBmp, + &sgDiffBtnSize + ); + UiSetStaticBmp(window, IDC_STATIC_DIFF_DESC, sgBackgroundBmp, &bgSize); + return 1; +} + +//=========================================================================== +static void DrawDiffBtn(HWND hWndBtn, int nDiff, BOOL bPressed) { + TPBMP tpbmp; + int nBtnBytes; + + tpbmp = (TPBMP) GetWindowLong(hWndBtn, GWL_USERDATA); + if (tpbmp == NULL || sgDiffBtnBmp == NULL) + return; + + // Calculate byte offset of each button in source bitmap + nBtnBytes = sgDiffBtnSize.cx * tpbmp->datasize.cy; + + // now draw the appropriate button into + SBltROP3 ( + tpbmp->data, + sgDiffBtnBmp + ((nDiff*NUM_DIFF_BTN_POSITIONS)+bPressed)*nBtnBytes, + tpbmp->datasize.cx, + tpbmp->datasize.cy, + tpbmp->datasize.cx, + sgDiffBtnSize.cx, + NULL, + SRCCOPY + ); + + // Make sure storm redraws this button + InvalidateRect(hWndBtn, NULL, FALSE); +} + +//=========================================================================== +static void DestroyDiffBtns(HWND window) { + HWND hWndBtn; + RECT r; + TPBMP tpbmp; + + for (int i=0; idata) { + FREE(tpbmp->data); + tpbmp->data = 0; + } + + FREE(tpbmp); + } + } +} + +//=========================================================================== +static void InitDiffBtns(HWND window) { + HWND hWndBtn; + RECT r; + TPBMP tpbmp; + + for (int i=0; idata = (LPBYTE) ALLOC(r.right*r.bottom); + tpbmp->datasize.cx = r.right; + tpbmp->datasize.cy = r.bottom; + tpbmp->userdata = 0; + + SetWindowLong(hWndBtn, GWL_USERDATA, (LONG) tpbmp); + + // set it so the button uses the bmp just created + SDlgSetBitmap( + hWndBtn, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND | SDLG_USAGE_SELECTED | SDLG_USAGE_NORMAL, + tpbmp->data, + NULL, + tpbmp->datasize.cx, + tpbmp->datasize.cy + ); + + // Init the button image + DrawDiffBtn(hWndBtn, i, FALSE); + } +} + +//=========================================================================== +static void InitDefaultOptions(HWND hWnd) { + // Init unused game flags to 0 + sglPrivate = 0; + sglRestricted = 0; + + // Set to impossible values, so that help text is updated. + sglDifficulty = -1; + + // Simulate button clicks, so that description text gets updated. + SendDlgItemMessage(hWnd, IDC_RADIO_NORMAL, BM_CLICK, 0, 0); +} + +//=========================================================================== +static void SetBtns(HWND window, int nSelected) { + if (sglDifficulty != -1) + DrawDiffBtn(GetDlgItem(window, IDC_RADIO_NORMAL+sglDifficulty), sglDifficulty, FALSE); + + DrawDiffBtn(GetDlgItem(window, IDC_RADIO_NORMAL+nSelected), nSelected, TRUE); +} + +//=========================================================================== +static void SetDesc(HWND hWndDesc, LONG lFirstString, LONG lValue) { + char szText[MAX_STRING_LEN]; + + LoadString(global_hinstance, lFirstString + lValue, szText, sizeof(szText)); + SetWindowText(hWndDesc, szText); +} + +//=========================================================================== +static int ProcessName(LPSTR szName) { + char szTemp[MAX_GAME_LEN]; + int nStart, nEnd; + + // Take the name and remove leading and trailing spaces + strcpy(szTemp, szName); + + // Proceed until we find a non-space or null termination + for (nStart=0; ;nStart++) { + if (szTemp[nStart] != ' ') + break; + if (szTemp[nStart] == 0) + return 0; + } + + + // Now start at the end and look for a non-space character. Proceed until + // we reach the beginning + for (nEnd=strlen(szTemp)-1; ;nEnd--) { + + if (szTemp[nEnd] != ' ') + break; + + if (nEnd <= nStart) + return 0; + } + szTemp[++nEnd] = 0; // NULL terminate string before trailing spaces + + strcpy(szName, &szTemp[nStart]); + return(nEnd - nStart); // Length of string not including NULL termination +} + + + + +//=========================================================================== +BOOL TryCreateGame(HWND window) { + char szString[256]; + char szGameDesc[SNETSPI_MAXSTRINGLENGTH]; + BOOL bReturn; + + + // Create Game description for Storm (and for display of game later) + GameData2Txt( + &sgGameData, + sgCreateParams.playerdata->playername, + sgCreateParams.playerdata->playerdescription, + szGameDesc, + sizeof(szGameDesc)); + + if (!UiAuthCallback( + SNET_AUTHTYPE_GAME, + sgCreateParams.playerdata->playername, + sgCreateParams.playerdata->playerdescription, + 0, + szGameDesc, + szString, + sizeof(szString))) { + UiMessageBoxCallback(window, szString, NULL, MB_ICONWARNING | MB_OK); + return 0; + } + + // Make sure the application has allocated enough data for the structure + // (could be version differences with the .exe) + if (sgCreateParams.programdata->initdatabytes >= sizeof(sgGameData)) { + TGAMEDATA *pInitData = (TGAMEDATA *)sgCreateParams.programdata->initdata; + pInitData->bDiff = sgGameData.bDiff; + } + + bReturn = SNetCreateGame(sgGameInfo.szName, + sgGameInfo.szPassword, + szGameDesc, + GetPlayerCategory(sgCreateParams.playerdata->playerdescription), //### MM Diablo Patch #2 3/21/97 + sgCreateParams.programdata->initdata, // Diablo is responsible for making this point to an sgGameData structure + sgCreateParams.programdata->initdatabytes, + sgCreateParams.createdata->maxplayers, + sgCreateParams.playerdata->playername, + NULL, + sgCreateParams.playerid); + + if (bReturn == FALSE) { + char szFmt[128]; + if (GetLastError() == SNET_ERROR_ALREADY_EXISTS) { + LoadString(global_hinstance, IDS_GAMEALREADYEXISTS, szFmt, sizeof(szFmt)); + sprintf(szString, szFmt, sgGameInfo.szName); + } + else + LoadString(global_hinstance, IDS_CREATEGAMEERROR, szString, sizeof(szString)); + + UiMessageBoxCallback(window, szString, NULL, MB_ICONWARNING | MB_OK); + } + + return bReturn; +} + + +//=========================================================================== +static HFONT SetFonts (HWND window) { + HFONT hFont = NULL; + LOGFONT lFont; + + if ((hFont = (HFONT) SendMessage(window, WM_GETFONT, 0, 0L))) { + // Start with dialog font and modify size and weight + if (GetObject(hFont, sizeof(LOGFONT), (LPSTR) &lFont)) { + lFont.lfHeight = -MulDiv(12, 96, 72); // height of 12 pixels + lFont.lfWidth = 0; // let Windows autosize width + + if (hFont = CreateFontIndirect((LPLOGFONT) &lFont)) { + SendDlgItemMessage(window, IDC_RADIO_NORMAL, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(window, IDC_RADIO_NIGHTMARE, WM_SETFONT, (WPARAM)hFont, 0); + SendDlgItemMessage(window, IDC_RADIO_HELL, WM_SETFONT, (WPARAM)hFont, 0); + } + } + } + return hFont; +} + +//=========================================================================== +static BOOL CALLBACK ChatCreateGameDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + static HWND hWndName, hWndPassword; + static HFONT shFont; + + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: { + char szText[MAX_STRING_LEN]; + + // First, verify user entered required information + if (!SendMessage(hWndName, WM_GETTEXTLENGTH, 0, 0L)) { + LoadString(global_hinstance,IDS_NAME_REQUIRED,szText,MAX_STRING_LEN); + UiOkDialog(window, szText, TRUE); + return 0; + } + + // Fill create game structure + SendMessage(hWndName, WM_GETTEXT, sizeof(sgGameInfo.szName), (LPARAM)((LPSTR)sgGameInfo.szName)); + if (IsNastyName(sgGameInfo.szName) || InvalidChars(sgGameInfo.szName, "") || !ProcessName(sgGameInfo.szName)) { + LoadString(global_hinstance,IDS_GAME_NAME_INVALID,szText,MAX_STRING_LEN); + UiOkDialog(window, szText, TRUE); + sgGameInfo.szName[0] = 0; + return 0; + } + + + // Check if password was entered + sgGameInfo.szPassword[0] = 0; + if (SendMessage(hWndPassword, WM_GETTEXTLENGTH, 0, 0)) { + SendMessage(hWndPassword, WM_GETTEXT, sizeof(sgGameInfo.szPassword), (LPARAM)(LPSTR)(sgGameInfo.szPassword)); + } + + // Now that we have verified that the create game is successful, we can start + // modifying the global create game data. + + // Set difficulty + sgGameData.bDiff = (BYTE) sglDifficulty; + + UiSndPlayEnter(); + + if (TryCreateGame(window)) + SDlgEndDialog(window, TRUE); + return 0; + + } + case IDCANCEL: + UiSndPlayEnter(); + SDlgEndDialog(window, FALSE); + return 0; + + + case IDC_RADIO_NORMAL: + case IDC_RADIO_NIGHTMARE: + case IDC_RADIO_HELL: { + int nDiff = LOWORD(wparam) - IDC_RADIO_NORMAL; + int nNotify = HIWORD(wparam); + + // Don't allow these buttons to get the keyboard focus + if (nNotify == BN_SETFOCUS) + SetFocus(hWndName); + + if (sglDifficulty != nDiff) { + if (sglDifficulty != -1) { + // Unhilite previous button + SendMessage((HWND)GetDlgItem(window, sglDifficulty + IDC_RADIO_NORMAL), BM_SETSTATE, FALSE, 0); + UiSndPlayClick(); + } + + SetBtns(window, nDiff); + SetDesc(GetDlgItem(window, IDC_STATIC_DIFF_DESC), + IDS_NORMAL_DESC_XLONG, + nDiff); + + sglDifficulty = nDiff; + } + + // Make sure current selection is hilited (windows will want to unhilite it) + SendMessage((HWND)lparam, BM_SETSTATE, TRUE, 0); + break; + } + } + break; + + + case WM_CTLCOLORSTATIC: + if (GetWindowLong((HWND)lparam, GWL_ID) == IDC_TITLE) { + UiSetTextYellow((HDC)wparam); + return (BOOL) GetStockObject(NULL_BRUSH); + } + + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + + case WM_DESTROY: + DestroyArtwork(window); + DestroyDiffBtns(window); + if (shFont) + DeleteObject(shFont); + + hWndName = hWndPassword = NULL; + break; + + case WM_INITDIALOG: + hWndName = GetDlgItem(window, IDC_EDIT_NAME); + hWndPassword = GetDlgItem(window, IDC_EDIT_PASSWORD); + + LoadArtwork(window); + InitDiffBtns(window); + InitDefaultOptions(window); + shFont = SetFonts(window); + + SendMessage(hWndName, EM_LIMITTEXT, sizeof(sgGameInfo.szName)-1, 0); + SendMessage(hWndPassword, EM_LIMITTEXT, sizeof(sgGameInfo.szPassword)-1, 0); + + return 1; + + } + + return SDlgDefDialogProc(window,message,wparam,lparam); + +} + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + + +//=========================================================================== +BOOL CALLBACK UiCreateGameCallback (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + + BOOL bResult; + + + // Init global params data + sgCreateParams.createdata = createdata; + sgCreateParams.programdata = programdata; + sgCreateParams.playerdata = playerdata; + sgCreateParams.interfacedata = interfacedata; + sgCreateParams.versiondata = versiondata; + sgCreateParams.playerid = playerid; + + + + // DISPLAY THE DIALOG BOX + bResult = SDlgDialogBox(global_hinstance,TEXT("DIALOG_CREATE_GAME"),interfacedata->parentwindow,ChatCreateGameDialogProc); + if (bResult == -1) + return 0; + return bResult; +} diff --git a/src/Uisrc/UI/CREADUNG.CPP b/src/Uisrc/UI/CREADUNG.CPP new file mode 100644 index 0000000..df6b02b --- /dev/null +++ b/src/Uisrc/UI/CREADUNG.CPP @@ -0,0 +1,385 @@ +//**************************************************************************** +// CreaDung.cpp +// Diablo UI create multi player dungeon "Doom style" popup dialog +// +// By Frank Pearce +// created 11.7.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern int SelHeroGetMode(void); + void SelHeroSetDiff(int difficulty); + extern int SelOkDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus); + extern BOOL Txt2HeroInfo(char *szDesc, TUIHEROINFO *pHeroInfo); + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_DLGTITLE, + IDC_DLGTITLE2, + 0 + }; + static int sgDiffID[] = { + IDC_DLGTITLE3, + 0 + }; + static int sgDiffDescID[] = { + IDC_DIFFDESC, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgListIDs[] = { + IDC_DIFFBTN1, + IDC_DIFFBTN2, + IDC_DIFFBTN3, + 0 + }; + + static SNETCREATEDATAPTR sgCreateData; + static SNETPROGRAMDATAPTR sgCre8ProgramData; + static SNETPLAYERDATAPTR sgCre8PlayerData; + static DWORD *sgpCre8PlayerID; + static int sgPlayersMode; // single or multi player + static BOOL sgDiffLoadFocus; + static LPCSTR sgGameName; + static int sgLastError; + + +//**************************************************************************** +//**************************************************************************** +void SelDiffLoadFocus(BOOL loadfocus) { + sgDiffLoadFocus = loadfocus; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDiffSetInfo(HWND window, int childid) { + TCHAR desc[256]; + HWND child; + + LoadString( + global_hinstance, + IDS_NORMAL + (childid - IDC_DIFFBTN1), + desc, + 255 + ); + child = GetDlgItem(window, IDC_DLGTITLE3); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), desc); + UiDoomStaticReset(window, sgDiffID, AF_BIGGRAY); + + LoadString( + global_hinstance, + IDS_NORMAL_DESC_XLONG + (childid - IDC_DIFFBTN1), + desc, + 255 + ); + child = GetDlgItem(window, IDC_DIFFDESC); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), desc); + UiDoomStaticReset(window, sgDiffDescID, AF_SMALLGRAY); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDiffDestroy(HWND window) { + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgDiffDescID); + UiDoomCtrlsDestroy(window, sgDiffID); + UiDoomCtrlsDestroy(window, sgTextIDs); + + // free the background of the dlg + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + if (sgDiffLoadFocus) { + FocusAnimateDestroy(); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDiffInit(HWND window) { + TPBMP tpBmp; + + if (sgDiffLoadFocus) { + FocusAnimateInit("ui_art\\focus16.pcx"); + } + else { + FocusReInit(); + } + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT("popup"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\seldiff.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + } + + UiOnPaintBtns(window, sgListIDs); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomStaticInit(window, sgDiffID, AF_BIGGRAY); + UiDoomStaticInit(window, sgDiffDescID, AF_SMALLGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_MED); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDiffAbort(HWND window, int ReturnVal) { + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDiffAttemptCreate(HWND window) { + char szGameDesc[256]; + TGAMEDATA GameData; + TGAMEDATA *pInitData; + HWND child = GetFocus(); + + if (window != GetParent(child)) return; + + // create a string describing the game + GameData.bDiff = GetWindowLong(child, GWL_ID) - IDC_DIFFBTN1; + GameData2Txt( + &GameData, + sgCre8PlayerData->playername, + sgCre8PlayerData->playerdescription, + szGameDesc, + sizeof(szGameDesc) + ); + + // get the diff setting and stuff it into initdata + if (sgCre8ProgramData->initdatabytes >= sizeof(TGAMEDATA)) { + pInitData = (TGAMEDATA *)sgCre8ProgramData->initdata; + pInitData->bDiff = GetWindowLong(child, GWL_ID) - IDC_DIFFBTN1; + } + + // try to create the game + if (SNetCreateGame( + sgGameName, // game name + NULL, // game password + szGameDesc, + 0, //### MM Diablo Patch #2 3/21/97 + sgCre8ProgramData->initdata, + sgCre8ProgramData->initdatabytes, + sgCreateData->maxplayers, + sgCre8PlayerData->playername, // player name + NULL, + sgpCre8PlayerID + ) + ) { + SelDiffAbort(window, IDOK); + } + else { + // display a creation error + TCHAR errfmt[128], errstr[192]; + sgLastError = GetLastError(); + switch (sgLastError) { + case SNET_ERROR_ALREADY_EXISTS: + LoadString(global_hinstance, IDS_DUPGAMENAME_FMT, errfmt, 127); + wsprintf(errstr, errfmt, sgGameName); + break; + default: + LoadString(global_hinstance, IDS_CREATEGAME_ERR, errstr, 191); + break; + } + SelOkDialog(window, errstr, NULL, FALSE); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDiffMultiCreate(HWND window) { + char szGameDesc[SNETSPI_MAXSTRINGLENGTH]; + char err[256]; + TGAMEDATA GameData; + + // Create Game description for Storm (and for display of game later) + GameData.bDiff = GetWindowLong(GetFocus(), GWL_ID) - IDC_DIFFBTN1; + GameData2Txt( + &GameData, + sgCre8PlayerData->playername, + sgCre8PlayerData->playerdescription, + szGameDesc, + sizeof(szGameDesc) + ); + + if (! + UiAuthCallback( + SNET_AUTHTYPE_GAME, + sgCre8PlayerData->playername, + sgCre8PlayerData->playerdescription, + 0, + szGameDesc, + err, + sizeof(err) + ) + ) { + SelOkDialog(window, err, NULL, FALSE); + } + else { + SelDiffAttemptCreate(window); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDiffModeCreate(HWND window) { + if (sgPlayersMode == MULTIPLAYER) { + SelDiffMultiCreate(window); + } + else { + // let the select hero screen handle the create restrictions + SelHeroSetDiff(GetWindowLong(GetFocus(), GWL_ID) - IDC_DIFFBTN1); + SelDiffAbort(window, IDOK); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDiffInterpretClick(HWND window, int x, int y) { + if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKEOK), x, y)) { + SelDiffModeCreate(window); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKECANCEL), x, y)) { + SelDiffAbort(window, IDCANCEL); + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK SelDiffDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + SelDiffSetInfo(window, LOWORD(wparam)); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + SelDiffModeCreate(window); + } + else if (LOWORD(wparam) == IDOK) { + SelDiffModeCreate(window); + } + else if (LOWORD(wparam) == IDCANCEL) { + SelDiffAbort(window, IDCANCEL); + } + break; + + case WM_LBUTTONDOWN: + SelDiffInterpretClick(window, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_DESTROY: + SelDiffDestroy(window); + break; + + case WM_INITDIALOG: + sgPlayersMode = lparam; + SelDiffInit(window); + return 0; + + case WM_TIMER: + if (wparam == FOCUS_TIMER_ID) { + FocusAnimate(window, GetFocus()); + } + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiDoomCreateGame (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid, + BOOL loadfocus, + LPCSTR gamename) { + int result; + + sgCreateData = createdata; + sgCre8ProgramData = programdata; + sgCre8PlayerData = playerdata; + sgpCre8PlayerID = playerid; + + sgDiffLoadFocus = loadfocus; + + sgGameName = gamename; + + // DISPLAY THE DIALOG BOX + result = SDlgDialogBoxParam( + global_hinstance, + TEXT("SELDIFF_DIALOG"), + interfacedata->parentwindow, + SelDiffDialogProc, + SelHeroGetMode() + ); + + if (result == IDOK) + return TRUE; + SetLastError(sgLastError); + return FALSE; +} diff --git a/src/Uisrc/UI/CREAHERO.CPP b/src/Uisrc/UI/CREAHERO.CPP new file mode 100644 index 0000000..fca070d --- /dev/null +++ b/src/Uisrc/UI/CREAHERO.CPP @@ -0,0 +1,47 @@ +//**************************************************************************** +// CreaHero.cpp +// Diablo UI create new character popup dialog +// +// By Frank Pearce +// created 9.20.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + // default starting values when this dll was created + static TUIDEFSTATS sgStats[UI_NUM_CLASSES] = { + { 30, 10, 20, 25}, // starting stats for a warrior + { 25, 20, 30, 20}, // starting stats for a rogue + { 15, 35, 25, 20}, // starting stats for a sorcerer + { 25, 15, 25, 20}, // starting stats for a monk + { 20, 20, 25, 20}, // starting stats for a bard + { 40, 0, 20, 25}, // starting stats for a barbarian + }; + + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK UiGetDefaultStats(int heroclass, TPUIDEFSTATS defaultstats) { + if (defaultstats) { + defaultstats->strength = sgStats[heroclass].strength; + defaultstats->magic = sgStats[heroclass].magic; + defaultstats->dexterity = sgStats[heroclass].dexterity; + defaultstats->vitality = sgStats[heroclass].vitality; + return 1; + } + + return 0; +} + + diff --git a/src/Uisrc/UI/CREDITS.CPP b/src/Uisrc/UI/CREDITS.CPP new file mode 100644 index 0000000..c27c04c --- /dev/null +++ b/src/Uisrc/UI/CREDITS.CPP @@ -0,0 +1,380 @@ +//**************************************************************************** +// +// Credits.CPP +// Diablo UI credits screen +// +// By Michael Morhaime (9/16/96) +// Modified 10.3.96 by Frank Pearce +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + #define PIXELS_PER_SCROLL 1 + #define ID_CREDITS_TIMER 1 + #define MILLISEC_PER_SEC 1000 + #define PIXELS_PER_SEC 20 + #define DEFAULT_TIMER (MILLISEC_PER_SEC / (PIXELS_PER_SEC / PIXELS_PER_SCROLL)) + #define USER_TIMER (MILLISEC_PER_SEC / (pixelspersec / PIXELS_PER_SCROLL)) + + #define VERTICAL_PAD 30 // Padding above and below viewable part of offscreen rect + #define TAB_PIXEL_SIZE 40 + #define LINE_HEIGHT 22 + + static LPBYTE sgTextBits = NULL; // bitmap for scrolling text ctrl + static SIZE sgTextBitsSize; + static HSGDIFONT sgTextFont = NULL; + static int sgiTextLoc; + + static HGLOBAL sghCredits; // handle for the credits string resource + static int sgCreditsSize; // length of resource in bytes + + static void ScrollCredits(HWND window); + + +//**************************************************************************** +//**************************************************************************** +static void CreditsDestroy (HWND window) { + if (sgTextFont) { + SGdiDeleteObject(sgTextFont); + sgTextFont = NULL; + } + if (sgTextBits) { + FREE(sgTextBits); + sgTextBits = NULL; + } + + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + if (sghCredits) { + // free the credits text + FreeResource(sghCredits); + sghCredits = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void CreditsAbort(HWND window) { + UiFadeAbort(window); + SDlgKillTimer(window,ID_CREDITS_TIMER); + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, 1); +} + + +//**************************************************************************** +//**************************************************************************** +static void CreditsInit (HWND window, LPARAM pixelspersec) { + TPBMP tpBmp; + HWND child; + HFONT winfont; + RECT rect; + int nWidth, nHeight; + + // set up the timer based on the specified pixel rate + SDlgSetTimer( + window, + ID_CREDITS_TIMER, + (pixelspersec ? USER_TIMER : DEFAULT_TIMER), + NULL + ); + + // load the credits into memory + sghCredits = LoadResource( + global_hinstance, + FindResource(global_hinstance, TEXT("IDR_CREDITS"), TEXT("TEXT_FILES")) + ); + sgCreditsSize = SizeofResource( + global_hinstance, + FindResource(global_hinstance, TEXT("IDR_CREDITS"), TEXT("TEXT_FILES")) + ); + + // init a bmp for the window + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\credits.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window, FALSE); + } + + // alloc/create a bitmap for the scrolling text ctrl + child = GetDlgItem(window, ID_SCROLL_WINDOW); + GetWindowRect(child, &rect); + + nWidth = rect.right - rect.left; + nHeight = rect.bottom - rect.top + (VERTICAL_PAD*2); + + sgTextBits = (LPBYTE) ALLOC(nWidth * nHeight); + if (!sgTextBits) { + CreditsAbort(window); + return; + } + sgTextBitsSize.cx = nWidth; + sgTextBitsSize.cy = nHeight; + + UiCalcNewRect(&rect, 0, VERTICAL_PAD); + + SDlgSetBitmap( + child, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + sgTextBits, + &rect, + nWidth, + nHeight + ); + + // init the starting text coordinate and begin drawing the credits + sgiTextLoc = nHeight - VERTICAL_PAD; + ScrollCredits(window); + + // create the font for SGdiTextOut + winfont = CreateFont( + -17,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_ROMAN,TEXT("Times New Roman") + ); + if (winfont) { + BOOL result = SGdiImportFont(winfont,&sgTextFont); + DeleteObject(winfont); + if (! result) { + CreditsAbort(window); + } + } + else { + CreditsAbort(window); + } +} + + +//**************************************************************************** +//**************************************************************************** +static int sgCreditsLen; + +static int credit_length(LPTSTR credit) { + int len = 0; + + // find the length (in characters) of a single line + while ((*credit != '\r') && (*credit != '\n')) { + len++; + credit++; + if (len > sgCreditsLen) { + len = -1; + break; + } + } + return len; +} + + +//**************************************************************************** +//**************************************************************************** +static LPTSTR credit_next(LPTSTR lastcredit, int lastlen) { + // skip over last credit and cr/lf + lastcredit += (lastlen + 2); + sgCreditsLen -= (lastlen + 2); + + return lastcredit; +} + + +//**************************************************************************** +//**************************************************************************** +static void CreditsDraw(HWND window) { + int x, y, stringlen; + LPTSTR credits; + + // lock the resource and get it's size + credits = (LPTSTR)LockResource(sghCredits); + sgCreditsLen = sgCreditsSize; + + SGdiSelectObject(sgTextFont); + SGdiSetPitch(sgTextBitsSize.cx); + + for ( + y = sgiTextLoc; + sgCreditsLen > 0; + y += LINE_HEIGHT, credits = credit_next(credits, stringlen) + ) { + // init left coord + x = 0; + // handle tabs at the begining of a line + while (*credits == '\t') { + x += TAB_PIXEL_SIZE; + credits++; + sgCreditsLen--; + } + stringlen = credit_length(credits); + + // make sure the dest coords are in the buffer + if (stringlen == -1) break; + if (y < 0) continue; + if (y > (sgTextBitsSize.cy - VERTICAL_PAD)) break; + + if (stringlen) { +#if 1 + // draw a drop shadow + SGdiTextOut( + sgTextBits, + x + 2, + y + 2, + PALETTEINDEX(0), + credits, + stringlen + ); +#endif + + // draw the text + SGdiTextOut( + sgTextBits, + x, + y, + PALETTEINDEX(224), + credits, + stringlen + ); + } + } + + // has the bottom of the credits scrolled past the top? + if (y < 0) { + CreditsAbort(window); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ScrollCredits (HWND window) { + RECT rect; + HWND child = GetDlgItem(window, ID_SCROLL_WINDOW); + TPBMP tpBmp = (TPBMP) GetWindowLong(window, GWL_USERDATA); + + GetWindowRect(child, &rect); + ScreenToClient(window, (LPPOINT)&rect.left); + ScreenToClient(window, (LPPOINT)&rect.right); + + // Copy from Background bitmap to buffer for scrolling text ctrl + SBltROP3 ( + sgTextBits + (sgTextBitsSize.cx * VERTICAL_PAD), + tpBmp->data + (rect.top * tpBmp->datasize.cx) + rect.left, + sgTextBitsSize.cx, + rect.bottom - rect.top, + sgTextBitsSize.cx, + tpBmp->datasize.cx, + NULL, + SRCCOPY + ); + + sgiTextLoc -= PIXELS_PER_SCROLL; + CreditsDraw(window); + + InvalidateRect(child, NULL, FALSE); + UpdateWindow(child); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK CreditsDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + switch (message) { + + case WM_DESTROY: + CreditsDestroy(window); + break; + + case WM_INITDIALOG: + CreditsInit(window, lparam); + PostMessage(window, WM_USER+1000, 0, 0); + return 1; + + case WM_TIMER: + ScrollCredits(window); + break; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_PARENTNOTIFY: + if (LOWORD(wparam) == WM_LBUTTONDOWN || LOWORD(wparam) == WM_RBUTTONDOWN) { + CreditsAbort(window); + } + break; + + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + CreditsAbort(window); + return 0; + + case WM_KEYDOWN: + if (wparam == VK_SPACE) { + CreditsAbort(window); + } + return 0; + + case WM_COMMAND: + CreditsAbort(window); + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiCreditsDialog (UINT pixelspersec) { + // fuck allowing customizable speed + pixelspersec = 25; + + // start the dialog + SDlgDialogBoxParam( + global_hinstance, + TEXT("CREDITS_DIALOG"), + SDrawGetFrameWindow(), + CreditsDialogProc, + pixelspersec + ); + + return 1; +} diff --git a/src/Uisrc/UI/CREDITS.TXT b/src/Uisrc/UI/CREDITS.TXT new file mode 100644 index 0000000..23865d9 --- /dev/null +++ b/src/Uisrc/UI/CREDITS.TXT @@ -0,0 +1,90 @@ + Synergistic Software + +General Manager + Bob Clardy + +Lead Programmer + Donald Tsang + +Software Engineering + Jim Edwards, Gary Powell, D'Andre Pritchett + +Art Director + Kirt Lemons + +Artists + Darren Lamb, Mike McMillen, + Jason Robertson, Peter Watje + +Design + Kirt Lemons, Donald Tsang, Peter Watje + Jim Edwards, Mike McMillen + +Additional Design + Michael Ormsby + +Sound Design, SFX & Audio Engineering + Craig Utterback + +Quality Assurance Lead + Mona Branham + +Testers + Chris Barker, Steve Chin, Derek Clardy, Conor Durdy, + Amy Edwards, Greg Hightower, Tim Jensen, Jeremy Jones, + John Lang, Daudi Pritchett, Doug Van Horne, Gordon Wilcox + +Manual + Suzanne David, Linda Westerfield, + Ann Dickens Clardy, Kirt Lemons + +Voices + Jim Edwards, Paul Eiding, Eve Forward, + Mackenzie Powell, Rodney Sherwood, Craig Utterback + + + Additional Work + +Quest Text Writing + Eve Forward + +Thanks to + Trisha Durdy, Dustin Freeman, D'Andre Pritchett + + + + Special Thanks to Blizzard Entertainment + + + + + Sierra On-Line Inc. Northwest + +Quality Assurance Manager + Gary Stevens + +Quality Assurance Lead Tester + Bernadette Pryor + +Main Testers + Erik Johnson, David Lee, Kristofer Hall + +Additional Testers + Cade Myers, Jeff Ingham, Phil Kuhlmey, + Eric Gelfand, Mark Wyman, Torsten Reinl, + Erinn Hamilton + +Product Marketing Manager + Eddie Ranchigoda + +Public Relations Manager + Eric Twelker + +Associate Product Manager + Joe Roth + +Thanks to + Cindy Vanous, Joshua Bentley, Robert Zimmerman, Robert Jerauld, + Dennis Ham, Andrea Stone, Beth Quintana, Jennifer Keenan, Gary Brown, + Ken Eaton, Matt Eslick, Kate Powell, Bryon Mcpherson, David Beetlestone + diff --git a/src/Uisrc/UI/DCREDITS.TXT b/src/Uisrc/UI/DCREDITS.TXT new file mode 100644 index 0000000..37927c6 --- /dev/null +++ b/src/Uisrc/UI/DCREDITS.TXT @@ -0,0 +1,455 @@ +Game Design + Blizzard North + +Senior Designers + Erich Schaefer, David Brevik + +Additional Design + Max Schaefer, Eric Sexton, Kenneth Williams + +Lead Programmer + David Brevik + +Senior Programmers + Richard Seis, Doron Gartner, + Patrick Wyatt, Mike O'Brien + +Programming + Peter Brevik, Robin van der Wel, Jon Morin + +Special Guest Programmers + Collin Murray, Frank Pearce + +Battle.net Programming + Mike O'Brien, Mike Morhaime, Dan Liebgold + +Serial Communications Programming + Jeff Strain, Mike O'Brien + +Installer Programming + Bob Fitch, Patrick Wyatt + +Art Directors + Erich Schaefer, Samwise Didier + +Artwork + Michio Okamura, Eric Sexton, Ben Haas, Patrick Tougas, + Kelly Johnson, Erich Schaefer, Max Schaefer, Hugh Tom + Byrne, Roman Kenney, Samwise Didier, Dave Berggren, + Micky Neilson, Eric Flannum, Justin Thavirat, Brian + Sousa, Stu Rose, Nick Carpenter, Joeyray Hall + +Technical Artwork + Christopher Root, Mark Sutherland, + Robert Djordjevich, Jeffrey Vaughn + +Cinematic Art Directors + Duane Stinnett, Matt Samia + +3D Cinematic Artwork + Duane Stinnett, Matt Samia, Rob McNaughton, + Eric Flannum, Dave Pursley, Micky Neilson, + Maxx Marshall, Trevor Jacobs, Brian Sousa, + Samwise Didier, Ron Smorynski, Ben Haas, Patrick Tougas + +Cinematic Technical Artwork + Joeyray Hall + +Executive Producer + Allen Adham + +Producer + Bill Roper + +Associate Producer + James Phinney + +Diablo Strike Team + Allen Adham, Ron Millar, Mike O'Brien, + James Phinney, Bill Roper, Patrick Wyatt + +Music + Matt Uelmen + +Sound Design + Matt Uelmen, Glenn Stafford + +Cinematic Music & Sound + Glenn Stafford, Matt Uelmen + +Voice Production, Direction & Casting + Mark Schwarz, Glenn Stafford, Bill Roper + +Script & Story + Erich Schaefer, Eric Sexton, + Chris Metzen, Bill Roper + +Voice Editing + Glenn Stafford + +Voices + Michael Haley, Glynnis Talken, Michael Gough, + Paul Eiding, Lani Minella, Steve Brodie, Bill Roper, + Mark Schwarz, Glenn Stafford, Chris Metzen, Max Schaefer + +Recording Engineer + Robert Koenigsberg + +Manual Design & Layout + Peter Underwood, Jeffrey Vaughn, + Chris Metzen, Bill Roper + +Manual Artwork + Samwise Didier, Chris Metzen, + Roman Kenney, Maxx Marshall + +Provisional Director of QA (Lead Tester) + Shane Dabiri + +QA Assault Team (Testers) + Christopher Cross, Mike Givens, Dave Hale, + Brian "Doc" Love, Hung Nguyen, Dean Shipley, + Chris Sigaty, Ian Welke, Jamie Wiggs + +QA Special Ops Team (Compatibility Testers) + Adam Maxwell, Russell "Rug" Miller + +QA Artillery Support (Additional Testers) + Rich Alcazar, Mike Jones, Rev. Dan Moore, Matt Morris, + Mark Pfeiffer, Harish "Pepe the Enforcer" Rao, Chris Millar + +QA Counterintelligence + Alan Dabiri, Jesse McReynolds, Walter Takata + +Order of Network Information Services + Robert Bridenbecker, Jason "Brother Shaggy" Schmit, + Jamie "Brother Gug" Steigerwald, Richard Seis + +Customer Support + John Schwartz, Vic Larson, Chad Chaudry, Mick Yanko, + Brandon Riseling, Kirk Mahony, Tony Hardy, Richard + Amtower, Collin Smith, Andrew Edwards, Roger Eberhart + +Sales + Jorge Rivero, Rob Beatie + +Dunsel + Alan Dabiri + +Mr. Dabiri's Background Vocalists + Karin Colenzo, Christina Cade, + Kim Farrington, Melissa Edwards + +Public Relations + Linda Duttenhaver, Susan Wooley + +Marketing + John Patrick, Steve Huot, Neal Hubbard, Kathy Carter + +International Sales + Ralph Becker, Chris Yoshimura + +U.S. Sales + Todd Coyle, Danny Kearns + +Manufacturing + John Goodman, Tom Bryan + +Legal & Business + Paula Duffy, Eric Roeder, Paul Sams, Kenneth Williams + +Special Thanks To + Primenet, Earthlink, AOL, Compuserve, ATI, Matrox, STB, + Creative Labs, Logitech, U.S. Robotics, Gravis, Cyrix + +Thanks To + Ian Colquhoun, Rod Shean, Brian Fitzgerald, Sharon Schafer, Todd + Schafer, Richard and Sandra Schaefer, Rick Bowles, Greg Bogden, + Cindy Sievert, Brad Mason, Chuck Goldman, Karin Colenzo, Wendy + Brevik, Jennie Brevik, Hanna Carroll, Katie Newell, Karen Weiss, + Kurt Beaver, Stan McDonald, Brian Sexton, Michael Wan, Megan + Williams, Jessica Gensley, Beth Ann Parks, Brian Piltin, Johnathan + Root, Brett Supernaw, Sabeer Bhatia, Mark Rearick, Brad Mason, + Diane Kodama, Bernadette Sexton, Barbara Uhlmann, Patricia + McDonald, Kris Kelley, Alissa Vaage, Denise Hernandez, Paula + White, Rachel Marie Hawley, Laura Gaber, Isaac Matarasso, + Susan Stafford, Gretchen Witte, Jason Sailor, Eufemia Palomino, + Nathalie Didier, Nicole Welke, Dawn Caddel, Anna-Marcelle + Okamura, Amber Okamura, Megan Okamura Tracey McNaughton, + Trisha Ann Ochoa, Annie Strain, Dr. Gregory T. Street, Ray the Soda + Guy, Sam Raimi, A. Guinness Brewing Co., John Woo, Chow Yun Fat, + Jackie Chan,Proposition 215, Rumiko Takahashi, Bunchy & Mason, + The Friends of Stan, The Zoo Crew, Team Hamro, Brazil 2001, RUSH, + Cornholio, THE BROS., Dar, Emeril Lagasse, Tom Waits, Ice-Cube, + The Strike Team Deflectors, Tony Levin, Big Jim and the Twins, + Jag`rmeister, The Megasphere, Condor, The Allower, The Sunday + Night Group, Gravitar, Steinway Pianos, Round Table Pizza, The Poxy + Boggards, Urban Mystic & Co., Caffeine, Hunter Rose, Marly + mediums in the box, sweet Poteen, Dave Scarpitti, TheByter, Bim + Man, Krissann for color, Patty at Avalon Tattoo, James, Whaleboy, + Dunsel Training Institute, monkeys, Dob Bole, Rootes Group, Porshe, + Bongo, Scarlett, Apollo, The House of Mediocrity, Amelias, The King, + Saag and all the folks at Davidson + +In memory of + Lawrence and Barbara Williams + David A. Hargrave + Tony "Xatre" Collin + Thomas H Sexton + +Very Special Thanks to + Bob and Jan Davidson + Walter Forbes + +The Ring of One Thousand + Andrew Abernathy, Christopher Abramo, David Adams, David + Adcox, Marko Agterberg, Cory Aiken, Judah Altaras, John + Alvarez, Jose Alvarez, Richard Amable, Alexander Amaral, + Scott Amis, Vincent Amoroso, Mark An, David Andersen, Jason + Andrew Abernathy, Christopher Abramo, David Adams, David + Adcox, Marko Agterberg, Cory Aiken, Judah Altaras, John + Alvarez, Jose Alvarez, Richard Amable, Alexander Amaral, + Scott Amis, Vincent Amoroso, Mark An, David Andersen, Jason + Andersen, Aaron Anderson, George Anderson, Matthew + Anderson, Michael Anderson, Sean Anderson, Robert Andrade, + Cerny Andre, Michael Andreev, Devin Angle, Brian Apple, + Brian Arbuthnot, Billy Arden, Dorian Arnold, Andre Arsenault, + Erik Asplund, Mark Assam, John Athey, Jason Attard, Jeff + Atwood, Ricky Au, Scott Avery, Rand Babcock, Steve Babel, + Raymond Bacalso, Ed Bachta, Steven Back, Scott Baeder, Alex + Baevski, Scott Bailey, Kenneth Baird, Thomas Baker, Todd + Bala, Jan Ball, Greg Baltz, Blake Baltzley, Doug Bambrick, Wes + Bangerter, Paul Barfuss, Chris Barghout, Dave Barnebey, Jon + Barnhart, Terje Barth, Nicole Baskin, Bernard Baylen, Ryan + Bear, Phil Bedard, Todd Belcher, Chip Bell, Erez Ben-Aharon, + Jonathan Bender, Nick Bennett, Ireney Berezniak, Ted Berg, + Gunnar Bergem, Russell Beuker, Ed Bickford, Stephen Biles, + John Billdt, Gerald Binder, John Bird, Hannah Blackerby, Tom + Blackerby, Clayton Blackwell, Thomas Blake, Shawn Blaszak, + Daniel Bliss, Fred Bliss, Jeff Bliss, Jon Blum, Rune Boersjoe, + Andrew Boggs, Dave Boisvenu, Joe Bolt, John Bonds, Jeff + Borenstein, Dorian Borin, Ed Boris, Bartholomew Botta, + Michael Boutin, Michael Boyd, Charles Boyer, Mike + Boyersmith, Michael Boyko, Eric Bradberry, John Brandstetter, + Ryan Breding, Paul Brinkmann, Patrick Briscoe, Scott Brisko, + Jeremy Britton, Adrian Broadhead, Glenn Brouwer, Joe Brown, + Sébastien Brulotte, Darrell Brunsch, William Bryan, Jason + Bucher, Chris Buchinger, Clayton Buckingham, John Buckles, + David Bugay, Ed Bujone, Erik Burgess, Gabriel Burkett, Chris + Burnes, Richard Butler, Jeffrey Bye, Dougall Campbell, Donnie + Cannon, Shane Cantrell, Connor Caple, Daniel Carey, James + Carlton, Michael Carmel, Mike Carpenter, Ronald Carruthers, + Phil Carter, Bryce Cartmill, Eric Cartwright, Anthony Caruso, + Lon Casey, Tim Caster, Aaron Chan, Otto Chan, Gene Chang, + Hsiao-Lung Chang, William Chang, George Chappel, Larry + Charbonneau, Troy Chase, Bruce Chen, Chun Hsien Chen, Sam + Chen, Tzu-Mainn Chen, Mike Cheng, Chris Chiapusio, Damien + Chiesa, Nick Chin, Nim Ching, Jonathan Chinn, Michael Chinn, + Philander Chiu, Thayne Christiansen, Philip Chui, Steve + Cintamani, Richard Ciordia, Colin Clark, Steve Clark, Samuel + Clements, Meredith Clifton, Jeff Cohen, Dale Colton, Dax + Combe, Matt Compton, Jacob Conklin, Richard Conn, Zac + Cook, Tim Coolong, Gregory Coomer, Dennis Cosgrove, Kelly + Couch, Andrew Coulter, Eric Coutinho, David Coutts, James + Craig, John Craig, Kazial Craig, John Crawford, Marcelo + Crespo, Orville Crews, Tim Cristy, Elmer Crosby III, Russell + Cullison, Ryan Cupples, Andrew Dagley, Steve Dallaire, Richard + Dalton, David Dandar, Pro Daulo, Rob Dautermann, Mike + Davies, Kalieb Davis, Marshall Davis, Ronald Davis, Danny De + Bie, Marc De Filippis, Myles Deighton, Kent Dejarnett, Anthony + Delarosa, Neil Dempster, Peter Denitto, Joaquim Dentz, Scott + Dewar, Anish Dhingra, Philip Dhingra, David Diaz, Stewart + Dicks, Brad Dietz, Josh Dietz, Colleen Diggins, Mike Ditchburn, + Eric Dittman, Allen Do, Huy Doan, Matthew Dolman, Antoine + Dongois, Eamonn Donohoe, Bill Dorell, Mark Dorison, Dan + Dorsett, Chris Dorsey, Jim Dosé, Willis Doss, Chin Du, William + Dubis, Timothy Duewell, Brandon Dunn, Andrew Durham, Don + Duvall, Kevin Dvojack, Daniel Eaton, Paul Eberting, Eric + Echelbarger, Lance Eddleman, Ben Eggers, David Eggum, John + Ehde, Brian Eikenberry, Patrick Elven, Peter Engdahl, Philip + Engdahl, Michael Ennis, Darren Eslinger, Eric Ezell, Darren + Falslev, Stephen Feather, Tony Fenn, Ben Ferguson, Mike + Fernandez, Gwendal Feuillet, Guy Fietz, Julian Figueroa, Dale + Fillpot, Stan Finchem, Michael Finley, Nick Fisher, William + Fisher, Mark Fitlin, Dave Flatt, Joel J. Flores, John Folkers, + Steven Forgie, Tom Forsythe, Matthew Foster, Scott Francis, + Jim Frank, Paulo Fraser, Glenn French, Kurt Frerichs, Chris + Frey, Mark Friedman, Charles Friedmann, Dan Friend, Kirk + Fry, Aaron Fu, Erik Gaalema, Brandon Gabbard, Phil Gagner, + Tommy Gannon, David Gappmayer, Chris Garrison, Tony + Garrison, David Gasca, Jeremy Gasser, Michael Geist, Michael + Genereux, Daniel Genovese, Josh Gerwin, Paul Gibson, William + Gilchrist, Gabriel Gils Carbo, Chad Glendenin, Ryan Glinski, + Dean Gobrecht, Andrew Goldfinch, David Goodman, Mark + Goodson, Matt Gordon, Frank Gorgenyi, Sean Gould, Perry + Goutsos, Ed Govednik, Michael Grayson, Chris Green, Justin + Grenier, Jeff Greulich, Don Grey, Rob Griesbeck, Don Griffes, + Kimberly Griffeth, Jay Grizzard, Don Gronlund, Joe Gross, + Troy Growden, Greg Guilford, David Gusovsky, Jeremy + Guthrie, Adam Gutierrez, James Guzicki, Matthew Haas, Matt + Hadley, Ryan Hagelstrom, Bobby Hagen, Ben Hall, Brian Hall, + Kris Hall, Calvin Hamilton, Kris Hamilton, Bo Hammil, Dave + Hans, Rick Hansen, Robert Harlan, Travis Harlan, Seth + Harman, Jeff Harris, Shawn Hartford, Adam Hartsell, Neil + Harvey, Ray Hayes, John Hein, Chris Heinonen, Christer + Helsing, Chris Hempel, Dustin Hempel, Mathieu Henaire, Matt + Henry, Chuck Herb, Michael Herron, Sage Herron, Thomas + Herschbach, Cliff Hicks, Nelson Hicks, Paul Hierling, William + Hiers, Mike Higdon, Tim Hildebrand, Casey Hinkle, Ryan + Hitchings, Wes Hix, Alan Ho, Jenson Ho, Alan Hoffman, Jeff + Hoffman, Eleanor Hoffmann, Steve Hogg, Richard Holler, Brian + Homolya, Wade Hone, Joe Horvath, Jeff Howe, Eric Hudson, + Glen Huey, Chris Hufnagel, Joshua Hughes, Melissa Hughes, + Arief Hujaya, Thomas Hulen, Ryan Hupp, Justin Hurst, Rick + Hutchins, Steve Iams, Mike Iarossi, Bjorn Idren, Johan Idrén, + Micah Imparato, Joe Ingersoll, David Ingram, Greg Ipp, Rodney + Irvin, Darin Isola, Justin Itoh, Mario Ivan, Fredrik Ivarsson, + Dax Jacobson, Michael Jacques, Stevens Jacques, Duane Jahnke, + William Jambrosek, Daniel Janick, Narciso Jaramillo, Neil + Jariwala, Harvie Jarriell, Scott Javadi, Joe Jenkins, Bart + Jennings, Paul Jennings, Julien Jenny, Jason Jensen, Martin + Jeremy, Mark Jeschke, Andy Johnson, James Johnson, Leigh + Johnson, Mark Johnson, Rupert Johnson, Clyde Jones, Michael + Jones, Tim Jordan, Ben Judy, Michael Kaae, Steve Kaczkowski, + Neville Kadwa, Brian Kaisner, Yoshihisa Kameyama, Michael + Kanemura, Daniel Kao, Eric Karabin, Ben Katz, Christopher + Kawamura, Erick Kayser, Craig Keddie, Kevin Kelley, Bryan + Kemp, Michael Kendrigan, Dan Kerber, Timothy Kerber, Tomi + Keski-Heikkilä, Greg Kettering, Nathan Kilber, Howard Kim, + Orrin Kinion, Jon Kirst, David Kitch, John Klingbeil, Neil + Klopfenstein, Kerry Knouse, David Knox, Said Kobeissi, Jeff + Koches, Hades Kong, Jeff Kong, Kevin Konkle, Steve Koon, + David Koontz, Dan Koopmann, Steve Koskela, Kuan Kou, + Cameron Kracke, Jensen Krage, York Kramer, Cedar Kraus, + Jason Kraus, Bobby Krimen, Melissa Krispli, Steven Krispli, + James Kruger, Charles Kubasta, Kimmo Kulonen, Frank + Lackaff, Michael Lacour, Matt Lake, Jason Landry, Hans Erik + Lange, Michael Laramee, Brad Lascelle, Pat Laschinger, Alan + Lau, Sean Laurence, Anthony Lavey, Jr., Gary Le, Huey Le, + Stephane Le Roy Audy, Lim Leandro, Charles Lee, Conroy Lee, + Mike Lee, Shih-Hang Lee, Jonathan Leipert, Jason Lemann, + Ron Lenzi, Mitchell Leon, Stephanie Lesniewski, Brendan + Lewis, Robert Lewis, Sam Liao, Tom Liem, Adam Ligas, Steven + Liggett, Roger Lilley, Benjamin Lim, Jeff Lindholm, Johnson + Linwood, David Litchman, Bruce Lithimane, William Liu, + Wilson Liu, Robert Lobdell, Chris Logan, Razvan Loghin, Jack + Loh, George Loo, Russell Love, Juan Loyola, Ricardo Lozano, + Mike Luban, Tim Luc, Henry Luciano, Dianne Ludwig, Charles + Lueras, Derek Lung, Phong Ly, Scott MacGillivray, Dave Mack, + Alec Mak, Steve Mamayek, Michael Mancini, Daniel Mann, + Michael Mann, Chris Manofsky, Abdullah Marafie, Nicholas + Marcy, Piompino Mariano, Bob Marius, Trey Marshall, Dane + Martin, Gregg Martin, Renard Martin, Rich Martin, Scott + Martin, Thomas Martin, Jon Masters, Christopher Mathews, + Jay Mathis, Marc Matthews, Chris Mazur, Doug McBride, + Mackey McCandlish, Robin McCollum, Steven McCombie, + Andy McConnell, Michael McCourt, Bill McCoy, Doug + McCracken, Michael McDeed, Robert McDonald, Steve + McEachron, Craig McGee, Ryan McKenzie, Michael McKeown, + Daniel McMahon, Colin McMillan, Ian McWilliam, Mark + McWilliams, Khann Mean, Bryan Meason, Kenneth Medley, + Jeff Meek, John Mehr, Christopher Mende, Brian Mendenhall, + Peter Mengel, Michael Mersic, Mike Messom, Don Metcalf, + Gary Metzker, Scott Meyer, Joseph Michaud, Andrew Mielke, + Travis Mikalson, Troy Milburn, Ike Miller, Ronnie Miller, Sean + Miller, Steve Miller, Arthur Min, David Minniti, Brenda + Mirsberger, Bill Misek, David Mitchell, Joseph Mobley, Robert + Mollard, Will Mooar, Curtis Moore, Matthew Moore, Al + Morales, Ryan Moran, Lance Mortensen, Karel Mrazek, Ward + Mullee, William Munoz, Kirk Munro, Craig Murray, Shawn P. + Murray, Travis Murray, Michael Mushrush, Tom Mustaine, + David Myers, Joseph Myett, Morgan Najar, Kenta Nakamura, + Damian Nastri, Joshua Naumann, Nick Navarro, Douglas + Neitzel, Arnold Ng, Anthony Nguyen, Steve Nguyen, Joseph + Nicholas, Charles Nickolaus, Jon Nisbet, Patrick Nomee, David + Norling-Christensen, Bobby Norton, Joseph Nottingham, Frank + O'Connor, Jon Oden, David Oester, Lavern Ogden, Zach + Oglesby, Lucas Oldfield, Toby Olsson, Aaron Ondek, Sean + O'Neill, John Orlando, Samuel Orlando, Donovan Orloski, + David Pai, Nikolas Paldan, David Palek, John Palmieri, Anthony + Palmisano, Sanjay Pandit, Jesse Park, Alex Parker, Jimmy + Pasher, Lukasz Paszek, Andy Patterson, William Pelletier, + Duane Pemberton, Ivan Pemic, Kelly Pendergast, Mike + Penezich, Jon Penk, Willie Penley, Ron Penna, Matthew + Pennington, Kevin Pereira, Ross Perez, Ken Perkins, Brian + Peterik, Kelly Peterson, Chris Phillips, Rod Pickett, Cameron + Pierce, Reuben Pierce, Tim Pilger, Billy Pippin, Brad Plank, + Brian Plant, Craig Platt, David Plunkett, Michael Politi, Albert + Portillo, Brian Powell, David Powell, Franklin Powers Jr., Alan + Precourt, Michael Pronchick, Julian Quintana, Justin Radziej, + Steven Rajewski, Shawn Rawles, Ian Reardon, Marc Reed, Ric + Reichelt, Judd Reiffin, David Reilly, Garry Reisky, Drew + Ressler, Robert Reynolds, Walter Reynolds, Michael Rice, Ian + Richards, James Richards, Raymond Richmond, Dustin Riggs, + Keith Riskey, Brian Ro, Scott Roberts, Jorge Rodriguez, Chad + Rogers, Clint Rogers, Robert Rogers, Steve Rogers, Ethan Roots, + Ron Roque, William Ross, Sebastian Rossi, Jeff Rostis, Ben + Roth, Demar Roth, Rich Rouse, Oleg Rovner, Jonathan Roy, + Drew Rozema, Mike Ruggles, Mathias Russ, James Russell, Jim + Rutledge, James Rutter, Dave Ryder, Chris Salvadras, Anders + Samnerud, Nick Sanders, Jakob Sandgren, Joe Sapinsky, Tyler + Sargent, Jonas Saunders, Mark Savage, Scott Sawyer, Robert + Scanlon, Trevor Schaben, Aaron Schmidt, Chris Schmidt, Greg + Schultz, Nicholas Schumacher, Scott Schumacher, Kevin Scott, + Rastislav Seffer, Robert Seidler, Corey Sellers, Justin Sellers, + Marc Senecal, George Shannon, Ian Sheffield, Anoop Shekar, + Sandeep Shekar, Kevin Shelton, Leon Shephard, Eric Shepperd, + Jeffrey Shneidman, Samuel Shockey, Mark Shoemaker, Mike + Shupe, Sean Sibbet, Brian Sidharta, Jimmy Sieben, Eric + Siemens, William Silva, Jody Simpson, Jatinder Singh, Sonia + Siu, Omar Skarsvaag, Tom Skiba, Carl Skow, David Skuse, + Robert Slifka, Brent Smith, C. Eric Smith, Jared Smith, Jeffrey + Smith, Owen Smith, Shannon Smith, Steven Smith, Edward Smola, + Matthew Sneep, Eric Snow, Brad Sobel, Jean-Pierre Solignac, Rasmus + Sørensen, Andrew Sorg, Poppy Southcott, Ross Specter, Erik Spencer, + Keith Spencer, Chris Springer, Erikson Squier, Dean St. Onge, Stewart + Stanfield, John Stanley, Terrence Staton, Benjamin Stein, James + Steiner, David Steyer, William Stickney, Chris Stiff, James Stofer, + Norm Storch, Patrick Stovall, Brandon Sturgeon, Sean Stutler, Anne + Sukprasert, Jamal Sullivan, Bruce Sully, Jay Sung, Park Sung + Joon, Stein Sunnarvik, Nathan Surginer, Robert Swaringen, Lee + Sweeney, David Szabo, Scott Taft, Christian Takvam, Patrick + Talaska, Tadashi Tamaki, Simon Tan, Mark Taraba, Khon- + Whey Tay, John Taylor, Keith Taylor, Donald Temean, Phillip + Tesar, Pete Thao, Brian Thomas, Keith Thomas, Speed Thomas, + Miles Thorpe, Paul Thurrott, Mike Timbol, Nicholas Timmins, + Tom Tobin, Robert Towster, Hien Tran, Timothy Traviss, Toby + Traylor, Tony Treadwell, George Tremoulis, Paul Trinh, Thanh + Trinh, Chris Tristan, Brad Truswell, Jason Tryon, Mike Tu, + Gernel Tuazon, Eric Tuggle, Mike Turnbull, Lyle Ubben, + Amilcar Ubiera, Robert Ulozas, Arie Upton, Mark Van Noy, + Matthew Van Sickler, Jake Vantlin, Tony Vasquez, Brady + Vauclin, Gianpiero Vecchi, Chad Verrall, Chris Vicente, Brett + Vickers, David Vickery, Jonathan Vilante, Simon Vince, Ben + Vinson, David Voelkert, Paul Vogt, Nicholas Voorhies, Robert + Vreeland, Mike Vrooman, Rick Vuong, Brian Wachhaus, Todd + Wachhaus, Caine Wade, Mathew Wadstein, Kenneth Wagenius, + Trevor Wagner, John Wagstaff, Asad Wahid, Richard + Wahlberg, Helio Wakasugui, Richard Walker, Wilkins Walker, + Matthew Wallace, Daniel Walsh, Joel Walters, Andrew Waltz, + Tom Wang, Tony Wang, Jay Ward, Jonathan Ward, John + Warner, Mark Warren, Matt Washer, Mike Watson, Sean + Wattles, Mike Wayne, Christian Wehba, Benjamin Wei, Richard + Weight, Cary Wells, David Wenck, Bill Werring, Leonard + Wesley, Marlon West, Mikael Westerbacka, Brian Wharry, + Chris White, Chris White, Jeremy White, Greg Whitlock, Gary + Widener, Marty Wilfried, Israel Wilkinson, Michael Willams, + Derek Williams, Sean Willson, Nitzan Wilnai, Jim Wilson, + Karsten Wilson, William Wilt, Tim Winn, Brian Winzeler, Matt + Wise, Lee Wissmiller, Brendan Wolfe, Daniel Wolpert, Felix + Wong, Power Wong, Tony Wong, Tim Wood, Timothy Wood, + Jeremy Woods, Michael Woods, Bill Wright, Keith Wright, + Patrick Wu, Gang Xie, Robert Yao, Sun Lim Yap, Stephen Yau, + Erek Yedwabnick, Christopher Yee, Nick Yee, Juan Yip, David + Young, Rob Young, Seth Young, Alex Yu, Terry Zahn, Jia-Ning + Zhang, Eric Zieg, Jordan Zielin, Clint Zimmerman, Matt Zinke + + + + + No souls were sold in the making of this game. + + + + + diff --git a/src/Uisrc/UI/DEBUG/ARTFONT.SBR b/src/Uisrc/UI/DEBUG/ARTFONT.SBR new file mode 100644 index 0000000..0bffe76 Binary files /dev/null and b/src/Uisrc/UI/DEBUG/ARTFONT.SBR differ diff --git a/src/Uisrc/UI/DEBUG/CONNECT.SBR b/src/Uisrc/UI/DEBUG/CONNECT.SBR new file mode 100644 index 0000000..0d27e82 Binary files /dev/null and b/src/Uisrc/UI/DEBUG/CONNECT.SBR differ diff --git a/src/Uisrc/UI/DEBUG/COPYPROT.SBR b/src/Uisrc/UI/DEBUG/COPYPROT.SBR new file mode 100644 index 0000000..eaa9b89 Binary files /dev/null and b/src/Uisrc/UI/DEBUG/COPYPROT.SBR differ diff --git a/src/Uisrc/UI/DEBUG/CR8GAME.SBR b/src/Uisrc/UI/DEBUG/CR8GAME.SBR new file mode 100644 index 0000000..435a410 Binary files /dev/null and b/src/Uisrc/UI/DEBUG/CR8GAME.SBR differ diff --git a/src/Uisrc/UI/DEBUG/CREADUNG.SBR b/src/Uisrc/UI/DEBUG/CREADUNG.SBR new file mode 100644 index 0000000..9a5521b Binary files /dev/null and b/src/Uisrc/UI/DEBUG/CREADUNG.SBR differ diff --git a/src/Uisrc/UI/DEBUG/CREAHERO.SBR b/src/Uisrc/UI/DEBUG/CREAHERO.SBR new file mode 100644 index 0000000..ebc9b34 Binary files /dev/null and b/src/Uisrc/UI/DEBUG/CREAHERO.SBR differ diff --git a/src/Uisrc/UI/DEBUG/CREDITS.SBR b/src/Uisrc/UI/DEBUG/CREDITS.SBR new file mode 100644 index 0000000..9c8ceef Binary files /dev/null and b/src/Uisrc/UI/DEBUG/CREDITS.SBR differ diff --git a/src/Uisrc/UI/DEBUG/DEBUG/VC50.IDB b/src/Uisrc/UI/DEBUG/DEBUG/VC50.IDB new file mode 100644 index 0000000..08e29b2 Binary files /dev/null and b/src/Uisrc/UI/DEBUG/DEBUG/VC50.IDB differ diff --git a/src/Uisrc/UI/DEBUG/DIABEDIT.SBR b/src/Uisrc/UI/DEBUG/DIABEDIT.SBR new file mode 100644 index 0000000..74d319a Binary files /dev/null and b/src/Uisrc/UI/DEBUG/DIABEDIT.SBR differ diff --git a/src/Uisrc/UI/DEBUG/DIABLOUI.EXP b/src/Uisrc/UI/DEBUG/DIABLOUI.EXP new file mode 100644 index 0000000..6e42d71 Binary files /dev/null and b/src/Uisrc/UI/DEBUG/DIABLOUI.EXP differ diff --git a/src/Uisrc/UI/DEBUG/DIABLOUI.RES b/src/Uisrc/UI/DEBUG/DIABLOUI.RES new file mode 100644 index 0000000..3682082 Binary files /dev/null and b/src/Uisrc/UI/DEBUG/DIABLOUI.RES differ diff --git a/src/Uisrc/UI/DEBUG/DIABLOUI.SBR b/src/Uisrc/UI/DEBUG/DIABLOUI.SBR new file mode 100644 index 0000000..8e9659b Binary files /dev/null and b/src/Uisrc/UI/DEBUG/DIABLOUI.SBR differ diff --git a/src/Uisrc/UI/DEBUG/HELLFRUI.EXP b/src/Uisrc/UI/DEBUG/HELLFRUI.EXP new file mode 100644 index 0000000..136bd5e Binary files /dev/null and b/src/Uisrc/UI/DEBUG/HELLFRUI.EXP differ diff --git a/src/Uisrc/UI/DEBUG/HELLFRUI.LIB b/src/Uisrc/UI/DEBUG/HELLFRUI.LIB new file mode 100644 index 0000000..41bc48b Binary files /dev/null and b/src/Uisrc/UI/DEBUG/HELLFRUI.LIB differ diff --git a/src/Uisrc/UI/DEBUG/RCA15699 b/src/Uisrc/UI/DEBUG/RCA15699 new file mode 100644 index 0000000..e69de29 diff --git a/src/Uisrc/UI/DEBUG/STANDARD.LIB b/src/Uisrc/UI/DEBUG/STANDARD.LIB new file mode 100644 index 0000000..7d6fc5f Binary files /dev/null and b/src/Uisrc/UI/DEBUG/STANDARD.LIB differ diff --git a/src/Uisrc/UI/DEBUG/STORM.LIB b/src/Uisrc/UI/DEBUG/STORM.LIB new file mode 100644 index 0000000..67499fd Binary files /dev/null and b/src/Uisrc/UI/DEBUG/STORM.LIB differ diff --git a/src/Uisrc/UI/DEBUG/UI.PCH b/src/Uisrc/UI/DEBUG/UI.PCH new file mode 100644 index 0000000..489bb7c Binary files /dev/null and b/src/Uisrc/UI/DEBUG/UI.PCH differ diff --git a/src/Uisrc/UI/DEBUG/VC50.IDB b/src/Uisrc/UI/DEBUG/VC50.IDB new file mode 100644 index 0000000..46ae63d Binary files /dev/null and b/src/Uisrc/UI/DEBUG/VC50.IDB differ diff --git a/src/Uisrc/UI/DIABEDIT.CPP b/src/Uisrc/UI/DIABEDIT.CPP new file mode 100644 index 0000000..29c8e12 --- /dev/null +++ b/src/Uisrc/UI/DIABEDIT.CPP @@ -0,0 +1,290 @@ +//**************************************************************************** +// DiabEdit.cpp +// Diablo UI custom edit ctrl +// +// By Frank Pearce +// created 10.23.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + #define CURSOR_TIMER_ID 1 + #define CURSOR_TIMER_DELAY 500 + + #define MAX_RESTRICTED 256 + + #define LIMITPROP "LIMIT" + #define CURSORFLAGPROP "CURSOR" + #define RESTRICTEDPROP "RESTRICTED" + + +//**************************************************************************** +//**************************************************************************** +static void DiabEditNotify(HWND window, int notifycode) { + SendMessage( + GetParent(window), + WM_COMMAND, + MAKELONG(GetWindowLong(window, GWL_ID), notifycode), + (LPARAM)window + ); +} + + +//**************************************************************************** +//**************************************************************************** +void DiabEditPaint (HWND window) { + PAINTSTRUCT ps; + HDC dc = BeginPaint(window,&ps); + + // PAINT THE BITMAP + SDlgDrawBitmap(window,SDLG_USAGE_BACKGROUND,(HRGN)0); + + EndPaint(window,&ps); +} + + +//**************************************************************************** +//**************************************************************************** +static void DiabEditFlashCursor(HWND window) { + char buffer[256] = ""; + BOOL flag; + int len; + + flag = (BOOL) GetProp(window, CURSORFLAGPROP); + if (flag) { + flag = FALSE; + SetProp(window, CURSORFLAGPROP, (HANDLE) flag); + DiabEditNotify(window, DEN_UPDATE); + } + else { + flag = TRUE; + SetProp(window, CURSORFLAGPROP, (HANDLE) flag); + + GetWindowText(window, buffer, 255); + buffer[254] = 0; + len = strlen(buffer); + + buffer[len] = DIABLO_EDITCURSOR; + buffer[len+1] = 0; + SetWindowText(window, buffer); + DiabEditNotify(window, DEN_UPDATE); + + buffer[len] = 0; + SetWindowText(window, buffer); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DiabEditHandleChar(HWND window, WPARAM wparam, LPARAM lparam) { + unsigned char c; + LPSTR restricted; + char buffer[256] = ""; + + c = wparam & 0xff; + + if (c != '\b') { + // prescreen some characters that should never be allowed + if (c < ' ') return; + if ((c > '~') && (c < 192)) return; + + // screen user specified restricted chars + restricted = (LPSTR) GetProp(window, RESTRICTEDPROP); + if (restricted) { + while (*restricted) { + if (c == *restricted) return; + restricted++; + } + } + } + + // get the current string + GetWindowText(window,buffer,255); + buffer[254] = 0; + int len = strlen(buffer); + + switch (c) { + + case '\b': + if (len) { + buffer[len-1] = 0; + SetWindowText(window,buffer); + } + break; + + default: + // add the new char to the string + if (len < (int) GetProp(window, LIMITPROP)) { + buffer[len++] = c; + buffer[len] = 0; + SetWindowText(window,buffer); + } + break; + } + + DiabEditFlashCursor(window); +} + + +//**************************************************************************** +//**************************************************************************** +static void DiabEditHandleKeydown(HWND window, WPARAM wparam, LPARAM lparam) { + unsigned char c; + char buffer[256] = ""; + + // get the current string + GetWindowText(window,buffer,255); + buffer[254] = 0; + int len = strlen(buffer); + + switch (wparam) { + case VK_LEFT: + c = wparam & 0xff; + if (len) { + buffer[len-1] = 0; + SetWindowText(window,buffer); + } + DiabEditFlashCursor(window); + break; + + case VK_RIGHT: + case VK_UP: + case VK_DOWN: + default: + // don't do anything with these + break; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DiabEditSetRestricted(HWND window, LPSTR newrestricted) { + LPSTR oldrestricted = (LPSTR) GetProp(window, RESTRICTEDPROP); + + if (oldrestricted) { + strncpy(oldrestricted, newrestricted, MAX_RESTRICTED-1); + oldrestricted[MAX_RESTRICTED-1] = 0; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DiabEditCreate(HWND window) { + LPSTR restricted; + + SDlgSetTimer(window, CURSOR_TIMER_ID, CURSOR_TIMER_DELAY, NULL); + SetProp(window, CURSORFLAGPROP, (HANDLE) FALSE); + + restricted = (LPSTR) ALLOC(MAX_RESTRICTED); + if (!restricted) + return; + restricted[0] = 0; + SetProp(window, RESTRICTEDPROP, (HANDLE) restricted); +} + + +//**************************************************************************** +//**************************************************************************** +static void DiabEditDestroy(HWND window) { + SDlgKillTimer(window, CURSOR_TIMER_ID); + + RemoveProp(window, LIMITPROP); + RemoveProp(window, CURSORFLAGPROP); + LPSTR restricted = (LPSTR) RemoveProp(window, RESTRICTEDPROP); + if (restricted) { + FREE(restricted); + } +} + + +//**************************************************************************** +//**************************************************************************** +static LRESULT CALLBACK DiabEditWndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_CREATE: + DiabEditCreate(window); + break; + + case WM_DESTROY: + DiabEditDestroy(window); + break; + + case WM_GETDLGCODE: + return (DLGC_WANTCHARS | DLGC_WANTARROWS); + + case WM_CHAR: + DiabEditHandleChar(window, wparam, lparam); + break; + + case WM_KEYDOWN: + DiabEditHandleKeydown(window, wparam, lparam); + return 0; + + case WM_LBUTTONDOWN: + SetFocus(window); + break; + + case WM_SETFOCUS: + DiabEditNotify(window, DEN_SETFOCUS); + break; + + case WM_PAINT: + DiabEditPaint(window); + return 0; + + case WM_TIMER: + DiabEditFlashCursor(window); + return 0; + + case DEM_CLEAR: + SetWindowText(window, ""); + DiabEditNotify(window, DEN_UPDATE); + return 0; + + case DEM_LIMITTEXT: + SetProp(window, LIMITPROP, (HANDLE) wparam); + return 0; + + case DEM_GETLIMITTEXT: + return (LRESULT) GetProp(window, LIMITPROP); + + case DEM_CURSORON: + return (LRESULT) GetProp(window, CURSORFLAGPROP); + + case DEM_RESTRICTCHARS: + DiabEditSetRestricted(window, (LPSTR) lparam); + return 0; + } + return DefWindowProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +void DiabEditRegisterClass (void) { + WNDCLASS wndclass; + ZeroMemory(&wndclass,sizeof(WNDCLASS)); + wndclass.style = CS_CLASSDC; + wndclass.lpfnWndProc = DiabEditWndProc; + wndclass.hInstance = (HINSTANCE)GetModuleHandle(NULL); + wndclass.lpszClassName = "DIABLOEDIT"; + RegisterClass(&wndclass); +} diff --git a/src/Uisrc/UI/DIABEDIT.H b/src/Uisrc/UI/DIABEDIT.H new file mode 100644 index 0000000..384d589 --- /dev/null +++ b/src/Uisrc/UI/DIABEDIT.H @@ -0,0 +1,35 @@ +//**************************************************************************** +// DiabEdit.h +// Diablo UI custom edit ctrl +// +// By Frank Pearce +// created 10.23.96 +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** + #define DIABLO_EDITCURSOR '|' + + +//**************************************************************************** +// DiabloEdit ctrl notification messages +//**************************************************************************** + #define DEN_SETFOCUS 1 + #define DEN_KILLFOCUS 2 + #define DEN_UPDATE 3 + + +//**************************************************************************** +// messages the parent can send to the Diablo edit +//**************************************************************************** + #define DEM_CLEAR WM_USER + #define DEM_LIMITTEXT (WM_USER+1) + #define DEM_GETLIMITTEXT (WM_USER+2) + #define DEM_CURSORON (WM_USER+3) + #define DEM_RESTRICTCHARS (WM_USER+4) + + +//**************************************************************************** +//**************************************************************************** + void DiabEditRegisterClass(void); diff --git a/src/Uisrc/UI/DIABLOUI.APS b/src/Uisrc/UI/DIABLOUI.APS new file mode 100644 index 0000000..f44be32 Binary files /dev/null and b/src/Uisrc/UI/DIABLOUI.APS differ diff --git a/src/Uisrc/UI/DIABLOUI.CPP b/src/Uisrc/UI/DIABLOUI.CPP new file mode 100644 index 0000000..fae86f7 --- /dev/null +++ b/src/Uisrc/UI/DIABLOUI.CPP @@ -0,0 +1,141 @@ +/**************************************************************************** +* +* DIABLOUI.CPP +* Diablo UI library common code +* +* By Michael O'Brien (9/12/96) +* +***/ + +#define OEMRESOURCE + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +HINSTANCE global_hinstance = (HINSTANCE)0; + +LPBYTE ui_background = NULL; +SIZE ui_backgroundsize = {0,0}; + + +extern BOOL LoadGlobalHeroArt(void); +extern void FreeGlobalHeroArt(void); + +//**************************************************************************** +//**************************************************************************** +static BOOL sgSpawned = FALSE; + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL UiIsSpawned() { + return sgSpawned; +} + + +//=========================================================================== +void APIENTRY UiOnPaint (LPPARAMS params) { +#if 0 + LPBYTE videobuffer; + int pitch; + if (SDrawLockSurface(SDRAW_SURFACE_FRONT,NULL,&videobuffer,&pitch)) { + int screencx, screency; + SDrawGetScreenSize(&screencx,&screency,NULL); + if (ui_background) { + RECT destrect = {0,0,screencx-1,screency-1}; + RECT sourcerect = {0,0,ui_backgroundsize.cx-1,ui_backgroundsize.cy-1}; + SBltROP3Tiled(videobuffer, + &destrect, + pitch, + ui_background, + &sourcerect, + ui_backgroundsize.cx, + 0, + 0, + 0, + SRCCOPY); + } + else + SGdiRectangle(videobuffer,0,0,screencx-1,screency-1,PALETTEINDEX(0)); + SDrawUnlockSurface(SDRAW_SURFACE_FRONT,videobuffer); + } +#endif +} + +//=========================================================================== +BOOL APIENTRY UiSetBackgroundBitmap (HWND window, + LPPALETTEENTRY palette, + LPBYTE bitmapbits, + int width, + int height) { + ui_background = bitmapbits; + ui_backgroundsize.cx = width; + ui_backgroundsize.cy = height; + return SDrawUpdatePalette(10,236,palette+10); +} + + +//=========================================================================== +//=========================================================================== +void APIENTRY UiSetSpawned(BOOL spawned) { + sgSpawned = spawned; +} + + +//=========================================================================== +//=========================================================================== +static BOOL sgInUI; +void APIENTRY UiInitialize(void) { + sgInUI = TRUE; + + UiSndInit(); + ArtFontInit(); + LoadGlobalHeroArt(); + + UiLoadCursor(); +} + + +//=========================================================================== +//=========================================================================== +void APIENTRY UiDestroy() { + + UiDestroyCursor(); + FreeGlobalHeroArt(); + + sgInUI = FALSE; +} + + +//=========================================================================== +//=========================================================================== +void APIENTRY UiAppActivate(BOOL activating) { + if (! sgInUI) return; + +} + + +//=========================================================================== +//=========================================================================== +//=========================================================================== +extern "C" BOOL APIENTRY DllMain (HINSTANCE instance, DWORD reason, LPVOID) { + switch (reason) { + case DLL_PROCESS_ATTACH: + global_hinstance = instance; + DiabEditRegisterClass(); + UiCreateIdentityPal(); + break; + case DLL_PROCESS_DETACH: + UiFreeIdentityPal(); + break; + } + return 1; +} + diff --git a/src/Uisrc/UI/DIABLOUI.DEF b/src/Uisrc/UI/DIABLOUI.DEF new file mode 100644 index 0000000..4406002 --- /dev/null +++ b/src/Uisrc/UI/DIABLOUI.DEF @@ -0,0 +1,31 @@ +LIBRARY hellfrui +EXPORTS +UiInitialize +UiDestroy +UiOnPaint +UiTitleDialog +UiCreditsDialog +UiSupportDialog +UiMainMenuDialog +UiSetBackgroundBitmap +UiSelHeroSingDialog +UiSelHeroMultDialog +UiGetDefaultStats +UiCreateGameCallback +UiDrawDescCallback +UiArtCallback +UiSoundCallback +UiAuthCallback +UiGetDataCallback +UiCategoryCallback +UiLogonDialog +UiProgressDialog +UiBetaDisclaimer +UiCopyProtError +UiMessageBoxCallback +UiSelectProvider +UiSelectGame +UiCreatePlayerDescription +UiCreateGameCriteria +UiSetSpawned +UiAppActivate \ No newline at end of file diff --git a/src/Uisrc/UI/DIABLOUI.H b/src/Uisrc/UI/DIABLOUI.H new file mode 100644 index 0000000..01de79b --- /dev/null +++ b/src/Uisrc/UI/DIABLOUI.H @@ -0,0 +1,265 @@ +//*************************************************************************** +// DiabloUI.h +// created 9.13.96 +//*************************************************************************** + + +//*************************************************************************** +extern "C" void APIENTRY UiInitialize(void); +extern "C" void APIENTRY UiSetSpawned(BOOL bSpawned); +extern "C" void APIENTRY UiDestroy(); +extern "C" void APIENTRY UiAppActivate(BOOL activating); + + +//*************************************************************************** +extern "C" BOOL CALLBACK UiCreateGameCallback (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); + +extern "C" BOOL CALLBACK UiArtCallback (DWORD providerid, + DWORD artid, + LPPALETTEENTRY pe, + LPBYTE buffer, + DWORD buffersize, + int *width, + int *height, + int *bitdepth); + +extern "C" BOOL CALLBACK UiSoundCallback(DWORD providerid, DWORD soundid, DWORD flags); + +extern "C" BOOL CALLBACK UiDrawDescCallback (DWORD providerid, + DWORD itemtype, + LPCSTR itemname, + LPCSTR itemdescription, + DWORD itemflags, + DWORD drawflags, + DWORD time, + LPDRAWITEMSTRUCT lpdis); + +extern "C" BOOL CALLBACK UiMessageBoxCallback(HWND hWnd, + LPCTSTR lpText, + LPCTSTR lpCaption, + UINT uType); + +extern "C" BOOL CALLBACK UiAuthCallback(DWORD dwItemType, LPCSTR szName, LPCSTR szDesc, DWORD dwUserFlags, LPCSTR szItem, LPSTR szErrorBuf, DWORD dwErrorBufSize); +extern "C" BOOL CALLBACK UiGetDataCallback(DWORD providerid, DWORD dataid, LPVOID buffer, DWORD buffersize, DWORD *bytesused); + +extern "C" BOOL CALLBACK UiCategoryCallback( + BOOL userinitiated, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD * categorybits, + DWORD * categorymask); + +//*************************************************************************** +enum _ui_classes { + UI_WARRIOR = 0, + UI_ROGUE, + UI_SORCERER, + UI_MONK, + UI_BARD, + UI_BARBARIAN, + UI_NUM_CLASSES +}; + +//*************************************************************************** +extern "C" BOOL APIENTRY UiTitleDialog (UINT timeoutseconds); +extern "C" BOOL APIENTRY UiBetaDisclaimer (UINT timeoutseconds); +extern "C" BOOL APIENTRY UiCreditsDialog (UINT pixelspersec); +extern "C" BOOL APIENTRY UiSupportDialog (UINT pixelspersec); + +//*************************************************************************** +enum _copyprot_results { + COPYPROT_OK = 1, + COPYPROT_CANCEL +}; +extern "C" BOOL APIENTRY UiCopyProtError (DWORD *result); + +//*************************************************************************** +#define DEFAULT_ATTRACT_TIMEOUT 30 +typedef void (CALLBACK *PLAYSND)(LPCSTR); +enum _mainmenu_selections { + MAINMENU_SINGLE_PLAYER = 1, + MAINMENU_MULTIPLAYER, + MAINMENU_REPLAY_INTRO, + MAINMENU_SUPPORT, + MAINMENU_SHOW_CREDITS, + MAINMENU_EXIT_DIABLO, + MAINMENU_ATTRACT_MODE +}; +extern "C" BOOL APIENTRY UiMainMenuDialog(LPCTSTR registration, + DWORD * selection, + bool allowMultiplayer, + PLAYSND sndfcn = NULL, + UINT attracttimeoutseconds = DEFAULT_ATTRACT_TIMEOUT); + +//*************************************************************************** +#define MAX_GAME_LEN 32 +#define MAX_PASSWORD_LEN 32 + +enum _difficulty { + DIFF_NORMAL, + DIFF_NIGHTMARE, + DIFF_HELL, + NUM_DIFFICULTIES +}; + + +typedef struct _gamedata TGAMEDATA; +struct _gamedata { + DWORD dwSeed; + BYTE bDiff; // Use enum's from _difficulty settings +}; + + +//*************************************************************************** +//*************************************************************************** +// all the functions and structures for selecting/creating/deleting heros +//*************************************************************************** +//*************************************************************************** +#define MAX_NAME_LEN 16 // including terminting char +#define MAX_CLASS_LEN 16 // including terminting char + +typedef struct _uiheroinfo TUIHEROINFO; +typedef TUIHEROINFO *TPUIHEROINFO; + +typedef struct _uidefaultstats { + WORD strength; + WORD magic; + WORD dexterity; + WORD vitality; +} TUIDEFSTATS, *TPUIDEFSTATS; + +struct _uiheroinfo { + TPUIHEROINFO next; + char name[MAX_NAME_LEN]; // eg "Frasier" + + WORD level; + BYTE heroclass; // UI_WARRIOR, etc. + BYTE herorank; // # of times hero has killed Diablo (range = 0..NUM_DIFFICULTIES) + + WORD strength; + WORD magic; + WORD dexterity; + WORD vitality; + + DWORD gold; + BOOL hassaved; + BOOL spawned; +}; + +//*************************************************************************** + +#define UI_DESC_MAXLENGTH 128 + +// The following routines output a null terminated string to the provided preallocated +// pointers. The maximum length of the string is defined by the above constant. +extern "C" BOOL APIENTRY UiCreatePlayerDescription(TPUIHEROINFO pHeroInfo, DWORD dwProgramId, LPSTR pPlayerDesc); + +// Call this routine to generate a query string used by Battle.net to sort games in the +// JoinGame list. Returns the number of bytes written out to szQuery. +extern "C" int APIENTRY UiCreateGameCriteria(TPUIHEROINFO pHeroInfo, LPSTR pszQuery); + +//*************************************************************************** + +typedef BOOL (CALLBACK *ENUMHEROPROC)(TPUIHEROINFO); +typedef BOOL (CALLBACK *ENUMHEROS)(ENUMHEROPROC); +typedef BOOL (CALLBACK *CREATEHERO)(TPUIHEROINFO); +typedef BOOL (CALLBACK *DELETEHERO)(TPUIHEROINFO); +typedef BOOL (CALLBACK *GETDEFHERO)(int, TPUIDEFSTATS); + +enum _selhero_selections { + SELHERO_NEW_DUNGEON = 1, + SELHERO_CONTINUE, + SELHERO_CONNECT, + SELHERO_PREVIOUS +}; +extern "C" BOOL APIENTRY UiSelHeroSingDialog( + ENUMHEROS enumfcn, + CREATEHERO createfcn, + DELETEHERO deletefcn, + GETDEFHERO getstatsfcn, + DWORD *selection, + LPSTR heroname, + int *difficulty, + bool allowBard, + bool allowBarbarian + ); +extern "C" BOOL APIENTRY UiSelHeroMultDialog( + ENUMHEROS enumfcn, + CREATEHERO createfcn, + DELETEHERO deletefcn, + GETDEFHERO getstatsfcn, + DWORD *selection, + LPSTR heroname, + bool allowBard, + bool allowBarbarian + ); + +// if the default starting statistics for a character class change +// then Diablo.exe will have to provide this function +extern "C" BOOL CALLBACK UiGetDefaultStats(int heroclass, TPUIDEFSTATS defaultstats); + +//*************************************************************************** +extern "C" BOOL APIENTRY UiLogonDialog(HWND parent, + DWORD *selection, + LPSTR logonname, + UINT maxnamelen, + LPSTR logonpassword, + UINT maxpasswordlen); + +//*************************************************************************** +typedef int (CALLBACK *PROGRESSFCN)(void); +extern "C" BOOL APIENTRY UiProgressDialog(HWND parent, + LPCSTR progresstext, + BOOL abortable, + PROGRESSFCN progressfcn, + DWORD callspersec); + +//*************************************************************************** +extern "C" void APIENTRY UiOnPaint (LPPARAMS params); +extern "C" BOOL APIENTRY UiSetBackgroundBitmap (HWND window, + LPPALETTEENTRY palette, + LPBYTE bitmapbits, + int width, + int height); + +//*************************************************************************** +//*************************************************************************** +extern "C" BOOL APIENTRY UiSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid); +extern "C" BOOL APIENTRY UiSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); + + +//*************************************************************************** +//*************************************************************************** + #define DEVNAME_LEN SNETSPI_MAXSTRINGLENGTH + #define DEVDESC_LEN SNETSPI_MAXSTRINGLENGTH + #define MAX_DIAL_LEN 32 + enum _dialmodes { + MODE_ANSWER = (IDCANCEL + 1), + MODE_DIALOLD, + MODE_DIALNEW + }; + typedef struct _modeminfo TMODEM; + typedef TMODEM *TPMODEM; + struct _modeminfo { + TPMODEM next; + DWORD deviceid; + TCHAR devicename[DEVNAME_LEN]; + TCHAR devicedesc[DEVDESC_LEN]; + }; diff --git a/src/Uisrc/UI/DIABLOUI.RC b/src/Uisrc/UI/DIABLOUI.RC new file mode 100644 index 0000000..f1740dd --- /dev/null +++ b/src/Uisrc/UI/DIABLOUI.RC @@ -0,0 +1,116 @@ +//Microsoft Developer Studio generated resource script. +// +#include "unused.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "mike.rc" +#include "frank.rc" + +///////////////////////////////////////////////////////////////////////////// +#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 + "unused.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""mike.rc""\r\n" + "#include ""frank.rc""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "frank.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""mike.rc""\r\n" + "#include ""frank.rc""\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "frank.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Uisrc/UI/DIRLINK.CPP b/src/Uisrc/UI/DIRLINK.CPP new file mode 100644 index 0000000..179596f --- /dev/null +++ b/src/Uisrc/UI/DIRLINK.CPP @@ -0,0 +1,481 @@ +//**************************************************************************** +// DirLink.cpp +// Diablo UI create/join direct link multiplayer game +// +// By Frank Pearce +// created 11.8.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +#define SERIAL_JOIN_AUTHORIZE 0 + +//**************************************************************************** +//**************************************************************************** + extern void TitleLogoDestroy(void); + extern void TitleLogoInit(HWND window); + extern void TitleFramesInit(HWND window, LPCTSTR filename); + extern void TitleLogoAnimate(HWND window); + + extern int SelOkDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus); + + extern BOOL UiDoomCreateGame (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid, + BOOL loadfocus, + LPCSTR gamename); + + +//**************************************************************************** +//**************************************************************************** + #define PROVIDERID 'SCBL' + + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define LOGO_TIMER_ID 2 + #define LOGO_FPS 17 + #define LOGO_TIMER_DELAY 55 + + #define ENUM_TIMER_ID 3 // how often we re-enum available games + #define ENUM_TIMER_DELAY 2000 + + +//**************************************************************************** +//**************************************************************************** + static int sgTitleIDs[] = { + IDC_DLGTITLE, + IDC_DLGTITLE2, + 0 + }; + static int sgTextIDs[] = { + IDC_DLGTITLE3, + 0 + }; + static int sgGameDescID[] = { + IDC_LINKDESC, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgListIDs[] = { + IDC_DIRLINKBTN1, + IDC_DIRLINKBTN2, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** + #define GAMENAME_LEN SNETSPI_MAXSTRINGLENGTH + #define DESCRIPTION_LEN SNETSPI_MAXSTRINGLENGTH + + typedef struct _serialgame TGAME; + typedef TGAME *TPGAME; + struct _serialgame { + DWORD gameid; + TCHAR gamename[GAMENAME_LEN]; + TCHAR gamedesc[DESCRIPTION_LEN]; + }; + static TGAME sgGame; + + static SNETPROGRAMDATAPTR sgDLProgramData; + static SNETPLAYERDATAPTR sgDLPlayerData; + static SNETUIDATAPTR sgDLInterfaceData; + static SNETVERSIONDATAPTR sgDLVersionData; + static DWORD *sgpDLPlayerID; + + static void DirLinkUpdateGame(HWND window); + static void DirLinkAutoJoin(HWND window); + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK DirLinkEnum(DWORD gameid, + LPCSTR gamename, + LPCSTR gamedesc) { + sgGame.gameid = gameid; + strcpy(sgGame.gamename, gamename); + strcpy(sgGame.gamedesc, gamedesc); + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkSetInfo(HWND window, int childid) { + TCHAR desc[256]; + HWND child = GetDlgItem(window, IDC_LINKDESC); + + if (childid == IDC_DIRLINKBTN1) + LoadString(global_hinstance, IDS_CREATEDESC, desc, 255); + else + LoadString(global_hinstance, IDS_RETRYCONNDESC, desc, 255); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), desc); + UiDoomStaticReset(window, sgGameDescID, AF_SMALLGRAY); +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkDestroy(HWND window) { + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgGameDescID); + UiDoomCtrlsDestroy(window, sgTextIDs); + UiDoomCtrlsDestroy(window, sgTitleIDs); + + // free the background of the dlg + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + TitleLogoDestroy(); + FocusAnimateDestroy(); +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkInit(HWND window) { + TPBMP tpBmp; + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus16.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + // set up the animating diablo logo + TitleLogoInit(window); + TitleFramesInit(window,TEXT("ui_art\\hf_logo2.pcx")); + TitleLogoAnimate(window); + SDlgSetTimer(window, LOGO_TIMER_ID, LOGO_TIMER_DELAY, NULL); + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\selgame.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window); + } + + UiOnPaintBtns(window, sgListIDs); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTitleIDs, AF_BIGGRAY); + UiDoomStaticInit(window, sgTextIDs, AF_MEDGRAY); + UiDoomStaticInit(window, sgGameDescID, AF_SMALLGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_MED); + + // see if there's a game + DirLinkUpdateGame(window); + DirLinkAutoJoin(window); + + // set a timer so the game list is periodically updated + SDlgSetTimer(window, ENUM_TIMER_ID, ENUM_TIMER_DELAY, NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkAbort(HWND window, int ReturnVal) { + UiSndPlayEnter(); + UiFadeAbort(window); + SDlgKillTimer(window, ENUM_TIMER_ID); + SDlgKillTimer(window, LOGO_TIMER_ID); + SDlgKillTimer(window, FOCUS_TIMER_ID); + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkCreate(HWND window) { + SNETUIDATA interfacedata; + SNETCREATEDATA createdata; + + // create new interface data + CopyMemory(&interfacedata,sgDLInterfaceData,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = window; + + ZeroMemory(&createdata,sizeof(SNETCREATEDATA)); + createdata.size = sizeof(SNETCREATEDATA); + createdata.providerid = PROVIDERID; + createdata.maxplayers = sgDLProgramData->maxplayers; + createdata.createflags = 0; + + if (UiDoomCreateGame( + &createdata, + sgDLProgramData, + sgDLPlayerData, + &interfacedata, + sgDLVersionData, + sgpDLPlayerID, + FALSE, + sgDLPlayerData->playername + ) + ) { + DirLinkAbort(window, IDOK); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkAutoJoin(HWND window) { + if (! sgGame.gameid) return; + +#if SERIAL_JOIN_AUTHORIZE + if (! + UiAuthCallback( + SNET_AUTHTYPE_GAME, + sgDLPlayerData->playername, + sgDLPlayerData->playerdescription, + 0, + sgGame.gamedesc, + NULL, + 0 + ) + ) { + return; + } +#endif + + if (SNetJoinGame( + sgGame.gameid, + sgGame.gamename, + NULL, + sgDLPlayerData->playername, + sgDLPlayerData->playerdescription, + sgpDLPlayerID + ) + ) { + DirLinkAbort(window, IDOK); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkJoin(HWND window) { + char err[256]; + if (! + UiAuthCallback( + SNET_AUTHTYPE_GAME, + sgDLPlayerData->playername, + sgDLPlayerData->playerdescription, + 0, + sgGame.gamedesc, + err, + sizeof(err) + ) + ) { + SelOkDialog(window, err, NULL, FALSE); + return; + } + + if (SNetJoinGame( + sgGame.gameid, + sgGame.gamename, + NULL, + sgDLPlayerData->playername, + sgDLPlayerData->playerdescription, + sgpDLPlayerID + ) + ) { + DirLinkAbort(window, IDOK); + } + else { + // unable to join the specified game + TCHAR format[64], errstr[128]; + LoadString(global_hinstance, IDS_JOIN_ERR, format, 63); + wsprintf(errstr, format, sgGame.gamename); + SelOkDialog(window, errstr, NULL, FALSE); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkAttemptJoin(HWND window) { + HWND child = GetFocus(); + + if (window != GetParent(child)) return; + + if (IDC_DIRLINKBTN1 == GetWindowLong(child, GWL_ID)) { + DirLinkCreate(window); + } + else if (sgGame.gameid) { + DirLinkJoin(window); + } + else { + // a game has not been detected + TCHAR errstr[128]; + LoadString(global_hinstance, IDS_NOGAME_ERR, errstr, 127); + SelOkDialog(window, errstr, NULL, FALSE); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkUpdateGame(HWND window) { + // clear old info + sgGame.gameid = 0; + sgGame.gamename[0] = 0; + sgGame.gamedesc[0] = 0; + + // enum will fill in info if a game exists + if (! SNetEnumGames(0, 0, DirLinkEnum, NULL)) { //### MM Diablo Patch #2 3/21/97 + if (GetLastError() == SNET_ERROR_VERSION_MISMATCH) { + // display a version mismatch error + TCHAR err[128]; + LoadString(global_hinstance, IDS_VERSION_ERR, err, 127); + SelOkDialog(window, err, NULL, FALSE); + DirLinkAbort(window, IDCANCEL); + } + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DirLinkInterpretClick(HWND window, int x, int y) { + if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKEOK), x, y)) { + DirLinkAttemptJoin(window); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKECANCEL), x, y)) { + DirLinkAbort(window, IDCANCEL); + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK DirLinkDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + DirLinkSetInfo(window, LOWORD(wparam)); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + DirLinkAttemptJoin(window); + } + else if (LOWORD(wparam) == IDOK) { + DirLinkAttemptJoin(window); + } + else if (LOWORD(wparam) == IDCANCEL) { + DirLinkAbort(window, IDCANCEL); + } + break; + + case WM_LBUTTONDOWN: + DirLinkInterpretClick(window, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_DESTROY: + DirLinkDestroy(window); + break; + + case WM_INITDIALOG: + // Post this WM_USER message first so that fade gets started even if + // DirLinkInit() needs to go into a modal dialog to display an error. + PostMessage(window, WM_USER+1000, 0, 0); + DirLinkInit(window); + return 0; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_TIMER: + switch (wparam) { + case FOCUS_TIMER_ID: + FocusAnimate(window, GetFocus()); + break; + case LOGO_TIMER_ID: + TitleLogoAnimate(window); + break; + case ENUM_TIMER_ID: + DirLinkUpdateGame(window); + DirLinkAutoJoin(window); + break; + } + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiDirectLinkGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + int result = 0; + + // save parameters for use throughout this file + sgDLProgramData = programdata; + sgDLPlayerData = playerdata; + sgDLInterfaceData = interfacedata; + sgDLVersionData = versiondata; + sgpDLPlayerID = playerid; + + // make sure fonts are loaded + ArtFontLoad(); + + // DISPLAY THE DIALOG BOX + result = SDlgDialogBox(global_hinstance, + TEXT("DIRLINK_DIALOG"), + interfacedata->parentwindow, + DirLinkDialogProc); + + ArtFontDestroy(); + + if (result == IDOK) + return TRUE; + return FALSE; +} diff --git a/src/Uisrc/UI/DISCLAIM.CPP b/src/Uisrc/UI/DISCLAIM.CPP new file mode 100644 index 0000000..0f54f38 --- /dev/null +++ b/src/Uisrc/UI/DISCLAIM.CPP @@ -0,0 +1,169 @@ +//**************************************************************************** +//*** +//*** DISCLAIM.CPP +//*** Diablo UI disclaimer screen dialog (for the Battle.Net beta) +//*** +//*** By Frank Pearce (10/14/96) +//*** +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" + + +#define ALLOW_TIMEOUT 0 + +//**************************************************************************** +//**************************************************************************** + #define TIMER_ID 1 + #define MILLISEC_PER_SEC 1000 + #define DEFAULT_TIMEOUT 10 + + static int sgTextIDs0[] = { + IDC_TEXT1, + IDC_TEXT2, + 0 + }; + static int sgTextIDs1[] = { + IDC_TEXT3, + IDC_TEXT4, + IDC_TEXT5, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** +static void DisclaimerDestroy (HWND window) { + UiDoomCtrlsDestroy(window, sgTextIDs1); + UiDoomCtrlsDestroy(window, sgTextIDs0); + + // free the background of the dlg + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); +} + + +//**************************************************************************** +//**************************************************************************** +static void DisclaimerInit(HWND window, LPARAM lparam) { + TPBMP tpBmp; + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\disclaim.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window, FALSE); + } + +#if ALLOW_TIMEOUT + if (lparam) + SDlgSetTimer(window, TIMER_ID, lparam*MILLISEC_PER_SEC, NULL); + else + SDlgSetTimer(window, TIMER_ID, DEFAULT_TIMEOUT*MILLISEC_PER_SEC, NULL); +#endif + + UiDoomStaticInit(window, sgTextIDs0, AF_BIGGRAY); + UiDoomStaticInit(window, sgTextIDs1, AF_MED); +} + + +//**************************************************************************** +//**************************************************************************** +static void DisclaimerAbort(HWND window) { + UiFadeAbort(window); +#if ALLOW_TIMEOUT + SDlgKillTimer(window, TIMER_ID); +#endif + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, 1); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK DisclaimerDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_DESTROY: + DisclaimerDestroy(window); + break; + + case WM_INITDIALOG: + DisclaimerInit(window, lparam); + PostMessage(window, WM_USER+1000, 0, 0); + return 1; + + case WM_COMMAND: + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_KEYDOWN: + DisclaimerAbort(window); + return 0; + + case WM_PARENTNOTIFY: + if (LOWORD(wparam) == WM_LBUTTONDOWN || LOWORD(wparam) == WM_RBUTTONDOWN) { + DisclaimerAbort(window); + } + break; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + +#if ALLOW_TIMEOUT + case WM_TIMER: + switch (wparam) { + case TIMER_ID: + DisclaimerAbort(window); + break; + } + return 0; +#endif + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//*** +//*** EXPORTED FUNCTIONS +//*** +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiBetaDisclaimer (UINT timeoutseconds) { + SDlgDialogBoxParam( + global_hinstance, + "DISCLAIMER_DIALOG", + SDrawGetFrameWindow(), + DisclaimerDialogProc, + timeoutseconds + ); + + return 1; +} diff --git a/src/Uisrc/UI/DOOM.CPP b/src/Uisrc/UI/DOOM.CPP new file mode 100644 index 0000000..a95b33f --- /dev/null +++ b/src/Uisrc/UI/DOOM.CPP @@ -0,0 +1,398 @@ +//**************************************************************************** +// Doom.cpp +// created 10.23.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" + + +//**************************************************************************** +//**************************************************************************** + extern int FocusWidth(void); + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomTextEditDraw(HWND window) { + TPBMP tpBmp; + BOOL cursor; + RECT rect; + TCHAR buf[256]; + TCHAR * prntstr; + int x, y, width, len; + + tpBmp = (TPBMP) GetWindowLong(window, GWL_USERDATA); + if (! tpBmp) return; + if (! tpBmp->data) return; + + GetWindowText(window, buf, 255); + len = strlen(buf); + + // calculate the width that can be allowed + x = FocusWidth() + ArtFontGridWidth(); + GetClientRect(window, &rect); + width = rect.right - (2 * FocusWidth()) - (2 * ArtFontGridWidth()); + + // don't use cursor in calc of width + if (TRUE == (cursor = SendMessage(window, DEM_CURSORON, 0, 0))) + buf[len - 1] = 0; + + prntstr = buf; + while ((*prntstr) && (ArtFontPixelWidth(prntstr) > width)) + prntstr++; + + // add the cursor back on + if (cursor) + buf[len - 1] = DIABLO_EDITCURSOR; + + y = (tpBmp->datasize.cy - ArtFontHeight()) / 2; + ArtFontDraw(prntstr, tpBmp, x, y); +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomTextBtnDraw(HWND window, BOOL getsfocus) { + TPBMP tpBmp; + TCHAR textbuf[256]; + TCHAR * text; + int x, y, len, width, maxwidth; + + tpBmp = (TPBMP) GetWindowLong(window, GWL_USERDATA); + if (! tpBmp) return; + if (! tpBmp->data) return; + + GetWindowText(window, textbuf, 255); + if (strlen(textbuf)) + text = textbuf; + else + text = tpBmp->text; + + width = ArtFontPixelWidth(text); + + if (getsfocus) { + // truncate string until it fits in the region + maxwidth = tpBmp->datasize.cx - (FocusWidth() * 2); + len = strlen(text); + for ( ; width > maxwidth; width = ArtFontPixelWidth(text)) { + text[--len] = 0; + } + } + + x = (tpBmp->datasize.cx - width - 1) / 2; + y = (tpBmp->datasize.cy - ArtFontHeight()) / 2; + ArtFontDraw(text, tpBmp, x, y); + + InvalidateRect(window, NULL, FALSE); +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomTextDraw(HWND window, LONG style) { + TPBMP tpBmp; + TCHAR textbuf[256]; + TCHAR * text; + int x, width; + + tpBmp = (TPBMP) GetWindowLong(window, GWL_USERDATA); + if (! tpBmp) return; + if (! tpBmp->data) return; + + GetWindowText(window, textbuf, 255); + if (strlen(textbuf)) + text = textbuf; + else + text = tpBmp->text; + + if (0 != (style & SS_RIGHT)) { + width = ArtFontPixelWidth(text); + x = tpBmp->datasize.cx - width - 1; + } + else if (0 != (style & SS_CENTER)) { + width = ArtFontPixelWidth(text); + x = (tpBmp->datasize.cx - width - 1) / 2; + } + else { + x = 0; + } + + ArtFontDraw(text, tpBmp, x, 0); + + InvalidateRect(window, NULL, FALSE); +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomCreateBg(HWND Parent, HWND Child, int usage) { + TPBMP ChildBmp; + RECT rect; + + // create a TBMP for the child + GetClientRect(Child, &rect); + ChildBmp = UiAllocBmp(); + ChildBmp->datasize.cx = rect.right; + ChildBmp->datasize.cy = rect.bottom; + ChildBmp->data = (LPBYTE) ALLOC(rect.right * rect.bottom); + SetWindowLong(Child, GWL_USERDATA, (LONG) ChildBmp); + + // set it so the ctrl uses the bmp just created + SDlgSetBitmap( + Child, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + usage, + ChildBmp->data, + NULL, + ChildBmp->datasize.cx, + ChildBmp->datasize.cy + ); +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomDrawBg(HWND Parent, HWND Child) { + TPBMP ChildBmp, ParentBmp; + RECT rect; + + ParentBmp = (TPBMP) GetWindowLong(Parent, GWL_USERDATA); + ChildBmp = (TPBMP) GetWindowLong(Child, GWL_USERDATA); + if (! ParentBmp) return; + if (! ParentBmp->data) return; + if (! ChildBmp) return; + if (! ChildBmp->data) return; + + GetWindowRect(Child,&rect); + ScreenToClient(Parent, (LPPOINT)&rect.left); + ScreenToClient(Parent, (LPPOINT)&rect.right); + + SBltROP3 ( + ChildBmp->data, + ParentBmp->data + (rect.top * ParentBmp->datasize.cx) + rect.left, + ChildBmp->datasize.cx, + ChildBmp->datasize.cy, + ChildBmp->datasize.cx, + ParentBmp->datasize.cx, + NULL, + SRCCOPY + ); +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomEditCreate(HWND Parent, HWND Child, int fontnum) { + if (! Child) return; + + // create a bmp and draw parent image into it + UiDoomCreateBg(Parent, Child, SDLG_USAGE_BACKGROUND); + UiDoomDrawBg(Parent, Child); + + // draw the text into the bmp + ArtFontSet(fontnum); + UiDoomTextEditDraw(Child); +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomEditReset(HWND Parent, HWND Child, int fontnum) { + if (! Child) return; + + UiDoomDrawBg(Parent, Child); + + // draw the text into the bmp + ArtFontSet(fontnum); + UiDoomTextEditDraw(Child); +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomStaticCreate(HWND Parent, HWND Child, int fontnum) { + if (! Child) return; + + // create a bmp and draw parent image into it + UiDoomCreateBg(Parent, Child, SDLG_USAGE_BACKGROUND); + UiDoomDrawBg(Parent, Child); + + // draw the text into the bmp + ArtFontSet(fontnum); + UiDoomTextDraw(Child, GetWindowLong(Child, GWL_STYLE)); + + // save the window text in the bmp text buffer + TCHAR textbuf[256]; + GetWindowText(Child, textbuf, 255); + if (strlen(textbuf)) { + UiSetBmpText((TPBMP) GetWindowLong(Child, GWL_USERDATA), textbuf); + SetWindowText(Child, TEXT("")); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomStaticReset(HWND Parent, HWND Child, int fontnum) { + if (! Child) return; + + UiDoomDrawBg(Parent, Child); + + // draw the text into the bmp + ArtFontSet(fontnum); + UiDoomTextDraw(Child, GetWindowLong(Child, GWL_STYLE)); + + // save the window text in the bmp text buffer + TCHAR textbuf[256]; + GetWindowText(Child, textbuf, 255); + if (strlen(textbuf)) { + UiSetBmpText((TPBMP) GetWindowLong(Child, GWL_USERDATA), textbuf); + SetWindowText(Child, TEXT("")); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomButtonCreate(HWND Parent, HWND Child, int fontnum, BOOL getsfocus) { + if (! Child) return; + + // create a bmp and draw parent image into it + UiDoomCreateBg( + Parent, + Child, + SDLG_USAGE_BACKGROUND | SDLG_USAGE_NORMAL | SDLG_USAGE_SELECTED | SDLG_USAGE_GRAYED + ); + UiDoomDrawBg(Parent, Child); + + // draw the text into the bmp + ArtFontSet(fontnum); + UiDoomTextBtnDraw(Child, getsfocus); + + // save the window text in the bmp text buffer + TCHAR textbuf[256]; + GetWindowText(Child, textbuf, 255); + if (strlen(textbuf)) { + UiSetBmpText((TPBMP) GetWindowLong(Child, GWL_USERDATA), textbuf); + SetWindowText(Child, TEXT("")); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void UiDoomButtonReset(HWND Parent, HWND Child, int fontnum, BOOL getsfocus) { + if (! Child) return; + + UiDoomDrawBg(Parent, Child); + + // draw the text into the bmp + ArtFontSet(fontnum); + UiDoomTextBtnDraw(Child, getsfocus); + + // save the window text in the bmp text buffer + TCHAR textbuf[256]; + GetWindowText(Child, textbuf, 255); + if (strlen(textbuf)) { + UiSetBmpText((TPBMP) GetWindowLong(Child, GWL_USERDATA), textbuf); + SetWindowText(Child, TEXT("")); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiDoomButtonsInit(HWND Parent, int * BtnIDs, int fontnum, BOOL getsfocus) { + for ( ; *BtnIDs; BtnIDs++) { + UiDoomButtonCreate( + Parent, + GetDlgItem(Parent, *BtnIDs), + fontnum, + getsfocus + ); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiDoomButtonsReset(HWND Parent, int * BtnIDs, int fontnum, BOOL getsfocus) { + for ( ; *BtnIDs; BtnIDs++) { + UiDoomButtonReset( + Parent, + GetDlgItem(Parent, *BtnIDs), + fontnum, + getsfocus + ); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiDoomStaticInit(HWND Parent, int * TextIDs, int fontnum) { + for ( ; *TextIDs; TextIDs++) { + UiDoomStaticCreate( + Parent, + GetDlgItem(Parent, *TextIDs), + fontnum + ); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiDoomStaticReset(HWND Parent, int * TextIDs, int fontnum) { + for ( ; *TextIDs; TextIDs++) { + UiDoomStaticReset( + Parent, + GetDlgItem(Parent, *TextIDs), + fontnum + ); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiDoomEditInit(HWND Parent, int * EditIDs, int fontnum) { + for ( ; *EditIDs; EditIDs++) { + UiDoomEditCreate( + Parent, + GetDlgItem(Parent, *EditIDs), + fontnum + ); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiDoomEditReset(HWND Parent, int * EditIDs, int fontnum) { + for ( ; *EditIDs; EditIDs++) { + UiDoomEditReset( + Parent, + GetDlgItem(Parent, *EditIDs), + fontnum + ); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiDoomCtrlsDestroy(HWND Parent, int * CtrlIDs) { + HWND child; + + for ( ; *CtrlIDs; CtrlIDs++) { + child = GetDlgItem(Parent, *CtrlIDs); + if (! child) continue; + UiFreeBmp((TPBMP) GetWindowLong(child, GWL_USERDATA)); + SetWindowLong(child, GWL_USERDATA, (LONG) NULL); + } +} diff --git a/src/Uisrc/UI/DOOM.H b/src/Uisrc/UI/DOOM.H new file mode 100644 index 0000000..f8cd6d4 --- /dev/null +++ b/src/Uisrc/UI/DOOM.H @@ -0,0 +1,24 @@ +//**************************************************************************** +// Doom.h +// created 9.13.96 +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +void UiDoomButtonsInit(HWND Parent, + int * BtnIDs, + int fontnum = 0, + BOOL getsfocus = TRUE); +void UiDoomButtonsReset(HWND Parent, + int * BtnIDs, + int fontnum = 0, + BOOL getsfocus = TRUE); +void UiDoomStaticInit(HWND Parent, int * TextIDs, int fontnum = 0); +void UiDoomStaticReset(HWND Parent, int * TextIDs, int fontnum = 0); + +void UiDoomEditInit(HWND Parent, int * EditIDs, int fontnum = 0); +void UiDoomEditReset(HWND Parent, int * EditIDs, int fontnum = 0); + +void UiDoomCtrlsDestroy(HWND Parent, int * BtnIDs); + diff --git a/src/Uisrc/UI/ENTRDIAL.CPP b/src/Uisrc/UI/ENTRDIAL.CPP new file mode 100644 index 0000000..4ba9fc9 --- /dev/null +++ b/src/Uisrc/UI/ENTRDIAL.CPP @@ -0,0 +1,195 @@ +//**************************************************************************** +// EntrDial.cpp +// Diablo UI enter dial string for modem +// +// By Frank Pearce +// created 11.23.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern void ModemSetInfo(HWND window, LPCSTR infotitle, LPCSTR text); + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define RESTRICTED_CHARS TEXT("<>%&?") + + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgEditIDs[] = { + IDC_DIALEDIT, + 0 + }; + + static LPSTR sgDialString; + + +//**************************************************************************** +//**************************************************************************** +static void EntrDialSetInfo(HWND window) { + TCHAR title[64], desc[256]; + + LoadString(global_hinstance, IDS_ENTERDIAL_TITLE, title, 63); + LoadString(global_hinstance, IDS_ENTERDIAL_INFO, desc, 255); + ModemSetInfo(GetParent(window), title, desc); +} + + +//**************************************************************************** +//**************************************************************************** +static void EntrDialDestroy(HWND window) { + FocusAnimateDestroy(); + UiDoomCtrlsDestroy(window, sgEditIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + ModemSetInfo(GetParent(window), NULL, NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void EntrDialInit(HWND window) { + HWND child; + HWND parent = GetParent(window); + + // point this window at the same bmp it's parent uses + SetWindowLong( + window, + GWL_USERDATA, + GetWindowLong(parent, GWL_USERDATA) + ); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomEditInit(window, sgEditIDs, AF_MED); + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + child = GetDlgItem(window, IDC_DIALEDIT); + // limit the amout of text that can be typed + SendMessage(child, DEM_LIMITTEXT, MAX_DIAL_LEN-1, 0); + + // restritc chars that can be entered + SendMessage(child, DEM_RESTRICTCHARS, 0, (LPARAM)RESTRICTED_CHARS); + + EntrDialSetInfo(window); +} + + +//**************************************************************************** +//**************************************************************************** +static void EntrDialAbort(HWND window, int ReturnVal) { + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + + // get the dial string from the edit + GetWindowText( + GetDlgItem(window, IDC_DIALEDIT), + sgDialString, + MAX_DIAL_LEN + ); + sgDialString[MAX_DIAL_LEN-1] = 0; + + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void EntrDialDEN(HWND window, WPARAM wparam, LPARAM lparam) { + switch (HIWORD(wparam)) { + case DEN_UPDATE: + UiDoomEditReset(window, sgEditIDs, AF_MED); + break; + case DEN_SETFOCUS: + FocusAnimate(window, GetFocus()); + break; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void EntrDialInterpretClick(HWND window, int x, int y) { + if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKEOK), x, y)) { + EntrDialAbort(window, IDOK); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKECANCEL), x, y)) { + EntrDialAbort(window, IDCANCEL); + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK EnterDialDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: + EntrDialAbort(window, IDOK); + break; + case IDCANCEL: + EntrDialAbort(window, IDCANCEL); + break; + case IDC_DIALEDIT: + EntrDialDEN(window, wparam, lparam); + break; + } + break; + + case WM_LBUTTONDOWN: + EntrDialInterpretClick(window, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_DESTROY: + EntrDialDestroy(window); + break; + + case WM_INITDIALOG: + sgDialString = (LPSTR) lparam; + EntrDialInit(window); + return 0; + + case WM_TIMER: + FocusAnimate(window, GetFocus()); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} diff --git a/src/Uisrc/UI/ENTRNAME.CPP b/src/Uisrc/UI/ENTRNAME.CPP new file mode 100644 index 0000000..663ca9b --- /dev/null +++ b/src/Uisrc/UI/ENTRNAME.CPP @@ -0,0 +1,198 @@ +//**************************************************************************** +// EntrName.cpp +// Diablo UI enter name for a new hero +// +// By Frank Pearce +// created 10.20.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern void SelHeroSetTitle(HWND window, LPCTSTR title); + extern int SelHeroGetMode(void); + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define RESTRICTED_CHARS TEXT(" ,<>%&\\\"?*#/") + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgEditIDs[] = { + IDC_NAMEEDIT, + 0 + }; + + static LPSTR sgName; + + +//**************************************************************************** +//**************************************************************************** +static void EntrNameDestroy(HWND window) { + FocusAnimateDestroy(); + UiDoomCtrlsDestroy(window, sgEditIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + SelHeroSetTitle(GetParent(window), NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void EntrNameInit(HWND window) { + TCHAR buf[32]; + HWND child; + HWND parent = GetParent(window); + + // set the title for the parent + if (SelHeroGetMode() == MULTIPLAYER) + LoadString(global_hinstance, IDS_NEWMULTHERO, buf, 32-1); + else + LoadString(global_hinstance, IDS_NEWSINGHERO, buf, 32-1); + SelHeroSetTitle(parent, buf); + + // point this window at the same bmp it's parent uses + SetWindowLong( + window, + GWL_USERDATA, + GetWindowLong(parent, GWL_USERDATA) + ); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomEditInit(window, sgEditIDs, AF_MED); + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + child = GetDlgItem(window, IDC_NAMEEDIT); + // limit the amout of text that can be typed + SendMessage(child, DEM_LIMITTEXT, MAX_NAME_LEN-1, 0); + // restritc chars that can be entered + if (SelHeroGetMode() == MULTIPLAYER) { + SendMessage(child, DEM_RESTRICTCHARS, 0, (LPARAM)RESTRICTED_CHARS); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void EntrNameAbort(HWND window, int ReturnVal) { + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + + // get the name text from the edit + GetWindowText( + GetDlgItem(window, IDC_NAMEEDIT), + sgName, + MAX_NAME_LEN + ); + sgName[MAX_NAME_LEN-1] = 0; + + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void EntrNameDEN(HWND window, WPARAM wparam, LPARAM lparam) { + switch (HIWORD(wparam)) { + case DEN_UPDATE: + UiDoomEditReset(window, sgEditIDs, AF_MED); + break; + case DEN_SETFOCUS: + FocusAnimate(window, GetFocus()); + break; + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK EnterNameDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: + EntrNameAbort(window, IDOK); + break; + case IDCANCEL: + EntrNameAbort(window, IDCANCEL); + break; + case IDC_NAMEEDIT: + EntrNameDEN(window, wparam, lparam); + break; + } + break; + + case WM_LBUTTONDOWN: + if ( + UiIsPtInWindow( + window, + GetDlgItem(window, IDC_FAKEOK), + LOWORD(lparam), + HIWORD(lparam) + ) + ) { + EntrNameAbort(window, IDOK); + } + else if ( + UiIsPtInWindow( + window, + GetDlgItem(window, IDC_FAKECANCEL), + LOWORD(lparam), + HIWORD(lparam) + ) + ) { + EntrNameAbort(window, IDCANCEL); + } + break; + + case WM_DESTROY: + EntrNameDestroy(window); + break; + + case WM_INITDIALOG: + sgName = (LPSTR) lparam; + EntrNameInit(window); + return 0; + + case WM_TIMER: + FocusAnimate(window, GetFocus()); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} diff --git a/src/Uisrc/UI/FADE.CPP b/src/Uisrc/UI/FADE.CPP new file mode 100644 index 0000000..663c184 --- /dev/null +++ b/src/Uisrc/UI/FADE.CPP @@ -0,0 +1,142 @@ +//**************************************************************************** +// fade.cpp +// created 10.28.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + #define FADE_TIMER_ID 16 + #define FADE_TIMER_DELAY 50 + + +//**************************************************************************** +//**************************************************************************** + static int sgFadeStep; + static BOOL sgFading; + static PALETTEENTRY sgFadePal[PALETTE_REGISTERS]; + + +//**************************************************************************** +//**************************************************************************** +static void RestoreWindowsColors(void) { + HPALETTE hPal; + + // Get Windows Default colors from the system + hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); + + GetPaletteEntries(hPal, 0, 10, &sgFadePal[0]); + GetPaletteEntries(hPal, 10, 10, &sgFadePal[PALETTE_REGISTERS-10]); + SDrawUpdatePalette(0, PALETTE_REGISTERS, &sgFadePal[0], TRUE); +} + + +//**************************************************************************** +// an async fade function +//**************************************************************************** +void UiVidFade(int max, int curr) { + PALETTEENTRY * PalEntry = UiPaletteEntry(0); + + if (max == curr) { + memcpy(sgFadePal, PalEntry, (PALETTE_REGISTERS * sizeof(PALETTEENTRY))); + } + else if (curr == 0) { + memcpy(sgFadePal, PalEntry, (PALETTE_REGISTERS * sizeof(PALETTEENTRY))); + UiClearPalette(sgFadePal); + } + else { + for (int palreg = 0; palreg < PALETTE_REGISTERS; palreg++, PalEntry++) { + sgFadePal[palreg].peRed = (PalEntry->peRed * curr) / max; + sgFadePal[palreg].peGreen = (PalEntry->peGreen * curr) / max; + sgFadePal[palreg].peBlue = (PalEntry->peBlue * curr) / max; + } + } + SDrawUpdatePalette(0, PALETTE_REGISTERS, sgFadePal, TRUE); +} + + +//**************************************************************************** +//**************************************************************************** +void UiVidFadeOut(int steps) { + PALETTEENTRY * PalEntry = UiPaletteEntry(0); + + memcpy(sgFadePal, PalEntry, (PALETTE_REGISTERS * sizeof(PALETTEENTRY))); + for (int index = 0; index < steps; index++) { + PalEntry = UiPaletteEntry(0); + for (int palreg = 0; palreg < PALETTE_REGISTERS; palreg++, PalEntry++) { + sgFadePal[palreg].peRed -= (PalEntry->peRed / steps); + sgFadePal[palreg].peGreen -= (PalEntry->peGreen / steps); + sgFadePal[palreg].peBlue -= (PalEntry->peBlue / steps); + } + SDrawUpdatePalette(0, PALETTE_REGISTERS, sgFadePal, TRUE); + } + + UiClearPalette(sgFadePal); + SDrawUpdatePalette(0, PALETTE_REGISTERS, sgFadePal, TRUE); + UiClearCursor(); + SDrawClearSurface(SDRAW_SURFACE_FRONT); + RestoreWindowsColors(); +} + + +//**************************************************************************** +//**************************************************************************** +static void CALLBACK UiFadeTimerProc(HWND window, + UINT message, + UINT timerid, + DWORD systime) { + if (sgFadeStep <= DEFAULT_FADE_STEPS) { + UiVidFade(DEFAULT_FADE_STEPS, sgFadeStep); + sgFadeStep++; + } + else { + SDlgKillTimer(window, FADE_TIMER_ID); + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiIsFading() { + return sgFading && (sgFadeStep <= DEFAULT_FADE_STEPS); +} + + +//**************************************************************************** +//**************************************************************************** +void UiFadeAbort(HWND window) { + if (! UiIsFading()) return; + sgFading = FALSE; +} + + +//**************************************************************************** +//**************************************************************************** +void UiFadeInit(HWND window, BOOL turnoncursor) { + UiFlushIOMessages(GetParent(window)); + if (turnoncursor) + UiSetCursor(); + sgFading = FALSE; + sgFadeStep = 0; +} + + +//**************************************************************************** +// use this for screens that fade out but don't fade in +//**************************************************************************** +void UiAltFadeInit(HWND window) { + UiFlushIOMessages(GetParent(window)); +} + + +//**************************************************************************** +//**************************************************************************** +void UiFadeStart(HWND window) { + if (! sgFading) { + BOOL result = SDlgSetTimer(window, FADE_TIMER_ID, FADE_TIMER_DELAY, UiFadeTimerProc); + sgFading = TRUE; + } +} diff --git a/src/Uisrc/UI/FADE.H b/src/Uisrc/UI/FADE.H new file mode 100644 index 0000000..3ca9324 --- /dev/null +++ b/src/Uisrc/UI/FADE.H @@ -0,0 +1,19 @@ +//**************************************************************************** +// fade.h +// created 10.28.96 +//**************************************************************************** + +#define DEFAULT_FADE_STEPS 5 +#define DEFAULT_STEPS 5 + +//**************************************************************************** +//**************************************************************************** +void UiVidFade(int max, int curr); +void UiVidFadeOut(int steps); + +void UiFadeInit(HWND window, BOOL turnoncursor = TRUE); +void UiAltFadeInit(HWND window); +void UiFadeStart(HWND window); + +void UiFadeAbort(HWND window); +BOOL UiIsFading(); diff --git a/src/Uisrc/UI/FOCUS.CPP b/src/Uisrc/UI/FOCUS.CPP new file mode 100644 index 0000000..93e15f3 --- /dev/null +++ b/src/Uisrc/UI/FOCUS.CPP @@ -0,0 +1,234 @@ +//**************************************************************************** +// Focus.cpp +// code for animating the input focus indicator (for a "Doom-like" interface +// +// By Frank Pearce +// created 10.16.96 +//**************************************************************************** + + +#include "pch.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + #define MAX_FRAMES 8 + + static HTRANS sgTransHandles[MAX_FRAMES]; + static SIZE sgFrameSize; + static int sgFrame; + static BOOL sgFocusLostBefore; + static HWND sgLastFocusWnd; + + +//**************************************************************************** +//**************************************************************************** +void FocusSnd(HWND focus) { + if (focus == sgLastFocusWnd) return; + if (sgFocusLostBefore) { + UiSndPlayClick(); + } + sgLastFocusWnd = focus; +} + + +//**************************************************************************** +// returns the width of a frame of the focus animation +//**************************************************************************** +int FocusWidth(void) { + return sgFrameSize.cx; +} + + +//**************************************************************************** +//**************************************************************************** +static void FocusInvalidate(HWND child) { + RECT rect; + + GetClientRect(child, &rect); + rect.bottom--; + rect.right--; + + // invalidate right side of ctrl + rect.left = rect.right - sgFrameSize.cx; + InvalidateRect(child, &rect, FALSE); + + // invalidate left side of ctrl + rect.left = 0; + rect.right = sgFrameSize.cx - 1; + InvalidateRect(child, &rect, FALSE); +} + + +//**************************************************************************** +//**************************************************************************** +void FocusErase(HWND parent, HWND child) { + TPBMP ParentBmp, ChildBmp; + RECT rect; + int xoffset; + + ParentBmp = (TPBMP) GetWindowLong(parent, GWL_USERDATA); + ChildBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! ParentBmp) return; + if (! ChildBmp) return; + if (! ParentBmp->data) return; + if (! ChildBmp->data) return; + + GetWindowRect(child,&rect); + ScreenToClient(parent, (LPPOINT)&rect.left); + ScreenToClient(parent, (LPPOINT)&rect.right); + + // erase the left end + SBltROP3 ( + ChildBmp->data, + ParentBmp->data + (rect.top * ParentBmp->datasize.cx) + rect.left, + sgFrameSize.cx, + ChildBmp->datasize.cy, + ChildBmp->datasize.cx, + ParentBmp->datasize.cx, + NULL, + SRCCOPY + ); + + // erase the right end + xoffset = ChildBmp->datasize.cx - sgFrameSize.cx; + SBltROP3 ( + ChildBmp->data + xoffset, + ParentBmp->data + (rect.top * ParentBmp->datasize.cx) + rect.left + xoffset, + sgFrameSize.cx, + ChildBmp->datasize.cy, + ChildBmp->datasize.cx, + ParentBmp->datasize.cx, + NULL, + SRCCOPY + ); + + FocusInvalidate(child); +} + + +//**************************************************************************** +//**************************************************************************** +void FocusLost(HWND parent, HWND child) { + int id = GetWindowLong(child, GWL_ID); + FocusErase(parent, child); + sgFocusLostBefore = TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +BOOL FocusAnimate(HWND parent, HWND child) { + TPBMP ChildBmp; + int xoffset, yoffset; + RECT rect; + + if (! child) return FALSE; + + int id = GetWindowLong(child, GWL_ID); + + if (parent != GetParent(child)) + return FALSE; + + // erase the previous image + FocusErase(parent, child); + + ChildBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! ChildBmp) return FALSE; + if (! ChildBmp->data) return FALSE; + + GetWindowRect(child,&rect); + ScreenToClient(parent, (LPPOINT)&rect.left); + ScreenToClient(parent, (LPPOINT)&rect.right); + + if (sgTransHandles[sgFrame]) { + // center the image vertically + yoffset = (ChildBmp->datasize.cy - sgFrameSize.cy) / 2; +// yoffset = 0; + + // draw onto the left end + STransBlt(ChildBmp->data, 0, yoffset, ChildBmp->datasize.cx, sgTransHandles[sgFrame]); + + // draw onto the right end + xoffset = ChildBmp->datasize.cx - sgFrameSize.cx; + STransBlt(ChildBmp->data, xoffset, yoffset, ChildBmp->datasize.cx, sgTransHandles[sgFrame]); + + FocusInvalidate(child); + } + + + // advance to the next frame + sgFrame++; + if (sgFrame >= MAX_FRAMES) + sgFrame = 0; + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +void FocusAnimateDestroy(void) { + for (int index = 0; index < MAX_FRAMES; index++) { + if (sgTransHandles[index]) { + STransDelete(sgTransHandles[index]); + sgTransHandles[index] = NULL; + } + } +} + + +//**************************************************************************** +//**************************************************************************** +void FocusReInit(void) { + sgFocusLostBefore = FALSE; + sgLastFocusWnd = NULL; +} + + +//**************************************************************************** +//**************************************************************************** +void FocusAnimateInit(LPCSTR filename) { + LPBYTE srcframes = NULL; + SIZE srcsize; + RECT rect; + + sgFocusLostBefore = FALSE; + sgLastFocusWnd = NULL; + + UiLoadBmpFile( + filename, + &srcframes, + &srcsize + ); + + memset(sgTransHandles, 0, sizeof(sgTransHandles)); + + if (srcframes) { + sgFrameSize.cx = srcsize.cx; + sgFrameSize.cy = srcsize.cy / MAX_FRAMES; + + // create an HTRANS for each frame in the animation + for (int index = 0; index < MAX_FRAMES; index++) { + + rect.left = 0; + rect.right = sgFrameSize.cx - 1; + rect.top = index * sgFrameSize.cy; + rect.bottom = rect.top + sgFrameSize.cy - 1; + + STransCreate( + srcframes, + sgFrameSize.cx, + sgFrameSize.cy, + 8, + &rect, + PALETTEINDEX(250), + &sgTransHandles[index] + ); + } + + FREE(srcframes); + } + sgFrame = 0; +} + diff --git a/src/Uisrc/UI/FRANK.APS b/src/Uisrc/UI/FRANK.APS new file mode 100644 index 0000000..f8ed36e Binary files /dev/null and b/src/Uisrc/UI/FRANK.APS differ diff --git a/src/Uisrc/UI/FRANK.H b/src/Uisrc/UI/FRANK.H new file mode 100644 index 0000000..3603894 --- /dev/null +++ b/src/Uisrc/UI/FRANK.H @@ -0,0 +1,189 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Frank.rc +// +#define IDS_WARRIOR 4 +#define IDS_ROGUE 5 +#define IDS_SORCERER 6 +#define IDS_CONFIRM_DELETE 7 +#define IDS_CONFIRM_OVERWRITE 8 +#define IDS_NAME_ERR 15 +#define IDS_CREATE_ERR 16 +#define IDS_DELETE_ERR 17 +#define IDS_ENUMCHAR_ERR 18 +#define IDS_FIRST_NASTY 19 +#define IDS_STRING20 20 +#define IDS_STRING21 21 +#define IDS_STRING22 22 +#define IDS_STRING23 23 +#define IDS_STRING24 24 +#define IDS_STRING25 25 +#define IDS_LAST_NASTY 26 +#define IDS_COPYPROT_ERR 27 +#define IDS_MULTILIST_TITLE 28 +#define IDS_SINGLIST_TITLE 29 +#define IDS_NEWHERO 30 +#define IDS_NEWSINGHERO 31 +#define IDS_NEWMULTHERO 32 +#define IDS_PLAYERSSUPPORTED 33 +#define IDS_DELETESINGHERO 34 +#define IDS_DELETEMULTHERO 35 +#define IDS_CREATEGAME 36 +#define IDS_JOIN_ERR 37 +#define IDS_CREATEGAME_ERR 38 +#define IDS_NORMAL 39 +#define IDS_NIGHTMARE 40 +#define IDS_HELL 41 +#define IDS_CREATEDESC 42 +#define IDS_NOGAME_ERR 43 +#define IDS_SELCONN_ERR 44 +#define IDS_SPAWN_ERR 45 +#define IDS_NOMODEM_ERR 46 +#define IDS_RETRYCONNDESC 47 +#define IDS_GAMEDESCFMT 49 +#define IDS_VERSION_ERR 50 +#define IDS_MODEMJOIN_ERR 51 +#define IDS_CALL_FMT 52 +#define IDS_INITMODEM_ERR 53 +#define IDS_MODEM_CREATE 54 +#define IDS_MODEM_DIALNEW 55 +#define IDS_MODEM_DIALOLD 56 +#define IDS_SELDIAL_INFOTITLE 57 +#define IDS_ENTERDIAL_INFO 58 +#define IDS_ENTERDIAL_TITLE 59 +#define IDS_SPAWNDATA_ERR 63 +#define IDS_NOANSWER_ERR 64 +#define IDS_NOTONE_ERR 65 +#define IDS_BUSY_ERR 66 +#define IDS_MODEM_CREATE2 67 +#define IDS_MODEM_JOIN 68 +#define IDS_SPAWNCLASS_ERR 69 +#define IDS_SPAWNINTRO_ERR 70 +#define IDS_MODEMGAMENAME_FMT 71 +#define IDS_DUPGAMENAME_FMT 73 +#define IDS_MODEMJOINPREV 74 +#define IDS_MODEMJOINNEW 75 +#define IDS_MODEMOFF_ERR 76 +#define IDS_JOINGAMES 77 +#define IDS_MEMORY_ERR 78 +#define IDC_CREATECHAR_BTN 1000 +#define ID_SCROLL_WINDOW 1000 +#define IDC_MULTIPLAYER_BTN 1001 +#define IDC_REPLAYINTRO_BTN 1002 +#define IDC_SHOWCREDITS_BTN 1003 +#define IDDELETE 1006 +#define IDC_NEWDUNGEON_BTN 1007 +#define IDC_CHARNAME 1010 +#define IDC_CHARCLASS 1011 +#define IDC_CHARGOLD 1013 +#define IDC_CHARLEVEL 1014 +#define IDC_CHARVIT 1015 +#define IDC_CHARDEX 1016 +#define IDC_CHARMAGIC 1017 +#define IDC_CHARSTR 1018 +#define IDC_HEROS_LBOX 1020 +#define IDC_WARRIOR_RADIO 1022 +#define IDC_SORCERER_RADIO 1023 +#define IDC_ROGUE_RADIO 1024 +#define IDC_HERONAME_EDIT 1025 +#define IDC_OKCANCEL_TEXT 1026 +#define IDC_CLASS_DESCRIPTION 1027 +#define IDC_LOGONNAME_EDIT 1028 +#define IDC_LOGONPASSWORD_EDIT 1029 +#define IDC_UIGENERIC_PROGRESS 1030 +#define IDC_PROGRESS_TEXT 1031 +#define IDC_NDNORMAL_RADIO 1033 +#define IDC_NDADVANCED_RADIO 1034 +#define IDC_NDNIGHTMARE_RADIO 1035 +#define IDC_DIFFICULTY_DESCRIPTION 1036 +#define IDC_DLGTITLE 1038 +#define IDC_HEROIMAGE 1040 +#define IDC_REGISTRATION 1042 +#define IDC_LOGO 1043 +#define IDC_SINGLEPLAYER_BTN 1044 +#define IDC_HEROBTN1 1047 +#define IDC_HEROBTN2 1048 +#define IDC_HEROBTN3 1049 +#define IDC_HEROBTN4 1050 +#define IDC_HEROBTN5 1051 +#define IDC_HEROBTN6 1052 +#define IDC_FAKECANCEL 1054 +#define IDC_FAKEOK 1056 +#define IDC_LEVELLBL 1057 +#define IDC_STRLBL 1058 +#define IDC_MAGLBL 1059 +#define IDC_DEXLBL 1060 +#define IDC_VITLBL 1061 +#define IDC_WARRIORBTN 1062 +#define IDC_ROGUEBTN 1063 +#define IDC_SORCERERBTN 1064 +#define IDC_NAMEEDIT 1065 +#define IDC_SMACKER 1066 +#define IDC_BLIZZARD 1067 +#define IDC_CONNECTBTN1 1069 +#define IDC_CONNECTBTN2 1070 +#define IDC_CONNECTBTN3 1071 +#define IDC_CONNECTBTN4 1072 +#define IDC_CONNECTBTN5 1073 +#define IDC_CONNECTBTN6 1074 +#define IDC_REQTITLE 1075 +#define IDC_PLAYERSTEXT 1076 +#define IDC_DLGTITLE2 1080 +#define IDC_CONNECTTEXT 1081 +#define IDC_TEXT1 1082 +#define IDC_TEXT2 1083 +#define IDC_TEXT3 1084 +#define IDC_TEXT4 1085 +#define IDC_TEXT5 1086 +#define IDC_GAMEBTN1 1088 +#define IDC_GAMEBTN2 1089 +#define IDC_GAMEBTN3 1090 +#define IDC_GAMEBTN4 1091 +#define IDC_GAMEBTN5 1092 +#define IDC_GAMEBTN6 1093 +#define IDC_DIFFBTN1 1094 +#define IDC_DIFFBTN2 1095 +#define IDC_DIFFBTN3 1096 +#define IDC_DLGTITLE3 1097 +#define IDC_GAMEDESC 1098 +#define IDC_DIFFDESC 1099 +#define IDC_DIRLINKBTN1 1100 +#define IDC_DIRLINKBTN2 1101 +#define IDC_LINKDESC 1102 +#define IDC_SCROLLBAR 1105 +#define IDC_LOADBTN 1106 +#define IDC_NEWBTN 1107 +#define IDC_MODEMDESC 1108 +#define IDC_OK 1109 +#define IDC_MODEMBTN1 1110 +#define IDC_MODEMBTN2 1111 +#define IDC_MODEMBTN3 1112 +#define IDC_MODEMBTN4 1113 +#define IDC_MODEMBTN5 1114 +#define IDC_MODEMBTN6 1115 +#define IDC_DIALEDIT 1116 +#define IDC_DIALBTN1 1117 +#define IDC_DIALBTN2 1118 +#define IDC_DIALBTN3 1119 +#define IDC_DIALBTN4 1120 +#define IDC_DIALBTN5 1121 +#define IDC_DIALBTN6 1122 +#define IDC_REQDESC 1123 +#define IDS_MONKBTN 1124 +#define IDC_MONKBTN 1125 +#define IDS_BARDBTN 1126 +#define IDC_MONKBTN2 1126 +#define IDC_BARDBTN 1127 +#define IDC_SUPPORT_BTN 1128 +#define IDC_BARBARIANBTN 1129 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 124 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1125 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Uisrc/UI/FRANK.RC b/src/Uisrc/UI/FRANK.RC new file mode 100644 index 0000000..a96c355 --- /dev/null +++ b/src/Uisrc/UI/FRANK.RC @@ -0,0 +1,905 @@ +//Microsoft Developer Studio generated resource script. +// +#include "frank.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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +TITLESCREEN_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + // The text is in the art. + //CTEXT "Copyright © 1997 Synergistic Software",IDC_BLIZZARD, + // 22,173,212,11,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,203 +END + +MAINMENU_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Start Game",IDC_SINGLEPLAYER_BTN,26,81,204,18, + BS_NOTIFY + PUSHBUTTON "Replay Intro",IDC_REPLAYINTRO_BTN,26,99,204,18, + BS_NOTIFY + PUSHBUTTON "Support",IDC_SUPPORT_BTN,26,117,204,18, + BS_NOTIFY + PUSHBUTTON "Credits",IDC_SHOWCREDITS_BTN,26,135,204,18, + BS_NOTIFY + PUSHBUTTON "Exit Hellfire",IDCANCEL,26,153,204,18,BS_NOTIFY + LTEXT "",IDC_REGISTRATION,7,187,242,9,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 +END + +MAINMENU_DIALOG2 DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Single Player",IDC_SINGLEPLAYER_BTN,26,81,204,18, + BS_NOTIFY + PUSHBUTTON "Multi Player",IDC_MULTIPLAYER_BTN,26,99,204,18, + BS_NOTIFY + PUSHBUTTON "Replay Intro",IDC_REPLAYINTRO_BTN,26,117,204,18, + BS_NOTIFY + PUSHBUTTON "Support",IDC_SUPPORT_BTN,26,135,204,18, + BS_NOTIFY + PUSHBUTTON "Credits",IDC_SHOWCREDITS_BTN,26,153,204,18, + BS_NOTIFY + PUSHBUTTON "Exit Hellfire",IDCANCEL,26,171,204,18,BS_NOTIFY + LTEXT "",IDC_REGISTRATION,7,187,242,9,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 +END + +SELHERO_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + RTEXT "Strength:",IDC_STRLBL,16,151,44,9 + RTEXT "Magic:",IDC_MAGLBL,16,160,44,9 + RTEXT "Dexterity:",IDC_DEXLBL,16,169,44,9 + RTEXT "Vitality:",IDC_VITLBL,16,178,44,9 + CTEXT "",IDC_CHARSTR,64,151,16,9 + CTEXT "",IDC_CHARMAGIC,64,160,16,9 + CTEXT "",IDC_CHARDEX,64,169,16,9 + CTEXT "",IDC_CHARVIT,64,178,16,9 + RTEXT "Level:",IDC_LEVELLBL,16,136,44,9 + CTEXT "",IDC_CHARLEVEL,64,136,16,9 + CONTROL "",IDC_HEROIMAGE,"Static",SS_BLACKFRAME | WS_DISABLED,12, + 89,72,32 + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 + CTEXT "Single Player Characters",IDC_DLGTITLE,10,68,236,15, + WS_DISABLED +END + +OKCANCEL_DIALOG DIALOGEX 0, 0, 112, 61 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "OK",IDC_OK,8,41,44,12 + PUSHBUTTON "Cancel",IDCANCEL,60,41,44,12 + CTEXT "",IDC_OKCANCEL_TEXT,8,5,96,34,0,WS_EX_TRANSPARENT +END + +LOGON_DIALOG DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_LOGONNAME_EDIT,52,34,88,12,ES_AUTOHSCROLL + EDITTEXT IDC_LOGONPASSWORD_EDIT,52,50,88,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,102,85,44,12 + PUSHBUTTON "Cancel",IDCANCEL,102,99,44,12 + RTEXT "Name:",IDC_STATIC,8,34,41,9,0,WS_EX_TRANSPARENT + RTEXT "Password:",IDC_STATIC,7,50,41,9,0,WS_EX_TRANSPARENT + CTEXT "Connect to Battlenet",IDC_DLGTITLE,0,8,154,9,0, + WS_EX_TRANSPARENT + LTEXT "You can open an account on battlenet FREE at WWW.BATTLE.NET.", + IDC_STATIC,8,76,88,38,0,WS_EX_TRANSPARENT +END + +PROGRESS_DIALOG DIALOGEX 0, 0, 112, 61 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "",IDC_PROGRESS_TEXT,0,4,112,18,0,WS_EX_TRANSPARENT + PUSHBUTTON "Cancel",IDCANCEL,34,42,44,12 + CONTROL "",IDC_UIGENERIC_PROGRESS,"Static",SS_BLACKFRAME,10,22, + 91,16 +END + +OK_DIALOG DIALOGEX 0, 0, 112, 61 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDC_OK,34,41,44,12 + CTEXT "",IDC_OKCANCEL_TEXT,8,5,96,34,0,WS_EX_TRANSPARENT +END + +BIGOK_DIALOG DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDC_OK,55,99,44,12 + CTEXT "",IDC_OKCANCEL_TEXT,8,20,139,75,0,WS_EX_TRANSPARENT + CTEXT "",IDC_DLGTITLE,7,7,140,9,0,WS_EX_TRANSPARENT +END + +BIGOKCANCEL_DIALOG DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDC_OK,22,99,44,12 + CTEXT "",IDC_OKCANCEL_TEXT,8,20,139,75,0,WS_EX_TRANSPARENT + DEFPUSHBUTTON "Cancel",IDCANCEL,88,99,44,12 + CTEXT "",IDC_DLGTITLE,7,7,140,9,0,WS_EX_TRANSPARENT +END + +CREDITS_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "TIMES NEW ROMAN", 700, 0, 0x1 +BEGIN + CONTROL "",ID_SCROLL_WINDOW,"Static",SS_BLACKFRAME | WS_DISABLED, + 12,48,232,106 +END + +SUPPORT_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "TIMES NEW ROMAN", 700, 0, 0x1 +BEGIN + CONTROL "",ID_SCROLL_WINDOW,"Static",SS_BLACKFRAME | WS_DISABLED, + 12,48,232,106 +END + +DISCLAIMER_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Not For Review",IDC_TEXT1,25,7,96,15 + CTEXT "Not For Resale",IDC_TEXT2,134,7,96,15 + LTEXT "This is a five level beta of Hellfire, playable only over Battle.net. There are some features that are not yet implemented, notably multi player quests. Please send all comments and bug reports to bnbeta@blizzard.com.", + IDC_TEXT3,8,30,240,70 + LTEXT "This version of Hellfire is intended for the use of registered Battle.net beta testers only. This beta is for integrity testing of Blizzard Entertainment's Battle.net service and is not intended for review by the media or resale in any manner.", + IDC_TEXT4,8,100,240,70 + LTEXT "Unauthorized distribution is strictly prohibited.", + IDC_TEXT5,8,170,240,14 +END + +SELLIST_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,196,180,48,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "",IDC_HEROBTN1,106,108,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN2,106,119,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN3,106,130,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN4,106,141,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN5,106,152,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN6,106,163,128,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,96,180,48,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Hero",IDC_DLGTITLE,106,89,128,14,WS_DISABLED + CONTROL "",IDC_SCROLLBAR,"Static",SS_BLACKFRAME | WS_DISABLED, + 234,103,10,75 + PUSHBUTTON "Delete",IDDELETE,146,180,48,15,BS_NOTIFY | WS_DISABLED | + NOT WS_TABSTOP +END + +SELCLASS_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Warrior",IDC_WARRIORBTN,106,105,128,14,BS_NOTIFY + PUSHBUTTON "Rogue",IDC_ROGUEBTN,106,119,128,14,BS_NOTIFY + PUSHBUTTON "Sorcerer",IDC_SORCERERBTN,106,133,128,14,BS_NOTIFY + PUSHBUTTON "Monk",IDC_MONKBTN,106,147,128,14,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + CTEXT "Choose Class",IDC_DLGTITLE,106,89,128,14,WS_DISABLED +END + +SELCLASS_DIALOG2 DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Warrior",IDC_WARRIORBTN,106,105,128,14,BS_NOTIFY + PUSHBUTTON "Rogue",IDC_ROGUEBTN,106,119,128,14,BS_NOTIFY + PUSHBUTTON "Sorcerer",IDC_SORCERERBTN,106,133,128,14,BS_NOTIFY + PUSHBUTTON "Monk",IDC_MONKBTN,106,147,128,14,BS_NOTIFY + PUSHBUTTON "Bard",IDC_BARDBTN,106,161,128,14,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + CTEXT "Choose Class",IDC_DLGTITLE,106,89,128,14,WS_DISABLED +END + +SELCLASS_DIALOG3 DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Warrior",IDC_WARRIORBTN,106,108,128,11,BS_NOTIFY + PUSHBUTTON "Rogue",IDC_ROGUEBTN,106,119,128,11,BS_NOTIFY + PUSHBUTTON "Sorcerer",IDC_SORCERERBTN,106,130,128,11,BS_NOTIFY + PUSHBUTTON "Monk",IDC_MONKBTN,106,141,128,11,BS_NOTIFY + PUSHBUTTON "Bard",IDC_BARDBTN,106,153,128,11,BS_NOTIFY + PUSHBUTTON "Barbarian",IDC_BARBARIANBTN,106,163,128,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + CTEXT "Choose Class",IDC_DLGTITLE,106,89,128,14,WS_DISABLED +END + +ENTERNAME_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CONTROL "",IDC_NAMEEDIT,"DIABLOEDIT",WS_TABSTOP,106,133,128,14 + CTEXT "Enter Name",IDC_DLGTITLE,106,89,128,14,WS_DISABLED + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP +END + +SELYESNO_DIALOG DIALOGEX 0, 81, 256, 122 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Yes",IDC_OK,92,84,72,15,BS_NOTIFY + PUSHBUTTON "No",IDCANCEL,92,99,72,15,BS_NOTIFY + LTEXT "",IDC_OKCANCEL_TEXT,48,8,160,71,WS_DISABLED +END + +SELCONNECT_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "",IDC_CONNECTBTN1,122,108,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_CONNECTBTN2,122,119,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_CONNECTBTN3,122,130,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_CONNECTBTN4,122,141,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_CONNECTBTN5,122,152,114,11,BS_NOTIFY + CTEXT "Multi Player Game",IDC_DLGTITLE,10,68,236,15, + WS_DISABLED + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,182,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + LTEXT "",IDC_CONNECTTEXT,14,122,82,72,WS_DISABLED + LTEXT "Requirements:",IDC_REQTITLE,14,108,82,9,WS_DISABLED + LTEXT "",IDC_PLAYERSTEXT,14,92,82,9,WS_DISABLED + CTEXT "Select Connection",IDC_DLGTITLE2,120,89,118,14, + WS_DISABLED + PUSHBUTTON "",IDC_CONNECTBTN6,122,163,114,11,BS_NOTIFY + CONTROL "",IDC_SCROLLBAR,"Static",SS_BLACKFRAME | WS_DISABLED, + 236,103,10,75 + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 +END + +SELOK_DIALOG DIALOGEX 0, 81, 256, 122 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDC_OK,92,84,72,15,BS_NOTIFY + LTEXT "",IDC_OKCANCEL_TEXT,56,8,160,71,WS_DISABLED +END + +SELIPXGAME_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "",IDC_GAMEBTN1,122,108,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN2,122,119,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN3,122,130,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN4,122,141,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN5,122,152,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN6,122,163,114,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + CTEXT "Join IPX Games",IDC_DLGTITLE,10,68,236,15,WS_DISABLED + CTEXT "Select Game",IDC_DLGTITLE2,120,89,118,14,WS_DISABLED + LTEXT "Description:",IDC_DLGTITLE3,14,89,82,14,WS_DISABLED + LTEXT "",IDC_GAMEDESC,14,108,82,81,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 + CONTROL "",IDC_SCROLLBAR,"Static",SS_BLACKFRAME | WS_DISABLED, + 236,103,10,75 +END + +SELDIFF_DIALOG DIALOGEX 0, 65, 256, 135 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Create Game",IDC_DLGTITLE,10,3,236,15,WS_DISABLED + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,115,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Normal",IDC_DIFFBTN1,120,54,118,11,BS_NOTIFY + PUSHBUTTON "Nightmare",IDC_DIFFBTN2,120,65,118,11,BS_NOTIFY + PUSHBUTTON "Hell",IDC_DIFFBTN3,120,76,118,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,115,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Difficulty",IDC_DLGTITLE2,120,24,118,15, + WS_DISABLED + CTEXT "",IDC_DLGTITLE3,14,24,82,14,WS_DISABLED + LTEXT "",IDC_DIFFDESC,14,43,82,81,WS_DISABLED +END + +DIRLINK_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Direct Link Connection",IDC_DLGTITLE,10,68,236,15, + WS_DISABLED + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Create Game",IDC_DIRLINKBTN1,120,119,118,11,BS_NOTIFY + PUSHBUTTON "Retry Connection",IDC_DIRLINKBTN2,120,130,118,11, + BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Action",IDC_DLGTITLE2,120,89,118,15,WS_DISABLED + LTEXT "Link Status:",IDC_DLGTITLE3,14,89,82,14,WS_DISABLED + LTEXT "",IDC_LINKDESC,14,108,82,81,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 +END + +SPAWNERR_DIALOG DIALOGEX 0, 69, 256, 134 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "OK",IDC_OK,92,103,72,18,BS_NOTIFY + LTEXT "",IDC_OKCANCEL_TEXT,56,15,160,75,WS_DISABLED +END + +SELLOAD_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Load Game",IDC_LOADBTN,106,119,128,14,BS_NOTIFY + PUSHBUTTON "New Game",IDC_NEWBTN,106,133,128,14,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Save File Exists",IDC_DLGTITLE,106,89,128,14, + WS_DISABLED +END + +MODEM_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Modem Connection",IDC_DLGTITLE,10,68,236,15 + CTEXT "",IDC_DLGTITLE2,14,89,82,14 + LTEXT "",IDC_MODEMDESC,14,108,82,81 + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 +END + +SELMODEM_DIALOG DIALOGEX 0, 65, 256, 135 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,115,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "",IDC_MODEMBTN1,122,43,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN2,122,54,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN3,122,65,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN4,122,76,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN5,122,87,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN6,122,98,114,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,115,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Modem",IDC_DLGTITLE2,120,24,118,14,WS_DISABLED + CONTROL "",IDC_SCROLLBAR,"Static",SS_BLACKFRAME | WS_DISABLED, + 236,38,10,75 + CTEXT "Modem Game Setup",IDC_DLGTITLE,10,3,236,15,WS_DISABLED + CTEXT "Requirments:",IDC_DLGTITLE3,14,24,82,14,WS_DISABLED + LTEXT "The modem must be 14400 BPS or faster. If the device you want to use is not listed here, please check your modem to ensure that it is configured correctly.", + IDC_REQDESC,14,43,82,81,WS_DISABLED +END + +ENTERDIAL_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CONTROL "",IDC_DIALEDIT,"DIABLOEDIT",WS_TABSTOP,122,133,114,14 + CTEXT "Enter Number",IDC_DLGTITLE,122,89,114,14,WS_DISABLED + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP +END + +SELDIAL_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Create Game",IDC_DIALBTN1,122,108,114,11,BS_NOTIFY + PUSHBUTTON "Enter New Number",IDC_DIALBTN2,122,119,114,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Action",IDC_DLGTITLE,120,89,118,14,WS_DISABLED + PUSHBUTTON "",IDC_DIALBTN3,122,130,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_DIALBTN4,122,141,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_DIALBTN5,122,152,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_DIALBTN6,122,163,114,11,BS_NOTIFY +END + +MODMSTAT_DIALOG DIALOGEX 0, 81, 256, 122 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,92,84,72,15,BS_NOTIFY + LTEXT "Attempting to connect...",IDC_OKCANCEL_TEXT,56,8,160,71, + WS_DISABLED +END + +SELCRE8JOIN_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Create Game",IDC_DIALBTN1,122,108,114,11,BS_NOTIFY + PUSHBUTTON "Join Game",IDC_DIALBTN2,122,119,114,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Action",IDC_DLGTITLE,120,89,118,14,WS_DISABLED +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "TITLESCREEN_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "MAINMENU_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "MAINMENU_DIALOG2", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELHERO_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "OKCANCEL_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 105 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + "LOGON_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 111 + END + + "PROGRESS_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 105 + TOPMARGIN, 7 + BOTTOMMARGIN, 52 + END + + "OK_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 105 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + "BIGOK_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 111 + END + + "BIGOKCANCEL_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 111 + END + + "CREDITS_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 193 + END + + "SUPPORT_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 193 + END + + "DISCLAIMER_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELLIST_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELCLASS_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELCLASS_DIALOG2", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "ENTERNAME_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELYESNO_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + HORZGUIDE, 7 + END + + "SELCONNECT_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELOK_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + HORZGUIDE, 7 + END + + "SELIPXGAME_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELDIFF_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 128 + END + + "DIRLINK_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SPAWNERR_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + HORZGUIDE, 7 + END + + "SELLOAD_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "MODEM_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELMODEM_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 128 + END + + "ENTERDIAL_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELDIAL_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "MODMSTAT_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + HORZGUIDE, 7 + END + + "SELCRE8JOIN_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "frank.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// TEXT_FILES +// + +IDR_CREDITS TEXT_FILES DISCARDABLE "credits.txt" +IDR_SUPPORT TEXT_FILES DISCARDABLE "support.txt" + +///////////////////////////////////////////////////////////////////////////// +// +// ART_FILES +// + +IDR_POPUPART ART_FILES DISCARDABLE "srpopup.raw" +IDR_BTNART ART_FILES DISCARDABLE "but_sml.raw" +IDR_ARTPAL ART_FILES DISCARDABLE "srpopup.pal" + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +DIABLOCURSOR CURSOR DISCARDABLE "pointer.cur" +DIABLOIBEAM CURSOR DISCARDABLE "ibeam.cur" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_WARRIOR "Warrior" + IDS_ROGUE "Rogue" + IDS_SORCERER "Sorcerer" + IDS_CONFIRM_DELETE "\nAre you sure you want to delete the character ""%s""?" + IDS_CONFIRM_OVERWRITE "\nCharacter already exists. Do you want to overwrite ""%s""?" + IDS_NAME_ERR "\nInvalid name. A name cannot contain spaces, reserved characters, or reserved words." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_CREATE_ERR "\n\nUnable to create character." + IDS_DELETE_ERR "\n\nDelete character failed." + IDS_ENUMCHAR_ERR "\n\nUnable to read character files." + IDS_FIRST_NASTY "gvdl" + IDS_STRING20 "dvou" + IDS_STRING21 "tiju" + IDS_STRING22 "cjudi" + IDS_STRING23 "bttipmf" + IDS_STRING24 "ojhhfs" + IDS_STRING25 "cmj{{bse" + IDS_LAST_NASTY "benjo" + IDS_COPYPROT_ERR "Please insert the Diablo CD into your CD-ROM drive and press 'OK'." + IDS_MULTILIST_TITLE "Multi Player Characters" + IDS_SINGLIST_TITLE "Single Player Characters" + IDS_NEWHERO "New Hero" + IDS_NEWSINGHERO "New Single Player Hero" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NEWMULTHERO "New Multi Player Hero" + IDS_PLAYERSSUPPORTED "Players Supported: %d" + IDS_DELETESINGHERO "Delete Single Player Hero" + IDS_DELETEMULTHERO "Delete Multi Player Hero" + IDS_CREATEGAME "Create Game" + IDS_JOIN_ERR "\n\nUnable to join game ""%s.""" + IDS_CREATEGAME_ERR "\n\nUnable to create game." + IDS_NORMAL "Normal" + IDS_NIGHTMARE "Nightmare" + IDS_HELL "Hell" + IDS_CREATEDESC "Create a new game with a difficulty setting of your choice." + IDS_NOGAME_ERR "\n\nA multi player game was not detected!" + IDS_SELCONN_ERR "\n\nUnable to initialize selected connection method." + IDS_SPAWN_ERR "You have selected a feature only available in the full retail version of Hellfire. For ordering information call (800) 953-SNOW." + IDS_NOMODEM_ERR "\nUnable to detect a modem. Please install or configure a modem." + IDS_RETRYCONNDESC "A direct link connection was not detected. Check your cable connections and confirm that the connected computer has created a game, then retry." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_GAMEDESCFMT "%s.\nCreated by %s, a level %d %s." + IDS_VERSION_ERR "\nUnable to join the detected game. Your version of Hellfire is incompatible with the game creator's version." + IDS_MODEMJOIN_ERR "\nUnable to establish a connection. A game of Hellfire was not detected at the specified phone number." + IDS_CALL_FMT "Call %s" + IDS_INITMODEM_ERR "\n\nUnable to initialize the selected device." + IDS_MODEM_CREATE "Create a new game with a difficulty setting of your choice. Another player can dial in and join your game in progress." + IDS_MODEM_DIALNEW "Enter and call a number not listed here and join a game already in progress at that number." + IDS_MODEM_DIALOLD "Call the selected number and join a game already in progress at that number." + IDS_SELDIAL_INFOTITLE "Description:" + IDS_ENTERDIAL_INFO "Enter the number you want to call exactly as you would dial it. We recommend including a code to disable call waiting." + IDS_ENTERDIAL_TITLE "Description:" + IDS_SPAWNDATA_ERR "Unable to locate the Spawned Hellfire data file." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NOANSWER_ERR "\n\nUnable to connect. There was no answer at the number dialed." + IDS_NOTONE_ERR "\n\nUnable to dial. No dial tone was detected." + IDS_BUSY_ERR "\n\nUnable to connect. The number dialed was busy." + IDS_MODEM_CREATE2 "Create a new game with a difficulty setting of your choice. The connected player can join your game after you create it." + IDS_MODEM_JOIN "Join the game created by the person that you currently have a connection with." + IDS_SPAWNCLASS_ERR "The Rogue and Sorcerer are only available in the full retail version of Hellfire. For ordering information call (800) 953-SNOW." + IDS_SPAWNINTRO_ERR "The Hellfire introduction cinematic is only available in the full retail version of Hellfire. For ordering information call (800) 953-SNOW." + IDS_MODEMGAMENAME_FMT "Game %d" + IDS_DUPGAMENAME_FMT "Unable to create game. The game ""%s"" already exists." + IDS_MODEMJOINPREV "Join Previous Game" + IDS_MODEMJOINNEW "Join New Game" + IDS_MODEMOFF_ERR "Modem not detected. Please ensure that your modem is turned on and connected correctly." + IDS_JOINGAMES "Join Games" + IDS_MEMORY_ERR "Not enough memory. Hellfire requires that your system have a minimum of 16 MB of RAM to play multiplayer games." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Uisrc/UI/FRANK.SAV b/src/Uisrc/UI/FRANK.SAV new file mode 100644 index 0000000..3551145 --- /dev/null +++ b/src/Uisrc/UI/FRANK.SAV @@ -0,0 +1,887 @@ +//Microsoft Developer Studio generated resource script. +// +#include "frank.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 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +TITLESCREEN_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + // The text is in the art. + //CTEXT "Copyright © 1997 Synergistic Software",IDC_BLIZZARD, + // 22,173,212,11,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,203 +END + +MAINMENU_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Start Game",IDC_SINGLEPLAYER_BTN,26,81,204,18, + BS_NOTIFY + PUSHBUTTON "Replay Intro",IDC_REPLAYINTRO_BTN,26,99,204,18, + BS_NOTIFY + PUSHBUTTON "Support",IDC_SUPPORT_BTN,26,117,204,18, + BS_NOTIFY + PUSHBUTTON "Credits",IDC_SHOWCREDITS_BTN,26,135,204,18, + BS_NOTIFY + PUSHBUTTON "Exit Hellfire",IDCANCEL,26,153,204,18,BS_NOTIFY + LTEXT "",IDC_REGISTRATION,7,187,242,9,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 +END + +MAINMENU_DIALOG2 DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Start Game",IDC_SINGLEPLAYER_BTN,26,81,204,18, + BS_NOTIFY + PUSHBUTTON "Multiplayer",IDC_MULTIPLAYER_BTN,26,99,204,18, + BS_NOTIFY + PUSHBUTTON "Replay Intro",IDC_REPLAYINTRO_BTN,26,117,204,18, + BS_NOTIFY + PUSHBUTTON "Support",IDC_SUPPORT_BTN,26,135,204,18, + BS_NOTIFY + PUSHBUTTON "Credits",IDC_SHOWCREDITS_BTN,26,153,204,18, + BS_NOTIFY + PUSHBUTTON "Exit Hellfire",IDCANCEL,26,171,204,18,BS_NOTIFY + LTEXT "",IDC_REGISTRATION,7,187,242,9,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 +END + +SELHERO_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + RTEXT "Strength:",IDC_STRLBL,16,151,44,9 + RTEXT "Magic:",IDC_MAGLBL,16,160,44,9 + RTEXT "Dexterity:",IDC_DEXLBL,16,169,44,9 + RTEXT "Vitality:",IDC_VITLBL,16,178,44,9 + CTEXT "",IDC_CHARSTR,64,151,16,9 + CTEXT "",IDC_CHARMAGIC,64,160,16,9 + CTEXT "",IDC_CHARDEX,64,169,16,9 + CTEXT "",IDC_CHARVIT,64,178,16,9 + RTEXT "Level:",IDC_LEVELLBL,16,136,44,9 + CTEXT "",IDC_CHARLEVEL,64,136,16,9 + CONTROL "",IDC_HEROIMAGE,"Static",SS_BLACKFRAME | WS_DISABLED,12, + 89,72,32 + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,0,0, + 256,65 + CTEXT "Single Player Characters",IDC_DLGTITLE,10,68,236,15, + WS_DISABLED +END + +OKCANCEL_DIALOG DIALOGEX 0, 0, 112, 61 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "OK",IDC_OK,8,41,44,12 + PUSHBUTTON "Cancel",IDCANCEL,60,41,44,12 + CTEXT "",IDC_OKCANCEL_TEXT,8,5,96,34,0,WS_EX_TRANSPARENT +END + +LOGON_DIALOG DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_LOGONNAME_EDIT,52,34,88,12,ES_AUTOHSCROLL + EDITTEXT IDC_LOGONPASSWORD_EDIT,52,50,88,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,102,85,44,12 + PUSHBUTTON "Cancel",IDCANCEL,102,99,44,12 + RTEXT "Name:",IDC_STATIC,8,34,41,9,0,WS_EX_TRANSPARENT + RTEXT "Password:",IDC_STATIC,7,50,41,9,0,WS_EX_TRANSPARENT + CTEXT "Connect to Battlenet",IDC_DLGTITLE,0,8,154,9,0, + WS_EX_TRANSPARENT + LTEXT "You can open an account on battlenet FREE at WWW.BATTLE.NET.", + IDC_STATIC,8,76,88,38,0,WS_EX_TRANSPARENT +END + +PROGRESS_DIALOG DIALOGEX 0, 0, 112, 61 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "",IDC_PROGRESS_TEXT,0,4,112,18,0,WS_EX_TRANSPARENT + PUSHBUTTON "Cancel",IDCANCEL,34,42,44,12 + CONTROL "",IDC_UIGENERIC_PROGRESS,"Static",SS_BLACKFRAME,10,22, + 91,16 +END + +OK_DIALOG DIALOGEX 0, 0, 112, 61 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDC_OK,34,41,44,12 + CTEXT "",IDC_OKCANCEL_TEXT,8,5,96,34,0,WS_EX_TRANSPARENT +END + +BIGOK_DIALOG DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDC_OK,55,99,44,12 + CTEXT "",IDC_OKCANCEL_TEXT,8,20,139,75,0,WS_EX_TRANSPARENT + CTEXT "",IDC_DLGTITLE,7,7,140,9,0,WS_EX_TRANSPARENT +END + +BIGOKCANCEL_DIALOG DIALOGEX 0, 0, 154, 118 +STYLE DS_CENTER | WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDC_OK,22,99,44,12 + CTEXT "",IDC_OKCANCEL_TEXT,8,20,139,75,0,WS_EX_TRANSPARENT + DEFPUSHBUTTON "Cancel",IDCANCEL,88,99,44,12 + CTEXT "",IDC_DLGTITLE,7,7,140,9,0,WS_EX_TRANSPARENT +END + +CREDITS_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "TIMES NEW ROMAN", 700, 0, 0x1 +BEGIN + CONTROL "",ID_SCROLL_WINDOW,"Static",SS_BLACKFRAME | WS_DISABLED, + 12,48,232,106 +END + +SUPPORT_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "TIMES NEW ROMAN", 700, 0, 0x1 +BEGIN + CONTROL "",ID_SCROLL_WINDOW,"Static",SS_BLACKFRAME | WS_DISABLED, + 12,48,232,106 +END + +DISCLAIMER_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Not For Review",IDC_TEXT1,25,7,96,15 + CTEXT "Not For Resale",IDC_TEXT2,134,7,96,15 + LTEXT "This is a five level beta of Hellfire, playable only over Battle.net. There are some features that are not yet implemented, notably multi player quests. Please send all comments and bug reports to bnbeta@blizzard.com.", + IDC_TEXT3,8,30,240,70 + LTEXT "This version of Hellfire is intended for the use of registered Battle.net beta testers only. This beta is for integrity testing of Blizzard Entertainment's Battle.net service and is not intended for review by the media or resale in any manner.", + IDC_TEXT4,8,100,240,70 + LTEXT "Unauthorized distribution is strictly prohibited.", + IDC_TEXT5,8,170,240,14 +END + +SELLIST_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,196,180,48,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "",IDC_HEROBTN1,106,108,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN2,106,119,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN3,106,130,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN4,106,141,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN5,106,152,128,11,BS_NOTIFY + PUSHBUTTON "",IDC_HEROBTN6,106,163,128,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,96,180,48,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Hero",IDC_DLGTITLE,106,89,128,14,WS_DISABLED + CONTROL "",IDC_SCROLLBAR,"Static",SS_BLACKFRAME | WS_DISABLED, + 234,103,10,75 + PUSHBUTTON "Delete",IDDELETE,146,180,48,15,BS_NOTIFY | WS_DISABLED | + NOT WS_TABSTOP +END + +SELCLASS_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Warrior",IDC_WARRIORBTN,106,105,128,14,BS_NOTIFY + PUSHBUTTON "Rogue",IDC_ROGUEBTN,106,119,128,14,BS_NOTIFY + PUSHBUTTON "Sorcerer",IDC_SORCERERBTN,106,133,128,14,BS_NOTIFY + PUSHBUTTON "Monk",IDC_MONKBTN,106,147,128,14,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + CTEXT "Choose Class",IDC_DLGTITLE,106,89,128,14,WS_DISABLED +END + +SELCLASS_DIALOG2 DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Warrior",IDC_WARRIORBTN,106,105,128,14,BS_NOTIFY + PUSHBUTTON "Rogue",IDC_ROGUEBTN,106,119,128,14,BS_NOTIFY + PUSHBUTTON "Sorcerer",IDC_SORCERERBTN,106,133,128,14,BS_NOTIFY + PUSHBUTTON "Monk",IDC_MONKBTN,106,147,128,14,BS_NOTIFY + PUSHBUTTON "Bard",IDC_BARDBTN,106,161,128,14,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + CTEXT "Choose Class",IDC_DLGTITLE,106,89,128,14,WS_DISABLED +END + +ENTERNAME_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CONTROL "",IDC_NAMEEDIT,"DIABLOEDIT",WS_TABSTOP,106,133,128,14 + CTEXT "Enter Name",IDC_DLGTITLE,106,89,128,14,WS_DISABLED + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP +END + +SELYESNO_DIALOG DIALOGEX 0, 81, 256, 122 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Yes",IDC_OK,92,84,72,15,BS_NOTIFY + PUSHBUTTON "No",IDCANCEL,92,99,72,15,BS_NOTIFY + LTEXT "",IDC_OKCANCEL_TEXT,48,8,160,71,WS_DISABLED +END + +SELCONNECT_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "",IDC_CONNECTBTN1,122,108,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_CONNECTBTN2,122,119,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_CONNECTBTN3,122,130,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_CONNECTBTN4,122,141,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_CONNECTBTN5,122,152,114,11,BS_NOTIFY + CTEXT "Multi Player Game",IDC_DLGTITLE,10,68,236,15, + WS_DISABLED + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,182,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + LTEXT "",IDC_CONNECTTEXT,14,122,82,72,WS_DISABLED + LTEXT "Requirements:",IDC_REQTITLE,14,108,82,9,WS_DISABLED + LTEXT "",IDC_PLAYERSTEXT,14,92,82,9,WS_DISABLED + CTEXT "Select Connection",IDC_DLGTITLE2,120,89,118,14, + WS_DISABLED + PUSHBUTTON "",IDC_CONNECTBTN6,122,163,114,11,BS_NOTIFY + CONTROL "",IDC_SCROLLBAR,"Static",SS_BLACKFRAME | WS_DISABLED, + 236,103,10,75 + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,50,0, + 256,65 +END + +SELOK_DIALOG DIALOGEX 0, 81, 256, 122 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDC_OK,92,84,72,15,BS_NOTIFY + LTEXT "",IDC_OKCANCEL_TEXT,56,8,160,71,WS_DISABLED +END + +SELIPXGAME_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "",IDC_GAMEBTN1,122,108,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN2,122,119,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN3,122,130,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN4,122,141,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN5,122,152,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_GAMEBTN6,122,163,114,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + CTEXT "Join IPX Games",IDC_DLGTITLE,10,68,236,15,WS_DISABLED + CTEXT "Select Game",IDC_DLGTITLE2,120,89,118,14,WS_DISABLED + LTEXT "Description:",IDC_DLGTITLE3,14,89,82,14,WS_DISABLED + LTEXT "",IDC_GAMEDESC,14,108,82,81,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,50,0, + 256,65 + CONTROL "",IDC_SCROLLBAR,"Static",SS_BLACKFRAME | WS_DISABLED, + 236,103,10,75 +END + +SELDIFF_DIALOG DIALOGEX 0, 65, 256, 135 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Create Game",IDC_DLGTITLE,10,3,236,15,WS_DISABLED + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,115,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Normal",IDC_DIFFBTN1,120,54,118,11,BS_NOTIFY + PUSHBUTTON "Nightmare",IDC_DIFFBTN2,120,65,118,11,BS_NOTIFY + PUSHBUTTON "Hell",IDC_DIFFBTN3,120,76,118,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,115,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Difficulty",IDC_DLGTITLE2,120,24,118,15, + WS_DISABLED + CTEXT "",IDC_DLGTITLE3,14,24,82,14,WS_DISABLED + LTEXT "",IDC_DIFFDESC,14,43,82,81,WS_DISABLED +END + +DIRLINK_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Direct Link Connection",IDC_DLGTITLE,10,68,236,15, + WS_DISABLED + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Create Game",IDC_DIRLINKBTN1,120,119,118,11,BS_NOTIFY + PUSHBUTTON "Retry Connection",IDC_DIRLINKBTN2,120,130,118,11, + BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Action",IDC_DLGTITLE2,120,89,118,15,WS_DISABLED + LTEXT "Link Status:",IDC_DLGTITLE3,14,89,82,14,WS_DISABLED + LTEXT "",IDC_LINKDESC,14,108,82,81,WS_DISABLED + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,50,0, + 256,65 +END + +SPAWNERR_DIALOG DIALOGEX 0, 69, 256, 134 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "OK",IDC_OK,92,103,72,18,BS_NOTIFY + LTEXT "",IDC_OKCANCEL_TEXT,56,15,160,75,WS_DISABLED +END + +SELLOAD_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,172,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Load Game",IDC_LOADBTN,106,119,128,14,BS_NOTIFY + PUSHBUTTON "New Game",IDC_NEWBTN,106,133,128,14,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,112,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Save File Exists",IDC_DLGTITLE,106,89,128,14, + WS_DISABLED +END + +MODEM_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CTEXT "Modem Connection",IDC_DLGTITLE,10,68,236,15 + CTEXT "",IDC_DLGTITLE2,14,89,82,14 + LTEXT "",IDC_MODEMDESC,14,108,82,81 + CONTROL "",IDC_LOGO,"Static",SS_BLACKFRAME | WS_DISABLED,50,0, + 256,65 +END + +SELMODEM_DIALOG DIALOGEX 0, 65, 256, 135 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,115,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "",IDC_MODEMBTN1,122,43,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN2,122,54,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN3,122,65,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN4,122,76,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN5,122,87,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_MODEMBTN6,122,98,114,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,115,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Modem",IDC_DLGTITLE2,120,24,118,14,WS_DISABLED + CONTROL "",IDC_SCROLLBAR,"Static",SS_BLACKFRAME | WS_DISABLED, + 236,38,10,75 + CTEXT "Modem Game Setup",IDC_DLGTITLE,10,3,236,15,WS_DISABLED + CTEXT "Requirments:",IDC_DLGTITLE3,14,24,82,14,WS_DISABLED + LTEXT "The modem must be 14400 BPS or faster. If the device you want to use is not listed here, please check your modem to ensure that it is configured correctly.", + IDC_REQDESC,14,43,82,81,WS_DISABLED +END + +ENTERDIAL_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + CONTROL "",IDC_DIALEDIT,"DIABLOEDIT",WS_TABSTOP,122,133,114,14 + CTEXT "Enter Number",IDC_DLGTITLE,122,89,114,14,WS_DISABLED + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP +END + +SELDIAL_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Create Game",IDC_DIALBTN1,122,108,114,11,BS_NOTIFY + PUSHBUTTON "Enter New Number",IDC_DIALBTN2,122,119,114,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Action",IDC_DLGTITLE,120,89,118,14,WS_DISABLED + PUSHBUTTON "",IDC_DIALBTN3,122,130,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_DIALBTN4,122,141,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_DIALBTN5,122,152,114,11,BS_NOTIFY + PUSHBUTTON "",IDC_DIALBTN6,122,163,114,11,BS_NOTIFY +END + +MODMSTAT_DIALOG DIALOGEX 0, 81, 256, 122 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,92,84,72,15,BS_NOTIFY + LTEXT "Attempting to connect...",IDC_OKCANCEL_TEXT,56,8,160,71, + WS_DISABLED +END + +SELCRE8JOIN_DIALOG DIALOGEX 0, 0, 256, 203 +STYLE WS_POPUP | WS_VISIBLE +EXSTYLE WS_EX_TRANSPARENT +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDC_FAKECANCEL,180,180,56,15,BS_NOTIFY | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "Create Game",IDC_DIALBTN1,122,108,114,11,BS_NOTIFY + PUSHBUTTON "Join Game",IDC_DIALBTN2,122,119,114,11,BS_NOTIFY + PUSHBUTTON "OK",IDC_FAKEOK,120,180,56,15,WS_DISABLED | NOT + WS_TABSTOP + CTEXT "Select Action",IDC_DLGTITLE,120,89,118,14,WS_DISABLED +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "TITLESCREEN_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "MAINMENU_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "MAINMENU_DIALOG2", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELHERO_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "OKCANCEL_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 105 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + "LOGON_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 111 + END + + "PROGRESS_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 105 + TOPMARGIN, 7 + BOTTOMMARGIN, 52 + END + + "OK_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 105 + TOPMARGIN, 7 + BOTTOMMARGIN, 54 + END + + "BIGOK_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 111 + END + + "BIGOKCANCEL_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 147 + TOPMARGIN, 7 + BOTTOMMARGIN, 111 + END + + "CREDITS_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 193 + END + + "SUPPORT_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 242 + TOPMARGIN, 7 + BOTTOMMARGIN, 193 + END + + "DISCLAIMER_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELLIST_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELCLASS_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELCLASS_DIALOG2", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "ENTERNAME_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELYESNO_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + HORZGUIDE, 7 + END + + "SELCONNECT_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELOK_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + HORZGUIDE, 7 + END + + "SELIPXGAME_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELDIFF_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 128 + END + + "DIRLINK_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SPAWNERR_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + HORZGUIDE, 7 + END + + "SELLOAD_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "MODEM_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELMODEM_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 128 + END + + "ENTERDIAL_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "SELDIAL_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + "MODMSTAT_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + HORZGUIDE, 7 + END + + "SELCRE8JOIN_DIALOG", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 249 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "frank.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// TEXT_FILES +// + +IDR_CREDITS TEXT_FILES DISCARDABLE "credits.txt" +IDR_SUPPORT TEXT_FILES DISCARDABLE "support.txt" + +///////////////////////////////////////////////////////////////////////////// +// +// ART_FILES +// + +IDR_POPUPART ART_FILES DISCARDABLE "srpopup.raw" +IDR_BTNART ART_FILES DISCARDABLE "but_sml.raw" +IDR_ARTPAL ART_FILES DISCARDABLE "srpopup.pal" + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +DIABLOCURSOR CURSOR DISCARDABLE "pointer.cur" +DIABLOIBEAM CURSOR DISCARDABLE "ibeam.cur" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_WARRIOR "Warrior" + IDS_ROGUE "Rogue" + IDS_SORCERER "Sorcerer" + IDS_CONFIRM_DELETE "\nAre you sure you want to delete the character ""%s""?" + IDS_CONFIRM_OVERWRITE "\nCharacter already exists. Do you want to overwrite ""%s""?" + IDS_NAME_ERR "\nInvalid name. A name cannot contain spaces, reserved characters, or reserved words." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_CREATE_ERR "\n\nUnable to create character." + IDS_DELETE_ERR "\n\nDelete character failed." + IDS_ENUMCHAR_ERR "\n\nUnable to read character files." + IDS_FIRST_NASTY "gvdl" + IDS_STRING20 "dvou" + IDS_STRING21 "tiju" + IDS_STRING22 "cjudi" + IDS_STRING23 "bttipmf" + IDS_STRING24 "ojhhfs" + IDS_STRING25 "cmj{{bse" + IDS_LAST_NASTY "benjo" + IDS_COPYPROT_ERR "Please insert the Hellfire CD into your CD-ROM drive and press 'OK'." + IDS_MULTILIST_TITLE "Multi Player Characters" + IDS_SINGLIST_TITLE "Single Player Characters" + IDS_NEWHERO "New Hero" + IDS_NEWSINGHERO "New Single Player Hero" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NEWMULTHERO "New Multi Player Hero" + IDS_PLAYERSSUPPORTED "Players Supported: %d" + IDS_DELETESINGHERO "Delete Single Player Hero" + IDS_DELETEMULTHERO "Delete Multi Player Hero" + IDS_CREATEGAME "Create Game" + IDS_JOIN_ERR "\n\nUnable to join game ""%s.""" + IDS_CREATEGAME_ERR "\n\nUnable to create game." + IDS_NORMAL "Normal" + IDS_NIGHTMARE "Nightmare" + IDS_HELL "Hell" + IDS_CREATEDESC "Create a new game with a difficulty setting of your choice." + IDS_NOGAME_ERR "\n\nA multi player game was not detected!" + IDS_SELCONN_ERR "\n\nUnable to initialize selected connection method." + IDS_SPAWN_ERR "You have selected a feature only available in the full retail version of Hellfire. For ordering information call (800) 953-SNOW." + IDS_NOMODEM_ERR "\nUnable to detect a modem. Please install or configure a modem." + IDS_RETRYCONNDESC "A direct link connection was not detected. Check your cable connections and confirm that the connected computer has created a game, then retry." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_GAMEDESCFMT "%s.\nCreated by %s, a level %d %s." + IDS_VERSION_ERR "\nUnable to join the detected game. Your version of Hellfire is incompatible with the game creator's version." + IDS_MODEMJOIN_ERR "\nUnable to establish a connection. A game of Hellfire was not detected at the specified phone number." + IDS_CALL_FMT "Call %s" + IDS_INITMODEM_ERR "\n\nUnable to initialize the selected device." + IDS_MODEM_CREATE "Create a new game with a difficulty setting of your choice. Another player can dial in and join your game in progress." + IDS_MODEM_DIALNEW "Enter and call a number not listed here and join a game already in progress at that number." + IDS_MODEM_DIALOLD "Call the selected number and join a game already in progress at that number." + IDS_SELDIAL_INFOTITLE "Description:" + IDS_ENTERDIAL_INFO "Enter the number you want to call exactly as you would dial it. We recommend including a code to disable call waiting." + IDS_ENTERDIAL_TITLE "Description:" + IDS_SPAWNDATA_ERR "Unable to locate the Spawned Hellfire data file." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NOANSWER_ERR "\n\nUnable to connect. There was no answer at the number dialed." + IDS_NOTONE_ERR "\n\nUnable to dial. No dial tone was detected." + IDS_BUSY_ERR "\n\nUnable to connect. The number dialed was busy." + IDS_MODEM_CREATE2 "Create a new game with a difficulty setting of your choice. The connected player can join your game after you create it." + IDS_MODEM_JOIN "Join the game created by the person that you currently have a connection with." + IDS_SPAWNCLASS_ERR "The Rogue and Sorcerer are only available in the full retail version of Hellfire. For ordering information call (800) 953-SNOW." + IDS_SPAWNINTRO_ERR "The Hellfire introduction cinematic is only available in the full retail version of Hellfire. For ordering information call (800) 953-SNOW." + IDS_MODEMGAMENAME_FMT "Game %d" + IDS_DUPGAMENAME_FMT "Unable to create game. The game ""%s"" already exists." + IDS_MODEMJOINPREV "Join Previous Game" + IDS_MODEMJOINNEW "Join New Game" + IDS_MODEMOFF_ERR "Modem not detected. Please ensure that your modem is turned on and connected correctly." + IDS_JOINGAMES "Join Games" + IDS_MEMORY_ERR "Not enough memory. Hellfire requires that your system have a minimum of 16 MB of RAM to play multiplayer games." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Uisrc/UI/IBEAM.CUR b/src/Uisrc/UI/IBEAM.CUR new file mode 100644 index 0000000..bdc85c4 Binary files /dev/null and b/src/Uisrc/UI/IBEAM.CUR differ diff --git a/src/Uisrc/UI/ICONCURS.ICO b/src/Uisrc/UI/ICONCURS.ICO new file mode 100644 index 0000000..1bdfeda Binary files /dev/null and b/src/Uisrc/UI/ICONCURS.ICO differ diff --git a/src/Uisrc/UI/LINK.CUR b/src/Uisrc/UI/LINK.CUR new file mode 100644 index 0000000..2608ade Binary files /dev/null and b/src/Uisrc/UI/LINK.CUR differ diff --git a/src/Uisrc/UI/LOCAL.CPP b/src/Uisrc/UI/LOCAL.CPP new file mode 100644 index 0000000..d26ac93 --- /dev/null +++ b/src/Uisrc/UI/LOCAL.CPP @@ -0,0 +1,640 @@ +//**************************************************************************** +// local.cpp +// created 9.13.96 +//**************************************************************************** + +#define OEMRESOURCE + +#include "pch.h" +#include "artfont.h" + + +#define TEST_REDRAW 0 // 0 in final + + +//**************************************************************************** +//**************************************************************************** + #define WNDPROCPROP TEXT("UIWNDPROC") + + static PALETTEENTRY sgPalette[PALETTE_REGISTERS]; + static HPALETTE sghPalIdentity = NULL; + + +//**************************************************************************** +void UiCreateIdentityPal(void) { + LOGPALETTE *lPalette; + PALETTEENTRY *pe; + DWORD *pDword; + + lPalette = (LOGPALETTE *)ALLOC(sizeof(LOGPALETTE) + (PALETTE_REGISTERS-1)*sizeof(PALETTEENTRY)); + if (lPalette == NULL) + return; + + lPalette->palVersion = 0x300; + lPalette->palNumEntries = PALETTE_REGISTERS; + pe = &lPalette->palPalEntry[0]; + pDword = (DWORD *)pe; + for (int i=0; ipeFlags = PC_EXPLICIT; + } + + sghPalIdentity = CreatePalette(lPalette); + FREE(lPalette); +} + +//**************************************************************************** +void UiFreeIdentityPal(void) { + if (sghPalIdentity) { + DeleteObject(sghPalIdentity); + sghPalIdentity = NULL; + } +} + +//**************************************************************************** +HPALETTE UiGetIdentityPal(void) { + return sghPalIdentity; +} + + +//**************************************************************************** +//**************************************************************************** +PALETTEENTRY * UiPaletteEntry(int index) { + return &sgPalette[index]; +} + + +//**************************************************************************** +//**************************************************************************** +void UiClearPalette(PALETTEENTRY * pe) { + for (int palreg = 0; palreg < PALETTE_REGISTERS; palreg++) { + pe[palreg].peRed = 0; + pe[palreg].peGreen = 0; + pe[palreg].peBlue = 0; + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiLoadBmpFile (LPCTSTR filename, + LPBYTE *bitmapbits, + SIZE *bitmapsize) { + + int width, height; + + // DETERMINE THE IMAGE DIMENSIONS + if (!SBmpLoadImage(filename,NULL,NULL,0,&width,&height)) { + if (bitmapbits) { + *bitmapbits = 0; + } + if (bitmapsize) { + bitmapsize->cx = 0; + bitmapsize->cy = 0; + } + return 0; + } + + if (bitmapsize) { + bitmapsize->cx = width; + bitmapsize->cy = height; + } + + // LOAD THE IMAGE + *bitmapbits = (LPBYTE)ALLOC(width*height); + + if (!*bitmapbits) { + if (bitmapsize) { + bitmapsize->cx = 0; + bitmapsize->cy = 0; + } + return 0; + } + + if (!SBmpLoadImage(filename,NULL,*bitmapbits,width*height)) { + FREE(*bitmapbits); + *bitmapbits = NULL; + + bitmapsize->cx = 0; + bitmapsize->cy = 0; + return 0; + } + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +BOOL LoadArtFile ( HWND window, + HWND parent, + LPCTSTR controltype, + DWORD controlstyle, + LONG usageflags, + LPCTSTR filename, + LPBYTE *bitmapbits, + SIZE *bitmapsize, + BOOL updatepal) { + + PALETTEENTRY pe[PALETTE_REGISTERS]; + int width, height; + + // DETERMINE THE IMAGE DIMENSIONS + if (!SBmpLoadImage(filename,NULL,NULL,0,&width,&height)) { + if (bitmapbits) { + *bitmapbits = 0; + } + if (bitmapsize) { + bitmapsize->cx = 0; + bitmapsize->cy = 0; + } + return 0; + } + + if (bitmapsize) { + bitmapsize->cx = width; + bitmapsize->cy = height; + } + + // LOAD THE IMAGE + *bitmapbits = (LPBYTE)ALLOC(width*height); + if (!*bitmapbits) { + if (bitmapsize) { + bitmapsize->cx = 0; + bitmapsize->cy = 0; + } + return 0; + } + if (!SBmpLoadImage(filename, pe, *bitmapbits, width*height)) { + if (bitmapsize) { + bitmapsize->cx = 0; + bitmapsize->cy = 0; + } + FREE(*bitmapbits); + *bitmapbits = 0; + return 0; + } + + // REGISTER THE IMAGE WITH THE DIALOG BOX MANAGER + if (!SDlgSetBitmap( + window, + parent, + controltype, + controlstyle, + usageflags, + *bitmapbits, + NULL, + width, + height + )) { + if (bitmapsize) { + bitmapsize->cx = 0; + bitmapsize->cy = 0; + } + FREE(*bitmapbits); + *bitmapbits = 0; + return 0; + } + + // IF THIS IS A SCREEN BACKGROUND, USE ITS PALETTE + if ((!controltype) || (!*controltype)) { + HPALETTE hPal; + + // Get Windows Default colors from the system + hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE); + GetPaletteEntries(hPal, 0, 10, &pe[0]); + GetPaletteEntries(hPal, 10, 10, &pe[PALETTE_REGISTERS-10]); + + memcpy(sgPalette, pe, (PALETTE_REGISTERS * sizeof(PALETTEENTRY))); + if (updatepal) { + SDrawUpdatePalette(0, 255, &sgPalette[0], TRUE); + } + else { + UiClearPalette(pe); + SDrawUpdatePalette(0, PALETTE_REGISTERS, pe, TRUE); + } + } + + return 1; +} + + +//**************************************************************************** +// given a rect, calculate a new rect of the same size +// that uses the new given upper left coordinates +//**************************************************************************** +void UiCalcNewRect(RECT *rect, int xoffset, int yoffset) { + rect->right -= rect->left; + rect->right += xoffset - 1; + rect->left = xoffset; + + rect->bottom -= rect->top; + rect->bottom += yoffset - 1; + rect->top = yoffset; +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiSetStaticBmp(HWND parent, int child_id, LPBYTE bmpbits, SIZE *bmpsize) { + HWND child = GetDlgItem(parent, child_id); + RECT rect; + + GetWindowRect(child,&rect); + ScreenToClient(parent, (LPPOINT)&rect.left); + ScreenToClient(parent, (LPPOINT)&rect.right); + + SDlgSetBitmap( + child, + NULL, + TEXT("Static"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + bmpbits, + &rect, + bmpsize->cx, + bmpsize->cy + ); + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +void UiSetBtnBmp(HWND button, DWORD usage, RECT *rect, LPBYTE bmpbits, SIZE *bmpsize) { + SDlgSetBitmap( + button, + NULL, + TEXT("Button"), + SDLG_STYLE_ANY, + usage, + bmpbits, + rect, + bmpsize->cx, + bmpsize->cy + ); +} + + +//**************************************************************************** +//**************************************************************************** +void UiSetButtonBitmaps(HWND parent, int *btn_ids, LPBYTE bmpbits, SIZE *bmpsize) { + LONG yoffset = 0; + HWND child; + RECT rect; + + for ( ; *btn_ids; btn_ids++) { + // set up the button bitmaps so the use different parts of the texture + child = GetDlgItem(parent, *btn_ids); + if (! child) continue; + + GetClientRect(child, &rect); + + UiCalcNewRect(&rect, 0, yoffset); + UiSetBtnBmp(child, SDLG_USAGE_NORMAL_UNFOCUSED, &rect, bmpbits, bmpsize); + rect.bottom++; + rect.right++; + yoffset = rect.bottom; + + UiCalcNewRect(&rect, 0, yoffset); + UiSetBtnBmp(child, SDLG_USAGE_SELECTED_UNFOCUSED, &rect, bmpbits, bmpsize); + rect.bottom++; + rect.right++; + yoffset = rect.bottom; + + UiCalcNewRect(&rect, 0, yoffset); + UiSetBtnBmp(child, SDLG_USAGE_NORMAL_FOCUSED, &rect, bmpbits, bmpsize); + rect.bottom++; + rect.right++; + yoffset = rect.bottom; + + UiCalcNewRect(&rect, 0, yoffset); + UiSetBtnBmp(child, SDLG_USAGE_SELECTED_FOCUSED, &rect, bmpbits, bmpsize); + rect.bottom++; + rect.right++; + yoffset = rect.bottom; + + UiCalcNewRect(&rect, 0, yoffset); + UiSetBtnBmp(child, SDLG_USAGE_GRAYED, &rect, bmpbits, bmpsize); + rect.bottom++; + rect.right++; + yoffset = rect.bottom; + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiSetTextYellow(HDC hdc) { + SetTextColor(hdc, RGB(0xff, 0xff, 0x00)); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiIsPtInWindow(HWND parent, HWND window, int xpos, int ypos) { + RECT rect; + + if (! parent) return FALSE; + if (! window) return FALSE; + + GetWindowRect(window, &rect); + ScreenToClient(parent, (LPPOINT)&rect.left); + ScreenToClient(parent, (LPPOINT)&rect.right); + + if (xpos < rect.left) return FALSE; + if (xpos >= rect.right) return FALSE; + if (ypos < rect.top) return FALSE; + if (ypos >= rect.bottom) return FALSE; + + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +void UiPaintBtn(HWND window) { + PAINTSTRUCT ps; + HDC dc = SDlgBeginPaint(window, &ps); + SDlgEndPaint(window, &ps); +} + + +//**************************************************************************** +//**************************************************************************** +static LRESULT CALLBACK OnPaintBtnProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + LRESULT result; + WNDPROC oldproc = (WNDPROC) GetProp(window, WNDPROCPROP); + + switch (message) { + case WM_DESTROY: + RemoveProp(window, WNDPROCPROP); + if (oldproc) { + SetWindowLong(window, GWL_WNDPROC, (LONG) oldproc); + } + break; + + case WM_PAINT: + UiPaintBtn(window); + return 0; + } + + if (oldproc) + result = CallWindowProc(oldproc, window, message, wparam, lparam); + else + result = DefWindowProc(window, message, wparam, lparam); + return result; +} + + +//**************************************************************************** +//**************************************************************************** +void UiOnPaintBtns(HWND window, int * BtnIDs) { + HWND child; + WNDPROC oldproc; + + for (; *BtnIDs; BtnIDs++) { + child = GetDlgItem(window, *BtnIDs); + if (! child) continue; + + oldproc = (WNDPROC) GetWindowLong(child, GWL_WNDPROC); + SetProp(child, WNDPROCPROP,(HANDLE) oldproc); + SetWindowLong(child, GWL_WNDPROC, (LONG) OnPaintBtnProc); + } +} + + +//**************************************************************************** +//**************************************************************************** +static LRESULT CALLBACK ActiveDownBtnProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + LRESULT result; + HWND oldfocus; + WNDPROC oldproc = (WNDPROC) GetProp(window, WNDPROCPROP); + + switch (message) { +#if TEST_REDRAW + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_KEYDOWN: + if (wparam == VK_SCROLL) { + SDrawClearSurface(SDRAW_SURFACE_FRONT); + } + break; +#endif + case WM_LBUTTONDOWN: + // set the focus to this window + oldfocus = GetFocus(); + SetFocus(window); + + // make sure the windows involved in focus changing update + InvalidateRect(oldfocus, NULL, FALSE); + InvalidateRect(window, NULL, FALSE); + UpdateWindow(oldfocus); + UpdateWindow(window); + + // notify the parent of the click + PostMessage( + GetParent(window), + WM_COMMAND, + MAKELONG(GetWindowLong(window, GWL_ID), BN_CLICKED), + (LPARAM) window + ); + return 0; + + case WM_DESTROY: + RemoveProp(window, WNDPROCPROP); + if (oldproc) { + SetWindowLong(window, GWL_WNDPROC, (LONG) oldproc); + } + break; + + case WM_PAINT: + UiPaintBtn(window); + return 0; + } + + if (oldproc) + result = CallWindowProc(oldproc, window, message, wparam, lparam); + else + result = DefWindowProc(window, message, wparam, lparam); + return result; +} + + +//**************************************************************************** +//**************************************************************************** +void UiActiveDownBtns(HWND window, int * BtnIDs) { + HWND child; + WNDPROC oldproc; + + for (; *BtnIDs; BtnIDs++) { + child = GetDlgItem(window, *BtnIDs); + if (! child) continue; + + oldproc = (WNDPROC) GetWindowLong(child, GWL_WNDPROC); + SetProp(child, WNDPROCPROP,(HANDLE) oldproc); + SetWindowLong(child, GWL_WNDPROC, (LONG) ActiveDownBtnProc); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiFlushIOMessages(HWND window) { + MSG msg; + + while ( + PeekMessage(&msg, window, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) || + PeekMessage(&msg, window, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) + ); +} + + +//**************************************************************************** +//**************************************************************************** +TPBMP UiAllocBmp(void) { + TPBMP tpBmp = (TPBMP) ALLOC(sizeof(TBMP)); + + if (tpBmp) { + tpBmp->data = NULL; + tpBmp->datasize.cx = 0; + tpBmp->datasize.cy = 0; + tpBmp->userdata = 0; + tpBmp->text[0] = 0; + } + return tpBmp; +} + + +//**************************************************************************** +//**************************************************************************** +void UiFreeBmp(TPBMP tpBmp) { + if (tpBmp) { + if (tpBmp->data) { + FREE(tpBmp->data); + tpBmp->data = 0; + } + FREE(tpBmp); + } +} + + +//**************************************************************************** +//**************************************************************************** +void UiSetBmpText(TPBMP tpBmp, LPCSTR text) { + if (! tpBmp) return; + + if (text) { + strncpy(tpBmp->text, text, BMP_TEXT_LEN-1); + tpBmp->text[BMP_TEXT_LEN-1] = 0; + } + else { + tpBmp->text[0] = 0; + } +} + + +//**************************************************************************** +//**************************************************************************** +#define CURSOR_FILE TEXT("ui_art\\cursor.pcx") +static LPBYTE sgCurData = NULL; +static LPBYTE sgCurMask = NULL; +static SIZE sgCurSize; + +//**************************************************************************** +static void UiGenCursorMask(void) { + LPBYTE data = sgCurData; + LPBYTE mask = sgCurMask; + + if (! mask) return; + if (! data) return; + + for (int i = 0; i < (sgCurSize.cx * sgCurSize.cy); i++) { + if (*data++) { + *mask++ = 0; + } + else { + *mask++ = 255; + } + } +} + +//**************************************************************************** +void UiLoadCursor(void) { + int width, height; + + // determine the size of the curspr + if (!SBmpLoadImage(CURSOR_FILE,NULL,NULL,0,&width,&height)) + return; + + // allocate space for the data and mask + sgCurData = (LPBYTE)ALLOC(width*height); + + if (!sgCurData) + return; + + sgCurMask = (LPBYTE)ALLOC(width*height); + if (!sgCurMask) { + FREE(sgCurData); + sgCurData = NULL; + return; + } + + // load the cursor data + if (!SBmpLoadImage(CURSOR_FILE, NULL, sgCurData, width*height)) { + FREE(sgCurData); + sgCurData = NULL; + FREE(sgCurMask); + sgCurMask = NULL; + return; + } + + // save the cursor size + sgCurSize.cx = width; + sgCurSize.cy = height; + + // generate a mask for the cursor + UiGenCursorMask(); +} + +//**************************************************************************** +void UiDestroyCursor(void) { + if (sgCurData) { + FREE(sgCurData); + sgCurData = NULL; + } + if (sgCurMask) { + FREE(sgCurMask); + sgCurMask = NULL; + } +} + +//**************************************************************************** +void UiSetCursor(void) { + if (! sgCurData) { + UiLoadCursor(); + } + SDlgSetSystemCursor(sgCurMask, sgCurData, &sgCurSize, OCR_NORMAL); +} + +//**************************************************************************** +void UiClearCursor(void) { + SDlgSetSystemCursor(NULL, NULL, NULL, OCR_NORMAL); +} + + +//**************************************************************************** +void UiSetWindowsCursors(HWND hWnd) { + HCURSOR OldArrow = NULL; + + UiClearCursor(); // Make sure Storm cursor has been turned off + SDlgSetCursor(hWnd, LoadCursor(global_hinstance, "DIABLOCURSOR"), OCR_NORMAL, &OldArrow); +} + diff --git a/src/Uisrc/UI/LOCAL.H b/src/Uisrc/UI/LOCAL.H new file mode 100644 index 0000000..32b64bb --- /dev/null +++ b/src/Uisrc/UI/LOCAL.H @@ -0,0 +1,136 @@ +//**************************************************************************** +// local.cpp +// created 9.13.96 +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +extern HINSTANCE global_hinstance; + + +//**************************************************************************** +//**************************************************************************** + enum _modes { + SINGLEPLAYER, + MULTIPLAYER, + }; + + #define BMP_TEXT_LEN 256 + typedef struct _bmp { + LPBYTE data; + SIZE datasize; + LONG userdata; + TCHAR text[BMP_TEXT_LEN]; + } TBMP, * TPBMP; + + + +typedef struct _gameinfo TGAMEINFO; +struct _gameinfo { + char szName[MAX_GAME_LEN]; + char szPassword[MAX_PASSWORD_LEN]; +}; + + + +//**************************************************************************** +//**************************************************************************** +#define PALETTE_REGISTERS 256 +PALETTEENTRY * UiPaletteEntry(int index); +void UiClearPalette(PALETTEENTRY * pe); + + +//**************************************************************************** +//**************************************************************************** +BOOL LoadArtFile ( HWND window, + HWND parent, + LPCTSTR controltype, + DWORD controlstyle, + LONG usageflags, + LPCTSTR filename, + LPBYTE *bitmapbits, + SIZE *bitmapsize = NULL, + BOOL updatepal = TRUE); + +BOOL UiLoadBmpFile (LPCTSTR filename, + LPBYTE *bitmapbits, + SIZE *bitmapsize); + +//**************************************************************************** +BOOL UiSetStaticBmp(HWND parent, + int child_id, + LPBYTE bmpbits, + SIZE *bmpsize); + +//**************************************************************************** +void UiCalcNewRect(RECT *rect, + int xoffset, + int yoffset); + +//**************************************************************************** +void UiSetBtnBmp(HWND button, + DWORD usage, + RECT *rect, + LPBYTE bmpbits, + SIZE *bmpsize); + +void UiSetButtonBitmaps(HWND parent, + int *btn_ids, + LPBYTE bmpbits, + SIZE *bmpsize); + +//**************************************************************************** +void UiSetTextYellow(HDC hdc); + +//**************************************************************************** +BOOL UiIsPtInWindow(HWND parent, HWND window, int xpos, int ypos); + +//**************************************************************************** +void UiCreateIdentityPal(void); +void UiFreeIdentityPal(void); +HPALETTE UiGetIdentityPal(void); + +//**************************************************************************** +void UiLoadCursor(void); +void UiDestroyCursor(void); +void UiSetCursor(void); +void UiClearCursor(void); + +void UiSetWindowsCursors(HWND hWnd); + +//**************************************************************************** +void UiPaintBtn(HWND window); +void UiOnPaintBtns(HWND window, int * BtnIDs); +void UiActiveDownBtns(HWND window, int * BtnIDs); + +//**************************************************************************** +void UiFlushIOMessages(HWND window); + + +BOOL Txt2GameData(char *szDesc, TGAMEDATA *pGameData, LPSTR *ppszPlayerName, LPSTR *ppszPlayerDesc); +void GameData2Txt(TGAMEDATA *pGameData, LPCSTR szPlayerName, LPCSTR szPlayerDesc, LPSTR szDesc, int nMaxLength); + +//**************************************************************************** +TPBMP UiAllocBmp(void); +void UiFreeBmp(TPBMP tpBmp); +void UiSetBmpText(TPBMP tpBmp, LPCSTR text); + +//**************************************************************************** +BOOL UiIsSpawned(void); + +//**************************************************************************** +void FocusAnimateInit(LPCTSTR filename); +void FocusReInit(void); +void FocusAnimateDestroy(void); +BOOL FocusAnimate(HWND parent, HWND child); +void FocusLost(HWND parent, HWND child); +void FocusErase(HWND parent, HWND child); +void FocusSnd(HWND focus); + +//**************************************************************************** +BOOL UiRegLoadString (LPCTSTR keyname, + LPCTSTR valuename, + DWORD flags, + LPTSTR buffer, + DWORD bufferchars); diff --git a/src/Uisrc/UI/LOGON.CPP b/src/Uisrc/UI/LOGON.CPP new file mode 100644 index 0000000..a2a0b6e --- /dev/null +++ b/src/Uisrc/UI/LOGON.CPP @@ -0,0 +1,190 @@ +//**************************************************************************** +// Logon.cpp +// Diablo UI log on to battlenet popup dialog +// +// By Frank Pearce +// created 9.25.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + #define DEFAULT_LEN 16 + + static LPBYTE sgBgBmp = NULL; + static LPBYTE sgBtnBmp = NULL; + + static LPSTR sgName; + static LPSTR sgPassword; + static UINT sgNameLen; + static UINT sgPasswordLen; + + +//**************************************************************************** +//**************************************************************************** +static void LogonSaveInfo(HWND window) { + HWND edit; + + // get the logon name + if (sgName) { + edit = GetDlgItem(window, IDC_LOGONNAME_EDIT); + GetWindowText(edit, sgName, sgNameLen); + } + + // get the logon password + if (sgPassword) { + edit = GetDlgItem(window, IDC_LOGONPASSWORD_EDIT); + GetWindowText(edit, sgPassword, sgPasswordLen); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void LogonClearInfo(HWND window) { + // clear the logon name + if (sgName) + *sgName = 0; + + // clear the logon password + if (sgPassword) + *sgPassword = 0; +} + + +//**************************************************************************** +//**************************************************************************** +static void LogonDestroy(HWND window) { + if (sgBgBmp) { + FREE(sgBgBmp); + sgBgBmp = NULL; + } + if (sgBtnBmp) { + FREE(sgBtnBmp); + sgBtnBmp = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void LogonInit(HWND window) { + HWND edit; + + // load ctrl/dlg bmps + LoadArtFile( + window, + GetParent(window), + TEXT("Popup"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\lpopup.pcx"), + &sgBgBmp, + NULL + ); + LoadArtFile( + NULL, + window, + TEXT("Button"), + SDLG_STYLE_ANYPUSHBUTTON, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\button.pcx"), + &sgBtnBmp, + NULL + ); + + // make sure there were some lengths set + if (!sgNameLen) sgNameLen = DEFAULT_LEN; + if (!sgPasswordLen) sgPasswordLen = DEFAULT_LEN; + + // limit length of logon name + edit = GetDlgItem(window, IDC_LOGONNAME_EDIT); + SendMessage(edit, EM_LIMITTEXT, sgNameLen, 0); + SetFocus(edit); + + // limit length of logon password + edit = GetDlgItem(window, IDC_LOGONPASSWORD_EDIT); + SendMessage(edit, EM_LIMITTEXT, sgNameLen, 0); + + return; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK LogonDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: + LogonSaveInfo(window); + SDlgEndDialog(window,IDOK); + break; + case IDCANCEL: + LogonClearInfo(window); + SDlgEndDialog(window,IDCANCEL); + break; + } + break; + + case WM_CTLCOLORSTATIC: + if (GetWindowLong((HWND)lparam, GWL_ID) == IDC_DLGTITLE) { + UiSetTextYellow((HDC)wparam); + return (BOOL) GetStockObject(NULL_BRUSH); + } + break; + + case WM_DESTROY: + LogonDestroy(window); + break; + + case WM_INITDIALOG: + LogonInit(window); + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiLogonDialog(HWND parent, + DWORD *selection, + LPSTR logonname, + UINT maxnamelen, + LPSTR logonpassword, + UINT maxpasswordlen +) { + DWORD result; + + sgName = logonname; + sgPassword = logonpassword; + sgNameLen = maxnamelen; + sgPasswordLen = maxpasswordlen; + + result = SDlgDialogBox( + global_hinstance, + TEXT("LOGON_DIALOG"), + parent, + LogonDialogProc + ); + + if (selection) + *selection = result; + + return 1; +} diff --git a/src/Uisrc/UI/MAINMENU.CPP b/src/Uisrc/UI/MAINMENU.CPP new file mode 100644 index 0000000..5191e7f --- /dev/null +++ b/src/Uisrc/UI/MAINMENU.CPP @@ -0,0 +1,368 @@ +//**************************************************************************** +// MainMenu.cpp +// Diablo UI main menu dialog +// +// By Frank Pearce +// created 9.17.96 +//**************************************************************************** + +#define OEMRESOURCE + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +#define ALLOW_SINGLE 1 // 1 in final + +#define MIN_MEMORY_REQ 0x00dac000L // 14MB + + +//**************************************************************************** +//**************************************************************************** + extern void TitleLogoDestroy(void); + extern void TitleLogoInit(HWND window); + extern void TitleFramesInit(HWND window, LPCTSTR filename); + extern void TitleLogoAnimate(HWND window); + + extern int SpawnErrDialog(HWND parent, int errstrid, BOOL onmainmenu); + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define LOGO_TIMER_ID 2 + #define LOGO_FPS 17 // frames per second + #define LOGO_TIMER_DELAY 55 //(MILLISEC_PER_SEC / LOGO_FPS) + + #define ATTRACT_TIMER_ID 3 + + #define MAX_REG_LEN 64 + + static TCHAR sgRegistration[MAX_REG_LEN]; + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_REGISTRATION, + 0 + }; +#if ALLOW_SINGLE + static int sgBtnIDs[] = { + IDC_SINGLEPLAYER_BTN, + IDC_MULTIPLAYER_BTN, + IDC_REPLAYINTRO_BTN, + IDC_SUPPORT_BTN, + IDC_SHOWCREDITS_BTN, + IDCANCEL, + 0 + }; +#else + static int sgGrayBtnIDs[] = { + IDC_SINGLEPLAYER_BTN, + 0 + }; + static int sgBtnIDs[] = { + IDC_MULTIPLAYER_BTN, + IDC_REPLAYINTRO_BTN, + IDC_SUPPORT_BTN, + IDC_SHOWCREDITS_BTN, + IDCANCEL, + 0 + }; +#endif + + static UINT sgAttractTimeout; + + +//**************************************************************************** +//**************************************************************************** +LPCTSTR GetRegStr(void) { + return sgRegistration; +} + + +//**************************************************************************** +//**************************************************************************** +static void MainMenuDestroy(HWND window) { + TitleLogoDestroy(); + + FocusAnimateDestroy(); + +#if ALLOW_SINGLE + UiDoomCtrlsDestroy(window, sgBtnIDs); +#else + UiDoomCtrlsDestroy(window, sgGrayBtnIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); +#endif + UiDoomCtrlsDestroy(window, sgTextIDs); + + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + UiClearCursor(); +} + + +//**************************************************************************** +//**************************************************************************** +static void MainMenuResetAttractTimer(HWND window) { + // Crashes so we pulled this. + //SDlgSetTimer(window, ATTRACT_TIMER_ID, sgAttractTimeout * MILLISEC_PER_SEC, NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void MainMenuInit(HWND window, UINT attracttimeout) { + TPBMP tpBmp; + HWND child; + + // init a bmp for the window + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + UiIsSpawned() ? TEXT("ui_art\\swmmenu.pcx") : TEXT("ui_art\\mainmenu.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window); + } + + // set the reg string + child = GetDlgItem(window, IDC_REGISTRATION); + SetWindowText(child, sgRegistration); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_SMALLGRAY); +#if ALLOW_SINGLE + UiDoomButtonsInit(window, sgBtnIDs, AF_HUGE); +#else + UiDoomButtonsInit(window, sgBtnIDs, AF_HUGE); + UiDoomButtonsInit(window, sgGrayBtnIDs, AF_HUGEGRAY); + EnableWindow(GetDlgItem(window, IDC_SINGLEPLAYER_BTN), FALSE); +#endif + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus42.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + // set up the animating diablo logo + TitleLogoInit(window); + TitleFramesInit(window,TEXT("ui_art\\hf_logo2.pcx")); + TitleLogoAnimate(window); + SDlgSetTimer(window, LOGO_TIMER_ID, LOGO_TIMER_DELAY, NULL); + + MainMenuResetAttractTimer(window); + + UiActiveDownBtns(window, sgBtnIDs); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL HasMultiplayerMemory(void) { + MEMORYSTATUS memstat; + + memstat.dwLength = sizeof(MEMORYSTATUS); + GlobalMemoryStatus(&memstat); + return(memstat.dwTotalPhys > MIN_MEMORY_REQ); +} + + +//**************************************************************************** +//**************************************************************************** +static void MainMenuAbort(HWND window, int ReturnVal, BOOL playsnd) { + //Crashes so we pulled this. + //SDlgKillTimer(window, ATTRACT_TIMER_ID); + + if (UiIsSpawned()) { + if (ReturnVal == MAINMENU_REPLAY_INTRO) { + SpawnErrDialog(window, IDS_SPAWNINTRO_ERR, TRUE); + MainMenuResetAttractTimer(window); + return; + } + } + + // if user selected multiplayer confirm memory requirements + if (ReturnVal == MAINMENU_MULTIPLAYER) { + if (! HasMultiplayerMemory()) { + SpawnErrDialog(window, IDS_MEMORY_ERR, TRUE); + MainMenuResetAttractTimer(window); + return; + } + } + + UiFadeAbort(window); + if (playsnd) + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + SDlgKillTimer(window, LOGO_TIMER_ID); + + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void MainMenuBtnAction(HWND window, int id) { + switch (id) { + case IDC_SINGLEPLAYER_BTN: + MainMenuAbort(window,MAINMENU_SINGLE_PLAYER, TRUE); + break; + case IDC_MULTIPLAYER_BTN: + MainMenuAbort(window,MAINMENU_MULTIPLAYER, TRUE); + break; + case IDC_REPLAYINTRO_BTN: + MainMenuAbort(window,MAINMENU_REPLAY_INTRO, TRUE); + break; + case IDC_SUPPORT_BTN: + MainMenuAbort(window,MAINMENU_SUPPORT, TRUE); + break; + case IDC_SHOWCREDITS_BTN: + MainMenuAbort(window,MAINMENU_SHOW_CREDITS, TRUE); + break; + case IDCANCEL: + MainMenuAbort(window,MAINMENU_EXIT_DIABLO, TRUE); + break; + case IDOK: { + // enter key was pressed + HWND FocusBtn = GetFocus(); + int BtnID = GetWindowLong(FocusBtn, GWL_ID); + SendMessage(window, WM_COMMAND, BtnID, NULL); + } + break; + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK MainMenuDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + MainMenuResetAttractTimer(window); + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_CLICKED) { + MainMenuBtnAction(window, LOWORD(wparam)); + } + break; + + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MOUSEMOVE: + MainMenuResetAttractTimer(window); + break; + + case WM_DESTROY: + MainMenuDestroy(window); + break; + + case WM_INITDIALOG: + MainMenuInit(window, lparam); + PostMessage(window, WM_USER+1000, 0, 0); + return 1; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_TIMER: + switch (wparam) { + case FOCUS_TIMER_ID: + FocusAnimate(window, GetFocus()); + break; + case LOGO_TIMER_ID: + TitleLogoAnimate(window); + break; + case ATTRACT_TIMER_ID: + if (! UiIsSpawned()) { + MainMenuAbort(window,MAINMENU_ATTRACT_MODE, FALSE); + } + break; + } + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiMainMenuDialog(LPCTSTR registration, + DWORD * selection, + bool allowMultiplayer, + PLAYSND sndfcn, + UINT attracttimeoutseconds + ) { + DWORD result; + + sgAttractTimeout = attracttimeoutseconds; + + // init the play sound routine for diabloui + UiSndSetFcn(sndfcn); + + // init the custom non-windows font + ArtFontLoad(); + + sgRegistration[0] = 0; + if (registration) + strncpy(sgRegistration, registration, MAX_REG_LEN); + + // DISPLAY THE DIALOG BOX + result = (DWORD)SDlgDialogBox( + global_hinstance, + (allowMultiplayer) ? TEXT("MAINMENU_DIALOG2") : TEXT("MAINMENU_DIALOG"), + SDrawGetFrameWindow(), + MainMenuDialogProc + ); + + if (result == MAINMENU_EXIT_DIABLO) { + ArtFontDestroy(); + } + + // set the results + if (selection) + *selection = result; + + return 1; +} diff --git a/src/Uisrc/UI/MIKE.APS b/src/Uisrc/UI/MIKE.APS new file mode 100644 index 0000000..080b630 Binary files /dev/null and b/src/Uisrc/UI/MIKE.APS differ diff --git a/src/Uisrc/UI/MIKE.H b/src/Uisrc/UI/MIKE.H new file mode 100644 index 0000000..5f53084 --- /dev/null +++ b/src/Uisrc/UI/MIKE.H @@ -0,0 +1,86 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Mike.rc +// +#define ID_SCROLL_WINDOW 1000 +#define IDS_GAME_PUBLIC 1001 +#define IDC_AD 1001 +#define IDS_GAME_PRIVATE 1002 +#define IDS_DIFF_NORMAL 1003 +#define IDC_USERLIST 1003 +#define IDS_DIFF_NIGHTMARE 1004 +#define IDS_DIFF_HELL 1005 +#define IDC_CHATWINDOW 1005 +#define IDS_PUBLIC_DESC 1006 +#define IDC_CHATEDIT 1006 +#define IDS_PRIVATE_DESC 1007 +#define ID_CHATJOIN 1007 +#define ID_CHATCREATE 1008 +#define IDS_NAME_REQUIRED 1008 +#define ID_SENDMSG 1009 +#define IDS_PASSWORD_REQUIRED 1009 +#define IDC_EDIT_NAME 1010 +#define IDS_CHAT_HELP 1010 +#define IDC_EDIT_PASSWORD 1011 +#define IDS_GAME_DESC_INCLNAME 1011 +#define IDC_TYPE_PUBLIC 1012 +#define IDS_GAME_DESC 1012 +#define IDC_TYPE_PRIVATE 1013 +#define IDS_NO_ALLOW_SPAWN 1013 +#define IDC_DIF_NORMAL 1014 +#define IDS_DIFF_NORMAL_SHORT 1014 +#define IDC_DIF_NIGHTMARE 1015 +#define IDS_DIFF_NIGHTMARE_SHORT 1015 +#define IDC_DIF_HELL 1016 +#define IDS_DIFF_HELL_SHORT 1016 +#define IDS_NO_ALLOW_SPAWN_SHORT 1017 +#define IDC_COMBO1 1020 +#define IDC_CHAT_CHANNEL 1020 +#define IDC_EDIT1 1022 +#define IDS_NORMAL_DESC 1023 +#define IDS_NIGHTMARE_DESC 1024 +#define IDS_HELL_DESC 1025 +#define IDS_OPEN_DESC 1026 +#define IDC_LIST1 1027 +#define IDS_RESTRICTED_DESC 1027 +#define IDS_GAME_NAME_INVALID 1028 +#define IDC_STATIC_DESC 1029 +#define IDC_STATIC_GAMETYPE_DESC 1029 +#define IDS_NORMAL_DESC_XLONG 1029 +#define IDC_TITLE 1030 +#define IDS_NIGHTMARE_DESC_XLONG 1030 +#define IDC_GAMEDESCRIPTION 1031 +#define IDS_HELL_DESC_XLONG 1031 +#define IDC_RADIO_NORMAL 1032 +#define IDS_LEVEL_AUTHORIZATION 1032 +#define IDC_RADIO_NIGHTMARE 1033 +#define IDS_GAMECREATOR_FMT 1033 +#define IDS_GAMECREATOR 1033 +#define IDS_CREATOR 1033 +#define IDC_RADIO_HELL 1034 +#define IDS_AM 1034 +#define IDS_PM 1035 +#define IDS_CREATIONTIME_FMT 1036 +#define IDS_TIME 1037 +#define IDS_CREATOR_FMT 1038 +#define IDS_GAMEALREADYEXISTS 1039 +#define IDC_STATIC_DIFF_DESC 1040 +#define IDS_CREATEGAMEERROR 1040 +#define IDS_NIGHTMARE_MINREQ 1041 +#define IDC_CHECK1 1042 +#define IDS_HELL_MINREQ 1042 +#define IDS_AUTH_STRTOOLONG 1043 +#define IDS_AUTH_BADHERODESC 1044 +#define IDS_AUTH_CHANNELRESTRICTED 1045 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 128 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1048 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Uisrc/UI/MIKE.RC b/src/Uisrc/UI/MIKE.RC new file mode 100644 index 0000000..4c6146d --- /dev/null +++ b/src/Uisrc/UI/MIKE.RC @@ -0,0 +1,221 @@ +//Microsoft Developer Studio generated resource script. +// +#include "mike.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 + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "DIALOG_CREATE_GAME", DIALOG + BEGIN + LEFTMARGIN, 10 + RIGHTMARGIN, 244 + TOPMARGIN, 10 + BOTTOMMARGIN, 139 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "mike.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +DIALOG_CREATE_GAME DIALOGEX 0, 61, 256, 146 +STYLE WS_POPUP | WS_VISIBLE +FONT 13, "Times New Roman", 700, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT_NAME,168,50,76,12,ES_AUTOHSCROLL + EDITTEXT IDC_EDIT_PASSWORD,168,69,76,12,ES_AUTOHSCROLL + PUSHBUTTON "Normal",IDC_RADIO_NORMAL,46,22,34,29,BS_BOTTOM | + BS_NOTIFY | WS_GROUP | NOT WS_TABSTOP + PUSHBUTTON "Nightmare",IDC_RADIO_NIGHTMARE,25,54,34,29,BS_BOTTOM | + BS_NOTIFY | NOT WS_TABSTOP + PUSHBUTTON "Hell",IDC_RADIO_HELL,67,54,34,29,BS_BOTTOM | BS_NOTIFY | + NOT WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,181,128,34,15,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,219,128,34,15,WS_GROUP + LTEXT "",IDC_STATIC_DIFF_DESC,10,88,104,50 + CTEXT "Create Game",IDC_TITLE,130,10,114,9,0,WS_EX_TRANSPARENT + RTEXT "Name:",IDC_STATIC,130,50,36,12,0,WS_EX_TRANSPARENT + RTEXT "Password:",IDC_STATIC,130,69,36,12,0,WS_EX_TRANSPARENT + CTEXT "Difficulty",IDC_STATIC,10,10,104,9,0,WS_EX_TRANSPARENT + LTEXT "To make the game private, enter a password below.", + IDC_STATIC,130,23,114,18,0,WS_EX_TRANSPARENT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Cursor +// + +DIABLO_LINKCURSOR CURSOR DISCARDABLE "link.cur" +DIABLO_ARROWCURSOR CURSOR DISCARDABLE "arrow.cur" + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1997,3,21,1 + PRODUCTVERSION 1,1,0,2 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Blizzard Entertainment\0" + VALUE "FileDescription", "DiabloUI\0" + VALUE "FileVersion", "1997, 3, 21, 1\0" + VALUE "InternalName", "DiabloUI\0" + VALUE "LegalCopyright", "Copyright © 1997\0" + VALUE "OriginalFilename", "DiabloUI.dll\0" + VALUE "ProductName", "Blizzard Entertainment DiabloUI\0" + VALUE "ProductVersion", "1, 1, 0, 2\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_GAME_PUBLIC "Public" + IDS_GAME_PRIVATE "Private - Requires password" + IDS_DIFF_NORMAL "Normal Difficulty" + IDS_DIFF_NIGHTMARE "Nightmare Difficulty" + IDS_DIFF_HELL "Hell Difficulty" + IDS_PUBLIC_DESC "This game will appear in the master list of games. A password will not be required to play." + IDS_PRIVATE_DESC "This game will not appear in the master list of games. A password is required." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NAME_REQUIRED "You must enter a name for the game." + IDS_PASSWORD_REQUIRED "A password is required for all private games." + IDS_GAME_DESC_INCLNAME "%s: %s" + IDS_GAME_DESC "%s" + IDS_DIFF_NORMAL_SHORT "Norm." + IDS_DIFF_NIGHTMARE_SHORT "Ntmare." + IDS_DIFF_HELL_SHORT "Hell" + IDS_NORMAL_DESC "Normal Difficulty\nThis is where a starting character should begin the quest to defeat Diablo." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_NIGHTMARE_DESC "Nightmare Difficulty\nThis is recommended for experienced characters only." + IDS_HELL_DESC "Hell Difficulty\nOnly the most experienced characters should venture in this realm." + IDS_OPEN_DESC "Open to players with spawned versions of Diablo." + IDS_RESTRICTED_DESC "Only players with the full retail version of Diablo may join this game." + IDS_GAME_NAME_INVALID "Invalid name. A valid name must not contain reserved words or reserved characters." + IDS_NORMAL_DESC_XLONG "Normal Difficulty\nThis is where a starting character should begin the quest to defeat Diablo." + IDS_NIGHTMARE_DESC_XLONG + "Nightmare Difficulty\nThe denizens of the Labyrinth have been bolstered and will prove to be a greater challenge. This is recommended for experienced characters only." + IDS_HELL_DESC_XLONG "Hell Difficulty\nThe most powerful of the underworld's creatures lurk at the gateway into Hell. Only the most experienced characters should venture in this realm." + IDS_LEVEL_AUTHORIZATION "(L" + IDS_CREATOR "Creator: " + IDS_AM "am" + IDS_PM "pm" + IDS_CREATIONTIME_FMT "%s: %d:%02d%s" + IDS_TIME "Time" + IDS_GAMEALREADYEXISTS "There is already a game running using the name: %s." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_CREATEGAMEERROR "Unable to create game." + IDS_NIGHTMARE_MINREQ "Your character must reach level 20 before you can enter a multiplayer game of Nightmare difficulty." + IDS_HELL_MINREQ "Your character must reach level 30 before you can enter a multiplayer game of Hell Difficulty." + IDS_AUTH_STRTOOLONG "Error: Unable to authorize. String too long." + IDS_AUTH_BADHERODESC "Error: Unable to authorize. Unrecognized character information." + IDS_AUTH_CHANNELRESTRICTED + """%s"" is a restricted channel, and you are not authorized to enter." +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Uisrc/UI/MODEM.CPP b/src/Uisrc/UI/MODEM.CPP new file mode 100644 index 0000000..2fc511b --- /dev/null +++ b/src/Uisrc/UI/MODEM.CPP @@ -0,0 +1,621 @@ +//**************************************************************************** +// Modem.cpp +// Diablo UI create/join modem multiplayer game +// +// By Frank Pearce +// created 11.18.96 +//**************************************************************************** + + +#include "pch.h" +#include +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern void TitleLogoDestroy(void); + extern void TitleLogoInit(HWND window); + extern void TitleFramesInit(HWND window, LPCTSTR filename); + extern void TitleLogoAnimate(HWND window); + + extern int ModmStatDialog(HWND parent); + + extern int SelOkDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus); + + extern BOOL UiDoomCreateGame ( + SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid, + BOOL loadfocus, + LPCSTR gamename + ); + extern BOOL CALLBACK EnterDialDialogProc( + HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam + ); + extern BOOL CALLBACK SelDialDialogProc( + HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam + ); + extern BOOL CALLBACK SelCre8JoinDialogProc( + HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam + ); + extern void SelDialSaveBookEntries(LPCSTR dialstring); + + + +//**************************************************************************** +//**************************************************************************** + #define PROVIDERID 'MODM' + + #define MILLISEC_PER_SEC 1000 + + #define LOGO_TIMER_ID 2 + #define LOGO_FPS 17 + #define LOGO_TIMER_DELAY 55 + + // messages to post to invoke child dialogs + enum _modemstates { + WM_STATE_SELDIALANSWER = (WM_USER+2000), + WM_STATE_ENTERDIAL, + WM_STATE_SELCRE8JOIN + }; + + +//**************************************************************************** +//**************************************************************************** + #define GAMENAME_LEN SNETSPI_MAXSTRINGLENGTH + #define DESCRIPTION_LEN SNETSPI_MAXSTRINGLENGTH + + typedef struct _modemgame TMGAME; + typedef TMGAME *TPMGAME; + struct _modemgame { + DWORD gameid; + TCHAR gamename[GAMENAME_LEN]; + TCHAR gamedesc[DESCRIPTION_LEN]; + }; + static TMGAME sgMGame; + static BOOL sgConnected; + static int sgGameCount; + static int sgLastJoined; + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgDescTitle[] = { + IDC_DLGTITLE2, + 0 + }; + static int sgModemDescID[] = { + IDC_MODEMDESC, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** + // storm related data + static SNETPROGRAMDATAPTR sgMdmProgramData; + static SNETPLAYERDATAPTR sgMdmPlayerData; + static SNETUIDATAPTR sgMdmInterfaceData; + static SNETVERSIONDATAPTR sgMdmVersionData; + static DWORD *sgpMdmPlayerID; + + +//**************************************************************************** +//**************************************************************************** +BOOL ModemConnected(void) { + return sgConnected; +} + + +//**************************************************************************** +//**************************************************************************** +void ModemSetInfo(HWND window, LPCSTR infotitle, LPCSTR text) { + HWND child = GetDlgItem(window, IDC_MODEMDESC); + if (! child) return; + TPBMP tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + UiSetBmpText(tpBmp, text); + UiDoomStaticReset(window, sgModemDescID, AF_SMALLGRAY); + + child = GetDlgItem(window, IDC_DLGTITLE2); + if (! child) return; + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + UiSetBmpText(tpBmp, infotitle); + UiDoomStaticReset(window, sgDescTitle, AF_MEDGRAY); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK ModemGameEnum(DWORD gameid, + LPCSTR gamename, + LPCSTR gamedesc) { + sgMGame.gameid = gameid; + strcpy(sgMGame.gamename, gamename); + strcpy(sgMGame.gamedesc, gamedesc); + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +BOOL ModemEnum(void) { + // clear old info + sgMGame.gameid = 0; + sgMGame.gamename[0] = 0; + sgMGame.gamedesc[0] = 0; + + if (SNetEnumGames(0, 0, ModemGameEnum, NULL)) { //### MM Diablo Patch #2 3/21/97 + if (! sgMGame.gameid) + return FALSE; + return TRUE; + } + else { + return FALSE; + } +} + + +//**************************************************************************** +//**************************************************************************** +LPCSTR ModemGameName(void) { + return sgMGame.gamename; +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemUpdateGame(HWND window) { + // clear old info + sgMGame.gameid = 0; + sgMGame.gamename[0] = 0; + sgMGame.gamedesc[0] = 0; + + // enum will fill in info if a game exists + if (! SNetEnumGames(0, 0, ModemGameEnum, NULL)) { //### MM Diablo Patch #2 3/21/97 + switch (GetLastError()) { + case SNET_ERROR_NO_NETWORK: + sgConnected = FALSE; + sgGameCount = sgLastJoined = 1; + break; + default: + break; + } + } + else { + sgConnected = TRUE; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemDestroy(HWND window) { + UiDoomCtrlsDestroy(window, sgModemDescID); + UiDoomCtrlsDestroy(window, sgDescTitle); + UiDoomCtrlsDestroy(window, sgTextIDs); + + // free the background of the dlg + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + TitleLogoDestroy(); +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemAbort(HWND window, int ReturnVal) { + UiFadeAbort(window); + SDlgKillTimer(window, LOGO_TIMER_ID); + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemInit(HWND window) { + TPBMP tpBmp; + + // set up the animating diablo logo + TitleLogoInit(window); + TitleFramesInit(window,TEXT("ui_art\\hf_logo2.pcx")); + TitleLogoAnimate(window); + SDlgSetTimer(window, LOGO_TIMER_ID, LOGO_TIMER_DELAY, NULL); + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\selgame.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window); + } + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomStaticInit(window, sgDescTitle, AF_MEDGRAY); + UiDoomStaticInit(window, sgModemDescID, AF_SMALLGRAY); + + // try to enum modem games + ModemUpdateGame(window); + if (sgConnected) { + PostMessage(window, WM_STATE_SELCRE8JOIN, 0, 0); + } + else { + sgGameCount = sgLastJoined = 1; + PostMessage(window, WM_STATE_SELDIALANSWER, 0, 0); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemCreate(HWND window) { + char namefmt[32]; + char gamename[64]; + SNETUIDATA interfacedata; + SNETCREATEDATA createdata; + + // create new interface data + CopyMemory(&interfacedata,sgMdmInterfaceData,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = window; + + ZeroMemory(&createdata,sizeof(SNETCREATEDATA)); + createdata.size = sizeof(SNETCREATEDATA); + createdata.providerid = PROVIDERID; + createdata.maxplayers = sgMdmProgramData->maxplayers; + createdata.createflags = 0; + + LoadString(global_hinstance, IDS_MODEMGAMENAME_FMT, namefmt, 31); + wsprintf(gamename, namefmt, sgGameCount); + + if (UiDoomCreateGame( + &createdata, + sgMdmProgramData, + sgMdmPlayerData, + &interfacedata, + sgMdmVersionData, + sgpMdmPlayerID, + TRUE, + gamename + ) + ) { + sgGameCount++; + ModemAbort(window, IDOK); + } + else { + if (! sgConnected) { + PostMessage(window, WM_STATE_SELDIALANSWER, 0, 0); + return; + } + if (GetLastError() == SNET_ERROR_ALREADY_EXISTS) { + sgGameCount++; + } + PostMessage(window, WM_STATE_SELCRE8JOIN, 0, 0); + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL sgSNetJoinDone; +static BOOL sgJoinResult; +static int sgSNetJoinErr; +static void __cdecl ModemJoinThread(void *dialstring) { + sgSNetJoinDone = FALSE; + sgJoinResult = SNetJoinGame( + 0, + (sgConnected ? sgMGame.gamename: (LPCSTR)dialstring), + NULL, + sgMdmPlayerData->playername, + sgMdmPlayerData->playerdescription, + sgpMdmPlayerID + ); + if (! sgJoinResult) + sgSNetJoinErr = GetLastError(); + sgSNetJoinDone = TRUE; + _endthread(); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL ModemJoinDone(void) { + return sgSNetJoinDone; +} + + +//**************************************************************************** +//**************************************************************************** +int ModemLastJoinedNumber(void) { + return sgLastJoined; +} + + +//**************************************************************************** +//**************************************************************************** +int ModemGameNumber(LPCSTR gamename) { + + BYTE * szName = (BYTE *)gamename; + + // locate the game number in the string + while ((*szName) && ((*szName < '0') || (*szName > '9'))) { + szName++; + } + + if (*szName) { + return atoi((LPSTR)szName); + } + return 0; +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemJoin(HWND window, LPCSTR DialString) { + + sgSNetJoinDone = FALSE; + _beginthread(ModemJoinThread, 0, (void *)DialString); + + ModmStatDialog(window); + + if (sgJoinResult) { + // is this the first link up? + if (! sgConnected) { + SelDialSaveBookEntries(DialString); + ModemEnum(); + } + // update the local game number + sgGameCount = sgLastJoined = ModemGameNumber(sgMGame.gamename); + sgGameCount++; + + ModemAbort(window, IDOK); + } + else { + TCHAR err[128]; + + switch (sgSNetJoinErr) { + case SNET_ERROR_VERSION_MISMATCH: + LoadString(global_hinstance, IDS_VERSION_ERR, err, 127); + SelOkDialog(window, err, NULL, TRUE); + break; + case SNET_ERROR_CANCELLED: + // just bring up previous menu + break; + case SNET_ERROR_NOT_CONNECTED: + // no answer + LoadString(global_hinstance, IDS_NOANSWER_ERR, err, 127); + SelOkDialog(window, err, NULL, TRUE); + break; + case SNET_ERROR_NO_NETWORK: + // no dial tone + LoadString(global_hinstance, IDS_NOTONE_ERR, err, 127); + SelOkDialog(window, err, NULL, TRUE); + break; +// fgp.patch1.start.1/17/96 +// case SNET_ERROR_HOST_UNREACHABLE: + case SNET_ERROR_NETWORK_BUSY: +// fgp.patch1.end.1/17/96 + // busy signal + LoadString(global_hinstance, IDS_BUSY_ERR, err, 127); + SelOkDialog(window, err, NULL, TRUE); + break; + case SNET_ERROR_BAD_PROVIDER: + // unable to establish a connection to the modem + LoadString(global_hinstance, IDS_MODEMOFF_ERR, err, 127); + SelOkDialog(window, err, NULL, TRUE); + break; + default: + LoadString(global_hinstance, IDS_MODEMJOIN_ERR, err, 127); + SelOkDialog(window, err, NULL, TRUE); + break; + } + + if (sgConnected) { + PostMessage(window, WM_STATE_SELCRE8JOIN, 0, 0); + } + else { + PostMessage(window, WM_STATE_SELDIALANSWER, 0, 0); + } + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemSelDialAnswer(HWND window) { + TCHAR dialstring[MAX_DIAL_LEN]; + int result; + + // bring up the enter name screen + result = SDlgDialogBoxParam( + global_hinstance, + TEXT("SELDIAL_DIALOG"), + window, + SelDialDialogProc, + (LPARAM) dialstring + ); + + switch (result) { + case MODE_DIALNEW: + PostMessage(window, WM_STATE_ENTERDIAL, 0, 0); + break; + case MODE_DIALOLD: + ModemJoin(window, dialstring); + break; + case MODE_ANSWER: + ModemCreate(window); + break; + default: + ModemAbort(window, IDCANCEL); + break; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemEnterDial(HWND window) { + TCHAR dialstring[MAX_DIAL_LEN]; + int result; + + // bring up the enter name screen + result = SDlgDialogBoxParam( + global_hinstance, + TEXT("ENTERDIAL_DIALOG"), + window, + EnterDialDialogProc, + (LPARAM) &dialstring + ); + + if (result == IDOK) { + ModemJoin(window, dialstring); + } + else { + PostMessage(window, WM_STATE_SELDIALANSWER, 0, 0); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ModemSelCre8Join(HWND window) { + int result; + + // bring up the enter name screen + result = SDlgDialogBox( + global_hinstance, + TEXT("SELCRE8JOIN_DIALOG"), + window, + SelDialDialogProc + ); + + switch (result) { + case MODE_DIALNEW: + ModemJoin(window, sgMGame.gamename); + break; + case MODE_ANSWER: + ModemCreate(window); + break; + case SNET_ERROR_NO_NETWORK: + sgConnected = FALSE; + PostMessage(window, WM_STATE_SELDIALANSWER, 0, 0); + break; + default: + ModemAbort(window, IDCANCEL); + break; + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK ModemDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_DESTROY: + ModemDestroy(window); + break; + + case WM_INITDIALOG: + ModemInit(window); + PostMessage(window, WM_USER+1000, 0, 0); + return 0; + + case WM_STATE_SELDIALANSWER: + ModemSelDialAnswer(window); + return 0; + + case WM_STATE_ENTERDIAL: + ModemEnterDial(window); + return 0; + + case WM_STATE_SELCRE8JOIN: + ModemSelCre8Join(window); + return 0; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_TIMER: + TitleLogoAnimate(window); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiModemGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + int result = 0; + + // save parameters for use throughout this file + sgMdmProgramData = programdata; + sgMdmPlayerData = playerdata; + sgMdmInterfaceData = interfacedata; + sgMdmVersionData = versiondata; + sgpMdmPlayerID = playerid; + + // make sure fonts are loaded + ArtFontLoad(); + + // DISPLAY THE DIALOG BOX + result = SDlgDialogBox(global_hinstance, + TEXT("MODEM_DIALOG"), + interfacedata->parentwindow, + ModemDialogProc); + + ArtFontDestroy(); + + if (result == IDOK) + return TRUE; + return FALSE; +} diff --git a/src/Uisrc/UI/MODMSTAT.CPP b/src/Uisrc/UI/MODMSTAT.CPP new file mode 100644 index 0000000..d35d12c --- /dev/null +++ b/src/Uisrc/UI/MODMSTAT.CPP @@ -0,0 +1,209 @@ +//**************************************************************************** +// ModmStat.cpp +// Diablo UI modem status thread/dialog +// +// By Frank Pearce +// created 12.1.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + + extern BOOL ModemJoinDone(void); + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_OKCANCEL_TEXT, + 0 + }; + static int sgBtnIDs[] = { + IDCANCEL, + 0 + }; + +//**************************************************************************** +//**************************************************************************** + static TCHAR sgStatStr[SNETSPI_MAXSTRINGLENGTH]; + static BOOL sgStatChanged; + static BOOL sgAbortable; + static SNETABORTPROC sgpAbortFcn; + + +//**************************************************************************** +//**************************************************************************** +static void ModmStatDestroy(HWND window) { + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + FocusAnimateDestroy(); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); +} + + +//**************************************************************************** +//**************************************************************************** +static void ModmStatInit(HWND window) { + TPBMP tpBmp; + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT("Popup"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\black.pcx"), + &tpBmp->data, + &tpBmp->datasize + ); + } + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_MEDGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG); + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + UiActiveDownBtns(window, sgBtnIDs); + + // init the globals + sgStatStr[0] = 0; + sgStatChanged = FALSE; + sgpAbortFcn = (SNETABORTPROC) NULL; + + // don't allow cancel right away + HWND child = GetDlgItem(window, IDCANCEL); + ShowWindow(child, FALSE); + sgAbortable = FALSE; +} + + +//**************************************************************************** +//**************************************************************************** +static void ModmStatAbort(HWND window, BOOL callabortfcn) { + if (! sgAbortable) return; + + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + + if (callabortfcn && sgpAbortFcn) + sgpAbortFcn(); + + SDlgEndDialog(window, 0); +} + + +//**************************************************************************** +//**************************************************************************** +static void ModmStatUpdateStatus(HWND window) { + sgStatChanged = FALSE; + + if (! sgpAbortFcn) return; + + HWND child = GetDlgItem(window, IDC_OKCANCEL_TEXT); + if (! child) return; + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), sgStatStr); + UiDoomStaticReset(window, sgTextIDs, AF_MEDGRAY); + + child = GetDlgItem(window, IDCANCEL); + ShowWindow(child, TRUE); + sgAbortable = TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK ModmStatDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + } + else if (LOWORD(wparam) == IDOK) { + ModmStatAbort(window, TRUE); + } + else if (LOWORD(wparam) == IDCANCEL) { + ModmStatAbort(window, TRUE); + } + break; + + case WM_DESTROY: + ModmStatDestroy(window); + break; + + case WM_INITDIALOG: + ModmStatInit(window); + return 0; + + case WM_TIMER: + if (sgStatChanged) { + ModmStatUpdateStatus(window); + } + if (ModemJoinDone()) { + sgAbortable = TRUE; + ModmStatAbort(window, FALSE); + } + FocusAnimate(window, GetFocus()); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK ModmStatStatusCallback(LPCSTR statstr, + DWORD completed, + DWORD remaining, + DWORD flags, + SNETABORTPROC abortfcn) { + strcpy(sgStatStr, statstr); + sgStatChanged = TRUE; + sgpAbortFcn = abortfcn; + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +int ModmStatDialog(HWND parent) { + return SDlgDialogBox( + global_hinstance, + TEXT("MODMSTAT_DIALOG"), + parent, + ModmStatDialogProc + ); +} diff --git a/src/Uisrc/UI/MONO.CPP b/src/Uisrc/UI/MONO.CPP new file mode 100644 index 0000000..2c87e35 --- /dev/null +++ b/src/Uisrc/UI/MONO.CPP @@ -0,0 +1,95 @@ +#ifdef _DEBUG +#include "mono.h" + + +// Allocate space for the MonoDriver data. +// and Call the constructor for one MonoDevice data object. +MonoDevice::DeviceData MonoDevice::MDA; + +MonoDevice::DeviceData::DeviceData() : + fhDevice (CreateFile("\\\\.\\DARKMONO.VXD", 0, 0, NULL, NULL, + FILE_FLAG_DELETE_ON_CLOSE, NULL)), + fEnabled((fhDevice != INVALID_HANDLE_VALUE)), + fNextRow(0), + fNextCol(0) +{ + ClearScreen(); +} + +MonoDevice::DeviceData::~DeviceData() +{ + if( Status() ) + { + CloseHandle(fhDevice); + fEnabled = false; + fhDevice = INVALID_HANDLE_VALUE; + fNextRow = 0; + fNextCol = 0; + } +} + +int MonoDevice::PutString( int row, int col, char const * string ) +{ + int Result = 0; + if( Status() && row < HEIGHT && col < WIDTH) + { + short buff[3 + 41]; // allow WIDTH character string + int len = strlen( string ); + Result = len; + int bufferLen = 0; + + for (;len > 0; len -= WIDTH, ++row, col=0, string += bufferLen ) + { + bufferLen = ((len + col) > WIDTH)? WIDTH - (len + col) : len; + if (row >= HEIGHT) + row = 0; + buff[0] = static_cast(row); + buff[1] = static_cast(col); + buff[2] = static_cast(bufferLen); + if( buff[2] > (WIDTH - col) ) + { + buff[2] = (WIDTH - col); + strncpy( reinterpret_cast(buff + 3), string, buff[2] ); + } + else + strcpy( reinterpret_cast(buff + 3), string ); + + DeviceIoControl(MDA.fhDevice, PUT_STRING, + &(buff[0]), sizeof( buff ), NULL, 0, NULL, NULL); + } + + } + return Result; +} + +void __cdecl MonoDevice::Printf( int row, int col, char const * const format, ... ) +{ + if( Status() ) + { + char strbuf [ 256 ]; + va_list argptr; + + va_start(argptr,format); + vsprintf(strbuf,format,argptr); + va_end(argptr); + + PutString( row, col, strbuf ); + } +} + +void __cdecl MonoDevice::Printf( char const * const format, ... ) +{ + if( Status() ) + { + char strbuf [ 256 ]; + va_list argptr; + + va_start(argptr,format); + vsprintf(strbuf,format,argptr); + va_end(argptr); + + PutString( strbuf ); + } +} + +#endif diff --git a/src/Uisrc/UI/MONO.H b/src/Uisrc/UI/MONO.H new file mode 100644 index 0000000..c4ccb4a --- /dev/null +++ b/src/Uisrc/UI/MONO.H @@ -0,0 +1,226 @@ + +/* ======================================================================== + Copyright (c) 1990,1997 Synergistic Software + All Rights Reserved + Author: + ======================================================================== */ + + +#ifdef _DEBUG +#ifndef _MONO_H_ +#define _MONO_H_ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +//#ifdef __BORLANDC__ +//#pragma option -a4 +//#endif +//#ifdef _MSC_VER +//#pragma pack(push,4) +//#endif + +// Define __cdecl for non Microsoft compilers. +#if (!defined(_MSC_VER) && !defined(__cdecl) ) +#define __cdecl +#endif + +// This class is to help put text strings out to a monochrome monitor under +// Windows95. +// It requires the DARKMONO.VXD driver to be installed to work. +// It does do line wrapping. +// There is no stored buffer of the text, so no scrolling. + +class MonoDevice +{ +private: + // Helper class to do auto initialization and to keep from opening the + // driver more than once. + class DeviceData { + private: + friend class MonoDevice; + explicit DeviceData(); + inline bool Status() const; + + + HANDLE fhDevice; + bool fEnabled; + int fNextRow; + int fNextCol; + + protected: + public: + ~DeviceData(); + }; + + enum MonoDimisions + { + WIDTH = 80, + HEIGHT = 24 + }; + + enum MonoFunctions + { + VERSION = 1, + CURSOR_ON = 2, + CURSOR_OFF = 3, + SET_ATTRIBUTE = 4, + CLEAR_SCREEN = 5, + PUT_CHAR = 6, + PUT_STRING = 7 + }; + + // Can't create or distroy one of these. + MonoDevice(); + ~MonoDevice(); + + // Can only have one Monochrome display. + static DeviceData MDA; +public: + typedef enum Attrib + { + ERASE =0x00,NORM =0x07, NORM_BLNK =0x87, + INVRS =0x70,UNDRLN =0x01, UNDRLN_BLNK =0x81, + INVRS_BLNK=0xF0,HI =0x0F, HI_BLNK =0x8F, + HI_UNDRLN=0x09, HI_UNDRLN_BLNK=0x89 + }; + + + static inline bool Status() { return MDA.Status(); } + static inline bool IsEnabled(); + static inline void Enable(); + static inline void Disable(); + static inline void SetAttribute( Attrib attribute ); + static inline void CursorOn(); + static inline void CursorOff(); + static inline void ClearScreen( char fill = ERASE); + static inline bool PutChar( int row, int col, char value ); + static inline bool PutChar( char value ); + static int PutString( int row, int col, char const * const string ); + static inline int PutString( char const * const string ); + static void __cdecl Printf( int row, int col, char const * const format, ... ); + static void __cdecl Printf(char const * const format, ... ); +}; + +inline bool MonoDevice::DeviceData::Status() const +{ + return fhDevice != INVALID_HANDLE_VALUE && fEnabled; +} + +inline bool MonoDevice::IsEnabled() +{ + return MDA.fEnabled; +} + +inline void MonoDevice::Enable() +{ + MDA.fEnabled = true; +} + +inline void MonoDevice::Disable() +{ + MDA.fEnabled = false; +} + +inline void MonoDevice::SetAttribute( Attrib attribute ) +{ + if( Status() ) + { + unsigned char attr = static_cast(attribute); + DeviceIoControl(MDA.fhDevice, SET_ATTRIBUTE, + &attr, sizeof( attr ), + NULL, 0, NULL, NULL); + } +} + +inline void MonoDevice::CursorOn() +{ + if( Status() ) + DeviceIoControl(MDA.fhDevice, CURSOR_ON, + NULL, 0, NULL, 0, NULL, NULL); +} + +inline void MonoDevice::CursorOff() +{ + if( Status() ) + DeviceIoControl(MDA.fhDevice, CURSOR_OFF, + NULL, 0, NULL, 0, NULL, NULL); +} + +inline void MonoDevice::ClearScreen( char fill ) +{ + if( Status() ) + { + DeviceIoControl(MDA.fhDevice, CLEAR_SCREEN, + &fill, sizeof( fill ), NULL, 0, NULL, NULL); + MDA.fNextRow = 0; + MDA.fNextCol = 0; + } +} + +inline bool MonoDevice::PutChar( int row, int col, char value ) +{ + bool Result = false; + + if( Status() && row < HEIGHT && col < WIDTH) + { + short buff[3]; + buff[0] = static_cast(row); + buff[1] = static_cast(col); + buff[2] = value; // high byte doesn't matter + DeviceIoControl(MDA.fhDevice, PUT_CHAR, + &(buff[0]), sizeof( buff ), NULL, 0, NULL, NULL); + Result = true; + } + return Result; +} + +inline bool MonoDevice::PutChar( char value ) +{ + bool const Result = PutChar (MDA.fNextCol, MDA.fNextRow, value); + if (Result) + { + ++MDA.fNextCol; + if (MDA.fNextCol > WIDTH) + { + MDA.fNextCol = 0; + ++MDA.fNextRow; + if (MDA.fNextRow > HEIGHT) + { + MDA.fNextRow = 0; + } + } + } + return Result; +} + +inline int MonoDevice::PutString( char const * const string ) +{ + int const Result = PutString(MDA.fNextRow, MDA.fNextCol, string); + MDA.fNextCol += Result % WIDTH; + if (MDA.fNextCol > WIDTH) + { + MDA.fNextCol %= WIDTH; + ++MDA.fNextRow; + } + MDA.fNextRow += Result / WIDTH; + if (MDA.fNextRow > HEIGHT) + { + MDA.fNextRow %= HEIGHT; + } + return Result; +} + + +//#ifdef __BORLANDC__ +//#pragma option -a. +//#endif +//#ifdef _MSC_VER +//#pragma pack(pop) +//#endif + +#endif +#endif + \ No newline at end of file diff --git a/src/Uisrc/UI/OKCANCEL.CPP b/src/Uisrc/UI/OKCANCEL.CPP new file mode 100644 index 0000000..85e1a54 --- /dev/null +++ b/src/Uisrc/UI/OKCANCEL.CPP @@ -0,0 +1,377 @@ +//**************************************************************************** +// OkCancel.cpp +// Diablo UI ok/cancel dialog +// +// By Frank Pearce +// created 9.23.96 +//**************************************************************************** + +#include "pch.h" + +#include "uisnd.h" +//**************************************************************************** +//**************************************************************************** +#define TEXT_NO_FIT 0xff000000l // indicates that dialog was too small to accomodate text + + enum _sizes { + SIZE_NORMAL, + SIZE_BIG, + NUM_SIZES + }; + + typedef struct _dlg_desc { + char szTemplate[32]; + } DLG_DESC; + + static LPBYTE sgBgBmp = NULL; + static LPBYTE sgBtnBmp = NULL; + static LPCSTR sgTitle; + static int sgSize; + static BOOL sgErrorFlag; + static BOOL sgTestSize = FALSE; + + +//**************************************************************************** +//**************************************************************************** +static void OkCancelDestroy(HWND window) { + if (sgBgBmp) { + FREE(sgBgBmp); + sgBgBmp = NULL; + } + if (sgBtnBmp) { + FREE(sgBtnBmp); + sgBtnBmp = NULL; + } +} + + + +//**************************************************************************** +//**************************************************************************** +BOOL IsTextTooLarge(HWND hWnd, LPCSTR szText) { + HDC hDC; + RECT r, rSave; + + + // If there is no text, size is ok + if (!szText || !szText[0]) + return FALSE; + + if (!hWnd) return TRUE; + + GetClientRect(hWnd, &r); + r.right--; + r.bottom--; + rSave = r; + + hDC = GetDC(hWnd); + // Select the font for this window + HFONT hOldFont = (HFONT)SelectObject(hDC, (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0)); + if (hDC) { + DrawText(hDC, szText, strlen(szText), &r, DT_CALCRECT | DT_WORDBREAK); + + if (hOldFont) + SelectObject(hDC, hOldFont); + ReleaseDC(hWnd, hDC); + + + if (r.bottom > rSave.bottom || r.right > rSave.right) + return TRUE; + } + + return FALSE; +} +//**************************************************************************** +// OkCancelInit() +// +// if sgTestSize is set, this routine will verify whether the text fits +// in the allotted text controls. +// +// A return value of 0 indicates that the dialog is too small. +// A return value of 1 indicates success. +//**************************************************************************** +static BOOL OkCancelInit(HWND window, LPCSTR okcanceltext) { + SIZE btnsize; + int BtnIDs[] = { IDC_OK, IDCANCEL, 0 }; + LPCTSTR popupfile; + LPCTSTR spopup = TEXT("ui_art\\spopup.pcx"); + LPCTSTR lpopup = TEXT("ui_art\\lpopup.pcx"); + LPCTSTR srpopup = TEXT("ui_art\\srpopup.pcx"); + LPCTSTR lrpopup = TEXT("ui_art\\lrpopup.pcx"); + HWND child; + + if (sgSize == SIZE_NORMAL) { + if (sgErrorFlag) popupfile = srpopup; + else popupfile = spopup; + } + else { //(sgSize == SIZE_BIG) + if (sgErrorFlag) popupfile = lrpopup; + else popupfile = lpopup; + } + + if (SDrawGetFrameWindow() == GetParent(window)) { + PALETTEENTRY *pal; + + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + popupfile, + &sgBgBmp, + FALSE + ); + + // load just the part of the palette the dialog uses + pal = UiPaletteEntry(0); + SDrawUpdatePalette(0, 10, &pal[0]); // Windows colors also + SDrawUpdatePalette(0x70, 144, &pal[0x70], TRUE); + } + else { + LoadArtFile( + window, + GetParent(window), + TEXT("Popup"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + popupfile, + &sgBgBmp, + NULL + ); + } + + if (SDrawGetFrameWindow() == GetParent(window)) + UiAltFadeInit(window); + + UiLoadBmpFile( + TEXT("ui_art\\but_sml.pcx"), + &sgBtnBmp, + &btnsize + ); + UiSetButtonBitmaps(window, BtnIDs, sgBtnBmp, &btnsize); + + child = GetDlgItem(window, IDC_OKCANCEL_TEXT); + SetWindowText(child, okcanceltext); + + if (sgTestSize && IsTextTooLarge(child, okcanceltext)) + return 0; + + if (sgTitle != NULL) { + child = GetDlgItem(window, IDC_DLGTITLE); + + if (sgTestSize && IsTextTooLarge(child, sgTitle)) + return 0; + + if (child) + SetWindowText(child, sgTitle); + } + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static void OkCancelAbort(HWND window, int retval) { + UiSndPlayEnter(); + SDlgEndDialog(window, retval); +} + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK OkCancelDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_DESTROY: + ShowCursor(FALSE); + OkCancelDestroy(window); + if (SDrawGetFrameWindow() == GetParent(window)) + UiVidFadeOut(DEFAULT_STEPS*2); + break; + + case WM_INITDIALOG: + // Make sure cursor is visible + ShowCursor(TRUE); + if (!OkCancelInit(window, (LPCSTR)lparam)) + SDlgEndDialog(window, TEXT_NO_FIT); + return 1; + + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDOK: + switch (GetWindowLong(GetFocus(), GWL_ID)) { + case IDC_OK: + OkCancelAbort(window, IDOK); + break; + default: + OkCancelAbort(window, IDCANCEL); + break; + } + break; + case IDC_OK: + OkCancelAbort(window, IDOK); + break; + case IDCANCEL: + OkCancelAbort(window, IDCANCEL); + break; + } + break; + + case WM_CTLCOLORSTATIC: + if (GetWindowLong((HWND)lparam, GWL_ID) == IDC_DLGTITLE) { + UiSetTextYellow((HDC)wparam); + return (BOOL) GetStockObject(NULL_BRUSH); + } + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + + +//**************************************************************************** +//**************************************************************************** +int UiOkCancelDialog(HWND parent, LPCSTR okcanceltext, BOOL errorflag) { + + sgSize = SIZE_NORMAL; + sgTitle = NULL; + sgErrorFlag = errorflag; + sgTestSize = FALSE; + + return SDlgDialogBoxParam( + global_hinstance, + TEXT("OKCANCEL_DIALOG"), + parent, + OkCancelDialogProc, + (LPARAM)okcanceltext + ); +} + + +//**************************************************************************** +//**************************************************************************** +int UiOkDialog(HWND parent, LPCSTR oktext, BOOL errorflag) { + + sgSize = SIZE_NORMAL; + sgTitle = NULL; + sgErrorFlag = errorflag; + sgTestSize = FALSE; + + return SDlgDialogBoxParam( + global_hinstance, + TEXT("OK_DIALOG"), + parent, + OkCancelDialogProc, + (LPARAM)oktext + ); +} + + +//**************************************************************************** +//**************************************************************************** +int UiBigOkCancelDialog(HWND parent, LPCSTR oktext, LPCSTR title, BOOL errorflag) { + + sgSize = SIZE_BIG; + sgTitle = title; + sgErrorFlag = errorflag; + sgTestSize = FALSE; + + return SDlgDialogBoxParam( + global_hinstance, + TEXT("BIGOKCANCEL_DIALOG"), + parent, + OkCancelDialogProc, + (LPARAM)oktext + ); +} + + +//**************************************************************************** +//**************************************************************************** +int UiBigOkDialog(HWND parent, LPCSTR oktext, LPCSTR title, BOOL errorflag) { + + sgSize = SIZE_BIG; + sgTitle = title; + sgErrorFlag = errorflag; + sgTestSize = FALSE; + + return SDlgDialogBoxParam( + global_hinstance, + TEXT("BIGOK_DIALOG"), + parent, + OkCancelDialogProc, + (LPARAM)oktext + ); +} + +//**************************************************************************** +//*** +//*** EXPORTED FUNCTIONS +//*** +//**************************************************************************** + +static DLG_DESC sgOkDlgs[NUM_SIZES] = { + { TEXT("OK_DIALOG") }, + { TEXT("BIGOK_DIALOG") }, +}; + +static DLG_DESC sgOkCancelDlgs[NUM_SIZES] = { + { TEXT("OKCANCEL_DIALOG") }, + { TEXT("BIGOKCANCEL_DIALOG") }, +}; + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK UiMessageBoxCallback(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) { + DWORD dwReturn; + DLG_DESC *pDlgInfo; + + sgTitle = lpCaption; + + // choose between MB_OK and MB_OKCANCEL + if ((uType & MB_TYPEMASK) == MB_OK) + pDlgInfo = sgOkDlgs; + else + pDlgInfo = sgOkCancelDlgs; + + // Set dialog error flag + switch (uType & MB_ICONMASK) { + case MB_ICONWARNING: + case MB_ICONERROR: + sgErrorFlag = TRUE; + break; + + default: + sgErrorFlag = FALSE; + } + + + sgTestSize = TRUE; + for (sgSize=0; sgSize +#include +#include +#include "..\storm.h" +#include "diabloui.h" +#include "DiabEdit.h" +#include "local.h" +#include "Fade.h" +#include "Doom.h" +#include "Sbar.h" +#include "mike.h" +#include "frank.h" diff --git a/src/Uisrc/UI/POINTER.CUR b/src/Uisrc/UI/POINTER.CUR new file mode 100644 index 0000000..22b2dba Binary files /dev/null and b/src/Uisrc/UI/POINTER.CUR differ diff --git a/src/Uisrc/UI/PROGRESS.CPP b/src/Uisrc/UI/PROGRESS.CPP new file mode 100644 index 0000000..4f750d1 --- /dev/null +++ b/src/Uisrc/UI/PROGRESS.CPP @@ -0,0 +1,350 @@ +//**************************************************************************** +// Progress.cpp +// Diablo UI progress bar popup dialog +// +// By Frank Pearce +// created 9.26.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + #define PROGRESS_TIMER_ID 1 + #define MILLISEC_PER_SEC 1000 + #define CALLS_PER_SEC 20 + #define USER_DELAY (MILLISEC_PER_SEC / sgCallsPerSec) + #define DEFAULT_DELAY (MILLISEC_PER_SEC / CALLS_PER_SEC) + + #define FILL_X 0 + #define FILL_Y 0 + + static LPBYTE sgBgBmp = NULL; + static LPBYTE sgBtnBmp = NULL; + + // the progress bar background + static LPBYTE sgProgBgBmp = NULL; + static SIZE sgProgBgSize; + + // the fill image for the progress bar + static LPBYTE sgProgFillBmp = NULL; + static SIZE sgProgFillSize; + + // the current image based on percent complete + static LPBYTE sgProgBmp = NULL; + static SIZE sgProgSize; + + static BOOL sgAbortable; + static DWORD sgCallsPerSec; + static PROGRESSFCN sgProgressFcn; + static int sgnResult; + static BOOL sgbEndDialog; + + +//**************************************************************************** +//**************************************************************************** +static void ProgressDraw(HWND window, int percent) { + RECT rect; + HWND child = GetDlgItem(window, IDC_UIGENERIC_PROGRESS); + + // draw the bg + if (sgProgBgBmp) + SBltROP3( + sgProgBmp, + sgProgBgBmp, + sgProgSize.cx, + sgProgSize.cy, + sgProgSize.cx, + sgProgBgSize.cx, + NULL, + SRCCOPY + ); + + // draw the fill + if (sgProgFillBmp) + SBltROP3( + sgProgBmp + (FILL_Y * sgProgSize.cx) + FILL_X, + sgProgFillBmp, + ((sgProgSize.cx - (2 * FILL_X)) * percent) / 100, + sgProgSize.cy - (2 * FILL_Y), + sgProgSize.cx, + sgProgFillSize.cx, + NULL, + SRCCOPY + ); + + // invalidate the region + GetWindowRect(child, &rect); + ScreenToClient(window, (LPPOINT)&rect.left); + ScreenToClient(window, (LPPOINT)&rect.right); + InvalidateRect(window, &rect, FALSE); +} + + +//**************************************************************************** +//**************************************************************************** +static void ProgressDestroy(HWND window) { + if (sgBgBmp) { + FREE(sgBgBmp); + sgBgBmp = NULL; + } + if (sgBtnBmp) { + FREE(sgBtnBmp); + sgBtnBmp = NULL; + } + if (sgProgBgBmp) { + FREE(sgProgBgBmp); + sgProgBgBmp = NULL; + } + if (sgProgFillBmp) { + FREE(sgProgFillBmp); + sgProgFillBmp = NULL; + } + if (sgProgBmp) { + FREE(sgProgBmp); + sgProgBmp = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ProgressInit(HWND window, LPCSTR progresstext) { + PALETTEENTRY * pal; + HWND child; + RECT rect; + SIZE btnsize; + int BtnIDs[] = { IDCANCEL, 0 }; + + if (sgCallsPerSec) + SDlgSetTimer(window,PROGRESS_TIMER_ID,USER_DELAY,NULL); + else + SDlgSetTimer(window,PROGRESS_TIMER_ID,DEFAULT_DELAY,NULL); + + // load ctrl/dlg bmps + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\spopup.pcx"), + &sgBgBmp, + NULL, + FALSE + ); + + if (SDrawGetFrameWindow() == GetParent(window)) + UiAltFadeInit(window); + + + // load just the part of the palette the dialog uses + pal = UiPaletteEntry(0); + SDrawUpdatePalette(0, 10, &pal[0]); // Windows colors also + SDrawUpdatePalette(0x70, 144, &pal[0x70], TRUE); + + + UiLoadBmpFile( + TEXT("ui_art\\but_sml.pcx"), + &sgBtnBmp, + &btnsize + ); + if (sgBtnBmp) + UiSetButtonBitmaps(window, BtnIDs, sgBtnBmp, &btnsize); + + // load progress bar textures + UiLoadBmpFile( + TEXT("ui_art\\prog_bg.pcx"), + &sgProgBgBmp, + &sgProgBgSize + ); + UiLoadBmpFile( + TEXT("ui_art\\prog_fil.pcx"), + &sgProgFillBmp, + &sgProgFillSize + ); + + // alloc/create a bitmap for the progress indicator + child = GetDlgItem(window, IDC_UIGENERIC_PROGRESS); + GetClientRect(child, &rect); + + sgProgBmp = (LPBYTE) ALLOC(rect.right * rect.bottom); + if (!sgProgBmp) + return; + + sgProgSize.cx = rect.right; + sgProgSize.cy = rect.bottom; + + SDlgSetBitmap( + child, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + sgProgBmp, + NULL, + rect.right, + rect.bottom + ); + ProgressDraw(window, 0); + + // set the text describing what progress is being monitored + child = GetDlgItem(window, IDC_PROGRESS_TEXT); + SetWindowText(child, progresstext); + + // show/hide cancel button based on abortable flag + child = GetDlgItem(window, IDCANCEL); + ShowWindow(child, (sgAbortable ? SW_SHOWNORMAL : SW_HIDE)); + EnableWindow(child, sgAbortable); +} + + +//**************************************************************************** +//**************************************************************************** +static void ProgressEndDialog(HWND window, int nResult) { + sgnResult = IDCANCEL; + sgbEndDialog = TRUE; +} + +//**************************************************************************** +//**************************************************************************** +static void ProgressAbort(HWND window) { + SDlgKillTimer(window, PROGRESS_TIMER_ID); + if (SDrawGetFrameWindow() == GetParent(window)) + UiVidFadeOut(DEFAULT_STEPS*2); + ProgressEndDialog(window, 0); + sgnResult = 0; +} + + +//**************************************************************************** +//**************************************************************************** +static void ProgressTimer(HWND window) { + int percent; + + percent = sgProgressFcn(); + + if (percent >= 100) { + ProgressAbort(window); + } + else { + ProgressDraw(window, percent); + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK ProgressDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (LOWORD(wparam) == IDCANCEL) { + SDlgKillTimer(window, PROGRESS_TIMER_ID); + + if (SDrawGetFrameWindow() == GetParent(window)) + UiVidFadeOut(DEFAULT_STEPS*2); + ProgressEndDialog(window, IDCANCEL); + } + break; + + case WM_DESTROY: + ShowCursor(FALSE); + ProgressDestroy(window); + break; + + case WM_INITDIALOG: + ProgressInit(window, (LPCSTR)lparam); + + // Choose our cursors + UiSetWindowsCursors(SDrawGetFrameWindow()); + UiSetWindowsCursors(window); + ShowCursor(TRUE); + return 1; + + case WM_TIMER: + ProgressTimer(window); + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +static void ProcessMessages(HWND hWnd) { + while (IsWindow(hWnd) && !sgbEndDialog) { + MSG message; + if (PeekMessage(&message,(HWND)0,0,0,PM_REMOVE)) { + if (message.message == WM_QUIT) + PostQuitMessage(message.wParam); + else if (!IsDialogMessage(hWnd,&message)) { + TranslateMessage(&message); + DispatchMessage(&message); + } + } + else { + SDlgCheckTimers(); + SDlgUpdateCursor(); + } + } + + // Get rid of the window if it is killing itself + if (sgbEndDialog) { + DestroyWindow(hWnd); + sgbEndDialog = FALSE; + } +} + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiProgressDialog(HWND parent, + LPCSTR progresstext, + BOOL abortable, + PROGRESSFCN progressfcn, + DWORD callspersec +) { + + sgProgressFcn = progressfcn; + sgAbortable = abortable; + sgCallsPerSec = callspersec; + sgnResult = -1; + sgbEndDialog = FALSE; + + HWND hWndProgress = SDlgCreateDialogParam( + global_hinstance, + TEXT("PROGRESS_DIALOG"), + parent, + ProgressDialogProc, + (LPARAM) progresstext + ); + + if (!hWndProgress) + return FALSE; + + // Now process messages until dialog exits + // (that way we'll behave modal to the outside world of Diablo.exe) + ProcessMessages(hWndProgress); + + if (sgnResult == IDCANCEL || sgnResult == -1) + return FALSE; + + return TRUE; +} diff --git a/src/Uisrc/UI/RELEASE/ARTFONT.SBR b/src/Uisrc/UI/RELEASE/ARTFONT.SBR new file mode 100644 index 0000000..f243a2b Binary files /dev/null and b/src/Uisrc/UI/RELEASE/ARTFONT.SBR differ diff --git a/src/Uisrc/UI/RELEASE/CONNECT.SBR b/src/Uisrc/UI/RELEASE/CONNECT.SBR new file mode 100644 index 0000000..477e337 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/CONNECT.SBR differ diff --git a/src/Uisrc/UI/RELEASE/COPYPROT.SBR b/src/Uisrc/UI/RELEASE/COPYPROT.SBR new file mode 100644 index 0000000..43ce280 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/COPYPROT.SBR differ diff --git a/src/Uisrc/UI/RELEASE/CR8GAME.SBR b/src/Uisrc/UI/RELEASE/CR8GAME.SBR new file mode 100644 index 0000000..7fb431a Binary files /dev/null and b/src/Uisrc/UI/RELEASE/CR8GAME.SBR differ diff --git a/src/Uisrc/UI/RELEASE/CREADUNG.SBR b/src/Uisrc/UI/RELEASE/CREADUNG.SBR new file mode 100644 index 0000000..bbade8f Binary files /dev/null and b/src/Uisrc/UI/RELEASE/CREADUNG.SBR differ diff --git a/src/Uisrc/UI/RELEASE/CREAHERO.SBR b/src/Uisrc/UI/RELEASE/CREAHERO.SBR new file mode 100644 index 0000000..b122148 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/CREAHERO.SBR differ diff --git a/src/Uisrc/UI/RELEASE/CREDITS.SBR b/src/Uisrc/UI/RELEASE/CREDITS.SBR new file mode 100644 index 0000000..1b8f7b8 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/CREDITS.SBR differ diff --git a/src/Uisrc/UI/RELEASE/DIABEDIT.SBR b/src/Uisrc/UI/RELEASE/DIABEDIT.SBR new file mode 100644 index 0000000..08c7ffe Binary files /dev/null and b/src/Uisrc/UI/RELEASE/DIABEDIT.SBR differ diff --git a/src/Uisrc/UI/RELEASE/DIABLOUI.RES b/src/Uisrc/UI/RELEASE/DIABLOUI.RES new file mode 100644 index 0000000..695ec39 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/DIABLOUI.RES differ diff --git a/src/Uisrc/UI/RELEASE/DIABLOUI.SBR b/src/Uisrc/UI/RELEASE/DIABLOUI.SBR new file mode 100644 index 0000000..f535918 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/DIABLOUI.SBR differ diff --git a/src/Uisrc/UI/RELEASE/DIRLINK.SBR b/src/Uisrc/UI/RELEASE/DIRLINK.SBR new file mode 100644 index 0000000..83a6982 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/DIRLINK.SBR differ diff --git a/src/Uisrc/UI/RELEASE/DISCLAIM.SBR b/src/Uisrc/UI/RELEASE/DISCLAIM.SBR new file mode 100644 index 0000000..9cbb2f3 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/DISCLAIM.SBR differ diff --git a/src/Uisrc/UI/RELEASE/DOOM.SBR b/src/Uisrc/UI/RELEASE/DOOM.SBR new file mode 100644 index 0000000..399af6f Binary files /dev/null and b/src/Uisrc/UI/RELEASE/DOOM.SBR differ diff --git a/src/Uisrc/UI/RELEASE/ENTRDIAL.SBR b/src/Uisrc/UI/RELEASE/ENTRDIAL.SBR new file mode 100644 index 0000000..4197200 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/ENTRDIAL.SBR differ diff --git a/src/Uisrc/UI/RELEASE/ENTRNAME.SBR b/src/Uisrc/UI/RELEASE/ENTRNAME.SBR new file mode 100644 index 0000000..0ec9e47 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/ENTRNAME.SBR differ diff --git a/src/Uisrc/UI/RELEASE/FADE.SBR b/src/Uisrc/UI/RELEASE/FADE.SBR new file mode 100644 index 0000000..5cc399b Binary files /dev/null and b/src/Uisrc/UI/RELEASE/FADE.SBR differ diff --git a/src/Uisrc/UI/RELEASE/FOCUS.SBR b/src/Uisrc/UI/RELEASE/FOCUS.SBR new file mode 100644 index 0000000..417bf9d Binary files /dev/null and b/src/Uisrc/UI/RELEASE/FOCUS.SBR differ diff --git a/src/Uisrc/UI/RELEASE/HELLFRUI.EXP b/src/Uisrc/UI/RELEASE/HELLFRUI.EXP new file mode 100644 index 0000000..91f0f54 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/HELLFRUI.EXP differ diff --git a/src/Uisrc/UI/RELEASE/HELLFRUI.LIB b/src/Uisrc/UI/RELEASE/HELLFRUI.LIB new file mode 100644 index 0000000..c09e62f Binary files /dev/null and b/src/Uisrc/UI/RELEASE/HELLFRUI.LIB differ diff --git a/src/Uisrc/UI/RELEASE/LOCAL.SBR b/src/Uisrc/UI/RELEASE/LOCAL.SBR new file mode 100644 index 0000000..025fc96 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/LOCAL.SBR differ diff --git a/src/Uisrc/UI/RELEASE/LOGON.SBR b/src/Uisrc/UI/RELEASE/LOGON.SBR new file mode 100644 index 0000000..8618f7a Binary files /dev/null and b/src/Uisrc/UI/RELEASE/LOGON.SBR differ diff --git a/src/Uisrc/UI/RELEASE/MAINMENU.SBR b/src/Uisrc/UI/RELEASE/MAINMENU.SBR new file mode 100644 index 0000000..0e69a92 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/MAINMENU.SBR differ diff --git a/src/Uisrc/UI/RELEASE/MODEM.SBR b/src/Uisrc/UI/RELEASE/MODEM.SBR new file mode 100644 index 0000000..667ec35 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/MODEM.SBR differ diff --git a/src/Uisrc/UI/RELEASE/MODMSTAT.SBR b/src/Uisrc/UI/RELEASE/MODMSTAT.SBR new file mode 100644 index 0000000..2eb1926 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/MODMSTAT.SBR differ diff --git a/src/Uisrc/UI/RELEASE/OKCANCEL.SBR b/src/Uisrc/UI/RELEASE/OKCANCEL.SBR new file mode 100644 index 0000000..659a58d Binary files /dev/null and b/src/Uisrc/UI/RELEASE/OKCANCEL.SBR differ diff --git a/src/Uisrc/UI/RELEASE/PROGRESS.SBR b/src/Uisrc/UI/RELEASE/PROGRESS.SBR new file mode 100644 index 0000000..3e92c2a Binary files /dev/null and b/src/Uisrc/UI/RELEASE/PROGRESS.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SBAR.SBR b/src/Uisrc/UI/RELEASE/SBAR.SBR new file mode 100644 index 0000000..6d5dd56 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SBAR.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELCLASS.SBR b/src/Uisrc/UI/RELEASE/SELCLASS.SBR new file mode 100644 index 0000000..26e5cde Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELCLASS.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELCONN.SBR b/src/Uisrc/UI/RELEASE/SELCONN.SBR new file mode 100644 index 0000000..879a595 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELCONN.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELDIAL.SBR b/src/Uisrc/UI/RELEASE/SELDIAL.SBR new file mode 100644 index 0000000..944db17 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELDIAL.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELGAME.SBR b/src/Uisrc/UI/RELEASE/SELGAME.SBR new file mode 100644 index 0000000..1a833b0 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELGAME.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELHERO.SBR b/src/Uisrc/UI/RELEASE/SELHERO.SBR new file mode 100644 index 0000000..9e4c87e Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELHERO.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELIPX.SBR b/src/Uisrc/UI/RELEASE/SELIPX.SBR new file mode 100644 index 0000000..92430a5 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELIPX.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELLIST.SBR b/src/Uisrc/UI/RELEASE/SELLIST.SBR new file mode 100644 index 0000000..e53eb6c Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELLIST.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELLOAD.SBR b/src/Uisrc/UI/RELEASE/SELLOAD.SBR new file mode 100644 index 0000000..147ff20 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELLOAD.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELMODEM.SBR b/src/Uisrc/UI/RELEASE/SELMODEM.SBR new file mode 100644 index 0000000..f51affd Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELMODEM.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SELYESNO.SBR b/src/Uisrc/UI/RELEASE/SELYESNO.SBR new file mode 100644 index 0000000..45d462f Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SELYESNO.SBR differ diff --git a/src/Uisrc/UI/RELEASE/SUPPORT.SBR b/src/Uisrc/UI/RELEASE/SUPPORT.SBR new file mode 100644 index 0000000..eb1ac4f Binary files /dev/null and b/src/Uisrc/UI/RELEASE/SUPPORT.SBR differ diff --git a/src/Uisrc/UI/RELEASE/TITLE.SBR b/src/Uisrc/UI/RELEASE/TITLE.SBR new file mode 100644 index 0000000..7e3d29b Binary files /dev/null and b/src/Uisrc/UI/RELEASE/TITLE.SBR differ diff --git a/src/Uisrc/UI/RELEASE/UI.PCH b/src/Uisrc/UI/RELEASE/UI.PCH new file mode 100644 index 0000000..d6e227f Binary files /dev/null and b/src/Uisrc/UI/RELEASE/UI.PCH differ diff --git a/src/Uisrc/UI/RELEASE/UISND.SBR b/src/Uisrc/UI/RELEASE/UISND.SBR new file mode 100644 index 0000000..2158f9b Binary files /dev/null and b/src/Uisrc/UI/RELEASE/UISND.SBR differ diff --git a/src/Uisrc/UI/RELEASE/VC50.IDB b/src/Uisrc/UI/RELEASE/VC50.IDB new file mode 100644 index 0000000..2437438 Binary files /dev/null and b/src/Uisrc/UI/RELEASE/VC50.IDB differ diff --git a/src/Uisrc/UI/SAMPLE.CPP b/src/Uisrc/UI/SAMPLE.CPP new file mode 100644 index 0000000..9360315 --- /dev/null +++ b/src/Uisrc/UI/SAMPLE.CPP @@ -0,0 +1,109 @@ +/**************************************************************************** +* +* SAMPLE.CPP +* Diablo UI sample dialog +* +* By Michael O'Brien (9/12/96) +* +***/ + +#include "pch.h" + +static SIZE bgsize; +static LPBYTE backgroundbitmap = NULL; +static LPBYTE buttonbitmap = NULL; + +//=========================================================================== +static void DestroyArtwork (HWND window) { + if (buttonbitmap) { + FREE(buttonbitmap); + buttonbitmap = NULL; + } + if (backgroundbitmap) { + FREE(backgroundbitmap); + backgroundbitmap = NULL; + } +} + +//=========================================================================== +static BOOL LoadArtwork (HWND window) { + SIZE artsize; + + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\samp_bkg.pcx"), + &backgroundbitmap, + &bgsize + ); + + LoadArtFile( + NULL, + window, + TEXT("Button"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\samp_btn.pcx"), + &buttonbitmap, + &artsize + ); + + return 1; +} + +//=========================================================================== +static BOOL CALLBACK SampleDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + + case IDOK: + SDlgEndDialog(window,1); + break; + + case IDCANCEL: + SDlgEndDialog(window,0); + break; + + } + break; + + case WM_DESTROY: + DestroyArtwork(window); + break; + + case WM_INITDIALOG: + LoadArtwork(window); + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + +//=========================================================================== +BOOL APIENTRY UiSampleDialog (DWORD *selection) { + if (!selection) + return 0; + *selection = 0; + + // DISPLAY THE DIALOG BOX + *selection = (DWORD)SDlgDialogBox(global_hinstance, + TEXT("SAMPLE_DIALOG"), + SDrawGetFrameWindow(), + SampleDialogProc); + + return 1; +} diff --git a/src/Uisrc/UI/SBAR.CPP b/src/Uisrc/UI/SBAR.CPP new file mode 100644 index 0000000..274a5c7 --- /dev/null +++ b/src/Uisrc/UI/SBAR.CPP @@ -0,0 +1,280 @@ +//**************************************************************************** +// Sbar.cpp +// Diablo UI scroll bar to accompany "Doom style" lists +// +// By Frank Pearce +// created 11.11.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + #define SBAR_ENABLED 1 // 1 when they work correctly + + #define ARROW_HGT 22 + #define ARROW_FRAMES 2 // 2 up frames and 2 down frames + + #define THUMB_X 3 + #define THUMB_Y ARROW_HGT + #define THUMB_WDT 18 + #define THUMB_RANGE(x) (x->ctrlsize.cy - x->thumbsize.cy - (2*ARROW_HGT)) + + #define FSB_UP 0x00000001 + #define FSB_PGUP 0x00000002 + #define FSB_DN 0x00000004 + #define FSB_PGDN 0x00000008 + #define FSB_THMB 0x00000010 + + +//**************************************************************************** +//**************************************************************************** +typedef struct _sbardata { + LONG flags; + + LPBYTE ctrldata; // the composed image of the scrollbar + SIZE ctrlsize; + + LPBYTE bgdata; // the scrollbar bg art + SIZE bgsize; + + LPBYTE thumbdata; // the art for the thumb + SIZE thumbsize; + + LPBYTE arrowdata; // the art for the arrows + SIZE arrowsize; + + int max; // max entries int the list + int current; // currently selected entry (0 based) + +} TSBAR, * TPSBAR; + + +//**************************************************************************** +//**************************************************************************** +BOOL SbarUpClick(HWND sbar) { + TPSBAR tpSbar = (TPSBAR) GetWindowLong(sbar, GWL_USERDATA); + if (! tpSbar) return FALSE; + if (tpSbar->flags) { + tpSbar->flags = 0; + return TRUE; + } + return FALSE; +} + + +//**************************************************************************** +//**************************************************************************** +int SbarInterpretClick(HWND sbar, int x, int y) { +#if SBAR_ENABLED + int thumbtop, thumbbot; + POINT pt = { x, y}; + + // confirm sbar exists + if (! sbar) return DSB_NONE; + if (! IsWindowVisible(sbar)) return DSB_NONE; + + // get a pointer to the sbar data + TPSBAR tpSbar = (TPSBAR) GetWindowLong(sbar, GWL_USERDATA); + if (! tpSbar) return DSB_NONE; + + // calculate the thumb top and bottom + if (tpSbar->max > 1) + thumbtop = THUMB_Y + (THUMB_RANGE(tpSbar) * tpSbar->current) / (tpSbar->max - 1); + else + thumbtop = THUMB_Y; + thumbbot = thumbtop + tpSbar->thumbsize.cy; + + // convert mouse coords to sbar coords + ScreenToClient(sbar, &pt); + + // determine location of click + if (pt.y < ARROW_HGT) { + tpSbar->flags = FSB_UP; + return DSB_UP; + } + if (pt.y < thumbtop) { + tpSbar->flags = FSB_PGUP; + return DSB_PAGEUP; + } + if (pt.y < thumbbot) { + tpSbar->flags = FSB_THMB; + return DSB_THUMB; + } + if (pt.y < (tpSbar->ctrlsize.cy - ARROW_HGT)) { + tpSbar->flags = FSB_PGDN; + return DSB_PAGEDOWN; + } + tpSbar->flags = FSB_DN; + return DSB_DOWN; +#else + return DSB_NONE; +#endif +} + + +//**************************************************************************** +//**************************************************************************** +void SbarDraw(HWND parent, int SbarID, int Entries, int Current) { +#if SBAR_ENABLED + int yoff, arrowframe; + HWND sbar = GetDlgItem(parent, SbarID); + if (! sbar) return; + TPSBAR tpSbar = (TPSBAR) GetWindowLong(sbar, GWL_USERDATA); + if (! tpSbar) return; + if (! tpSbar->ctrldata) return; + + // save Entries and Current + tpSbar->max = Entries; + tpSbar->current = Current; + + // draw the sbar bg + if (! tpSbar->bgdata) return; + RECT dstrect, srcrect; + dstrect.left = srcrect.left = 0; + dstrect.top = srcrect.top = 0; + dstrect.right = tpSbar->ctrlsize.cx - 1; + dstrect.bottom = tpSbar->ctrlsize.cy - 1; + srcrect.right = tpSbar->ctrlsize.cx - 1; + srcrect.bottom = tpSbar->bgsize.cy - 1; + SBltROP3Tiled( + tpSbar->ctrldata, // dest ptr + &dstrect, // dest rect ptr + tpSbar->ctrlsize.cx, // dest cx + tpSbar->bgdata, // src ptr + &srcrect, // src rect + tpSbar->bgsize.cx, // src cx + 0, // src xoff + 0, // src yoff + NULL, // pattern, + SRCCOPY // copy cmd + ); + + // draw the thumb + if (! tpSbar->thumbdata) return; + if (Entries > 1) + yoff = THUMB_Y + (THUMB_RANGE(tpSbar) * Current) / (Entries - 1); + else + yoff = THUMB_Y; + SBltROP3 ( + tpSbar->ctrldata + (yoff * tpSbar->ctrlsize.cx) + THUMB_X, // dest ptr + tpSbar->thumbdata, // src ptr + THUMB_WDT, // blt wdth + tpSbar->thumbsize.cy, // blt hgt + tpSbar->ctrlsize.cx, // dest cx + tpSbar->thumbsize.cx, // src cx + NULL, // pattern + SRCCOPY // copy cmd + ); + + // draw the up arrow + if (tpSbar->flags & FSB_UP) + arrowframe = 0; + else + arrowframe = 1; + SBltROP3 ( + tpSbar->ctrldata, // dest ptr + tpSbar->arrowdata + (arrowframe * ARROW_HGT * tpSbar->arrowsize.cx), // src ptr + tpSbar->ctrlsize.cx, // blt wdth + ARROW_HGT, // blt hgt + tpSbar->ctrlsize.cx, // dest cx + tpSbar->arrowsize.cx, // src cx + NULL, // pattern + SRCCOPY // copy cmd + ); + + // draw the down arrow + if (tpSbar->flags & FSB_DN) + arrowframe = 2; + else + arrowframe = 3; + SBltROP3 ( + tpSbar->ctrldata + ((tpSbar->ctrlsize.cy - ARROW_HGT) * tpSbar->ctrlsize.cx), // dest ptr + tpSbar->arrowdata + (arrowframe * ARROW_HGT * tpSbar->arrowsize.cx), // src ptr + tpSbar->ctrlsize.cx, // blt wdth + ARROW_HGT, // blt hgt + tpSbar->ctrlsize.cx, // dest cx + tpSbar->arrowsize.cx, // src cx + NULL, // pattern + SRCCOPY // copy cmd + ); + + + InvalidateRect(sbar, NULL, FALSE); +#endif +} + + +//**************************************************************************** +//**************************************************************************** +void SbarInit(HWND parent, int SbarID) { +#if SBAR_ENABLED + TPSBAR tpSbar; + RECT rect; + + HWND sbar = GetDlgItem(parent, SbarID); + if (! sbar) return; + + // alloc a structure to contain all the sbar's data + tpSbar = (TPSBAR) ALLOC(sizeof(TSBAR)); + if (! tpSbar) return; + SetWindowLong(sbar, GWL_USERDATA, (LONG) tpSbar); + + tpSbar->flags = 0; + // set up a bmp for the ctrl + GetClientRect(sbar, &rect); + tpSbar->ctrlsize.cx = rect.right; + tpSbar->ctrlsize.cy = rect.bottom; + tpSbar->ctrldata = (LPBYTE) ALLOC(rect.right * rect.bottom); + if (! tpSbar->ctrldata) return; + SDlgSetBitmap( + sbar, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + tpSbar->ctrldata, + NULL, + tpSbar->ctrlsize.cx, + tpSbar->ctrlsize.cy + ); + + // load some image data for the scroll bar + UiLoadBmpFile("ui_art\\sb_bg.pcx", &tpSbar->bgdata, &tpSbar->bgsize); + UiLoadBmpFile("ui_art\\sb_thumb.pcx", &tpSbar->thumbdata, &tpSbar->thumbsize); + UiLoadBmpFile("ui_art\\sb_arrow.pcx", &tpSbar->arrowdata, &tpSbar->arrowsize); +#else + HWND sbar = GetDlgItem(parent, SbarID); + if (! sbar) return; + ShowWindow(sbar, SW_HIDE); +#endif +} + + +//**************************************************************************** +//**************************************************************************** +void SbarDestroy(HWND parent, int SbarID) { +#if SBAR_ENABLED + HWND sbar = GetDlgItem(parent, SbarID); + if (! sbar) return; + + TPSBAR tpSbar = (TPSBAR) GetWindowLong(sbar, GWL_USERDATA); + if (! tpSbar) return; + + if (tpSbar->ctrldata) + FREE(tpSbar->ctrldata); + if (tpSbar->bgdata) + FREE(tpSbar->bgdata); + if (tpSbar->thumbdata) + FREE(tpSbar->thumbdata); + if (tpSbar->arrowdata) + FREE(tpSbar->arrowdata); + + FREE(tpSbar); + SetWindowLong(sbar, GWL_USERDATA, (LONG) NULL); +#endif +} + + diff --git a/src/Uisrc/UI/SBAR.H b/src/Uisrc/UI/SBAR.H new file mode 100644 index 0000000..cf18fc7 --- /dev/null +++ b/src/Uisrc/UI/SBAR.H @@ -0,0 +1,30 @@ +//**************************************************************************** +// Sbar.h +// Diablo UI scroll bar to accompany "Doom style" lists +// +// By Frank Pearce +// created 11.11.96 +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +enum _clickloc { // defines click locations in the scroll bar + DSB_NONE, + DSB_UP, + DSB_DOWN, + DSB_PAGEUP, + DSB_PAGEDOWN, + DSB_THUMB +}; + + +//**************************************************************************** +//**************************************************************************** +void SbarInit(HWND parent, int SbarID); +void SbarDestroy(HWND parent, int SbarID); + +void SbarDraw(HWND parent, int SbarID, int Entries, int Current); + +BOOL SbarUpClick(HWND sbar); +int SbarInterpretClick(HWND sbar, int x, int y); diff --git a/src/Uisrc/UI/SELCLASS.CPP b/src/Uisrc/UI/SELCLASS.CPP new file mode 100644 index 0000000..c004f88 --- /dev/null +++ b/src/Uisrc/UI/SELCLASS.CPP @@ -0,0 +1,236 @@ +//**************************************************************************** +// SelClass.cpp +// Diablo UI select class for a new hero +// +// By Frank Pearce +// created 10.18.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern void SelHeroGetDefStats(int heroclass, TPUIDEFSTATS stats); + extern void SelHeroSetStats(HWND window, TPUIHEROINFO hero); + extern void SelHeroClearStats(HWND window); + extern void SelHeroSetTitle(HWND window, LPCTSTR title); + extern int SelHeroGetMode(void); + + extern int SpawnErrDialog(HWND parent, int errstrid, BOOL onmainmenu); + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgListIDs[] = { + IDC_WARRIORBTN, + IDC_ROGUEBTN, + IDC_SORCERERBTN, + IDC_MONKBTN, + IDC_BARDBTN, + IDC_BARBARIANBTN, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** +static void SelClassDestroy(HWND window) { + FocusAnimateDestroy(); + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + SelHeroSetTitle(GetParent(window), NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelClassInit(HWND window) { + TCHAR buf[32]; + HWND parent = GetParent(window); + + // set the title for the parent + if (SelHeroGetMode() == MULTIPLAYER) + LoadString(global_hinstance, IDS_NEWMULTHERO, buf, 32-1); + else + LoadString(global_hinstance, IDS_NEWSINGHERO, buf, 32-1); + SelHeroSetTitle(parent, buf); + + // point this window at the same bmp it's parent uses + SetWindowLong( + window, + GWL_USERDATA, + GetWindowLong(parent, GWL_USERDATA) + ); + + UiOnPaintBtns(window, sgListIDs); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_MED); + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus16.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void UpdateStats(HWND window, int childid) { + TUIHEROINFO focused; + TUIDEFSTATS defstats; + + + // MM: make sure we init name field to zero since SelHeroSetStats() will + // be using it. + ZeroMemory((LPBYTE)&focused, sizeof(focused)); + + focused.level = 1; + switch (childid) + { + case IDC_WARRIORBTN: + focused.heroclass = UI_WARRIOR; + break; + case IDC_ROGUEBTN: + focused.heroclass = UI_ROGUE; + break; + case IDC_SORCERERBTN: + focused.heroclass = UI_SORCERER; + break; + case IDC_MONKBTN: + focused.heroclass = UI_MONK; + break; + case IDC_BARDBTN: + focused.heroclass = UI_BARD; + break; + case IDC_BARBARIANBTN: + focused.heroclass = UI_BARBARIAN; + break; + } + SelHeroGetDefStats(focused.heroclass, &defstats); + + focused.strength = defstats.strength; + focused.magic = defstats.magic; + focused.dexterity = defstats.dexterity; + focused.vitality = defstats.vitality; + + SelHeroSetStats(GetParent(window), &focused); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelClassAbort(HWND window, int ReturnVal) { + if (UiIsSpawned() && (ReturnVal == IDOK)) { + if (IDC_WARRIORBTN != GetWindowLong(GetFocus(), GWL_ID)) { + SpawnErrDialog(window, IDS_SPAWNCLASS_ERR, FALSE); + return; + } + } + + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + + if (ReturnVal == IDOK) { + // return the id of the focused button + ReturnVal = GetWindowLong(GetFocus(), GWL_ID); + } + + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK SelClassDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + UpdateStats(window, LOWORD(wparam)); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + SelClassAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDOK) { + SelClassAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDCANCEL) { + SelClassAbort(window, IDCANCEL); + } + break; + + case WM_LBUTTONDOWN: + if ( + UiIsPtInWindow( + window, + GetDlgItem(window, IDC_FAKEOK), + LOWORD(lparam), + HIWORD(lparam) + ) + ) { + SelClassAbort(window, IDOK); + } + else if ( + UiIsPtInWindow( + window, + GetDlgItem(window, IDC_FAKECANCEL), + LOWORD(lparam), + HIWORD(lparam) + ) + ) { + SelClassAbort(window, IDCANCEL); + } + break; + + case WM_DESTROY: + SelClassDestroy(window); + break; + + case WM_INITDIALOG: + SelClassInit(window); + return 0; + + case WM_TIMER: + FocusAnimate(window, GetFocus()); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} diff --git a/src/Uisrc/UI/SELCONN.CPP b/src/Uisrc/UI/SELCONN.CPP new file mode 100644 index 0000000..e30b5bf --- /dev/null +++ b/src/Uisrc/UI/SELCONN.CPP @@ -0,0 +1,902 @@ +//**************************************************************************** +// SelConn.cpp +// Diablo UI select connection method (in "doom-style" menu format) +// +// By Frank Pearce +// created 10.22.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +#define SB_ALWAYS_ON 0 // 0 in final + + +//**************************************************************************** +//**************************************************************************** + extern void TitleLogoDestroy(void); + extern void TitleLogoInit(HWND window); + extern void TitleFramesInit(HWND window, LPCTSTR filename); + extern void TitleLogoAnimate(HWND window); + + extern int SelOkDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus); + + extern BOOL UiSelectDevice( + DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata + ); + + extern void UiSetProviderID(DWORD id); + extern void UiSetBasicInterface(BOOL basic); + extern DWORD UiGetProviderID(); + +//**************************************************************************** +//**************************************************************************** + #define OLDPROCPROP TEXT("UIOLDPROC") + + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define LOGO_TIMER_ID 2 + #define LOGO_FPS 17 + #define LOGO_TIMER_DELAY 55 + + #define MAX_VISIBLE (IDC_CONNECTBTN6 - IDC_CONNECTBTN1 + 1) + + #define DESCRIPTION_LEN SNETSPI_MAXSTRINGLENGTH + #define REQUIREMENTS_LEN SNETSPI_MAXSTRINGLENGTH + + typedef struct _provider TPROVIDERINFO; + typedef TPROVIDERINFO *TPPROVIDERINFO; + struct _provider { + TPPROVIDERINFO next; + BOOL isbasicinterface; + DWORD id; // provider id + DWORD players; // players supported + TCHAR description[DESCRIPTION_LEN]; // provider name + TCHAR requirements[REQUIREMENTS_LEN]; // provider info + }; + + +//**************************************************************************** +//**************************************************************************** + static int sgBigTextIDs[] = { + IDC_DLGTITLE, + IDC_DLGTITLE2, + 0 + }; + static int sgSmallTextIDs[] = { + IDC_CONNECTTEXT, + IDC_PLAYERSTEXT, + 0 + }; + static int sgLblTextIDs[] = { + IDC_REQTITLE, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgListIDs[] = { + IDC_CONNECTBTN1, + IDC_CONNECTBTN2, + IDC_CONNECTBTN3, + IDC_CONNECTBTN4, + IDC_CONNECTBTN5, + IDC_CONNECTBTN6, + 0 + }; + + static TPPROVIDERINFO sgProviderList; + static int sgProvListLen; + + static SNETCAPSPTR sgmincaps; + static SNETPROGRAMDATAPTR sgprogramdata; + static SNETPLAYERDATAPTR sgplayerdata; + static SNETUIDATAPTR sginterfacedata; + static SNETVERSIONDATAPTR sgversiondata; + + static BOOL sgRequireUpgrade; + + +//**************************************************************************** +//**************************************************************************** +TPPROVIDERINFO SelConnAllocNode(void) { + return (TPPROVIDERINFO) ALLOC(sizeof(TPROVIDERINFO)); +} +//**************************************************************************** +//**************************************************************************** +static void SelConnFreeNode(TPPROVIDERINFO node) { + if (node) { + FREE(node); + } +} +//**************************************************************************** +//**************************************************************************** +static void SelConnFreeList(TPPROVIDERINFO list) { + TPPROVIDERINFO next; + + while (list) { + next = list->next; + SelConnFreeNode(list); + list = next; + } +} +//**************************************************************************** +//**************************************************************************** +TPPROVIDERINFO SelConnAddNode(TPPROVIDERINFO list, TPPROVIDERINFO node) { + node->next = list; + return node; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelConnEnum(DWORD id, + LPCSTR description, + LPCSTR requirements, + SNETCAPSPTR caps) { + TPPROVIDERINFO newprovider = SelConnAllocNode(); + if (! newprovider) return 0; + newprovider->next = NULL; + newprovider->isbasicinterface = caps->flags & SNET_CAPS_BASICINTERFACE; + newprovider->id = id; + newprovider->players = caps->maxplayers; + strcpy(newprovider->description, description); + strcpy(newprovider->requirements, requirements); + sgProviderList = SelConnAddNode(sgProviderList, newprovider); + sgProvListLen++; + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnSetInfo(HWND window, int childid) { + TCHAR format[64]; + TCHAR supported[72]; + TPPROVIDERINFO tpProvider; + HWND child; + TPBMP tpBmp; + + child = GetDlgItem(window, childid); + if (! child) return; + + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + + tpProvider = (TPPROVIDERINFO) tpBmp->userdata; + if (! tpProvider) return; + + child = GetDlgItem(window, IDC_CONNECTTEXT); + if (! child) return; + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), tpProvider->requirements); + + child = GetDlgItem(window, IDC_PLAYERSTEXT); + if (! child) return; + LoadString(global_hinstance, IDS_PLAYERSSUPPORTED, format, 63); + if (sgprogramdata) + wsprintf(supported, format, min(sgprogramdata->maxplayers, tpProvider->players)); + else + wsprintf(supported, format, tpProvider->players); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), supported); + + UiDoomStaticReset(window, sgSmallTextIDs, AF_SMALLGRAY); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnSetProviders(HWND window, TPPROVIDERINFO provider) { + HWND child; + TPBMP tpBmp; + int * ctrlid = sgListIDs; + + for (; *ctrlid; ctrlid++) { + child = GetDlgItem(window, *ctrlid); + if (! child) continue; + if (! provider) { + EnableWindow(child, FALSE); + continue; + } + + EnableWindow(child, TRUE); + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) continue; + + tpBmp->userdata = (LONG) provider; + UiSetBmpText(tpBmp, provider->description); + + provider = provider->next; + } + + UiDoomButtonsReset(window, sgListIDs, AF_SMALL); +} + + +//**************************************************************************** +//**************************************************************************** +static int SelConnGetFocusNum(void) { + HWND btn = GetFocus(); + if (! btn) return 0; + TPBMP tpBmp = (TPBMP) GetWindowLong(btn, GWL_USERDATA); + if (! tpBmp) return 0; + TPPROVIDERINFO list = sgProviderList; + if (! list) return 0; + TPPROVIDERINFO node = (TPPROVIDERINFO) tpBmp->userdata; + if (! node) return 0; + + int nodenum = 0; + + while (list && (list != node)) { + nodenum++; + list = list->next; + } + + return nodenum; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnUpdateSbar(HWND window) { + SbarDraw(window, IDC_SCROLLBAR, sgProvListLen, SelConnGetFocusNum()); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnTab(HWND child) { + HWND parent, newfocus; + int index; + int NewID[] = { + IDC_CONNECTBTN2, + IDC_CONNECTBTN3, + IDC_CONNECTBTN4, + IDC_CONNECTBTN5, + IDC_CONNECTBTN6, + IDC_CONNECTBTN1 + }; + + parent = GetParent(child); + newfocus = child; + do { + index = GetWindowLong(newfocus, GWL_ID) - IDC_CONNECTBTN1; + newfocus = GetDlgItem(parent, NewID[index]); + } while (! IsWindowEnabled(newfocus)); + SetFocus(newfocus); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnShiftTab(HWND child) { + HWND parent, newfocus; + int index; + int NewID[] = { + IDC_CONNECTBTN6, + IDC_CONNECTBTN1, + IDC_CONNECTBTN2, + IDC_CONNECTBTN3, + IDC_CONNECTBTN4, + IDC_CONNECTBTN5 + }; + + parent = GetParent(child); + newfocus = child; + do { + index = GetWindowLong(newfocus, GWL_ID) - IDC_CONNECTBTN1; + newfocus = GetDlgItem(parent, NewID[index]); + } while (! IsWindowEnabled(newfocus)); + SetFocus(newfocus); +} + + +//**************************************************************************** +//**************************************************************************** +static int GetNumProvNode(HWND btn) { + if (! btn) return 0; + TPBMP tpBmp = (TPBMP) GetWindowLong(btn, GWL_USERDATA); + if (! tpBmp) return 0; + TPPROVIDERINFO list = sgProviderList; + if (! list) return 0; + TPPROVIDERINFO node = (TPPROVIDERINFO) tpBmp->userdata; + if (! node) return 0; + + int nodenum = 0; + + while (list && (list != node)) { + nodenum++; + list = list->next; + } + + return nodenum; +} + + +//**************************************************************************** +//**************************************************************************** +static TPPROVIDERINFO GetProvider(int index) { + TPPROVIDERINFO list = sgProviderList; + + while (list && index) { + list = list->next; + index--; + } + return list; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnPageDown(HWND focus) { + HWND parent = GetParent(focus); + if (! parent) return; + + // get info of 1st btn + HWND btn1 = GetDlgItem(parent, IDC_CONNECTBTN1); + if (! btn1) return; + + // see if there is info below the bottom + TPBMP tpBmp = (TPBMP) GetWindowLong(GetDlgItem(parent, IDC_CONNECTBTN6), GWL_USERDATA); + if (! tpBmp) return; + TPPROVIDERINFO tpProvider = (TPPROVIDERINFO) tpBmp->userdata; + if ((! tpProvider) || (! tpProvider->next)) { + SelConnShiftTab(btn1); + return; + } + + // calc the index of the new top + int newtop = GetNumProvNode(btn1) + MAX_VISIBLE; + if (newtop > (sgProvListLen - MAX_VISIBLE)) + newtop = sgProvListLen - MAX_VISIBLE; + + // get the pointer to that index + tpProvider = GetProvider(newtop); + if (! tpProvider) return; + + // update everything on the screen + UiSndPlayClick(); + SelConnSetProviders(parent, tpProvider); + SelConnSetInfo(parent, GetWindowLong(focus, GWL_ID)); + SelConnUpdateSbar(parent); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnPageUp(HWND focus) { + HWND parent = GetParent(focus); + if (! parent) return; + HWND btn1 = GetDlgItem(parent, IDC_CONNECTBTN1); + if (! btn1) return; + + // see if there is info off the top + TPBMP tpBmp = (TPBMP) GetWindowLong(btn1, GWL_USERDATA); + if (! tpBmp) return; + TPPROVIDERINFO tpProvider = (TPPROVIDERINFO) tpBmp->userdata; + if (! tpProvider) return; + if (tpProvider == sgProviderList) { + SelConnTab(GetDlgItem(parent, IDC_CONNECTBTN6)); + return; + } + + // calc the index of the new top + int newtop = GetNumProvNode(btn1) - MAX_VISIBLE; + if (newtop < 0) + newtop = 0; + + // get the pointer to that index + tpProvider = GetProvider(newtop); + if (! tpProvider) return; + + // update everything on the screen + UiSndPlayClick(); + SelConnSetProviders(parent, tpProvider); + SelConnSetInfo(parent, GetWindowLong(focus, GWL_ID)); + SelConnUpdateSbar(parent); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnScrollDown(HWND focus) { + // see if there is info below the focus + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (! tpBmp) return; + TPPROVIDERINFO tpProvider = (TPPROVIDERINFO) tpBmp->userdata; + if (! tpProvider) return; + if (! tpProvider->next) return; + + if (GetWindowLong(focus, GWL_ID) < IDC_CONNECTBTN6) { + // handle it just like a tab + SelConnTab(focus); + return; + } + + // advance the list + HWND child = GetDlgItem(GetParent(focus), IDC_CONNECTBTN2); + if (! child) return; + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + tpProvider = (TPPROVIDERINFO) tpBmp->userdata; + if (! tpProvider) return; + UiSndPlayClick(); + SelConnSetProviders(GetParent(focus), tpProvider); + SelConnSetInfo(GetParent(focus), GetWindowLong(focus, GWL_ID)); + SelConnUpdateSbar(GetParent(focus)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnScrollUp(HWND focus) { + if (GetWindowLong(focus, GWL_ID) > IDC_CONNECTBTN1) { + // handle it just like a shift-tab + SelConnShiftTab(focus); + return; + } + + // see if there is info off the top + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (! tpBmp) return; + TPPROVIDERINFO tpProvider = (TPPROVIDERINFO) tpBmp->userdata; + if (! tpProvider) return; + TPPROVIDERINFO tpProviderList = sgProviderList; + if (tpProvider == tpProviderList) return; + + // retreat the list + while (tpProviderList && (tpProviderList->next != tpProvider)) { + tpProviderList = tpProviderList->next; + } + UiSndPlayClick(); + SelConnSetProviders(GetParent(focus), tpProviderList); + SelConnSetInfo(GetParent(focus), GetWindowLong(focus, GWL_ID)); + SelConnUpdateSbar(GetParent(focus)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnDestroy(HWND window) { + SbarDestroy(window, IDC_SCROLLBAR); + SelConnFreeList(sgProviderList); + + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgBigTextIDs); + UiDoomCtrlsDestroy(window, sgLblTextIDs); + UiDoomCtrlsDestroy(window, sgSmallTextIDs); + + // free the background of the dlg + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + TitleLogoDestroy(); + FocusAnimateDestroy(); +} + + +//**************************************************************************** +//**************************************************************************** +static LRESULT CALLBACK SelConnListEntryWndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + LRESULT result; + WNDPROC oldproc = (WNDPROC) GetProp(window, OLDPROCPROP); + + switch (message) { + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_KEYDOWN: + switch (wparam) { + case VK_SPACE: + case VK_RETURN: + SendMessage(GetParent(window), WM_COMMAND, IDOK, (LPARAM)NULL); + break; + case VK_ESCAPE: + SendMessage(GetParent(window), WM_COMMAND, IDCANCEL, (LPARAM)NULL); + break; + case VK_TAB: + if (GetKeyState(VK_SHIFT) < 0) { + SelConnShiftTab(window); + } + else { + SelConnTab(window); + } + break; + case VK_UP: + case VK_LEFT: + SelConnScrollUp(window); + break; + case VK_DOWN: + case VK_RIGHT: + SelConnScrollDown(window); + break; + case VK_PRIOR: + SelConnPageUp(window); + break; + case VK_NEXT: + SelConnPageDown(window); + break; + + } + return 0; + + case WM_DESTROY: + RemoveProp(window, OLDPROCPROP); + if (oldproc) { + SetWindowLong(window, GWL_WNDPROC, (LONG) oldproc); + } + break; + + case WM_PAINT: + UiPaintBtn(window); + return 0; + } + + if (oldproc) + result = CallWindowProc(oldproc, window, message, wparam, lparam); + else + result = DefWindowProc(window, message, wparam, lparam); + return result; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnSubclassEntries(HWND window) { + HWND child; + int *ListID; + WNDPROC oldproc; + + for (ListID = sgListIDs; *ListID; ListID++) { + child = GetDlgItem(window, *ListID); + if (! child) continue; + + oldproc = (WNDPROC) GetWindowLong(child, GWL_WNDPROC); + SetProp(child, OLDPROCPROP,(HANDLE) oldproc); + SetWindowLong(child, GWL_WNDPROC, (LONG) SelConnListEntryWndProc); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnInit(HWND window) { + TPBMP tpBmp; + + SelConnSubclassEntries(window); + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus16.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + // set up the animating diablo logo + TitleLogoInit(window); + TitleFramesInit(window,TEXT("ui_art\\hf_logo2.pcx")); + TitleLogoAnimate(window); + SDlgSetTimer(window, LOGO_TIMER_ID, LOGO_TIMER_DELAY, NULL); + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\selconn.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window); + } + + // set up a doom-like interface + UiDoomStaticInit(window, sgSmallTextIDs, AF_SMALLGRAY); + UiDoomStaticInit(window, sgLblTextIDs, AF_SMALLGRAY); + UiDoomStaticInit(window, sgBigTextIDs, AF_BIGGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_SMALL); + + // get provider list + sgProvListLen = 0; + sgProviderList = NULL; + SNetEnumProviders(NULL, SelConnEnum); + + // set provider buttons to contain text + SelConnSetProviders(window, sgProviderList); + + // init the scroll bar + SbarInit(window, IDC_SCROLLBAR); +#if SB_ALWAYS_ON != 1 + if (sgProvListLen <= MAX_VISIBLE) { + ShowWindow(GetDlgItem(window, IDC_SCROLLBAR), FALSE); + } +#endif +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnAbort(HWND window, int ReturnVal) { + if (ReturnVal == IDCANCEL) + UiSndPlayEnter(); + UiFadeAbort(window); + SDlgKillTimer(window, LOGO_TIMER_ID); + SDlgKillTimer(window, FOCUS_TIMER_ID); + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelConnInitProvider(HWND window) { + TPPROVIDERINFO tpProvider; + SNETUIDATA tUiData; + + UiSndPlayEnter(); + UiSetProviderID(0); + UiSetBasicInterface(FALSE); + + TPBMP tpBmp = (TPBMP) GetWindowLong(GetFocus(), GWL_USERDATA); + if (! tpBmp) + return FALSE; + + tpProvider = (TPPROVIDERINFO) tpBmp->userdata; + if (! tpProvider) + return FALSE; + UiSetProviderID(tpProvider->id); + UiSetBasicInterface(tpProvider->isbasicinterface); + + if (sginterfacedata) + tUiData = *sginterfacedata; + tUiData.parentwindow = window; + + // Hide cursor while inside Initialize() routine. + // That way the .snp can take control of the cursor and do whatever it wants. + UiClearCursor(); + BOOL bResult = SNetInitializeProvider( + UiGetProviderID(), + sgprogramdata, + sgplayerdata, + &tUiData, + sgversiondata); + UiSetCursor(); + + if (bResult) { + return UiSelectDevice( + UiGetProviderID(), + sgprogramdata, + sgplayerdata, + &tUiData, + sgversiondata + ); + } + else { + return FALSE; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnInitError(HWND window) { + switch (GetLastError()) { + case SNET_ERROR_CANCELLED: + // do nothing if the user cancelled during connect + break; + default: + // error initializing connection method + TCHAR errstr[128]; + LoadString(global_hinstance, IDS_SELCONN_ERR, errstr, 127); + SelOkDialog(window, errstr, NULL, FALSE); + break; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnAttemptInit(HWND window) { + if (SelConnInitProvider(window)) { + SelConnAbort(window, IDOK); + } + else if (GetLastError() == SNET_ERROR_REQUIRES_UPGRADE) { + sgRequireUpgrade = TRUE; + SelConnAbort(window, 0); + } + else { + switch (UiGetProviderID()) { + case 'MODM': + case 'IPXN': + case 'SCBL': + SelConnInitError(window); + break; + + default: + // do nothing, and hope the provider notified the user of the error + break; + } + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelConnInterpretClick(HWND window, int x, int y) { + if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKEOK), x, y)) { + SelConnAttemptInit(window); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKECANCEL), x, y)) { + SelConnAbort(window, IDCANCEL); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_SCROLLBAR), x, y)) { + int SbarClick = SbarInterpretClick(GetDlgItem(window, IDC_SCROLLBAR), x, y); + switch (SbarClick) { + case DSB_UP: + SelConnScrollUp(GetFocus()); + break; + case DSB_PAGEUP: + SelConnPageUp(GetFocus()); + break; + case DSB_DOWN: + SelConnScrollDown(GetFocus()); + break; + case DSB_PAGEDOWN: + SelConnPageDown(GetFocus()); + break; + default: + break; + } + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK SelConnDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + SelConnSetInfo(window, LOWORD(wparam)); + SelConnUpdateSbar(window); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + SelConnAttemptInit(window); + } + else if (LOWORD(wparam) == IDOK) { + SelConnAttemptInit(window); + } + else if (LOWORD(wparam) == IDCANCEL) { + SelConnAbort(window, IDCANCEL); + } + break; + + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + SelConnInterpretClick(window, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_LBUTTONUP: + if (SbarUpClick(GetDlgItem(window, IDC_SCROLLBAR))) { + SelConnUpdateSbar(window); + } + break; + + case WM_DESTROY: + SelConnDestroy(window); + break; + + case WM_INITDIALOG: + SelConnInit(window); + PostMessage(window, WM_USER+1000, 0, 0); + return 0; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_TIMER: + switch (wparam) { + case FOCUS_TIMER_ID: + FocusAnimate(window, GetFocus()); + break; + case LOGO_TIMER_ID: + TitleLogoAnimate(window); + break; + } + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiSelectProvider (SNETCAPSPTR mincaps, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *providerid) { + + DWORD result = 0; + + sgmincaps = mincaps; + sgprogramdata = programdata; + sgplayerdata = playerdata; + sginterfacedata = interfacedata; + sgversiondata = versiondata; + sgRequireUpgrade = FALSE; + + // make sure fonts are loaded + ArtFontLoad(); + + // DISPLAY THE DIALOG BOX + result = (DWORD)SDlgDialogBox(global_hinstance, + TEXT("SELCONNECT_DIALOG"), + SDrawGetFrameWindow(), + SelConnDialogProc); + + + if (result == IDOK) { + ArtFontDestroy(); + } + + + if (providerid) + *providerid = UiGetProviderID(); + + if (sgRequireUpgrade) { + SetLastError(SNET_ERROR_REQUIRES_UPGRADE); + return FALSE; + } + else if (result == IDOK) { + return TRUE; + } + else { + SetLastError(SNET_ERROR_CANCELLED); + return FALSE; + } +} diff --git a/src/Uisrc/UI/SELDIAL.CPP b/src/Uisrc/UI/SELDIAL.CPP new file mode 100644 index 0000000..b5e96ec --- /dev/null +++ b/src/Uisrc/UI/SELDIAL.CPP @@ -0,0 +1,432 @@ +//**************************************************************************** +// SelDial.cpp +// Diablo UI select "dial" or "answer" for modem setup +// +// By Frank Pearce +// created 11.23.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern void ModemSetInfo(HWND window, LPCSTR infotitle, LPCSTR text); + extern BOOL ModemConnected(void); + extern BOOL ModemEnum(void); + extern LPCSTR ModemGameName(void); + extern int ModemLastJoinedNumber(void); + extern int ModemGameNumber(LPCSTR gamename); + + +//**************************************************************************** +//**************************************************************************** + #define PHONEBOOK_KEY "Diablo\\Phone Book" + #define PHONEBOOK_ENTRY1 "Entry1" + #define PHONEBOOK_ENTRY2 "Entry2" + #define PHONEBOOK_ENTRY3 "Entry3" + #define PHONEBOOK_ENTRY4 "Entry4" + + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define ENUM_TIMER_ID 2 + #define ENUM_TIMER_DELAY 2000 + + #define PHONEBOOK_SIZE 4 + typedef struct _phonenumber { + TCHAR number[MAX_DIAL_LEN]; + } TNUMBER, * TPNUMBER; + + +//**************************************************************************** +//**************************************************************************** + static char * sgPhoneEntryNames[PHONEBOOK_SIZE] = { + PHONEBOOK_ENTRY1, + PHONEBOOK_ENTRY2, + PHONEBOOK_ENTRY3, + PHONEBOOK_ENTRY4, + }; + + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgListIDs[] = { + IDC_DIALBTN1, + IDC_DIALBTN2, + IDC_DIALBTN3, + IDC_DIALBTN4, + IDC_DIALBTN5, + IDC_DIALBTN6, + 0 + }; + + static TNUMBER sgPhoneBook[PHONEBOOK_SIZE]; + static LPTSTR sgDialString; + + +//**************************************************************************** +//**************************************************************************** +void SelDialSaveBookEntries(LPCSTR dialstring) { + TCHAR entry[MAX_DIAL_LEN]; + int i, lasttomove; + + // is the string already in the list? + for (i = 0; i < PHONEBOOK_SIZE; i++) { + if ( + SRegLoadString( + PHONEBOOK_KEY, + sgPhoneEntryNames[i], + SREG_FLAG_USERSPECIFIC, + entry, + MAX_DIAL_LEN + ) + ) { + entry[MAX_DIAL_LEN-1] = 0; + if (0 == strcmp(entry, dialstring)) { + break; + } + } + } + + if (i == PHONEBOOK_SIZE) + lasttomove = PHONEBOOK_SIZE - 1; + else + lasttomove = i; + + // move all other numbers down in the phone book + for (i = lasttomove-1; i >= 0; i--) { + entry[0] = 0; + if ( + SRegLoadString( + PHONEBOOK_KEY, + sgPhoneEntryNames[i], + SREG_FLAG_USERSPECIFIC, + entry, + MAX_DIAL_LEN + ) + ) { + entry[MAX_DIAL_LEN-1] = 0; + if (strlen(entry)) { + SRegSaveString( + PHONEBOOK_KEY, + sgPhoneEntryNames[i+1], + SREG_FLAG_USERSPECIFIC, + entry + ); + } + } + } + + // save the number in the first slot + SRegSaveString( + PHONEBOOK_KEY, + sgPhoneEntryNames[0], + SREG_FLAG_USERSPECIFIC, + dialstring + ); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialGetBookEntries(void) { + for (int i = 0; i < PHONEBOOK_SIZE; i++) { + if ( + SRegLoadString( + PHONEBOOK_KEY, + sgPhoneEntryNames[i], + SREG_FLAG_USERSPECIFIC, + sgPhoneBook[i].number, + MAX_DIAL_LEN + ) + ) { + sgPhoneBook[i].number[MAX_DIAL_LEN-1] = 0; + } + else { + sgPhoneBook[i].number[0] = 0; + } + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialPhoneBook(HWND window) { + int i; + HWND child; + TPBMP tpBmp; + TCHAR fmt[32]; + TCHAR callstr[64]; + + // make sure my phone book is empty + for (i = 0; i < PHONEBOOK_SIZE; i++) + sgPhoneBook[i].number[0] = 0; + + // get the phone book numbers + SelDialGetBookEntries(); + + // put the info into the buttons + LoadString(global_hinstance, IDS_CALL_FMT, fmt, 31); + for (i = 0; i < PHONEBOOK_SIZE; i++) { + child = GetDlgItem(window, IDC_DIALBTN3 + i); + if (! child) continue; + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) continue; + if (strlen(sgPhoneBook[i].number)) { + wsprintf(callstr, fmt, sgPhoneBook[i].number); + UiSetBmpText(tpBmp, callstr); + } + else { + EnableWindow(child, FALSE); + UiSetBmpText(tpBmp, NULL); + } + } + + UiDoomButtonsReset(window, sgListIDs, AF_SMALL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialSetInfo(HWND window, int childid) { + TCHAR title[64], desc[256]; + LoadString(global_hinstance, IDS_SELDIAL_INFOTITLE, title, 63); + switch (childid) { + case IDC_DIALBTN1: + if (ModemConnected()) { + LoadString(global_hinstance, IDS_MODEM_CREATE2, desc, 255); + } + else { + LoadString(global_hinstance, IDS_MODEM_CREATE, desc, 255); + } + break; + case IDC_DIALBTN2: + if (ModemConnected()) { + LoadString(global_hinstance, IDS_MODEM_JOIN, desc, 255); + } + else { + LoadString(global_hinstance, IDS_MODEM_DIALNEW, desc, 255); + } + break; + default: + LoadString(global_hinstance, IDS_MODEM_DIALOLD, desc, 255); + break; + } + ModemSetInfo(GetParent(window), title, desc); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialDestroy(HWND window) { + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + FocusAnimateDestroy(); + ModemSetInfo(GetParent(window), NULL, NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialSetJoinBtn(HWND window) { + char joinstr[64]; + HWND child = GetDlgItem(window, IDC_DIALBTN2); + if (! child) return; + + if (ModemGameNumber(ModemGameName()) > ModemLastJoinedNumber()) + LoadString(global_hinstance, IDS_MODEMJOINNEW, joinstr, 63); + else + LoadString(global_hinstance, IDS_MODEMJOINPREV, joinstr, 63); + + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), joinstr); + UiDoomButtonsReset(window, sgListIDs, AF_SMALL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialClearJoinBtn(HWND window) { + HWND child = GetDlgItem(window, IDC_DIALBTN2); + if (! child) return; + + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), NULL); + + UiDoomButtonsReset(window, sgListIDs, AF_SMALL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialAbort(HWND window, int ReturnVal) { + if ((ReturnVal == IDOK) || (ReturnVal == IDCANCEL)) + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + SDlgKillTimer(window, ENUM_TIMER_ID); + if (IDOK == ReturnVal) { + // see what the selection was + int ID = GetWindowLong(GetFocus(), GWL_ID); + switch (ID) { + case IDC_DIALBTN1: + SDlgEndDialog(window, MODE_ANSWER); + break; + case IDC_DIALBTN2: + SDlgEndDialog(window, MODE_DIALNEW); + break; + default: { + if (sgDialString) + strcpy(sgDialString, sgPhoneBook[ID - IDC_DIALBTN3].number); + SDlgEndDialog(window, MODE_DIALOLD); + } + break; + } + } + else { + SDlgEndDialog(window, ReturnVal); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialEnum(HWND window) { + HWND child = GetDlgItem(window, IDC_DIALBTN2); + if (! child) return; + + if (ModemEnum()) { + SelDialSetJoinBtn(window); + EnableWindow(child, TRUE); + ShowWindow(child, TRUE); + } + else { + if (GetLastError() == SNET_ERROR_NO_NETWORK) { + SelDialAbort(window, SNET_ERROR_NO_NETWORK); + } + else { + if (GetFocus() == child) { + SetFocus(GetDlgItem(window, IDC_DIALBTN1)); + } + SelDialClearJoinBtn(window); + EnableWindow(child, FALSE); + ShowWindow(child, FALSE); + } + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialInit(HWND window) { + HWND parent = GetParent(window); + + // point this window at the same bmp it's parent uses + SetWindowLong( + window, + GWL_USERDATA, + GetWindowLong(parent, GWL_USERDATA) + ); + + FocusAnimateInit("ui_art\\focus16.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + UiOnPaintBtns(window, sgListIDs); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_SMALL); + + if (! ModemConnected()) { + SelDialPhoneBook(window); + } + else { + SDlgSetTimer(window, ENUM_TIMER_ID, ENUM_TIMER_DELAY, NULL); + SelDialEnum(window); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelDialInterpretClick(HWND window, int x, int y) { + if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKEOK), x, y)) { + SelDialAbort(window, IDOK); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKECANCEL), x, y)) { + SelDialAbort(window, IDCANCEL); + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK SelDialDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + SelDialSetInfo(window, LOWORD(wparam)); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + SelDialAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDOK) { + SelDialAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDCANCEL) { + SelDialAbort(window, IDCANCEL); + } + break; + + case WM_LBUTTONDOWN: + SelDialInterpretClick(window, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_DESTROY: + SelDialDestroy(window); + break; + + case WM_INITDIALOG: + sgDialString = (LPSTR) lparam; + SelDialInit(window); + return 0; + + case WM_TIMER: + switch (wparam) { + case FOCUS_TIMER_ID: + FocusAnimate(window, GetFocus()); + break; + case ENUM_TIMER_ID: + SelDialEnum(window); + break; + } + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} diff --git a/src/Uisrc/UI/SELGAME.CPP b/src/Uisrc/UI/SELGAME.CPP new file mode 100644 index 0000000..0a2eac4 --- /dev/null +++ b/src/Uisrc/UI/SELGAME.CPP @@ -0,0 +1,129 @@ +//**************************************************************************** +// SelGame.cpp +// Diablo UI select multiplayer game +// +// By Frank Pearce +// created 11.5.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** +extern BOOL UiSelectIPXGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern BOOL UiDirectLinkGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); +extern BOOL UiModemGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid); + + + +//**************************************************************************** +//**************************************************************************** + #define ID_NETWORK 'IPXN' + #define ID_MODEM 'MODM' + #define ID_SERIAL 'SCBL' + + +//**************************************************************************** +//**************************************************************************** +static DWORD sgProviderID; +static BOOL sgBasicInterface; +void UiSetBasicInterface(BOOL basic) { + sgBasicInterface = basic; +} +BOOL UiIsBasicInterface(void) { + return sgBasicInterface; +} +void UiSetProviderID(DWORD id) { + sgProviderID = id; +} +DWORD UiGetProviderID(void) { + return sgProviderID; +} + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiSelectGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + BOOL success; + + if (UiIsBasicInterface()) { + return UiSelectIPXGame( + flags, + programdata, + playerdata, + interfacedata, + versiondata, + playerid + ); + } + + switch (UiGetProviderID()) { + case ID_NETWORK: + success = UiSelectIPXGame( + flags, + programdata, + playerdata, + interfacedata, + versiondata, + playerid + ); + break; + + case ID_MODEM: + success = UiModemGame( + flags, + programdata, + playerdata, + interfacedata, + versiondata, + playerid + ); + break; + + case ID_SERIAL: + success = UiDirectLinkGame( + flags, + programdata, + playerdata, + interfacedata, + versiondata, + playerid + ); + break; + + default: + success = SNetSelectGame( + flags, + programdata, + playerdata, + interfacedata, + versiondata, + playerid + ); + break; + } + + return success; +} diff --git a/src/Uisrc/UI/SELHERO.CPP b/src/Uisrc/UI/SELHERO.CPP new file mode 100644 index 0000000..5969fc8 --- /dev/null +++ b/src/Uisrc/UI/SELHERO.CPP @@ -0,0 +1,1073 @@ +//**************************************************************************** +// SelHero.cpp +// Diablo UI select hero dialogs +// +// By Frank Pearce +// created 9.19.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern int UiCreaHeroDlg(HWND parent, GETDEFHERO getstatsfcn, LPSTR newname, int * charclass); + extern int UiOkCancelDialog(HWND parent, LPCSTR okcanceltext, BOOL errorflag); + extern int UiOkDialog(HWND parent, LPCSTR oktext, BOOL errorflag); + extern int SelYesNoDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus); + extern int SelOkDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus); + + extern BOOL CALLBACK SelListDialogProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); + extern BOOL CALLBACK SelClassDialogProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); + extern BOOL CALLBACK SelLoadDialogProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); + extern BOOL CALLBACK SelDiffDialogProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); + extern BOOL CALLBACK EnterNameDialogProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); + + extern void HeroInfo2Txt(TUIHEROINFO *pHeroInfo, char *szDesc); + + extern void SelDiffLoadFocus(BOOL loadfocus); + static void SelHeroAbort(HWND window, int retval); + + +//**************************************************************************** +//**************************************************************************** + extern void TitleLogoDestroy(void); + extern void TitleLogoInit(HWND window); + extern void TitleFramesInit(HWND window, LPCTSTR filename); + extern void TitleLogoAnimate(HWND window); + + #define MILLISEC_PER_SEC 1000 + + #define LOGO_TIMER_ID 2 + #define LOGO_FPS 17 + #define LOGO_TIMER_DELAY 55 + + +//**************************************************************************** +//**************************************************************************** + enum _wm_states { + WM_STATE_SELLIST = (WM_USER + 2000), + + WM_STATE_SELCLASS, + WM_STATE_ENTERNAME, + + WM_STATE_SELLOAD, + WM_STATE_SELDIFF, + + WM_STATE_CONTINUE, + WM_STATE_NEWHERO, + WM_STATE_DELETEHERO + }; + + +//**************************************************************************** +//**************************************************************************** + static LPBYTE sgHerosBmp = NULL; + static SIZE sgHerosSize; + + static int sgMode; // single or multi player + + //*** strings to put the hero stats in + static char selheroname[MAX_NAME_LEN]; + static char selherolevel[8]; + static char selherostr[4]; + static char selheromagic[4]; + static char selherodex[4]; + static char selherovit[4]; + static BOOL hassaved; + + static ENUMHEROS sgEnumFcn; + static CREATEHERO sgCreateFcn; + static DELETEHERO sgDeleteFcn; + static GETDEFHERO sgGetStatsFcn; + static bool sgAllowBard; + static bool sgAllowBarbarian; + + static TPUIHEROINFO sgHeroList; + static TUIHEROINFO sgNewHero; // for use when a new hero is being created + static int sgListLen; + static int sgDifficulty; + + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgLblIDs[] = { + IDC_LEVELLBL, + IDC_STRLBL, + IDC_MAGLBL, + IDC_DEXLBL, + IDC_VITLBL, + 0 + }; + static int sgDataIDs[] = { + IDC_CHARLEVEL, + IDC_CHARSTR, + IDC_CHARMAGIC, + IDC_CHARDEX, + IDC_CHARVIT, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** +TPUIHEROINFO GetHeroList(void) { + return sgHeroList; +} +int GetNumHeros(void) { + return sgListLen; +} + + +//**************************************************************************** +//**************************************************************************** +void SelHeroSetDiff(int difficulty) { + sgDifficulty = difficulty; +} + + +//**************************************************************************** +//**************************************************************************** +LPCTSTR SelectedName(void) { + return selheroname; +} + + +//**************************************************************************** +//**************************************************************************** +TPUIHEROINFO SelHeroAllocNode(void) { + return (TPUIHEROINFO) ALLOC(sizeof(TUIHEROINFO)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelHeroFreeNode(TPUIHEROINFO node) { + if (node) { + FREE(node); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelHeroFreeList(TPUIHEROINFO list) { + TPUIHEROINFO next; + + while (list) { + next = list->next; + SelHeroFreeNode(list); + list = next; + } +} + + +//**************************************************************************** +//**************************************************************************** +TPUIHEROINFO SelHeroAddNode(TPUIHEROINFO list, TPUIHEROINFO node) { + node->next = list; + return node; +} + + +//**************************************************************************** +//**************************************************************************** +static TPUIHEROINFO SelHeroDeleteNode(TPUIHEROINFO list, LPCSTR namekey) { + TPUIHEROINFO current, previous, found; + + current = list; + previous = NULL; + found = NULL; + + while (current && !found) { + if (strcmp(current->name, namekey) == 0) { + found = current; + } + else { + previous = current; + current = current->next; + } + } + + if (found) { + if (previous) + previous->next = found->next; + else + list = found->next; + SelHeroFreeNode(found); + } + + return list; +} + + +//**************************************************************************** +//**************************************************************************** +static TPUIHEROINFO SelHeroFindNode(TPUIHEROINFO list, LPCSTR namekey) { + TPUIHEROINFO current = list; + + while (current) { + if (_stricmp(current->name, namekey) == 0) + break; + current = current->next; + } + + return current; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelHeroEnumHero(TPUIHEROINFO heroinfo) { + TPUIHEROINFO newhero = SelHeroAllocNode(); + if (! newhero) + return 0; + memcpy(newhero, heroinfo, sizeof(TUIHEROINFO)); + newhero->next = NULL; + sgHeroList = SelHeroAddNode(sgHeroList, newhero); + sgListLen++; + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelHeroGetHeros(HWND window) { + TPUIHEROINFO dummyslot; + // add a "new hero" slot at the end of the list + TPUIHEROINFO newhero = SelHeroAllocNode(); + if (!newhero) + return; + + newhero->next = NULL; + LoadString(global_hinstance, IDS_NEWHERO, newhero->name, MAX_NAME_LEN-1); + newhero->level = 0; + sgHeroList = SelHeroAddNode(sgHeroList, newhero); + dummyslot = sgHeroList; + sgListLen = 1; + + // add all the other heros to the list + if (! sgEnumFcn(SelHeroEnumHero)) { + TCHAR err[64]; + // the enum failed -- notify the user + LoadString(global_hinstance, IDS_ENUMCHAR_ERR, err, 64); + UiOkDialog(window, err, TRUE); + } + + if (dummyslot == sgHeroList) { + PostMessage(window, WM_STATE_SELCLASS, 0, 0); + } + else { + PostMessage(window, WM_STATE_SELLIST, 0, 0); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelHeroResetFocus(HWND window, int childID) { + SetFocus(GetDlgItem(window, childID)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelHeroSetImage(HWND window, int heroclass) { + RECT rect; + HWND child = GetDlgItem(window, IDC_HEROIMAGE); + + InvalidateRect(child, NULL, FALSE); + + GetClientRect(child, &rect); + + // hack since the art hasn't changed. + if (heroclass == UI_BARBARIAN) + heroclass = UI_WARRIOR; + else if (heroclass == UI_NUM_CLASSES) + --heroclass; + + UiCalcNewRect(&rect, 0, rect.bottom * heroclass); + + SDlgSetBitmap( + child, + NULL, + TEXT("Static"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + sgHerosBmp, + &rect, + sgHerosSize.cx, + sgHerosSize.cy + ); +} + + +//**************************************************************************** +//**************************************************************************** +int SelHeroGetMode(void) { + return sgMode; +} + + +//**************************************************************************** +//**************************************************************************** +void SelHeroGetDefStats(int heroclass, TPUIDEFSTATS stats) { + sgGetStatsFcn(heroclass, stats);; +} + + +//**************************************************************************** +//**************************************************************************** +void SelHeroClearStats(HWND window) { + LPTSTR empty = "--"; + HWND child; + + hassaved = FALSE; + selheroname[0] = 0; + + child = GetDlgItem(window, IDC_CHARLEVEL); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), empty); + child = GetDlgItem(window, IDC_CHARSTR); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), empty); + child = GetDlgItem(window, IDC_CHARMAGIC); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), empty); + child = GetDlgItem(window, IDC_CHARDEX); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), empty); + child = GetDlgItem(window, IDC_CHARVIT); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), empty); + + SelHeroSetImage(window, UI_NUM_CLASSES); + + UiDoomStaticReset(window, sgDataIDs, AF_SMALLGRAY); +} + + +//**************************************************************************** +//**************************************************************************** +void SelHeroSetStats(HWND window, TPUIHEROINFO hero) { + HWND child; + + if (! hero->level) { + SelHeroClearStats(window); + return; + } + + hassaved = hero->hassaved; + strcpy(selheroname, hero->name); + + child = GetDlgItem(window, IDC_CHARLEVEL); + wsprintf(selherolevel, "%d", hero->level); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), selherolevel); + + child = GetDlgItem(window, IDC_CHARSTR); + wsprintf(selherostr, "%d", hero->strength); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), selherostr); + + child = GetDlgItem(window, IDC_CHARMAGIC); + wsprintf(selheromagic, "%d", hero->magic); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), selheromagic); + + child = GetDlgItem(window, IDC_CHARDEX); + wsprintf(selherodex, "%d", hero->dexterity); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), selherodex); + + child = GetDlgItem(window, IDC_CHARVIT); + wsprintf(selherovit, "%d", hero->vitality); + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), selherovit); + + SelHeroSetImage(window, hero->heroclass); + + UiDoomStaticReset(window, sgDataIDs, AF_SMALLGRAY); +} + + +//**************************************************************************** +//**************************************************************************** +void SelHeroSetTitle(HWND window, LPCTSTR title) { + HWND child = GetDlgItem(window, IDC_DLGTITLE); + if (! child) return; + UiSetBmpText((TPBMP)GetWindowLong(child, GWL_USERDATA), title); + UiDoomStaticReset(window, sgTextIDs, AF_BIGGRAY); +} + +//**************************************************************************** +//**************************************************************************** +static void convert_nasty(LPSTR nasty) { + while (*nasty != 0) { + (*nasty)--; + nasty++; + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL IsNastyName(LPCTSTR name) { + TCHAR tempname[SNETSPI_MAXSTRINGLENGTH]; + TCHAR nasty[MAX_NAME_LEN]; + + strcpy(tempname, name); + _strlwr(tempname); + + for (int index = IDS_FIRST_NASTY; index <= IDS_LAST_NASTY; index++) { + LoadString(global_hinstance, index, nasty, MAX_NAME_LEN-1); + convert_nasty(nasty); + _strlwr(nasty); + if (strstr(tempname, nasty)) { + return TRUE; + } + } + return FALSE; +} + + +//**************************************************************************** +// InvalidChars() +// +// NOTE: SPACE is not included as a bad char. SPACE and any other additional bad +// characters should be placed into the additional string. Things like GAME NAME +// may include spaces. +//**************************************************************************** +BOOL InvalidChars(LPCTSTR name, LPCTSTR additionalbad) { + LPTSTR basicbad = ",<>%&\\\"?*#/"; + unsigned char c; + + if (strpbrk(name, basicbad)) + return TRUE; + + if (strpbrk(name, additionalbad)) + return TRUE; + + while (0 != (c = *name)) { + if (c < ' ') return TRUE; + if ((c > '~') && (c < 0xc0)) return TRUE; + name++; + } + return FALSE; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL ValidName(LPCTSTR name) { + BOOL validname = TRUE; + + // single player name restrictions + if (! strlen(name)) + validname = FALSE; + + // check multi player name restrictions + if (sgMode == MULTIPLAYER) { + if (IsNastyName(name) || InvalidChars(name, " ")) { + validname = FALSE; + } + } + + return validname; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelHeroCreateNew(HWND window, LPCTSTR newname) { + TCHAR title[32]; + TCHAR format[128]; + TCHAR confirm[128 + MAX_NAME_LEN]; + TPUIHEROINFO oldhero; + + if (SelHeroGetMode() == MULTIPLAYER) + LoadString(global_hinstance, IDS_NEWMULTHERO, title, 32-1); + else + LoadString(global_hinstance, IDS_NEWSINGHERO, title, 32-1); + + // make sure the name doesn't have reserved words or chars + if (! ValidName(newname)) { + LoadString(global_hinstance, IDS_NAME_ERR, format, 127); + SelOkDialog(window, format, title, TRUE); + return FALSE; + } + + // see if this name is already used + oldhero = SelHeroFindNode(sgHeroList, newname); + if (oldhero) { + // the name already exists -- confirm the overwrite + LoadString(global_hinstance, IDS_CONFIRM_OVERWRITE, format, 127); + wsprintf(confirm, format, oldhero->name); + if (IDCANCEL == SelYesNoDialog(window, confirm, title, TRUE)) { + return FALSE; + } + } + + strcpy(sgNewHero.name, newname); + sgNewHero.hassaved = FALSE; + + // create the hero file + if (! sgCreateFcn(&sgNewHero)) { + // notify user of the failure + LoadString(global_hinstance, IDS_CREATE_ERR, format, 127); + UiOkDialog(window, format, TRUE); + return FALSE; + } + + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +static void DoDeleteHero(HWND window) { + TCHAR title[32]; + TCHAR format[64]; + TCHAR confirm[64 + MAX_NAME_LEN]; + TPUIHEROINFO hero; + + if (SelHeroGetMode() == MULTIPLAYER) + LoadString(global_hinstance, IDS_DELETEMULTHERO, title, 32-1); + else + LoadString(global_hinstance, IDS_DELETESINGHERO, title, 32-1); + + // confirm the delete + LoadString(global_hinstance, IDS_CONFIRM_DELETE, format, 63); + wsprintf(confirm, format, selheroname); + if (IDCANCEL == SelYesNoDialog(window, confirm, title, TRUE)) { + PostMessage(window, WM_STATE_SELLIST, 0, 0); + return; + } + + // find the hero node to delete + hero = SelHeroFindNode(sgHeroList, selheroname); + if (! hero) { + PostMessage(window, WM_STATE_SELLIST, 0, 0); + return; + } + + // make the callback for the delete + if (! sgDeleteFcn(hero)) { + // the delete failed + LoadString(global_hinstance, IDS_DELETE_ERR, format, 63); + SelOkDialog(window, format, title, TRUE); + PostMessage(window, WM_STATE_SELLIST, 0, 0); + return; + } + + // delete the node + sgHeroList = SelHeroDeleteNode(sgHeroList, selheroname); + sgListLen--; + + // if there are no more heros, go straight to create + LoadString(global_hinstance, IDS_NEWHERO, format, MAX_NAME_LEN-1); + if (0 == strcmp(format, sgHeroList->name)) { + PostMessage(window, WM_STATE_SELCLASS, 0, 0); + } + else { + SelHeroSetStats(window, sgHeroList); + PostMessage(window, WM_STATE_SELLIST, 0, 0); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DoSelList(HWND window) { + int result; + + // bring up the hero selection list + result = SDlgDialogBox( + global_hinstance, + TEXT("SELLIST_DIALOG"), + window, + SelListDialogProc + ); + + if (result == IDOK) { + if (! strlen(selheroname)) { + PostMessage(window, WM_STATE_SELCLASS, 0, 0); + } + else if (sgMode == MULTIPLAYER) { + // a multiplayer hero was selected + PostMessage(window, WM_STATE_CONTINUE, 0, 0); + } + else { + // a single player hero was selected + if (hassaved) { + PostMessage(window, WM_STATE_SELLOAD, 0, 0); + } + else { + sgDifficulty = DIFF_NORMAL; + SelHeroAbort(window, SELHERO_NEW_DUNGEON); + } + } + } + else if (result == IDDELETE) { + PostMessage(window, WM_STATE_DELETEHERO, 0, 0); + } + else { + SelHeroAbort(window, SELHERO_PREVIOUS); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DoSelClass(HWND window) { + int result; + + // bring up the hero selection list + if (sgAllowBarbarian) + { + result = SDlgDialogBox( + global_hinstance, + TEXT("SELCLASS_DIALOG3"), + window, + SelClassDialogProc + ); + } + else if (sgAllowBard) + { + result = SDlgDialogBox( + global_hinstance, + TEXT("SELCLASS_DIALOG2"), + window, + SelClassDialogProc + ); + } + else + { + result = SDlgDialogBox( + global_hinstance, + TEXT("SELCLASS_DIALOG"), + window, + SelClassDialogProc + ); + } + + if ((result == -1) || (result == IDCANCEL)) { + TCHAR buf[32]; + LoadString(global_hinstance, IDS_NEWHERO, buf, 32-1); + if (strcmp(buf, sgHeroList->name) == 0) { + SelHeroAbort(window, SELHERO_PREVIOUS); + } + else { + PostMessage(window, WM_STATE_SELLIST, 0, 0); + } + } + else { + switch (result) { + case IDC_ROGUEBTN: + sgNewHero.heroclass = UI_ROGUE; + break; + case IDC_SORCERERBTN: + sgNewHero.heroclass = UI_SORCERER; + break; + case IDC_MONKBTN: + sgNewHero.heroclass = UI_MONK; + break; + case IDC_BARDBTN: + sgNewHero.heroclass = UI_BARD; + break; + case IDC_BARBARIANBTN: + sgNewHero.heroclass = UI_BARBARIAN; + break; + case IDC_WARRIORBTN: + default: + sgNewHero.heroclass = UI_WARRIOR; + break; + } + PostMessage(window, WM_STATE_ENTERNAME, 0, 0); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DoEnterName(HWND window) { + TCHAR newname[MAX_NAME_LEN]; + int result; + + // bring up the enter name screen + result = SDlgDialogBoxParam( + global_hinstance, + TEXT("ENTERNAME_DIALOG"), + window, + EnterNameDialogProc, + (LPARAM) &newname + ); + + if (result == IDOK) { + newname[MAX_NAME_LEN-1] = 0; + if (SelHeroCreateNew(window, newname)) { + PostMessage(window, WM_STATE_NEWHERO, 0, 0); + } + else { + PostMessage(window, WM_STATE_ENTERNAME, 0, 0); + } + } + else { + PostMessage(window, WM_STATE_SELCLASS, 0, 0); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DoSelLoad(HWND window) { + int result; + + // bring up the enter name screen + result = SDlgDialogBox( + global_hinstance, + TEXT("SELLOAD_DIALOG"), + window, + SelLoadDialogProc + ); + + if ((result == -1) || (result == IDCANCEL)) { + PostMessage(window, WM_STATE_SELLIST, 0, 0); + } + else { + if (result == IDC_LOADBTN) { + PostMessage(window, WM_STATE_CONTINUE, 0, 0); + } + else { + PostMessage(window, WM_STATE_SELDIFF, 0, 0); + } + } +} + + +//**************************************************************************** +//**************************************************************************** +static void DoSelDiff(HWND window) { + int result; + +// if (SelHeroGetMode() == SINGLEPLAYER) { +// // single player is always NORMAL difficulty +// SelHeroSetDiff(DIFF_NORMAL); +// SelHeroAbort(window, SELHERO_NEW_DUNGEON); +// return; +// } + + // bring up the select difficulty options + SelDiffLoadFocus(TRUE); + result = SDlgDialogBoxParam( + global_hinstance, + TEXT("SELDIFF_DIALOG"), + window, + SelDiffDialogProc, + sgMode + ); + + if (result == IDOK) { + // confirm the charcter can create a dungeon of the difficulty setting specified + char szGameDesc[SNETSPI_MAXSTRINGLENGTH]; + char szPlayerDesc[SNETSPI_MAXSTRINGLENGTH]; + char err[256]; + TGAMEDATA GameData; + TPUIHEROINFO pHeroInfo; + + pHeroInfo = SelHeroFindNode(sgHeroList, selheroname); + if (pHeroInfo) { + UiCreatePlayerDescription(pHeroInfo, 'DBLO', szPlayerDesc); + + // Create Game description for Storm (and for display of game later) + GameData.bDiff = sgDifficulty; + GameData2Txt( + &GameData, + selheroname, + szPlayerDesc, + szGameDesc, + sizeof(szGameDesc) + ); + + if ((sgMode == MULTIPLAYER) && + ! UiAuthCallback( + SNET_AUTHTYPE_GAME, + selheroname, + szPlayerDesc, + 0, + szGameDesc, + err, + sizeof(err) + ) + ) { + SelOkDialog(window, err, NULL, TRUE); + PostMessage(window, WM_STATE_SELDIFF, 0, 0); + } + else { + SelHeroAbort(window, SELHERO_NEW_DUNGEON); + } + } + else { + SelHeroAbort(window, SELHERO_NEW_DUNGEON); + } + } + else { + PostMessage(window, WM_STATE_SELLOAD, 0, 0); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelHeroDestroy(HWND window) { + UiDoomCtrlsDestroy(window, sgDataIDs); + UiDoomCtrlsDestroy(window, sgLblIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + + SelHeroFreeList(sgHeroList); + + if (sgHerosBmp) { + FREE(sgHerosBmp); + sgHerosBmp = NULL; + } + + // free the background of the dlg + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + TitleLogoDestroy(); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelHeroAbort(HWND window, int retval) { + UiFadeAbort(window); + SDlgKillTimer(window, LOGO_TIMER_ID); + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, retval); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelHeroInit(HWND window) { + TPBMP tpBmp; + + // create a list of available heros + SelHeroGetHeros(window); + + // set up the animating diablo logo + TitleLogoInit(window); + TitleFramesInit(window,TEXT("ui_art\\hf_logo2.pcx")); + TitleLogoAnimate(window); + SDlgSetTimer(window, LOGO_TIMER_ID, LOGO_TIMER_DELAY, NULL); + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\selhero.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window); + } + + UiLoadBmpFile( + TEXT("ui_art\\heros.pcx"), + &sgHerosBmp, + &sgHerosSize + ); + + // init the ctrls to use doom text + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomStaticInit(window, sgLblIDs, AF_SMALLGRAY); + UiDoomStaticInit(window, sgDataIDs, AF_SMALLGRAY); + + SelHeroClearStats(window); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelHeroDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_DESTROY: + SelHeroDestroy(window); + break; + + case WM_INITDIALOG: + SelHeroInit(window); + PostMessage(window, WM_USER+1000, 0, 0); + return 0; + + case WM_STATE_SELLIST: + DoSelList(window); + return 0; + + case WM_STATE_SELCLASS: + DoSelClass(window); + return 0; + + case WM_STATE_ENTERNAME: + DoEnterName(window); + return 0; + + case WM_STATE_SELLOAD: + DoSelLoad(window); + return 0; + + case WM_STATE_SELDIFF: + DoSelDiff(window); + return 0; + + case WM_STATE_NEWHERO: + strcpy(selheroname, sgNewHero.name); + if (sgMode == MULTIPLAYER) { + SelHeroAbort(window, SELHERO_CONNECT); + } + else { + //sgDifficulty = DIFF_NORMAL; + //SelHeroAbort(window, SELHERO_NEW_DUNGEON); + PostMessage(window, WM_STATE_SELDIFF, 0, 0); + } + return 0; + + case WM_STATE_DELETEHERO: + DoDeleteHero(window); + return 0; + + case WM_STATE_CONTINUE: + if (sgMode == MULTIPLAYER) { + SelHeroAbort(window, SELHERO_CONNECT); + } + else { + SelHeroAbort(window, SELHERO_CONTINUE); + } + return 0; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_TIMER: + TitleLogoAnimate(window); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiSelHeroMultDialog ( + ENUMHEROS enumfcn, + CREATEHERO createfcn, + DELETEHERO deletefcn, + GETDEFHERO getstatsfcn, + DWORD *selection, + LPSTR heroname, + bool allowBard, + bool allowBarbarian) { + DWORD result = 0; + + // make sure fonts are loaded + ArtFontLoad(); + + sgEnumFcn = enumfcn; + sgCreateFcn = createfcn; + sgDeleteFcn = deletefcn; + sgGetStatsFcn = getstatsfcn; + sgAllowBard = allowBard; + sgAllowBarbarian = allowBarbarian; + + sgHeroList = NULL; + sgMode = MULTIPLAYER; + + // DISPLAY THE DIALOG BOX + result = (DWORD)SDlgDialogBox(global_hinstance, + TEXT("SELHERO_DIALOG"), + SDrawGetFrameWindow(), + SelHeroDialogProc); + + // set the results + if (selection) + *selection = result; + if (heroname) + strcpy(heroname, selheroname); + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiSelHeroSingDialog ( + ENUMHEROS enumfcn, + CREATEHERO createfcn, + DELETEHERO deletefcn, + GETDEFHERO getstatsfcn, + DWORD *selection, + LPSTR heroname, + int *difficulty, + bool allowBard, + bool allowBarbarian) { + DWORD result = 0; + + // make sure fonts are loaded + ArtFontLoad(); + + sgEnumFcn = enumfcn; + sgCreateFcn = createfcn; + sgDeleteFcn = deletefcn; + sgGetStatsFcn = getstatsfcn; + sgAllowBard = allowBard; + sgAllowBarbarian = allowBarbarian; + + sgHeroList = NULL; + sgMode = SINGLEPLAYER; + + // DISPLAY THE DIALOG BOX + result = (DWORD)SDlgDialogBox(global_hinstance, + TEXT("SELHERO_DIALOG"), + SDrawGetFrameWindow(), + SelHeroDialogProc); + // set the results + if (selection) + *selection = result; + if (heroname) + strcpy(heroname, selheroname); + if (difficulty) + *difficulty = sgDifficulty; + + // if the result is any option that starts the game, free fonts, snds. etc. + if (result != SELHERO_PREVIOUS) { + ArtFontDestroy(); + } + + return 1; +} diff --git a/src/Uisrc/UI/SELIPX.CPP b/src/Uisrc/UI/SELIPX.CPP new file mode 100644 index 0000000..41ac5dd --- /dev/null +++ b/src/Uisrc/UI/SELIPX.CPP @@ -0,0 +1,1127 @@ +//**************************************************************************** +// SelIPX.cpp +// Diablo UI select IPX multiplayer game +// +// By Frank Pearce +// created 11.6.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +#define SB_ALWAYS_ON 0 // 0 in final + +#define MIN_DESC_LEN 16 + +//**************************************************************************** +//**************************************************************************** + extern BOOL Txt2HeroInfo(char *szDesc, TUIHEROINFO *pHeroInfo); + extern void TitleLogoDestroy(void); + extern void TitleLogoInit(HWND window); + extern void TitleFramesInit(HWND window, LPCTSTR filename); + extern void TitleLogoAnimate(HWND window); + + extern int SelOkDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus); + + extern DWORD UiGetProviderID(void); + + extern BOOL UiDoomCreateGame (SNETCREATEDATAPTR createdata, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid, + BOOL loadfocus, + LPCSTR gamename); + + + static void SelIPXShiftTab(HWND child); + +//**************************************************************************** +//**************************************************************************** + #define OLDPROCPROP TEXT("UIOLDPROC") + #define PROVIDERID 'IPXN' + + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define LOGO_TIMER_ID 2 + #define LOGO_FPS 17 + #define LOGO_TIMER_DELAY 55 + + #define ENUM_TIMER_ID 3 // how often we re-enum available games + #define ENUM_TIMER_DELAY 1000 + + #define MAX_VISIBLE 6 + + +//**************************************************************************** +//**************************************************************************** + static int sgTitleIDs[] = { + IDC_DLGTITLE, + IDC_DLGTITLE2, + 0 + }; + static int sgTextIDs[] = { + IDC_DLGTITLE3, + 0 + }; + static int sgGameDescID[] = { + IDC_GAMEDESC, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgListIDs[] = { + IDC_GAMEBTN1, + IDC_GAMEBTN2, + IDC_GAMEBTN3, + IDC_GAMEBTN4, + IDC_GAMEBTN5, + IDC_GAMEBTN6, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** + #define GAMENAME_LEN SNETSPI_MAXSTRINGLENGTH + #define DESCRIPTION_LEN SNETSPI_MAXSTRINGLENGTH + + typedef struct _ipxgame TIPXGAME; + typedef TIPXGAME *TPIPXGAME; + struct _ipxgame { + TPIPXGAME next; + DWORD gameid; + BOOL gamevalid; + TCHAR gamename[GAMENAME_LEN]; + TCHAR gamedesc[DESCRIPTION_LEN]; + }; + static TPIPXGAME sgGameList; + static int sgIPXListLen; + static BOOL sgGamesChanged; + + static SNETPROGRAMDATAPTR sgIPXProgramData; + static SNETPLAYERDATAPTR sgIPXPlayerData; + static SNETUIDATAPTR sgIPXInterfaceData; + static SNETVERSIONDATAPTR sgIPXVersionData; + static DWORD *sgpIPXPlayerID; + + +//**************************************************************************** +//**************************************************************************** +TPIPXGAME SelIPXAllocNode(void) { + return (TPIPXGAME) ALLOC(sizeof(TIPXGAME)); +} +//**************************************************************************** +//**************************************************************************** +static void SelIPXFreeNode(TPIPXGAME node) { + if (node) FREE(node); +} +//**************************************************************************** +//**************************************************************************** +static void SelIPXFreeList(TPIPXGAME list) { + TPIPXGAME next; + + while (list) { + next = list->next; + SelIPXFreeNode(list); + list = next; + } +} +//**************************************************************************** +//**************************************************************************** +static TPIPXGAME SelIPXAddNode(TPIPXGAME list, TPIPXGAME node) { + node->next = list; + return node; +} +//**************************************************************************** +// insert a node at the end of the list +//**************************************************************************** +static TPIPXGAME SelIPXAddEnd(TPIPXGAME list, TPIPXGAME node) { + TPIPXGAME head = list; + TPIPXGAME curr = list; + TPIPXGAME prev = NULL; + +// while (curr && curr->gameid) { + while (curr) { + prev = curr; + curr = curr->next; + } + + node->next = curr; + if (prev) + prev->next = node; + else + head = node; + + return head; +} +//**************************************************************************** +//**************************************************************************** +static TPIPXGAME SelIPXFindNode(TPIPXGAME list, DWORD gameid) { + while (list) { + if (list->gameid == gameid) + break; + list = list->next; + } + return list; +} +static TPIPXGAME SelIPXFindNodeName(TPIPXGAME list, LPCSTR name) { + while (list) { + if (! stricmp(list->gamename, name)) + break; + list = list->next; + } + return list; +} + + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXInvalAll(TPIPXGAME list) { + while (list) { + list->gamevalid = FALSE; + list = list->next; + } +} + + +//**************************************************************************** +//**************************************************************************** +static TPIPXGAME SelIPXDeleteInval(TPIPXGAME list) { + TPIPXGAME head = list; + TPIPXGAME curr = list; + TPIPXGAME prev = NULL; + + while (curr) { + // skip valid nodes & the "create" node + if ((curr->gamevalid) || (! curr->gameid)) { + prev = curr; + curr = curr->next; + continue; + } + + // set the next of the previous to point at next of invalid node + if (prev) + prev->next = curr->next; + else + head = curr->next; + + // remove the invalid node from the list + SelIPXFreeNode(curr); + sgGamesChanged = TRUE; + sgIPXListLen--; + + // set the new curr + if (prev) + curr = prev->next; + else + curr = head->next; + } + + return head; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelIPXEnum(DWORD gameid, + LPCSTR gamename, + LPCSTR gamedesc) { + TPIPXGAME newgame; + + // see if the game is already in the list + if (NULL != (newgame = SelIPXFindNode(sgGameList, gameid))) { + newgame->gamevalid = TRUE; + return TRUE; + } + + // the game needs to be added to the list + newgame = SelIPXAllocNode(); + if (! newgame) return FALSE; + newgame->gameid = gameid; + newgame->gamevalid = TRUE; + newgame->next = NULL; + strcpy(newgame->gamename, gamename); + strcpy(newgame->gamedesc, gamedesc); + sgGameList = SelIPXAddEnd(sgGameList, newgame); + sgIPXListLen++; + sgGamesChanged = TRUE; + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXSetGames(HWND window, TPIPXGAME gamelist) { + HWND child; + TPBMP tpBmp; + int * ctrlid = sgListIDs; + + for (; *ctrlid; ctrlid++) { + child = GetDlgItem(window, *ctrlid); + if (! child) continue; + + if (! gamelist) { + // no list entry for this button + if (child == GetFocus()) + SelIPXShiftTab(child); + EnableWindow(child, FALSE); + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (tpBmp) { + tpBmp->userdata = (LONG) NULL; + UiSetBmpText(tpBmp, ""); + } + } + else { + // set the button to use this list entry + EnableWindow(child, TRUE); + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (tpBmp) { + tpBmp->userdata = (LONG) gamelist; + UiSetBmpText(tpBmp, gamelist->gamename); + } + gamelist = gamelist->next; + } + } + + UiDoomButtonsReset(window, sgListIDs, AF_MED); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXSetInfo(HWND window, int childid) { + TPBMP tpBmp; + TPIPXGAME tpGame; + HWND child = GetDlgItem(window, childid); + HWND gamedesc = GetDlgItem(window, IDC_GAMEDESC); + + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + tpGame = (TPIPXGAME) tpBmp->userdata; + if (! tpGame) return; + + if (! tpGame->gameid) { + // handle the "new game" option + UiSetBmpText((TPBMP)GetWindowLong(gamedesc, GWL_USERDATA), tpGame->gamedesc); + UiDoomStaticReset(window, sgGameDescID, AF_SMALLGRAY); + return; + } + + // make sure there is game desc info + if ((! tpGame->gamedesc) || (strlen(tpGame->gamedesc) < MIN_DESC_LEN)) { + UiSetBmpText((TPBMP)GetWindowLong(gamedesc, GWL_USERDATA), ""); + UiDoomStaticReset(window, sgGameDescID, AF_SMALLGRAY); + return; + } + + // convert the gamedesc into something the user understands + TCHAR szGameDescCopy[128]; + TCHAR szGameInfo[256]; + TGAMEDATA GameData; + TUIHEROINFO HeroInfo; + char * szCreator = ""; + char * szCreatorDesc = ""; + + strcpy(szGameDescCopy, tpGame->gamedesc); + if ( + (! Txt2GameData(szGameDescCopy, &GameData, &szCreator, &szCreatorDesc)) || + (! Txt2HeroInfo(szCreatorDesc, &HeroInfo)) + ) { + UiSetBmpText((TPBMP)GetWindowLong(gamedesc, GWL_USERDATA), NULL); + UiDoomStaticReset(window, sgGameDescID, AF_SMALLGRAY); + return; + } + + TCHAR szDiff[32]; + TCHAR szClass[32]; + TCHAR szDescFmt[128]; + LoadString(global_hinstance, IDS_DIFF_NORMAL + GameData.bDiff, szDiff, 31); + LoadString(global_hinstance, IDS_WARRIOR + HeroInfo.heroclass, szClass, 31); + LoadString(global_hinstance, IDS_GAMEDESCFMT, szDescFmt, 127); + wsprintf(szGameInfo, szDescFmt, szDiff, szCreator, HeroInfo.level, szClass); + + UiSetBmpText((TPBMP)GetWindowLong(gamedesc, GWL_USERDATA), szGameInfo); + UiDoomStaticReset(window, sgGameDescID, AF_SMALLGRAY); +} + + +//**************************************************************************** +//**************************************************************************** +static int SelIPXGetFocusNum(void) { + HWND btn = GetFocus(); + if (! btn) return 0; + TPBMP tpBmp = (TPBMP) GetWindowLong(btn, GWL_USERDATA); + if (! tpBmp) return 0; + TPIPXGAME list = sgGameList; + if (! list) return 0; + TPIPXGAME node = (TPIPXGAME) tpBmp->userdata; + if (! node) return 0; + + int nodenum = 0; + + while (list && (list != node)) { + nodenum++; + list = list->next; + } + + return nodenum; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXUpdateSbar(HWND window) { + SbarDraw(window, IDC_SCROLLBAR, sgIPXListLen, SelIPXGetFocusNum()); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXUpdateGames(HWND window) { + // assume all games are invalid + sgGamesChanged = FALSE; + SelIPXInvalAll(sgGameList); + + // enum the games to update the list + SNetEnumGames(0, 0, SelIPXEnum, NULL); //### MM Diablo Patch #2 3/21/97 + + // delete games that are no longer valid + sgGameList = SelIPXDeleteInval(sgGameList); + + // set game buttons to contain text + if (sgGamesChanged) { + SelIPXSetGames(window, sgGameList); + #if SB_ALWAYS_ON != 1 + if (sgIPXListLen <= MAX_VISIBLE) { + ShowWindow(GetDlgItem(window, IDC_SCROLLBAR), FALSE); + } + else { + ShowWindow(GetDlgItem(window, IDC_SCROLLBAR), TRUE); + } + #endif + SelIPXSetInfo(window, GetWindowLong(GetFocus(), GWL_ID)); + SelIPXUpdateSbar(window); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXDestroy(HWND window) { + SelIPXFreeList(sgGameList); + sgGameList = NULL; + + SbarDestroy(window, IDC_SCROLLBAR); + + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgGameDescID); + UiDoomCtrlsDestroy(window, sgTextIDs); + UiDoomCtrlsDestroy(window, sgTitleIDs); + + // free the background of the dlg + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + TitleLogoDestroy(); + FocusAnimateDestroy(); + SDrawClearSurface(SDRAW_SURFACE_FRONT); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXTab(HWND child) { + HWND parent, newfocus; + int index; + int NewID[] = { + IDC_GAMEBTN2, + IDC_GAMEBTN3, + IDC_GAMEBTN4, + IDC_GAMEBTN5, + IDC_GAMEBTN6, + IDC_GAMEBTN1 + }; + + parent = GetParent(child); + newfocus = child; + do { + index = GetWindowLong(newfocus, GWL_ID) - IDC_GAMEBTN1; + newfocus = GetDlgItem(parent, NewID[index]); + } while (! IsWindowEnabled(newfocus)); + SetFocus(newfocus); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXShiftTab(HWND child) { + HWND parent, newfocus; + int index; + int NewID[] = { + IDC_GAMEBTN6, + IDC_GAMEBTN1, + IDC_GAMEBTN2, + IDC_GAMEBTN3, + IDC_GAMEBTN4, + IDC_GAMEBTN5 + }; + + parent = GetParent(child); + newfocus = child; + do { + index = GetWindowLong(newfocus, GWL_ID) - IDC_GAMEBTN1; + newfocus = GetDlgItem(parent, NewID[index]); + } while (! IsWindowEnabled(newfocus)); + SetFocus(newfocus); +} + + +//**************************************************************************** +//**************************************************************************** +static int GetNumIPXNode(HWND btn) { + if (! btn) return 0; + TPBMP tpBmp = (TPBMP) GetWindowLong(btn, GWL_USERDATA); + if (! tpBmp) return 0; + TPIPXGAME list = sgGameList; + if (! list) return 0; + TPIPXGAME node = (TPIPXGAME) tpBmp->userdata; + if (! node) return 0; + + int nodenum = 0; + + while (list && (list != node)) { + nodenum++; + list = list->next; + } + + return nodenum; +} + + +//**************************************************************************** +//**************************************************************************** +static TPIPXGAME GetGame(int index) { + TPIPXGAME list = sgGameList; + + while (list && index) { + list = list->next; + index--; + } + return list; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXPageDown(HWND focus) { + HWND parent = GetParent(focus); + if (! parent) return; + + // get info of 1st btn + HWND btn1 = GetDlgItem(parent, IDC_GAMEBTN1); + if (! btn1) return; + + // see if there is info below the bottom + TPBMP tpBmp = (TPBMP) GetWindowLong(GetDlgItem(parent, IDC_GAMEBTN6), GWL_USERDATA); + if (! tpBmp) return; + TPIPXGAME tpGame = (TPIPXGAME) tpBmp->userdata; + if ((! tpGame) || (! tpGame->next)) { + SelIPXShiftTab(btn1); + return; + } + + // calc the index of the new top + int newtop = GetNumIPXNode(btn1) + MAX_VISIBLE; + if (newtop > (sgIPXListLen - MAX_VISIBLE)) + newtop = sgIPXListLen - MAX_VISIBLE; + + // get the pointer to that index + tpGame = GetGame(newtop); + if (! tpGame) return; + + // update everything on the screen + UiSndPlayClick(); + SelIPXSetGames(parent, tpGame); + SelIPXSetInfo(parent, GetWindowLong(focus, GWL_ID)); + SelIPXUpdateSbar(parent); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXPageUp(HWND focus) { + HWND parent = GetParent(focus); + if (! parent) return; + HWND btn1 = GetDlgItem(parent, IDC_GAMEBTN1); + if (! btn1) return; + + // see if there is info off the top + TPBMP tpBmp = (TPBMP) GetWindowLong(btn1, GWL_USERDATA); + if (! tpBmp) return; + TPIPXGAME tpGame = (TPIPXGAME) tpBmp->userdata; + if (! tpGame) return; + if (tpGame == sgGameList) { + SelIPXTab(GetDlgItem(parent, IDC_GAMEBTN6)); + return; + } + + // calc the index of the new top + int newtop = GetNumIPXNode(btn1) - MAX_VISIBLE; + if (newtop < 0) + newtop = 0; + + // get the pointer to that index + tpGame = GetGame(newtop); + if (! tpGame) return; + + // update everything on the screen + UiSndPlayClick(); + SelIPXSetGames(parent, tpGame); + SelIPXSetInfo(parent, GetWindowLong(focus, GWL_ID)); + SelIPXUpdateSbar(parent); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXScrollDown(HWND focus) { + // see if there is info below the focus + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (! tpBmp) return; + TPIPXGAME tpGame = (TPIPXGAME) tpBmp->userdata; + if (! tpGame) return; + if (! tpGame->next) return; + + if (GetWindowLong(focus, GWL_ID) < IDC_GAMEBTN6) { + // handle it just like a tab + SelIPXTab(focus); + return; + } + + // advance the list + HWND child = GetDlgItem(GetParent(focus), IDC_GAMEBTN2); + if (! child) return; + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + tpGame = (TPIPXGAME) tpBmp->userdata; + if (! tpGame) return; + UiSndPlayClick(); + SelIPXSetGames(GetParent(focus), tpGame); + SelIPXSetInfo(GetParent(focus), GetWindowLong(focus, GWL_ID)); + SelIPXUpdateSbar(GetParent(focus)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXScrollUp(HWND focus) { + if (GetWindowLong(focus, GWL_ID) > IDC_GAMEBTN1) { + // handle it just like a shift-tab + SelIPXShiftTab(focus); + return; + } + + // see if there is info off the top + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (! tpBmp) return; + TPIPXGAME tpGame = (TPIPXGAME) tpBmp->userdata; + if (! tpGame) return; + TPIPXGAME tpGameList = sgGameList; + if (tpGame == tpGameList) return; + + // retreat the list + while (tpGameList && (tpGameList->next != tpGame)) { + tpGameList = tpGameList->next; + } + UiSndPlayClick(); + SelIPXSetGames(GetParent(focus), tpGameList); + SelIPXSetInfo(GetParent(focus), GetWindowLong(focus, GWL_ID)); + SelIPXUpdateSbar(GetParent(focus)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXShowList(HWND window, BOOL showflag) { + HWND child; + int childid; + + for (childid = IDC_GAMEBTN1; childid <= IDC_GAMEBTN6; childid++) { + child = GetDlgItem(window, childid); + if (! child) continue; + ShowWindow(child, showflag); + } + + child = GetDlgItem(window, IDC_SCROLLBAR); + if (sgIPXListLen <= MAX_VISIBLE) { + ShowWindow(child, FALSE); + } + else { + ShowWindow(child, showflag); + } +} + + +//**************************************************************************** +//**************************************************************************** +static LRESULT CALLBACK IPXListEntryWndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + LRESULT result; + WNDPROC oldproc = (WNDPROC) GetProp(window, OLDPROCPROP); + + switch (message) { + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_KEYDOWN: + switch (wparam) { + case VK_SPACE: + case VK_RETURN: + SendMessage(GetParent(window), WM_COMMAND, IDOK, (LPARAM)NULL); + break; + + case VK_ESCAPE: + SendMessage(GetParent(window), WM_COMMAND, IDCANCEL, (LPARAM)NULL); + break; + + case VK_TAB: + if (GetKeyState(VK_SHIFT) < 0) { + SelIPXShiftTab(window); + } + else { + SelIPXTab(window); + } + break; + + case VK_UP: + case VK_LEFT: + SelIPXScrollUp(window); + break; + + case VK_DOWN: + case VK_RIGHT: + SelIPXScrollDown(window); + break; + + case VK_PRIOR: + SelIPXPageUp(window); + break; + + case VK_NEXT: + SelIPXPageDown(window); + break; + + case VK_DELETE: + SendMessage(GetParent(window),message,wparam,lparam); + break; + } + return 0; + + case WM_DESTROY: + RemoveProp(window, OLDPROCPROP); + if (oldproc) { + SetWindowLong(window, GWL_WNDPROC, (LONG) oldproc); + } + break; + + case WM_PAINT: + UiPaintBtn(window); + return 0; + } + + if (oldproc) + result = CallWindowProc(oldproc, window, message, wparam, lparam); + else + result = DefWindowProc(window, message, wparam, lparam); + return result; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXSubclassEntries(HWND window) { + HWND child; + int *ListID; + WNDPROC oldproc; + + for (ListID = sgListIDs; *ListID; ListID++) { + child = GetDlgItem(window, *ListID); + if (! child) continue; + + oldproc = (WNDPROC) GetWindowLong(child, GWL_WNDPROC); + SetProp(child, OLDPROCPROP,(HANDLE) oldproc); + SetWindowLong(child, GWL_WNDPROC, (LONG) IPXListEntryWndProc); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXInit(HWND window) { + TPBMP tpBmp; + + SelIPXSubclassEntries(window); + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus16.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + // set up the animating diablo logo + TitleLogoInit(window); + TitleFramesInit(window,TEXT("ui_art\\hf_logo2.pcx")); + TitleLogoAnimate(window); + SDlgSetTimer(window, LOGO_TIMER_ID, LOGO_TIMER_DELAY, NULL); + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\selgame.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window); + } + + // if the provider is not IPX use a generic title + if (UiGetProviderID() != PROVIDERID) { + TCHAR generictitle[64]; + HWND child = GetDlgItem(window, IDC_DLGTITLE); + LoadString(global_hinstance, IDS_JOINGAMES, generictitle, 63); + SetWindowText(child, generictitle); + } + + // set up a doom-like interface + UiDoomStaticInit(window, sgTitleIDs, AF_BIGGRAY); + UiDoomStaticInit(window, sgTextIDs, AF_MEDGRAY); + UiDoomStaticInit(window, sgGameDescID, AF_SMALLGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_MED); + + // set a "create game" option + sgIPXListLen = 0; + sgGameList = SelIPXAllocNode(); + if (sgGameList) { + sgIPXListLen++; + sgGameList->gameid = 0; + sgGameList->gamedesc[0] = 0; + sgGameList->next = NULL; + LoadString(global_hinstance, IDS_CREATEGAME, sgGameList->gamename, GAMENAME_LEN-1); + LoadString(global_hinstance, IDS_CREATEDESC, sgGameList->gamedesc, DESCRIPTION_LEN-1); + } + + // get list of games + SNetEnumGames(0, 0, SelIPXEnum, NULL); //### MM Diablo Patch #2 3/21/97 + SelIPXSetGames(window, sgGameList); + + // set a timer so the game list is periodically updated + SDlgSetTimer(window, ENUM_TIMER_ID, ENUM_TIMER_DELAY, NULL); + + // init the scroll bar + SbarInit(window, IDC_SCROLLBAR); +#if SB_ALWAYS_ON != 1 + if (sgIPXListLen <= MAX_VISIBLE) { + ShowWindow(GetDlgItem(window, IDC_SCROLLBAR), FALSE); + } +#endif +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXAbort(HWND window, int ReturnVal) { + UiFadeAbort(window); + SDlgKillTimer(window, ENUM_TIMER_ID); + SDlgKillTimer(window, LOGO_TIMER_ID); + SDlgKillTimer(window, FOCUS_TIMER_ID); + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXDetermineGameName(LPSTR gamename) { + if (! SelIPXFindNodeName(sgGameList, sgIPXPlayerData->playername)) { + strcpy(gamename, sgIPXPlayerData->playername); + return; + } + + int gamenum = 2; + do { + wsprintf(gamename, "%s %d", sgIPXPlayerData->playername, gamenum++); + } while (SelIPXFindNodeName(sgGameList, gamename)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXCreate(HWND window) { + SNETUIDATA interfacedata; + SNETCREATEDATA createdata; + + // make sure the list is current + SelIPXUpdateGames(window); + + // create new interface data + CopyMemory(&interfacedata,sgIPXInterfaceData,sizeof(SNETUIDATA)); + interfacedata.size = sizeof(SNETUIDATA); + interfacedata.parentwindow = window; + + ZeroMemory(&createdata,sizeof(SNETCREATEDATA)); + createdata.size = sizeof(SNETCREATEDATA); + createdata.providerid = PROVIDERID; + createdata.maxplayers = sgIPXProgramData->maxplayers; + createdata.createflags = 0; + + HWND focus = GetFocus(); + SelIPXShowList(window, FALSE); + + char gamename[SNETSPI_MAXSTRINGLENGTH]; + SelIPXDetermineGameName(gamename); + + if (UiDoomCreateGame( + &createdata, + sgIPXProgramData, + sgIPXPlayerData, + &interfacedata, + sgIPXVersionData, + sgpIPXPlayerID, + FALSE, + gamename + ) + ) { + SelIPXAbort(window, IDOK); + } + else { + SelIPXShowList(window, TRUE); + SetFocus(focus); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXJoin(HWND window, TPIPXGAME tpGame) { + char err[256]; + if (! + UiAuthCallback( + SNET_AUTHTYPE_GAME, + sgIPXPlayerData->playername, + sgIPXPlayerData->playerdescription, + 0, + tpGame->gamedesc, + err, + sizeof(err) + ) + ) { + SelOkDialog(window, err, NULL, FALSE); + return; + } + + if (SNetJoinGame( + tpGame->gameid, + tpGame->gamename, + NULL, + sgIPXPlayerData->playername, + sgIPXPlayerData->playerdescription, + sgpIPXPlayerID + ) + ) { + SelIPXAbort(window, IDOK); + } + else { + // unable to join the specified game + TCHAR format[64], errstr[128]; + LoadString(global_hinstance, IDS_JOIN_ERR, format, 63); + wsprintf(errstr, format, tpGame->gamename); + SelOkDialog(window, errstr, NULL, FALSE); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXAttemptJoin(HWND window) { + TPBMP tpBmp; + TPIPXGAME tpGame; + HWND child = GetFocus(); + + if (window != GetParent(child)) return; + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + tpGame = (TPIPXGAME) tpBmp->userdata; + + UiSndPlayEnter(); + if (tpGame->gameid) + SelIPXJoin(window, tpGame); + else + SelIPXCreate(window); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelIPXInterpretClick(HWND window, int x, int y) { + if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKEOK), x, y)) { + SelIPXAttemptJoin(window); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKECANCEL), x, y)) { + SelIPXAbort(window, IDCANCEL); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_SCROLLBAR), x, y)) { + int SbarClick = SbarInterpretClick(GetDlgItem(window, IDC_SCROLLBAR), x, y); + switch (SbarClick) { + case DSB_UP: + SelIPXScrollUp(GetFocus()); + break; + case DSB_PAGEUP: + SelIPXPageUp(GetFocus()); + break; + case DSB_DOWN: + SelIPXScrollDown(GetFocus()); + break; + case DSB_PAGEDOWN: + SelIPXPageDown(GetFocus()); + break; + default: + break; + } + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelIPXDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + SelIPXSetInfo(window, LOWORD(wparam)); + SelIPXUpdateSbar(window); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + SelIPXAttemptJoin(window); + } + else if (LOWORD(wparam) == IDOK) { + SelIPXAttemptJoin(window); + } + else if (LOWORD(wparam) == IDCANCEL) { + SelIPXAbort(window, IDCANCEL); + } + break; + + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + SelIPXInterpretClick(window, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_LBUTTONUP: + if (SbarUpClick(GetDlgItem(window, IDC_SCROLLBAR))) { + SelIPXUpdateSbar(window); + } + break; + + case WM_DESTROY: + SelIPXDestroy(window); + break; + + case WM_INITDIALOG: + SelIPXInit(window); + PostMessage(window, WM_USER+1000, 0, 0); + return 0; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_TIMER: + switch (wparam) { + case FOCUS_TIMER_ID: + FocusAnimate(window, GetFocus()); + break; + case LOGO_TIMER_ID: + TitleLogoAnimate(window); + break; + case ENUM_TIMER_ID: + SelIPXUpdateGames(window); + break; + } + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiSelectIPXGame (DWORD flags, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata, + DWORD *playerid) { + int result = 0; + + // save parameters for use throughout this file + sgIPXProgramData = programdata; + sgIPXPlayerData = playerdata; + sgIPXInterfaceData = interfacedata; + sgIPXVersionData = versiondata; + sgpIPXPlayerID = playerid; + + // make sure fonts are loaded + ArtFontLoad(); + + // DISPLAY THE DIALOG BOX + result = SDlgDialogBox(global_hinstance, + TEXT("SELIPXGAME_DIALOG"), + interfacedata->parentwindow, + SelIPXDialogProc); + + ArtFontDestroy(); + + if (result == IDOK) + return TRUE; + + return FALSE; +} diff --git a/src/Uisrc/UI/SELLIST.CPP b/src/Uisrc/UI/SELLIST.CPP new file mode 100644 index 0000000..3543ee6 --- /dev/null +++ b/src/Uisrc/UI/SELLIST.CPP @@ -0,0 +1,606 @@ +//**************************************************************************** +// SelList.cpp +// Diablo UI select hero dialogs +// +// By Frank Pearce +// created 10.18.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern void SelHeroSetStats(HWND window, TPUIHEROINFO hero); + extern void SelHeroClearStats(HWND window); + extern void SelHeroSetTitle(HWND window, LPCTSTR title); + extern int SelHeroGetMode(void); + extern TPUIHEROINFO GetHeroList(void); + extern int GetNumHeros(void); + extern LPCTSTR SelectedName(void); + + +//**************************************************************************** +//**************************************************************************** + #define OLDPROCPROP TEXT("UIOLDPROC") + + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define MAX_VISIBLE (IDC_HEROBTN6 - IDC_HEROBTN1 + 1) + + +//**************************************************************************** +//**************************************************************************** + static TPUIHEROINFO sgFirstHero = NULL; + + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgDeleteIDs[] = { + IDDELETE, + 0 + }; + static int sgListIDs[] = { + IDC_HEROBTN1, + IDC_HEROBTN2, + IDC_HEROBTN3, + IDC_HEROBTN4, + IDC_HEROBTN5, + IDC_HEROBTN6, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** +static void SelListDestroy(HWND window) { + SbarDestroy(window, IDC_SCROLLBAR); + FocusAnimateDestroy(); + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgDeleteIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + SelHeroSetTitle(GetParent(window), NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListSetList(HWND window, TPUIHEROINFO firsthero) { + HWND child; + TPBMP tpBmp; + int *ListID; + + for (ListID = sgListIDs; *ListID; ListID++) { + child = GetDlgItem(window, *ListID); + if (! child) + continue; + + if (! firsthero) { + EnableWindow(child, FALSE); + continue; + } + + EnableWindow(child, TRUE); + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + UiSetBmpText(tpBmp, firsthero->name); + if (tpBmp) + tpBmp->userdata = (LONG) firsthero; + + firsthero = firsthero->next; + } + + UiDoomButtonsReset(window, sgListIDs, AF_MED); +} + + +//**************************************************************************** +//**************************************************************************** +static void UpdateStats(HWND window, int childid) { + HWND child = GetDlgItem(window, childid); + if (! child) return; + TPBMP tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + TPUIHEROINFO focusedhero = (TPUIHEROINFO) tpBmp->userdata; + + if (focusedhero) { + if (focusedhero->level) + UiDoomButtonsReset(window, sgDeleteIDs, AF_BIG, FALSE); + else + UiDoomButtonsReset(window, sgDeleteIDs, AF_BIGGRAY, FALSE); + SelHeroSetStats(GetParent(window), focusedhero); + } + else { + UiDoomButtonsReset(window, sgDeleteIDs, AF_BIGGRAY, FALSE); + SelHeroClearStats(GetParent(window)); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListTab(HWND child) { + HWND parent, newfocus; + int index; + int NewID[] = { + IDC_HEROBTN2, + IDC_HEROBTN3, + IDC_HEROBTN4, + IDC_HEROBTN5, + IDC_HEROBTN6, + IDC_HEROBTN1 + }; + + parent = GetParent(child); + newfocus = child; + do { + index = GetWindowLong(newfocus, GWL_ID) - IDC_HEROBTN1; + newfocus = GetDlgItem(parent, NewID[index]); + } while (! IsWindowEnabled(newfocus)); + SetFocus(newfocus); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListShiftTab(HWND child) { + HWND parent, newfocus; + int index; + int NewID[] = { + IDC_HEROBTN6, + IDC_HEROBTN1, + IDC_HEROBTN2, + IDC_HEROBTN3, + IDC_HEROBTN4, + IDC_HEROBTN5 + }; + + parent = GetParent(child); + newfocus = child; + do { + index = GetWindowLong(newfocus, GWL_ID) - IDC_HEROBTN1; + newfocus = GetDlgItem(parent, NewID[index]); + } while (! IsWindowEnabled(newfocus)); + SetFocus(newfocus); +} + + +//**************************************************************************** +//**************************************************************************** +static int GetNumNode(HWND btn) { + if (! btn) return 0; + TPBMP tpBmp = (TPBMP) GetWindowLong(btn, GWL_USERDATA); + if (! tpBmp) return 0; + TPUIHEROINFO list = GetHeroList(); + if (! list) return 0; + TPUIHEROINFO node = (TPUIHEROINFO) tpBmp->userdata; + if (! node) return 0; + + int nodenum = 0; + + while (list && (list != node)) { + nodenum++; + list = list->next; + } + + return nodenum; +} + + +//**************************************************************************** +//**************************************************************************** +static TPUIHEROINFO GetHero(int index) { + TPUIHEROINFO list = GetHeroList(); + + while (list && index) { + list = list->next; + index--; + } + return list; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListUpdateSbar(HWND window) { + SbarDraw(window, IDC_SCROLLBAR, GetNumHeros(), GetNumNode(GetFocus())); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListPageDown(HWND focus) { + HWND parent = GetParent(focus); + if (! parent) return; + + // get info of 1st btn + HWND btn1 = GetDlgItem(parent, IDC_HEROBTN1); + if (! btn1) return; + + // see if there is info below the bottom + TPBMP tpBmp = (TPBMP) GetWindowLong(GetDlgItem(parent, IDC_HEROBTN6), GWL_USERDATA); + if (! tpBmp) return; + TPUIHEROINFO tpHero = (TPUIHEROINFO) tpBmp->userdata; + if ((! tpHero) || (! tpHero->next)) { + SelListShiftTab(btn1); + return; + } + + // calc the index of the new top + int newtop = GetNumNode(btn1) + MAX_VISIBLE; + if (newtop > (GetNumHeros() - MAX_VISIBLE)) + newtop = GetNumHeros() - MAX_VISIBLE; + + // get the pointer to that index + tpHero = GetHero(newtop); + if (! tpHero) return; + + // update everything on the screen + UiSndPlayClick(); + SelListSetList(parent, tpHero); + UpdateStats(parent, GetWindowLong(focus, GWL_ID)); + SelListUpdateSbar(parent); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListPageUp(HWND focus) { + HWND parent = GetParent(focus); + if (! parent) return; + HWND btn1 = GetDlgItem(parent, IDC_HEROBTN1); + if (! btn1) return; + + // see if there is info off the top + TPBMP tpBmp = (TPBMP) GetWindowLong(btn1, GWL_USERDATA); + if (! tpBmp) return; + TPUIHEROINFO tpHero = (TPUIHEROINFO) tpBmp->userdata; + if (! tpHero) return; + if (tpHero == GetHeroList()) { + SelListTab(GetDlgItem(parent, IDC_HEROBTN6)); + return; + } + + // calc the index of the new top + int newtop = GetNumNode(btn1) - MAX_VISIBLE; + if (newtop < 0) + newtop = 0; + + // get the pointer to that index + tpHero = GetHero(newtop); + if (! tpHero) return; + + // update everything on the screen + UiSndPlayClick(); + SelListSetList(parent, tpHero); + UpdateStats(parent, GetWindowLong(focus, GWL_ID)); + SelListUpdateSbar(parent); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListScrollDown(HWND focus) { + // see if there is info below the focus + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (! tpBmp) return; + TPUIHEROINFO tpHero = (TPUIHEROINFO) tpBmp->userdata; + if (! tpHero) return; + if (! tpHero->next) return; + + if (GetWindowLong(focus, GWL_ID) < IDC_HEROBTN6) { + // handle it just like a tab + SelListTab(focus); + return; + } + + // advance the list + HWND child = GetDlgItem(GetParent(focus), IDC_HEROBTN2); + if (! child) return; + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + tpHero = (TPUIHEROINFO) tpBmp->userdata; + if (! tpHero) return; + UiSndPlayClick(); + SelListSetList(GetParent(focus), tpHero); + UpdateStats(GetParent(focus), GetWindowLong(focus, GWL_ID)); + SelListUpdateSbar(GetParent(focus)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListScrollUp(HWND focus) { + if (GetWindowLong(focus, GWL_ID) > IDC_HEROBTN1) { + // handle it just like a shift-tab + SelListShiftTab(focus); + return; + } + + // see if there is info off the top + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (! tpBmp) return; + TPUIHEROINFO tpHero = (TPUIHEROINFO) tpBmp->userdata; + TPUIHEROINFO tpHeroList; + if (! tpHero) return; + if (tpHero == (tpHeroList = GetHeroList())) return; + + // retreat the list + while (tpHeroList && (tpHeroList->next != tpHero)) { + tpHeroList = tpHeroList->next; + } + UiSndPlayClick(); + SelListSetList(GetParent(focus), tpHeroList); + UpdateStats(GetParent(focus), GetWindowLong(focus, GWL_ID)); + SelListUpdateSbar(GetParent(focus)); +} + + +//**************************************************************************** +//**************************************************************************** +static LRESULT CALLBACK ListEntryWndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + LRESULT result; + WNDPROC oldproc = (WNDPROC) GetProp(window, OLDPROCPROP); + + switch (message) { + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_KEYDOWN: + switch (wparam) { + case VK_SPACE: + case VK_RETURN: + SendMessage(GetParent(window), WM_COMMAND, IDOK, (LPARAM)NULL); + break; + + case VK_ESCAPE: + SendMessage(GetParent(window), WM_COMMAND, IDCANCEL, (LPARAM)NULL); + break; + + case VK_TAB: + if (GetKeyState(VK_SHIFT) < 0) { + SelListShiftTab(window); + } + else { + SelListTab(window); + } + break; + + case VK_UP: + case VK_LEFT: + SelListScrollUp(window); + break; + + case VK_DOWN: + case VK_RIGHT: + SelListScrollDown(window); + break; + + case VK_PRIOR: + SelListPageUp(window); + break; + + case VK_NEXT: + SelListPageDown(window); + break; + + case VK_DELETE: + SendMessage(GetParent(window),message,wparam,lparam); + break; + } + return 0; + + case WM_DESTROY: + RemoveProp(window, OLDPROCPROP); + if (oldproc) { + SetWindowLong(window, GWL_WNDPROC, (LONG) oldproc); + } + break; + + case WM_PAINT: + UiPaintBtn(window); + return 0; + } + + if (oldproc) + result = CallWindowProc(oldproc, window, message, wparam, lparam); + else + result = DefWindowProc(window, message, wparam, lparam); + return result; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListSubclassEntries(HWND window) { + HWND child; + int *ListID; + WNDPROC oldproc; + + for (ListID = sgListIDs; *ListID; ListID++) { + child = GetDlgItem(window, *ListID); + if (! child) continue; + + oldproc = (WNDPROC) GetWindowLong(child, GWL_WNDPROC); + SetProp(child, OLDPROCPROP,(HANDLE) oldproc); + SetWindowLong(child, GWL_WNDPROC, (LONG) ListEntryWndProc); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListInit(HWND window) { + TCHAR buf[32]; + HWND parent = GetParent(window); + + SelListSubclassEntries(window); + + // set the title for the parent + if (SelHeroGetMode() == MULTIPLAYER) + LoadString(global_hinstance, IDS_MULTILIST_TITLE, buf, 32-1); + else + LoadString(global_hinstance, IDS_SINGLIST_TITLE, buf, 32-1); + SelHeroSetTitle(parent, buf); + + // point this window at the same bmp it's parent uses + SetWindowLong( + window, + GWL_USERDATA, + GetWindowLong(parent, GWL_USERDATA) + ); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgDeleteIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_MED); + + // set the names into the fake listbox + sgFirstHero = GetHeroList(); + SelListSetList(window, sgFirstHero); + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus16.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + // init the scroll bar + SbarInit(window, IDC_SCROLLBAR); + if (GetNumHeros() <= MAX_VISIBLE) { + ShowWindow(GetDlgItem(window, IDC_SCROLLBAR), FALSE); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListAbort(HWND window, int ReturnVal) { + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelListInterpretClick(HWND window, int x, int y) { + if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKEOK), x, y)) { + SelListAbort(window, IDOK); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKECANCEL), x, y)) { + SelListAbort(window, IDCANCEL); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDDELETE), x, y)) { + if (strlen(SelectedName())) { + SelListAbort(window, IDDELETE); + } + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_SCROLLBAR), x, y)) { + int SbarClick = SbarInterpretClick(GetDlgItem(window, IDC_SCROLLBAR), x, y); + switch (SbarClick) { + case DSB_UP: + SelListScrollUp(GetFocus()); + break; + + case DSB_DOWN: + SelListScrollDown(GetFocus()); + break; + + case DSB_PAGEUP: + SelListPageUp(GetFocus()); + break; + + case DSB_PAGEDOWN: + SelListPageDown(GetFocus()); + break; + + default: + break; + } + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK SelListDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + UpdateStats(window, LOWORD(wparam)); + SelListUpdateSbar(window); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + SelListAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDOK) { + SelListAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDCANCEL) { + SelListAbort(window, IDCANCEL); + } + break; + + case WM_KEYDOWN: + if (wparam == VK_DELETE) { + if (strlen(SelectedName())) { + SelListAbort(window, IDDELETE); + } + } + break; + + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + SelListInterpretClick(window, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_LBUTTONUP: + if (SbarUpClick(GetDlgItem(window, IDC_SCROLLBAR))) { + SelListUpdateSbar(window); + } + break; + + case WM_DESTROY: + SelListDestroy(window); + break; + + case WM_INITDIALOG: + SelListInit(window); + return 0; + + case WM_TIMER: + FocusAnimate(window, GetFocus()); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} diff --git a/src/Uisrc/UI/SELLOAD.CPP b/src/Uisrc/UI/SELLOAD.CPP new file mode 100644 index 0000000..bf4c59b --- /dev/null +++ b/src/Uisrc/UI/SELLOAD.CPP @@ -0,0 +1,171 @@ +//**************************************************************************** +// SelLoad.cpp +// Diablo UI load/new game for a single player hero with a save file +// +// By Frank Pearce +// created 11.14.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern void SelHeroSetTitle(HWND window, LPCTSTR title); + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgListIDs[] = { + IDC_LOADBTN, + IDC_NEWBTN, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** +static void SelLoadDestroy(HWND window) { + FocusAnimateDestroy(); + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + SelHeroSetTitle(GetParent(window), NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelLoadInit(HWND window) { + TCHAR buf[32]; + HWND parent = GetParent(window); + + // set the title for the parent + LoadString(global_hinstance, IDS_SINGLIST_TITLE, buf, 32-1); + SelHeroSetTitle(parent, buf); + + // point this window at the same bmp it's parent uses + SetWindowLong( + window, + GWL_USERDATA, + GetWindowLong(parent, GWL_USERDATA) + ); + + UiOnPaintBtns(window, sgListIDs); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_MED); + + // set up the animating focus indicator + FocusAnimateInit("ui_art\\focus16.pcx"); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelLoadAbort(HWND window, int ReturnVal) { + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + + if (ReturnVal == IDOK) { + // return the id of the focused button + ReturnVal = GetWindowLong(GetFocus(), GWL_ID); + } + + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +BOOL CALLBACK SelLoadDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + SelLoadAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDOK) { + SelLoadAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDCANCEL) { + SelLoadAbort(window, IDCANCEL); + } + break; + + case WM_LBUTTONDOWN: + if ( + UiIsPtInWindow( + window, + GetDlgItem(window, IDC_FAKEOK), + LOWORD(lparam), + HIWORD(lparam) + ) + ) { + SelLoadAbort(window, IDOK); + } + else if ( + UiIsPtInWindow( + window, + GetDlgItem(window, IDC_FAKECANCEL), + LOWORD(lparam), + HIWORD(lparam) + ) + ) { + SelLoadAbort(window, IDCANCEL); + } + break; + + case WM_DESTROY: + SelLoadDestroy(window); + break; + + case WM_INITDIALOG: + SelLoadInit(window); + return 0; + + case WM_TIMER: + FocusAnimate(window, GetFocus()); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} diff --git a/src/Uisrc/UI/SELMODEM.CPP b/src/Uisrc/UI/SELMODEM.CPP new file mode 100644 index 0000000..c380214 --- /dev/null +++ b/src/Uisrc/UI/SELMODEM.CPP @@ -0,0 +1,769 @@ +//**************************************************************************** +// SelModem.cpp +// Diablo UI select modem from a list of modems +// +// By Frank Pearce +// created 11.22.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern int SelOkDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus); + extern BOOL CALLBACK ModmStatStatusCallback( + LPCSTR statstr, + DWORD completed, + DWORD remaining, + DWORD flags, + SNETABORTPROC abortfcn + ); + + +//**************************************************************************** +//**************************************************************************** + #define OLDPROCPROP TEXT("UIOLDPROC") + + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + #define MAX_VISIBLE (IDC_MODEMBTN6 - IDC_MODEMBTN1 + 1) + + +//**************************************************************************** +//**************************************************************************** + static TPMODEM sgModemList; + static int sgNumModems; + static DWORD sgDeviceID; + + static SNETPROGRAMDATAPTR sgSMProgramData; + static SNETPLAYERDATAPTR sgSMPlayerData; + static SNETUIDATAPTR sgSMInterfaceData; + static SNETVERSIONDATAPTR sgSMVersionData; + + static int sgTextIDs[] = { + IDC_DLGTITLE, + 0 + }; + static int sgText2IDs[] = { + IDC_DLGTITLE2, + IDC_DLGTITLE3, + 0 + }; + static int sgDescID[] = { + IDC_REQDESC, + 0 + }; + static int sgBtnIDs[] = { + IDC_FAKEOK, + IDC_FAKECANCEL, + 0 + }; + static int sgListIDs[] = { + IDC_MODEMBTN1, + IDC_MODEMBTN2, + IDC_MODEMBTN3, + IDC_MODEMBTN4, + IDC_MODEMBTN5, + IDC_MODEMBTN6, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** +static TPMODEM ModemAllocNode(void) { + return (TPMODEM) ALLOC(sizeof(TMODEM)); +} +//**************************************************************************** +//**************************************************************************** +static void ModemFreeNode(TPMODEM node) { + if (node) FREE(node); +} +//**************************************************************************** +//**************************************************************************** +static void ModemFreeList(TPMODEM list) { + TPMODEM next; + + while (list) { + next = list->next; + ModemFreeNode(list); + list = next; + } +} +//**************************************************************************** +//**************************************************************************** +static TPMODEM ModemAddNode(TPMODEM list, TPMODEM node) { + node->next = list; + return node; +} +//**************************************************************************** +//**************************************************************************** +static TPMODEM ModemFindNode(TPMODEM list, DWORD deviceid) { + while (list) { + if (list->deviceid == deviceid) + break; + list = list->next; + } + return list; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelModemEnum(DWORD deviceid, + LPCSTR devicename, + LPCSTR devicedesc) { + TPMODEM modem; + + modem = ModemAllocNode(); + if (! modem) return FALSE; + modem->next = NULL; + modem->deviceid = deviceid; + strcpy(modem->devicename, devicename); + strcpy(modem->devicedesc, devicedesc); + sgModemList = ModemAddNode(sgModemList, modem); + sgNumModems++; + return TRUE; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemDestroy(HWND window) { + SbarDestroy(window, IDC_SCROLLBAR); + UiDoomCtrlsDestroy(window, sgListIDs); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + UiDoomCtrlsDestroy(window, sgText2IDs); + UiDoomCtrlsDestroy(window, sgDescID); + + // free the background of the dlg + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemSetList(HWND window, TPMODEM firstmodem) { + HWND child; + TPBMP tpBmp; + int *ListID; + + for (ListID = sgListIDs; *ListID; ListID++) { + child = GetDlgItem(window, *ListID); + if (! child) + continue; + + if (! firstmodem) { + EnableWindow(child, FALSE); + continue; + } + + EnableWindow(child, TRUE); + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + UiSetBmpText(tpBmp, firstmodem->devicename); + if (tpBmp) + tpBmp->userdata = (LONG) firstmodem; + + firstmodem = firstmodem->next; + } + + UiDoomButtonsReset(window, sgListIDs, AF_SMALL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemTab(HWND child) { + HWND parent, newfocus; + int index; + int NewID[] = { + IDC_MODEMBTN2, + IDC_MODEMBTN3, + IDC_MODEMBTN4, + IDC_MODEMBTN5, + IDC_MODEMBTN6, + IDC_MODEMBTN1 + }; + + parent = GetParent(child); + newfocus = child; + do { + index = GetWindowLong(newfocus, GWL_ID) - IDC_MODEMBTN1; + newfocus = GetDlgItem(parent, NewID[index]); + } while (! IsWindowEnabled(newfocus)); + SetFocus(newfocus); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemShiftTab(HWND child) { + HWND parent, newfocus; + int index; + int NewID[] = { + IDC_MODEMBTN6, + IDC_MODEMBTN1, + IDC_MODEMBTN2, + IDC_MODEMBTN3, + IDC_MODEMBTN4, + IDC_MODEMBTN5 + }; + + parent = GetParent(child); + newfocus = child; + do { + index = GetWindowLong(newfocus, GWL_ID) - IDC_MODEMBTN1; + newfocus = GetDlgItem(parent, NewID[index]); + } while (! IsWindowEnabled(newfocus)); + SetFocus(newfocus); +} + + +//**************************************************************************** +//**************************************************************************** +static int GetNumNode(HWND btn) { + if (! btn) return 0; + TPBMP tpBmp = (TPBMP) GetWindowLong(btn, GWL_USERDATA); + if (! tpBmp) return 0; + TPMODEM list = sgModemList; + if (! list) return 0; + TPMODEM node = (TPMODEM) tpBmp->userdata; + if (! node) return 0; + + int nodenum = 0; + + while (list && (list != node)) { + nodenum++; + list = list->next; + } + + return nodenum; +} + + +//**************************************************************************** +//**************************************************************************** +static TPMODEM GetModem(int index) { + TPMODEM list = sgModemList; + + while (list && index) { + list = list->next; + index--; + } + return list; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemUpdateSbar(HWND window) { + SbarDraw(window, IDC_SCROLLBAR, sgNumModems, GetNumNode(GetFocus())); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemPageDown(HWND focus) { + HWND parent = GetParent(focus); + if (! parent) return; + + // get info of 1st btn + HWND btn1 = GetDlgItem(parent, IDC_MODEMBTN1); + if (! btn1) return; + + // see if there is info below the bottom + TPBMP tpBmp = (TPBMP) GetWindowLong(GetDlgItem(parent, IDC_MODEMBTN6), GWL_USERDATA); + if (! tpBmp) return; + TPMODEM tpModem = (TPMODEM) tpBmp->userdata; + if ((! tpModem) || (! tpModem->next)) { + SelModemShiftTab(btn1); + return; + } + + // calc the index of the new top + int newtop = GetNumNode(btn1) + MAX_VISIBLE; + if (newtop > (sgNumModems - MAX_VISIBLE)) + newtop = sgNumModems - MAX_VISIBLE; + + // get the pointer to that index + tpModem = GetModem(newtop); + if (! tpModem) return; + + // update everything on the screen + UiSndPlayClick(); + SelModemSetList(parent, tpModem); + SelModemUpdateSbar(parent); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemPageUp(HWND focus) { + HWND parent = GetParent(focus); + if (! parent) return; + HWND btn1 = GetDlgItem(parent, IDC_MODEMBTN1); + if (! btn1) return; + + // see if there is info off the top + TPBMP tpBmp = (TPBMP) GetWindowLong(btn1, GWL_USERDATA); + if (! tpBmp) return; + TPMODEM tpModem = (TPMODEM) tpBmp->userdata; + if (! tpModem) return; + if (tpModem == sgModemList) { + SelModemTab(GetDlgItem(parent, IDC_MODEMBTN6)); + return; + } + + // calc the index of the new top + int newtop = GetNumNode(btn1) - MAX_VISIBLE; + if (newtop < 0) + newtop = 0; + + // get the pointer to that index + tpModem = GetModem(newtop); + if (! tpModem) return; + + // update everything on the screen + UiSndPlayClick(); + SelModemSetList(parent, tpModem); + SelModemUpdateSbar(parent); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemScrollDown(HWND focus) { + // see if there is info below the focus + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (! tpBmp) return; + TPMODEM tpModem = (TPMODEM) tpBmp->userdata; + if (! tpModem) return; + if (! tpModem->next) return; + + if (GetWindowLong(focus, GWL_ID) < IDC_MODEMBTN6) { + // handle it just like a tab + SelModemTab(focus); + return; + } + + // advance the list + HWND child = GetDlgItem(GetParent(focus), IDC_MODEMBTN2); + if (! child) return; + tpBmp = (TPBMP) GetWindowLong(child, GWL_USERDATA); + if (! tpBmp) return; + tpModem = (TPMODEM) tpBmp->userdata; + if (! tpModem) return; + UiSndPlayClick(); + SelModemSetList(GetParent(focus), tpModem); + SelModemUpdateSbar(GetParent(focus)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemScrollUp(HWND focus) { + if (GetWindowLong(focus, GWL_ID) > IDC_MODEMBTN1) { + // handle it just like a shift-tab + SelModemShiftTab(focus); + return; + } + + // see if there is info off the top + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (! tpBmp) return; + TPMODEM tpModem = (TPMODEM) tpBmp->userdata; + TPMODEM tpModemList; + if (! tpModem) return; + if (tpModem == (tpModemList = sgModemList)) return; + + // retreat the list + while (tpModemList && (tpModemList->next != tpModem)) { + tpModemList = tpModemList->next; + } + UiSndPlayClick(); + SelModemSetList(GetParent(focus), tpModemList); + SelModemUpdateSbar(GetParent(focus)); +} + + +//**************************************************************************** +//**************************************************************************** +static LRESULT CALLBACK ModemListWndProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + LRESULT result; + WNDPROC oldproc = (WNDPROC) GetProp(window, OLDPROCPROP); + + switch (message) { + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_KEYDOWN: + switch (wparam) { + case VK_SPACE: + case VK_RETURN: + SendMessage(GetParent(window), WM_COMMAND, IDOK, (LPARAM)NULL); + break; + + case VK_ESCAPE: + SendMessage(GetParent(window), WM_COMMAND, IDCANCEL, (LPARAM)NULL); + break; + + case VK_TAB: + if (GetKeyState(VK_SHIFT) < 0) { + SelModemShiftTab(window); + } + else { + SelModemTab(window); + } + break; + + case VK_UP: + case VK_LEFT: + SelModemScrollUp(window); + break; + + case VK_DOWN: + case VK_RIGHT: + SelModemScrollDown(window); + break; + + case VK_PRIOR: + SelModemPageUp(window); + break; + + case VK_NEXT: + SelModemPageDown(window); + break; + } + return 0; + + case WM_DESTROY: + RemoveProp(window, OLDPROCPROP); + if (oldproc) { + SetWindowLong(window, GWL_WNDPROC, (LONG) oldproc); + } + break; + + case WM_PAINT: + UiPaintBtn(window); + return 0; + } + + if (oldproc) + result = CallWindowProc(oldproc, window, message, wparam, lparam); + else + result = DefWindowProc(window, message, wparam, lparam); + return result; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemSubclassEntries(HWND window) { + HWND child; + int *ListID; + WNDPROC oldproc; + + for (ListID = sgListIDs; *ListID; ListID++) { + child = GetDlgItem(window, *ListID); + if (! child) continue; + + oldproc = (WNDPROC) GetWindowLong(child, GWL_WNDPROC); + SetProp(child, OLDPROCPROP,(HANDLE) oldproc); + SetWindowLong(child, GWL_WNDPROC, (LONG) ModemListWndProc); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemInit(HWND window) { + HWND parent = GetParent(window); + + SelModemSubclassEntries(window); + + // load texture maps for this dialog + TPBMP tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT("popup"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\seldiff.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + } + + + // set up a doom-like interface + UiDoomStaticInit(window, sgDescID, AF_SMALLGRAY); + UiDoomStaticInit(window, sgText2IDs, AF_MEDGRAY); + UiDoomStaticInit(window, sgTextIDs, AF_BIGGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG, FALSE); + UiDoomButtonsInit(window, sgListIDs, AF_SMALL); + + // set the names into the fake listbox + SelModemSetList(window, sgModemList); + + // set up the animating focus indicator + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + // init the scroll bar + SbarInit(window, IDC_SCROLLBAR); + if (sgNumModems <= MAX_VISIBLE) { + ShowWindow(GetDlgItem(window, IDC_SCROLLBAR), FALSE); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemAbort(HWND window, int ReturnVal) { + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + + if (ReturnVal == IDOK) { + // get the id of the selected device + HWND focus = GetFocus(); + if (focus) { + TPBMP tpBmp = (TPBMP) GetWindowLong(focus, GWL_USERDATA); + if (tpBmp) { + TPMODEM tpModem = (TPMODEM) tpBmp->userdata; + if (tpModem) { + sgDeviceID = tpModem->deviceid; + } + } + } + } + + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelModemInterpretClick(HWND window, int x, int y) { + if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKEOK), x, y)) { + SelModemAbort(window, IDOK); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_FAKECANCEL), x, y)) { + SelModemAbort(window, IDCANCEL); + } + else if (UiIsPtInWindow(window, GetDlgItem(window, IDC_SCROLLBAR), x, y)) { + int SbarClick = SbarInterpretClick(GetDlgItem(window, IDC_SCROLLBAR), x, y); + switch (SbarClick) { + case DSB_UP: + SelModemScrollUp(GetFocus()); + break; + + case DSB_DOWN: + SelModemScrollDown(GetFocus()); + break; + + case DSB_PAGEUP: + SelModemPageUp(GetFocus()); + break; + + case DSB_PAGEDOWN: + SelModemPageDown(GetFocus()); + break; + + default: + break; + } + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelModemDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + SelModemUpdateSbar(window); + } + else if (HIWORD(wparam) == BN_DOUBLECLICKED) { + SelModemAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDOK) { + SelModemAbort(window, IDOK); + } + else if (LOWORD(wparam) == IDCANCEL) { + SelModemAbort(window, IDCANCEL); + } + break; + + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + SelModemInterpretClick(window, LOWORD(lparam), HIWORD(lparam)); + break; + + case WM_LBUTTONUP: + if (SbarUpClick(GetDlgItem(window, IDC_SCROLLBAR))) { + SelModemUpdateSbar(window); + } + break; + + case WM_DESTROY: + SelModemDestroy(window); + break; + + case WM_INITDIALOG: + SelModemInit(window); + return 0; + + case WM_TIMER: + FocusAnimate(window, GetFocus()); + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelModemInitDevice(HWND window, DWORD deviceid) { + SNETUIDATA uidata; + + // create new interface data + CopyMemory(&uidata,sgSMInterfaceData,sizeof(SNETUIDATA)); + uidata.statuscallback = ModmStatStatusCallback; + uidata.size = sizeof(SNETUIDATA); + uidata.parentwindow = window; + + return SNetInitializeDevice( + deviceid, + sgSMProgramData, + sgSMPlayerData, + &uidata, + sgSMVersionData + ); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelModemNoModem(DWORD providerid) { + if (providerid == 'MODM') { + TCHAR err[128]; + LoadString(global_hinstance, IDS_NOMODEM_ERR, err, 127); + SelOkDialog(sgSMInterfaceData->parentwindow, err, NULL, FALSE); + return FALSE; + } + else { + return TRUE; + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelModemOneModem(void) { + if (SelModemInitDevice(sgSMInterfaceData->parentwindow, sgModemList->deviceid)) { + ModemFreeList(sgModemList); + return TRUE; + } + else { + // error initializing modem + TCHAR initerr[128]; + LoadString(global_hinstance, IDS_INITMODEM_ERR, initerr, 127); + SelOkDialog(sgSMInterfaceData->parentwindow, initerr, NULL, FALSE); + ModemFreeList(sgModemList); + return TRUE; + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelModemListModems(void) { + int result = SDlgDialogBox( + global_hinstance, + TEXT("SELMODEM_DIALOG"), + sgSMInterfaceData->parentwindow, + SelModemDialogProc + ); + + if (result == IDOK) { + if (SelModemInitDevice(sgSMInterfaceData->parentwindow, sgDeviceID)) { + ModemFreeList(sgModemList); + return TRUE; + } + else { + // error initializing device + TCHAR initerr[128]; + LoadString(global_hinstance, IDS_INITMODEM_ERR, initerr, 127); + SelOkDialog(sgSMInterfaceData->parentwindow, initerr, NULL, FALSE); + ModemFreeList(sgModemList); + return FALSE; + } + } + else { + // user cancelled + ModemFreeList(sgModemList); + SetLastError(SNET_ERROR_CANCELLED); + return FALSE; + } +} + + +//**************************************************************************** +//**************************************************************************** +BOOL UiSelectDevice(DWORD providerid, + SNETPROGRAMDATAPTR programdata, + SNETPLAYERDATAPTR playerdata, + SNETUIDATAPTR interfacedata, + SNETVERSIONDATAPTR versiondata) { + sgSMProgramData = programdata; + sgSMPlayerData = playerdata; + sgSMInterfaceData = interfacedata; + sgSMVersionData = versiondata; + + // enum all devices + sgModemList = NULL; + sgNumModems = 0; + SNetEnumDevices(SelModemEnum); + + switch (sgNumModems) { + case 0: + return SelModemNoModem(providerid); + + case 1: + return SelModemOneModem(); + + default: + return SelModemListModems(); + } +} diff --git a/src/Uisrc/UI/SELMULT.CPP b/src/Uisrc/UI/SELMULT.CPP new file mode 100644 index 0000000..e9e9519 --- /dev/null +++ b/src/Uisrc/UI/SELMULT.CPP @@ -0,0 +1,465 @@ +//**************************************************************************** +// SelMult.cpp +// Diablo UI select multi player game character dialog +// +// By Frank Pearce +// created 9.19.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** +extern int CreaHeroDlg(HWND parent, char * newname, int * charclass); + + +//**************************************************************************** +//**************************************************************************** +static SIZE bgsize; +static LPBYTE backgroundbitmap = NULL; +static LPBYTE buttonbitmap = NULL; + +//*** strings to put the hero stats in +static char selheroname[NAME_LEN]; +static char selheroclass[CLASS_LEN]; +static char selherolevel[8]; +static char selherostr[8]; +static char selheromagic[8]; +static char selherodex[8]; +static char selherovit[8]; +static char selherogold[16]; + + +static ENUMHEROS global_enumfcn; +static CREATEHERO global_createfcn; +static DELETEHERO global_deletefcn; + +static TPUIHEROINFO herolist; + + +//**************************************************************************** +//**************************************************************************** +TPUIHEROINFO SelMultAllocNode(void) { + return (TPUIHEROINFO) ALLOC(sizeof(TUIHEROINFO)); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultFreeNode(TPUIHEROINFO node) { + FREE(node); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultFreeList(TPUIHEROINFO list) { + TPUIHEROINFO next; + + while (list) { + next = list->next; + SelMultFreeNode(list); + list = next; + } +} + + +//**************************************************************************** +//**************************************************************************** +TPUIHEROINFO SelMultAddNode(TPUIHEROINFO list, TPUIHEROINFO node) { + node->next = list; + return node; +} + + +//**************************************************************************** +//**************************************************************************** +static TPUIHEROINFO SelMultDeleteNode(TPUIHEROINFO list, const char * namekey) { + TPUIHEROINFO current, previous, found; + + current = list; + previous = NULL; + found = NULL; + + while (current && !found) { + if (strcmp(current->name, namekey) == 0) { + found = current; + } + else { + previous = current; + current = current->next; + } + } + + if (found) { + if (previous) + previous->next = found->next; + else + list = found->next; + SelMultFreeNode(found); + } + + return list; +} + + +//**************************************************************************** +//**************************************************************************** +static TPUIHEROINFO SelMultFindNode(TPUIHEROINFO list, const char * namekey) { + TPUIHEROINFO current = list; + + while (current) { + if (strcmp(current->name, namekey) == 0) + break; + current = current->next; + } + + return current; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelMultEnumHero(TPUIHEROINFO heroinfo) { + TPUIHEROINFO newhero = SelMultAllocNode(); + memcpy(newhero, heroinfo, sizeof(TUIHEROINFO)); + herolist = SelMultAddNode(herolist, newhero); + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultGetHeros(void) { + global_enumfcn(SelMultEnumHero); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultSetStats(HWND window, HWND lbox) { + TPUIHEROINFO hero; + HWND child; + + SendMessage( + lbox, + LB_GETTEXT, + SendMessage(lbox, LB_GETCURSEL, 0, 0), + (LPARAM) selheroname + ); + + hero = SelMultFindNode(herolist, selheroname); + + child = GetDlgItem(window, IDC_CHARNAME); + SetWindowText(child, selheroname); + + child = GetDlgItem(window, IDC_CHARCLASS); + strcpy(selheroclass, hero->heroclass); + SetWindowText(child, selheroclass); + + child = GetDlgItem(window, IDC_CHARLEVEL); + wsprintf(selherolevel, "%d", hero->level); + SetWindowText(child, selherolevel); + + child = GetDlgItem(window, IDC_CHARSTR); + wsprintf(selherostr, "%d", hero->strength); + SetWindowText(child, selherostr); + + child = GetDlgItem(window, IDC_CHARMAGIC); + wsprintf(selheromagic, "%d", hero->magic); + SetWindowText(child, selheromagic); + + child = GetDlgItem(window, IDC_CHARDEX); + wsprintf(selherodex, "%d", hero->dexterity); + SetWindowText(child, selherodex); + + child = GetDlgItem(window, IDC_CHARVIT); + wsprintf(selherovit, "%d", hero->vitality); + SetWindowText(child, selherovit); + + child = GetDlgItem(window, IDC_CHARGOLD); + wsprintf(selherogold, "%d", hero->gold); + SetWindowText(child, selherogold); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultClearStats(HWND window) { + HWND child; + + child = GetDlgItem(window, IDC_CHARNAME); + SetWindowText(child, NULL); + child = GetDlgItem(window, IDC_CHARCLASS); + SetWindowText(child, NULL); + child = GetDlgItem(window, IDC_CHARLEVEL); + SetWindowText(child, NULL); + child = GetDlgItem(window, IDC_CHARSTR); + SetWindowText(child, NULL); + child = GetDlgItem(window, IDC_CHARMAGIC); + SetWindowText(child, NULL); + child = GetDlgItem(window, IDC_CHARDEX); + SetWindowText(child, NULL); + child = GetDlgItem(window, IDC_CHARVIT); + SetWindowText(child, NULL); + child = GetDlgItem(window, IDC_CHARGOLD); + SetWindowText(child, NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultCreateNew(HWND window) { + TPUIHEROINFO newhero; + char newname[NAME_LEN]; + int charclass; + HWND lbox; + + // bring up the create char popup + if (IDCANCEL == CreaHeroDlg(window, newname, &charclass)) + return; + +#if 0 + lbox = GetDlgItem(window, IDC_MULTICHARS_LBOX); + + // ~~~fgp.add more code here + // if the name has no length use a default name + + if (NULL != (newhero = SelMultFindNode(herolist, newname))) { + // the name already exists + // confirm the overwrite + TCHAR buf[64]; + wsprintf(buf, "Overwrite %s?", newname); + if (IDCANCEL == SDrawMessageBox(buf,TEXT("Confirm Overwrite"),MB_OKCANCEL)) + return; + + // make the new hero the currently selected lbox entry + SendMessage(lbox, LB_SELECTSTRING, -1, (LPARAM)newname); + } + else { + // the user didn't enter a duplicate name + int index; + + // add the new hero to the hero list + newhero = SelMultAllocNode(); + herolist = SelMultAddNode(herolist, newhero); + + // add the new hero to the listbox and select it + index = SendMessage(lbox, LB_ADDSTRING, 0, (LPARAM)newname); + SendMessage(lbox, LB_SETCURSEL, index, 0); + } + + // call the create fcn for the new hero + global_createfcn(newhero); + + // update the displayed stats + SelMultSetStats(window, lbox); +#endif +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultDeleteHero(HWND window) { + TPUIHEROINFO hero; + TCHAR buf[64]; + HWND lbox; + + // confirm the delete + wsprintf(buf, "Delete %s?", selheroname); + if (IDCANCEL == SDrawMessageBox(buf,TEXT("Confirm Delete"),MB_OKCANCEL)) + return; + + // find the hero node to delete + lbox = GetDlgItem(window, IDC_MULTICHARS_LBOX); + hero = SelMultFindNode(herolist, selheroname); + + // make the callback for the delete + global_deletefcn(hero); + + // delete the node + herolist = SelMultDeleteNode(herolist, selheroname); + + // remove it from the listbox + SendMessage( + lbox, + LB_DELETESTRING, + SendMessage(lbox, LB_GETCURSEL, 0, 0), + 0 + ); + + // select a new hero automatically + if (SendMessage(lbox, LB_GETCOUNT, 0, 0)) { + SendMessage(lbox, LB_SETCURSEL, 0, 0); + SelMultSetStats(window, lbox); + } + else { + // disable the DELETE button + EnableWindow(GetDlgItem(window, IDC_DELETECHAR_BTN), FALSE); + SelMultClearStats(window); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultInitLbox(HWND window, HWND lbox) { + TPUIHEROINFO currenthero = herolist; + + SendMessage(lbox, WM_SETREDRAW, FALSE, 0); + + // fill the list box with all available multiplayer game characters + while (currenthero) { + SendMessage(lbox, LB_ADDSTRING, 0, (LPARAM)(currenthero->name)); + currenthero = currenthero->next; + } + + // if heros already exist default selection to first hero + if (SendMessage(lbox, LB_GETCOUNT, 0, 0)) { + SendMessage(lbox, LB_SETCURSEL, 0, 0); + SelMultSetStats(window, lbox); + } + else { + // disable the DELETE button + EnableWindow(GetDlgItem(window, IDC_DELETECHAR_BTN), FALSE); + } + + SendMessage(lbox, WM_SETREDRAW, TRUE, 0); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelMultConfirmSelected(HWND window) { + // if the listbox is empty the create dlg needs to be popped up + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static void SelMultDestroy(HWND window) { + if (buttonbitmap) { + FREE(buttonbitmap); + buttonbitmap = NULL; + } + if (backgroundbitmap) { + FREE(backgroundbitmap); + backgroundbitmap = NULL; + } + + SelMultFreeList(herolist); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelMultInit(HWND window) { + SIZE artsize; + + // load texture maps for this dialog + if (!LoadArtFile(window,NULL,TEXT(""),TEXT("ui_art\\samp_bkg.pcx"),&backgroundbitmap,&bgsize)) + return 0; + if (!LoadArtFile(NULL,window,TEXT("Button"),TEXT("ui_art\\samp_btn.pcx"),&buttonbitmap,&artsize)) + return 0; + + SelMultGetHeros(); + SelMultInitLbox(window, GetDlgItem(window, IDC_MULTICHARS_LBOX)); + + // set bg bitmaps for stat displays + UiSetChildBmp(window, IDC_CHARNAME, backgroundbitmap, &bgsize); + UiSetChildBmp(window, IDC_CHARCLASS, backgroundbitmap, &bgsize); + UiSetChildBmp(window, IDC_CHARLEVEL, backgroundbitmap, &bgsize); + UiSetChildBmp(window, IDC_CHARSTR, backgroundbitmap, &bgsize); + UiSetChildBmp(window, IDC_CHARMAGIC, backgroundbitmap, &bgsize); + UiSetChildBmp(window, IDC_CHARDEX, backgroundbitmap, &bgsize); + UiSetChildBmp(window, IDC_CHARVIT, backgroundbitmap, &bgsize); + UiSetChildBmp(window, IDC_CHARGOLD, backgroundbitmap, &bgsize); + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelMultDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDC_CREATECHAR_BTN: + SelMultCreateNew(window); + break; + case IDC_DELETECHAR_BTN: + SelMultDeleteHero(window); + break; + case IDC_CONNECT_BTN: + if (SelMultConfirmSelected(window)) { + SDlgEndDialog(window,SELMULT_CONNECT); + } + break; + case IDC_MULTICHARS_LBOX: + if (HIWORD(wparam) == LBN_SELCHANGE) { + // a character was selected -- update the stats on the screen + SelMultSetStats(window, (HWND)lparam); + } + break; + case IDCANCEL: + SDlgEndDialog(window,SELMULT_PREVIOUS); + break; + } + break; + + case WM_DESTROY: + SelMultDestroy(window); + break; + + case WM_INITDIALOG: + SelMultInit(window); + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiSelMultDialog ( + ENUMHEROS enumfcn, + CREATEHERO createfcn, + DELETEHERO deletefcn, + DWORD *selection, + char *heroname) { + DWORD result = 0; + + global_enumfcn = enumfcn; + global_createfcn = createfcn; + global_deletefcn = deletefcn; + herolist = NULL; + + // DISPLAY THE DIALOG BOX + result = (DWORD)SDlgDialogBox(global_hinstance, + TEXT("SELMULTI_DIALOG"), + SDrawGetFrameWindow(), + SelMultDialogProc); + + // set the results + if (selection) + *selection = result; + if (heroname) + strcpy(heroname, selheroname); + + return 1; +} diff --git a/src/Uisrc/UI/SELSING.CPP b/src/Uisrc/UI/SELSING.CPP new file mode 100644 index 0000000..642c128 --- /dev/null +++ b/src/Uisrc/UI/SELSING.CPP @@ -0,0 +1,121 @@ +//**************************************************************************** +// SelSing.cpp +// Diablo UI select dialog +// +// By Frank Pearce +// created 9.17.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** +static SIZE bgsize; +static LPBYTE backgroundbitmap = NULL; +static LPBYTE buttonbitmap = NULL; + +static char selectedname[NAME_LEN]; + + +//**************************************************************************** +//**************************************************************************** +static void SelSingDestroy(HWND window) { + if (buttonbitmap) { + FREE(buttonbitmap); + buttonbitmap = NULL; + } + if (backgroundbitmap) { + FREE(backgroundbitmap); + backgroundbitmap = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL SelSingInit(HWND window) { + SIZE artsize; + + if (!LoadArtFile(window,NULL,TEXT(""),TEXT("ui_art\\samp_bkg.pcx"),&backgroundbitmap,&bgsize)) + return 0; + if (!LoadArtFile(NULL,window,TEXT("Button"),TEXT("ui_art\\samp_btn.pcx"),&buttonbitmap,&artsize)) + return 0; + + return 1; +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelSingDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + switch (LOWORD(wparam)) { + case IDC_CREATECHAR_BTN: + // bring up the create char popup + break; + case IDC_DELETECHAR_BTN: + // bring up delete confirm dlg + break; + case IDC_NEWDUNGEON_BTN: + // somehow indicate which character is selected to main application + SDlgEndDialog(window,SELSING_NEW_DUNGEON); + break; + case IDC_CONTINUE_BTN: + // somehow indicate which character is selected to main application + SDlgEndDialog(window,SELSING_CONTINUE); + break; + case IDCANCEL: + SDlgEndDialog(window,SELSING_PREVIOUS); + break; + } + break; + + case WM_DESTROY: + SelSingDestroy(window); + break; + + case WM_INITDIALOG: + SelSingInit(window); + return 1; + + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + +//**************************************************************************** +//* +//* EXPORTED FUNCTIONS +//* +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiSelSingDialog ( + ENUMHEROS enumfcn, + CREATEHERO createfcn, + DELETEHERO deletefcn, + DWORD *selection, + char *heroname) { + DWORD result; + + // DISPLAY THE DIALOG BOX + result = (DWORD)SDlgDialogBox(global_hinstance, + TEXT("SELSINGLE_DIALOG"), + SDrawGetFrameWindow(), + SelSingDialogProc); + + if (selection) + *selection = result; + if (heroname) + strcpy(heroname, selectedname); + + return 1; +} diff --git a/src/Uisrc/UI/SELYESNO.CPP b/src/Uisrc/UI/SELYESNO.CPP new file mode 100644 index 0000000..b0182eb --- /dev/null +++ b/src/Uisrc/UI/SELYESNO.CPP @@ -0,0 +1,243 @@ +//**************************************************************************** +// SelYesNo.cpp +// Diablo UI select hero "yes/no" dialog +// +// By Frank Pearce +// created 10.21.96 +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" +#include "uisnd.h" + + +//**************************************************************************** +//**************************************************************************** + extern void SelHeroSetTitle(HWND window, LPCTSTR title); + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define FOCUS_TIMER_ID 1 + #define FOCUS_FPS 16 // frames per second + #define FOCUS_TIMER_DELAY 55 //(MILLISEC_PER_SEC / FOCUS_FPS) + + +//**************************************************************************** +//**************************************************************************** + static int sgTextIDs[] = { + IDC_OKCANCEL_TEXT, + 0 + }; + static int sgBtnIDs[] = { + IDC_OK, + IDCANCEL, + 0 + }; + + static LPCTSTR sgTitle; + static LPCTSTR sgYesNoText; + static BOOL sgLoadFocus; + static BOOL sgMainMenuBG; + static SNETABORTPROC sgpAbortFcn; + + +//**************************************************************************** +//**************************************************************************** +static void SelYesNoDestroy(HWND window) { + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + if (sgLoadFocus) + FocusAnimateDestroy(); + UiDoomCtrlsDestroy(window, sgBtnIDs); + UiDoomCtrlsDestroy(window, sgTextIDs); + if (sgTitle) { + SelHeroSetTitle(GetParent(window), NULL); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SelYesNoInit(HWND window) { + TPBMP tpBmp; + HWND parent = GetParent(window); + + if (sgTitle) + SelHeroSetTitle(parent, sgTitle); + + // load texture maps for this dialog + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT("Popup"), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + (sgMainMenuBG ? + (UiIsSpawned() ? TEXT("ui_art\\swmmpop.pcx") : TEXT("ui_art\\mmpopup.pcx")) : + TEXT("ui_art\\black.pcx") + ), + &tpBmp->data, + &tpBmp->datasize + ); + } + + SetWindowText(GetDlgItem(window, IDC_OKCANCEL_TEXT), sgYesNoText); + + // set up a doom-like interface + UiDoomStaticInit(window, sgTextIDs, AF_MEDGRAY); + UiDoomButtonsInit(window, sgBtnIDs, AF_BIG); + + // set up the animating focus indicator + if (sgLoadFocus) + FocusAnimateInit("ui_art\\focus.pcx"); + else + FocusReInit(); + SDlgSetTimer(window, FOCUS_TIMER_ID, FOCUS_TIMER_DELAY, NULL); + + UiActiveDownBtns(window, sgBtnIDs); +} + + +//**************************************************************************** +//**************************************************************************** +static void SelYesNoAbort(HWND window, int ReturnVal) { + UiSndPlayEnter(); + SDlgKillTimer(window, FOCUS_TIMER_ID); + + if ((ReturnVal == IDCANCEL) && (sgpAbortFcn)) + sgpAbortFcn(); + + if (ReturnVal == IDOK) + // return the id of the focused button + ReturnVal = GetWindowLong(GetFocus(), GWL_ID); + + SDlgEndDialog(window, ReturnVal); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SelYesNoDialogProc(HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_COMMAND: + if (HIWORD(wparam) == BN_KILLFOCUS) { + FocusLost(window, (HWND) lparam); + } + else if (HIWORD(wparam) == BN_SETFOCUS) { + FocusSnd((HWND) lparam); + FocusAnimate(window, (HWND) lparam); + } + else if (LOWORD(wparam) == IDOK) { + switch (GetWindowLong(GetFocus(), GWL_ID)) { + case IDC_OK: + SelYesNoAbort(window, IDOK); + break; + default: + SelYesNoAbort(window, IDCANCEL); + break; + } + } + else if (LOWORD(wparam) == IDCANCEL) { + SelYesNoAbort(window, IDCANCEL); + } + else if (LOWORD(wparam) == IDC_OK) { + SelYesNoAbort(window, IDOK); + } + break; + + case WM_DESTROY: + SelYesNoDestroy(window); + break; + + case WM_INITDIALOG: + SelYesNoInit(window); + return 0; + + case WM_TIMER: + if (! FocusAnimate(window, GetFocus())) { + HWND child = GetDlgItem(window, IDC_OK); + if (child) + SetFocus(child); + else + SetFocus(GetDlgItem(window, IDCANCEL)); + } + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//**************************************************************************** +int SelYesNoDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus) { + sgTitle = title; + sgYesNoText = text; + sgLoadFocus = loadfocus; + sgMainMenuBG = FALSE; + sgpAbortFcn = NULL; + + return SDlgDialogBox( + global_hinstance, + TEXT("SELYESNO_DIALOG"), + parent, + SelYesNoDialogProc + ); +} + + +//**************************************************************************** +//**************************************************************************** +int SelOkDialog(HWND parent, LPCTSTR text, LPCTSTR title, BOOL loadfocus) { + sgTitle = title; + sgYesNoText = text; + sgLoadFocus = loadfocus; + sgMainMenuBG = FALSE; + sgpAbortFcn = NULL; + + return SDlgDialogBox( + global_hinstance, + TEXT("SELOK_DIALOG"), + parent, + SelYesNoDialogProc + ); +} + + +//**************************************************************************** +//**************************************************************************** +int SpawnErrDialog(HWND parent, int errstrid, BOOL onmainmenu) { + TCHAR buf[256]; + + LoadString(global_hinstance, errstrid, buf, 255); + sgLoadFocus = FALSE; + sgMainMenuBG = onmainmenu; + sgTitle = NULL; + sgYesNoText = buf; + sgpAbortFcn = NULL; + + return SDlgDialogBox( + global_hinstance, + TEXT("SPAWNERR_DIALOG"), + parent, + SelYesNoDialogProc + ); +} + + diff --git a/src/Uisrc/UI/SRPOPUP.PAL b/src/Uisrc/UI/SRPOPUP.PAL new file mode 100644 index 0000000..51af73d Binary files /dev/null and b/src/Uisrc/UI/SRPOPUP.PAL differ diff --git a/src/Uisrc/UI/SRPOPUP.RAW b/src/Uisrc/UI/SRPOPUP.RAW new file mode 100644 index 0000000..2c3ed97 Binary files /dev/null and b/src/Uisrc/UI/SRPOPUP.RAW differ diff --git a/src/Uisrc/UI/STORM.LIB b/src/Uisrc/UI/STORM.LIB new file mode 100644 index 0000000..67499fd Binary files /dev/null and b/src/Uisrc/UI/STORM.LIB differ diff --git a/src/Uisrc/UI/SUPPORT.CPP b/src/Uisrc/UI/SUPPORT.CPP new file mode 100644 index 0000000..d489e0e --- /dev/null +++ b/src/Uisrc/UI/SUPPORT.CPP @@ -0,0 +1,382 @@ +//**************************************************************************** +// +// Support.CPP +// Hellfire UI Support screen +// +// By Michael Morhaime (9/16/96) +// Modified 10.3.96 by Frank Pearce +// Copied 10.7.97 by Gary Powell +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + #define PIXELS_PER_SCROLL 1 + #define ID_SUPPORT_TIMER 1 + #define MILLISEC_PER_SEC 1000 + #define PIXELS_PER_SEC 20 + #define DEFAULT_TIMER (MILLISEC_PER_SEC / (PIXELS_PER_SEC / PIXELS_PER_SCROLL)) + #define USER_TIMER (MILLISEC_PER_SEC / (pixelspersec / PIXELS_PER_SCROLL)) + + #define VERTICAL_PAD 30 // Padding above and below viewable part of offscreen rect + #define TAB_PIXEL_SIZE 40 + #define LINE_HEIGHT 22 + + static LPBYTE sgTextBits = NULL; // bitmap for scrolling text ctrl + static SIZE sgTextBitsSize; + static HSGDIFONT sgTextFont = NULL; + static int sgiTextLoc; + + static HGLOBAL sghSupport; // handle for the Support string resource + static int sgSupportSize; // length of resource in bytes + + static void ScrollSupport(HWND window); + + +//**************************************************************************** +//**************************************************************************** +static void SupportDestroy (HWND window) { + if (sgTextFont) { + SGdiDeleteObject(sgTextFont); + sgTextFont = NULL; + } + if (sgTextBits) { + FREE(sgTextBits); + sgTextBits = NULL; + } + + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); + + if (sghSupport) { + // free the Support text + FreeResource(sghSupport); + sghSupport = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void SupportAbort(HWND window) { + UiFadeAbort(window); + SDlgKillTimer(window,ID_SUPPORT_TIMER); + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, 1); +} + + +//**************************************************************************** +//**************************************************************************** +static void SupportInit (HWND window, LPARAM pixelspersec) { + TPBMP tpBmp; + HWND child; + HFONT winfont; + RECT rect; + int nWidth, nHeight; + + // set up the timer based on the specified pixel rate + SDlgSetTimer( + window, + ID_SUPPORT_TIMER, + (pixelspersec ? USER_TIMER : DEFAULT_TIMER), + NULL + ); + + // load the Support into memory + sghSupport = LoadResource( + global_hinstance, + FindResource(global_hinstance, TEXT("IDR_SUPPORT"), TEXT("TEXT_FILES")) + ); + sgSupportSize = SizeofResource( + global_hinstance, + FindResource(global_hinstance, TEXT("IDR_SUPPORT"), TEXT("TEXT_FILES")) + ); + + // init a bmp for the window + tpBmp = UiAllocBmp(); + if (tpBmp) { + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\support.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window, FALSE); + } + + // alloc/create a bitmap for the scrolling text ctrl + child = GetDlgItem(window, ID_SCROLL_WINDOW); + GetWindowRect(child, &rect); + + nWidth = rect.right - rect.left; + nHeight = rect.bottom - rect.top + (VERTICAL_PAD*2); + + sgTextBits = (LPBYTE) ALLOC(nWidth * nHeight); + if (!sgTextBits ) { + SupportAbort(window); + return; + } + + sgTextBitsSize.cx = nWidth; + sgTextBitsSize.cy = nHeight; + + UiCalcNewRect(&rect, 0, VERTICAL_PAD); + + SDlgSetBitmap( + child, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + sgTextBits, + &rect, + nWidth, + nHeight + ); + + // init the starting text coordinate and begin drawing the Support + sgiTextLoc = nHeight - VERTICAL_PAD; + ScrollSupport(window); + + // create the font for SGdiTextOut + winfont = CreateFont( + -17,0,0,0,FW_BOLD,0,0,0,ANSI_CHARSET, + OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, + VARIABLE_PITCH | FF_ROMAN,TEXT("Times New Roman") + ); + if (winfont) { + BOOL result = SGdiImportFont(winfont,&sgTextFont); + DeleteObject(winfont); + if (! result) { + SupportAbort(window); + } + } + else { + SupportAbort(window); + } +} + + +//**************************************************************************** +//**************************************************************************** +static int sgSupportLen; + +static int credit_length(LPTSTR credit) { + int len = 0; + + // find the length (in characters) of a single line + while ((*credit != '\r') && (*credit != '\n')) { + len++; + credit++; + if (len > sgSupportLen) { + len = -1; + break; + } + } + return len; +} + + +//**************************************************************************** +//**************************************************************************** +static LPTSTR support_next(LPTSTR lastline, int lastlen) { + // skip over last line and cr/lf + lastline += (lastlen + 2); + sgSupportLen -= (lastlen + 2); + + return lastline; +} + + +//**************************************************************************** +//**************************************************************************** +static void SupportDraw(HWND window) { + int x, y, stringlen; + LPTSTR Support; + + // lock the resource and get it's size + Support = (LPTSTR)LockResource(sghSupport); + sgSupportLen = sgSupportSize; + + SGdiSelectObject(sgTextFont); + SGdiSetPitch(sgTextBitsSize.cx); + + for ( + y = sgiTextLoc; + sgSupportLen > 0; + y += LINE_HEIGHT, Support = support_next(Support, stringlen) + ) { + // init left coord + x = 0; + // handle tabs at the begining of a line + while (*Support == '\t') { + x += TAB_PIXEL_SIZE; + Support++; + sgSupportLen--; + } + stringlen = credit_length(Support); + + // make sure the dest coords are in the buffer + if (stringlen == -1) break; + if (y < 0) continue; + if (y > (sgTextBitsSize.cy - VERTICAL_PAD)) break; + + if (stringlen) { +#if 1 + // draw a drop shadow + SGdiTextOut( + sgTextBits, + x + 2, + y + 2, + PALETTEINDEX(0), + Support, + stringlen + ); +#endif + + // draw the text + SGdiTextOut( + sgTextBits, + x, + y, + PALETTEINDEX(224), + Support, + stringlen + ); + } + } + + // has the bottom of the Support scrolled past the top? + if (y < 0) { + SupportAbort(window); + } +} + + +//**************************************************************************** +//**************************************************************************** +static void ScrollSupport (HWND window) { + RECT rect; + HWND child = GetDlgItem(window, ID_SCROLL_WINDOW); + TPBMP tpBmp = (TPBMP) GetWindowLong(window, GWL_USERDATA); + + GetWindowRect(child, &rect); + ScreenToClient(window, (LPPOINT)&rect.left); + ScreenToClient(window, (LPPOINT)&rect.right); + + // Copy from Background bitmap to buffer for scrolling text ctrl + SBltROP3 ( + sgTextBits + (sgTextBitsSize.cx * VERTICAL_PAD), + tpBmp->data + (rect.top * tpBmp->datasize.cx) + rect.left, + sgTextBitsSize.cx, + rect.bottom - rect.top, + sgTextBitsSize.cx, + tpBmp->datasize.cx, + NULL, + SRCCOPY + ); + + sgiTextLoc -= PIXELS_PER_SCROLL; + SupportDraw(window); + + InvalidateRect(child, NULL, FALSE); + UpdateWindow(child); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK SupportDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + + switch (message) { + + case WM_DESTROY: + SupportDestroy(window); + break; + + case WM_INITDIALOG: + SupportInit(window, lparam); + PostMessage(window, WM_USER+1000, 0, 0); + return 1; + + case WM_TIMER: + ScrollSupport(window); + break; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_PARENTNOTIFY: + if (LOWORD(wparam) == WM_LBUTTONDOWN || LOWORD(wparam) == WM_RBUTTONDOWN) { + SupportAbort(window); + } + break; + + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + SupportAbort(window); + return 0; + + case WM_KEYDOWN: + if (wparam == VK_SPACE) { + SupportAbort(window); + } + return 0; + + case WM_COMMAND: + SupportAbort(window); + break; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +/**************************************************************************** +* +* EXPORTED FUNCTIONS +* +***/ + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiSupportDialog (UINT pixelspersec) { + // fuck allowing customizable speed + pixelspersec = 25; + + // start the dialog + SDlgDialogBoxParam( + global_hinstance, + TEXT("SUPPORT_DIALOG"), + SDrawGetFrameWindow(), + SupportDialogProc, + pixelspersec + ); + + return 1; +} diff --git a/src/Uisrc/UI/SUPPORT.TXT b/src/Uisrc/UI/SUPPORT.TXT new file mode 100644 index 0000000..906d924 --- /dev/null +++ b/src/Uisrc/UI/SUPPORT.TXT @@ -0,0 +1,22 @@ + +Sierra On-Line maintains a web site at http://www.sierra.com +Follow the links to visit customer service or the discussion +boards associated with Hellfire. + +Sierra On-Line has e-mail technical support at this address: +support@sierra.com +To help us better serve you, please be sure to include the name of +the product, the version number, and the nature of the problem. + + +Blizzard Disclaimer: + Hellfire(tm) is not supported or maintained by Blizzard Entertainment. + Blizzard Entertainment has not tested or certified the quality or + compatibility of this product. All calls or inquiries regarding this + product should be directed to Sierra On-Line, not to Blizzard + Entertainment. + +You can reach the Sierra On-Line customer service support +department from 8am to 4:45pm PST, Monday through Friday at +(425) 644-4343. + diff --git a/src/Uisrc/UI/TEXT_FIL.BIN b/src/Uisrc/UI/TEXT_FIL.BIN new file mode 100644 index 0000000..6a0b197 --- /dev/null +++ b/src/Uisrc/UI/TEXT_FIL.BIN @@ -0,0 +1,235 @@ +Marafie Abdullah, Andrew Abernathy, Christopher Abramo, +David Adams, David Adcox, Marko Agterberg, Cory Aiken, +Judah Altaras, John Alvarez, Jose Alvarez, Richard Amable, +Alexander Amaral, Scott Amis, Vincent Amoroso, Mark An, +David Andersen, Jason Andersen, Aaron Anderson, George +Anderson, Matthew Anderson, Michael Anderson, Sean +Anderson, Robert Andrade, Cerny Andre, Michael Andreev, +Devin Angle, Brian Apple, Brian Arbuthnot, Billy Arden, Dorian +Arnold, Andre Arsenault, Min Arthur, Erik Asplund, Mark +Assam, John Athey, Jason Attard, Jeff Atwood, Ricky Au, Scott +Avery, Rand Babcock, Steve Babel, Raymond Bacalso, Ed Bachta, +Steven Back, Scott Baeder, Alex Baevski, Scott Bailey, Kenneth +Baird, Thomas Baker, Todd Bala, Jan Ball, Blake Baltzley, Doug +Bambrick, Wes Bangerter, Paul Barfuss, Chris Barghout, Dave +Barnebey, Jon Barnhart, Terje Barth, Nicole Baskin, Bernard +Baylen, Ryan Bear, Phil Bedard, Todd Belcher, Chip Bell, Erez +Ben-Aharon, Jonathan Bender, Nick Bennett, Ireney Berezniak, +Ted Berg, Gunnar Bergem, Russell Beuker, Ed Bickford, Stephen +Biles, John Billdt, John Bird, Hannah Blackerby, Tom Blackerby, +Clayton Blackwell, Thomas Blake, Shawn Blaszak, Daniel Bliss, +Fred Bliss, Jeff Bliss, Jon Blum, Hagen Bobby, Rune Boersjoe, +Andrew Boggs, Dave Boisvenu, John Bonds, Jeff Borenstein, +Dorian Borin, Ed Boris, Bartholomew Botta, Michael Boutin, +Michael Boyd, Mike Boyersmith, Michael Boyko, Eric Bradberry, +John Brandstetter, Ryan Breding, Vickers Brett, Paul Brinkmann, +Patrick Briscoe, Scott Brisko, Jeremy Britton, Adrian Broadhead, +Glenn Brouwer, Joe Brown, Sully Bruce, Sébastien Brulotte, +Darrell Brunsch, William Bryan, Jason Bucher, Chris Buchinger, +John Buckles, David Bugay, Erik Burgess, Gabriel Burkett, Chris +Burnes, Richard Butler, Clayton Buuckingham, Jeffrey Bye, +Hamilton Calvin, Dougall Campbell, Donnie Cannon, Shane +Cantrell, Connor Caple, Daniel Carey, James Carlton, Michael +Carmel, Mike Carpenter, Ronald Carruthers, Phil Carter, Bryce +Cartmill, Anthony Caruso, Lon Casey, Tim Caster, Eric +Catrwright, Aaron Chan, Otto Chan, Gene Chang, Hsiao-Lung +Chang, William Chang, George Chappel, Larry Charbonneau, +Boyer Charles, Troy Chase, Bruce Chen, Chun Hsien Chen, Sam +Chen, Tzu-Mainn Chen, Mike Cheng, Chris Chiapusio, Damien +Chiesa, Nick Chin, Nim Ching, Jonathan Chinn, Michael Chinn, +Philander Chiu, Stiff Chris, Thayne Christiansen, Mende +Christopher, Philip Chui, Steve Cintamani, Richard Ciordia, +Colin Clark, Steve Clark, Samuel Clements, Meredith Clifton, Jeff +Cohen, Dale Colton, Dax Combe, Matt Compton, Jacob Conklin, +Richard Conn, Zac Cook, Groovy Cookie, Tim Coolong, Gregory +Coomer, Kelly Couch, Andrew Coulter, Eric Coutinho, David +Coutts, James Craig, John Craig, Kazial Craig, John Crawford, +Marcelo Crespo, Orville Crews, Tim Cristy, Elmer Crosby III, +Russell Cullison, Ryan Cupples, Andrew Dagley, Steve Dallaire, +Richard Dalton, Friend Dan, Kerber Dan, David Dandar, Pro +Daulo, Rob Dautermann, Szabo David, Mike Davies, Kalieb Davis, +Marshall Davis, Ronald Davis, Danny De Bie, Marc De Filippis, +Myles Deighton, Kent Dejarnett, Anthony Delarosa, Neil +Dempster, Peter Denitto, Cosgrove Dennis, Joaquim Dentz, Scott +Dewar, Anish Dhingra, David Diaz, Stewart Dicks, Brad Dietz, +Josh Dietz, Colleen Diggins, Mike Ditchburn, Eric Dittman, Allen +Do, Huy Doan, Matthew Dolman, Antoine Dongois, Eamonn +Donohoe, Bill Dorell, Mark Dorison, Dan Dorsett, Chris Dorsey, +Jim Dose', Willis Doss, Neitzel Douglas, Chin Du, William Dubis, +Timothy Duewell, Brandon Dunn, Andrew Durham, Don Duvall, +Kevin Dvojack, Daniel Eaton, Paul Eberting, Eric Echelbarger, +Bujone Ed, Lance Eddleman, Ben Eggers, David Eggum, John +Ehde, Brian Eikenberry, Peter Engdahl, Philip Engdahl, Michael +Ennis, Darren Eslinger, Eric Ezell, Darren Falslev, Stephen +Feather, Tony Fenn, Ben Ferguson, Mike Fernandez, Gwendal +Feuillet, Guy Fietz, Julian Figueroa, Dale Fillpot, Stan Finchem, +Michael Finley, Nick Fisher, William Fisher, Mark Fitlin, Dave +Flatt, Joel J. Flores, John Folkers, Steven Forgie, Tom Forsythe, +Matthew Foster, Scott Francis, Jim Frank, Paulo Fraser, Glenn +French, Kurt Frerichs, Chris Frey, Mark Friedman, Charles +Friedmann, Kirk Fry, Aaron Fu, Erik Gaalema, Brandon +Gabbard, Phil Gagner, Tommy Gannon, David Gappmayer, Chris +Garrison, Tony Garrison, David Gasca, Jeremy Gasser, Michael +Geist, Michael Genereux, Daniel Genovese, Binder Gerald, Josh +Gerwin, William Gilchrist, Gabriel Gils Carbo, Chad Glendenin, +Ryan Glinski, Dean Gobrecht, Andrew Goldfinch, David +Goodman, Mark Goodson, Matt Gordon, Frank Gorgenyi, Sean +Gould, Perry Goutsos, Ed Govednik, Michael Grayson, Chris +Green, Baltz Greg, Justin Grenier, Jeff Greulich, Don Grey, Rob +Griesbeck, Don Griffes, Kimberly Griffeth, Jay Grizzard, Don +Gronlund, Joe Gross, Troy Growden, Greg Guilford, David +Gusovsky, Jeremy Guthrie, Adam Gutierrez, James Guzicki, +Matthew Haas, Matt Hadley, Ryan Hagelstrom, Ben Hall, Brian +Hall, Kris Hall, Kris Hamilton, Bo Hammil, Dave Hans, Rick +Hansen, Robert Harlan, Travis Harlan, Seth Harman, Jeff Harris, +Shawn Hartford, Adam Hartsell, Neil Harvey, Ray Hayes, John +Hein, Chris Heinonen, Christer Helsing, Chris Hempel, Dustin +Hempel, Mathieu Henaire, Matt Henry, Chuck Herb, Michael +Herron, Sage Herron, Thomas Herschbach, Cliff Hicks, Nelson +Hicks, Paul Hierling, William Hiers, Mike Higdon, Tim +Hildebrand, Casey Hinkle, Ryan Hitchings, Wes Hix, Alan Ho, +Jenson Ho, Alan Hoffman, Jeff Hoffman, Eleanor Hoffmann, +Steve Hogg, Richard Holler, Brian Homolya, Wade Hone, Joe +Horvath, Jeff Howe, Eric Hudson, Glen Huey, Chris Hufnagel, +Joshua Hughes, Melissa Hughes, Arief Hujaya, Thomas Hulen, +Ryan Hupp, Justin Hurst, Rick Hutchins, Steve Iams, Mike +Iarossi, Bjorn Idren, Johan Idrén, Micah Imparato, Joe Ingersoll, +David Ingram, Greg Ipp, Rodney Irvin, Darin Isola, Justin Itoh, +Mario Ivan, Fredrik Ivarsson, Dax Jacobson, Michael Jacques, +Stevens Jacques, Duane Jahnke, William Jambrosek, Daniel +Janick, Narciso Jaramillo, Neil Jariwala, Harvie Jarriell, Scott +Javadi, Solignac Jean-Pierre, Meek Jeff, Joe Jenkins, Bart +Jennings, Paul Jennings, Julien Jenny, Jason Jensen, Martin +Jeremy, Mark Jeschke, Bolt Joe, Andy Johnson, James Johnson, +Leigh Johnson, Mark Johnson, Rupert Johnson, Clyde Jones, +Michael Jones, Tim Jordan, Ben Judy, Steve Kaczkowski, Neville +Kadwa, Brian Kaisner, Yoshihisa Kameyama, Michael +Kanemura, Daniel Kao, Eric Karabin, Ben Katz, Christopher +Kawamura, Erick Kayser, Craig Keddie, Kevin Kelley, Bryan +Kemp, Timothy Kerber, Tomi Keski-Heikkilä, Greg Kettering, +Nathan Kilber, Howard Kim, Orrin Kinion, Jon Kirst, David +Kitch, John Klingbeil, Neil Klopfenstein, Kerry Knouse, David +Knox, Said Kobeissi, Jeff Koches, Hades Kong, Jeff Kong, Kevin +Konkle, Steve Koon, David Koontz, Dan Koopmann, Steve +Koskela, Kuan Kou, Cameron Kracke, Jensen Krage, York +Kramer, Cedar Kraus, Jason Kraus, Bobby Krimen, Melissa +Krispli, Steven Krispli, James Kruger, Charles Kubasta, Kimmo +Kulonen, Frank Lackaff, Matt Lake, Jason Landry, Hans Erik +Lange, Michael Laramee, Brad Lascelle, Pat Laschinger, Alan +Lau, Sean Laurence, Anthony Lavey, Jr., Gary Le, Huey Le, +Stephane Le Roy Audy, Lim Leandro, Charles Lee, Conroy Lee, +Mike Lee, Shih-Hang Lee, Jonathan Leipert, Jason Lemann, Ron +Lenzi, Mitchell Leon, Stephanie Lesniewski, Brendan Lewis, +Robert Lewis, Sam Liao, Tom Liem, Adam Ligas, Steven Liggett, +Roger Lilley, Benjamin Lim, Jeff Lindholm, Johnson Linwood, +David Litchman, Bruce Lithimane, William Liu, Wilson Liu, +Robert Lobdell, Chris Logan, Razvan Loghin, Jack Loh, George +Loo, Russell Love, Juan Loyola, Ricardo Lozano, Mike Luban, +Tim Luc, Henry Luciano, Dianne Ludwig, Charles Lueras, Derek +Lung, Derek Lung, Phong Ly, Scott MacGillivray, Dave Mack, +Alec Mak, Steve Mamayek, Michael Mancini, Daniel Mann, +Michael Mann, Chris Manofsky, Nicholas Marcy, Piompino +Mariano, Bob Marius, Savage Mark, Trey Marshall, Dane +Martin, Gregg Martin, Renard Martin, Rich Martin, Scott +Martin, Thomas Martin, Jon Masters, Christopher Mathews, Jay +Mathis, Marc Matthews, Chris Mazur, Doug McBride, Mackey +McCandlish, Robin McCollum, Steven McCombie, Andy +McConnell, Michael McCourt, Bill McCoy, Doug McCracken, +Michael McDeed, Robert McDonald, Steve McEachron, Craig +McGee, Ryan McKenzie, Michael McKeown, Daniel McMahon, +Colin McMillan, Ian McWilliam, Mark McWilliams, Khann +Mean, Bryan Meason, Kenneth Medley, John Mehr, Brian +Mendenhall, Peter Mengel, Michael Mersic, Mike Messom, Don +Metcalf, Gary Metzker, Scott Meyer, Kaae Michael, Kendrigan +Michael, Lacour Michael, Joseph Michaud, Andrew Mielke, +Travis Mikalson, Troy Milburn, Ike Miller, Ronnie Miller, Sean +Miller, Steve Miller, David Minniti, Brenda Mirsberger, Bill +Misek, David Mitchell, Joseph Mobley, Robert Mollard, Will +Mooar, Curtis Moore, Matthew Moore, Al Morales, Ryan Moran, +Lance Mortensen, Karel Mrazek, Ward Mullee, William Munoz, +Kirk Munro, Craig Murray, Shawn P. Murray, Travis Murray, +Michael Mushrush, Tom Mustaine, David Myers, Joseph Myett, +Morgan Najar, Kenta Nakamura, Damian Nastri, Joshua +Naumann, Nick Navarro, Arnold Ng, Anthony Nguyen, Steve +Nguyen, Joseph Nicholas, Charles Nickolaus, Jon Nisbet, Patrick +Nomee, David Norling-Christensen, Bobby Norton, Joseph +Nottingham, Frank O'connor, Frank O'connor, Jon Oden, David +Oester, Lavern Ogden, Zach Oglesby, Lucas Oldfield, Toby +Olsson, Aaron Ondek, Sean Oneill, John Orlando, Samuel +Orlando, Donovan Orloski, David Pai, Nikolas Paldan, David +Palek, John Palmieri, Anthony Palmisano, Sanjay Pandit, Jesse +Park, Alex Parker, Jimmy Pasher, Lukasz Paszek, Elven Patrick, +Andy Patterson, Gibson Paul, Duane Pemberton, Ivan Pemic, +Kelly Pendergast, Mike Penezich, Jon Penk, Willie Penley, Ron +Penna, Matthew Pennington, Kevin Pereira, Ross Perez, Ken +Perkins, Brian Peterik, Kelly Peterson, Dhingra Philip, Chris +Phillips, Rod Pickett, Cameron Pierce, Reuben Pierce, Tim Pilger, +Billy Pippin, Brad Plank, Brian Plant, Craig Platt, David Plunkett, +Michael Politi, Albert Portillo, Brian Powell, David Powell, +Franklin Powers Jr., Alan Precourt, Michael Pronchick, Julian +Quintana, Justin Radziej, Steven Rajewski, Shawn Rawles, Ian +Reardon, Marc Reed, Ric Reichelt, Judd Reiffin, David Reilly, +Garry Reisky, Drew Ressler, Robert Reynolds, Walter Reynolds, +Michael Rice, Ian Richards, James Richards, Raymond +Richmond, Dustin Riggs, Keith Riskey, Brian Ro, Scott Roberts, +Jorge Rodriguez, Chad Rogers, Clint Rogers, Robert Rogers, +Steve Rogers, Ethan Roots, Ron Roque, William Ross, Sebastian +Rossi, Jeff Rostis, Ben Roth, Demar Roth, Rich Rouse, Oleg +Rovner, Jonathan Roy, Drew Rozema, Mike Ruggles, Mathias +Russ, James Russell, Jim Rutledge, James Rutter, Dave Ryder, +Chris Salvadras, Anders Samnerud, Nick Sanders, Jakob +Sandgren, Joe Sapinsky, Tyler Sargent, Jonas Saunders, Scott +Sawyer, Robert Scanlon, Trevor Schaben, Aaron Schmidt, Chris +Schmidt, Greg Schultz, Nicholas Schumacher, Scott Schumacher, +Kevin Scott, Rastislav Seffer, Robert Seidler, Corey Sellers, Justin +Sellers, Marc Senecal, George Shannon, Ian Sheffield, Anoop +Shekar, Sandeep Shekar, Kevin Shelton, Leon Shephard, Eric +Shepperd, Jeffrey Shneidman, Samuel Shockey, Mark Shoemaker, +Mike Shupe, Sean Sibbet, Brian Sidharta, Jimmy Sieben, Eric +Siemens, William Silva, Jody Simpson, Jatinder Singh, Sonia Siu, +Omar Skarsvaag, Tom Skiba, Carl Skow, David Skuse, Robert +Slifka, Brent Smith, C. Eric Smith, Jared Smith, Jeffrey Smith, +Owen Smith, Owen Smith, Shannon Smith, Steven Smith, Edward +Smola, Matthew Sneep, Eric Snow, Brad Sobel, Rasmus Sørensen, +Andrew Sorg, Poppy Southcott, Ross Specter, Erik Spencer, Keith +Spencer, Chris Springer, Erikson Squier, Dean St. Onge, Stewart +Stanfield, John Stanley, Terrence Staton, Terrence Staton, +Benjamin Stein, James Steiner, David Steyer, William Stickney, +James Stofer, Norm Storch, Patrick Stovall, Brandon Sturgeon, +Sean Stutler, Anne Sukprasert, Jamal Sullivan, Jay Sung, Park +Sung Joon, Stein Sunnarvik, Nathan Surginer, Robert Swaringen, +Lee Sweeney, Scott Taft, Christian Takvam, Patrick Talaska, +Tadashi Tamaki, Simon Tan, Mark Taraba, Khon-Whey Tay, +John Taylor, Keith Taylor, Donald Temean, Phillip Tesar, Pete +Thao, Brian Thomas, Keith Thomas, Speed Thomas, Miles +Thorpe, Paul Thurrott, Mike Timbol, Nicholas Timmins, Tom +Tobin, Robert Towster, Hien Tran, Timothy Traviss, Toby +Traylor, Tony Treadwell, George Tremoulis, Paul TRINH, Thanh +TRINH, Chris Tristan, Brad Truswell, Jason Tryon, Mike Tu, +Gernel Tuazon, Eric Tuggle, Mike Turnbull, Lyle Ubben, Amilcar +Ubiera, Robert Ulozas, Arie Upton, Mark Van Noy, Matthew Van +Sickler, Jake Vantlin, Tony Vasquez, Brady Vauclin, Gianpiero +Vecchi, Chad Verrall, Chris Vicente, David Vickery, Jonathan +Vilante, Simon Vince, Ben Vinson, David Voelkert, Paul Vogt, +Nicholas Voorhies, Robert Vreeland, Mike Vrooman, Rick Vuong, +Brian Wachhaus, Todd Wachhaus, Caine Wade, Mathew +Wadstein, Kenneth Wagenius, Trevor Wagner, John Wagstaff, +Asad Wahid, Richard Wahlberg, Helio Wakasugui, Richard +Walker, Wilkins Walker, Matthew Wallace, Daniel Walsh, Joel +Walters, Andrew WALTZ, Tom Wang, Tony Wang, Jay Ward, +Jonathan Ward, John Warner, Mark Warren, Matt Washer, +Mike Watson, Sean Wattles, Mike Wayne, Christian Wehba, +Benjamin Wei, Richard Weight, Cary Wells, David Wenck, Bill +Werring, Leonard Wesley, Marlon West, Mikael Westerbacka, +Brian Wharry, Chris White, Chris White, Jeremy White, Greg +Whitlock, Gary Widener, Marty Wilfried, Israel Wilkinson, +Michael Willams, Derek Williams, Sean Willson, Nitzan Wilnai, +Jim Wilson, Karsten Wilson, William Wilt, Tim Winn, Brian +Winzeler, Matt Wise, Lee Wissmiller, Brendan Wolfe, Daniel +Wolpert, Felix Wong, Power Wong, Tony Wong, Tim Wood, +Timothy Wood, Jeremy Woods, Michael Woods, Bill Wright, +Keith Wright, Patrick WU, Gang Xie, Robert Yao, Sun Lim Yap, +Stephen Yau, Erek Yedwabnick, Christopher Yee, Nick Yee, Juan +Yip, David Young, Rob Young, Seth Young, Alex Yu, Terry Zahn, +Jia-Ning Zhang, Eric Zieg, Jordan Zielin, Clint Zimmerman, Matt +Zinke, , diff --git a/src/Uisrc/UI/TITLE.CPP b/src/Uisrc/UI/TITLE.CPP new file mode 100644 index 0000000..c787c08 --- /dev/null +++ b/src/Uisrc/UI/TITLE.CPP @@ -0,0 +1,316 @@ +//**************************************************************************** +//*** +//*** TITLE.CPP +//*** Diablo UI title screen dialog +//*** +//*** By Frank Pearce (9/13/96) +//*** +//**************************************************************************** + + +#include "pch.h" +#include "artfont.h" + + +//**************************************************************************** +//**************************************************************************** + #define MILLISEC_PER_SEC 1000 + + #define TIMEOUT_TIMER_ID 1 + #define DEFAULT_TIMEOUT 5 + + #define LOGO_TIMER_ID 2 + #define LOGO_FPS 17 + #define LOGO_TIMER_DELAY 55 // (MILLISEC_PER_SEC / LOGO_FPS) + + #define MAX_FRAMES 30 + + static LPBYTE sgLogoBmp = NULL; + static SIZE sgLogoBmpSize; + + static HTRANS sgTransHandles[MAX_FRAMES]; + static int sgFrame; + + static int sgBlizIDs[] = { + IDC_BLIZZARD, + 0 + }; + + +//**************************************************************************** +//**************************************************************************** +void TitleLogoAnimate(HWND window) { + RECT rect; + TPBMP tpBmp = (TPBMP) GetWindowLong(window, GWL_USERDATA); + HWND child = GetDlgItem(window, IDC_LOGO); + + if (! IsWindowVisible(window)) return; + if (! child) return; + if (! tpBmp) return; + if (! tpBmp->data) return; + if (! sgTransHandles[0]) return; + + sgFrame++; + if ((! sgTransHandles[sgFrame]) || (sgFrame >= MAX_FRAMES)) + sgFrame = 0; + + GetWindowRect(child, &rect); + ScreenToClient(window, (LPPOINT)&rect.left); + ScreenToClient(window, (LPPOINT)&rect.right); + + // Copy from Background bitmap to buffer for animating logo + SBltROP3 ( + sgLogoBmp, + tpBmp->data + (rect.top * tpBmp->datasize.cx) + rect.left, + sgLogoBmpSize.cx, + (sgLogoBmpSize.cy > 480) ? 480 : sgLogoBmpSize.cy, + sgLogoBmpSize.cx, + tpBmp->datasize.cx, + NULL, + SRCCOPY + ); + + STransBlt(sgLogoBmp, 0, 0, sgLogoBmpSize.cx, sgTransHandles[sgFrame]); + + InvalidateRect(child, NULL, FALSE); +} + + +//**************************************************************************** +//**************************************************************************** +void TitleLogoDestroy(void) { + for (int index = 0; index < MAX_FRAMES; index++) { + if (sgTransHandles[index]) { + STransDelete(sgTransHandles[index]); + sgTransHandles[index] = NULL; + } + } + + if (sgLogoBmp) { + FREE(sgLogoBmp); + sgLogoBmp = NULL; + } +} + + +//**************************************************************************** +//**************************************************************************** +static void TitleDestroy (HWND window) { + TitleLogoDestroy(); + + UiDoomCtrlsDestroy(window, sgBlizIDs); + + UiFreeBmp((TPBMP) GetWindowLong(window, GWL_USERDATA)); + SetWindowLong(window, GWL_USERDATA, (LONG) 0); +} + + +//**************************************************************************** +//**************************************************************************** +void TitleLogoInit(HWND window) { + RECT rect; + HWND child; + + // alloc/create a bitmap for the animating logo + child = GetDlgItem(window, IDC_LOGO); + if (! child) return; + GetClientRect(child, &rect); + + sgLogoBmp = (LPBYTE) ALLOC(rect.right * rect.bottom); + if (!sgLogoBmp) { + return; + } + sgLogoBmpSize.cx = rect.right; + sgLogoBmpSize.cy = rect.bottom; + + SDlgSetBitmap( + child, + NULL, + NULL, + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + sgLogoBmp, + NULL, + rect.right, + rect.bottom + ); +} + + +//**************************************************************************** +//**************************************************************************** +void TitleFramesInit(HWND window, LPCTSTR filename) { + LPBYTE srcframes = NULL; + SIZE srcsize; + RECT rect; + + UiLoadBmpFile( + filename, + &srcframes, + &srcsize + ); + + memset(sgTransHandles, 0, sizeof(sgTransHandles)); + + if (srcframes) { + int frames = srcsize.cy / sgLogoBmpSize.cy; + if (frames > MAX_FRAMES) + frames = MAX_FRAMES; + // create an HTRANS for each frame in the animation + for (int index = 0; index < frames; index++) { + + rect.left = 0; + rect.right = sgLogoBmpSize.cx - 1; + rect.top = index * sgLogoBmpSize.cy; + rect.bottom = rect.top + sgLogoBmpSize.cy - 1; + + STransCreate( + srcframes, + sgLogoBmpSize.cx, + sgLogoBmpSize.cy, + 8, + &rect, + PALETTEINDEX(250), + &sgTransHandles[index] + ); + + } + + FREE(srcframes); + } + sgFrame = 0; +} + + +//**************************************************************************** +//**************************************************************************** +static void TitleInit(HWND window, LPARAM lparam) { + TPBMP tpBmp; + + // set up a bmp for the window + tpBmp = UiAllocBmp(); + SetWindowLong(window, GWL_USERDATA, (LONG) tpBmp); + if (tpBmp) { + LoadArtFile( + window, + NULL, + TEXT(""), + SDLG_STYLE_ANY, + SDLG_USAGE_BACKGROUND, + TEXT("ui_art\\hf_title.pcx"), + &tpBmp->data, + &tpBmp->datasize, + FALSE + ); + UiFadeInit(window, FALSE); + } + + UiDoomStaticInit(window, sgBlizIDs, AF_MEDGRAY); + + // set up the animating diablo logo + TitleLogoInit(window); + TitleFramesInit(window,TEXT("ui_art\\hf_logo1.pcx")); + TitleLogoAnimate(window); + SDlgSetTimer(window, LOGO_TIMER_ID, LOGO_TIMER_DELAY, NULL); + + // set a timer so the screen will timeout + if (lparam) + SDlgSetTimer(window, TIMEOUT_TIMER_ID, lparam*MILLISEC_PER_SEC, NULL); + else + SDlgSetTimer(window, TIMEOUT_TIMER_ID, DEFAULT_TIMEOUT*MILLISEC_PER_SEC, NULL); +} + + +//**************************************************************************** +//**************************************************************************** +static void TitleAbort(HWND window) { + UiFadeAbort(window); + SDlgKillTimer(window, LOGO_TIMER_ID); + SDlgKillTimer(window, TIMEOUT_TIMER_ID); + UiVidFadeOut(DEFAULT_STEPS*2); + SDlgEndDialog(window, 1); +} + + +//**************************************************************************** +//**************************************************************************** +static BOOL CALLBACK TitleDialogProc (HWND window, + UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + + case WM_DESTROY: + TitleDestroy(window); + break; + + case WM_INITDIALOG: + TitleInit(window, lparam); + PostMessage(window, WM_USER+1000, 0, 0); + return 1; + + case WM_PARENTNOTIFY: + if (LOWORD(wparam) == WM_LBUTTONDOWN || LOWORD(wparam) == WM_RBUTTONDOWN) { + TitleAbort(window); + } + break; + + case WM_GETDLGCODE: + return DLGC_WANTALLKEYS; + + case WM_COMMAND: + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_KEYDOWN: + TitleAbort(window); + return 0; + + case WM_USER+1000: + if (! UiIsFading()) { + UiFadeStart(window); + } + return 0; + + case WM_TIMER: + switch (wparam) { + case TIMEOUT_TIMER_ID: + TitleAbort(window); + break; + case LOGO_TIMER_ID: + TitleLogoAnimate(window); + break; + } + return 0; + + case WM_SYSKEYUP: + case WM_SYSKEYDOWN: + SendMessage(SDrawGetFrameWindow(), message, wparam, lparam); + break; + } + return SDlgDefDialogProc(window,message,wparam,lparam); +} + + +//**************************************************************************** +//*** +//*** EXPORTED FUNCTIONS +//*** +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +BOOL APIENTRY UiTitleDialog (UINT timeoutseconds) { + // init the custom non-windows font + ArtFontLoad(); + + SDlgDialogBoxParam( + global_hinstance, + "TITLESCREEN_DIALOG", + SDrawGetFrameWindow(), + TitleDialogProc, + timeoutseconds + ); + + return 1; +} diff --git a/src/Uisrc/UI/UI.DSP b/src/Uisrc/UI/UI.DSP new file mode 100644 index 0000000..f48a7ad --- /dev/null +++ b/src/Uisrc/UI/UI.DSP @@ -0,0 +1,351 @@ +# Microsoft Developer Studio Project File - Name="ui" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ui - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ui.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ui.mak" CFG="ui - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ui - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ui - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ui - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\Release" +# PROP BASE Intermediate_Dir ".\Release" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\Release" +# PROP Intermediate_Dir ".\Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /Gi /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FR /YX /FD /G5Fry /c +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 +# ADD LINK32 tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:"0x20000000" /subsystem:windows /dll /map /machine:I386 /out:"..\..\windebug\hellfrui.dll" /libpath:"..\..\windebug" +# SUBTRACT LINK32 /verbose /incremental:yes + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\ui___Win" +# PROP BASE Intermediate_Dir ".\ui___Win" +# PROP BASE Target_Dir "." +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\debug" +# PROP Intermediate_Dir ".\debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "." +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MDd /W3 /Gm /Gi /GR /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /Fd".\debug\Debug/" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# ADD LINK32 winspool.lib comdlg32.lib uuid.lib tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:"0x20000000" /subsystem:windows /dll /map:"..\..\windebug/hellfrui.map" /debug /machine:I386 /out:"..\..\windebug\hellfrui.dll" /libpath:"..\..\windebug" +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "ui - Win32 Release" +# Name "ui - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\artfont.cpp +# End Source File +# Begin Source File + +SOURCE=.\connect.cpp +# End Source File +# Begin Source File + +SOURCE=.\CopyProt.cpp +# End Source File +# Begin Source File + +SOURCE=.\cr8game.cpp +# End Source File +# Begin Source File + +SOURCE=.\CreaDung.cpp +# End Source File +# Begin Source File + +SOURCE=.\CreaHero.cpp +# End Source File +# Begin Source File + +SOURCE=.\credits.cpp +# End Source File +# Begin Source File + +SOURCE=.\DiabEdit.cpp +# End Source File +# Begin Source File + +SOURCE=.\Diabloui.cpp +# End Source File +# Begin Source File + +SOURCE=.\Diabloui.def +# End Source File +# Begin Source File + +SOURCE=.\DiabloUI.rc + +!IF "$(CFG)" == "ui - Win32 Release" + +!ELSEIF "$(CFG)" == "ui - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\DirLink.cpp +# End Source File +# Begin Source File + +SOURCE=.\disclaim.cpp +# End Source File +# Begin Source File + +SOURCE=.\Doom.cpp +# End Source File +# Begin Source File + +SOURCE=.\EntrDial.cpp +# End Source File +# Begin Source File + +SOURCE=.\EntrName.cpp +# End Source File +# Begin Source File + +SOURCE=.\Fade.cpp +# End Source File +# Begin Source File + +SOURCE=.\Focus.cpp +# End Source File +# Begin Source File + +SOURCE=.\local.cpp +# End Source File +# Begin Source File + +SOURCE=.\Logon.cpp +# End Source File +# Begin Source File + +SOURCE=.\MainMenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\Modem.cpp +# End Source File +# Begin Source File + +SOURCE=.\ModmStat.cpp +# End Source File +# Begin Source File + +SOURCE=.\OkCancel.cpp +# End Source File +# Begin Source File + +SOURCE=.\Progress.cpp +# End Source File +# Begin Source File + +SOURCE=.\Sbar.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelClass.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelConn.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelDial.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelGame.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelHero.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelIPX.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelList.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelLoad.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelModem.cpp +# End Source File +# Begin Source File + +SOURCE=.\SelYesNo.cpp +# End Source File +# Begin Source File + +SOURCE=.\Support.cpp +# End Source File +# Begin Source File + +SOURCE=.\Title.cpp +# End Source File +# Begin Source File + +SOURCE=.\UiSnd.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\artfont.h +# End Source File +# Begin Source File + +SOURCE=.\DiabEdit.h +# End Source File +# Begin Source File + +SOURCE=.\Diabloui.h +# End Source File +# Begin Source File + +SOURCE=.\Doom.h +# End Source File +# Begin Source File + +SOURCE=.\Fade.h +# End Source File +# Begin Source File + +SOURCE=.\local.h +# End Source File +# Begin Source File + +SOURCE=.\Pch.h +# End Source File +# Begin Source File + +SOURCE=.\Sbar.h +# End Source File +# Begin Source File + +SOURCE=.\UiSnd.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\arrow.cur +# End Source File +# Begin Source File + +SOURCE=.\ibeam.cur +# End Source File +# Begin Source File + +SOURCE=.\link.cur +# End Source File +# Begin Source File + +SOURCE=.\Pointer.cur +# End Source File +# End Group +# Begin Source File + +SOURCE=.\But_sml.raw +# End Source File +# Begin Source File + +SOURCE=.\Credits.txt +# End Source File +# Begin Source File + +SOURCE=.\Frank.rc +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\Mike.rc +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\Srpopup.pal +# End Source File +# Begin Source File + +SOURCE=.\Srpopup.raw +# End Source File +# Begin Source File + +SOURCE=.\Support.txt +# End Source File +# End Target +# End Project diff --git a/src/Uisrc/UI/UI.PLG b/src/Uisrc/UI/UI.PLG new file mode 100644 index 0000000..bce1d82 --- /dev/null +++ b/src/Uisrc/UI/UI.PLG @@ -0,0 +1,17 @@ +--------------------Configuration: ui - Win32 Release-------------------- +Begining build with project "U:\diabloui\ui\ui.dsp", at root. +Active configuration is Win32 (x86) Dynamic-Link Library (based on Win32 (x86) Dynamic-Link Library) + +Project's tools are: + "32-bit C/C++ Compiler for 80x86" with flags "/nologo /MT /W3 /O2 /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fp".\Release/ui.pch" /YX /Fo".\Release/" /Fd".\Release/" /FD /G5Fry /c " + "OLE Type Library Maker" with flags "/nologo /D "NDEBUG" /mktyplib203 /win32 " + "Win32 Resource Compiler" with flags "/l 0x409 /fo".\Release/DiabloUI.res" /d "NDEBUG" " + "Browser Database Maker" with flags "/nologo /o".\Release/ui.bsc" " + "COFF Linker for 80x86" with flags "tapi32.lib kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib wsock32.lib storm.lib /nologo /base:"0x20000000" /subsystem:windows /dll /incremental:no /pdb:".\Release/diabloui.pdb" /map:".\Release/diabloui.map" /machine:I386 /def:".\Diabloui.def" /out:"..\bin\diabloui.dll" /implib:".\Release/diabloui.lib" /libpath:"u:\diabloui" " + "Custom Build" with flags "" + "" with flags "" + + + + +diabloui.dll - 0 error(s), 0 warning(s) diff --git a/src/Uisrc/UI/UISND.CPP b/src/Uisrc/UI/UISND.CPP new file mode 100644 index 0000000..9ca9fd3 --- /dev/null +++ b/src/Uisrc/UI/UISND.CPP @@ -0,0 +1,48 @@ +//**************************************************************************** +// UiSnd.cpp +// created 10.20.96 +//**************************************************************************** + + +#include "pch.h" + + +//**************************************************************************** +//**************************************************************************** + static PLAYSND sgPlaySndFcn; + + +//**************************************************************************** +//**************************************************************************** +void UiSndPlay(LPCSTR sndfile) { + if (! sgPlaySndFcn) return; + sgPlaySndFcn(sndfile); +} + + +//**************************************************************************** +//**************************************************************************** +void UiSndSetFcn(PLAYSND sndfcn) { + sgPlaySndFcn = sndfcn; +} + + +//**************************************************************************** +//**************************************************************************** +void UiSndInit(void) { + sgPlaySndFcn = (PLAYSND) NULL; +} + + +//**************************************************************************** +//**************************************************************************** +void UiSndPlayClick(void) { + UiSndPlay("sfx\\items\\titlemov.wav"); +} + + +//**************************************************************************** +//**************************************************************************** +void UiSndPlayEnter(void) { + UiSndPlay("sfx\\items\\titlslct.wav"); +} diff --git a/src/Uisrc/UI/UISND.H b/src/Uisrc/UI/UISND.H new file mode 100644 index 0000000..83ebfaa --- /dev/null +++ b/src/Uisrc/UI/UISND.H @@ -0,0 +1,13 @@ +//**************************************************************************** +// UiSnd.h +// created 9.13.96 +//**************************************************************************** + + +//**************************************************************************** +//**************************************************************************** +void UiSndInit(void); +void UiSndSetFcn(PLAYSND sndfcn); +void UiSndPlay(LPCSTR sndfile); +void UiSndPlayClick(void); +void UiSndPlayEnter(void); diff --git a/src/Uisrc/UI/UNUSED.H b/src/Uisrc/UI/UNUSED.H new file mode 100644 index 0000000..a9a26c9 --- /dev/null +++ b/src/Uisrc/UI/UNUSED.H @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by DiabloUI.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 103 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Uisrc/UISRC.DSP b/src/Uisrc/UISRC.DSP new file mode 100644 index 0000000..a2080e1 --- /dev/null +++ b/src/Uisrc/UISRC.DSP @@ -0,0 +1,312 @@ +# Microsoft Developer Studio Project File - Name="uisrc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=uisrc - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "uisrc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "uisrc.mak" CFG="uisrc - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "uisrc - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "uisrc - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "uisrc - Win32 Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f uisrc.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "uisrc.exe" +# PROP BASE Bsc_Name "uisrc.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "NMAKE /f uisrc.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "uisrc.exe" +# PROP Bsc_Name "uisrc.bsc" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "uisrc - Win32 Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f uisrc.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "uisrc.exe" +# PROP BASE Bsc_Name "uisrc.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "NMAKE /f uisrc.mak" +# PROP Rebuild_Opt "/a" +# PROP Target_File "uisrc.exe" +# PROP Bsc_Name "uisrc.bsc" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "uisrc - Win32 Release" +# Name "uisrc - Win32 Debug" + +!IF "$(CFG)" == "uisrc - Win32 Release" + +!ELSEIF "$(CFG)" == "uisrc - Win32 Debug" + +!ENDIF + +# Begin Group "Source Files" + +# PROP Default_Filter "*.cpp" +# Begin Source File + +SOURCE=.\Ui\Artfont.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Connect.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Copyprot.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Cr8game.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Creadung.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Creahero.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Credits.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Diabedit.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Diabloui.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Dirlink.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Disclaim.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Doom.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Entrdial.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Entrname.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Fade.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Focus.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Local.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Logon.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Mainmenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Modem.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Modmstat.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Okcancel.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Progress.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Sample.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Sbar.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selclass.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selconn.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Seldial.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selgame.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selhero.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selipx.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Sellist.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selload.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selmodem.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selmult.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selsing.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Selyesno.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Title.cpp +# End Source File +# Begin Source File + +SOURCE=.\Ui\Uisnd.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "*.h" +# Begin Source File + +SOURCE=.\Ui\Artfont.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Bnet.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Diabedit.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Diabloui.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Doom.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Fade.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Frank.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Local.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Mike.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Pch.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Sbar.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Uisnd.h +# End Source File +# Begin Source File + +SOURCE=.\Ui\Unused.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "*.rc" +# Begin Source File + +SOURCE=.\Ui\Diabloui.rc +# End Source File +# Begin Source File + +SOURCE=.\Ui\Frank.rc +# End Source File +# Begin Source File + +SOURCE=.\Ui\Mike.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/src/Uisrc/UISRC.PLG b/src/Uisrc/UISRC.PLG new file mode 100644 index 0000000..f8d54ba --- /dev/null +++ b/src/Uisrc/UISRC.PLG @@ -0,0 +1,13 @@ +--------------------Configuration: uisrc - Win32 Debug-------------------- + + +Microsoft (R) Program Maintenance Utility Version 1.62.7022 +Copyright (C) Microsoft Corp 1988-1997. All rights reserved. + +NMAKE : fatal error U1052: file 'uisrc.mak' not found +Stop. +Error executing NMAKE. + + + +uisrc.exe - 1 error(s), 0 warning(s) diff --git a/src/Uisrc/UI_ART/BADCONN.PCX b/src/Uisrc/UI_ART/BADCONN.PCX new file mode 100644 index 0000000..63d3037 Binary files /dev/null and b/src/Uisrc/UI_ART/BADCONN.PCX differ diff --git a/src/Uisrc/UI_ART/BLACK.PCX b/src/Uisrc/UI_ART/BLACK.PCX new file mode 100644 index 0000000..2e933a5 Binary files /dev/null and b/src/Uisrc/UI_ART/BLACK.PCX differ diff --git a/src/Uisrc/UI_ART/BNBUTTNS.PCX b/src/Uisrc/UI_ART/BNBUTTNS.PCX new file mode 100644 index 0000000..be86238 Binary files /dev/null and b/src/Uisrc/UI_ART/BNBUTTNS.PCX differ diff --git a/src/Uisrc/UI_ART/BNCONNBG.PCX b/src/Uisrc/UI_ART/BNCONNBG.PCX new file mode 100644 index 0000000..57e5c84 Binary files /dev/null and b/src/Uisrc/UI_ART/BNCONNBG.PCX differ diff --git a/src/Uisrc/UI_ART/BNJOINBG.PCX b/src/Uisrc/UI_ART/BNJOINBG.PCX new file mode 100644 index 0000000..9a06ae2 Binary files /dev/null and b/src/Uisrc/UI_ART/BNJOINBG.PCX differ diff --git a/src/Uisrc/UI_ART/BNSELCHN.PCX b/src/Uisrc/UI_ART/BNSELCHN.PCX new file mode 100644 index 0000000..26d535b Binary files /dev/null and b/src/Uisrc/UI_ART/BNSELCHN.PCX differ diff --git a/src/Uisrc/UI_ART/BN_BKG.PCX b/src/Uisrc/UI_ART/BN_BKG.PCX new file mode 100644 index 0000000..e207abc Binary files /dev/null and b/src/Uisrc/UI_ART/BN_BKG.PCX differ diff --git a/src/Uisrc/UI_ART/BUTTON.PCX b/src/Uisrc/UI_ART/BUTTON.PCX new file mode 100644 index 0000000..2d0986f Binary files /dev/null and b/src/Uisrc/UI_ART/BUTTON.PCX differ diff --git a/src/Uisrc/UI_ART/BUT_LRG.PCX b/src/Uisrc/UI_ART/BUT_LRG.PCX new file mode 100644 index 0000000..808657c Binary files /dev/null and b/src/Uisrc/UI_ART/BUT_LRG.PCX differ diff --git a/src/Uisrc/UI_ART/BUT_MED.PCX b/src/Uisrc/UI_ART/BUT_MED.PCX new file mode 100644 index 0000000..b8500a8 Binary files /dev/null and b/src/Uisrc/UI_ART/BUT_MED.PCX differ diff --git a/src/Uisrc/UI_ART/BUT_SML.PCX b/src/Uisrc/UI_ART/BUT_SML.PCX new file mode 100644 index 0000000..666c3ad Binary files /dev/null and b/src/Uisrc/UI_ART/BUT_SML.PCX differ diff --git a/src/Uisrc/UI_ART/BUT_XSM.PCX b/src/Uisrc/UI_ART/BUT_XSM.PCX new file mode 100644 index 0000000..c6363ef Binary files /dev/null and b/src/Uisrc/UI_ART/BUT_XSM.PCX differ diff --git a/src/Uisrc/UI_ART/CD_ICONS.PCX b/src/Uisrc/UI_ART/CD_ICONS.PCX new file mode 100644 index 0000000..e2147c8 Binary files /dev/null and b/src/Uisrc/UI_ART/CD_ICONS.PCX differ diff --git a/src/Uisrc/UI_ART/CHAT_BKG.PCX b/src/Uisrc/UI_ART/CHAT_BKG.PCX new file mode 100644 index 0000000..bf13bd3 Binary files /dev/null and b/src/Uisrc/UI_ART/CHAT_BKG.PCX differ diff --git a/src/Uisrc/UI_ART/CONNANIM.PCX b/src/Uisrc/UI_ART/CONNANIM.PCX new file mode 100644 index 0000000..28839ef Binary files /dev/null and b/src/Uisrc/UI_ART/CONNANIM.PCX differ diff --git a/src/Uisrc/UI_ART/CONNECT.PCX b/src/Uisrc/UI_ART/CONNECT.PCX new file mode 100644 index 0000000..350dbe6 Binary files /dev/null and b/src/Uisrc/UI_ART/CONNECT.PCX differ diff --git a/src/Uisrc/UI_ART/CREAHERO.PCX b/src/Uisrc/UI_ART/CREAHERO.PCX new file mode 100644 index 0000000..10282d6 Binary files /dev/null and b/src/Uisrc/UI_ART/CREAHERO.PCX differ diff --git a/src/Uisrc/UI_ART/CREAT_BG.PCX b/src/Uisrc/UI_ART/CREAT_BG.PCX new file mode 100644 index 0000000..e1a5179 Binary files /dev/null and b/src/Uisrc/UI_ART/CREAT_BG.PCX differ diff --git a/src/Uisrc/UI_ART/CREDITS.PCX b/src/Uisrc/UI_ART/CREDITS.PCX new file mode 100644 index 0000000..90831b7 Binary files /dev/null and b/src/Uisrc/UI_ART/CREDITS.PCX differ diff --git a/src/Uisrc/UI_ART/CURSOR.PCX b/src/Uisrc/UI_ART/CURSOR.PCX new file mode 100644 index 0000000..796fd96 Binary files /dev/null and b/src/Uisrc/UI_ART/CURSOR.PCX differ diff --git a/src/Uisrc/UI_ART/DIFFBTNS.PCX b/src/Uisrc/UI_ART/DIFFBTNS.PCX new file mode 100644 index 0000000..ea087b9 Binary files /dev/null and b/src/Uisrc/UI_ART/DIFFBTNS.PCX differ diff --git a/src/Uisrc/UI_ART/DISCLAIM.PCX b/src/Uisrc/UI_ART/DISCLAIM.PCX new file mode 100644 index 0000000..2e933a5 Binary files /dev/null and b/src/Uisrc/UI_ART/DISCLAIM.PCX differ diff --git a/src/Uisrc/UI_ART/DP_PREFS b/src/Uisrc/UI_ART/DP_PREFS new file mode 100644 index 0000000..0fd8e1a Binary files /dev/null and b/src/Uisrc/UI_ART/DP_PREFS differ diff --git a/src/Uisrc/UI_ART/EPOPUP.PCX b/src/Uisrc/UI_ART/EPOPUP.PCX new file mode 100644 index 0000000..1c5929c Binary files /dev/null and b/src/Uisrc/UI_ART/EPOPUP.PCX differ diff --git a/src/Uisrc/UI_ART/FOCUS.PCX b/src/Uisrc/UI_ART/FOCUS.PCX new file mode 100644 index 0000000..b582314 Binary files /dev/null and b/src/Uisrc/UI_ART/FOCUS.PCX differ diff --git a/src/Uisrc/UI_ART/FOCUS16.PCX b/src/Uisrc/UI_ART/FOCUS16.PCX new file mode 100644 index 0000000..00e2f69 Binary files /dev/null and b/src/Uisrc/UI_ART/FOCUS16.PCX differ diff --git a/src/Uisrc/UI_ART/FOCUS42.PCX b/src/Uisrc/UI_ART/FOCUS42.PCX new file mode 100644 index 0000000..9fe951a Binary files /dev/null and b/src/Uisrc/UI_ART/FOCUS42.PCX differ diff --git a/src/Uisrc/UI_ART/FONT16.BIN b/src/Uisrc/UI_ART/FONT16.BIN new file mode 100644 index 0000000..4644d34 Binary files /dev/null and b/src/Uisrc/UI_ART/FONT16.BIN differ diff --git a/src/Uisrc/UI_ART/FONT16G.PCX b/src/Uisrc/UI_ART/FONT16G.PCX new file mode 100644 index 0000000..c60b11e Binary files /dev/null and b/src/Uisrc/UI_ART/FONT16G.PCX differ diff --git a/src/Uisrc/UI_ART/FONT16S.PCX b/src/Uisrc/UI_ART/FONT16S.PCX new file mode 100644 index 0000000..92d43b1 Binary files /dev/null and b/src/Uisrc/UI_ART/FONT16S.PCX differ diff --git a/src/Uisrc/UI_ART/FONT24.BIN b/src/Uisrc/UI_ART/FONT24.BIN new file mode 100644 index 0000000..a85e5c9 Binary files /dev/null and b/src/Uisrc/UI_ART/FONT24.BIN differ diff --git a/src/Uisrc/UI_ART/FONT24G.PCX b/src/Uisrc/UI_ART/FONT24G.PCX new file mode 100644 index 0000000..a248cad Binary files /dev/null and b/src/Uisrc/UI_ART/FONT24G.PCX differ diff --git a/src/Uisrc/UI_ART/FONT24S.PCX b/src/Uisrc/UI_ART/FONT24S.PCX new file mode 100644 index 0000000..bde1871 Binary files /dev/null and b/src/Uisrc/UI_ART/FONT24S.PCX differ diff --git a/src/Uisrc/UI_ART/FONT30.BIN b/src/Uisrc/UI_ART/FONT30.BIN new file mode 100644 index 0000000..445346d Binary files /dev/null and b/src/Uisrc/UI_ART/FONT30.BIN differ diff --git a/src/Uisrc/UI_ART/FONT30G.PCX b/src/Uisrc/UI_ART/FONT30G.PCX new file mode 100644 index 0000000..fb5ef5a Binary files /dev/null and b/src/Uisrc/UI_ART/FONT30G.PCX differ diff --git a/src/Uisrc/UI_ART/FONT30S.PCX b/src/Uisrc/UI_ART/FONT30S.PCX new file mode 100644 index 0000000..d801c01 Binary files /dev/null and b/src/Uisrc/UI_ART/FONT30S.PCX differ diff --git a/src/Uisrc/UI_ART/FONT42.BIN b/src/Uisrc/UI_ART/FONT42.BIN new file mode 100644 index 0000000..9598a09 Binary files /dev/null and b/src/Uisrc/UI_ART/FONT42.BIN differ diff --git a/src/Uisrc/UI_ART/FONT42G.PCX b/src/Uisrc/UI_ART/FONT42G.PCX new file mode 100644 index 0000000..550289b Binary files /dev/null and b/src/Uisrc/UI_ART/FONT42G.PCX differ diff --git a/src/Uisrc/UI_ART/FONT42Y.PCX b/src/Uisrc/UI_ART/FONT42Y.PCX new file mode 100644 index 0000000..4a36544 Binary files /dev/null and b/src/Uisrc/UI_ART/FONT42Y.PCX differ diff --git a/src/Uisrc/UI_ART/GREENLAG.PCX b/src/Uisrc/UI_ART/GREENLAG.PCX new file mode 100644 index 0000000..e0bf980 Binary files /dev/null and b/src/Uisrc/UI_ART/GREENLAG.PCX differ diff --git a/src/Uisrc/UI_ART/HERONUM.PCX b/src/Uisrc/UI_ART/HERONUM.PCX new file mode 100644 index 0000000..ca73572 Binary files /dev/null and b/src/Uisrc/UI_ART/HERONUM.PCX differ diff --git a/src/Uisrc/UI_ART/HEROPORT.PCX b/src/Uisrc/UI_ART/HEROPORT.PCX new file mode 100644 index 0000000..e7e3a93 Binary files /dev/null and b/src/Uisrc/UI_ART/HEROPORT.PCX differ diff --git a/src/Uisrc/UI_ART/HEROS.PCX b/src/Uisrc/UI_ART/HEROS.PCX new file mode 100644 index 0000000..6c050b5 Binary files /dev/null and b/src/Uisrc/UI_ART/HEROS.PCX differ diff --git a/src/Uisrc/UI_ART/HF_LOGO1.PCX b/src/Uisrc/UI_ART/HF_LOGO1.PCX new file mode 100644 index 0000000..c074a82 Binary files /dev/null and b/src/Uisrc/UI_ART/HF_LOGO1.PCX differ diff --git a/src/Uisrc/UI_ART/HF_TITLE.PCX b/src/Uisrc/UI_ART/HF_TITLE.PCX new file mode 100644 index 0000000..1a4429c Binary files /dev/null and b/src/Uisrc/UI_ART/HF_TITLE.PCX differ diff --git a/src/Uisrc/UI_ART/HPOPUP.PCX b/src/Uisrc/UI_ART/HPOPUP.PCX new file mode 100644 index 0000000..5c9658b Binary files /dev/null and b/src/Uisrc/UI_ART/HPOPUP.PCX differ diff --git a/src/Uisrc/UI_ART/IPX_BKG.PCX b/src/Uisrc/UI_ART/IPX_BKG.PCX new file mode 100644 index 0000000..440f69e Binary files /dev/null and b/src/Uisrc/UI_ART/IPX_BKG.PCX differ diff --git a/src/Uisrc/UI_ART/LEPOPUP.PCX b/src/Uisrc/UI_ART/LEPOPUP.PCX new file mode 100644 index 0000000..3cfbed5 Binary files /dev/null and b/src/Uisrc/UI_ART/LEPOPUP.PCX differ diff --git a/src/Uisrc/UI_ART/LISTBOX.PCX b/src/Uisrc/UI_ART/LISTBOX.PCX new file mode 100644 index 0000000..8a3af8b Binary files /dev/null and b/src/Uisrc/UI_ART/LISTBOX.PCX differ diff --git a/src/Uisrc/UI_ART/LIST_GRY.PCX b/src/Uisrc/UI_ART/LIST_GRY.PCX new file mode 100644 index 0000000..68b16b4 Binary files /dev/null and b/src/Uisrc/UI_ART/LIST_GRY.PCX differ diff --git a/src/Uisrc/UI_ART/LOGO.PCX b/src/Uisrc/UI_ART/LOGO.PCX new file mode 100644 index 0000000..14817e6 Binary files /dev/null and b/src/Uisrc/UI_ART/LOGO.PCX differ diff --git a/src/Uisrc/UI_ART/LPOPUP.PCX b/src/Uisrc/UI_ART/LPOPUP.PCX new file mode 100644 index 0000000..3cfbed5 Binary files /dev/null and b/src/Uisrc/UI_ART/LPOPUP.PCX differ diff --git a/src/Uisrc/UI_ART/LRPOPUP.PCX b/src/Uisrc/UI_ART/LRPOPUP.PCX new file mode 100644 index 0000000..441c1d7 Binary files /dev/null and b/src/Uisrc/UI_ART/LRPOPUP.PCX differ diff --git a/src/Uisrc/UI_ART/MAINMENU.PCX b/src/Uisrc/UI_ART/MAINMENU.PCX new file mode 100644 index 0000000..8344133 Binary files /dev/null and b/src/Uisrc/UI_ART/MAINMENU.PCX differ diff --git a/src/Uisrc/UI_ART/MENU.PCX b/src/Uisrc/UI_ART/MENU.PCX new file mode 100644 index 0000000..6eae183 Binary files /dev/null and b/src/Uisrc/UI_ART/MENU.PCX differ diff --git a/src/Uisrc/UI_ART/MMPOPUP.PCX b/src/Uisrc/UI_ART/MMPOPUP.PCX new file mode 100644 index 0000000..0d14205 Binary files /dev/null and b/src/Uisrc/UI_ART/MMPOPUP.PCX differ diff --git a/src/Uisrc/UI_ART/PRINTER0.BIN b/src/Uisrc/UI_ART/PRINTER0.BIN new file mode 100644 index 0000000..a536e94 Binary files /dev/null and b/src/Uisrc/UI_ART/PRINTER0.BIN differ diff --git a/src/Uisrc/UI_ART/PROG_BG.PCX b/src/Uisrc/UI_ART/PROG_BG.PCX new file mode 100644 index 0000000..21aadcb Binary files /dev/null and b/src/Uisrc/UI_ART/PROG_BG.PCX differ diff --git a/src/Uisrc/UI_ART/PROG_FIL.PCX b/src/Uisrc/UI_ART/PROG_FIL.PCX new file mode 100644 index 0000000..a686555 Binary files /dev/null and b/src/Uisrc/UI_ART/PROG_FIL.PCX differ diff --git a/src/Uisrc/UI_ART/R1_GRY.PCX b/src/Uisrc/UI_ART/R1_GRY.PCX new file mode 100644 index 0000000..ca710ca Binary files /dev/null and b/src/Uisrc/UI_ART/R1_GRY.PCX differ diff --git a/src/Uisrc/UI_ART/R3_GRY.PCX b/src/Uisrc/UI_ART/R3_GRY.PCX new file mode 100644 index 0000000..17a7013 Binary files /dev/null and b/src/Uisrc/UI_ART/R3_GRY.PCX differ diff --git a/src/Uisrc/UI_ART/RADIO1.PCX b/src/Uisrc/UI_ART/RADIO1.PCX new file mode 100644 index 0000000..9963ae1 Binary files /dev/null and b/src/Uisrc/UI_ART/RADIO1.PCX differ diff --git a/src/Uisrc/UI_ART/RADIO2.PCX b/src/Uisrc/UI_ART/RADIO2.PCX new file mode 100644 index 0000000..d6b1be4 Binary files /dev/null and b/src/Uisrc/UI_ART/RADIO2.PCX differ diff --git a/src/Uisrc/UI_ART/RADIO3.PCX b/src/Uisrc/UI_ART/RADIO3.PCX new file mode 100644 index 0000000..78d2bac Binary files /dev/null and b/src/Uisrc/UI_ART/RADIO3.PCX differ diff --git a/src/Uisrc/UI_ART/RADIO4.PCX b/src/Uisrc/UI_ART/RADIO4.PCX new file mode 100644 index 0000000..0331c72 Binary files /dev/null and b/src/Uisrc/UI_ART/RADIO4.PCX differ diff --git a/src/Uisrc/UI_ART/REDLAG.PCX b/src/Uisrc/UI_ART/REDLAG.PCX new file mode 100644 index 0000000..18be66c Binary files /dev/null and b/src/Uisrc/UI_ART/REDLAG.PCX differ diff --git a/src/Uisrc/UI_ART/SB_ARROW.PCX b/src/Uisrc/UI_ART/SB_ARROW.PCX new file mode 100644 index 0000000..6daee29 Binary files /dev/null and b/src/Uisrc/UI_ART/SB_ARROW.PCX differ diff --git a/src/Uisrc/UI_ART/SB_BG.PCX b/src/Uisrc/UI_ART/SB_BG.PCX new file mode 100644 index 0000000..3fefb1d Binary files /dev/null and b/src/Uisrc/UI_ART/SB_BG.PCX differ diff --git a/src/Uisrc/UI_ART/SB_THUMB.PCX b/src/Uisrc/UI_ART/SB_THUMB.PCX new file mode 100644 index 0000000..f874971 Binary files /dev/null and b/src/Uisrc/UI_ART/SB_THUMB.PCX differ diff --git a/src/Uisrc/UI_ART/SCRLARRW.PCX b/src/Uisrc/UI_ART/SCRLARRW.PCX new file mode 100644 index 0000000..f9c4e31 Binary files /dev/null and b/src/Uisrc/UI_ART/SCRLARRW.PCX differ diff --git a/src/Uisrc/UI_ART/SCRLBAR.PCX b/src/Uisrc/UI_ART/SCRLBAR.PCX new file mode 100644 index 0000000..74ad334 Binary files /dev/null and b/src/Uisrc/UI_ART/SCRLBAR.PCX differ diff --git a/src/Uisrc/UI_ART/SCRLTHMB.PCX b/src/Uisrc/UI_ART/SCRLTHMB.PCX new file mode 100644 index 0000000..144fe17 Binary files /dev/null and b/src/Uisrc/UI_ART/SCRLTHMB.PCX differ diff --git a/src/Uisrc/UI_ART/SELCONN.PCX b/src/Uisrc/UI_ART/SELCONN.PCX new file mode 100644 index 0000000..c734127 Binary files /dev/null and b/src/Uisrc/UI_ART/SELCONN.PCX differ diff --git a/src/Uisrc/UI_ART/SELDIFF.PCX b/src/Uisrc/UI_ART/SELDIFF.PCX new file mode 100644 index 0000000..ffd3510 Binary files /dev/null and b/src/Uisrc/UI_ART/SELDIFF.PCX differ diff --git a/src/Uisrc/UI_ART/SELGAME.PCX b/src/Uisrc/UI_ART/SELGAME.PCX new file mode 100644 index 0000000..c734127 Binary files /dev/null and b/src/Uisrc/UI_ART/SELGAME.PCX differ diff --git a/src/Uisrc/UI_ART/SELHERO.PCX b/src/Uisrc/UI_ART/SELHERO.PCX new file mode 100644 index 0000000..dc49f5e Binary files /dev/null and b/src/Uisrc/UI_ART/SELHERO.PCX differ diff --git a/src/Uisrc/UI_ART/SMLOGO.PCX b/src/Uisrc/UI_ART/SMLOGO.PCX new file mode 100644 index 0000000..05bb854 Binary files /dev/null and b/src/Uisrc/UI_ART/SMLOGO.PCX differ diff --git a/src/Uisrc/UI_ART/SPECIAL.PCX b/src/Uisrc/UI_ART/SPECIAL.PCX new file mode 100644 index 0000000..9ebf1ec Binary files /dev/null and b/src/Uisrc/UI_ART/SPECIAL.PCX differ diff --git a/src/Uisrc/UI_ART/SPOPUP.PCX b/src/Uisrc/UI_ART/SPOPUP.PCX new file mode 100644 index 0000000..0029f35 Binary files /dev/null and b/src/Uisrc/UI_ART/SPOPUP.PCX differ diff --git a/src/Uisrc/UI_ART/SPWNPORT.PCX b/src/Uisrc/UI_ART/SPWNPORT.PCX new file mode 100644 index 0000000..42296b8 Binary files /dev/null and b/src/Uisrc/UI_ART/SPWNPORT.PCX differ diff --git a/src/Uisrc/UI_ART/SRPOPUP.PCX b/src/Uisrc/UI_ART/SRPOPUP.PCX new file mode 100644 index 0000000..8216de5 Binary files /dev/null and b/src/Uisrc/UI_ART/SRPOPUP.PCX differ diff --git a/src/Uisrc/UI_ART/SUPPORT.PCX b/src/Uisrc/UI_ART/SUPPORT.PCX new file mode 100644 index 0000000..90831b7 Binary files /dev/null and b/src/Uisrc/UI_ART/SUPPORT.PCX differ diff --git a/src/Uisrc/UI_ART/SWMMENU.PCX b/src/Uisrc/UI_ART/SWMMENU.PCX new file mode 100644 index 0000000..6ef2290 Binary files /dev/null and b/src/Uisrc/UI_ART/SWMMENU.PCX differ diff --git a/src/Uisrc/UI_ART/SWMMPOP.PCX b/src/Uisrc/UI_ART/SWMMPOP.PCX new file mode 100644 index 0000000..8b40bdf Binary files /dev/null and b/src/Uisrc/UI_ART/SWMMPOP.PCX differ diff --git a/src/Uisrc/UI_ART/TITLE.PCX b/src/Uisrc/UI_ART/TITLE.PCX new file mode 100644 index 0000000..5aa9c2d Binary files /dev/null and b/src/Uisrc/UI_ART/TITLE.PCX differ diff --git a/src/Uisrc/UI_ART/WELCOME.PCX b/src/Uisrc/UI_ART/WELCOME.PCX new file mode 100644 index 0000000..67b02e8 Binary files /dev/null and b/src/Uisrc/UI_ART/WELCOME.PCX differ diff --git a/src/Uisrc/UI_ART/XSMLOGO.PCX b/src/Uisrc/UI_ART/XSMLOGO.PCX new file mode 100644 index 0000000..3e85aaf Binary files /dev/null and b/src/Uisrc/UI_ART/XSMLOGO.PCX differ diff --git a/src/Uisrc/UI_ART/YELLOLAG.PCX b/src/Uisrc/UI_ART/YELLOLAG.PCX new file mode 100644 index 0000000..3249b84 Binary files /dev/null and b/src/Uisrc/UI_ART/YELLOLAG.PCX differ diff --git a/src/WAVE.CPP b/src/WAVE.CPP new file mode 100644 index 0000000..d02ba83 --- /dev/null +++ b/src/WAVE.CPP @@ -0,0 +1,341 @@ +//****************************************************************** +// wave.cpp +// created 10.18.96 +// written by Patrick Wyatt +//****************************************************************** + + +#include "diablo.h" +#pragma hdrstop +#include "storm.h" +#include "sound.h" +#include "engine.h" + + +//****************************************************************** +// externs +//****************************************************************** +extern HSARCHIVE ghsMainArchive; +void FileErrorDlg(const char * pszName); +// pjw.patch1.start.1/13/97 +BOOL InsertCDDlg(); +// pjw.patch1.end.1/13/97 + + +//****************************************************************** +//****************************************************************** +static void reinsert_cd(HSFILE hsFile,DWORD * pdwTryCount,const char * pszFile) { + HSARCHIVE hsArchive; + + // fatal if we've tried to many times + if (*pdwTryCount >= 5) FileErrorDlg(pszFile); + + if (hsFile && SFileGetFileArchive(hsFile,&hsArchive) && (hsArchive != ghsMainArchive)) { + // wait for transient disk error to disappear + Sleep(20); + *pdwTryCount += 1; + } + else { + // pjw.patch1.start.1/13/97 + if (! InsertCDDlg()) FileErrorDlg(pszFile); + // pjw.patch1.end.1/13/97 + } +} + + + +//****************************************************************** +//****************************************************************** +void patSFileCloseFile(HSFILE handle) { + SFileCloseFile(handle); +} + + +//****************************************************************** +//****************************************************************** +DWORD patSFileGetFileSize(HSFILE handle,LPDWORD filesizehigh) { + DWORD dwSize; + DWORD dwTryCount = 0; + while (0 == (dwSize = SFileGetFileSize(handle,filesizehigh))) + reinsert_cd(handle,&dwTryCount,NULL); + return dwSize; +} + + +//****************************************************************** +//****************************************************************** +BOOL patSFileOpenFile(LPCTSTR filename,HSFILE *handle,BOOL bCanFail) { + DWORD dwTryCount = 0; + while (1) { + if (SFileOpenFile(filename,handle)) return TRUE; + if (bCanFail && GetLastError() == SFILE_ERROR_FILE_NOT_FOUND) + return FALSE; + reinsert_cd(NULL,&dwTryCount,filename); + } +} + + +//****************************************************************** +//****************************************************************** +// pjw.patch1.start.1/13/97 +void patSFileReadFile(HSFILE handle,LPVOID buffer,DWORD bytestoread) { + +/* --- old code --- + BOOL bResult; + DWORD dwTryCount = 0; + while (bytestoread) { + DWORD dwBytes; + bResult = SFileReadFile(handle,buffer,bytestoread,&dwBytes,NULL); + if (bResult) return; + + // hopefully we got some bytes + buffer = (LPVOID) ((LPBYTE) buffer + dwBytes); + bytestoread -= dwBytes; + + reinsert_cd(handle,&dwTryCount,NULL); + } +*/ + DWORD dwBytes; + DWORD dwTryCount = 0; + DWORD dwPos = patSFileSetFilePointer(handle,0,NULL,FILE_CURRENT); + while (! SFileReadFile(handle,buffer,bytestoread,&dwBytes,NULL)) { + reinsert_cd(handle,&dwTryCount,NULL); + patSFileSetFilePointer(handle,dwPos,NULL,FILE_BEGIN); + } + app_assert(bytestoread == dwBytes); +} +// pjw.patch1.end.1/13/97 + + +//****************************************************************** +//****************************************************************** +DWORD patSFileSetFilePointer(HSFILE handle,LONG distancetomove,PLONG distancetomovehigh,DWORD movemethod) { + DWORD dwTryCount = 0; + while (1) { + DWORD dwResult = SFileSetFilePointer(handle,distancetomove,distancetomovehigh,movemethod); + if (dwResult != 0xffffffff) + return dwResult; + reinsert_cd(handle,&dwTryCount,NULL); + } +} + + +//****************************************************************** +//****************************************************************** +typedef struct TMemFile { + DWORD dwFileSize; // total file size + DWORD dwFileOffset; // offset in file + DWORD dwBufSize; // buffer size + DWORD dwBufPos; // position in buffer + DWORD dwBufLeft; // bytes left in buffer + LPBYTE lpBuf; // buffer + HSFILE hsFile; // file handle +} TMemFile; +#define MIN_BUF_SIZE 4096 + + +//****************************************************************** +//****************************************************************** +static void MemFileFillBuf(TMemFile * pMemFile) { + app_assert(pMemFile); + + // move to current file position + patSFileSetFilePointer( + pMemFile->hsFile, + pMemFile->dwFileOffset, + 0, + FILE_BEGIN + ); + + // read min(buffer size,file bytes left) + DWORD dwRead = pMemFile->dwFileSize - pMemFile->dwFileOffset; + dwRead = min(pMemFile->dwBufSize,dwRead); + if (dwRead) patSFileReadFile(pMemFile->hsFile,pMemFile->lpBuf,dwRead); + + // update buffer status + pMemFile->dwBufLeft = dwRead; + pMemFile->dwBufPos = 0; +} + + +//****************************************************************** +//****************************************************************** +static void MemFileLoad(HSFILE hsFile,TMemFile * pMemFile,DWORD dwBufSize = 0xffffffff) { + // validate parameters + app_assert(hsFile); + app_assert(pMemFile); + ZeroMemory(pMemFile,sizeof(*pMemFile)); + + // create a buffer for file data no larger than total file size + pMemFile->dwFileSize = patSFileGetFileSize(hsFile); + pMemFile->dwBufSize = max(dwBufSize,MIN_BUF_SIZE); + pMemFile->dwBufSize = min(pMemFile->dwBufSize,pMemFile->dwFileSize); + pMemFile->lpBuf = DiabloAllocPtrSig(pMemFile->dwBufSize,'SNDt'); + pMemFile->hsFile = hsFile; +} + + +//****************************************************************** +//****************************************************************** +static void MemFileFree(TMemFile * pMemFile) { + app_assert(pMemFile); + DiabloFreePtr(pMemFile->lpBuf); +} + + +//****************************************************************** +//****************************************************************** +static BOOL MemFileRead(TMemFile * pMemFile,LPVOID lpBuf,DWORD dwBytes) { + app_assert(pMemFile); + app_assert(lpBuf); + + while (dwBytes) { + // re-fill buffer if required + if (! pMemFile->dwBufLeft) + MemFileFillBuf(pMemFile); + + // copy bytes from buffer + DWORD dwRead = min(dwBytes,pMemFile->dwBufLeft); + if (! dwRead) return FALSE; + CopyMemory(lpBuf,pMemFile->lpBuf + pMemFile->dwBufPos,dwRead); + + // update file + pMemFile->dwFileOffset += dwRead; + pMemFile->dwBufPos += dwRead; + pMemFile->dwBufLeft -= dwRead; + + // update bytes to read + dwBytes -= dwRead; + } + + return TRUE; +} + + +//****************************************************************** +//****************************************************************** +static DWORD MemFileSeek(TMemFile * pMemFile,LONG lDist,DWORD dwMethod) { + // @@ fix this stuff later if these routines get re-used + app_assert(dwMethod == FILE_CURRENT); + app_assert(lDist >= 0); + + if ((DWORD) lDist < pMemFile->dwBufLeft) { + pMemFile->dwBufLeft -= lDist; + pMemFile->dwBufPos += lDist; + } + else { + pMemFile->dwBufLeft = 0; + } + + pMemFile->dwFileOffset += lDist; + return pMemFile->dwFileOffset; +} + + +//****************************************************************** +//****************************************************************** +static BOOL find_chunk(TMemFile * pMemFile,FOURCC ckID,CKINFO * pck) { + struct { + FOURCC ckID; + DWORD dwSize; + } ckHdr; + + while (1) { + + // read chunk header + if (! MemFileRead(pMemFile,&ckHdr,sizeof(ckHdr))) + return FALSE; + + // does it match? + if (ckHdr.ckID == ckID) + break; + + // skip over this chunk + if (0xffffFFFF == MemFileSeek(pMemFile,ckHdr.dwSize,FILE_CURRENT)) + return FALSE; + } + + // get chunk size and position + pck->dwSize = ckHdr.dwSize; + pck->dwOffset = MemFileSeek(pMemFile,0,FILE_CURRENT); + return (pck->dwOffset != 0xffffFFFF); +} + + +//****************************************************************** +//****************************************************************** +static BOOL read_header(TMemFile * pMemFile,WAVEFORMATEX * pwfx,CKINFO * pWaveInfo) { + app_assert(pMemFile); + app_assert(pwfx); + CKINFO fmtInfo; + + // read "RIFF" DWORD=len "WAVE" + MMCKINFO mmck; + if (! MemFileRead(pMemFile,&mmck,sizeof(FOURCC)*2 + sizeof(DWORD))) + return FALSE; + + if ((mmck.ckid != FOURCC_RIFF) || (mmck.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) + return FALSE; + + // Search the input file for for the 'fmt ' chunk + if (! find_chunk(pMemFile,mmioFOURCC('f', 'm', 't', ' '),&fmtInfo)) + return FALSE; + + // Expect 'fmt' chunk to be at least as large as + if (fmtInfo.dwSize < sizeof(PCMWAVEFORMAT)) + return FALSE; + + // Read the 'fmt ' chunk into + PCMWAVEFORMAT pcm; + if (! MemFileRead(pMemFile,&pcm,sizeof(pcm))) + return FALSE; + + // seek over any additional junk in the 'fmt ' chunk + if (0xffffFFFF == MemFileSeek(pMemFile,fmtInfo.dwSize - sizeof(pcm),FILE_CURRENT)) + return FALSE; + + // copy the bytes from the pcm structure to the waveformatex structure + pwfx->wFormatTag = pcm.wf.wFormatTag; + pwfx->nChannels = pcm.wf.nChannels; + pwfx->nSamplesPerSec = pcm.wf.nSamplesPerSec; + pwfx->nAvgBytesPerSec = pcm.wf.nAvgBytesPerSec; + pwfx->nBlockAlign = pcm.wf.nBlockAlign; + pwfx->wBitsPerSample = pcm.wBitsPerSample; + pwfx->cbSize = 0; + + // do we need to find the body info? + if (! pWaveInfo) return TRUE; + return find_chunk(pMemFile,mmioFOURCC('d', 'a', 't', 'a'),pWaveInfo); +} + + +//****************************************************************** +//****************************************************************** +BOOL wave_read_header(HSFILE hsFile,WAVEFORMATEX * pwfx) { + TMemFile memFile; + MemFileLoad(hsFile,&memFile,0); + BOOL bResult = read_header(&memFile,pwfx,NULL); + MemFileFree(&memFile); + return bResult; +} + + +//****************************************************************** +//****************************************************************** +LPBYTE wave_load_file(HSFILE hsFile,WAVEFORMATEX * pwfx,CKINFO * pWaveInfo) { + TMemFile memFile; + MemFileLoad(hsFile,&memFile); + if (! read_header(&memFile,pwfx,pWaveInfo)) { + MemFileFree(&memFile); + return NULL; + } + + return memFile.lpBuf; +} + + +//****************************************************************** +//****************************************************************** +void wave_free_file(LPBYTE lpWave) { + DiabloFreePtr(lpWave); +} diff --git a/src/Windebug/ATOMST~1.DLL b/src/Windebug/ATOMST~1.DLL new file mode 100644 index 0000000..723bac7 Binary files /dev/null and b/src/Windebug/ATOMST~1.DLL differ diff --git a/src/Windebug/BACKLASH.NFO b/src/Windebug/BACKLASH.NFO new file mode 100644 index 0000000..f8f39c9 --- /dev/null +++ b/src/Windebug/BACKLASH.NFO @@ -0,0 +1,134 @@ + + ß ß ß Ý + Û Ü Ü ÜÛÜ Ý ÛÜ ßÜÛÜ ÜÛÜß ÛÝ + ° ÛÛÜ ßÜÜ ÜÛÜß ÜÛÛ Üß ß ßßßß Û ßßß ßßßß ß ß ßÜÛßß ß ßßß ßß ÛÛ ßÜ + ± ÛßÛÛÜ ßÛÛß ÜÜÛÛßß Ûß ÜÜÛÛÛÛÛÛÛß ÞÛÝÛÛÛÛÛÛß ÜÜÛÛÛ²±° ÜÜÛÛÛÛÛÛ²±° ÛÛÛ Û + ° ÛÛÛÛÛÛÜ ß ÛÛÛß °°° ÜÛÛß ÜÜ ÜÜ ÛÛ ÛÛÛß ÜÜÜ ÛÛÛß Ü ÜÜÜ Þ ÛÛÛ Û + ÛÛÛ ßÛÛÛÜ ßÛÛ Ü ±±± ÞÛÛ ÛÛÛ Ûß ÜÛÛß °°° ß ÛÛÛ Ü ÛÛÛ ÛÛÛ ßßÜ ÛÛÛ ² ÛÛÛ Û° + ° ÛÛÛ Ü ßÛÛÛ ÛÛ ß ²²² ÛÛÝÞ ÛÛÛ ÜÛÛß ±±±± Þ ÛÛÛ ÛÛÛ ßÛÛÛÜÜÜ ÛÛÛ ß ÛÛÛ Û± + ± ²²² ß ÜÛÛÛ ÛÛ ÛÛÛÛÛ ÛÛ ²Ý²²²ÛÛÛß Ü² ²²²² Û ²²² ÛÛÛÛÛ Ü ßÛÛÜ ßÛ ÛÛÛÛÛ ²° + °² ±±± ßÛÛÛß ÜÛÛ ÛÛÛ ÛÛ Þ ±±± ßÛÛÜ ß ÛÛÛÛ ² ±±± Ü ÛÛÛ °ÛÛÛÜ ÛÛÛ Û Ü ÛÛÛ ± + ±Û °°° Ü ßÛÛÜ ßÛ Ý ÛÛÛ ÛÛÝ °°° Ü ßÛÛÜ ßÛÛÛ Ý °°° ² ÛÛÛ ß²ßß ÛÛÛ Û ² ÛÛÛ ° + °Û ßß ÛÛÛ Û Û ÛÛÛ ÞÛÛÜ ßß ÛÛÛ ÛÛÛÜ ÛÛÛ ß ÜÛÛÛß Û Ü ÛÛÛ + ßÛÛÛÛÛÛÛÛÛÛÛß Û Ü ÛÛÛ ßÛÛÛÛÛÛÛ²±° ÛÛÛ ßÛÛÛ²±° °± ÛÛß ²ÛÛÛÛÛÛß ÜÛßÞÜ ÛÛÛ ° + Ü Ý ÛÛÛ ßÜ ÜÜÜ Ü ßÛÛ ÛÜÜ Ü Û Þ ßÝÞÛÝ ± + ß ßß ßßßÛÛÜÜ ÜÝ Ûß ßÛß ÛÝ ßÛÛÜ Û ÜßÛÜÛßßßß ß Ý ß ASCII Û ° + ß ßßÛß Ý ß Þ ß ß Ý Ûß ß proudly presents Ý + + + ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿ + ÚÁÄùú úùÄÁ¿ + ³³ þ DiABLO HELLFiRE MULTiPLAYER PATCH þ ³³ + ÀÂÄÄÄÄùú úùÄÄÄÄÂÙ + ÚÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅ¿ + ³³ SUPPLiER......:n/a ÆÅ REQUiRED CPU.......:P90 ³³ + À³Ä CRACKER.......:LTD. ³³ REQUiRED RAM.......:16MB ij٠+ Ú³ÄÄ STRiPPER......:n/a ³³ REQUiRED HD SPACE..:- Äij¿ + ³³ PACKAGER......:LTD ŵ REQUiRED OS........:WIN95 ³³ + ³ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ³ + À³¿ RELEASE.DATE..:11/30/97 ÆÅ DiRECTX............: 5.0 Ú³Ù + ³ú PROTECTiON....:n/a ³³ SVGA...............: YES ú³ + ³ú RELEASE.SiZE..:2kb ³³ SOUNDBLASTER.......: YES ú³ + Ú³Ù GAME TYPE.....:RPG ŵ GENERAL-MiDi.......: NOPE À³¿ + ³ÀÄÄÍÍÍÑÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ;ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÑÍÍÍÄÄÙ³ + ÀÂÄùú ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ úùÄÂÙ + ÀÄÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÄÙ + + + ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿ + ÚÁÄùú úùÄÁ¿ + ³³ þ RELEASE NOTES: þ ³³ + ÀÂÄÄÄùú As we all was and are big fans of this fantastic ³ + ³ RPG we missed the Multiplayer Options which made ³ + ³ Diablo one of the best games in `97. ³ + ³ And when i saw that Multiplayer Routines are included ³ + ³ in the Release of Hellfire i looked through the code ³ + ³ and found the routine. ³ + ³ Seems that just some Beta testers was allowed to play ³ + ³ Hellfire in Multiplayer Mode. ³ + ³ I take no responsibility for any damage to your character ³ + ³ crashed or whatever while using this patch. ³ + ³ Battle.Net isnt supported, guess why! :p ³ + ³ úùÄÄÄÂÙ + ³ ³ + ³ ³ + ³ ³ + ÚÁÄùú úùÄÁ¿ + ³³ þ iNSTALL NOTES: þ ³³ + ÀÂÄùú úùÄÂÙ + ³ Run the patch from your Hellfire Directory! ³ + ³ Thats all! ³ + ³ ³ + ³ ³ + ³ ³ + ³ ³ + ÚÁÄÄÄùú úùÄÄÄÁ¿ + ³³ þ þ ³³ + ÀÂÄùú úùÄÂÙ + ³ ³ + ³ ³ + ÀÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÙ + + + ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿ + ÚÁÄùú úùÄÁ¿ + ³³ þ GROUP GREETiNGS þ ³³ + ÀÂÄÄÄùú úùÄÄÄÂÙ + Ú³Ù À³¿ + þ³ CAMPAiGN - CLASS - PARADOX - RAZOR - SAC - SCANDAL - TRSi ³þ + À³¿ Ú³Ù + ÚÁÄÄÄùú úùÄÄÄÁ¿ + ³³ þ WE ARE BACK iN FULL ARMOR, SO TAKE CARE BOYS!! þ ³³ + ÀÂÄùú úùÄÂÙ + ÀÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÙ + + + ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿ + ÚÁÄùú úùÄÁ¿ + ³³ þ þ ³³ + ÀÂÄÄÄùú Ú¿ Ú¿ úùÄÄÄÂÙ + Ú³ÄÄÄÄÄÄÁ³¿ LTD..ASMADi Ú³ÁÄÄÄÄÄij¿ + À³¿ Ú³Ù À³¿ Ú³Ù + ³³ ³³ APOLLO..CAULDRON..COCKROACH..CONTROL..CYRAXX..FiBRE ³³ ³³ + ³³ ³³ FLi7E..iNFiNiTY..JAYDEE..KHADGAR..LGB..MAYHEM ³³ ³³ + ³³ ³³ OVERHEAD..OLiVER STONED..PALLADiN..QUAD..SEKTOiD ³³ ³³ + ³³ ³³ SiLVER..STUPiT..TANKARD..YODLER..ZoLDAN..ZZ187 ³³ ³³ + Ú³Ù À³¿ Ú³Ù À³¿ + ÀÅ¿ ÚÅÙ ÀÅ¿ ÚÅÙ + À³ÄÄÄÄij٠À³ÄÄÄÄij٠+ ÚÙ ³ BLH-HELPLiNE@USA.NET ³ À¿ + ³³ þ ÚÙ À¿ þ ³³ + ÀÂÄùú ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ úùÄÂÙ + ÀÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÙ + + + ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿ + ÚÁÄùú úùÄÁ¿ + ³³ þ DiSTRiBUTiON SYSTEMS þ ³³ + ÀÂÄÂÄÄÄùú úùÄÄÄÂÄÂÙ + ³ÚÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅ¿³ + Ú³Ù³ T.. N........... ĵ 4 NODES Å BBS GERMAN HQ ÆÄ 10 GiGZ ³À³¿ + óÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅij´ + ³³ ³ F....... O. S....... ĵ 34 MBiT Å FTP WORLD HQ ÆÄ 13 GiGZ ³ ³³ + óÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅij´ + ³³ ³ T.. R..... M..... ĵ 100 MBiT Å FTP EURO HQ ÆÄ 26 GiGZ ³ ³³ + óÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅij´ + ³³ ³ C...... ĵ 10 MBiT Å FTP GERMAN HQ ÆÄ 19 GiGZ ³ ³³ + óÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅij´ + À³¿³ T.. W..... H.... ĵ 34 MBiT Å FTP DUTCH HQ ÆÄ 7 GiGZ ³Ú³Ù + ÃÙÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙÀ´ + ÚÁÄÄÄÄÄùú úùÄÄÄÄÄÁ¿ + ³³ þ þ ³³ + ÀÂÄùú úùÄÂÙ + ÀÄÄÄÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÄÄÄÙ + + + ÚÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄ¿ + ÚÁÄùú úùÄÁ¿ + ³³ þ A SOFTWARE WORTH CODiNG í iS A SOFTWARE WORTH USiNG þ ³³ + ÀÂÄÄÄùú úùÄÄÄÂÙ + ÀÅÄÄÄÄÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÄÄÄÄÅÙ + ÀÄÄÄÄÄÂÄÄÄÄÄ[ NFO HEADER BY ROY - NFO DESiGN BY YOdLER ]ÄÄÄÄÄÂÄÄÄÄÄÙ + ÀÄÄÄÄÄÄÄÄÄÄÄÄ[ LAST UPDATE: 11-18-97 BY MAYHEM ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + - - -- ---> FEEL THE BACKLASH <--- -- - - diff --git a/src/Windebug/CLOCK001.LOG b/src/Windebug/CLOCK001.LOG new file mode 100644 index 0000000..d86fe57 --- /dev/null +++ b/src/Windebug/CLOCK001.LOG @@ -0,0 +1,7403 @@ +Time Based Sampler Version 3.0 + (11/14/1996--18:57:29) + +CPU Family Pentium +Sample rate 1.000 ms +Sample time 200.00 seconds +Total samples 192107 +Recorded samples 192107 +Sample Timer VTD +EIP Granularity 1 +User Comment Testing hellfire.exe + + + + 32 Bit 16 Bit V86 + + Total Samples (%) Samples Iopl=0 Iopl=1 Iopl=2 Iopl=3 (%) Samples Iopl=0 Iopl=1 Iopl=2 Iopl=3 (%) Samples Iopl=0 Iopl=3 (%) + +Ring 0 146962 76.50 146962 10747 0 0 136215 76.50 0 0 0 0 0 0.00 0 0 0 0.00 +Ring 1 0 0.00 0 0 0 0 0 0.00 0 0 0 0 0 0.00 0 0 0 0.00 +Ring 2 0 0.00 0 0 0 0 0 0.00 0 0 0 0 0 0.00 0 0 0 0.00 +Ring 3 10537 5.48 3675 3675 0 0 0 1.91 6862 6862 0 0 0 3.57 0 0 0 0.00 +V8086 Mode 34608 18.01 0 0 0 0 0 0.00 0 0 0 0 0 0.00 34608 0 34608 18.01 + + + + + + + + + + + + +Code Seg Mode Ring DPL Base Limit Samples (%) + + 28H 32 Bit 0 0 0H fffff000H 146962 76.50 + 3bH 16 Bit 3 3 c3403800H 7ffH 25 0.01 + 93H 32 Bit 3 3 c00293f1H ffH 75 0.04 + 117H 16 Bit 3 3 c560H b3ffH 1883 0.98 + 11fH 16 Bit 3 3 90300H 7e7fH 529 0.28 + 127H 16 Bit 3 3 803037c0H 423fH 113 0.06 + 137H 32 Bit 3 3 0H fffff000H 3343 1.74 + 16fH 16 Bit 3 3 98d00H 3fH 15 0.01 + 1dfH 16 Bit 3 3 801c4000H 33fH 53 0.03 + 237H 16 Bit 3 3 801c5000H 111fH 1 0.00 + 30fH 16 Bit 3 3 801c9000H 8fffH 104 0.05 + 317H 16 Bit 3 3 801d2000H 4fffH 27 0.01 + 367H 16 Bit 3 3 801d7000H 2fffH 2 0.00 + 397H 16 Bit 3 3 801dd000H 2fffH 223 0.12 + 447H 16 Bit 3 3 801e0000H ebfH 827 0.43 + 457H 16 Bit 3 3 801e1000H 453fH 74 0.04 + 45fH 16 Bit 3 3 801e6000H 14ffH 22 0.01 + 467H 32 Bit 3 3 801e8000H dc3fH 206 0.11 + 46fH 32 Bit 3 3 801f6000H 2cbfH 14 0.01 + 4b7H 16 Bit 3 3 8019bc20H 9ffH 4 0.00 + 4f7H 32 Bit 3 3 801fe5c0H 313fH 30 0.02 + 527H 16 Bit 3 3 80204000H ac7fH 583 0.30 + 52fH 16 Bit 3 3 8ba20H 1b9fH 195 0.10 + 537H 16 Bit 3 3 89380H 269fH 27 0.01 + 53fH 16 Bit 3 3 871a0H 21dfH 9 0.00 + 547H 16 Bit 3 3 82d80H 441fH 48 0.02 + 54fH 16 Bit 3 3 82060H d1fH 7 0.00 + 557H 16 Bit 3 3 817a0H 8bfH 2 0.00 + 567H 16 Bit 3 3 7ca40H 161fH 8 0.00 + 56fH 16 Bit 3 3 7bfa0H a9fH 2 0.00 + 5dfH 16 Bit 3 3 801942c0H 4bfH 3 0.00 + 647H 16 Bit 3 3 28460H 1edfH 21 0.01 + 64fH 32 Bit 3 3 802ff9a0H 13ffH 7 0.00 + 65fH 16 Bit 3 3 8019b3c0H 85fH 4 0.00 + 66fH 16 Bit 3 3 74780H 243fH 7 0.00 + 140fH 16 Bit 3 3 80229340H 113fH 14 0.01 + 169fH 16 Bit 3 3 80228000H 133fH 62 0.03 + 16a7H 16 Bit 3 3 80227000H 5dfH 1 0.00 + 16afH 16 Bit 3 3 80222000H 475fH 251 0.13 + 16b7H 16 Bit 3 3 2a340H c5fH 2 0.00 + 16e7H 16 Bit 3 3 2e600H 7f5fH 17 0.01 + 16ffH 16 Bit 3 3 38f40H 281fH 7 0.00 + 170fH 16 Bit 3 3 3e100H 35bfH 2 0.00 + 1727H 16 Bit 3 3 47000H 58bfH 22 0.01 + 1737H 16 Bit 3 3 52300H 213fH 3 0.00 + 1747H 16 Bit 3 3 58f20H 2cffH 162 0.08 + 174fH 16 Bit 3 3 5bc20H 573fH 56 0.03 + 1757H 16 Bit 3 3 61360H 821fH 1 0.00 + 175fH 16 Bit 3 3 69580H 74ffH 164 0.09 + 1767H 16 Bit 3 3 70a80H 261fH 12 0.01 + 176fH 16 Bit 3 3 8021c000H 585fH 145 0.08 + 1777H 16 Bit 3 3 80213000H 84bfH 579 0.30 + 1787H 16 Bit 3 3 8020f000H 12ffH 99 0.05 + 1a67H 16 Bit 3 3 802339a0H 3a3fH 31 0.02 + 1a97H 16 Bit 3 3 801b6340H 4bfH 4 0.00 + 1a9fH 16 Bit 3 3 801b6800H 441fH 162 0.08 + 1aa7H 16 Bit 3 3 801bac20H 8bfH 1 0.00 + 1aafH 16 Bit 3 3 1f300H 4bffH 29 0.02 + 1b7fH 16 Bit 3 3 80268920H bbfH 2 0.00 + 1c9fH 16 Bit 3 3 801c06e0H 125fH 1 0.00 + 1e57H 16 Bit 3 3 80195900H 10ffH 51 0.03 + 1e7fH 16 Bit 3 3 802b3e00H 23bfH 15 0.01 + 1e87H 16 Bit 3 3 802b61c0H 425fH 121 0.06 + 1e97H 16 Bit 3 3 801e58c0H 59fH 26 0.01 + 1f2fH 16 Bit 3 3 80230000H 1cffH 1 0.00 + 28d7H 16 Bit 3 3 18f00H 13fH 1 0.00 + + 70H V8086 3 0 0H 0H 414 0.22 + 224H V8086 3 0 0H 0H 14292 7.44 + fcb2H V8086 3 0 0H 0H 1870 0.97 + ff03H V8086 3 0 0H 0H 13835 7.20 + ffffH V8086 3 0 0H 0H 4197 2.18 + + + + +Module Name Samples (%) 32Bit 16Bit V8086 + +VMM 115802 60.28 115802 0 0 +SICE 7 0.00 7 0 0 +IOS 86 0.04 86 0 0 +NWLINK 925 0.48 925 0 0 +CONFIGMG 7 0.00 7 0 0 +VSHARE 162 0.08 162 0 0 +VWIN32 158 0.08 158 0 0 +VCOMM 2 0.00 2 0 0 +IFSMGR 6220 3.24 6220 0 0 +VFAT 431 0.22 431 0 0 +VCACHE 33 0.02 33 0 0 +VCDFSD 1559 0.81 1559 0 0 +VXDLDR 1 0.00 1 0 0 +VPICD 13 0.01 13 0 0 +VTD 51 0.03 51 0 0 +VDMAD 1 0.00 1 0 0 +V86MMGR 12 0.01 12 0 0 +DOSMGR 396 0.21 396 0 0 +VMPOLL 2105 1.10 2105 0 0 +SHELL 1340 0.70 1340 0 0 +VMCPD 18 0.01 18 0 0 +VTDAPI 3 0.00 3 0 0 +NDIS 9 0.00 9 0 0 +VSHINIT 456 0.24 456 0 0 +VTBS 31 0.02 31 0 0 +WDEBUG 1583 0.82 1583 0 0 +VDD 2243 1.17 2243 0 0 +VMOUSE 8 0.00 8 0 0 +MSMINI 3 0.00 3 0 0 +MSDelta 1 0.00 1 0 0 +ENABLE 2 0.00 2 0 0 +KERNEL 2525 1.31 0 2525 0 +SB16SND 196 0.10 0 196 0 +MSACMMAP 1 0.00 0 1 0 +KEYBOARD 1 0.00 0 1 0 +MMSYSTEM 213 0.11 0 213 0 +GDI 923 0.48 7 916 0 +USER 1585 0.83 0 1585 0 +DIBENG 1148 0.60 221 927 0 +SYSTEM 53 0.03 0 53 0 +DISPLAY 131 0.07 0 131 0 +DMBRDOBJ 2 0.00 0 2 0 +DMDRWOBJ 223 0.12 0 223 0 +MSGSRV32 1 0.00 0 1 0 +CSPMAN 31 0.02 0 31 0 +COMMCTRL 1 0.00 0 1 0 +vs3xxx 1 0.00 1 0 0 +SB16 2 0.00 2 0 0 +DSVXD 1 0.00 1 0 0 +CDFS 1806 0.94 1806 0 0 +CDTSD 1 0.00 1 0 0 +CDVSD 7 0.00 7 0 0 +DiskVSD 4 0.00 4 0 0 +voltrack 7 0.00 7 0 0 +scsi1hlp 4 0.00 4 0 0 +EL90X 8 0.00 8 0 0 +NETBEUI 3 0.00 3 0 0 +MITSVSD 2 0.00 2 0 0 +VTDI 1 0.00 1 0 0 +VIP 6 0.00 6 0 0 +MSTCP 2 0.00 2 0 0 +VNBT 1 0.00 1 0 0 +VSERVER 797 0.41 797 0 0 +SCSIPORT 595 0.31 595 0 0 +ideatapi 35 0.02 35 0 0 +kernel32 1737 0.90 1737 0 0 +GDI32 118 0.06 118 0 0 +ADVAPI32 2 0.00 2 0 0 +USER32 275 0.14 275 0 0 +AFVXD 4 0.00 4 0 0 +COMCTL32 36 0.02 36 0 0 +VSHWIN32 16 0.01 16 0 0 +VTUNE 4 0.00 4 0 0 +MCKRNL 1 0.00 1 0 0 +MCUTIL 173 0.09 173 0 0 +VSHIELD 273 0.14 273 0 0 +WINMM 69 0.04 69 0 0 +EXPLORER 66 0.03 66 0 0 +SHELL32 7 0.00 7 0 0 +MSO97 1 0.00 1 0 0 +HPCOLA 5 0.00 5 0 0 +MFC40 5 0.00 5 0 0 +MSVCRT40 1 0.00 1 0 0 +SNDVOL32 100 0.05 100 0 0 +VB40032 255 0.13 255 0 0 +WSOCK32 1 0.00 1 0 0 +MSVCRT20 7 0.00 7 0 0 +HPSNMP 20 0.01 20 0 0 +HPPELK 1 0.00 1 0 0 +OLE32 20 0.01 20 0 0 +RPCRT4 1 0.00 1 0 0 +OLEAUT32 141 0.07 141 0 0 +DAO3032 1 0.00 1 0 0 +COMDLG32 2 0.00 2 0 0 +THREED32 32 0.02 32 0 0 +MFC40 163 0.08 163 0 0 +MSVCRT40 23 0.01 23 0 0 +TABCTL32 2 0.00 2 0 0 +SPIN32 2 0.00 2 0 0 +GRID32 1 0.00 1 0 0 +HELLFIRE 1 0.00 1 0 0 +STORMD 6 0.00 6 0 0 +MSVCRTD 13 0.01 13 0 0 +DDRAW 2 0.00 2 0 0 +DDHELP 1 0.00 1 0 0 +DDRAW16 2 0.00 0 2 0 +URL 1 0.00 1 0 0 +SHELL32 1 0.00 1 0 0 +DSOUND 4 0.00 4 0 0 +AUTORUN 129 0.07 129 0 0 +SHELL32 1 0.00 1 0 0 +OLE32 1 0.00 1 0 0 +MSVCRT20 1 0.00 1 0 0 +HIMEM 14292 7.44 0 0 14292 + +Other32B 9733 5.07 +Other16B 54 0.03 +OtherV86 20316 10.58 + + + + + + + + + + + + +Module Name VMM + + CS:EIP Samples (%) Map Offset Symbol + 28:c0001027 1 0.00 1:27 + 28:c0001300 210 0.11 1:300 + 28:c000130b 30 0.02 1:30b + 28:c0001311 76 0.04 1:311 + 28:c0001a05 12735 6.63 1:a05 + 28:c0001a0a 2 0.00 1:a0a + 28:c0001a0d 47 0.02 1:a0d + 28:c0001a0f 2 0.00 1:a0f + 28:c0001a16 21 0.01 1:a16 + 28:c0001a1c 3 0.00 1:a1c + 28:c0001a23 1711 0.89 1:a23 + 28:c0001b46 4177 2.17 1:b46 + 28:c0001b49 597 0.31 1:b49 + 28:c0001b4f 8 0.00 1:b4f + 28:c0001b56 175 0.09 1:b56 + 28:c0001dc4 19 0.01 1:dc4 + 28:c0001dcd 1 0.00 1:dcd + 28:c0001dd2 1 0.00 1:dd2 + 28:c0001dd4 3 0.00 1:dd4 + 28:c0001dd7 2 0.00 1:dd7 + 28:c0001ddd 2 0.00 1:ddd + 28:c0001df8 1 0.00 1:df8 + 28:c0001dfc 1 0.00 1:dfc + 28:c0001e04 1 0.00 1:e04 + 28:c0001e0d 2 0.00 1:e0d + 28:c0001e24 1 0.00 1:e24 + 28:c0001e26 1 0.00 1:e26 + 28:c0001e28 1 0.00 1:e28 + 28:c00020b9 5 0.00 1:10b9 + 28:c00020d6 2 0.00 1:10d6 + 28:c00020f4 1 0.00 1:10f4 + 28:c0002248 1 0.00 1:1248 + 28:c000231c 2 0.00 1:131c + 28:c000232c 1 0.00 1:132c + 28:c0002493 1 0.00 1:1493 + 28:c0002533 161 0.08 1:1533 + 28:c000253c 46 0.02 1:153c + 28:c0002544 11 0.01 1:1544 + 28:c0002549 83 0.04 1:1549 + 28:c000254e 1999 1.04 1:154e + 28:c0002552 76 0.04 1:1552 + 28:c0002556 33 0.02 1:1556 + 28:c000255d 52 0.03 1:155d + 28:c0002565 40 0.02 1:1565 + 28:c0002569 676 0.35 1:1569 + 28:c0002570 395 0.21 1:1570 + 28:c0002575 186 0.10 1:1575 + 28:c0002578 154 0.08 1:1578 + 28:c000257c 43 0.02 1:157c + 28:c0002582 298 0.16 1:1582 + 28:c00025df 1 0.00 1:15df + 28:c00025e1 1 0.00 1:15e1 + 28:c00025f5 2 0.00 1:15f5 + 28:c00025fb 1 0.00 1:15fb + 28:c000262e 1 0.00 1:162e + 28:c0002654 2 0.00 1:1654 + 28:c000265e 3 0.00 1:165e + 28:c0002664 1 0.00 1:1664 + 28:c0002778 229 0.12 1:1778 + 28:c0002779 89 0.05 1:1779 + 28:c000277f 47 0.02 1:177f + 28:c0002787 133 0.07 1:1787 + 28:c000278a 88 0.05 1:178a + 28:c0002795 102 0.05 1:1795 + 28:c0002796 78 0.04 1:1796 + 28:c00027dc 6 0.00 1:17dc + 28:c00027de 1 0.00 1:17de + 28:c00027e2 3 0.00 1:17e2 + 28:c00027f4 1 0.00 1:17f4 + 28:c000280d 4 0.00 1:180d + 28:c0002812 1 0.00 1:1812 + 28:c0002829 7 0.00 1:1829 + 28:c0002832 1 0.00 1:1832 + 28:c0002845 2 0.00 1:1845 + 28:c0002858 10 0.01 1:1858 + 28:c0002870 1 0.00 1:1870 + 28:c0002885 1 0.00 1:1885 + 28:c00028b1 1 0.00 1:18b1 + 28:c00028f6 4 0.00 1:18f6 + 28:c00028fd 2 0.00 1:18fd + 28:c000290c 1 0.00 1:190c + 28:c000290e 1 0.00 1:190e + 28:c0002910 1 0.00 1:1910 + 28:c000293e 2 0.00 1:193e + 28:c0002944 4 0.00 1:1944 + 28:c0002951 1 0.00 1:1951 + 28:c0002981 1 0.00 1:1981 + 28:c0002a04 1 0.00 1:1a04 + 28:c0002a18 1 0.00 1:1a18 + 28:c0002afa 1 0.00 1:1afa + 28:c0002c1e 1 0.00 1:1c1e + 28:c0002c48 13 0.01 1:1c48 + 28:c0002c89 14 0.01 1:1c89 + 28:c0002d2c 2095 1.09 1:1d2c + 28:c0002d2e 47 0.02 1:1d2e + 28:c0002d2f 48 0.02 1:1d2f + 28:c0002d83 1683 0.88 1:1d83 + 28:c0002e4c 1 0.00 1:1e4c + 28:c000308b 17 0.01 1:208b + 28:c0003302 3 0.00 1:2302 + 28:c000332d 9 0.00 1:232d + 28:c000335c 1 0.00 1:235c + 28:c0003367 324 0.17 1:2367 + 28:c000336a 50 0.03 1:236a + 28:c0003380 396 0.21 1:2380 + 28:c0003383 2 0.00 1:2383 + 28:c0003408 428 0.22 1:2408 + 28:c000340b 84 0.04 1:240b + 28:c000340c 3 0.00 1:240c + 28:c0003412 56 0.03 1:2412 + 28:c0003413 63 0.03 1:2413 + 28:c0003414 8 0.00 1:2414 + 28:c0003448 432 0.22 1:2448 + 28:c0003449 87 0.05 1:2449 + 28:c000344e 85 0.04 1:244e + 28:c000345c 1 0.00 1:245c + 28:c0003461 77 0.04 1:2461 + 28:c0003469 3 0.00 1:2469 + 28:c000346b 76 0.04 1:246b + 28:c0003478 560 0.29 1:2478 + 28:c0003479 77 0.04 1:2479 + 28:c000347f 81 0.04 1:247f + 28:c0003485 13 0.01 1:2485 + 28:c0003487 109 0.06 1:2487 + 28:c000348a 45 0.02 1:248a + 28:c00034ad 406 0.21 1:24ad + 28:c00034b3 2 0.00 1:24b3 + 28:c00034b6 3 0.00 1:24b6 + 28:c00034be 25 0.01 1:24be + 28:c00034c4 41 0.02 1:24c4 + 28:c00034cb 113 0.06 1:24cb + 28:c00034ce 35 0.02 1:24ce + 28:c00034cf 81 0.04 1:24cf + 28:c00034ee 1617 0.84 1:24ee + 28:c00034ef 18 0.01 1:24ef + 28:c00034f3 101 0.05 1:24f3 + 28:c00034f6 51 0.03 1:24f6 + 28:c00034f9 9 0.00 1:24f9 + 28:c00034fd 284 0.15 1:24fd + 28:c00034ff 44 0.02 1:24ff + 28:c0003504 63 0.03 1:2504 + 28:c0003507 154 0.08 1:2507 + 28:c000350a 1940 1.01 1:250a + 28:c000350d 281 0.15 1:250d + 28:c0003510 82 0.04 1:2510 + 28:c0003514 569 0.30 1:2514 + 28:c0003518 324 0.17 1:2518 + 28:c000351c 246 0.13 1:251c + 28:c000351f 59 0.03 1:251f + 28:c0003523 346 0.18 1:2523 + 28:c0003526 14 0.01 1:2526 + 28:c0003527 200 0.10 1:2527 + 28:c0003528 337 0.18 1:2528 + 28:c000352e 667 0.35 1:252e + 28:c0003530 92 0.05 1:2530 + 28:c0003531 175 0.09 1:2531 + 28:c0003537 19 0.01 1:2537 + 28:c0003539 16 0.01 1:2539 + 28:c000353c 77 0.04 1:253c + 28:c000353e 83 0.04 1:253e + 28:c0003540 35 0.02 1:2540 + 28:c0003546 227 0.12 1:2546 + 28:c0003549 22 0.01 1:2549 + 28:c000354f 34 0.02 1:254f + 28:c0003556 1568 0.82 1:2556 + 28:c0003560 23 0.01 1:2560 + 28:c000356a 76 0.04 1:256a + 28:c0003571 89 0.05 1:2571 + 28:c0003575 41 0.02 1:2575 + 28:c0003578 15 0.01 1:2578 + 28:c000357c 21 0.01 1:257c + 28:c0003584 270 0.14 1:2584 + 28:c000358e 21 0.01 1:258e + 28:c0003590 12 0.01 1:2590 + 28:c0003595 5 0.00 1:2595 + 28:c0003597 6020 3.13 1:2597 + 28:c000359a 32 0.02 1:259a + 28:c00035a5 7 0.00 1:25a5 + 28:c00035a9 45 0.02 1:25a9 + 28:c00035ab 37 0.02 1:25ab + 28:c00035ae 15 0.01 1:25ae + 28:c00035b2 7 0.00 1:25b2 + 28:c00035b4 72 0.04 1:25b4 + 28:c00035b9 166 0.09 1:25b9 + 28:c00035ba 70 0.04 1:25ba + 28:c00035c0 83 0.04 1:25c0 + 28:c00035c3 318 0.17 1:25c3 + 28:c00035c5 1546 0.80 1:25c5 + 28:c00035c8 1 0.00 1:25c8 + 28:c00035ca 296 0.15 1:25ca + 28:c00035cd 58 0.03 1:25cd + 28:c00035ce 106 0.06 1:25ce + 28:c00035d1 75 0.04 1:25d1 + 28:c00035d4 7 0.00 1:25d4 + 28:c00035d5 177 0.09 1:25d5 + 28:c00035d7 84 0.04 1:25d7 + 28:c00035d9 82 0.04 1:25d9 + 28:c00035da 1418 0.74 1:25da + 28:c00035f9 57 0.03 1:25f9 + 28:c00035fa 31 0.02 1:25fa + 28:c0003600 2 0.00 1:2600 + 28:c0003601 82 0.04 1:2601 + 28:c000360c 110 0.06 1:260c + 28:c000360d 164 0.09 1:260d + 28:c0003612 34 0.02 1:2612 + 28:c0003613 121 0.06 1:2613 + 28:c0003673 7371 3.84 1:2673 + 28:c0003679 1558 0.81 1:2679 + 28:c000367e 9 0.00 1:267e + 28:c0003686 96 0.05 1:2686 + 28:c000368b 19 0.01 1:268b + 28:c000368d 38 0.02 1:268d + 28:c0003690 89 0.05 1:2690 + 28:c0003692 72 0.04 1:2692 + 28:c0003698 68 0.04 1:2698 + 28:c000369a 7 0.00 1:269a + 28:c00036a0 43 0.02 1:26a0 + 28:c00036a8 39 0.02 1:26a8 + 28:c00036aa 1 0.00 1:26aa + 28:c00036bd 103 0.05 1:26bd + 28:c00036be 162 0.08 1:26be + 28:c00036c0 40 0.02 1:26c0 + 28:c00036c1 83 0.04 1:26c1 + 28:c00036c7 38 0.02 1:26c7 + 28:c00036cb 114 0.06 1:26cb + 28:c00036cd 16 0.01 1:26cd + 28:c00036d3 21 0.01 1:26d3 + 28:c00036d7 51 0.03 1:26d7 + 28:c00036da 17 0.01 1:26da + 28:c00036dd 39 0.02 1:26dd + 28:c00036e4 205 0.11 1:26e4 + 28:c00036e5 23 0.01 1:26e5 + 28:c00036e8 49 0.03 1:26e8 + 28:c00036eb 20 0.01 1:26eb + 28:c00036f0 355 0.18 1:26f0 + 28:c00036f2 116 0.06 1:26f2 + 28:c00036f8 1 0.00 1:26f8 + 28:c00036fd 265 0.14 1:26fd + 28:c00036ff 105 0.05 1:26ff + 28:c0003700 18 0.01 1:2700 + 28:c0003705 33 0.02 1:2705 + 28:c000370a 4 0.00 1:270a + 28:c000370d 9 0.00 1:270d + 28:c0003714 60 0.03 1:2714 + 28:c0003715 93 0.05 1:2715 + 28:c0003718 634 0.33 1:2718 + 28:c0003719 82 0.04 1:2719 + 28:c000371f 42 0.02 1:271f + 28:c0003723 102 0.05 1:2723 + 28:c0003725 41 0.02 1:2725 + 28:c000372f 72 0.04 1:272f + 28:c0003735 30 0.02 1:2735 + 28:c0003739 775 0.40 1:2739 + 28:c000373a 27 0.01 1:273a + 28:c000373d 36 0.02 1:273d + 28:c0003745 1947 1.01 1:2745 + 28:c0003747 146 0.08 1:2747 + 28:c0003752 718 0.37 1:2752 + 28:c0003754 84 0.04 1:2754 + 28:c0003755 26 0.01 1:2755 + 28:c000375a 45 0.02 1:275a + 28:c0003764 37 0.02 1:2764 + 28:c0003765 89 0.05 1:2765 + 28:c0003770 83 0.04 1:2770 + 28:c0003777 2 0.00 1:2777 + 28:c000377d 4 0.00 1:277d + 28:c0003781 972 0.51 1:2781 + 28:c0003783 181 0.09 1:2783 + 28:c0003787 1 0.00 1:2787 + 28:c000378b 82 0.04 1:278b + 28:c0003790 68 0.04 1:2790 + 28:c0003791 81 0.04 1:2791 + 28:c0003797 27 0.01 1:2797 + 28:c000379a 33 0.02 1:279a + 28:c00037a0 39 0.02 1:27a0 + 28:c00037bb 32 0.02 1:27bb + 28:c00037be 16 0.01 1:27be + 28:c00037cb 47 0.02 1:27cb + 28:c00037cc 538 0.28 1:27cc + 28:c00037ce 103 0.05 1:27ce + 28:c00037d5 42 0.02 1:27d5 + 28:c00037d8 70 0.04 1:27d8 + 28:c00037db 12 0.01 1:27db + 28:c00037f1 42 0.02 1:27f1 + 28:c00037f2 68 0.04 1:27f2 + 28:c00037f3 85 0.04 1:27f3 + 28:c00037f5 4 0.00 1:27f5 + 28:c00037fb 2 0.00 1:27fb + 28:c0003801 78 0.04 1:2801 + 28:c0003805 5 0.00 1:2805 + 28:c0003807 6 0.00 1:2807 + 28:c0003809 24 0.01 1:2809 + 28:c000380c 62 0.03 1:280c + 28:c000380f 1 0.00 1:280f + 28:c0003812 6 0.00 1:2812 + 28:c0003816 82 0.04 1:2816 + 28:c000381a 29 0.02 1:281a + 28:c000381e 65 0.03 1:281e + 28:c0003821 27 0.01 1:2821 + 28:c0003823 3 0.00 1:2823 + 28:c0003826 65 0.03 1:2826 + 28:c0003828 30 0.02 1:2828 + 28:c000382c 63 0.03 1:282c + 28:c0003830 917 0.48 1:2830 + 28:c0003834 173 0.09 1:2834 + 28:c0003839 85 0.04 1:2839 + 28:c000383c 256 0.13 1:283c + 28:c000383f 180 0.09 1:283f + 28:c0003843 93 0.05 1:2843 + 28:c0003849 40 0.02 1:2849 + 28:c000384a 58 0.03 1:284a + 28:c000384b 87 0.05 1:284b + 28:c000384d 11 0.01 1:284d + 28:c0003853 23 0.01 1:2853 + 28:c0003856 1 0.00 1:2856 + 28:c0003858 78 0.04 1:2858 + 28:c000385b 25 0.01 1:285b + 28:c0003860 61 0.03 1:2860 + 28:c0003864 26 0.01 1:2864 + 28:c0003868 38 0.02 1:2868 + 28:c000386c 42 0.02 1:286c + 28:c0003873 23 0.01 1:2873 + 28:c0003876 3 0.00 1:2876 + 28:c0003879 4 0.00 1:2879 + 28:c000387c 20 0.01 1:287c + 28:c0003880 46 0.02 1:2880 + 28:c0003885 10 0.01 1:2885 + 28:c0003887 14 0.01 1:2887 + 28:c00038a0 283 0.15 1:28a0 + 28:c00038a6 68 0.04 1:28a6 + 28:c00038a8 43 0.02 1:28a8 + 28:c00038ad 1 0.00 1:28ad + 28:c00038af 41 0.02 1:28af + 28:c00038b1 47 0.02 1:28b1 + 28:c00038b2 41 0.02 1:28b2 + 28:c00038dd 991 0.52 1:28dd + 28:c00038e0 42 0.02 1:28e0 + 28:c00038e3 57 0.03 1:28e3 + 28:c00038e6 24 0.01 1:28e6 + 28:c00038e9 69 0.04 1:28e9 + 28:c00038f1 113 0.06 1:28f1 + 28:c00038f2 62 0.03 1:28f2 + 28:c0003923 6972 3.63 1:2923 + 28:c0003925 7 0.00 1:2925 + 28:c0003927 42 0.02 1:2927 + 28:c000394c 229 0.12 1:294c + 28:c0003950 22 0.01 1:2950 + 28:c0003951 236 0.12 1:2951 + 28:c000396f 1161 0.60 1:296f + 28:c0003970 2 0.00 1:2970 + 28:c000397c 1 0.00 1:297c + 28:c00039f9 51 0.03 1:29f9 + 28:c0003a16 7 0.00 1:2a16 + 28:c0003a23 1 0.00 1:2a23 + 28:c0003a53 8 0.00 1:2a53 + 28:c0003a56 1 0.00 1:2a56 + 28:c0003ace 15 0.01 1:2ace + 28:c0003af6 1 0.00 1:2af6 + 28:c00044a4 315 0.16 1:34a4 + 28:c00044a8 12 0.01 1:34a8 + 28:c00044aa 99 0.05 1:34aa + 28:c00044ab 42 0.02 1:34ab + 28:c00044ac 19 0.01 1:34ac + 28:c00044b0 48 0.02 1:34b0 + 28:c00044b4 127 0.07 1:34b4 + 28:c00044b6 32 0.02 1:34b6 + 28:c00044b9 33 0.02 1:34b9 + 28:c00044c0 12 0.01 1:34c0 + 28:c0004611 3 0.00 1:3611 + 28:c000469c 1 0.00 1:369c + 28:c00046a5 7 0.00 1:36a5 + 28:c00046bd 2 0.00 1:36bd + 28:c00046ca 1 0.00 1:36ca + 28:c00046d9 1 0.00 1:36d9 + 28:c0004716 3 0.00 1:3716 + 28:c00047b4 5 0.00 1:37b4 + 28:c00047cb 1 0.00 1:37cb + 28:c0004856 7 0.00 1:3856 + 28:c000485b 3 0.00 1:385b + 28:c000485f 1 0.00 1:385f + 28:c000486d 4 0.00 1:386d + 28:c000486f 113 0.06 1:386f + 28:c0004871 2 0.00 1:3871 + 28:c0004874 1 0.00 1:3874 + 28:c0004879 1 0.00 1:3879 + 28:c000487e 66 0.03 1:387e + 28:c0004886 1 0.00 1:3886 + 28:c0004891 1 0.00 1:3891 + 28:c000489a 23 0.01 1:389a + 28:c00048b0 1 0.00 1:38b0 + 28:c00048dc 1 0.00 1:38dc + 28:c00048ec 1 0.00 1:38ec + 28:c000493a 1 0.00 1:393a + 28:c00049f8 1 0.00 1:39f8 + 28:c0004a66 2 0.00 1:3a66 + 28:c0004a71 1 0.00 1:3a71 + 28:c0004b1b 1 0.00 1:3b1b + 28:c0004b1e 1 0.00 1:3b1e + 28:c0004b24 1 0.00 1:3b24 + 28:c0004b32 1 0.00 1:3b32 + 28:c0004b3a 1 0.00 1:3b3a + 28:c0004c88 1 0.00 1:3c88 + 28:c0004c96 1 0.00 1:3c96 + 28:c0004cb4 2 0.00 1:3cb4 + 28:c0004cc6 1 0.00 1:3cc6 + 28:c0004cf9 2 0.00 1:3cf9 + 28:c00051f2 1 0.00 1:41f2 + 28:c0005260 1 0.00 1:4260 + 28:c0005398 1 0.00 1:4398 + 28:c0005442 1 0.00 1:4442 + 28:c000547b 1 0.00 1:447b + 28:c000558f 1 0.00 1:458f + 28:c00055ed 1 0.00 1:45ed + 28:c000562b 1 0.00 1:462b + 28:c00056f6 1 0.00 1:46f6 + 28:c0005702 1 0.00 1:4702 + 28:c000589d 1 0.00 1:489d + 28:c00058a1 2 0.00 1:48a1 + 28:c0005903 1 0.00 1:4903 + 28:c0005950 2 0.00 1:4950 + 28:c000599e 1 0.00 1:499e + 28:c00059ac 1 0.00 1:49ac + 28:c00059c4 2 0.00 1:49c4 + 28:c0005a20 1 0.00 1:4a20 + 28:c0005b87 1 0.00 1:4b87 + 28:c0005b9a 1 0.00 1:4b9a + 28:c0005bd2 1 0.00 1:4bd2 + 28:c0005c0a 2 0.00 1:4c0a + 28:c0005c1a 1 0.00 1:4c1a + 28:c0005d8f 2 0.00 1:4d8f + 28:c0005dc4 1 0.00 1:4dc4 + 28:c0005dd7 1 0.00 1:4dd7 + 28:c0005e96 1 0.00 1:4e96 + 28:c0005e98 1 0.00 1:4e98 + 28:c0005ed0 1 0.00 1:4ed0 + 28:c0006428 1 0.00 1:5428 + 28:c0006b63 1 0.00 1:5b63 + 28:c0006b67 1 0.00 1:5b67 + 28:c0006b8c 1 0.00 1:5b8c + 28:c0006e3e 1 0.00 1:5e3e + 28:c000777c 21 0.01 1:677c + 28:c0007781 1 0.00 1:6781 + 28:c0007782 1 0.00 1:6782 + 28:c0007786 5 0.00 1:6786 + 28:c0007789 3 0.00 1:6789 + 28:c000778e 1 0.00 1:678e + 28:c0007792 1 0.00 1:6792 + 28:c0007795 1 0.00 1:6795 + 28:c00077a0 1 0.00 1:67a0 + 28:c00077ee 1 0.00 1:67ee + 28:c00077f6 10 0.01 1:67f6 + 28:c00077fa 2 0.00 1:67fa + 28:c000781a 5 0.00 1:681a + 28:c0007820 1 0.00 1:6820 + 28:c0007827 1 0.00 1:6827 + 28:c000782b 1 0.00 1:682b + 28:c0007835 1 0.00 1:6835 + 28:c0007838 5 0.00 1:6838 + 28:c000783b 11 0.01 1:683b + 28:c0007844 1 0.00 1:6844 + 28:c0007dfc 611 0.32 1:6dfc + 28:c0007dfe 71 0.04 1:6dfe + 28:c0007e04 180 0.09 1:6e04 + 28:c0007e06 9 0.00 1:6e06 + 28:c0007e0a 66 0.03 1:6e0a + 28:c0007e13 156 0.08 1:6e13 + 28:c0007e16 124 0.06 1:6e16 + 28:c0007e18 63 0.03 1:6e18 + 28:c0007e1b 523 0.27 1:6e1b + 28:c0007e20 4 0.00 1:6e20 + 28:c0007e30 2 0.00 1:6e30 + 28:c0007e34 1 0.00 1:6e34 + 28:c0007e3d 1 0.00 1:6e3d + 28:c0007e40 2 0.00 1:6e40 + 28:c0007e4e 2 0.00 1:6e4e + 28:c0007e56 1 0.00 1:6e56 + 28:c0007e76 2 0.00 1:6e76 + 28:c0008109 1 0.00 1:7109 + 28:c00083b6 1 0.00 1:73b6 + 28:c00083ee 1 0.00 1:73ee + 28:c000860d 1 0.00 1:760d + 28:c000882e 1 0.00 1:782e + 28:c0008868 78 0.04 1:7868 + 28:c000886f 7 0.00 1:786f + 28:c000887d 88 0.05 1:787d + 28:c0008882 5 0.00 1:7882 + 28:c0008885 19 0.01 1:7885 + 28:c0008887 55 0.03 1:7887 + 28:c000888c 68 0.04 1:788c + 28:c0008894 45 0.02 1:7894 + 28:c000889a 236 0.12 1:789a + 28:c000889c 35 0.02 1:789c + 28:c00088a1 47 0.02 1:78a1 + 28:c00088a6 154 0.08 1:78a6 + 28:c00088ab 80 0.04 1:78ab + 28:c0008a14 9 0.00 1:7a14 + 28:c0008a18 5 0.00 1:7a18 + 28:c0008a1e 89 0.05 1:7a1e + 28:c0008a26 9 0.00 1:7a26 + 28:c0008a2a 7 0.00 1:7a2a + 28:c0008a2c 79 0.04 1:7a2c + 28:c0008a32 8 0.00 1:7a32 + 28:c0008a39 72 0.04 1:7a39 + 28:c0008a3c 5 0.00 1:7a3c + 28:c0008a3e 1 0.00 1:7a3e + 28:c0008a41 62 0.03 1:7a41 + 28:c0008a44 4 0.00 1:7a44 + 28:c0008a47 88 0.05 1:7a47 + 28:c0008a86 1 0.00 1:7a86 + 28:c0008ad4 31 0.02 1:7ad4 + 28:c0008ad8 3 0.00 1:7ad8 + 28:c0008ade 55 0.03 1:7ade + 28:c0008ae0 28 0.01 1:7ae0 + 28:c0008ae4 2 0.00 1:7ae4 + 28:c0008ae6 127 0.07 1:7ae6 + 28:c0008aeb 28 0.01 1:7aeb + 28:c0008aef 2 0.00 1:7aef + 28:c0008af2 1088 0.57 1:7af2 + 28:c0008af5 785 0.41 1:7af5 + 28:c0008af8 359 0.19 1:7af8 + 28:c0008afb 23 0.01 1:7afb + 28:c0008afd 69 0.04 1:7afd + 28:c0008b06 45 0.02 1:7b06 + 28:c0008b08 3 0.00 1:7b08 + 28:c0008b0a 55 0.03 1:7b0a + 28:c0008b0d 39 0.02 1:7b0d + 28:c0008b1d 2903 1.51 1:7b1d + 28:c0008b1e 3 0.00 1:7b1e + 28:c0008b21 1 0.00 1:7b21 + 28:c0008b23 1 0.00 1:7b23 + 28:c0008b28 4 0.00 1:7b28 + 28:c0008b78 6 0.00 1:7b78 + 28:c0008b7d 4 0.00 1:7b7d + 28:c0008b82 2 0.00 1:7b82 + 28:c0008b87 1 0.00 1:7b87 + 28:c0008bc8 3 0.00 1:7bc8 + 28:c0008bce 2 0.00 1:7bce + 28:c0008bed 16 0.01 1:7bed + 28:c0008bf0 2 0.00 1:7bf0 + 28:c0008bf6 2 0.00 1:7bf6 + 28:c0008c05 2 0.00 1:7c05 + 28:c0008c16 9 0.00 1:7c16 + 28:c0008d50 4 0.00 1:7d50 + 28:c0008d5d 2 0.00 1:7d5d + 28:c0008f54 5 0.00 1:7f54 + 28:c0008f58 1 0.00 1:7f58 + 28:c0008fc3 2511 1.31 1:7fc3 + 28:c00090d6 1 0.00 1:80d6 + 28:c00090ec 1 0.00 1:80ec + 28:c00090f0 1 0.00 1:80f0 + 28:c0009111 2 0.00 1:8111 + 28:c00092d7 2 0.00 1:82d7 + 28:c00093a8 598 0.31 1:83a8 + 28:c00098b8 1 0.00 1:88b8 + 28:c00098cc 1 0.00 1:88cc + 28:c00098fb 2 0.00 1:88fb + 28:c00099bb 12 0.01 1:89bb + 28:c00099c5 1 0.00 1:89c5 + 28:c00099d0 3 0.00 1:89d0 + 28:c00099d3 5 0.00 1:89d3 + 28:c00099d5 5 0.00 1:89d5 + 28:c00099d6 1 0.00 1:89d6 + 28:c00099df 3 0.00 1:89df + 28:c0009ae0 18 0.01 1:8ae0 + 28:c0009ae2 2 0.00 1:8ae2 + 28:c0009ae8 2 0.00 1:8ae8 + 28:c0009ff1 45 0.02 1:8ff1 + 28:c0009ff7 95 0.05 1:8ff7 + 28:c0009ffb 107 0.06 1:8ffb + 28:c0009ffd 30 0.02 1:8ffd + 28:c0009ffe 49 0.03 1:8ffe + 28:c000a004 4 0.00 1:9004 + 28:c000a006 33 0.02 1:9006 + 28:c000a007 10 0.01 1:9007 + 28:c000a009 28 0.01 1:9009 + 28:c000a00b 7 0.00 1:900b + 28:c000a00d 45 0.02 1:900d + 28:c000a014 53 0.03 1:9014 + 28:c000a017 75 0.04 1:9017 + 28:c000a018 48 0.02 1:9018 + 28:c000a01a 52 0.03 1:901a + 28:c000a020 6 0.00 1:9020 + 28:c000a022 59 0.03 1:9022 + 28:c000a023 58 0.03 1:9023 + 28:c000a025 53 0.03 1:9025 + 28:c000a027 6 0.00 1:9027 + 28:c000a029 82 0.04 1:9029 + 28:c000a02e 60 0.03 1:902e + 28:c000a030 44 0.02 1:9030 + 28:c000a038 867 0.45 1:9038 + 28:c000a03e 44 0.02 1:903e + 28:c000a059 44 0.02 1:9059 + 28:c000a060 147 0.08 1:9060 + 28:c000a062 103 0.05 1:9062 + 28:c000a063 74 0.04 1:9063 + 28:c000a069 450 0.23 1:9069 + 28:c000a06a 99 0.05 1:906a + 28:c000a06c 41 0.02 1:906c + 28:c000a07f 137 0.07 1:907f + 28:c000a082 31 0.02 1:9082 + 28:c000a086 24 0.01 1:9086 + 28:c000a089 47 0.02 1:9089 + 28:c000a08b 138 0.07 1:908b + 28:c000a090 1 0.00 1:9090 + 28:c000a099 2 0.00 1:9099 + 28:c000a09b 41 0.02 1:909b + 28:c000a09d 14 0.01 1:909d + 28:c000a0a2 2 0.00 1:90a2 + 28:c000a0a4 33 0.02 1:90a4 + 28:c000a0ad 52 0.03 1:90ad + 28:c000a0b2 88 0.05 1:90b2 + 28:c000a0b8 110 0.06 1:90b8 + 28:c000a0b9 79 0.04 1:90b9 + 28:c000a0ba 26 0.01 1:90ba + 28:c000a0bc 7 0.00 1:90bc + 28:c000a0bd 65 0.03 1:90bd + 28:c000a0bf 1 0.00 1:90bf + 28:c000a0c1 43 0.02 1:90c1 + 28:c000a0c9 3 0.00 1:90c9 + 28:c000a0d2 1 0.00 1:90d2 + 28:c000a0e7 1 0.00 1:90e7 + 28:c000a0fc 2 0.00 1:90fc + 28:c000a118 1 0.00 1:9118 + 28:c000a137 1 0.00 1:9137 + 28:c000a13d 1 0.00 1:913d + 28:c000a1b8 5 0.00 1:91b8 + 28:c000a3f7 10 0.01 1:93f7 + 28:c000a400 1 0.00 1:9400 + 28:c000a405 1 0.00 1:9405 + 28:c000a41e 6 0.00 1:941e + 28:c000a420 3 0.00 1:9420 + 28:c000a422 237 0.12 1:9422 + 28:c000a424 54 0.03 1:9424 + 28:c000a426 63 0.03 1:9426 + 28:c000a429 50 0.03 1:9429 + 28:c000a42b 2 0.00 1:942b + 28:c000a441 1 0.00 1:9441 + 28:c000a46d 38 0.02 1:946d + 28:c000a470 49 0.03 1:9470 + 28:c000a475 93 0.05 1:9475 + 28:c000a476 1 0.00 1:9476 + 28:c000a477 25 0.01 1:9477 + 28:c000a47a 1057 0.55 1:947a + 28:c000a47c 46 0.02 1:947c + 28:c000a47e 37 0.02 1:947e + 28:c000a481 57 0.03 1:9481 + 28:c000a483 9 0.00 1:9483 + 28:c000a486 37 0.02 1:9486 + 28:c000a488 63 0.03 1:9488 + 28:c000a48a 12 0.01 1:948a + 28:c000a48f 32 0.02 1:948f + 28:c000a492 46 0.02 1:9492 + 28:c000a495 50 0.03 1:9495 + 28:c000a497 78 0.04 1:9497 + 28:c000a499 37 0.02 1:9499 + 28:c000a793 268 0.14 1:9793 + 28:c000a795 55 0.03 1:9795 + 28:c000a7a1 37 0.02 1:97a1 + 28:c000a7aa 208 0.11 1:97aa + 28:c000a7ac 223 0.12 1:97ac + 28:c000a7ae 324 0.17 1:97ae + 28:c000a7af 325 0.17 1:97af + 28:c000a7b1 482 0.25 1:97b1 + 28:c000a7b2 361 0.19 1:97b2 + 28:c000a7b4 110 0.06 1:97b4 + 28:c000a7b7 135 0.07 1:97b7 + 28:c000a7b9 107 0.06 1:97b9 + 28:c000a7bb 37 0.02 1:97bb + 28:c000a805 1 0.00 1:9805 + 28:c000a90b 475 0.25 1:990b + 28:c000a90f 187 0.10 1:990f + 28:c000a912 49 0.03 1:9912 + 28:c000a91c 99 0.05 1:991c + 28:c000a922 161 0.08 1:9922 + 28:c000a928 68 0.04 1:9928 + 28:c000a92e 83 0.04 1:992e + 28:c000a933 48 0.02 1:9933 + 28:c000a939 464 0.24 1:9939 + 28:c000a93d 194 0.10 1:993d + 28:c000a940 36 0.02 1:9940 + 28:c000a94d 19 0.01 1:994d + 28:c000a954 35 0.02 1:9954 + 28:c000a956 14 0.01 1:9956 + 28:c000a95b 70 0.04 1:995b + 28:c000a95f 22 0.01 1:995f + 28:c000a961 11 0.01 1:9961 + 28:c000a963 4 0.00 1:9963 + 28:c000a96d 54 0.03 1:996d + 28:c000a973 2 0.00 1:9973 + 28:c000a97c 43 0.02 1:997c + 28:c000a97e 10 0.01 1:997e + 28:c000a980 29 0.02 1:9980 + 28:c000a986 68 0.04 1:9986 + 28:c000a98b 44 0.02 1:998b + 28:c000a98d 32 0.02 1:998d + 28:c000a993 954 0.50 1:9993 + 28:c000a9a1 60 0.03 1:99a1 + 28:c000a9a6 75 0.04 1:99a6 + 28:c000a9ac 49 0.03 1:99ac + 28:c000a9ae 85 0.04 1:99ae + 28:c0256164 1 0.00 6:164 + 28:c02561be 1 0.00 6:1be + 28:c02561cc 1 0.00 6:1cc + 28:c02561d8 1 0.00 6:1d8 + 28:c02561e7 1 0.00 6:1e7 + 28:c0256200 1 0.00 6:200 + 28:c0256207 1 0.00 6:207 + 28:c02562d8 2 0.00 6:2d8 + 28:c02562de 2 0.00 6:2de + 28:c02562f1 1 0.00 6:2f1 + 28:c0256df5 2 0.00 6:df5 + 28:c0256e0e 1 0.00 6:e0e + 28:c0256e32 1 0.00 6:e32 + 28:c0256e44 1 0.00 6:e44 + 28:c0256e4e 1 0.00 6:e4e + 28:c0256e64 1 0.00 6:e64 + 28:c0256e7f 1 0.00 6:e7f + 28:c0256e88 1 0.00 6:e88 + 28:c0256e8b 1 0.00 6:e8b + 28:c0256edc 2 0.00 6:edc + 28:c0256ee6 1 0.00 6:ee6 + 28:c0256eeb 1 0.00 6:eeb + 28:c0256efb 1 0.00 6:efb + 28:c0256eff 2 0.00 6:eff + 28:c0256f03 1 0.00 6:f03 + 28:c0256f05 4 0.00 6:f05 + 28:c0256f17 2 0.00 6:f17 + 28:c0256f1c 4 0.00 6:f1c + 28:c0256f33 1 0.00 6:f33 + 28:c0256f78 1 0.00 6:f78 + 28:c0256f88 1 0.00 6:f88 + 28:c0256f97 2 0.00 6:f97 + 28:c0256f9b 2 0.00 6:f9b + 28:c0256fdc 1 0.00 6:fdc + 28:c025701f 2 0.00 6:101f + 28:c0257023 1 0.00 6:1023 + 28:c0257030 2 0.00 6:1030 + 28:c0257034 1 0.00 6:1034 + 28:c0257038 1 0.00 6:1038 + 28:c025703f 1 0.00 6:103f + 28:c0257052 3 0.00 6:1052 + 28:c02570a6 1 0.00 6:10a6 + 28:c02570ba 1 0.00 6:10ba + 28:c02570cb 7 0.00 6:10cb + 28:c02570cf 1 0.00 6:10cf + 28:c02570d3 1 0.00 6:10d3 + 28:c02575dc 1 0.00 6:15dc + 28:c0257663 1 0.00 6:1663 + 28:c0257895 1 0.00 6:1895 + 28:c0257912 1 0.00 6:1912 + 28:c0257b45 1 0.00 6:1b45 + 28:c0257b46 1 0.00 6:1b46 + 28:c0257b67 1 0.00 6:1b67 + 28:c0257b7c 1 0.00 6:1b7c + 28:c0257b86 1 0.00 6:1b86 + 28:c025825c 2 0.00 6:225c + 28:c0258262 2 0.00 6:2262 + 28:c0258267 1 0.00 6:2267 + 28:c025826c 1 0.00 6:226c + 28:c025826f 2 0.00 6:226f + 28:c0258276 2 0.00 6:2276 + 28:c025827a 1 0.00 6:227a + 28:c02582c6 1 0.00 6:22c6 + 28:c02582d3 1 0.00 6:22d3 + 28:c02582d6 2 0.00 6:22d6 + 28:c02582dc 1 0.00 6:22dc + 28:c02582e9 2 0.00 6:22e9 + 28:c02582f1 1 0.00 6:22f1 + 28:c02582f6 2 0.00 6:22f6 + 28:c02582fd 2 0.00 6:22fd + 28:c0258305 2 0.00 6:2305 + 28:c0258308 1 0.00 6:2308 + 28:c025830b 1 0.00 6:230b + 28:c0258321 1 0.00 6:2321 + 28:c025834e 1 0.00 6:234e + 28:c0258350 1 0.00 6:2350 + 28:c0258353 3 0.00 6:2353 + 28:c02583a0 1 0.00 6:23a0 + 28:c02583ac 1 0.00 6:23ac + 28:c02583b3 1 0.00 6:23b3 + 28:c02583bb 2 0.00 6:23bb + 28:c02583c8 1 0.00 6:23c8 + 28:c02583cd 1 0.00 6:23cd + 28:c02583df 1 0.00 6:23df + 28:c02583e6 1 0.00 6:23e6 + 28:c0259b6f 1 0.00 6:3b6f + 28:c0259fc2 1 0.00 6:3fc2 + 28:c025a000 1 0.00 6:4000 + 28:c025a0f3 1 0.00 6:40f3 + 28:c025a6b1 1 0.00 6:46b1 + 28:c025a7a6 1 0.00 6:47a6 + 28:c025a7eb 1 0.00 6:47eb + 28:c025a927 1 0.00 6:4927 + 28:c025abb6 1 0.00 6:4bb6 + 28:c025ae4d 1 0.00 6:4e4d + 28:c025af72 1 0.00 6:4f72 + 28:c025af7d 1 0.00 6:4f7d + 28:c025af86 1 0.00 6:4f86 + 28:c025bddb 1 0.00 6:5ddb + 28:c025bde5 1 0.00 6:5de5 + 28:c025bdfc 2 0.00 6:5dfc + 28:c025be0b 87 0.05 6:5e0b + 28:c025be0e 99 0.05 6:5e0e + 28:c025be4d 2 0.00 6:5e4d + 28:c025be5d 1 0.00 6:5e5d + 28:c025bea3 1 0.00 6:5ea3 + 28:c025beaa 1 0.00 6:5eaa + 28:c025beb6 5 0.00 6:5eb6 + 28:c025becf 1 0.00 6:5ecf + 28:c025bee6 2 0.00 6:5ee6 + 28:c025beea 1 0.00 6:5eea + 28:c025bef3 1 0.00 6:5ef3 + 28:c025bf0a 2 0.00 6:5f0a + 28:c025bf0d 10 0.01 6:5f0d + 28:c025bf99 1 0.00 6:5f99 + 28:c025c040 1 0.00 6:6040 + 28:c025c045 1 0.00 6:6045 + 28:c025c0b7 1 0.00 6:60b7 + 28:c025c2ff 1 0.00 6:62ff + 28:c025c30a 1 0.00 6:630a + 28:c025c317 1 0.00 6:6317 + 28:c025c33e 1 0.00 6:633e + 28:c025c3a7 1 0.00 6:63a7 + 28:c025c3ac 1 0.00 6:63ac + 28:c025c450 1 0.00 6:6450 + 28:c025c48d 1 0.00 6:648d + 28:c025c5c5 1 0.00 6:65c5 + 28:c025c7f3 579 0.30 6:67f3 + 28:c025c7fa 1602 0.83 6:67fa + 28:c025c7fc 10 0.01 6:67fc + 28:c025c807 15 0.01 6:6807 + 28:c025c80d 8 0.00 6:680d + 28:c025c81e 349 0.18 6:681e + 28:c025c81f 75 0.04 6:681f + 28:c0230666 1 0.00 d:666 + 28:c0231288 11 0.01 d:1288 + 28:c023128c 3 0.00 d:128c + 28:c0231293 1 0.00 d:1293 + 28:c023129d 1 0.00 d:129d + 28:c02312a3 1 0.00 d:12a3 + 28:c02312a6 1 0.00 d:12a6 + 28:c02312aa 1 0.00 d:12aa + 28:c02312b2 1 0.00 d:12b2 + 28:c02312b5 1 0.00 d:12b5 + 28:c02312ba 2 0.00 d:12ba + 28:c02312c2 7 0.00 d:12c2 + 28:c02312c9 2 0.00 d:12c9 + 28:c02312cc 8 0.00 d:12cc + 28:c02312ce 4 0.00 d:12ce + 28:c02312d4 2 0.00 d:12d4 + 28:c02312d8 5 0.00 d:12d8 + 28:c02312d9 2 0.00 d:12d9 + 28:c02312de 1 0.00 d:12de + 28:c02312e3 1 0.00 d:12e3 + 28:c02312e6 1 0.00 d:12e6 + 28:c02312eb 5 0.00 d:12eb + 28:c02312ef 1 0.00 d:12ef + 28:c02312f2 1 0.00 d:12f2 + 28:c0231410 3 0.00 d:1410 + 28:c023141c 1 0.00 d:141c + 28:c0231420 1 0.00 d:1420 + 28:c0231422 2 0.00 d:1422 + 28:c0231426 4 0.00 d:1426 + 28:c0231428 3 0.00 d:1428 + 28:c023143c 2 0.00 d:143c + 28:c023143e 1 0.00 d:143e + 28:c0231442 1 0.00 d:1442 + 28:c023145c 2 0.00 d:145c + 28:c023145d 1 0.00 d:145d + 28:c0231463 1 0.00 d:1463 + 28:c023146f 2 0.00 d:146f + 28:c023147a 2 0.00 d:147a + 28:c023148a 2 0.00 d:148a + 28:c0231493 1 0.00 d:1493 + 28:c0231499 1 0.00 d:1499 + 28:c02314a2 1 0.00 d:14a2 + 28:c02314ce 2 0.00 d:14ce + 28:c02314d8 1 0.00 d:14d8 + 28:c02314de 1 0.00 d:14de + 28:c02314ed 1 0.00 d:14ed + 28:c02314f0 6 0.00 d:14f0 + 28:c02314f3 1 0.00 d:14f3 + 28:c02314f5 4 0.00 d:14f5 + 28:c02314f6 1 0.00 d:14f6 + 28:c02314f7 1 0.00 d:14f7 + 28:c0231507 2 0.00 d:1507 + 28:c023150d 4 0.00 d:150d + 28:c0231513 8 0.00 d:1513 + 28:c023151b 3 0.00 d:151b + 28:c0231521 1 0.00 d:1521 + 28:c023152b 1 0.00 d:152b + 28:c0231534 1 0.00 d:1534 + 28:c0231536 2 0.00 d:1536 + 28:c0231539 1 0.00 d:1539 + 28:c023153d 2 0.00 d:153d + 28:c0231540 2 0.00 d:1540 + 28:c0231546 32 0.02 d:1546 + 28:c023154b 1 0.00 d:154b + 28:c0231553 3 0.00 d:1553 + 28:c0231556 13 0.01 d:1556 + 28:c02315d7 4 0.00 d:15d7 + 28:c02315dd 1 0.00 d:15dd + 28:c02315de 3 0.00 d:15de + 28:c02315e3 1 0.00 d:15e3 + 28:c02315e7 1 0.00 d:15e7 + 28:c02315ec 1 0.00 d:15ec + 28:c023160f 1 0.00 d:160f + 28:c0231616 2 0.00 d:1616 + 28:c023177e 6 0.00 d:177e + 28:c0231781 1 0.00 d:1781 + 28:c0231785 1 0.00 d:1785 + 28:c0231792 1 0.00 d:1792 + 28:c02317b6 3 0.00 d:17b6 + 28:c02317ca 1 0.00 d:17ca + 28:c02317d7 2 0.00 d:17d7 + 28:c02317ef 1 0.00 d:17ef + 28:c0231816 1 0.00 d:1816 + 28:c023181e 1 0.00 d:181e + 28:c023182a 3 0.00 d:182a + 28:c023182e 1 0.00 d:182e + 28:c0231836 2 0.00 d:1836 + 28:c023183e 1 0.00 d:183e + 28:c0231844 2 0.00 d:1844 + 28:c023184b 1 0.00 d:184b + 28:c0231854 4 0.00 d:1854 + 28:c0231856 2 0.00 d:1856 + 28:c023185a 2 0.00 d:185a + 28:c0231866 1 0.00 d:1866 + 28:c02318ac 1 0.00 d:18ac + 28:c02318b5 40 0.02 d:18b5 + 28:c02318b7 6 0.00 d:18b7 + 28:c02318be 2 0.00 d:18be + 28:c02318c2 2 0.00 d:18c2 + 28:c02318c7 1 0.00 d:18c7 + 28:c02318cb 1 0.00 d:18cb + 28:c02318ce 7 0.00 d:18ce + 28:c02318d4 3 0.00 d:18d4 + 28:c02318d8 3 0.00 d:18d8 + 28:c02318da 1 0.00 d:18da + 28:c023191d 8 0.00 d:191d + 28:c0231921 1 0.00 d:1921 + 28:c023192e 1 0.00 d:192e + 28:c0231932 2 0.00 d:1932 + 28:c0231935 1 0.00 d:1935 + 28:c0231937 3 0.00 d:1937 + 28:c0231939 1 0.00 d:1939 + 28:c023194e 1 0.00 d:194e + 28:c0231954 2 0.00 d:1954 + 28:c023195a 4 0.00 d:195a + 28:c023196a 2 0.00 d:196a + 28:c023196f 1 0.00 d:196f + 28:c0231972 1 0.00 d:1972 + 28:c0231974 1 0.00 d:1974 + 28:c0231978 2 0.00 d:1978 + 28:c023198d 2 0.00 d:198d + 28:c023199a 1 0.00 d:199a + 28:c023199c 1 0.00 d:199c + 28:c023199e 2 0.00 d:199e + 28:c02319a1 3 0.00 d:19a1 + 28:c02319a5 1 0.00 d:19a5 + 28:c02319a8 3 0.00 d:19a8 + 28:c02319ad 6 0.00 d:19ad + 28:c02319af 12 0.01 d:19af + 28:c02319bd 1 0.00 d:19bd + 28:c02319c0 4 0.00 d:19c0 + 28:c02319cf 1 0.00 d:19cf + 28:c02319d6 1 0.00 d:19d6 + 28:c02319db 3 0.00 d:19db + 28:c02319e0 3 0.00 d:19e0 + 28:c02319e6 5 0.00 d:19e6 + 28:c02319f0 1 0.00 d:19f0 + 28:c02319f3 7 0.00 d:19f3 + 28:c02319f9 4 0.00 d:19f9 + 28:c0231a01 2 0.00 d:1a01 + 28:c0231a08 2 0.00 d:1a08 + 28:c0231a0c 7 0.00 d:1a0c + 28:c0231a0e 1 0.00 d:1a0e + 28:c0231a12 1 0.00 d:1a12 + 28:c0231a14 1 0.00 d:1a14 + 28:c0231a18 1 0.00 d:1a18 + 28:c0231a1a 3 0.00 d:1a1a + 28:c0231a23 1 0.00 d:1a23 + 28:c0231a25 2 0.00 d:1a25 + 28:c0231a39 5 0.00 d:1a39 + 28:c0231a3d 10 0.01 d:1a3d + 28:c0231a44 3 0.00 d:1a44 + 28:c0231a49 2 0.00 d:1a49 + 28:c0231a50 4 0.00 d:1a50 + 28:c0231a59 2 0.00 d:1a59 + 28:c0231a5f 2 0.00 d:1a5f + 28:c0231a62 1 0.00 d:1a62 + 28:c0231ba3 1 0.00 d:1ba3 + 28:c0231c0a 1 0.00 d:1c0a + 28:c0231c1d 1 0.00 d:1c1d + 28:c0231e80 1 0.00 d:1e80 + 28:c0231eef 1 0.00 d:1eef + 28:c0231f79 1 0.00 d:1f79 + 28:c0231fb7 1 0.00 d:1fb7 + 28:c0231fd8 1 0.00 d:1fd8 + 28:c02321f3 1 0.00 d:21f3 + 28:c02321f4 1 0.00 d:21f4 + 28:c0232238 1 0.00 d:2238 + 28:c0232290 2 0.00 d:2290 + 28:c02322b0 1 0.00 d:22b0 + 28:c0232307 1 0.00 d:2307 + 28:c023260c 7 0.00 d:260c + 28:c023260d 1 0.00 d:260d + 28:c023260e 2 0.00 d:260e + 28:c0232613 1 0.00 d:2613 + 28:c0232626 3 0.00 d:2626 + 28:c023262a 1 0.00 d:262a + 28:c0232634 1 0.00 d:2634 + 28:c023269b 5 0.00 d:269b + 28:c023269f 1 0.00 d:269f + 28:c02326a4 4 0.00 d:26a4 + 28:c02326b2 1 0.00 d:26b2 + 28:c023337e 33 0.02 e:37e + 28:c0233380 1 0.00 e:380 + 28:c023a312 1 0.00 11:312 + 28:c023a776 1 0.00 11:776 + 28:c024e08c 1 0.00 16:8c + 28:c024e1ab 1 0.00 16:1ab + 28:c024e1bb 3 0.00 16:1bb + +Module Name SICE + + CS:EIP Samples (%) Map Offset Symbol + 28:c002954f 1 0.00 1:163 + 28:c003c9da 3 0.00 1:135ee + 28:c003c9eb 1 0.00 1:135ff + 28:c003caab 2 0.00 1:136bf + +Module Name IOS + + CS:EIP Samples (%) Map Offset Symbol + 28:c00fe557 12 0.01 1:723 + 28:c00fe55a 1 0.00 1:726 + 28:c00fe55e 1 0.00 1:72a + 28:c00fe7bf 15 0.01 1:98b + 28:c00fe7c4 1 0.00 1:990 + 28:c00fe86d 1 0.00 1:a39 + 28:c00fe8c4 1 0.00 1:a90 + 28:c00fe8d8 1 0.00 1:aa4 + 28:c00fe8ee 1 0.00 1:aba + 28:c00fe8fe 1 0.00 1:aca + 28:c00fe90d 3 0.00 1:ad9 + 28:c00fe91a 1 0.00 1:ae6 + 28:c00fe91e 1 0.00 1:aea + 28:c00fe924 1 0.00 1:af0 + 28:c00fe936 1 0.00 1:b02 + 28:c00fe9b3 1 0.00 1:b7f + 28:c00fea2a 1 0.00 1:bf6 + 28:c00ff09d 7 0.00 1:1269 + 28:c00ff120 7 0.00 1:12ec + 28:c00ff136 2 0.00 1:1302 + 28:c00ff13e 1 0.00 1:130a + 28:c00ff19f 12 0.01 1:136b + 28:c00ff1ba 2 0.00 1:1386 + 28:c00ff1d0 1 0.00 1:139c + 28:c00ff1d7 1 0.00 1:13a3 + 28:c00ff1de 1 0.00 1:13aa + 28:c00ff42b 1 0.00 1:15f7 + 28:c00ff49e 1 0.00 1:166a + 28:c00ff5d9 1 0.00 1:17a5 + 28:c00ff7a0 1 0.00 1:196c + 28:c00ffba0 1 0.00 1:1d6c + 28:c025e3c9 1 0.00 4:a91 + 28:c025e3e1 1 0.00 4:aa9 + 28:c025e3e3 1 0.00 4:aab + +Module Name NWLINK + + CS:EIP Samples (%) Map Offset Symbol + 28:c0101bbb 1 0.00 1:1b23 + 28:c0101c8b 1 0.00 1:1bf3 + 28:c0101fd7 1 0.00 1:1f3f + 28:c010204c 1 0.00 1:1fb4 + 28:c01038bb 592 0.31 1:3823 + 28:c01038c1 73 0.04 1:3829 + 28:c01038c3 201 0.10 1:382b + 28:c01038c4 53 0.03 1:382c + 28:c0103d9f 2 0.00 1:3d07 + +Module Name CONFIGMG + + CS:EIP Samples (%) Map Offset Symbol + 28:c0244258 1 0.00 9:4d48 + 28:c0245c2f 1 0.00 9:671f + 28:c0245d11 1 0.00 9:6801 + 28:c0248e2c 2 0.00 9:991c + 28:c0248e3d 1 0.00 9:992d + 28:c0249618 1 0.00 9:a108 + +Module Name VSHARE + + CS:EIP Samples (%) Map Offset Symbol + 28:c01095c2 80 0.04 1:29e + 28:c01095c6 16 0.01 1:2a2 + 28:c01095c7 34 0.02 1:2a3 + 28:c01095ca 32 0.02 1:2a6 + +Module Name VWIN32 + + CS:EIP Samples (%) Map Offset Symbol + 28:c010af85 1 0.00 1:3fd + 28:c010afc9 2 0.00 1:441 + 28:c010afec 1 0.00 1:464 + 28:c010b318 1 0.00 1:790 + 28:c010b31c 1 0.00 1:794 + 28:c010b335 2 0.00 1:7ad + 28:c010b337 2 0.00 1:7af + 28:c010b381 1 0.00 1:7f9 + 28:c010b393 1 0.00 1:80b + 28:c010b3be 11 0.01 1:836 + 28:c010b3bf 1 0.00 1:837 + 28:c010b3c7 1 0.00 1:83f + 28:c010b3d0 1 0.00 1:848 + 28:c010b3d6 2 0.00 1:84e + 28:c010b3d9 8 0.00 1:851 + 28:c010b3e9 1 0.00 1:861 + 28:c010b3ee 4 0.00 1:866 + 28:c010b3f3 1 0.00 1:86b + 28:c010b3fe 2 0.00 1:876 + 28:c010b403 1 0.00 1:87b + 28:c010b404 1 0.00 1:87c + 28:c010b530 3 0.00 1:9a8 + 28:c010b53f 2 0.00 1:9b7 + 28:c010b556 1 0.00 1:9ce + 28:c010b55f 1 0.00 1:9d7 + 28:c010b58e 1 0.00 1:a06 + 28:c010b5af 2 0.00 1:a27 + 28:c010b6f4 1 0.00 1:b6c + 28:c010b878 1 0.00 1:cf0 + 28:c0261578 1 0.00 4:104 + 28:c0261618 1 0.00 4:1a4 + 28:c02616f4 2 0.00 4:280 + 28:c02616f6 2 0.00 4:282 + 28:c0261702 1 0.00 4:28e + 28:c026171d 1 0.00 4:2a9 + 28:c02619f3 1 0.00 4:57f + 28:c0261a05 1 0.00 4:591 + 28:c0261b22 1 0.00 4:6ae + 28:c0261b62 2 0.00 4:6ee + 28:c0261ba1 2 0.00 4:72d + 28:c0261f9f 4 0.00 4:b2b + 28:c0261fa5 1 0.00 4:b31 + 28:c0261fb8 1 0.00 4:b44 + 28:c0262007 3 0.00 4:b93 + 28:c026200c 2 0.00 4:b98 + 28:c0262016 2 0.00 4:ba2 + 28:c026201a 1 0.00 4:ba6 + 28:c026201f 1 0.00 4:bab + 28:c026203a 1 0.00 4:bc6 + 28:c02622de 1 0.00 4:e6a + 28:c026234b 1 0.00 4:ed7 + 28:c02634cd 1 0.00 4:2059 + 28:c02638bc 1 0.00 4:2448 + 28:c0263ccb 1 0.00 4:2857 + 28:c0263d18 1 0.00 4:28a4 + 28:c0263d22 1 0.00 4:28ae + 28:c0263dc6 1 0.00 4:2952 + 28:c0263de0 1 0.00 4:296c + 28:c0263ec5 2 0.00 4:2a51 + 28:c0263ed0 1 0.00 4:2a5c + 28:c0263f12 1 0.00 4:2a9e + 28:c0263f13 1 0.00 4:2a9f + 28:c0263f16 1 0.00 4:2aa2 + 28:c0263f25 1 0.00 4:2ab1 + 28:c0263f34 1 0.00 4:2ac0 + 28:c0263f37 2 0.00 4:2ac3 + 28:c0263f3b 5 0.00 4:2ac7 + 28:c0263f41 2 0.00 4:2acd + 28:c0263f60 1 0.00 4:2aec + 28:c0263f62 1 0.00 4:2aee + 28:c0263f73 1 0.00 4:2aff + 28:c0263f7c 1 0.00 4:2b08 + 28:c0263f7e 1 0.00 4:2b0a + 28:c0263f82 1 0.00 4:2b0e + 28:c0263f95 1 0.00 4:2b21 + 28:c0263fb5 1 0.00 4:2b41 + 28:c0263fb6 2 0.00 4:2b42 + 28:c0263fc8 2 0.00 4:2b54 + 28:c0263fcb 2 0.00 4:2b57 + 28:c0263fd1 1 0.00 4:2b5d + 28:c0263fe3 1 0.00 4:2b6f + 28:c0264052 1 0.00 4:2bde + 28:c026405e 1 0.00 4:2bea + 28:c026408b 1 0.00 4:2c17 + 28:c0264097 1 0.00 4:2c23 + 28:c0264e61 1 0.00 4:39ed + 28:c0264e81 1 0.00 4:3a0d + 28:c0264e8f 1 0.00 4:3a1b + 28:c0264f29 1 0.00 4:3ab5 + 28:c0264f32 1 0.00 4:3abe + 28:c0264f7c 1 0.00 4:3b08 + 28:c0264f90 2 0.00 4:3b1c + 28:c0264f92 1 0.00 4:3b1e + 28:c0264f9a 1 0.00 4:3b26 + 28:c0264fe1 1 0.00 4:3b6d + 28:c026504b 4 0.00 4:3bd7 + 28:c026508d 1 0.00 4:3c19 + 28:c02650e1 1 0.00 4:3c6d + 28:c02650ec 1 0.00 4:3c78 + 28:c02651e7 1 0.00 4:3d73 + 28:c02651f5 2 0.00 4:3d81 + 28:c0265216 2 0.00 4:3da2 + +Module Name VCOMM + + CS:EIP Samples (%) Map Offset Symbol + 28:c010c27a 1 0.00 1:12 + 28:c0267654 1 0.00 4:10e8 + +Module Name IFSMGR + + CS:EIP Samples (%) Map Offset Symbol + 28:c010cdb4 5 0.00 1:4b4 + 28:c010cdbb 5 0.00 1:4bb + 28:c010cdc1 219 0.11 1:4c1 + 28:c010cdc8 8 0.00 1:4c8 + 28:c010ceb3 2 0.00 1:5b3 + 28:c010cebd 9 0.00 1:5bd + 28:c010cec3 3 0.00 1:5c3 + 28:c010cf23 4 0.00 1:623 + 28:c010cf26 1 0.00 1:626 + 28:c010cf40 1 0.00 1:640 + 28:c010cf52 3 0.00 1:652 + 28:c010cf61 5 0.00 1:661 + 28:c010cf66 1 0.00 1:666 + 28:c010cf69 10 0.01 1:669 + 28:c010cf6e 6 0.00 1:66e + 28:c010cf74 6 0.00 1:674 + 28:c010cf79 2 0.00 1:679 + 28:c010cf7f 22 0.01 1:67f + 28:c010cf89 1 0.00 1:689 + 28:c010cf96 1 0.00 1:696 + 28:c010cf9e 1 0.00 1:69e + 28:c010cfa1 6 0.00 1:6a1 + 28:c010cfa7 1 0.00 1:6a7 + 28:c010cfb1 1 0.00 1:6b1 + 28:c010cfb9 2 0.00 1:6b9 + 28:c010cfc7 1 0.00 1:6c7 + 28:c010cfd6 2 0.00 1:6d6 + 28:c010cfde 1 0.00 1:6de + 28:c010d02e 7 0.00 1:72e + 28:c010d034 2 0.00 1:734 + 28:c010d038 3 0.00 1:738 + 28:c010d04b 1 0.00 1:74b + 28:c010d053 1 0.00 1:753 + 28:c010d055 1 0.00 1:755 + 28:c010d059 1 0.00 1:759 + 28:c010d061 1 0.00 1:761 + 28:c010d064 1 0.00 1:764 + 28:c010d06b 1 0.00 1:76b + 28:c010d071 1 0.00 1:771 + 28:c010d077 4 0.00 1:777 + 28:c010d08b 1 0.00 1:78b + 28:c010d096 2 0.00 1:796 + 28:c010d0b1 7 0.00 1:7b1 + 28:c010d0b6 2 0.00 1:7b6 + 28:c010d0bd 1 0.00 1:7bd + 28:c010d0cb 1 0.00 1:7cb + 28:c010d0e7 1 0.00 1:7e7 + 28:c010d0ed 1 0.00 1:7ed + 28:c010d0f6 2 0.00 1:7f6 + 28:c010d0fd 1 0.00 1:7fd + 28:c010d101 1 0.00 1:801 + 28:c010d127 2 0.00 1:827 + 28:c010d14b 2 0.00 1:84b + 28:c010d14f 1 0.00 1:84f + 28:c010d157 2 0.00 1:857 + 28:c010d17d 1 0.00 1:87d + 28:c010d190 1 0.00 1:890 + 28:c010d1aa 1 0.00 1:8aa + 28:c010d1b6 2 0.00 1:8b6 + 28:c010d1c8 2 0.00 1:8c8 + 28:c010d1d8 1 0.00 1:8d8 + 28:c010d1e4 1 0.00 1:8e4 + 28:c010d1f0 2 0.00 1:8f0 + 28:c010d1f6 2 0.00 1:8f6 + 28:c010d2cb 1 0.00 1:9cb + 28:c010d6b5 1 0.00 1:db5 + 28:c010d77d 1 0.00 1:e7d + 28:c010d7e4 320 0.17 1:ee4 + 28:c010d7e8 334 0.17 1:ee8 + 28:c010d7ea 35 0.02 1:eea + 28:c010d7f3 44 0.02 1:ef3 + 28:c010d7f5 34 0.02 1:ef5 + 28:c010d810 536 0.28 1:f10 + 28:c010d816 689 0.36 1:f16 + 28:c010d819 1579 0.82 1:f19 + 28:c010d81d 1303 0.68 1:f1d + 28:c010d81f 91 0.05 1:f1f + 28:c010d820 3 0.00 1:f20 + 28:c010da40 7 0.00 1:1140 + 28:c010da52 6 0.00 1:1152 + 28:c010da7a 3 0.00 1:117a + 28:c010da81 1 0.00 1:1181 + 28:c010dabc 3 0.00 1:11bc + 28:c010dac2 1 0.00 1:11c2 + 28:c010dacc 10 0.01 1:11cc + 28:c010dad2 1 0.00 1:11d2 + 28:c010dad6 1 0.00 1:11d6 + 28:c010dae5 2 0.00 1:11e5 + 28:c010dae9 1 0.00 1:11e9 + 28:c010daea 2 0.00 1:11ea + 28:c010daf9 1 0.00 1:11f9 + 28:c010db31 1 0.00 1:1231 + 28:c010db58 2 0.00 1:1258 + 28:c010db61 3 0.00 1:1261 + 28:c010db78 1 0.00 1:1278 + 28:c010ddac 1 0.00 1:14ac + 28:c010ddb1 4 0.00 1:14b1 + 28:c010ddc8 3 0.00 1:14c8 + 28:c010dea6 23 0.01 1:15a6 + 28:c010dea8 3 0.00 1:15a8 + 28:c010dea9 2 0.00 1:15a9 + 28:c010deb8 1 0.00 1:15b8 + 28:c010dfa0 4 0.00 1:16a0 + 28:c010e174 7 0.00 1:1874 + 28:c010e177 4 0.00 1:1877 + 28:c010e1a4 2 0.00 1:18a4 + 28:c010e1ac 1 0.00 1:18ac + 28:c010e1b8 2 0.00 1:18b8 + 28:c010e1ef 5 0.00 1:18ef + 28:c010e210 3 0.00 1:1910 + 28:c010e22b 2 0.00 1:192b + 28:c010e232 1 0.00 1:1932 + 28:c010e238 1 0.00 1:1938 + 28:c010e244 1 0.00 1:1944 + 28:c010e255 2 0.00 1:1955 + 28:c010e27e 1 0.00 1:197e + 28:c010e281 1 0.00 1:1981 + 28:c010e2b6 2 0.00 1:19b6 + 28:c010e5ff 1 0.00 1:1cff + 28:c010e66f 1 0.00 1:1d6f + 28:c010e69f 1 0.00 1:1d9f + 28:c010e7d5 1 0.00 1:1ed5 + 28:c010e8f8 1 0.00 1:1ff8 + 28:c010e97c 2 0.00 1:207c + 28:c010e991 1 0.00 1:2091 + 28:c010e996 1 0.00 1:2096 + 28:c010e9c2 1 0.00 1:20c2 + 28:c010e9cb 1 0.00 1:20cb + 28:c010ee58 1 0.00 1:2558 + 28:c010ee64 1 0.00 1:2564 + 28:c010ee6a 1 0.00 1:256a + 28:c010ee6b 1 0.00 1:256b + 28:c010ee73 1 0.00 1:2573 + 28:c010ee77 1 0.00 1:2577 + 28:c010f14a 3 0.00 1:284a + 28:c010f304 4 0.00 1:2a04 + 28:c010f30a 1 0.00 1:2a0a + 28:c010f333 1 0.00 1:2a33 + 28:c010f337 6 0.00 1:2a37 + 28:c010f380 1 0.00 1:2a80 + 28:c010f388 1 0.00 1:2a88 + 28:c010f39a 4 0.00 1:2a9a + 28:c010f39e 4 0.00 1:2a9e + 28:c010f99a 1 0.00 1:309a + 28:c010fa6c 19 0.01 1:316c + 28:c010fa73 7 0.00 1:3173 + 28:c010fa7c 1 0.00 1:317c + 28:c010fc1e 1 0.00 1:331e + 28:c010fc28 1 0.00 1:3328 + 28:c010fc38 1 0.00 1:3338 + 28:c010fced 1 0.00 1:33ed + 28:c0110115 3 0.00 1:3815 + 28:c0110133 1 0.00 1:3833 + 28:c0110154 1 0.00 1:3854 + 28:c011015b 1 0.00 1:385b + 28:c01101a3 1 0.00 1:38a3 + 28:c0110412 1 0.00 1:3b12 + 28:c0110594 1 0.00 1:3c94 + 28:c011059a 1 0.00 1:3c9a + 28:c01105b6 1 0.00 1:3cb6 + 28:c0110f30 1 0.00 1:4630 + 28:c01117ec 13 0.01 1:4eec + 28:c01117f6 3 0.00 1:4ef6 + 28:c0267e40 9 0.00 3:c + 28:c0267e4a 1 0.00 3:16 + 28:c0267e8c 1 0.00 3:58 + 28:c02685a2 2 0.00 3:76e + 28:c02685c0 1 0.00 3:78c + 28:c02685d6 1 0.00 3:7a2 + 28:c02685ec 1 0.00 3:7b8 + 28:c02685f4 1 0.00 3:7c0 + 28:c0268602 3 0.00 3:7ce + 28:c026860f 5 0.00 3:7db + 28:c026862e 1 0.00 3:7fa + 28:c026863c 2 0.00 3:808 + 28:c026864e 1 0.00 3:81a + 28:c02697eb 7 0.00 3:19b7 + 28:c0269801 1 0.00 3:19cd + 28:c02698a8 1 0.00 3:1a74 + 28:c02698b9 1 0.00 3:1a85 + 28:c0269a73 7 0.00 3:1c3f + 28:c0269aaa 2 0.00 3:1c76 + 28:c0269b3e 8 0.00 3:1d0a + 28:c0269d48 12 0.01 3:1f14 + 28:c0269d53 1 0.00 3:1f1f + 28:c0269d58 1 0.00 3:1f24 + 28:c0269d59 4 0.00 3:1f25 + 28:c0269d78 4 0.00 3:1f44 + 28:c0269d97 3 0.00 3:1f63 + 28:c0269f63 3 0.00 3:212f + 28:c0269fad 1 0.00 3:2179 + 28:c026a07e 7 0.00 3:224a + 28:c026a07f 1 0.00 3:224b + 28:c026a09b 2 0.00 3:2267 + 28:c026a09d 1 0.00 3:2269 + 28:c026a0a5 1 0.00 3:2271 + 28:c026a0d6 1 0.00 3:22a2 + 28:c026c59a 1 0.00 3:4766 + 28:c026c5dd 1 0.00 3:47a9 + 28:c026c5f6 1 0.00 3:47c2 + 28:c026c656 2 0.00 3:4822 + 28:c026c6e7 1 0.00 3:48b3 + 28:c026c73c 1 0.00 3:4908 + 28:c026cdf0 1 0.00 3:4fbc + 28:c026cef3 2 0.00 3:50bf + 28:c026cffc 4 0.00 3:51c8 + 28:c026d030 2 0.00 3:51fc + 28:c026d0ac 1 0.00 3:5278 + 28:c026d126 3 0.00 3:52f2 + 28:c026d15a 3 0.00 3:5326 + 28:c026d314 3 0.00 3:54e0 + 28:c026d317 2 0.00 3:54e3 + 28:c026d337 1 0.00 3:5503 + 28:c026d371 1 0.00 3:553d + 28:c026d3a6 1 0.00 3:5572 + 28:c026d3a9 2 0.00 3:5575 + 28:c026d3ae 2 0.00 3:557a + 28:c026d3c5 1 0.00 3:5591 + 28:c026d3d9 1 0.00 3:55a5 + 28:c026d6d8 2 0.00 3:58a4 + 28:c026d6d9 1 0.00 3:58a5 + 28:c026d6e0 1 0.00 3:58ac + 28:c026d95c 1 0.00 3:5b28 + 28:c026d969 1 0.00 3:5b35 + 28:c026da5a 9 0.00 3:5c26 + 28:c026da7c 1 0.00 3:5c48 + 28:c026dc00 1 0.00 3:5dcc + 28:c026dc29 1 0.00 3:5df5 + 28:c026dc2f 1 0.00 3:5dfb + 28:c026dc3c 2 0.00 3:5e08 + 28:c026dc42 1 0.00 3:5e0e + 28:c026dc5c 4 0.00 3:5e28 + 28:c026de18 4 0.00 3:5fe4 + 28:c026de2b 1 0.00 3:5ff7 + 28:c026de40 1 0.00 3:600c + 28:c026de72 1 0.00 3:603e + 28:c026dea8 2 0.00 3:6074 + 28:c026deab 1 0.00 3:6077 + 28:c026def0 5 0.00 3:60bc + 28:c026def6 2 0.00 3:60c2 + 28:c026df0d 1 0.00 3:60d9 + 28:c026df10 5 0.00 3:60dc + 28:c026edc0 10 0.01 3:6f8c + 28:c026edcc 1 0.00 3:6f98 + 28:c026edd0 2 0.00 3:6f9c + 28:c026edd6 5 0.00 3:6fa2 + 28:c026ef8a 1 0.00 3:7156 + 28:c026efa0 1 0.00 3:716c + 28:c026f1d8 21 0.01 3:73a4 + 28:c026f1e1 1 0.00 3:73ad + 28:c026f9e0 1 0.00 3:7bac + 28:c0271d08 3 0.00 3:9ed4 + 28:c0271d2a 2 0.00 3:9ef6 + 28:c0271d38 1 0.00 3:9f04 + 28:c0271d40 1 0.00 3:9f0c + 28:c0271d5c 1 0.00 3:9f28 + 28:c0271f51 1 0.00 3:a11d + 28:c0277804 2 0.00 3:f9d0 + 28:c027791f 1 0.00 3:faeb + 28:c0277a50 1 0.00 3:fc1c + 28:c027a177 1 0.00 3:12343 + 28:c027a185 1 0.00 3:12351 + 28:c027a1ab 1 0.00 3:12377 + 28:c027a1bc 1 0.00 3:12388 + 28:c027a1be 1 0.00 3:1238a + 28:c027a1f9 1 0.00 3:123c5 + 28:c027a212 4 0.00 3:123de + 28:c027a215 1 0.00 3:123e1 + 28:c027a21d 1 0.00 3:123e9 + 28:c027a220 3 0.00 3:123ec + 28:c027a22e 3 0.00 3:123fa + 28:c027a22f 1 0.00 3:123fb + 28:c027a235 1 0.00 3:12401 + 28:c027a239 1 0.00 3:12405 + 28:c027a244 1 0.00 3:12410 + 28:c027a24a 1 0.00 3:12416 + 28:c027a24d 2 0.00 3:12419 + 28:c027a2b1 2 0.00 3:1247d + 28:c027a2b2 1 0.00 3:1247e + 28:c027a2b5 2 0.00 3:12481 + 28:c027a2b6 1 0.00 3:12482 + 28:c027a2bd 1 0.00 3:12489 + 28:c027a2c8 1 0.00 3:12494 + 28:c027a2d7 1 0.00 3:124a3 + 28:c027a2ee 1 0.00 3:124ba + 28:c027a394 2 0.00 3:12560 + 28:c027a39b 1 0.00 3:12567 + 28:c027a3e1 1 0.00 3:125ad + 28:c027a3eb 1 0.00 3:125b7 + 28:c027a4d3 1 0.00 3:1269f + 28:c027a506 1 0.00 3:126d2 + 28:c027a514 3 0.00 3:126e0 + 28:c027a51a 1 0.00 3:126e6 + 28:c027a51c 1 0.00 3:126e8 + 28:c027a51e 3 0.00 3:126ea + 28:c027a522 1 0.00 3:126ee + 28:c027a526 1 0.00 3:126f2 + 28:c027a555 2 0.00 3:12721 + 28:c027a55e 1 0.00 3:1272a + 28:c027a560 1 0.00 3:1272c + 28:c027a565 1 0.00 3:12731 + 28:c027a568 1 0.00 3:12734 + 28:c027a569 3 0.00 3:12735 + 28:c027a56d 2 0.00 3:12739 + 28:c027a5a3 2 0.00 3:1276f + 28:c027a5a9 4 0.00 3:12775 + 28:c027a5b0 24 0.01 3:1277c + 28:c027a5b2 5 0.00 3:1277e + 28:c027a5b3 7 0.00 3:1277f + 28:c027a5b6 43 0.02 3:12782 + 28:c027a5be 5 0.00 3:1278a + 28:c027a5c0 12 0.01 3:1278c + 28:c027a5c5 3 0.00 3:12791 + 28:c027a5d2 5 0.00 3:1279e + 28:c027a5fe 6 0.00 3:127ca + 28:c027a601 9 0.00 3:127cd + 28:c027a60a 6 0.00 3:127d6 + 28:c027a60c 5 0.00 3:127d8 + 28:c027a610 9 0.00 3:127dc + 28:c027a614 26 0.01 3:127e0 + 28:c027a616 15 0.01 3:127e2 + 28:c027a61c 4 0.00 3:127e8 + 28:c027a61e 2 0.00 3:127ea + 28:c027a61f 1 0.00 3:127eb + 28:c027a9fb 1 0.00 3:12bc7 + 28:c027ac88 16 0.01 3:12e54 + 28:c027ac8d 4 0.00 3:12e59 + 28:c027ac91 9 0.00 3:12e5d + 28:c027acb0 1 0.00 3:12e7c + 28:c027acb8 2 0.00 3:12e84 + 28:c027accb 1 0.00 3:12e97 + 28:c027acda 1 0.00 3:12ea6 + 28:c027ad0f 13 0.01 3:12edb + 28:c027ad18 10 0.01 3:12ee4 + 28:c027ad35 1 0.00 3:12f01 + 28:c027ad4a 1 0.00 3:12f16 + 28:c027ad73 2 0.00 3:12f3f + 28:c027ad78 2 0.00 3:12f44 + 28:c027adb6 1 0.00 3:12f82 + 28:c027aed8 2 0.00 3:130a4 + 28:c027af1b 1 0.00 3:130e7 + 28:c027af37 1 0.00 3:13103 + 28:c027af47 1 0.00 3:13113 + 28:c027af49 1 0.00 3:13115 + 28:c027af55 3 0.00 3:13121 + 28:c027af61 1 0.00 3:1312d + 28:c027b05e 2 0.00 3:1322a + 28:c027b075 1 0.00 3:13241 + 28:c027b0a4 1 0.00 3:13270 + 28:c027b0ff 1 0.00 3:132cb + 28:c027b12e 2 0.00 3:132fa + 28:c027b474 12 0.01 3:13640 + 28:c027b478 3 0.00 3:13644 + 28:c027b47b 3 0.00 3:13647 + 28:c027b484 11 0.01 3:13650 + 28:c027b48b 10 0.01 3:13657 + 28:c027b48d 3 0.00 3:13659 + 28:c027b4a0 1 0.00 3:1366c + 28:c027b76e 3 0.00 3:1393a + 28:c027b775 4 0.00 3:13941 + 28:c027b796 1 0.00 3:13962 + 28:c027b7b6 1 0.00 3:13982 + 28:c027b7c0 1 0.00 3:1398c + 28:c027b7d5 1 0.00 3:139a1 + +Module Name VFAT + + CS:EIP Samples (%) Map Offset Symbol + 28:c0113b83 1 0.00 1:3 + 28:c0113bfe 1 0.00 1:7e + 28:c0113c57 2 0.00 1:d7 + 28:c0113c5d 1 0.00 1:dd + 28:c0114137 1 0.00 1:5b7 + 28:c0114495 1 0.00 1:915 + 28:c01145bc 4 0.00 1:a3c + 28:c0114701 1 0.00 1:b81 + 28:c0114771 2 0.00 1:bf1 + 28:c0114912 1 0.00 1:d92 + 28:c0114951 1 0.00 1:dd1 + 28:c0114984 1 0.00 1:e04 + 28:c01149b3 1 0.00 1:e33 + 28:c01149b7 2 0.00 1:e37 + 28:c01149c3 20 0.01 1:e43 + 28:c01149c6 1 0.00 1:e46 + 28:c01149cd 3 0.00 1:e4d + 28:c01149d1 1 0.00 1:e51 + 28:c01149d7 1 0.00 1:e57 + 28:c01149de 4 0.00 1:e5e + 28:c01149e4 10 0.01 1:e64 + 28:c0114a0a 1 0.00 1:e8a + 28:c0114a86 1 0.00 1:f06 + 28:c0114a95 3 0.00 1:f15 + 28:c0114aa8 1 0.00 1:f28 + 28:c0114aaa 1 0.00 1:f2a + 28:c0114aac 2 0.00 1:f2c + 28:c0114aae 4 0.00 1:f2e + 28:c0114ab4 1 0.00 1:f34 + 28:c0114ab8 5 0.00 1:f38 + 28:c0114abc 2 0.00 1:f3c + 28:c0114abe 2 0.00 1:f3e + 28:c0114ac1 3 0.00 1:f41 + 28:c0114acb 5 0.00 1:f4b + 28:c0114f00 5 0.00 1:1380 + 28:c0114f08 1 0.00 1:1388 + 28:c0114f27 2 0.00 1:13a7 + 28:c0114f38 1 0.00 1:13b8 + 28:c0114f71 1 0.00 1:13f1 + 28:c0114f77 1 0.00 1:13f7 + 28:c0114f81 1 0.00 1:1401 + 28:c0115028 1 0.00 1:14a8 + 28:c011697c 1 0.00 1:2dfc + 28:c01169a8 2 0.00 1:2e28 + 28:c01169aa 1 0.00 1:2e2a + 28:c01169b7 1 0.00 1:2e37 + 28:c01169fc 2 0.00 1:2e7c + 28:c0116c0e 1 0.00 1:308e + 28:c0116c15 2 0.00 1:3095 + 28:c0116c3f 1 0.00 1:30bf + 28:c0116c91 1 0.00 1:3111 + 28:c0116d21 1 0.00 1:31a1 + 28:c0117565 1 0.00 1:39e5 + 28:c0117a79 1 0.00 1:3ef9 + 28:c0117d78 1 0.00 1:41f8 + 28:c0117da4 1 0.00 1:4224 + 28:c0117df4 1 0.00 1:4274 + 28:c0117ea4 1 0.00 1:4324 + 28:c0117f1e 1 0.00 1:439e + 28:c0117f2c 1 0.00 1:43ac + 28:c011800c 1 0.00 1:448c + 28:c0118124 1 0.00 1:45a4 + 28:c0118163 1 0.00 1:45e3 + 28:c01182a8 1 0.00 1:4728 + 28:c01183c8 3 0.00 1:4848 + 28:c01183f0 1 0.00 1:4870 + 28:c0118468 1 0.00 1:48e8 + 28:c011848b 1 0.00 1:490b + 28:c01184c3 1 0.00 1:4943 + 28:c0118904 2 0.00 1:4d84 + 28:c0118976 1 0.00 1:4df6 + 28:c0118a60 20 0.01 1:4ee0 + 28:c0118a63 19 0.01 1:4ee3 + 28:c0118a6a 1 0.00 1:4eea + 28:c0118bd9 1 0.00 1:5059 + 28:c0118be6 1 0.00 1:5066 + 28:c0118d03 73 0.04 1:5183 + 28:c0118d05 1 0.00 1:5185 + 28:c0118d14 5 0.00 1:5194 + 28:c0118d30 1 0.00 1:51b0 + 28:c0118d3c 2 0.00 1:51bc + 28:c0118db3 1 0.00 1:5233 + 28:c0118e17 1 0.00 1:5297 + 28:c011a378 1 0.00 1:67f8 + 28:c011a37c 1 0.00 1:67fc + 28:c011a37f 3 0.00 1:67ff + 28:c011a387 1 0.00 1:6807 + 28:c011a3a0 1 0.00 1:6820 + 28:c011a3ad 4 0.00 1:682d + 28:c011a42c 1 0.00 1:68ac + 28:c011a978 1 0.00 1:6df8 + 28:c011aa88 1 0.00 1:6f08 + 28:c011ab1b 1 0.00 1:6f9b + 28:c011ab1d 1 0.00 1:6f9d + 28:c011ab2e 1 0.00 1:6fae + 28:c011ab4c 2 0.00 1:6fcc + 28:c011abbe 1 0.00 1:703e + 28:c011abd9 3 0.00 1:7059 + 28:c011abdb 1 0.00 1:705b + 28:c011abdf 1 0.00 1:705f + 28:c011abea 2 0.00 1:706a + 28:c011abf4 3 0.00 1:7074 + 28:c011abfa 1 0.00 1:707a + 28:c011abfb 1 0.00 1:707b + 28:c011abfd 1 0.00 1:707d + 28:c011ac01 1 0.00 1:7081 + 28:c011ac18 3 0.00 1:7098 + 28:c011ac1b 1 0.00 1:709b + 28:c011ac2d 1 0.00 1:70ad + 28:c011ac45 1 0.00 1:70c5 + 28:c011ac5b 1 0.00 1:70db + 28:c011ac75 1 0.00 1:70f5 + 28:c011ac78 1 0.00 1:70f8 + 28:c011ac7c 1 0.00 1:70fc + 28:c011aca6 1 0.00 1:7126 + 28:c011acb1 2 0.00 1:7131 + 28:c011acba 3 0.00 1:713a + 28:c011ad26 1 0.00 1:71a6 + 28:c011ad62 1 0.00 1:71e2 + 28:c011ad6e 2 0.00 1:71ee + 28:c011ad79 1 0.00 1:71f9 + 28:c011ad98 1 0.00 1:7218 + 28:c011ada3 1 0.00 1:7223 + 28:c011adff 1 0.00 1:727f + 28:c011ae1e 1 0.00 1:729e + 28:c011ae55 1 0.00 1:72d5 + 28:c011ae5b 4 0.00 1:72db + 28:c011ae60 1 0.00 1:72e0 + 28:c011ae67 1 0.00 1:72e7 + 28:c011ae6b 1 0.00 1:72eb + 28:c011ae71 1 0.00 1:72f1 + 28:c011ae78 2 0.00 1:72f8 + 28:c011ae7c 1 0.00 1:72fc + 28:c011ae7d 3 0.00 1:72fd + 28:c011af68 4 0.00 1:73e8 + 28:c011afa1 1 0.00 1:7421 + 28:c011b03a 8 0.00 1:74ba + 28:c011b089 1 0.00 1:7509 + 28:c011b4ee 1 0.00 1:796e + 28:c011b4f4 1 0.00 1:7974 + 28:c011b4f9 1 0.00 1:7979 + 28:c011b52d 3 0.00 1:79ad + 28:c011b532 1 0.00 1:79b2 + 28:c011b544 1 0.00 1:79c4 + 28:c011b54d 1 0.00 1:79cd + 28:c011b556 1 0.00 1:79d6 + 28:c011b622 2 0.00 1:7aa2 + 28:c011b638 1 0.00 1:7ab8 + 28:c011b63c 1 0.00 1:7abc + 28:c011b656 1 0.00 1:7ad6 + 28:c011b92c 7 0.00 1:7dac + 28:c011b93e 1 0.00 1:7dbe + 28:c011b999 2 0.00 1:7e19 + 28:c011b9c1 1 0.00 1:7e41 + 28:c011bcfc 3 0.00 1:817c + 28:c011bd02 6 0.00 1:8182 + 28:c011bd45 1 0.00 1:81c5 + 28:c011bd54 1 0.00 1:81d4 + 28:c011bd9c 1 0.00 1:821c + 28:c011bdd3 1 0.00 1:8253 + 28:c011c096 1 0.00 1:8516 + 28:c011c99e 1 0.00 1:8e1e + 28:c011cc23 1 0.00 1:90a3 + 28:c011cccc 3 0.00 1:914c + 28:c011ccd5 2 0.00 1:9155 + 28:c011ccdf 2 0.00 1:915f + 28:c011ccf1 1 0.00 1:9171 + 28:c011ccfa 1 0.00 1:917a + 28:c011cd28 1 0.00 1:91a8 + 28:c011cd54 5 0.00 1:91d4 + 28:c011cd60 1 0.00 1:91e0 + 28:c011cd69 1 0.00 1:91e9 + 28:c011cd6b 1 0.00 1:91eb + 28:c011cdc0 1 0.00 1:9240 + 28:c011cdc9 1 0.00 1:9249 + 28:c011cdd0 1 0.00 1:9250 + 28:c011ce04 1 0.00 1:9284 + 28:c011ce08 1 0.00 1:9288 + 28:c011ce0a 1 0.00 1:928a + 28:c011ce0f 1 0.00 1:928f + 28:c011d36b 5 0.00 1:97eb + 28:c011d386 3 0.00 1:9806 + 28:c011d38c 1 0.00 1:980c + 28:c011d3a4 1 0.00 1:9824 + 28:c011d41d 1 0.00 1:989d + +Module Name VCACHE + + CS:EIP Samples (%) Map Offset Symbol + 28:c011e0a3 1 0.00 1:113 + 28:c011e115 1 0.00 1:185 + 28:c011e1db 1 0.00 1:24b + 28:c011e30e 1 0.00 1:37e + 28:c011e344 1 0.00 1:3b4 + 28:c011e375 1 0.00 1:3e5 + 28:c011e37a 1 0.00 1:3ea + 28:c011e398 3 0.00 1:408 + 28:c011e39b 12 0.01 1:40b + 28:c011e3a0 1 0.00 1:410 + 28:c011e5b0 2 0.00 1:620 + 28:c011e638 1 0.00 1:6a8 + 28:c011e670 1 0.00 1:6e0 + 28:c011e674 1 0.00 1:6e4 + 28:c011e678 3 0.00 1:6e8 + 28:c011e67c 1 0.00 1:6ec + 28:c011f630 1 0.00 1:16a0 + +Module Name VCDFSD + + CS:EIP Samples (%) Map Offset Symbol + 28:c011f6fd 4 0.00 1:2d + 28:c011f702 2 0.00 1:32 + 28:c011f703 1 0.00 1:33 + 28:c011f70a 568 0.30 1:3a + 28:c011f70f 984 0.51 1:3f + +Module Name VXDLDR + + CS:EIP Samples (%) Map Offset Symbol + 28:c011f878 1 0.00 1:c + +Module Name VPICD + + CS:EIP Samples (%) Map Offset Symbol + 28:c0120724 2 0.00 1:6cc + 28:c012078c 1 0.00 1:734 + 28:c0120942 1 0.00 1:8ea + 28:c0120cc8 1 0.00 1:c70 + 28:c0120dbe 1 0.00 1:d66 + 28:c01217b8 1 0.00 1:1760 + 28:c01218db 1 0.00 1:1883 + 28:c0121906 5 0.00 1:18ae + +Module Name VTD + + CS:EIP Samples (%) Map Offset Symbol + 28:c0122bac 13 0.01 1:c + 28:c0122bb9 31 0.02 1:19 + 28:c0122c8e 4 0.00 1:ee + 28:c0122cb7 2 0.00 1:117 + 28:c012300d 1 0.00 1:46d + +Module Name VDMAD + + CS:EIP Samples (%) Map Offset Symbol + 28:c0126168 1 0.00 6:7cc + +Module Name V86MMGR + + CS:EIP Samples (%) Map Offset Symbol + 28:c0126481 2 0.00 1:f9 + 28:c012648d 2 0.00 1:105 + 28:c0126490 2 0.00 1:108 + 28:c0126491 1 0.00 1:109 + 28:c01264a1 3 0.00 1:119 + 28:c01264a8 1 0.00 1:120 + 28:c01269e0 1 0.00 1:658 + +Module Name DOSMGR + + CS:EIP Samples (%) Map Offset Symbol + 28:c0286b72 1 0.00 5:ce + 28:c0286b98 238 0.12 5:f4 + 28:c0286b9b 25 0.01 5:f7 + 28:c0286b9e 8 0.00 5:fa + 28:c0286ba0 47 0.02 5:fc + 28:c0286ba6 2 0.00 5:102 + 28:c0286baa 23 0.01 5:106 + 28:c0286bb0 11 0.01 5:10c + 28:c0286bb1 32 0.02 5:10d + 28:c0286f56 1 0.00 5:4b2 + 28:c02201c6 1 0.00 a:1c6 + 28:c02201cd 1 0.00 a:1cd + 28:c02201ef 2 0.00 a:1ef + 28:c022020f 1 0.00 a:20f + 28:c0232878 2 0.00 c:48 + 28:c0232cf2 1 0.00 c:4c2 + +Module Name VMPOLL + + CS:EIP Samples (%) Map Offset Symbol + 28:c012921c 93 0.05 1:c8 + 28:c012921f 2 0.00 1:cb + 28:c0129227 2 0.00 1:d3 + 28:c012922d 75 0.04 1:d9 + 28:c0129233 35 0.02 1:df + 28:c0129239 68 0.04 1:e5 + 28:c012923f 158 0.08 1:eb + 28:c0129244 41 0.02 1:f0 + 28:c012924a 1446 0.75 1:f6 + 28:c0129253 92 0.05 1:ff + 28:c012925b 33 0.02 1:107 + 28:c0129263 37 0.02 1:10f + 28:c02202fc 8 0.00 5:54 + 28:c0220302 4 0.00 5:5a + 28:c0220308 1 0.00 5:60 + 28:c022030c 1 0.00 5:64 + 28:c0220310 1 0.00 5:68 + 28:c0220316 3 0.00 5:6e + 28:c0220336 5 0.00 5:8e + +Module Name SHELL + + CS:EIP Samples (%) Map Offset Symbol + 28:c01298b0 562 0.29 1:47c + 28:c01298b6 475 0.25 1:482 + 28:c01298bc 43 0.02 1:488 + 28:c01298c0 39 0.02 1:48c + 28:c01298c6 67 0.03 1:492 + 28:c01298ca 38 0.02 1:496 + 28:c01298d0 73 0.04 1:49c + 28:c01298d1 37 0.02 1:49d + 28:c022047c 3 0.00 a:12c + 28:c022049f 3 0.00 a:14f + +Module Name VMCPD + + CS:EIP Samples (%) Map Offset Symbol + 28:c012a616 1 0.00 1:282 + 28:c012a62b 2 0.00 1:297 + 28:c012a631 1 0.00 1:29d + 28:c012a638 1 0.00 1:2a4 + 28:c012a6db 7 0.00 1:347 + 28:c012a6dd 3 0.00 1:349 + 28:c012a727 2 0.00 1:393 + 28:c012ab49 1 0.00 1:7b5 + +Module Name VTDAPI + + CS:EIP Samples (%) Map Offset Symbol + 28:c012ac61 1 0.00 1:49 + 28:c012acb4 1 0.00 1:9c + 28:c012ae22 1 0.00 1:20a + +Module Name NDIS + + CS:EIP Samples (%) Map Offset Symbol + 28:c0131176 1 0.00 1:46e + 28:c0131482 1 0.00 1:77a + 28:c01316cf 1 0.00 1:9c7 + 28:c0131a84 5 0.00 1:d7c + 28:c0131c93 1 0.00 1:f8b + +Module Name VSHINIT + + CS:EIP Samples (%) Map Offset Symbol + 28:c0139d80 1 0.00 1:1c0 + 28:c0139d8d 82 0.04 1:1cd + 28:c0139d9c 170 0.09 1:1dc + 28:c0139d9f 12 0.01 1:1df + 28:c0139da5 24 0.01 1:1e5 + 28:c013a196 1 0.00 1:5d6 + 28:c013a1c5 3 0.00 1:605 + 28:c013a1e0 1 0.00 1:620 + 28:c013a1ea 1 0.00 1:62a + 28:c013a21c 2 0.00 1:65c + 28:c013a23b 1 0.00 1:67b + 28:c013a23d 5 0.00 1:67d + 28:c013a24a 3 0.00 1:68a + 28:c013a26e 1 0.00 1:6ae + 28:c013a272 1 0.00 1:6b2 + 28:c013a285 16 0.01 1:6c5 + 28:c013a2ae 1 0.00 1:6ee + 28:c013a2cd 1 0.00 1:70d + 28:c013a2d5 1 0.00 1:715 + 28:c013a2de 1 0.00 1:71e + 28:c013a315 4 0.00 1:755 + 28:c013a31c 3 0.00 1:75c + 28:c013a321 2 0.00 1:761 + 28:c013a328 1 0.00 1:768 + 28:c013a330 3 0.00 1:770 + 28:c013a340 1 0.00 1:780 + 28:c013a347 3 0.00 1:787 + 28:c013a37a 4 0.00 1:7ba + 28:c013a40f 1 0.00 1:84f + 28:c013a564 9 0.00 1:9a4 + 28:c013a565 1 0.00 1:9a5 + 28:c013a56d 1 0.00 1:9ad + 28:c013a577 2 0.00 1:9b7 + 28:c013a581 1 0.00 1:9c1 + 28:c013a5aa 3 0.00 1:9ea + 28:c013a5d0 1 0.00 1:a10 + 28:c013a5e5 5 0.00 1:a25 + 28:c013a5e8 1 0.00 1:a28 + 28:c013a5f6 1 0.00 1:a36 + 28:c013a5f9 1 0.00 1:a39 + 28:c013a5fb 2 0.00 1:a3b + 28:c013a600 1 0.00 1:a40 + 28:c013a631 1 0.00 1:a71 + 28:c013a644 3 0.00 1:a84 + 28:c013a64b 3 0.00 1:a8b + 28:c013a67b 1 0.00 1:abb + 28:c013a68f 2 0.00 1:acf + 28:c013a8b0 1 0.00 1:cf0 + 28:c013a8cf 4 0.00 1:d0f + 28:c013a8d6 5 0.00 1:d16 + 28:c013a8eb 1 0.00 1:d2b + 28:c013a8f8 2 0.00 1:d38 + 28:c013a907 1 0.00 1:d47 + 28:c013a90c 1 0.00 1:d4c + 28:c013a91b 4 0.00 1:d5b + 28:c013a91e 1 0.00 1:d5e + 28:c013a927 1 0.00 1:d67 + 28:c013a936 4 0.00 1:d76 + 28:c013a944 1 0.00 1:d84 + 28:c013a94a 1 0.00 1:d8a + 28:c013a94d 1 0.00 1:d8d + 28:c013a9d2 4 0.00 1:e12 + 28:c013aa17 3 0.00 1:e57 + 28:c013aa1a 1 0.00 1:e5a + 28:c013aa2c 3 0.00 1:e6c + 28:c013aa47 1 0.00 1:e87 + 28:c013abbd 4 0.00 1:ffd + 28:c013abc1 1 0.00 1:1001 + 28:c013abc2 1 0.00 1:1002 + 28:c013af2a 1 0.00 1:136a + 28:c013af71 1 0.00 1:13b1 + 28:c013af75 1 0.00 1:13b5 + 28:c013af79 1 0.00 1:13b9 + 28:c013b213 3 0.00 1:1653 + 28:c013b219 2 0.00 1:1659 + 28:c013b22b 5 0.00 1:166b + 28:c013b430 5 0.00 1:1870 + 28:c013e840 2 0.00 1:4c80 + +Module Name VTBS + + CS:EIP Samples (%) Map Offset Symbol + 28:c0140114 2 0.00 1:14bc + 28:c01406b8 5 0.00 1:1a60 + 28:c01406c3 5 0.00 1:1a6b + 28:c01406cb 1 0.00 1:1a73 + 28:c0140dd6 1 0.00 1:217e + 28:c0140e03 1 0.00 1:21ab + 28:c0140ea0 1 0.00 1:2248 + 28:c0140f9c 1 0.00 1:2344 + 28:c014116d 3 0.00 1:2515 + 28:c0141174 1 0.00 1:251c + 28:c01411b1 4 0.00 1:2559 + 28:c01411b5 3 0.00 1:255d + 28:c014120d 2 0.00 1:25b5 + 28:c0141390 1 0.00 1:2738 + +Module Name WDEBUG + + CS:EIP Samples (%) Map Offset Symbol + 28:c0141ef2 1 0.00 1:1e + 28:c01424d8 1 0.00 1:604 + 28:c0142518 1423 0.74 1:644 + 28:c014251b 53 0.03 1:647 + 28:c014251e 48 0.02 1:64a + 28:c0142520 57 0.03 1:64c + +Module Name VDD + + CS:EIP Samples (%) Map Offset Symbol + 28:c0149330 1 0.00 1:35c + 28:c014934f 1993 1.04 1:37b + 28:c0149352 34 0.02 1:37e + 28:c0149357 119 0.06 1:383 + 28:c0149358 43 0.02 1:384 + 28:c022d25f 1 0.00 6:28f + 28:c022e529 1 0.00 6:1559 + 28:c022e630 1 0.00 6:1660 + 28:c022e6da 1 0.00 6:170a + 28:c022e738 1 0.00 6:1768 + 28:c022ead0 1 0.00 6:1b00 + 28:c022eb47 1 0.00 6:1b77 + 28:c022eb49 1 0.00 6:1b79 + 28:c022eb60 1 0.00 6:1b90 + 28:c025369e 44 0.02 b:3026 + +Module Name VMOUSE + + CS:EIP Samples (%) Map Offset Symbol + 28:c014ab90 1 0.00 1:8b4 + 28:c02a6adc 1 0.00 3:9ec + 28:c02a6af5 1 0.00 3:a05 + 28:c02a6b5a 2 0.00 3:a6a + 28:c02a6b92 1 0.00 3:aa2 + 28:c02a6c7c 1 0.00 3:b8c + 28:c02a6ca3 1 0.00 3:bb3 + +Module Name MSMINI + + CS:EIP Samples (%) Map Offset Symbol + 28:c014abc9 1 0.00 1:39 + 28:c014abde 1 0.00 1:4e + 28:c014ac9e 1 0.00 1:10e + +Module Name MSDelta + + CS:EIP Samples (%) Map Offset Symbol + 28:c014b38c 1 0.00 1:290 + +Module Name ENABLE + + CS:EIP Samples (%) Map Offset Symbol + 28:c0220662 2 0.00 7:1be + +Module Name KERNEL + + CS:EIP Samples (%) Map Offset Symbol + 117:c0 1 0.00 1:c0 + 117:c6 1 0.00 1:c6 + 117:f1 1 0.00 1:f1 + 117:10d 4 0.00 1:10d + 117:119 1 0.00 1:119 + 117:160 1 0.00 1:160 + 117:161 1 0.00 1:161 + 117:4ae 1 0.00 1:4ae + 117:4ba 2 0.00 1:4ba + 117:67b 1 0.00 1:67b + 117:686 1 0.00 1:686 + 117:94b 1 0.00 1:94b + 117:9be 1 0.00 1:9be + 117:177a 1 0.00 1:177a + 117:17de 25 0.01 1:17de + 117:17e1 16 0.01 1:17e1 + 117:17e2 1 0.00 1:17e2 + 117:183e 2 0.00 1:183e + 117:1862 1 0.00 1:1862 + 117:1867 4 0.00 1:1867 + 117:1869 3 0.00 1:1869 + 117:186b 9 0.00 1:186b + 117:1874 19 0.01 1:1874 + 117:1894 1 0.00 1:1894 + 117:189e 1 0.00 1:189e + 117:18a6 1 0.00 1:18a6 + 117:18d1 1 0.00 1:18d1 + 117:193c 1 0.00 1:193c + 117:1a72 1 0.00 1:1a72 + 117:1a77 1 0.00 1:1a77 + 117:1b09 1 0.00 1:1b09 + 117:1b0c 1 0.00 1:1b0c + 117:1bfd 1 0.00 1:1bfd + 117:1c08 1 0.00 1:1c08 + 117:1c0e 2 0.00 1:1c0e + 117:1c10 1 0.00 1:1c10 + 117:1c71 1 0.00 1:1c71 + 117:1c7f 1 0.00 1:1c7f + 117:1c86 1 0.00 1:1c86 + 117:1cb7 1 0.00 1:1cb7 + 117:1e58 1 0.00 1:1e58 + 117:1ee6 1 0.00 1:1ee6 + 117:2350 1 0.00 1:2350 + 117:2426 1 0.00 1:2426 + 117:24db 1 0.00 1:24db + 117:24fd 1 0.00 1:24fd + 117:2527 1 0.00 1:2527 + 117:252e 11 0.01 1:252e + 117:258a 1 0.00 1:258a + 117:262a 1 0.00 1:262a + 117:2692 2 0.00 1:2692 + 117:2694 1 0.00 1:2694 + 117:27ab 1 0.00 1:27ab + 117:27b2 1 0.00 1:27b2 + 117:27c2 1 0.00 1:27c2 + 117:27d1 3 0.00 1:27d1 + 117:27ff 2 0.00 1:27ff + 117:2815 1 0.00 1:2815 + 117:3060 2 0.00 1:3060 + 117:31d2 1 0.00 1:31d2 + 117:340e 1 0.00 1:340e + 117:3415 1 0.00 1:3415 + 117:3417 2 0.00 1:3417 + 117:3419 2 0.00 1:3419 + 117:3434 2 0.00 1:3434 + 117:3439 6 0.00 1:3439 + 117:343e 1 0.00 1:343e + 117:3443 1 0.00 1:3443 + 117:3449 2 0.00 1:3449 + 117:345c 1 0.00 1:345c + 117:3487 1 0.00 1:3487 + 117:348f 1 0.00 1:348f + 117:349a 4 0.00 1:349a + 117:34a9 2 0.00 1:34a9 + 117:34ad 4 0.00 1:34ad + 117:34b8 2 0.00 1:34b8 + 117:34ba 1 0.00 1:34ba + 117:34fd 2 0.00 1:34fd + 117:34fe 1 0.00 1:34fe + 117:3511 1 0.00 1:3511 + 117:3534 1 0.00 1:3534 + 117:3538 1 0.00 1:3538 + 117:3562 4 0.00 1:3562 + 117:3567 5 0.00 1:3567 + 117:356d 1 0.00 1:356d + 117:3573 1 0.00 1:3573 + 117:3575 1 0.00 1:3575 + 117:357a 1 0.00 1:357a + 117:357d 1 0.00 1:357d + 117:3581 1 0.00 1:3581 + 117:3589 2 0.00 1:3589 + 117:3591 1 0.00 1:3591 + 117:3594 8 0.00 1:3594 + 117:3595 4 0.00 1:3595 + 117:3599 4 0.00 1:3599 + 117:359b 1 0.00 1:359b + 117:35a1 1 0.00 1:35a1 + 117:35aa 5 0.00 1:35aa + 117:35b0 1 0.00 1:35b0 + 117:35bc 1 0.00 1:35bc + 117:35c1 1 0.00 1:35c1 + 117:35c4 1 0.00 1:35c4 + 117:35c6 1 0.00 1:35c6 + 117:35c8 1 0.00 1:35c8 + 117:37aa 1 0.00 1:37aa + 117:386e 1 0.00 1:386e + 117:38f6 1 0.00 1:38f6 + 117:3908 1 0.00 1:3908 + 117:3910 4 0.00 1:3910 + 117:3918 1 0.00 1:3918 + 117:3932 1 0.00 1:3932 + 117:393c 2 0.00 1:393c + 117:394e 1 0.00 1:394e + 117:3962 1 0.00 1:3962 + 117:3990 2 0.00 1:3990 + 117:39c2 1 0.00 1:39c2 + 117:39d2 1 0.00 1:39d2 + 117:39eb 1 0.00 1:39eb + 117:39ed 1 0.00 1:39ed + 117:3a06 4 0.00 1:3a06 + 117:3a0e 1 0.00 1:3a0e + 117:3a15 2 0.00 1:3a15 + 117:3a24 1 0.00 1:3a24 + 117:3a2d 2 0.00 1:3a2d + 117:3a33 1 0.00 1:3a33 + 117:3a3d 1 0.00 1:3a3d + 117:3a90 2 0.00 1:3a90 + 117:3b3f 1 0.00 1:3b3f + 117:3ba6 1 0.00 1:3ba6 + 117:3bb7 1 0.00 1:3bb7 + 117:3c58 2 0.00 1:3c58 + 117:3c67 1 0.00 1:3c67 + 117:3c7a 1 0.00 1:3c7a + 117:3c96 1 0.00 1:3c96 + 117:3cbc 1 0.00 1:3cbc + 117:3cf1 3 0.00 1:3cf1 + 117:4120 1 0.00 1:4120 + 117:4137 1 0.00 1:4137 + 117:4186 1 0.00 1:4186 + 117:424c 2 0.00 1:424c + 117:4254 1 0.00 1:4254 + 117:4267 1 0.00 1:4267 + 117:42cb 1 0.00 1:42cb + 117:42d1 1 0.00 1:42d1 + 117:42e8 2 0.00 1:42e8 + 117:42ee 1 0.00 1:42ee + 117:42f2 2 0.00 1:42f2 + 117:430f 1 0.00 1:430f + 117:4333 1 0.00 1:4333 + 117:43b2 2 0.00 1:43b2 + 117:4434 4 0.00 1:4434 + 117:4437 4 0.00 1:4437 + 117:4582 2 0.00 1:4582 + 117:4584 2 0.00 1:4584 + 117:4590 1 0.00 1:4590 + 117:459c 1 0.00 1:459c + 117:45f1 3 0.00 1:45f1 + 117:45f6 1 0.00 1:45f6 + 117:45f9 1 0.00 1:45f9 + 117:47de 1 0.00 1:47de + 117:4851 2 0.00 1:4851 + 117:4872 2 0.00 1:4872 + 117:499e 2 0.00 1:499e + 117:49a2 1 0.00 1:49a2 + 117:49fe 1 0.00 1:49fe + 117:4a1e 1 0.00 1:4a1e + 117:4a2e 1 0.00 1:4a2e + 117:4a5a 2 0.00 1:4a5a + 117:4afb 2 0.00 1:4afb + 117:4c0d 1 0.00 1:4c0d + 117:4c78 1 0.00 1:4c78 + 117:4c7d 1 0.00 1:4c7d + 117:5133 1 0.00 1:5133 + 117:5135 1 0.00 1:5135 + 117:5138 1 0.00 1:5138 + 117:513e 1 0.00 1:513e + 117:5142 1 0.00 1:5142 + 117:5159 1 0.00 1:5159 + 117:5178 1 0.00 1:5178 + 117:5188 2 0.00 1:5188 + 117:5191 1 0.00 1:5191 + 117:51a2 1 0.00 1:51a2 + 117:52a4 1 0.00 1:52a4 + 117:53b7 1 0.00 1:53b7 + 117:5450 1 0.00 1:5450 + 117:550e 1 0.00 1:550e + 117:5594 5 0.00 1:5594 + 117:5597 1 0.00 1:5597 + 117:559f 1 0.00 1:559f + 117:55a4 3 0.00 1:55a4 + 117:55ae 4 0.00 1:55ae + 117:55b5 2 0.00 1:55b5 + 117:55bb 1 0.00 1:55bb + 117:55bf 7 0.00 1:55bf + 117:55c1 1 0.00 1:55c1 + 117:55c2 1 0.00 1:55c2 + 117:55d7 3 0.00 1:55d7 + 117:55f4 3 0.00 1:55f4 + 117:5793 4 0.00 1:5793 + 117:57a0 5 0.00 1:57a0 + 117:57b5 1 0.00 1:57b5 + 117:57d4 1 0.00 1:57d4 + 117:57e8 1 0.00 1:57e8 + 117:5800 1 0.00 1:5800 + 117:5809 3 0.00 1:5809 + 117:5828 11 0.01 1:5828 + 117:5838 1 0.00 1:5838 + 117:583b 1 0.00 1:583b + 117:5840 2 0.00 1:5840 + 117:5852 1 0.00 1:5852 + 117:5857 1 0.00 1:5857 + 117:5860 1 0.00 1:5860 + 117:5862 1 0.00 1:5862 + 117:588f 1 0.00 1:588f + 117:59b5 2 0.00 1:59b5 + 117:5a1e 1 0.00 1:5a1e + 117:5a47 5 0.00 1:5a47 + 117:5a4c 1 0.00 1:5a4c + 117:5a50 8 0.00 1:5a50 + 117:5a56 1 0.00 1:5a56 + 117:5a5c 4 0.00 1:5a5c + 117:5a69 3 0.00 1:5a69 + 117:5a6e 1 0.00 1:5a6e + 117:5a76 1 0.00 1:5a76 + 117:5aa9 3 0.00 1:5aa9 + 117:5aaf 1 0.00 1:5aaf + 117:5ab2 5 0.00 1:5ab2 + 117:5ab6 3 0.00 1:5ab6 + 117:5aba 7 0.00 1:5aba + 117:5ac1 3 0.00 1:5ac1 + 117:5ac2 11 0.01 1:5ac2 + 117:5b25 39 0.02 1:5b25 + 117:5b2a 15 0.01 1:5b2a + 117:5b32 9 0.00 1:5b32 + 117:5b37 9 0.00 1:5b37 + 117:5b3c 7 0.00 1:5b3c + 117:5b41 3 0.00 1:5b41 + 117:5b43 5 0.00 1:5b43 + 117:5b45 5 0.00 1:5b45 + 117:5dd5 4 0.00 1:5dd5 + 117:5dde 9 0.00 1:5dde + 117:5dec 15 0.01 1:5dec + 117:5dee 46 0.02 1:5dee + 117:5df0 105 0.05 1:5df0 + 117:5df3 13 0.01 1:5df3 + 117:5df7 3 0.00 1:5df7 + 117:5e00 4 0.00 1:5e00 + 117:5e05 1 0.00 1:5e05 + 117:5e0f 1 0.00 1:5e0f + 117:5e16 1 0.00 1:5e16 + 117:5e1c 2 0.00 1:5e1c + 117:5e2d 2 0.00 1:5e2d + 117:5e36 5 0.00 1:5e36 + 117:5e41 4 0.00 1:5e41 + 117:5e4c 35 0.02 1:5e4c + 117:5e67 5 0.00 1:5e67 + 117:5e7e 6 0.00 1:5e7e + 117:5e89 2 0.00 1:5e89 + 117:5e8d 8 0.00 1:5e8d + 117:5eaf 11 0.01 1:5eaf + 117:5eb1 126 0.07 1:5eb1 + 117:5eb4 25 0.01 1:5eb4 + 117:5eb9 60 0.03 1:5eb9 + 117:5ebd 2 0.00 1:5ebd + 117:5ec6 8 0.00 1:5ec6 + 117:5ed6 8 0.00 1:5ed6 + 117:5edf 1 0.00 1:5edf + 117:5ef3 1 0.00 1:5ef3 + 117:5f05 5 0.00 1:5f05 + 117:5f1a 5 0.00 1:5f1a + 117:5f1f 1 0.00 1:5f1f + 117:5f22 1 0.00 1:5f22 + 117:5f26 6 0.00 1:5f26 + 117:5f2a 1 0.00 1:5f2a + 117:5f2f 6 0.00 1:5f2f + 117:5f80 3 0.00 1:5f80 + 117:5f81 1 0.00 1:5f81 + 117:5f83 2 0.00 1:5f83 + 117:5f86 2 0.00 1:5f86 + 117:5fd6 5 0.00 1:5fd6 + 117:5fdb 1 0.00 1:5fdb + 117:5fdd 1 0.00 1:5fdd + 117:5fe5 2 0.00 1:5fe5 + 117:6009 2 0.00 1:6009 + 117:600c 7 0.00 1:600c + 117:6021 4 0.00 1:6021 + 117:6036 3 0.00 1:6036 + 117:60ea 1 0.00 1:60ea + 117:60f3 1 0.00 1:60f3 + 117:6154 2 0.00 1:6154 + 117:615a 7 0.00 1:615a + 117:6168 11 0.01 1:6168 + 117:618b 39 0.02 1:618b + 117:618d 21 0.01 1:618d + 117:6190 4 0.00 1:6190 + 117:6194 15 0.01 1:6194 + 117:6196 72 0.04 1:6196 + 117:619d 2 0.00 1:619d + 117:61a0 9 0.00 1:61a0 + 117:61a8 1 0.00 1:61a8 + 117:61aa 2 0.00 1:61aa + 117:61ad 2 0.00 1:61ad + 117:61b3 5 0.00 1:61b3 + 117:61bc 1 0.00 1:61bc + 117:61bd 5 0.00 1:61bd + 117:65a1 1 0.00 1:65a1 + 117:731c 1 0.00 1:731c + 117:7321 1 0.00 1:7321 + 117:73dd 1 0.00 1:73dd + 117:73ee 1 0.00 1:73ee + 117:7401 1 0.00 1:7401 + 117:755a 1 0.00 1:755a + 117:7836 1 0.00 1:7836 + 117:784b 1 0.00 1:784b + 117:785f 1 0.00 1:785f + 117:7899 1 0.00 1:7899 + 117:794c 6 0.00 1:794c + 117:795a 3 0.00 1:795a + 117:7965 2 0.00 1:7965 + 117:79c7 12 0.01 1:79c7 + 117:79c8 1 0.00 1:79c8 + 117:79d0 1 0.00 1:79d0 + 117:79d3 3 0.00 1:79d3 + 117:79e6 1 0.00 1:79e6 + 117:79eb 11 0.01 1:79eb + 117:79ed 1 0.00 1:79ed + 117:79f6 1 0.00 1:79f6 + 117:79fc 2 0.00 1:79fc + 117:7a01 10 0.01 1:7a01 + 117:7a06 5 0.00 1:7a06 + 117:7a2f 1 0.00 1:7a2f + 117:7a31 2 0.00 1:7a31 + 117:7d31 1 0.00 1:7d31 + 117:7d49 2 0.00 1:7d49 + 117:7d60 1 0.00 1:7d60 + 117:7d68 1 0.00 1:7d68 + 117:7e11 1 0.00 1:7e11 + 117:7e67 1 0.00 1:7e67 + 117:7e7c 4 0.00 1:7e7c + 117:7e80 4 0.00 1:7e80 + 117:7e84 1 0.00 1:7e84 + 117:7e8f 1 0.00 1:7e8f + 117:7e93 2 0.00 1:7e93 + 117:7eb4 1 0.00 1:7eb4 + 117:7ebb 2 0.00 1:7ebb + 117:7ec4 5 0.00 1:7ec4 + 117:7ec9 1 0.00 1:7ec9 + 117:7ed7 2 0.00 1:7ed7 + 117:7edd 1 0.00 1:7edd + 117:7ee2 1 0.00 1:7ee2 + 117:7ee6 1 0.00 1:7ee6 + 117:7efa 1 0.00 1:7efa + 117:7efc 2 0.00 1:7efc + 117:7eff 1 0.00 1:7eff + 117:7f04 1 0.00 1:7f04 + 117:7f13 7 0.00 1:7f13 + 117:7f4b 1 0.00 1:7f4b + 117:7f60 1 0.00 1:7f60 + 117:7f76 1 0.00 1:7f76 + 117:7f86 2 0.00 1:7f86 + 117:7f95 1 0.00 1:7f95 + 117:7f97 1 0.00 1:7f97 + 117:7f9d 1 0.00 1:7f9d + 117:7f9f 2 0.00 1:7f9f + 117:7fa6 2 0.00 1:7fa6 + 117:7fad 2 0.00 1:7fad + 117:7fb4 3 0.00 1:7fb4 + 117:7fb7 3 0.00 1:7fb7 + 117:7fbd 29 0.02 1:7fbd + 117:7fcd 5 0.00 1:7fcd + 117:7fce 84 0.04 1:7fce + 117:7fd3 26 0.01 1:7fd3 + 117:7fd6 3 0.00 1:7fd6 + 117:849a 3 0.00 1:849a + 117:84a0 2 0.00 1:84a0 + 117:84d1 1 0.00 1:84d1 + 117:8587 1 0.00 1:8587 + 117:858a 1 0.00 1:858a + 117:85e8 2 0.00 1:85e8 + 117:85ed 1 0.00 1:85ed + 117:85fe 1 0.00 1:85fe + 117:87a6 1 0.00 1:87a6 + 117:87cb 1 0.00 1:87cb + 117:87d1 6 0.00 1:87d1 + 117:87d7 4 0.00 1:87d7 + 117:8818 1 0.00 1:8818 + 117:8820 5 0.00 1:8820 + 117:8824 1 0.00 1:8824 + 117:93ea 2 0.00 1:93ea + 117:940e 16 0.01 1:940e + 117:9414 1 0.00 1:9414 + 117:9429 1 0.00 1:9429 + 117:95cf 1 0.00 1:95cf + 117:9618 1 0.00 1:9618 + 117:9aab 8 0.00 1:9aab + 117:9dbb 2 0.00 1:9dbb + 117:9e0f 2 0.00 1:9e0f + 117:9e92 5 0.00 1:9e92 + 117:a505 1 0.00 1:a505 + 117:a522 1 0.00 1:a522 + 117:a95a 1 0.00 1:a95a + 117:a961 1 0.00 1:a961 + 117:a967 1 0.00 1:a967 + 117:a96f 1 0.00 1:a96f + 117:a97f 1 0.00 1:a97f + 117:a982 1 0.00 1:a982 + 117:a9f2 2 0.00 1:a9f2 + 117:aa01 1 0.00 1:aa01 + 117:aa03 1 0.00 1:aa03 + 117:aa06 1 0.00 1:aa06 + 117:aa09 1 0.00 1:aa09 + 117:aa13 1 0.00 1:aa13 + 117:aa17 1 0.00 1:aa17 + 117:aa1b 1 0.00 1:aa1b + 117:aa61 2 0.00 1:aa61 + 117:aa65 1 0.00 1:aa65 + 117:aa68 6 0.00 1:aa68 + 117:aa6b 2 0.00 1:aa6b + 117:aa77 3 0.00 1:aa77 + 117:aa7a 2 0.00 1:aa7a + 117:aa85 5 0.00 1:aa85 + 117:aad5 1 0.00 1:aad5 + 117:aad7 1 0.00 1:aad7 + 117:aad8 11 0.01 1:aad8 + 117:aadc 9 0.00 1:aadc + 117:aae0 9 0.00 1:aae0 + 117:aae1 12 0.01 1:aae1 + 117:aae6 22 0.01 1:aae6 + 117:aaeb 9 0.00 1:aaeb + 117:aaec 28 0.01 1:aaec + 117:aaee 3 0.00 1:aaee + 117:aafa 6 0.00 1:aafa + 117:aafc 11 0.01 1:aafc + 117:ac0f 1 0.00 1:ac0f + 117:ac15 1 0.00 1:ac15 + 117:ac1f 3 0.00 1:ac1f + 117:ac22 1 0.00 1:ac22 + 117:ae98 1 0.00 1:ae98 + 117:af0a 3 0.00 1:af0a + 117:af10 1 0.00 1:af10 + 117:af12 1 0.00 1:af12 + 117:af39 2 0.00 1:af39 + 117:af3d 1 0.00 1:af3d + 117:af4a 4 0.00 1:af4a + 117:af54 2 0.00 1:af54 + 117:af69 1 0.00 1:af69 + 117:b10a 1 0.00 1:b10a + 11f:136 2 0.00 2:136 + 11f:142 1 0.00 2:142 + 11f:152 2 0.00 2:152 + 11f:158 1 0.00 2:158 + 11f:3f1 1 0.00 2:3f1 + 11f:412 1 0.00 2:412 + 11f:513 1 0.00 2:513 + 11f:86e 1 0.00 2:86e + 11f:960 1 0.00 2:960 + 11f:966 3 0.00 2:966 + 11f:96e 15 0.01 2:96e + 11f:970 3 0.00 2:970 + 11f:978 1 0.00 2:978 + 11f:cfe 1 0.00 2:cfe + 11f:273b 1 0.00 2:273b + 11f:2ac0 1 0.00 2:2ac0 + 11f:2ac9 1 0.00 2:2ac9 + 11f:2b12 4 0.00 2:2b12 + 11f:2b57 2 0.00 2:2b57 + 11f:2b76 1 0.00 2:2b76 + 11f:2b87 2 0.00 2:2b87 + 11f:2bbe 1 0.00 2:2bbe + 11f:2bfe 1 0.00 2:2bfe + 11f:2c0f 8 0.00 2:2c0f + 11f:2c17 2 0.00 2:2c17 + 11f:2c1b 1 0.00 2:2c1b + 11f:2ff4 1 0.00 2:2ff4 + 11f:2ff6 1 0.00 2:2ff6 + 11f:3003 2 0.00 2:3003 + 11f:3066 2 0.00 2:3066 + 11f:306d 1 0.00 2:306d + 11f:3070 1 0.00 2:3070 + 11f:3105 3 0.00 2:3105 + 11f:3288 1 0.00 2:3288 + 11f:32e3 1 0.00 2:32e3 + 11f:32ed 1 0.00 2:32ed + 11f:32ff 1 0.00 2:32ff + 11f:3317 1 0.00 2:3317 + 11f:37fd 3 0.00 2:37fd + 11f:42c4 1 0.00 2:42c4 + 11f:4d29 3 0.00 2:4d29 + 11f:4d30 1 0.00 2:4d30 + 11f:4d34 2 0.00 2:4d34 + 11f:4d37 2 0.00 2:4d37 + 11f:4d3b 1 0.00 2:4d3b + 11f:4d3d 1 0.00 2:4d3d + 11f:52a6 1 0.00 2:52a6 + 11f:52a8 1 0.00 2:52a8 + 11f:52b6 1 0.00 2:52b6 + 11f:52c6 1 0.00 2:52c6 + 11f:52dd 1 0.00 2:52dd + 11f:52e6 1 0.00 2:52e6 + 11f:5327 1 0.00 2:5327 + 11f:534e 1 0.00 2:534e + 11f:5358 1 0.00 2:5358 + 11f:5650 1 0.00 2:5650 + 11f:5667 1 0.00 2:5667 + 11f:566c 1 0.00 2:566c + 11f:5671 1 0.00 2:5671 + 11f:5678 1 0.00 2:5678 + 11f:570e 2 0.00 2:570e + 11f:5712 2 0.00 2:5712 + 11f:5714 1 0.00 2:5714 + 11f:572b 1 0.00 2:572b + 11f:574b 2 0.00 2:574b + 11f:575d 4 0.00 2:575d + 11f:5760 3 0.00 2:5760 + 11f:5763 9 0.00 2:5763 + 11f:576c 8 0.00 2:576c + 11f:5770 2 0.00 2:5770 + 11f:5774 3 0.00 2:5774 + 11f:577b 1 0.00 2:577b + 11f:577e 8 0.00 2:577e + 11f:5783 3 0.00 2:5783 + 11f:57d1 25 0.01 2:57d1 + 11f:57e0 1 0.00 2:57e0 + 11f:57e6 2 0.00 2:57e6 + 11f:5911 2 0.00 2:5911 + 11f:595a 2 0.00 2:595a + 11f:595e 1 0.00 2:595e + 11f:596d 1 0.00 2:596d + 11f:5a6c 4 0.00 2:5a6c + 11f:5aa2 1 0.00 2:5aa2 + 11f:5aa6 1 0.00 2:5aa6 + 11f:5aab 1 0.00 2:5aab + 11f:5ab1 3 0.00 2:5ab1 + 11f:5ab4 2 0.00 2:5ab4 + 11f:5ab8 1 0.00 2:5ab8 + 11f:5aba 1 0.00 2:5aba + 11f:5abe 2 0.00 2:5abe + 11f:5adb 2 0.00 2:5adb + 11f:5ae8 1 0.00 2:5ae8 + 11f:5af3 2 0.00 2:5af3 + 11f:5afe 1 0.00 2:5afe + 11f:5b01 1 0.00 2:5b01 + 11f:5b06 1 0.00 2:5b06 + 11f:5b25 6 0.00 2:5b25 + 11f:5b33 6 0.00 2:5b33 + 11f:5b48 1 0.00 2:5b48 + 11f:5b4c 1 0.00 2:5b4c + 11f:5b75 1 0.00 2:5b75 + 11f:5b78 3 0.00 2:5b78 + 11f:5b7e 2 0.00 2:5b7e + 11f:5b8d 9 0.00 2:5b8d + 11f:5b90 4 0.00 2:5b90 + 11f:5b94 5 0.00 2:5b94 + 11f:5b96 1 0.00 2:5b96 + 11f:5b9a 4 0.00 2:5b9a + 11f:5ba0 1 0.00 2:5ba0 + 11f:5bad 1 0.00 2:5bad + 11f:5bc6 1 0.00 2:5bc6 + 11f:5bde 1 0.00 2:5bde + 11f:5be2 14 0.01 2:5be2 + 11f:5bed 1 0.00 2:5bed + 11f:5bf0 1 0.00 2:5bf0 + 11f:5bf2 1 0.00 2:5bf2 + 11f:5c18 17 0.01 2:5c18 + 11f:5c1a 1 0.00 2:5c1a + 11f:5c4e 1 0.00 2:5c4e + 11f:5c72 5 0.00 2:5c72 + 11f:5c77 7 0.00 2:5c77 + 11f:5c7a 11 0.01 2:5c7a + 11f:5c7e 1 0.00 2:5c7e + 11f:5c85 5 0.00 2:5c85 + 11f:5c8a 20 0.01 2:5c8a + 11f:5c8c 5 0.00 2:5c8c + 11f:5c8e 8 0.00 2:5c8e + 11f:5c93 26 0.01 2:5c93 + 11f:5c95 1 0.00 2:5c95 + 11f:5cb5 1 0.00 2:5cb5 + 11f:5cb9 2 0.00 2:5cb9 + 11f:5d1a 6 0.00 2:5d1a + 11f:5d1d 1 0.00 2:5d1d + 11f:5e25 1 0.00 2:5e25 + 11f:5e96 1 0.00 2:5e96 + 11f:5eb9 1 0.00 2:5eb9 + 11f:5ee1 2 0.00 2:5ee1 + 11f:5ee6 1 0.00 2:5ee6 + 11f:5eee 1 0.00 2:5eee + 11f:5ef6 1 0.00 2:5ef6 + 11f:5efb 1 0.00 2:5efb + 11f:5f00 3 0.00 2:5f00 + 11f:5f34 2 0.00 2:5f34 + 11f:5f47 1 0.00 2:5f47 + 11f:5f74 1 0.00 2:5f74 + 11f:5f88 1 0.00 2:5f88 + 11f:5f96 2 0.00 2:5f96 + 11f:5f9e 1 0.00 2:5f9e + 11f:5fa7 1 0.00 2:5fa7 + 11f:5fb8 1 0.00 2:5fb8 + 11f:5fcd 1 0.00 2:5fcd + 11f:5fd0 2 0.00 2:5fd0 + 11f:5fd3 2 0.00 2:5fd3 + 11f:5fd6 3 0.00 2:5fd6 + 11f:5fdc 4 0.00 2:5fdc + 11f:5fdd 5 0.00 2:5fdd + 11f:5fe1 2 0.00 2:5fe1 + 11f:5fe5 3 0.00 2:5fe5 + 11f:5fe9 1 0.00 2:5fe9 + 11f:5fed 5 0.00 2:5fed + 11f:5ff1 1 0.00 2:5ff1 + 11f:5ff5 4 0.00 2:5ff5 + 11f:5ff8 1 0.00 2:5ff8 + 11f:5ffa 2 0.00 2:5ffa + 11f:6010 1 0.00 2:6010 + 11f:6032 2 0.00 2:6032 + 11f:6038 1 0.00 2:6038 + 11f:6046 2 0.00 2:6046 + 11f:6048 3 0.00 2:6048 + 11f:604d 3 0.00 2:604d + 11f:604e 1 0.00 2:604e + 11f:6074 1 0.00 2:6074 + 11f:609b 1 0.00 2:609b + 11f:60c8 1 0.00 2:60c8 + 11f:60d2 1 0.00 2:60d2 + 11f:6104 1 0.00 2:6104 + 11f:615c 2 0.00 2:615c + 11f:6162 1 0.00 2:6162 + 11f:6167 1 0.00 2:6167 + 11f:61d3 2 0.00 2:61d3 + 11f:6327 1 0.00 2:6327 + 11f:633c 1 0.00 2:633c + 11f:640e 3 0.00 2:640e + 11f:641a 1 0.00 2:641a + 11f:6afb 3 0.00 2:6afb + 11f:6b00 1 0.00 2:6b00 + 11f:6b1f 1 0.00 2:6b1f + 11f:6b58 1 0.00 2:6b58 + 11f:6b67 1 0.00 2:6b67 + 11f:6c29 2 0.00 2:6c29 + 11f:6c2e 1 0.00 2:6c2e + 11f:75e6 16 0.01 2:75e6 + 11f:75f0 1 0.00 2:75f0 + 11f:75f6 1 0.00 2:75f6 + 11f:75fb 4 0.00 2:75fb + 11f:7600 5 0.00 2:7600 + 11f:7603 8 0.00 2:7603 + 11f:760c 3 0.00 2:760c + 11f:7c5c 1 0.00 2:7c5c + 127:4 1 0.00 3:4 + 127:3b 1 0.00 3:3b + 127:47 1 0.00 3:47 + 127:50 1 0.00 3:50 + 127:285 1 0.00 3:285 + 127:70c 2 0.00 3:70c + 127:714 5 0.00 3:714 + 127:722 1 0.00 3:722 + 127:745 6 0.00 3:745 + 127:74c 6 0.00 3:74c + 127:74f 1 0.00 3:74f + 127:16b5 2 0.00 3:16b5 + 127:16ca 1 0.00 3:16ca + 127:1879 1 0.00 3:1879 + 127:1ada 1 0.00 3:1ada + 127:1aeb 2 0.00 3:1aeb + 127:1afa 2 0.00 3:1afa + 127:1b10 1 0.00 3:1b10 + 127:1b20 1 0.00 3:1b20 + 127:1b42 1 0.00 3:1b42 + 127:1b7f 1 0.00 3:1b7f + 127:1cf0 1 0.00 3:1cf0 + 127:1d21 1 0.00 3:1d21 + 127:1d37 1 0.00 3:1d37 + 127:1d95 1 0.00 3:1d95 + 127:1d9f 1 0.00 3:1d9f + 127:1db0 1 0.00 3:1db0 + 127:1dc4 1 0.00 3:1dc4 + 127:1e10 1 0.00 3:1e10 + 127:1e57 1 0.00 3:1e57 + 127:1e60 2 0.00 3:1e60 + 127:1e70 1 0.00 3:1e70 + 127:2155 1 0.00 3:2155 + 127:2350 1 0.00 3:2350 + 127:272e 5 0.00 3:272e + 127:272f 1 0.00 3:272f + 127:2737 1 0.00 3:2737 + 127:273c 1 0.00 3:273c + 127:273f 6 0.00 3:273f + 127:274f 1 0.00 3:274f + 127:3186 1 0.00 3:3186 + 127:31a0 1 0.00 3:31a0 + 127:3248 1 0.00 3:3248 + 127:3ada 1 0.00 3:3ada + 127:3cb7 1 0.00 3:3cb7 + 127:3f20 1 0.00 3:3f20 + 127:3f29 1 0.00 3:3f29 + 127:410a 3 0.00 3:410a + 127:4110 1 0.00 3:4110 + 127:413a 2 0.00 3:413a + 127:414c 2 0.00 3:414c + 127:4152 1 0.00 3:4152 + 127:41c0 12 0.01 3:41c0 + 127:41f2 3 0.00 3:41f2 + 127:41f7 6 0.00 3:41f7 + 127:4204 8 0.00 3:4204 + +Module Name SB16SND + + CS:EIP Samples (%) Map Offset Symbol +1aaf:1150 1 0.00 1:1150 +1aaf:1153 3 0.00 1:1153 +1aaf:1157 3 0.00 1:1157 +1aaf:115a 2 0.00 1:115a +1aaf:1164 1 0.00 1:1164 +1aaf:116c 1 0.00 1:116c +1aaf:116f 1 0.00 1:116f +1aaf:1173 2 0.00 1:1173 +1aaf:1176 4 0.00 1:1176 +1aaf:1188 2 0.00 1:1188 +1aaf:1c06 1 0.00 1:1c06 +1aaf:1cae 1 0.00 1:1cae +1aaf:23de 2 0.00 1:23de +1aaf:23e4 1 0.00 1:23e4 +1aaf:28a8 1 0.00 1:28a8 +1aaf:308b 1 0.00 1:308b +1aaf:3375 1 0.00 1:3375 +1aaf:3774 1 0.00 1:3774 +1a97:37 1 0.00 4:37 +1a97:e6 1 0.00 4:e6 +1a97:1d4 1 0.00 4:1d4 +1a97:1fb 1 0.00 4:1fb +1a9f:107c 6 0.00 3:107c +1a9f:1085 1 0.00 3:1085 +1a9f:108f 2 0.00 3:108f +1a9f:1096 2 0.00 3:1096 +1a9f:10a3 1 0.00 3:10a3 +1a9f:10aa 1 0.00 3:10aa +1a9f:10bc 1 0.00 3:10bc +1a9f:10c2 1 0.00 3:10c2 +1a9f:10c8 1 0.00 3:10c8 +1a9f:10cc 4 0.00 3:10cc +1a9f:10ee 3 0.00 3:10ee +1a9f:10f6 4 0.00 3:10f6 +1a9f:13ad 2 0.00 3:13ad +1a9f:13ec 4 0.00 3:13ec +1a9f:13fa 1 0.00 3:13fa +1a9f:13fe 1 0.00 3:13fe +1a9f:140b 1 0.00 3:140b +1a9f:1410 7 0.00 3:1410 +1a9f:141d 1 0.00 3:141d +1a9f:142a 1 0.00 3:142a +1a9f:142e 1 0.00 3:142e +1a9f:143a 3 0.00 3:143a +1a9f:1443 1 0.00 3:1443 +1a9f:1451 4 0.00 3:1451 +1a9f:1453 67 0.03 3:1453 +1a9f:1455 4 0.00 3:1455 +1a9f:145a 1 0.00 3:145a +1a9f:146e 4 0.00 3:146e +1a9f:1475 1 0.00 3:1475 +1a9f:1481 2 0.00 3:1481 +1a9f:1488 2 0.00 3:1488 +1a9f:148e 1 0.00 3:148e +1a9f:1792 1 0.00 3:1792 +1a9f:17d7 1 0.00 3:17d7 +1a9f:1e38 4 0.00 3:1e38 +1a9f:1e43 1 0.00 3:1e43 +1a9f:1e48 4 0.00 3:1e48 +1a9f:1e76 1 0.00 3:1e76 +1a9f:1e78 1 0.00 3:1e78 +1a9f:1e94 1 0.00 3:1e94 +1a9f:1e9c 5 0.00 3:1e9c +1a9f:1ec7 2 0.00 3:1ec7 +1a9f:1fc6 5 0.00 3:1fc6 +1aa7:460 1 0.00 2:460 + +Module Name MSACMMAP + + CS:EIP Samples (%) Map Offset Symbol +28d7:a2 1 0.00 3:a2 + +Module Name KEYBOARD + + CS:EIP Samples (%) Map Offset Symbol + 237:a4c 1 0.00 9:a4c + +Module Name MMSYSTEM + + CS:EIP Samples (%) Map Offset Symbol +1e97:6b 14 0.01 1:6b +1e97:8b 2 0.00 1:8b +1e97:2d6 6 0.00 1:2d6 +1e97:2dc 2 0.00 1:2dc +1e97:2ea 2 0.00 1:2ea +1e7f:1337 1 0.00 4:1337 +1e7f:1397 1 0.00 4:1397 +1e7f:146e 10 0.01 4:146e +1e7f:148f 2 0.00 4:148f +1e7f:14fd 1 0.00 4:14fd +1e87:8e8 1 0.00 3:8e8 +1e87:95a 5 0.00 3:95a +1e87:966 1 0.00 3:966 +1e87:968 1 0.00 3:968 +1e87:96b 1 0.00 3:96b +1e87:96f 5 0.00 3:96f +1e87:976 6 0.00 3:976 +1e87:985 4 0.00 3:985 +1e87:a88 3 0.00 3:a88 +1e87:a9a 1 0.00 3:a9a +1e87:ab0 1 0.00 3:ab0 +1e87:ab3 19 0.01 3:ab3 +1e87:ac7 11 0.01 3:ac7 +1e87:1b4a 5 0.00 3:1b4a +1e87:1b4e 1 0.00 3:1b4e +1e87:1b63 1 0.00 3:1b63 +1e87:1b6e 1 0.00 3:1b6e +1e87:1b74 1 0.00 3:1b74 +1e87:1b7d 1 0.00 3:1b7d +1e87:1b82 5 0.00 3:1b82 +1e87:1b85 11 0.01 3:1b85 +1e87:1b89 6 0.00 3:1b89 +1e87:1b8e 2 0.00 3:1b8e +1e87:1b94 1 0.00 3:1b94 +1e87:1b9a 5 0.00 3:1b9a +1e87:1b9c 1 0.00 3:1b9c +1e87:1ba0 5 0.00 3:1ba0 +1e87:1ba4 4 0.00 3:1ba4 +1e87:1ba7 1 0.00 3:1ba7 +1e87:1bab 6 0.00 3:1bab +1e87:1bb0 2 0.00 3:1bb0 +1e87:1ce3 3 0.00 3:1ce3 +1e57:130 3 0.00 9:130 +1e57:136 1 0.00 9:136 +1e57:189 1 0.00 9:189 +1e57:199 1 0.00 9:199 +1e57:272 2 0.00 9:272 +1e57:276 1 0.00 9:276 +1e57:28b 2 0.00 9:28b +1e57:294 2 0.00 9:294 +1e57:299 1 0.00 9:299 +1e57:347 4 0.00 9:347 +1e57:34a 1 0.00 9:34a +1e57:352 1 0.00 9:352 +1e57:358 2 0.00 9:358 +1e57:36d 1 0.00 9:36d +1e57:928 3 0.00 9:928 +1e57:934 5 0.00 9:934 +1e57:952 2 0.00 9:952 +1e57:957 1 0.00 9:957 +1e57:978 2 0.00 9:978 +1e57:9b0 1 0.00 9:9b0 +1e57:9fe 3 0.00 9:9fe +1e57:a09 1 0.00 9:a09 +1e57:a5e 2 0.00 9:a5e +1e57:a76 1 0.00 9:a76 +1e57:a81 2 0.00 9:a81 +1e57:a92 2 0.00 9:a92 +1e57:ad4 1 0.00 9:ad4 +1e57:aef 1 0.00 9:aef +1e57:ca3 1 0.00 9:ca3 + +Module Name GDI + + CS:EIP Samples (%) Map Offset Symbol + 647:eda 1 0.00 25:eda + 647:10ca 2 0.00 25:10ca + 647:10d3 1 0.00 25:10d3 + 647:11d7 1 0.00 25:11d7 + 647:12c9 1 0.00 25:12c9 + 647:12cf 1 0.00 25:12cf + 647:12dc 1 0.00 25:12dc + 647:12e2 1 0.00 25:12e2 + 647:12ed 1 0.00 25:12ed + 647:17b5 1 0.00 25:17b5 + 647:1c69 2 0.00 25:1c69 + 647:1c76 1 0.00 25:1c76 + 647:1c78 1 0.00 25:1c78 + 647:1c82 1 0.00 25:1c82 + 647:1dde 1 0.00 25:1dde + 647:1de2 1 0.00 25:1de2 + 647:1de6 1 0.00 25:1de6 + 647:1e11 1 0.00 25:1e11 + 647:1eb7 1 0.00 25:1eb7 + 66f:8ac 1 0.00 2a:8ac + 66f:9d6 1 0.00 2a:9d6 + 66f:1996 1 0.00 2a:1996 + 66f:1b70 1 0.00 2a:1b70 + 66f:20c4 3 0.00 2a:20c4 + 56f:888 1 0.00 a:888 + 56f:a48 1 0.00 a:a48 + 567:18f 2 0.00 9:18f + 567:a8a 1 0.00 9:a8a + 567:ba2 1 0.00 9:ba2 + 567:14e0 2 0.00 9:14e0 + 567:1502 2 0.00 9:1502 + 557:144 1 0.00 7:144 + 557:47c 1 0.00 7:47c + 54f:1a7 1 0.00 6:1a7 + 54f:447 1 0.00 6:447 + 54f:761 2 0.00 6:761 + 54f:940 3 0.00 6:940 + 547:d76 1 0.00 5:d76 + 547:ed7 2 0.00 5:ed7 + 547:f7c 1 0.00 5:f7c + 547:fac 1 0.00 5:fac + 547:1040 1 0.00 5:1040 + 547:1381 1 0.00 5:1381 + 547:148e 1 0.00 5:148e + 547:14aa 2 0.00 5:14aa + 547:170e 1 0.00 5:170e + 547:1730 1 0.00 5:1730 + 547:176a 1 0.00 5:176a + 547:1770 1 0.00 5:1770 + 547:1b0e 2 0.00 5:1b0e + 547:1b10 1 0.00 5:1b10 + 547:1b1a 1 0.00 5:1b1a + 547:1bb0 1 0.00 5:1bb0 + 547:1bb9 1 0.00 5:1bb9 + 547:1bbf 1 0.00 5:1bbf + 547:1cf0 1 0.00 5:1cf0 + 547:2006 2 0.00 5:2006 + 547:20e4 1 0.00 5:20e4 + 547:2134 1 0.00 5:2134 + 547:2200 1 0.00 5:2200 + 547:2291 1 0.00 5:2291 + 547:2512 1 0.00 5:2512 + 547:2559 1 0.00 5:2559 + 547:259f 1 0.00 5:259f + 547:2637 1 0.00 5:2637 + 547:26a0 1 0.00 5:26a0 + 547:26a9 1 0.00 5:26a9 + 547:2a00 1 0.00 5:2a00 + 547:2a95 1 0.00 5:2a95 + 547:2a98 1 0.00 5:2a98 + 547:2b07 1 0.00 5:2b07 + 547:2bac 1 0.00 5:2bac + 547:2d30 1 0.00 5:2d30 + 547:2d61 1 0.00 5:2d61 + 547:2d73 1 0.00 5:2d73 + 547:2e59 1 0.00 5:2e59 + 547:30c0 1 0.00 5:30c0 + 547:351e 1 0.00 5:351e + 547:3556 1 0.00 5:3556 + 547:355c 1 0.00 5:355c + 547:3dad 1 0.00 5:3dad + 53f:7c9 1 0.00 4:7c9 + 53f:897 1 0.00 4:897 + 53f:8c5 1 0.00 4:8c5 + 53f:d04 2 0.00 4:d04 + 53f:f77 1 0.00 4:f77 + 53f:f9d 1 0.00 4:f9d + 53f:1003 1 0.00 4:1003 + 53f:114d 1 0.00 4:114d + 537:745 1 0.00 3:745 + 537:7cf 1 0.00 3:7cf + 537:937 1 0.00 3:937 + 537:956 1 0.00 3:956 + 537:992 1 0.00 3:992 + 537:995 6 0.00 3:995 + 537:b4c 3 0.00 3:b4c + 537:c76 1 0.00 3:c76 + 537:cb4 1 0.00 3:cb4 + 537:cb8 1 0.00 3:cb8 + 537:f93 1 0.00 3:f93 + 537:1117 1 0.00 3:1117 + 537:17e3 1 0.00 3:17e3 + 537:1a9c 1 0.00 3:1a9c + 537:1c7e 1 0.00 3:1c7e + 537:1e97 1 0.00 3:1e97 + 537:1f5a 1 0.00 3:1f5a + 537:209a 1 0.00 3:209a + 537:220e 1 0.00 3:220e + 537:2638 1 0.00 3:2638 + 52f:6 2 0.00 2:6 + 52f:30 2 0.00 2:30 + 52f:3d 1 0.00 2:3d + 52f:3f 22 0.01 2:3f + 52f:42 24 0.01 2:42 + 52f:45 11 0.01 2:45 + 52f:4a 6 0.00 2:4a + 52f:4e 8 0.00 2:4e + 52f:50 1 0.00 2:50 + 52f:5e 2 0.00 2:5e + 52f:60 1 0.00 2:60 + 52f:64 2 0.00 2:64 + 52f:66 2 0.00 2:66 + 52f:68 21 0.01 2:68 + 52f:6e 3 0.00 2:6e + 52f:72 4 0.00 2:72 + 52f:74 3 0.00 2:74 + 52f:76 16 0.01 2:76 + 52f:81 3 0.00 2:81 + 52f:83 2 0.00 2:83 + 52f:85 25 0.01 2:85 + 52f:88 3 0.00 2:88 + 52f:8d 1 0.00 2:8d + 52f:90 1 0.00 2:90 + 52f:93 4 0.00 2:93 + 52f:97 1 0.00 2:97 + 52f:99 1 0.00 2:99 + 52f:a1 1 0.00 2:a1 + 52f:a4 1 0.00 2:a4 + 52f:e7 1 0.00 2:e7 + 52f:5e5 1 0.00 2:5e5 + 52f:5e9 1 0.00 2:5e9 + 52f:c35 5 0.00 2:c35 + 52f:c41 1 0.00 2:c41 + 52f:c53 2 0.00 2:c53 + 52f:ca2 5 0.00 2:ca2 + 52f:ce2 1 0.00 2:ce2 + 52f:cf2 1 0.00 2:cf2 + 52f:1590 1 0.00 2:1590 + 52f:164a 1 0.00 2:164a + 52f:1a69 1 0.00 2:1a69 + 527:279 1 0.00 1:279 + 527:43b 2 0.00 1:43b + 527:44b 1 0.00 1:44b + 527:470 1 0.00 1:470 + 527:4e4 1 0.00 1:4e4 + 527:5b4 1 0.00 1:5b4 + 527:662 3 0.00 1:662 + 527:66a 2 0.00 1:66a + 527:684 1 0.00 1:684 + 527:6d4 1 0.00 1:6d4 + 527:6df 1 0.00 1:6df + 527:70d 1 0.00 1:70d + 527:77b 1 0.00 1:77b + 527:815 1 0.00 1:815 + 527:877 1 0.00 1:877 + 527:889 1 0.00 1:889 + 527:890 1 0.00 1:890 + 527:977 1 0.00 1:977 + 527:a16 1 0.00 1:a16 + 527:a2a 1 0.00 1:a2a + 527:a6d 2 0.00 1:a6d + 527:a78 1 0.00 1:a78 + 527:aa8 1 0.00 1:aa8 + 527:ad2 1 0.00 1:ad2 + 527:af9 1 0.00 1:af9 + 527:b20 2 0.00 1:b20 + 527:b57 1 0.00 1:b57 + 527:b65 1 0.00 1:b65 + 527:b83 1 0.00 1:b83 + 527:bae 1 0.00 1:bae + 527:c19 1 0.00 1:c19 + 527:c31 1 0.00 1:c31 + 527:e4c 1 0.00 1:e4c + 527:e54 1 0.00 1:e54 + 527:e5e 1 0.00 1:e5e + 527:e61 1 0.00 1:e61 + 527:eea 1 0.00 1:eea + 527:1276 1 0.00 1:1276 + 527:138f 1 0.00 1:138f + 527:1ba2 1 0.00 1:1ba2 + 527:1c1d 2 0.00 1:1c1d + 527:1c2f 1 0.00 1:1c2f + 527:1c38 1 0.00 1:1c38 + 527:1c52 1 0.00 1:1c52 + 527:1c96 1 0.00 1:1c96 + 527:1cab 3 0.00 1:1cab + 527:1cb0 1 0.00 1:1cb0 + 527:1ce3 1 0.00 1:1ce3 + 527:1cf9 1 0.00 1:1cf9 + 527:1d60 1 0.00 1:1d60 + 527:1d67 1 0.00 1:1d67 + 527:1d87 1 0.00 1:1d87 + 527:1dfc 1 0.00 1:1dfc + 527:1e09 1 0.00 1:1e09 + 527:1fce 1 0.00 1:1fce + 527:2336 1 0.00 1:2336 + 527:29ea 3 0.00 1:29ea + 527:29fd 1 0.00 1:29fd + 527:2b03 4 0.00 1:2b03 + 527:2e9a 1 0.00 1:2e9a + 527:2f70 1 0.00 1:2f70 + 527:2f75 1 0.00 1:2f75 + 527:2f79 1 0.00 1:2f79 + 527:2f92 1 0.00 1:2f92 + 527:30ad 1 0.00 1:30ad + 527:3169 1 0.00 1:3169 + 527:36a2 1 0.00 1:36a2 + 527:36ac 2 0.00 1:36ac + 527:37e3 1 0.00 1:37e3 + 527:3846 1 0.00 1:3846 + 527:3960 1 0.00 1:3960 + 527:39fe 1 0.00 1:39fe + 527:3ab8 3 0.00 1:3ab8 + 527:3ac4 1 0.00 1:3ac4 + 527:3acd 1 0.00 1:3acd + 527:3ade 2 0.00 1:3ade + 527:3ae8 1 0.00 1:3ae8 + 527:3afd 1 0.00 1:3afd + 527:3b03 1 0.00 1:3b03 + 527:3b0c 1 0.00 1:3b0c + 527:3b15 1 0.00 1:3b15 + 527:3b6a 1 0.00 1:3b6a + 527:3b93 1 0.00 1:3b93 + 527:3bb8 1 0.00 1:3bb8 + 527:3be0 1 0.00 1:3be0 + 527:3bff 1 0.00 1:3bff + 527:3c02 1 0.00 1:3c02 + 527:3c17 1 0.00 1:3c17 + 527:3c40 1 0.00 1:3c40 + 527:3e30 1 0.00 1:3e30 + 527:3e95 1 0.00 1:3e95 + 527:3e99 1 0.00 1:3e99 + 527:3ea5 1 0.00 1:3ea5 + 527:3eb9 1 0.00 1:3eb9 + 527:3ed7 1 0.00 1:3ed7 + 527:3ef7 3 0.00 1:3ef7 + 527:3efe 2 0.00 1:3efe + 527:3f04 1 0.00 1:3f04 + 527:3f11 2 0.00 1:3f11 + 527:3f13 1 0.00 1:3f13 + 527:3f1e 1 0.00 1:3f1e + 527:3f98 2 0.00 1:3f98 + 527:3f9f 1 0.00 1:3f9f + 527:4012 1 0.00 1:4012 + 527:4287 1 0.00 1:4287 + 527:428a 2 0.00 1:428a + 527:428c 1 0.00 1:428c + 527:4297 1 0.00 1:4297 + 527:4334 3 0.00 1:4334 + 527:4365 1 0.00 1:4365 + 527:447a 1 0.00 1:447a + 527:44b1 1 0.00 1:44b1 + 527:44b8 1 0.00 1:44b8 + 527:44bd 1 0.00 1:44bd + 527:44c9 1 0.00 1:44c9 + 527:44cd 1 0.00 1:44cd + 527:460c 1 0.00 1:460c + 527:46db 1 0.00 1:46db + 527:46ed 1 0.00 1:46ed + 527:46f9 2 0.00 1:46f9 + 527:479c 1 0.00 1:479c + 527:4a4a 1 0.00 1:4a4a + 527:4a4e 1 0.00 1:4a4e + 527:4aa2 1 0.00 1:4aa2 + 527:4ad6 1 0.00 1:4ad6 + 527:4b76 1 0.00 1:4b76 + 527:4bd2 1 0.00 1:4bd2 + 527:4eff 1 0.00 1:4eff + 527:4f04 2 0.00 1:4f04 + 527:4f1b 1 0.00 1:4f1b + 527:4f85 1 0.00 1:4f85 + 527:50be 2 0.00 1:50be + 527:50c4 2 0.00 1:50c4 + 527:50cc 1 0.00 1:50cc + 527:50e0 2 0.00 1:50e0 + 527:50e7 1 0.00 1:50e7 + 527:50ef 2 0.00 1:50ef + 527:50f6 1 0.00 1:50f6 + 527:5118 1 0.00 1:5118 + 527:5126 1 0.00 1:5126 + 527:5140 1 0.00 1:5140 + 527:514b 1 0.00 1:514b + 527:52ab 5 0.00 1:52ab + 527:52b7 1 0.00 1:52b7 + 527:52c5 1 0.00 1:52c5 + 527:52c7 2 0.00 1:52c7 + 527:52cb 1 0.00 1:52cb + 527:5310 3 0.00 1:5310 + 527:5313 1 0.00 1:5313 + 527:5316 2 0.00 1:5316 + 527:531c 2 0.00 1:531c + 527:5323 1 0.00 1:5323 + 527:532c 1 0.00 1:532c + 527:532e 1 0.00 1:532e + 527:582e 1 0.00 1:582e + 527:58e1 1 0.00 1:58e1 + 527:591b 1 0.00 1:591b + 527:597d 1 0.00 1:597d + 527:5a59 1 0.00 1:5a59 + 527:5a90 1 0.00 1:5a90 + 527:5a9c 1 0.00 1:5a9c + 527:5ab7 2 0.00 1:5ab7 + 527:5abd 1 0.00 1:5abd + 527:5ac5 1 0.00 1:5ac5 + 527:5b10 2 0.00 1:5b10 + 527:5b17 1 0.00 1:5b17 + 527:5b19 1 0.00 1:5b19 + 527:5b1f 1 0.00 1:5b1f + 527:5b22 1 0.00 1:5b22 + 527:5b37 1 0.00 1:5b37 + 527:5b4b 1 0.00 1:5b4b + 527:5b64 1 0.00 1:5b64 + 527:5b7d 1 0.00 1:5b7d + 527:5cc0 1 0.00 1:5cc0 + 527:5ccc 1 0.00 1:5ccc + 527:5d78 1 0.00 1:5d78 + 527:5de1 1 0.00 1:5de1 + 527:5e22 2 0.00 1:5e22 + 527:5e25 2 0.00 1:5e25 + 527:5e6d 3 0.00 1:5e6d + 527:5e73 1 0.00 1:5e73 + 527:5ebf 4 0.00 1:5ebf + 527:5ec4 2 0.00 1:5ec4 + 527:5ed4 1 0.00 1:5ed4 + 527:5f5a 6 0.00 1:5f5a + 527:5f68 1 0.00 1:5f68 + 527:5f82 1 0.00 1:5f82 + 527:5fa4 2 0.00 1:5fa4 + 527:5fac 1 0.00 1:5fac + 527:5faf 1 0.00 1:5faf + 527:5fb1 3 0.00 1:5fb1 + 527:5fbc 1 0.00 1:5fbc + 527:5fc8 1 0.00 1:5fc8 + 527:5fed 2 0.00 1:5fed + 527:5ff7 2 0.00 1:5ff7 + 527:5ffb 1 0.00 1:5ffb + 527:601d 1 0.00 1:601d + 527:6039 1 0.00 1:6039 + 527:603f 1 0.00 1:603f + 527:604d 3 0.00 1:604d + 527:609e 2 0.00 1:609e + 527:60d5 1 0.00 1:60d5 + 527:60d7 1 0.00 1:60d7 + 527:6177 1 0.00 1:6177 + 527:61ba 1 0.00 1:61ba + 527:6237 1 0.00 1:6237 + 527:625d 1 0.00 1:625d + 527:6292 3 0.00 1:6292 + 527:62d1 1 0.00 1:62d1 + 527:6316 1 0.00 1:6316 + 527:6498 2 0.00 1:6498 + 527:64ab 2 0.00 1:64ab + 527:64bc 2 0.00 1:64bc + 527:64c2 1 0.00 1:64c2 + 527:64c4 3 0.00 1:64c4 + 527:64c8 1 0.00 1:64c8 + 527:64cf 2 0.00 1:64cf + 527:64d6 1 0.00 1:64d6 + 527:64f5 1 0.00 1:64f5 + 527:64fe 2 0.00 1:64fe + 527:6504 3 0.00 1:6504 + 527:650c 2 0.00 1:650c + 527:6516 1 0.00 1:6516 + 527:651d 2 0.00 1:651d + 527:657a 1 0.00 1:657a + 527:65a6 3 0.00 1:65a6 + 527:65a9 3 0.00 1:65a9 + 527:65bf 2 0.00 1:65bf + 527:65c3 2 0.00 1:65c3 + 527:65d3 1 0.00 1:65d3 + 527:65d8 1 0.00 1:65d8 + 527:6615 3 0.00 1:6615 + 527:661d 1 0.00 1:661d + 527:661f 1 0.00 1:661f + 527:6629 1 0.00 1:6629 + 527:6630 1 0.00 1:6630 + 527:6652 1 0.00 1:6652 + 527:6657 2 0.00 1:6657 + 527:665a 1 0.00 1:665a + 527:6660 3 0.00 1:6660 + 527:668b 1 0.00 1:668b + 527:6695 2 0.00 1:6695 + 527:6699 1 0.00 1:6699 + 527:66ea 1 0.00 1:66ea + 527:66ed 1 0.00 1:66ed + 527:66fb 1 0.00 1:66fb + 527:670b 2 0.00 1:670b + 527:670f 1 0.00 1:670f + 527:671e 3 0.00 1:671e + 527:6722 2 0.00 1:6722 + 527:6734 1 0.00 1:6734 + 527:6737 2 0.00 1:6737 + 527:6783 1 0.00 1:6783 + 527:67b4 1 0.00 1:67b4 + 527:67b5 1 0.00 1:67b5 + 527:67b9 1 0.00 1:67b9 + 527:67bc 1 0.00 1:67bc + 527:681a 1 0.00 1:681a + 527:681d 1 0.00 1:681d + 527:6824 1 0.00 1:6824 + 527:6828 1 0.00 1:6828 + 527:6855 1 0.00 1:6855 + 527:6942 3 0.00 1:6942 + 527:6969 1 0.00 1:6969 + 527:696f 1 0.00 1:696f + 527:6978 1 0.00 1:6978 + 527:697e 5 0.00 1:697e + 527:698e 1 0.00 1:698e + 527:6a1d 1 0.00 1:6a1d + 527:6a53 2 0.00 1:6a53 + 527:6b76 1 0.00 1:6b76 + 527:6bac 1 0.00 1:6bac + 527:6bd8 1 0.00 1:6bd8 + 527:6c17 1 0.00 1:6c17 + 527:6c1a 1 0.00 1:6c1a + 527:6c42 1 0.00 1:6c42 + 527:6c83 1 0.00 1:6c83 + 527:6db4 1 0.00 1:6db4 + 527:6ffc 1 0.00 1:6ffc + 527:703c 1 0.00 1:703c + 527:71cc 1 0.00 1:71cc + 527:7277 1 0.00 1:7277 + 527:737c 1 0.00 1:737c + 527:73a6 1 0.00 1:73a6 + 527:73aa 2 0.00 1:73aa + 527:7565 5 0.00 1:7565 + 527:756c 1 0.00 1:756c + 527:7582 1 0.00 1:7582 + 527:75e2 1 0.00 1:75e2 + 527:75f8 2 0.00 1:75f8 + 527:7601 1 0.00 1:7601 + 527:7610 1 0.00 1:7610 + 527:761d 1 0.00 1:761d + 527:7637 2 0.00 1:7637 + 527:7654 1 0.00 1:7654 + 527:7656 1 0.00 1:7656 + 527:767e 1 0.00 1:767e + 527:7690 1 0.00 1:7690 + 527:775e 1 0.00 1:775e + 527:7818 1 0.00 1:7818 + 527:788e 1 0.00 1:788e + 527:78e9 1 0.00 1:78e9 + 527:7a93 1 0.00 1:7a93 + 527:7b09 1 0.00 1:7b09 + 527:7b3f 1 0.00 1:7b3f + 527:7b57 1 0.00 1:7b57 + 527:7b5d 2 0.00 1:7b5d + 527:7c05 1 0.00 1:7c05 + 527:7c7a 1 0.00 1:7c7a + 527:7c89 1 0.00 1:7c89 + 527:7d57 1 0.00 1:7d57 + 527:7d76 1 0.00 1:7d76 + 527:7d9e 1 0.00 1:7d9e + 527:7fb9 1 0.00 1:7fb9 + 527:80b3 1 0.00 1:80b3 + 527:8153 1 0.00 1:8153 + 527:8170 1 0.00 1:8170 + 527:817c 1 0.00 1:817c + 527:8182 1 0.00 1:8182 + 527:8195 1 0.00 1:8195 + 527:81a6 1 0.00 1:81a6 + 527:81b2 1 0.00 1:81b2 + 527:81bb 1 0.00 1:81bb + 527:81dc 1 0.00 1:81dc + 527:8216 1 0.00 1:8216 + 527:8221 1 0.00 1:8221 + 527:8263 3 0.00 1:8263 + 527:827b 1 0.00 1:827b + 527:82b7 1 0.00 1:82b7 + 527:82c0 10 0.01 1:82c0 + 527:82cb 1 0.00 1:82cb + 527:8308 1 0.00 1:8308 + 527:8340 1 0.00 1:8340 + 527:8348 1 0.00 1:8348 + 527:834e 1 0.00 1:834e + 527:8350 1 0.00 1:8350 + 527:8368 1 0.00 1:8368 + 527:837f 1 0.00 1:837f + 527:83a2 1 0.00 1:83a2 + 527:83e2 1 0.00 1:83e2 + 527:83e8 1 0.00 1:83e8 + 527:83eb 1 0.00 1:83eb + 527:840b 1 0.00 1:840b + 527:843a 1 0.00 1:843a + 527:843f 1 0.00 1:843f + 527:8447 1 0.00 1:8447 + 527:8478 1 0.00 1:8478 + 527:84d3 1 0.00 1:84d3 + 527:84dd 5 0.00 1:84dd + 527:84f6 1 0.00 1:84f6 + 527:84fa 3 0.00 1:84fa + 527:84fc 2 0.00 1:84fc + 527:8504 1 0.00 1:8504 + 527:8508 2 0.00 1:8508 + 527:8530 1 0.00 1:8530 + 527:8534 2 0.00 1:8534 + 527:853b 1 0.00 1:853b + 527:853e 1 0.00 1:853e + 527:8540 2 0.00 1:8540 + 527:8581 1 0.00 1:8581 + 527:858d 2 0.00 1:858d + 527:858f 2 0.00 1:858f + 527:8598 1 0.00 1:8598 + 527:85b0 1 0.00 1:85b0 + 527:85c0 1 0.00 1:85c0 + 527:85c7 1 0.00 1:85c7 + 527:85ca 2 0.00 1:85ca + 527:85d5 2 0.00 1:85d5 + 527:85d7 1 0.00 1:85d7 + 527:85dd 1 0.00 1:85dd + 527:85f8 1 0.00 1:85f8 + 527:8616 2 0.00 1:8616 + 527:8653 1 0.00 1:8653 + 527:8658 1 0.00 1:8658 + 527:8661 1 0.00 1:8661 + 527:8668 3 0.00 1:8668 + 527:866e 2 0.00 1:866e + 527:8671 3 0.00 1:8671 + 527:867b 1 0.00 1:867b + 527:867f 1 0.00 1:867f + 527:8682 1 0.00 1:8682 + 527:8e7a 1 0.00 1:8e7a + 527:8fc9 1 0.00 1:8fc9 + 527:8fe2 1 0.00 1:8fe2 + 527:9116 1 0.00 1:9116 + 527:9132 1 0.00 1:9132 + 527:92ca 1 0.00 1:92ca + 527:92d6 2 0.00 1:92d6 + 527:92de 1 0.00 1:92de + 527:931e 1 0.00 1:931e + 527:9336 1 0.00 1:9336 + 527:9356 1 0.00 1:9356 + 527:93ca 1 0.00 1:93ca + 527:941b 6 0.00 1:941b + 527:9459 1 0.00 1:9459 + 527:9484 1 0.00 1:9484 + 527:94a2 1 0.00 1:94a2 + 527:9599 1 0.00 1:9599 + 527:9900 2 0.00 1:9900 + 527:9963 1 0.00 1:9963 + 527:99d6 1 0.00 1:99d6 + 527:9ba4 1 0.00 1:9ba4 + 527:9c9c 1 0.00 1:9c9c + 527:a2cb 1 0.00 1:a2cb + 527:a44d 1 0.00 1:a44d + 527:a46f 2 0.00 1:a46f + 527:a471 1 0.00 1:a471 + 527:a47a 1 0.00 1:a47a + 527:a486 1 0.00 1:a486 + 527:a4c0 1 0.00 1:a4c0 + 527:a4e3 1 0.00 1:a4e3 + 527:a6aa 3 0.00 1:a6aa + 527:a6b5 1 0.00 1:a6b5 + 527:a6cb 1 0.00 1:a6cb + 527:a6e4 1 0.00 1:a6e4 + 527:a727 3 0.00 1:a727 + 527:a795 1 0.00 1:a795 + 527:a861 2 0.00 1:a861 + 527:a889 1 0.00 1:a889 + 527:a88c 2 0.00 1:a88c + 527:a8a0 2 0.00 1:a8a0 + 527:a8aa 1 0.00 1:a8aa + 527:a8b0 1 0.00 1:a8b0 + 527:a8b2 3 0.00 1:a8b2 + 527:a8b9 1 0.00 1:a8b9 + 527:a8c2 1 0.00 1:a8c2 + 64f:2eb 1 0.00 26:2eb + 64f:7f8 1 0.00 26:7f8 + 64f:110d 1 0.00 26:110d + 64f:1154 1 0.00 26:1154 + 64f:11d1 1 0.00 26:11d1 + 64f:11f0 1 0.00 26:11f0 + 64f:124b 1 0.00 26:124b + 5df:46 2 0.00 18:46 + 5df:477 1 0.00 18:477 + 65f:22a 2 0.00 28:22a + 65f:32c 1 0.00 28:32c + 65f:32e 1 0.00 28:32e + +Module Name USER + + CS:EIP Samples (%) Map Offset Symbol +16b7:1fd 1 0.00 1b:1fd +16b7:2ca 1 0.00 1b:2ca +16e7:1110 2 0.00 15:1110 +16e7:1183 1 0.00 15:1183 +16e7:2085 2 0.00 15:2085 +16e7:2099 1 0.00 15:2099 +16e7:582c 1 0.00 15:582c +16e7:5867 1 0.00 15:5867 +16e7:5870 1 0.00 15:5870 +16e7:587b 1 0.00 15:587b +16e7:6046 1 0.00 15:6046 +16e7:60ef 1 0.00 15:60ef +16e7:60f6 1 0.00 15:60f6 +16e7:61a5 1 0.00 15:61a5 +16e7:61b0 1 0.00 15:61b0 +16e7:629d 1 0.00 15:629d +16e7:6519 1 0.00 15:6519 +16ff:2cd 1 0.00 12:2cd +16ff:45a 1 0.00 12:45a +16ff:7f9 1 0.00 12:7f9 +16ff:b6a 1 0.00 12:b6a +16ff:1576 1 0.00 12:1576 +16ff:183b 1 0.00 12:183b +16ff:2224 1 0.00 12:2224 +170f:22fd 1 0.00 10:22fd +170f:270d 1 0.00 10:270d +1727:13e 1 0.00 d:13e +1727:176 1 0.00 d:176 +1727:183 1 0.00 d:183 +1727:1b1 1 0.00 d:1b1 +1727:4c1 1 0.00 d:4c1 +1727:5fd 1 0.00 d:5fd +1727:637 1 0.00 d:637 +1727:685 1 0.00 d:685 +1727:78f 1 0.00 d:78f +1727:957 2 0.00 d:957 +1727:ca8 1 0.00 d:ca8 +1727:cb4 1 0.00 d:cb4 +1727:e12 1 0.00 d:e12 +1727:e35 1 0.00 d:e35 +1727:e4c 1 0.00 d:e4c +1727:e76 1 0.00 d:e76 +1727:1011 1 0.00 d:1011 +1727:10ce 1 0.00 d:10ce +1727:1268 2 0.00 d:1268 +1727:17e2 1 0.00 d:17e2 +1737:104 1 0.00 b:104 +1737:120 1 0.00 b:120 +1737:a26 1 0.00 b:a26 +1747:45 2 0.00 9:45 +1747:88 2 0.00 9:88 +1747:17f 6 0.00 9:17f +1747:2a7 1 0.00 9:2a7 +1747:2e3 1 0.00 9:2e3 +1747:2f2 1 0.00 9:2f2 +1747:323 1 0.00 9:323 +1747:385 1 0.00 9:385 +1747:3b4 1 0.00 9:3b4 +1747:3b7 1 0.00 9:3b7 +1747:3d1 1 0.00 9:3d1 +1747:3f3 2 0.00 9:3f3 +1747:403 2 0.00 9:403 +1747:41e 2 0.00 9:41e +1747:497 2 0.00 9:497 +1747:4af 1 0.00 9:4af +1747:4b6 3 0.00 9:4b6 +1747:4d6 1 0.00 9:4d6 +1747:4f8 1 0.00 9:4f8 +1747:50a 2 0.00 9:50a +1747:59c 2 0.00 9:59c +1747:59f 1 0.00 9:59f +1747:6aa 1 0.00 9:6aa +1747:6c5 1 0.00 9:6c5 +1747:6c9 1 0.00 9:6c9 +1747:6d8 1 0.00 9:6d8 +1747:6dc 3 0.00 9:6dc +1747:6f6 4 0.00 9:6f6 +1747:8e9 1 0.00 9:8e9 +1747:934 3 0.00 9:934 +1747:b01 1 0.00 9:b01 +1747:b96 1 0.00 9:b96 +1747:ba6 1 0.00 9:ba6 +1747:bae 1 0.00 9:bae +1747:bc4 1 0.00 9:bc4 +1747:bc8 4 0.00 9:bc8 +1747:10d4 2 0.00 9:10d4 +1747:1112 2 0.00 9:1112 +1747:1135 1 0.00 9:1135 +1747:1154 2 0.00 9:1154 +1747:1187 1 0.00 9:1187 +1747:1193 1 0.00 9:1193 +1747:1676 1 0.00 9:1676 +1747:167d 1 0.00 9:167d +1747:168d 2 0.00 9:168d +1747:169c 1 0.00 9:169c +1747:16a4 1 0.00 9:16a4 +1747:16a6 1 0.00 9:16a6 +1747:16db 1 0.00 9:16db +1747:16e3 1 0.00 9:16e3 +1747:16e8 1 0.00 9:16e8 +1747:16eb 1 0.00 9:16eb +1747:16f1 1 0.00 9:16f1 +1747:16f8 1 0.00 9:16f8 +1747:170c 1 0.00 9:170c +1747:173a 1 0.00 9:173a +1747:1741 1 0.00 9:1741 +1747:1750 1 0.00 9:1750 +1747:1791 3 0.00 9:1791 +1747:17eb 3 0.00 9:17eb +1747:1836 1 0.00 9:1836 +1747:186b 1 0.00 9:186b +1747:1872 1 0.00 9:1872 +1747:1905 1 0.00 9:1905 +1747:1909 1 0.00 9:1909 +1747:191d 3 0.00 9:191d +1747:1923 1 0.00 9:1923 +1747:194a 2 0.00 9:194a +1747:1959 2 0.00 9:1959 +1747:1979 1 0.00 9:1979 +1747:19a5 1 0.00 9:19a5 +1747:19ae 1 0.00 9:19ae +1747:1c12 1 0.00 9:1c12 +1747:1da3 1 0.00 9:1da3 +1747:1daa 1 0.00 9:1daa +1747:1f1e 1 0.00 9:1f1e +1747:2040 1 0.00 9:2040 +1747:2051 1 0.00 9:2051 +1747:2053 1 0.00 9:2053 +1747:2056 1 0.00 9:2056 +1747:2066 1 0.00 9:2066 +1747:2068 1 0.00 9:2068 +1747:209f 4 0.00 9:209f +1747:20ab 2 0.00 9:20ab +1747:20e4 3 0.00 9:20e4 +1747:20ec 1 0.00 9:20ec +1747:20f2 1 0.00 9:20f2 +1747:20f8 2 0.00 9:20f8 +1747:2101 1 0.00 9:2101 +1747:2116 1 0.00 9:2116 +1747:213f 1 0.00 9:213f +1747:2142 1 0.00 9:2142 +1747:2146 1 0.00 9:2146 +1747:21dd 1 0.00 9:21dd +1747:2408 2 0.00 9:2408 +1747:26b6 2 0.00 9:26b6 +1747:26e4 1 0.00 9:26e4 +1747:2823 1 0.00 9:2823 +1747:28b2 1 0.00 9:28b2 +1747:28c4 1 0.00 9:28c4 +1747:2959 1 0.00 9:2959 +1747:2a18 12 0.01 9:2a18 +1747:2a26 1 0.00 9:2a26 +1747:2a4a 1 0.00 9:2a4a +1747:2a4b 1 0.00 9:2a4b +174f:828 1 0.00 8:828 +174f:af8 1 0.00 8:af8 +174f:1018 1 0.00 8:1018 +174f:102e 2 0.00 8:102e +174f:103b 1 0.00 8:103b +174f:10f6 1 0.00 8:10f6 +174f:1822 1 0.00 8:1822 +174f:1826 1 0.00 8:1826 +174f:2e2e 3 0.00 8:2e2e +174f:2e36 9 0.00 8:2e36 +174f:2e50 1 0.00 8:2e50 +174f:2e55 2 0.00 8:2e55 +174f:2e7c 1 0.00 8:2e7c +174f:2e8e 4 0.00 8:2e8e +174f:2ea3 1 0.00 8:2ea3 +174f:2eb6 1 0.00 8:2eb6 +174f:2eba 1 0.00 8:2eba +174f:2edb 4 0.00 8:2edb +174f:2f57 1 0.00 8:2f57 +174f:3128 2 0.00 8:3128 +174f:34ea 1 0.00 8:34ea +174f:3ceb 1 0.00 8:3ceb +174f:3d38 3 0.00 8:3d38 +174f:3d56 1 0.00 8:3d56 +174f:3d6a 1 0.00 8:3d6a +174f:3db6 1 0.00 8:3db6 +174f:4159 1 0.00 8:4159 +174f:4757 2 0.00 8:4757 +174f:476e 1 0.00 8:476e +174f:4796 5 0.00 8:4796 +1757:de1 1 0.00 7:de1 +175f:58d 1 0.00 6:58d +175f:58e 1 0.00 6:58e +175f:bd0 1 0.00 6:bd0 +175f:bd8 1 0.00 6:bd8 +175f:fa3 2 0.00 6:fa3 +175f:1065 1 0.00 6:1065 +175f:106f 1 0.00 6:106f +175f:10c8 1 0.00 6:10c8 +175f:1364 1 0.00 6:1364 +175f:1379 1 0.00 6:1379 +175f:1466 3 0.00 6:1466 +175f:1472 1 0.00 6:1472 +175f:149a 1 0.00 6:149a +175f:14c6 1 0.00 6:14c6 +175f:14f2 2 0.00 6:14f2 +175f:1536 1 0.00 6:1536 +175f:1539 1 0.00 6:1539 +175f:153c 1 0.00 6:153c +175f:1749 1 0.00 6:1749 +175f:18fc 1 0.00 6:18fc +175f:1c3f 1 0.00 6:1c3f +175f:2456 1 0.00 6:2456 +175f:246d 1 0.00 6:246d +175f:2542 2 0.00 6:2542 +175f:2aea 1 0.00 6:2aea +175f:2af4 1 0.00 6:2af4 +175f:2b04 4 0.00 6:2b04 +175f:2b5b 1 0.00 6:2b5b +175f:2b5f 1 0.00 6:2b5f +175f:2d98 1 0.00 6:2d98 +175f:3fd0 1 0.00 6:3fd0 +175f:4316 1 0.00 6:4316 +175f:4342 1 0.00 6:4342 +175f:435e 1 0.00 6:435e +175f:4368 1 0.00 6:4368 +175f:4405 1 0.00 6:4405 +175f:44ba 2 0.00 6:44ba +175f:44d9 3 0.00 6:44d9 +175f:44e4 1 0.00 6:44e4 +175f:4527 1 0.00 6:4527 +175f:453c 1 0.00 6:453c +175f:453e 1 0.00 6:453e +175f:4548 1 0.00 6:4548 +175f:45b9 1 0.00 6:45b9 +175f:45cc 1 0.00 6:45cc +175f:45f2 1 0.00 6:45f2 +175f:4683 2 0.00 6:4683 +175f:46e9 1 0.00 6:46e9 +175f:46f1 1 0.00 6:46f1 +175f:46f6 1 0.00 6:46f6 +175f:473d 1 0.00 6:473d +175f:4778 1 0.00 6:4778 +175f:4779 1 0.00 6:4779 +175f:4780 1 0.00 6:4780 +175f:48d6 1 0.00 6:48d6 +175f:49fa 1 0.00 6:49fa +175f:4baf 1 0.00 6:4baf +175f:4bb5 1 0.00 6:4bb5 +175f:4d39 1 0.00 6:4d39 +175f:4f17 1 0.00 6:4f17 +175f:4f4d 1 0.00 6:4f4d +175f:5296 1 0.00 6:5296 +175f:52c2 1 0.00 6:52c2 +175f:5581 1 0.00 6:5581 +175f:55da 1 0.00 6:55da +175f:5629 1 0.00 6:5629 +175f:5716 1 0.00 6:5716 +175f:574c 1 0.00 6:574c +175f:580e 1 0.00 6:580e +175f:583a 1 0.00 6:583a +175f:588c 1 0.00 6:588c +175f:5914 1 0.00 6:5914 +175f:598a 1 0.00 6:598a +175f:59a3 2 0.00 6:59a3 +175f:59bc 1 0.00 6:59bc +175f:5b70 1 0.00 6:5b70 +175f:5b83 1 0.00 6:5b83 +175f:5d26 2 0.00 6:5d26 +175f:5d32 2 0.00 6:5d32 +175f:5d3f 1 0.00 6:5d3f +175f:5d47 1 0.00 6:5d47 +175f:5d4f 2 0.00 6:5d4f +175f:5d57 1 0.00 6:5d57 +175f:5d76 3 0.00 6:5d76 +175f:5d7d 1 0.00 6:5d7d +175f:5d81 2 0.00 6:5d81 +175f:5d86 1 0.00 6:5d86 +175f:5d8a 2 0.00 6:5d8a +175f:5e0d 1 0.00 6:5e0d +175f:5e35 5 0.00 6:5e35 +175f:5e44 3 0.00 6:5e44 +175f:5e55 1 0.00 6:5e55 +175f:5e62 1 0.00 6:5e62 +175f:5e63 1 0.00 6:5e63 +175f:5e66 1 0.00 6:5e66 +175f:5eda 1 0.00 6:5eda +175f:5fb5 1 0.00 6:5fb5 +175f:5fc7 1 0.00 6:5fc7 +175f:5fd6 2 0.00 6:5fd6 +175f:603f 2 0.00 6:603f +175f:6155 1 0.00 6:6155 +175f:615c 1 0.00 6:615c +175f:6198 1 0.00 6:6198 +175f:61ad 1 0.00 6:61ad +175f:633e 1 0.00 6:633e +175f:638c 1 0.00 6:638c +175f:647f 1 0.00 6:647f +175f:6652 1 0.00 6:6652 +175f:6868 1 0.00 6:6868 +175f:6891 1 0.00 6:6891 +175f:68ec 1 0.00 6:68ec +175f:6917 1 0.00 6:6917 +175f:6982 1 0.00 6:6982 +175f:6a35 1 0.00 6:6a35 +175f:6c41 1 0.00 6:6c41 +175f:6d77 1 0.00 6:6d77 +175f:6daf 1 0.00 6:6daf +175f:6e93 2 0.00 6:6e93 +175f:722a 1 0.00 6:722a +175f:7240 1 0.00 6:7240 +175f:728c 1 0.00 6:728c +175f:7294 1 0.00 6:7294 +175f:7299 1 0.00 6:7299 +175f:7372 1 0.00 6:7372 +175f:73be 1 0.00 6:73be +175f:7404 1 0.00 6:7404 +175f:7442 2 0.00 6:7442 +175f:7451 1 0.00 6:7451 +175f:745c 4 0.00 6:745c +175f:747b 1 0.00 6:747b +175f:7482 1 0.00 6:7482 +1767:5f6 1 0.00 5:5f6 +1767:673 1 0.00 5:673 +1767:20c0 1 0.00 5:20c0 +1767:213e 1 0.00 5:213e +1767:2188 1 0.00 5:2188 +1767:21bf 1 0.00 5:21bf +1767:21ee 1 0.00 5:21ee +1767:21fb 1 0.00 5:21fb +1767:23b6 1 0.00 5:23b6 +1767:240c 1 0.00 5:240c +1767:245c 1 0.00 5:245c +1767:25f9 1 0.00 5:25f9 +1787:565 1 0.00 1:565 +1787:591 2 0.00 1:591 +1787:60c 1 0.00 1:60c +1787:624 1 0.00 1:624 +1787:65e 1 0.00 1:65e +1787:66b 1 0.00 1:66b +1787:71f 2 0.00 1:71f +1787:732 1 0.00 1:732 +1787:943 1 0.00 1:943 +1787:988 2 0.00 1:988 +1787:9a5 8 0.00 1:9a5 +1787:9a8 1 0.00 1:9a8 +1787:9be 6 0.00 1:9be +1787:9c9 1 0.00 1:9c9 +1787:9d6 2 0.00 1:9d6 +1787:9dc 1 0.00 1:9dc +1787:9eb 1 0.00 1:9eb +1787:9f5 5 0.00 1:9f5 +1787:9f7 1 0.00 1:9f7 +1787:9fb 1 0.00 1:9fb +1787:a21 3 0.00 1:a21 +1787:a23 2 0.00 1:a23 +1787:a25 4 0.00 1:a25 +1787:a27 3 0.00 1:a27 +1787:a2f 1 0.00 1:a2f +1787:a33 1 0.00 1:a33 +1787:a3a 5 0.00 1:a3a +1787:a44 1 0.00 1:a44 +1787:a49 2 0.00 1:a49 +1787:a4f 2 0.00 1:a4f +1787:a51 2 0.00 1:a51 +1787:a57 1 0.00 1:a57 +1787:a75 2 0.00 1:a75 +1787:a84 1 0.00 1:a84 +1787:a9a 2 0.00 1:a9a +1787:aa4 2 0.00 1:aa4 +1787:aba 1 0.00 1:aba +1787:abb 2 0.00 1:abb +1787:ac3 2 0.00 1:ac3 +1787:acc 1 0.00 1:acc +1787:ad8 8 0.00 1:ad8 +1787:adf 1 0.00 1:adf +1787:aed 1 0.00 1:aed +1787:af2 2 0.00 1:af2 +1787:b65 1 0.00 1:b65 +1787:c59 2 0.00 1:c59 +1787:c64 2 0.00 1:c64 +1787:cdf 2 0.00 1:cdf +1777:79 1 0.00 3:79 +1777:fc 2 0.00 3:fc +1777:10f 2 0.00 3:10f +1777:12c 1 0.00 3:12c +1777:19f 11 0.01 3:19f +1777:1a8 1 0.00 3:1a8 +1777:1bb 1 0.00 3:1bb +1777:1c5 3 0.00 3:1c5 +1777:1da 1 0.00 3:1da +1777:1dd 1 0.00 3:1dd +1777:1e1 4 0.00 3:1e1 +1777:1e9 1 0.00 3:1e9 +1777:2fa 1 0.00 3:2fa +1777:359 1 0.00 3:359 +1777:377 1 0.00 3:377 +1777:501 1 0.00 3:501 +1777:759 3 0.00 3:759 +1777:764 5 0.00 3:764 +1777:773 1 0.00 3:773 +1777:7af 1 0.00 3:7af +1777:84f 1 0.00 3:84f +1777:85d 2 0.00 3:85d +1777:88a 4 0.00 3:88a +1777:88c 1 0.00 3:88c +1777:8da 2 0.00 3:8da +1777:8de 3 0.00 3:8de +1777:8e6 1 0.00 3:8e6 +1777:8e8 3 0.00 3:8e8 +1777:8e9 2 0.00 3:8e9 +1777:8ee 2 0.00 3:8ee +1777:8f2 6 0.00 3:8f2 +1777:8f5 6 0.00 3:8f5 +1777:8f6 1 0.00 3:8f6 +1777:8f7 1 0.00 3:8f7 +1777:8f8 2 0.00 3:8f8 +1777:909 1 0.00 3:909 +1777:90f 6 0.00 3:90f +1777:915 3 0.00 3:915 +1777:92a 2 0.00 3:92a +1777:932 4 0.00 3:932 +1777:934 14 0.01 3:934 +1777:939 2 0.00 3:939 +1777:948 1 0.00 3:948 +1777:94a 2 0.00 3:94a +1777:94f 3 0.00 3:94f +1777:952 1 0.00 3:952 +1777:97b 2 0.00 3:97b +1777:97e 1 0.00 3:97e +1777:986 2 0.00 3:986 +1777:98b 2 0.00 3:98b +1777:9a5 4 0.00 3:9a5 +1777:9b1 1 0.00 3:9b1 +1777:9bc 5 0.00 3:9bc +1777:9c4 2 0.00 3:9c4 +1777:9c9 4 0.00 3:9c9 +1777:9ce 1 0.00 3:9ce +1777:9d3 3 0.00 3:9d3 +1777:9db 3 0.00 3:9db +1777:9e2 6 0.00 3:9e2 +1777:9ed 1 0.00 3:9ed +1777:9ef 6 0.00 3:9ef +1777:9f1 1 0.00 3:9f1 +1777:9f9 4 0.00 3:9f9 +1777:a06 1 0.00 3:a06 +1777:a98 1 0.00 3:a98 +1777:aed 2 0.00 3:aed +1777:aef 1 0.00 3:aef +1777:b18 1 0.00 3:b18 +1777:b3a 1 0.00 3:b3a +1777:b4d 1 0.00 3:b4d +1777:b56 17 0.01 3:b56 +1777:b5a 1 0.00 3:b5a +1777:b5f 2 0.00 3:b5f +1777:b60 1 0.00 3:b60 +1777:b61 2 0.00 3:b61 +1777:b62 3 0.00 3:b62 +1777:b65 1 0.00 3:b65 +1777:b6a 1 0.00 3:b6a +1777:b71 1 0.00 3:b71 +1777:b79 2 0.00 3:b79 +1777:b7c 5 0.00 3:b7c +1777:b9f 2 0.00 3:b9f +1777:ba3 2 0.00 3:ba3 +1777:baa 3 0.00 3:baa +1777:baf 2 0.00 3:baf +1777:bb2 10 0.01 3:bb2 +1777:bb8 3 0.00 3:bb8 +1777:bd9 3 0.00 3:bd9 +1777:be8 14 0.01 3:be8 +1777:bea 1 0.00 3:bea +1777:bef 1 0.00 3:bef +1777:bf1 4 0.00 3:bf1 +1777:bf6 15 0.01 3:bf6 +1777:bf7 15 0.01 3:bf7 +1777:bfe 2 0.00 3:bfe +1777:c06 6 0.00 3:c06 +1777:c0d 1 0.00 3:c0d +1777:c2c 2 0.00 3:c2c +1777:c34 3 0.00 3:c34 +1777:c3c 1 0.00 3:c3c +1777:c45 1 0.00 3:c45 +1777:c4d 1 0.00 3:c4d +1777:c52 1 0.00 3:c52 +1777:c5b 3 0.00 3:c5b +1777:c63 2 0.00 3:c63 +1777:c70 1 0.00 3:c70 +1777:c71 1 0.00 3:c71 +1777:c79 1 0.00 3:c79 +1777:c8c 2 0.00 3:c8c +1777:c8d 4 0.00 3:c8d +1777:c93 2 0.00 3:c93 +1777:cc1 1 0.00 3:cc1 +1777:cdb 1 0.00 3:cdb +1777:cdf 1 0.00 3:cdf +1777:ce0 2 0.00 3:ce0 +1777:cf7 1 0.00 3:cf7 +1777:dda 2 0.00 3:dda +1777:de0 1 0.00 3:de0 +1777:dee 1 0.00 3:dee +1777:e40 2 0.00 3:e40 +1777:e44 2 0.00 3:e44 +1777:e57 1 0.00 3:e57 +1777:e6e 2 0.00 3:e6e +1777:e81 1 0.00 3:e81 +1777:e91 1 0.00 3:e91 +1777:f1a 1 0.00 3:f1a +1777:f2a 5 0.00 3:f2a +1777:f30 1 0.00 3:f30 +1777:f39 3 0.00 3:f39 +1777:f3b 4 0.00 3:f3b +1777:f3c 4 0.00 3:f3c +1777:f6b 1 0.00 3:f6b +1777:f76 1 0.00 3:f76 +1777:f7b 1 0.00 3:f7b +1777:f98 1 0.00 3:f98 +1777:fd6 1 0.00 3:fd6 +1777:fe3 2 0.00 3:fe3 +1777:1016 1 0.00 3:1016 +1777:107b 2 0.00 3:107b +1777:109b 1 0.00 3:109b +1777:10bb 1 0.00 3:10bb +1777:112b 3 0.00 3:112b +1777:112c 2 0.00 3:112c +1777:1131 9 0.00 3:1131 +1777:1135 3 0.00 3:1135 +1777:1140 10 0.01 3:1140 +1777:1148 9 0.00 3:1148 +1777:1153 1 0.00 3:1153 +1777:1159 13 0.01 3:1159 +1777:115d 4 0.00 3:115d +1777:1196 1 0.00 3:1196 +1777:119d 5 0.00 3:119d +1777:119e 6 0.00 3:119e +1777:11fb 1 0.00 3:11fb +1777:12fc 2 0.00 3:12fc +1777:1301 1 0.00 3:1301 +1777:1318 1 0.00 3:1318 +1777:132b 1 0.00 3:132b +1777:1369 1 0.00 3:1369 +1777:137a 1 0.00 3:137a +1777:146f 2 0.00 3:146f +1777:1477 7 0.00 3:1477 +1777:147d 1 0.00 3:147d +1777:1482 2 0.00 3:1482 +1777:1488 1 0.00 3:1488 +1777:148f 1 0.00 3:148f +1777:14ee 1 0.00 3:14ee +1777:157e 1 0.00 3:157e +1777:1584 1 0.00 3:1584 +1777:16b7 1 0.00 3:16b7 +1777:16c5 1 0.00 3:16c5 +1777:170c 1 0.00 3:170c +1777:17bf 1 0.00 3:17bf +1777:1cf0 1 0.00 3:1cf0 +1777:1e15 1 0.00 3:1e15 +1777:2392 1 0.00 3:2392 +1777:240e 2 0.00 3:240e +1777:2428 1 0.00 3:2428 +1777:2484 1 0.00 3:2484 +1777:248f 1 0.00 3:248f +1777:249a 2 0.00 3:249a +1777:24be 1 0.00 3:24be +1777:24d9 2 0.00 3:24d9 +1777:25a6 1 0.00 3:25a6 +1777:2618 2 0.00 3:2618 +1777:261e 1 0.00 3:261e +1777:267f 1 0.00 3:267f +1777:2742 1 0.00 3:2742 +1777:282d 1 0.00 3:282d +1777:2997 1 0.00 3:2997 +1777:29a2 1 0.00 3:29a2 +1777:29b6 1 0.00 3:29b6 +1777:2ad5 1 0.00 3:2ad5 +1777:30a8 1 0.00 3:30a8 +1777:3150 2 0.00 3:3150 +1777:31c6 1 0.00 3:31c6 +1777:31e0 1 0.00 3:31e0 +1777:3fe4 1 0.00 3:3fe4 +1777:400f 1 0.00 3:400f +1777:40a4 1 0.00 3:40a4 +1777:40dc 1 0.00 3:40dc +1777:419e 2 0.00 3:419e +1777:4254 1 0.00 3:4254 +1777:476b 1 0.00 3:476b +1777:4b6b 1 0.00 3:4b6b +1777:4fda 6 0.00 3:4fda +1777:4fe0 3 0.00 3:4fe0 +1777:4fe6 1 0.00 3:4fe6 +1777:4feb 1 0.00 3:4feb +1777:5001 2 0.00 3:5001 +1777:5079 2 0.00 3:5079 +1777:50ce 1 0.00 3:50ce +1777:5113 1 0.00 3:5113 +1777:513a 1 0.00 3:513a +1777:5162 1 0.00 3:5162 +1777:5178 1 0.00 3:5178 +1777:524d 1 0.00 3:524d +1777:5261 2 0.00 3:5261 +1777:5283 1 0.00 3:5283 +1777:5300 1 0.00 3:5300 +1777:531c 1 0.00 3:531c +1777:533b 1 0.00 3:533b +1777:5357 1 0.00 3:5357 +1777:5379 3 0.00 3:5379 +1777:5418 1 0.00 3:5418 +1777:5462 1 0.00 3:5462 +1777:5909 2 0.00 3:5909 +1777:5990 2 0.00 3:5990 +1777:5992 1 0.00 3:5992 +1777:5b2c 1 0.00 3:5b2c +1777:5b2e 1 0.00 3:5b2e +1777:5b42 1 0.00 3:5b42 +1777:5fa4 1 0.00 3:5fa4 +1777:5fb6 2 0.00 3:5fb6 +1777:6038 1 0.00 3:6038 +1777:609c 2 0.00 3:609c +1777:60be 1 0.00 3:60be +1777:644f 1 0.00 3:644f +1777:688e 1 0.00 3:688e +1777:7a5b 1 0.00 3:7a5b +1777:8275 8 0.00 3:8275 +1777:8277 1 0.00 3:8277 +1777:8286 1 0.00 3:8286 +1777:8290 2 0.00 3:8290 +1777:8298 2 0.00 3:8298 +1777:829e 3 0.00 3:829e +1777:82cb 1 0.00 3:82cb +1777:82e4 1 0.00 3:82e4 +1777:82e7 2 0.00 3:82e7 +1777:82ec 1 0.00 3:82ec +1777:8342 1 0.00 3:8342 +1777:83a8 1 0.00 3:83a8 +1777:83ef 1 0.00 3:83ef +1777:8421 1 0.00 3:8421 +176f:276 1 0.00 4:276 +176f:430 11 0.01 4:430 +176f:434 1 0.00 4:434 +176f:442 1 0.00 4:442 +176f:44b 1 0.00 4:44b +176f:476 5 0.00 4:476 +176f:497 1 0.00 4:497 +176f:499 4 0.00 4:499 +176f:49d 2 0.00 4:49d +176f:4e1 13 0.01 4:4e1 +176f:4e4 1 0.00 4:4e4 +176f:4ee 1 0.00 4:4ee +176f:504 1 0.00 4:504 +176f:50a 1 0.00 4:50a +176f:557 2 0.00 4:557 +176f:55e 1 0.00 4:55e +176f:566 1 0.00 4:566 +176f:568 2 0.00 4:568 +176f:59d 2 0.00 4:59d +176f:61a 1 0.00 4:61a +176f:874 1 0.00 4:874 +176f:8d8 5 0.00 4:8d8 +176f:8de 1 0.00 4:8de +176f:8e3 1 0.00 4:8e3 +176f:904 2 0.00 4:904 +176f:907 1 0.00 4:907 +176f:958 1 0.00 4:958 +176f:1122 13 0.01 4:1122 +176f:1133 1 0.00 4:1133 +176f:114c 2 0.00 4:114c +176f:117e 1 0.00 4:117e +176f:1198 1 0.00 4:1198 +176f:1318 1 0.00 4:1318 +176f:132e 1 0.00 4:132e +176f:1367 5 0.00 4:1367 +176f:136a 1 0.00 4:136a +176f:1376 4 0.00 4:1376 +176f:1379 1 0.00 4:1379 +176f:139d 1 0.00 4:139d +176f:13e9 1 0.00 4:13e9 +176f:13eb 1 0.00 4:13eb +176f:1413 1 0.00 4:1413 +176f:1a87 1 0.00 4:1a87 +176f:1f7f 1 0.00 4:1f7f +176f:1f84 2 0.00 4:1f84 +176f:1f95 1 0.00 4:1f95 +176f:2127 1 0.00 4:2127 +176f:25f8 3 0.00 4:25f8 +176f:2621 1 0.00 4:2621 +176f:2690 1 0.00 4:2690 +176f:45ea 1 0.00 4:45ea +176f:4bc0 1 0.00 4:4bc0 +176f:4e77 2 0.00 4:4e77 +176f:4e89 3 0.00 4:4e89 +176f:4e8e 3 0.00 4:4e8e +176f:4e93 1 0.00 4:4e93 +176f:4ebf 1 0.00 4:4ebf +176f:4ec4 1 0.00 4:4ec4 +176f:5044 1 0.00 4:5044 +176f:521e 2 0.00 4:521e +176f:5222 1 0.00 4:5222 +176f:5343 1 0.00 4:5343 +176f:5390 1 0.00 4:5390 +176f:53db 1 0.00 4:53db +176f:5438 1 0.00 4:5438 +176f:543f 3 0.00 4:543f +176f:544f 1 0.00 4:544f +176f:5462 2 0.00 4:5462 +176f:547c 1 0.00 4:547c +176f:5568 1 0.00 4:5568 +176f:556e 1 0.00 4:556e +176f:5612 1 0.00 4:5612 +176f:56a8 2 0.00 4:56a8 +176f:57a9 1 0.00 4:57a9 +16af:670 5 0.00 1c:670 +16af:676 1 0.00 1c:676 +16af:685 2 0.00 1c:685 +16af:68e 2 0.00 1c:68e +16af:6a1 1 0.00 1c:6a1 +16af:6a2 1 0.00 1c:6a2 +16af:6aa 1 0.00 1c:6aa +16af:6dc 1 0.00 1c:6dc +16af:6e2 1 0.00 1c:6e2 +16af:6f6 1 0.00 1c:6f6 +16af:700 1 0.00 1c:700 +16af:72e 3 0.00 1c:72e +16af:82d 3 0.00 1c:82d +16af:83f 1 0.00 1c:83f +16af:840 1 0.00 1c:840 +16af:886 5 0.00 1c:886 +16af:89b 2 0.00 1c:89b +16af:8a9 1 0.00 1c:8a9 +16af:8b2 1 0.00 1c:8b2 +16af:8d6 1 0.00 1c:8d6 +16af:8f2 10 0.01 1c:8f2 +16af:8ff 1 0.00 1c:8ff +16af:915 1 0.00 1c:915 +16af:91a 1 0.00 1c:91a +16af:923 1 0.00 1c:923 +16af:958 4 0.00 1c:958 +16af:969 1 0.00 1c:969 +16af:96e 1 0.00 1c:96e +16af:973 2 0.00 1c:973 +16af:976 2 0.00 1c:976 +16af:97d 1 0.00 1c:97d +16af:9a2 3 0.00 1c:9a2 +16af:9a4 1 0.00 1c:9a4 +16af:a3a 3 0.00 1c:a3a +16af:a95 1 0.00 1c:a95 +16af:ab2 2 0.00 1c:ab2 +16af:aba 1 0.00 1c:aba +16af:abc 2 0.00 1c:abc +16af:ad0 1 0.00 1c:ad0 +16af:ae3 1 0.00 1c:ae3 +16af:105f 1 0.00 1c:105f +16af:108d 3 0.00 1c:108d +16af:1096 1 0.00 1c:1096 +16af:11b0 1 0.00 1c:11b0 +16af:1382 1 0.00 1c:1382 +16af:1603 1 0.00 1c:1603 +16af:1606 1 0.00 1c:1606 +16af:1609 3 0.00 1c:1609 +16af:160c 1 0.00 1c:160c +16af:1a3f 1 0.00 1c:1a3f +16af:1fd0 5 0.00 1c:1fd0 +16af:23b1 1 0.00 1c:23b1 +16af:260f 3 0.00 1c:260f +16af:2624 3 0.00 1c:2624 +16af:2a84 4 0.00 1c:2a84 +16af:2a86 1 0.00 1c:2a86 +16af:2a8d 1 0.00 1c:2a8d +16af:2a96 1 0.00 1c:2a96 +16af:2a97 3 0.00 1c:2a97 +16af:2a99 1 0.00 1c:2a99 +16af:2a9c 2 0.00 1c:2a9c +16af:2aa0 2 0.00 1c:2aa0 +16af:2aac 3 0.00 1c:2aac +16af:2aad 1 0.00 1c:2aad +16af:2aae 2 0.00 1c:2aae +16af:2ab3 1 0.00 1c:2ab3 +16af:2b8d 1 0.00 1c:2b8d +16af:2c18 23 0.01 1c:2c18 +16af:2c1a 4 0.00 1c:2c1a +16af:2c1f 16 0.01 1c:2c1f +16af:2c24 1 0.00 1c:2c24 +16af:2c3c 2 0.00 1c:2c3c +16af:2c40 1 0.00 1c:2c40 +16af:2e1b 1 0.00 1c:2e1b +16af:34d9 1 0.00 1c:34d9 +16af:351b 1 0.00 1c:351b +16af:368b 4 0.00 1c:368b +16af:36a2 1 0.00 1c:36a2 +16af:36a5 1 0.00 1c:36a5 +16af:36c1 1 0.00 1c:36c1 +16af:37b9 1 0.00 1c:37b9 +16af:37ca 1 0.00 1c:37ca +16af:37ce 2 0.00 1c:37ce +16af:3825 1 0.00 1c:3825 +16af:38bb 1 0.00 1c:38bb +16af:3909 11 0.01 1c:3909 +16af:390e 1 0.00 1c:390e +16af:3916 4 0.00 1c:3916 +16af:391d 2 0.00 1c:391d +16af:3934 2 0.00 1c:3934 +16af:3936 1 0.00 1c:3936 +16af:393c 1 0.00 1c:393c +16af:394e 1 0.00 1c:394e +16af:396a 1 0.00 1c:396a +16af:397a 1 0.00 1c:397a +16af:3995 1 0.00 1c:3995 +16af:39b7 1 0.00 1c:39b7 +16af:39ed 1 0.00 1c:39ed +16af:3b96 3 0.00 1c:3b96 +16af:3b9a 1 0.00 1c:3b9a +16af:3b9f 3 0.00 1c:3b9f +16af:3bbd 1 0.00 1c:3bbd +16af:3bc7 3 0.00 1c:3bc7 +16af:3bca 4 0.00 1c:3bca +16af:3be9 2 0.00 1c:3be9 +16af:3bf2 1 0.00 1c:3bf2 +16af:3bfa 3 0.00 1c:3bfa +16af:3bfe 1 0.00 1c:3bfe +16af:3c08 1 0.00 1c:3c08 +16af:3c0d 1 0.00 1c:3c0d +16af:3c2a 1 0.00 1c:3c2a +16af:3c36 1 0.00 1c:3c36 +16af:3c97 5 0.00 1c:3c97 +16af:3c98 1 0.00 1c:3c98 +16af:3d14 1 0.00 1c:3d14 +16af:3d36 1 0.00 1c:3d36 +16af:3d53 1 0.00 1c:3d53 +16af:3dc7 1 0.00 1c:3dc7 +16a7:15a 1 0.00 1d:15a +169f:44 5 0.00 1e:44 +169f:49 1 0.00 1e:49 +169f:f9e 20 0.01 1e:f9e +169f:fa6 1 0.00 1e:fa6 +169f:fa8 1 0.00 1e:fa8 +169f:fd9 1 0.00 1e:fd9 +169f:1036 17 0.01 1e:1036 +169f:1039 2 0.00 1e:1039 +169f:1040 1 0.00 1e:1040 +169f:1048 1 0.00 1e:1048 +169f:104c 1 0.00 1e:104c +169f:1069 1 0.00 1e:1069 +169f:109d 2 0.00 1e:109d +169f:10ae 5 0.00 1e:10ae +169f:10b4 1 0.00 1e:10b4 +169f:1131 1 0.00 1e:1131 +169f:1137 1 0.00 1e:1137 + +Module Name DIBENG + + CS:EIP Samples (%) Map Offset Symbol + 447:267 1 0.00 1:267 + 447:2e7 1 0.00 1:2e7 + 447:2f8 1 0.00 1:2f8 + 447:471 1 0.00 1:471 + 447:536 1 0.00 1:536 + 447:693 1 0.00 1:693 + 447:696 57 0.03 1:696 + 447:699 3 0.00 1:699 + 447:799 372 0.19 1:799 + 447:79c 18 0.01 1:79c + 447:8e2 227 0.12 1:8e2 + 447:8e6 14 0.01 1:8e6 + 447:928 1 0.00 1:928 + 447:96b 1 0.00 1:96b + 447:9b5 1 0.00 1:9b5 + 447:9bc 1 0.00 1:9bc + 447:9bf 1 0.00 1:9bf + 447:9c3 6 0.00 1:9c3 + 447:9c5 5 0.00 1:9c5 + 447:9c7 15 0.01 1:9c7 + 447:9cb 31 0.02 1:9cb + 447:9cd 4 0.00 1:9cd + 447:9d1 6 0.00 1:9d1 + 447:9d4 6 0.00 1:9d4 + 447:9d6 5 0.00 1:9d6 + 447:af9 1 0.00 1:af9 + 447:b48 18 0.01 1:b48 + 447:b4b 1 0.00 1:b4b + 447:b4c 18 0.01 1:b4c + 447:cf1 1 0.00 1:cf1 + 447:d90 1 0.00 1:d90 + 447:daa 1 0.00 1:daa + 447:dd1 1 0.00 1:dd1 + 447:e01 1 0.00 1:e01 + 447:e06 1 0.00 1:e06 + 447:e09 1 0.00 1:e09 + 447:e46 1 0.00 1:e46 + 447:e63 1 0.00 1:e63 + 457:bc 1 0.00 3:bc + 457:c0 1 0.00 3:c0 + 457:f1 1 0.00 3:f1 + 457:348 1 0.00 3:348 + 457:385 2 0.00 3:385 + 457:38c 2 0.00 3:38c + 457:396 1 0.00 3:396 + 457:3ad 1 0.00 3:3ad + 457:458 1 0.00 3:458 + 457:47e 1 0.00 3:47e + 457:4af 1 0.00 3:4af + 457:580 1 0.00 3:580 + 457:6c4 1 0.00 3:6c4 + 457:734 1 0.00 3:734 + 457:7e2 1 0.00 3:7e2 + 457:e99 7 0.00 3:e99 + 457:203b 1 0.00 3:203b + 457:205e 1 0.00 3:205e + 457:206c 1 0.00 3:206c + 457:2098 1 0.00 3:2098 + 457:20a4 1 0.00 3:20a4 + 457:20e8 2 0.00 3:20e8 + 457:2147 1 0.00 3:2147 + 457:21c1 1 0.00 3:21c1 + 457:223c 1 0.00 3:223c + 457:2265 1 0.00 3:2265 + 457:2276 1 0.00 3:2276 + 457:227a 1 0.00 3:227a + 457:239a 1 0.00 3:239a + 457:23b3 3 0.00 3:23b3 + 457:23b6 2 0.00 3:23b6 + 457:23bd 1 0.00 3:23bd + 457:2496 1 0.00 3:2496 + 457:24c3 1 0.00 3:24c3 + 457:24c6 1 0.00 3:24c6 + 457:2571 1 0.00 3:2571 + 457:2629 1 0.00 3:2629 + 457:2673 1 0.00 3:2673 + 457:27a2 1 0.00 3:27a2 + 457:2aa5 3 0.00 3:2aa5 + 457:2aaf 2 0.00 3:2aaf + 457:2ab7 2 0.00 3:2ab7 + 457:2adc 2 0.00 3:2adc + 457:2ade 2 0.00 3:2ade + 457:2c3f 1 0.00 3:2c3f + 457:2fd2 1 0.00 3:2fd2 + 457:30b7 2 0.00 3:30b7 + 457:335f 1 0.00 3:335f + 457:34ae 1 0.00 3:34ae + 457:370f 1 0.00 3:370f + 457:383e 1 0.00 3:383e + 457:395f 1 0.00 3:395f + 457:3a1a 1 0.00 3:3a1a + 457:3b82 1 0.00 3:3b82 + 457:3c79 1 0.00 3:3c79 + 45f:b 1 0.00 4:b + 45f:434 1 0.00 4:434 + 45f:9ab 2 0.00 4:9ab + 45f:a20 1 0.00 4:a20 + 45f:b3f 1 0.00 4:b3f + 45f:b9a 1 0.00 4:b9a + 45f:b9c 1 0.00 4:b9c + 45f:ba4 3 0.00 4:ba4 + 45f:be8 1 0.00 4:be8 + 45f:dea 1 0.00 4:dea + 45f:e22 1 0.00 4:e22 + 45f:f23 1 0.00 4:f23 + 45f:f28 1 0.00 4:f28 + 45f:fa4 1 0.00 4:fa4 + 45f:fa6 1 0.00 4:fa6 + 45f:fae 1 0.00 4:fae + 45f:fe5 1 0.00 4:fe5 + 45f:ff8 1 0.00 4:ff8 + 45f:ffb 1 0.00 4:ffb + 467:12 1 0.00 5:12 + 467:22 1 0.00 5:22 + 467:84 1 0.00 5:84 + 467:db 1 0.00 5:db + 467:36e 1 0.00 5:36e + 467:3b1 1 0.00 5:3b1 + 467:bb2 1 0.00 5:bb2 + 467:ced 1 0.00 5:ced + 467:d04 1 0.00 5:d04 + 467:f6c 2 0.00 5:f6c + 467:137d 1 0.00 5:137d + 467:1843 1 0.00 5:1843 + 467:2a34 1 0.00 5:2a34 + 467:2a65 17 0.01 5:2a65 + 467:2bd3 7 0.00 5:2bd3 + 467:2bd6 21 0.01 5:2bd6 + 467:2bda 1 0.00 5:2bda + 467:2bdc 2 0.00 5:2bdc + 467:2bde 2 0.00 5:2bde + 467:2be1 7 0.00 5:2be1 + 467:2be5 1 0.00 5:2be5 + 467:2be7 4 0.00 5:2be7 + 467:2be9 1 0.00 5:2be9 + 467:2bec 6 0.00 5:2bec + 467:2bef 13 0.01 5:2bef + 467:2bf3 43 0.02 5:2bf3 + 467:2bf7 9 0.00 5:2bf7 + 467:2bf9 4 0.00 5:2bf9 + 467:2bfb 1 0.00 5:2bfb + 467:2c02 6 0.00 5:2c02 + 467:2c04 5 0.00 5:2c04 + 467:2c06 2 0.00 5:2c06 + 467:2c09 8 0.00 5:2c09 + 467:2c10 8 0.00 5:2c10 + 467:2c14 3 0.00 5:2c14 + 467:2c5a 1 0.00 5:2c5a + 467:2dc6 1 0.00 5:2dc6 + 467:3559 1 0.00 5:3559 + 467:3570 1 0.00 5:3570 + 467:3806 1 0.00 5:3806 + 467:383c 1 0.00 5:383c + 467:39f0 1 0.00 5:39f0 + 467:3bd1 1 0.00 5:3bd1 + 467:3d81 1 0.00 5:3d81 + 467:4304 1 0.00 5:4304 + 467:44db 1 0.00 5:44db + 467:4957 5 0.00 5:4957 + 467:4970 1 0.00 5:4970 + 467:499b 1 0.00 5:499b + 467:5512 1 0.00 5:5512 + 467:61a6 1 0.00 5:61a6 + 46f:509 1 0.00 6:509 + 46f:56d 1 0.00 6:56d + 46f:578 1 0.00 6:578 + 46f:5c0 1 0.00 6:5c0 + 46f:60d 1 0.00 6:60d + 46f:616 1 0.00 6:616 + 46f:885 1 0.00 6:885 + 46f:89b 1 0.00 6:89b + 46f:912 1 0.00 6:912 + 46f:bdf 1 0.00 6:bdf + 46f:cb4 1 0.00 6:cb4 + 46f:102d 1 0.00 6:102d + 46f:1252 1 0.00 6:1252 + 46f:12d0 1 0.00 6:12d0 + 4b7:65 1 0.00 f:65 + 4b7:1cd 1 0.00 f:1cd + 4b7:456 1 0.00 f:456 + 4b7:5b1 1 0.00 f:5b1 + +Module Name SYSTEM + + CS:EIP Samples (%) Map Offset Symbol + 1df:46 1 0.00 1:46 + 1df:17c 1 0.00 1:17c + 1df:1c5 15 0.01 1:1c5 + 1df:1c6 3 0.00 1:1c6 + 1df:1cb 10 0.01 1:1cb + 1df:1cf 10 0.01 1:1cf + 1df:1d9 2 0.00 1:1d9 + 1df:1df 2 0.00 1:1df + 1df:1e1 4 0.00 1:1e1 + 1df:1e4 4 0.00 1:1e4 + 1df:230 1 0.00 1:230 + +Module Name DISPLAY + + CS:EIP Samples (%) Map Offset Symbol + 30f:30 4 0.00 2:30 + 30f:16f 1 0.00 2:16f + 30f:2f6 1 0.00 2:2f6 + 30f:4ac 4 0.00 2:4ac + 30f:4b0 3 0.00 2:4b0 + 30f:4c4 1 0.00 2:4c4 + 30f:9d6 1 0.00 2:9d6 + 30f:a87 1 0.00 2:a87 + 30f:b18 2 0.00 2:b18 + 30f:b36 1 0.00 2:b36 + 30f:b50 1 0.00 2:b50 + 30f:b64 1 0.00 2:b64 + 30f:b76 1 0.00 2:b76 + 30f:1260 1 0.00 2:1260 + 30f:128b 1 0.00 2:128b + 30f:15e0 1 0.00 2:15e0 + 30f:174d 1 0.00 2:174d + 30f:17a7 1 0.00 2:17a7 + 30f:1dcc 1 0.00 2:1dcc + 30f:1de0 2 0.00 2:1de0 + 30f:2054 1 0.00 2:2054 + 30f:2b39 2 0.00 2:2b39 + 30f:2f48 1 0.00 2:2f48 + 30f:375c 3 0.00 2:375c + 30f:377f 2 0.00 2:377f + 30f:4f06 1 0.00 2:4f06 + 30f:56b0 3 0.00 2:56b0 + 30f:56cb 1 0.00 2:56cb + 30f:56e2 1 0.00 2:56e2 + 30f:56ec 1 0.00 2:56ec + 30f:56ee 1 0.00 2:56ee + 30f:5704 1 0.00 2:5704 + 30f:572d 1 0.00 2:572d + 30f:5754 1 0.00 2:5754 + 30f:5977 1 0.00 2:5977 + 30f:5b13 1 0.00 2:5b13 + 30f:5b15 1 0.00 2:5b15 + 30f:5b4c 1 0.00 2:5b4c + 30f:5b63 1 0.00 2:5b63 + 30f:5b8a 1 0.00 2:5b8a + 30f:5bb6 1 0.00 2:5bb6 + 30f:5beb 1 0.00 2:5beb + 30f:5c6c 37 0.02 2:5c6c + 30f:5d10 1 0.00 2:5d10 + 30f:6847 1 0.00 2:6847 + 30f:711f 7 0.00 2:711f + 317:d05 1 0.00 3:d05 + 317:d58 1 0.00 3:d58 + 317:d70 1 0.00 3:d70 + 317:e30 1 0.00 3:e30 + 317:f1e 1 0.00 3:f1e + 317:10ca 1 0.00 3:10ca + 317:10cf 2 0.00 3:10cf + 317:10f1 2 0.00 3:10f1 + 317:10f4 5 0.00 3:10f4 + 317:10fe 1 0.00 3:10fe + 317:111c 1 0.00 3:111c + 317:1294 1 0.00 3:1294 + 317:130c 1 0.00 3:130c + 317:1366 1 0.00 3:1366 + 317:137f 1 0.00 3:137f + 317:138b 1 0.00 3:138b + 317:1af6 1 0.00 3:1af6 + 317:26e3 1 0.00 3:26e3 + 317:2bfc 1 0.00 3:2bfc + 317:30f5 1 0.00 3:30f5 + 317:31c9 1 0.00 3:31c9 + +Module Name DMBRDOBJ + + CS:EIP Samples (%) Map Offset Symbol + 367:143a 1 0.00 1:143a + 367:1468 1 0.00 1:1468 + +Module Name DMDRWOBJ + + CS:EIP Samples (%) Map Offset Symbol + 397:400 3 0.00 1:400 + 397:407 1 0.00 1:407 + 397:40f 78 0.04 1:40f + 397:481 1 0.00 1:481 + 397:486 1 0.00 1:486 + 397:48f 2 0.00 1:48f + 397:493 1 0.00 1:493 + 397:4b2 1 0.00 1:4b2 + 397:4b7 1 0.00 1:4b7 + 397:4dc 1 0.00 1:4dc + 397:4ee 1 0.00 1:4ee + 397:4f4 1 0.00 1:4f4 + 397:7fa 1 0.00 1:7fa + 397:930 1 0.00 1:930 + 397:a20 1 0.00 1:a20 + 397:b07 8 0.00 1:b07 + 397:b0b 1 0.00 1:b0b + 397:b1e 1 0.00 1:b1e + 397:b34 12 0.01 1:b34 + 397:b38 3 0.00 1:b38 + 397:b4e 2 0.00 1:b4e + 397:b52 1 0.00 1:b52 + 397:1484 1 0.00 1:1484 + 397:1d56 3 0.00 1:1d56 + 397:1d8d 1 0.00 1:1d8d + 397:1df4 1 0.00 1:1df4 + 397:1fd1 4 0.00 1:1fd1 + 397:2047 1 0.00 1:2047 + 397:2087 1 0.00 1:2087 + 397:20a6 1 0.00 1:20a6 + 397:20eb 1 0.00 1:20eb + 397:20ed 1 0.00 1:20ed + 397:20f3 47 0.02 1:20f3 + 397:20fa 1 0.00 1:20fa + 397:20fe 1 0.00 1:20fe + 397:2122 1 0.00 1:2122 + 397:2136 1 0.00 1:2136 + 397:2144 2 0.00 1:2144 + 397:214e 1 0.00 1:214e + 397:2165 2 0.00 1:2165 + 397:2169 7 0.00 1:2169 + 397:216e 4 0.00 1:216e + 397:2170 1 0.00 1:2170 + 397:217b 2 0.00 1:217b + 397:218a 2 0.00 1:218a + 397:2196 1 0.00 1:2196 + 397:21d8 1 0.00 1:21d8 + 397:21dc 1 0.00 1:21dc + 397:2210 6 0.00 1:2210 + 397:222a 1 0.00 1:222a + 397:227f 2 0.00 1:227f + 397:2282 1 0.00 1:2282 + +Module Name MSGSRV32 + + CS:EIP Samples (%) Map Offset Symbol +1f2f:1d 1 0.00 1:1d + +Module Name CSPMAN + + CS:EIP Samples (%) Map Offset Symbol +1a67:38ab 31 0.02 1:38ab + +Module Name COMMCTRL + + CS:EIP Samples (%) Map Offset Symbol +1c9f:27 1 0.00 1:27 + +Module Name vs3xxx + + CS:EIP Samples (%) Map Offset Symbol + 28:c3434542 1 0.00 1:542 + +Module Name SB16 + + CS:EIP Samples (%) Map Offset Symbol + 28:c1035275 1 0.00 1:4361 + 28:c11b5fca 1 0.00 4:26ee + +Module Name DSVXD + + CS:EIP Samples (%) Map Offset Symbol + 28:c103ca39 1 0.00 1:591 + +Module Name CDFS + + CS:EIP Samples (%) Map Offset Symbol + 28:c1040df4 489 0.25 1:0 + 28:c1040df8 642 0.33 1:4 + 28:c1040dfb 33 0.02 1:7 + 28:c1040e3f 384 0.20 1:4b + 28:c1040e40 36 0.02 1:4c + 28:c1040f24 2 0.00 1:130 + 28:c1040f51 1 0.00 1:15d + 28:c1040f88 1 0.00 1:194 + 28:c104104b 2 0.00 1:257 + 28:c104105d 1 0.00 1:269 + 28:c10410fd 3 0.00 1:309 + 28:c1041105 1 0.00 1:311 + 28:c11e267c 3 0.00 3:3bd0 + 28:c11e26ac 5 0.00 3:3c00 + 28:c11e2c46 1 0.00 3:419a + 28:c11e2c48 1 0.00 3:419c + 28:c11e2c5c 1 0.00 3:41b0 + 28:c11e329c 3 0.00 3:47f0 + 28:c11e3310 2 0.00 3:4864 + 28:c11e3390 1 0.00 3:48e4 + 28:c11e404c 1 0.00 3:55a0 + 28:c11e409c 2 0.00 3:55f0 + 28:c11e40b6 1 0.00 3:560a + 28:c11e40bc 1 0.00 3:5610 + 28:c11e40df 1 0.00 3:5633 + 28:c11e411d 1 0.00 3:5671 + 28:c11e4120 1 0.00 3:5674 + 28:c11e413c 3 0.00 3:5690 + 28:c11e414b 7 0.00 3:569f + 28:c11e414d 1 0.00 3:56a1 + 28:c11e415f 1 0.00 3:56b3 + 28:c11e4174 1 0.00 3:56c8 + 28:c11e41de 2 0.00 3:5732 + 28:c11e41eb 1 0.00 3:573f + 28:c11e41fc 1 0.00 3:5750 + 28:c11e4411 1 0.00 3:5965 + 28:c11e4425 1 0.00 3:5979 + 28:c11e4440 1 0.00 3:5994 + 28:c11e4475 1 0.00 3:59c9 + 28:c11e4477 1 0.00 3:59cb + 28:c11e46bb 1 0.00 3:5c0f + 28:c11e46fc 1 0.00 3:5c50 + 28:c11e4787 1 0.00 3:5cdb + 28:c11e4797 2 0.00 3:5ceb + 28:c11e47b1 1 0.00 3:5d05 + 28:c11e4846 1 0.00 3:5d9a + 28:c11e492c 1 0.00 3:5e80 + 28:c11e49d7 1 0.00 3:5f2b + 28:c11e49de 1 0.00 3:5f32 + 28:c11e49e4 1 0.00 3:5f38 + 28:c11e4a44 1 0.00 3:5f98 + 28:c11e4a46 1 0.00 3:5f9a + 28:c11e4a59 3 0.00 3:5fad + 28:c11e4a72 1 0.00 3:5fc6 + 28:c11e4a77 1 0.00 3:5fcb + 28:c11e4a97 1 0.00 3:5feb + 28:c11e4b0f 1 0.00 3:6063 + 28:c11e4eac 1 0.00 3:6400 + 28:c11e4ed2 2 0.00 3:6426 + 28:c11e4f62 1 0.00 3:64b6 + 28:c11e5057 1 0.00 3:65ab + 28:c11e522f 1 0.00 3:6783 + 28:c11e524d 1 0.00 3:67a1 + 28:c11e529c 2 0.00 3:67f0 + 28:c11e529f 1 0.00 3:67f3 + 28:c11e5403 1 0.00 3:6957 + 28:c11e5443 1 0.00 3:6997 + 28:c11e5682 3 0.00 3:6bd6 + 28:c11e5b3c 2 0.00 3:7090 + 28:c11e5b3d 1 0.00 3:7091 + 28:c11e5b47 1 0.00 3:709b + 28:c11e5b68 1 0.00 3:70bc + 28:c11e5b6f 2 0.00 3:70c3 + 28:c11e5b76 1 0.00 3:70ca + 28:c11e5c50 1 0.00 3:71a4 + 28:c11e5c55 1 0.00 3:71a9 + 28:c11e5e2f 1 0.00 3:7383 + 28:c11e5f7c 3 0.00 3:74d0 + 28:c11e5f84 1 0.00 3:74d8 + 28:c11e5f91 1 0.00 3:74e5 + 28:c11e6021 1 0.00 3:7575 + 28:c11e62e0 4 0.00 3:7834 + 28:c11e62fd 5 0.00 3:7851 + 28:c11e638c 1 0.00 3:78e0 + 28:c11e63d4 1 0.00 3:7928 + 28:c11e640f 1 0.00 3:7963 + 28:c11e6421 1 0.00 3:7975 + 28:c11e646d 1 0.00 3:79c1 + 28:c11e649e 1 0.00 3:79f2 + 28:c11e64ee 1 0.00 3:7a42 + 28:c11e6558 1 0.00 3:7aac + 28:c11e65ec 1 0.00 3:7b40 + 28:c11e667c 1 0.00 3:7bd0 + 28:c11e668d 1 0.00 3:7be1 + 28:c11e6690 1 0.00 3:7be4 + 28:c11e6692 1 0.00 3:7be6 + 28:c11e66cc 1 0.00 3:7c20 + 28:c11e6730 1 0.00 3:7c84 + 28:c11e6733 2 0.00 3:7c87 + 28:c11e675c 2 0.00 3:7cb0 + 28:c11e6771 1 0.00 3:7cc5 + 28:c11e677c 1 0.00 3:7cd0 + 28:c11e678a 1 0.00 3:7cde + 28:c11e6792 1 0.00 3:7ce6 + 28:c11e68a9 1 0.00 3:7dfd + 28:c11e6bec 1 0.00 3:8140 + 28:c11e6c1c 2 0.00 3:8170 + 28:c11e6c3c 2 0.00 3:8190 + 28:c11e6c45 1 0.00 3:8199 + 28:c11e6c57 1 0.00 3:81ab + 28:c11e6ca4 1 0.00 3:81f8 + 28:c11e6e29 1 0.00 3:837d + 28:c11e702c 1 0.00 3:8580 + 28:c11e70ae 1 0.00 3:8602 + 28:c102c8d5 1 0.00 4:a1 + 28:c102c8db 67 0.03 4:a7 + +Module Name CDTSD + + CS:EIP Samples (%) Map Offset Symbol + 28:c102ca3e 1 0.00 1:86 + +Module Name CDVSD + + CS:EIP Samples (%) Map Offset Symbol + 28:c103d691 2 0.00 1:379 + 28:c103d6b7 1 0.00 1:39f + 28:c103d6ba 1 0.00 1:3a2 + 28:c103d82f 1 0.00 1:517 + 28:c103e145 1 0.00 1:e2d + 28:c11e8ee1 1 0.00 3:3cd + +Module Name DiskVSD + + CS:EIP Samples (%) Map Offset Symbol + 28:c104191c 1 0.00 1:40 + 28:c1041bd4 2 0.00 1:2f8 + 28:c1041c5d 1 0.00 1:381 + +Module Name voltrack + + CS:EIP Samples (%) Map Offset Symbol + 28:c103e41a 1 0.00 1:112 + 28:c103e47c 1 0.00 1:174 + 28:c103e590 1 0.00 1:288 + 28:c103e7a1 1 0.00 1:499 + 28:c103e80a 1 0.00 1:502 + 28:c11ec13c 1 0.00 4:998 + 28:c11ec22d 1 0.00 4:a89 + +Module Name scsi1hlp + + CS:EIP Samples (%) Map Offset Symbol + 28:c11ec6bc 1 0.00 3:40c + 28:c11ec6d7 1 0.00 3:427 + 28:c11ec6e5 1 0.00 3:435 + 28:c11ec947 1 0.00 3:697 + +Module Name EL90X + + CS:EIP Samples (%) Map Offset Symbol + 28:c10499f4 1 0.00 1:1584 + 28:c104ddf0 1 0.00 1:5980 + 28:c104def8 2 0.00 1:5a88 + 28:c104df6f 1 0.00 1:5aff + 28:c104e077 1 0.00 1:5c07 + 28:c104e2d2 1 0.00 1:5e62 + 28:c7644b16 1 0.00 2:7e2 + +Module Name NETBEUI + + CS:EIP Samples (%) Map Offset Symbol + 28:c1052905 1 0.00 1:35d5 + 28:c105297c 1 0.00 1:364c + 28:c1055b25 1 0.00 1:67f5 + +Module Name MITSVSD + + CS:EIP Samples (%) Map Offset Symbol + 28:c1046d7c 1 0.00 1:112c + 28:c1046f36 1 0.00 1:12e6 + +Module Name VTDI + + CS:EIP Samples (%) Map Offset Symbol + 28:c10589a2 1 0.00 1:96 + +Module Name VIP + + CS:EIP Samples (%) Map Offset Symbol + 28:c105d620 1 0.00 1:367c + 28:c105d66c 1 0.00 1:36c8 + 28:c105eb83 1 0.00 1:4bdf + 28:c105f4cf 1 0.00 1:552b + 28:c1060839 1 0.00 1:6895 + 28:c106100c 1 0.00 1:7068 + +Module Name MSTCP + + CS:EIP Samples (%) Map Offset Symbol + 28:c1066fdf 1 0.00 1:453 + 28:c106710c 1 0.00 1:580 + +Module Name VNBT + + CS:EIP Samples (%) Map Offset Symbol + 28:c1085828 1 0.00 1:ff5c + +Module Name VSERVER + + CS:EIP Samples (%) Map Offset Symbol + 28:c109404c 4 0.00 1:8b54 + 28:c1094054 6 0.00 1:8b5c + 28:c109443f 708 0.37 1:8f47 + 28:c1094445 56 0.03 1:8f4d + 28:c1094446 23 0.01 1:8f4e + +Module Name SCSIPORT + + CS:EIP Samples (%) Map Offset Symbol + 28:c10a0288 5 0.00 1:0 + 28:c10a028d 13 0.01 1:5 + 28:c10a0314 1 0.00 1:8c + 28:c10a039e 1 0.00 1:116 + 28:c10a03e3 1 0.00 1:15b + 28:c10a03e5 531 0.28 1:15d + 28:c10a0457 1 0.00 1:1cf + 28:c10a045a 2 0.00 1:1d2 + 28:c10a05c5 1 0.00 1:33d + 28:c10a06be 1 0.00 1:436 + 28:c10a06c7 3 0.00 1:43f + 28:c10a0781 2 0.00 1:4f9 + 28:c10a0827 3 0.00 1:59f + 28:c10a086d 1 0.00 1:5e5 + 28:c10a0a1c 11 0.01 1:794 + 28:c10a0a1e 2 0.00 1:796 + 28:c10a0a4a 1 0.00 1:7c2 + 28:c10a0a55 2 0.00 1:7cd + 28:c10a0cbc 11 0.01 1:a34 + 28:c10a0cff 2 0.00 1:a77 + +Module Name ideatapi + + CS:EIP Samples (%) Map Offset Symbol + 28:c34bcaf6 1 0.00 1:16f6 + 28:c34bcba6 1 0.00 1:17a6 + 28:c34bcbae 1 0.00 1:17ae + 28:c34bcbe9 1 0.00 1:17e9 + 28:c34bcd29 1 0.00 1:1929 + 28:c34bcdbe 1 0.00 1:19be + 28:c34bce43 1 0.00 1:1a43 + 28:c34bce6d 1 0.00 1:1a6d + 28:c34bceb9 1 0.00 1:1ab9 + 28:c34bcecc 1 0.00 1:1acc + 28:c34bcfa4 1 0.00 1:1ba4 + 28:c34bd0a9 3 0.00 1:1ca9 + 28:c34bd138 1 0.00 1:1d38 + 28:c34bd1f8 1 0.00 1:1df8 + 28:c34bd1ff 1 0.00 1:1dff + 28:c34bd20e 1 0.00 1:1e0e + 28:c34bd426 1 0.00 1:2026 + 28:c34bd42a 1 0.00 1:202a + 28:c34bd42d 1 0.00 1:202d + 28:c34bd439 1 0.00 1:2039 + 28:c34bd46c 1 0.00 1:206c + 28:c34bd6e7 1 0.00 1:22e7 + 28:c34bdb1f 1 0.00 1:271f + 28:c34bde17 1 0.00 1:2a17 + 28:c34be332 1 0.00 1:2f32 + 28:c34be4ff 1 0.00 1:30ff + 28:c34be542 1 0.00 1:3142 + 28:c34c0ba6 1 0.00 1:57a6 + 28:c34c0de7 1 0.00 1:59e7 + 28:c34c430e 2 0.00 1:8f0e + 28:c34c4326 1 0.00 1:8f26 + 28:c34c4368 1 0.00 1:8f68 + +Module Name kernel32 + + CS:EIP Samples (%) Map Offset Symbol + 137:bff710e1 2 0.00 1:e1 + 137:bff710e3 1 0.00 1:e3 + 137:bff710f0 1 0.00 1:f0 + 137:bff710fe 1 0.00 1:fe + 137:bff7114c 1 0.00 1:14c + 137:bff71170 1 0.00 1:170 + 137:bff71178 1 0.00 1:178 + 137:bff7117e 2 0.00 1:17e + 137:bff711b6 1 0.00 1:1b6 + 137:bff711be 1 0.00 1:1be + 137:bff711cf 2 0.00 1:1cf + 137:bff712b9 2 0.00 1:2b9 + 137:bff712c5 13 0.01 1:2c5 + 137:bff713d4 14 0.01 1:3d4 + 137:bff713d8 6 0.00 1:3d8 + 137:bff713db 3 0.00 1:3db + 137:bff71511 17 0.01 1:511 + 137:bff71513 9 0.00 1:513 + 137:bff71515 5 0.00 1:515 + 137:bff71517 3 0.00 1:517 + 137:bff7151a 1 0.00 1:51a + 137:bff7151d 2 0.00 1:51d + 137:bff71520 1 0.00 1:520 + 137:bff71522 1 0.00 1:522 + 137:bff71527 4 0.00 1:527 + 137:bff71528 2 0.00 1:528 + 137:bff7152b 5 0.00 1:52b + 137:bff71535 8 0.00 1:535 + 137:bff7153b 3 0.00 1:53b + 137:bff71540 8 0.00 1:540 + 137:bff71548 1 0.00 1:548 + 137:bff7154a 2 0.00 1:54a + 137:bff71550 1 0.00 1:550 + 137:bff71556 4 0.00 1:556 + 137:bff7155c 4 0.00 1:55c + 137:bff71566 2 0.00 1:566 + 137:bff7156b 11 0.01 1:56b + 137:bff71571 1 0.00 1:571 + 137:bff71576 1 0.00 1:576 + 137:bff7157d 2 0.00 1:57d + 137:bff7158d 2 0.00 1:58d + 137:bff71590 1 0.00 1:590 + 137:bff715a1 1 0.00 1:5a1 + 137:bff715a6 2 0.00 1:5a6 + 137:bff715a7 2 0.00 1:5a7 + 137:bff715a9 2 0.00 1:5a9 + 137:bff715af 11 0.01 1:5af + 137:bff715d6 16 0.01 1:5d6 + 137:bff715d9 2 0.00 1:5d9 + 137:bff715de 1 0.00 1:5de + 137:bff715e2 13 0.01 1:5e2 + 137:bff715e5 2 0.00 1:5e5 + 137:bff715e8 2 0.00 1:5e8 + 137:bff715eb 2 0.00 1:5eb + 137:bff715ee 5 0.00 1:5ee + 137:bff715f0 2 0.00 1:5f0 + 137:bff715f8 2 0.00 1:5f8 + 137:bff715fc 1 0.00 1:5fc + 137:bff715fe 1 0.00 1:5fe + 137:bff71607 3 0.00 1:607 + 137:bff71611 1 0.00 1:611 + 137:bff7161a 3 0.00 1:61a + 137:bff71626 2 0.00 1:626 + 137:bff7162b 8 0.00 1:62b + 137:bff71639 3 0.00 1:639 + 137:bff71644 52 0.03 1:644 + 137:bff71655 2 0.00 1:655 + 137:bff718e2 9 0.00 1:8e2 + 137:bff718e7 1 0.00 1:8e7 + 137:bff718e9 1 0.00 1:8e9 + 137:bff718ef 1 0.00 1:8ef + 137:bff718f7 2 0.00 1:8f7 + 137:bff718fc 4 0.00 1:8fc + 137:bff71906 1 0.00 1:906 + 137:bff71907 5 0.00 1:907 + 137:bff71916 3 0.00 1:916 + 137:bff71918 1 0.00 1:918 + 137:bff7191e 2 0.00 1:91e + 137:bff71923 7 0.00 1:923 + 137:bff719c4 8 0.00 1:9c4 + 137:bff719c7 2 0.00 1:9c7 + 137:bff719c8 2 0.00 1:9c8 + 137:bff719cc 1 0.00 1:9cc + 137:bff719d1 2 0.00 1:9d1 + 137:bff719d7 4 0.00 1:9d7 + 137:bff719dd 1 0.00 1:9dd + 137:bff719eb 3 0.00 1:9eb + 137:bff719f0 2 0.00 1:9f0 + 137:bff719f6 2 0.00 1:9f6 + 137:bff719f9 4 0.00 1:9f9 + 137:bff71a0c 2 0.00 1:a0c + 137:bff71a22 1 0.00 1:a22 + 137:bff71a25 2 0.00 1:a25 + 137:bff71a28 2 0.00 1:a28 + 137:bff71a3a 4 0.00 1:a3a + 137:bff71a3f 1 0.00 1:a3f + 137:bff71a49 4 0.00 1:a49 + 137:bff71a51 1 0.00 1:a51 + 137:bff71a53 1 0.00 1:a53 + 137:bff71a56 2 0.00 1:a56 + 137:bff71a5e 16 0.01 1:a5e + 137:bff71a64 3 0.00 1:a64 + 137:bff71a6b 1 0.00 1:a6b + 137:bff71a72 3 0.00 1:a72 + 137:bff71a73 1 0.00 1:a73 + 137:bff71a79 3 0.00 1:a79 + 137:bff71a7d 1 0.00 1:a7d + 137:bff71a84 1 0.00 1:a84 + 137:bff71a89 1 0.00 1:a89 + 137:bff71a92 2 0.00 1:a92 + 137:bff71a97 5 0.00 1:a97 + 137:bff71aa2 1 0.00 1:aa2 + 137:bff71ab3 1 0.00 1:ab3 + 137:bff71ab5 2 0.00 1:ab5 + 137:bff71ab6 2 0.00 1:ab6 + 137:bff71ab7 2 0.00 1:ab7 + 137:bff71abb 1 0.00 1:abb + 137:bff71bc1 2 0.00 1:bc1 + 137:bff71bca 2 0.00 1:bca + 137:bff71bd9 1 0.00 1:bd9 + 137:bff71bdc 5 0.00 1:bdc + 137:bff71be6 1 0.00 1:be6 + 137:bff71bec 1 0.00 1:bec + 137:bff71bf5 2 0.00 1:bf5 + 137:bff71bff 4 0.00 1:bff + 137:bff71ec8 1 0.00 1:ec8 + 137:bff71f3c 4 0.00 1:f3c + 137:bff71f46 2 0.00 1:f46 + 137:bff71f4a 1 0.00 1:f4a + 137:bff71f53 6 0.00 1:f53 + 137:bff71f5a 1 0.00 1:f5a + 137:bff71f6d 1 0.00 1:f6d + 137:bff71f74 1 0.00 1:f74 + 137:bff71f7e 2 0.00 1:f7e + 137:bff71f83 1 0.00 1:f83 + 137:bff71f86 1 0.00 1:f86 + 137:bff71f88 2 0.00 1:f88 + 137:bff71f8a 2 0.00 1:f8a + 137:bff71f98 4 0.00 1:f98 + 137:bff71fb0 2 0.00 1:fb0 + 137:bff71fb4 1 0.00 1:fb4 + 137:bff71fbb 1 0.00 1:fbb + 137:bff71fbe 2 0.00 1:fbe + 137:bff71fc6 2 0.00 1:fc6 + 137:bff72436 2 0.00 1:1436 + 137:bff7243e 1 0.00 1:143e + 137:bff72442 1 0.00 1:1442 + 137:bff72448 1 0.00 1:1448 + 137:bff7244e 3 0.00 1:144e + 137:bff72791 7 0.00 1:1791 + 137:bff72794 3 0.00 1:1794 + 137:bff72796 5 0.00 1:1796 + 137:bff7279e 1 0.00 1:179e + 137:bff727a3 2 0.00 1:17a3 + 137:bff727a9 1 0.00 1:17a9 + 137:bff727c5 1 0.00 1:17c5 + 137:bff728d0 5 0.00 1:18d0 + 137:bff728de 1 0.00 1:18de + 137:bff728e7 4 0.00 1:18e7 + 137:bff728eb 2 0.00 1:18eb + 137:bff728f1 2 0.00 1:18f1 + 137:bff728f9 2 0.00 1:18f9 + 137:bff72906 2 0.00 1:1906 + 137:bff72910 1 0.00 1:1910 + 137:bff7291e 1 0.00 1:191e + 137:bff72925 2 0.00 1:1925 + 137:bff7292d 7 0.00 1:192d + 137:bff72930 3 0.00 1:1930 + 137:bff72938 6 0.00 1:1938 + 137:bff7293a 1 0.00 1:193a + 137:bff72964 11 0.01 1:1964 + 137:bff72966 3 0.00 1:1966 + 137:bff72969 2 0.00 1:1969 + 137:bff7296c 1 0.00 1:196c + 137:bff7296e 2 0.00 1:196e + 137:bff72971 5 0.00 1:1971 + 137:bff72976 4 0.00 1:1976 + 137:bff7297a 3 0.00 1:197a + 137:bff72999 1 0.00 1:1999 + 137:bff7299d 1 0.00 1:199d + 137:bff729a8 3 0.00 1:19a8 + 137:bff72a57 6 0.00 1:1a57 + 137:bff72a6e 4 0.00 1:1a6e + 137:bff72a71 1 0.00 1:1a71 + 137:bff72a7c 1 0.00 1:1a7c + 137:bff72abb 3 0.00 1:1abb + 137:bff72ac5 1 0.00 1:1ac5 + 137:bff72ace 1 0.00 1:1ace + 137:bff72adc 2 0.00 1:1adc + 137:bff72ade 1 0.00 1:1ade + 137:bff72b12 2 0.00 1:1b12 + 137:bff72b1e 1 0.00 1:1b1e + 137:bff72b20 2 0.00 1:1b20 + 137:bff72b22 1 0.00 1:1b22 + 137:bff72b2a 1 0.00 1:1b2a + 137:bff72b3a 1 0.00 1:1b3a + 137:bff72b3f 1 0.00 1:1b3f + 137:bff72c5b 1 0.00 1:1c5b + 137:bff72c64 1 0.00 1:1c64 + 137:bff72c73 1 0.00 1:1c73 + 137:bff732fb 1 0.00 1:22fb + 137:bff7331c 1 0.00 1:231c + 137:bff73625 12 0.01 1:2625 + 137:bff73628 1 0.00 1:2628 + 137:bff73635 1 0.00 1:2635 + 137:bff73647 4 0.00 1:2647 + 137:bff7364d 2 0.00 1:264d + 137:bff73650 2 0.00 1:2650 + 137:bff73655 2 0.00 1:2655 + 137:bff73663 1 0.00 1:2663 + 137:bff73667 1 0.00 1:2667 + 137:bff7366c 1 0.00 1:266c + 137:bff7380c 1 0.00 1:280c + 137:bff73df6 2 0.00 1:2df6 + 137:bff73eb6 1 0.00 1:2eb6 + 137:bff73ef6 1 0.00 1:2ef6 + 137:bff74049 1 0.00 1:3049 + 137:bff74220 1 0.00 1:3220 + 137:bff74222 1 0.00 1:3222 + 137:bff74230 16 0.01 1:3230 + 137:bff74232 8 0.00 1:3232 + 137:bff74233 8 0.00 1:3233 + 137:bff7423a 5 0.00 1:323a + 137:bff7423c 15 0.01 1:323c + 137:bff74242 3 0.00 1:3242 + 137:bff74244 3 0.00 1:3244 + 137:bff74247 11 0.01 1:3247 + 137:bff7424a 1 0.00 1:324a + 137:bff7424d 26 0.01 1:324d + 137:bff7424f 7 0.00 1:324f + 137:bff74255 4 0.00 1:3255 + 137:bff74256 4 0.00 1:3256 + 137:bff74257 1 0.00 1:3257 + 137:bff74269 10 0.01 1:3269 + 137:bff7426d 10 0.01 1:326d + 137:bff74277 10 0.01 1:3277 + 137:bff7427b 14 0.01 1:327b + 137:bff74282 3 0.00 1:3282 + 137:bff74284 12 0.01 1:3284 + 137:bff7428a 3 0.00 1:328a + 137:bff7428c 4 0.00 1:328c + 137:bff74290 3 0.00 1:3290 + 137:bff74292 1 0.00 1:3292 + 137:bff74297 27 0.01 1:3297 + 137:bff7429e 6 0.00 1:329e + 137:bff742a8 10 0.01 1:32a8 + 137:bff742aa 3 0.00 1:32aa + 137:bff742ad 1 0.00 1:32ad + 137:bff742af 11 0.01 1:32af + 137:bff742b3 2 0.00 1:32b3 + 137:bff742b5 2 0.00 1:32b5 + 137:bff742b7 14 0.01 1:32b7 + 137:bff742bd 1 0.00 1:32bd + 137:bff742bf 8 0.00 1:32bf + 137:bff742c1 4 0.00 1:32c1 + 137:bff742c3 54 0.03 1:32c3 + 137:bff742c5 1 0.00 1:32c5 + 137:bff742e0 1 0.00 1:32e0 + 137:bff742ec 2 0.00 1:32ec + 137:bff742f1 18 0.01 1:32f1 + 137:bff74320 1 0.00 1:3320 + 137:bff74340 2 0.00 1:3340 + 137:bff74346 1 0.00 1:3346 + 137:bff7434f 8 0.00 1:334f + 137:bff74351 8 0.00 1:3351 + 137:bff74357 2 0.00 1:3357 + 137:bff74358 3 0.00 1:3358 + 137:bff7436d 1 0.00 1:336d + 137:bff74371 4 0.00 1:3371 + 137:bff74376 1 0.00 1:3376 + 137:bff74393 1 0.00 1:3393 + 137:bff74398 2 0.00 1:3398 + 137:bff743a0 1 0.00 1:33a0 + 137:bff743a7 1 0.00 1:33a7 + 137:bff743ad 5 0.00 1:33ad + 137:bff743af 1 0.00 1:33af + 137:bff743d1 1 0.00 1:33d1 + 137:bff743e1 1 0.00 1:33e1 + 137:bff7453c 1 0.00 1:353c + 137:bff74551 2 0.00 1:3551 + 137:bff74586 1 0.00 1:3586 + 137:bff745a3 1 0.00 1:35a3 + 137:bff74608 1 0.00 1:3608 + 137:bff7462c 1 0.00 1:362c + 137:bff746df 1 0.00 1:36df + 137:bff74793 1 0.00 1:3793 + 137:bff748c8 3 0.00 1:38c8 + 137:bff74966 5 0.00 1:3966 + 137:bff7496e 8 0.00 1:396e + 137:bff74b5d 1 0.00 1:3b5d + 137:bff74b6d 1 0.00 1:3b6d + 137:bff7525d 1 0.00 1:425d + 137:bff7571b 1 0.00 1:471b + 137:bff7572e 1 0.00 1:472e + 137:bff75747 1 0.00 1:4747 + 137:bff7574a 2 0.00 1:474a + 137:bff7574d 1 0.00 1:474d + 137:bff7575d 4 0.00 1:475d + 137:bff75812 1 0.00 1:4812 + 137:bff75816 1 0.00 1:4816 + 137:bff75ab9 1 0.00 1:4ab9 + 137:bff75ace 1 0.00 1:4ace + 137:bff75ad3 1 0.00 1:4ad3 + 137:bff75ade 1 0.00 1:4ade + 137:bff764de 1 0.00 1:54de + 137:bff76698 14 0.01 1:5698 + 137:bff7669c 1 0.00 1:569c + 137:bff766a2 1 0.00 1:56a2 + 137:bff766a7 3 0.00 1:56a7 + 137:bff766ad 1 0.00 1:56ad + 137:bff766b1 1 0.00 1:56b1 + 137:bff766b3 6 0.00 1:56b3 + 137:bff766bf 3 0.00 1:56bf + 137:bff766cc 4 0.00 1:56cc + 137:bff766d4 2 0.00 1:56d4 + 137:bff766dc 4 0.00 1:56dc + 137:bff766de 1 0.00 1:56de + 137:bff766df 1 0.00 1:56df + 137:bff766e0 1 0.00 1:56e0 + 137:bff766ed 2 0.00 1:56ed + 137:bff766f0 1 0.00 1:56f0 + 137:bff76744 1 0.00 1:5744 + 137:bff7674c 1 0.00 1:574c + 137:bff7675a 2 0.00 1:575a + 137:bff76777 3 0.00 1:5777 + 137:bff7677f 1 0.00 1:577f + 137:bff76781 1 0.00 1:5781 + 137:bff7678b 2 0.00 1:578b + 137:bff7683c 5 0.00 1:583c + 137:bff76843 8 0.00 1:5843 + 137:bff7684d 1 0.00 1:584d + 137:bff76d34 4 0.00 1:5d34 + 137:bff76d47 2 0.00 1:5d47 + 137:bff76d4a 1 0.00 1:5d4a + 137:bff76d80 1 0.00 1:5d80 + 137:bff76da6 1 0.00 1:5da6 + 137:bff76f19 1 0.00 1:5f19 + 137:bff76fb6 1 0.00 1:5fb6 + 137:bff77166 1 0.00 1:6166 + 137:bff77251 1 0.00 1:6251 + 137:bff7725a 1 0.00 1:625a + 137:bff7762c 5 0.00 1:662c + 137:bff77636 1 0.00 1:6636 + 137:bff77649 1 0.00 1:6649 + 137:bff77651 1 0.00 1:6651 + 137:bff77658 4 0.00 1:6658 + 137:bff77672 7 0.00 1:6672 + 137:bff77885 1 0.00 1:6885 + 137:bff77ad1 1 0.00 1:6ad1 + 137:bff77aef 1 0.00 1:6aef + 137:bff77b0b 1 0.00 1:6b0b + 137:bff77b16 1 0.00 1:6b16 + 137:bff78000 1 0.00 2:0 + 137:bff7800d 1 0.00 2:d + 137:bff78019 1 0.00 2:19 + 137:bff78020 1 0.00 2:20 + 137:bff78028 1 0.00 2:28 + 137:bff7802c 1 0.00 2:2c + 137:bff78042 1 0.00 2:42 + 137:bff7806b 1 0.00 2:6b + 137:bff780a0 2 0.00 2:a0 + 137:bff780ad 1 0.00 2:ad + 137:bff780b6 1 0.00 2:b6 + 137:bff780b8 1 0.00 2:b8 + 137:bff780bb 2 0.00 2:bb + 137:bff780c0 3 0.00 2:c0 + 137:bff780c2 2 0.00 2:c2 + 137:bff780cb 1 0.00 2:cb + 137:bff780ed 8 0.00 2:ed + 137:bff780f3 3 0.00 2:f3 + 137:bff780f9 2 0.00 2:f9 + 137:bff78104 2 0.00 2:104 + 137:bff7811b 1 0.00 2:11b + 137:bff78120 2 0.00 2:120 + 137:bff78138 2 0.00 2:138 + 137:bff78171 2 0.00 2:171 + 137:bff78179 1 0.00 2:179 + 137:bff78180 1 0.00 2:180 + 137:bff78189 1 0.00 2:189 + 137:bff781c6 4 0.00 2:1c6 + 137:bff781cc 9 0.00 2:1cc + 137:bff781d1 1 0.00 2:1d1 + 137:bff781d6 4 0.00 2:1d6 + 137:bff781dc 1 0.00 2:1dc + 137:bff781e3 1 0.00 2:1e3 + 137:bff7821b 5 0.00 2:21b + 137:bff7822c 1 0.00 2:22c + 137:bff78259 1 0.00 2:259 + 137:bff78276 1 0.00 2:276 + 137:bff782b1 1 0.00 2:2b1 + 137:bff782c7 1 0.00 2:2c7 + 137:bff782c9 1 0.00 2:2c9 + 137:bff782de 1 0.00 2:2de + 137:bff782f2 1 0.00 2:2f2 + 137:bff782ff 2 0.00 2:2ff + 137:bff7834f 1 0.00 2:34f + 137:bff78358 1 0.00 2:358 + 137:bff78371 3 0.00 2:371 + 137:bff78396 1 0.00 2:396 + 137:bff783ba 1 0.00 2:3ba + 137:bff783cb 2 0.00 2:3cb + 137:bff783df 1 0.00 2:3df + 137:bff783e2 8 0.00 2:3e2 + 137:bff783f1 1 0.00 2:3f1 + 137:bff783f4 3 0.00 2:3f4 + 137:bff78476 1 0.00 2:476 + 137:bff7847b 1 0.00 2:47b + 137:bff7847c 1 0.00 2:47c + 137:bff78482 1 0.00 2:482 + 137:bff78499 1 0.00 2:499 + 137:bff784e6 1 0.00 2:4e6 + 137:bff784f0 8 0.00 2:4f0 + 137:bff784f6 4 0.00 2:4f6 + 137:bff784f7 1 0.00 2:4f7 + 137:bff784fb 3 0.00 2:4fb + 137:bff78500 2 0.00 2:500 + 137:bff78509 4 0.00 2:509 + 137:bff78516 1 0.00 2:516 + 137:bff78518 1 0.00 2:518 + 137:bff7851a 1 0.00 2:51a + 137:bff7851b 1 0.00 2:51b + 137:bff78524 2 0.00 2:524 + 137:bff78535 12 0.01 2:535 + 137:bff78537 7 0.00 2:537 + 137:bff7853d 6 0.00 2:53d + 137:bff78541 7 0.00 2:541 + 137:bff7857f 3 0.00 2:57f + 137:bff78583 5 0.00 2:583 + 137:bff7858c 1 0.00 2:58c + 137:bff78592 1 0.00 2:592 + 137:bff78639 1 0.00 2:639 + 137:bff78672 1 0.00 2:672 + 137:bff78706 1 0.00 2:706 + 137:bff78710 1 0.00 2:710 + 137:bff791f8 4 0.00 2:11f8 + 137:bff79213 1 0.00 2:1213 + 137:bff79217 1 0.00 2:1217 + 137:bff7922d 1 0.00 2:122d + 137:bff79236 2 0.00 2:1236 + 137:bff7923e 1 0.00 2:123e + 137:bff79286 1 0.00 2:1286 + 137:bff792b4 1 0.00 2:12b4 + 137:bff793d8 1 0.00 2:13d8 + 137:bff79439 1 0.00 2:1439 + 137:bff79464 3 0.00 2:1464 + 137:bff79470 1 0.00 2:1470 + 137:bff79477 1 0.00 2:1477 + 137:bff79485 2 0.00 2:1485 + 137:bff79496 2 0.00 2:1496 + 137:bff794aa 1 0.00 2:14aa + 137:bff794ac 2 0.00 2:14ac + 137:bff794b2 2 0.00 2:14b2 + 137:bff794b8 2 0.00 2:14b8 + 137:bff79522 1 0.00 2:1522 + 137:bff79524 1 0.00 2:1524 + 137:bff7952b 4 0.00 2:152b + 137:bff7952d 1 0.00 2:152d + 137:bff7952f 1 0.00 2:152f + 137:bff79547 2 0.00 2:1547 + 137:bff79554 5 0.00 2:1554 + 137:bff79558 2 0.00 2:1558 + 137:bff79666 1 0.00 2:1666 + 137:bff79677 1 0.00 2:1677 + 137:bff79685 1 0.00 2:1685 + 137:bff796b8 1 0.00 2:16b8 + 137:bff79705 4 0.00 2:1705 + 137:bff79720 4 0.00 2:1720 + 137:bff79729 1 0.00 2:1729 + 137:bff79883 7 0.00 2:1883 + 137:bff79888 1 0.00 2:1888 + 137:bff7988b 2 0.00 2:188b + 137:bff7989d 5 0.00 2:189d + 137:bff798a0 1 0.00 2:18a0 + 137:bff798a6 1 0.00 2:18a6 + 137:bff798a9 3 0.00 2:18a9 + 137:bff798b8 1 0.00 2:18b8 + 137:bff798bd 1 0.00 2:18bd + 137:bff798c1 1 0.00 2:18c1 + 137:bff79919 1 0.00 2:1919 + 137:bff7992b 2 0.00 2:192b + 137:bff79948 1 0.00 2:1948 + 137:bff79953 1 0.00 2:1953 + 137:bff7995f 1 0.00 2:195f + 137:bff79970 2 0.00 2:1970 + 137:bff7997c 1 0.00 2:197c + 137:bff7999f 1 0.00 2:199f + 137:bff799d7 1 0.00 2:19d7 + 137:bff799e3 1 0.00 2:19e3 + 137:bff799e6 1 0.00 2:19e6 + 137:bff799f1 1 0.00 2:19f1 + 137:bff79a30 4 0.00 2:1a30 + 137:bff79a32 1 0.00 2:1a32 + 137:bff79cf8 1 0.00 2:1cf8 + 137:bff79f4d 1 0.00 2:1f4d + 137:bff7a188 1 0.00 2:2188 + 137:bff7a333 1 0.00 2:2333 + 137:bff7a339 1 0.00 2:2339 + 137:bff7a48b 1 0.00 2:248b + 137:bff7a7a3 2 0.00 2:27a3 + 137:bff7a7b5 3 0.00 2:27b5 + 137:bff7a7c0 5 0.00 2:27c0 + 137:bff7a7c2 2 0.00 2:27c2 + 137:bff7a7cf 1 0.00 2:27cf + 137:bff7a862 1 0.00 2:2862 + 137:bff7a873 1 0.00 2:2873 + 137:bff7a897 1 0.00 2:2897 + 137:bff7a941 1 0.00 2:2941 + 137:bff7a97d 1 0.00 2:297d + 137:bff7aa10 1 0.00 2:2a10 + 137:bff7aa15 1 0.00 2:2a15 + 137:bff7aa1f 2 0.00 2:2a1f + 137:bff7aa68 1 0.00 2:2a68 + 137:bff7abc8 1 0.00 2:2bc8 + 137:bff7ae21 3 0.00 2:2e21 + 137:bff7aec1 3 0.00 2:2ec1 + 137:bff7af2c 1 0.00 2:2f2c + 137:bff7af8b 1 0.00 2:2f8b + 137:bff7b095 1 0.00 2:3095 + 137:bff7b096 1 0.00 2:3096 + 137:bff7b0cd 7 0.00 2:30cd + 137:bff7b0d6 2 0.00 2:30d6 + 137:bff7b0d9 1 0.00 2:30d9 + 137:bff7b0e5 1 0.00 2:30e5 + 137:bff7b13c 1 0.00 2:313c + 137:bff7b148 1 0.00 2:3148 + 137:bff7b157 2 0.00 2:3157 + 137:bff7b176 1 0.00 2:3176 + 137:bff7b17f 3 0.00 2:317f + 137:bff7b197 1 0.00 2:3197 + 137:bff7b199 1 0.00 2:3199 + 137:bff7b19c 2 0.00 2:319c + 137:bff7b19f 1 0.00 2:319f + 137:bff7b1a2 1 0.00 2:31a2 + 137:bff7b264 2 0.00 2:3264 + 137:bff7b266 2 0.00 2:3266 + 137:bff7b277 1 0.00 2:3277 + 137:bff7b2ab 1 0.00 2:32ab + 137:bff7b2cd 1 0.00 2:32cd + 137:bff7b2d7 1 0.00 2:32d7 + 137:bff7b794 1 0.00 2:3794 + 137:bff7b840 1 0.00 2:3840 + 137:bff7b9b5 1 0.00 2:39b5 + 137:bff7ba7e 1 0.00 2:3a7e + 137:bff7bb67 2 0.00 2:3b67 + 137:bff7bb88 3 0.00 2:3b88 + 137:bff7bbf7 1 0.00 2:3bf7 + 137:bff7bea9 1 0.00 2:3ea9 + 137:bff7beb0 1 0.00 2:3eb0 + 137:bff7bfe6 1 0.00 2:3fe6 + 137:bff7c472 1 0.00 2:4472 + 137:bff7c5f0 1 0.00 2:45f0 + 137:bff7c692 1 0.00 2:4692 + 137:bff7cd77 1 0.00 2:4d77 + 137:bff7d37e 1 0.00 2:537e + 137:bff7d87b 1 0.00 2:587b + 137:bff7dc3e 1 0.00 2:5c3e + 137:bff7dcb3 1 0.00 2:5cb3 + 137:bff7dcc9 1 0.00 2:5cc9 + 137:bff7ddbf 1 0.00 2:5dbf + 137:bff7e160 1 0.00 2:6160 + 137:bff7e3b6 1 0.00 2:63b6 + 137:bff7e3cf 1 0.00 2:63cf + 137:bff7eb01 1 0.00 2:6b01 + 137:bff7ebca 1 0.00 2:6bca + 137:bff7ecbc 1 0.00 2:6cbc + 137:bff7edd1 1 0.00 2:6dd1 + 137:bff7ede1 1 0.00 2:6de1 + 137:bff7ee7c 1 0.00 2:6e7c + 137:bff7eeed 3 0.00 2:6eed + 137:bff81376 1 0.00 2:9376 + 137:bff81390 1 0.00 2:9390 + 137:bff81581 1 0.00 2:9581 + 137:bff8168b 1 0.00 2:968b + 137:bff81756 1 0.00 2:9756 + 137:bff81b6a 1 0.00 2:9b6a + 137:bff81b89 4 0.00 2:9b89 + 137:bff81b9b 1 0.00 2:9b9b + 137:bff82973 1 0.00 2:a973 + 137:bff829d8 1 0.00 2:a9d8 + 137:bff83255 1 0.00 2:b255 + 137:bff847cb 1 0.00 2:c7cb + 137:bff84b18 1 0.00 2:cb18 + 137:bff85f81 1 0.00 2:df81 + 137:bff86775 2 0.00 2:e775 + 137:bff86776 1 0.00 2:e776 + 137:bff8679b 3 0.00 2:e79b + 137:bff867b5 1 0.00 2:e7b5 + 137:bff867b6 1 0.00 2:e7b6 + 137:bff868b8 4 0.00 2:e8b8 + 137:bff868ba 5 0.00 2:e8ba + 137:bff87307 1 0.00 2:f307 + 137:bff873d8 1 0.00 2:f3d8 + 137:bff88587 1 0.00 2:10587 + 137:bff889bb 1 0.00 2:109bb + 137:bff890c7 1 0.00 2:110c7 + 137:bff8a1cc 4 0.00 2:121cc + 137:bff8a23e 2 0.00 2:1223e + 137:bff8a268 2 0.00 2:12268 + 137:bff8a4b8 1 0.00 2:124b8 + 137:bff8a4c9 1 0.00 2:124c9 + 137:bff8a506 6 0.00 2:12506 + 137:bff8a50f 1 0.00 2:1250f + 137:bff8a514 1 0.00 2:12514 + 137:bff8a522 1 0.00 2:12522 + 137:bff8d066 1 0.00 2:15066 + 137:bff8d0f0 1 0.00 2:150f0 + 137:bff90595 2 0.00 2:18595 + 137:bff90eb5 1 0.00 2:18eb5 + 137:bff90eb6 1 0.00 2:18eb6 + 137:bff90ebd 2 0.00 2:18ebd + 137:bff90f24 1 0.00 2:18f24 + 137:bff91066 1 0.00 2:19066 + 137:bff910f8 1 0.00 2:190f8 + 137:bff91142 3 0.00 2:19142 + 137:bff91265 2 0.00 2:19265 + 137:bff91268 3 0.00 2:19268 + 137:bff9129c 2 0.00 2:1929c + 137:bff912df 1 0.00 2:192df + 137:bff920b0 4 0.00 2:1a0b0 + 137:bff920c8 1 0.00 2:1a0c8 + 137:bff9248c 1 0.00 2:1a48c + 137:bff92571 2 0.00 2:1a571 + 137:bff92576 1 0.00 2:1a576 + 137:bff925bf 1 0.00 2:1a5bf + 137:bff925e2 1 0.00 2:1a5e2 + 137:bff926e6 2 0.00 2:1a6e6 + 137:bff926f1 1 0.00 2:1a6f1 + 137:bff92763 1 0.00 2:1a763 + 137:bff928c9 9 0.00 2:1a8c9 + 137:bff928cd 5 0.00 2:1a8cd + 137:bff928e0 4 0.00 2:1a8e0 + 137:bff92b0d 5 0.00 2:1ab0d + 137:bff92b11 2 0.00 2:1ab11 + 137:bff92b24 2 0.00 2:1ab24 + 137:bff96803 2 0.00 2:1e803 + 137:bff9682b 1 0.00 2:1e82b + 137:bff9685b 1 0.00 2:1e85b + 137:bff96868 3 0.00 2:1e868 + 137:bff9687a 1 0.00 2:1e87a + 137:bff97c71 2 0.00 2:1fc71 + 137:bff97c77 2 0.00 2:1fc77 + 137:bff97c8a 2 0.00 2:1fc8a + 137:bff97c90 2 0.00 2:1fc90 + 137:bff97c9a 2 0.00 2:1fc9a + 137:bff9a17d 1 0.00 2:2217d + 137:bff9b939 1 0.00 2:23939 + 137:bff9cca9 1 0.00 2:24ca9 + 137:bffb8881 1 0.00 2:40881 + +Module Name GDI32 + + CS:EIP Samples (%) Map Offset Symbol + 137:bff310e1 1 0.00 1:e1 + 137:bff3134f 1 0.00 1:34f + 137:bff31a7c 1 0.00 1:a7c + 137:bff31b82 1 0.00 1:b82 + 137:bff31f1f 1 0.00 1:f1f + 137:bff32035 1 0.00 1:1035 + 137:bff3215a 4 0.00 1:115a + 137:bff32160 1 0.00 1:1160 + 137:bff32175 1 0.00 1:1175 + 137:bff3237c 1 0.00 1:137c + 137:bff323c0 1 0.00 1:13c0 + 137:bff3249f 1 0.00 1:149f + 137:bff324b9 1 0.00 1:14b9 + 137:bff34379 2 0.00 1:3379 + 137:bff344ba 1 0.00 1:34ba + 137:bff34656 1 0.00 1:3656 + 137:bff34d39 1 0.00 1:3d39 + 137:bff34da5 1 0.00 1:3da5 + 137:bff34db1 1 0.00 1:3db1 + 137:bff34f8b 1 0.00 1:3f8b + 137:bff34f8e 1 0.00 1:3f8e + 137:bff39854 2 0.00 1:8854 + 137:bff3c495 1 0.00 1:b495 + 137:bff31bf9 1 0.00 1:bf9 + 137:bff31f92 1 0.00 1:f92 + 137:bff320e8 1 0.00 1:10e8 + 137:bff3249b 1 0.00 1:149b + 137:bff341bb 1 0.00 1:31bb + 137:bff3438c 1 0.00 1:338c + 137:bff3a350 2 0.00 1:9350 + 137:bff3a560 1 0.00 1:9560 + 137:bff3a5c6 1 0.00 1:95c6 + 137:bff3caa4 1 0.00 1:baa4 + 137:bff3d4ea 1 0.00 1:c4ea + 137:bff3d564 1 0.00 1:c564 + 137:bff3d746 1 0.00 1:c746 + 137:bff3e9d5 1 0.00 1:d9d5 + 137:bff3ede8 1 0.00 1:dde8 + 137:bff3f9a3 1 0.00 1:e9a3 + 137:bff3fe19 1 0.00 1:ee19 + 137:bff3fea4 1 0.00 1:eea4 + 137:bff40102 1 0.00 1:f102 + 137:bff41046 1 0.00 1:10046 + 137:bff41089 1 0.00 1:10089 + 137:bff410eb 1 0.00 1:100eb + 137:bff4113e 1 0.00 1:1013e + 137:bff420bb 1 0.00 1:110bb + 137:bff4227b 1 0.00 1:1127b + 137:bff42527 1 0.00 1:11527 + 137:bff425f3 1 0.00 1:115f3 + 137:bff426b5 1 0.00 1:116b5 + 137:bff426f8 1 0.00 1:116f8 + 137:bff42996 1 0.00 1:11996 + 137:bff42cf7 1 0.00 1:11cf7 + 137:bff42daf 1 0.00 1:11daf + 137:bff43b1f 1 0.00 1:12b1f + 137:bff43b68 1 0.00 1:12b68 + 137:bff4421f 1 0.00 1:1321f + 137:bff44230 1 0.00 1:13230 + 137:bff44dd6 1 0.00 1:13dd6 + 137:bff4540a 1 0.00 1:1440a + 137:bff4542a 1 0.00 1:1442a + 137:bff4542f 1 0.00 1:1442f + 137:bff45ede 1 0.00 1:14ede + 137:bff45fb0 1 0.00 1:14fb0 + 137:bff4608a 1 0.00 1:1508a + 137:bff46099 3 0.00 1:15099 + 137:bff46184 1 0.00 1:15184 + 137:bff46224 1 0.00 1:15224 + 137:bff464aa 1 0.00 1:154aa + 137:bff4667c 1 0.00 1:1567c + 137:bff46d18 1 0.00 1:15d18 + 137:bff46ec5 1 0.00 1:15ec5 + 137:bff47247 1 0.00 1:16247 + 137:bff4730b 1 0.00 1:1630b + 137:bff4730f 6 0.00 1:1630f + 137:bff47379 1 0.00 1:16379 + 137:bff478c7 1 0.00 1:168c7 + 137:bff47bd1 1 0.00 1:16bd1 + 137:bff47e21 2 0.00 1:16e21 + 137:bff47fc9 1 0.00 1:16fc9 + 137:bff4825f 1 0.00 1:1725f + 137:bff482d8 1 0.00 1:172d8 + 137:bff48368 1 0.00 1:17368 + 137:bff4837d 1 0.00 1:1737d + 137:bff484cc 1 0.00 1:174cc + 137:bff484f6 1 0.00 1:174f6 + 137:bff48603 1 0.00 1:17603 + 137:bff488df 2 0.00 1:178df + 137:bff48bb7 1 0.00 1:17bb7 + 137:bff48bbc 1 0.00 1:17bbc + 137:bff48bfa 1 0.00 1:17bfa + 137:bff48c5b 1 0.00 1:17c5b + 137:bff48c5d 1 0.00 1:17c5d + 137:bff48cac 1 0.00 1:17cac + 137:bff48f9a 1 0.00 1:17f9a + 137:bff48fbb 1 0.00 1:17fbb + 137:bff492fc 1 0.00 1:182fc + 137:bff493e6 1 0.00 1:183e6 + 137:bff493ed 1 0.00 1:183ed + 137:bff493f7 1 0.00 1:183f7 + 137:bff495e9 1 0.00 1:185e9 + 137:bff49a54 1 0.00 1:18a54 + +Module Name ADVAPI32 + + CS:EIP Samples (%) Map Offset Symbol + 137:bfed164e 1 0.00 1:64e + 137:bfed1b08 1 0.00 1:b08 + +Module Name USER32 + + CS:EIP Samples (%) Map Offset Symbol + 137:bff63e25 1 0.00 1:2e25 + 137:bff644fe 1 0.00 1:34fe + 137:bff6633e 1 0.00 1:533e + 137:bff61095 1 0.00 1:95 + 137:bff611cd 1 0.00 1:1cd + 137:bff6148f 1 0.00 1:48f + 137:bff61f2b 1 0.00 1:f2b + 137:bff62038 1 0.00 1:1038 + 137:bff622f6 1 0.00 1:12f6 + 137:bff623a9 1 0.00 1:13a9 + 137:bff623ad 1 0.00 1:13ad + 137:bff623de 1 0.00 1:13de + 137:bff63c2a 1 0.00 1:2c2a + 137:bff63e71 1 0.00 1:2e71 + 137:bff64079 1 0.00 1:3079 + 137:bff6408a 1 0.00 1:308a + 137:bff6409e 1 0.00 1:309e + 137:bff6446b 1 0.00 1:346b + 137:bff64473 1 0.00 1:3473 + 137:bff64503 1 0.00 1:3503 + 137:bff645ad 1 0.00 1:35ad + 137:bff646e1 1 0.00 1:36e1 + 137:bff64774 1 0.00 1:3774 + 137:bff64954 1 0.00 1:3954 + 137:bff649b9 1 0.00 1:39b9 + 137:bff64a57 1 0.00 1:3a57 + 137:bff64a66 1 0.00 1:3a66 + 137:bff64a76 3 0.00 1:3a76 + 137:bff64b27 2 0.00 1:3b27 + 137:bff64d8d 1 0.00 1:3d8d + 137:bff65120 1 0.00 1:4120 + 137:bff6512b 1 0.00 1:412b + 137:bff6512f 1 0.00 1:412f + 137:bff65134 1 0.00 1:4134 + 137:bff662d2 3 0.00 1:52d2 + 137:bff663d4 2 0.00 1:53d4 + 137:bff663f8 1 0.00 1:53f8 + 137:bff61095 2 0.00 1:95 + 137:bff61097 5 0.00 1:97 + 137:bff611a1 7 0.00 1:1a1 + 137:bff611cd 1 0.00 1:1cd + 137:bff61476 1 0.00 1:476 + 137:bff6147c 1 0.00 1:47c + 137:bff614a1 1 0.00 1:4a1 + 137:bff6173f 1 0.00 1:73f + 137:bff61767 1 0.00 1:767 + 137:bff61d9a 1 0.00 1:d9a + 137:bff61e94 1 0.00 1:e94 + 137:bff61f52 1 0.00 1:f52 + 137:bff62032 1 0.00 1:1032 + 137:bff62061 1 0.00 1:1061 + 137:bff6206e 1 0.00 1:106e + 137:bff62301 1 0.00 1:1301 + 137:bff62333 2 0.00 1:1333 + 137:bff62365 2 0.00 1:1365 + 137:bff6237a 2 0.00 1:137a + 137:bff623ad 2 0.00 1:13ad + 137:bff623fe 1 0.00 1:13fe + 137:bff62e82 1 0.00 1:1e82 + 137:bff62e92 1 0.00 1:1e92 + 137:bff63a86 1 0.00 1:2a86 + 137:bff63c2a 2 0.00 1:2c2a + 137:bff63e58 1 0.00 1:2e58 + 137:bff63e5f 2 0.00 1:2e5f + 137:bff63e71 2 0.00 1:2e71 + 137:bff63e84 6 0.00 1:2e84 + 137:bff63e89 1 0.00 1:2e89 + 137:bff64460 6 0.00 1:3460 + 137:bff64466 4 0.00 1:3466 + 137:bff6446b 14 0.01 1:346b + 137:bff6446d 10 0.01 1:346d + 137:bff64478 8 0.00 1:3478 + 137:bff64479 1 0.00 1:3479 + 137:bff6447a 2 0.00 1:347a + 137:bff644a9 2 0.00 1:34a9 + 137:bff644b4 4 0.00 1:34b4 + 137:bff644bf 1 0.00 1:34bf + 137:bff644c4 1 0.00 1:34c4 + 137:bff644d5 2 0.00 1:34d5 + 137:bff644d7 1 0.00 1:34d7 + 137:bff644e5 1 0.00 1:34e5 + 137:bff644f5 1 0.00 1:34f5 + 137:bff644fb 7 0.00 1:34fb + 137:bff644fe 3 0.00 1:34fe + 137:bff64500 1 0.00 1:3500 + 137:bff6450b 2 0.00 1:350b + 137:bff64513 5 0.00 1:3513 + 137:bff645ad 2 0.00 1:35ad + 137:bff64697 3 0.00 1:3697 + 137:bff6469c 2 0.00 1:369c + 137:bff646a0 1 0.00 1:36a0 + 137:bff646a5 2 0.00 1:36a5 + 137:bff646b9 4 0.00 1:36b9 + 137:bff64733 1 0.00 1:3733 + 137:bff64780 6 0.00 1:3780 + 137:bff64789 3 0.00 1:3789 + 137:bff647aa 6 0.00 1:37aa + 137:bff647c9 2 0.00 1:37c9 + 137:bff647cb 4 0.00 1:37cb + 137:bff647d3 2 0.00 1:37d3 + 137:bff647d9 2 0.00 1:37d9 + 137:bff647db 1 0.00 1:37db + 137:bff649f1 1 0.00 1:39f1 + 137:bff64a76 1 0.00 1:3a76 + 137:bff64b27 7 0.00 1:3b27 + 137:bff64b29 3 0.00 1:3b29 + 137:bff64b34 1 0.00 1:3b34 + 137:bff64b3f 2 0.00 1:3b3f + 137:bff64b48 1 0.00 1:3b48 + 137:bff64b7e 1 0.00 1:3b7e + 137:bff64ba8 6 0.00 1:3ba8 + 137:bff64bf4 3 0.00 1:3bf4 + 137:bff64ca3 1 0.00 1:3ca3 + 137:bff64cc2 1 0.00 1:3cc2 + 137:bff64cf9 1 0.00 1:3cf9 + 137:bff64d2d 1 0.00 1:3d2d + 137:bff64d39 1 0.00 1:3d39 + 137:bff64d81 1 0.00 1:3d81 + 137:bff64d8d 6 0.00 1:3d8d + 137:bff64d92 1 0.00 1:3d92 + 137:bff64d95 2 0.00 1:3d95 + 137:bff64d9b 1 0.00 1:3d9b + 137:bff64d9d 1 0.00 1:3d9d + 137:bff64dcc 1 0.00 1:3dcc + 137:bff64e02 1 0.00 1:3e02 + 137:bff64e0d 1 0.00 1:3e0d + 137:bff64e25 1 0.00 1:3e25 + 137:bff64e4b 1 0.00 1:3e4b + 137:bff65120 2 0.00 1:4120 + 137:bff6512b 1 0.00 1:412b + 137:bff65153 2 0.00 1:4153 + 137:bff662d2 3 0.00 1:52d2 + 137:bff66332 1 0.00 1:5332 + 137:bff6633e 1 0.00 1:533e + 137:bff66374 1 0.00 1:5374 + 137:bff66392 2 0.00 1:5392 + 137:bff663f8 1 0.00 1:53f8 + +Module Name AFVXD + + CS:EIP Samples (%) Map Offset Symbol + 28:c10c5334 1 0.00 1:0 + 28:c10c7e90 1 0.00 1:2b5c + 28:c10c8d9a 1 0.00 1:3a66 + 28:c10c8e0c 1 0.00 1:3ad8 + +Module Name COMCTL32 + + CS:EIP Samples (%) Map Offset Symbol + 137:202b3d56 1 0.00 1:2d56 + 137:202ca7b8 1 0.00 1:197b8 + 137:202e9453 1 0.00 1:38453 + 137:202e9498 1 0.00 1:38498 + 137:bfc01477 3 0.00 1:477 + 137:bfc0173e 1 0.00 1:73e + 137:bfc0e54e 1 0.00 1:d54e + 137:bfc0e56a 1 0.00 1:d56a + 137:bfc12469 1 0.00 1:11469 + 137:bfc1275a 1 0.00 1:1175a + 137:bfc149b5 1 0.00 1:139b5 + 137:bfc14adf 1 0.00 1:13adf + 137:bfc173c0 1 0.00 1:163c0 + 137:bfc17620 1 0.00 1:16620 + 137:bfc17638 1 0.00 1:16638 + 137:bfc19bfa 1 0.00 1:18bfa + 137:bfc20ae8 1 0.00 1:1fae8 + 137:bfc2112f 1 0.00 1:2012f + 137:bfc222fc 1 0.00 1:212fc + 137:bfc2c05f 2 0.00 1:2b05f + 137:bfc2de7e 1 0.00 1:2ce7e + 137:bfc2df6c 1 0.00 1:2cf6c + 137:bfc2e256 1 0.00 1:2d256 + 137:bfc2e283 1 0.00 1:2d283 + 137:bfc2e2a2 1 0.00 1:2d2a2 + 137:bfc2e2e6 1 0.00 1:2d2e6 + 137:bfc2e3a1 1 0.00 1:2d3a1 + 137:bfc2f74d 1 0.00 1:2e74d + 137:bfc2f7ae 1 0.00 1:2e7ae + 137:bfc0c04e 1 0.00 1:b04e + 137:bfc0c8c6 1 0.00 1:b8c6 + 137:bfc2c706 1 0.00 1:2b706 + 137:bfc2f784 1 0.00 1:2e784 + +Module Name VSHWIN32 + + CS:EIP Samples (%) Map Offset Symbol + 137:403784 1 0.00 1:2784 + 137:4037bc 1 0.00 1:27bc + 137:406cdb 1 0.00 1:5cdb + 137:406ceb 3 0.00 1:5ceb + 137:406cf3 4 0.00 1:5cf3 + 137:406cff 1 0.00 1:5cff + 137:406d20 2 0.00 1:5d20 + 137:406d24 1 0.00 1:5d24 + 137:406d39 2 0.00 1:5d39 + +Module Name VTUNE + + CS:EIP Samples (%) Map Offset Symbol + 137:401030 1 0.00 1:30 + 137:467b80 1 0.00 1:66b80 + 137:47ba52 1 0.00 1:7aa52 + 137:4827ff 1 0.00 1:817ff + +Module Name MCKRNL + + CS:EIP Samples (%) Map Offset Symbol + 28:c10cf131 1 0.00 1:30d + +Module Name MCUTIL + + CS:EIP Samples (%) Map Offset Symbol + 28:c10d45f9 1 0.00 1:1fd + 28:c10d4770 6 0.00 1:374 + 28:c10d479d 1 0.00 1:3a1 + 28:c10d47a3 3 0.00 1:3a7 + 28:c10d47a8 1 0.00 1:3ac + 28:c10d47b9 1 0.00 1:3bd + 28:c10d47bc 2 0.00 1:3c0 + 28:c10d4a28 7 0.00 1:62c + 28:c10d4a37 2 0.00 1:63b + 28:c10d4a46 2 0.00 1:64a + 28:c10d4dd6 10 0.01 1:9da + 28:c10d4dec 1 0.00 1:9f0 + 28:c10d4df5 2 0.00 1:9f9 + 28:c10d4e07 1 0.00 1:a0b + 28:c10d4e10 5 0.00 1:a14 + 28:c10d4e1f 3 0.00 1:a23 + 28:c10d4e66 4 0.00 1:a6a + 28:c10d4e6a 1 0.00 1:a6e + 28:c10d5095 10 0.01 1:c99 + 28:c10d5096 2 0.00 1:c9a + 28:c10d509e 1 0.00 1:ca2 + 28:c10d50a6 1 0.00 1:caa + 28:c10d50aa 3 0.00 1:cae + 28:c10d50ad 2 0.00 1:cb1 + 28:c10d50b2 2 0.00 1:cb6 + 28:c10d50b9 2 0.00 1:cbd + 28:c10d50bb 1 0.00 1:cbf + 28:c10d6737 1 0.00 1:233b + 28:c10d75a8 8 0.00 1:31ac + 28:c10d75b7 1 0.00 1:31bb + 28:c10d75ba 1 0.00 1:31be + 28:c10d75c0 12 0.01 1:31c4 + 28:c10d75c4 72 0.04 1:31c8 + 28:c10d75c6 1 0.00 1:31ca + +Module Name VSHIELD + + CS:EIP Samples (%) Map Offset Symbol + 28:c10d8893 4 0.00 1:2c3 + 28:c10d89a9 1 0.00 1:3d9 + 28:c10d89b6 1 0.00 1:3e6 + 28:c10d89cc 1 0.00 1:3fc + 28:c10d8a05 1 0.00 1:435 + 28:c10d8a54 2 0.00 1:484 + 28:c10d8a82 2 0.00 1:4b2 + 28:c10d8b7d 2 0.00 1:5ad + 28:c10d8ba9 1 0.00 1:5d9 + 28:c10d8bd7 2 0.00 1:607 + 28:c10d8c05 1 0.00 1:635 + 28:c10d8c10 3 0.00 1:640 + 28:c10d8dfd 1 0.00 1:82d + 28:c10d8e01 1 0.00 1:831 + 28:c10d8e18 3 0.00 1:848 + 28:c10d8fce 1 0.00 1:9fe + 28:c10d8fdb 1 0.00 1:a0b + 28:c10d900d 1 0.00 1:a3d + 28:c10d9017 1 0.00 1:a47 + 28:c10d9052 1 0.00 1:a82 + 28:c10d9059 1 0.00 1:a89 + 28:c10d905a 1 0.00 1:a8a + 28:c10d9066 1 0.00 1:a96 + 28:c10d9702 2 0.00 1:1132 + 28:c10d9706 1 0.00 1:1136 + 28:c10d9718 1 0.00 1:1148 + 28:c10d972e 1 0.00 1:115e + 28:c10d9e0f 1 0.00 1:183f + 28:c10d9e21 1 0.00 1:1851 + 28:c10d9e7a 5 0.00 1:18aa + 28:c10d9e80 5 0.00 1:18b0 + 28:c10d9eb2 1 0.00 1:18e2 + 28:c10d9eb4 3 0.00 1:18e4 + 28:c10d9ed3 1 0.00 1:1903 + 28:c10d9f53 1 0.00 1:1983 + 28:c10da9b0 1 0.00 1:23e0 + 28:c10daa98 1 0.00 1:24c8 + 28:c10daaa1 2 0.00 1:24d1 + 28:c10dac68 1 0.00 1:2698 + 28:c10dac76 1 0.00 1:26a6 + 28:c10dacac 2 0.00 1:26dc + 28:c10dacb5 2 0.00 1:26e5 + 28:c10dacd2 5 0.00 1:2702 + 28:c10dacd5 9 0.00 1:2705 + 28:c10dacdd 15 0.01 1:270d + 28:c10dacde 6 0.00 1:270e + 28:c10dace4 1 0.00 1:2714 + 28:c10dad27 14 0.01 1:2757 + 28:c10dad29 1 0.00 1:2759 + 28:c10dad55 21 0.01 1:2785 + 28:c10dad57 1 0.00 1:2787 + 28:c10dadf7 1 0.00 1:2827 + 28:c10dae01 4 0.00 1:2831 + 28:c10dae34 2 0.00 1:2864 + 28:c10dae6b 5 0.00 1:289b + 28:c10dae72 3 0.00 1:28a2 + 28:c10dae7b 1 0.00 1:28ab + 28:c10dae7d 1 0.00 1:28ad + 28:c10dae81 1 0.00 1:28b1 + 28:c10dae86 1 0.00 1:28b6 + 28:c10dae95 1 0.00 1:28c5 + 28:c10daea0 1 0.00 1:28d0 + 28:c10daf5f 1 0.00 1:298f + 28:c10db00e 1 0.00 1:2a3e + 28:c10dba9d 2 0.00 1:34cd + 28:c10dbaac 2 0.00 1:34dc + 28:c10dbaaf 1 0.00 1:34df + 28:c10dbab0 4 0.00 1:34e0 + 28:c10dbab1 6 0.00 1:34e1 + 28:c10dbab5 10 0.01 1:34e5 + 28:c10dbab9 43 0.02 1:34e9 + 28:c10dbabb 1 0.00 1:34eb + 28:c10dbb0a 2 0.00 1:353a + 28:c10dbb14 1 0.00 1:3544 + 28:c10dbb22 2 0.00 1:3552 + 28:c10dbb3a 2 0.00 1:356a + 28:c10dbb41 1 0.00 1:3571 + 28:c10dbb44 6 0.00 1:3574 + 28:c10dbb47 3 0.00 1:3577 + 28:c10dbb49 1 0.00 1:3579 + 28:c10dbb51 1 0.00 1:3581 + 28:c10dbb56 3 0.00 1:3586 + 28:c10dbb5e 2 0.00 1:358e + 28:c10dbb62 4 0.00 1:3592 + 28:c10dbb64 1 0.00 1:3594 + 28:c10dbb6a 2 0.00 1:359a + 28:c10dbb71 2 0.00 1:35a1 + 28:c10dbb73 4 0.00 1:35a3 + 28:c10dc2d7 2 0.00 1:3d07 + 28:c10dc2f5 1 0.00 1:3d25 + 28:c10dc2fb 1 0.00 1:3d2b + +Module Name WINMM + + CS:EIP Samples (%) Map Offset Symbol + 137:bfe61854 1 0.00 1:854 + 137:bfe61878 2 0.00 1:878 + 137:bfe6187a 2 0.00 1:87a + 137:bfe6439d 1 0.00 1:339d + 137:bfe643b6 1 0.00 1:33b6 + 137:bfe64437 1 0.00 1:3437 + 137:bfe656e9 1 0.00 1:46e9 + 137:bfe662d5 1 0.00 1:52d5 + 137:bfe6184a 6 0.00 1:84a + 137:bfe6185e 4 0.00 1:85e + 137:bfe61861 1 0.00 1:861 + 137:bfe61868 1 0.00 1:868 + 137:bfe61878 19 0.01 1:878 + 137:bfe6187a 2 0.00 1:87a + 137:bfe6188c 1 0.00 1:88c + 137:bfe6439d 10 0.01 1:339d + 137:bfe643a2 3 0.00 1:33a2 + 137:bfe643aa 1 0.00 1:33aa + 137:bfe643bd 1 0.00 1:33bd + 137:bfe643d4 3 0.00 1:33d4 + 137:bfe643ed 1 0.00 1:33ed + 137:bfe64414 1 0.00 1:3414 + 137:bfe64bfe 1 0.00 1:3bfe + 137:bfe6958e 4 0.00 1:858e + +Module Name EXPLORER + + CS:EIP Samples (%) Map Offset Symbol + 137:401823 5 0.00 1:823 + 137:401832 7 0.00 1:832 + 137:401872 2 0.00 1:872 + 137:401875 1 0.00 1:875 + 137:401894 2 0.00 1:894 + 137:4018c8 1 0.00 1:8c8 + 137:4018cb 1 0.00 1:8cb + 137:40191e 1 0.00 1:91e + 137:4022d1 5 0.00 1:12d1 + 137:402302 2 0.00 1:1302 + 137:40230b 1 0.00 1:130b + 137:402600 1 0.00 1:1600 + 137:402a63 1 0.00 1:1a63 + 137:403a7e 1 0.00 1:2a7e + 137:403fb6 1 0.00 1:2fb6 + 137:407fb2 4 0.00 1:6fb2 + 137:407fb6 2 0.00 1:6fb6 + 137:407fd6 1 0.00 1:6fd6 + 137:407fe8 4 0.00 1:6fe8 + 137:40805b 4 0.00 1:705b + 137:40805c 1 0.00 1:705c + 137:4080b5 1 0.00 1:70b5 + 137:4080bc 1 0.00 1:70bc + 137:409599 1 0.00 1:8599 + 137:40a1eb 1 0.00 1:91eb + 137:40af9f 1 0.00 1:9f9f + 137:40e91f 1 0.00 1:d91f + 137:414510 2 0.00 1:13510 + 137:414520 4 0.00 1:13520 + 137:414529 2 0.00 1:13529 + 137:41452c 1 0.00 1:1352c + 137:414537 1 0.00 1:13537 + 137:41453a 1 0.00 1:1353a + 137:414542 1 0.00 1:13542 + +Module Name SHELL32 + + CS:EIP Samples (%) Map Offset Symbol + 137:7eb4177c 1 0.00 1:77c + 137:7eb4309e 1 0.00 1:209e + 137:7eb4bfad 1 0.00 1:afad + 137:7eb56958 1 0.00 1:15958 + 137:7eb591ca 1 0.00 1:181ca + 137:7eb5a44b 1 0.00 1:1944b + 137:7eb5e19c 1 0.00 1:1d19c + +Module Name MSO97 + + CS:EIP Samples (%) Map Offset Symbol + 137:306c3796 1 0.00 1:2796 + +Module Name HPCOLA + + CS:EIP Samples (%) Map Offset Symbol + 137:1014f3c 1 0.00 1:3f3c + 137:1016bb9 1 0.00 1:5bb9 + 137:10199d6 1 0.00 1:89d6 + 137:101a043 1 0.00 1:9043 + 137:101d8bc 1 0.00 1:c8bc + +Module Name MFC40 + + CS:EIP Samples (%) Map Offset Symbol + 137:5f801161 1 0.00 1:161 + 137:5f80140c 1 0.00 1:40c + 137:5f801d9f 1 0.00 1:d9f + 137:5f80436c 1 0.00 1:336c + 137:5f83aceb 1 0.00 1:39ceb + +Module Name MSVCRT40 + + CS:EIP Samples (%) Map Offset Symbol + 137:1021d7f3 1 0.00 1:1c7f3 + +Module Name SNDVOL32 + + CS:EIP Samples (%) Map Offset Symbol + 137:40198c 11 0.01 1:98c + 137:401992 1 0.00 1:992 + 137:401998 5 0.00 1:998 + 137:4019b8 1 0.00 1:9b8 + 137:4019c0 1 0.00 1:9c0 + 137:402073 4 0.00 1:1073 + 137:402078 1 0.00 1:1078 + 137:4020bb 1 0.00 1:10bb + 137:40211a 1 0.00 1:111a + 137:402259 2 0.00 1:1259 + 137:402261 1 0.00 1:1261 + 137:403ff1 1 0.00 1:2ff1 + 137:404484 1 0.00 1:3484 + 137:4058a1 12 0.01 1:48a1 + 137:4058a2 1 0.00 1:48a2 + 137:4058ad 1 0.00 1:48ad + 137:4058b0 1 0.00 1:48b0 + 137:4058b7 3 0.00 1:48b7 + 137:4058bb 3 0.00 1:48bb + 137:4058c8 1 0.00 1:48c8 + 137:4058ce 5 0.00 1:48ce + 137:4058d4 12 0.01 1:48d4 + 137:4058d8 3 0.00 1:48d8 + 137:4058da 1 0.00 1:48da + 137:4058de 6 0.00 1:48de + 137:4058f6 9 0.00 1:48f6 + 137:40592f 1 0.00 1:492f + 137:405935 7 0.00 1:4935 + 137:405939 3 0.00 1:4939 + +Module Name VB40032 + + CS:EIP Samples (%) Map Offset Symbol + 137:f7227d8 1 0.00 1:17d8 + 137:f722811 1 0.00 1:1811 + 137:f723b7f 1 0.00 1:2b7f + 137:f7246b5 1 0.00 1:36b5 + 137:f7246ee 3 0.00 1:36ee + 137:f7246f8 1 0.00 1:36f8 + 137:f72488c 1 0.00 1:388c + 137:f725421 1 0.00 1:4421 + 137:f725d77 1 0.00 1:4d77 + 137:f725d88 1 0.00 1:4d88 + 137:f725da9 1 0.00 1:4da9 + 137:f725dce 1 0.00 1:4dce + 137:f72698c 1 0.00 1:598c + 137:f7270a5 1 0.00 1:60a5 + 137:f72832a 2 0.00 1:732a + 137:f72836e 2 0.00 1:736e + 137:f72837e 3 0.00 1:737e + 137:f72843f 1 0.00 1:743f + 137:f728444 1 0.00 1:7444 + 137:f729b01 2 0.00 1:8b01 + 137:f729b32 1 0.00 1:8b32 + 137:f729bb5 1 0.00 1:8bb5 + 137:f729bce 1 0.00 1:8bce + 137:f72ac49 1 0.00 1:9c49 + 137:f72ac78 1 0.00 1:9c78 + 137:f72ae6e 1 0.00 1:9e6e + 137:f72af61 1 0.00 1:9f61 + 137:f72b182 1 0.00 1:a182 + 137:f72b19e 2 0.00 1:a19e + 137:f72b1a3 1 0.00 1:a1a3 + 137:f72beb4 1 0.00 1:aeb4 + 137:f72c1f0 1 0.00 1:b1f0 + 137:f72c1f7 1 0.00 1:b1f7 + 137:f72c21c 1 0.00 1:b21c + 137:f72c5d0 1 0.00 1:b5d0 + 137:f72c8a8 1 0.00 1:b8a8 + 137:f72cc9f 1 0.00 1:bc9f + 137:f72ccc6 1 0.00 1:bcc6 + 137:f72e585 1 0.00 1:d585 + 137:f72e5f3 1 0.00 1:d5f3 + 137:f72e60b 2 0.00 1:d60b + 137:f72f149 1 0.00 1:e149 + 137:f72f1f2 2 0.00 1:e1f2 + 137:f72f1ff 1 0.00 1:e1ff + 137:f72f21a 1 0.00 1:e21a + 137:f72f31d 1 0.00 1:e31d + 137:f72f36e 1 0.00 1:e36e + 137:f72f375 1 0.00 1:e375 + 137:f72f3cd 1 0.00 1:e3cd + 137:f72f464 1 0.00 1:e464 + 137:f72f47d 1 0.00 1:e47d + 137:f72f4d3 1 0.00 1:e4d3 + 137:f72f4d9 1 0.00 1:e4d9 + 137:f72f4e3 1 0.00 1:e4e3 + 137:f72f4f6 3 0.00 1:e4f6 + 137:f72f516 1 0.00 1:e516 + 137:f72f56f 1 0.00 1:e56f + 137:f72f821 1 0.00 1:e821 + 137:f72f897 1 0.00 1:e897 + 137:f7300e5 1 0.00 1:f0e5 + 137:f7300f6 1 0.00 1:f0f6 + 137:f730121 1 0.00 1:f121 + 137:f73068c 1 0.00 1:f68c + 137:f7306ac 1 0.00 1:f6ac + 137:f73090c 1 0.00 1:f90c + 137:f730939 1 0.00 1:f939 + 137:f730991 1 0.00 1:f991 + 137:f730aa6 1 0.00 1:faa6 + 137:f730b78 1 0.00 1:fb78 + 137:f730bc9 1 0.00 1:fbc9 + 137:f730c64 1 0.00 1:fc64 + 137:f730e42 1 0.00 1:fe42 + 137:f730e4c 2 0.00 1:fe4c + 137:f730e5d 1 0.00 1:fe5d + 137:f732d8d 1 0.00 1:11d8d + 137:f732ecc 1 0.00 1:11ecc + 137:f732ee8 1 0.00 1:11ee8 + 137:f733066 1 0.00 1:12066 + 137:f736016 2 0.00 1:15016 + 137:f736036 1 0.00 1:15036 + 137:f736046 1 0.00 1:15046 + 137:f736075 1 0.00 1:15075 + 137:f736078 1 0.00 1:15078 + 137:f736094 2 0.00 1:15094 + 137:f73642b 1 0.00 1:1542b + 137:f736435 1 0.00 1:15435 + 137:f736442 2 0.00 1:15442 + 137:f73678b 2 0.00 1:1578b + 137:f736796 1 0.00 1:15796 + 137:f7378ab 1 0.00 1:168ab + 137:f737b12 1 0.00 1:16b12 + 137:f737b1a 1 0.00 1:16b1a + 137:f737b24 1 0.00 1:16b24 + 137:f73955d 1 0.00 1:1855d + 137:f739ed6 3 0.00 1:18ed6 + 137:f739eed 1 0.00 1:18eed + 137:f73a992 1 0.00 1:19992 + 137:f73ae72 1 0.00 1:19e72 + 137:f73ae79 1 0.00 1:19e79 + 137:f73b0ea 1 0.00 1:1a0ea + 137:f73b203 1 0.00 1:1a203 + 137:f73b403 1 0.00 1:1a403 + 137:f73b4ab 1 0.00 1:1a4ab + 137:f73b5f8 1 0.00 1:1a5f8 + 137:f73b63a 1 0.00 1:1a63a + 137:f73c63d 1 0.00 1:1b63d + 137:f73c64c 1 0.00 1:1b64c + 137:f73c651 1 0.00 1:1b651 + 137:f73c8ac 1 0.00 1:1b8ac + 137:f74167e 3 0.00 1:2067e + 137:f7416be 1 0.00 1:206be + 137:f742a91 2 0.00 1:21a91 + 137:f742c8f 2 0.00 1:21c8f + 137:f74566d 1 0.00 1:2466d + 137:f74a142 1 0.00 1:29142 + 137:f750dcb 1 0.00 1:2fdcb + 137:f751947 1 0.00 1:30947 + 137:f75c29a 2 0.00 1:3b29a + 137:f75c45f 1 0.00 1:3b45f + 137:f75caba 4 0.00 1:3baba + 137:f75caf8 1 0.00 1:3baf8 + 137:f75cb86 3 0.00 1:3bb86 + 137:f75ff9e 1 0.00 1:3ef9e + 137:f760122 1 0.00 1:3f122 + 137:f76a3a4 1 0.00 1:493a4 + 137:f772171 1 0.00 1:51171 + 137:f772895 1 0.00 1:51895 + 137:f772898 1 0.00 1:51898 + 137:f7728a7 7 0.00 1:518a7 + 137:f7728c3 2 0.00 1:518c3 + 137:f7728d1 1 0.00 1:518d1 + 137:f7728d9 2 0.00 1:518d9 + 137:f77367e 1 0.00 1:5267e + 137:f7739ac 1 0.00 1:529ac + 137:f773a01 1 0.00 1:52a01 + 137:f779df6 1 0.00 1:58df6 + 137:f779e02 1 0.00 1:58e02 + 137:f779ee9 1 0.00 1:58ee9 + 137:f779fd7 1 0.00 1:58fd7 + 137:f780a7d 1 0.00 1:5fa7d + 137:f780abc 1 0.00 1:5fabc + 137:f780ae5 1 0.00 1:5fae5 + 137:f780af5 1 0.00 1:5faf5 + 137:f780b99 2 0.00 1:5fb99 + 137:f780bbd 1 0.00 1:5fbbd + 137:f780c26 1 0.00 1:5fc26 + 137:f782c14 1 0.00 1:61c14 + 137:f7888ab 2 0.00 1:678ab + 137:f7888b5 1 0.00 1:678b5 + 137:f788901 1 0.00 1:67901 + 137:f78891c 1 0.00 1:6791c + 137:f788afb 1 0.00 1:67afb + 137:f788b0b 1 0.00 1:67b0b + 137:f788b8c 1 0.00 1:67b8c + 137:f7a212f 2 0.00 2:12f + 137:f7a21b8 1 0.00 2:1b8 + 137:f7a21f5 1 0.00 2:1f5 + 137:f7a2235 1 0.00 2:235 + 137:f7a2484 1 0.00 2:484 + 137:f7a275c 2 0.00 2:75c + 137:f7a2771 1 0.00 2:771 + 137:f7a277e 2 0.00 2:77e + 137:f7a2796 1 0.00 2:796 + 137:f7a27b1 1 0.00 2:7b1 + 137:f7a27bb 1 0.00 2:7bb + 137:f7a27e2 1 0.00 2:7e2 + 137:f7a27f3 1 0.00 2:7f3 + 137:f7a29bd 1 0.00 2:9bd + 137:f7a29c9 2 0.00 2:9c9 + 137:f7a2b19 1 0.00 2:b19 + 137:f7a2b3c 1 0.00 2:b3c + 137:f7a2cff 1 0.00 2:cff + 137:f7a2d54 1 0.00 2:d54 + 137:f7a2e4b 1 0.00 2:e4b + 137:f7a2e7a 1 0.00 2:e7a + 137:f7a2e8a 1 0.00 2:e8a + 137:f7a2e96 2 0.00 2:e96 + 137:f7a2ed3 1 0.00 2:ed3 + 137:f7a2f0a 1 0.00 2:f0a + 137:f7a37e4 1 0.00 2:17e4 + 137:f7a3840 1 0.00 2:1840 + 137:f7a3856 1 0.00 2:1856 + 137:f7a3917 2 0.00 2:1917 + 137:f7a3b51 1 0.00 2:1b51 + 137:f7a3c0f 1 0.00 2:1c0f + 137:f7a3c15 1 0.00 2:1c15 + 137:f7a3c23 1 0.00 2:1c23 + 137:f7a3d33 1 0.00 2:1d33 + 137:f7a4752 1 0.00 2:2752 + 137:f7a4774 1 0.00 2:2774 + 137:f7a4857 1 0.00 2:2857 + 137:f7a4d71 2 0.00 2:2d71 + 137:f7a4d78 1 0.00 2:2d78 + 137:f7a5434 2 0.00 2:3434 + 137:f7a5a75 1 0.00 2:3a75 + 137:f7a5a91 1 0.00 2:3a91 + 137:f7a5d6d 1 0.00 2:3d6d + 137:f7a600b 1 0.00 2:400b + 137:f7a61e7 1 0.00 2:41e7 + 137:f7a679c 1 0.00 2:479c + 137:f7a757d 1 0.00 2:557d + 137:f7aa68a 1 0.00 2:868a + 137:f7aae97 1 0.00 2:8e97 + 137:f7ab600 4 0.00 2:9600 + 137:f7acd3c 1 0.00 2:ad3c + +Module Name WSOCK32 + + CS:EIP Samples (%) Map Offset Symbol + 137:7e2ea468 1 0.00 1:9468 + +Module Name MSVCRT20 + + CS:EIP Samples (%) Map Offset Symbol + 137:7fd8174f 1 0.00 1:74f + 137:7fd819c6 1 0.00 1:9c6 + 137:7fd81a14 1 0.00 1:a14 + 137:7fd83bba 1 0.00 1:2bba + 137:7fd83bc5 2 0.00 1:2bc5 + 137:7fd83bc9 1 0.00 1:2bc9 + +Module Name HPSNMP + + CS:EIP Samples (%) Map Offset Symbol + 137:1081d2d 1 0.00 1:d2d + 137:1083bc5 1 0.00 1:2bc5 + 137:1083d58 1 0.00 1:2d58 + 137:108447e 1 0.00 1:347e + 137:1084a0d 1 0.00 1:3a0d + 137:1085976 1 0.00 1:4976 + 137:1085ed1 5 0.00 1:4ed1 + 137:1085ed3 1 0.00 1:4ed3 + 137:1085f1e 3 0.00 1:4f1e + 137:1085f84 4 0.00 1:4f84 + 137:10883d7 1 0.00 1:73d7 + +Module Name HPPELK + + CS:EIP Samples (%) Map Offset Symbol + 137:14110f7 1 0.00 1:f7 + +Module Name OLE32 + + CS:EIP Samples (%) Map Offset Symbol + 137:19e01298 2 0.00 1:298 + 137:19e012ff 2 0.00 1:2ff + 137:19e01320 1 0.00 1:320 + 137:19e0135e 1 0.00 1:35e + 137:19e01368 5 0.00 1:368 + 137:19e0137a 1 0.00 1:37a + 137:19e013c6 1 0.00 1:3c6 + 137:19e013ce 1 0.00 1:3ce + 137:19e3dee5 2 0.00 1:3cee5 + 137:19e3deee 1 0.00 1:3ceee + 137:19e3df21 2 0.00 1:3cf21 + 137:19e3e04e 1 0.00 1:3d04e + +Module Name RPCRT4 + + CS:EIP Samples (%) Map Offset Symbol + 137:7fd02c9a 1 0.00 1:1c9a + +Module Name OLEAUT32 + + CS:EIP Samples (%) Map Offset Symbol + 137:65345641 1 0.00 1:4641 + 137:6534577d 1 0.00 1:477d + 137:6534578e 1 0.00 1:478e + 137:65345795 1 0.00 1:4795 + 137:65345796 1 0.00 1:4796 + 137:6534579b 1 0.00 1:479b + 137:653457ae 1 0.00 1:47ae + 137:653457b2 1 0.00 1:47b2 + 137:6534597a 2 0.00 1:497a + 137:6534598b 1 0.00 1:498b + 137:65345ae9 1 0.00 1:4ae9 + 137:65345bd1 1 0.00 1:4bd1 + 137:65345bf9 1 0.00 1:4bf9 + 137:65345c19 1 0.00 1:4c19 + 137:65345eb2 1 0.00 1:4eb2 + 137:65347070 1 0.00 1:6070 + 137:6534707c 2 0.00 1:607c + 137:6534709d 1 0.00 1:609d + 137:6534709e 1 0.00 1:609e + 137:653470a3 1 0.00 1:60a3 + 137:653470b6 1 0.00 1:60b6 + 137:653470bc 1 0.00 1:60bc + 137:653470f5 1 0.00 1:60f5 + 137:65347109 1 0.00 1:6109 + 137:6534f66c 1 0.00 1:e66c + 137:6534f7c1 1 0.00 1:e7c1 + 137:653592b8 1 0.00 1:182b8 + 137:6535930b 1 0.00 1:1830b + 137:65359312 1 0.00 1:18312 + 137:6535a363 1 0.00 1:19363 + 137:6535a699 1 0.00 1:19699 + 137:6535d0c4 1 0.00 1:1c0c4 + 137:6535f8c0 2 0.00 1:1e8c0 + 137:6535f8c6 1 0.00 1:1e8c6 + 137:653605a0 1 0.00 1:1f5a0 + 137:6536064a 1 0.00 1:1f64a + 137:653610e9 1 0.00 1:200e9 + 137:65361c77 1 0.00 1:20c77 + 137:65361ddf 2 0.00 1:20ddf + 137:65361e02 1 0.00 1:20e02 + 137:653627f8 2 0.00 1:217f8 + 137:65362814 1 0.00 1:21814 + 137:65363869 1 0.00 1:22869 + 137:6536387b 1 0.00 1:2287b + 137:6536388c 1 0.00 1:2288c + 137:6536388e 1 0.00 1:2288e + 137:65363894 1 0.00 1:22894 + 137:6536414f 5 0.00 1:2314f + 137:65364156 1 0.00 1:23156 + 137:65364164 1 0.00 1:23164 + 137:6536416d 1 0.00 1:2316d + 137:6536417b 2 0.00 1:2317b + 137:653641f5 4 0.00 1:231f5 + 137:653641ff 2 0.00 1:231ff + 137:65364205 1 0.00 1:23205 + 137:653649d4 1 0.00 1:239d4 + 137:65364b56 1 0.00 1:23b56 + 137:65364b66 1 0.00 1:23b66 + 137:65364b6f 1 0.00 1:23b6f + 137:65364c40 1 0.00 1:23c40 + 137:65364c43 3 0.00 1:23c43 + 137:65365ca4 1 0.00 1:24ca4 + 137:65365e13 1 0.00 1:24e13 + 137:65365e17 1 0.00 1:24e17 + 137:65365e7a 1 0.00 1:24e7a + 137:6536dd75 1 0.00 1:2cd75 + 137:6536dd7f 1 0.00 1:2cd7f + 137:6536fcf4 2 0.00 1:2ecf4 + 137:6538ca90 1 0.00 1:4ba90 + 137:6538d3d0 1 0.00 1:4c3d0 + 137:6538d3f2 3 0.00 1:4c3f2 + 137:65390339 1 0.00 1:4f339 + 137:6539902c 7 0.00 1:5802c + 137:65399047 1 0.00 1:58047 + 137:6539904d 1 0.00 1:5804d + 137:65399077 1 0.00 1:58077 + 137:65399088 1 0.00 1:58088 + 137:6539909e 1 0.00 1:5809e + 137:653990af 1 0.00 1:580af + 137:653990b6 1 0.00 1:580b6 + 137:65399111 1 0.00 1:58111 + 137:65399311 1 0.00 1:58311 + 137:65399324 1 0.00 1:58324 + 137:65399337 1 0.00 1:58337 + 137:653993f8 1 0.00 1:583f8 + 137:653998b8 1 0.00 1:588b8 + 137:653998e9 1 0.00 1:588e9 + 137:653999b5 1 0.00 1:589b5 + 137:65399fe2 2 0.00 1:58fe2 + 137:65399ff7 1 0.00 1:58ff7 + 137:65399ffd 1 0.00 1:58ffd + 137:6539aa3a 1 0.00 1:59a3a + 137:6539aa42 1 0.00 1:59a42 + 137:6539ac36 1 0.00 1:59c36 + 137:6539ac53 1 0.00 1:59c53 + 137:6539aff9 2 0.00 1:59ff9 + 137:6539b093 1 0.00 1:5a093 + 137:6539b095 1 0.00 1:5a095 + 137:6539b0a9 2 0.00 1:5a0a9 + 137:6539b0ce 1 0.00 1:5a0ce + 137:6539b0d7 1 0.00 1:5a0d7 + 137:6539b160 1 0.00 1:5a160 + 137:6539b18d 1 0.00 1:5a18d + 137:6539b197 1 0.00 1:5a197 + 137:653a13a2 1 0.00 1:603a2 + 137:653a13cf 1 0.00 1:603cf + 137:653a1472 1 0.00 1:60472 + 137:653a1597 1 0.00 1:60597 + 137:653a17f5 2 0.00 1:607f5 + 137:653a1815 2 0.00 1:60815 + 137:653a1888 1 0.00 1:60888 + +Module Name DAO3032 + + CS:EIP Samples (%) Map Offset Symbol + 137:4729e31 1 0.00 1:28e31 + +Module Name COMDLG32 + + CS:EIP Samples (%) Map Offset Symbol + 137:217a1293 2 0.00 1:293 + +Module Name THREED32 + + CS:EIP Samples (%) Map Offset Symbol + 137:16e1670 2 0.00 1:670 + 137:16e1690 2 0.00 1:690 + 137:16e2c12 1 0.00 1:1c12 + 137:16e2d57 1 0.00 1:1d57 + 137:16e7cc0 1 0.00 1:6cc0 + 137:16e7f80 1 0.00 1:6f80 + 137:16e7ff6 2 0.00 1:6ff6 + 137:16e7ffb 1 0.00 1:6ffb + 137:16e82c4 1 0.00 1:72c4 + 137:16e95b0 1 0.00 1:85b0 + 137:16e9620 1 0.00 1:8620 + 137:16e99a7 1 0.00 1:89a7 + 137:16ea631 1 0.00 1:9631 + 137:16eab10 1 0.00 1:9b10 + 137:16eaed0 1 0.00 1:9ed0 + 137:16ed080 1 0.00 1:c080 + 137:16ed3bb 1 0.00 1:c3bb + 137:16f0f50 1 0.00 1:ff50 + 137:16f6de2 1 0.00 1:15de2 + 137:16f6e90 1 0.00 1:15e90 + 137:16f6ec6 1 0.00 1:15ec6 + 137:16f701c 2 0.00 1:1601c + 137:16f7022 1 0.00 1:16022 + 137:16f7352 1 0.00 1:16352 + 137:16f74c3 1 0.00 1:164c3 + 137:16f7763 2 0.00 1:16763 + 137:16f7ba4 1 0.00 1:16ba4 + +Module Name MFC40 + + CS:EIP Samples (%) Map Offset Symbol + 137:5f801000 10 0.01 1:0 + 137:5f801016 1 0.00 1:16 + 137:5f801022 1 0.00 1:22 + 137:5f80103f 1 0.00 1:3f + 137:5f801055 1 0.00 1:55 + 137:5f801064 1 0.00 1:64 + 137:5f80107c 1 0.00 1:7c + 137:5f801083 1 0.00 1:83 + 137:5f801092 1 0.00 1:92 + 137:5f8010a2 2 0.00 1:a2 + 137:5f8010b4 1 0.00 1:b4 + 137:5f8010f8 1 0.00 1:f8 + 137:5f801123 1 0.00 1:123 + 137:5f801186 1 0.00 1:186 + 137:5f8011c4 2 0.00 1:1c4 + 137:5f8011cb 2 0.00 1:1cb + 137:5f8011d4 1 0.00 1:1d4 + 137:5f8011e0 1 0.00 1:1e0 + 137:5f8011e3 1 0.00 1:1e3 + 137:5f8011e5 3 0.00 1:1e5 + 137:5f8011e8 1 0.00 1:1e8 + 137:5f8011eb 3 0.00 1:1eb + 137:5f801243 3 0.00 1:243 + 137:5f801252 2 0.00 1:252 + 137:5f801259 1 0.00 1:259 + 137:5f80125c 1 0.00 1:25c + 137:5f801288 2 0.00 1:288 + 137:5f801290 1 0.00 1:290 + 137:5f8012aa 1 0.00 1:2aa + 137:5f8012b9 2 0.00 1:2b9 + 137:5f8012c9 1 0.00 1:2c9 + 137:5f8012d0 2 0.00 1:2d0 + 137:5f801327 1 0.00 1:327 + 137:5f801358 1 0.00 1:358 + 137:5f801375 1 0.00 1:375 + 137:5f8013f6 1 0.00 1:3f6 + 137:5f80155f 2 0.00 1:55f + 137:5f80157c 1 0.00 1:57c + 137:5f80157f 1 0.00 1:57f + 137:5f8015ad 1 0.00 1:5ad + 137:5f8015d3 1 0.00 1:5d3 + 137:5f80175a 1 0.00 1:75a + 137:5f80187e 1 0.00 1:87e + 137:5f801897 1 0.00 1:897 + 137:5f801b2d 1 0.00 1:b2d + 137:5f801b7d 1 0.00 1:b7d + 137:5f801d34 1 0.00 1:d34 + 137:5f801d83 1 0.00 1:d83 + 137:5f801d9f 1 0.00 1:d9f + 137:5f801dad 2 0.00 1:dad + 137:5f802029 1 0.00 1:1029 + 137:5f802461 1 0.00 1:1461 + 137:5f802555 1 0.00 1:1555 + 137:5f80292d 4 0.00 1:192d + 137:5f8035d0 1 0.00 1:25d0 + 137:5f803732 1 0.00 1:2732 + 137:5f80385b 1 0.00 1:285b + 137:5f803b4c 1 0.00 1:2b4c + 137:5f803b74 1 0.00 1:2b74 + 137:5f8045be 1 0.00 1:35be + 137:5f804fae 3 0.00 1:3fae + 137:5f804fe1 1 0.00 1:3fe1 + 137:5f805024 2 0.00 1:4024 + 137:5f805ac8 1 0.00 1:4ac8 + 137:5f8061ab 1 0.00 1:51ab + 137:5f806e14 2 0.00 1:5e14 + 137:5f80b9e8 3 0.00 1:a9e8 + 137:5f811b9d 2 0.00 1:10b9d + 137:5f82137a 1 0.00 1:2037a + 137:5f821413 1 0.00 1:20413 + 137:5f82145b 1 0.00 1:2045b + 137:5f8215de 2 0.00 1:205de + 137:5f82166a 1 0.00 1:2066a + 137:5f8216b6 1 0.00 1:206b6 + 137:5f8216fe 1 0.00 1:206fe + 137:5f821703 1 0.00 1:20703 + 137:5f82172a 1 0.00 1:2072a + 137:5f821737 1 0.00 1:20737 + 137:5f82186e 1 0.00 1:2086e + 137:5f82188a 1 0.00 1:2088a + 137:5f82195b 2 0.00 1:2095b + 137:5f821967 1 0.00 1:20967 + 137:5f82196f 1 0.00 1:2096f + 137:5f821b48 1 0.00 1:20b48 + 137:5f821b4c 1 0.00 1:20b4c + 137:5f821b61 1 0.00 1:20b61 + 137:5f821c07 1 0.00 1:20c07 + 137:5f82a0d4 1 0.00 1:290d4 + 137:5f83358b 1 0.00 1:3258b + 137:5f833592 2 0.00 1:32592 + 137:5f853ff5 1 0.00 1:52ff5 + 137:5f853ff6 1 0.00 1:52ff6 + 137:5f854026 1 0.00 1:53026 + 137:5f854039 1 0.00 1:53039 + 137:5f85403b 4 0.00 1:5303b + 137:5f854056 1 0.00 1:53056 + 137:5f854071 1 0.00 1:53071 + 137:5f862565 1 0.00 1:61565 + 137:5f862619 2 0.00 1:61619 + 137:5f862630 1 0.00 1:61630 + 137:5f8627f1 1 0.00 1:617f1 + 137:5f8627f3 1 0.00 1:617f3 + 137:5f86298e 1 0.00 1:6198e + 137:5f866676 1 0.00 1:65676 + 137:5f866683 1 0.00 1:65683 + 137:5f866684 1 0.00 1:65684 + 137:5f867048 1 0.00 1:66048 + 137:5f867217 1 0.00 1:66217 + 137:5f867ff6 1 0.00 1:66ff6 + 137:5f86804b 1 0.00 1:6704b + 137:5f86804d 1 0.00 1:6704d + 137:5f868052 1 0.00 1:67052 + 137:5f8680c3 2 0.00 1:670c3 + 137:5f868723 2 0.00 1:67723 + 137:5f86a018 1 0.00 1:69018 + 137:5f86adca 1 0.00 1:69dca + 137:5f870e2e 1 0.00 1:6fe2e + 137:5f870faf 1 0.00 1:6ffaf + 137:5f870feb 1 0.00 1:6ffeb + 137:5f871326 1 0.00 1:70326 + +Module Name MSVCRT40 + + CS:EIP Samples (%) Map Offset Symbol + 137:10226468 6 0.00 1:25468 + 137:1022646b 1 0.00 1:2546b + 137:10226481 2 0.00 1:25481 + 137:10237020 2 0.00 1:36020 + 137:10237036 1 0.00 1:36036 + 137:10237077 4 0.00 1:36077 + 137:102370a2 1 0.00 1:360a2 + 137:10237140 1 0.00 1:36140 + 137:10237220 3 0.00 1:36220 + 137:10237263 1 0.00 1:36263 + 137:10237277 1 0.00 1:36277 + +Module Name TABCTL32 + + CS:EIP Samples (%) Map Offset Symbol + 137:212f8969 1 0.00 1:7969 + 137:212f8970 1 0.00 1:7970 + +Module Name SPIN32 + + CS:EIP Samples (%) Map Offset Symbol + 137:19e623a 1 0.00 1:523a + 137:19e6304 1 0.00 1:5304 + +Module Name GRID32 + + CS:EIP Samples (%) Map Offset Symbol + 137:1a6b564 1 0.00 1:a564 + +Module Name HELLFIRE + + CS:EIP Samples (%) Map Offset Symbol + 137:4e768b 1 0.00 1:e668b + +Module Name STORMD + + CS:EIP Samples (%) Map Offset Symbol + 137:15005aef 1 0.00 1:4aef + 137:150067cd 1 0.00 1:57cd + 137:15008730 1 0.00 1:7730 + 137:15017dc1 1 0.00 1:16dc1 + 137:1501e28c 1 0.00 1:1d28c + 137:1501e6ef 1 0.00 1:1d6ef + +Module Name MSVCRTD + + CS:EIP Samples (%) Map Offset Symbol + 137:10216d89 1 0.00 1:15d89 + 137:10216da1 11 0.01 1:15da1 + 137:10217012 1 0.00 1:16012 + +Module Name DDRAW + + CS:EIP Samples (%) Map Offset Symbol + 137:baaa1277 1 0.00 1:277 + 137:baaba1fe 1 0.00 1:191fe + +Module Name DDHELP + + CS:EIP Samples (%) Map Offset Symbol + 137:40436e 1 0.00 1:336e + +Module Name DDRAW16 + + CS:EIP Samples (%) Map Offset Symbol +1b7f:524 1 0.00 5:524 +1b7f:77a 1 0.00 5:77a + +Module Name URL + + CS:EIP Samples (%) Map Offset Symbol + 137:63281dd1 1 0.00 1:dd1 + +Module Name SHELL32 + + CS:EIP Samples (%) Map Offset Symbol + 137:7eb49ddd 1 0.00 1:8ddd + +Module Name DSOUND + + CS:EIP Samples (%) Map Offset Symbol + 137:beaf1040 1 0.00 1:40 + 137:beaf8ddf 1 0.00 1:7ddf + 137:beafff0b 1 0.00 1:ef0b + 137:beb072a1 1 0.00 1:162a1 + +Module Name AUTORUN + + CS:EIP Samples (%) Map Offset Symbol + 137:4032b6 1 0.00 1:22b6 + 137:4035cf 1 0.00 1:25cf + 137:40a5fe 1 0.00 1:95fe + 137:40aca4 1 0.00 1:9ca4 + 137:40aca7 1 0.00 1:9ca7 + 137:40acad 3 0.00 1:9cad + 137:40acb1 1 0.00 1:9cb1 + 137:40acb7 2 0.00 1:9cb7 + 137:40acc5 1 0.00 1:9cc5 + 137:40accc 1 0.00 1:9ccc + 137:40acd2 4 0.00 1:9cd2 + 137:40acd8 2 0.00 1:9cd8 + 137:40acdd 10 0.01 1:9cdd + 137:40ace3 1 0.00 1:9ce3 + 137:40ace5 4 0.00 1:9ce5 + 137:40ace8 1 0.00 1:9ce8 + 137:40aceb 2 0.00 1:9ceb + 137:40acf2 1 0.00 1:9cf2 + 137:40acf5 1 0.00 1:9cf5 + 137:40ad02 1 0.00 1:9d02 + 137:40b998 1 0.00 1:a998 + 137:40b9aa 1 0.00 1:a9aa + 137:40b9b0 2 0.00 1:a9b0 + 137:40b9bb 1 0.00 1:a9bb + 137:40ba63 1 0.00 1:aa63 + 137:40be3e 2 0.00 1:ae3e + 137:40c1d6 1 0.00 1:b1d6 + 137:40c39b 1 0.00 1:b39b + 137:40d799 1 0.00 1:c799 + 137:40df25 2 0.00 1:cf25 + 137:40df2e 4 0.00 1:cf2e + 137:40df48 3 0.00 1:cf48 + 137:40df5b 4 0.00 1:cf5b + 137:40df61 1 0.00 1:cf61 + 137:40df67 6 0.00 1:cf67 + 137:40df76 5 0.00 1:cf76 + 137:40df7d 1 0.00 1:cf7d + 137:40df90 1 0.00 1:cf90 + 137:40df9c 5 0.00 1:cf9c + 137:40e057 1 0.00 1:d057 + 137:40e05a 1 0.00 1:d05a + 137:40e0a2 1 0.00 1:d0a2 + 137:411220 1 0.00 1:10220 + 137:411508 2 0.00 1:10508 + 137:411513 2 0.00 1:10513 + 137:41151a 25 0.01 1:1051a + 137:41151c 2 0.00 1:1051c + 137:411527 1 0.00 1:10527 + 137:411535 6 0.00 1:10535 + 137:4129b0 1 0.00 1:119b0 + 137:412a54 1 0.00 1:11a54 + 137:413390 1 0.00 1:12390 + 137:4133be 1 0.00 1:123be + +Module Name SHELL32 + + CS:EIP Samples (%) Map Offset Symbol + 137:7eb5375c 1 0.00 1:1275c + +Module Name OLE32 + + CS:EIP Samples (%) Map Offset Symbol + 137:19e0f02c 1 0.00 1:e02c + +Module Name MSVCRT20 + + CS:EIP Samples (%) Map Offset Symbol + 137:7fd8438b 1 0.00 1:338b + +Module Name HIMEM + + CS:EIP Samples (%) Map Offset Symbol + 224:70 13634 7.10 0:0 + 224:a3 658 0.34 0:0 + + + +Module Name Other B32 + + CS:EIP Samples (%) + 28:bff7b45a 1 0.00 + 28:bff7b4f7 2 0.00 + 28:bff7b558 1 0.00 + 28:c100d2bc 1436 0.75 + 28:c100d2c1 24 0.01 + 28:c100d2cc 32 0.02 + 28:c100d418 1720 0.90 + 28:c100d41d 144 0.07 + 28:c100d428 552 0.29 + 28:c100d45c 1152 0.60 + 28:c100d461 68 0.04 + 28:c100d466 1 0.00 + 28:c100d46c 218 0.11 + 28:c100d574 1434 0.75 + 28:c100d579 69 0.04 + 28:c100d57e 11 0.01 + 28:c100d584 118 0.06 + 28:c100dc84 227 0.12 + 28:c100dc89 50 0.03 + 28:c100dc94 139 0.07 + 28:c100dd10 38 0.02 + 28:c100dd15 227 0.12 + 28:c100dd1a 303 0.16 + 28:c100dd20 1 0.00 + 28:c100df54 41 0.02 + 28:c100df5e 3 0.00 + 28:c100df64 40 0.02 + 28:c100dfc8 231 0.12 + 28:c100dfcd 29 0.02 + 28:c100dfd2 1 0.00 + 28:c100dfd8 17 0.01 + 28:c100e098 1 0.00 + 28:c100e0f8 1045 0.54 + 28:c100e0fd 45 0.02 + 28:c100e102 22 0.01 + 28:c100e108 112 0.06 + 28:c100e4dd 2 0.00 + 28:c100e69d 1 0.00 + 28:c100e940 2 0.00 + + 93:a 75 0.04 + + 137:b01dae 1 0.00 + 137:b01e98 1 0.00 + 137:b10020 1 0.00 + 137:b412d6 1 0.00 + 137:bfe6a044 13 0.01 + 137:bfe6a047 1 0.00 + 137:bfe6a04e 6 0.00 + 137:bff4b020 7 0.00 + 137:bff4b02c 1 0.00 + 137:bff4b031 2 0.00 + 137:bff4b056 2 0.00 + 137:bff4b060 1 0.00 + 137:bff67020 13 0.01 + 137:bff6702c 9 0.00 + 137:bff67031 1 0.00 + 137:bff67056 4 0.00 + 137:bffbc45c 3 0.00 + 137:bffbc461 1 0.00 + + 4f7:934 2 0.00 + 4f7:939 1 0.00 + 4f7:942 1 0.00 + 4f7:946 1 0.00 + 4f7:94a 1 0.00 + 4f7:94f 1 0.00 + 4f7:954 1 0.00 + 4f7:957 1 0.00 + 4f7:959 4 0.00 + 4f7:95d 1 0.00 + 4f7:964 1 0.00 + 4f7:966 2 0.00 + 4f7:968 2 0.00 + 4f7:96e 1 0.00 + 4f7:972 2 0.00 + 4f7:97c 1 0.00 + 4f7:984 1 0.00 + 4f7:995 1 0.00 + 4f7:9a0 1 0.00 + 4f7:9a3 1 0.00 + 4f7:9d2 1 0.00 + 4f7:9d3 1 0.00 + 4f7:9f3 1 0.00 + + + +Module Name Other B16 + + CS:EIP Samples (%) + 3b:204 1 0.00 + 3b:3c2 1 0.00 + 3b:3d2 4 0.00 + 3b:3de 5 0.00 + 3b:3ec 14 0.01 + + 16f:20 2 0.00 + 16f:28 13 0.01 + +140f:1c4 3 0.00 +140f:1ca 1 0.00 +140f:33a 3 0.00 +140f:350 3 0.00 +140f:356 1 0.00 +140f:836 1 0.00 +140f:918 1 0.00 +140f:aca 1 0.00 + + + +Module Name Other V86 + + CS:EIP Samples (%) + 70:5 393 0.20 + 70:46e 21 0.01 + +fcb2:2ff7 1870 0.97 + +ff03:4269 2 0.00 +ff03:427a 1 0.00 +ff03:45a6 1 0.00 +ff03:461e 9247 4.81 +ff03:462a 286 0.15 +ff03:462f 86 0.04 +ff03:4634 7 0.00 +ff03:463c 82 0.04 +ff03:4641 345 0.18 +ff03:4646 506 0.26 +ff03:464c 1713 0.89 +ff03:4652 81 0.04 +ff03:4654 1 0.00 +ff03:4697 405 0.21 +ff03:469a 3 0.00 +ff03:46fc 991 0.52 +ff03:46fd 75 0.04 +ff03:5311 1 0.00 +ff03:5326 1 0.00 +ff03:7132 1 0.00 + +ffff:40 1 0.00 +ffff:b2c 1 0.00 +ffff:20b4 1658 0.86 +ffff:20b7 2 0.00 +ffff:20b9 1 0.00 +ffff:20be 76 0.04 +ffff:20c1 2 0.00 +ffff:214d 169 0.09 +ffff:214f 34 0.02 +ffff:2152 77 0.04 +ffff:2159 171 0.09 +ffff:2160 131 0.07 +ffff:2165 66 0.03 +ffff:2167 190 0.10 +ffff:216c 206 0.11 +ffff:2173 117 0.06 +ffff:2177 25 0.01 +ffff:2179 9 0.00 +ffff:217b 16 0.01 +ffff:217d 29 0.02 +ffff:2181 23 0.01 +ffff:21a6 489 0.25 +ffff:21a9 65 0.03 +ffff:21df 575 0.30 +ffff:21e0 64 0.03 + diff --git a/src/Windebug/CLOCK001.MDB b/src/Windebug/CLOCK001.MDB new file mode 100644 index 0000000..e0a4ed2 Binary files /dev/null and b/src/Windebug/CLOCK001.MDB differ diff --git a/src/Windebug/COMMAND.TXT b/src/Windebug/COMMAND.TXT new file mode 100644 index 0000000..e14f56f --- /dev/null +++ b/src/Windebug/COMMAND.TXT @@ -0,0 +1 @@ +Multitest;Barbariantest;Cowquest;Theoquest;NestArt diff --git a/src/Windebug/CSIPS.TBS b/src/Windebug/CSIPS.TBS new file mode 100644 index 0000000..5236c0c Binary files /dev/null and b/src/Windebug/CSIPS.TBS differ diff --git a/src/Windebug/DATA/DIABSMAL.CEL b/src/Windebug/DATA/DIABSMAL.CEL new file mode 100644 index 0000000..6ef8df8 Binary files /dev/null and b/src/Windebug/DATA/DIABSMAL.CEL differ diff --git a/src/Windebug/DATA/HF_LOGO3.CEL b/src/Windebug/DATA/HF_LOGO3.CEL new file mode 100644 index 0000000..82e37b1 Binary files /dev/null and b/src/Windebug/DATA/HF_LOGO3.CEL differ diff --git a/src/Windebug/DATA/INV/OBJCURS2.CEL b/src/Windebug/DATA/INV/OBJCURS2.CEL new file mode 100644 index 0000000..28929a7 Binary files /dev/null and b/src/Windebug/DATA/INV/OBJCURS2.CEL differ diff --git a/src/Windebug/DATA/SPELICON.CEL b/src/Windebug/DATA/SPELICON.CEL new file mode 100644 index 0000000..8fdef81 Binary files /dev/null and b/src/Windebug/DATA/SPELICON.CEL differ diff --git a/src/Windebug/DATA/SPELLBK.CEL b/src/Windebug/DATA/SPELLBK.CEL new file mode 100644 index 0000000..ed62ab8 Binary files /dev/null and b/src/Windebug/DATA/SPELLBK.CEL differ diff --git a/src/Windebug/DATA/SPELLBKB.CEL b/src/Windebug/DATA/SPELLBKB.CEL new file mode 100644 index 0000000..ed30a72 Binary files /dev/null and b/src/Windebug/DATA/SPELLBKB.CEL differ diff --git a/src/Windebug/DATA/SPELLI2.CEL b/src/Windebug/DATA/SPELLI2.CEL new file mode 100644 index 0000000..0a69a84 Binary files /dev/null and b/src/Windebug/DATA/SPELLI2.CEL differ diff --git a/src/Windebug/DEBUG/VC50.IDB b/src/Windebug/DEBUG/VC50.IDB new file mode 100644 index 0000000..0ca98e8 Binary files /dev/null and b/src/Windebug/DEBUG/VC50.IDB differ diff --git a/src/Windebug/DIABLO.BSC b/src/Windebug/DIABLO.BSC new file mode 100644 index 0000000..7c42cf4 Binary files /dev/null and b/src/Windebug/DIABLO.BSC differ diff --git a/src/Windebug/DIABLO.PCC b/src/Windebug/DIABLO.PCC new file mode 100644 index 0000000..737f712 Binary files /dev/null and b/src/Windebug/DIABLO.PCC differ diff --git a/src/Windebug/DIABLO.PCH b/src/Windebug/DIABLO.PCH new file mode 100644 index 0000000..c209c0d Binary files /dev/null and b/src/Windebug/DIABLO.PCH differ diff --git a/src/Windebug/DIABLO.RES b/src/Windebug/DIABLO.RES new file mode 100644 index 0000000..d99383f Binary files /dev/null and b/src/Windebug/DIABLO.RES differ diff --git a/src/Windebug/DIABLO.SUP b/src/Windebug/DIABLO.SUP new file mode 100644 index 0000000..47ff7d9 --- /dev/null +++ b/src/Windebug/DIABLO.SUP @@ -0,0 +1,6 @@ +//SUPPRESSIONPROJ:Diablo +//VERSION:5.00 +//ENABLE:Yes + +ignore param 5 KERNEL32.DLL:CreateFileA in function EXE:"MonoDevice::DeviceData::DeviceData" +ignore param 7 KERNEL32.DLL:DeviceIoControl in function EXE:"MonoDevice::ClearScreen" diff --git a/src/Windebug/DIABLOUI.RES b/src/Windebug/DIABLOUI.RES new file mode 100644 index 0000000..f28d57a Binary files /dev/null and b/src/Windebug/DIABLOUI.RES differ diff --git a/src/Windebug/FILE_ID.DIZ b/src/Windebug/FILE_ID.DIZ new file mode 100644 index 0000000..070fe2b --- /dev/null +++ b/src/Windebug/FILE_ID.DIZ @@ -0,0 +1,6 @@ + DiABLO HELLFiRE MULTiPLAYER PATCH [1/1] +ßßßßÛÜßßßßÛÜßßßßÛÛ ²Û ÛÛ ²Û ßßßÛÜ ÜÛßÛÛßßß ÜÛ +:²ÛÜÛß ²Û ÛÛ ²Û ß ÛÛÜÛß ÛÛ ²Û ÛÛ ßÛÜÜ ²ÛÜÛÛ +|ÛÛ Û² ÛÛßÛÛ ÛÛ Ü ÛÛ ÛÛ ÛÛ ÛÛßÛÛ ÜÜ ÛÛ ÛÛ ÛÛ +³ÛÛÜÛß ÛÛ Û² ßÛÜÛÛ ÛÛ Û² ßÛÜÜÜ Û² ²ÛÜÛß ÛÛ Û² +ÀÄÄÄÄ[ RELEASE DATE: 11/30/1997 ]ÄÄÄÄÄroyÄÄÄÄ diff --git a/src/Windebug/GENDATA/HELLFIRE.SAV b/src/Windebug/GENDATA/HELLFIRE.SAV new file mode 100644 index 0000000..506bb11 Binary files /dev/null and b/src/Windebug/GENDATA/HELLFIRE.SAV differ diff --git a/src/Windebug/GENDATA/HELLFIRE.SMK b/src/Windebug/GENDATA/HELLFIRE.SMK new file mode 100644 index 0000000..5b9bb4a Binary files /dev/null and b/src/Windebug/GENDATA/HELLFIRE.SMK differ diff --git a/src/Windebug/GENDATA/LOGO.SMK b/src/Windebug/GENDATA/LOGO.SMK new file mode 100644 index 0000000..5fe3ee0 Binary files /dev/null and b/src/Windebug/GENDATA/LOGO.SMK differ diff --git a/src/Windebug/HELLFIRE.EDB b/src/Windebug/HELLFIRE.EDB new file mode 100644 index 0000000..1f02b2d Binary files /dev/null and b/src/Windebug/HELLFIRE.EDB differ diff --git a/src/Windebug/HELLFIRE.EXE b/src/Windebug/HELLFIRE.EXE new file mode 100644 index 0000000..d6e144f Binary files /dev/null and b/src/Windebug/HELLFIRE.EXE differ diff --git a/src/Windebug/HELLFIRE.LDB b/src/Windebug/HELLFIRE.LDB new file mode 100644 index 0000000..700d70c Binary files /dev/null and b/src/Windebug/HELLFIRE.LDB differ diff --git a/src/Windebug/HELLFI~1 b/src/Windebug/HELLFI~1 new file mode 100644 index 0000000..07da851 Binary files /dev/null and b/src/Windebug/HELLFI~1 differ diff --git a/src/Windebug/HELLFI~1.EXE b/src/Windebug/HELLFI~1.EXE new file mode 100644 index 0000000..5342f47 Binary files /dev/null and b/src/Windebug/HELLFI~1.EXE differ diff --git a/src/Windebug/HELLFI~1.HIP b/src/Windebug/HELLFI~1.HIP new file mode 100644 index 0000000..9442c69 Binary files /dev/null and b/src/Windebug/HELLFI~1.HIP differ diff --git a/src/Windebug/HELLFI~1.TXT b/src/Windebug/HELLFI~1.TXT new file mode 100644 index 0000000..77613a6 --- /dev/null +++ b/src/Windebug/HELLFI~1.TXT @@ -0,0 +1,17 @@ +Application d:\diablo97\windebug\hellfire_hiprof.exe started properly. +Note: Passing this info to the GUI: requested "ddraw.dll", located "c:\windows\system\ddraw.dll" +Warning: LoadLibrary of ddraw.dll (UNEXPECTED) +Warning: *** To avoid potentially incorrect operation of your application, +Warning: *** please add the above dll and any subsequent unexpected dlls to +Warning: *** your AtomTools list and reinstrument your application. +Note: Passing this info to the GUI: requested "dsound.dll", located "c:\windows\system\dsound.dll" +Warning: LoadLibrary of dsound.dll (UNEXPECTED) +Note: Passing this info to the GUI: requested "smackw32.dll", located "d:\diablo97\windebug\smackw32.dll" +Warning: LoadLibrary of smackw32.dll (UNEXPECTED) +Note: Passing this info to the GUI: requested "D:\DIABLO97\WINDEBUG\Standard.snp", located "d:\diablo97\windebug\standard.snp" +Warning: LoadLibrary of D:\DIABLO97\WINDEBUG\Standard.snp (UNEXPECTED) +Note: Passing this info to the GUI: requested "D:\DIABLO97\WINDEBUG\StandardD.snp", located "d:\diablo97\windebug\standardd.snp" +Warning: LoadLibrary of D:\DIABLO97\WINDEBUG\StandardD.snp (UNEXPECTED) +Note: Passing this info to the GUI: requested "D:\DIABLO97\WINDEBUG\StandardD.snp", located "d:\diablo97\windebug\standardd.snp" +Warning: LoadLibrary of D:\DIABLO97\WINDEBUG\StandardD.snp (UNEXPECTED) +Application terminated properly. diff --git a/src/Windebug/HELLFI~2.HIP b/src/Windebug/HELLFI~2.HIP new file mode 100644 index 0000000..604caf8 Binary files /dev/null and b/src/Windebug/HELLFI~2.HIP differ diff --git a/src/Windebug/HELLFI~2.TXT b/src/Windebug/HELLFI~2.TXT new file mode 100644 index 0000000..7045f13 --- /dev/null +++ b/src/Windebug/HELLFI~2.TXT @@ -0,0 +1,17 @@ +Application d:\diablo97\windebug\hellfire.exe started properly. +Note: Passing this info to the GUI: requested "ddraw.dll", located "c:\windows\system\ddraw.dll" +Warning: LoadLibrary of ddraw.dll (UNEXPECTED) +Warning: *** To avoid potentially incorrect operation of your application, +Warning: *** please add the above dll and any subsequent unexpected dlls to +Warning: *** your AtomTools list and reinstrument your application. +Note: Passing this info to the GUI: requested "dsound.dll", located "c:\windows\system\dsound.dll" +Warning: LoadLibrary of dsound.dll (UNEXPECTED) +Note: Passing this info to the GUI: requested "smackw32.dll", located "d:\diablo97\windebug\smackw32.dll" +Warning: LoadLibrary of smackw32.dll (UNEXPECTED) +Note: Passing this info to the GUI: requested "D:\DIABLO97\WINDEBUG\Standard.snp", located "d:\diablo97\windebug\standard.snp" +Warning: LoadLibrary of D:\DIABLO97\WINDEBUG\Standard.snp (UNEXPECTED) +Note: Passing this info to the GUI: requested "D:\DIABLO97\WINDEBUG\StandardD.snp", located "d:\diablo97\windebug\standardd.snp" +Warning: LoadLibrary of D:\DIABLO97\WINDEBUG\StandardD.snp (UNEXPECTED) +Note: Passing this info to the GUI: requested "D:\DIABLO97\WINDEBUG\StandardD.snp", located "d:\diablo97\windebug\standardd.snp" +Warning: LoadLibrary of D:\DIABLO97\WINDEBUG\StandardD.snp (UNEXPECTED) +Application terminated properly. diff --git a/src/Windebug/HELLFI~3.HIP b/src/Windebug/HELLFI~3.HIP new file mode 100644 index 0000000..5c977c1 Binary files /dev/null and b/src/Windebug/HELLFI~3.HIP differ diff --git a/src/Windebug/HELLFI~4.HIP b/src/Windebug/HELLFI~4.HIP new file mode 100644 index 0000000..056e17e Binary files /dev/null and b/src/Windebug/HELLFI~4.HIP differ diff --git a/src/Windebug/HELLFI~5.HIP b/src/Windebug/HELLFI~5.HIP new file mode 100644 index 0000000..3aafac1 Binary files /dev/null and b/src/Windebug/HELLFI~5.HIP differ diff --git a/src/Windebug/HELLFI~6.HIP b/src/Windebug/HELLFI~6.HIP new file mode 100644 index 0000000..f967097 Binary files /dev/null and b/src/Windebug/HELLFI~6.HIP differ diff --git a/src/Windebug/HELLFI~7.HIP b/src/Windebug/HELLFI~7.HIP new file mode 100644 index 0000000..1485c5c Binary files /dev/null and b/src/Windebug/HELLFI~7.HIP differ diff --git a/src/Windebug/HELLFI~8.HIP b/src/Windebug/HELLFI~8.HIP new file mode 100644 index 0000000..b37d7a4 Binary files /dev/null and b/src/Windebug/HELLFI~8.HIP differ diff --git a/src/Windebug/HELLFI~9.HIP b/src/Windebug/HELLFI~9.HIP new file mode 100644 index 0000000..5ac6508 Binary files /dev/null and b/src/Windebug/HELLFI~9.HIP differ diff --git a/src/Windebug/HELLFRUI.DLL b/src/Windebug/HELLFRUI.DLL new file mode 100644 index 0000000..8496eaa Binary files /dev/null and b/src/Windebug/HELLFRUI.DLL differ diff --git a/src/Windebug/HELLFRUI.EXP b/src/Windebug/HELLFRUI.EXP new file mode 100644 index 0000000..1a16b44 Binary files /dev/null and b/src/Windebug/HELLFRUI.EXP differ diff --git a/src/Windebug/HELLFRUI.LIB b/src/Windebug/HELLFRUI.LIB new file mode 100644 index 0000000..93f6128 Binary files /dev/null and b/src/Windebug/HELLFRUI.LIB differ diff --git a/src/Windebug/HELLFR~1 b/src/Windebug/HELLFR~1 new file mode 100644 index 0000000..76b99a6 Binary files /dev/null and b/src/Windebug/HELLFR~1 differ diff --git a/src/Windebug/HELLFR~1.DLL b/src/Windebug/HELLFR~1.DLL new file mode 100644 index 0000000..43ef4bf Binary files /dev/null and b/src/Windebug/HELLFR~1.DLL differ diff --git a/src/Windebug/HELLF~10.HIP b/src/Windebug/HELLF~10.HIP new file mode 100644 index 0000000..b8ec2c6 Binary files /dev/null and b/src/Windebug/HELLF~10.HIP differ diff --git a/src/Windebug/HLFPATCH.EXE b/src/Windebug/HLFPATCH.EXE new file mode 100644 index 0000000..cc51dd3 Binary files /dev/null and b/src/Windebug/HLFPATCH.EXE differ diff --git a/src/Windebug/HSV/SINGLE_0.HSV b/src/Windebug/HSV/SINGLE_0.HSV new file mode 100644 index 0000000..a0f34f9 Binary files /dev/null and b/src/Windebug/HSV/SINGLE_0.HSV differ diff --git a/src/Windebug/HSV/SINGLE_2.HSV b/src/Windebug/HSV/SINGLE_2.HSV new file mode 100644 index 0000000..e8a30e5 Binary files /dev/null and b/src/Windebug/HSV/SINGLE_2.HSV differ diff --git a/src/Windebug/HSV/SINGLE_3.HSV b/src/Windebug/HSV/SINGLE_3.HSV new file mode 100644 index 0000000..c55f70b Binary files /dev/null and b/src/Windebug/HSV/SINGLE_3.HSV differ diff --git a/src/Windebug/HSV/SINGLE_4.HSV b/src/Windebug/HSV/SINGLE_4.HSV new file mode 100644 index 0000000..91addd8 Binary files /dev/null and b/src/Windebug/HSV/SINGLE_4.HSV differ diff --git a/src/Windebug/HSV/SINGLE_5.HSV b/src/Windebug/HSV/SINGLE_5.HSV new file mode 100644 index 0000000..07dc390 Binary files /dev/null and b/src/Windebug/HSV/SINGLE_5.HSV differ diff --git a/src/Windebug/HSV/SINGLE_6.HSV b/src/Windebug/HSV/SINGLE_6.HSV new file mode 100644 index 0000000..02eaffe Binary files /dev/null and b/src/Windebug/HSV/SINGLE_6.HSV differ diff --git a/src/Windebug/HSV/SINGLE_7.HSV b/src/Windebug/HSV/SINGLE_7.HSV new file mode 100644 index 0000000..e721d63 Binary files /dev/null and b/src/Windebug/HSV/SINGLE_7.HSV differ diff --git a/src/Windebug/HSV/SINGLE_8.HSV b/src/Windebug/HSV/SINGLE_8.HSV new file mode 100644 index 0000000..c49ae6d Binary files /dev/null and b/src/Windebug/HSV/SINGLE_8.HSV differ diff --git a/src/Windebug/HSV/SINGLE_9.HSV b/src/Windebug/HSV/SINGLE_9.HSV new file mode 100644 index 0000000..ce87824 Binary files /dev/null and b/src/Windebug/HSV/SINGLE_9.HSV differ diff --git a/src/Windebug/ITEMS/BOMBS1.CEL b/src/Windebug/ITEMS/BOMBS1.CEL new file mode 100644 index 0000000..22f90f1 Binary files /dev/null and b/src/Windebug/ITEMS/BOMBS1.CEL differ diff --git a/src/Windebug/ITEMS/COWS1.CEL b/src/Windebug/ITEMS/COWS1.CEL new file mode 100644 index 0000000..d3b791e Binary files /dev/null and b/src/Windebug/ITEMS/COWS1.CEL differ diff --git a/src/Windebug/ITEMS/DONKYS1.CEL b/src/Windebug/ITEMS/DONKYS1.CEL new file mode 100644 index 0000000..6725c2b Binary files /dev/null and b/src/Windebug/ITEMS/DONKYS1.CEL differ diff --git a/src/Windebug/ITEMS/HALFPS1.CEL b/src/Windebug/ITEMS/HALFPS1.CEL new file mode 100644 index 0000000..c2c103a Binary files /dev/null and b/src/Windebug/ITEMS/HALFPS1.CEL differ diff --git a/src/Windebug/ITEMS/MAP/MAPZTOWN.CEL b/src/Windebug/ITEMS/MAP/MAPZTOWN.CEL new file mode 100644 index 0000000..02f8c50 Binary files /dev/null and b/src/Windebug/ITEMS/MAP/MAPZTOWN.CEL differ diff --git a/src/Windebug/ITEMS/MOOSES1.CEL b/src/Windebug/ITEMS/MOOSES1.CEL new file mode 100644 index 0000000..3fd4e8e Binary files /dev/null and b/src/Windebug/ITEMS/MOOSES1.CEL differ diff --git a/src/Windebug/ITEMS/RUNES1.CEL b/src/Windebug/ITEMS/RUNES1.CEL new file mode 100644 index 0000000..4680ea8 Binary files /dev/null and b/src/Windebug/ITEMS/RUNES1.CEL differ diff --git a/src/Windebug/ITEMS/TEDDYS1.CEL b/src/Windebug/ITEMS/TEDDYS1.CEL new file mode 100644 index 0000000..ed2a846 Binary files /dev/null and b/src/Windebug/ITEMS/TEDDYS1.CEL differ diff --git a/src/Windebug/ITEMS/WHOLEPS1.CEL b/src/Windebug/ITEMS/WHOLEPS1.CEL new file mode 100644 index 0000000..ecd98cb Binary files /dev/null and b/src/Windebug/ITEMS/WHOLEPS1.CEL differ diff --git a/src/Windebug/LAGGAME/SINGLE_2.HSV b/src/Windebug/LAGGAME/SINGLE_2.HSV new file mode 100644 index 0000000..f9992ef Binary files /dev/null and b/src/Windebug/LAGGAME/SINGLE_2.HSV differ diff --git a/src/Windebug/MISSILES/EX_BLU2.CL2 b/src/Windebug/MISSILES/EX_BLU2.CL2 new file mode 100644 index 0000000..a1939ab Binary files /dev/null and b/src/Windebug/MISSILES/EX_BLU2.CL2 differ diff --git a/src/Windebug/MISSILES/EX_BLU3.CL2 b/src/Windebug/MISSILES/EX_BLU3.CL2 new file mode 100644 index 0000000..30b478a Binary files /dev/null and b/src/Windebug/MISSILES/EX_BLU3.CL2 differ diff --git a/src/Windebug/MISSILES/EX_ORA1.CL2 b/src/Windebug/MISSILES/EX_ORA1.CL2 new file mode 100644 index 0000000..30c9071 Binary files /dev/null and b/src/Windebug/MISSILES/EX_ORA1.CL2 differ diff --git a/src/Windebug/MISSILES/EX_RED3.CL2 b/src/Windebug/MISSILES/EX_RED3.CL2 new file mode 100644 index 0000000..74cc39e Binary files /dev/null and b/src/Windebug/MISSILES/EX_RED3.CL2 differ diff --git a/src/Windebug/MISSILES/EX_YEL2.CL2 b/src/Windebug/MISSILES/EX_YEL2.CL2 new file mode 100644 index 0000000..0151513 Binary files /dev/null and b/src/Windebug/MISSILES/EX_YEL2.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N1.CL2 b/src/Windebug/MISSILES/FBA_N1.CL2 new file mode 100644 index 0000000..72037a9 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N1.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N10.CL2 b/src/Windebug/MISSILES/FBA_N10.CL2 new file mode 100644 index 0000000..a8a270c Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N10.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N11.CL2 b/src/Windebug/MISSILES/FBA_N11.CL2 new file mode 100644 index 0000000..06d0735 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N11.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N12.CL2 b/src/Windebug/MISSILES/FBA_N12.CL2 new file mode 100644 index 0000000..d22b1b7 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N12.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N13.CL2 b/src/Windebug/MISSILES/FBA_N13.CL2 new file mode 100644 index 0000000..c71f1e7 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N13.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N14.CL2 b/src/Windebug/MISSILES/FBA_N14.CL2 new file mode 100644 index 0000000..2f755fa Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N14.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N15.CL2 b/src/Windebug/MISSILES/FBA_N15.CL2 new file mode 100644 index 0000000..09ca171 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N15.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N16.CL2 b/src/Windebug/MISSILES/FBA_N16.CL2 new file mode 100644 index 0000000..fe9d40c Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N16.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N2.CL2 b/src/Windebug/MISSILES/FBA_N2.CL2 new file mode 100644 index 0000000..0f20c95 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N2.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N3.CL2 b/src/Windebug/MISSILES/FBA_N3.CL2 new file mode 100644 index 0000000..75d77a1 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N3.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N4.CL2 b/src/Windebug/MISSILES/FBA_N4.CL2 new file mode 100644 index 0000000..e83d5b8 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N4.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N5.CL2 b/src/Windebug/MISSILES/FBA_N5.CL2 new file mode 100644 index 0000000..ddf970f Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N5.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N6.CL2 b/src/Windebug/MISSILES/FBA_N6.CL2 new file mode 100644 index 0000000..eeb778f Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N6.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N7.CL2 b/src/Windebug/MISSILES/FBA_N7.CL2 new file mode 100644 index 0000000..6ce89d9 Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N7.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N8.CL2 b/src/Windebug/MISSILES/FBA_N8.CL2 new file mode 100644 index 0000000..7286dce Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N8.CL2 differ diff --git a/src/Windebug/MISSILES/FBA_N9.CL2 b/src/Windebug/MISSILES/FBA_N9.CL2 new file mode 100644 index 0000000..63ff49e Binary files /dev/null and b/src/Windebug/MISSILES/FBA_N9.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N1.CL2 b/src/Windebug/MISSILES/FBB_N1.CL2 new file mode 100644 index 0000000..96f4cc5 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N1.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N10.CL2 b/src/Windebug/MISSILES/FBB_N10.CL2 new file mode 100644 index 0000000..5c28dc5 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N10.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N11.CL2 b/src/Windebug/MISSILES/FBB_N11.CL2 new file mode 100644 index 0000000..3018b23 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N11.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N12.CL2 b/src/Windebug/MISSILES/FBB_N12.CL2 new file mode 100644 index 0000000..c700705 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N12.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N13.CL2 b/src/Windebug/MISSILES/FBB_N13.CL2 new file mode 100644 index 0000000..f755a7b Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N13.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N14.CL2 b/src/Windebug/MISSILES/FBB_N14.CL2 new file mode 100644 index 0000000..69b4655 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N14.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N15.CL2 b/src/Windebug/MISSILES/FBB_N15.CL2 new file mode 100644 index 0000000..0560541 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N15.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N16.CL2 b/src/Windebug/MISSILES/FBB_N16.CL2 new file mode 100644 index 0000000..12ba0d9 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N16.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N2.CL2 b/src/Windebug/MISSILES/FBB_N2.CL2 new file mode 100644 index 0000000..869ff95 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N2.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N3.CL2 b/src/Windebug/MISSILES/FBB_N3.CL2 new file mode 100644 index 0000000..6e5d8f6 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N3.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N4.CL2 b/src/Windebug/MISSILES/FBB_N4.CL2 new file mode 100644 index 0000000..c6a789d Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N4.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N5.CL2 b/src/Windebug/MISSILES/FBB_N5.CL2 new file mode 100644 index 0000000..f7247ec Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N5.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N6.CL2 b/src/Windebug/MISSILES/FBB_N6.CL2 new file mode 100644 index 0000000..0367394 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N6.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N7.CL2 b/src/Windebug/MISSILES/FBB_N7.CL2 new file mode 100644 index 0000000..15b549c Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N7.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N8.CL2 b/src/Windebug/MISSILES/FBB_N8.CL2 new file mode 100644 index 0000000..bf2193b Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N8.CL2 differ diff --git a/src/Windebug/MISSILES/FBB_N9.CL2 b/src/Windebug/MISSILES/FBB_N9.CL2 new file mode 100644 index 0000000..c3bf151 Binary files /dev/null and b/src/Windebug/MISSILES/FBB_N9.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N1.CL2 b/src/Windebug/MISSILES/FBC_N1.CL2 new file mode 100644 index 0000000..834a339 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N1.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N10.CL2 b/src/Windebug/MISSILES/FBC_N10.CL2 new file mode 100644 index 0000000..95c6902 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N10.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N11.CL2 b/src/Windebug/MISSILES/FBC_N11.CL2 new file mode 100644 index 0000000..a9e20a7 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N11.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N12.CL2 b/src/Windebug/MISSILES/FBC_N12.CL2 new file mode 100644 index 0000000..ca44513 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N12.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N13.CL2 b/src/Windebug/MISSILES/FBC_N13.CL2 new file mode 100644 index 0000000..3be2f2a Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N13.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N14.CL2 b/src/Windebug/MISSILES/FBC_N14.CL2 new file mode 100644 index 0000000..0ef7bcb Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N14.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N15.CL2 b/src/Windebug/MISSILES/FBC_N15.CL2 new file mode 100644 index 0000000..050b13e Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N15.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N16.CL2 b/src/Windebug/MISSILES/FBC_N16.CL2 new file mode 100644 index 0000000..746a169 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N16.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N2.CL2 b/src/Windebug/MISSILES/FBC_N2.CL2 new file mode 100644 index 0000000..ccd17b4 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N2.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N3.CL2 b/src/Windebug/MISSILES/FBC_N3.CL2 new file mode 100644 index 0000000..5748d19 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N3.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N4.CL2 b/src/Windebug/MISSILES/FBC_N4.CL2 new file mode 100644 index 0000000..e49ad69 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N4.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N5.CL2 b/src/Windebug/MISSILES/FBC_N5.CL2 new file mode 100644 index 0000000..f4f483a Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N5.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N6.CL2 b/src/Windebug/MISSILES/FBC_N6.CL2 new file mode 100644 index 0000000..1c75c2c Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N6.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N7.CL2 b/src/Windebug/MISSILES/FBC_N7.CL2 new file mode 100644 index 0000000..f8ba3d8 Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N7.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N8.CL2 b/src/Windebug/MISSILES/FBC_N8.CL2 new file mode 100644 index 0000000..57b57bd Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N8.CL2 differ diff --git a/src/Windebug/MISSILES/FBC_N9.CL2 b/src/Windebug/MISSILES/FBC_N9.CL2 new file mode 100644 index 0000000..162ecff Binary files /dev/null and b/src/Windebug/MISSILES/FBC_N9.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N1.CL2 b/src/Windebug/MISSILES/FBD_N1.CL2 new file mode 100644 index 0000000..39a0ae3 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N1.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N10.CL2 b/src/Windebug/MISSILES/FBD_N10.CL2 new file mode 100644 index 0000000..a468a4d Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N10.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N11.CL2 b/src/Windebug/MISSILES/FBD_N11.CL2 new file mode 100644 index 0000000..e9cd485 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N11.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N12.CL2 b/src/Windebug/MISSILES/FBD_N12.CL2 new file mode 100644 index 0000000..04679d8 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N12.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N13.CL2 b/src/Windebug/MISSILES/FBD_N13.CL2 new file mode 100644 index 0000000..acb0bda Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N13.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N14.CL2 b/src/Windebug/MISSILES/FBD_N14.CL2 new file mode 100644 index 0000000..01b9341 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N14.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N15.CL2 b/src/Windebug/MISSILES/FBD_N15.CL2 new file mode 100644 index 0000000..04d0d2c Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N15.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N16.CL2 b/src/Windebug/MISSILES/FBD_N16.CL2 new file mode 100644 index 0000000..0a2651b Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N16.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N2.CL2 b/src/Windebug/MISSILES/FBD_N2.CL2 new file mode 100644 index 0000000..a49df87 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N2.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N3.CL2 b/src/Windebug/MISSILES/FBD_N3.CL2 new file mode 100644 index 0000000..4ce05d8 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N3.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N4.CL2 b/src/Windebug/MISSILES/FBD_N4.CL2 new file mode 100644 index 0000000..ec366b8 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N4.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N5.CL2 b/src/Windebug/MISSILES/FBD_N5.CL2 new file mode 100644 index 0000000..13bd131 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N5.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N6.CL2 b/src/Windebug/MISSILES/FBD_N6.CL2 new file mode 100644 index 0000000..276b088 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N6.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N7.CL2 b/src/Windebug/MISSILES/FBD_N7.CL2 new file mode 100644 index 0000000..753011a Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N7.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N8.CL2 b/src/Windebug/MISSILES/FBD_N8.CL2 new file mode 100644 index 0000000..994fca1 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N8.CL2 differ diff --git a/src/Windebug/MISSILES/FBD_N9.CL2 b/src/Windebug/MISSILES/FBD_N9.CL2 new file mode 100644 index 0000000..9c690c3 Binary files /dev/null and b/src/Windebug/MISSILES/FBD_N9.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA1.CL2 b/src/Windebug/MISSILES/MS_BLA1.CL2 new file mode 100644 index 0000000..87661e9 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA1.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA10.CL2 b/src/Windebug/MISSILES/MS_BLA10.CL2 new file mode 100644 index 0000000..7144c93 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA10.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA11.CL2 b/src/Windebug/MISSILES/MS_BLA11.CL2 new file mode 100644 index 0000000..3ec02cd Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA11.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA12.CL2 b/src/Windebug/MISSILES/MS_BLA12.CL2 new file mode 100644 index 0000000..bcdb504 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA12.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA13.CL2 b/src/Windebug/MISSILES/MS_BLA13.CL2 new file mode 100644 index 0000000..74eb220 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA13.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA14.CL2 b/src/Windebug/MISSILES/MS_BLA14.CL2 new file mode 100644 index 0000000..b3ddb9c Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA14.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA15.CL2 b/src/Windebug/MISSILES/MS_BLA15.CL2 new file mode 100644 index 0000000..d50c60d Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA15.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA16.CL2 b/src/Windebug/MISSILES/MS_BLA16.CL2 new file mode 100644 index 0000000..b80bd77 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA16.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA2.CL2 b/src/Windebug/MISSILES/MS_BLA2.CL2 new file mode 100644 index 0000000..10d1b2a Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA2.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA3.CL2 b/src/Windebug/MISSILES/MS_BLA3.CL2 new file mode 100644 index 0000000..2fc7adc Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA3.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA4.CL2 b/src/Windebug/MISSILES/MS_BLA4.CL2 new file mode 100644 index 0000000..aeeb9c6 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA4.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA5.CL2 b/src/Windebug/MISSILES/MS_BLA5.CL2 new file mode 100644 index 0000000..c22b10e Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA5.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA6.CL2 b/src/Windebug/MISSILES/MS_BLA6.CL2 new file mode 100644 index 0000000..5ce8943 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA6.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA7.CL2 b/src/Windebug/MISSILES/MS_BLA7.CL2 new file mode 100644 index 0000000..947a646 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA7.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA8.CL2 b/src/Windebug/MISSILES/MS_BLA8.CL2 new file mode 100644 index 0000000..7de7a73 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA8.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLA9.CL2 b/src/Windebug/MISSILES/MS_BLA9.CL2 new file mode 100644 index 0000000..5005f6a Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLA9.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB1.CL2 b/src/Windebug/MISSILES/MS_BLB1.CL2 new file mode 100644 index 0000000..35d3baa Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB1.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB10.CL2 b/src/Windebug/MISSILES/MS_BLB10.CL2 new file mode 100644 index 0000000..9cdb07d Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB10.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB11.CL2 b/src/Windebug/MISSILES/MS_BLB11.CL2 new file mode 100644 index 0000000..91c09f4 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB11.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB12.CL2 b/src/Windebug/MISSILES/MS_BLB12.CL2 new file mode 100644 index 0000000..21effc5 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB12.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB13.CL2 b/src/Windebug/MISSILES/MS_BLB13.CL2 new file mode 100644 index 0000000..5b598e7 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB13.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB14.CL2 b/src/Windebug/MISSILES/MS_BLB14.CL2 new file mode 100644 index 0000000..87a16ed Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB14.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB15.CL2 b/src/Windebug/MISSILES/MS_BLB15.CL2 new file mode 100644 index 0000000..fd04532 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB15.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB16.CL2 b/src/Windebug/MISSILES/MS_BLB16.CL2 new file mode 100644 index 0000000..fdf2890 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB16.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB2.CL2 b/src/Windebug/MISSILES/MS_BLB2.CL2 new file mode 100644 index 0000000..ff655b9 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB2.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB3.CL2 b/src/Windebug/MISSILES/MS_BLB3.CL2 new file mode 100644 index 0000000..3e0b1b0 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB3.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB4.CL2 b/src/Windebug/MISSILES/MS_BLB4.CL2 new file mode 100644 index 0000000..3720326 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB4.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB5.CL2 b/src/Windebug/MISSILES/MS_BLB5.CL2 new file mode 100644 index 0000000..981d9d3 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB5.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB6.CL2 b/src/Windebug/MISSILES/MS_BLB6.CL2 new file mode 100644 index 0000000..9f6f709 Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB6.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB7.CL2 b/src/Windebug/MISSILES/MS_BLB7.CL2 new file mode 100644 index 0000000..441d59f Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB7.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB8.CL2 b/src/Windebug/MISSILES/MS_BLB8.CL2 new file mode 100644 index 0000000..a30b40e Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB8.CL2 differ diff --git a/src/Windebug/MISSILES/MS_BLB9.CL2 b/src/Windebug/MISSILES/MS_BLB9.CL2 new file mode 100644 index 0000000..affc83c Binary files /dev/null and b/src/Windebug/MISSILES/MS_BLB9.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA1.CL2 b/src/Windebug/MISSILES/MS_ORA1.CL2 new file mode 100644 index 0000000..c20d7fa Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA1.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA10.CL2 b/src/Windebug/MISSILES/MS_ORA10.CL2 new file mode 100644 index 0000000..bdd14ba Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA10.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA11.CL2 b/src/Windebug/MISSILES/MS_ORA11.CL2 new file mode 100644 index 0000000..5c6366c Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA11.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA12.CL2 b/src/Windebug/MISSILES/MS_ORA12.CL2 new file mode 100644 index 0000000..1b9b326 Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA12.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA13.CL2 b/src/Windebug/MISSILES/MS_ORA13.CL2 new file mode 100644 index 0000000..52e3eea Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA13.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA14.CL2 b/src/Windebug/MISSILES/MS_ORA14.CL2 new file mode 100644 index 0000000..3bd25ff Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA14.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA15.CL2 b/src/Windebug/MISSILES/MS_ORA15.CL2 new file mode 100644 index 0000000..14a2db3 Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA15.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA16.CL2 b/src/Windebug/MISSILES/MS_ORA16.CL2 new file mode 100644 index 0000000..ad13fca Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA16.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA2.CL2 b/src/Windebug/MISSILES/MS_ORA2.CL2 new file mode 100644 index 0000000..fe8ae3c Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA2.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA3.CL2 b/src/Windebug/MISSILES/MS_ORA3.CL2 new file mode 100644 index 0000000..bc2c2da Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA3.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA4.CL2 b/src/Windebug/MISSILES/MS_ORA4.CL2 new file mode 100644 index 0000000..24b65fa Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA4.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA5.CL2 b/src/Windebug/MISSILES/MS_ORA5.CL2 new file mode 100644 index 0000000..46b1a3c Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA5.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA6.CL2 b/src/Windebug/MISSILES/MS_ORA6.CL2 new file mode 100644 index 0000000..465a0fe Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA6.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA7.CL2 b/src/Windebug/MISSILES/MS_ORA7.CL2 new file mode 100644 index 0000000..4862db0 Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA7.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA8.CL2 b/src/Windebug/MISSILES/MS_ORA8.CL2 new file mode 100644 index 0000000..209a016 Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA8.CL2 differ diff --git a/src/Windebug/MISSILES/MS_ORA9.CL2 b/src/Windebug/MISSILES/MS_ORA9.CL2 new file mode 100644 index 0000000..2d8caec Binary files /dev/null and b/src/Windebug/MISSILES/MS_ORA9.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB1.CL2 b/src/Windebug/MISSILES/MS_REB1.CL2 new file mode 100644 index 0000000..27ca10f Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB1.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB10.CL2 b/src/Windebug/MISSILES/MS_REB10.CL2 new file mode 100644 index 0000000..d03aad2 Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB10.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB11.CL2 b/src/Windebug/MISSILES/MS_REB11.CL2 new file mode 100644 index 0000000..46827e6 Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB11.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB12.CL2 b/src/Windebug/MISSILES/MS_REB12.CL2 new file mode 100644 index 0000000..535a6af Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB12.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB13.CL2 b/src/Windebug/MISSILES/MS_REB13.CL2 new file mode 100644 index 0000000..1ce637b Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB13.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB14.CL2 b/src/Windebug/MISSILES/MS_REB14.CL2 new file mode 100644 index 0000000..049974e Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB14.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB15.CL2 b/src/Windebug/MISSILES/MS_REB15.CL2 new file mode 100644 index 0000000..6206e7c Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB15.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB16.CL2 b/src/Windebug/MISSILES/MS_REB16.CL2 new file mode 100644 index 0000000..64eadbd Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB16.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB2.CL2 b/src/Windebug/MISSILES/MS_REB2.CL2 new file mode 100644 index 0000000..4c1e49e Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB2.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB3.CL2 b/src/Windebug/MISSILES/MS_REB3.CL2 new file mode 100644 index 0000000..4784a6e Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB3.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB4.CL2 b/src/Windebug/MISSILES/MS_REB4.CL2 new file mode 100644 index 0000000..1ba2f43 Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB4.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB5.CL2 b/src/Windebug/MISSILES/MS_REB5.CL2 new file mode 100644 index 0000000..519fc9c Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB5.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB6.CL2 b/src/Windebug/MISSILES/MS_REB6.CL2 new file mode 100644 index 0000000..6ba9de0 Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB6.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB7.CL2 b/src/Windebug/MISSILES/MS_REB7.CL2 new file mode 100644 index 0000000..689c49d Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB7.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB8.CL2 b/src/Windebug/MISSILES/MS_REB8.CL2 new file mode 100644 index 0000000..aabb4eb Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB8.CL2 differ diff --git a/src/Windebug/MISSILES/MS_REB9.CL2 b/src/Windebug/MISSILES/MS_REB9.CL2 new file mode 100644 index 0000000..44849b0 Binary files /dev/null and b/src/Windebug/MISSILES/MS_REB9.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB1.CL2 b/src/Windebug/MISSILES/MS_YEB1.CL2 new file mode 100644 index 0000000..0718e80 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB1.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB10.CL2 b/src/Windebug/MISSILES/MS_YEB10.CL2 new file mode 100644 index 0000000..cd70530 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB10.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB11.CL2 b/src/Windebug/MISSILES/MS_YEB11.CL2 new file mode 100644 index 0000000..5ff95d6 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB11.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB12.CL2 b/src/Windebug/MISSILES/MS_YEB12.CL2 new file mode 100644 index 0000000..5fdda44 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB12.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB13.CL2 b/src/Windebug/MISSILES/MS_YEB13.CL2 new file mode 100644 index 0000000..f3f7f9f Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB13.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB14.CL2 b/src/Windebug/MISSILES/MS_YEB14.CL2 new file mode 100644 index 0000000..df69c4b Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB14.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB15.CL2 b/src/Windebug/MISSILES/MS_YEB15.CL2 new file mode 100644 index 0000000..ef4f9c1 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB15.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB16.CL2 b/src/Windebug/MISSILES/MS_YEB16.CL2 new file mode 100644 index 0000000..477e9db Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB16.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB2.CL2 b/src/Windebug/MISSILES/MS_YEB2.CL2 new file mode 100644 index 0000000..8b77c9c Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB2.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB3.CL2 b/src/Windebug/MISSILES/MS_YEB3.CL2 new file mode 100644 index 0000000..ce83ba9 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB3.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB4.CL2 b/src/Windebug/MISSILES/MS_YEB4.CL2 new file mode 100644 index 0000000..2cc8f3d Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB4.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB5.CL2 b/src/Windebug/MISSILES/MS_YEB5.CL2 new file mode 100644 index 0000000..7121254 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB5.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB6.CL2 b/src/Windebug/MISSILES/MS_YEB6.CL2 new file mode 100644 index 0000000..3b313ad Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB6.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB7.CL2 b/src/Windebug/MISSILES/MS_YEB7.CL2 new file mode 100644 index 0000000..859c992 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB7.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB8.CL2 b/src/Windebug/MISSILES/MS_YEB8.CL2 new file mode 100644 index 0000000..386c985 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB8.CL2 differ diff --git a/src/Windebug/MISSILES/MS_YEB9.CL2 b/src/Windebug/MISSILES/MS_YEB9.CL2 new file mode 100644 index 0000000..ad93540 Binary files /dev/null and b/src/Windebug/MISSILES/MS_YEB9.CL2 differ diff --git a/src/Windebug/MISSILES/REFLECT.CL2 b/src/Windebug/MISSILES/REFLECT.CL2 new file mode 100644 index 0000000..fa01985 Binary files /dev/null and b/src/Windebug/MISSILES/REFLECT.CL2 differ diff --git a/src/Windebug/MISSILES/REFLEC~1.CL2 b/src/Windebug/MISSILES/REFLEC~1.CL2 new file mode 100644 index 0000000..f23938e Binary files /dev/null and b/src/Windebug/MISSILES/REFLEC~1.CL2 differ diff --git a/src/Windebug/MISSILES/RGLOWS1.CL2 b/src/Windebug/MISSILES/RGLOWS1.CL2 new file mode 100644 index 0000000..d0fbfda Binary files /dev/null and b/src/Windebug/MISSILES/RGLOWS1.CL2 differ diff --git a/src/Windebug/MISSILES/SPAWNS1.CL2 b/src/Windebug/MISSILES/SPAWNS1.CL2 new file mode 100644 index 0000000..6abfce9 Binary files /dev/null and b/src/Windebug/MISSILES/SPAWNS1.CL2 differ diff --git a/src/Windebug/MISSILES/SPAWNS2.CL2 b/src/Windebug/MISSILES/SPAWNS2.CL2 new file mode 100644 index 0000000..0d779f7 Binary files /dev/null and b/src/Windebug/MISSILES/SPAWNS2.CL2 differ diff --git a/src/Windebug/MISSILES/SPAWNS3.CL2 b/src/Windebug/MISSILES/SPAWNS3.CL2 new file mode 100644 index 0000000..8f42577 Binary files /dev/null and b/src/Windebug/MISSILES/SPAWNS3.CL2 differ diff --git a/src/Windebug/MISSILES/SPAWNS4.CL2 b/src/Windebug/MISSILES/SPAWNS4.CL2 new file mode 100644 index 0000000..f301310 Binary files /dev/null and b/src/Windebug/MISSILES/SPAWNS4.CL2 differ diff --git a/src/Windebug/MISSILES/SPAWNS5.CL2 b/src/Windebug/MISSILES/SPAWNS5.CL2 new file mode 100644 index 0000000..4881044 Binary files /dev/null and b/src/Windebug/MISSILES/SPAWNS5.CL2 differ diff --git a/src/Windebug/MISSILES/SPAWNS6.CL2 b/src/Windebug/MISSILES/SPAWNS6.CL2 new file mode 100644 index 0000000..628dbd8 Binary files /dev/null and b/src/Windebug/MISSILES/SPAWNS6.CL2 differ diff --git a/src/Windebug/MISSILES/SPAWNS7.CL2 b/src/Windebug/MISSILES/SPAWNS7.CL2 new file mode 100644 index 0000000..8213c45 Binary files /dev/null and b/src/Windebug/MISSILES/SPAWNS7.CL2 differ diff --git a/src/Windebug/MISSILES/SPAWNS8.CL2 b/src/Windebug/MISSILES/SPAWNS8.CL2 new file mode 100644 index 0000000..17e0fc0 Binary files /dev/null and b/src/Windebug/MISSILES/SPAWNS8.CL2 differ diff --git a/src/Windebug/MISSILES/STORM.RES b/src/Windebug/MISSILES/STORM.RES new file mode 100644 index 0000000..2433693 Binary files /dev/null and b/src/Windebug/MISSILES/STORM.RES differ diff --git a/src/Windebug/MONSTERS/ANTWORM/DEBUG.TXT b/src/Windebug/MONSTERS/ANTWORM/DEBUG.TXT new file mode 100644 index 0000000..a2b886b --- /dev/null +++ b/src/Windebug/MONSTERS/ANTWORM/DEBUG.TXT @@ -0,0 +1,8 @@ +Worm width 192 height 119 +Worm width 192 height 119 +Neutral frame count 14 +Walk frame count 12 +Attack frame count 12 +Get hit frame count 6 +Die frame count 20 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/ANTWORM/WORMA.CL2 b/src/Windebug/MONSTERS/ANTWORM/WORMA.CL2 new file mode 100644 index 0000000..89e415a Binary files /dev/null and b/src/Windebug/MONSTERS/ANTWORM/WORMA.CL2 differ diff --git a/src/Windebug/MONSTERS/ANTWORM/WORMD.CL2 b/src/Windebug/MONSTERS/ANTWORM/WORMD.CL2 new file mode 100644 index 0000000..f94b75d Binary files /dev/null and b/src/Windebug/MONSTERS/ANTWORM/WORMD.CL2 differ diff --git a/src/Windebug/MONSTERS/ANTWORM/WORMH.CL2 b/src/Windebug/MONSTERS/ANTWORM/WORMH.CL2 new file mode 100644 index 0000000..88818b9 Binary files /dev/null and b/src/Windebug/MONSTERS/ANTWORM/WORMH.CL2 differ diff --git a/src/Windebug/MONSTERS/ANTWORM/WORMN.CL2 b/src/Windebug/MONSTERS/ANTWORM/WORMN.CL2 new file mode 100644 index 0000000..f018df9 Binary files /dev/null and b/src/Windebug/MONSTERS/ANTWORM/WORMN.CL2 differ diff --git a/src/Windebug/MONSTERS/ANTWORM/WORMW.CL2 b/src/Windebug/MONSTERS/ANTWORM/WORMW.CL2 new file mode 100644 index 0000000..d8dcc9c Binary files /dev/null and b/src/Windebug/MONSTERS/ANTWORM/WORMW.CL2 differ diff --git a/src/Windebug/MONSTERS/BSPIDR/BSPIDRD.CL2 b/src/Windebug/MONSTERS/BSPIDR/BSPIDRD.CL2 new file mode 100644 index 0000000..6bb7839 Binary files /dev/null and b/src/Windebug/MONSTERS/BSPIDR/BSPIDRD.CL2 differ diff --git a/src/Windebug/MONSTERS/BSPIDR/BSPIDRH.CL2 b/src/Windebug/MONSTERS/BSPIDR/BSPIDRH.CL2 new file mode 100644 index 0000000..75ec4dd Binary files /dev/null and b/src/Windebug/MONSTERS/BSPIDR/BSPIDRH.CL2 differ diff --git a/src/Windebug/MONSTERS/BSPIDR/BSPIDRN.CL2 b/src/Windebug/MONSTERS/BSPIDR/BSPIDRN.CL2 new file mode 100644 index 0000000..653d1b0 Binary files /dev/null and b/src/Windebug/MONSTERS/BSPIDR/BSPIDRN.CL2 differ diff --git a/src/Windebug/MONSTERS/BSPIDR/BSPIDRS.CL2 b/src/Windebug/MONSTERS/BSPIDR/BSPIDRS.CL2 new file mode 100644 index 0000000..910b098 Binary files /dev/null and b/src/Windebug/MONSTERS/BSPIDR/BSPIDRS.CL2 differ diff --git a/src/Windebug/MONSTERS/BSPIDR/BSPIDRW.CL2 b/src/Windebug/MONSTERS/BSPIDR/BSPIDRW.CL2 new file mode 100644 index 0000000..b767462 Binary files /dev/null and b/src/Windebug/MONSTERS/BSPIDR/BSPIDRW.CL2 differ diff --git a/src/Windebug/MONSTERS/BSPIDR/DEBUG.TXT b/src/Windebug/MONSTERS/BSPIDR/DEBUG.TXT new file mode 100644 index 0000000..94d14be --- /dev/null +++ b/src/Windebug/MONSTERS/BSPIDR/DEBUG.TXT @@ -0,0 +1,8 @@ +BSpidr width 148 height 111 +BSpidr width 148 height 111 +Neutral frame count 12 +Walk frame count 10 +Attack frame count 15 +Get hit frame count 6 +Die frame count 20 +Special frame count 10 diff --git a/src/Windebug/MONSTERS/BUBBA/BUBBAA.CL2 b/src/Windebug/MONSTERS/BUBBA/BUBBAA.CL2 new file mode 100644 index 0000000..037ab9c Binary files /dev/null and b/src/Windebug/MONSTERS/BUBBA/BUBBAA.CL2 differ diff --git a/src/Windebug/MONSTERS/BUBBA/BUBBAD.CL2 b/src/Windebug/MONSTERS/BUBBA/BUBBAD.CL2 new file mode 100644 index 0000000..4f3b6f1 Binary files /dev/null and b/src/Windebug/MONSTERS/BUBBA/BUBBAD.CL2 differ diff --git a/src/Windebug/MONSTERS/BUBBA/BUBBAH.CL2 b/src/Windebug/MONSTERS/BUBBA/BUBBAH.CL2 new file mode 100644 index 0000000..405e1fa Binary files /dev/null and b/src/Windebug/MONSTERS/BUBBA/BUBBAH.CL2 differ diff --git a/src/Windebug/MONSTERS/BUBBA/BUBBAN.CL2 b/src/Windebug/MONSTERS/BUBBA/BUBBAN.CL2 new file mode 100644 index 0000000..9c36191 Binary files /dev/null and b/src/Windebug/MONSTERS/BUBBA/BUBBAN.CL2 differ diff --git a/src/Windebug/MONSTERS/BUBBA/BUBBAW.CL2 b/src/Windebug/MONSTERS/BUBBA/BUBBAW.CL2 new file mode 100644 index 0000000..4ef6985 Binary files /dev/null and b/src/Windebug/MONSTERS/BUBBA/BUBBAW.CL2 differ diff --git a/src/Windebug/MONSTERS/BUBBA/DEBUG.TXT b/src/Windebug/MONSTERS/BUBBA/DEBUG.TXT new file mode 100644 index 0000000..752b74c --- /dev/null +++ b/src/Windebug/MONSTERS/BUBBA/DEBUG.TXT @@ -0,0 +1,9 @@ +bubba width 154 height 128 +bubba width 154 height 128 +bubba width 154 height 128 +Neutral frame count 8 +Walk frame count 18 +Attack frame count 12 +Get hit frame count 8 +Die frame count 21 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/BYCLPS/BYCLPOS.TXT b/src/Windebug/MONSTERS/BYCLPS/BYCLPOS.TXT new file mode 100644 index 0000000..ce33bfd --- /dev/null +++ b/src/Windebug/MONSTERS/BYCLPS/BYCLPOS.TXT @@ -0,0 +1,8 @@ +byclops width 180 height 123 +byclops width 180 height 123 +Neutral frame count 10 +Walk frame count 11 +Attack frame count 16 +Get hit frame count 6 +Die frame count 16 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/BYCLPS/BYCLPSA.CL2 b/src/Windebug/MONSTERS/BYCLPS/BYCLPSA.CL2 new file mode 100644 index 0000000..d125f86 Binary files /dev/null and b/src/Windebug/MONSTERS/BYCLPS/BYCLPSA.CL2 differ diff --git a/src/Windebug/MONSTERS/BYCLPS/BYCLPSD.CL2 b/src/Windebug/MONSTERS/BYCLPS/BYCLPSD.CL2 new file mode 100644 index 0000000..19f2670 Binary files /dev/null and b/src/Windebug/MONSTERS/BYCLPS/BYCLPSD.CL2 differ diff --git a/src/Windebug/MONSTERS/BYCLPS/BYCLPSH.CL2 b/src/Windebug/MONSTERS/BYCLPS/BYCLPSH.CL2 new file mode 100644 index 0000000..ee02b65 Binary files /dev/null and b/src/Windebug/MONSTERS/BYCLPS/BYCLPSH.CL2 differ diff --git a/src/Windebug/MONSTERS/BYCLPS/BYCLPSN.CL2 b/src/Windebug/MONSTERS/BYCLPS/BYCLPSN.CL2 new file mode 100644 index 0000000..2706ba1 Binary files /dev/null and b/src/Windebug/MONSTERS/BYCLPS/BYCLPSN.CL2 differ diff --git a/src/Windebug/MONSTERS/BYCLPS/BYCLPSW.CL2 b/src/Windebug/MONSTERS/BYCLPS/BYCLPSW.CL2 new file mode 100644 index 0000000..1d6f51b Binary files /dev/null and b/src/Windebug/MONSTERS/BYCLPS/BYCLPSW.CL2 differ diff --git a/src/Windebug/MONSTERS/CLASP/CLASPA.CL2 b/src/Windebug/MONSTERS/CLASP/CLASPA.CL2 new file mode 100644 index 0000000..fdbc786 Binary files /dev/null and b/src/Windebug/MONSTERS/CLASP/CLASPA.CL2 differ diff --git a/src/Windebug/MONSTERS/CLASP/CLASPD.CL2 b/src/Windebug/MONSTERS/CLASP/CLASPD.CL2 new file mode 100644 index 0000000..7598f5d Binary files /dev/null and b/src/Windebug/MONSTERS/CLASP/CLASPD.CL2 differ diff --git a/src/Windebug/MONSTERS/CLASP/CLASPH.CL2 b/src/Windebug/MONSTERS/CLASP/CLASPH.CL2 new file mode 100644 index 0000000..a09c14b Binary files /dev/null and b/src/Windebug/MONSTERS/CLASP/CLASPH.CL2 differ diff --git a/src/Windebug/MONSTERS/CLASP/CLASPN.CL2 b/src/Windebug/MONSTERS/CLASP/CLASPN.CL2 new file mode 100644 index 0000000..792c30a Binary files /dev/null and b/src/Windebug/MONSTERS/CLASP/CLASPN.CL2 differ diff --git a/src/Windebug/MONSTERS/CLASP/CLASPW.CL2 b/src/Windebug/MONSTERS/CLASP/CLASPW.CL2 new file mode 100644 index 0000000..da34f62 Binary files /dev/null and b/src/Windebug/MONSTERS/CLASP/CLASPW.CL2 differ diff --git a/src/Windebug/MONSTERS/CLASP/DEBUG.TXT b/src/Windebug/MONSTERS/CLASP/DEBUG.TXT new file mode 100644 index 0000000..4bf6db5 --- /dev/null +++ b/src/Windebug/MONSTERS/CLASP/DEBUG.TXT @@ -0,0 +1,8 @@ +Clasp width 176 height 109 +Clasp width 176 height 109 +Neutral frame count 10 +Walk frame count 12 +Attack frame count 15 +Get hit frame count 6 +Die frame count 16 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/EYE/DEBUG.TXT b/src/Windebug/MONSTERS/EYE/DEBUG.TXT new file mode 100644 index 0000000..1119a86 --- /dev/null +++ b/src/Windebug/MONSTERS/EYE/DEBUG.TXT @@ -0,0 +1,9 @@ +eye0 width 156 height 128 +eye0 width 156 height 128 +eye0 width 156 height 128 +Neutral frame count 12 +Walk frame count 13 +Attack frame count 13 +Get hit frame count 7 +Die frame count 21 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/EYE/EYEA.CL2 b/src/Windebug/MONSTERS/EYE/EYEA.CL2 new file mode 100644 index 0000000..f6180e9 Binary files /dev/null and b/src/Windebug/MONSTERS/EYE/EYEA.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE/EYED.CL2 b/src/Windebug/MONSTERS/EYE/EYED.CL2 new file mode 100644 index 0000000..76f93e0 Binary files /dev/null and b/src/Windebug/MONSTERS/EYE/EYED.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE/EYEH.CL2 b/src/Windebug/MONSTERS/EYE/EYEH.CL2 new file mode 100644 index 0000000..f26f712 Binary files /dev/null and b/src/Windebug/MONSTERS/EYE/EYEH.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE/EYEN.CL2 b/src/Windebug/MONSTERS/EYE/EYEN.CL2 new file mode 100644 index 0000000..60727fe Binary files /dev/null and b/src/Windebug/MONSTERS/EYE/EYEN.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE/EYEW.CL2 b/src/Windebug/MONSTERS/EYE/EYEW.CL2 new file mode 100644 index 0000000..c4a7a90 Binary files /dev/null and b/src/Windebug/MONSTERS/EYE/EYEW.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE2/DEBUG.TXT b/src/Windebug/MONSTERS/EYE2/DEBUG.TXT new file mode 100644 index 0000000..5574765 --- /dev/null +++ b/src/Windebug/MONSTERS/EYE2/DEBUG.TXT @@ -0,0 +1,9 @@ +eye width 140 height 142 +eye width 140 height 142 +eye width 140 height 142 +Neutral frame count 12 +Walk frame count 13 +Attack frame count 13 +Get hit frame count 7 +Die frame count 21 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/EYE2/EYE2A.CL2 b/src/Windebug/MONSTERS/EYE2/EYE2A.CL2 new file mode 100644 index 0000000..9a0e00c Binary files /dev/null and b/src/Windebug/MONSTERS/EYE2/EYE2A.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE2/EYE2D.CL2 b/src/Windebug/MONSTERS/EYE2/EYE2D.CL2 new file mode 100644 index 0000000..0eb9a2f Binary files /dev/null and b/src/Windebug/MONSTERS/EYE2/EYE2D.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE2/EYE2H.CL2 b/src/Windebug/MONSTERS/EYE2/EYE2H.CL2 new file mode 100644 index 0000000..cd9c5ac Binary files /dev/null and b/src/Windebug/MONSTERS/EYE2/EYE2H.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE2/EYE2N.CL2 b/src/Windebug/MONSTERS/EYE2/EYE2N.CL2 new file mode 100644 index 0000000..74a7aa4 Binary files /dev/null and b/src/Windebug/MONSTERS/EYE2/EYE2N.CL2 differ diff --git a/src/Windebug/MONSTERS/EYE2/EYE2W.CL2 b/src/Windebug/MONSTERS/EYE2/EYE2W.CL2 new file mode 100644 index 0000000..f172f32 Binary files /dev/null and b/src/Windebug/MONSTERS/EYE2/EYE2W.CL2 differ diff --git a/src/Windebug/MONSTERS/FLESH/DEBUG.TXT b/src/Windebug/MONSTERS/FLESH/DEBUG.TXT new file mode 100644 index 0000000..63bfc2a --- /dev/null +++ b/src/Windebug/MONSTERS/FLESH/DEBUG.TXT @@ -0,0 +1,8 @@ +Flesh width 164 height 141 +Flesh width 164 height 141 +Neutral frame count 15 +Walk frame count 24 +Attack frame count 15 +Get hit frame count 6 +Die frame count 16 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/FLESH/FLESHA.CL2 b/src/Windebug/MONSTERS/FLESH/FLESHA.CL2 new file mode 100644 index 0000000..ae78dbb Binary files /dev/null and b/src/Windebug/MONSTERS/FLESH/FLESHA.CL2 differ diff --git a/src/Windebug/MONSTERS/FLESH/FLESHD.CL2 b/src/Windebug/MONSTERS/FLESH/FLESHD.CL2 new file mode 100644 index 0000000..839cac3 Binary files /dev/null and b/src/Windebug/MONSTERS/FLESH/FLESHD.CL2 differ diff --git a/src/Windebug/MONSTERS/FLESH/FLESHH.CL2 b/src/Windebug/MONSTERS/FLESH/FLESHH.CL2 new file mode 100644 index 0000000..0bf8614 Binary files /dev/null and b/src/Windebug/MONSTERS/FLESH/FLESHH.CL2 differ diff --git a/src/Windebug/MONSTERS/FLESH/FLESHN.CL2 b/src/Windebug/MONSTERS/FLESH/FLESHN.CL2 new file mode 100644 index 0000000..52ca6d4 Binary files /dev/null and b/src/Windebug/MONSTERS/FLESH/FLESHN.CL2 differ diff --git a/src/Windebug/MONSTERS/FLESH/FLESHW.CL2 b/src/Windebug/MONSTERS/FLESH/FLESHW.CL2 new file mode 100644 index 0000000..eefceba Binary files /dev/null and b/src/Windebug/MONSTERS/FLESH/FLESHW.CL2 differ diff --git a/src/Windebug/MONSTERS/FORK/DEBUG.TXT b/src/Windebug/MONSTERS/FORK/DEBUG.TXT new file mode 100644 index 0000000..15f7c89 --- /dev/null +++ b/src/Windebug/MONSTERS/FORK/DEBUG.TXT @@ -0,0 +1,8 @@ +Fork width 188 height 121 +Fork width 188 height 121 +Neutral frame count 10 +Walk frame count 10 +Attack frame count 15 +Get hit frame count 6 +Die frame count 16 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/FORK/FORKA.CL2 b/src/Windebug/MONSTERS/FORK/FORKA.CL2 new file mode 100644 index 0000000..7193b28 Binary files /dev/null and b/src/Windebug/MONSTERS/FORK/FORKA.CL2 differ diff --git a/src/Windebug/MONSTERS/FORK/FORKD.CL2 b/src/Windebug/MONSTERS/FORK/FORKD.CL2 new file mode 100644 index 0000000..fdf510d Binary files /dev/null and b/src/Windebug/MONSTERS/FORK/FORKD.CL2 differ diff --git a/src/Windebug/MONSTERS/FORK/FORKH.CL2 b/src/Windebug/MONSTERS/FORK/FORKH.CL2 new file mode 100644 index 0000000..8879864 Binary files /dev/null and b/src/Windebug/MONSTERS/FORK/FORKH.CL2 differ diff --git a/src/Windebug/MONSTERS/FORK/FORKN.CL2 b/src/Windebug/MONSTERS/FORK/FORKN.CL2 new file mode 100644 index 0000000..3f65595 Binary files /dev/null and b/src/Windebug/MONSTERS/FORK/FORKN.CL2 differ diff --git a/src/Windebug/MONSTERS/FORK/FORKW.CL2 b/src/Windebug/MONSTERS/FORK/FORKW.CL2 new file mode 100644 index 0000000..f9d4971 Binary files /dev/null and b/src/Windebug/MONSTERS/FORK/FORKW.CL2 differ diff --git a/src/Windebug/MONSTERS/GOATLORD/GOATLD.CL2 b/src/Windebug/MONSTERS/GOATLORD/GOATLD.CL2 new file mode 100644 index 0000000..23109ba Binary files /dev/null and b/src/Windebug/MONSTERS/GOATLORD/GOATLD.CL2 differ diff --git a/src/Windebug/MONSTERS/GRAVDG/GDIGGER.TXT b/src/Windebug/MONSTERS/GRAVDG/GDIGGER.TXT new file mode 100644 index 0000000..2f9e97c --- /dev/null +++ b/src/Windebug/MONSTERS/GRAVDG/GDIGGER.TXT @@ -0,0 +1,8 @@ +gd0 width 124 height 111 +gd0 width 124 height 111 +Neutral frame count 24 +Walk frame count 24 +Attack frame count 12 +Get hit frame count 6 +Die frame count 16 +Special frame count 16 diff --git a/src/Windebug/MONSTERS/GRAVDG/GRAVDGA.CL2 b/src/Windebug/MONSTERS/GRAVDG/GRAVDGA.CL2 new file mode 100644 index 0000000..511f3ed Binary files /dev/null and b/src/Windebug/MONSTERS/GRAVDG/GRAVDGA.CL2 differ diff --git a/src/Windebug/MONSTERS/GRAVDG/GRAVDGD.CL2 b/src/Windebug/MONSTERS/GRAVDG/GRAVDGD.CL2 new file mode 100644 index 0000000..7c71e41 Binary files /dev/null and b/src/Windebug/MONSTERS/GRAVDG/GRAVDGD.CL2 differ diff --git a/src/Windebug/MONSTERS/GRAVDG/GRAVDGH.CL2 b/src/Windebug/MONSTERS/GRAVDG/GRAVDGH.CL2 new file mode 100644 index 0000000..6321f35 Binary files /dev/null and b/src/Windebug/MONSTERS/GRAVDG/GRAVDGH.CL2 differ diff --git a/src/Windebug/MONSTERS/GRAVDG/GRAVDGN.CL2 b/src/Windebug/MONSTERS/GRAVDG/GRAVDGN.CL2 new file mode 100644 index 0000000..2b937a9 Binary files /dev/null and b/src/Windebug/MONSTERS/GRAVDG/GRAVDGN.CL2 differ diff --git a/src/Windebug/MONSTERS/GRAVDG/GRAVDGS.CL2 b/src/Windebug/MONSTERS/GRAVDG/GRAVDGS.CL2 new file mode 100644 index 0000000..3c4c82c Binary files /dev/null and b/src/Windebug/MONSTERS/GRAVDG/GRAVDGS.CL2 differ diff --git a/src/Windebug/MONSTERS/GRAVDG/GRAVDGW.CL2 b/src/Windebug/MONSTERS/GRAVDG/GRAVDGW.CL2 new file mode 100644 index 0000000..a7046ec Binary files /dev/null and b/src/Windebug/MONSTERS/GRAVDG/GRAVDGW.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT/HELBATA.CL2 b/src/Windebug/MONSTERS/HELLBAT/HELBATA.CL2 new file mode 100644 index 0000000..a967371 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT/HELBATA.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT/HELBATD.CL2 b/src/Windebug/MONSTERS/HELLBAT/HELBATD.CL2 new file mode 100644 index 0000000..7e21f56 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT/HELBATD.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT/HELBATH.CL2 b/src/Windebug/MONSTERS/HELLBAT/HELBATH.CL2 new file mode 100644 index 0000000..8e372b1 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT/HELBATH.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT/HELBATN.CL2 b/src/Windebug/MONSTERS/HELLBAT/HELBATN.CL2 new file mode 100644 index 0000000..7383a4b Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT/HELBATN.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT/HELBATS.CL2 b/src/Windebug/MONSTERS/HELLBAT/HELBATS.CL2 new file mode 100644 index 0000000..5a17779 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT/HELBATS.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT/HELBATW.CL2 b/src/Windebug/MONSTERS/HELLBAT/HELBATW.CL2 new file mode 100644 index 0000000..7231e4a Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT/HELBATW.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT/HELLBAT.TXT b/src/Windebug/MONSTERS/HELLBAT/HELLBAT.TXT new file mode 100644 index 0000000..8f7aebb --- /dev/null +++ b/src/Windebug/MONSTERS/HELLBAT/HELLBAT.TXT @@ -0,0 +1,8 @@ +napalm0 width 96 height 102 +napalm0 width 96 height 102 +Neutral frame count 18 +Walk frame count 16 +Attack frame count 14 +Get hit frame count 6 +Die frame count 18 +Special frame count 11 diff --git a/src/Windebug/MONSTERS/HELLBAT2/BHELBTA.CL2 b/src/Windebug/MONSTERS/HELLBAT2/BHELBTA.CL2 new file mode 100644 index 0000000..96bdbb6 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT2/BHELBTA.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT2/BHELBTD.CL2 b/src/Windebug/MONSTERS/HELLBAT2/BHELBTD.CL2 new file mode 100644 index 0000000..21506d3 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT2/BHELBTD.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT2/BHELBTH.CL2 b/src/Windebug/MONSTERS/HELLBAT2/BHELBTH.CL2 new file mode 100644 index 0000000..20ceaaf Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT2/BHELBTH.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT2/BHELBTN.CL2 b/src/Windebug/MONSTERS/HELLBAT2/BHELBTN.CL2 new file mode 100644 index 0000000..a976a15 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT2/BHELBTN.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT2/BHELBTS.CL2 b/src/Windebug/MONSTERS/HELLBAT2/BHELBTS.CL2 new file mode 100644 index 0000000..9452843 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT2/BHELBTS.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT2/BHELBTW.CL2 b/src/Windebug/MONSTERS/HELLBAT2/BHELBTW.CL2 new file mode 100644 index 0000000..1a8b291 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBAT2/BHELBTW.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBAT2/BHELLBAT.TXT b/src/Windebug/MONSTERS/HELLBAT2/BHELLBAT.TXT new file mode 100644 index 0000000..ffa5e08 --- /dev/null +++ b/src/Windebug/MONSTERS/HELLBAT2/BHELLBAT.TXT @@ -0,0 +1,8 @@ +blakbat width 96 height 102 +blakbat width 96 height 102 +Neutral frame count 18 +Walk frame count 16 +Attack frame count 14 +Get hit frame count 6 +Die frame count 18 +Special frame count 11 diff --git a/src/Windebug/MONSTERS/HELLBUG/HELLBGA.CL2 b/src/Windebug/MONSTERS/HELLBUG/HELLBGA.CL2 new file mode 100644 index 0000000..bcfb979 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBUG/HELLBGA.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBUG/HELLBGD.CL2 b/src/Windebug/MONSTERS/HELLBUG/HELLBGD.CL2 new file mode 100644 index 0000000..97897cd Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBUG/HELLBGD.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBUG/HELLBGH.CL2 b/src/Windebug/MONSTERS/HELLBUG/HELLBGH.CL2 new file mode 100644 index 0000000..a84973d Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBUG/HELLBGH.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBUG/HELLBGN.CL2 b/src/Windebug/MONSTERS/HELLBUG/HELLBGN.CL2 new file mode 100644 index 0000000..12cd163 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBUG/HELLBGN.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBUG/HELLBGS.CL2 b/src/Windebug/MONSTERS/HELLBUG/HELLBGS.CL2 new file mode 100644 index 0000000..1237ff8 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBUG/HELLBGS.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBUG/HELLBGW.CL2 b/src/Windebug/MONSTERS/HELLBUG/HELLBGW.CL2 new file mode 100644 index 0000000..9e883f7 Binary files /dev/null and b/src/Windebug/MONSTERS/HELLBUG/HELLBGW.CL2 differ diff --git a/src/Windebug/MONSTERS/HELLBUG/HELLBUG.TXT b/src/Windebug/MONSTERS/HELLBUG/HELLBUG.TXT new file mode 100644 index 0000000..8283c09 --- /dev/null +++ b/src/Windebug/MONSTERS/HELLBUG/HELLBUG.TXT @@ -0,0 +1,8 @@ +helbug0 width 198 height 230 +helbug0 width 198 height 230 +Neutral frame count 8 +Walk frame count 8 +Attack frame count 14 +Get hit frame count 6 +Die frame count 14 +Special frame count 12 diff --git a/src/Windebug/MONSTERS/HORKD/DEBUG.TXT b/src/Windebug/MONSTERS/HORKD/DEBUG.TXT new file mode 100644 index 0000000..d7e15fb --- /dev/null +++ b/src/Windebug/MONSTERS/HORKD/DEBUG.TXT @@ -0,0 +1,8 @@ +HorkD width 138 height 144 +HorkD width 138 height 144 +Neutral frame count 15 +Walk frame count 8 +Attack frame count 16 +Get hit frame count 6 +Die frame count 16 +Special frame count 9 diff --git a/src/Windebug/MONSTERS/HORKD/HORKDA.CL2 b/src/Windebug/MONSTERS/HORKD/HORKDA.CL2 new file mode 100644 index 0000000..c663f95 Binary files /dev/null and b/src/Windebug/MONSTERS/HORKD/HORKDA.CL2 differ diff --git a/src/Windebug/MONSTERS/HORKD/HORKDD.CL2 b/src/Windebug/MONSTERS/HORKD/HORKDD.CL2 new file mode 100644 index 0000000..503ba87 Binary files /dev/null and b/src/Windebug/MONSTERS/HORKD/HORKDD.CL2 differ diff --git a/src/Windebug/MONSTERS/HORKD/HORKDH.CL2 b/src/Windebug/MONSTERS/HORKD/HORKDH.CL2 new file mode 100644 index 0000000..124b269 Binary files /dev/null and b/src/Windebug/MONSTERS/HORKD/HORKDH.CL2 differ diff --git a/src/Windebug/MONSTERS/HORKD/HORKDN.CL2 b/src/Windebug/MONSTERS/HORKD/HORKDN.CL2 new file mode 100644 index 0000000..ea8c7f5 Binary files /dev/null and b/src/Windebug/MONSTERS/HORKD/HORKDN.CL2 differ diff --git a/src/Windebug/MONSTERS/HORKD/HORKDS.CL2 b/src/Windebug/MONSTERS/HORKD/HORKDS.CL2 new file mode 100644 index 0000000..630fb98 Binary files /dev/null and b/src/Windebug/MONSTERS/HORKD/HORKDS.CL2 differ diff --git a/src/Windebug/MONSTERS/HORKD/HORKDW.CL2 b/src/Windebug/MONSTERS/HORKD/HORKDW.CL2 new file mode 100644 index 0000000..e121ddd Binary files /dev/null and b/src/Windebug/MONSTERS/HORKD/HORKDW.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH/DEBUG.TXT b/src/Windebug/MONSTERS/LICH/DEBUG.TXT new file mode 100644 index 0000000..6424b25 --- /dev/null +++ b/src/Windebug/MONSTERS/LICH/DEBUG.TXT @@ -0,0 +1,7 @@ +lich0 width 96 height 148 +Neutral frame count 12 +Walk frame count 10 +Attack frame count 10 +Get hit frame count 7 +Die frame count 21 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/LICH/LICHA.CL2 b/src/Windebug/MONSTERS/LICH/LICHA.CL2 new file mode 100644 index 0000000..460680f Binary files /dev/null and b/src/Windebug/MONSTERS/LICH/LICHA.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH/LICHD.CL2 b/src/Windebug/MONSTERS/LICH/LICHD.CL2 new file mode 100644 index 0000000..91b2d8a Binary files /dev/null and b/src/Windebug/MONSTERS/LICH/LICHD.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH/LICHH.CL2 b/src/Windebug/MONSTERS/LICH/LICHH.CL2 new file mode 100644 index 0000000..14a6154 Binary files /dev/null and b/src/Windebug/MONSTERS/LICH/LICHH.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH/LICHN.CL2 b/src/Windebug/MONSTERS/LICH/LICHN.CL2 new file mode 100644 index 0000000..f5e5e09 Binary files /dev/null and b/src/Windebug/MONSTERS/LICH/LICHN.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH/LICHW.CL2 b/src/Windebug/MONSTERS/LICH/LICHW.CL2 new file mode 100644 index 0000000..8942882 Binary files /dev/null and b/src/Windebug/MONSTERS/LICH/LICHW.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH2/DEBUG.TXT b/src/Windebug/MONSTERS/LICH2/DEBUG.TXT new file mode 100644 index 0000000..ef65d32 --- /dev/null +++ b/src/Windebug/MONSTERS/LICH2/DEBUG.TXT @@ -0,0 +1,7 @@ +lich0 width 136 height 119 +Neutral frame count 12 +Walk frame count 10 +Attack frame count 10 +Get hit frame count 7 +Die frame count 21 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/LICH2/LICH2A.CL2 b/src/Windebug/MONSTERS/LICH2/LICH2A.CL2 new file mode 100644 index 0000000..4684aa4 Binary files /dev/null and b/src/Windebug/MONSTERS/LICH2/LICH2A.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH2/LICH2D.CL2 b/src/Windebug/MONSTERS/LICH2/LICH2D.CL2 new file mode 100644 index 0000000..03abd55 Binary files /dev/null and b/src/Windebug/MONSTERS/LICH2/LICH2D.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH2/LICH2H.CL2 b/src/Windebug/MONSTERS/LICH2/LICH2H.CL2 new file mode 100644 index 0000000..2889a62 Binary files /dev/null and b/src/Windebug/MONSTERS/LICH2/LICH2H.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH2/LICH2N.CL2 b/src/Windebug/MONSTERS/LICH2/LICH2N.CL2 new file mode 100644 index 0000000..473c9d7 Binary files /dev/null and b/src/Windebug/MONSTERS/LICH2/LICH2N.CL2 differ diff --git a/src/Windebug/MONSTERS/LICH2/LICH2W.CL2 b/src/Windebug/MONSTERS/LICH2/LICH2W.CL2 new file mode 100644 index 0000000..b64ce1d Binary files /dev/null and b/src/Windebug/MONSTERS/LICH2/LICH2W.CL2 differ diff --git a/src/Windebug/MONSTERS/NKR/NAKRULE.TXT b/src/Windebug/MONSTERS/NKR/NAKRULE.TXT new file mode 100644 index 0000000..b625518 --- /dev/null +++ b/src/Windebug/MONSTERS/NKR/NAKRULE.TXT @@ -0,0 +1,8 @@ +nakrule width 226 height 189 +nakrule width 226 height 189 +Neutral frame count 1 +Walk frame count 6 +Attack frame count 16 +Get hit frame count 6 +Die frame count 16 +Special frame count 16 diff --git a/src/Windebug/MONSTERS/NKR/NKRA.CL2 b/src/Windebug/MONSTERS/NKR/NKRA.CL2 new file mode 100644 index 0000000..293c8f0 Binary files /dev/null and b/src/Windebug/MONSTERS/NKR/NKRA.CL2 differ diff --git a/src/Windebug/MONSTERS/NKR/NKRD.CL2 b/src/Windebug/MONSTERS/NKR/NKRD.CL2 new file mode 100644 index 0000000..aa7a702 Binary files /dev/null and b/src/Windebug/MONSTERS/NKR/NKRD.CL2 differ diff --git a/src/Windebug/MONSTERS/NKR/NKRH.CL2 b/src/Windebug/MONSTERS/NKR/NKRH.CL2 new file mode 100644 index 0000000..24e92dc Binary files /dev/null and b/src/Windebug/MONSTERS/NKR/NKRH.CL2 differ diff --git a/src/Windebug/MONSTERS/NKR/NKRN.CL2 b/src/Windebug/MONSTERS/NKR/NKRN.CL2 new file mode 100644 index 0000000..4dd1b1e Binary files /dev/null and b/src/Windebug/MONSTERS/NKR/NKRN.CL2 differ diff --git a/src/Windebug/MONSTERS/NKR/NKRS.CL2 b/src/Windebug/MONSTERS/NKR/NKRS.CL2 new file mode 100644 index 0000000..91d5af4 Binary files /dev/null and b/src/Windebug/MONSTERS/NKR/NKRS.CL2 differ diff --git a/src/Windebug/MONSTERS/NKR/NKRW.CL2 b/src/Windebug/MONSTERS/NKR/NKRW.CL2 new file mode 100644 index 0000000..e065de0 Binary files /dev/null and b/src/Windebug/MONSTERS/NKR/NKRW.CL2 differ diff --git a/src/Windebug/MONSTERS/RAT/DEBUG.TXT b/src/Windebug/MONSTERS/RAT/DEBUG.TXT new file mode 100644 index 0000000..2b81df3 --- /dev/null +++ b/src/Windebug/MONSTERS/RAT/DEBUG.TXT @@ -0,0 +1,8 @@ +Rat width 104 height 78 +Rat width 104 height 78 +Neutral frame count 11 +Walk frame count 8 +Attack frame count 12 +Get hit frame count 6 +Die frame count 20 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/RAT/RATA.CL2 b/src/Windebug/MONSTERS/RAT/RATA.CL2 new file mode 100644 index 0000000..d98582d Binary files /dev/null and b/src/Windebug/MONSTERS/RAT/RATA.CL2 differ diff --git a/src/Windebug/MONSTERS/RAT/RATD.CL2 b/src/Windebug/MONSTERS/RAT/RATD.CL2 new file mode 100644 index 0000000..c9d3d75 Binary files /dev/null and b/src/Windebug/MONSTERS/RAT/RATD.CL2 differ diff --git a/src/Windebug/MONSTERS/RAT/RATH.CL2 b/src/Windebug/MONSTERS/RAT/RATH.CL2 new file mode 100644 index 0000000..233d18e Binary files /dev/null and b/src/Windebug/MONSTERS/RAT/RATH.CL2 differ diff --git a/src/Windebug/MONSTERS/RAT/RATN.CL2 b/src/Windebug/MONSTERS/RAT/RATN.CL2 new file mode 100644 index 0000000..e191220 Binary files /dev/null and b/src/Windebug/MONSTERS/RAT/RATN.CL2 differ diff --git a/src/Windebug/MONSTERS/RAT/RATW.CL2 b/src/Windebug/MONSTERS/RAT/RATW.CL2 new file mode 100644 index 0000000..1ad96e0 Binary files /dev/null and b/src/Windebug/MONSTERS/RAT/RATW.CL2 differ diff --git a/src/Windebug/MONSTERS/REAPER/REAPA.CL2 b/src/Windebug/MONSTERS/REAPER/REAPA.CL2 new file mode 100644 index 0000000..cd07263 Binary files /dev/null and b/src/Windebug/MONSTERS/REAPER/REAPA.CL2 differ diff --git a/src/Windebug/MONSTERS/REAPER/REAPD.CL2 b/src/Windebug/MONSTERS/REAPER/REAPD.CL2 new file mode 100644 index 0000000..ad1635f Binary files /dev/null and b/src/Windebug/MONSTERS/REAPER/REAPD.CL2 differ diff --git a/src/Windebug/MONSTERS/REAPER/REAPER.TXT b/src/Windebug/MONSTERS/REAPER/REAPER.TXT new file mode 100644 index 0000000..8c1dc2d --- /dev/null +++ b/src/Windebug/MONSTERS/REAPER/REAPER.TXT @@ -0,0 +1,8 @@ +babyd width 180 height 163 +babyd width 180 height 163 +Neutral frame count 12 +Walk frame count 10 +Attack frame count 14 +Get hit frame count 6 +Die frame count 16 +Special frame count 1 diff --git a/src/Windebug/MONSTERS/REAPER/REAPH.CL2 b/src/Windebug/MONSTERS/REAPER/REAPH.CL2 new file mode 100644 index 0000000..eda4c2d Binary files /dev/null and b/src/Windebug/MONSTERS/REAPER/REAPH.CL2 differ diff --git a/src/Windebug/MONSTERS/REAPER/REAPN.CL2 b/src/Windebug/MONSTERS/REAPER/REAPN.CL2 new file mode 100644 index 0000000..1413d9c Binary files /dev/null and b/src/Windebug/MONSTERS/REAPER/REAPN.CL2 differ diff --git a/src/Windebug/MONSTERS/REAPER/REAPW.CL2 b/src/Windebug/MONSTERS/REAPER/REAPW.CL2 new file mode 100644 index 0000000..01c1a61 Binary files /dev/null and b/src/Windebug/MONSTERS/REAPER/REAPW.CL2 differ diff --git a/src/Windebug/MONSTERS/SCORP/DEBUG.TXT b/src/Windebug/MONSTERS/SCORP/DEBUG.TXT new file mode 100644 index 0000000..5dc2f8b --- /dev/null +++ b/src/Windebug/MONSTERS/SCORP/DEBUG.TXT @@ -0,0 +1,8 @@ +Scorpn width 64 height 67 +Scorpn width 64 height 67 +Neutral frame count 10 +Walk frame count 10 +Attack frame count 12 +Get hit frame count 6 +Die frame count 15 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/SCORP/SCORPA.CL2 b/src/Windebug/MONSTERS/SCORP/SCORPA.CL2 new file mode 100644 index 0000000..4209a6f Binary files /dev/null and b/src/Windebug/MONSTERS/SCORP/SCORPA.CL2 differ diff --git a/src/Windebug/MONSTERS/SCORP/SCORPD.CL2 b/src/Windebug/MONSTERS/SCORP/SCORPD.CL2 new file mode 100644 index 0000000..7acea89 Binary files /dev/null and b/src/Windebug/MONSTERS/SCORP/SCORPD.CL2 differ diff --git a/src/Windebug/MONSTERS/SCORP/SCORPH.CL2 b/src/Windebug/MONSTERS/SCORP/SCORPH.CL2 new file mode 100644 index 0000000..f08fe3d Binary files /dev/null and b/src/Windebug/MONSTERS/SCORP/SCORPH.CL2 differ diff --git a/src/Windebug/MONSTERS/SCORP/SCORPN.CL2 b/src/Windebug/MONSTERS/SCORP/SCORPN.CL2 new file mode 100644 index 0000000..3cdba76 Binary files /dev/null and b/src/Windebug/MONSTERS/SCORP/SCORPN.CL2 differ diff --git a/src/Windebug/MONSTERS/SCORP/SCORPW.CL2 b/src/Windebug/MONSTERS/SCORP/SCORPW.CL2 new file mode 100644 index 0000000..2bd2fa9 Binary files /dev/null and b/src/Windebug/MONSTERS/SCORP/SCORPW.CL2 differ diff --git a/src/Windebug/MONSTERS/SPAWN/DEBUG.TXT b/src/Windebug/MONSTERS/SPAWN/DEBUG.TXT new file mode 100644 index 0000000..599d2fa --- /dev/null +++ b/src/Windebug/MONSTERS/SPAWN/DEBUG.TXT @@ -0,0 +1,8 @@ +Spawn width 164 height 124 +Spawn width 164 height 124 +Neutral frame count 15 +Walk frame count 12 +Attack frame count 14 +Get hit frame count 11 +Die frame count 14 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/SPAWN/SPAWNA.CL2 b/src/Windebug/MONSTERS/SPAWN/SPAWNA.CL2 new file mode 100644 index 0000000..52749fa Binary files /dev/null and b/src/Windebug/MONSTERS/SPAWN/SPAWNA.CL2 differ diff --git a/src/Windebug/MONSTERS/SPAWN/SPAWND.CL2 b/src/Windebug/MONSTERS/SPAWN/SPAWND.CL2 new file mode 100644 index 0000000..9fb005d Binary files /dev/null and b/src/Windebug/MONSTERS/SPAWN/SPAWND.CL2 differ diff --git a/src/Windebug/MONSTERS/SPAWN/SPAWNH.CL2 b/src/Windebug/MONSTERS/SPAWN/SPAWNH.CL2 new file mode 100644 index 0000000..e0b7ce7 Binary files /dev/null and b/src/Windebug/MONSTERS/SPAWN/SPAWNH.CL2 differ diff --git a/src/Windebug/MONSTERS/SPAWN/SPAWNN.CL2 b/src/Windebug/MONSTERS/SPAWN/SPAWNN.CL2 new file mode 100644 index 0000000..fccacf3 Binary files /dev/null and b/src/Windebug/MONSTERS/SPAWN/SPAWNN.CL2 differ diff --git a/src/Windebug/MONSTERS/SPAWN/SPAWNW.CL2 b/src/Windebug/MONSTERS/SPAWN/SPAWNW.CL2 new file mode 100644 index 0000000..515a4b0 Binary files /dev/null and b/src/Windebug/MONSTERS/SPAWN/SPAWNW.CL2 differ diff --git a/src/Windebug/MONSTERS/SPIDER/DEBUG.TXT b/src/Windebug/MONSTERS/SPIDER/DEBUG.TXT new file mode 100644 index 0000000..d999edd --- /dev/null +++ b/src/Windebug/MONSTERS/SPIDER/DEBUG.TXT @@ -0,0 +1,8 @@ +Spider width 148 height 110 +Spider width 148 height 110 +Neutral frame count 12 +Walk frame count 10 +Attack frame count 15 +Get hit frame count 6 +Die frame count 20 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/SPIDER/SPIDERA.CL2 b/src/Windebug/MONSTERS/SPIDER/SPIDERA.CL2 new file mode 100644 index 0000000..aeb5074 Binary files /dev/null and b/src/Windebug/MONSTERS/SPIDER/SPIDERA.CL2 differ diff --git a/src/Windebug/MONSTERS/SPIDER/SPIDERD.CL2 b/src/Windebug/MONSTERS/SPIDER/SPIDERD.CL2 new file mode 100644 index 0000000..253c38e Binary files /dev/null and b/src/Windebug/MONSTERS/SPIDER/SPIDERD.CL2 differ diff --git a/src/Windebug/MONSTERS/SPIDER/SPIDERH.CL2 b/src/Windebug/MONSTERS/SPIDER/SPIDERH.CL2 new file mode 100644 index 0000000..bb2e2f2 Binary files /dev/null and b/src/Windebug/MONSTERS/SPIDER/SPIDERH.CL2 differ diff --git a/src/Windebug/MONSTERS/SPIDER/SPIDERN.CL2 b/src/Windebug/MONSTERS/SPIDER/SPIDERN.CL2 new file mode 100644 index 0000000..8f43908 Binary files /dev/null and b/src/Windebug/MONSTERS/SPIDER/SPIDERN.CL2 differ diff --git a/src/Windebug/MONSTERS/SPIDER/SPIDERW.CL2 b/src/Windebug/MONSTERS/SPIDER/SPIDERW.CL2 new file mode 100644 index 0000000..0e68587 Binary files /dev/null and b/src/Windebug/MONSTERS/SPIDER/SPIDERW.CL2 differ diff --git a/src/Windebug/MONSTERS/UNRAV/UNRAVA.CL2 b/src/Windebug/MONSTERS/UNRAV/UNRAVA.CL2 new file mode 100644 index 0000000..8c6a1da Binary files /dev/null and b/src/Windebug/MONSTERS/UNRAV/UNRAVA.CL2 differ diff --git a/src/Windebug/MONSTERS/UNRAV/UNRAVW.CL2 b/src/Windebug/MONSTERS/UNRAV/UNRAVW.CL2 new file mode 100644 index 0000000..dc3174e Binary files /dev/null and b/src/Windebug/MONSTERS/UNRAV/UNRAVW.CL2 differ diff --git a/src/Windebug/MONSTERS/WSCORP/DEBUG.TXT b/src/Windebug/MONSTERS/WSCORP/DEBUG.TXT new file mode 100644 index 0000000..3d31207 --- /dev/null +++ b/src/Windebug/MONSTERS/WSCORP/DEBUG.TXT @@ -0,0 +1,8 @@ +wScorp width 86 height 81 +wScorp width 86 height 81 +Neutral frame count 10 +Walk frame count 10 +Attack frame count 12 +Get hit frame count 6 +Die frame count 15 +Special frame count 0 diff --git a/src/Windebug/MONSTERS/WSCORP/WSCORPA.CL2 b/src/Windebug/MONSTERS/WSCORP/WSCORPA.CL2 new file mode 100644 index 0000000..285992c Binary files /dev/null and b/src/Windebug/MONSTERS/WSCORP/WSCORPA.CL2 differ diff --git a/src/Windebug/MONSTERS/WSCORP/WSCORPD.CL2 b/src/Windebug/MONSTERS/WSCORP/WSCORPD.CL2 new file mode 100644 index 0000000..0db6943 Binary files /dev/null and b/src/Windebug/MONSTERS/WSCORP/WSCORPD.CL2 differ diff --git a/src/Windebug/MONSTERS/WSCORP/WSCORPH.CL2 b/src/Windebug/MONSTERS/WSCORP/WSCORPH.CL2 new file mode 100644 index 0000000..9763271 Binary files /dev/null and b/src/Windebug/MONSTERS/WSCORP/WSCORPH.CL2 differ diff --git a/src/Windebug/MONSTERS/WSCORP/WSCORPN.CL2 b/src/Windebug/MONSTERS/WSCORP/WSCORPN.CL2 new file mode 100644 index 0000000..335974a Binary files /dev/null and b/src/Windebug/MONSTERS/WSCORP/WSCORPN.CL2 differ diff --git a/src/Windebug/MONSTERS/WSCORP/WSCORPW.CL2 b/src/Windebug/MONSTERS/WSCORP/WSCORPW.CL2 new file mode 100644 index 0000000..215b3ca Binary files /dev/null and b/src/Windebug/MONSTERS/WSCORP/WSCORPW.CL2 differ diff --git a/src/Windebug/NLEVELS/CUTL5.CEL b/src/Windebug/NLEVELS/CUTL5.CEL new file mode 100644 index 0000000..58f593b Binary files /dev/null and b/src/Windebug/NLEVELS/CUTL5.CEL differ diff --git a/src/Windebug/NLEVELS/CUTL5.PAL b/src/Windebug/NLEVELS/CUTL5.PAL new file mode 100644 index 0000000..dc5dc99 Binary files /dev/null and b/src/Windebug/NLEVELS/CUTL5.PAL differ diff --git a/src/Windebug/NLEVELS/CUTL6.CEL b/src/Windebug/NLEVELS/CUTL6.CEL new file mode 100644 index 0000000..5edb74c Binary files /dev/null and b/src/Windebug/NLEVELS/CUTL6.CEL differ diff --git a/src/Windebug/NLEVELS/CUTL6.PAL b/src/Windebug/NLEVELS/CUTL6.PAL new file mode 100644 index 0000000..aa699de Binary files /dev/null and b/src/Windebug/NLEVELS/CUTL6.PAL differ diff --git a/src/Windebug/NLEVELS/L5DATA/L5.AMP b/src/Windebug/NLEVELS/L5DATA/L5.AMP new file mode 100644 index 0000000..d1d7819 Binary files /dev/null and b/src/Windebug/NLEVELS/L5DATA/L5.AMP differ diff --git a/src/Windebug/NLEVELS/L5DATA/L5.CEL b/src/Windebug/NLEVELS/L5DATA/L5.CEL new file mode 100644 index 0000000..96fdb78 Binary files /dev/null and b/src/Windebug/NLEVELS/L5DATA/L5.CEL differ diff --git a/src/Windebug/NLEVELS/L5DATA/L5.MIN b/src/Windebug/NLEVELS/L5DATA/L5.MIN new file mode 100644 index 0000000..9c4b8ee Binary files /dev/null and b/src/Windebug/NLEVELS/L5DATA/L5.MIN differ diff --git a/src/Windebug/NLEVELS/L5DATA/L5.SOL b/src/Windebug/NLEVELS/L5DATA/L5.SOL new file mode 100644 index 0000000..52a9ffa Binary files /dev/null and b/src/Windebug/NLEVELS/L5DATA/L5.SOL differ diff --git a/src/Windebug/NLEVELS/L5DATA/L5.TIL b/src/Windebug/NLEVELS/L5DATA/L5.TIL new file mode 100644 index 0000000..9c7c10f Binary files /dev/null and b/src/Windebug/NLEVELS/L5DATA/L5.TIL differ diff --git a/src/Windebug/NLEVELS/L5DATA/L5BASE.PAL b/src/Windebug/NLEVELS/L5DATA/L5BASE.PAL new file mode 100644 index 0000000..559460c Binary files /dev/null and b/src/Windebug/NLEVELS/L5DATA/L5BASE.PAL differ diff --git a/src/Windebug/NLEVELS/L5DATA/L5DOOR.CEL b/src/Windebug/NLEVELS/L5DATA/L5DOOR.CEL new file mode 100644 index 0000000..1f8005c Binary files /dev/null and b/src/Windebug/NLEVELS/L5DATA/L5DOOR.CEL differ diff --git a/src/Windebug/NLEVELS/L5DATA/L5S.CEL b/src/Windebug/NLEVELS/L5DATA/L5S.CEL new file mode 100644 index 0000000..9b3d10e Binary files /dev/null and b/src/Windebug/NLEVELS/L5DATA/L5S.CEL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6.AMP b/src/Windebug/NLEVELS/L6DATA/L6.AMP new file mode 100644 index 0000000..056ac0d Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6.AMP differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6.CEL b/src/Windebug/NLEVELS/L6DATA/L6.CEL new file mode 100644 index 0000000..b2733d4 Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6.CEL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6.MIN b/src/Windebug/NLEVELS/L6DATA/L6.MIN new file mode 100644 index 0000000..4b5cbea Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6.MIN differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6.SOL b/src/Windebug/NLEVELS/L6DATA/L6.SOL new file mode 100644 index 0000000..3270ca3 Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6.SOL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6.TIL b/src/Windebug/NLEVELS/L6DATA/L6.TIL new file mode 100644 index 0000000..46a148a Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6.TIL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6BASE.PAL b/src/Windebug/NLEVELS/L6DATA/L6BASE.PAL new file mode 100644 index 0000000..9d76596 Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6BASE.PAL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6BASE1.PAL b/src/Windebug/NLEVELS/L6DATA/L6BASE1.PAL new file mode 100644 index 0000000..25fa9b6 Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6BASE1.PAL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6BASE2.PAL b/src/Windebug/NLEVELS/L6DATA/L6BASE2.PAL new file mode 100644 index 0000000..9d76596 Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6BASE2.PAL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6BASE3.PAL b/src/Windebug/NLEVELS/L6DATA/L6BASE3.PAL new file mode 100644 index 0000000..642703d Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6BASE3.PAL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6BASE4.PAL b/src/Windebug/NLEVELS/L6DATA/L6BASE4.PAL new file mode 100644 index 0000000..b5c9224 Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6BASE4.PAL differ diff --git a/src/Windebug/NLEVELS/L6DATA/L6BASE5.PAL b/src/Windebug/NLEVELS/L6DATA/L6BASE5.PAL new file mode 100644 index 0000000..bedbe28 Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/L6BASE5.PAL differ diff --git a/src/Windebug/NLEVELS/L6DATA/NEST.COL b/src/Windebug/NLEVELS/L6DATA/NEST.COL new file mode 100644 index 0000000..0ea9d6d Binary files /dev/null and b/src/Windebug/NLEVELS/L6DATA/NEST.COL differ diff --git a/src/Windebug/NLEVELS/TOWNDATA/TOWN.CEL b/src/Windebug/NLEVELS/TOWNDATA/TOWN.CEL new file mode 100644 index 0000000..2a00d37 Binary files /dev/null and b/src/Windebug/NLEVELS/TOWNDATA/TOWN.CEL differ diff --git a/src/Windebug/NLEVELS/TOWNDATA/TOWN.MIN b/src/Windebug/NLEVELS/TOWNDATA/TOWN.MIN new file mode 100644 index 0000000..7bc368e Binary files /dev/null and b/src/Windebug/NLEVELS/TOWNDATA/TOWN.MIN differ diff --git a/src/Windebug/NLEVELS/TOWNDATA/TOWN.SOL b/src/Windebug/NLEVELS/TOWNDATA/TOWN.SOL new file mode 100644 index 0000000..e17b7a5 Binary files /dev/null and b/src/Windebug/NLEVELS/TOWNDATA/TOWN.SOL differ diff --git a/src/Windebug/NLEVELS/TOWNDATA/TOWN.TIL b/src/Windebug/NLEVELS/TOWNDATA/TOWN.TIL new file mode 100644 index 0000000..ef63f94 Binary files /dev/null and b/src/Windebug/NLEVELS/TOWNDATA/TOWN.TIL differ diff --git a/src/Windebug/OBJECTS/L5BOOKS.CEL b/src/Windebug/OBJECTS/L5BOOKS.CEL new file mode 100644 index 0000000..e3e796b Binary files /dev/null and b/src/Windebug/OBJECTS/L5BOOKS.CEL differ diff --git a/src/Windebug/OBJECTS/L5DOOR.CEL b/src/Windebug/OBJECTS/L5DOOR.CEL new file mode 100644 index 0000000..1f8005c Binary files /dev/null and b/src/Windebug/OBJECTS/L5DOOR.CEL differ diff --git a/src/Windebug/OBJECTS/L5LEVER.CEL b/src/Windebug/OBJECTS/L5LEVER.CEL new file mode 100644 index 0000000..9755bd5 Binary files /dev/null and b/src/Windebug/OBJECTS/L5LEVER.CEL differ diff --git a/src/Windebug/OBJECTS/L5LIGHT.CEL b/src/Windebug/OBJECTS/L5LIGHT.CEL new file mode 100644 index 0000000..1194856 Binary files /dev/null and b/src/Windebug/OBJECTS/L5LIGHT.CEL differ diff --git a/src/Windebug/OBJECTS/L5SARCO.CEL b/src/Windebug/OBJECTS/L5SARCO.CEL new file mode 100644 index 0000000..7812ff6 Binary files /dev/null and b/src/Windebug/OBJECTS/L5SARCO.CEL differ diff --git a/src/Windebug/OBJECTS/L6POD1.CEL b/src/Windebug/OBJECTS/L6POD1.CEL new file mode 100644 index 0000000..da7f07b Binary files /dev/null and b/src/Windebug/OBJECTS/L6POD1.CEL differ diff --git a/src/Windebug/OBJECTS/L6POD2.CEL b/src/Windebug/OBJECTS/L6POD2.CEL new file mode 100644 index 0000000..893473b Binary files /dev/null and b/src/Windebug/OBJECTS/L6POD2.CEL differ diff --git a/src/Windebug/OBJECTS/URN.CEL b/src/Windebug/OBJECTS/URN.CEL new file mode 100644 index 0000000..63d05b1 Binary files /dev/null and b/src/Windebug/OBJECTS/URN.CEL differ diff --git a/src/Windebug/OBJECTS/URNEXPLD.CEL b/src/Windebug/OBJECTS/URNEXPLD.CEL new file mode 100644 index 0000000..46e0edf Binary files /dev/null and b/src/Windebug/OBJECTS/URNEXPLD.CEL differ diff --git a/src/Windebug/ORGDLL/STORM.DLL b/src/Windebug/ORGDLL/STORM.DLL new file mode 100644 index 0000000..21f620d Binary files /dev/null and b/src/Windebug/ORGDLL/STORM.DLL differ diff --git a/src/Windebug/PATCH.TXT b/src/Windebug/PATCH.TXT new file mode 100644 index 0000000..72a0648 --- /dev/null +++ b/src/Windebug/PATCH.TXT @@ -0,0 +1,259 @@ +HELLFIRE (European/US) PATCH README v1.01 +01/13/98 + +TABLE OF CONTENTS + +[1] WHAT THE PATCH FIXES +[2] HOW TO INSTALL THE PATCH +[3] IF YOU STILL EXPERIANCE PROBLEMS + +[1] WHAT THE PATCH FIXES +==================================== +This patch provides fixes and enhancements to the Hellfire 1.00 product. It provides a new executable (HELLFIRE.EXE), an interface library (HELLFRUI.DLL), a patch text file (Patch.txt), and a version text file (Version.txt. + + +List of changes +-------------------------------------------------------------------------- +- Fixed Gossip (same gossip from each towner every time) +- Fixed disappearing quests (upon re-entering the town level, quest statuses were incorrectly cleared through array bounds overstep). +- Fixed generating spell books by Adria (would "morph" on new game). +- Fixed the bug where picking up gold when your inventory is full duplicates the gold in your hand and fills your gold slot. +- Fixed the Berserk spell to prevent crashes (large numbers of berserk monsters occasionally attacked dead monsters). +- Fixed inactive monsters to prevent same kind of crash as above +- Fixed entering levels; had crashed on some systems (seemingly randomly). +- Fixed doppelganger's items to not clone Diablo +- Fixed generating rings of fire behind a wall. +- Sped up monk's open-hand attack (users complained he should be faster with feet than with the sweeping staff). +- Various small internal fixes to prevent potential misbehavior. +- Fixed monster hitpoint variable type for tough monsters (some monsters, especially in Nightmare/Hell difficulty, had way fewer hit points than specified) +- Changed Search spell to show items on automap, too (users complained they couldn't find things behind solid walls in Caves, Nest, Crypt). +- Fix to unique items changing between games (veil of steel, arkaine's valor, etc). +- Fixed to dropping and picking back up oiled items (bonus was lost). +- Fixed Cathedral Map activation crash bug +- Added sounds to Mana Drain and Disenchant traps +- Monster hit points in Nightmare/Hell are +100/200 instead of +1.5/+3 +- Fixed monster stats display in Nightmare/Hell to reflect the halving. +- Balance/Stability/Harmony now does something + + + +[2] HOW TO INSTALL THE PATCH +==================================== + +This patch is a self-extracting executable that will place four files into the program directory that contains the Hellfire.exe file. If you have not installed to the default directory, make the appropriate changes on the next screen. + +To start the install process, simply double click on the HF101 file and follow the given instructions. + + +[3] IF YOU STILL EXPERIENCE PROBLEMS +==================================== + +Customer Service Support and Sales + +United States +U.S.A. Sales Phone: (800) 757-7707 +Sierra Direct +International Sales: (425) 746-5771 +Sundays 8 AM to 9PM CST +Hours: Monday-Saturday 7AM to 11 PM CST, +FAX: (402) 393-3224 + +7100 W. Center Rd +STE 301 +Omaha, NE 68106 + + +United Kingdom +CUC Software International Limited +Main: (0118) 920-9111 +Monday-Friday, 9:00 a.m. - 5:00 p.m. +Fax: (0118) 987-5603 +Disk/CD replacements in the U.K. are £6.00, +or £7.00 outside the UK. Add "ATTN.: Returns." + +2 Beacontree Plaza, +Gillette Way, +Reading, Berkshire +RG2 0BS United Kingdom + +France +CUC Software International Limited +Parc Tertiaire de Meudon +Phone: (01) 46-01-46-50 +Fax: (01) 46-30-00-65 +Lundi au Vendredi de 9h à 19h + +Immeuble "Le Newton" +25 rue Jeanne Braconnier +92366 Meudon La Forêt Cedex +France + +Germany +CUC Software International Limited +Tel: (0) 6103-99-40-40 +Montag bis Freitag von 9h - 19Uhr +Fax: (0) 6103-99-40-35 +Robert-Bosh-Str. 32 +D-63303 Dreieich +Germany + +On-Line Sales +Internet USA: http://www.sierra.com +Internet United Kingdom:http://www.sierra-online.co.uk +Internet France: http://www.sierra.fr +Internet Germany: http://www.sierra.de + +THE SIERRA NO-RISK GUARANTEE +The Promise: We want you to be happy with every Sierra product you purchase from us. Period. If for any reason you're unhappy with the product, return it within 30 days for an exchange or a full refund EVEN IF YOU BOUGHT IT RETAIL. (Hardware ordered direct must be returned within ten days.) Please send back your product, signature required if mailing via US Postal Service. + +The Only Catch: You've got to tell us why you don't like the game. Otherwise, we'll never get any better. Send it back to us and we promise we'll make things right. (If you bought it at a retail outlet, please send your original sales receipt.) + +* Returns valid in North America only. + +Disk and or Manual Replacement: +Sierra On-Line Fulfillment +4100 West 190th Street +Torrance, CA 90504 + +Product Returns: +Sierra On-Line Returns +4100 West 190th Street +Torrance, CA 90504 + + +NOTE: To replace your disk(s) please send only Disk #1 (or the CD) and copy of your dated Receipt, if less then 90 days. After 90 days please include a $10 handling fee along with Disk / CD #1. For Documentation, please include a $ 5.00 handling fee and a photocopy ONLY of disk #1. Payment should be made at the time of your request. Sorry, no credit cards. + +* Returns to this address valid in North America only. + +Technical Support +Automated Technical Support Line - USA: +1-425-644-4343 +Sierra On-Line offers a 24-hour Automated Technical Support line with recorded answers to the most frequently asked technical questions. To access this service, call (425) 644-4343, and follow the recorded instructions to find your specific topic and resolve the issue. If this fails to solve your problem, you may still write, or fax us with your questions, or contact us via our web site. + +U.S. Technical Support +Sierra On-Line +Technical Support +Main: (425) 644-4343 +Monday-Friday, 8:00 a.m. - 4:45 p.m. PST +Fax: (425) 644-7697 +P.O. Box 85006 +Bellevue, WA 98015-8506 + +Automated Technical Support Line - United Kingdom: +(0118) 920-9111 +CUC Software International Limited offers a 24-hour Automated Technical Support line with recorded answers to the most frequently asked technical questions. To access this service, call (0118) 920-9111, and follow the recorded instructions to find your specific topic and resolve the issue. If this fails to solve your problem, you may still write, or fax us with your questions, or contact us via our Internet or CompuServe sites. + +U.K. Technical Support +CUC Software International Limited +Phone: (0118) 920-9111 +Monday-Friday, 9:00 a.m. - 5:00 p.m. +Fax: (0118) 987-5603 +Disk/CD replacements in the U.K. are £6.00, +or £7.00 outside the UK. Add "ATTN.: Returns." +2 Beacontree Plaza, +Gillette Way, +Reading, Berkshire +RG2 0BS United Kingdom + +France +CUC Software International Limited +Téléphone: 01-46-01-46-50 +Lundi au Vendredi de 9h à 19h +Fax: 01-46-30-00-65 + +Parc Tertiaire de Meudon +Immeuble "Le Newton" +25 rue Jeanne Braconnier +92366 Meudon La Forêt Cedex +France + +Germany +CUC Software International Limited +Tel: (0) 6103-99-40-40 +Montag bis Freitag von 9 - 19Uhr +Fax: (0) 6103-99-40-35 +Mailbox: (0) 6103-99-40-35 + +Robert-Bosh-Str. 32 +D-63303 Dreieich +Deutschland + +Spain +CUC Software International Limited +Teléfono: (01) 383-2623 +Lunes a Viernes de 9h30 a 14h y de 15h a 18h30 +Fax: (01) 381-2437 + +Avenida de Burgos 9 +1º-OF2 +28036 Madrid +Spain + +Italy Contattare il vostro distribotore. + + + + + +(Please note: If your product does not provide hints on the 900 hint line, then do not include this hint section in your manuals) + +24-Hour Automated Hint Lines + +U.S.A.: +1-900-370-5583 +$.95 per minute (must be 18 years or older, or have parental permission). + +You may also contact Direct Sales to inquire whether a hint book is available for your product. + +You may also write to our hint department for free hints. Please let us know what game you are playing and where you are struck. + +Sierra Online, Attn: Hint Department +P O Box 53210 +Bellevue, WA 98015 + +Canada: +1-900-451-3356 +$1.25 (Canadian) per minute (must be 18 years or older, or have parental permission). You may also contact Direct Sales at 800-757-7707 to inquire whether a hint book is available for your product. + +France: +08-36-68-46-50 +2,23F TTC la minute; tariff en vigueur au 1 Juillet 1996. (France métropolitaine seulement) + +Germany: +019-515-616 +Kosten: 1,20 DM pro Minute (Nur in Deutschland verfügbar) + +Italy: +Contattare il vostro distribotore + +Spain: +Coktel Educative Multimedia +Teléfono: (01) 383-2623 +Lunes a Viernes de 9h30 a 14h y de 15h a 18h30 +Fax: (01) 381-2437 + +Avenida de Burgos 9 +1º-OF2 +28036 Madrid +Spain + +United Kingdom: +New Programs hint line: (0891) 660-660 (within the UK only) + +For adventure programs released after January 1, 1993. Charged 50p/minute at all times. Maximum call length 7.5 minutes. Maximum charge is £3.75. Must have permission of the person who pays the phone bill before calling. Line available in the UK only. Requires a touch tone phone. + + +Sierra Warranty + +You are entitled to use this product for your own use, but may not copy, reproduce, translate, publicly perform, display, or reduce to any electronic medium or machine- readable form, reproductions of the software or manual to other parties in any way, nor sell, rent or lease the product to others without prior written permission of Sierra. You may use one copy of the product on a single computer. YOU MAY NOT NETWORK THE PRODUCT OR OTHERWISE INSTALL IT OR USE IT ON MORE THAN ONE COMPUTER AT THE SAME TIME. + +UNAUTHORIZED REPRESENTATIONS: SIERRA WARRANTS ONLY THAT THE PROGRAM WILL PERFORM AS DESCRIBED IN THE USER DOCUMENTATION. NO OTHER ADVERTISING, DESCRIPTION, OR REPRESENTATION, WHETHER MADE BY A SIERRA DEALER, DISTRIBUTOR, AGENT, OR EMPLOYEE, SHALL BE BINDING UPON SIERRA OR SHALL CHANGE THE TERMS OF THIS WARRANTY. + +IMPLIED WARRANTIES LIMITED: EXCEPT AS STATED ABOVE, SIERRA MAKES NO WARRANTY, EXPRESS OR IMPLIED, REGARDING THIS PRODUCT. SIERRA DISCLAIMS ANY WARRANTY THAT THE SOFTWARE IS FIT FOR A PARTICULAR PURPOSE, AND ANY IMPLIED WARRANTY OF MERCHANTABILITY SHALL BE LIMITED TO THE NINETY (90) DAY DURATION OF THIS LIMITED EXPRESS WARRANTY AND IS OTHERWISE EXPRESSLY AND SPECIFICALLY DISCLAIMED. SOME STATES DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY LASTS, SO THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + +NO CONSEQUENTIAL DAMAGES: SIERRA SHALL NOT BE LIABLE FOR SPECIAL, INCIDENTAL, CONSEQUENTIAL OR OTHER DAMAGES, EVEN IF SIERRA IS ADVISED OF OR AWARE OF THE POSSIBILITY OF SUCH DAMAGES. THIS MEANS THAT SIERRA SHALL NOT BE RESPONSIBLE OR LIABLE FOR LOST PROFITS OR REVENUES, OR FOR DAMAGES OR COSTS INCURRED AS A RESULT OF LOSS OF TIME, DATA OR USE OF THE SOFTWARE, OR FROM ANY OTHER CAUSE EXCEPT THE ACTUAL COST OF THE PRODUCT. IN NO EVENT SHALL SIERRA'S LIABILITY EXCEED THE PURCHASE PRICE OF THIS PRODUCT. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU. + + +Copyright/Trademarks + +(c) 1997 Sierra On-Line, Inc. (R) and (TM) designate trademarks of, or licensed to Sierra On-Line, Inc. All rights reserved. \ No newline at end of file diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHAAS.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHAAS.CL2 new file mode 100644 index 0000000..e5b6f3a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHAAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHAAT.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHAAT.CL2 new file mode 100644 index 0000000..13fb48a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHAAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHAAW.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHAAW.CL2 new file mode 100644 index 0000000..aa08595 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHAAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHADT.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHADT.CL2 new file mode 100644 index 0000000..6e55fbe Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHADT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHAFM.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHAFM.CL2 new file mode 100644 index 0000000..6ee516e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHAFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHAHT.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHAHT.CL2 new file mode 100644 index 0000000..d0044cd Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHAHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHALM.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHALM.CL2 new file mode 100644 index 0000000..03612b7 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHALM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHAQM.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHAQM.CL2 new file mode 100644 index 0000000..1889612 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHAQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHAST.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHAST.CL2 new file mode 100644 index 0000000..1d5a13c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHAST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHA/MHAWL.CL2 b/src/Windebug/PLRGFX/MONK/MHA/MHAWL.CL2 new file mode 100644 index 0000000..5afd8da Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHA/MHAWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBAS.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBAS.CL2 new file mode 100644 index 0000000..0f4d49e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBAT.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBAT.CL2 new file mode 100644 index 0000000..f88ebf3 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBAW.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBAW.CL2 new file mode 100644 index 0000000..3d52cf1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBDT.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBDT.CL2 new file mode 100644 index 0000000..7114564 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBFM.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBFM.CL2 new file mode 100644 index 0000000..3e5ff94 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBHT.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBHT.CL2 new file mode 100644 index 0000000..6abbfa6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBLM.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBLM.CL2 new file mode 100644 index 0000000..160a0be Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBQM.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBQM.CL2 new file mode 100644 index 0000000..085401a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBST.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBST.CL2 new file mode 100644 index 0000000..c31ba87 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHB/MHBWL.CL2 b/src/Windebug/PLRGFX/MONK/MHB/MHBWL.CL2 new file mode 100644 index 0000000..d3008e6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHB/MHBWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDAS.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDAS.CL2 new file mode 100644 index 0000000..834cfd7 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDAT.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDAT.CL2 new file mode 100644 index 0000000..fc1c8b7 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDAW.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDAW.CL2 new file mode 100644 index 0000000..a0616b2 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDBL.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDBL.CL2 new file mode 100644 index 0000000..73e24cf Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDDT.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDDT.CL2 new file mode 100644 index 0000000..4903223 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDFM.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDFM.CL2 new file mode 100644 index 0000000..5f49c7f Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDLM.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDLM.CL2 new file mode 100644 index 0000000..f8e763c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDQM.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDQM.CL2 new file mode 100644 index 0000000..5ce6e22 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDST.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDST.CL2 new file mode 100644 index 0000000..a8b8b4b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHD/MHDWL.CL2 b/src/Windebug/PLRGFX/MONK/MHD/MHDWL.CL2 new file mode 100644 index 0000000..ccf8d06 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHD/MHDWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHAS.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHAS.CL2 new file mode 100644 index 0000000..2444dbc Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHAT.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHAT.CL2 new file mode 100644 index 0000000..b6a3221 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHAW.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHAW.CL2 new file mode 100644 index 0000000..082fbee Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHDT.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHDT.CL2 new file mode 100644 index 0000000..6701546 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHFM.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHFM.CL2 new file mode 100644 index 0000000..80b62a8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHLM.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHLM.CL2 new file mode 100644 index 0000000..ab403c9 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHQM.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHQM.CL2 new file mode 100644 index 0000000..c20a405 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHST.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHST.CL2 new file mode 100644 index 0000000..af3dcd8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHH/MHHWL.CL2 b/src/Windebug/PLRGFX/MONK/MHH/MHHWL.CL2 new file mode 100644 index 0000000..a93a459 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHH/MHHWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMAS.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMAS.CL2 new file mode 100644 index 0000000..cdd4537 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMAT.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMAT.CL2 new file mode 100644 index 0000000..0089f48 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMAW.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMAW.CL2 new file mode 100644 index 0000000..5f621e7 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMBL.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMBL.CL2 new file mode 100644 index 0000000..cd54cbe Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMDT.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMDT.CL2 new file mode 100644 index 0000000..17c022f Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMFM.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMFM.CL2 new file mode 100644 index 0000000..1fd21b5 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMHT.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMHT.CL2 new file mode 100644 index 0000000..06a284e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMLM.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMLM.CL2 new file mode 100644 index 0000000..36e166a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMQM.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMQM.CL2 new file mode 100644 index 0000000..a0edccf Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMST.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMST.CL2 new file mode 100644 index 0000000..f85aab6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHM/MHMWL.CL2 b/src/Windebug/PLRGFX/MONK/MHM/MHMWL.CL2 new file mode 100644 index 0000000..61a102f Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHM/MHMWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNAS.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNAS.CL2 new file mode 100644 index 0000000..bb516ee Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNAT.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNAT.CL2 new file mode 100644 index 0000000..156b34e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNAW.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNAW.CL2 new file mode 100644 index 0000000..4d292e8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNBL.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNBL.CL2 new file mode 100644 index 0000000..ca15171 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNDT.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNDT.CL2 new file mode 100644 index 0000000..f63458a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNFM.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNFM.CL2 new file mode 100644 index 0000000..f764036 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNHT.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNHT.CL2 new file mode 100644 index 0000000..81d55ea Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNLM.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNLM.CL2 new file mode 100644 index 0000000..5d0de6e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNQM.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNQM.CL2 new file mode 100644 index 0000000..2cd9078 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNST.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNST.CL2 new file mode 100644 index 0000000..3e711b7 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHN/MHNWL.CL2 b/src/Windebug/PLRGFX/MONK/MHN/MHNWL.CL2 new file mode 100644 index 0000000..df47f15 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHN/MHNWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSAS.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSAS.CL2 new file mode 100644 index 0000000..90abec0 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSAT.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSAT.CL2 new file mode 100644 index 0000000..649d919 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSAW.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSAW.CL2 new file mode 100644 index 0000000..00fb28f Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSBL.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSBL.CL2 new file mode 100644 index 0000000..97c1783 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSDT.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSDT.CL2 new file mode 100644 index 0000000..c57bbfd Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSFM.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSFM.CL2 new file mode 100644 index 0000000..0a549f1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSHT.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSHT.CL2 new file mode 100644 index 0000000..c3e2b73 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSLM.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSLM.CL2 new file mode 100644 index 0000000..417aea1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSQM.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSQM.CL2 new file mode 100644 index 0000000..893bc06 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSST.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSST.CL2 new file mode 100644 index 0000000..ddfe5dc Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHS/MHSWL.CL2 b/src/Windebug/PLRGFX/MONK/MHS/MHSWL.CL2 new file mode 100644 index 0000000..7e66994 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHS/MHSWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTAS.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTAS.CL2 new file mode 100644 index 0000000..fbd1841 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTAT.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTAT.CL2 new file mode 100644 index 0000000..0ed9074 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTAW.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTAW.CL2 new file mode 100644 index 0000000..974eb23 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTBL.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTBL.CL2 new file mode 100644 index 0000000..991d426 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTDT.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTDT.CL2 new file mode 100644 index 0000000..74de08d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTFM.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTFM.CL2 new file mode 100644 index 0000000..06c7363 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTHT.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTHT.CL2 new file mode 100644 index 0000000..c3cefa5 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTLM.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTLM.CL2 new file mode 100644 index 0000000..2e8d64f Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTQM.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTQM.CL2 new file mode 100644 index 0000000..28b25f7 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTST.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTST.CL2 new file mode 100644 index 0000000..e259302 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHT/MHTWL.CL2 b/src/Windebug/PLRGFX/MONK/MHT/MHTWL.CL2 new file mode 100644 index 0000000..43f93a8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHT/MHTWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUAS.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUAS.CL2 new file mode 100644 index 0000000..0426311 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUAT.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUAT.CL2 new file mode 100644 index 0000000..04fac31 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUAW.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUAW.CL2 new file mode 100644 index 0000000..83cb343 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUBL.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUBL.CL2 new file mode 100644 index 0000000..7122485 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUDT.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUDT.CL2 new file mode 100644 index 0000000..2116669 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUFM.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUFM.CL2 new file mode 100644 index 0000000..d3d6379 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUHT.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUHT.CL2 new file mode 100644 index 0000000..e69b59c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHULM.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHULM.CL2 new file mode 100644 index 0000000..707eb23 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHULM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUQM.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUQM.CL2 new file mode 100644 index 0000000..811902d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUST.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUST.CL2 new file mode 100644 index 0000000..1a255ff Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MHU/MHUWL.CL2 b/src/Windebug/PLRGFX/MONK/MHU/MHUWL.CL2 new file mode 100644 index 0000000..b0804e1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MHU/MHUWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLAAS.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLAAS.CL2 new file mode 100644 index 0000000..5ff5650 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLAAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLAAT.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLAAT.CL2 new file mode 100644 index 0000000..0f8d2eb Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLAAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLAAW.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLAAW.CL2 new file mode 100644 index 0000000..6e84c59 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLAAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLADT.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLADT.CL2 new file mode 100644 index 0000000..dc6d105 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLADT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLAFM.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLAFM.CL2 new file mode 100644 index 0000000..13a4684 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLAFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLAHT.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLAHT.CL2 new file mode 100644 index 0000000..43e2f55 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLAHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLALM.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLALM.CL2 new file mode 100644 index 0000000..0104e8b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLALM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLAQM.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLAQM.CL2 new file mode 100644 index 0000000..b702f96 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLAQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLAST.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLAST.CL2 new file mode 100644 index 0000000..d19a640 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLAST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLA/MLAWL.CL2 b/src/Windebug/PLRGFX/MONK/MLA/MLAWL.CL2 new file mode 100644 index 0000000..7a0d193 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLA/MLAWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBAS.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBAS.CL2 new file mode 100644 index 0000000..ca2bf3c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBAT.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBAT.CL2 new file mode 100644 index 0000000..8048a88 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBAW.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBAW.CL2 new file mode 100644 index 0000000..8d5a1cd Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBDT.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBDT.CL2 new file mode 100644 index 0000000..a0e1e99 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBFM.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBFM.CL2 new file mode 100644 index 0000000..9952c8d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBHT.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBHT.CL2 new file mode 100644 index 0000000..4aec18b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBLM.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBLM.CL2 new file mode 100644 index 0000000..6505d29 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBQM.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBQM.CL2 new file mode 100644 index 0000000..9e7d4eb Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBST.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBST.CL2 new file mode 100644 index 0000000..3b661e8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLB/MLBWL.CL2 b/src/Windebug/PLRGFX/MONK/MLB/MLBWL.CL2 new file mode 100644 index 0000000..a4b1802 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLB/MLBWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDAS.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDAS.CL2 new file mode 100644 index 0000000..33136a8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDAT.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDAT.CL2 new file mode 100644 index 0000000..8adea7f Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDAW.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDAW.CL2 new file mode 100644 index 0000000..cacdacd Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDBL.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDBL.CL2 new file mode 100644 index 0000000..7fa6da5 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDDT.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDDT.CL2 new file mode 100644 index 0000000..4c05c47 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDFM.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDFM.CL2 new file mode 100644 index 0000000..8a593e2 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDHT.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDHT.CL2 new file mode 100644 index 0000000..ed48aa1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDLM.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDLM.CL2 new file mode 100644 index 0000000..0c790f3 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDQM.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDQM.CL2 new file mode 100644 index 0000000..462524d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDST.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDST.CL2 new file mode 100644 index 0000000..d9cd602 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLD/MLDWL.CL2 b/src/Windebug/PLRGFX/MONK/MLD/MLDWL.CL2 new file mode 100644 index 0000000..a32b489 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLD/MLDWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHAS.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHAS.CL2 new file mode 100644 index 0000000..efde859 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHAT.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHAT.CL2 new file mode 100644 index 0000000..5549202 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHAW.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHAW.CL2 new file mode 100644 index 0000000..80fda25 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHBL.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHBL.CL2 new file mode 100644 index 0000000..3e656af Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHDT.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHDT.CL2 new file mode 100644 index 0000000..5081849 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHFM.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHFM.CL2 new file mode 100644 index 0000000..696c489 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHHT.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHHT.CL2 new file mode 100644 index 0000000..dd111f8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHLM.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHLM.CL2 new file mode 100644 index 0000000..4152860 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHQM.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHQM.CL2 new file mode 100644 index 0000000..be96936 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHST.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHST.CL2 new file mode 100644 index 0000000..ece860c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLH/MLHWL.CL2 b/src/Windebug/PLRGFX/MONK/MLH/MLHWL.CL2 new file mode 100644 index 0000000..ffe2037 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLH/MLHWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMAS.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMAS.CL2 new file mode 100644 index 0000000..9b1dca6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMAT.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMAT.CL2 new file mode 100644 index 0000000..6ebd6a3 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMAW.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMAW.CL2 new file mode 100644 index 0000000..8f9259b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMBL.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMBL.CL2 new file mode 100644 index 0000000..56ba7f6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMDT.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMDT.CL2 new file mode 100644 index 0000000..f3bfa97 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMFM.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMFM.CL2 new file mode 100644 index 0000000..c11b1b0 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMHT.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMHT.CL2 new file mode 100644 index 0000000..280c7ae Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMLM.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMLM.CL2 new file mode 100644 index 0000000..e85d518 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMQM.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMQM.CL2 new file mode 100644 index 0000000..69535e6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMST.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMST.CL2 new file mode 100644 index 0000000..24f28e2 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLM/MLMWL.CL2 b/src/Windebug/PLRGFX/MONK/MLM/MLMWL.CL2 new file mode 100644 index 0000000..7562f3d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLM/MLMWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNAS.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNAS.CL2 new file mode 100644 index 0000000..37a4304 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNAT.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNAT.CL2 new file mode 100644 index 0000000..2ae0f70 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNAW.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNAW.CL2 new file mode 100644 index 0000000..5d6c760 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNBL.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNBL.CL2 new file mode 100644 index 0000000..a53d860 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNDT.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNDT.CL2 new file mode 100644 index 0000000..a4d973b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNFM.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNFM.CL2 new file mode 100644 index 0000000..8b01c38 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNHT.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNHT.CL2 new file mode 100644 index 0000000..68a572b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNLM.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNLM.CL2 new file mode 100644 index 0000000..644d712 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNQM.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNQM.CL2 new file mode 100644 index 0000000..efe4da1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNST.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNST.CL2 new file mode 100644 index 0000000..2ccdb1a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLN/MLNWL.CL2 b/src/Windebug/PLRGFX/MONK/MLN/MLNWL.CL2 new file mode 100644 index 0000000..3dd01ec Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLN/MLNWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSAS.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSAS.CL2 new file mode 100644 index 0000000..d4541a4 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSAT.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSAT.CL2 new file mode 100644 index 0000000..cd9116a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSAW.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSAW.CL2 new file mode 100644 index 0000000..0969ba1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSBL.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSBL.CL2 new file mode 100644 index 0000000..8bdb08d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSDT.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSDT.CL2 new file mode 100644 index 0000000..a5fafa6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSFM.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSFM.CL2 new file mode 100644 index 0000000..05ba173 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSHT.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSHT.CL2 new file mode 100644 index 0000000..ab4b522 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSLM.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSLM.CL2 new file mode 100644 index 0000000..fbc5c24 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSQM.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSQM.CL2 new file mode 100644 index 0000000..3150cb3 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSST.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSST.CL2 new file mode 100644 index 0000000..44c4d62 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLS/MLSWL.CL2 b/src/Windebug/PLRGFX/MONK/MLS/MLSWL.CL2 new file mode 100644 index 0000000..a1a6e21 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLS/MLSWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTAS.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTAS.CL2 new file mode 100644 index 0000000..c47802b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTAT.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTAT.CL2 new file mode 100644 index 0000000..8b930d7 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTAW.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTAW.CL2 new file mode 100644 index 0000000..e6ee5d4 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTBL.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTBL.CL2 new file mode 100644 index 0000000..80af36a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTDT.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTDT.CL2 new file mode 100644 index 0000000..41f5b9c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTFM.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTFM.CL2 new file mode 100644 index 0000000..be87c2b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTHT.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTHT.CL2 new file mode 100644 index 0000000..f184462 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTLM.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTLM.CL2 new file mode 100644 index 0000000..6b3788b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTQM.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTQM.CL2 new file mode 100644 index 0000000..2a91075 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTST.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTST.CL2 new file mode 100644 index 0000000..b488547 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLT/MLTWL.CL2 b/src/Windebug/PLRGFX/MONK/MLT/MLTWL.CL2 new file mode 100644 index 0000000..ba90770 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLT/MLTWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUAS.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUAS.CL2 new file mode 100644 index 0000000..6f640cc Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUAT.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUAT.CL2 new file mode 100644 index 0000000..2b00696 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUAW.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUAW.CL2 new file mode 100644 index 0000000..2cee40d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUBL.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUBL.CL2 new file mode 100644 index 0000000..d69b26c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUDT.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUDT.CL2 new file mode 100644 index 0000000..8657434 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUFM.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUFM.CL2 new file mode 100644 index 0000000..0bbbfa4 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUHT.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUHT.CL2 new file mode 100644 index 0000000..a49d704 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLULM.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLULM.CL2 new file mode 100644 index 0000000..6bd9f1a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLULM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUQM.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUQM.CL2 new file mode 100644 index 0000000..c3c6681 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUST.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUST.CL2 new file mode 100644 index 0000000..40eb92d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MLU/MLUWL.CL2 b/src/Windebug/PLRGFX/MONK/MLU/MLUWL.CL2 new file mode 100644 index 0000000..620776a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MLU/MLUWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMAAS.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMAAS.CL2 new file mode 100644 index 0000000..6eb01f2 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMAAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMAAT.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMAAT.CL2 new file mode 100644 index 0000000..b9e7f62 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMAAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMAAW.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMAAW.CL2 new file mode 100644 index 0000000..b86e972 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMAAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMADT.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMADT.CL2 new file mode 100644 index 0000000..991c6d7 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMADT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMAFM.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMAFM.CL2 new file mode 100644 index 0000000..8cf4b8d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMAFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMAHT.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMAHT.CL2 new file mode 100644 index 0000000..d29093c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMAHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMALM.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMALM.CL2 new file mode 100644 index 0000000..19e5b44 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMALM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMAQM.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMAQM.CL2 new file mode 100644 index 0000000..6406ecc Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMAQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMAST.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMAST.CL2 new file mode 100644 index 0000000..b1ca7dd Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMAST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMA/MMAWL.CL2 b/src/Windebug/PLRGFX/MONK/MMA/MMAWL.CL2 new file mode 100644 index 0000000..235bde6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMA/MMAWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBAS.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBAS.CL2 new file mode 100644 index 0000000..7814247 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBAT.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBAT.CL2 new file mode 100644 index 0000000..e42fc83 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBAW.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBAW.CL2 new file mode 100644 index 0000000..c54c3fd Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBDT.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBDT.CL2 new file mode 100644 index 0000000..e301aa8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBFM.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBFM.CL2 new file mode 100644 index 0000000..7e56e28 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBHT.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBHT.CL2 new file mode 100644 index 0000000..00fed3b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBLM.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBLM.CL2 new file mode 100644 index 0000000..84c6c56 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBQM.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBQM.CL2 new file mode 100644 index 0000000..2f3fc07 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBST.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBST.CL2 new file mode 100644 index 0000000..583c8df Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMB/MMBWL.CL2 b/src/Windebug/PLRGFX/MONK/MMB/MMBWL.CL2 new file mode 100644 index 0000000..eda35f3 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMB/MMBWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDAS.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDAS.CL2 new file mode 100644 index 0000000..6e235fc Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDAT.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDAT.CL2 new file mode 100644 index 0000000..b1e8572 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDAW.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDAW.CL2 new file mode 100644 index 0000000..8d86e6b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDBL.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDBL.CL2 new file mode 100644 index 0000000..9b03295 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDDT.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDDT.CL2 new file mode 100644 index 0000000..2940a37 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDFM.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDFM.CL2 new file mode 100644 index 0000000..f7b3785 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDHT.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDHT.CL2 new file mode 100644 index 0000000..1a94aa9 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDLM.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDLM.CL2 new file mode 100644 index 0000000..5e18a2d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDQM.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDQM.CL2 new file mode 100644 index 0000000..1e90815 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDST.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDST.CL2 new file mode 100644 index 0000000..2d721cb Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMD/MMDWL.CL2 b/src/Windebug/PLRGFX/MONK/MMD/MMDWL.CL2 new file mode 100644 index 0000000..76d6a9d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMD/MMDWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHAS.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHAS.CL2 new file mode 100644 index 0000000..bc65005 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHAT.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHAT.CL2 new file mode 100644 index 0000000..7e4e569 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHAW.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHAW.CL2 new file mode 100644 index 0000000..f352704 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHBL.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHBL.CL2 new file mode 100644 index 0000000..384e334 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHDT.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHDT.CL2 new file mode 100644 index 0000000..682e658 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHFM.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHFM.CL2 new file mode 100644 index 0000000..0d9ad6e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHHT.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHHT.CL2 new file mode 100644 index 0000000..149ac2b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHLM.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHLM.CL2 new file mode 100644 index 0000000..2589b83 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHQM.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHQM.CL2 new file mode 100644 index 0000000..c3cb8d3 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHST.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHST.CL2 new file mode 100644 index 0000000..e5f3d0c Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMH/MMHWL.CL2 b/src/Windebug/PLRGFX/MONK/MMH/MMHWL.CL2 new file mode 100644 index 0000000..d3642bf Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMH/MMHWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMAS.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMAS.CL2 new file mode 100644 index 0000000..a76b531 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMAT.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMAT.CL2 new file mode 100644 index 0000000..7e72d57 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMAW.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMAW.CL2 new file mode 100644 index 0000000..83cb9ca Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMBL.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMBL.CL2 new file mode 100644 index 0000000..46e4cca Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMDT.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMDT.CL2 new file mode 100644 index 0000000..e555ced Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMFM.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMFM.CL2 new file mode 100644 index 0000000..8d6ed15 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMHT.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMHT.CL2 new file mode 100644 index 0000000..b6ed0e1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMLM.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMLM.CL2 new file mode 100644 index 0000000..59612a5 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMQM.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMQM.CL2 new file mode 100644 index 0000000..c656554 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMST.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMST.CL2 new file mode 100644 index 0000000..9f26638 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMM/MMMWL.CL2 b/src/Windebug/PLRGFX/MONK/MMM/MMMWL.CL2 new file mode 100644 index 0000000..45e1997 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMM/MMMWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNAS.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNAS.CL2 new file mode 100644 index 0000000..954a6d4 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNAT.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNAT.CL2 new file mode 100644 index 0000000..bd09a9e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNAW.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNAW.CL2 new file mode 100644 index 0000000..ef88d66 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNBL.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNBL.CL2 new file mode 100644 index 0000000..d704871 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNDT.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNDT.CL2 new file mode 100644 index 0000000..ccbd836 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNFM.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNFM.CL2 new file mode 100644 index 0000000..ad9d5c1 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNHT.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNHT.CL2 new file mode 100644 index 0000000..9c36ef9 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNLM.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNLM.CL2 new file mode 100644 index 0000000..b93b2b9 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNQM.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNQM.CL2 new file mode 100644 index 0000000..900b6c0 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNST.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNST.CL2 new file mode 100644 index 0000000..f00c12e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMN/MMNWL.CL2 b/src/Windebug/PLRGFX/MONK/MMN/MMNWL.CL2 new file mode 100644 index 0000000..14de590 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMN/MMNWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSAS.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSAS.CL2 new file mode 100644 index 0000000..f3c8fc3 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSAT.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSAT.CL2 new file mode 100644 index 0000000..569882f Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSAW.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSAW.CL2 new file mode 100644 index 0000000..fa29a66 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSBL.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSBL.CL2 new file mode 100644 index 0000000..1c593eb Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSDT.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSDT.CL2 new file mode 100644 index 0000000..1143044 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSFM.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSFM.CL2 new file mode 100644 index 0000000..c890481 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSHT.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSHT.CL2 new file mode 100644 index 0000000..3a95384 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSLM.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSLM.CL2 new file mode 100644 index 0000000..58f4ca6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSQM.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSQM.CL2 new file mode 100644 index 0000000..436463e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSST.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSST.CL2 new file mode 100644 index 0000000..55704f5 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMS/MMSWL.CL2 b/src/Windebug/PLRGFX/MONK/MMS/MMSWL.CL2 new file mode 100644 index 0000000..1534832 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMS/MMSWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTAS.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTAS.CL2 new file mode 100644 index 0000000..2427862 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTAT.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTAT.CL2 new file mode 100644 index 0000000..934e29b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTAW.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTAW.CL2 new file mode 100644 index 0000000..f5a34f6 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTBL.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTBL.CL2 new file mode 100644 index 0000000..9363aa9 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTDT.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTDT.CL2 new file mode 100644 index 0000000..3b6e6db Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTFM.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTFM.CL2 new file mode 100644 index 0000000..130a9fa Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTHT.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTHT.CL2 new file mode 100644 index 0000000..6f79b29 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTLM.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTLM.CL2 new file mode 100644 index 0000000..742302a Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTLM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTQM.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTQM.CL2 new file mode 100644 index 0000000..1e27f2d Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTST.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTST.CL2 new file mode 100644 index 0000000..ff5e671 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMT/MMTWL.CL2 b/src/Windebug/PLRGFX/MONK/MMT/MMTWL.CL2 new file mode 100644 index 0000000..fcf3253 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMT/MMTWL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUAS.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUAS.CL2 new file mode 100644 index 0000000..4726d8e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUAS.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUAT.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUAT.CL2 new file mode 100644 index 0000000..aa5a01e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUAT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUAW.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUAW.CL2 new file mode 100644 index 0000000..212a4bb Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUAW.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUBL.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUBL.CL2 new file mode 100644 index 0000000..6f83474 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUBL.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUDT.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUDT.CL2 new file mode 100644 index 0000000..1f263d8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUDT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUFM.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUFM.CL2 new file mode 100644 index 0000000..7b4d02e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUFM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUHT.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUHT.CL2 new file mode 100644 index 0000000..158ded8 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUHT.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMULM.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMULM.CL2 new file mode 100644 index 0000000..1d5576e Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMULM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUQM.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUQM.CL2 new file mode 100644 index 0000000..0abc74b Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUQM.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUST.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUST.CL2 new file mode 100644 index 0000000..97fea77 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUST.CL2 differ diff --git a/src/Windebug/PLRGFX/MONK/MMU/MMUWL.CL2 b/src/Windebug/PLRGFX/MONK/MMU/MMUWL.CL2 new file mode 100644 index 0000000..7694d18 Binary files /dev/null and b/src/Windebug/PLRGFX/MONK/MMU/MMUWL.CL2 differ diff --git a/src/Windebug/RESPON~1.TXT b/src/Windebug/RESPON~1.TXT new file mode 100644 index 0000000..aaff365 --- /dev/null +++ b/src/Windebug/RESPON~1.TXT @@ -0,0 +1,26 @@ +"D:\diablo97\WinDebug\Hellfire.exe" +/countsMask 83 +/profileDir "D:\diablo97\WinDebug" +/timeStampCounter +/additionalArgruments "" +/retainProfiles 15 +/tracePoint pause before "hellfire.exe|DIABLO.OBJ|WinMain" +/tracePoint resume before "hellfire.exe|MISSILES.OBJ|AddShowMagicItems" +/atomToolData + "D:\diablo97\WinDebug" # project dir + "D:\diablo97\WinDebug\Hellfire_hiprof.exe" # run application name + "" # run arguments + "D:\diablo97\WinDebug" # run working directory + 12 # number of DLLs + "d:\diablo97\windebug\hellfire.exe" 1 1498624 -148881920 29159769 1 + "c:\windows\system\kernel32.dll" 0 411136 -1103719424 28987318 0 + "c:\windows\system\user32.dll" 0 44544 -1103719424 28987318 0 + "c:\windows\system\gdi32.dll" 0 131072 -1103719424 28987318 0 + "c:\windows\system\advapi32.dll" 0 43008 1540953856 29080264 0 + "c:\windows\system\shell32.dll" 0 817664 1739412480 29022120 0 + "c:\windows\system\comctl32.dll" 0 379152 1540953856 29080264 0 + "c:\windows\system\version.dll" 0 6656 -1103719424 28987318 0 + "d:\diablo97\windebug\hellfrui.dll" 1 199168 -1279813376 29086355 1 + "d:\diablo97\windebug\stormd.dll" 1 318464 635496704 29159751 1 + "c:\windows\system\comdlg32.dll" 0 92672 1739412480 29022120 0 + "c:\windows\system\msvcrtd.dll" 0 376320 -1752288000 29121749 0 diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT1.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT1.WAV new file mode 100644 index 0000000..d01e0bd Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT10.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT10.WAV new file mode 100644 index 0000000..3e0b1c0 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT10.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT11.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT11.WAV new file mode 100644 index 0000000..e768c78 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT11.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT12.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT12.WAV new file mode 100644 index 0000000..2c9dcc9 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT12.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT2.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT2.WAV new file mode 100644 index 0000000..8b2277e Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT2.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT3.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT3.WAV new file mode 100644 index 0000000..57a6055 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT3.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT4.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT4.WAV new file mode 100644 index 0000000..4b38cc8 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT4A.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT4A.WAV new file mode 100644 index 0000000..0841b23 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT4A.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT5.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT5.WAV new file mode 100644 index 0000000..27d22ec Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT5.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT6.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT6.WAV new file mode 100644 index 0000000..9f503f1 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT6.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT7.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT7.WAV new file mode 100644 index 0000000..1e41df4 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT7.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT8.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT8.WAV new file mode 100644 index 0000000..c46f7e8 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT8.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/COWSUT9.WAV b/src/Windebug/SFX/HELLFIRE/COWSUT9.WAV new file mode 100644 index 0000000..12b45f3 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/COWSUT9.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/CRNRSTON.WAV b/src/Windebug/SFX/HELLFIRE/CRNRSTON.WAV new file mode 100644 index 0000000..86b2250 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/CRNRSTON.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/DEFILER1.WAV b/src/Windebug/SFX/HELLFIRE/DEFILER1.WAV new file mode 100644 index 0000000..b6338d7 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/DEFILER1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/DEFILER2.WAV b/src/Windebug/SFX/HELLFIRE/DEFILER2.WAV new file mode 100644 index 0000000..276eaf3 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/DEFILER2.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/DEFILER3.WAV b/src/Windebug/SFX/HELLFIRE/DEFILER3.WAV new file mode 100644 index 0000000..5c6b2a4 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/DEFILER3.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/DEFILER4.WAV b/src/Windebug/SFX/HELLFIRE/DEFILER4.WAV new file mode 100644 index 0000000..c6a309a Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/DEFILER4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/DEFILER5.WAV b/src/Windebug/SFX/HELLFIRE/DEFILER5.WAV new file mode 100644 index 0000000..c16d7c5 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/DEFILER5.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/DEFILER6.WAV b/src/Windebug/SFX/HELLFIRE/DEFILER6.WAV new file mode 100644 index 0000000..426effc Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/DEFILER6.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/DEFILER7.WAV b/src/Windebug/SFX/HELLFIRE/DEFILER7.WAV new file mode 100644 index 0000000..cf0a5c5 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/DEFILER7.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/DEFILER8.WAV b/src/Windebug/SFX/HELLFIRE/DEFILER8.WAV new file mode 100644 index 0000000..ddfed75 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/DEFILER8.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER1.WAV b/src/Windebug/SFX/HELLFIRE/FARMER1.WAV new file mode 100644 index 0000000..c448276 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER10.WAV b/src/Windebug/SFX/HELLFIRE/FARMER10.WAV new file mode 100644 index 0000000..351a828 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER10.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER11.WAV b/src/Windebug/SFX/HELLFIRE/FARMER11.WAV new file mode 100644 index 0000000..1995dcb Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER11.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER12.WAV b/src/Windebug/SFX/HELLFIRE/FARMER12.WAV new file mode 100644 index 0000000..ab6023b Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER12.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER13.WAV b/src/Windebug/SFX/HELLFIRE/FARMER13.WAV new file mode 100644 index 0000000..83ffddc Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER13.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER14.WAV b/src/Windebug/SFX/HELLFIRE/FARMER14.WAV new file mode 100644 index 0000000..459323f Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER14.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER15.WAV b/src/Windebug/SFX/HELLFIRE/FARMER15.WAV new file mode 100644 index 0000000..b658cb8 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER15.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER16.WAV b/src/Windebug/SFX/HELLFIRE/FARMER16.WAV new file mode 100644 index 0000000..73e2543 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER16.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER17.WAV b/src/Windebug/SFX/HELLFIRE/FARMER17.WAV new file mode 100644 index 0000000..0ee8a0b Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER17.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER2.WAV b/src/Windebug/SFX/HELLFIRE/FARMER2.WAV new file mode 100644 index 0000000..effa5f8 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER2.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER2A.WAV b/src/Windebug/SFX/HELLFIRE/FARMER2A.WAV new file mode 100644 index 0000000..b37f7e8 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER2A.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER3.WAV b/src/Windebug/SFX/HELLFIRE/FARMER3.WAV new file mode 100644 index 0000000..832d449 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER3.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER4.WAV b/src/Windebug/SFX/HELLFIRE/FARMER4.WAV new file mode 100644 index 0000000..ddc752a Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER5.WAV b/src/Windebug/SFX/HELLFIRE/FARMER5.WAV new file mode 100644 index 0000000..f0ac8fe Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER5.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER6.WAV b/src/Windebug/SFX/HELLFIRE/FARMER6.WAV new file mode 100644 index 0000000..a9a1bf1 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER6.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER7.WAV b/src/Windebug/SFX/HELLFIRE/FARMER7.WAV new file mode 100644 index 0000000..ce580ad Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER7.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER8.WAV b/src/Windebug/SFX/HELLFIRE/FARMER8.WAV new file mode 100644 index 0000000..15c11fb Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER8.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/FARMER9.WAV b/src/Windebug/SFX/HELLFIRE/FARMER9.WAV new file mode 100644 index 0000000..e002bc9 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/FARMER9.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NAKRUL1.WAV b/src/Windebug/SFX/HELLFIRE/NAKRUL1.WAV new file mode 100644 index 0000000..ad149e9 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NAKRUL1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NAKRUL2.WAV b/src/Windebug/SFX/HELLFIRE/NAKRUL2.WAV new file mode 100644 index 0000000..d951f65 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NAKRUL2.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NAKRUL3.WAV b/src/Windebug/SFX/HELLFIRE/NAKRUL3.WAV new file mode 100644 index 0000000..ef72f40 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NAKRUL3.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NAKRUL4.WAV b/src/Windebug/SFX/HELLFIRE/NAKRUL4.WAV new file mode 100644 index 0000000..86e5dd9 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NAKRUL4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NAKRUL5.WAV b/src/Windebug/SFX/HELLFIRE/NAKRUL5.WAV new file mode 100644 index 0000000..080d095 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NAKRUL5.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NAKRUL6.WAV b/src/Windebug/SFX/HELLFIRE/NAKRUL6.WAV new file mode 100644 index 0000000..c1a44d1 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NAKRUL6.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR1.WAV b/src/Windebug/SFX/HELLFIRE/NARATR1.WAV new file mode 100644 index 0000000..0badb85 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR2.WAV b/src/Windebug/SFX/HELLFIRE/NARATR2.WAV new file mode 100644 index 0000000..2d57e89 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR2.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR3.WAV b/src/Windebug/SFX/HELLFIRE/NARATR3.WAV new file mode 100644 index 0000000..6cd1d6a Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR3.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR4.WAV b/src/Windebug/SFX/HELLFIRE/NARATR4.WAV new file mode 100644 index 0000000..ba5bf2f Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR5.WAV b/src/Windebug/SFX/HELLFIRE/NARATR5.WAV new file mode 100644 index 0000000..91ac5f7 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR5.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR6.WAV b/src/Windebug/SFX/HELLFIRE/NARATR6.WAV new file mode 100644 index 0000000..97f8cc6 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR6.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR7.WAV b/src/Windebug/SFX/HELLFIRE/NARATR7.WAV new file mode 100644 index 0000000..10ff63d Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR7.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR8.WAV b/src/Windebug/SFX/HELLFIRE/NARATR8.WAV new file mode 100644 index 0000000..2ec6c04 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR8.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/NARATR9.WAV b/src/Windebug/SFX/HELLFIRE/NARATR9.WAV new file mode 100644 index 0000000..93a4338 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/NARATR9.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/SKLJRN1.WAV b/src/Windebug/SFX/HELLFIRE/SKLJRN1.WAV new file mode 100644 index 0000000..779e73f Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/SKLJRN1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/SKLJRN2.WAV b/src/Windebug/SFX/HELLFIRE/SKLJRN2.WAV new file mode 100644 index 0000000..bbe40f7 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/SKLJRN2.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/SKLJRN3.WAV b/src/Windebug/SFX/HELLFIRE/SKLJRN3.WAV new file mode 100644 index 0000000..704be18 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/SKLJRN3.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/SKLJRN4.WAV b/src/Windebug/SFX/HELLFIRE/SKLJRN4.WAV new file mode 100644 index 0000000..62d97c1 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/SKLJRN4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/SKLJRN5.WAV b/src/Windebug/SFX/HELLFIRE/SKLJRN5.WAV new file mode 100644 index 0000000..b424e61 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/SKLJRN5.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/SKLJRN6.WAV b/src/Windebug/SFX/HELLFIRE/SKLJRN6.WAV new file mode 100644 index 0000000..83878ce Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/SKLJRN6.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/SKLJRN7.WAV b/src/Windebug/SFX/HELLFIRE/SKLJRN7.WAV new file mode 100644 index 0000000..a88f459 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/SKLJRN7.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TEDDYBR1.WAV b/src/Windebug/SFX/HELLFIRE/TEDDYBR1.WAV new file mode 100644 index 0000000..31f31c4 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TEDDYBR1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TEDDYBR2.WAV b/src/Windebug/SFX/HELLFIRE/TEDDYBR2.WAV new file mode 100644 index 0000000..c2e283c Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TEDDYBR2.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TEDDYBR3.WAV b/src/Windebug/SFX/HELLFIRE/TEDDYBR3.WAV new file mode 100644 index 0000000..e215d0a Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TEDDYBR3.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TEDDYBR4.WAV b/src/Windebug/SFX/HELLFIRE/TEDDYBR4.WAV new file mode 100644 index 0000000..222cf1e Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TEDDYBR4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG1.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG1.WAV new file mode 100644 index 0000000..7c595ec Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG2A.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG2A.WAV new file mode 100644 index 0000000..c8b17a2 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG2A.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG2B.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG2B.WAV new file mode 100644 index 0000000..68e1bc0 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG2B.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG2C.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG2C.WAV new file mode 100644 index 0000000..23a6e25 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG2C.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG2D.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG2D.WAV new file mode 100644 index 0000000..958722b Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG2D.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG3A.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG3A.WAV new file mode 100644 index 0000000..4e67823 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG3A.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG3B.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG3B.WAV new file mode 100644 index 0000000..75ab533 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG3B.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG3C.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG3C.WAV new file mode 100644 index 0000000..2ebfd7b Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG3C.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG3D.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG3D.WAV new file mode 100644 index 0000000..9910b64 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG3D.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG3E.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG3E.WAV new file mode 100644 index 0000000..0824e36 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG3E.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG4.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG4.WAV new file mode 100644 index 0000000..02f3e66 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSNG5.WAV b/src/Windebug/SFX/HELLFIRE/TRDSNG5.WAV new file mode 100644 index 0000000..9bb9fe3 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSNG5.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK1.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK1.WAV new file mode 100644 index 0000000..6e38142 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK1.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK2A.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK2A.WAV new file mode 100644 index 0000000..f0785c1 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK2A.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK2B.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK2B.WAV new file mode 100644 index 0000000..5d2e159 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK2B.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK2C.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK2C.WAV new file mode 100644 index 0000000..d947d55 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK2C.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK2D.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK2D.WAV new file mode 100644 index 0000000..b2e8686 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK2D.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK3A.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK3A.WAV new file mode 100644 index 0000000..c706328 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK3A.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK3B.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK3B.WAV new file mode 100644 index 0000000..d61744f Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK3B.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK3C.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK3C.WAV new file mode 100644 index 0000000..4963608 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK3C.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK3D.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK3D.WAV new file mode 100644 index 0000000..e8beaf2 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK3D.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK3E.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK3E.WAV new file mode 100644 index 0000000..ad737e2 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK3E.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK4.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK4.WAV new file mode 100644 index 0000000..f88d27b Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK4.WAV differ diff --git a/src/Windebug/SFX/HELLFIRE/TRDSPK5.WAV b/src/Windebug/SFX/HELLFIRE/TRDSPK5.WAV new file mode 100644 index 0000000..10f1de2 Binary files /dev/null and b/src/Windebug/SFX/HELLFIRE/TRDSPK5.WAV differ diff --git a/src/Windebug/SFX/ITEMS/CRCLOS.WAV b/src/Windebug/SFX/ITEMS/CRCLOS.WAV new file mode 100644 index 0000000..57c24c3 Binary files /dev/null and b/src/Windebug/SFX/ITEMS/CRCLOS.WAV differ diff --git a/src/Windebug/SFX/ITEMS/CROPEN.WAV b/src/Windebug/SFX/ITEMS/CROPEN.WAV new file mode 100644 index 0000000..f82e4d7 Binary files /dev/null and b/src/Windebug/SFX/ITEMS/CROPEN.WAV differ diff --git a/src/Windebug/SFX/ITEMS/PODPOP5.WAV b/src/Windebug/SFX/ITEMS/PODPOP5.WAV new file mode 100644 index 0000000..3498442 Binary files /dev/null and b/src/Windebug/SFX/ITEMS/PODPOP5.WAV differ diff --git a/src/Windebug/SFX/ITEMS/PODPOP8.WAV b/src/Windebug/SFX/ITEMS/PODPOP8.WAV new file mode 100644 index 0000000..f99f5e7 Binary files /dev/null and b/src/Windebug/SFX/ITEMS/PODPOP8.WAV differ diff --git a/src/Windebug/SFX/ITEMS/URNPOP2.WAV b/src/Windebug/SFX/ITEMS/URNPOP2.WAV new file mode 100644 index 0000000..debca63 Binary files /dev/null and b/src/Windebug/SFX/ITEMS/URNPOP2.WAV differ diff --git a/src/Windebug/SFX/ITEMS/URNPOP3.WAV b/src/Windebug/SFX/ITEMS/URNPOP3.WAV new file mode 100644 index 0000000..043454c Binary files /dev/null and b/src/Windebug/SFX/ITEMS/URNPOP3.WAV differ diff --git a/src/Windebug/SFX/MISC/FBALLBOW.WAV b/src/Windebug/SFX/MISC/FBALLBOW.WAV new file mode 100644 index 0000000..bc88cc8 Binary files /dev/null and b/src/Windebug/SFX/MISC/FBALLBOW.WAV differ diff --git a/src/Windebug/SFX/MISC/NESTXPLD.WAV b/src/Windebug/SFX/MISC/NESTXPLD.WAV new file mode 100644 index 0000000..4b363b0 Binary files /dev/null and b/src/Windebug/SFX/MISC/NESTXPLD.WAV differ diff --git a/src/Windebug/SFX/MISC/NEWBFIRE.WAV b/src/Windebug/SFX/MISC/NEWBFIRE.WAV new file mode 100644 index 0000000..828012e Binary files /dev/null and b/src/Windebug/SFX/MISC/NEWBFIRE.WAV differ diff --git a/src/Windebug/SFX/MISC/STING1.WAV b/src/Windebug/SFX/MISC/STING1.WAV new file mode 100644 index 0000000..a0eb6be Binary files /dev/null and b/src/Windebug/SFX/MISC/STING1.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK01.WAV b/src/Windebug/SFX/MONK/MONK01.WAV new file mode 100644 index 0000000..0c51cda Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK01.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK08.WAV b/src/Windebug/SFX/MONK/MONK08.WAV new file mode 100644 index 0000000..021b14c Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK08.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK09.WAV b/src/Windebug/SFX/MONK/MONK09.WAV new file mode 100644 index 0000000..f61ff95 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK09.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK10.WAV b/src/Windebug/SFX/MONK/MONK10.WAV new file mode 100644 index 0000000..6b8fd93 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK10.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK11.WAV b/src/Windebug/SFX/MONK/MONK11.WAV new file mode 100644 index 0000000..b0229ab Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK11.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK12.WAV b/src/Windebug/SFX/MONK/MONK12.WAV new file mode 100644 index 0000000..d44959f Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK12.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK13.WAV b/src/Windebug/SFX/MONK/MONK13.WAV new file mode 100644 index 0000000..8a585ef Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK13.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK14.WAV b/src/Windebug/SFX/MONK/MONK14.WAV new file mode 100644 index 0000000..68c6cba Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK14.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK15.WAV b/src/Windebug/SFX/MONK/MONK15.WAV new file mode 100644 index 0000000..704d6fd Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK15.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK16.WAV b/src/Windebug/SFX/MONK/MONK16.WAV new file mode 100644 index 0000000..4fb1a01 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK16.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK24.WAV b/src/Windebug/SFX/MONK/MONK24.WAV new file mode 100644 index 0000000..189935e Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK24.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK27.WAV b/src/Windebug/SFX/MONK/MONK27.WAV new file mode 100644 index 0000000..84d05f7 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK27.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK29.WAV b/src/Windebug/SFX/MONK/MONK29.WAV new file mode 100644 index 0000000..6d33e71 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK29.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK34.WAV b/src/Windebug/SFX/MONK/MONK34.WAV new file mode 100644 index 0000000..e036343 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK34.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK35.WAV b/src/Windebug/SFX/MONK/MONK35.WAV new file mode 100644 index 0000000..74b5d79 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK35.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK43.WAV b/src/Windebug/SFX/MONK/MONK43.WAV new file mode 100644 index 0000000..a7202b1 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK43.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK46.WAV b/src/Windebug/SFX/MONK/MONK46.WAV new file mode 100644 index 0000000..94bce9e Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK46.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK49.WAV b/src/Windebug/SFX/MONK/MONK49.WAV new file mode 100644 index 0000000..32b1317 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK49.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK50.WAV b/src/Windebug/SFX/MONK/MONK50.WAV new file mode 100644 index 0000000..0693227 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK50.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK52.WAV b/src/Windebug/SFX/MONK/MONK52.WAV new file mode 100644 index 0000000..5a430ba Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK52.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK54.WAV b/src/Windebug/SFX/MONK/MONK54.WAV new file mode 100644 index 0000000..c97adc9 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK54.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK55.WAV b/src/Windebug/SFX/MONK/MONK55.WAV new file mode 100644 index 0000000..b14e111 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK55.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK56.WAV b/src/Windebug/SFX/MONK/MONK56.WAV new file mode 100644 index 0000000..4e1c7c7 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK56.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK61.WAV b/src/Windebug/SFX/MONK/MONK61.WAV new file mode 100644 index 0000000..368f6bd Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK61.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK62.WAV b/src/Windebug/SFX/MONK/MONK62.WAV new file mode 100644 index 0000000..8bcb578 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK62.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK68.WAV b/src/Windebug/SFX/MONK/MONK68.WAV new file mode 100644 index 0000000..140791c Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK68.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK69.WAV b/src/Windebug/SFX/MONK/MONK69.WAV new file mode 100644 index 0000000..bc10e90 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK69.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK69B.WAV b/src/Windebug/SFX/MONK/MONK69B.WAV new file mode 100644 index 0000000..a28b7d7 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK69B.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK70.WAV b/src/Windebug/SFX/MONK/MONK70.WAV new file mode 100644 index 0000000..6dcde70 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK70.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK71.WAV b/src/Windebug/SFX/MONK/MONK71.WAV new file mode 100644 index 0000000..c5313df Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK71.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK79.WAV b/src/Windebug/SFX/MONK/MONK79.WAV new file mode 100644 index 0000000..be7c649 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK79.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK80.WAV b/src/Windebug/SFX/MONK/MONK80.WAV new file mode 100644 index 0000000..1460ce4 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK80.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK82.WAV b/src/Windebug/SFX/MONK/MONK82.WAV new file mode 100644 index 0000000..e42a722 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK82.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK83.WAV b/src/Windebug/SFX/MONK/MONK83.WAV new file mode 100644 index 0000000..f532cdb Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK83.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK87.WAV b/src/Windebug/SFX/MONK/MONK87.WAV new file mode 100644 index 0000000..d659df3 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK87.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK88.WAV b/src/Windebug/SFX/MONK/MONK88.WAV new file mode 100644 index 0000000..c83382f Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK88.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK89.WAV b/src/Windebug/SFX/MONK/MONK89.WAV new file mode 100644 index 0000000..ecaa6e7 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK89.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK91.WAV b/src/Windebug/SFX/MONK/MONK91.WAV new file mode 100644 index 0000000..e98709f Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK91.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK92.WAV b/src/Windebug/SFX/MONK/MONK92.WAV new file mode 100644 index 0000000..e2fe589 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK92.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK94.WAV b/src/Windebug/SFX/MONK/MONK94.WAV new file mode 100644 index 0000000..3bf8aeb Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK94.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK95.WAV b/src/Windebug/SFX/MONK/MONK95.WAV new file mode 100644 index 0000000..82bf1d0 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK95.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK96.WAV b/src/Windebug/SFX/MONK/MONK96.WAV new file mode 100644 index 0000000..e471455 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK96.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK97.WAV b/src/Windebug/SFX/MONK/MONK97.WAV new file mode 100644 index 0000000..30e28e7 Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK97.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK98.WAV b/src/Windebug/SFX/MONK/MONK98.WAV new file mode 100644 index 0000000..f936ecc Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK98.WAV differ diff --git a/src/Windebug/SFX/MONK/MONK99.WAV b/src/Windebug/SFX/MONK/MONK99.WAV new file mode 100644 index 0000000..668bcea Binary files /dev/null and b/src/Windebug/SFX/MONK/MONK99.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK01.WAV b/src/Windebug/SFX/MONKOLD/MONK01.WAV new file mode 100644 index 0000000..02189dd Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK01.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK02.WAV b/src/Windebug/SFX/MONKOLD/MONK02.WAV new file mode 100644 index 0000000..7ec0abc Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK02.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK03.WAV b/src/Windebug/SFX/MONKOLD/MONK03.WAV new file mode 100644 index 0000000..1d86665 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK03.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK04.WAV b/src/Windebug/SFX/MONKOLD/MONK04.WAV new file mode 100644 index 0000000..3180ca6 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK04.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK05.WAV b/src/Windebug/SFX/MONKOLD/MONK05.WAV new file mode 100644 index 0000000..675f247 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK05.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK06.WAV b/src/Windebug/SFX/MONKOLD/MONK06.WAV new file mode 100644 index 0000000..f9dfd13 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK06.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK07.WAV b/src/Windebug/SFX/MONKOLD/MONK07.WAV new file mode 100644 index 0000000..459a8c9 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK07.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK08.WAV b/src/Windebug/SFX/MONKOLD/MONK08.WAV new file mode 100644 index 0000000..2e238b5 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK08.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK09.WAV b/src/Windebug/SFX/MONKOLD/MONK09.WAV new file mode 100644 index 0000000..b1394c5 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK09.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK10.WAV b/src/Windebug/SFX/MONKOLD/MONK10.WAV new file mode 100644 index 0000000..cc7bf65 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK10.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK100.WAV b/src/Windebug/SFX/MONKOLD/MONK100.WAV new file mode 100644 index 0000000..8566c83 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK100.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK101.WAV b/src/Windebug/SFX/MONKOLD/MONK101.WAV new file mode 100644 index 0000000..63d8132 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK101.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK102.WAV b/src/Windebug/SFX/MONKOLD/MONK102.WAV new file mode 100644 index 0000000..72fd7e2 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK102.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK11.WAV b/src/Windebug/SFX/MONKOLD/MONK11.WAV new file mode 100644 index 0000000..15ab908 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK11.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK12.WAV b/src/Windebug/SFX/MONKOLD/MONK12.WAV new file mode 100644 index 0000000..71e4af2 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK12.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK13.WAV b/src/Windebug/SFX/MONKOLD/MONK13.WAV new file mode 100644 index 0000000..009643a Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK13.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK14.WAV b/src/Windebug/SFX/MONKOLD/MONK14.WAV new file mode 100644 index 0000000..0256b51 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK14.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK15.WAV b/src/Windebug/SFX/MONKOLD/MONK15.WAV new file mode 100644 index 0000000..fab47cb Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK15.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK16.WAV b/src/Windebug/SFX/MONKOLD/MONK16.WAV new file mode 100644 index 0000000..dcc14b2 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK16.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK17.WAV b/src/Windebug/SFX/MONKOLD/MONK17.WAV new file mode 100644 index 0000000..2b52c9a Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK17.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK18.WAV b/src/Windebug/SFX/MONKOLD/MONK18.WAV new file mode 100644 index 0000000..2c86f7a Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK18.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK19.WAV b/src/Windebug/SFX/MONKOLD/MONK19.WAV new file mode 100644 index 0000000..68629b5 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK19.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK20.WAV b/src/Windebug/SFX/MONKOLD/MONK20.WAV new file mode 100644 index 0000000..0b3a570 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK20.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK21.WAV b/src/Windebug/SFX/MONKOLD/MONK21.WAV new file mode 100644 index 0000000..2e8930d Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK21.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK22.WAV b/src/Windebug/SFX/MONKOLD/MONK22.WAV new file mode 100644 index 0000000..024cccf Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK22.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK23.WAV b/src/Windebug/SFX/MONKOLD/MONK23.WAV new file mode 100644 index 0000000..083e642 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK23.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK24.WAV b/src/Windebug/SFX/MONKOLD/MONK24.WAV new file mode 100644 index 0000000..2163943 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK24.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK25.WAV b/src/Windebug/SFX/MONKOLD/MONK25.WAV new file mode 100644 index 0000000..ed42a50 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK25.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK26.WAV b/src/Windebug/SFX/MONKOLD/MONK26.WAV new file mode 100644 index 0000000..bfca2cd Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK26.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK27.WAV b/src/Windebug/SFX/MONKOLD/MONK27.WAV new file mode 100644 index 0000000..7f2b4e4 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK27.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK28.WAV b/src/Windebug/SFX/MONKOLD/MONK28.WAV new file mode 100644 index 0000000..6ecc605 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK28.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK29.WAV b/src/Windebug/SFX/MONKOLD/MONK29.WAV new file mode 100644 index 0000000..ea9751d Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK29.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK30.WAV b/src/Windebug/SFX/MONKOLD/MONK30.WAV new file mode 100644 index 0000000..bfbfa0f Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK30.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK31.WAV b/src/Windebug/SFX/MONKOLD/MONK31.WAV new file mode 100644 index 0000000..d598c83 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK31.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK32.WAV b/src/Windebug/SFX/MONKOLD/MONK32.WAV new file mode 100644 index 0000000..b6d3123 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK32.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK33.WAV b/src/Windebug/SFX/MONKOLD/MONK33.WAV new file mode 100644 index 0000000..a663c83 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK33.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK34.WAV b/src/Windebug/SFX/MONKOLD/MONK34.WAV new file mode 100644 index 0000000..c60ed95 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK34.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK35.WAV b/src/Windebug/SFX/MONKOLD/MONK35.WAV new file mode 100644 index 0000000..c4bba41 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK35.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK36.WAV b/src/Windebug/SFX/MONKOLD/MONK36.WAV new file mode 100644 index 0000000..e78e212 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK36.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK37.WAV b/src/Windebug/SFX/MONKOLD/MONK37.WAV new file mode 100644 index 0000000..e2b3a00 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK37.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK38.WAV b/src/Windebug/SFX/MONKOLD/MONK38.WAV new file mode 100644 index 0000000..9ed66b3 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK38.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK39.WAV b/src/Windebug/SFX/MONKOLD/MONK39.WAV new file mode 100644 index 0000000..0ab51b7 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK39.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK40.WAV b/src/Windebug/SFX/MONKOLD/MONK40.WAV new file mode 100644 index 0000000..1c89129 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK40.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK41.WAV b/src/Windebug/SFX/MONKOLD/MONK41.WAV new file mode 100644 index 0000000..bb640e3 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK41.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK42.WAV b/src/Windebug/SFX/MONKOLD/MONK42.WAV new file mode 100644 index 0000000..f2163ac Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK42.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK43.WAV b/src/Windebug/SFX/MONKOLD/MONK43.WAV new file mode 100644 index 0000000..3247b85 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK43.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK44.WAV b/src/Windebug/SFX/MONKOLD/MONK44.WAV new file mode 100644 index 0000000..bb02a63 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK44.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK45.WAV b/src/Windebug/SFX/MONKOLD/MONK45.WAV new file mode 100644 index 0000000..8988bdf Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK45.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK46.WAV b/src/Windebug/SFX/MONKOLD/MONK46.WAV new file mode 100644 index 0000000..0aa9793 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK46.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK47.WAV b/src/Windebug/SFX/MONKOLD/MONK47.WAV new file mode 100644 index 0000000..af00d95 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK47.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK48.WAV b/src/Windebug/SFX/MONKOLD/MONK48.WAV new file mode 100644 index 0000000..cc1a855 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK48.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK49.WAV b/src/Windebug/SFX/MONKOLD/MONK49.WAV new file mode 100644 index 0000000..e849ef8 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK49.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK50.WAV b/src/Windebug/SFX/MONKOLD/MONK50.WAV new file mode 100644 index 0000000..b2eb0b9 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK50.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK51.WAV b/src/Windebug/SFX/MONKOLD/MONK51.WAV new file mode 100644 index 0000000..c78c215 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK51.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK52.WAV b/src/Windebug/SFX/MONKOLD/MONK52.WAV new file mode 100644 index 0000000..467bdae Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK52.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK53.WAV b/src/Windebug/SFX/MONKOLD/MONK53.WAV new file mode 100644 index 0000000..15118ad Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK53.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK54.WAV b/src/Windebug/SFX/MONKOLD/MONK54.WAV new file mode 100644 index 0000000..9dcad19 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK54.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK55.WAV b/src/Windebug/SFX/MONKOLD/MONK55.WAV new file mode 100644 index 0000000..a8934ab Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK55.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK56.WAV b/src/Windebug/SFX/MONKOLD/MONK56.WAV new file mode 100644 index 0000000..59a9f4c Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK56.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK57.WAV b/src/Windebug/SFX/MONKOLD/MONK57.WAV new file mode 100644 index 0000000..5e9a884 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK57.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK58.WAV b/src/Windebug/SFX/MONKOLD/MONK58.WAV new file mode 100644 index 0000000..2ed85ac Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK58.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK59.WAV b/src/Windebug/SFX/MONKOLD/MONK59.WAV new file mode 100644 index 0000000..125f9f0 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK59.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK60.WAV b/src/Windebug/SFX/MONKOLD/MONK60.WAV new file mode 100644 index 0000000..5a52d6d Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK60.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK61.WAV b/src/Windebug/SFX/MONKOLD/MONK61.WAV new file mode 100644 index 0000000..62ec2e8 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK61.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK62.WAV b/src/Windebug/SFX/MONKOLD/MONK62.WAV new file mode 100644 index 0000000..3e5e5f8 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK62.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK63.WAV b/src/Windebug/SFX/MONKOLD/MONK63.WAV new file mode 100644 index 0000000..e6a0baf Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK63.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK64.WAV b/src/Windebug/SFX/MONKOLD/MONK64.WAV new file mode 100644 index 0000000..0005c3b Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK64.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK65.WAV b/src/Windebug/SFX/MONKOLD/MONK65.WAV new file mode 100644 index 0000000..cae717d Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK65.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK66.WAV b/src/Windebug/SFX/MONKOLD/MONK66.WAV new file mode 100644 index 0000000..16e85f7 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK66.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK67.WAV b/src/Windebug/SFX/MONKOLD/MONK67.WAV new file mode 100644 index 0000000..10e9ea6 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK67.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK68.WAV b/src/Windebug/SFX/MONKOLD/MONK68.WAV new file mode 100644 index 0000000..55bb806 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK68.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK69.WAV b/src/Windebug/SFX/MONKOLD/MONK69.WAV new file mode 100644 index 0000000..95f3df7 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK69.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK69B.WAV b/src/Windebug/SFX/MONKOLD/MONK69B.WAV new file mode 100644 index 0000000..3e0fc52 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK69B.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK70.WAV b/src/Windebug/SFX/MONKOLD/MONK70.WAV new file mode 100644 index 0000000..f379ab8 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK70.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK71.WAV b/src/Windebug/SFX/MONKOLD/MONK71.WAV new file mode 100644 index 0000000..8509966 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK71.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK72.WAV b/src/Windebug/SFX/MONKOLD/MONK72.WAV new file mode 100644 index 0000000..369624b Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK72.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK73.WAV b/src/Windebug/SFX/MONKOLD/MONK73.WAV new file mode 100644 index 0000000..1e3cd4f Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK73.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK74.WAV b/src/Windebug/SFX/MONKOLD/MONK74.WAV new file mode 100644 index 0000000..1b3fe3d Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK74.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK75.WAV b/src/Windebug/SFX/MONKOLD/MONK75.WAV new file mode 100644 index 0000000..a853dee Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK75.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK76.WAV b/src/Windebug/SFX/MONKOLD/MONK76.WAV new file mode 100644 index 0000000..0b18a14 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK76.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK77.WAV b/src/Windebug/SFX/MONKOLD/MONK77.WAV new file mode 100644 index 0000000..7153421 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK77.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK78.WAV b/src/Windebug/SFX/MONKOLD/MONK78.WAV new file mode 100644 index 0000000..74e5ed5 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK78.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK79.WAV b/src/Windebug/SFX/MONKOLD/MONK79.WAV new file mode 100644 index 0000000..7c5f504 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK79.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK80.WAV b/src/Windebug/SFX/MONKOLD/MONK80.WAV new file mode 100644 index 0000000..6843c43 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK80.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK81.WAV b/src/Windebug/SFX/MONKOLD/MONK81.WAV new file mode 100644 index 0000000..9e18c36 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK81.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK82.WAV b/src/Windebug/SFX/MONKOLD/MONK82.WAV new file mode 100644 index 0000000..ea0c351 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK82.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK83.WAV b/src/Windebug/SFX/MONKOLD/MONK83.WAV new file mode 100644 index 0000000..c9d0b50 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK83.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK84.WAV b/src/Windebug/SFX/MONKOLD/MONK84.WAV new file mode 100644 index 0000000..428ff1b Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK84.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK85.WAV b/src/Windebug/SFX/MONKOLD/MONK85.WAV new file mode 100644 index 0000000..7405610 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK85.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK86.WAV b/src/Windebug/SFX/MONKOLD/MONK86.WAV new file mode 100644 index 0000000..db733b3 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK86.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK87.WAV b/src/Windebug/SFX/MONKOLD/MONK87.WAV new file mode 100644 index 0000000..4f1f5a8 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK87.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK88.WAV b/src/Windebug/SFX/MONKOLD/MONK88.WAV new file mode 100644 index 0000000..63cd13f Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK88.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK89.WAV b/src/Windebug/SFX/MONKOLD/MONK89.WAV new file mode 100644 index 0000000..b4fdbd8 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK89.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK90.WAV b/src/Windebug/SFX/MONKOLD/MONK90.WAV new file mode 100644 index 0000000..c5f6d46 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK90.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK91.WAV b/src/Windebug/SFX/MONKOLD/MONK91.WAV new file mode 100644 index 0000000..7fe42b4 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK91.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK92.WAV b/src/Windebug/SFX/MONKOLD/MONK92.WAV new file mode 100644 index 0000000..79ec5ab Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK92.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK93.WAV b/src/Windebug/SFX/MONKOLD/MONK93.WAV new file mode 100644 index 0000000..8aaa5d6 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK93.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK94.WAV b/src/Windebug/SFX/MONKOLD/MONK94.WAV new file mode 100644 index 0000000..2b2dd0c Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK94.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK95.WAV b/src/Windebug/SFX/MONKOLD/MONK95.WAV new file mode 100644 index 0000000..cf83ee8 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK95.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK96.WAV b/src/Windebug/SFX/MONKOLD/MONK96.WAV new file mode 100644 index 0000000..0bb1c80 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK96.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK97.WAV b/src/Windebug/SFX/MONKOLD/MONK97.WAV new file mode 100644 index 0000000..e098c4e Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK97.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK98.WAV b/src/Windebug/SFX/MONKOLD/MONK98.WAV new file mode 100644 index 0000000..184c2a3 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK98.WAV differ diff --git a/src/Windebug/SFX/MONKOLD/MONK99.WAV b/src/Windebug/SFX/MONKOLD/MONK99.WAV new file mode 100644 index 0000000..2077917 Binary files /dev/null and b/src/Windebug/SFX/MONKOLD/MONK99.WAV differ diff --git a/src/Windebug/SIERRA.INF b/src/Windebug/SIERRA.INF new file mode 100644 index 0000000..e04f0fa --- /dev/null +++ b/src/Windebug/SIERRA.INF @@ -0,0 +1,3 @@ +[Ident] +Version=1.0.1.0 +PatchVersion=1.0.1.0 diff --git a/src/Windebug/SINGLE_0.DBL b/src/Windebug/SINGLE_0.DBL new file mode 100644 index 0000000..ed557b8 Binary files /dev/null and b/src/Windebug/SINGLE_0.DBL differ diff --git a/src/Windebug/SINGLE_0.HSV b/src/Windebug/SINGLE_0.HSV new file mode 100644 index 0000000..af4bafb Binary files /dev/null and b/src/Windebug/SINGLE_0.HSV differ diff --git a/src/Windebug/SINGLE_0.ORG b/src/Windebug/SINGLE_0.ORG new file mode 100644 index 0000000..ec6c64b Binary files /dev/null and b/src/Windebug/SINGLE_0.ORG differ diff --git a/src/Windebug/SINGLE_0.SAV b/src/Windebug/SINGLE_0.SAV new file mode 100644 index 0000000..65a0816 Binary files /dev/null and b/src/Windebug/SINGLE_0.SAV differ diff --git a/src/Windebug/SINGLE_0.TST b/src/Windebug/SINGLE_0.TST new file mode 100644 index 0000000..e69de29 diff --git a/src/Windebug/SINGLE_1.HSV b/src/Windebug/SINGLE_1.HSV new file mode 100644 index 0000000..92418b6 Binary files /dev/null and b/src/Windebug/SINGLE_1.HSV differ diff --git a/src/Windebug/SINGLE_1.SAV b/src/Windebug/SINGLE_1.SAV new file mode 100644 index 0000000..2f830a3 Binary files /dev/null and b/src/Windebug/SINGLE_1.SAV differ diff --git a/src/Windebug/SINGLE_1.TST b/src/Windebug/SINGLE_1.TST new file mode 100644 index 0000000..e22a626 Binary files /dev/null and b/src/Windebug/SINGLE_1.TST differ diff --git a/src/Windebug/SINGLE_2.BAD b/src/Windebug/SINGLE_2.BAD new file mode 100644 index 0000000..e8a30e5 Binary files /dev/null and b/src/Windebug/SINGLE_2.BAD differ diff --git a/src/Windebug/SINGLE_2.HSV b/src/Windebug/SINGLE_2.HSV new file mode 100644 index 0000000..c0fb21f Binary files /dev/null and b/src/Windebug/SINGLE_2.HSV differ diff --git a/src/Windebug/SINGLE_2.ORG b/src/Windebug/SINGLE_2.ORG new file mode 100644 index 0000000..fdb0a85 Binary files /dev/null and b/src/Windebug/SINGLE_2.ORG differ diff --git a/src/Windebug/SINGLE_3.HSV b/src/Windebug/SINGLE_3.HSV new file mode 100644 index 0000000..d251efb Binary files /dev/null and b/src/Windebug/SINGLE_3.HSV differ diff --git a/src/Windebug/SINGLE_3.SAV b/src/Windebug/SINGLE_3.SAV new file mode 100644 index 0000000..d5ddf1d Binary files /dev/null and b/src/Windebug/SINGLE_3.SAV differ diff --git a/src/Windebug/SINGLE_4.HSV b/src/Windebug/SINGLE_4.HSV new file mode 100644 index 0000000..117e7fa Binary files /dev/null and b/src/Windebug/SINGLE_4.HSV differ diff --git a/src/Windebug/SINGLE_5.HSV b/src/Windebug/SINGLE_5.HSV new file mode 100644 index 0000000..731a29c Binary files /dev/null and b/src/Windebug/SINGLE_5.HSV differ diff --git a/src/Windebug/SINGLE_6.SSV b/src/Windebug/SINGLE_6.SSV new file mode 100644 index 0000000..33a4361 Binary files /dev/null and b/src/Windebug/SINGLE_6.SSV differ diff --git a/src/Windebug/SINGLE_7.HSV b/src/Windebug/SINGLE_7.HSV new file mode 100644 index 0000000..5107291 Binary files /dev/null and b/src/Windebug/SINGLE_7.HSV differ diff --git a/src/Windebug/SINGLE_8.HSV b/src/Windebug/SINGLE_8.HSV new file mode 100644 index 0000000..5f5bdaa Binary files /dev/null and b/src/Windebug/SINGLE_8.HSV differ diff --git a/src/Windebug/SMACKW32.DLL b/src/Windebug/SMACKW32.DLL new file mode 100644 index 0000000..e756b2f Binary files /dev/null and b/src/Windebug/SMACKW32.DLL differ diff --git a/src/Windebug/STANDARD.SNP b/src/Windebug/STANDARD.SNP new file mode 100644 index 0000000..54b2343 Binary files /dev/null and b/src/Windebug/STANDARD.SNP differ diff --git a/src/Windebug/STORM.DLL b/src/Windebug/STORM.DLL new file mode 100644 index 0000000..21f620d Binary files /dev/null and b/src/Windebug/STORM.DLL differ diff --git a/src/Windebug/STORM.EXP b/src/Windebug/STORM.EXP new file mode 100644 index 0000000..1f456e0 Binary files /dev/null and b/src/Windebug/STORM.EXP differ diff --git a/src/Windebug/STORM.LIB b/src/Windebug/STORM.LIB new file mode 100644 index 0000000..67499fd Binary files /dev/null and b/src/Windebug/STORM.LIB differ diff --git a/src/Windebug/STORM.RES b/src/Windebug/STORM.RES new file mode 100644 index 0000000..d4caef6 Binary files /dev/null and b/src/Windebug/STORM.RES differ diff --git a/src/Windebug/STORMD.EXP b/src/Windebug/STORMD.EXP new file mode 100644 index 0000000..9e0b30b Binary files /dev/null and b/src/Windebug/STORMD.EXP differ diff --git a/src/Windebug/STORMD.LIB b/src/Windebug/STORMD.LIB new file mode 100644 index 0000000..e3894a2 Binary files /dev/null and b/src/Windebug/STORMD.LIB differ diff --git a/src/Windebug/STORMDLL.PCH b/src/Windebug/STORMDLL.PCH new file mode 100644 index 0000000..6e83481 Binary files /dev/null and b/src/Windebug/STORMDLL.PCH differ diff --git a/src/Windebug/STORMD~1 b/src/Windebug/STORMD~1 new file mode 100644 index 0000000..ba3ecb8 Binary files /dev/null and b/src/Windebug/STORMD~1 differ diff --git a/src/Windebug/STORMD~1.DLL b/src/Windebug/STORMD~1.DLL new file mode 100644 index 0000000..ad5696f Binary files /dev/null and b/src/Windebug/STORMD~1.DLL differ diff --git a/src/Windebug/STORM_~1 b/src/Windebug/STORM_~1 new file mode 100644 index 0000000..7ae8497 Binary files /dev/null and b/src/Windebug/STORM_~1 differ diff --git a/src/Windebug/STRINGS.TXT b/src/Windebug/STRINGS.TXT new file mode 100644 index 0000000..1706e2f --- /dev/null +++ b/src/Windebug/STRINGS.TXT @@ -0,0 +1,9057 @@ +L$screen??.PCX +screen%02d.PCX +*?+@A +(B)C +?AAAAAAACEEEEIIIIDNOOOOOX0UUUUYbBaaaaaaaceeeeiiiionooooo/0uuuuyby +dd_emulate +dd_backbuf +ds_noduplicates +()*+ +$!!#"!% +%"! +ahds + !"#32 +$Keyboard Shortcuts:|F1: Open Help Screen|Esc: Display Main Menu|Tab: Display Auto-map|Space: Hide all info screens|S: Open Speedbook|B: Open Spellbook|I: Open Inventory screen|C: Open Character screen|Q: Open Quest log|F: Reduce screen brightness|G: Increase screen brightness|Z: Zoom Game Screen|+ / -: Zoom Automap|1 - 8: Use Belt item|F5, F6, F7, F8: Set hot key for skill or spell|Shift + Left Click: Attack without moving||$Movement:|If you hold the mouse button down while moving, the character will continue to move in that direction.||$Combat:|Holding down the shift key and then left-clicking allows the character to attack without moving.||$Auto-map:|To access the auto-map, click the 'MAP' button on the Information Bar or press 'TAB' on the keyboard. Zooming in and out of the map is done with the + and - keys. Scrolling the map uses the arrow keys.||$Picking up Objects:|Useable items that are small in size, such as potions or scrolls, are automatically placed in your 'belt' located at the top of the Interface bar . When an item is placed in the belt, a small number appears in that box. Items may be used by either pressing the corresponding number or right-clicking on the item.||$Gold|You can select a specific amount of gold to drop by right clicking on a pile of gold in your inventory.||$Skills & Spells:|You can access your list of skills and spells by left-clicking on the 'SPELLS' button in the interface bar. Memorized spells and those available through staffs are listed here. Left-clicking on the spell you wish to cast will ready the spell. A readied spell may be cast by simply right-clicking in the play area.||$Using the Speedbook for Spells|Left-clicking on the 'readied spell' button will open the 'Speedbook' which allows you to select a skill or spell for immediate use. To use a readied skill or spell, simply right-click in the main play area.||$Setting Spell Hotkeys|You can assign up to four Hot Keys for skills, spells or scrolls. Start by opening the 'speedbook' as described in the section above. Press the F5, F6, F7 or F8 keys after highlighting the spell you wish to assign.||$Spell Books|Reading more than one book increases your knowledge of that spell, allowing you to cast the spell more effectively.|& +HELLFIRE +ScreenSaveActive + !"#320.16 +?Gamma Correction +game +hero +perml%02d +perms%02d +templ%02d +temps%02d +NUSDBAMHT +WRSMR +unknown action +Sound Volume +Music Volume +`h```` +(null) +?IsProcessorFeaturePresent +KERNEL32 +e+000 +LC_TIME +LC_NUMERIC +LC_MONETARY +LC_CTYPE +LC_COLLATE +LC_ALL +SunMonTueWedThuFriSat +JanFebMarAprMayJunJulAugSepOctNovDec +@runtime error +TLOSS error +SING error +DOMAIN error +R6028 +- unable to initialize heap +R6027 +- not enough space for lowio initialization +R6026 +- not enough space for stdio initialization +R6025 +- pure virtual function call +R6024 +- not enough space for _onexit/atexit table +R6019 +- unable to open console device +R6018 +- unexpected heap error +R6017 +- unexpected multithread lock error +R6016 +- not enough space for thread data +abnormal program termination +R6009 +- not enough space for environment +R6008 +- not enough space for arguments +R6002 +- floating point not loaded +Microsoft Visual C++ Runtime Library +Runtime Error! +Program: + +united-states +united-kingdom +united states +united kingdom +turkey +taiwan +switzerland +sweden +spain +south-korea +south korea +singapore +russia +pr-china +pr china +portugal +poland +norway +new-zealand +new zealand +netherlands +mexico +korea +japan +italy +ireland +iceland +hungary +hong-kong +hong kong +holland +greece +great britain +germany +france +finland +england +denmark +china +canada +britain +brazil +belgium +austria +australia +america +turkish +swiss +swedish +spanish-modern +spanish-mexican +spanish +slovak +russian +portuguese-brazilian +portuguese +polish +norwegian-nynorsk +norwegian-bokmal +norwegian +korean +japanese +italian-swiss +italian +irish-english +icelandic +hungarian +greek +german-swiss +german-austrian +german +french-swiss +french-canadian +french-belgian +french +finnish +english-usa +english-us +english-uk +english-nz +english-ire +english-can +english-aus +english-american +english +dutch-belgian +dutch +danish +czech +chinese-traditional +chinese-singapore +chinese-simplified +chinese-hongkong +chinese +canadian +belgian +australian +american-english +american english +american +GetLastActivePopup +GetActiveWindow +MessageBoxA +user32.dll +1#QNAN +1#INF +1#IND +1#SNAN +H:mm:ss +dddd, MMMM dd, yyyy +M/d/yy +December +November +October +September +August +July +June +April +March +February +January +Saturday +Friday +Thursday +Wednesday +Tuesday +Monday +Sunday +am/pm +frexp +fmod +_hypot +_cabs +ldexp +modf +fabs +floor +ceil +sqrt +atan2 +atan +acos +asin +tanh +cosh +sinh +log10 +!This program cannot be run in DOS mode. +.text +`.rdata +@.data +.idata +.rsrc +@.reloc +=(a_ +=,#U +=0#U +=,#U +=0#U +tJhpfu +QhX`O +Rhh`O +h@#U +h@#U +h@#U +h@#U +Et#h +Et#h +hl&U +h@#U +=D$U +=h&U +=|b_ +=|b_ +Ph@#U +h@#U +h@#U +=h&U +=|b_ +=|b_ +h@#U +=|b_ +=|b_ +=0#U +=,#U +=$#U +=P%U +=h&U +=h&U +h@#U +Qh@#U +Qh@#U +Ph@#U +Rh@#U +Ph@#U +=$#U +5lYv +5lYv +5lYv +5lYv +5lYv +5lYv +5lYv +5lYv +5lYv +5lYv +5lYv +5lYv +=|b_ +=|b_ +=|b_ +=|b_ +=`!U +=0#U +=,#U +=,#U +=@d_ +5@Yv +=lYv +5@Yv +=lYv +5lYv +=|b_ +=|b_ +5lYv +5@Yv +=lYv +5@Yv +=lYv +=|b_ +=|b_ +=X!U +=X!U +5lYv +5lYv +=$#U +=$#U +=|b_ +=|b_ +=$#U +=|b_ +=|b_ +=$#U +1hh!U +=$#U +u"hh!U +}"hh!U +|=hh!U +hh!U +Rhh!U +h@#U +h@#U +=0#U +=,#U +=dc_ +=h&U +=|b_ +=,#U +=0#U +=8d_ += a_ +h, P +hD P +h\ P +ht P +=(Yv +=(Yv +=,Yv +=`c_ +=(a_ +=(a_ +=(a_ +h0jO +Rh0jO +h0jO +h@jO +Rh@jO +h@jO +hPjO +RhPjO +hPjO +=HYp +=$#U +=h&U +=pd_ +=PYv +=Xd_ +=h&U +=|b_ +=|b_ +=|b_ +=0#U +=,#U +=h&U +=$#U +=|b_ +=`&U +=`!U +=pd_ +=Xd_ +=h&U +=,#U +=|b_ +=PYv +=pd_ +=(d_ +=,d_ +=pd_ +=Xd_ +=,d_ +=(d_ +=HYp +QhP#P +Qht#P +=h&U +=h&U +=h&U +=h&U +=HYp +=HYp +=$#U +=$#U +=0#U +=|b_ +=0#U +=|b_ +=Xd_ +=pd_ +=PYv +=Xd_ +=0#U +=|b_ +=|b_ +=0#U +=0#U +=|b_ +=|b_ +5lYv +=,a_ +=,a_ +=,a_ +=,a_ +=dc_ +=h&U +=,#U +=,d_ +Ph,$P +=(d_ +Qh<$P +=,d_ +=$d_ +QhP$P +=(d_ +Qh`$P +h0%P +hd%P +h(&P +hX&P +hH'P +hx'P +h8(P +hh(P +h()P +hX)P +h$*P +hL*P +hd*P +=Pd_ +hp*P +5lYv +5lYv +5lYv +=Xd_ +=Xd_ +=pd_ +=hc_ +=pd_ +=pd_ +=lYv +h +P +h8+P +hP+P +=@d_ +Ph`4h +h8,P +hP,P +hh,P +hP-P +hhGP +t0h0HP +hdHP +=`eh +ulh|HP +hPIP +hhIP +t0h$JP +hTJP +hlJP +t&h4KP +$hhKP +=`eh +h4LP +h`LP +hDMP +hlMP +h0NP +RhHNP +PhPNP +h`NP +"Rh(OP +/RhS +hD>S +hp>S +h(?S +h`?S +Qh4CS +hhCS +RhpCS +h,DS +hTDS +hpDS +Ph0ES +Ph8ES +hPES +PhpES +h$FS +hj +=p_v +=l`v +=Ld_ +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +h@#U +=|b_ +D$8' +D$(j +T$4j +SVWUj +l$ u +T$$j +WSUVj +L$(j +Pj#Wj +Qj%Wj +C*PjTVj +QjUVj +RjVVj +C-PjWVj +QjRVj +SjSVj +UUSh +T$ j +D$(j +D$.% +D$.% +D$ j +D$,j +L$xj +rtf=z +r[f=z +tUf= +D$$j +T$$j +T$ +united-states +united-kingdom +united states +united kingdom +turkey +taiwan +switzerland +sweden +spain +south-korea +south korea +singapore +russia +pr-china +pr china +portugal +poland +norway +new-zealand +new zealand +netherlands +mexico +korea +japan +italy +ireland +iceland +hungary +hong-kong +hong kong +holland +greece +great britain +germany +france +finland +england +denmark +china +canada +britain +brazil +belgium +austria +australia +america +turkish +swiss +swedish +spanish-modern +spanish-mexican +spanish +slovak +russian +portuguese-brazilian +portuguese +polish +norwegian-nynorsk +norwegian-bokmal +norwegian +korean +japanese +italian-swiss +italian +irish-english +icelandic +hungarian +greek +german-swiss +german-austrian +german +french-swiss +french-canadian +french-belgian +french +finnish +english-usa +english-us +english-uk +english-nz +english-ire +english-can +english-aus +english-american +english +dutch-belgian +dutch +danish +czech +chinese-traditional +chinese-singapore +chinese-simplified +chinese-hongkong +chinese +canadian +belgian +australian +american-english +american english +american +GetLastActivePopup +GetActiveWindow +MessageBoxA +user32.dll +1#QNAN +1#INF +1#IND +1#SNAN +H:mm:ss +dddd, MMMM dd, yyyy +M/d/yy +December +November +October +September +August +July +June +April +March +February +January +Saturday +Friday +Thursday +Wednesday +Tuesday +Monday +Sunday +am/pm +frexp +fmod +_hypot +_cabs +ldexp +modf +fabs +floor +ceil +sqrt +atan2 +atan +acos +asin +tanh +cosh +sinh +log10 +unknown error 0x%08x +DD_OK +DDERR_ALREADYINITIALIZED +DDERR_BLTFASTCANTCLIP +DDERR_CANNOTATTACHSURFACE +DDERR_CANNOTDETACHSURFACE +DDERR_CANTCREATEDC +DDERR_CANTDUPLICATE +DDERR_CLIPPERISUSINGHWND +DDERR_COLORKEYNOTSET +DDERR_CURRENTLYNOTAVAIL +DDERR_DIRECTDRAWALREADYCREATED +DDERR_EXCEPTION +DDERR_EXCLUSIVEMODEALREADYSET +DDERR_GENERIC +DDERR_HEIGHTALIGN +DDERR_HWNDALREADYSET +DDERR_HWNDSUBCLASSED +DDERR_IMPLICITLYCREATED +DDERR_INCOMPATIBLEPRIMARY +DDERR_INVALIDCAPS +DDERR_INVALIDCLIPLIST +DDERR_INVALIDDIRECTDRAWGUID +DDERR_INVALIDMODE +DDERR_INVALIDOBJECT +DDERR_INVALIDPARAMS +DDERR_INVALIDPIXELFORMAT +DDERR_INVALIDPOSITION +DDERR_INVALIDRECT +DDERR_LOCKEDSURFACES +DDERR_NO3D +DDERR_NOALPHAHW +DDERR_NOBLTHW +DDERR_NOCLIPLIST +DDERR_NOCLIPPERATTACHED +DDERR_NOCOLORCONVHW +DDERR_NOCOLORKEY +DDERR_NOCOLORKEYHW +DDERR_NOCOOPERATIVELEVELSET +DDERR_NODC +DDERR_NODDROPSHW +DDERR_NODIRECTDRAWHW +DDERR_NOEMULATION +DDERR_NOEXCLUSIVEMODE +DDERR_NOFLIPHW +DDERR_NOGDI +DDERR_NOHWND +DDERR_NOMIRRORHW +DDERR_NOOVERLAYDEST +DDERR_NOOVERLAYHW +DDERR_NOPALETTEATTACHED +DDERR_NOPALETTEHW +DDERR_NORASTEROPHW +DDERR_NOROTATIONHW +DDERR_NOSTRETCHHW +DDERR_NOT4BITCOLOR +DDERR_NOT4BITCOLORINDEX +DDERR_NOT8BITCOLOR +DDERR_NOTAOVERLAYSURFACE +DDERR_NOTEXTUREHW +DDERR_NOTFLIPPABLE +DDERR_NOTFOUND +DDERR_NOTLOCKED +DDERR_NOTPALETTIZED +DDERR_NOVSYNCHW +DDERR_NOZBUFFERHW +DDERR_NOZOVERLAYHW +DDERR_OUTOFCAPS +DDERR_OUTOFMEMORY +DDERR_OUTOFVIDEOMEMORY +DDERR_OVERLAYCANTCLIP +DDERR_OVERLAYCOLORKEYONLYONEACTIVE +DDERR_OVERLAYNOTVISIBLE +DDERR_PALETTEBUSY +DDERR_PRIMARYSURFACEALREADYEXISTS +DDERR_REGIONTOOSMALL +DDERR_SURFACEALREADYATTACHED +DDERR_SURFACEALREADYDEPENDENT +DDERR_SURFACEBUSY +DDERR_SURFACEISOBSCURED +DDERR_SURFACELOST +DDERR_SURFACENOTATTACHED +DDERR_TOOBIGHEIGHT +DDERR_TOOBIGSIZE +DDERR_TOOBIGWIDTH +DDERR_UNSUPPORTED +DDERR_UNSUPPORTEDFORMAT +DDERR_UNSUPPORTEDMASK +DDERR_VERTICALBLANKINPROGRESS +DDERR_WASSTILLDRAWING +DDERR_WRONGMODE +DDERR_XALIGN +DDERR_CANTLOCKSURFACE +DDERR_CANTPAGELOCK +DDERR_CANTPAGEUNLOCK +DDERR_DCALREADYCREATED +DDERR_INVALIDSURFACETYPE +DDERR_NOMIPMAPHW +DDERR_NOTPAGELOCKED +DDERR unknown 0x%x +dwMaxChars >= sizeof(szUnknown) + 10 +D:\diablo97\appfat.cpp +DS_OK +DSERR_ALLOCATED +DSERR_ALREADYINITIALIZED +DSERR_BADFORMAT +DSERR_BUFFERLOST +DSERR_CONTROLUNAVAIL +DSERR_INVALIDCALL +DSERR_INVALIDPARAM +DSERR_NOAGGREGATION +DSERR_NODRIVER +DSERR_OUTOFMEMORY +DSERR_PRIOLEVELNEEDED +E_NOINTERFACE +DSERR unknown 0x%x +dwMaxChars >= sizeof(szUnknown) + 10 +D:\diablo97\appfat.cpp +ERROR +pszFmt +D:\diablo97\appfat.cpp +Hellfire +assertion failed (%d:%s) +Direct draw error (%s:%d) +Direct sound error (%s:%d) +center_window: %s +at: %s line %d +ErrDlg: %d +FileErrDlg +DiskFreeDlg +InsertCDDlg +D:\diablo97\automap.cpp +Levels\L1Data\L1.AMP +D:\diablo97\automap.cpp +NLevels\L5Data\L5.AMP +D:\diablo97\automap.cpp +Levels\L2Data\L2.AMP +D:\diablo97\automap.cpp +Levels\L3Data\L3.AMP +D:\diablo97\automap.cpp +NLevels\L6Data\L6.AMP +D:\diablo97\automap.cpp +Levels\L4Data\L4.AMP +D:\diablo97\automap.cpp +gpBuffer +D:\diablo97\automap.cpp +game: +password: +Level: Nest %i +Level: Crypt %i +Level: %i +gpBuffer +D:\diablo97\capture.cpp +D:\diablo97\capture.cpp +D:\diablo97\capture.cpp +pbSrcDst +D:\diablo97\CODEC.CPP +pszPassword +D:\diablo97\CODEC.CPP +dwSrcBytes +D:\diablo97\CODEC.CPP +pbSrcDst +D:\diablo97\CODEC.CPP +pszPassword +D:\diablo97\CODEC.CPP +Invalid encode parameters +REGISTRATION_BLOCK +%&'*)( +332./+-01,##### +Enter +Character Information +Quests log +Automap +Main Menu +Inventory +Spell book +Send Message +Player Attack +gpBuffer +D:\diablo97\CONTROL.CPP +%s Skill +%s Spell +Damages undead only +Spell Level 0 - Unusable +Spell Level %i +Scroll of %s +1 Scroll +%i Scrolls +Staff of %s +1 Charge +%i Charges +Spell Hot Key #F%i +gpBuffer +D:\diablo97\CONTROL.CPP +gpBuffer +D:\diablo97\CONTROL.CPP +gpBuffer +D:\diablo97\CONTROL.CPP +gpBuffer +D:\diablo97\CONTROL.CPP +gpBuffer +D:\diablo97\CONTROL.CPP +! pBtmBuff +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +CtrlPan\SmalText.CEL +D:\diablo97\CONTROL.CPP +Data\Char.CEL +D:\diablo97\CONTROL.CPP +Data\SpelIcon.CEL +D:\diablo97\CONTROL.CPP +CtrlPan\Panel8.CEL +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +CtrlPan\P8Bulbs.CEL +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +CtrlPan\TalkPanl.CEL +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +CtrlPan\P8But2.CEL +D:\diablo97\CONTROL.CPP +CtrlPan\TalkButt.CEL +D:\diablo97\CONTROL.CPP +CtrlPan\Panel8bu.CEL +D:\diablo97\CONTROL.CPP +Data\CharBut.CEL +D:\diablo97\CONTROL.CPP +Items\DurIcons.CEL +D:\diablo97\CONTROL.CPP +Data\SpellBk.CEL +D:\diablo97\CONTROL.CPP +Data\SpellBkB.CEL +D:\diablo97\CONTROL.CPP +Data\SpellI2.CEL +D:\diablo97\CONTROL.CPP +Data\Quest.CEL +D:\diablo97\CONTROL.CPP +CtrlPan\Golddrop.cel +Player friendly +Player attack +Hotkey : %s +Select current spell button +Hotkey : 's' +%s Skill +%s Spell +Spell Level 0 - Unusable +Spell Level %i +Scroll of %s +1 Scroll +%i Scrolls +Staff of %s +1 Charge +%i Charges +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +D:\diablo97\CONTROL.CPP +%i gold %s +Requirements not met +Level : %i +Hit Points %i of %i +Warrior +Rogue +Sorceror +Monk +Bard +None +%i%% +%i-%i +%i%% +%i%% +%i%% +Level Up +gpBuffer +D:\diablo97\CONTROL.CPP +Skill +Staff (%i charges) +Mana: %i Dam: %i - %i +Mana: %i Dam: n/a +Mana: %i Dam: 1/3 tgt hp +Spell Level 0 - Unusable +Spell Level %i +piece +pieces +You have %u gold +%s. How many do +you want to remove? +gpBuffer +D:\diablo97\CONTROL.CPP +! pCursCels +D:\diablo97\CURSOR.CPP +D:\diablo97\CURSOR.CPP +Data\Inv\Objcurs.CEL +D:\diablo97\CURSOR.CPP +Data\Inv\Objcurs2.CEL +D:\diablo97\CURSOR.CPP +D:\diablo97\CURSOR.CPP +Town Portal +from %s +Portal to +The Unholy Altar +level 15 +nd <= MAXDEAD +D:\diablo97\DEAD.CPP +! pSquareCel +D:\diablo97\DEBUG.CPP +D:\diablo97\DEBUG.CPP +Data\Square.CEL +D:\diablo97\DEBUG.CPP +Seeds desynced +Plr %i : Active = %i + Plr %i is %s + Lvl = %i : Change = %i + x = %i, y = %i : tx = %i, ty = %i : fx = %i, fy = %i + mode = %i : daction = %i : walk[0] = %i + inv = %i : hp = %i +Quest %i : Active = %i, Var1 = %i +Monsters not cleared +Players not cleared +Level %i : Monst Active Sum = %i : dFlag sum = %i +Solid Sum = %i:%i : Monst Vol = %i : Dungeon Sum = %i +Num themes = %i/%i : Trans Sum = %i : dPiece Sum = %i +dung sum = %i : L4Dungeon sum = %i +dungeon Y=%i sum = %i +Monster %i = %s +X = %i, Y = %i +Enemy = %i, HP = %i +Mode = %i, Var1 = %i +Active List = %i, Squelch = %i +Current debug monster = %i +REGISTRATION_TABLE +If you are looking at this you might want to try these command line flags. +End of flags list. +D:\diablo97\DIABLO.CPP +D:\diablo97\DIABLO.CPP +D:\diablo97\DIABLO.CPP +D:\diablo97\DIABLO.CPP +D:\diablo97\DIABLO.CPP +ghMainWnd +D:\diablo97\DIABLO.CPP +saveProc == GM_Game +D:\diablo97\DIABLO.CPP +ghMainWnd +D:\diablo97\DIABLO.CPP +DiabloEvent +HellfireEvent +HELLFIRE +gendata\logo.smk +Intro +gendata\Hellfire.smk +Theoquest +Cowquest +NestArt +Bardtest +Multitest +MouseY < 352 +D:\diablo97\DIABLO.CPP +Can't get program name +\hellfire.ini +I need help! Heal me! +Go through that door first. +Give me some gold please. +Look out behind you! +dwMsg < sizeof(spszMsgTbl) / sizeof(spszMsgTbl[0]) +D:\diablo97\DIABLO.CPP +NetMsg +STOP QUEST TEXT MODE +Message Speed = %i +[ MESSAGE = %i ] +[ MESSAGE SPEED = %i ] +No help available +while in stores +IDX = %i : Seed = %i : CF = %i +Numitems : %i +seed = %i +Mid1 = %i : Mid2 = %i : Mid3 = %i +End = %i +Mid: %i +PX = %i PY = %i +CX = %i CY = %i DP = %i +EFlag = %i +START QUEST TEXT MODE +Message = %i +Message = %i +Message Speed = %i +Message = %i +Message Speed = %i +Normal +Nightmare +Hell +%s, mode = %s +! pDungeonCels +D:\diablo97\DIABLO.CPP +D:\diablo97\DIABLO.CPP +NLevels\TownData\Town.CEL +D:\diablo97\DIABLO.CPP +NLevels\TownData\Town.TIL +D:\diablo97\DIABLO.CPP +NLevels\TownData\Town.MIN +D:\diablo97\DIABLO.CPP +Levels\TownData\TownS.CEL +D:\diablo97\DIABLO.CPP +Levels\L1Data\L1.CEL +D:\diablo97\DIABLO.CPP +Levels\L1Data\L1.TIL +D:\diablo97\DIABLO.CPP +Levels\L1Data\L1.MIN +D:\diablo97\DIABLO.CPP +Levels\L1Data\L1S.CEL +D:\diablo97\DIABLO.CPP +NLevels\L5Data\L5.CEL +D:\diablo97\DIABLO.CPP +NLevels\L5Data\L5.TIL +D:\diablo97\DIABLO.CPP +NLevels\L5Data\L5.MIN +D:\diablo97\DIABLO.CPP +NLevels\L5Data\L5S.CEL +D:\diablo97\DIABLO.CPP +Levels\L2Data\L2.CEL +D:\diablo97\DIABLO.CPP +Levels\L2Data\L2.TIL +D:\diablo97\DIABLO.CPP +Levels\L2Data\L2.MIN +D:\diablo97\DIABLO.CPP +Levels\L2Data\L2S.CEL +D:\diablo97\DIABLO.CPP +Levels\L3Data\L3.CEL +D:\diablo97\DIABLO.CPP +Levels\L3Data\L3.TIL +D:\diablo97\DIABLO.CPP +Levels\L3Data\L3.MIN +D:\diablo97\DIABLO.CPP +Levels\L1Data\L1S.CEL +D:\diablo97\DIABLO.CPP +NLevels\L6Data\L6.CEL +D:\diablo97\DIABLO.CPP +NLevels\L6Data\L6.TIL +D:\diablo97\DIABLO.CPP +NLevels\L6Data\L6.MIN +D:\diablo97\DIABLO.CPP +Levels\L1Data\L1S.CEL +D:\diablo97\DIABLO.CPP +Levels\L4Data\L4.CEL +D:\diablo97\DIABLO.CPP +Levels\L4Data\L4.TIL +D:\diablo97\DIABLO.CPP +Levels\L4Data\L4.MIN +D:\diablo97\DIABLO.CPP +Levels\L2Data\L2S.CEL +LoadLvlGFX +! pSpeedCels +D:\diablo97\DIABLO.CPP +D:\diablo97\DIABLO.CPP +CreateLevel +! pSpeedCels +D:\diablo97\DIABLO.CPP +D:\diablo97\DIABLO.CPP +-- Network timeout -- +-- Waiting for players -- +Unable to initialize memory +gendata\doom.smk +D:\diablo97\doom.cpp +D:\diablo97\doom.cpp +Items\Map\MapZtown.CEL +REGISTRATION_BLOCK +D:\diablo97\DRLG_L1.CPP +D:\diablo97\DRLG_L1.CPP +lv >= 0 +D:\diablo97\DRLG_L1.CPP +D:\diablo97\DRLG_L1.CPP +D:\diablo97\DRLG_L1.CPP +D:\diablo97\DRLG_L1.CPP +Levels\L1Data\rnd6.DUN +D:\diablo97\DRLG_L1.CPP +Levels\L1Data\SKngDO.DUN +D:\diablo97\DRLG_L1.CPP +Levels\L1Data\Banner2.DUN +D:\diablo97\DRLG_L1.CPP +REGISTRATION_BLOCK +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +xzy{ +D:\diablo97\DRLG_L2.CPP +D:\diablo97\DRLG_L2.CPP +D:\diablo97\DRLG_L2.CPP +D:\diablo97\DRLG_L2.CPP +D:\diablo97\DRLG_L2.CPP +Levels\L2Data\Blind2.DUN +D:\diablo97\DRLG_L2.CPP +Levels\L2Data\Blood1.DUN +D:\diablo97\DRLG_L2.CPP +Levels\L2Data\Bonestr2.DUN +D:\diablo97\DRLG_L2.CPP +D:\diablo97\DRLG_L2.CPP +D:\diablo97\DRLG_L2.CPP +D:\diablo97\DRLG_L2.CPP +REGISTRATION_BLOCK +D:\diablo97\DRLG_L3.CPP +D:\diablo97\DRLG_L3.CPP +D:\diablo97\DRLG_L3.CPP +D:\diablo97\DRLG_L3.CPP +gbMaxPlayers == 1 +D:\diablo97\drlg_l4.cpp +D:\diablo97\drlg_l4.cpp +Levels\L4Data\Warlord.DUN +D:\diablo97\drlg_l4.cpp +Levels\L4Data\Vile1.DUN +D:\diablo97\drlg_l4.cpp +D:\diablo97\drlg_l4.cpp +Levels\L4Data\diab1.DUN +D:\diablo97\drlg_l4.cpp +D:\diablo97\drlg_l4.cpp +Levels\L4Data\diab2b.DUN +D:\diablo97\drlg_l4.cpp +Levels\L4Data\diab2a.DUN +D:\diablo97\drlg_l4.cpp +D:\diablo97\drlg_l4.cpp +Levels\L4Data\diab3b.DUN +D:\diablo97\drlg_l4.cpp +Levels\L4Data\diab3a.DUN +D:\diablo97\drlg_l4.cpp +D:\diablo97\drlg_l4.cpp +Levels\L4Data\diab4b.DUN +D:\diablo97\drlg_l4.cpp +Levels\L4Data\diab4a.DUN +D:\diablo97\drlg_l4.cpp +gbMaxPlayers == 1 +D:\diablo97\drlg_l4.cpp +gpBuffer +D:\diablo97\drlg_l4.cpp +pnum != myplr +D:\diablo97\dthread.cpp +pbSrc +D:\diablo97\dthread.cpp +dwLen +D:\diablo97\dthread.cpp +D:\diablo97\dthread.cpp +sghThread == INVALID_HANDLE_VALUE +D:\diablo97\dthread.cpp +! sgpInfoHead +D:\diablo97\dthread.cpp +! sghWorkToDoEvent +D:\diablo97\dthread.cpp +dthread:1 +sghThread == INVALID_HANDLE_VALUE +D:\diablo97\dthread.cpp +dthread2: +dthread4: +gdwDeltaBytesSec +D:\diablo97\dthread.cpp +D:\diablo97\dthread.cpp +d:%u +dthread3: +(%s) +D:\diablo97\dthread.cpp +! gpBuffer +D:\diablo97\dx.cpp +! sgdwLockCount +D:\diablo97\dx.cpp +! sgpBackBuf +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +bSuccess +D:\diablo97\dx.cpp +! gpBuffer +D:\diablo97\dx.cpp +! sgdwLockCount +D:\diablo97\dx.cpp +! sgpBackBuf +D:\diablo97\dx.cpp +lpDDSPrimary +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +caps.dwCaps & DDSCAPS_PRIMARYSURFACE +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +ddraw.dll +D:\diablo97\dx.cpp +DirectDrawCreate +D:\diablo97\dx.cpp +lock_buf_priv +D:\diablo97\dx.cpp +gpBuffer +D:\diablo97\dx.cpp +Draw lock underflow: 0x%x +draw main unlock error +draw consistency error +lpDDSBackBuf +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +! lpDDSBackBuf +D:\diablo97\dx.cpp +D:\diablo97\dx.cpp +ghMainWnd +D:\diablo97\dx.cpp +Sfx\Misc\Walk1.wav +Sfx\Misc\Walk2.wav +Sfx\Misc\Walk3.wav +Sfx\Misc\Walk4.wav +Sfx\Misc\BFire.wav +Sfx\Misc\Fmag.wav +Sfx\Misc\Tmag.wav +Sfx\Misc\Lghit.wav +Sfx\Misc\Lghit1.wav +Sfx\Misc\Swing.wav +Sfx\Misc\Swing2.wav +Sfx\Misc\Dead.wav +Sfx\Misc\Sting1.wav +Sfx\Misc\FBallBow.wav +Sfx\Misc\Questdon.wav +Sfx\Items\Armrfkd.wav +Sfx\Items\Barlfire.wav +Sfx\Items\Barrel.wav +Sfx\Items\PodPop8.wav +Sfx\Items\PodPop5.wav +Sfx\Items\UrnPop3.wav +Sfx\Items\UrnPop2.wav +Sfx\Items\Bhit.wav +Sfx\Items\Bhit1.wav +Sfx\Items\Chest.wav +Sfx\Items\Doorclos.wav +Sfx\Items\Dooropen.wav +Sfx\Items\Flipanvl.wav +Sfx\Items\Flipaxe.wav +Sfx\Items\Flipblst.wav +Sfx\Items\Flipbody.wav +Sfx\Items\Flipbook.wav +Sfx\Items\Flipbow.wav +Sfx\Items\Flipcap.wav +Sfx\Items\Flipharm.wav +Sfx\Items\Fliplarm.wav +Sfx\Items\Flipmag.wav +Sfx\Items\Flipmag1.wav +Sfx\Items\Flipmush.wav +Sfx\Items\Flippot.wav +Sfx\Items\Flipring.wav +Sfx\Items\Fliprock.wav +Sfx\Items\Flipscrl.wav +Sfx\Items\Flipshld.wav +Sfx\Items\Flipsign.wav +Sfx\Items\Flipstaf.wav +Sfx\Items\Flipswor.wav +Sfx\Items\Gold.wav +Sfx\Items\Hlmtfkd.wav +Sfx\Items\Invanvl.wav +Sfx\Items\Invaxe.wav +Sfx\Items\Invblst.wav +Sfx\Items\Invbody.wav +Sfx\Items\Invbook.wav +Sfx\Items\Invbow.wav +Sfx\Items\Invcap.wav +Sfx\Items\Invgrab.wav +Sfx\Items\Invharm.wav +Sfx\Items\Invlarm.wav +Sfx\Items\Invmush.wav +Sfx\Items\Invpot.wav +Sfx\Items\Invring.wav +Sfx\Items\Invrock.wav +Sfx\Items\Invscrol.wav +Sfx\Items\Invshiel.wav +Sfx\Items\Invsign.wav +Sfx\Items\Invstaf.wav +Sfx\Items\Invsword.wav +Sfx\Items\Lever.wav +Sfx\Items\Magic.wav +Sfx\Items\Magic1.wav +Sfx\Items\Readbook.wav +Sfx\Items\Sarc.wav +Sfx\Items\Shielfkd.wav +Sfx\Items\Swrdfkd.wav +Sfx\Items\Titlemov.wav +Sfx\Items\Titlslct.wav +Sfx\Misc\blank.wav +Sfx\Items\Trap.wav +Sfx\Misc\Cast1.wav +Sfx\Misc\Cast10.wav +Sfx\Misc\Cast12.wav +Sfx\Misc\Cast2.wav +Sfx\Misc\Cast3.wav +Sfx\Misc\Cast4.wav +Sfx\Misc\Cast5.wav +Sfx\Misc\Cast6.wav +Sfx\Misc\Cast7.wav +Sfx\Misc\Cast8.wav +Sfx\Misc\Cast9.wav +Sfx\Misc\Healing.wav +Sfx\Misc\Repair.wav +Sfx\Misc\Acids1.wav +Sfx\Misc\Acids2.wav +Sfx\Misc\Apoc.wav +Sfx\Misc\Arrowall.wav +Sfx\Misc\Bldboil.wav +Sfx\Misc\Blodstar.wav +Sfx\Misc\Blsimpt.wav +Sfx\Misc\Bonesp.wav +Sfx\Misc\Bsimpct.wav +Sfx\Misc\Caldron.wav +Sfx\Misc\Cbolt.wav +Sfx\Misc\Chltning.wav +Sfx\Misc\DSerp.wav +Sfx\Misc\Elecimp1.wav +Sfx\Misc\Elementl.wav +Sfx\Misc\Ethereal.wav +Sfx\Misc\Fball.wav +Sfx\Misc\Fbolt1.wav +Sfx\Misc\Fbolt2.wav +Sfx\Misc\Firimp1.wav +Sfx\Misc\Firimp2.wav +Sfx\Misc\Flamwave.wav +Sfx\Misc\Flash.wav +Sfx\Misc\Fountain.wav +Sfx\Misc\Golum.wav +Sfx\Misc\Golumded.wav +Sfx\Misc\Gshrine.wav +Sfx\Misc\Guard.wav +Sfx\Misc\Grdlanch.wav +Sfx\Misc\Holybolt.wav +Sfx\Misc\Hyper.wav +Sfx\Misc\Infravis.wav +Sfx\Misc\Invisibl.wav +Sfx\Misc\Invpot.wav +Sfx\Misc\Lning1.wav +Sfx\Misc\Ltning.wav +Sfx\Misc\Mshield.wav +Sfx\Misc\NestXpld.wav +Sfx\Misc\Nova.wav +Sfx\Misc\Portal.wav +Sfx\Misc\Puddle.wav +Sfx\Misc\Resur.wav +Sfx\Misc\Scurse.wav +Sfx\Misc\Scurimp.wav +Sfx\Misc\Sentinel.wav +Sfx\Misc\Shatter.wav +Sfx\Misc\Soulfire.wav +Sfx\Misc\Spoutlop.wav +Sfx\Misc\Spoutstr.wav +Sfx\Misc\Storm.wav +Sfx\Misc\Trapdis.wav +Sfx\Misc\Teleport.wav +Sfx\Misc\Vtheft.wav +Sfx\Misc\Wallloop.wav +Sfx\Misc\Wallstrt.wav +Sfx\Misc\LMag.wav +Sfx\Towners\Bmaid01.wav +Sfx\Towners\Bmaid02.wav +Sfx\Towners\Bmaid03.wav +Sfx\Towners\Bmaid04.wav +Sfx\Towners\Bmaid05.wav +Sfx\Towners\Bmaid06.wav +Sfx\Towners\Bmaid07.wav +Sfx\Towners\Bmaid08.wav +Sfx\Towners\Bmaid09.wav +Sfx\Towners\Bmaid10.wav +Sfx\Towners\Bmaid11.wav +Sfx\Towners\Bmaid12.wav +Sfx\Towners\Bmaid13.wav +Sfx\Towners\Bmaid14.wav +Sfx\Towners\Bmaid15.wav +Sfx\Towners\Bmaid16.wav +Sfx\Towners\Bmaid17.wav +Sfx\Towners\Bmaid18.wav +Sfx\Towners\Bmaid19.wav +Sfx\Towners\Bmaid20.wav +Sfx\Towners\Bmaid21.wav +Sfx\Towners\Bmaid22.wav +Sfx\Towners\Bmaid23.wav +Sfx\Towners\Bmaid24.wav +Sfx\Towners\Bmaid25.wav +Sfx\Towners\Bmaid26.wav +Sfx\Towners\Bmaid27.wav +Sfx\Towners\Bmaid28.wav +Sfx\Towners\Bmaid29.wav +Sfx\Towners\Bmaid30.wav +Sfx\Towners\Bmaid31.wav +Sfx\Towners\Bmaid32.wav +Sfx\Towners\Bmaid33.wav +Sfx\Towners\Bmaid34.wav +Sfx\Towners\Bmaid35.wav +Sfx\Towners\Bmaid36.wav +Sfx\Towners\Bmaid37.wav +Sfx\Towners\Bmaid38.wav +Sfx\Towners\Bmaid39.wav +Sfx\Towners\Bmaid40.wav +Sfx\Towners\Bsmith01.wav +Sfx\Towners\Bsmith02.wav +Sfx\Towners\Bsmith03.wav +Sfx\Towners\Bsmith04.wav +Sfx\Towners\Bsmith05.wav +Sfx\Towners\Bsmith06.wav +Sfx\Towners\Bsmith07.wav +Sfx\Towners\Bsmith08.wav +Sfx\Towners\Bsmith09.wav +Sfx\Towners\Bsmith10.wav +Sfx\Towners\Bsmith11.wav +Sfx\Towners\Bsmith12.wav +Sfx\Towners\Bsmith13.wav +Sfx\Towners\Bsmith14.wav +Sfx\Towners\Bsmith15.wav +Sfx\Towners\Bsmith16.wav +Sfx\Towners\Bsmith17.wav +Sfx\Towners\Bsmith18.wav +Sfx\Towners\Bsmith19.wav +Sfx\Towners\Bsmith20.wav +Sfx\Towners\Bsmith21.wav +Sfx\Towners\Bsmith22.wav +Sfx\Towners\Bsmith23.wav +Sfx\Towners\Bsmith24.wav +Sfx\Towners\Bsmith25.wav +Sfx\Towners\Bsmith26.wav +Sfx\Towners\Bsmith27.wav +Sfx\Towners\Bsmith28.wav +Sfx\Towners\Bsmith29.wav +Sfx\Towners\Bsmith30.wav +Sfx\Towners\Bsmith31.wav +Sfx\Towners\Bsmith32.wav +Sfx\Towners\Bsmith33.wav +Sfx\Towners\Bsmith34.wav +Sfx\Towners\Bsmith35.wav +Sfx\Towners\Bsmith36.wav +Sfx\Towners\Bsmith37.wav +Sfx\Towners\Bsmith38.wav +Sfx\Towners\Bsmith39.wav +Sfx\Towners\Bsmith40.wav +Sfx\Towners\Bsmith41.wav +Sfx\Towners\Bsmith42.wav +Sfx\Towners\Bsmith43.wav +Sfx\Towners\Bsmith44.wav +Sfx\Towners\Bsmith45.wav +Sfx\Towners\Bsmith46.wav +Sfx\Towners\Bsmith47.wav +Sfx\Towners\Bsmith48.wav +Sfx\Towners\Bsmith49.wav +Sfx\Towners\Bsmith50.wav +Sfx\Towners\Bsmith51.wav +Sfx\Towners\Bsmith52.wav +Sfx\Towners\Bsmith53.wav +Sfx\Towners\Bsmith54.wav +Sfx\Towners\Bsmith55.wav +Sfx\Towners\Bsmith56.wav +Sfx\Towners\Cow1.wav +Sfx\Towners\Cow2.wav +Sfx\Towners\Deadguy2.wav +Sfx\Towners\Drunk01.wav +Sfx\Towners\Drunk02.wav +Sfx\Towners\Drunk03.wav +Sfx\Towners\Drunk04.wav +Sfx\Towners\Drunk05.wav +Sfx\Towners\Drunk06.wav +Sfx\Towners\Drunk07.wav +Sfx\Towners\Drunk08.wav +Sfx\Towners\Drunk09.wav +Sfx\Towners\Drunk10.wav +Sfx\Towners\Drunk11.wav +Sfx\Towners\Drunk12.wav +Sfx\Towners\Drunk13.wav +Sfx\Towners\Drunk14.wav +Sfx\Towners\Drunk15.wav +Sfx\Towners\Drunk16.wav +Sfx\Towners\Drunk17.wav +Sfx\Towners\Drunk18.wav +Sfx\Towners\Drunk19.wav +Sfx\Towners\Drunk20.wav +Sfx\Towners\Drunk21.wav +Sfx\Towners\Drunk22.wav +Sfx\Towners\Drunk23.wav +Sfx\Towners\Drunk24.wav +Sfx\Towners\Drunk25.wav +Sfx\Towners\Drunk26.wav +Sfx\Towners\Drunk27.wav +Sfx\Towners\Drunk28.wav +Sfx\Towners\Drunk29.wav +Sfx\Towners\Drunk30.wav +Sfx\Towners\Drunk31.wav +Sfx\Towners\Drunk32.wav +Sfx\Towners\Drunk33.wav +Sfx\Towners\Drunk34.wav +Sfx\Towners\Drunk35.wav +Sfx\Towners\Healer01.wav +Sfx\Towners\Healer02.wav +Sfx\Towners\Healer03.wav +Sfx\Towners\Healer04.wav +Sfx\Towners\Healer05.wav +Sfx\Towners\Healer06.wav +Sfx\Towners\Healer07.wav +Sfx\Towners\Healer08.wav +Sfx\Towners\Healer09.wav +Sfx\Towners\Healer10.wav +Sfx\Towners\Healer11.wav +Sfx\Towners\Healer12.wav +Sfx\Towners\Healer13.wav +Sfx\Towners\Healer14.wav +Sfx\Towners\Healer15.wav +Sfx\Towners\Healer16.wav +Sfx\Towners\Healer17.wav +Sfx\Towners\Healer18.wav +Sfx\Towners\Healer19.wav +Sfx\Towners\Healer20.wav +Sfx\Towners\Healer21.wav +Sfx\Towners\Healer22.wav +Sfx\Towners\Healer23.wav +Sfx\Towners\Healer24.wav +Sfx\Towners\Healer25.wav +Sfx\Towners\Healer26.wav +Sfx\Towners\Healer27.wav +Sfx\Towners\Healer28.wav +Sfx\Towners\Healer29.wav +Sfx\Towners\Healer30.wav +Sfx\Towners\Healer31.wav +Sfx\Towners\Healer32.wav +Sfx\Towners\Healer33.wav +Sfx\Towners\Healer34.wav +Sfx\Towners\Healer35.wav +Sfx\Towners\Healer36.wav +Sfx\Towners\Healer37.wav +Sfx\Towners\Healer38.wav +Sfx\Towners\Healer39.wav +Sfx\Towners\Healer40.wav +Sfx\Towners\Healer41.wav +Sfx\Towners\Healer42.wav +Sfx\Towners\Healer43.wav +Sfx\Towners\Healer44.wav +Sfx\Towners\Healer45.wav +Sfx\Towners\Healer46.wav +Sfx\Towners\Healer47.wav +Sfx\Towners\Pegboy01.wav +Sfx\Towners\Pegboy02.wav +Sfx\Towners\Pegboy03.wav +Sfx\Towners\Pegboy04.wav +Sfx\Towners\Pegboy05.wav +Sfx\Towners\Pegboy06.wav +Sfx\Towners\Pegboy07.wav +Sfx\Towners\Pegboy08.wav +Sfx\Towners\Pegboy09.wav +Sfx\Towners\Pegboy10.wav +Sfx\Towners\Pegboy11.wav +Sfx\Towners\Pegboy12.wav +Sfx\Towners\Pegboy13.wav +Sfx\Towners\Pegboy14.wav +Sfx\Towners\Pegboy15.wav +Sfx\Towners\Pegboy16.wav +Sfx\Towners\Pegboy17.wav +Sfx\Towners\Pegboy18.wav +Sfx\Towners\Pegboy19.wav +Sfx\Towners\Pegboy20.wav +Sfx\Towners\Pegboy21.wav +Sfx\Towners\Pegboy22.wav +Sfx\Towners\Pegboy23.wav +Sfx\Towners\Pegboy24.wav +Sfx\Towners\Pegboy25.wav +Sfx\Towners\Pegboy26.wav +Sfx\Towners\Pegboy27.wav +Sfx\Towners\Pegboy28.wav +Sfx\Towners\Pegboy29.wav +Sfx\Towners\Pegboy30.wav +Sfx\Towners\Pegboy31.wav +Sfx\Towners\Pegboy32.wav +Sfx\Towners\Pegboy33.wav +Sfx\Towners\Pegboy34.wav +Sfx\Towners\Pegboy35.wav +Sfx\Towners\Pegboy36.wav +Sfx\Towners\Pegboy37.wav +Sfx\Towners\Pegboy38.wav +Sfx\Towners\Pegboy39.wav +Sfx\Towners\Pegboy40.wav +Sfx\Towners\Pegboy41.wav +Sfx\Towners\Pegboy42.wav +Sfx\Towners\Pegboy43.wav +Sfx\Towners\Priest00.wav +Sfx\Towners\Priest01.wav +Sfx\Towners\Priest02.wav +Sfx\Towners\Priest03.wav +Sfx\Towners\Priest04.wav +Sfx\Towners\Priest05.wav +Sfx\Towners\Priest06.wav +Sfx\Towners\Priest07.wav +Sfx\Towners\Storyt00.wav +Sfx\Towners\Storyt01.wav +Sfx\Towners\Storyt02.wav +Sfx\Towners\Storyt03.wav +Sfx\Towners\Storyt04.wav +Sfx\Towners\Storyt05.wav +Sfx\Towners\Storyt06.wav +Sfx\Towners\Storyt07.wav +Sfx\Towners\Storyt08.wav +Sfx\Towners\Storyt09.wav +Sfx\Towners\Storyt10.wav +Sfx\Towners\Storyt11.wav +Sfx\Towners\Storyt12.wav +Sfx\Towners\Storyt13.wav +Sfx\Towners\Storyt14.wav +Sfx\Towners\Storyt15.wav +Sfx\Towners\Storyt16.wav +Sfx\Towners\Storyt17.wav +Sfx\Towners\Storyt18.wav +Sfx\Towners\Storyt19.wav +Sfx\Towners\Storyt20.wav +Sfx\Towners\Storyt21.wav +Sfx\Towners\Storyt22.wav +Sfx\Towners\Storyt23.wav +Sfx\Towners\Storyt24.wav +Sfx\Towners\Storyt25.wav +Sfx\Towners\Storyt26.wav +Sfx\Towners\Storyt27.wav +Sfx\Towners\Storyt28.wav +Sfx\Towners\Storyt29.wav +Sfx\Towners\Storyt30.wav +Sfx\Towners\Storyt31.wav +Sfx\Towners\Storyt32.wav +Sfx\Towners\Storyt33.wav +Sfx\Towners\Storyt34.wav +Sfx\Towners\Storyt35.wav +Sfx\Towners\Storyt36.wav +Sfx\Towners\Storyt37.wav +Sfx\Towners\Storyt38.wav +Sfx\Towners\Tavown00.wav +Sfx\Towners\Tavown01.wav +Sfx\Towners\Tavown02.wav +Sfx\Towners\Tavown03.wav +Sfx\Towners\Tavown04.wav +Sfx\Towners\Tavown05.wav +Sfx\Towners\Tavown06.wav +Sfx\Towners\Tavown07.wav +Sfx\Towners\Tavown08.wav +Sfx\Towners\Tavown09.wav +Sfx\Towners\Tavown10.wav +Sfx\Towners\Tavown11.wav +Sfx\Towners\Tavown12.wav +Sfx\Towners\Tavown13.wav +Sfx\Towners\Tavown14.wav +Sfx\Towners\Tavown15.wav +Sfx\Towners\Tavown16.wav +Sfx\Towners\Tavown17.wav +Sfx\Towners\Tavown18.wav +Sfx\Towners\Tavown19.wav +Sfx\Towners\Tavown20.wav +Sfx\Towners\Tavown21.wav +Sfx\Towners\Tavown22.wav +Sfx\Towners\Tavown23.wav +Sfx\Towners\Tavown24.wav +Sfx\Towners\Tavown25.wav +Sfx\Towners\Tavown26.wav +Sfx\Towners\Tavown27.wav +Sfx\Towners\Tavown28.wav +Sfx\Towners\Tavown29.wav +Sfx\Towners\Tavown30.wav +Sfx\Towners\Tavown31.wav +Sfx\Towners\Tavown32.wav +Sfx\Towners\Tavown33.wav +Sfx\Towners\Tavown34.wav +Sfx\Towners\Tavown35.wav +Sfx\Towners\Tavown36.wav +Sfx\Towners\Tavown37.wav +Sfx\Towners\Tavown38.wav +Sfx\Towners\Tavown39.wav +Sfx\Towners\Tavown40.wav +Sfx\Towners\Tavown41.wav +Sfx\Towners\Tavown42.wav +Sfx\Towners\Tavown43.wav +Sfx\Towners\Tavown44.wav +Sfx\Towners\Tavown45.wav +Sfx\Towners\Witch01.wav +Sfx\Towners\Witch02.wav +Sfx\Towners\Witch03.wav +Sfx\Towners\Witch04.wav +Sfx\Towners\Witch05.wav +Sfx\Towners\Witch06.wav +Sfx\Towners\Witch07.wav +Sfx\Towners\Witch08.wav +Sfx\Towners\Witch09.wav +Sfx\Towners\Witch10.wav +Sfx\Towners\Witch11.wav +Sfx\Towners\Witch12.wav +Sfx\Towners\Witch13.wav +Sfx\Towners\Witch14.wav +Sfx\Towners\Witch15.wav +Sfx\Towners\Witch16.wav +Sfx\Towners\Witch17.wav +Sfx\Towners\Witch18.wav +Sfx\Towners\Witch19.wav +Sfx\Towners\Witch20.wav +Sfx\Towners\Witch21.wav +Sfx\Towners\Witch22.wav +Sfx\Towners\Witch23.wav +Sfx\Towners\Witch24.wav +Sfx\Towners\Witch25.wav +Sfx\Towners\Witch26.wav +Sfx\Towners\Witch27.wav +Sfx\Towners\Witch28.wav +Sfx\Towners\Witch29.wav +Sfx\Towners\Witch30.wav +Sfx\Towners\Witch31.wav +Sfx\Towners\Witch32.wav +Sfx\Towners\Witch33.wav +Sfx\Towners\Witch34.wav +Sfx\Towners\Witch35.wav +Sfx\Towners\Witch36.wav +Sfx\Towners\Witch37.wav +Sfx\Towners\Witch38.wav +Sfx\Towners\Witch39.wav +Sfx\Towners\Witch40.wav +Sfx\Towners\Witch41.wav +Sfx\Towners\Witch42.wav +Sfx\Towners\Witch43.wav +Sfx\Towners\Witch44.wav +Sfx\Towners\Witch45.wav +Sfx\Towners\Witch46.wav +Sfx\Towners\Witch47.wav +Sfx\Towners\Witch48.wav +Sfx\Towners\Witch49.wav +Sfx\Towners\Witch50.wav +Sfx\Towners\Wound01.wav +Sfx\Sorceror\Mage01.wav +Sfx\Sorceror\Mage02.wav +Sfx\Sorceror\Mage03.wav +Sfx\Sorceror\Mage04.wav +Sfx\Sorceror\Mage05.wav +Sfx\Sorceror\Mage06.wav +Sfx\Sorceror\Mage07.wav +Sfx\Sorceror\Mage08.wav +Sfx\Sorceror\Mage09.wav +Sfx\Sorceror\Mage10.wav +Sfx\Sorceror\Mage11.wav +Sfx\Sorceror\Mage12.wav +Sfx\Sorceror\Mage13.wav +Sfx\Sorceror\Mage14.wav +Sfx\Sorceror\Mage15.wav +Sfx\Sorceror\Mage16.wav +Sfx\Sorceror\Mage17.wav +Sfx\Sorceror\Mage18.wav +Sfx\Sorceror\Mage19.wav +Sfx\Sorceror\Mage20.wav +Sfx\Sorceror\Mage21.wav +Sfx\Sorceror\Mage22.wav +Sfx\Sorceror\Mage23.wav +Sfx\Sorceror\Mage24.wav +Sfx\Sorceror\Mage25.wav +Sfx\Sorceror\Mage26.wav +Sfx\Sorceror\Mage27.wav +Sfx\Sorceror\Mage28.wav +Sfx\Sorceror\Mage29.wav +Sfx\Sorceror\Mage30.wav +Sfx\Sorceror\Mage31.wav +Sfx\Sorceror\Mage32.wav +Sfx\Sorceror\Mage33.wav +Sfx\Sorceror\Mage34.wav +Sfx\Sorceror\Mage35.wav +Sfx\Sorceror\Mage36.wav +Sfx\Sorceror\Mage37.wav +Sfx\Sorceror\Mage38.wav +Sfx\Sorceror\Mage39.wav +Sfx\Sorceror\Mage40.wav +Sfx\Sorceror\Mage41.wav +Sfx\Sorceror\Mage42.wav +Sfx\Sorceror\Mage43.wav +Sfx\Sorceror\Mage44.wav +Sfx\Sorceror\Mage45.wav +Sfx\Sorceror\Mage46.wav +Sfx\Sorceror\Mage47.wav +Sfx\Sorceror\Mage48.wav +Sfx\Sorceror\Mage49.wav +Sfx\Sorceror\Mage50.wav +Sfx\Sorceror\Mage51.wav +Sfx\Sorceror\Mage52.wav +Sfx\Sorceror\Mage53.wav +Sfx\Sorceror\Mage54.wav +Sfx\Sorceror\Mage55.wav +Sfx\Sorceror\Mage56.wav +Sfx\Sorceror\Mage57.wav +Sfx\Sorceror\Mage58.wav +Sfx\Sorceror\Mage59.wav +Sfx\Sorceror\Mage60.wav +Sfx\Sorceror\Mage61.wav +Sfx\Sorceror\Mage62.wav +Sfx\Sorceror\Mage63.wav +Sfx\Sorceror\Mage64.wav +Sfx\Sorceror\Mage65.wav +Sfx\Sorceror\Mage66.wav +Sfx\Sorceror\Mage67.wav +Sfx\Sorceror\Mage68.wav +Sfx\Sorceror\Mage69.wav +Sfx\Sorceror\Mage69b.wav +Sfx\Sorceror\Mage70.wav +Sfx\Sorceror\Mage71.wav +Sfx\Sorceror\Mage72.wav +Sfx\Sorceror\Mage73.wav +Sfx\Sorceror\Mage74.wav +Sfx\Sorceror\Mage75.wav +Sfx\Sorceror\Mage76.wav +Sfx\Sorceror\Mage77.wav +Sfx\Sorceror\Mage78.wav +Sfx\Sorceror\Mage79.wav +Sfx\Sorceror\Mage80.wav +Sfx\Sorceror\Mage81.wav +Sfx\Sorceror\Mage82.wav +Sfx\Sorceror\Mage83.wav +Sfx\Sorceror\Mage84.wav +Sfx\Sorceror\Mage85.wav +Sfx\Sorceror\Mage86.wav +Sfx\Sorceror\Mage87.wav +Sfx\Sorceror\Mage88.wav +Sfx\Sorceror\Mage89.wav +Sfx\Sorceror\Mage90.wav +Sfx\Sorceror\Mage91.wav +Sfx\Sorceror\Mage92.wav +Sfx\Sorceror\Mage93.wav +Sfx\Sorceror\Mage94.wav +Sfx\Sorceror\Mage95.wav +Sfx\Sorceror\Mage96.wav +Sfx\Sorceror\Mage97.wav +Sfx\Sorceror\Mage98.wav +Sfx\Sorceror\Mage99.wav +Sfx\Sorceror\Mage100.wav +Sfx\Sorceror\Mage101.wav +Sfx\Sorceror\Mage102.wav +Sfx\Rogue\Rogue01.wav +Sfx\Rogue\Rogue02.wav +Sfx\Rogue\Rogue03.wav +Sfx\Rogue\Rogue04.wav +Sfx\Rogue\Rogue05.wav +Sfx\Rogue\Rogue06.wav +Sfx\Rogue\Rogue07.wav +Sfx\Rogue\Rogue08.wav +Sfx\Rogue\Rogue09.wav +Sfx\Rogue\Rogue10.wav +Sfx\Rogue\Rogue11.wav +Sfx\Rogue\Rogue12.wav +Sfx\Rogue\Rogue13.wav +Sfx\Rogue\Rogue14.wav +Sfx\Rogue\Rogue15.wav +Sfx\Rogue\Rogue16.wav +Sfx\Rogue\Rogue17.wav +Sfx\Rogue\Rogue18.wav +Sfx\Rogue\Rogue19.wav +Sfx\Rogue\Rogue20.wav +Sfx\Rogue\Rogue21.wav +Sfx\Rogue\Rogue22.wav +Sfx\Rogue\Rogue23.wav +Sfx\Rogue\Rogue24.wav +Sfx\Rogue\Rogue25.wav +Sfx\Rogue\Rogue26.wav +Sfx\Rogue\Rogue27.wav +Sfx\Rogue\Rogue28.wav +Sfx\Rogue\Rogue29.wav +Sfx\Rogue\Rogue30.wav +Sfx\Rogue\Rogue31.wav +Sfx\Rogue\Rogue32.wav +Sfx\Rogue\Rogue33.wav +Sfx\Rogue\Rogue34.wav +Sfx\Rogue\Rogue35.wav +Sfx\Rogue\Rogue36.wav +Sfx\Rogue\Rogue37.wav +Sfx\Rogue\Rogue38.wav +Sfx\Rogue\Rogue39.wav +Sfx\Rogue\Rogue40.wav +Sfx\Rogue\Rogue41.wav +Sfx\Rogue\Rogue42.wav +Sfx\Rogue\Rogue43.wav +Sfx\Rogue\Rogue44.wav +Sfx\Rogue\Rogue45.wav +Sfx\Rogue\Rogue46.wav +Sfx\Rogue\Rogue47.wav +Sfx\Rogue\Rogue48.wav +Sfx\Rogue\Rogue49.wav +Sfx\Rogue\Rogue50.wav +Sfx\Rogue\Rogue51.wav +Sfx\Rogue\Rogue52.wav +Sfx\Rogue\Rogue53.wav +Sfx\Rogue\Rogue54.wav +Sfx\Rogue\Rogue55.wav +Sfx\Rogue\Rogue56.wav +Sfx\Rogue\Rogue57.wav +Sfx\Rogue\Rogue58.wav +Sfx\Rogue\Rogue59.wav +Sfx\Rogue\Rogue60.wav +Sfx\Rogue\Rogue61.wav +Sfx\Rogue\Rogue62.wav +Sfx\Rogue\Rogue63.wav +Sfx\Rogue\Rogue64.wav +Sfx\Rogue\Rogue65.wav +Sfx\Rogue\Rogue66.wav +Sfx\Rogue\Rogue67.wav +Sfx\Rogue\Rogue68.wav +Sfx\Rogue\Rogue69.wav +Sfx\Rogue\Rogue69b.wav +Sfx\Rogue\Rogue70.wav +Sfx\Rogue\Rogue71.wav +Sfx\Rogue\Rogue72.wav +Sfx\Rogue\Rogue73.wav +Sfx\Rogue\Rogue74.wav +Sfx\Rogue\Rogue75.wav +Sfx\Rogue\Rogue76.wav +Sfx\Rogue\Rogue77.wav +Sfx\Rogue\Rogue78.wav +Sfx\Rogue\Rogue79.wav +Sfx\Rogue\Rogue80.wav +Sfx\Rogue\Rogue81.wav +Sfx\Rogue\Rogue82.wav +Sfx\Rogue\Rogue83.wav +Sfx\Rogue\Rogue84.wav +Sfx\Rogue\Rogue85.wav +Sfx\Rogue\Rogue86.wav +Sfx\Rogue\Rogue87.wav +Sfx\Rogue\Rogue88.wav +Sfx\Rogue\Rogue89.wav +Sfx\Rogue\Rogue90.wav +Sfx\Rogue\Rogue91.wav +Sfx\Rogue\Rogue92.wav +Sfx\Rogue\Rogue93.wav +Sfx\Rogue\Rogue94.wav +Sfx\Rogue\Rogue95.wav +Sfx\Rogue\Rogue96.wav +Sfx\Rogue\Rogue97.wav +Sfx\Rogue\Rogue98.wav +Sfx\Rogue\Rogue99.wav +Sfx\Rogue\Rogue100.wav +Sfx\Rogue\Rogue101.wav +Sfx\Rogue\Rogue102.wav +Sfx\Warrior\Warior01.wav +Sfx\Warrior\Warior02.wav +Sfx\Warrior\Warior03.wav +Sfx\Warrior\Warior04.wav +Sfx\Warrior\Warior05.wav +Sfx\Warrior\Warior06.wav +Sfx\Warrior\Warior07.wav +Sfx\Warrior\Warior08.wav +Sfx\Warrior\Warior09.wav +Sfx\Warrior\Warior10.wav +Sfx\Warrior\Warior11.wav +Sfx\Warrior\Warior12.wav +Sfx\Warrior\Warior13.wav +Sfx\Warrior\Warior14.wav +Sfx\Warrior\Wario14b.wav +Sfx\Warrior\Wario14c.wav +Sfx\Warrior\Warior15.wav +Sfx\Warrior\Wario15b.wav +Sfx\Warrior\Wario15c.wav +Sfx\Warrior\Warior16.wav +Sfx\Warrior\Wario16b.wav +Sfx\Warrior\Wario16c.wav +Sfx\Warrior\Warior17.wav +Sfx\Warrior\Warior18.wav +Sfx\Warrior\Warior19.wav +Sfx\Warrior\Warior20.wav +Sfx\Warrior\Warior21.wav +Sfx\Warrior\Warior22.wav +Sfx\Warrior\Warior23.wav +Sfx\Warrior\Warior24.wav +Sfx\Warrior\Warior25.wav +Sfx\Warrior\Warior26.wav +Sfx\Warrior\Warior27.wav +Sfx\Warrior\Warior28.wav +Sfx\Warrior\Warior29.wav +Sfx\Warrior\Warior30.wav +Sfx\Warrior\Warior31.wav +Sfx\Warrior\Warior32.wav +Sfx\Warrior\Warior33.wav +Sfx\Warrior\Warior34.wav +Sfx\Warrior\Warior35.wav +Sfx\Warrior\Warior36.wav +Sfx\Warrior\Warior37.wav +Sfx\Warrior\Warior38.wav +Sfx\Warrior\Warior39.wav +Sfx\Warrior\Warior40.wav +Sfx\Warrior\Warior41.wav +Sfx\Warrior\Warior42.wav +Sfx\Warrior\Warior43.wav +Sfx\Warrior\Warior44.wav +Sfx\Warrior\Warior45.wav +Sfx\Warrior\Warior46.wav +Sfx\Warrior\Warior47.wav +Sfx\Warrior\Warior48.wav +Sfx\Warrior\Warior49.wav +Sfx\Warrior\Warior50.wav +Sfx\Warrior\Warior51.wav +Sfx\Warrior\Warior52.wav +Sfx\Warrior\Warior53.wav +Sfx\Warrior\Warior54.wav +Sfx\Warrior\Warior55.wav +Sfx\Warrior\Warior56.wav +Sfx\Warrior\Warior57.wav +Sfx\Warrior\Warior58.wav +Sfx\Warrior\Warior59.wav +Sfx\Warrior\Warior60.wav +Sfx\Warrior\Warior61.wav +Sfx\Warrior\Warior62.wav +Sfx\Warrior\Warior63.wav +Sfx\Warrior\Warior64.wav +Sfx\Warrior\Warior65.wav +Sfx\Warrior\Warior66.wav +Sfx\Warrior\Warior67.wav +Sfx\Warrior\Warior68.wav +Sfx\Warrior\Warior69.wav +Sfx\Warrior\Wario69b.wav +Sfx\Warrior\Warior70.wav +Sfx\Warrior\Warior71.wav +Sfx\Warrior\Warior72.wav +Sfx\Warrior\Warior73.wav +Sfx\Warrior\Warior74.wav +Sfx\Warrior\Warior75.wav +Sfx\Warrior\Warior76.wav +Sfx\Warrior\Warior77.wav +Sfx\Warrior\Warior78.wav +Sfx\Warrior\Warior79.wav +Sfx\Warrior\Warior80.wav +Sfx\Warrior\Warior81.wav +Sfx\Warrior\Warior82.wav +Sfx\Warrior\Warior83.wav +Sfx\Warrior\Warior84.wav +Sfx\Warrior\Warior85.wav +Sfx\Warrior\Warior86.wav +Sfx\Warrior\Warior87.wav +Sfx\Warrior\Warior88.wav +Sfx\Warrior\Warior89.wav +Sfx\Warrior\Warior90.wav +Sfx\Warrior\Warior91.wav +Sfx\Warrior\Warior92.wav +Sfx\Warrior\Warior93.wav +Sfx\Warrior\Warior94.wav +Sfx\Warrior\Warior95.wav +Sfx\Warrior\Wario95b.wav +Sfx\Warrior\Wario95c.wav +Sfx\Warrior\Wario95d.wav +Sfx\Warrior\Wario95e.wav +Sfx\Warrior\Wario95f.wav +Sfx\Warrior\Wario96b.wav +Sfx\Warrior\Wario97.wav +Sfx\Warrior\Wario98.wav +Sfx\Warrior\Warior99.wav +Sfx\Warrior\Wario100.wav +Sfx\Warrior\Wario101.wav +Sfx\Warrior\Wario102.wav +Sfx\Monk\Monk01.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk08.wav +Sfx\Monk\Monk09.wav +Sfx\Monk\Monk10.wav +Sfx\Monk\Monk11.wav +Sfx\Monk\Monk12.wav +Sfx\Monk\Monk13.wav +Sfx\Monk\Monk14.wav +Sfx\Monk\Monk15.wav +Sfx\Monk\Monk16.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk24.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk27.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk29.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk34.wav +Sfx\Monk\Monk35.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk43.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk46.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk49.wav +Sfx\Monk\Monk50.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk52.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk54.wav +Sfx\Monk\Monk55.wav +Sfx\Monk\Monk56.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk61.wav +Sfx\Monk\Monk62.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk68.wav +Sfx\Monk\Monk69.wav +Sfx\Monk\Monk69b.wav +Sfx\Monk\Monk70.wav +Sfx\Monk\Monk71.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk79.wav +Sfx\Monk\Monk80.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk82.wav +Sfx\Monk\Monk83.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk87.wav +Sfx\Monk\Monk88.wav +Sfx\Monk\Monk89.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk91.wav +Sfx\Monk\Monk92.wav +Sfx\Misc\blank.wav +Sfx\Monk\Monk94.wav +Sfx\Monk\Monk95.wav +Sfx\Monk\Monk96.wav +Sfx\Monk\Monk97.wav +Sfx\Monk\Monk98.wav +Sfx\Monk\Monk99.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Misc\blank.wav +Sfx\Rogue\Rogue01.wav +Sfx\Rogue\Rogue02.wav +Sfx\Rogue\Rogue03.wav +Sfx\Rogue\Rogue04.wav +Sfx\Rogue\Rogue05.wav +Sfx\Rogue\Rogue06.wav +Sfx\Rogue\Rogue07.wav +Sfx\Rogue\Rogue08.wav +Sfx\Rogue\Rogue09.wav +Sfx\Rogue\Rogue10.wav +Sfx\Rogue\Rogue11.wav +Sfx\Rogue\Rogue12.wav +Sfx\Rogue\Rogue13.wav +Sfx\Rogue\Rogue14.wav +Sfx\Rogue\Rogue15.wav +Sfx\Rogue\Rogue16.wav +Sfx\Rogue\Rogue17.wav +Sfx\Rogue\Rogue18.wav +Sfx\Rogue\Rogue19.wav +Sfx\Rogue\Rogue20.wav +Sfx\Rogue\Rogue21.wav +Sfx\Rogue\Rogue22.wav +Sfx\Rogue\Rogue23.wav +Sfx\Rogue\Rogue24.wav +Sfx\Rogue\Rogue25.wav +Sfx\Rogue\Rogue26.wav +Sfx\Rogue\Rogue27.wav +Sfx\Rogue\Rogue28.wav +Sfx\Rogue\Rogue29.wav +Sfx\Rogue\Rogue30.wav +Sfx\Rogue\Rogue31.wav +Sfx\Rogue\Rogue32.wav +Sfx\Rogue\Rogue33.wav +Sfx\Rogue\Rogue34.wav +Sfx\Rogue\Rogue35.wav +Sfx\Rogue\Rogue36.wav +Sfx\Rogue\Rogue37.wav +Sfx\Rogue\Rogue38.wav +Sfx\Rogue\Rogue39.wav +Sfx\Rogue\Rogue40.wav +Sfx\Rogue\Rogue41.wav +Sfx\Rogue\Rogue42.wav +Sfx\Rogue\Rogue43.wav +Sfx\Rogue\Rogue44.wav +Sfx\Rogue\Rogue45.wav +Sfx\Rogue\Rogue46.wav +Sfx\Rogue\Rogue47.wav +Sfx\Rogue\Rogue48.wav +Sfx\Rogue\Rogue49.wav +Sfx\Rogue\Rogue50.wav +Sfx\Rogue\Rogue51.wav +Sfx\Rogue\Rogue52.wav +Sfx\Rogue\Rogue53.wav +Sfx\Rogue\Rogue54.wav +Sfx\Rogue\Rogue55.wav +Sfx\Rogue\Rogue56.wav +Sfx\Rogue\Rogue57.wav +Sfx\Rogue\Rogue58.wav +Sfx\Rogue\Rogue59.wav +Sfx\Rogue\Rogue60.wav +Sfx\Rogue\Rogue61.wav +Sfx\Rogue\Rogue62.wav +Sfx\Rogue\Rogue63.wav +Sfx\Rogue\Rogue64.wav +Sfx\Rogue\Rogue65.wav +Sfx\Rogue\Rogue66.wav +Sfx\Rogue\Rogue67.wav +Sfx\Rogue\Rogue68.wav +Sfx\Rogue\Rogue69.wav +Sfx\Rogue\Rogue69b.wav +Sfx\Rogue\Rogue70.wav +Sfx\Rogue\Rogue71.wav +Sfx\Rogue\Rogue72.wav +Sfx\Rogue\Rogue73.wav +Sfx\Rogue\Rogue74.wav +Sfx\Rogue\Rogue75.wav +Sfx\Rogue\Rogue76.wav +Sfx\Rogue\Rogue77.wav +Sfx\Rogue\Rogue78.wav +Sfx\Rogue\Rogue79.wav +Sfx\Rogue\Rogue80.wav +Sfx\Rogue\Rogue81.wav +Sfx\Rogue\Rogue82.wav +Sfx\Rogue\Rogue83.wav +Sfx\Rogue\Rogue84.wav +Sfx\Rogue\Rogue85.wav +Sfx\Rogue\Rogue86.wav +Sfx\Rogue\Rogue87.wav +Sfx\Rogue\Rogue88.wav +Sfx\Rogue\Rogue89.wav +Sfx\Rogue\Rogue90.wav +Sfx\Rogue\Rogue91.wav +Sfx\Rogue\Rogue92.wav +Sfx\Rogue\Rogue93.wav +Sfx\Rogue\Rogue94.wav +Sfx\Rogue\Rogue95.wav +Sfx\Rogue\Rogue96.wav +Sfx\Rogue\Rogue97.wav +Sfx\Rogue\Rogue98.wav +Sfx\Rogue\Rogue99.wav +Sfx\Rogue\Rogue100.wav +Sfx\Rogue\Rogue101.wav +Sfx\Rogue\Rogue102.wav +Sfx\Narrator\Nar01.wav +Sfx\Narrator\Nar02.wav +Sfx\Narrator\Nar03.wav +Sfx\Narrator\Nar04.wav +Sfx\Narrator\Nar05.wav +Sfx\Narrator\Nar06.wav +Sfx\Narrator\Nar07.wav +Sfx\Narrator\Nar08.wav +Sfx\Narrator\Nar09.wav +Sfx\Misc\Lvl16int.wav +Sfx\Monsters\Butcher.wav +Sfx\Monsters\Garbud01.wav +Sfx\Monsters\Garbud02.wav +Sfx\Monsters\Garbud03.wav +Sfx\Monsters\Garbud04.wav +Sfx\Monsters\Izual01.wav +Sfx\Monsters\Lach01.wav +Sfx\Monsters\Lach02.wav +Sfx\Monsters\Lach03.wav +Sfx\Monsters\Laz01.wav +Sfx\Monsters\Laz02.wav +Sfx\Monsters\Sking01.wav +Sfx\Monsters\Snot01.wav +Sfx\Monsters\Snot02.wav +Sfx\Monsters\Snot03.wav +Sfx\Monsters\Warlrd01.wav +Sfx\Monsters\Wlock01.wav +Sfx\Monsters\Zhar01.wav +Sfx\Monsters\Zhar02.wav +Sfx\Monsters\DiabloD.wav +Sfx\Hellfire\Farmer1.wav +Sfx\Hellfire\Farmer2.wav +Sfx\Hellfire\Farmer2A.wav +Sfx\Hellfire\Farmer3.wav +Sfx\Hellfire\Farmer4.wav +Sfx\Hellfire\Farmer5.wav +Sfx\Hellfire\Farmer6.wav +Sfx\Hellfire\Farmer7.wav +Sfx\Hellfire\Farmer8.wav +Sfx\Hellfire\Farmer9.wav +Sfx\Hellfire\TEDDYBR1.wav +Sfx\Hellfire\TEDDYBR2.wav +Sfx\Hellfire\TEDDYBR3.wav +Sfx\Hellfire\TEDDYBR4.wav +Sfx\Hellfire\DEFILER1.wav +Sfx\Hellfire\DEFILER2.wav +Sfx\Hellfire\DEFILER3.wav +Sfx\Hellfire\DEFILER4.wav +Sfx\Hellfire\DEFILER8.wav +Sfx\Hellfire\DEFILER6.wav +Sfx\Hellfire\DEFILER7.wav +Sfx\Hellfire\NAKRUL1.wav +Sfx\Hellfire\NAKRUL2.wav +Sfx\Hellfire\NAKRUL3.wav +Sfx\Hellfire\NAKRUL4.wav +Sfx\Hellfire\NAKRUL5.wav +Sfx\Hellfire\NARATR3.wav +Sfx\Hellfire\COWSUT1.wav +Sfx\Hellfire\COWSUT2.wav +Sfx\Hellfire\COWSUT3.wav +Sfx\Hellfire\COWSUT4.wav +Sfx\Hellfire\COWSUT4A.wav +Sfx\Hellfire\COWSUT5.wav +Sfx\Hellfire\COWSUT6.wav +Sfx\Hellfire\COWSUT7.wav +Sfx\Hellfire\COWSUT8.wav +Sfx\Hellfire\COWSUT9.wav +Sfx\Hellfire\COWSUT10.wav +Sfx\Hellfire\COWSUT11.wav +Sfx\Hellfire\COWSUT12.wav +Sfx\Hellfire\Skljrn1.wav +Sfx\Hellfire\Naratr6.wav +Sfx\Hellfire\Naratr7.wav +Sfx\Hellfire\Naratr8.wav +Sfx\Hellfire\Naratr5.wav +Sfx\Hellfire\Naratr9.wav +Sfx\Hellfire\Naratr4.wav +Sfx\Hellfire\TRADER1.wav +Sfx\Items\Cropen.wav +Sfx\Items\Crclos.wav +nSFX < NUM_SFX +D:\diablo97\effects.cpp +D:\diablo97\effects.cpp +D:\diablo97\effects.cpp +D:\diablo97\effects.cpp +Monster sound problem +:%s playing %i +psfx < NUM_SFX +D:\diablo97\effects.cpp +pSFX +D:\diablo97\effects.cpp +pSFX->bFlags & sfx_STREAM +D:\diablo97\effects.cpp +psfx < NUM_SFX +D:\diablo97\effects.cpp +effects:1 +D:\diablo97\encrypt.cpp +D:\diablo97\encrypt.cpp +D:\diablo97\encrypt.cpp +D:\diablo97\encrypt.cpp +D:\diablo97\encrypt.cpp +D:\diablo97\encrypt.cpp +info.destoffset <= dwMaxBytes +D:\diablo97\encrypt.cpp +D:\diablo97\encrypt.cpp +D:\diablo97\encrypt.cpp +REGISTRATION_BLOCK +pDecodeTo != NULL +D:\diablo97\ENGINE.CPP +pRLEBytes != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pBuff != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pBuff != NULL +D:\diablo97\ENGINE.CPP +pDecodeTo != NULL +D:\diablo97\ENGINE.CPP +pRLEBytes != NULL +D:\diablo97\ENGINE.CPP +pDecodeTo != NULL +D:\diablo97\ENGINE.CPP +pRLEBytes != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pBuff != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pDecodeTo != NULL +D:\diablo97\ENGINE.CPP +pRLEBytes != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pBuff != NULL +D:\diablo97\ENGINE.CPP +pDecodeTo != NULL +D:\diablo97\ENGINE.CPP +pRLEBytes != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pDecodeTo != NULL +D:\diablo97\ENGINE.CPP +pRLEBytes != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +pBuff != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +gpBuffer +D:\diablo97\ENGINE.CPP +c:\memdump.txt +sig most ever amount at max at end of game +------------------------------------------------------ +%4s 0x%08x 0x%08x %8dk %8d +D:\diablo97\ENGINE.CPP +------------------------------------------------ +max allocated 0x%08x %8dk +D:\diablo97\ENGINE.CPP +D:\diablo97\ENGINE.CPP +Bad signature unused: %s +memory block signature underflow: %s +memory free underflow +D:\diablo97\ENGINE.CPP +Memory block header corruption: %s +Memory block footer corruption: %s +Attempt to free memory with unknown signature %s +LoadFileInMem: %s:%d +Zero length SFILE: +pszName +D:\diablo97\ENGINE.CPP +LoadFileWithMem(NULL): +Zero length SFILE: +p != NULL +D:\diablo97\ENGINE.CPP +ttbl != NULL +D:\diablo97\ENGINE.CPP +nDataSize >= 0 +D:\diablo97\ENGINE.CPP +nDataSize >= 0 +D:\diablo97\ENGINE.CPP +nDataSize >= 0 +D:\diablo97\ENGINE.CPP +gpBuffer != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +nCel > 0 +D:\diablo97\ENGINE.CPP +nCel <= (int) pFrameTable[0] +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +gpBuffer != NULL +D:\diablo97\ENGINE.CPP +nCel > 0 +D:\diablo97\ENGINE.CPP +nCel <= (int) pFrameTable[0] +D:\diablo97\ENGINE.CPP +gpBuffer != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +nCel > 0 +D:\diablo97\ENGINE.CPP +nCel <= (int) pFrameTable[0] +D:\diablo97\ENGINE.CPP +gpBuffer != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +nCel > 0 +D:\diablo97\ENGINE.CPP +nCel <= (int) pFrameTable[0] +D:\diablo97\ENGINE.CPP +gpBuffer != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +nCel > 0 +D:\diablo97\ENGINE.CPP +nCel <= (int) pFrameTable[0] +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +gpBuffer != NULL +D:\diablo97\ENGINE.CPP +nCel > 0 +D:\diablo97\ENGINE.CPP +nCel <= (int) pFrameTable[0] +D:\diablo97\ENGINE.CPP +gpBuffer != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +nCel > 0 +D:\diablo97\ENGINE.CPP +nCel <= (int) pFrameTable[0] +D:\diablo97\ENGINE.CPP +gpBuffer != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +D:\diablo97\ENGINE.CPP +nCel > 0 +D:\diablo97\ENGINE.CPP +nCel <= (int) pFrameTable[0] +D:\diablo97\ENGINE.CPP +No automap available in town +No multiplayer functions in demo +Direct Sound Creation Failed +Not available in shareware version +Not enough space to save +No Pause in town +Copying to a hard disk is recommended +Multiplayer sync problem +No pause in multiplayer +Loading... +Saving... +Some are weakened as one grows strong +New strength is forged through destruction +Those who defend seldom attack +The sword of justice is swift and sharp +While the spirit is vigilant the body thrives +The powers of mana refocused renews +Time cannot diminish the power of steel +Magic is not always what it seems to be +What once was opened now is closed +Intensity comes at the cost of wisdom +Arcane power brings destruction +That which cannot be held cannot be harmed +Crimson and Azure become as the sun +Knowledge and wisdom at the cost of self +Drink and be refreshed +Wherever you go, there you are +Energy comes at the cost of wisdom +Riches abound when least expected +Where avarice fails, patience gains reward +Blessed by a benevolent companion! +The hands of men may be guided by fate +Strength is bolstered by heavenly faith +The essence of life flows from within +The way is made clear when viewed from above +Salvation comes at the cost of wisdom +Mysteries are revealed in the light of reason +Those who are last may yet be first +Generosity brings its own rewards +You must be at least level 8 to use this. +You must be at least level 13 to use this. +You must be at least level 17 to use this. +Arcane knowledge gained! +That which does not kill you... +Knowledge is power. +Give and you shall receive. +Some experience is gained by touch. +There's no place like home. +Spirtual energy is restored. +You feel more agile. +You feel stronger. +You feel wiser. +You feel refreshed. +That which can break will. +gpBuffer +D:\diablo97\error.cpp +Exception code: %08X %s +%08X %02X:%08X %s +Registers: +EAX:%08X +EBX:%08X +ECX:%08X +EDX:%08X +ESI:%08X +EDI:%08X +CS:EIP:%04X:%08X +EBP:%08X +GS:%04X +Flags:%08X +Call stack: +Module +%04X:%08X %s +ACCESS_VIOLATION +DATATYPE_MISALIGNMENT +BREAKPOINT +SINGLE_STEP +ARRAY_BOUNDS_EXCEEDED +FLT_DENORMAL_OPERAND +FLT_DIVIDE_BY_ZERO +FLT_INEXACT_RESULT +FLT_INVALID_OPERATION +FLT_OVERFLOW +FLT_STACK_CHECK +FLT_UNDERFLOW +INT_DIVIDE_BY_ZERO +INT_OVERFLOW +PRIV_INSTRUCTION +IN_PAGE_ERROR +ILLEGAL_INSTRUCTION +NONCONTINUABLE_EXCEPTION +STACK_OVERFLOW +INVALID_DISPOSITION +GUARD_PAGE +INVALID_HANDLE +NTDLL.DLL +Save Game +Options +New Game +Load Game +Quit Hellfire +Options +New Game +Restart In Town +Quit Hellfire +Gamma +Previous Menu +Music +Music Disabled +Sound +Sound Disabled +Walk +Fast Walk +pMenuItems == sgSingleMenu +D:\diablo97\GameMenu.cpp +pMenuItems == sgMultiMenu +D:\diablo97\GameMenu.cpp +bActivate +D:\diablo97\GameMenu.cpp +bActivate +D:\diablo97\GameMenu.cpp +bActivate +D:\diablo97\GameMenu.cpp +bActivate +D:\diablo97\GameMenu.cpp +gbMaxPlayers == 1 +D:\diablo97\GameMenu.cpp +gbValidSaveFile +D:\diablo97\GameMenu.cpp +ghMainWnd +D:\diablo97\GameMenu.cpp +saveProc == DisableInputWndProc +D:\diablo97\GameMenu.cpp +bActivate +D:\diablo97\GameMenu.cpp +gbMaxPlayers == 1 +D:\diablo97\GameMenu.cpp +ghMainWnd +D:\diablo97\GameMenu.cpp +saveProc == DisableInputWndProc +D:\diablo97\GameMenu.cpp +bActivate +D:\diablo97\GameMenu.cpp +bActivate +D:\diablo97\GameMenu.cpp +D:\diablo97\GENDUNG.CPP +NLevels\TownData\Town.SOL +D:\diablo97\GENDUNG.CPP +Levels\L1Data\L1.SOL +D:\diablo97\GENDUNG.CPP +NLevels\L5Data\L5.SOL +D:\diablo97\GENDUNG.CPP +Levels\L2Data\L2.SOL +D:\diablo97\GENDUNG.CPP +Levels\L3Data\L3.SOL +D:\diablo97\GENDUNG.CPP +NLevels\L6Data\L6.SOL +D:\diablo97\GENDUNG.CPP +Levels\L4Data\L4.SOL +FillSolidBlockTbls +D:\diablo97\GENDUNG.CPP +gpBuffer +D:\diablo97\GENDUNG.CPP +Pause +pszStr +D:\diablo97\gmenu.cpp +D:\diablo97\gmenu.cpp +D:\diablo97\gmenu.cpp +D:\diablo97\gmenu.cpp +D:\diablo97\gmenu.cpp +D:\diablo97\gmenu.cpp +! sgpLogo +D:\diablo97\gmenu.cpp +D:\diablo97\gmenu.cpp +Data\hf_logo3.CEL +D:\diablo97\gmenu.cpp +Data\BigTGold.CEL +D:\diablo97\gmenu.cpp +Data\PentSpin.CEL +D:\diablo97\gmenu.cpp +Data\option.CEL +D:\diablo97\gmenu.cpp +Data\optbar.CEL +gpBuffer +D:\diablo97\gmenu.cpp +sgpCurrItem +D:\diablo97\gmenu.cpp +sgpCurrItem +D:\diablo97\gmenu.cpp +sgpCurrItem +D:\diablo97\gmenu.cpp +plOffset +D:\diablo97\gmenu.cpp +pMenuItem +D:\diablo97\gmenu.cpp +pItem +D:\diablo97\gmenu.cpp +pItem +D:\diablo97\gmenu.cpp +pItem +D:\diablo97\gmenu.cpp +dwTicks >= MIN_SLIDER_TICKS && dwTicks <= MAX_SLIDER_TICKS +D:\diablo97\gmenu.cpp +Hellfire Help +Press ESC to end or the arrow keys to scroll. +internal version unknown +Hellfire v1.00 +%s\%s\ +%s%s\ +Microsoft Office Shortcut Bar.lnk +open +Control Panel\Desktop +Unable to register window class +Unable to create main window +MOM Parent +DiabloCD +\diabdat.mpq +diabdat.mpq +ui_art\title.pcx +Main program archive: diabdat.mpq +DiabloInstall +\patch_rt.mpq +DiabloInstall +\hellfire.mpq +DiabloInstall +\hfmonk.mpq +DiabloInstall +\hfmusic.mpq +DiabloInstall +\hfvoice.mpq +DiabloInstall +\hfopt1.mpq +DiabloInstall +\hfopt2.mpq +Can't get program path +SFileSetBasePath +Can't get program name +Archives +D:\diablo97\init.cpp +uBytes >= sizeof(VS_FIXEDFILEINFO) +D:\diablo97\init.cpp +version %d.%d.%d.%d +D:\diablo97\init.cpp +sgpBackCel +D:\diablo97\Interfac.cpp +gpBuffer +D:\diablo97\Interfac.cpp +ghMainWnd +D:\diablo97\Interfac.cpp +plr[myplr].plrlevel == currlevel +D:\diablo97\Interfac.cpp +plr[myplr].plrlevel == currlevel +D:\diablo97\Interfac.cpp +plr[myplr].plrlevel == currlevel +D:\diablo97\Interfac.cpp +plr[myplr].plrlevel == currlevel +D:\diablo97\Interfac.cpp +plr[myplr].plrlevel == currlevel +D:\diablo97\Interfac.cpp +ghMainWnd +D:\diablo97\Interfac.cpp +saveProc == DisableInputWndProc +D:\diablo97\Interfac.cpp +D:\diablo97\Interfac.cpp +! sgpBackCel +D:\diablo97\Interfac.cpp +D:\diablo97\Interfac.cpp +Gendata\Cuttt.CEL +Gendata\Cuttt.pal +D:\diablo97\Interfac.cpp +Gendata\Cutl1d.CEL +Gendata\Cutl1d.pal +D:\diablo97\Interfac.cpp +Nlevels\cutl5.CEL +Nlevels\cutl5.pal +D:\diablo97\Interfac.cpp +Gendata\Cut2.CEL +Gendata\Cut2.pal +D:\diablo97\Interfac.cpp +Gendata\Cut3.CEL +Gendata\Cut3.pal +D:\diablo97\Interfac.cpp +Nlevels\cutl6.CEL +Nlevels\cutl6.pal +D:\diablo97\Interfac.cpp +Gendata\Cut4.CEL +Gendata\Cut4.pal +D:\diablo97\Interfac.cpp +Gendata\Cutgate.CEL +Gendata\Cutgate.pal +D:\diablo97\Interfac.cpp +Gendata\Cutl1d.CEL +Gendata\Cutl1d.pal +D:\diablo97\Interfac.cpp +Gendata\Cuttt.CEL +Gendata\Cuttt.pal +D:\diablo97\Interfac.cpp +Gendata\Cuttt.CEL +Gendata\Cuttt.pal +D:\diablo97\Interfac.cpp +Gendata\Cutl1d.CEL +Gendata\Cutl1d.pal +D:\diablo97\Interfac.cpp +Nlevels\cutl5.CEL +Nlevels\cutl5.pal +D:\diablo97\Interfac.cpp +Gendata\Cut2.CEL +Gendata\Cut2.pal +D:\diablo97\Interfac.cpp +Gendata\Cut3.CEL +Gendata\Cut3.pal +D:\diablo97\Interfac.cpp +Nlevels\cutl6.CEL +Nlevels\cutl6.pal +D:\diablo97\Interfac.cpp +Gendata\Cut4.CEL +Gendata\Cut4.pal +D:\diablo97\Interfac.cpp +Gendata\Cutl1d.CEL +Gendata\Cutl1d.pal +D:\diablo97\Interfac.cpp +Gendata\Cut2.CEL +Gendata\Cut2.pal +D:\diablo97\Interfac.cpp +Gendata\Cutportr.CEL +Gendata\Cutportr.pal +D:\diablo97\Interfac.cpp +Gendata\Cutl1d.CEL +Gendata\Cutl1d.pal +D:\diablo97\Interfac.cpp +Gendata\Cut2.CEL +Gendata\Cut2.pal +D:\diablo97\Interfac.cpp +Gendata\Cutportr.CEL +Gendata\Cutportr.pal +D:\diablo97\Interfac.cpp +Gendata\Cutl1d.CEL +Gendata\Cutl1d.pal +D:\diablo97\Interfac.cpp +Gendata\Cutportl.CEL +Gendata\Cutportl.pal +D:\diablo97\Interfac.cpp +Gendata\Cutstart.CEL +Gendata\Cutstart.pal +D:\diablo97\Interfac.cpp +Gendata\Cutstart.CEL +Gendata\Cutstart.pal +D:\diablo97\Interfac.cpp +Gendata\Cuttt.CEL +Gendata\Cuttt.pal +D:\diablo97\Interfac.cpp +Gendata\Cutl1d.CEL +Gendata\Cutl1d.pal +D:\diablo97\Interfac.cpp +Nlevels\Cutl5.CEL +Nlevels\Cutl5.pal +D:\diablo97\Interfac.cpp +Gendata\Cut2.CEL +Gendata\Cut2.pal +D:\diablo97\Interfac.cpp +Gendata\Cut3.CEL +Gendata\Cut3.pal +D:\diablo97\Interfac.cpp +Nlevels\Cutl6.CEL +Nlevels\Cutl6.pal +D:\diablo97\Interfac.cpp +Gendata\Cut4.CEL +Gendata\Cut4.pal +D:\diablo97\Interfac.cpp +Gendata\Cuttt.CEL +Gendata\Cuttt.pal +Unknown progress mode +D:\diablo97\inv.cpp +! pInvCels +D:\diablo97\inv.cpp +D:\diablo97\inv.cpp +Data\Inv\Inv.CEL +D:\diablo97\inv.cpp +Data\Inv\Inv_rog.CEL +D:\diablo97\inv.cpp +Data\Inv\Inv_Sor.CEL +D:\diablo97\inv.cpp +Data\Inv\Inv_Sor.CEL +D:\diablo97\inv.cpp +Data\Inv\Inv_rog.CEL +gpBuffer +D:\diablo97\inv.cpp +gpBuffer +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp +!invtest[i] +D:\diablo97\inv.cpp +plr[myplr].InvGrid[i] <= plr[myplr]._pNumInv +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp +pCursCels +D:\diablo97\inv.cpp + InvGetItem: deleting item %d. + InvGetItem: itemactive[%2.2d]: %2.2d + InvGetItem: Removing item index %d (struct %d,numitems %d) from item list! + AutoGetItem: set item[%d].iDelFlag = TRUE + AutogetItem: Removing item index %d (struct %d,numitems %d) from item list! +AutogetItem + VerifyItemActiveList: Duplicate item detected: itemactive[%d] = %d (%d %8.8x %4.4x) + Doing SyncGetItem... + Attempting to find item by (x,y) + Bad (x,y). Did FindGetItem->%d. + (x,y) said ii == %d, FindGetItem says ii == %d + Nongood (x,y) + FindGetItem returned %d + Removing item from map! + Removing item index %d (struct %d,numitems %d) from item list! + Item removed. FindGetItem->%d, numitems->%d +FindGetItem(idx,ci,iseed) == -1 +D:\diablo97\inv.cpp +FindGetItem(idx, ci, iseed) == -1 +D:\diablo97\inv.cpp + Item is definitely removed! +numitems >= MAXITEMS + Duplicate item detected! +A duplicate item has been detected. Destroying duplicate... +CanPut(x,y) +D:\diablo97\inv.cpp + InvPutItem +Player %i dropping item. +numitems >= MAXITEMS + Duplicate item detected! +A duplicate item has been detected from another player. +Failed to find a good square to drop in! +CanPut(x,y) +D:\diablo97\inv.cpp +ii >= 0 +D:\diablo97\inv.cpp +SyncPutItem: respawning object %d! +D:\diablo97\inv.cpp +%i gold %s +Gold +Short Sword +Buckler +Club +Short Bow +Short Staff of Mana +Cleaver +The Undead Crown +Empyrean Band +Magic Rock +Optic Amulet +Ring of Truth +Tavern Sign +Harlequin Crest +Veil of Steel +Golden Elixir +Anvil of Fury +Black Mushroom +Brain +Fungal Tome +Spectral Elixir +Blood Stone +Cathedral Map +Heart +Potion of Healing +Potion of Mana +Scroll of Identify +Scroll of Town Portal +Arkaine's Valor +Potion of Full Healing +Potion of Full Mana +Griswold's Edge +Bovine Plate +Staff of Lazarus +Scroll of Resurrect +Blacksmith Oil +Short Staff +Sword +Dagger +Rune Bomb +Theodore +Auric Amulet +Torn Note 1 +Torn Note 2 +Torn Note 3 +Reconstructed Note +Brown Suit +Grey Suit +Skull Cap +Helm +Helm +Full Helm +Helm +Crown +Crown +Great Helm +Helm +Cape +Cape +Rags +Rags +Cloak +Cloak +Robe +Robe +Quilted Armor +Armor +Leather Armor +Armor +Hard Leather Armor +Armor +Studded Leather Armor +Armor +Ring Mail +Mail +Chain Mail +Mail +Scale Mail +Mail +Breast Plate +Plate +Splint Mail +Mail +Plate Mail +Plate +Field Plate +Plate +Gothic Plate +Plate +Full Plate Mail +Plate +Buckler +Shield +Small Shield +Shield +Large Shield +Shield +Kite Shield +Shield +Tower Shield +Shield +Gothic Shield +Shield +Potion of Healing +Potion of Full Healing +Potion of Mana +Potion of Full Mana +Potion of Rejuvenation +Potion of Full Rejuvenation +Blacksmith Oil +Oil of Accuracy +Oil of Sharpness +Elixir of Strength +Elixir of Magic +Elixir of Dexterity +Elixir of Vitality +Scroll of Healing +Scroll of Search +Scroll of Lightning +Scroll of Identify +Scroll of Resurrect +Scroll of Fire Wall +Scroll of Inferno +Scroll of Town Portal +Scroll of Flash +Scroll of Infravision +Scroll of Phasing +Scroll of Mana Shield +Scroll of Flame Wave +Scroll of Fireball +Scroll of Stone Curse +Scroll of Chain Lightning +Scroll of Guardian +Non Item +Scroll of Nova +Scroll of Golem +Scroll of None +Scroll of Teleport +Scroll of Apocalypse +Book of +Book of +Book of +Book of +Dagger +Dagger +Short Sword +Sword +Falchion +Sword +Scimitar +Sword +Claymore +Sword +Blade +Blade +Sabre +Sabre +Long Sword +Sword +Broad Sword +Sword +Bastard Sword +Sword +Two-Handed Sword +Sword +Great Sword +Sword +Small Axe +Large Axe +Broad Axe +Battle Axe +Great Axe +Mace +Mace +Morning Star +Mace +War Hammer +Hammer +Spiked Club +Club +Club +Club +Flail +Flail +Maul +Maul +Short Bow +Hunter's Bow +Long Bow +Composite Bow +Short Battle Bow +Long Battle Bow +Short War Bow +Long War Bow +Short Staff +Staff +Long Staff +Staff +Composite Staff +Staff +Quarter Staff +Staff +War Staff +Staff +Ring +Ring +Ring +Ring +Ring +Ring +Amulet +Amulet +Amulet +Amulet +Rune of Fire +Rune +Rune of Lightning +Rune +Greater Rune of Fire +Rune +Greater Rune of Lightning +Rune +Rune of Stone +Rune +Brass +Bronze +Iron +Steel +Silver +Gold +Platinum +Mithril +Meteoric +Weird +Strange +Useless +Bent +Weak +Jagged +Deadly +Heavy +Vicious +Brutal +Massive +Savage +Ruthless +Merciless +Clumsy +Dull +Sharp +Fine +Warrior's +Soldier's +Lord's +Knight's +Master's +Champion's +King's +Vulnerable +Rusted +Fine +Strong +Grand +Valiant +Glorious +Blessed +Saintly +Awesome +Holy +Godly +Crimson +Crimson +Garnet +Ruby +Blue +Azure +Lapis +Cobalt +Sapphire +White +Pearl +Ivory +Crystal +Diamond +Topaz +Amber +Jade +Obsidian +Emerald +Hyena's +Frog's +Spider's +Raven's +Snake's +Serpent's +Drake's +Dragon's +Wyrm's +Hydra's +Angel's +Arch-Angel's +Plentiful +Bountiful +Flaming +Lightning +Jester's +Crystalline +Doppelganger's +quality +maiming +slaying +gore +carnage +slaughter +pain +tears +health +protection +absorption +deflection +osmosis +frailty +weakness +strength +might +power +giants +titans +paralysis +atrophy +dexterity +skill +accuracy +precision +perfection +the fool +dyslexia +magic +the mind +brilliance +sorcery +wizardry +illness +disease +vitality +zest +vigor +life +trouble +the pit +the sky +the moon +the stars +the heavens +the zodiac +the vulture +the jackal +the fox +the jaguar +the eagle +the wolf +the tiger +the lion +the mammoth +the whale +fragility +brittleness +sturdiness +craftsmanship +structure +the ages +the dark +the night +light +radiance +flame +fire +burning +shock +lightning +thunder +many +plenty +thorns +corruption +thieves +the bear +the bat +vampires +the leech +blood +piercing +puncturing +bashing +readiness +swiftness +speed +haste +balance +stability +harmony +blocking +devastation +decay +peril +The Butcher's Cleaver +The Undead Crown +Empyrean Band +Optic Amulet +Ring of Truth +Harlequin Crest +Veil of Steel +Arkaine's Valor +Griswold's Edge +Bovine Plate +The Rift Bow +The Needler +The Celestial Bow +Deadly Hunter +Bow of the Dead +The Blackoak Bow +Flamedart +Fleshstinger +Windforce +Eaglehorn +Gonnagal's Dirk +The Defender +Gryphons Claw +Black Razor +Gibbous Moon +Ice Shank +The Executioner's Blade +The Bonesaw +Shadowhawk +Wizardspike +Lightsabre +The Falcon's Talon +Inferno +Doombringer +The Grizzly +The Grandfather +The Mangler +Sharp Beak +BloodSlayer +The Celestial Axe +Wicked Axe +Stonecleaver +Aguinara's Hatchet +Hellslayer +Messerschmidt's Reaver +Crackrust +Hammer of Jholm +Civerb's Cudgel +The Celestial Star +Baranar's Star +Gnarled Root +The Cranium Basher +Schaefer's Hammer +Dreamflange +Staff of Shadows +Immolator +Storm Spire +Gleamsong +Thundercall +The Protector +Naj's Puzzler +Mindcry +Rod of Onan +Helm of Sprits +Thinking Cap +OverLord's Helm +Fool's Crest +Gotterdamerung +Royal Circlet +Torn Flesh of Souls +The Gladiator's Bane +The Rainbow Cloak +Leather of Aut +Wisdom's Wrap +Sparking Mail +Scavenger Carapace +Nightscape +Naj's Light Plate +Demonspike Coat +The Deflector +Split Skull Shield +Dragon's Breach +Blackoak Shield +Holy Defender +Stormshield +Bramble +Ring of Regha +The Bleeder +Constricting Ring +Ring of Engagement +Giant's Knuckle +Mercurial Ring +Xorine's Ring +Karik's Ring +Ring of Magma +Ring of the Mystics +Ring of Thunder +Amulet of Warding +Gnat Sting +Flambeau +Armor of Gloom +Blitzen +Thunderclap +Shirotachi +Eater of Souls +Diamondedge +Bone Chain Armor +Demon Plate Armor +Acolyte's Amulet +Gladiator's Ring +Oil of Accuracy +Oil of Mastery +Oil of Sharpness +Oil of Death +Oil of Skill +Blacksmith Oil +Oil of Fortitude +Oil of Permanence +Oil of Hardening +Oil of Imperviousness +Armor2 +FBttle +GoldFlip +Helmut +Mace +Shield +SwrdFlip +Rock +Cleaver +Staff +Ring +CrownF +LArmor +WShield +Scroll +FPlateAr +FBook +Food +FBttleBB +FBttleDY +FBttleOR +FBttleBR +FBttleBL +FBttleBY +FBttleWH +FBttleDB +FEar +FBrain +FMush +Innsign +Bldstn +Fanvil +FLazStaf +bombs1 +halfps1 +wholeps1 +runes1 +teddys1 +cows1 +donkys1 +mooses1 +SItem +Items\%s.CEL +! itemanims[i] +D:\diablo97\ITEMS.CPP +D:\diablo97\ITEMS.CPP +Initing items... +(DWORD) p < MAX_PLRS +D:\diablo97\ITEMS.CPP +plr[p]._pNAnim[d] +D:\diablo97\ITEMS.CPP +%s %s +%s %s +%s of %s +%s of %s +Staff of %s +%s %s +%s of %s +%s %s +%s of %s +SetupItem: setting up object %d! +Ear of %s +CornerstoneRestore: respawning object %d! + RespawnItem: Respawning item %d! +D:\diablo97\ITEMS.CPP +%i gold %s +increases a weapon's +chance to hit +greatly increases a +weapon's chance to hit +increases a weapon's +damage potential +greatly increases a weapon's +damage potential - not bows +reduces attributes needed +to use armor or weapons +restores 20% of an +item's durability +increases an item's +current and max durability +makes an item indestructible +increases the armor class +of armor and shields +greatly increases the armor +class of armor and shields +fully recover life +recover partial life +recover life +deadly heal +recover mana +fully recover mana +increase strength +increase magic +increase dexterity +increase vitality +decrease strength +decrease strength +decrease dexterity +decrease vitality +recover life and mana +fully recover life and mana +sets fire trap +sets lightning trap +sets petrification trap +chance to hit : %+i%% +%+i%% damage +to hit: %+i%%, %+i%% damage +%+i%% armor +armor class: %i +armor class: %i +Resist Fire : %+i%% +Resist Fire : 75%% MAX +Resist Lightning : %+i%% +Resist Lightning : 75%% MAX +Resist Magic : %+i%% +Resist Magic : 75%% MAX +Resist All : %+i%% +Resist All : 75%% MAX +spells are increased 1 level +spells are increased 2 levels +spells are decreased 1 level +Extra charges +%i %s charges +Fire hit damage: %i +Fire hit damage: %i-%i +Lightning hit damage: %i +Lightning hit damage: %i-%i +%+i to strength +%+i to magic +%+i to dexterity +%+i to vitality +%+i to all attributes +%+i damage from enemies +Hit Points : %+i +Mana : %+i +high durability +decreased durability +indestructible ++%i%% light radius +-%i%% light radius +multiple arrows per shot +fire arrows damage: %i +fire arrows damage: %i-%i +lightning arrows damage %i +lightning arrows damage %i-%i +fireball damage: %i +fireball damage: %i-%i +attacker takes 1-3 damage +user loses all mana +you can't heal +absorbs half of trap damage +knocks target back ++200% damage vs. demons +All Resistance equals 0 +hit monster doesn't heal +hit steals 3% mana +hit steals 5% mana +hit steals 3% life +hit steals 5% life +penetrates target's armor +quick attack +fast attack +faster attack +fastest attack +fast hit recovery +faster hit recovery +fastest hit recovery +fast block +adds %i points to damage +fires random speed arrows +unusual item damage +altered durability +Faster attack swing +one handed sword +constantly lose hit points +life stealing +no strength requirement +see with infravision +lightning damage: %i +lightning damage: %i-%i +charged bolts on hits +Resist Fire : %+i%% +occasional triple damage +decaying %+i%% damage +2x dmg to monst, 1x to you +Random 0 - 500% damage +low dur, %+i%% damage +to hit: %+i%%, %+i%% damage +extra AC vs demons +extra AC vs undead +50%% Mana moved to Health +40%% Health moved to Mana +Another ability (NW) +gpBuffer +D:\diablo97\ITEMS.CPP +gpBuffer +D:\diablo97\ITEMS.CPP +Right-click to read +Right-click to read, then +left-click to target +Right click to use +Right click to use +Right click to use +Right click to read +Right click to read +Right click to view +Level : %i +Doubles gold capacity +damage: %i Indestructible +damage: %i Dur: %i/%i +damage: %i-%i Indestructible +damage: %i-%i Dur: %i/%i +armor: %i Indestructible +armor: %i Dur: %i/%i +dam: %i Dur: %i/%i +dam: %i-%i Dur: %i/%i +Charges: %i/%i +unique item +Required: +%s %i Str +%s %i Mag +%s %i Dex +damage: %i Indestructible +damage: %i Dur: %i/%i +damage: %i-%i Indestructible +damage: %i-%i Dur: %i/%i +Charges: %i/%i +Not Identified +armor: %i Indestructible +armor: %i Dur: %i/%i +Not Identified +Charges: %i/%i +Not Identified +Required: +%s %i Str +%s %i Mag +%s %i Dex +nIndex < gnNumGetRecords +D:\diablo97\ITEMS.CPP +gnNumGetRecords > 0 +D:\diablo97\ITEMS.CPP +D:\diablo97\LIGHTING.CPP +! pLightTbl +D:\diablo97\LIGHTING.CPP +D:\diablo97\LIGHTING.CPP +D:\diablo97\LIGHTING.CPP +PlrGFX\Infra.TRN +D:\diablo97\LIGHTING.CPP +D:\diablo97\LIGHTING.CPP +PlrGFX\Stone.TRN +D:\diablo97\LIGHTING.CPP +gbMaxPlayers == 1 +D:\diablo97\loadsave.cpp +Invalid save file +D:\diablo97\loadsave.cpp +gbMaxPlayers == 1 +D:\diablo97\loadsave.cpp +D:\diablo97\loadsave.cpp +D:\diablo97\loadsave.cpp +gbMaxPlayers == 1 +D:\diablo97\loadsave.cpp +D:\diablo97\loadsave.cpp +FILEBUFF >= tbuff - SaveBuff +D:\diablo97\loadsave.cpp +D:\diablo97\loadsave.cpp +D:\diablo97\loadsave.cpp +Unable to display mainmenu +Unable to display SelHeroSing +Can't load multiplayer dialog +gendata\Hellfire.smk +D:\diablo97\minitext.cpp +D:\diablo97\minitext.cpp +! pMedTextCels +D:\diablo97\minitext.cpp +D:\diablo97\minitext.cpp +Data\MedTextS.CEL +D:\diablo97\minitext.cpp +Data\TextBox.CEL +(DWORD) m < gdwAllTextEntries +D:\diablo97\minitext.cpp +gpBuffer +D:\diablo97\minitext.cpp +gpBuffer +D:\diablo97\minitext.cpp +Arrows +Fireba +Guard +Lghning +Firewal +MagBlos +Portal +Bluexfr +Bluexbk +Manashld +Blood +Bone +Metlhit +Farrow +Doom +Blodbur +Newexp +Shatter1 +Bigexp +Inferno +Thinlght +Flare +Flareexp +Magball +Krull +Miniltng +Holy +Holyexpl +Larrow +Firarwex +Acidbf +Acidspla +Acidpud +Ethrshld +Firerun +Ressur1 +Sklball +Rportal +Fireplar +Scubmisb +Scbsexpb +Scubmisc +Scbsexpc +Scubmisd +Scbsexpd +spawns +reflect +ms_ora +ms_bla +ms_reb +ms_yeb +rglows1 +ex_yel2 +ex_blu3 +ex_red3 +ms_blb +myplr < MAX_PLRS && myplr >= 0 +D:\diablo97\MISSILES.CPP +i < 64 && i >= 0 +D:\diablo97\MISSILES.CPP +fx < MAXDUNX && fx >= 0 +D:\diablo97\MISSILES.CPP +fy < MAXDUNY && fy >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +id < MAX_PLRS && id >= 0 +D:\diablo97\MISSILES.CPP +sn < 64 && sn >= 0 +D:\diablo97\MISSILES.CPP +nummissiles <= MAXMISSILES +D:\diablo97\MISSILES.CPP +i < MAXMISSILES +D:\diablo97\MISSILES.CPP +m < MAXMONSTERS && m >= 0 +D:\diablo97\MISSILES.CPP +monster[m].MType != NULL +D:\diablo97\MISSILES.CPP +m < MAXMONSTERS && m >= 0 +D:\diablo97\MISSILES.CPP +monster[m].MData != NULL +D:\diablo97\MISSILES.CPP +monster[m].MType != NULL +D:\diablo97\MISSILES.CPP +pnum < MAX_PLRS && pnum >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +Missiles\%s.CL2 +D:\diablo97\MISSILES.CPP +Missiles\%s.CL2 +D:\diablo97\MISSILES.CPP +Missiles\%s%i.CL2 +D:\diablo97\MISSILES.CPP +D:\diablo97\MISSILES.CPP +D:\diablo97\MISSILES.CPP +nummissiles <= MAXMISSILES +D:\diablo97\MISSILES.CPP +mx < MAXMISSILES && mx >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +nummissiles <= MAXMISSILES +D:\diablo97\MISSILES.CPP +mx < MAXMISSILES && mx >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +dx < MAXDUNX && dx >= 0 +D:\diablo97\MISSILES.CPP +dy < MAXDUNY && dy >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +p < MAX_PLRS && p >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +id < MAXMONSTERS +D:\diablo97\MISSILES.CPP +monster[id].MType != NULL +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +numtrigs <= MAXTRIGGERS +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +tx < MAXDUNX && tx >= 0 +D:\diablo97\MISSILES.CPP +ty < MAXDUNY && ty >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +id < MAXMONSTERS && id >= 0 +D:\diablo97\MISSILES.CPP +monster[id].MType != NULL +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +id < MAXMONSTERS && id >= 0 +D:\diablo97\MISSILES.CPP +monster[id].MType != NULL +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +mx < MAXDUNX && mx >= 0 +D:\diablo97\MISSILES.CPP +my < MAXDUNY && my >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +mx < MAXDUNX && mx >= 0 +D:\diablo97\MISSILES.CPP +my < MAXDUNY && my >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +monst < MAXMONSTERS && monst >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +missile[i]._mix < MAXDUNX && missile[i]._mix >= 0 +D:\diablo97\MISSILES.CPP +missile[i]._miy < MAXDUNY && missile[i]._miy >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +i < MAXMISSILES && i >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +mi < MAXMISSILES && mi >= 0 +D:\diablo97\MISSILES.CPP +\\.\DARKMONO.VXD +Monsters\Zombie\Zombie%c.CL2 +Monsters\Zombie\Zombie%c%i.WAV +Zombie +Monsters\Zombie\Zombie%c.CL2 +Monsters\Zombie\Zombie%c%i.WAV +Monsters\Zombie\Bluered.TRN +Ghoul +Monsters\Zombie\Zombie%c.CL2 +Monsters\Zombie\Zombie%c%i.WAV +Monsters\Zombie\Grey.TRN +Rotting Carcass +Monsters\Zombie\Zombie%c.CL2 +Monsters\Zombie\Zombie%c%i.WAV +Monsters\Zombie\Yellow.TRN +Black Death +Monsters\FalSpear\Phall%c.CL2 +Monsters\FalSpear\Phall%c%i.WAV +Monsters\FalSpear\FallenT.TRN +Fallen One +Monsters\FalSpear\Phall%c.CL2 +Monsters\FalSpear\Phall%c%i.WAV +Monsters\FalSpear\Dark.TRN +Carver +Monsters\FalSpear\Phall%c.CL2 +Monsters\FalSpear\Phall%c%i.WAV +Devil Kin +Monsters\FalSpear\Phall%c.CL2 +Monsters\FalSpear\Phall%c%i.WAV +Monsters\FalSpear\Blue.TRN +Dark One +Monsters\SkelAxe\SklAx%c.CL2 +Monsters\SkelAxe\SklAx%c%i.WAV +Monsters\SkelAxe\White.TRN +Skeleton +Monsters\SkelAxe\SklAx%c.CL2 +Monsters\SkelAxe\SklAx%c%i.WAV +Monsters\SkelAxe\Skelt.TRN +Corpse Axe +Monsters\SkelAxe\SklAx%c.CL2 +Monsters\SkelAxe\SklAx%c%i.WAV +Burning Dead +Monsters\SkelAxe\SklAx%c.CL2 +Monsters\SkelAxe\SklAx%c%i.WAV +Monsters\SkelAxe\Black.TRN +Horror +Monsters\FalSword\Fall%c.CL2 +Monsters\FalSword\Fall%c%i.WAV +Monsters\FalSword\FallenT.TRN +Fallen One +Monsters\FalSword\Fall%c.CL2 +Monsters\FalSword\Fall%c%i.WAV +Monsters\FalSword\Dark.TRN +Carver +Monsters\FalSword\Fall%c.CL2 +Monsters\FalSword\Fall%c%i.WAV +Devil Kin +Monsters\FalSword\Fall%c.CL2 +Monsters\FalSword\Fall%c%i.WAV +Monsters\FalSword\Blue.TRN +Dark One +Monsters\Scav\Scav%c.CL2 +Monsters\Scav\Scav%c%i.WAV +Scavenger +Monsters\Scav\Scav%c.CL2 +Monsters\Scav\Scav%c%i.WAV +Monsters\Scav\ScavBr.TRN +Plague Eater +Monsters\Scav\Scav%c.CL2 +Monsters\Scav\Scav%c%i.WAV +Monsters\Scav\ScavBe.TRN +Shadow Beast +Monsters\Scav\Scav%c.CL2 +Monsters\Scav\Scav%c%i.WAV +Monsters\Scav\ScavW.TRN +Bone Gasher +Monsters\SkelBow\SklBw%c.CL2 +Monsters\SkelBow\SklBw%c%i.WAV +Monsters\SkelBow\White.TRN +Skeleton +Monsters\SkelBow\SklBw%c.CL2 +Monsters\SkelBow\SklBw%c%i.WAV +Monsters\SkelBow\Skelt.TRN +Corpse Bow +Monsters\SkelBow\SklBw%c.CL2 +Monsters\SkelBow\SklBw%c%i.WAV +Burning Dead +Monsters\SkelBow\SklBw%c.CL2 +Monsters\SkelBow\SklBw%c%i.WAV +Monsters\SkelBow\Black.TRN +Horror +Monsters\SkelSd\SklSr%c.CL2 +Monsters\SkelSd\SklSr%c%i.WAV +Monsters\SkelSd\White.TRN +Skeleton Captain +Monsters\SkelSd\SklSr%c.CL2 +Monsters\SkelSd\SklSr%c%i.WAV +Monsters\SkelSd\Skelt.TRN +Corpse Captain +Monsters\SkelSd\SklSr%c.CL2 +Monsters\SkelSd\SklSr%c%i.WAV +Burning Dead Captain +Monsters\SkelSd\SklSr%c.CL2 +Monsters\SkelSd\SklSr%c%i.WAV +Monsters\SkelSd\Black.TRN +Horror Captain +Monsters\TSneak\TSneak%c.CL2 +Monsters\TSneak\Sneakl%c%i.WAV +Invisible Lord +Monsters\Sneak\Sneak%c.CL2 +Monsters\Sneak\Sneak%c%i.WAV +Hidden +Monsters\Sneak\Sneak%c.CL2 +Monsters\Sneak\Sneak%c%i.WAV +Monsters\Sneak\Sneakv2.TRN +Stalker +Monsters\Sneak\Sneak%c.CL2 +Monsters\Sneak\Sneak%c%i.WAV +Monsters\Sneak\Sneakv3.TRN +Unseen +Monsters\Sneak\Sneak%c.CL2 +Monsters\Sneak\Sneak%c%i.WAV +Monsters\Sneak\Sneakv1.TRN +Illusion Weaver +Monsters\GoatLord\GoatL%c.CL2 +Monsters\newsfx\Satyr%c%i.WAV +Satyr Lord +Monsters\GoatMace\Goat%c.CL2 +Monsters\GoatMace\Goat%c%i.WAV +Flesh Clan +Monsters\GoatMace\Goat%c.CL2 +Monsters\GoatMace\Goat%c%i.WAV +Monsters\GoatMace\Beige.TRN +Stone Clan +Monsters\GoatMace\Goat%c.CL2 +Monsters\GoatMace\Goat%c%i.WAV +Monsters\GoatMace\Red.TRN +Fire Clan +Monsters\GoatMace\Goat%c.CL2 +Monsters\GoatMace\Goat%c%i.WAV +Monsters\GoatMace\Gray.TRN +Night Clan +Monsters\Bat\Bat%c.CL2 +Monsters\Bat\Bat%c%i.WAV +Monsters\Bat\red.trn +Fiend +Monsters\Bat\Bat%c.CL2 +Monsters\Bat\Bat%c%i.WAV +Blink +Monsters\Bat\Bat%c.CL2 +Monsters\Bat\Bat%c%i.WAV +Monsters\Bat\grey.trn +Gloom +Monsters\Bat\Bat%c.CL2 +Monsters\Bat\Bat%c%i.WAV +Monsters\Bat\orange.trn +Familiar +Monsters\GoatBow\GoatB%c.CL2 +Monsters\GoatBow\GoatB%c%i.WAV +Flesh Clan +Monsters\GoatBow\GoatB%c.CL2 +Monsters\GoatBow\GoatB%c%i.WAV +Monsters\GoatBow\Beige.TRN +Stone Clan +Monsters\GoatBow\GoatB%c.CL2 +Monsters\GoatBow\GoatB%c%i.WAV +Monsters\GoatBow\Red.TRN +Fire Clan +Monsters\GoatBow\GoatB%c.CL2 +Monsters\GoatBow\GoatB%c%i.WAV +Monsters\GoatBow\Gray.TRN +Night Clan +Monsters\Acid\Acid%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Acid Beast +Monsters\Acid\Acid%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Monsters\Acid\AcidBlk.TRN +Poison Spitter +Monsters\Acid\Acid%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Monsters\Acid\AcidB.TRN +Pit Beast +Monsters\Acid\Acid%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Monsters\Acid\AcidR.TRN +Lava Maw +Monsters\SKing\SKing%c.CL2 +Monsters\SKing\SKing%c%i.WAV +Monsters\SkelAxe\White.TRN +Skeleton King +Monsters\FatC\FatC%c.CL2 +Monsters\FatC\FatC%c%i.WAV +The Butcher +Monsters\Fat\Fat%c.CL2 +Monsters\Fat\Fat%c%i.WAV +Overlord +Monsters\Fat\Fat%c.CL2 +Monsters\Fat\Fat%c%i.WAV +Monsters\Fat\Blue.TRN +Mud Man +Monsters\Fat\Fat%c.CL2 +Monsters\Fat\Fat%c%i.WAV +Monsters\Fat\FatB.TRN +Toad Demon +Monsters\Fat\Fat%c.CL2 +Monsters\Fat\Fat%c%i.WAV +Monsters\Fat\FatF.TRN +Flayed One +Monsters\Worm\Worm%c.CL2 +Monsters\Fat\Fat%c%i.WAV +Wyrm +Monsters\Worm\Worm%c.CL2 +Monsters\Fat\Fat%c%i.WAV +Cave Slug +Monsters\Worm\Worm%c.CL2 +Monsters\Fat\Fat%c%i.WAV +Devil Wyrm +Monsters\Worm\Worm%c.CL2 +Monsters\Fat\Fat%c%i.WAV +Devourer +Monsters\Magma\Magma%c.CL2 +Monsters\Magma\Magma%c%i.WAV +Magma Demon +Monsters\Magma\Magma%c.CL2 +Monsters\Magma\Magma%c%i.WAV +Monsters\Magma\Yellow.TRN +Blood Stone +Monsters\Magma\Magma%c.CL2 +Monsters\Magma\Magma%c%i.WAV +Monsters\Magma\Blue.TRN +Hell Stone +Monsters\Magma\Magma%c.CL2 +Monsters\Magma\Magma%c%i.WAV +Monsters\Magma\Wierd.TRN +Lava Lord +Monsters\Rhino\Rhino%c.CL2 +Monsters\Rhino\Rhino%c%i.WAV +Horned Demon +Monsters\Rhino\Rhino%c.CL2 +Monsters\Rhino\Rhino%c%i.WAV +Monsters\Rhino\Orange.TRN +Mud Runner +Monsters\Rhino\Rhino%c.CL2 +Monsters\Rhino\Rhino%c%i.WAV +Monsters\Rhino\Blue.TRN +Frost Charger +Monsters\Rhino\Rhino%c.CL2 +Monsters\Rhino\Rhino%c%i.WAV +Monsters\Rhino\RhinoB.TRN +Obsidian Lord +Monsters\Demskel\Demskl%c.CL2 +Monsters\Thin\Thin%c%i.WAV +Monsters\Thin\Thinv3.TRN +oldboned +Monsters\Thin\Thin%c.CL2 +Monsters\Thin\Thin%c%i.WAV +Monsters\Thin\Thinv3.TRN +Red Death +Monsters\Thin\Thin%c.CL2 +Monsters\Thin\Thin%c%i.WAV +Monsters\Thin\Thinv3.TRN +Litch Demon +Monsters\Thin\Thin%c.CL2 +Monsters\Thin\Thin%c%i.WAV +Monsters\Thin\Thinv3.TRN +Undead Balrog +Monsters\Fireman\FireM%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Incinerator +Monsters\Fireman\FireM%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Flame Lord +Monsters\Fireman\FireM%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Doom Fire +Monsters\Fireman\FireM%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Hell Burner +Monsters\Thin\Thin%c.CL2 +Monsters\Thin\Thin%c%i.WAV +Monsters\Thin\Thinv3.TRN +Red Storm +Monsters\Thin\Thin%c.CL2 +Monsters\Thin\Thin%c%i.WAV +Storm Rider +Monsters\Thin\Thin%c.CL2 +Monsters\Thin\Thin%c%i.WAV +Monsters\Thin\Thinv2.TRN +Storm Lord +Monsters\Thin\Thin%c.CL2 +Monsters\Thin\Thin%c%i.WAV +Monsters\Thin\Thinv1.TRN +Maelstorm +Monsters\BigFall\Fallg%c.CL2 +Monsters\newsfx\KBrute%c%i.WAV +Devil Kin Brute +Monsters\Gargoyle\Gargo%c.CL2 +Monsters\Gargoyle\Gargo%c%i.WAV +Winged-Demon +Monsters\Gargoyle\Gargo%c.CL2 +Monsters\Gargoyle\Gargo%c%i.WAV +Monsters\Gargoyle\GarE.TRN +Gargoyle +Monsters\Gargoyle\Gargo%c.CL2 +Monsters\Gargoyle\Gargo%c%i.WAV +Monsters\Gargoyle\GargBr.TRN +Blood Claw +Monsters\Gargoyle\Gargo%c.CL2 +Monsters\Gargoyle\Gargo%c%i.WAV +Monsters\Gargoyle\GargB.TRN +Death Wing +Monsters\Mega\Mega%c.CL2 +Monsters\Mega\Mega%c%i.WAV +Slayer +Monsters\Mega\Mega%c.CL2 +Monsters\Mega\Mega%c%i.WAV +Monsters\Mega\Guard.TRN +Guardian +Monsters\Mega\Mega%c.CL2 +Monsters\Mega\Mega%c%i.WAV +Monsters\Mega\Vtexl.TRN +Vortex Lord +Monsters\Mega\Mega%c.CL2 +Monsters\Mega\Mega%c%i.WAV +Monsters\Mega\Balr.TRN +Balrog +Monsters\Snake\Snake%c.CL2 +Monsters\Snake\Snake%c%i.WAV +Cave Viper +Monsters\Snake\Snake%c.CL2 +Monsters\Snake\Snake%c%i.WAV +Monsters\Snake\SnakR.TRN +Fire Drake +Monsters\Snake\Snake%c.CL2 +Monsters\Snake\Snake%c%i.WAV +Monsters\Snake\Snakg.TRN +Gold Viper +Monsters\Snake\Snake%c.CL2 +Monsters\Snake\Snake%c%i.WAV +Monsters\Snake\Snakb.TRN +Azure Drake +Monsters\Black\Black%c.CL2 +Monsters\Black\Black%c%i.WAV +Black Knight +Monsters\Black\Black%c.CL2 +Monsters\Black\Black%c%i.WAV +Monsters\Black\BlkKntRT.TRN +Doom Guard +Monsters\Black\Black%c.CL2 +Monsters\Black\Black%c%i.WAV +Monsters\Black\BlkKntBT.TRN +Steel Lord +Monsters\Black\Black%c.CL2 +Monsters\Black\Black%c%i.WAV +Monsters\Black\BlkKntBe.TRN +Blood Knight +Monsters\Unrav\Unrav%c.CL2 +Monsters\newsfx\Shred%c%i.WAV +The Shredded +Monsters\Unrav\Unrav%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Hollow One +Monsters\Unrav\Unrav%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Pain Master +Monsters\Unrav\Unrav%c.CL2 +Monsters\Acid\Acid%c%i.WAV +Reality Weaver +Monsters\Succ\Scbs%c.CL2 +Monsters\Succ\Scbs%c%i.WAV +Succubus +Monsters\Succ\Scbs%c.CL2 +Monsters\Succ\Scbs%c%i.WAV +Monsters\Succ\Succb.TRN +Snow Witch +Monsters\Succ\Scbs%c.CL2 +Monsters\Succ\Scbs%c%i.WAV +Monsters\Succ\Succrw.TRN +Hell Spawn +Monsters\Succ\Scbs%c.CL2 +Monsters\Succ\Scbs%c%i.WAV +Monsters\Succ\Succbw.TRN +Soul Burner +Monsters\Mage\Mage%c.CL2 +Monsters\Mage\Mage%c%i.WAV +Counselor +Monsters\Mage\Mage%c.CL2 +Monsters\Mage\Mage%c%i.WAV +Monsters\Mage\Cnselg.TRN +Magistrate +Monsters\Mage\Mage%c.CL2 +Monsters\Mage\Mage%c%i.WAV +Monsters\Mage\Cnselgd.TRN +Cabalist +Monsters\Mage\Mage%c.CL2 +Monsters\Mage\Mage%c%i.WAV +Monsters\Mage\Cnselbk.TRN +Advocate +Monsters\Golem\Golem%c.CL2 +Monsters\Golem\Golm%c%i.WAV +Golem +Monsters\Diablo\Diablo%c.CL2 +Monsters\Diablo\Diablo%c%i.WAV +The Dark Lord +Monsters\DarkMage\Dmage%c.CL2 +Monsters\DarkMage\Dmag%c%i.WAV +The Arch-Litch Malignus +Monsters\Fork\Fork%c.CL2 +Monsters\newsfx\HBoar%c%i.WAV +Hellboar +Monsters\Scorp\Scorp%c.CL2 +Monsters\newsfx\Stingr%c%i.WAV +Stinger +Monsters\Eye\Eye%c.CL2 +Monsters\newsfx\psyco%c%i.WAV +Psychorb +Monsters\Spider\Spider%c.CL2 +Monsters\newsfx\SLord%c%i.WAV +Arachnon +Monsters\TSneak\TSneak%c.CL2 +Monsters\newsfx\FTwin%c%i.WAV +Felltwin +Monsters\Spawn\Spawn%c.CL2 +Monsters\newsfx\HSpawn%c%i.WAV +Hork Spawn +Monsters\WScorp\WScorp%c.CL2 +Monsters\newsfx\Stingr%c%i.WAV +Venomtail +Monsters\Eye2\Eye2%c.CL2 +Monsters\newsfx\Psyco%c%i.WAV +Necromorb +Monsters\bSpidr\bSpidr%c.CL2 +Monsters\newsfx\SLord%c%i.WAV +Spider Lord +Monsters\Clasp\Clasp%c.CL2 +Monsters\newsfx\Lworm%c%i.WAV +Lashworm +Monsters\AntWorm\Worm%c.CL2 +Monsters\newsfx\TchAnt%c%i.WAV +Torchant +Monsters\HorkD\HorkD%c.CL2 +Monsters\newsfx\HDemon%c%i.WAV +Hork Demon +Monsters\Hellbug\Hellbg%c.CL2 +Monsters\newsfx\Defile%c%i.WAV +Hell Bug +Monsters\Gravdg\Gravdg%c.CL2 +Monsters\newsfx\GDiggr%c%i.WAV +Gravedigger +Monsters\Rat\Rat%c.CL2 +Monsters\newsfx\TmbRat%c%i.WAV +Tomb Rat +Monsters\Hellbat\Helbat%c.CL2 +Monsters\newsfx\HelBat%c%i.WAV +Firebat +Monsters\Demskel\Demskl%c.CL2 +Monsters\newsfx\SWing%c%i.WAV +Monsters\Thin\Thinv3.TRN +Skullwing +Monsters\Lich\Lich%c.CL2 +Monsters\newsfx\Lich%c%i.WAV +Lich +Monsters\Bubba\Bubba%c.CL2 +Monsters\newsfx\Crypt%c%i.WAV +Crypt Demon +Monsters\Hellbat2\bhelbt%c.CL2 +Monsters\newsfx\HelBat%c%i.WAV +Hellbat +Monsters\Demskel\Demskl%c.CL2 +Monsters\newsfx\SWing%c%i.WAV +Monsters\Thin\Thinv3.TRN +Bone Demon +Monsters\Lich2\Lich2%c.CL2 +Monsters\newsfx\Lich%c%i.WAV +Arch Lich +Monsters\Byclps\Byclps%c.CL2 +Monsters\newsfx\Biclop%c%i.WAV +Biclops +Monsters\Flesh\Flesh%c.CL2 +Monsters\newsfx\FleshT%c%i.WAV +Flesh Thing +Monsters\Reaper\Reap%c.CL2 +Monsters\newsfx\Reaper%c%i.WAV +Reaper +Monsters\Nkr\Nkr%c.CL2 +Monsters\newsfx\Nakrul%c%i.WAV +Na-Krul +Gharbad the Weak +BSDB +Skeleton King +GENRL +Zhar the Mad +GENERAL +Snotspill +Arch-Bishop Lazarus +GENERAL +Red Vex +REDV +BlackJade +BLKJD +Lachdanan +BHKA +Warlord of Blood +GENERAL +The Butcher +GENRL +Hork Demon +GENRL +The Defiler +GENRL +Na-Krul +GENRL +Bonehead Keenaxe +BHKA +Bladeskin the Slasher +BSTS +Soulpus +GENERAL +Pukerat the Unclean +Boneripper +Rotfeast the Hungry +Gutshank the Quick +Brokenhead Bangshield +BHBS +Bongo +Rotcarnage +RCRN +Shadowbite +SHBT +Deadeye +Madeye the Dead +El Chupacabras +GENERAL +Skullfire +SKFR +Warpskull +TSPO +Goretongue +Pulsecrawler +BHKA +Moonbender +GENERAL +Wrathraven +GENERAL +Spineeater +GENERAL +Blackash the Burning +BASHTB +Shadowcrow +GENERAL +Blightstone the Weak +BHKA +Bilefroth the Pit Master +BFTP +Bloodskin Darkbow +BSDB +Foulwing +Shadowdrinker +SHDR +Hazeshifter +BHKA +Deathspit +BFDS +Bloodgutter +BGBL +Deathshade Fleshmaul +DSFM +Warmaggot the Mad +GENERAL +Glasskull the Jagged +BHKA +Blightfire +Nightwing the Cold +GENERAL +Gorestone +GENERAL +Bronzefist Firestone +GENERAL +Wrathfire the Doomed +WFTD +Firewound the Grim +BHKA +Baron Sludge +Blighthorn Steelmace +BHSM +Chaoshowler +GENERAL +Doomgrin the Rotting +GENERAL +Madburner +GENERAL +Bonesaw the Litch +GENERAL +Breakspine +GENERAL +Devilskull Sharpbone +GENERAL +Brokenstorm +GENERAL +Stormbane +GENERAL +Oozedrool +GENERAL +Goldblight of the Flame +GENERAL +Blackstorm +GENERAL +Plaguewrath +GENERAL +The Flayer +GENERAL +Bluehorn +GENERAL +Warpfire Hellspawn +GENERAL +Fangspeir +GENERAL +Festerskull +GENERAL +Lionskull the Bent +GENERAL +Blacktongue +GENERAL +Viletouch +GENERAL +Viperflame +GENERAL +Fangskin +BHKA +Witchfire the Unholy +GENERAL +Blackskull +BHKA +Soulslash +GENERAL +Windspawn +GENERAL +Lord of the Pit +GENERAL +Rustweaver +GENERAL +Howlingire the Shade +GENERAL +Doomcloud +GENERAL +Bloodmoon Soulfire +GENERAL +Witchmoon +GENERAL +Gorefeast +GENERAL +Graywar the Slayer +GENERAL +Dreadjudge +GENERAL +Stareye the Witch +GENERAL +Steelskull the Hunter +GENERAL +Sir Gorash +GENERAL +The Vizier +GENERAL +Zamphir +GENERAL +Bloodlust +GENERAL +Webwidow +GENERAL +Fleshdancer +GENERAL +Grimspike +GENERAL +Doomlock +GENERAL +Invalid Monster +nwahds +(DWORD)nummtypes <= MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +(DWORD)monst < MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +! Monsters[monst].Anims[anim].CMem +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +(DWORD)monst < MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)mtype < MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +monst->MData != NULL +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L4Data\diab1.DUN +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L4Data\diab2a.DUN +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L4Data\diab3a.DUN +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L4Data\diab4a.DUN +D:\diablo97\MONSTER.CPP +(DWORD)nummtypes <= MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +(DWORD)nummtypes <= MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +(DWORD)nummonsters < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)nummtypes <= MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +uniqtype < nummtypes +D:\diablo97\MONSTER.CPP +Monsters\Monsters\%s.TRN +(uniquetrans << 8) + 4864 < LIGHTSIZE +D:\diablo97\MONSTER.CPP +(DWORD)nummtypes <= MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +skeltype < nummtypes +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L1Data\Banner1.DUN +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L2Data\Blood2.DUN +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L2Data\Blind2.DUN +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L3Data\Anvil.DUN +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L4Data\Warlord.DUN +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +Levels\L4Data\Vile1.DUN +D:\diablo97\MONSTER.CPP +(DWORD)leader < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)nummonsters < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)monster[nummonsters]._mx < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)monster[nummonsters]._my < MAXDUNY +D:\diablo97\MONSTER.CPP +(DWORD)(nummonsters-1) < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)nummonsters <= MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)md < 8 +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)(mx+1) < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)(my+1) < MAXDUNY +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +(DWORD)monster[i]._mx < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)monster[i]._my < MAXDUNY +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +M_StartKill: Invalid monster %d +MonstStartKill: Invalid monster %d +MonstStartKill: Monster %d "%s" MType NULL +(DWORD)nummonsters <= MAXMONSTERS +D:\diablo97\MONSTER.CPP +M_SyncStartKill: Invalid monster %d +pnum != myplr +D:\diablo97\MONSTER.CPP +M_DoStand: Invalid monster %d +M_DoStand: Monster %d "%s" MType NULL +M_DoWalk: Invalid monster %d +M_DoWalk: Monster %d "%s" MType NULL +M_ChangeLightOffset: Invalid monster %d +M_DoWalk2: Invalid monster %d +M_DoWalk2: Monster %d "%s" MType NULL +M_DoWalk3: Invalid monster %d +M_DoWalk3: Monster %d "%s" MType NULL +M_TryM2MHit: Invalid monster %d +M_TryM2MHit: Monster %d "%s" MType NULL +Invalid monster %d getting hit by monster +Monster %d "%s" getting hit by monster: MType NULL +M2MStartKill: Invalid monster (attacker) %d +M2MStartKill: Invalid monster (killed) %d +M2MStartKill: Monster %d "%s" MType NULL +M_DoAttack: Invalid monster %d +M_DoAttack: Monster %d "%s" MType NULL +M_DoAttack: Monster %d "%s" MData NULL +M_TryH2HHit: Invalid monster %d +M_TryH2HHit: Monster %d "%s" MType NULL +(DWORD)pnum < MAX_PLRS +D:\diablo97\MONSTER.CPP +M_DoRAttack: Invalid monster %d +M_DoRAttack: Monster %d "%s" MType NULL +M_DoRAttack: Monster %d "%s" MData NULL +M_DoRSpAttack: Invalid monster %d +M_DoRSpAttack: Monster %d "%s" MType NULL +M_DoRSpAttack: Monster %d "%s" MData NULL +M_DoSAttack: Invalid monster %d +M_DoSAttack: Monster %d "%s" MType NULL +M_DoSAttack: Monster %d "%s" MData NULL +M_DoFadein: Invalid monster %d +M_DoFadeout: Invalid monster %d +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +M_DoHeal: Invalid monster %d +M_DoTalk: Invalid monster %d +setpc_x != 0 +D:\diablo97\MONSTER.CPP +SS Talk = %i, Flags = %i +gbMaxPlayers == 1 +D:\diablo97\MONSTER.CPP +M_Teleport: Invalid monster %d +(DWORD)Monst->_mx < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)Monst->_my < MAXDUNY +D:\diablo97\MONSTER.CPP +M_DoGotHit: Invalid monster %d +M_DoGotHit: Monster %d "%s" MType NULL +M_UpdateLeader: Invalid monster %d +(DWORD)nummonsters <= MAXMONSTERS +D:\diablo97\MONSTER.CPP +gendata\DiabVic2.smk +gendata\DiabVic1.smk +gendata\DiabVic1.smk +gendata\DiabVic3.smk +gendata\Diabend.smk +gendata\loopdend.smk +(DWORD)myplr < MAX_PLRS +D:\diablo97\MONSTER.CPP +M_DoDeath: Invalid monster %d +M_DoDeath: Monster %d "%s" MType NULL +!(dFlags[monster[i]._mx+1][monster[i]._my] & BFLAG_MONSTLR) && !(dFlags[monster[i]._mx][monster[i]._my+1] & BFLAG_MONSTLR) +D:\diablo97\MONSTER.CPP +M_DoSpStand: Invalid monster %d +M_DoSpStand: Monster %d "%s" MType NULL +M_DoDelay: Invalid monster %d +M_DoDelay: Monster %d "%s" MType NULL +M_DoStone: Invalid monster %d +M_WalkDir: Invalid monster %d +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +(DWORD)fx < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)fy < MAXDUNY +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +(DWORD)fx < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)fy < MAXDUNY +D:\diablo97\MONSTER.CPP +(DWORD)monster[i]._mx < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)monster[i]._my < MAXDUNY +D:\diablo97\MONSTER.CPP +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +(DWORD)fx < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)fy < MAXDUNY +D:\diablo97\MONSTER.CPP +(DWORD)monster[i]._mx < MAXDUNX +D:\diablo97\MONSTER.CPP +(DWORD)monster[i]._my < MAXDUNY +D:\diablo97\MONSTER.CPP +GroupUnity: Invalid monster %d +(DWORD)nummonsters <= MAXMONSTERS +D:\diablo97\MONSTER.CPP +M_PathWalk: Invalid monster %d +M_Face: Invalid monster %d +M_Face: Monster %d "%s" MType NULL +MAI_Zombie: Invalid monster %d +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +MAI_SkelSd: Invalid monster %d +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +MAI_Path: Invalid monster %d +MAI_Snake: Invalid monster %d +Monst->_mgoalvar2 >= 0 && Monst->_mgoalvar2 < 8 +D:\diablo97\MONSTER.CPP +MAI_Bat: Invalid monster %d +MAI_SkelBow: Invalid monster %d +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +MAI_Fat: Invalid monster %d +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +MAI_Sneak: Invalid monster %d +M_StartFadein: Invalid monster %d +M_StartFadein: Monster %d "%s" MType NULL +M_StartFadeout: Invalid monster %d +M_StartFadeout: Monster %d "%s" MType NULL +MAI_Fireman: Invalid monster %d +MAI_Fallen: Invalid monster %d +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +MAI_Cleaver: Invalid monster %d +MAI_Round: Invalid monster %d +MAI_Ranged: Invalid monster %d +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +MAI_Scav: Invalid monster %d +(DWORD)i < MAXMONSTERS +D:\diablo97\MONSTER.CPP +monster[i].MType != NULL +D:\diablo97\MONSTER.CPP +MAI_Garg: Invalid monster %d +M_StartHeal: Invalid monster %d +M_StartHeal: Monster %d "%s" MType NULL +MAI_RoundRanged: Invalid monster %d +MAI_RR2: Invalid monster %d +MAI_Golum: Invalid monster %d +MAI_SkelKing: Invalid monster %d +MAI_Rhino: Invalid monster %d +MAI_HorkDemon: Invalid monster %d +MAI_Counselor: Invalid monster %d +MAI_Garbud: Invalid monster %d +MAI_Zhar: Invalid monster %d +MAI_SnotSpil: Invalid monster %d +MAI_Lazurus: Invalid monster %d +gendata\fprst3.smk +MAI_Lazhelp: Invalid monster %d +MAI_Lachdanan: Invalid monster %d +MAI_Warlord: Invalid monster %d +(DWORD)nummonsters <= MAXMONSTERS +D:\diablo97\MONSTER.CPP +(DWORD)nummonsters <= MAXMONSTERS +D:\diablo97\MONSTER.CPP +Illegal enemy monster %d for monster "%s" +Illegal enemy player %d for monster "%s" +(DWORD)nummtypes <= MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +D:\diablo97\MONSTER.CPP +DirOK: Invalid monster %d +tmp >= 0 +D:\diablo97\MONSTER.CPP +SyncMonsterAnim: Invalid monster %d +(DWORD)monster[m]._mMTidx < MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +(DWORD)nummonsters <= MAXMONSTERS +D:\diablo97\MONSTER.CPP +Total kills : %i +Hit Points : %i-%i +No magic resistance +Resists : +Magic +Fire +Lightning +Immune : +Magic +Fire +Lightning +No resistances +No Immunities +Some Magic Resistances +No resistances +Some Magic Immunities +No Immunities +MissToMonst: Invalid missile %d +MissToMonst: Invalid monster %d +Monst->_mmode == MM_MISSILE +D:\diablo97\MONSTER.CPP +(DWORD)nummtypes <= MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +(DWORD)nummtypes <= MAX_LVLMTYPES +D:\diablo97\MONSTER.CPP +TalktoMonster: Invalid monster %d +SpawnGolum: Invalid monster %d +CanTalkToMonst: Invalid monster %d +CheckMonsterHit: Invalid monster %d +pszMovie +D:\diablo97\movie.cpp +ghMainWnd +D:\diablo97\movie.cpp +Sfx\Misc\blank.wav +saveProc == MovieWndProc +D:\diablo97\movie.cpp +Hellfire +Video Player +pszArchive +D:\diablo97\mpqapi.cpp +pszArchive +D:\diablo97\mpqapi.cpp +dwChar < MAX_CHARACTERS +D:\diablo97\mpqapi.cpp +gbMaxPlayers != 1 +D:\diablo97\mpqapi.cpp +sghArchive != INVALID_HANDLE_VALUE +D:\diablo97\mpqapi.cpp +pszName +D:\diablo97\mpqapi.cpp +MPQ free list error +Out of free block entries +sghArchive != INVALID_HANDLE_VALUE +D:\diablo97\mpqapi.cpp +fnGetName +D:\diablo97\mpqapi.cpp +sghArchive != INVALID_HANDLE_VALUE +D:\diablo97\mpqapi.cpp +pszName +D:\diablo97\mpqapi.cpp +pbData +D:\diablo97\mpqapi.cpp +dwLen +D:\diablo97\mpqapi.cpp +Hash collision between "%s" and existing file +Out of hash space +D:\diablo97\mpqapi.cpp +sectoroffsettable +D:\diablo97\mpqapi.cpp +sectoroffsettable +D:\diablo97\mpqapi.cpp +D:\diablo97\mpqapi.cpp +destsize <= pBlk->sizealloc +D:\diablo97\mpqapi.cpp +D:\diablo97\mpqapi.cpp +sghArchive != INVALID_HANDLE_VALUE +D:\diablo97\mpqapi.cpp +pszOld +D:\diablo97\mpqapi.cpp +pszNew +D:\diablo97\mpqapi.cpp +sghArchive != INVALID_HANDLE_VALUE +D:\diablo97\mpqapi.cpp +pszName +D:\diablo97\mpqapi.cpp +pszArchive +D:\diablo97\mpqapi.cpp +sghArchive == INVALID_HANDLE_VALUE +D:\diablo97\mpqapi.cpp +! sgpBlockTbl +D:\diablo97\mpqapi.cpp +D:\diablo97\mpqapi.cpp +fhdr.hdr.blockcount == BLOCK_ENTRIES +D:\diablo97\mpqapi.cpp +fhdr.hdr.blockoffset == BLOCK_TBL_OFFSET +D:\diablo97\mpqapi.cpp +BLOCK_TBL_SIZE == dwTemp +D:\diablo97\mpqapi.cpp +(block table) +! sgpHashTbl +D:\diablo97\mpqapi.cpp +D:\diablo97\mpqapi.cpp +fhdr.hdr.hashcount == HASH_ENTRIES +D:\diablo97\mpqapi.cpp +fhdr.hdr.hashoffset == HASH_TBL_OFFSET +D:\diablo97\mpqapi.cpp +HASH_TBL_SIZE == dwTemp +D:\diablo97\mpqapi.cpp +(hash table) +pHdr +D:\diablo97\mpqapi.cpp +pdwNextFileStart +D:\diablo97\mpqapi.cpp +D:\diablo97\mpqapi.cpp +D:\diablo97\mpqapi.cpp +pszArchive +D:\diablo97\mpqapi.cpp +dwChar < MAX_CHARACTERS +D:\diablo97\mpqapi.cpp +(block table) +(block table) +(hash table) +(hash table) +c:\droplog.txt +(%8.8x,%2.2d): +(DWORD) pnum < MAX_PLRS +D:\diablo97\msg.cpp +pMsg +D:\diablo97\msg.cpp +dwLen <= gdwLargestMsgSize +D:\diablo97\msg.cpp +sgpCurrPkt +D:\diablo97\msg.cpp +sgpCurrPkt->dwSpaceLeft >= dwLen +D:\diablo97\msg.cpp +D:\diablo97\msg.cpp +ghMainWnd +D:\diablo97\msg.cpp +! sgpMegaPkt +D:\diablo97\msg.cpp +! sgpCurrPkt +D:\diablo97\msg.cpp +Waiting for game data... +The game ended +Unable to get level data +D:\diablo97\msg.cpp +currlevel == 0 +D:\diablo97\msg.cpp +plr[myplr].plrlevel == 0 +D:\diablo97\msg.cpp +(DWORD) nPlayer < MAX_PLRS +D:\diablo97\msg.cpp +D:\diablo97\msg.cpp +D:\diablo97\msg.cpp +(DWORD)mi < MAXMONSTERS +D:\diablo97\msg.cpp +x < DMAXX +D:\diablo97\msg.cpp +y < DMAXY +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp +(DWORD)mi < MAXMONSTERS +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp +pSync != NULL +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp +bLevel != 0 +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp +(DWORD)i < MAXPORTAL +D:\diablo97\msg.cpp +(DWORD)i <= MAXMULTIQUESTS +D:\diablo97\msg.cpp +(DWORD)ii < MAXITEMS +D:\diablo97\msg.cpp +(DWORD) currlevel < NUMLEVELS +D:\diablo97\msg.cpp +monster[i].MType != NULL +D:\diablo97\msg.cpp + DeltaLoadLevel: moving object from (x,y)->(%2.2x,%2.2x) to (x,y)->(%2.2x,%2.2x)! +done +D:\diablo97\msg.cpp + DeltaLoadLevel: respawning %d (%4.4x,%4.4x,%8.8x) @ (x,y)->(%2.2x,%2.2x) +mx < DMAXX +D:\diablo97\msg.cpp +my < DMAXY +D:\diablo97\msg.cpp +x < DMAXX +D:\diablo97\msg.cpp +y < DMAXY +D:\diablo97\msg.cpp +x < DMAXX +D:\diablo97\msg.cpp +y < DMAXY +D:\diablo97\msg.cpp +x < DMAXX +D:\diablo97\msg.cpp +y < DMAXY +D:\diablo97\msg.cpp +x < DMAXX +D:\diablo97\msg.cpp +y < DMAXY +D:\diablo97\msg.cpp +ii < MAXITEMS +D:\diablo97\msg.cpp +pnum < MAX_PLRS +D:\diablo97\msg.cpp +pnum < MAX_PLRS +D:\diablo97\msg.cpp +p != NULL +D:\diablo97\msg.cpp +pnum < MAX_PLRS +D:\diablo97\msg.cpp +p != NULL +D:\diablo97\msg.cpp +p != NULL +D:\diablo97\msg.cpp +x < DMAXX +D:\diablo97\msg.cpp +y < DMAXY +D:\diablo97\msg.cpp +(DWORD)ii < MAXITEMS +D:\diablo97\msg.cpp +bPlr < MAX_PLRS +D:\diablo97\msg.cpp +pszStr +D:\diablo97\msg.cpp +dwStrLen < sizeof(cmd.str) +D:\diablo97\msg.cpp +(DWORD)pnum < MAX_PLRS +D:\diablo97\msg.cpp +(DWORD)pnum < MAX_PLRS +D:\diablo97\msg.cpp +pCmd != NULL +D:\diablo97\msg.cpp +p->wOffset == sgdwRecvOffset +D:\diablo97\msg.cpp +msg:1 +CMD_SYNCDATA(%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_WALKXY(%d):(%d,%d) +CMD_ADDSTR(%d) +CMD_ADDMAG(%d) +CMD_ADDDEX(%d) +CMD_ADDVIT(%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_SBSPELL(%d) +%s has cast an illegal spell. +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_GOTOGETITEM(%d): xy->(%d,%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_REQUESTGETITEM(%d,%8.8x): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) +currlevel == plr[myplr].plrlevel +D:\diablo97\msg.cpp + Item found. FindGetItem returned %d and iDelFlag is FALSE. + Item not found. Resending. + Resend expired. Extra Item. +CMD_GETITEM(%d,%8.8x,%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + Data: bCmd = %2.2x + Data: bMaster = %2.2x + Data: bPnum = %2.2x + Data: bCursitem = %2.2x + Data: bLevel = %2.2x + Data: x = %2.2x + Data: y = %2.2x + Data: wIndx = %4.4x + Data: wCI = %4.4x + Data: dwSeed = %8.8x + Data: bID = %2.2x + Data: bDur = %2.2x + Data: bMDur = %2.2x + Data: bCh = %2.2x + Data: bMCh = %2.2x + Data: wValue = %4.4x + Data: dwBuff = %8.8x + Data: dwTime = %8.8x + Looking in delta tbl[%d] + Found in delta tbl. + Item already picked up. + Local player got item. + Remote player (%d) got item. + Not found in delta tbl. Resending... +pI != NULL +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp + delta_get_item: item already picked up?! + delta_get_item: native item picked up from floor + delta_get_item: foreign item picked up from floor +delta:1 + delta_get_item: item not found + delta_get_item: added item to delta tbl + delta_get_item: could not add item to delta tbl +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_GOTOAUTOGETITEM(%d): xy->(%d,%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_REQUESTAUTOGETITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) +currlevel == plr[myplr].plrlevel +D:\diablo97\msg.cpp + Item found. + Item not found. Resending. + Resend expired. Extra Item. +CMD_AUTOGETITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + Data: bCmd = %2.2x + Data: bMaster = %2.2x + Data: bPnum = %2.2x + Data: bCursitem = %2.2x + Data: bLevel = %2.2x + Data: x = %2.2x + Data: y = %2.2x + Data: wIndx = %4.4x + Data: wCI = %4.4x + Data: dwSeed = %8.8x + Data: bID = %2.2x + Data: bDur = %2.2x + Data: bMDur = %2.2x + Data: bCh = %2.2x + Data: bMCh = %2.2x + Data: wValue = %4.4x + Data: dwBuff = %8.8x + Data: dwTime = %8.8x + Looking in delta tbl[%d] + Found in delta tbl. + Item already picked up. + Local player got item. + Remote player (%d) got item. + Not found in delta tbl. Resending... +CMD_ITEMEXTRA(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + Looking in delta tbl[%d] +CMD_PUTITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + Item on my level. + Put successful. Putting item into delta... + Dropping into delta tbl[%d] + Put unsuccessful. + Item not on my level. Adding to delta... + Dropping into delta tbl[%d] +pI != NULL +D:\diablo97\msg.cpp +x < DMAXX +D:\diablo97\msg.cpp +y < DMAXY +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp +Trying to drop a floor item? +(DWORD)pnum < MAX_PLRS +D:\diablo97\msg.cpp +CMD_SYNCPUTITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + Item on my level. + Put successful. Putting item into delta... + Dropping into delta tbl[%d] + Put unsuccessful. + Item not on my level. Adding to delta... + Dropping into delta tbl[%d] +CMD_RESPAWNITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + SyncPutting into level. + Adding to delta... + Dropping into delta tbl[%d] +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_ATTACKXY(%d): xy->(%d,%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_SATTACKXY(%d): xy->(%d,%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_RATTACKXY(%d): xy->(%d,%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_SPELLXYD(%d): xy->(%d,%d) +%s has cast an illegal spell. +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_SPELLXY(%d): xy->(%d,%d) +%s has cast an illegal spell. +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_TSPELLXY(%d): xy->(%d,%d) +%s has cast an illegal spell. +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_OPOBJXY(%d): xy->(%d,%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_DISARMXY(%d): xy->(%d,%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_OPOBJT(%d) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_ATTACKID(%d): id->%d +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_ATTACKPID(%d): id->%d +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_RATTACKID(%d): id->%d +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_RATTACKPID(%d): id->%d +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_SPELLID(%d): id->%d +%s has cast an illegal spell. +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_SPELLPID(%d): id->%d +%s has cast an illegal spell. +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_TSPELLID(%d): id->%d +%s has cast an illegal spell. +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_TSPELLPID(%d): id->%d +%s has cast an illegal spell. +CMD_KNOCKBACK(%d): id->%d +CMD_RESURRECT(%d): id->%d +CMD_HEALOTHER(%d): id->%d +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_TALKXY(%d): xy->(%d,%d) +CMD_NEWLVL(%d) +CMD_WARP(%d) +CMD_MONSTDEATH(%d): id->%d xy->(%d,%d) +CMD_KILLGOLEM(%d): xy->(%d,%d) +CMD_AWAKENGOLEM(%d) +CMD_MONSTDAMAGE(%d): id->%d +CMD_PLAYERDEAD(%d): id->%d +CMD_PLAYERDEAD(I'm dead!!!) +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\msg.cpp +CMD_PLAYERDAMAGE(%d) + I'm taking damage. + Current level->%d +CMD_OPENDOOR(%d): id->%d +(DWORD)oi < MAXOBJECTS +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp +CMD_CLOSEDOOR(%d): id->%d +CMD_OPERATEOBJ(%d): id->%d +CMD_PLAYEROPOBJ(%d): plrid->%d objid->%d +CMD_BREAKOBJ(%d): id1->%d id2->%d +CMD_CHANGEPLAYERITEMS(%d): index->%8.8x ci->%8.8x seed->%8.8x +CMD_DELPLAYERITEMS(%d): loc->%d +CMD_PLAYERLEVEL(%d) +CMD_DROPITEM(%d): index->%8.8x ci->%8.8x seed->%8.8x xy->(%d,%d) +CMD_ACK\SENDPLRINFO(%d) +(DWORD)pnum < MAX_PLRS +D:\diablo97\msg.cpp +CMD_PLAYERJOINLEVEL(%d) +(%d) received %d joinlevel before plrdata +Player '%s' (level %d) just joined the game +(%d) activating %d on joinlevel +CMD_ACTIVATEPORTAL(%d): xy->(%d,%d) +(DWORD)pnum < MAX_PLRS +D:\diablo97\msg.cpp +x < DMAXX +D:\diablo97\msg.cpp +y < DMAXY +D:\diablo97\msg.cpp +bLevel < NUMLEVELS +D:\diablo97\msg.cpp +CMD_DEACTIVEPORTAL(%d) +CMD_RETOWN(%d) +CMD_SETSTR(%d) +CMD_SETDEX(%d) +CMD_SETMAG(%d) +CMD_SETVIT(%d) +CMD_STRING(%d) +(DWORD)pnum < MAX_PLRS +D:\diablo97\msg.cpp +p != NULL +D:\diablo97\msg.cpp +CMD_SYNCQUEST(%d) +CMD_ENDSHIELD(%d) +CMD_CHEATEXPERIENCE(%d) +CMD_CHEATSPELLLEVEL(%d) +c:\dumphist.txt +%4u.%02u + %x%c %x%c %x%c %x%c +sgbNetInited +D:\diablo97\multi.cpp +bLen <= gdwNormalMsgSize - sizeof(TPktHdr) +D:\diablo97\multi.cpp +sgbNetInited +D:\diablo97\multi.cpp +bLen <= gdwNormalMsgSize - sizeof(TPktHdr) +D:\diablo97\multi.cpp +msg buffer failure +sgbNetInited +D:\diablo97\multi.cpp +pbMsg +D:\diablo97\multi.cpp +bLen +D:\diablo97\multi.cpp +bLen <= gdwNormalMsgSize - sizeof(TPktHdr) +D:\diablo97\multi.cpp +SNetSendMessage0 +D:\diablo97\multi.cpp +sgbNetInited +D:\diablo97\multi.cpp +bLen <= gdwNormalMsgSize - sizeof(TPktHdr) +D:\diablo97\multi.cpp +(DWORD) myplr < MAX_PLRS +D:\diablo97\multi.cpp +SNetSendMessage +sgbNetInited +D:\diablo97\multi.cpp +pbMsg +D:\diablo97\multi.cpp +bLen +D:\diablo97\multi.cpp +dwSendBytes < gdwNormalMsgSize +D:\diablo97\multi.cpp +SNetSendMessage +glpMsgTbl[i] +D:\diablo97\multi.cpp +(%d) buffering -- player %d left game due to 0x%x +(%d) player %d left game due to 0x%x +(%d) player %d --> inactive +Player '%s' just left the game +Player '%s' dropped due to timeout +Player '%s' killed Diablo and left the game! +sgbNetInited +D:\diablo97\multi.cpp +bGroupPlayers +D:\diablo97\multi.cpp +nLowestActive != -1 +D:\diablo97\multi.cpp +nLowestPlayer != -1 +D:\diablo97\multi.cpp +(%d) dropping player %d state 0x%x +sgbNetInited +D:\diablo97\multi.cpp +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\multi.cpp +SNetReceiveMsg +pnum != myplr +D:\diablo97\multi.cpp +pbSrc +D:\diablo97\multi.cpp +dwLen <= 0x0ffff +D:\diablo97\multi.cpp +dwBody <= 0x0ffff +D:\diablo97\multi.cpp +SNetSendMessage2 +(%d) NetClose +SNetRegisterEventHandler: +pEvt->data +D:\diablo97\multi.cpp +pEvt->databytes >= sizeof(DWORD) +D:\diablo97\multi.cpp +pEvt->playerid >= 0 && pEvt->playerid < MAX_PLRS +D:\diablo97\multi.cpp +(%d) callback: player %d left game due to 0x%x +pEvt->data +D:\diablo97\multi.cpp +pfExitProgram +D:\diablo97\multi.cpp +Hellfire Retail +SNetInitializeProvider: +local +local +local +local +local +SNetCreateGame1: +dwID == 0 +D:\diablo97\multi.cpp +! *pfExitProgram +D:\diablo97\multi.cpp +(%d) new game started +SNetGetGameInfo1 +SNetGetGameInfo2 +Network upgrade failed +(DWORD)pnum < MAX_PLRS +D:\diablo97\multi.cpp +Player '%s' (level %d) just joined the game +Player '%s' (level %d) is already in the game +(%d) making %d active -- recv_plrinfo +(%d) received all %d plrinfo +pszFcn +D:\diablo97\nthread.cpp +SNetGetTurnsInTransit +gdwTurnsInTransit +D:\diablo97\nthread.cpp +SNetSendTurn +pfSendAsync +D:\diablo97\nthread.cpp +sgbPacketCountdown +D:\diablo97\nthread.cpp +sgbSyncCountdown +D:\diablo97\nthread.cpp +SNetReceiveTurns +%02x %02x %02x %02x +%02x %02x %02x %02x +SNetGetProviderCaps: +gdwLargestMsgSize >= MIN_MSG_SIZE +D:\diablo97\nthread.cpp +caps.maxplayers +D:\diablo97\nthread.cpp +sghThread == INVALID_HANDLE_VALUE +D:\diablo97\nthread.cpp +nthread2: +n:%u +nthread3: +(%s) +sgbThreadIsRunning != bStart +D:\diablo97\nthread.cpp +L1Braz +L1Doors +Lever +Chest1 +Chest2 +Banner +SkulPile +SkulFire +SkulStik +CruxSk1 +CruxSk2 +CruxSk3 +Book1 +Book2 +Rockstan +Angel +Chest3 +Burncros +Candle2 +Nude2 +Switch4 +TNudeM +TNudeW +TSoul +L2Doors +WTorch4 +WTorch3 +Sarc +Flame1 +Prsrplt1 +Traphole +MiniWatr +WTorch2 +WTorch1 +BCase +BShelf +WeapStnd +Barrel +Barrelex +LShrineG +RShrineG +Bloodfnt +Decap +Pedistl +L3Doors +PFountn +Armstand +Goatshrn +Cauldren +MFountn +TFountn +Altboy +Mcirl +Bkslbrnt +Mushptch +LzStand +L1Braz +L1Doors +L5Lever +Chest1 +Chest2 +Banner +SkulPile +SkulFire +SkulStik +CruxSk1 +CruxSk2 +CruxSk3 +Book1 +Book2 +Rockstan +Angel +Chest3 +Burncros +L5Light +Nude2 +Switch4 +TNudeM +TNudeW +TSoul +L2Doors +WTorch4 +WTorch3 +L5Sarco +Flame1 +Prsrplt1 +Traphole +MiniWatr +WTorch2 +WTorch1 +BCase +BShelf +WeapStnd +Urnexpld +LShrineG +RShrineG +Bloodfnt +Decap +Pedistl +L3Doors +PFountn +Armstand +Goatshrn +Cauldren +MFountn +TFountn +Altboy +Mcirl +L5Books +Mushptch +LzStand +L1Braz +L1Doors +Lever +Chest1 +Chest2 +Banner +SkulPile +SkulFire +SkulStik +CruxSk1 +CruxSk2 +CruxSk3 +Book1 +Book2 +Rockstan +Angel +Chest3 +Burncros +Candle2 +Nude2 +Switch4 +TNudeM +TNudeW +TSoul +L2Doors +WTorch4 +WTorch3 +Sarc +Flame1 +Prsrplt1 +Traphole +MiniWatr +WTorch2 +WTorch1 +BCase +BShelf +WeapStnd +L6Pod1 +L6Pod2 +LShrineG +RShrineG +Bloodfnt +Decap +Pedistl +L3Doors +PFountn +Armstand +Goatshrn +Cauldren +MFountn +TFountn +Altboy +Mcirl +Bkslbrnt +Mushptch +LzStand +Mysterious +Hidden +Gloomy +Weird +Magical +Stone +Religious +Enchanted +Thaumaturgic +Fascinating +Cryptic +Magical +Eldritch +Eerie +Divine +Holy +Sacred +Spiritual +Spooky +Abandoned +Creepy +Quiet +Secluded +Ornate +Glimmering +Tainted +Oily +Glowing +Mendicant's +Sparkling +Town +Shimmering +Solar +Murphy's +The Great Conflict +The Wages of Sin are War +The Tale of the Horadrim +The Dark Exile +The Sin War +The Binding of the Three +The Realms Beyond +Tale of the Three +The Black King +Journal: The Ensorcellment +Journal: The Meeting +Journal: The Tirade +Journal: His Power Grows +Journal: NA-KRUL +Journal: The End +A Spellbook +numobjfiles == 0 +D:\diablo97\OBJECTS.CPP +Objects\%s.CEL +Objects\%s.CEL +Objects\%s.CEL +! pObjCels[numobjfiles] +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +Nlevels\L5data\L5door.CEL +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +Levels\L2Data\Blind2.DUN +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +Levels\L4Data\Warlord.DUN +D:\diablo97\OBJECTS.CPP +(DWORD)xp < MAXDUNX +D:\diablo97\OBJECTS.CPP +(DWORD)yp < MAXDUNY +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +Levels\L4Data\diab1.DUN +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +Levels\L4Data\diab2a.DUN +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +Levels\L4Data\diab3a.DUN +D:\diablo97\OBJECTS.CPP +numobjfiles == 0 +D:\diablo97\OBJECTS.CPP +Objects\%s.CEL +! pObjCels[numobjfiles] +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +gbMaxPlayers == 1 +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +Levels\L2Data\Blood2.DUN +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)v1 < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)o < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)oi < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +D:\diablo97\OBJECTS.CPP +Levels\L2Data\Blood2.DUN +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +D:\diablo97\OBJECTS.CPP +Crucified Skeleton +Lever +Open Door +Closed Door +Blocked Door +Ancient Tome +Book of Vileness +Skull Lever +Mythical Book +Small Chest +Chest +Large Chest +Sarcophagus +Bookshelf +Bookcase +Barrel +%s Shrine +Skeleton Tome +Library Book +Blood Fountain +Decapitated Body +Book of the Blind +Steel Tome +Book of Blood +Purifying Spring +Armor +Weapon Rack +Goat Shrine +Cauldron +Murky Pool +Fountain of Tears +Pedestal of Blood +Weapon Rack +Mushroom Patch +Vile Stand +Slain Hero +Trapped %s +D:\diablo97\PALETTE.CPP +D:\diablo97\PALETTE.CPP +pszFileName +D:\diablo97\PALETTE.CPP +Levels\TownData\Town.pal +Levels\L%iData\L%i_%i.PAL +NLevels\L5Data\L5Base.PAL +NLevels\L%iData\L%iBase%i.PAL +Unable to initialize save directory +pszDir +D:\diablo97\pfile.cpp +myplr >= 0 && myplr < MAX_PLRS +D:\diablo97\pfile.cpp +xrgyrkj1 +D:\diablo97\pfile.cpp +D:\diablo97\pfile.cpp +pszBuf +D:\diablo97\pfile.cpp +dwBufSize >= MAX_PATH +D:\diablo97\pfile.cpp +\dlinfo_%d.drv +\single_%d.sv +Unable to get save directory +pPack +D:\diablo97\pfile.cpp +xrgyrkj1 +D:\diablo97\pfile.cpp +dwBytes == dwSize +D:\diablo97\pfile.cpp +D:\diablo97\pfile.cpp +hsArchive +D:\diablo97\pfile.cpp +dwChar < MAX_CHARACTERS +D:\diablo97\pfile.cpp +Invalid save file +D:\diablo97\pfile.cpp +xrgyrkj1 +D:\diablo97\pfile.cpp +heroinfo->name[0] +D:\diablo97\pfile.cpp +myplr >= 0 && myplr < MAX_PLRS +D:\diablo97\pfile.cpp +dwChar != MAX_CHARACTERS +D:\diablo97\pfile.cpp +Unable to open archive +Unable to load character +dwChar < MAX_CHARACTERS +D:\diablo97\pfile.cpp +gbMaxPlayers == 1 +D:\diablo97\pfile.cpp +dwChar < MAX_CHARACTERS +D:\diablo97\pfile.cpp +gbMaxPlayers == 1 +D:\diablo97\pfile.cpp +Unable to read to save file archive +dwChar < MAX_CHARACTERS +D:\diablo97\pfile.cpp +gbMaxPlayers == 1 +D:\diablo97\pfile.cpp +dwChar < MAX_CHARACTERS +D:\diablo97\pfile.cpp +Unable to write to save file archive +gbMaxPlayers == 1 +D:\diablo97\pfile.cpp +dwChar < MAX_CHARACTERS +D:\diablo97\pfile.cpp +gbMaxPlayers == 1 +D:\diablo97\pfile.cpp +Unable to write to save file archive +bResult +D:\diablo97\pfile.cpp +! GetPermSaveNames(dwIndex,szPerm) +D:\diablo97\pfile.cpp +gbMaxPlayers == 1 +D:\diablo97\pfile.cpp +pszName +D:\diablo97\pfile.cpp +pbData +D:\diablo97\pfile.cpp +dwLen +D:\diablo97\pfile.cpp +gbMaxPlayers == 1 +D:\diablo97\pfile.cpp +dwChar < MAX_CHARACTERS +D:\diablo97\pfile.cpp +xrgyrkj1 +Unable to write to save file archive +pszName +D:\diablo97\pfile.cpp +pdwLen +D:\diablo97\pfile.cpp +gbMaxPlayers == 1 +D:\diablo97\pfile.cpp +dwChar < MAX_CHARACTERS +D:\diablo97\pfile.cpp +Unable to open save file archive +Unable to open save file +Invalid save file +D:\diablo97\pfile.cpp +Unable to read save file +dwBytes == *pdwLen +D:\diablo97\pfile.cpp +xrgyrkj1 +Invalid save file +Warrior +Rogue +Sorceror +Monk +Bard +Warrior +Rogue +Sorceror +Monk +Rogue +LoadPlrGFX: illegal player %d +(DWORD) pPlayer->_pClass <= NUM_CLASSES +D:\diablo97\PLAYER.CPP +%c%c%c +PLR:2 +PlrGFX\%s\%s\%s%s.CL2 +pData +D:\diablo97\PLAYER.CPP +InitPlayerGFX: illegal player %d +InitPlrGFXMem: illegal player %d +! plr[pnum]._pNData +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +%c%c%c +PlrGFX\%s\%s\%s%s.CL2 +hsFile +D:\diablo97\PLAYER.CPP +FreePlayerGFX: illegal player %d +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +D:\diablo97\PLAYER.CPP +NewPlrAnim: illegal player %d +ClearPlrPVars: illegal player %d +SetPlrAnims: illegal player %d +p != NULL +D:\diablo97\PLAYER.CPP +CreatePlayer: illegal player %d +NextPlrLevel: illegal player %d +AddPlrExperience: illegal player %d +InitPlayer: illegal player %d +InitPlayer: illegal player %d +InitPlayer: illegal player %d +PlrGetDir: illegal player %d +PlrGetDirXY: illegal player %d +PlrDirOK: illegal player %d +SetPlayerOld: illegal player %d +FixPlayerLocation: illegal player %d +StartStand: illegal player %d +StartWalkStand: illegal player %d +PM_ChangeLightOff: illegal player %d +PM_ChangeOffset: illegal player %d +StartWalk: illegal player %d +StartWalk2: illegal player %d +StartWalk3: illegal player %d +StartAttack: illegal player %d +StartRangeAttack: illegal player %d +StartPlrBlock: illegal player %d +StartSpell: illegal player %d +FixPlrWalkTags: illegal player %d +StartPlrHit: illegal player %d + Duplicate item detected! +A duplicate item has been detected. Destroying duplicate... +StartPlayerKill: illegal player %d +Ear of %s +PlrDeadItem: illegal player %d +DropHalfPlayersGold: illegal player %d +StripTopGold: illegal player %d +(DWORD)pnum < MAX_PLRS +D:\diablo97\PLAYER.CPP +StartNewLvl: illegal player %d +gbMaxPlayers == 1 +D:\diablo97\PLAYER.CPP +gbMaxPlayers == 1 +D:\diablo97\PLAYER.CPP +StartNewLvl +RestartTownLvl: illegal player %d +PM_DoWalk: illegal player %d +PM_DoWalk2: illegal player %d +PM_DoWalk3: illegal player %d +WeaponDur: illegal player %d +PlrHitMonst: illegal monster %d +PlrHitMonst: illegal player %d +PlrHitPlr: illegal target player %d +PlrHitPlr: illegal attacking player %d +PM_DoAttack: illegal player %d +PM_DoRangeAttack: illegal player %d +ShieldDur: illegal player %d +PM_DoBlock: illegal player %d +PM_DoSpell: illegal player %d +PM_DoGotHit: illegal player %d +ArmorDur: illegal player %d +PM_DoDeath: illegal player %d +CheckNewPath: illegal player %d +PlrDeathModeOK: illegal player %d +ValidatePlayer: illegal player %d +ProcessPlayers: illegal player %d +plr[myplr].InvGrid[i] <= plr[myplr]._pNumInv +D:\diablo97\PLAYER.CPP +ClrPlrPath: illegal player %d +MakePlrPath: illegal player %d +CheckPlrSpell: illegal player %d +SyncPlrAnim: illegal player %d +SyncPlrAnim +plr[p]._pAnimData +D:\diablo97\PLAYER.CPP +SyncInitPlr: illegal player %d +CheckStats: illegal player %d +ModifyPlrStr: illegal player %d +ModifyPlrMag: illegal player %d +ModifyPlrDex: illegal player %d +ModifyPlrVit: illegal player %d +SetPlayerHitPoints: illegal player %d +SetPlrStr: illegal player %d +SetPlrMag: illegal player %d +SetPlrDex: illegal player %d +SetPlrVit: illegal player %d +InitDungMsgs: illegal player %d +PlayDungMsgs: illegal player %d +pszMsg +D:\diablo97\plrmsg.cpp +pszFmt +D:\diablo97\plrmsg.cpp +strlen(pMsg->str) < sizeof(pMsg->str) +D:\diablo97\plrmsg.cpp +(DWORD) pnum < MAX_PLRS +D:\diablo97\plrmsg.cpp +pszStr +D:\diablo97\plrmsg.cpp +strlen(plr[pnum]._pName) < PLR_NAME_LEN +D:\diablo97\plrmsg.cpp +strlen(pszStr) < MAX_SEND_STR_LEN +D:\diablo97\plrmsg.cpp +%s (lvl %d): %s +(DWORD)i < MAXPORTAL +D:\diablo97\portal.cpp +(DWORD)i < MAXPORTAL +D:\diablo97\portal.cpp +(DWORD)i < MAXPORTAL +D:\diablo97\portal.cpp +(DWORD)i < MAXPORTAL +D:\diablo97\portal.cpp +(DWORD)portalindex < MAXPORTAL +D:\diablo97\portal.cpp +(DWORD)portalindex < MAXPORTAL +D:\diablo97\portal.cpp +The Magic Rock +Black Mushroom +Gharbad The Weak +Zhar the Mad +Lachdanan +Diablo +The Butcher +Ogden's Sign +Halls of the Blind +Valor +Anvil of Fury +Warlord of Blood +The Curse of King Leoric +Poisoned Water Supply +The Chamber of Bone +Archbishop Lazarus +Grave Matters +Farmer's Orchard +Little Girl +Wandering Trader +The Defiler +Na-Krul +Cornerstone of the World +The Jersey's Jersey +King Leoric's Tomb +The Chamber of Bone +Maze +A Dark Passage +Unholy Altar +Levels\L3Data\L3pwater.pal +To %s +(DWORD)i < MAXQUESTS +D:\diablo97\Quests.cpp +(DWORD)m < MAXMONSTERS +D:\diablo97\Quests.cpp +gbMaxPlayers == 1 +D:\diablo97\Quests.cpp +(DWORD)q < MAXQUESTS +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +Levels\L4Data\Warlord2.DUN +(DWORD)(rw + x - 1) < MDMAXX +D:\diablo97\Quests.cpp +(DWORD)(rh + y - 1) < MDMAXY +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +Levels\L2Data\Bonestr1.DUN +(DWORD)(rw + x - 1) < MDMAXX +D:\diablo97\Quests.cpp +(DWORD)(rh + y - 1) < MDMAXY +D:\diablo97\Quests.cpp +(DWORD)q < MAXQUESTS +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +Levels\L1Data\Banner1.DUN +(DWORD)(x+rw-1) < MDMAXX +D:\diablo97\Quests.cpp +(DWORD)(y+rh-1) < MDMAXY +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +Levels\L2Data\Blind1.DUN +(DWORD)(x+rw-1) < MDMAXX +D:\diablo97\Quests.cpp +(DWORD)(y+rh-1) < MDMAXY +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +Levels\L2Data\Blood2.DUN +(DWORD)(rw + x - 1) < MDMAXX +D:\diablo97\Quests.cpp +(DWORD)(rh + y - 1) < MDMAXY +D:\diablo97\Quests.cpp +D:\diablo97\Quests.cpp +Levels\L3Data\L3pwater.pal +Levels\L3Data\L3pfoul.pal +Quest Log +Close Quest Log +(DWORD)q < MAXQUESTS +D:\diablo97\Quests.cpp +quests[q]._qactive != QUEST_NOTAVAIL +D:\diablo97\Quests.cpp +REGISTRATION_BLOCK +standing +walking (1) +walking (2) +walking (3) +attacking +getting hit +dying +attacking (special) +fading in +fading out +attacking (ranged) +standing (special) +attacking (special ranged) +delaying +charging +stoned +healing +talking +standing +walking (1) +walking (2) +walking (3) +attacking (melee) +attacking (ranged) +blocking +getting hit +dying +casting a spell +changing levels +quitting +missileactive[i] < MAXMISSILES && missileactive[i] >= 0 +D:\diablo97\SCROLLRT.CPP +missileactive[i] < MAXMISSILES && missileactive[i] >= 0 +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +sx < MAXDUNX +D:\diablo97\SCROLLRT.CPP +sy < MAXDUNY +D:\diablo97\SCROLLRT.CPP +(sy-1) < MAXDUNY +D:\diablo97\SCROLLRT.CPP +pDeadGuy->_deadData[dd] != NULL +D:\diablo97\SCROLLRT.CPP +bItem <= MAXITEMS && bItem >= 0 +D:\diablo97\SCROLLRT.CPP +bItem <= MAXITEMS && bItem >= 0 +D:\diablo97\SCROLLRT.CPP +bv < MAXOBJECTS && bv >= 0 +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +sx < MAXDUNX +D:\diablo97\SCROLLRT.CPP +sy < MAXDUNY +D:\diablo97\SCROLLRT.CPP +(sy-1) < MAXDUNY +D:\diablo97\SCROLLRT.CPP +pDeadGuy->_deadData[dd] != NULL +D:\diablo97\SCROLLRT.CPP +bItem <= MAXITEMS && bItem >= 0 +D:\diablo97\SCROLLRT.CPP +bItem <= MAXITEMS && bItem >= 0 +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +sx < MAXDUNX +D:\diablo97\SCROLLRT.CPP +sy < MAXDUNY +D:\diablo97\SCROLLRT.CPP +(sy-1) < MAXDUNY +D:\diablo97\SCROLLRT.CPP +pDeadGuy->_deadData[dd] != NULL +D:\diablo97\SCROLLRT.CPP +bItem <= MAXITEMS && bItem >= 0 +D:\diablo97\SCROLLRT.CPP +bItem <= MAXITEMS && bItem >= 0 +D:\diablo97\SCROLLRT.CPP +bv < MAXOBJECTS && bv >= 0 +D:\diablo97\SCROLLRT.CPP +object[bv]._oAnimData +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +! sgdwCursWdt +D:\diablo97\SCROLLRT.CPP +sgdwCursWdt * sgdwCursHgt < sizeof sgSaveBack +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +D:\diablo97\SCROLLRT.CPP +ysize >= 0 && ysize <= 480 +D:\diablo97\SCROLLRT.CPP +D:\diablo97\SCROLLRT.CPP +! (dwX & 3) +D:\diablo97\SCROLLRT.CPP +! (dwWdt & 3) +D:\diablo97\SCROLLRT.CPP +! gpBuffer +D:\diablo97\SCROLLRT.CPP +D:\diablo97\SCROLLRT.CPP +gpBuffer +D:\diablo97\SCROLLRT.CPP +E(;)I7?7EAI-N3O+Y5 +N"C#N*C+N.#+*3++132+;3 +Skeleton King's Lair +Bone Chamber +Maze +Poisoned Water Supply +Archbishop Lazarus' Lair +ObjIndex: Active object not found at (%d,%d) +D:\diablo97\SetMaps.cpp +D:\diablo97\SetMaps.cpp +Levels\L1Data\SklKng1.DUN +Levels\L1Data\SklKng2.DUN +Levels\L1Data\L1_2.pal +Levels\L2Data\Bonecha2.DUN +Levels\L2Data\Bonecha1.DUN +Levels\L2Data\L2_2.pal +Levels\L1Data\Lv1MazeA.DUN +Levels\L1Data\Lv1MazeB.DUN +Levels\L1Data\L1_5.pal +Levels\L1Data\Lv1MazeA.DUN +Levels\L3Data\Foulwatr.DUN +Levels\L3Data\Foulwatr.DUN +Levels\L3Data\L3pfoul.pal +Levels\L1Data\Vile1.DUN +Levels\L1Data\Vile2.DUN +Levels\L1Data\L1_2.pal +Levels\L1Data\Vile1.DUN +Music\DTowne.wav +Music\DLvlA.wav +Music\DLvlB.wav +Music\DLvlC.wav +Music\DLvlD.wav +Music\DLvlE.wav +Music\DLvlF.wav +Music\Dintro.wav +D:\diablo97\SOUND.CPP +pSnd +D:\diablo97\SOUND.CPP +pDSB +D:\diablo97\SOUND.CPP +D:\diablo97\SOUND.CPP +Invalid sound format on file %s +D:\diablo97\SOUND.CPP +D:\diablo97\SOUND.CPP +sglpDS +D:\diablo97\SOUND.CPP +D:\diablo97\SOUND.CPP +D:\diablo97\SOUND.CPP +! sglpDS +D:\diablo97\SOUND.CPP +! sglpDS || bSuccess +D:\diablo97\SOUND.CPP +! sglpDS || bSuccess +D:\diablo97\SOUND.CPP +sglpDS +D:\diablo97\SOUND.CPP +D:\diablo97\SOUND.CPP +D:\diablo97\SOUND.CPP +dsound.dll +D:\diablo97\SOUND.CPP +DirectSoundCreate +D:\diablo97\SOUND.CPP +(DWORD) nTrack < NUM_MUSIC +D:\diablo97\SOUND.CPP +lVolume >= VOLUME_MIN +D:\diablo97\SOUND.CPP +lVolume <= VOLUME_MAX +D:\diablo97\SOUND.CPP +lVolume >= VOLUME_MIN +D:\diablo97\SOUND.CPP +lVolume <= VOLUME_MAX +D:\diablo97\SOUND.CPP +Firebolt +Firebolt +Healing +Lightning +Flash +Identify +Identify +Fire Wall +Town Portal +Stone Curse +Infravision +Phasing +Mana Shield +Fireball +Guardian +Chain Lightning +Flame Wave +Doom Serpents +Blood Ritual +Nova +Invisibility +Inferno +Golem +Blood Boil +Teleport +Apocalypse +Etherealize +Item Repair +Item Repair +Staff Recharge +Staff Recharge +Trap Disarm +Trap Disarm +Elemental +Charged Bolt +Holy Bolt +Resurrect +Telekinesis +Heal Other +Blood Star +Bone Spirit +Mana +the Magi +the Jester +Lightning Wall +Immolation +Warp +Reflect +Berserk +Ring of Fire +Search +Search +Rune of Fire +Rune of Light +Rune of Nova +Rune of Immolation +Rune of Stone +Griswold +Pepin +Ogden +Cain +Farnham +Adria +Gillian +Wirt +! pSTextBoxCels +D:\diablo97\stores.cpp +D:\diablo97\stores.cpp +Data\TextBox2.CEL +D:\diablo97\stores.cpp +Data\PentSpn2.CEL +D:\diablo97\stores.cpp +Data\TextSlid.CEL +D:\diablo97\stores.cpp +D:\diablo97\stores.cpp +D:\diablo97\stores.cpp +gpBuffer +D:\diablo97\stores.cpp +gpBuffer +D:\diablo97\stores.cpp +Welcome to the +Blacksmith's shop +Would you like to: +Talk to Griswold +Buy basic items +Buy premium items +Sell items +Repair items +Leave the shop +Charges: %i/%i +Damage: %i-%i +Armor: %i +Indestructible, +Dur: %i/%i, +No required attributes +Required: +%s %i Str +%s %i Mag +%s %i Dex +Unique Item +I have these items for sale : Your gold : %i +Back +I have these premium items for sale : Your gold : %i +Back +You have nothing I want. Your gold : %i +Back +Which item is for sale? Your gold : %i +Back +You have nothing to repair. Your gold : %i +Back +Repair which item? Your gold : %i +Back +itm->_iMaxDur > 0 +D:\diablo97\stores.cpp +Witch's shack +Would you like to: +Talk to Adria +Buy items +Sell items +Recharge staves +Leave the shack +I have these items for sale : Your gold : %i +Back +You have nothing I want. Your gold : %i +Back +Which item is for sale? Your gold : %i +Back +You have nothing to recharge. Your gold : %i +Back +Recharge which item? Your gold : %i +Back +You do not have enough gold +You do not have enough room in inventory +Are you sure you want to buy this item? +Are you sure you want to sell this item? +Are you sure you want to repair this item? +Are you sure you want to recharge this item? +Do we have a deal? +Are you sure you want to identify this item? +Wirt the Peg-legged boy +Talk to Wirt +I have something for sale, +but it will cost 50 gold +just to take a look. +What have you got? +Say goodbye +Talk to Wirt +Say goodbye +I have this item for sale : Your gold : %i +Leave +Welcome to the +Healer's home +Would you like to: +Talk to Pepin +Buy items +Leave Healer's home +I have these items for sale : Your gold : %i +Back +The Town Elder +Would you like to: +Talk to Cain +Identify an item +Say goodbye +You have nothing to identify. Your gold : %i +Back +Identify which item? Your gold : %i +Back +This item is: +Done +Talk to %s +Gossip +Back +Welcome to the +Rising Sun +Would you like to: +Talk to Ogden +Leave the tavern +Gillian +Would you like to: +Talk to Gillian +Say goodbye +Farnham the Drunk +Would you like to: +Talk to Farnham +Say Goodbye +dwMaxLen <= 0xffff +D:\diablo97\sync.cpp +(DWORD) sgnSyncPInv < NUM_INVLOC +D:\diablo97\sync.cpp +bad sync command +gbBufferMsgs != BUFFER_PROCESS +D:\diablo97\sync.cpp +wLen == 0 +D:\diablo97\sync.cpp + Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh blow to this land. The people always loved the King, and now they live in mortal fear of him. The question that I keep asking myself is how he could have fallen so far from the Light, as Leoric had always been the holiest of men. Only the vilest powers of Hell could so utterly destroy a man from within... | +The village needs your help, good master! Some months ago King Leoric's son, Prince Albrecht, was kidnapped. The King went into a rage and scoured the village for his missing child. With each passing day, Leoric seemed to slip deeper into madness. He sought to blame innocent townsfolk for the boy's disappearance and had them brutally executed. Less than half of us survived his insanity... +The King's Knights and Priests tried to placate him, but he turned against them and sadly, they were forced to kill him. With his dying breath the King called down a terrible curse upon his former followers. He vowed that they would serve him in darkness forever... +This is where things take an even darker twist than I thought possible! Our former King has risen from his eternal sleep and now commands a legion of undead minions within the Labyrinth. His body was buried in a tomb three levels beneath the Cathedral. Please, good master, put his soul at ease by destroying his now cursed form... | +As I told you, good master, the King was entombed three levels below. He's down there, waiting in the putrid darkness for his chance to destroy this land... | +The curse of our King has passed, but I fear that it was only part of a greater evil at work. However, we may yet be saved from the darkness that consumes our land, for your victory is a good omen. May Light guide you on your way, good master. | +The loss of his son was too much for King Leoric. I did what I could to ease his madness, but in the end it overcame him. A black curse has hung over this kingdom from that day forward, but perhaps if you were to free his spirit from his earthly prison, the curse would be lifted... | +I don't like to think about how the King died. I like to remember him for the kind and just ruler that he was. His death was so sad and seemed very wrong, somehow. | +I made many of the weapons and most of the armor that King Leoric used to outfit his knights. I even crafted a huge two-handed sword of the finest mithril for him, as well as a field crown to match. I still cannot believe how he died, but it must have been some sinister force that drove him insane! | +I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is King. King, so you hear me? HAIL TO THE KING! | +The dead who walk among the living follow the cursed King. He holds the power to raise yet more warriors for an ever growing army of the undead. If you do not stop his reign, he will surely march across this land and slay all who still live here. | +Look, I'm running a business here. I don't sell information, and I don't care about some King that's been dead longer than I've been alive. If you need something to use against this King of the undead, then I can help you out... | +The warmth of life has entered my tomb. Prepare yourself, mortal, to serve my Master for eternity! | +I see that this strange behavior puzzles you as well. I would surmise that since many demons fear the light of the sun and believe that it holds great power, it may be that the rising sun depicted on the sign you speak of has led them to believe that it too holds some arcane powers. Hmm, perhaps they are not all as smart as we had feared... | +Master, I have a strange experience to relate. I know that you have a great knowledge of those monstrosities that inhabit the labyrinth, and this is something that I cannot understand for the very life of me... I was awakened during the night by a scraping sound just outside of my tavern. When I looked out from my bedroom, I saw the shapes of small demon-like creatures in the inn yard. After a short time, they ran off, but not before stealing the sign to my inn. I don't know why the demons would steal my sign but leave my family in peace... 'tis strange, no? | +Oh, you didn't have to bring back my sign, but I suppose that it does save me the expense of having another one made. Well, let me see, what could I give you as a fee for finding it? Hmmm, what have we here... ah, yes! This cap was left in one of the rooms by a magician who stayed here some time ago. Perhaps it may be of some value to you. | +My goodness, demons running about the village at night, pillaging our homes - is nothing sacred? I hope that Ogden and Garda are all right. I suppose that they would come to see me if they were hurt... | +Oh my! Is that where the sign went? My Grandmother and I must have slept right through the whole thing. Thank the Light that those monsters didn't attack the inn. | +Demons stole Ogden's sign, you say? That doesn't sound much like the atrocities I've heard of - or seen. +Demons are concerned with ripping out your heart, not your signpost. | +You know what I think? Somebody took that sign, and they gonna want lots of money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece of cheese... | +No mortal can truly understand the mind of the demon. +Never let their erratic actions confuse you, as that too may be their plan. | +What - is he saying I took that? I suppose that Griswold is on his side, too. +Look, I got over simple sign stealing months ago. You can't turn a profit on a piece of wood. | +Hey - You that one that kill all! You get me Magic Banner or we attack! You no leave with life! You kill big uglies and give back Magic. Go past corner and door, find uglies. You give, you go! | +You kill uglies, get banner. You bring to me, or else... | +You give! Yes, good! Go now, we strong. We kill all with big Magic! | +This does not bode well, for it confirms my darkest fears. While I did not allow myself to believe the ancient legends, I cannot deny them now. Perhaps the time has come to reveal who I am. +My true name is Deckard Cain the Elder, and I am the last descendant of an ancient Brotherhood that was dedicated to safeguarding the secrets of a timeless evil. An evil that quite obviously has now been released. +The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party of simple townsfolk into the Labyrinth to find the King's missing son, Albrecht. Quite some time passed before they returned, and only a few of them escaped with their lives. +Curse me for a fool! I should have suspected his veiled treachery then. It must have been Lazarus himself who kidnapped Albrecht and has since hidden him within the Labyrinth. I do not understand why the Archbishop turned to the darkness, or what his interest is in the child, unless he means to sacrifice him to his dark masters! +That must be what he has planned! The survivors of his 'rescue party' say that Lazarus was last seen running into the deepest bowels of the labyrinth. You must hurry and save the prince from the sacrificial blade of this demented fiend! | +You must hurry and rescue Albrecht from the hands of Lazarus. The prince and the people of this kingdom are counting on you! | +Your story is quite grim, my friend. Lazarus will surely burn in Hell for his horrific deed. The boy that you describe is not our prince, but I believe that Albrecht may yet be in danger. The symbol of power that you speak of must be a portal in the very heart of the labyrinth. +Know this, my friend - The evil that you move against is the dark Lord of Terror. He is known to mortal men as Diablo. It was he who was imprisoned within the Labyrinth many centuries ago and I fear that he seeks to once again sow chaos in the realm of mankind. You must venture through the portal and destroy Diablo before it is too late! | +Lazarus was the Archbishop who led many of the townspeople into the labyrinth. I lost many good friends that day, and Lazarus never returned. I suppose he was killed along with most of the others. If you would do me a favor, good master - please do not talk to Farnham about that day. | +I was shocked when I heard of what the townspeople were planning to do that night. I thought that of all people, Lazarus would have had more sense than that. He was an Archbishop, and always seemed to care so much for the townsfolk of Tristram. So many were injured, I could not save them all... | +I remember Lazarus as being a very kind and giving man. He spoke at my mother's funeral, and was supportive of my grandmother and myself in a very troubled time. I pray every night that somehow, he is still alive and safe. | +I was there when Lazarus led us into the labyrinth. He spoke of holy retribution, but when we started fighting those hellspawn, he did not so much as lift his mace against them. He just ran deeper into the dim, endless chambers that were filled with the servants of darkness! | +They stab, then bite, then they're all around you. Liar! LIAR! They're all dead! Dead! Do you hear me? They just keep falling and falling... their blood spilling out all over the floor... all his fault... | +I did not know this Lazarus of whom you speak, but I do sense a great conflict within his being. He poses a great danger, and will stop at nothing to serve the powers of darkness which have claimed him as theirs. | +Yes, the righteous Lazarus, who was sooo effective against those monsters down there. Didn't help save my leg, did it? Look, I'll give you a free piece of advice. Ask Farnham, he was there. | +Abandon your foolish quest. All that awaits you is the wrath of my Master! You are too late to save the child. Now you will join him in Hell! | +Hmm, I don't know what I can really tell you about this that will be of any help. The water that fills our wells comes from an underground spring. I have heard of a tunnel that leads to a great lake - perhaps they are one and the same. Unfortunately, I do not know what would cause our water supply to be tainted. | +I have always tried to keep a large supply of foodstuffs and drink in our storage cellar, but with the entire town having no source of fresh water, even our stores will soon run dry. +Please, do what you can or I don't know what we will do. | +I'm glad I caught up to you in time! Our wells have become brackish and stagnant and some of the townspeople have become ill drinking from them. Our reserves of fresh water are quickly running dry. I believe that there is a passage that leads to the springs that serve our town. Please find what has caused this calamity, or we all will surely perish. | +Please, you must hurry. Every hour that passes brings us closer to having no water to drink. +We cannot survive for long without your help. | +What's that you say - the mere presence of the demons had caused the water to become tainted? Oh, truly a great evil lurks beneath our town, but your perseverance and courage gives us hope. Please take this ring - perhaps it will aid you in the destruction of such vile creatures. | +My grandmother is very weak, and Garda says that we cannot drink the water from the wells. Please, can you do something to help us? | +Pepin has told you the truth. We will need fresh water badly, and soon. I have tried to clear one of the smaller wells, but it reeks of stagnant filth. It must be getting clogged at the source. | +You drink water? | +The people of Tristram will die if you cannot restore fresh water to their wells. +Know this - demons are at the heart of this matter, but they remain ignorant of what they have spawned. | +For once, I'm with you. My business runs dry - so to speak - if I have no market to sell to. You better find out what is going on, and soon! | +A book that speaks of a chamber of human bones? Well, a Chamber of Bone is mentioned in certain archaic writings that I studied in the libraries of the East. These tomes inferred that when the Lords of the underworld desired to protect great treasures, they would create domains where those who died in the attempt to steal that treasure would be forever bound to defend it. A twisted, but strangely fitting, end? | +I am afraid that I don't know anything about that, good master. Cain has many books that may be of some help. | +This sounds like a very dangerous place. If you venture there, please take great care. | +I am afraid that I haven't heard anything about that. Perhaps Cain the Storyteller could be of some help. | +I know nothing of this place, but you may try asking Cain. He talks about many things, and it would not surprise me if he had some answers to your question. | +Okay, so listen. There's this chamber of wood, see. And his wife, you know - her - tells the tree... cause you gotta wait. Then I says, that might work against him, but if you think I'm gonna PAY for this... you... uh... yeah. | +You will become an eternal servant of the dark lords should you perish within this cursed domain. +Enter the Chamber of Bone at your own peril. | +A vast and mysterious treasure, you say? Maybe I could be interested in picking up a few things from you... or better yet, don't you need some rare and expensive supplies to get you through this ordeal? | +It seems that the Archbishop Lazarus goaded many of the townsmen into venturing into the Labyrinth to find the King's missing son. He played upon their fears and whipped them into a frenzied mob. None of them were prepared for what lay within the cold earth... Lazarus abandoned them down there - left in the clutches of unspeakable horrors - to die. | +Yes, Farnham has mumbled something about a hulking brute who wielded a fierce weapon. I believe he called him a butcher. | +By the Light, I know of this vile demon. There were many that bore the scars of his wrath upon their bodies when the few survivors of the charge led by Lazarus crawled from the Cathedral. I don't know what he used to slice open his victims, but it could not have been of this world. It left wounds festering with disease and even I found them almost impossible to treat. Beware if you plan to battle this fiend... | +When Farnham said something about a butcher killing people, I immediately discounted it. But since you brought it up, maybe it is true. | +I saw what Farnham calls the Butcher as it swathed a path through the bodies of my friends. He swung a cleaver as large as an axe, hewing limbs and cutting down brave men where they stood. I was separated from the fray by a host of small screeching demons and somehow found the stairway leading out. I never saw that hideous beast again, but his blood-stained visage haunts me to this day. | +Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, couldn't save them. Trapped in a room with so many bodies... so many friends... NOOOOOOOOOO! | +The Butcher is a sadistic creature that delights in the torture and pain of others. You have seen his handiwork in the drunkard Farnham. His destruction will do much to ensure the safety of this village. | +I know more than you'd think about that grisly fiend. His little friends got a hold of me and managed to get my leg before Griswold pulled me out of that hole. +I'll put it bluntly - kill him before he kills you and adds your corpse to his collection. | +Please, listen to me. The Archbishop Lazarus, he led us down here to find the lost prince. The bastard led us into a trap! Now everyone is dead... killed by a demon he called the Butcher. Avenge us! Find this Butcher and slay him so that our souls may finally rest... | +You recite an interesting rhyme written in a style that reminds me of other works. Let me think now - what was it? +...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of razor claws briefly scraping to torment those poor souls who have been made sightless for all eternity. The prison for those so damned is named the Halls of the Blind... | +I never much cared for poetry. Occasionally, I had cause to hire minstrels when the inn was doing well, but that seems like such a long time ago now. +What? Oh, yes... uh, well, I suppose you could see what someone else knows. | +This does seem familiar, somehow. I seem to recall reading something very much like that poem while researching the history of demonic afflictions. It spoke of a place of great evil that... wait - you're not going there are you? | +If you have questions about blindness, you should talk to Pepin. I know that he gave my grandmother a potion that helped clear her vision, so maybe he can help you, too. | +I am afraid that I have neither heard nor seen a place that matches your vivid description, my friend. Perhaps Cain the Storyteller could be of some help. | +Look here... that's pretty funny, huh? Get it? Blind - look here? | +This is a place of great anguish and terror, and so serves its master well. +Tread carefully or you may yourself be staying much longer than you had anticipated. | +Lets see, am I selling you something? No. Are you giving me money to tell you about this? No. Are you now leaving and going to talk to the storyteller who lives for this kind of thing? Yes. | +You claim to have spoken with Lachdanan? He was a great hero during his life. Lachdanan was an honorable and just man who served his King faithfully for years. But of course, you already know that. +Of those who were caught within the grasp of the King's Curse, Lachdanan would be the least likely to submit to the darkness without a fight, so I suppose that your story could be true. If I were in your place, my friend, I would find a way to release him from his torture. | +You speak of a brave warrior long dead! I'll have no such talk of speaking with departed souls in my inn yard, thank you very much. | +A golden elixir, you say. I have never concocted a potion of that color before, so I can't tell you how it would effect you if you were to try to drink it. As your healer, I strongly advise that should you find such an elixir, do as Lachdanan asks and DO NOT try to use it. | +I've never heard of a Lachdanan before. I'm sorry, but I don't think that I can be of much help to you. | +If it is actually Lachdanan that you have met, then I would advise that you aid him. I dealt with him on several occasions and found him to be honest and loyal in nature. The curse that fell upon the followers of King Leoric would fall especially hard upon him. | + Lachdanan is dead. Everybody knows that, and you can't fool me into thinking any other way. You can't talk to the dead. I know! | +You may meet people who are trapped within the Labyrinth, such as Lachdanan. +I sense in him honor and great guilt. Aid him, and you aid all of Tristram. | +Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened beneath him. He was incinerated in a ball of hellfire, and can't answer your questions anymore. Oh, that isn't what happened? Then I guess you'll be buying something or you'll be on your way. | +Please, don't kill me, just hear me out. I was once Captain of King Leoric's Knights, upholding the laws of this land with justice and honor. Then his dark Curse fell upon us for the role we played in his tragic death. As my fellow Knights succumbed to their twisted fate, I fled from the King's burial chamber, searching for some way to free myself from the Curse. I failed... +I have heard of a Golden Elixir that could lift the Curse and allow my soul to rest, but I have been unable to find it. My strength now wanes, and with it the last of my humanity as well. Please aid me and find the Elixir. I will repay your efforts - I swear upon my honor. | +You have not found the Golden Elixir. I fear that I am doomed for eternity. Please, keep trying... | +You have saved my soul from damnation, and for that I am in your debt. If there is ever a way that I can repay you from beyond the grave I will find it, but for now - take my helm. On the journey I am about to take I will have little use for it. May it protect you against the dark powers below. Go with the Light, my friend... | +Griswold speaks of The Anvil of Fury - a legendary artifact long searched for, but never found. Crafted from the metallic bones of the Razor Pit demons, the Anvil of Fury was smelt around the skulls of the five most powerful magi of the underworld. Carved with runes of power and chaos, any weapon or armor forged upon this Anvil will be immersed into the realm of Chaos, imbedding it with magical properties. It is said that the unpredictable nature of Chaos makes it difficult to know what the outcome of this smithing will be... | +Don't you think that Griswold would be a better person to ask about this? He's quite handy, you know. | +If you had been looking for information on the Pestle of Curing or the Silver Chalice of Purification, I could have assisted you, my friend. However, in this matter, you would be better served to speak to either Griswold or Cain. | +Griswold's father used to tell some of us when we were growing up about a giant anvil that was used to make mighty weapons. He said that when a hammer was struck upon this anvil, the ground would shake with a great fury. Whenever the earth moves, I always remember that story. | +Greetings! It's always a pleasure to see one of my best customers! I know that you have been venturing deeper into the Labyrinth, and there is a story I was told that you may find worth the time to listen to... +One of the men who returned from the Labyrinth told me about a mystic anvil that he came across during his escape. His description reminded me of legends I had heard in my youth about the burning Hellforge where powerful weapons of magic are crafted. The legend had it that deep within the Hellforge rested the Anvil of Fury! This Anvil contained within it the very essence of the demonic underworld... +It is said that any weapon crafted upon the burning Anvil is imbued with great power. If this anvil is indeed the Anvil of Fury, I may be able to make you a weapon capable of defeating even the darkest lord of Hell! +Find the Anvil for me, and I'll get to work! | +Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could be your best hope, and I am sure that I can make you one of legendary proportions. | +I can hardly believe it! This is the Anvil of Fury - good work, my friend. Now we'll show those bastards that there are no weapons in Hell more deadly than those made by men! Take this and may Light protect you. | +Griswold can't sell his anvil. What will he do then? And I'd be angry too if someone took my anvil! | +There are many artifacts within the Labyrinth that hold powers beyond the comprehension of mortals. Some of these hold fantastic power that can be used by either the Light or the Darkness. Securing the Anvil from below could shift the course of the Sin War towards the Light. | +If you were to find this artifact for Griswold, it could put a serious damper on my business here. Awwww, you'll never find it. | +The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. Wherever this book you read from resides it is surely a place of great power. +Legends speak of a pedestal that is carved from obsidian stone and has a pool of boiling blood atop its bone encrusted surface. There are also allusions to Stones of Blood that will open a door that guards an ancient treasure... +The nature of this treasure is shrouded in speculation, my friend, but it is said that the ancient hero Arkaine placed the holy armor Valor in a secret vault. Arkaine was the first mortal to turn the tide of the Sin War and chase the legions of darkness back to the Burning Hells. +Just before Arkaine died, his armor was hidden away in a secret vault. It is said that when this holy armor is again needed, a hero will arise to don Valor once more. Perhaps you are that hero... | +Every child hears the story of the warrior Arkaine and his mystic armor known as Valor. If you could find its resting place, you would be well protected against the evil in the Labyrinth. | +Hmm... it sounds like something I should remember, but I've been so busy learning new cures and creating better elixirs that I must have forgotten. Sorry... | +The story of the magic armor called Valor is something I often heard the boys talk about. You had better ask one of the men in the village. | +The armor known as Valor could be what tips the scales in your favor. I will tell you that many have looked for it - including myself. Arkaine hid it well, my friend, and it will take more than a bit of luck to unlock the secrets that have kept it concealed oh, lo these many years. | +Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz... | +Should you find these Stones of Blood, use them carefully. +The way is fraught with danger and your only hope rests within your self trust. | +You intend to find the armor known as Valor? +No one has ever figured out where Arkaine stashed the stuff, and if my contacts couldn't find it, I seriously doubt you ever will either. | +I know of only one legend that speaks of such a warrior as you describe. His story is found within the ancient chronicles of the Sin War... +Stained by a thousand years of war, blood and death, the Warlord of Blood stands upon a mountain of his tattered victims. His dark blade screams a black curse to the living; a tortured invitation to any who would stand before this Executioner of Hell. +It is also written that although he was once a mortal who fought beside the Legion of Darkness during the Sin War, he lost his humanity to his insatiable hunger for blood. | +I am afraid that I haven't heard anything about such a vicious warrior, good master. I hope that you do not have to fight him, for he sounds extremely dangerous. | +Cain would be able to tell you much more about something like this than I would ever wish to know. | +If you are to battle such a fierce opponent, may Light be your guide and your defender. I will keep you in my thoughts. | +Dark and wicked legends surrounds the one Warlord of Blood. Be well prepared, my friend, for he shows no mercy or quarter. | +Always you gotta talk about Blood? What about flowers, and sunshine, and that pretty girl that brings the drinks. Listen here, friend - you're obsessive, you know that? | +His prowess with the blade is awesome, and he has lived for thousands of years knowing only warfare. I am sorry... I can not see if you will defeat him. | +I haven't ever dealt with this Warlord you speak of, but he sounds like he's going through a lot of swords. Wouldn't mind supplying his armies... | +My blade sings for your blood, mortal, and by my dark masters it shall not be denied. | +Griswold speaks of the Heaven Stone that was destined for the enclave located in the east. It was being taken there for further study. This stone glowed with an energy that somehow granted vision beyond that which a normal man could possess. I do not know what secrets it holds, my friend, but finding this stone would certainly prove most valuable. | +The caravan stopped here to take on some supplies for their journey to the east. I sold them quite an array of fresh fruits and some excellent sweetbreads that Garda has just finished baking. Shame what happened to them... | +I don't know what it is that they thought they could see with that rock, but I will say this. If rocks are falling from the sky, you had better be careful! | +Well, a caravan of some very important people did stop here, but that was quite a while ago. They had strange accents and were starting on a long journey, as I recall. +I don't see how you could hope to find anything that they would have been carrying. | +Stay for a moment - I have a story you might find interesting. A caravan that was bound for the eastern kingdoms passed through here some time ago. It was supposedly carrying a piece of the heavens that had fallen to earth! The caravan was ambushed by cloaked riders just north of here along the roadway. I searched the wreckage for this sky rock, but it was nowhere to be found. If you should find it, I believe that I can fashion something useful from it. | +I am still waiting for you to bring me that stone from the heavens. I know that I can make something powerful out of it. | +Let me see that - aye... aye, it is as I believed. Give me a moment... +Ah, Here you are. I arranged pieces of the stone within a silver ring that my father left me. I hope it serves you well. | +I used to have a nice ring; it was a really expensive one, with blue and green and red and silver. Don't remember what happened to it, though. I really miss that ring... | +The Heaven Stone is very powerful, and were it any but Griswold who bid you find it, I would prevent it. He will harness its powers and its use will be for the good of us all. | +If anyone can make something out of that rock, Griswold can. He knows what he is doing, and as much as I try to steal his customers, I respect the quality of his work. | +The witch Adria seeks a black mushroom? I know as much about Black Mushrooms as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, but this is something that cannot be found in any of my stories or books. | +Let me just say this. Both Garda and I would never, EVER serve black mushrooms to our honored guests. If Adria wants some mushrooms in her stew, then that is her business, but I can't help you find any. Black mushrooms... disgusting! | +The witch told me that you were searching for the brain of a demon to assist me in creating my elixir. It should be of great value to the many who are injured by those foul beasts, if I can just unlock the secrets I suspect that its alchemy holds. If you can remove the brain of a demon when you kill it, I would be grateful if you could bring it to me. | +Excellent, this is just what I had in mind. I was able to finish the elixir without this, but it can't hurt to have this to study. Would you please carry this to the witch? I believe that she is expecting it. | +I think Ogden might have some mushrooms in the storage cellar. Why don't you ask him? | +If Adria doesn't have one of these, you can bet that's a rare thing indeed. I can offer you no more help than that, but it sounds like... a huge, gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose. | +Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, listen... here's the secret - moderation is the key! | +What do we have here? Interesting, it looks like a book of reagents. Keep your eyes open for a black mushroom. It should be fairly large and easy to identify. If you find it, bring it to me, won't you? | +It's a big, black mushroom that I need. Now run off and get it for me so that I can use it for a special concoction that I am working on. | +Yes, this will be perfect for a brew that I am creating. By the way, the healer is looking for the brain of some demon or another so he can treat those who have been afflicted by their poisonous venom. I believe that he intends to make an elixir from it. If you help him find what he needs, please see if you can get a sample of the elixir for me. | +Why have you brought that here? I have no need for a demon's brain at this time. I do need some of the elixir that the Healer is working on. He needs that grotesque organ that you are holding, and then bring me the elixir. Simple when you think about it, isn't it? | +What? Now you bring me that elixir from the healer? I was able to finish my brew without it. Why don't you just keep it... | +I don't have any mushrooms of any size or color for sale. How about something a bit more useful? | +So, the legend of the Map is real. Even I never truly believed any of it! I suppose it is time that I told you the truth about who I am, my friend. You see, I am not all that I seem... +My true name is Deckard Cain the Elder, and I am the last descendant of an ancient Brotherhood that was dedicated to keeping and safeguarding the secrets of a timeless evil. An evil that quite obviously has now been released... +The evil that you move against is the dark Lord of Terror - known to mortal men as Diablo. It was he who was imprisoned within the Labyrinth many centuries ago. The Map that you hold now was created ages ago to mark the time when Diablo would rise again from his imprisonment. When the two stars on that map align, Diablo will be at the height of his power. He will be all but invincible... +You are now in a race against time, my friend! Find Diablo and destroy him before the stars align, for we may never have a chance to rid the world of his evil again! | +Our time is running short! I sense his dark power building and only you can stop him from attaining his full might. | +I am sure that you tried your best, but I fear that even your strength and will may not be enough. Diablo is now at the height of his earthly power, and you will need all your courage and strength to defeat him. May the Light protect and guide you, my friend. I will help in any way that I am able. | +If the witch can't help you and suggests you see Cain, what makes you think that I would know anything? It sounds like this is a very serious matter. You should hurry along and see the storyteller as Adria suggests. | +I can't make much of the writing on this map, but perhaps Adria or Cain could help you decipher what this refers to. +I can see that it is a map of the stars in our sky, but any more than that is beyond my talents. | +The best person to ask about that sort of thing would be our storyteller. +Cain is very knowledgeable about ancient writings, and that is easily the oldest looking piece of paper that I have ever seen. | +I have never seen a map of this sort before. Where'd you get it? Although I have no idea how to read this, Cain or Adria may be able to provide the answers that you seek. | +Listen here, come close. I don't know if you know what I know, but you have really got somethin' here. That's a map. | +Oh, I'm afraid this does not bode well at all. This map of the stars portends great disaster, but its secrets are not mine to tell. The time has come for you to have a very serious conversation with the Storyteller... | +I've been looking for a map, but that certainly isn't it. You should show that to Adria - she can probably tell you what it is. I'll say one thing; it looks old, and old usually means valuable. | +Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you. | +Something for you I am making. Again, not kill Gharbad. Live and give good. +You take this as proof I keep word... | +Nothing yet! Almost done. +Very powerful, very strong. Live! Live! +No pain and promise I keep! | +This too good for you. Very Powerful! You want - you take! | +What?! Why are you here? All these interruptions are enough to make one insane. Here, take this and leave me to my work. Trouble me no more! | +Arrrrgh! Your curiosity will be the death of you!!! | +Hello, my friend. Stay awhile and listen... | +While you are venturing deeper into the Labyrinth you may find tomes of great knowledge hidden there. +Read them carefully for they can tell you things that even I cannot. | +I know of many myths and legends that may contain answers to questions that may arise in your journeys into the Labyrinth. If you come across challenges and questions to which you seek knowledge, seek me out and I will tell you what I can. | +Griswold - a man of great action and great courage. I bet he never told you about the time he went into the Labyrinth to save Wirt, did he? He knows his fair share of the dangers to be found there, but then again - so do you. He is a skilled craftsman, and if he claims to be able to help you in any way, you can count on his honesty and his skill. | +Ogden has owned and run the Rising Sun Inn and Tavern for almost four years now. He purchased it just a few short months before everything here went to hell. He and his wife Garda do not have the money to leave as they invested all they had in making a life for themselves here. He is a good man with a deep sense of responsibility. | +Poor Farnham. He is a disquieting reminder of the doomed assembly that entered into the Cathedral with Lazarus on that dark day. He escaped with his life, but his courage and much of his sanity were left in some dark pit. He finds comfort only at the bottom of his tankard nowadays, but there are occasional bits of truth buried within his constant ramblings. | +The witch, Adria, is an anomaly here in Tristram. She arrived shortly after the Cathedral was desecrated while most everyone else was fleeing. She had a small hut constructed at the edge of town, seemingly overnight, and has access to many strange and arcane artifacts and tomes of knowledge that even I have never seen before. | +The story of Wirt is a frightening and tragic one. He was taken from the arms of his mother and dragged into the labyrinth by the small, foul demons that wield wicked spears. There were many other children taken that day, including the son of King Leoric. The Knights of the palace went below, but never returned. The Blacksmith found the boy, but only after the foul beasts had begun to torture him for their sadistic pleasures. | +Ah, Pepin. I count him as a true friend - perhaps the closest I have here. He is a bit addled at times, but never a more caring or considerate soul has existed. His knowledge and skills are equaled by few, and his door is always open. | +Gillian is a fine woman. Much adored for her high spirits and her quick laugh, she holds a special place in my heart. She stays on at the tavern to support her elderly grandmother who is too sick to travel. I sometimes fear for her safety, but I know that any man in the village would rather die than see her harmed. | +Greetings, good master. Welcome to the Tavern of the Rising Sun! | +Many adventurers have graced the tables of my tavern, and ten times as many stories have been told over as much ale. The only thing that I ever heard any of them agree on was this old axiom. Perhaps it will help you. You can cut the flesh, but you must crush the bone. | +Griswold the blacksmith is extremely knowledgeable about weapons and armor. If you ever need work done on your gear, he is definitely the man to see. | +Farnham spends far too much time here, drowning his sorrows in cheap ale. I would make him leave, but he did suffer so during his time in the Labyrinth. | +Adria is wise beyond her years, but I must admit - she frightens me a little. +Well, no matter. If you ever have need to trade in items of sorcery, she maintains a strangely well-stocked hut just across the river. | +If you want to know more about the history of our village, the storyteller Cain knows quite a bit about the past. | +Wirt is a rapscallion and a little scoundrel. He was always getting into trouble, and it's no surprise what happened to him. +He probably went fooling about someplace that he shouldn't have been. I feel sorry for the boy, but I don't abide the company that he keeps. | +Pepin is a good man - and certainly the most generous in the village. He is always attending to the needs of others, but trouble of some sort or another does seem to follow him wherever he goes... | +Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, she would have fled from here long ago. +Goodness knows I begged her to leave, telling her that I would watch after the old woman, but she is too sweet and caring to have done so. | +What ails you, my friend? | +I have made a very interesting discovery. Unlike us, the creatures in the Labyrinth can heal themselves without the aid of potions or magic. If you hurt one of the monsters, make sure it is dead or it very well may regenerate itself. | +Before it was taken over by, well, whatever lurks below, the Cathedral was a place of great learning. There are many books to be found there. If you find any, you should read them all, for some may hold secrets to the workings of the Labyrinth. | +Griswold knows as much about the art of war as I do about the art of healing. He is a shrewd merchant, but his work is second to none. Oh, I suppose that may be because he is the only blacksmith left here. | +Cain is a true friend and a wise sage. He maintains a vast library and has an innate ability to discern the true nature of many things. If you ever have any questions, he is the person to go to. | +Even my skills have been unable to fully heal Farnham. Oh, I have been able to mend his body, but his mind and spirit are beyond anything I can do. | +While I use some limited forms of magic to create the potions and elixirs I store here, Adria is a true sorceress. She never seems to sleep, and she always has access to many mystic tomes and artifacts. I believe her hut may be much more than the hovel it appears to be, but I can never seem to get inside the place. | +Poor Wirt. I did all that was possible for the child, but I know he despises that wooden peg that I was forced to attach to his leg. His wounds were hideous. No one - and especially such a young child - should have to suffer the way he did. | +I really don't understand why Ogden stays here in Tristram. He suffers from a slight nervous condition, but he is an intelligent and industrious man who would do very well wherever he went. I suppose it may be the fear of the many murders that happen in the surrounding countryside, or perhaps the wishes of his wife that keep him and his family where they are. | +Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers from delusions. +She claims that they are visions, but I have no proof of that one way or the other. | +Good day! How may I serve you? | +My grandmother had a dream that you would come and talk to me. She has visions, you know and can see into the future. | +The woman at the edge of town is a witch! She seems nice enough, and her name, Adria, is very pleasing to the ear, but I am very afraid of her. +It would take someone quite brave, like you, to see what she is doing out there. | +Our Blacksmith is a point of pride to the people of Tristram. Not only is he a master craftsman who has won many contests within his guild, but he received praises from our King Leoric himself - may his soul rest in peace. Griswold is also a great hero; just ask Cain. | +Cain has been the storyteller of Tristram for as long as I can remember. He knows so much, and can tell you just about anything about almost everything. | +Farnham is a drunkard who fills his belly with ale and everyone else's ears with nonsense. +I know that both Pepin and Ogden feel sympathy for him, but I get so frustrated watching him slip farther and farther into a befuddled stupor every night. | +Pepin saved my grandmother's life, and I know that I can never repay him for that. His ability to heal any sickness is more powerful than the mightiest sword and more mysterious than any spell you can name. If you ever are in need of healing, Pepin can help you. | +I grew up with Wirt's mother, Canace. Although she was only slightly hurt when those hideous creatures stole him, she never recovered. I think she died of a broken heart. Wirt has become a mean-spirited youngster, looking only to profit from the sweat of others. I know that he suffered and has seen horrors that I cannot even imagine, but some of that darkness hangs over him still. | +Ogden and his wife have taken me and my grandmother into their home and have even let me earn a few gold pieces by working at the inn. I owe so much to them, and hope one day to leave this place and help them start a grand hotel in the east. | +Well, what can I do for ya? | +If you're looking for a good weapon, let me show this to you. Take your basic blunt weapon, such as a mace. Works like a charm against most of those undying horrors down there, and there's nothing better to shatter skinny little skeletons! | +The axe? Aye, that's a good weapon, balanced against any foe. Look how it cleaves the air, and then imagine a nice fat demon head in its path. Keep in mind, however, that it is slow to swing - but talk about dealing a heavy blow! | +Look at that edge, that balance. A sword in the right hands, and against the right foe, is the master of all weapons. Its keen blade finds little to hack or pierce on the undead, but against a living, breathing enemy, a sword will better slice their flesh! | +Your weapons and armor will show the signs of your struggles against the Darkness. If you bring them to me, with a bit of work and a hot forge, I can restore them to top fighting form. | +While I have to practically smuggle in the metals and tools I need from caravans that skirt the edges of our damned town, that witch, Adria, always seems to get whatever she needs. If I knew even the smallest bit about how to harness magic as she did, I could make some truly incredible things. | +Gillian is a nice lass. Shame that her gammer is in such poor health or I would arrange to get both of them out of here on one of the trading caravans. | +Sometimes I think that Cain talks too much, but I guess that is his calling in life. If I could bend steel as well as he can bend your ear, I could make a suit of court plate good enough for an Emperor! | +I was with Farnham that night that Lazarus led us into Labyrinth. I never saw the Archbishop again, and I may not have survived if Farnham was not at my side. I fear that the attack left his soul as crippled as, well, another did my leg. I cannot fight this battle for him now, but I would if I could. | +A good man who puts the needs of others above his own. You won't find anyone left in Tristram - or anywhere else for that matter - who has a bad thing to say about the healer. | +That lad is going to get himself into serious trouble... or I guess I should say, again. I've tried to interest him in working here and learning an honest trade, but he prefers the high profits of dealing in goods of dubious origin. I cannot hold that against him after what happened to him, but I do wish he would at least be careful. | +The Innkeeper has little business and no real way of turning a profit. He manages to make ends meet by providing food and lodging for those who occasionally drift through the village, but they are as likely to sneak off into the night as they are to pay him. If it weren't for the stores of grains and dried meats he kept in his cellar, why, most of us would have starved during that first year when the entire countryside was overrun by demons. | +Can't a fella drink in peace? | +The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too. | +Why don't that old crone do somethin' for a change. Sure, sure, she's got stuff, but you listen to me... she's unnatural. I ain't never seen her eat or drink - and you can't trust somebody who doesn't drink at least a little. | +Cain isn't what he says he is. Sure, sure, he talks a good story... some of 'em are real scary or funny... but I think he knows more than he knows he knows. | +Griswold? Good old Griswold. I love him like a brother! We fought together, you know, back when... we... Lazarus... Lazarus... Lazarus!!! | +Hehehe, I like Pepin. He really tries, you know. Listen here, you should make sure you get to know him. Good fella like that with people always wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a hero too... | +Wirt is a kid with more problems than even me, and I know all about problems. Listen here - that kid is gotta sweet deal, but he's been there, you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad... | +Ogden is the best man in town. I don't think his wife likes me much, but as long as she keeps tappin' kegs, I'll like her just fine. Seems like I been spendin' more time with Ogden than most, but he's so good to me... | +I wanna tell ya sumthin', 'cause I know all about this stuff. It's my specialty. This here is the best... theeeee best! That other ale ain't no good since those stupid dogs... | +No one ever lis... listens to me. Somewhere - I ain't too sure - but somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and just waitin' for someone to get it. | +I know you gots your own ideas, and I know you're not gonna believe this, but that weapon you got there - it just ain't no good against those big brutes! Oh, I don't care what Griswold says, they can't make anything like they used to in the old days... | +If I was you... and I ain't... but if I was, I'd sell all that stuff you got and get out of here. That boy out there... He's always got somethin good, but you gotta give him some gold or he won't even show you what he's got. | +I sense a soul in search of answers... | +Wisdom is earned, not given. If you discover a tome of knowledge, devour its words. Should you already have knowledge of the arcane mysteries scribed within a book, remember - that level of mastery can always increase. | +The greatest power is often the shortest lived. You may find ancient words of power written upon scrolls of parchment. The strength of these scrolls lies in the ability of either apprentice or adept to cast them with equal ability. Their weakness is that they must first be read aloud and can never be kept at the ready in your mind. Know also that these scrolls can be read but once, so use them with care. | +Though the heat of the sun is beyond measure, the mere flame of a candle is of greater danger. No energies, no matter how great, can be used without the proper focus. For many spells, ensorcelled Staves may be charged with magical energies many times over. I have the ability to restore their power - but know that nothing is done without a price. | +The sum of our knowledge is in the sum of its people. Should you find a book or scroll that you cannot decipher, do not hesitate to bring it to me. If I can make sense of it I will share what I find. | +To a man who only knows Iron, there is no greater magic than Steel. The blacksmith Griswold is more of a sorcerer than he knows. His ability to meld fire and metal is unequaled in this land. | +Corruption has the strength of deceit, but innocence holds the power of purity. The young woman Gillian has a pure heart, placing the needs of her matriarch over her own. She fears me, but it is only because she does not understand me. | +A chest opened in darkness holds no greater treasure than when it is opened in the light. The storyteller Cain is an enigma, but only to those who do not look. His knowledge of what lies beneath the cathedral is far greater than even he allows himself to realize. | +The higher you place your faith in one man, the farther it has to fall. Farnham has lost his soul, but not to any demon. It was lost when he saw his fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to be gleaned, but you must separate fact from fantasy. | +The hand, the heart and the mind can perform miracles when they are in perfect harmony. The healer Pepin sees into the body in a way that even I cannot. His ability to restore the sick and injured is magnified by his understanding of the creation of elixirs and potions. He is as great an ally as you have in Tristram. | +There is much about the future we cannot see, but when it comes it will be the children who wield it. The boy Wirt has a blackness upon his soul, but he poses no threat to the town or its people. His secretive dealings with the urchins and unspoken guilds of nearby towns gain him access to many devices that cannot be easily found in Tristram. While his methods may be reproachful, Wirt can provide assistance for your battle against the encroaching Darkness. | +Earthen walls and thatched canopy do not a home create. The innkeeper Ogden serves more of a purpose in this town than many understand. He provides shelter for Gillian and her matriarch, maintains what life Farnham has left to him, and provides an anchor for all who are left in the town to what Tristram once was. His tavern, and the simple pleasures that can still be found there, provide a glimpse of a life that the people here remember. It is that memory that continues to feed their hopes for your success. | +Pssst... over here... | +Not everyone in Tristram has a use - or a market - for everything you will find in the labyrinth. Not even me, as hard as that is to believe. +Sometimes, only you will be able to find a purpose for some things. | +Don't trust everything the drunk says. Too many ales have fogged his vision and his good sense. | +In case you haven't noticed, I don't buy anything from Tristram. I am an importer of quality goods. If you want to peddle junk, you'll have to see Griswold, Pepin or that witch, Adria. I'm sure that they will snap up whatever you can bring them... | +I guess I owe the blacksmith my life - what there is of it. Sure, Griswold offered me an apprenticeship at the smithy, and he is a nice enough guy, but I'll never get enough money to... well, let's just say that I have definite plans that require a large amount of gold. | +If I were a few years older, I would shower her with whatever riches I could muster, and let me assure you I can get my hands on some very nice stuff. Gillian is a beautiful girl who should get out of Tristram as soon as it is safe. Hmmm... maybe I'll take her with me when I go... | +Cain knows too much. He scares the life out of me - even more than that woman across the river. He keeps telling me about how lucky I am to be alive, and how my story is foretold in legend. I think he's off his crock. | +Farnham - now there is a man with serious problems, and I know all about how serious problems can be. He trusted too much in the integrity of one man, and Lazarus led him into the very jaws of death. Oh, I know what it's like down there, so don't even start telling me about your plans to destroy the evil that dwells in that Labyrinth. Just watch your legs... | +As long as you don't need anything reattached, old Pepin is as good as they come. +If I'd have had some of those potions he brews, I might still have my leg... | +Adria truly bothers me. Sure, Cain is creepy in what he can tell you about the past, but that witch can see into your past. She always has some way to get whatever she needs, too. Adria gets her hands on more merchandise than I've seen pass through the gates of the King's Bazaar during High Festival. | +Ogden is a fool for staying here. I could get him out of town for a very reasonable price, but he insists on trying to make a go of it with that stupid tavern. I guess at the least he gives Gillian a place to work, and his wife Garda does make a superb Shepherd's pie... | +Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any who would seek to steal the treasures secured within this room. So speaks the Lord of Terror, and so it is written. | +...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor awaits for the Hero of Light to awaken... | +I can see what you see not. +Vision milky then eyes rot. +When you turn they will be gone, +Whispering their hidden song. +Then you see what cannot be, +Shadows move where light should be. +Out of darkness, out of mind, +Cast down into the Halls of the Blind. | +The armories of Hell are home to the Warlord of Blood. In his wake lay the mutilated bodies of thousands. Angels and man alike have been cut down to fulfill his endless sacrifices to the Dark ones who scream for one thing - blood. | +Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. There is a war that rages on even now, beyond the fields that we know - between the utopian kingdoms of the High Heavens and the chaotic pits of the Burning Hells. This war is known as the Great Conflict, and it has raged and burned longer than any of the stars in the sky. Neither side ever gains sway for long as the forces of Light and Darkness constantly vie for control over all creation. | +Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. When the Eternal Conflict between the High Heavens and the Burning Hells falls upon mortal soil, it is called the Sin War. Angels and Demons walk amongst humanity in disguise, fighting in secret, away from the prying eyes of mortals. Some daring, powerful mortals have even allied themselves with either side, and helped to dictate the course of the Sin War. | +Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. Nearly three hundred years ago, it came to be known that the Three Prime Evils of the Burning Hells had mysteriously come to our world. The Three Brothers ravaged the lands of the east for decades, while humanity was left trembling in their wake. Our Order - the Horadrim - was founded by a group of secretive magi to hunt down and capture the Three Evils once and for all. +The original Horadrim captured two of the Three within powerful artifacts known as Soulstones and buried them deep beneath the desolate eastern sands. The third Evil escaped capture and fled to the west with many of the Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - was eventually captured, his essence set in a Soulstone and buried within this Labyrinth. +Be warned that the soulstone must be kept from discovery by those not of the faith. If Diablo were to be released, he would seek a body that is easily controlled as he would be very weak - perhaps that of an old man or a child. | +So it came to be that there was a great revolution within the Burning Hells known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils and banished their spirit forms to the mortal realm. The demons Belial (the Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of Hell during the absence of the Three Brothers. All of Hell polarized between the factions of Belial and Azmodan while the forces of the High Heavens continually battered upon the very Gates of Hell. | +Many demons traveled to the mortal realm in search of the Three Brothers. These demons were followed to the mortal plane by Angels who hunted them throughout the vast cities of the East. The Angels allied themselves with a secretive Order of mortal magi named the Horadrim, who quickly became adept at hunting demons. They also made many dark enemies in the underworlds. | +So it came to be that the Three Prime Evils were banished in spirit form to the mortal realm and after sewing chaos across the East for decades, they were hunted down by the cursed Order of the mortal Horadrim. The Horadrim used artifacts called Soulstones to contain the essence of Mephisto, the Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest brother - Diablo, the Lord of Terror - escaped to the west. +Eventually the Horadrim captured Diablo within a Soulstone as well, and buried him under an ancient, forgotten Cathedral. There, the Lord of Terror sleeps and awaits the time of his rebirth. Know ye that he will seek a body of youth and power to possess - one that is innocent and easily controlled. He will then arise to free his Brothers and once more fan the flames of the Sin War... | +All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When he awakened from his long slumber, my Lord and Master spoke to me of secrets that few mortals know. He told me the kingdoms of the High Heavens and the pits of the Burning Hells engage in an eternal war. He revealed the powers that have brought this discord to the realms of man. My lord has named the battle for this world and all who exist here the Sin War. | +Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished to this world long ago. My Lord wishes to bide his time and harness his awesome power so that he may free his captive brothers from their tombs beneath the sands of the east. Once my Lord releases his Brothers, the Sin War will once again know the fury of the Three. | +Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I awoke my Master from his sleep, he attempted to possess a mortal's form. Diablo attempted to claim the body of King Leoric, but my Master was too weak from his imprisonment. My Lord required a simple and innocent anchor to this world, and so found the boy Albrecht to be perfect for the task. While the good King Leoric was left maddened by Diablo's unsuccessful possession, I kidnapped his son Albrecht and brought him before my Master. I now await Diablo's call and pray that I will be rewarded when he at last emerges as the Lord of this world. | +Thank goodness you've returned! +Much has changed since you lived here, my friend. All was peaceful until the dark riders came and destroyed our village. Many were cut down where they stood, and those who took up arms were slain or dragged away to become slaves - or worse. The church at the edge of town has been desecrated and is being used for dark rituals. The screams that echo in the night are inhuman, but some of our townsfolk may yet survive. Follow the path that lies between my tavern and the blacksmith shop to find the church and save who you can. +Perhaps I can tell you more if we speak again. Good luck.| +Maintain your quest. Finding a treasure that is lost is not easy. Finding a treasure that is hidden less so. I will leave you with this. Do not let the sands of time confuse your search.| +A what?! This is foolishness. There's no treasure buried here in Tristram. Let me see that!! Ah, Look these drawings are inaccurate. They don't match our town at all. I'd keep my mind on what lies below the cathedral and not what lies below our topsoil.| +I really don't have time to discus some map you are looking for. I have many sick people that require my help and yours as well.| +The once proud Iswall is trapped deep beneath the surface of this world. His honor stripped and his visage altered. He is trapped in immortal torment. Charged to conceal the very thing that could free him.| +I'll bet that Wirt saw you coming and put on an act just so he could laugh at you later when you were running around the town with your nose in the dirt. I'd ignore it.| +There was a time when this town was a frequent stop for travelers from far and wide. Much has changed since then. But hidden caves and buried treasure are common fantasies of any child. Wirt seldom indulges in youthful games. So it may just be his imagination.| +Listen here. Come close. I don't know if you know what I know, but you've have really got something here. That's a map.| +My grandmother often tells me stories about the strange forces that inhabit the graveyard outside of the church. And it may well interest you to hear one of them. She said that if you were to leave the proper offering in the cemetary, enter the cathedral to pray for the dead, and then return, the offering would be altered in some strange way. I don't know if this is just the talk of an old sick woman, but anything seems possible these days.| +Hmmm. A vast and mysterious treasure you say. Mmmm. Maybe I could be interested in picking up a few things from you. Or better yet, don't you need some rare and expensive supplies to get you through this ordeal?| +Moo.| +I said, Moo.| +Look I'm just a cow, OK?| +All right, all right. I'm not really a cow. I don't normally go around like this; but, I was sitting at home minding my own business and all of a sudden these bugs & vines & bulbs & stuff started coming out of the floor... it was horrible! If only I had something normal to wear, it wouldn't be so bad. Hey! Could you go back to my place and get my suit for me? The brown one, not the gray one, that's for evening wear. I'd do it myself, but I don't want anyone seeing me like this. Here, take this, you might need it... to kill those things that have overgrown everything. You can't miss my house, it's just south of the fork in the river... you know... the one with the overgrown vegetable garden.| +All right, I'll cut the bull. I didn't mean to steer you wrong. I was sitting at home, feeling moo-dy, when things got really un-stable; a whole stampede of monsters came out of the floor! I just cowed. I just happened to be wearing this Jersey when I ran out the door, and now I look udderly ridiculous. If only I had something normal to wear, it wouldn't be so bad. Hey! Can you go back to my place and get my suit for me? The brown one, not the gray one, that's for evening wear. I'd do it myself, but I don't want anyone seeing me like this. Here, take this, you might need it... to kill those things that have overgrown everything. You can't miss my house, it's just south of the fork in the river... you know... the one with the overgrown vegetable garden.| +What are you wasting time for? Go get my suit! And hurry! That Holstein over there keeps winking at me! | +Hey, have you got my suit there? Quick, pass it over! These ears itch like you wouldn't believe!| +No no no no! This is my GRAY suit! It's for evening wear! Formal occasions! I can't wear THIS. What are you, some kind of weirdo? I need the BROWN suit.| +Ahh, that's MUCH better. Whew! At last, some dignity! Are my antlers on straight? Good. Look, thanks a lot for helping me out. Here, take this as a gift; and, you know... a little fashion tip... you could use a little... you could use a new... yknowwhatImean? The whole adventurer motif is just so... retro. Just a word of advice, eh? Ciao.| +And in the year of the Golden Light, it was so decreed that a great Cathedral be raised. The cornerstone of this holy place was to be carved from the translucent stone Antyrael, named for the Angel who shared his power with the Horadrim. +In the Year of Drawing Shadows, the ground shook and the Cathedral shattered and fell. As the building of catacombs and castles began and man stood against the ravages of the Sin War, the ruins were scavenged for their stones. And so it was that the cornerstone vanished from the eyes of man. +The stone was of this world -- and of all worlds -- as the Light is both within all things and beyond all things. Light and unity are the products of this holy foundation, a unity of purpose and a unity of possession.| +Waaaah! (sniff) Waaaah! (sniff)| +I lost Theo! I lost my best friend! We were playing over by the river, and Theo said he wanted to go look at the big green thing. I said we shouldn't, but we snuck over there, and then suddenly this BUG came out! We ran away but Theo fell down and the bug GRABBED him and took him away!| +Didja find him? You gotta find Theodore, please! He's just little. He can't take care of himself! Please!| +You found him! You found him! Thank you! Oh Theo, did those nasty bugs scare you? Hey! Ugh! There's something stuck to your fur! Ick! Come on, Theo, let's go home! Thanks again, hero person!| +So, you're the hero everyone's been talking about. Perhaps you could help a poor, simple farmer out of a terrible mess? At the edge of my orchard, just south of here, there's a horrible thing swelling out of the ground! I can't get to my crops or my bales of hay, and my poor cows will starve. The witch gave this to me and said that it would blast that thing out of my field. If you could destroy it, I would be forever grateful. I'd do it myself, but someone has to stay here with the cows...| +I knew that it couldn't be as simple as that witch made it sound. It's a sad world when you can't even trust your neighbors.| +It must truly be a fearsome task I've set before you. If there was just some way that I could... would a flagon of some nice, fresh milk help?| +Is it gone? Did you send it back to the dark recesses of Hades that spawned it? You what? Oh, don't tell me you lost it! Those things don't come cheap, you know. You've got to find it, and then blast that horror out of our town.| +I heard the explosion from here! Many thanks to you, kind stranger. What with all these things comin' out of the ground, monsters taking over the church, and so forth, these are trying times. I am but a poor farmer, but here -- take this with my great thanks.| +Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with all the other troubles. Maybe after you've cleansed the church of some of those creatures you could come back... and spare a little time to help a poor farmer?| +Oh, I could use your help, but perhaps after you've saved the catacombs from the desecration of those beasts.| +I need something done, but I couldn't impose on a perfect stranger. Perhaps after you've been here a while I might feel more comfortable asking a favor.| +I see in you the potential for greatness. Perhaps sometime while you are fulfilling your destiny, you could stop by and do a little favor for me?| +I think you could probably help me, but perhaps after you've gotten a little more powerful. I wouldn't want to injure the village's only chance to destroy the menace in the church!| +Cloudy and cooler today. Casting the nets of necromancy across the void landed two new subspecies of flying horror; a good day's work. Must remember to order some more bat guano and black candles from Adria; I'm running a bit low.| +I have tried spells, threats, abjuration and bargaining with this foul creature -- to no avail. My methods of enslaving lesser demons seem to have no effect on this fearsome beast.| +full of shadows that move just beyond the corners of my vision. The faint scrabble of claws dances at the edges of my hearing. They are searching, I think, for this journal.| +In its ranting, the creature has let slip its name -- Na-Krul. I have attempted to research the name, but the smaller demons have somehow destroyed my library. Na-Krul... The name fills me with a cold dread. I prefer to think of it only as The Creature rather than ponder its true name.| +The entrapped creature's howls of fury keep me from gaining much needed sleep. It rages against the one who sent it to the Void, and it calls foul curses upon me for trapping it here. Its words fill my heart with terror, and yet I cannot block out its voice.| +My time is quickly running out. I must record the ways to weaken the demon, and then conceal that text, lest his minions find some way to use my knowledge to free their lord. I hope that whoever finds this journal will seek the knowledge.| +Whoever finds this scroll is charged with stopping the demonic creature that lies within these walls. My time is over. Even now, its hellish minions claw at the frail door behind which I hide. +I have hobbled the demon with arcane magic and encased it within great walls, but I fear that will not be enough. +The spells found in my three grimoires will provide you protected entrance to his domain, but only if cast in their proper sequence. The levers at the entryway will remove the barriers and free the demon; touch them not! Use only these spells to gain entry or his power may be too great for you to defeat.| +Ahh, mammal, welcome. Such a... tasty planet you have. My Nest shall spread across this land, and you and your species shall serve as food for our colony. I'm sure our meeting will be quite... delicious. | +Have you been enjoying yourself, little mammal? How pathetic. Your little world will be no challenge at all.| +Come closer, morsel...come find me, the Defiler. I have waited thousands of years...do not try my patience any further. | +Ah, I can smell you...you are close! Close! Ssss...the scent of blood and fear...how enticing...| +We have long lain dormant, and the time to awaken has come. After our long sleep, we are filled with great hunger. Soon, now, we shall feed...| +These lands shall be defiled, and our brood shall overrun the fields that men call home. Our tendrils shall envelop this world, and we will feast on the flesh of its denizens. Man shall become our chattel and sustenance.| +Come closer, morsel! I smell your terror, and I hunger.| +In Spiritu Sanctum. | +Praedictum Otium. | +Efficio Obitus Ut Inimicus. | +(DWORD)i < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)themeCount < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)numthemes < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)t < MAXTHEMES +D:\diablo97\themes.cpp +(DWORD)numthemes < MAXTHEMES +D:\diablo97\themes.cpp +pbMsg +D:\diablo97\tmsg.cpp +bLen +D:\diablo97\tmsg.cpp +bLen <= dwMaxLen +D:\diablo97\tmsg.cpp +D:\diablo97\tmsg.cpp +pbMsg +D:\diablo97\tmsg.cpp +bLen +D:\diablo97\tmsg.cpp +D:\diablo97\tmsg.cpp +! sgpTimedMsgHead +D:\diablo97\tmsg.cpp +D:\diablo97\tmsg.cpp +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +item[bv]._iAnimData +D:\diablo97\TOWN.CPP +towner[mi]._tAnimData +D:\diablo97\TOWN.CPP +towner[mi]._tAnimData +D:\diablo97\TOWN.CPP +plr[bv]._pAnimData +D:\diablo97\TOWN.CPP +plr[bv]._pAnimData +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +gpBuffer +D:\diablo97\TOWN.CPP +D:\diablo97\TOWN.CPP +Levels\TownData\Town.TIL +D:\diablo97\TOWN.CPP +Levels\TownData\Sector1s.DUN +D:\diablo97\TOWN.CPP +D:\diablo97\TOWN.CPP +Levels\TownData\Sector2s.DUN +D:\diablo97\TOWN.CPP +D:\diablo97\TOWN.CPP +Levels\TownData\Sector3s.DUN +D:\diablo97\TOWN.CPP +D:\diablo97\TOWN.CPP +Levels\TownData\Sector4s.DUN +D:\diablo97\TOWN.CPP +D:\diablo97\TOWN.CPP +pAnim +D:\diablo97\towners.cpp +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Smith\SmithN.CEL +Griswold the Blacksmith +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\TwnF\TwnFN.CEL +Ogden the Tavern owner +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Butch\Deadguy.CEL +Wounded Townsman +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\TownWmn1\Witch.CEL +Adria the Witch +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\TownWmn1\WmnN.CEL +Gillian the Barmaid +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\TownBoy\PegKid1.CEL +Wirt the Peg-legged boy +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Healer\Healer.CEL +Pepin the Healer +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Strytell\Strytell.CEL +Cain the Elder +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Drunk\TwnDrunk.CEL +Farnham the Drunk +! pCowCels +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Animals\Cow.CEL +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Farmer\Farmrn2.CEL +Lester the farmer +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Farmer\cfrmrn2.CEL +D:\diablo97\towners.cpp +Towners\Farmer\mfrmrn2.CEL +Complete Nut +! towner[numtowners]._tNData +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Towners\Girl\Girlw1.CEL +D:\diablo97\towners.cpp +Towners\Girl\Girls1.CEL +Celia +D:\diablo97\towners.cpp +D:\diablo97\towners.cpp +Slain Townsman +D:\diablo97\towners.cpp +Towners\Farmer\mfrmrn2.CEL +Down to Crypt +Down to Hive +Down to dungeon +Down to catacombs +Down to caves +Down to hell +Up to level %i +Up to town +Down to level %i +Up to Crypt level %i +Cornerstone of the World +Down to Crypt level %i +Up to town +Up to level %i +Down to level %i +Up to town +Up to level %i +Down to level %i +Up to Nest level %i +Down to level %i +Up to town +Up to town +Up to level %i +Down to level %i +Up to town +Down to Diablo +Back to Level %i +Back to Level %i +Back to Level %i +gbMaxPlayers == 1 +D:\diablo97\TRIGS.CPP +Unknown trigger msg +bytestoread == dwBytes +D:\diablo97\wave.cpp +hsFile +D:\diablo97\wave.cpp +pMemFile +D:\diablo97\wave.cpp +D:\diablo97\wave.cpp +pMemFile +D:\diablo97\wave.cpp +D:\diablo97\wave.cpp +pMemFile +D:\diablo97\wave.cpp +pwfx +D:\diablo97\wave.cpp +pMemFile +D:\diablo97\wave.cpp +lpBuf +D:\diablo97\wave.cpp +pMemFile +D:\diablo97\wave.cpp +dwMethod == FILE_CURRENT +D:\diablo97\wave.cpp +lDist >= 0 +D:\diablo97\wave.cpp +D:\diablo97\wave.cpp +UUUU +sqrt +?pow +PKWARE Data Compression Library for Win32 +Copyright 1989-1995 PKWARE Inc. All Rights Reserved +Patent No. 5,051,745 +PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +Version 1.11 +PKWARE Data Compression Library for Win32 +Copyright 1989-1995 PKWARE Inc. All Rights Reserved. +Patent No. 5,051,745 +PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +Version 1.11 +SetUnhandledExceptionFilter +FormatMessageA +GetLastError +ExitProcess +OutputDebugStringA +Sleep +GetCurrentThreadId +DeleteFileA +CloseHandle +WriteFile +CreateFileA +SetThreadPriority +GetCurrentThread +CreateEventA +SetLastError +GetTickCount +GetPrivateProfileStringA +GetModuleFileNameA +InitializeCriticalSection +DeleteCriticalSection +EnterCriticalSection +LeaveCriticalSection +SetEvent +ResetEvent +WaitForSingleObject +GetProcAddress +LoadLibraryA +SetFilePointer +VirtualQuery +IsBadWritePtr +GetModuleHandleA +FindClose +FindNextFileA +FindFirstFileA +GetCurrentDirectoryA +GetDriveTypeA +GetLogicalDriveStringsA +DeviceIoControl +SetFileAttributesA +GetFileAttributesA +ReadFile +SetEndOfFile +GetFileSize +GetWindowsDirectoryA +GetDiskFreeSpaceA +GetComputerNameA +TerminateProcess +GetCurrentProcess +FileTimeToSystemTime +FileTimeToLocalFileTime +InterlockedDecrement +InterlockedIncrement +HeapFree +HeapAlloc +CreateThread +TlsSetValue +ExitThread +GetTimeZoneInformation +GetSystemTime +GetLocalTime +GetStartupInfoA +GetCommandLineA +GetVersion +FatalAppExitA +TlsAlloc +TlsFree +TlsGetValue +MultiByteToWideChar +WideCharToMultiByte +LCMapStringA +LCMapStringW +HeapDestroy +HeapCreate +VirtualFree +VirtualAlloc +HeapReAlloc +HeapSize +UnhandledExceptionFilter +RtlUnwind +FlushFileBuffers +FreeEnvironmentStringsA +FreeEnvironmentStringsW +GetEnvironmentStrings +GetEnvironmentStringsW +GetCPInfo +GetACP +GetOEMCP +SetHandleCount +GetStdHandle +GetFileType +GetStringTypeA +GetStringTypeW +IsValidLocale +IsValidCodePage +GetUserDefaultLCID +SetStdHandle +SetConsoleCtrlHandler +GetLocaleInfoA +GetLocaleInfoW +RaiseException +CompareStringA +CompareStringW +SetEnvironmentVariableA +KERNEL32.dll +wsprintfA +MessageBoxA +SetWindowPos +wvsprintfA +ShowCursor +ReleaseDC +GetDC +GetWindowRect +DialogBoxParamA +EndDialog +SetDlgItemTextA +SetCursorPos +PeekMessageA +ReleaseCapture +DispatchMessageA +TranslateMessage +DestroyWindow +SetFocus +SetForegroundWindow +GetTopWindow +GetLastActivePopup +FindWindowA +SetCapture +GetAsyncKeyState +GetSystemMetrics +ShowWindow +GetDesktopWindow +UpdateWindow +CreateWindowExA +RegisterClassExA +LoadImageA +LoadCursorA +LoadIconA +PostMessageA +GetWindow +GetClassNameA +GetForegroundWindow +DefWindowProcA +PostQuitMessage +SetWindowLongA +GetWindowLongA +InvalidateRect +GetKeyState +USER32.dll +GetDeviceCaps +TextOutA +GdiSetBatchLimit +GetStockObject +SetBkMode +SetBkColor +SetTextColor +GetSystemPaletteEntries +GDI32.dll +RegCloseKey +RegSetValueExA +RegQueryValueExA +RegOpenKeyExA +ADVAPI32.dll +SHGetPathFromIDListA +SHGetSpecialFolderLocation +ShellExecuteA +SHELL32.dll +VerQueryValueA +GetFileVersionInfoA +GetFileVersionInfoSizeA +VERSION.dll +UiDestroy +UiTitleDialog +UiInitialize +UiAppActivate +UiSupportDialog +UiCreditsDialog +UiMainMenuDialog +UiSelHeroSingDialog +UiSelHeroMultDialog +UiProgressDialog +UiSelectGame +UiSelectProvider +UiCategoryCallback +UiGetDataCallback +UiAuthCallback +UiSoundCallback +UiMessageBoxCallback +UiDrawDescCallback +UiCreateGameCallback +UiArtCallback +UiCreatePlayerDescription +hellfrui.dll +storm.dll +>!?&?G?L? +:Y;p;m<~< +> ?1?t? +0@0`0~0 +<"'?0?[?r? +=(>|> +;";(; +; ;$;(;,;0;4;8;<;@; +8<9@9 +P? +? ?$?(?,?0?4?8? >$>(>,>0>4>8><>@>D>H>L>P>T>X>\>`>d>h>l> +;P>T>X>\>`>d>h>l>p> +?$?4? +.\WinDebug/Hellfire.exe +NB10 +D:\diablo97\WinDebug\Hellfire.pdb diff --git a/src/Windebug/TOWNERS/FARMER/CFRMRN2.CEL b/src/Windebug/TOWNERS/FARMER/CFRMRN2.CEL new file mode 100644 index 0000000..7864269 Binary files /dev/null and b/src/Windebug/TOWNERS/FARMER/CFRMRN2.CEL differ diff --git a/src/Windebug/TOWNERS/FARMER/FARMER.TXT b/src/Windebug/TOWNERS/FARMER/FARMER.TXT new file mode 100644 index 0000000..aae8df6 --- /dev/null +++ b/src/Windebug/TOWNERS/FARMER/FARMER.TXT @@ -0,0 +1,8 @@ +farmer width 96 height 81 +farmer width 96 height 81 +Neutral frame count 15 +Walk frame count 1 +Attack frame count 1 +Get hit frame count 1 +Die frame count 1 +Special frame count 1 diff --git a/src/Windebug/TOWNERS/FARMER/FARMRN2.CEL b/src/Windebug/TOWNERS/FARMER/FARMRN2.CEL new file mode 100644 index 0000000..7bb1c79 Binary files /dev/null and b/src/Windebug/TOWNERS/FARMER/FARMRN2.CEL differ diff --git a/src/Windebug/TOWNERS/FARMER/MFRMRN2.CEL b/src/Windebug/TOWNERS/FARMER/MFRMRN2.CEL new file mode 100644 index 0000000..b97366b Binary files /dev/null and b/src/Windebug/TOWNERS/FARMER/MFRMRN2.CEL differ diff --git a/src/Windebug/TOWNERS/GIRL/GIRLS1.CEL b/src/Windebug/TOWNERS/GIRL/GIRLS1.CEL new file mode 100644 index 0000000..356fa81 Binary files /dev/null and b/src/Windebug/TOWNERS/GIRL/GIRLS1.CEL differ diff --git a/src/Windebug/TOWNERS/GIRL/GIRLS3.CEL b/src/Windebug/TOWNERS/GIRL/GIRLS3.CEL new file mode 100644 index 0000000..cfd9cea Binary files /dev/null and b/src/Windebug/TOWNERS/GIRL/GIRLS3.CEL differ diff --git a/src/Windebug/TOWNERS/GIRL/GIRLW1.CEL b/src/Windebug/TOWNERS/GIRL/GIRLW1.CEL new file mode 100644 index 0000000..50bd96f Binary files /dev/null and b/src/Windebug/TOWNERS/GIRL/GIRLW1.CEL differ diff --git a/src/Windebug/TOWNERS/GIRL/GIRLW3.CEL b/src/Windebug/TOWNERS/GIRL/GIRLW3.CEL new file mode 100644 index 0000000..de175ab Binary files /dev/null and b/src/Windebug/TOWNERS/GIRL/GIRLW3.CEL differ diff --git a/src/Windebug/TOWNERS/TRADER/TRADERN.CEL b/src/Windebug/TOWNERS/TRADER/TRADERN.CEL new file mode 100644 index 0000000..a2cefc8 Binary files /dev/null and b/src/Windebug/TOWNERS/TRADER/TRADERN.CEL differ diff --git a/src/Windebug/TOWNERS/TRADER/TRADERW.CEL b/src/Windebug/TOWNERS/TRADER/TRADERW.CEL new file mode 100644 index 0000000..68d69e3 Binary files /dev/null and b/src/Windebug/TOWNERS/TRADER/TRADERW.CEL differ diff --git a/src/Windebug/UI.PCH b/src/Windebug/UI.PCH new file mode 100644 index 0000000..c926917 Binary files /dev/null and b/src/Windebug/UI.PCH differ diff --git a/src/Windebug/UI_ART/BLACK.PCX b/src/Windebug/UI_ART/BLACK.PCX new file mode 100644 index 0000000..dadbaf6 Binary files /dev/null and b/src/Windebug/UI_ART/BLACK.PCX differ diff --git a/src/Windebug/UI_ART/FONT42G.PCX b/src/Windebug/UI_ART/FONT42G.PCX new file mode 100644 index 0000000..be6adf0 Binary files /dev/null and b/src/Windebug/UI_ART/FONT42G.PCX differ diff --git a/src/Windebug/UI_ART/HEROS.PCX b/src/Windebug/UI_ART/HEROS.PCX new file mode 100644 index 0000000..00d1e10 Binary files /dev/null and b/src/Windebug/UI_ART/HEROS.PCX differ diff --git a/src/Windebug/UI_ART/HF_LOGO1.PCX b/src/Windebug/UI_ART/HF_LOGO1.PCX new file mode 100644 index 0000000..0eae0ac Binary files /dev/null and b/src/Windebug/UI_ART/HF_LOGO1.PCX differ diff --git a/src/Windebug/UI_ART/HF_LOGO2.PCX b/src/Windebug/UI_ART/HF_LOGO2.PCX new file mode 100644 index 0000000..64f260e Binary files /dev/null and b/src/Windebug/UI_ART/HF_LOGO2.PCX differ diff --git a/src/Windebug/UI_ART/HF_TITLE.PCX b/src/Windebug/UI_ART/HF_TITLE.PCX new file mode 100644 index 0000000..937b7eb Binary files /dev/null and b/src/Windebug/UI_ART/HF_TITLE.PCX differ diff --git a/src/Windebug/UI_ART/MAINMENU.PCX b/src/Windebug/UI_ART/MAINMENU.PCX new file mode 100644 index 0000000..b5a3e01 Binary files /dev/null and b/src/Windebug/UI_ART/MAINMENU.PCX differ diff --git a/src/Windebug/UI_ART/SELCONN.PCX b/src/Windebug/UI_ART/SELCONN.PCX new file mode 100644 index 0000000..33cfe3c Binary files /dev/null and b/src/Windebug/UI_ART/SELCONN.PCX differ diff --git a/src/Windebug/UI_ART/SELGAME.PCX b/src/Windebug/UI_ART/SELGAME.PCX new file mode 100644 index 0000000..33cfe3c Binary files /dev/null and b/src/Windebug/UI_ART/SELGAME.PCX differ diff --git a/src/Windebug/UI_ART/SELHERO.PCX b/src/Windebug/UI_ART/SELHERO.PCX new file mode 100644 index 0000000..14e234c Binary files /dev/null and b/src/Windebug/UI_ART/SELHERO.PCX differ diff --git a/src/Windebug/UI_ART/SUPPORT.PCX b/src/Windebug/UI_ART/SUPPORT.PCX new file mode 100644 index 0000000..4fb4346 Binary files /dev/null and b/src/Windebug/UI_ART/SUPPORT.PCX differ diff --git a/src/Windebug/VC50.IDB b/src/Windebug/VC50.IDB new file mode 100644 index 0000000..47181f7 Binary files /dev/null and b/src/Windebug/VC50.IDB differ diff --git a/src/Windebug/VERSION.TXT b/src/Windebug/VERSION.TXT new file mode 100644 index 0000000..416ae08 --- /dev/null +++ b/src/Windebug/VERSION.TXT @@ -0,0 +1,3 @@ +Hellfire (European/US) +Version 1.01 +January 13, 1998 diff --git a/src/Winfinal/DIABLO.PCH b/src/Winfinal/DIABLO.PCH new file mode 100644 index 0000000..7e1227c Binary files /dev/null and b/src/Winfinal/DIABLO.PCH differ diff --git a/src/Winfinal/DIABLO.RES b/src/Winfinal/DIABLO.RES new file mode 100644 index 0000000..06daee0 Binary files /dev/null and b/src/Winfinal/DIABLO.RES differ diff --git a/src/Winfinal/HELLFIRE.EXE b/src/Winfinal/HELLFIRE.EXE new file mode 100644 index 0000000..4122adc Binary files /dev/null and b/src/Winfinal/HELLFIRE.EXE differ diff --git a/src/Winfinal/SINGLE_0.HSV b/src/Winfinal/SINGLE_0.HSV new file mode 100644 index 0000000..a502b13 Binary files /dev/null and b/src/Winfinal/SINGLE_0.HSV differ diff --git a/src/Winfinal/SINGLE_1.HSV b/src/Winfinal/SINGLE_1.HSV new file mode 100644 index 0000000..63c52db Binary files /dev/null and b/src/Winfinal/SINGLE_1.HSV differ diff --git a/src/Winfinal/SINGLE_2.HSV b/src/Winfinal/SINGLE_2.HSV new file mode 100644 index 0000000..ee388c5 Binary files /dev/null and b/src/Winfinal/SINGLE_2.HSV differ diff --git a/src/Winfinal/VC50.IDB b/src/Winfinal/VC50.IDB new file mode 100644 index 0000000..d6d02f6 Binary files /dev/null and b/src/Winfinal/VC50.IDB differ diff --git a/src/Winrel/COMMAND.TXT b/src/Winrel/COMMAND.TXT new file mode 100644 index 0000000..e322d55 --- /dev/null +++ b/src/Winrel/COMMAND.TXT @@ -0,0 +1 @@ +Multinest;Barbariantest;Cowquest;Theoquest;NestArt diff --git a/src/Winrel/DIABLO.BSC b/src/Winrel/DIABLO.BSC new file mode 100644 index 0000000..6b083d1 Binary files /dev/null and b/src/Winrel/DIABLO.BSC differ diff --git a/src/Winrel/DIABLO.PCH b/src/Winrel/DIABLO.PCH new file mode 100644 index 0000000..0fa418f Binary files /dev/null and b/src/Winrel/DIABLO.PCH differ diff --git a/src/Winrel/DIABLO.RES b/src/Winrel/DIABLO.RES new file mode 100644 index 0000000..facfd7d Binary files /dev/null and b/src/Winrel/DIABLO.RES differ diff --git a/src/Winrel/HELLFILE.TXT b/src/Winrel/HELLFILE.TXT new file mode 100644 index 0000000..4cffc82 --- /dev/null +++ b/src/Winrel/HELLFILE.TXT @@ -0,0 +1,15 @@ +10/30 10:16:11.280 SFileEnableDirectAccess(1) +10/30 10:16:13.910 SFileDdaInitialize(0x836ac374) +10/30 10:16:13.970 SFileSetBasePath("D:\diablo97\WinRel") +10/30 10:16:13.970 SFileOpenArchive("D:\diablo97\WinRel\diabdat.mpq",1000,0,*handle) +10/30 10:16:13.970 SFileOpenArchive("D:\DIABLO97\WINREL\diabdat.mpq",1000,0,*handle) +10/30 10:16:14.020 SFileOpenArchive("E:\diabdat.mpq",1000,0,*handle) +10/30 10:16:15.730 SFileOpenFile("ui_art\title.pcx",*handle) +10/30 10:16:15.780 SFileOpenFileEx(0x1580054,"ui_art\title.pcx",0x0,*handle) +10/30 10:16:15.780 SFileCloseFile(0x1770054) +10/30 10:16:15.780 SFileSetBasePath("D:\diablo97\WinRel") +10/30 10:16:15.780 SFileOpenArchive("D:\diablo97\WinRel\patch_rt.mpq",2000,0,*handle) +10/30 10:16:15.780 SFileOpenArchive("D:\DIABLO97\WINREL\patch_rt.mpq",2000,0,*handle) +10/30 10:16:15.840 SFileOpenArchive("C:\Diablo\patch_rt.mpq",2000,0,*handle) +10/30 10:16:15.840 SFileSetBasePath("D:\diablo97\WinRel") +10/30 10:16:15.840 SFileOpenArchive("D:\diablo97\WinRel\hellfire.mpq",8000,0,*handle) diff --git a/src/Winrel/HELLFIRE.EXE b/src/Winrel/HELLFIRE.EXE new file mode 100644 index 0000000..aa2ec4b Binary files /dev/null and b/src/Winrel/HELLFIRE.EXE differ diff --git a/src/Winrel/HELLFI~1.HIP b/src/Winrel/HELLFI~1.HIP new file mode 100644 index 0000000..55fb4c1 Binary files /dev/null and b/src/Winrel/HELLFI~1.HIP differ diff --git a/src/Winrel/HELLMEM.TXT b/src/Winrel/HELLMEM.TXT new file mode 100644 index 0000000..dc93456 --- /dev/null +++ b/src/Winrel/HELLMEM.TXT @@ -0,0 +1,89 @@ +10/30 10:16:11.170 [0x00a50060] SMemAlloc() u:\projects\storm\h\storm.h (2246) +10/30 10:16:11.220 [0x00f70064] SMemAlloc() D:\diablo97\UISRC\ui\local.cpp (29) +10/30 10:16:11.220 [0x00f70064] SMemFree() D:\diablo97\UISRC\ui\local.cpp (43) +10/30 10:16:13.640 [0x014a0fe8] SMemAlloc() D:\diablo97\dx.cpp (76) +10/30 10:16:13.640 [0x00f7005c] SMemAlloc() D:\diablo97\ENGINE.CPP (2129) +10/30 10:16:13.640 [0x01520050] SMemAlloc() SDRAW.CPP (56) +10/30 10:16:13.690 [0x01520050] SMemFree() SDRAW.CPP (62) +10/30 10:16:13.860 [0x0156004c] SMemAlloc() SVID.CPP (111) +10/30 10:16:13.860 [0x0152004c] SMemAlloc() SVID.CPP (562) +10/30 10:16:13.860 [0x01570050] SMemAlloc() .?AUSTREAM@@ (-2) +10/30 10:16:13.860 [0x01580050] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x01580078] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x015800a0] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x015800c8] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x015800f0] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x01580118] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x01590050] SMemAlloc() SCODE.CPP (835) +10/30 10:16:13.860 [0x015a0050] SMemAlloc() SCODE.CPP (837) +10/30 10:16:13.860 [0x01580050] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x01580078] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015800f0] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015800a0] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015800c8] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x01580118] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015b0050] SMemAlloc() SCODE.CPP (1004) +10/30 10:16:13.860 [0x01580050] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x01580078] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x015800a0] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x015800c8] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x015800f0] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x01580118] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x01580050] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x01580078] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015800f0] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015800a0] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015800c8] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x01580118] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015c0050] SMemAlloc() SCODE.CPP (1041) +10/30 10:16:13.860 [0x015705b0] SMemAlloc() .?AUSTREAM@@ (-2) +10/30 10:16:13.860 [0x01580050] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.860 [0x01580050] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.860 [0x015b0078] SMemAlloc() SCODE.CPP (1004) +10/30 10:16:13.910 [0x01580050] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x01580078] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x015800a0] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x015800c8] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x015800f0] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x01580118] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x01580050] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x01580078] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015800f0] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015800a0] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015800c8] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x01580118] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015c16e0] SMemAlloc() SCODE.CPP (1041) +10/30 10:16:13.910 [0x01570b10] SMemAlloc() .?AUSTREAM@@ (-2) +10/30 10:16:13.910 [0x01580050] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x01580050] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015b0090] SMemAlloc() SCODE.CPP (1004) +10/30 10:16:13.910 [0x01580050] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x01580078] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x015800a0] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x015800c8] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x015800f0] SMemAlloc() .?AUINST@@ (-2) +10/30 10:16:13.910 [0x01580050] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015800c8] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x01580078] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015800a0] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015800f0] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:13.910 [0x015c2870] SMemAlloc() SCODE.CPP (1041) +10/30 10:16:13.910 [0x01580058] SMemAlloc() D:\diablo97\init.cpp (447) +10/30 10:16:13.910 [0x00f7007c] SMemAlloc() D:\diablo97\ENGINE.CPP (2129) +10/30 10:16:13.970 [0x01580058] SMemFree() D:\diablo97\init.cpp (467) +10/30 10:16:13.970 [0x015d0050] SMemAlloc() SFILE.CPP (2032) +10/30 10:16:15.120 [0x01580054] SMemAlloc() .?AUARCHIVEREC@@ (-2) +10/30 10:16:15.120 [0x015e0050] SMemAlloc() SFILE.CPP (2079) +10/30 10:16:15.120 [0x015f0050] SMemAlloc() SFILE.CPP (2103) +10/30 10:16:15.180 [0x01611000] SMemAlloc() SFILE.CPP (2106) +10/30 10:16:15.730 [0x01630050] SMemAlloc() SFILE.CPP (2117) +10/30 10:16:15.780 [0x01760050] SMemAlloc() SFILE.CPP (2273) +10/30 10:16:15.780 [0x01770054] SMemAlloc() .?AUFILEREC@@ (-2) +10/30 10:16:15.780 [0x01780050] SMemAlloc() SFILE.CPP (2283) +10/30 10:16:15.780 [0x01760050] SMemFree() SFILE.CPP (1409) +10/30 10:16:15.780 [0x01780050] SMemFree() SFILE.CPP (1413) +10/30 10:16:15.780 [0x01770054] SMemFree() u:\projects\storm\h\storm.h (906) +10/30 10:16:15.840 [0x015801a4] SMemAlloc() .?AUARCHIVEREC@@ (-2) +10/30 10:16:15.840 [0x015e0080] SMemAlloc() SFILE.CPP (2079) +10/30 10:16:15.840 [0x015f1060] SMemAlloc() SFILE.CPP (2103) +10/30 10:16:15.840 [0x01600060] SMemAlloc() SFILE.CPP (2106) diff --git a/src/Winrel/HELLNET.TXT b/src/Winrel/HELLNET.TXT new file mode 100644 index 0000000..e69de29 diff --git a/src/Winrel/RESPON~1.TXT b/src/Winrel/RESPON~1.TXT new file mode 100644 index 0000000..7b10e4e --- /dev/null +++ b/src/Winrel/RESPON~1.TXT @@ -0,0 +1,25 @@ +"D:\diablo97\WinRel\Hellfire.exe" +/exclude "d:\diablo97\winrel\hellfrui.dll" +/exclude "d:\diablo97\winrel\storm.dll" +/countsMask 83 +/timeStampCounter +/retainProfiles 3 +/cpu pentium +/atomToolData + "D:\diablo97\WinRel" # project dir + "" # run application name + "" # run arguments + "D:\diablo97\WinRel" # run working directory + 12 # number of DLLs + "d:\diablo97\winrel\hellfire.exe" 1 1487872 -420951808 29155272 1 + "c:\windows\system\kernel32.dll" 0 411136 1550986240 28987310 0 + "c:\windows\system\user32.dll" 0 44544 1550986240 28987310 0 + "c:\windows\system\gdi32.dll" 0 131072 1550986240 28987310 0 + "c:\windows\system\advapi32.dll" 0 43008 -99307776 29080255 0 + "c:\windows\system\shell32.dll" 0 817664 99150848 29022112 0 + "c:\windows\system\comctl32.dll" 0 379152 -99307776 29080255 0 + "c:\windows\system\version.dll" 0 6656 1550986240 28987310 0 + "d:\diablo97\winrel\hellfrui.dll" 0 244224 -852656128 29155067 0 + "d:\diablo97\winrel\storm.dll" 0 137728 1204410624 29139231 0 + "c:\windows\system\crtdll.dll" 0 161280 1550986240 28987310 0 + "c:\windows\system\comdlg32.dll" 0 92672 99150848 29022112 0 diff --git a/src/Winrel/SINGLE_5.SAV b/src/Winrel/SINGLE_5.SAV new file mode 100644 index 0000000..f97a71f Binary files /dev/null and b/src/Winrel/SINGLE_5.SAV differ diff --git a/src/Winrel/SMACKW32.DLL b/src/Winrel/SMACKW32.DLL new file mode 100644 index 0000000..e756b2f Binary files /dev/null and b/src/Winrel/SMACKW32.DLL differ diff --git a/src/Winrel/STANDARD.SNP b/src/Winrel/STANDARD.SNP new file mode 100644 index 0000000..54b2343 Binary files /dev/null and b/src/Winrel/STANDARD.SNP differ diff --git a/src/Winrel/STORM.DLL b/src/Winrel/STORM.DLL new file mode 100644 index 0000000..21f620d Binary files /dev/null and b/src/Winrel/STORM.DLL differ diff --git a/src/Winrel/STRINGS.TXT b/src/Winrel/STRINGS.TXT new file mode 100644 index 0000000..1661639 --- /dev/null +++ b/src/Winrel/STRINGS.TXT @@ -0,0 +1,6158 @@ +screen??.PCX +screen%02d.PCX +*?+@A +(B)C +?AAAAAAACEEEEIIIIDNOOOOOX0UUUUYbBaaaaaaaceeeeiiiionooooo/0uuuuyby +dd_emulate +dd_backbuf +ds_noduplicates +If you are looking at this you might want to try these command line flags. +End of flags list. +()*+ +$!!#"!% +%"! +ahds + !"#32 +$Keyboard Shortcuts:|F1: Open Help Screen|Esc: Display Main Menu|Tab: Display Auto-map|Space: Hide all info screens|S: Open Speedbook|B: Open Spellbook|I: Open Inventory screen|C: Open Character screen|Q: Open Quest log|F: Reduce screen brightness|G: Increase screen brightness|Z: Zoom Game Screen|+ / -: Zoom Automap|1 - 8: Use Belt item|F5, F6, F7, F8: Set hot key for skill or spell|Shift + Left Click: Attack without moving||$Movement:|If you hold the mouse button down while moving, the character will continue to move in that direction.||$Combat:|Holding down the shift key and then left-clicking allows the character to attack without moving.||$Auto-map:|To access the auto-map, click the 'MAP' button on the Information Bar or press 'TAB' on the keyboard. Zooming in and out of the map is done with the + and - keys. Scrolling the map uses the arrow keys.||$Picking up Objects:|Useable items that are small in size, such as potions or scrolls, are automatically placed in your 'belt' located at the top of the Interface bar . When an item is placed in the belt, a small number appears in that box. Items may be used by either pressing the corresponding number or right-clicking on the item.||$Gold|You can select a specific amount of gold to drop by right clicking on a pile of gold in your inventory.||$Skills & Spells:|You can access your list of skills and spells by left-clicking on the 'SPELLS' button in the interface bar. Memorized spells and those available through staffs are listed here. Left-clicking on the spell you wish to cast will ready the spell. A readied spell may be cast by simply right-clicking in the play area.||$Using the Speedbook for Spells|Left-clicking on the 'readied spell' button will open the 'Speedbook' which allows you to select a skill or spell for immediate use. To use a readied skill or spell, simply right-click in the main play area.||$Setting Spell Hotkeys|You can assign up to four Hot Keys for skills, spells or scrolls. Start by opening the 'speedbook' as described in the section above. Press the F5, F6, F7 or F8 keys after highlighting the spell you wish to assign.||$Spell Books|Reading more than one book increases your knowledge of that spell, allowing you to cast the spell more effectively.|& +HELLFIRE +ScreenSaveActive + !"#320.16 +?Gamma Correction +game +hero +perml%02d +perms%02d +templ%02d +temps%02d +NUSDBAMHT +WRSMR +unknown action +Sound Volume +Music Volume +`h```` +(null) +?IsProcessorFeaturePresent +KERNEL32 +e+000 +LC_TIME +LC_NUMERIC +LC_MONETARY +LC_CTYPE +LC_COLLATE +LC_ALL +SunMonTueWedThuFriSat +JanFebMarAprMayJunJulAugSepOctNovDec +@runtime error +TLOSS error +SING error +DOMAIN error +R6028 +- unable to initialize heap +R6027 +- not enough space for lowio initialization +R6026 +- not enough space for stdio initialization +R6025 +- pure virtual function call +R6024 +- not enough space for _onexit/atexit table +R6019 +- unable to open console device +R6018 +- unexpected heap error +R6017 +- unexpected multithread lock error +R6016 +- not enough space for thread data +abnormal program termination +R6009 +- not enough space for environment +R6008 +- not enough space for arguments +R6002 +- floating point not loaded +Microsoft Visual C++ Runtime Library +Runtime Error! +Program: + +united-states +united-kingdom +united states +united kingdom +turkey +taiwan +switzerland +sweden +spain +south-korea +south korea +singapore +russia +pr-china +pr china +portugal +poland +norway +new-zealand +new zealand +netherlands +mexico +korea +japan +italy +ireland +iceland +hungary +hong-kong +hong kong +holland +greece +great britain +germany +france +finland +england +denmark +china +canada +britain +brazil +belgium +austria +australia +america +turkish +swiss +swedish +spanish-modern +spanish-mexican +spanish +slovak +russian +portuguese-brazilian +portuguese +polish +norwegian-nynorsk +norwegian-bokmal +norwegian +korean +japanese +italian-swiss +italian +irish-english +icelandic +hungarian +greek +german-swiss +german-austrian +german +french-swiss +french-canadian +french-belgian +french +finnish +english-usa +english-us +english-uk +english-nz +english-ire +english-can +english-aus +english-american +english +dutch-belgian +dutch +danish +czech +chinese-traditional +chinese-singapore +chinese-simplified +chinese-hongkong +chinese +canadian +belgian +australian +american-english +american english +american +GetLastActivePopup +GetActiveWindow +MessageBoxA +user32.dll +1#QNAN +1#INF +1#IND +1#SNAN +H:mm:ss +dddd, MMMM dd, yyyy +M/d/yy +December +November +October +September +August +July +June +April +March +February +January +Saturday +Friday +Thursday +Wednesday +Tuesday +Monday +Sunday +frexp +fmod +_hypot +_cabs +ldexp +modf +fabs +floor +ceil +sqrt +atan2 +atan +acos +asin +tanh +cosh +sinh +log10 +!This program cannot be run in DOS mode. +.text +`.rdata +@.data +.idata +.rsrc +u)PSVh +=@Sn +50,X +50,X +50,X +50,X +=@Sn +^vuhHSn +=x!o +=x!o +=x!o +=@Sn +=@Sn +u09=i +=@Sn +=L>i +=p,X +=8>i +=P\o +5x=i +=@Sn +-|!p +=H:p +=p,X +uXVh +=@Sn +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +=@Sn +9=dWn +;=dWn +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +5 Qj +=@Sn +9=dWn +;=dWn +9=dWn +;=dWn +9=dWn +;=dWn +h(Qj +h(Qj +%PQj +%TQj +=PQj +%DQj +5TQj +=(yY +5hWn +)u!j +>(yY +=dWn +9(yY +8'yY +8(yY +8'yY +8(yY +=dWn +V9-dWn +[u/j +;-dWn +=dWn +;5x!o +=dWn +95dWn +;5dWn +=DQj +=0(o +=DQj +9=dWn +;=dWn +;=x!o +Sjmj +;=x!o +;5x!o +;5x!o +=dWn +hX*L +L08Sj +;=x!o +;5x!o +;5x!o +;5x!o +;5x!o +;5x!o +;5x!o +;5x!o +;5x!o +;=x!o +;=x!o +;5x!o +;5x!o +;5x!o +;-x!o +;-x!o +;=x!o +;=x!o +;=x!o +;=x!o +;=x!o +=DQj +=hLX +=6)o +u=;=x!o +hp*L +=@Un +9=dWn +;=dWn +hX,L +hH,L +h4,L +h(,L +h|+L +}hl+L +vhX+L +ohD+L +hh8+L +ah(+L +5TLX +5TLX +5TLX +5TLX +5TLX +5TLX +5l,L +-l,L +=p,L +%p,L +50,X +hX-L +h`-L +=@Sn +=@Sn +=@Sn +=@Sn +50,X +=@Sn +=@Sn +=d!o +Yh@-L +=@Sn +5d!o +h@-L + G=`!o +=@Sn +h`-L +h\.L +hD.L +h(.L +=@Sn +=@Sn +hx.L +=@Sn +=@Sn +=@Sn +=@Sn +=@Sn +=@Sn +=@Sn +h`/L +=@Sn +h +united-states +united-kingdom +united states +united kingdom +turkey +taiwan +switzerland +sweden +spain +south-korea +south korea +singapore +russia +pr-china +pr china +portugal +poland +norway +new-zealand +new zealand +netherlands +mexico +korea +japan +italy +ireland +iceland +hungary +hong-kong +hong kong +holland +greece +great britain +germany +france +finland +england +denmark +china +canada +britain +brazil +belgium +austria +australia +america +turkish +swiss +swedish +spanish-modern +spanish-mexican +spanish +slovak +russian +portuguese-brazilian +portuguese +polish +norwegian-nynorsk +norwegian-bokmal +norwegian +korean +japanese +italian-swiss +italian +irish-english +icelandic +hungarian +greek +german-swiss +german-austrian +german +french-swiss +french-canadian +french-belgian +french +finnish +english-usa +english-us +english-uk +english-nz +english-ire +english-can +english-aus +english-american +english +dutch-belgian +dutch +danish +czech +chinese-traditional +chinese-singapore +chinese-simplified +chinese-hongkong +chinese +canadian +belgian +australian +american-english +american english +american +GetLastActivePopup +GetActiveWindow +MessageBoxA +user32.dll +1#QNAN +1#INF +1#IND +1#SNAN +H:mm:ss +dddd, MMMM dd, yyyy +M/d/yy +December +November +October +September +August +July +June +April +March +February +January +Saturday +Friday +Thursday +Wednesday +Tuesday +Monday +Sunday +frexp +fmod +_hypot +_cabs +ldexp +modf +fabs +floor +ceil +sqrt +atan2 +atan +acos +asin +tanh +cosh +sinh +log10 +unknown error 0x%08x +DDERR_CANTPAGEUNLOCK +DDERR_NOTPAGELOCKED +DD_OK +D:\diablo97\appfat.cpp +dwMaxChars >= sizeof(szUnknown) + 10 +DDERR unknown 0x%x +DDERR_CANTPAGELOCK +DDERR_NOMIPMAPHW +DDERR_INVALIDSURFACETYPE +DDERR_DCALREADYCREATED +DDERR_XALIGN +DDERR_WRONGMODE +DDERR_REGIONTOOSMALL +DDERR_PRIMARYSURFACEALREADYEXISTS +DDERR_OVERLAYNOTVISIBLE +DDERR_NOTPALETTIZED +DDERR_NOTLOCKED +DDERR_NOTFLIPPABLE +DDERR_NOTAOVERLAYSURFACE +DDERR_NOPALETTEHW +DDERR_NOPALETTEATTACHED +DDERR_NOOVERLAYDEST +DDERR_NOHWND +DDERR_NOEMULATION +DDERR_NODIRECTDRAWHW +DDERR_NODDROPSHW +DDERR_NODC +DDERR_NOCLIPPERATTACHED +DDERR_NOBLTHW +DDERR_INVALIDPOSITION +DDERR_INVALIDDIRECTDRAWGUID +DDERR_IMPLICITLYCREATED +DDERR_HWNDSUBCLASSED +DDERR_HWNDALREADYSET +DDERR_EXCLUSIVEMODEALREADYSET +DDERR_DIRECTDRAWALREADYCREATED +DDERR_CLIPPERISUSINGHWND +DDERR_CANTDUPLICATE +DDERR_CANTCREATEDC +DDERR_BLTFASTCANTCLIP +DDERR_WASSTILLDRAWING +DDERR_VERTICALBLANKINPROGRESS +DDERR_UNSUPPORTEDMASK +DDERR_UNSUPPORTEDFORMAT +DDERR_TOOBIGWIDTH +DDERR_TOOBIGSIZE +DDERR_TOOBIGHEIGHT +DDERR_SURFACENOTATTACHED +DDERR_SURFACELOST +DDERR_SURFACEISOBSCURED +DDERR_CANTLOCKSURFACE +DDERR_SURFACEBUSY +DDERR_SURFACEALREADYDEPENDENT +DDERR_SURFACEALREADYATTACHED +DDERR_COLORKEYNOTSET +DDERR_OUTOFVIDEOMEMORY +DDERR_OVERLAYCANTCLIP +DDERR_OVERLAYCOLORKEYONLYONEACTIVE +DDERR_PALETTEBUSY +DDERR_OUTOFCAPS +DDERR_NOZOVERLAYHW +DDERR_NOZBUFFERHW +DDERR_NOVSYNCHW +DDERR_NOTEXTUREHW +DDERR_NOT4BITCOLOR +DDERR_NOT4BITCOLORINDEX +DDERR_NOT8BITCOLOR +DDERR_NOSTRETCHHW +DDERR_NOROTATIONHW +DDERR_NORASTEROPHW +DDERR_NOOVERLAYHW +DDERR_NOTFOUND +DDERR_NOMIRRORHW +DDERR_NOGDI +DDERR_NOFLIPHW +DDERR_NOEXCLUSIVEMODE +DDERR_NOCOLORKEYHW +DDERR_NOCOLORKEY +DDERR_NOCOOPERATIVELEVELSET +DDERR_NOCOLORCONVHW +DDERR_NOCLIPLIST +DDERR_NOALPHAHW +DDERR_NO3D +DDERR_LOCKEDSURFACES +DDERR_INVALIDRECT +DDERR_INVALIDPIXELFORMAT +DDERR_INVALIDOBJECT +DDERR_INVALIDMODE +DDERR_INVALIDCLIPLIST +DDERR_INVALIDCAPS +DDERR_INCOMPATIBLEPRIMARY +DDERR_HEIGHTALIGN +DDERR_EXCEPTION +DDERR_CURRENTLYNOTAVAIL +DDERR_CANNOTDETACHSURFACE +DDERR_CANNOTATTACHSURFACE +DDERR_ALREADYINITIALIZED +DDERR_INVALIDPARAMS +DDERR_OUTOFMEMORY +DDERR_GENERIC +DDERR_UNSUPPORTED +DSERR_INVALIDCALL +DSERR_PRIOLEVELNEEDED +DSERR_BADFORMAT +DSERR_NODRIVER +DSERR_ALREADYINITIALIZED +DSERR_BUFFERLOST +DS_OK +DSERR unknown 0x%x +DSERR_CONTROLUNAVAIL +DSERR_ALLOCATED +DSERR_INVALIDPARAM +DSERR_OUTOFMEMORY +DSERR_NOAGGREGATION +E_NOINTERFACE +ERROR +Hellfire +pszFmt +assertion failed (%d:%s) +Direct draw error (%s:%d) +Direct sound error (%s:%d) +center_window: %s +ErrDlg: %d +at: %s line %d +FileErrDlg +DiskFreeDlg +InsertCDDlg +NLevels\L5Data\L5.AMP +Levels\L1Data\L1.AMP +Levels\L2Data\L2.AMP +NLevels\L6Data\L6.AMP +Levels\L3Data\L3.AMP +Levels\L4Data\L4.AMP +D:\diablo97\automap.cpp +gpBuffer +Level: %i +Level: Crypt %i +Level: Nest %i +password: +game: +D:\diablo97\capture.cpp +pszPassword +pbSrcDst +D:\diablo97\CODEC.CPP +dwSrcBytes +Invalid encode parameters +REGISTRATION_BLOCK +%&'*)( +332./+-01,##### +Player Attack +Send Message +Spell book +Inventory +Main Menu +Automap +Quests log +Character Information +Enter +D:\diablo97\CONTROL.CPP +Spell Hot Key #F%i +%s Skill +Spell Level %i +Spell Level 0 - Unusable +Damages undead only +%s Spell +%i Scrolls +1 Scroll +Scroll of %s +%i Charges +1 Charge +Staff of %s +CtrlPan\Golddrop.cel +Data\Quest.CEL +Data\SpellI2.CEL +Data\SpellBkB.CEL +Data\SpellBk.CEL +Items\DurIcons.CEL +Data\CharBut.CEL +CtrlPan\Panel8bu.CEL +CtrlPan\TalkButt.CEL +CtrlPan\P8But2.CEL +CtrlPan\TalkPanl.CEL +CtrlPan\P8Bulbs.CEL +CtrlPan\Panel8.CEL +Data\SpelIcon.CEL +Data\Char.CEL +CtrlPan\SmalText.CEL +! pBtmBuff +Hotkey : 's' +Select current spell button +Hotkey : %s +Player attack +Player friendly +Hit Points %i of %i +Level : %i +Requirements not met +%i gold %s +%i-%i +%i%% +None +Bard +Monk +Sorceror +Rogue +Warrior +Level Up +Skill +Staff (%i charges) +Mana: %i Dam: 1/3 tgt hp +Mana: %i Dam: n/a +Mana: %i Dam: %i - %i +pieces +piece +you want to remove? +%s. How many do +You have %u gold +Data\Inv\Objcurs2.CEL +Data\Inv\Objcurs.CEL +! pCursCels +D:\diablo97\CURSOR.CPP +from %s +Town Portal +level 15 +The Unholy Altar +Portal to +D:\diablo97\DEAD.CPP +nd <= MAXDEAD +Data\Square.CEL +! pSquareCel +D:\diablo97\DEBUG.CPP + inv = %i : hp = %i + mode = %i : daction = %i : walk[0] = %i + x = %i, y = %i : tx = %i, ty = %i : fx = %i, fy = %i + Lvl = %i : Change = %i + Plr %i is %s +Plr %i : Active = %i +Quest %i : Active = %i, Var1 = %i +Players not cleared +Monsters not cleared +dung sum = %i : L4Dungeon sum = %i +Num themes = %i/%i : Trans Sum = %i : dPiece Sum = %i +Solid Sum = %i:%i : Monst Vol = %i : Dungeon Sum = %i +Level %i : Monst Active Sum = %i : dFlag sum = %i +dungeon Y=%i sum = %i +Active List = %i, Squelch = %i +Mode = %i, Var1 = %i +Enemy = %i, HP = %i +X = %i, Y = %i +Monster %i = %s +Current debug monster = %i +REGISTRATION_TABLE +Look out behind you! +Give me some gold please. +Go through that door first. +I need help! Heal me! +D:\diablo97\DIABLO.CPP +saveProc == GM_Game +ghMainWnd +HellfireEvent +DiabloEvent +gendata\Hellfire.smk +Intro +gendata\logo.smk +HELLFIRE +Multitest +Bardtest +NestArt +Cowquest +Theoquest +MouseY < 352 +NetMsg +dwMsg < sizeof(spszMsgTbl) / sizeof(spszMsgTbl[0]) +\hellfire.ini +Can't get program name +Numitems : %i +IDX = %i : Seed = %i : CF = %i +while in stores +No help available +[ MESSAGE SPEED = %i ] +[ MESSAGE = %i ] +Message Speed = %i +STOP QUEST TEXT MODE +%s, mode = %s +Hell +Nightmare +Normal +Message = %i +START QUEST TEXT MODE +EFlag = %i +CX = %i CY = %i DP = %i +PX = %i PY = %i +Mid: %i +End = %i +Mid1 = %i : Mid2 = %i : Mid3 = %i +seed = %i +Levels\TownData\TownS.CEL +NLevels\TownData\Town.MIN +NLevels\TownData\Town.TIL +NLevels\TownData\Town.CEL +NLevels\L5Data\L5S.CEL +NLevels\L5Data\L5.MIN +NLevels\L5Data\L5.TIL +NLevels\L5Data\L5.CEL +Levels\L1Data\L1S.CEL +Levels\L1Data\L1.MIN +Levels\L1Data\L1.TIL +Levels\L1Data\L1.CEL +Levels\L2Data\L2S.CEL +Levels\L2Data\L2.MIN +Levels\L2Data\L2.TIL +Levels\L2Data\L2.CEL +NLevels\L6Data\L6.MIN +NLevels\L6Data\L6.TIL +NLevels\L6Data\L6.CEL +Levels\L3Data\L3.MIN +Levels\L3Data\L3.TIL +Levels\L3Data\L3.CEL +Levels\L4Data\L4.MIN +Levels\L4Data\L4.TIL +Levels\L4Data\L4.CEL +LoadLvlGFX +! pDungeonCels +! pSpeedCels +CreateLevel +-- Waiting for players -- +-- Network timeout -- +Unable to initialize memory +D:\diablo97\doom.cpp +Items\Map\MapZtown.CEL +REGISTRATION_BLOCK +D:\diablo97\DRLG_L1.CPP +lv >= 0 +Levels\L1Data\Banner2.DUN +Levels\L1Data\SKngDO.DUN +Levels\L1Data\rnd6.DUN +REGISTRATION_BLOCK +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3'/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +3*/, +xzy{ +D:\diablo97\DRLG_L2.CPP +Levels\L2Data\Bonestr2.DUN +Levels\L2Data\Blood1.DUN +Levels\L2Data\Blind2.DUN +REGISTRATION_BLOCK +D:\diablo97\DRLG_L3.CPP +Levels\L4Data\Vile1.DUN +Levels\L4Data\Warlord.DUN +gbMaxPlayers == 1 +D:\diablo97\drlg_l4.cpp +Levels\L4Data\diab4a.DUN +Levels\L4Data\diab4b.DUN +Levels\L4Data\diab3a.DUN +Levels\L4Data\diab3b.DUN +Levels\L4Data\diab2a.DUN +Levels\L4Data\diab2b.DUN +Levels\L4Data\diab1.DUN +dwLen +pbSrc +pnum != myplr +D:\diablo97\dthread.cpp +dthread2: +dthread:1 +! sghWorkToDoEvent +! sgpInfoHead +sghThread == INVALID_HANDLE_VALUE +d:%u +gdwDeltaBytesSec +dthread4: +dthread3: +(%s) +bSuccess +! sgpBackBuf +! sgdwLockCount +! gpBuffer +D:\diablo97\dx.cpp +caps.dwCaps & DDSCAPS_PRIMARYSURFACE +lpDDSPrimary +DirectDrawCreate +ddraw.dll +lock_buf_priv +Draw lock underflow: 0x%x +lpDDSBackBuf +draw consistency error +draw main unlock error +! lpDDSBackBuf +A<`J +A$`J +A|_J +Ad_J +AL_J +A4_J +@t^J +@\^J +@D^J +@,^J +@l]J +@T]J +@<]J +@$]J +@|\J +@d\J +@L\J +@4\J +At[J +A\[J +AD[J +A,[J +AlZJ +@TZJ +@bFlags & sfx_STREAM +pSFX +effects:1 +D:\diablo97\encrypt.cpp +info.destoffset <= dwMaxBytes +REGISTRATION_BLOCK +pRLEBytes != NULL +pDecodeTo != NULL +D:\diablo97\ENGINE.CPP +pCelBuff != NULL +pBuff != NULL +------------------------------------------------ +max allocated 0x%08x %8dk +%4s 0x%08x 0x%08x %8dk %8d +sig most ever amount at max at end of game +------------------------------------------------------ +c:\memdump.txt +Bad signature unused: %s +memory free underflow +memory block signature underflow: %s +Attempt to free memory with unknown signature %s +Memory block footer corruption: %s +Memory block header corruption: %s +Zero length SFILE: +LoadFileInMem: %s:%d +LoadFileWithMem(NULL): +pszName +nDataSize >= 0 +ttbl != NULL +p != NULL +nCel <= (int) pFrameTable[0] +nCel > 0 +gpBuffer != NULL +That which can break will. +You feel refreshed. +You feel wiser. +You feel stronger. +You feel more agile. +Spirtual energy is restored. +There's no place like home. +Some experience is gained by touch. +Give and you shall receive. +Knowledge is power. +That which does not kill you... +Arcane knowledge gained! +You must be at least level 17 to use this. +You must be at least level 13 to use this. +You must be at least level 8 to use this. +Generosity brings its own rewards +Those who are last may yet be first +Mysteries are revealed in the light of reason +Salvation comes at the cost of wisdom +The way is made clear when viewed from above +The essence of life flows from within +Strength is bolstered by heavenly faith +The hands of men may be guided by fate +Blessed by a benevolent companion! +Where avarice fails, patience gains reward +Riches abound when least expected +Energy comes at the cost of wisdom +Wherever you go, there you are +Drink and be refreshed +Knowledge and wisdom at the cost of self +Crimson and Azure become as the sun +That which cannot be held cannot be harmed +Arcane power brings destruction +Intensity comes at the cost of wisdom +What once was opened now is closed +Magic is not always what it seems to be +Time cannot diminish the power of steel +The powers of mana refocused renews +While the spirit is vigilant the body thrives +The sword of justice is swift and sharp +Those who defend seldom attack +New strength is forged through destruction +Some are weakened as one grows strong +Saving... +Loading... +No pause in multiplayer +Multiplayer sync problem +Copying to a hard disk is recommended +No Pause in town +Not enough space to save +Not available in shareware version +Direct Sound Creation Failed +No multiplayer functions in demo +No automap available in town +D:\diablo97\error.cpp +Flags:%08X +GS:%04X +EBP:%08X +CS:EIP:%04X:%08X +EAX:%08X +EBX:%08X +ECX:%08X +EDX:%08X +ESI:%08X +EDI:%08X +Registers: +%08X %02X:%08X %s +Exception code: %08X %s +%04X:%08X %s +Module +Call stack: +NTDLL.DLL +STACK_OVERFLOW +PRIV_INSTRUCTION +INT_OVERFLOW +INT_DIVIDE_BY_ZERO +FLT_UNDERFLOW +FLT_STACK_CHECK +FLT_OVERFLOW +FLT_INVALID_OPERATION +FLT_INEXACT_RESULT +FLT_DIVIDE_BY_ZERO +FLT_DENORMAL_OPERAND +ARRAY_BOUNDS_EXCEEDED +NONCONTINUABLE_EXCEPTION +INVALID_DISPOSITION +ILLEGAL_INSTRUCTION +IN_PAGE_ERROR +INVALID_HANDLE +ACCESS_VIOLATION +GUARD_PAGE +DATATYPE_MISALIGNMENT +BREAKPOINT +SINGLE_STEP +Fast Walk +Walk +Sound Disabled +Sound +Music Disabled +Music +Previous Menu +Gamma +Restart In Town +Quit Hellfire +Load Game +New Game +Options +Save Game +D:\diablo97\GameMenu.cpp +pMenuItems == sgSingleMenu +pMenuItems == sgMultiMenu +bActivate +saveProc == DisableInputWndProc +gbValidSaveFile +NLevels\TownData\Town.SOL +NLevels\L5Data\L5.SOL +Levels\L1Data\L1.SOL +Levels\L2Data\L2.SOL +NLevels\L6Data\L6.SOL +Levels\L3Data\L3.SOL +Levels\L4Data\L4.SOL +FillSolidBlockTbls +D:\diablo97\GENDUNG.CPP +Pause +D:\diablo97\gmenu.cpp +pszStr +Data\optbar.CEL +Data\option.CEL +Data\PentSpin.CEL +Data\BigTGold.CEL +Data\hf_logo3.CEL +! sgpLogo +sgpCurrItem +plOffset +pMenuItem +pItem +dwTicks >= MIN_SLIDER_TICKS && dwTicks <= MAX_SLIDER_TICKS +Press ESC to end or the arrow keys to scroll. +Hellfire Help +internal version unknown +Hellfire v1.00 +open +Microsoft Office Shortcut Bar.lnk +%s\%s\ +%s%s\ +Control Panel\Desktop +Unable to create main window +Unable to register window class +MOM Parent +\hfopt2.mpq +\hfopt1.mpq +\hfvoice.mpq +\hfmusic.mpq +\hfmonk.mpq +\hellfire.mpq +\patch_rt.mpq +DiabloInstall +Main program archive: diabdat.mpq +ui_art\title.pcx +DiabloCD +\diabdat.mpq +Archives +SFileSetBasePath +Can't get program path +version %d.%d.%d.%d +uBytes >= sizeof(VS_FIXEDFILEINFO) +D:\diablo97\init.cpp +D:\diablo97\Interfac.cpp +sgpBackCel +plr[myplr].plrlevel == currlevel +Unknown progress mode +Gendata\Cuttt.pal +Gendata\Cuttt.CEL +Nlevels\Cutl5.pal +Nlevels\Cutl5.CEL +Gendata\Cutl1d.pal +Gendata\Cutl1d.CEL +Gendata\Cut2.pal +Gendata\Cut2.CEL +Nlevels\Cutl6.pal +Nlevels\Cutl6.CEL +Gendata\Cut3.pal +Gendata\Cut3.CEL +Gendata\Cut4.pal +Gendata\Cut4.CEL +Gendata\Cutstart.pal +Gendata\Cutstart.CEL +Gendata\Cutportl.pal +Gendata\Cutportl.CEL +Gendata\Cutportr.pal +Gendata\Cutportr.CEL +Nlevels\cutl5.pal +Nlevels\cutl5.CEL +Nlevels\cutl6.pal +Nlevels\cutl6.CEL +Gendata\Cutgate.pal +Gendata\Cutgate.CEL +! sgpBackCel +D:\diablo97\inv.cpp +Data\Inv\Inv_rog.CEL +Data\Inv\Inv_Sor.CEL +Data\Inv\Inv.CEL +! pInvCels +plr[myplr].InvGrid[i] <= plr[myplr]._pNumInv +!invtest[i] +pCursCels + InvGetItem: Removing item index %d (struct %d,numitems %d) from item list! + InvGetItem: itemactive[%2.2d]: %2.2d + InvGetItem: deleting item %d. +AutogetItem + AutogetItem: Removing item index %d (struct %d,numitems %d) from item list! + AutoGetItem: set item[%d].iDelFlag = TRUE + VerifyItemActiveList: Duplicate item detected: itemactive[%d] = %d (%d %8.8x %4.4x) + Item is definitely removed! +FindGetItem(idx, ci, iseed) == -1 +FindGetItem(idx,ci,iseed) == -1 + Item removed. FindGetItem->%d, numitems->%d + Removing item index %d (struct %d,numitems %d) from item list! + Removing item from map! + FindGetItem returned %d + Nongood (x,y) + Bad (x,y). Did FindGetItem->%d. + (x,y) said ii == %d, FindGetItem says ii == %d + Attempting to find item by (x,y) + Doing SyncGetItem... + InvPutItem +CanPut(x,y) +A duplicate item has been detected. Destroying duplicate... + Duplicate item detected! +numitems >= MAXITEMS +SyncPutItem: respawning object %d! +ii >= 0 +Failed to find a good square to drop in! +A duplicate item has been detected from another player. +Player %i dropping item. +Gladiator's Ring +Acolyte's Amulet +Demon Plate Armor +Bone Chain Armor +Diamondedge +Eater of Souls +Shirotachi +Thunderclap +Blitzen +Armor of Gloom +Flambeau +Gnat Sting +Amulet of Warding +Ring of Thunder +Ring of the Mystics +Ring of Magma +Karik's Ring +Xorine's Ring +Mercurial Ring +Giant's Knuckle +Ring of Engagement +Constricting Ring +The Bleeder +Ring of Regha +Bramble +Stormshield +Holy Defender +Blackoak Shield +Dragon's Breach +Split Skull Shield +The Deflector +Demonspike Coat +Naj's Light Plate +Nightscape +Scavenger Carapace +Sparking Mail +Wisdom's Wrap +Leather of Aut +The Rainbow Cloak +The Gladiator's Bane +Torn Flesh of Souls +Royal Circlet +Gotterdamerung +Fool's Crest +OverLord's Helm +Thinking Cap +Helm of Sprits +Rod of Onan +Mindcry +Naj's Puzzler +The Protector +Thundercall +Gleamsong +Storm Spire +Immolator +Staff of Shadows +Dreamflange +Schaefer's Hammer +The Cranium Basher +Gnarled Root +Baranar's Star +The Celestial Star +Civerb's Cudgel +Hammer of Jholm +Crackrust +Messerschmidt's Reaver +Hellslayer +Aguinara's Hatchet +Stonecleaver +Wicked Axe +The Celestial Axe +BloodSlayer +Sharp Beak +The Mangler +The Grandfather +The Grizzly +Doombringer +Inferno +The Falcon's Talon +Lightsabre +Wizardspike +Shadowhawk +The Bonesaw +The Executioner's Blade +Ice Shank +Gibbous Moon +Black Razor +Gryphons Claw +The Defender +Gonnagal's Dirk +Eaglehorn +Windforce +Fleshstinger +Flamedart +The Blackoak Bow +Bow of the Dead +Deadly Hunter +The Celestial Bow +The Needler +The Rift Bow +The Butcher's Cleaver +peril +decay +devastation +blocking +harmony +stability +balance +haste +speed +swiftness +readiness +bashing +puncturing +piercing +blood +the leech +vampires +the bat +the bear +thieves +corruption +thorns +plenty +many +thunder +lightning +shock +burning +fire +flame +radiance +light +the night +the dark +the ages +structure +craftsmanship +sturdiness +brittleness +fragility +the whale +the mammoth +the lion +the tiger +the wolf +the eagle +the jaguar +the fox +the jackal +the vulture +the zodiac +the heavens +the stars +the moon +the sky +the pit +trouble +life +vigor +zest +vitality +disease +illness +wizardry +sorcery +brilliance +the mind +magic +dyslexia +the fool +perfection +precision +accuracy +skill +dexterity +atrophy +paralysis +titans +giants +power +might +strength +weakness +frailty +osmosis +deflection +absorption +protection +health +tears +pain +slaughter +carnage +gore +slaying +maiming +quality +Doppelganger's +Crystalline +Jester's +Lightning +Flaming +Bountiful +Plentiful +Arch-Angel's +Angel's +Hydra's +Wyrm's +Dragon's +Drake's +Serpent's +Snake's +Raven's +Spider's +Frog's +Hyena's +Emerald +Obsidian +Jade +Amber +Topaz +Diamond +Crystal +Ivory +Pearl +White +Sapphire +Cobalt +Lapis +Azure +Blue +Ruby +Garnet +Crimson +Godly +Holy +Awesome +Saintly +Blessed +Glorious +Valiant +Grand +Strong +Rusted +Vulnerable +King's +Champion's +Master's +Knight's +Lord's +Soldier's +Warrior's +Fine +Sharp +Dull +Clumsy +Merciless +Ruthless +Savage +Massive +Brutal +Vicious +Heavy +Deadly +Jagged +Weak +Bent +Useless +Strange +Weird +Meteoric +Mithril +Platinum +Silver +Steel +Iron +Bronze +Brass +Rune of Stone +Greater Rune of Lightning +Greater Rune of Fire +Rune of Lightning +Rune +Rune of Fire +Amulet +Ring +War Staff +Quarter Staff +Composite Staff +Long Staff +Staff +Long War Bow +Short War Bow +Long Battle Bow +Short Battle Bow +Composite Bow +Long Bow +Hunter's Bow +Maul +Flail +Spiked Club +Hammer +War Hammer +Morning Star +Mace +Great Axe +Battle Axe +Broad Axe +Large Axe +Small Axe +Great Sword +Two-Handed Sword +Bastard Sword +Broad Sword +Long Sword +Sabre +Blade +Claymore +Scimitar +Falchion +Book of +Scroll of Apocalypse +Scroll of Teleport +Scroll of None +Scroll of Golem +Scroll of Nova +Non Item +Scroll of Guardian +Scroll of Chain Lightning +Scroll of Stone Curse +Scroll of Fireball +Scroll of Flame Wave +Scroll of Mana Shield +Scroll of Phasing +Scroll of Infravision +Scroll of Flash +Scroll of Inferno +Scroll of Fire Wall +Scroll of Lightning +Scroll of Search +Scroll of Healing +Elixir of Vitality +Elixir of Dexterity +Elixir of Magic +Elixir of Strength +Oil of Sharpness +Oil of Accuracy +Potion of Full Rejuvenation +Potion of Rejuvenation +Gothic Shield +Tower Shield +Kite Shield +Large Shield +Small Shield +Shield +Full Plate Mail +Gothic Plate +Field Plate +Plate Mail +Splint Mail +Plate +Breast Plate +Scale Mail +Chain Mail +Mail +Ring Mail +Studded Leather Armor +Hard Leather Armor +Leather Armor +Armor +Quilted Armor +Robe +Cloak +Rags +Cape +Great Helm +Crown +Full Helm +Helm +Skull Cap +Grey Suit +Brown Suit +Reconstructed Note +Torn Note 3 +Torn Note 2 +Torn Note 1 +Auric Amulet +Theodore +Rune Bomb +Dagger +Sword +Short Staff +Blacksmith Oil +Scroll of Resurrect +Staff of Lazarus +Bovine Plate +Griswold's Edge +Potion of Full Mana +Potion of Full Healing +Arkaine's Valor +Scroll of Town Portal +Scroll of Identify +Potion of Mana +Potion of Healing +Heart +Cathedral Map +Blood Stone +Spectral Elixir +Fungal Tome +Brain +Black Mushroom +Anvil of Fury +Golden Elixir +Veil of Steel +Harlequin Crest +Tavern Sign +Ring of Truth +Optic Amulet +Magic Rock +Empyrean Band +The Undead Crown +Cleaver +Short Staff of Mana +Short Bow +Club +Buckler +Short Sword +Gold +Oil of Accuracy +Oil of Mastery +Oil of Sharpness +Oil of Death +Oil of Skill +Blacksmith Oil +Oil of Fortitude +Oil of Permanence +Oil of Hardening +Oil of Imperviousness +SItem +mooses1 +donkys1 +cows1 +teddys1 +runes1 +wholeps1 +halfps1 +bombs1 +FLazStaf +Fanvil +Bldstn +Innsign +FMush +FBrain +FEar +FBttleDB +FBttleWH +FBttleBY +FBttleBL +FBttleBR +FBttleOR +FBttleDY +FBttleBB +Food +FBook +FPlateAr +Scroll +WShield +LArmor +CrownF +Rock +SwrdFlip +Helmut +GoldFlip +FBttle +Armor2 +! itemanims[i] +Items\%s.CEL +D:\diablo97\ITEMS.CPP +Initing items... +plr[p]._pNAnim[d] +(DWORD) p < MAX_PLRS +%s of %s +%s %s +SetupItem: setting up object %d! +Ear of %s +CornerstoneRestore: respawning object %d! + RespawnItem: Respawning item %d! +sets petrification trap +sets lightning trap +sets fire trap +fully recover life and mana +recover life and mana +decrease vitality +decrease dexterity +decrease strength +increase vitality +increase dexterity +increase magic +increase strength +fully recover mana +recover mana +deadly heal +recover life +recover partial life +fully recover life +class of armor and shields +greatly increases the armor +of armor and shields +increases the armor class +makes an item indestructible +current and max durability +increases an item's +item's durability +restores 20% of an +to use armor or weapons +reduces attributes needed +damage potential - not bows +greatly increases a weapon's +damage potential +weapon's chance to hit +greatly increases a +chance to hit +increases a weapon's +Another ability (NW) +40%% Health moved to Mana +50%% Mana moved to Health +extra AC vs undead +extra AC vs demons +to hit: %+i%%, %+i%% damage +low dur, %+i%% damage +Random 0 - 500% damage +2x dmg to monst, 1x to you +decaying %+i%% damage +occasional triple damage +Resist Fire : %+i%% +charged bolts on hits +lightning damage: %i-%i +lightning damage: %i +see with infravision +no strength requirement +life stealing +constantly lose hit points +one handed sword +Faster attack swing +altered durability +unusual item damage +fires random speed arrows +adds %i points to damage +fast block +fastest hit recovery +faster hit recovery +fast hit recovery +fastest attack +faster attack +fast attack +quick attack +penetrates target's armor +hit steals 5% life +hit steals 3% life +hit steals 5% mana +hit steals 3% mana +hit monster doesn't heal +All Resistance equals 0 ++200% damage vs. demons +knocks target back +absorbs half of trap damage +you can't heal +user loses all mana +attacker takes 1-3 damage +fireball damage: %i-%i +fireball damage: %i +lightning arrows damage %i-%i +lightning arrows damage %i +fire arrows damage: %i-%i +fire arrows damage: %i +multiple arrows per shot +-%i%% light radius ++%i%% light radius +indestructible +decreased durability +high durability +Mana : %+i +Hit Points : %+i +%+i damage from enemies +%+i to all attributes +%+i to vitality +%+i to dexterity +%+i to magic +%+i to strength +Lightning hit damage: %i-%i +Lightning hit damage: %i +Fire hit damage: %i-%i +Fire hit damage: %i +%i %s charges +Extra charges +spells are decreased 1 level +spells are increased 2 levels +spells are increased 1 level +Resist All : 75%% MAX +Resist All : %+i%% +Resist Magic : 75%% MAX +Resist Magic : %+i%% +Resist Lightning : 75%% MAX +Resist Lightning : %+i%% +Resist Fire : 75%% MAX +armor class: %i +%+i%% armor +%+i%% damage +chance to hit : %+i%% +Doubles gold capacity +Right click to view +Right click to read +Right click to use +left-click to target +Right-click to read, then +Right-click to read +%s %i Dex +%s %i Mag +%s %i Str +Required: +unique item +Charges: %i/%i +dam: %i-%i Dur: %i/%i +dam: %i Dur: %i/%i +armor: %i Dur: %i/%i +armor: %i Indestructible +damage: %i-%i Dur: %i/%i +damage: %i-%i Indestructible +damage: %i Dur: %i/%i +damage: %i Indestructible +Not Identified +gnNumGetRecords > 0 +nIndex < gnNumGetRecords +D:\diablo97\LIGHTING.CPP +! pLightTbl +PlrGFX\Stone.TRN +PlrGFX\Infra.TRN +Invalid save file +D:\diablo97\loadsave.cpp +FILEBUFF >= tbuff - SaveBuff +Unable to display mainmenu +Unable to display SelHeroSing +Can't load multiplayer dialog +D:\diablo97\minitext.cpp +Data\TextBox.CEL +Data\MedTextS.CEL +! pMedTextCels +(DWORD) m < gdwAllTextEntries +ms_blb +ex_red3 +ex_blu3 +ex_yel2 +rglows1 +ms_yeb +ms_reb +ms_bla +ms_ora +reflect +spawns +Scbsexpd +Scubmisd +Scbsexpc +Scubmisc +Scbsexpb +Scubmisb +Fireplar +Rportal +Sklball +Ressur1 +Firerun +Ethrshld +Acidpud +Acidspla +Acidbf +Firarwex +Larrow +Holyexpl +Miniltng +Krull +Magball +Flareexp +Flare +Thinlght +Bigexp +Shatter1 +Newexp +Blodbur +Doom +Farrow +Metlhit +Bone +Blood +Manashld +Bluexbk +Bluexfr +Portal +MagBlos +Firewal +Lghning +Guard +Fireba +Arrows +i < 64 && i >= 0 +myplr < MAX_PLRS && myplr >= 0 +D:\diablo97\MISSILES.CPP +pn <= MAXTILES && pn >= 0 +fy < MAXDUNY && fy >= 0 +fx < MAXDUNX && fx >= 0 +sn < 64 && sn >= 0 +id < MAX_PLRS && id >= 0 +i < MAXMISSILES +nummissiles <= MAXMISSILES +monster[m].MType != NULL +m < MAXMONSTERS && m >= 0 +monster[m].MData != NULL +pnum < MAX_PLRS && pnum >= 0 +mi < MAXMISSILES && mi >= 0 +Missiles\%s%i.CL2 +Missiles\%s.CL2 +mx < MAXMISSILES && mx >= 0 +i < MAXMISSILES && i >= 0 +dy < MAXDUNY && dy >= 0 +dx < MAXDUNX && dx >= 0 +p < MAX_PLRS && p >= 0 +monster[id].MType != NULL +id < MAXMONSTERS +numtrigs <= MAXTRIGGERS +pn <= MAXTILES +ty < MAXDUNY && ty >= 0 +tx < MAXDUNX && tx >= 0 +id < MAXMONSTERS && id >= 0 +my < MAXDUNY && my >= 0 +mx < MAXDUNX && mx >= 0 +monst < MAXMONSTERS && monst >= 0 +missile[i]._miy < MAXDUNY && missile[i]._miy >= 0 +missile[i]._mix < MAXDUNX && missile[i]._mix >= 0 +\\.\DARKMONO.VXD +Doomlock +Grimspike +Fleshdancer +Webwidow +Bloodlust +Zamphir +The Vizier +Sir Gorash +Steelskull the Hunter +Stareye the Witch +Dreadjudge +Graywar the Slayer +Gorefeast +Witchmoon +Bloodmoon Soulfire +Doomcloud +Howlingire the Shade +Rustweaver +Lord of the Pit +Windspawn +Soulslash +Blackskull +Witchfire the Unholy +Fangskin +Viperflame +Viletouch +Blacktongue +Lionskull the Bent +Festerskull +Fangspeir +Warpfire Hellspawn +Bluehorn +The Flayer +Plaguewrath +Blackstorm +Goldblight of the Flame +Oozedrool +Stormbane +Brokenstorm +Devilskull Sharpbone +Breakspine +Bonesaw the Litch +Madburner +Doomgrin the Rotting +Chaoshowler +BHSM +Blighthorn Steelmace +Baron Sludge +Firewound the Grim +WFTD +Wrathfire the Doomed +Bronzefist Firestone +Gorestone +Nightwing the Cold +Blightfire +Glasskull the Jagged +Warmaggot the Mad +DSFM +Deathshade Fleshmaul +BGBL +Bloodgutter +BFDS +Deathspit +Hazeshifter +SHDR +Shadowdrinker +Foulwing +Bloodskin Darkbow +BFTP +Bilefroth the Pit Master +Blightstone the Weak +Shadowcrow +BASHTB +Blackash the Burning +Spineeater +Wrathraven +Moonbender +Pulsecrawler +Goretongue +TSPO +Warpskull +SKFR +Skullfire +El Chupacabras +Madeye the Dead +Deadeye +SHBT +Shadowbite +RCRN +Rotcarnage +Bongo +BHBS +Brokenhead Bangshield +Gutshank the Quick +Rotfeast the Hungry +Boneripper +Pukerat the Unclean +Soulpus +BSTS +Bladeskin the Slasher +Bonehead Keenaxe +The Defiler +Warlord of Blood +BHKA +Lachdanan +BLKJD +BlackJade +REDV +Red Vex +Arch-Bishop Lazarus +Snotspill +GENERAL +Zhar the Mad +GENRL +BSDB +Gharbad the Weak +Na-Krul +Monsters\newsfx\Nakrul%c%i.WAV +Monsters\Nkr\Nkr%c.CL2 +Reaper +Monsters\newsfx\Reaper%c%i.WAV +Monsters\Reaper\Reap%c.CL2 +Flesh Thing +Monsters\newsfx\FleshT%c%i.WAV +Monsters\Flesh\Flesh%c.CL2 +Biclops +Monsters\newsfx\Biclop%c%i.WAV +Monsters\Byclps\Byclps%c.CL2 +Arch Lich +Monsters\Lich2\Lich2%c.CL2 +Bone Demon +Hellbat +Monsters\Hellbat2\bhelbt%c.CL2 +Crypt Demon +Monsters\newsfx\Crypt%c%i.WAV +Monsters\Bubba\Bubba%c.CL2 +Lich +Monsters\newsfx\Lich%c%i.WAV +Monsters\Lich\Lich%c.CL2 +Skullwing +Monsters\newsfx\SWing%c%i.WAV +Firebat +Monsters\newsfx\HelBat%c%i.WAV +Monsters\Hellbat\Helbat%c.CL2 +Tomb Rat +Monsters\newsfx\TmbRat%c%i.WAV +Monsters\Rat\Rat%c.CL2 +Gravedigger +Monsters\newsfx\GDiggr%c%i.WAV +Monsters\Gravdg\Gravdg%c.CL2 +Hell Bug +Monsters\newsfx\Defile%c%i.WAV +Monsters\Hellbug\Hellbg%c.CL2 +Hork Demon +Monsters\newsfx\HDemon%c%i.WAV +Monsters\HorkD\HorkD%c.CL2 +Torchant +Monsters\newsfx\TchAnt%c%i.WAV +Monsters\AntWorm\Worm%c.CL2 +Lashworm +Monsters\newsfx\Lworm%c%i.WAV +Monsters\Clasp\Clasp%c.CL2 +Spider Lord +Monsters\bSpidr\bSpidr%c.CL2 +Necromorb +Monsters\newsfx\Psyco%c%i.WAV +Monsters\Eye2\Eye2%c.CL2 +Venomtail +Monsters\WScorp\WScorp%c.CL2 +Hork Spawn +Monsters\newsfx\HSpawn%c%i.WAV +Monsters\Spawn\Spawn%c.CL2 +Felltwin +Monsters\newsfx\FTwin%c%i.WAV +Arachnon +Monsters\newsfx\SLord%c%i.WAV +Monsters\Spider\Spider%c.CL2 +Psychorb +Monsters\newsfx\psyco%c%i.WAV +Monsters\Eye\Eye%c.CL2 +Stinger +Monsters\newsfx\Stingr%c%i.WAV +Monsters\Scorp\Scorp%c.CL2 +Hellboar +Monsters\newsfx\HBoar%c%i.WAV +Monsters\Fork\Fork%c.CL2 +The Arch-Litch Malignus +Monsters\DarkMage\Dmag%c%i.WAV +Monsters\DarkMage\Dmage%c.CL2 +The Dark Lord +Monsters\Diablo\Diablo%c%i.WAV +Monsters\Diablo\Diablo%c.CL2 +Golem +Monsters\Golem\Golm%c%i.WAV +Monsters\Golem\Golem%c.CL2 +Advocate +Monsters\Mage\Cnselbk.TRN +Cabalist +Monsters\Mage\Cnselgd.TRN +Magistrate +Monsters\Mage\Cnselg.TRN +Counselor +Monsters\Mage\Mage%c%i.WAV +Monsters\Mage\Mage%c.CL2 +Soul Burner +Monsters\Succ\Succbw.TRN +Hell Spawn +Monsters\Succ\Succrw.TRN +Snow Witch +Monsters\Succ\Succb.TRN +Succubus +Monsters\Succ\Scbs%c%i.WAV +Monsters\Succ\Scbs%c.CL2 +Reality Weaver +Pain Master +Hollow One +The Shredded +Monsters\newsfx\Shred%c%i.WAV +Monsters\Unrav\Unrav%c.CL2 +Blood Knight +Monsters\Black\BlkKntBe.TRN +Steel Lord +Monsters\Black\BlkKntBT.TRN +Doom Guard +Monsters\Black\BlkKntRT.TRN +Black Knight +Monsters\Black\Black%c%i.WAV +Monsters\Black\Black%c.CL2 +Azure Drake +Monsters\Snake\Snakb.TRN +Gold Viper +Monsters\Snake\Snakg.TRN +Fire Drake +Monsters\Snake\SnakR.TRN +Cave Viper +Monsters\Snake\Snake%c%i.WAV +Monsters\Snake\Snake%c.CL2 +Balrog +Monsters\Mega\Balr.TRN +Vortex Lord +Monsters\Mega\Vtexl.TRN +Guardian +Monsters\Mega\Guard.TRN +Slayer +Monsters\Mega\Mega%c%i.WAV +Monsters\Mega\Mega%c.CL2 +Death Wing +Monsters\Gargoyle\GargB.TRN +Blood Claw +Monsters\Gargoyle\GargBr.TRN +Gargoyle +Monsters\Gargoyle\GarE.TRN +Winged-Demon +Monsters\Gargoyle\Gargo%c%i.WAV +Monsters\Gargoyle\Gargo%c.CL2 +Devil Kin Brute +Monsters\newsfx\KBrute%c%i.WAV +Monsters\BigFall\Fallg%c.CL2 +Maelstorm +Monsters\Thin\Thinv1.TRN +Storm Lord +Monsters\Thin\Thinv2.TRN +Storm Rider +Red Storm +Hell Burner +Doom Fire +Flame Lord +Incinerator +Monsters\Fireman\FireM%c.CL2 +Undead Balrog +Litch Demon +Red Death +Monsters\Thin\Thin%c.CL2 +oldboned +Monsters\Thin\Thinv3.TRN +Monsters\Thin\Thin%c%i.WAV +Monsters\Demskel\Demskl%c.CL2 +Obsidian Lord +Monsters\Rhino\RhinoB.TRN +Frost Charger +Monsters\Rhino\Blue.TRN +Mud Runner +Monsters\Rhino\Orange.TRN +Horned Demon +Monsters\Rhino\Rhino%c%i.WAV +Monsters\Rhino\Rhino%c.CL2 +Lava Lord +Monsters\Magma\Wierd.TRN +Hell Stone +Monsters\Magma\Blue.TRN +Monsters\Magma\Yellow.TRN +Magma Demon +Monsters\Magma\Magma%c%i.WAV +Monsters\Magma\Magma%c.CL2 +Devourer +Devil Wyrm +Cave Slug +Wyrm +Monsters\Worm\Worm%c.CL2 +Flayed One +Monsters\Fat\FatF.TRN +Toad Demon +Monsters\Fat\FatB.TRN +Mud Man +Monsters\Fat\Blue.TRN +Overlord +Monsters\Fat\Fat%c%i.WAV +Monsters\Fat\Fat%c.CL2 +The Butcher +Monsters\FatC\FatC%c%i.WAV +Monsters\FatC\FatC%c.CL2 +Skeleton King +Monsters\SKing\SKing%c%i.WAV +Monsters\SKing\SKing%c.CL2 +Lava Maw +Monsters\Acid\AcidR.TRN +Pit Beast +Monsters\Acid\AcidB.TRN +Poison Spitter +Monsters\Acid\AcidBlk.TRN +Acid Beast +Monsters\Acid\Acid%c%i.WAV +Monsters\Acid\Acid%c.CL2 +Monsters\GoatBow\Gray.TRN +Monsters\GoatBow\Red.TRN +Monsters\GoatBow\Beige.TRN +Monsters\GoatBow\GoatB%c%i.WAV +Monsters\GoatBow\GoatB%c.CL2 +Familiar +Monsters\Bat\orange.trn +Gloom +Monsters\Bat\grey.trn +Blink +Fiend +Monsters\Bat\red.trn +Monsters\Bat\Bat%c%i.WAV +Monsters\Bat\Bat%c.CL2 +Night Clan +Monsters\GoatMace\Gray.TRN +Fire Clan +Monsters\GoatMace\Red.TRN +Stone Clan +Monsters\GoatMace\Beige.TRN +Flesh Clan +Monsters\GoatMace\Goat%c%i.WAV +Monsters\GoatMace\Goat%c.CL2 +Satyr Lord +Monsters\newsfx\Satyr%c%i.WAV +Monsters\GoatLord\GoatL%c.CL2 +Illusion Weaver +Monsters\Sneak\Sneakv1.TRN +Unseen +Monsters\Sneak\Sneakv3.TRN +Stalker +Monsters\Sneak\Sneakv2.TRN +Hidden +Monsters\Sneak\Sneak%c%i.WAV +Monsters\Sneak\Sneak%c.CL2 +Invisible Lord +Monsters\TSneak\Sneakl%c%i.WAV +Monsters\TSneak\TSneak%c.CL2 +Horror Captain +Monsters\SkelSd\Black.TRN +Burning Dead Captain +Corpse Captain +Monsters\SkelSd\Skelt.TRN +Skeleton Captain +Monsters\SkelSd\White.TRN +Monsters\SkelSd\SklSr%c%i.WAV +Monsters\SkelSd\SklSr%c.CL2 +Monsters\SkelBow\Black.TRN +Corpse Bow +Monsters\SkelBow\Skelt.TRN +Monsters\SkelBow\White.TRN +Monsters\SkelBow\SklBw%c%i.WAV +Monsters\SkelBow\SklBw%c.CL2 +Bone Gasher +Monsters\Scav\ScavW.TRN +Shadow Beast +Monsters\Scav\ScavBe.TRN +Plague Eater +Monsters\Scav\ScavBr.TRN +Scavenger +Monsters\Scav\Scav%c%i.WAV +Monsters\Scav\Scav%c.CL2 +Monsters\FalSword\Blue.TRN +Monsters\FalSword\Dark.TRN +Monsters\FalSword\FallenT.TRN +Monsters\FalSword\Fall%c%i.WAV +Monsters\FalSword\Fall%c.CL2 +Horror +Monsters\SkelAxe\Black.TRN +Burning Dead +Corpse Axe +Monsters\SkelAxe\Skelt.TRN +Skeleton +Monsters\SkelAxe\White.TRN +Monsters\SkelAxe\SklAx%c%i.WAV +Monsters\SkelAxe\SklAx%c.CL2 +Dark One +Monsters\FalSpear\Blue.TRN +Devil Kin +Carver +Monsters\FalSpear\Dark.TRN +Fallen One +Monsters\FalSpear\FallenT.TRN +Monsters\FalSpear\Phall%c%i.WAV +Monsters\FalSpear\Phall%c.CL2 +Black Death +Monsters\Zombie\Yellow.TRN +Rotting Carcass +Monsters\Zombie\Grey.TRN +Ghoul +Monsters\Zombie\Bluered.TRN +Zombie +Monsters\Zombie\Zombie%c%i.WAV +Monsters\Zombie\Zombie%c.CL2 +Invalid Monster +nwahds +D:\diablo97\MONSTER.CPP +(DWORD)nummtypes <= MAX_LVLMTYPES +! Monsters[monst].Anims[anim].CMem +(DWORD)monst < MAX_LVLMTYPES +monst->MData != NULL +(DWORD)mtype < MAX_LVLMTYPES +(DWORD)i < MAXMONSTERS +(uniquetrans << 8) + 4864 < LIGHTSIZE +Monsters\Monsters\%s.TRN +uniqtype < nummtypes +(DWORD)nummonsters < MAXMONSTERS +Levels\L3Data\Anvil.DUN +Levels\L2Data\Blood2.DUN +Levels\L1Data\Banner1.DUN +skeltype < nummtypes +(DWORD)monster[nummonsters]._my < MAXDUNY +(DWORD)monster[nummonsters]._mx < MAXDUNX +(DWORD)leader < MAXMONSTERS +(DWORD)(nummonsters-1) < MAXMONSTERS +(DWORD)nummonsters <= MAXMONSTERS +monster[i].MType != NULL +(DWORD)md < 8 +(DWORD)(my+1) < MAXDUNY +(DWORD)(mx+1) < MAXDUNX +(DWORD)monster[i]._my < MAXDUNY +(DWORD)monster[i]._mx < MAXDUNX +M_StartKill: Invalid monster %d +MonstStartKill: Monster %d "%s" MType NULL +MonstStartKill: Invalid monster %d +M_SyncStartKill: Invalid monster %d +M_DoStand: Monster %d "%s" MType NULL +M_DoStand: Invalid monster %d +M_DoWalk: Monster %d "%s" MType NULL +M_DoWalk: Invalid monster %d +M_ChangeLightOffset: Invalid monster %d +M_DoWalk2: Monster %d "%s" MType NULL +M_DoWalk2: Invalid monster %d +M_DoWalk3: Monster %d "%s" MType NULL +M_DoWalk3: Invalid monster %d +M_TryM2MHit: Monster %d "%s" MType NULL +M_TryM2MHit: Invalid monster %d +Monster %d "%s" getting hit by monster: MType NULL +Invalid monster %d getting hit by monster +M2MStartKill: Monster %d "%s" MType NULL +M2MStartKill: Invalid monster (killed) %d +M2MStartKill: Invalid monster (attacker) %d +M_DoAttack: Monster %d "%s" MData NULL +M_DoAttack: Monster %d "%s" MType NULL +M_DoAttack: Invalid monster %d +(DWORD)pnum < MAX_PLRS +M_TryH2HHit: Monster %d "%s" MType NULL +M_TryH2HHit: Invalid monster %d +M_DoRAttack: Monster %d "%s" MData NULL +M_DoRAttack: Monster %d "%s" MType NULL +M_DoRAttack: Invalid monster %d +M_DoRSpAttack: Monster %d "%s" MData NULL +M_DoRSpAttack: Monster %d "%s" MType NULL +M_DoRSpAttack: Invalid monster %d +M_DoSAttack: Monster %d "%s" MData NULL +M_DoSAttack: Monster %d "%s" MType NULL +M_DoSAttack: Invalid monster %d +M_DoFadein: Invalid monster %d +M_DoFadeout: Invalid monster %d +M_DoHeal: Invalid monster %d +SS Talk = %i, Flags = %i +setpc_x != 0 +M_DoTalk: Invalid monster %d +(DWORD)Monst->_my < MAXDUNY +(DWORD)Monst->_mx < MAXDUNX +M_Teleport: Invalid monster %d +M_DoGotHit: Monster %d "%s" MType NULL +M_DoGotHit: Invalid monster %d +M_UpdateLeader: Invalid monster %d +gendata\loopdend.smk +gendata\Diabend.smk +gendata\DiabVic3.smk +gendata\DiabVic1.smk +gendata\DiabVic2.smk +(DWORD)myplr < MAX_PLRS +!(dFlags[monster[i]._mx+1][monster[i]._my] & BFLAG_MONSTLR) && !(dFlags[monster[i]._mx][monster[i]._my+1] & BFLAG_MONSTLR) +M_DoDeath: Monster %d "%s" MType NULL +M_DoDeath: Invalid monster %d +M_DoSpStand: Monster %d "%s" MType NULL +M_DoSpStand: Invalid monster %d +M_DoDelay: Monster %d "%s" MType NULL +M_DoDelay: Invalid monster %d +M_DoStone: Invalid monster %d +M_WalkDir: Invalid monster %d +(DWORD)fy < MAXDUNY +(DWORD)fx < MAXDUNX +GroupUnity: Invalid monster %d +M_PathWalk: Invalid monster %d +MAI_Zombie: Invalid monster %d +MAI_SkelSd: Invalid monster %d +MAI_Path: Invalid monster %d +Monst->_mgoalvar2 >= 0 && Monst->_mgoalvar2 < 8 +MAI_Snake: Invalid monster %d +MAI_Bat: Invalid monster %d +MAI_SkelBow: Invalid monster %d +MAI_Fat: Invalid monster %d +MAI_Sneak: Invalid monster %d +M_StartFadein: Monster %d "%s" MType NULL +M_StartFadein: Invalid monster %d +M_StartFadeout: Monster %d "%s" MType NULL +M_StartFadeout: Invalid monster %d +MAI_Fireman: Invalid monster %d +MAI_Fallen: Invalid monster %d +MAI_Cleaver: Invalid monster %d +MAI_Round: Invalid monster %d +MAI_Ranged: Invalid monster %d +MAI_Scav: Invalid monster %d +MAI_Garg: Invalid monster %d +M_StartHeal: Monster %d "%s" MType NULL +M_StartHeal: Invalid monster %d +MAI_RoundRanged: Invalid monster %d +MAI_RR2: Invalid monster %d +MAI_Golum: Invalid monster %d +MAI_SkelKing: Invalid monster %d +MAI_Rhino: Invalid monster %d +MAI_HorkDemon: Invalid monster %d +MAI_Counselor: Invalid monster %d +MAI_Garbud: Invalid monster %d +MAI_Zhar: Invalid monster %d +MAI_SnotSpil: Invalid monster %d +gendata\fprst3.smk +MAI_Lazurus: Invalid monster %d +MAI_Lazhelp: Invalid monster %d +MAI_Lachdanan: Invalid monster %d +MAI_Warlord: Invalid monster %d +Illegal enemy player %d for monster "%s" +Illegal enemy monster %d for monster "%s" +tmp >= 0 +DirOK: Invalid monster %d +(DWORD)monster[m]._mMTidx < MAX_LVLMTYPES +SyncMonsterAnim: Invalid monster %d +Immune : +Lightning +Resists : +Fire +Magic +No magic resistance +Hit Points : %i-%i +Total kills : %i +Some Magic Immunities +Some Magic Resistances +No Immunities +No resistances +Monst->_mmode == MM_MISSILE +MissToMonst: Invalid monster %d +MissToMonst: Invalid missile %d +TalktoMonster: Invalid monster %d +SpawnGolum: Invalid monster %d +CanTalkToMonst: Invalid monster %d +CheckMonsterHit: Invalid monster %d +saveProc == MovieWndProc +D:\diablo97\movie.cpp +pszMovie +Hellfire +Video Player +D:\diablo97\mpqapi.cpp +pszArchive +dwChar < MAX_CHARACTERS +gbMaxPlayers != 1 +sghArchive != INVALID_HANDLE_VALUE +MPQ free list error +Out of free block entries +fnGetName +pbData +Out of hash space +Hash collision between "%s" and existing file +destsize <= pBlk->sizealloc +sectoroffsettable +pszNew +pszOld +(hash table) +HASH_TBL_SIZE == dwTemp +fhdr.hdr.hashoffset == HASH_TBL_OFFSET +fhdr.hdr.hashcount == HASH_ENTRIES +! sgpHashTbl +(block table) +BLOCK_TBL_SIZE == dwTemp +fhdr.hdr.blockoffset == BLOCK_TBL_OFFSET +fhdr.hdr.blockcount == BLOCK_ENTRIES +! sgpBlockTbl +sghArchive == INVALID_HANDLE_VALUE +pdwNextFileStart +pHdr +(%8.8x,%2.2d): +c:\droplog.txt +sgpCurrPkt->dwSpaceLeft >= dwLen +sgpCurrPkt +dwLen <= gdwLargestMsgSize +pMsg +(DWORD) pnum < MAX_PLRS +D:\diablo97\msg.cpp +Unable to get level data +The game ended +Waiting for game data... +! sgpCurrPkt +! sgpMegaPkt +plr[myplr].plrlevel == 0 +currlevel == 0 +(DWORD) nPlayer < MAX_PLRS +bLevel < NUMLEVELS +y < DMAXY +x < DMAXX +(DWORD)mi < MAXMONSTERS +pSync != NULL +bLevel != 0 +(DWORD)i < MAXPORTAL +(DWORD)i <= MAXMULTIQUESTS +(DWORD)ii < MAXITEMS +(DWORD) currlevel < NUMLEVELS + DeltaLoadLevel: respawning %d (%4.4x,%4.4x,%8.8x) @ (x,y)->(%2.2x,%2.2x) +done + DeltaLoadLevel: moving object from (x,y)->(%2.2x,%2.2x) to (x,y)->(%2.2x,%2.2x)! +my < DMAXY +mx < DMAXX +pnum < MAX_PLRS +ii < MAXITEMS +bPlr < MAX_PLRS +dwStrLen < sizeof(cmd.str) +pCmd != NULL +p->wOffset == sgdwRecvOffset +msg:1 +CMD_SYNCDATA(%d) +CMD_WALKXY(%d):(%d,%d) +gbBufferMsgs != BUFFER_PROCESS +CMD_ADDSTR(%d) +CMD_ADDMAG(%d) +CMD_ADDDEX(%d) +CMD_ADDVIT(%d) +%s has cast an illegal spell. +CMD_SBSPELL(%d) +CMD_GOTOGETITEM(%d): xy->(%d,%d) + Resend expired. Extra Item. + Item not found. Resending. + Item found. FindGetItem returned %d and iDelFlag is FALSE. +currlevel == plr[myplr].plrlevel +CMD_REQUESTGETITEM(%d,%8.8x): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + Not found in delta tbl. Resending... + Remote player (%d) got item. + Local player got item. + Item already picked up. + Found in delta tbl. + Looking in delta tbl[%d] + Data: dwTime = %8.8x + Data: dwBuff = %8.8x + Data: wValue = %4.4x + Data: bMCh = %2.2x + Data: bCh = %2.2x + Data: bMDur = %2.2x + Data: bDur = %2.2x + Data: bID = %2.2x + Data: dwSeed = %8.8x + Data: wCI = %4.4x + Data: wIndx = %4.4x + Data: y = %2.2x + Data: x = %2.2x + Data: bLevel = %2.2x + Data: bCursitem = %2.2x + Data: bPnum = %2.2x + Data: bMaster = %2.2x + Data: bCmd = %2.2x +CMD_GETITEM(%d,%8.8x,%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + delta_get_item: added item to delta tbl + delta_get_item: could not add item to delta tbl + delta_get_item: item not found +delta:1 + delta_get_item: foreign item picked up from floor + delta_get_item: native item picked up from floor + delta_get_item: item already picked up?! +pI != NULL +CMD_GOTOAUTOGETITEM(%d): xy->(%d,%d) + Item found. +CMD_REQUESTAUTOGETITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) +CMD_AUTOGETITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) +CMD_ITEMEXTRA(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + Item not on my level. Adding to delta... + Put unsuccessful. + Dropping into delta tbl[%d] + Put successful. Putting item into delta... + Item on my level. +CMD_PUTITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) +Trying to drop a floor item? +CMD_SYNCPUTITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) + Adding to delta... + SyncPutting into level. +CMD_RESPAWNITEM(%d): index->0x%8.8x ci->0x%8.8x seed->0x%8.8x xy->(%d,%d) +CMD_ATTACKXY(%d): xy->(%d,%d) +CMD_SATTACKXY(%d): xy->(%d,%d) +CMD_RATTACKXY(%d): xy->(%d,%d) +CMD_SPELLXYD(%d): xy->(%d,%d) +CMD_SPELLXY(%d): xy->(%d,%d) +CMD_TSPELLXY(%d): xy->(%d,%d) +CMD_OPOBJXY(%d): xy->(%d,%d) +CMD_DISARMXY(%d): xy->(%d,%d) +CMD_OPOBJT(%d) +CMD_ATTACKID(%d): id->%d +CMD_ATTACKPID(%d): id->%d +CMD_RATTACKID(%d): id->%d +CMD_RATTACKPID(%d): id->%d +CMD_SPELLID(%d): id->%d +CMD_SPELLPID(%d): id->%d +CMD_TSPELLID(%d): id->%d +CMD_TSPELLPID(%d): id->%d +CMD_KNOCKBACK(%d): id->%d +CMD_RESURRECT(%d): id->%d +CMD_HEALOTHER(%d): id->%d +CMD_TALKXY(%d): xy->(%d,%d) +CMD_NEWLVL(%d) +CMD_WARP(%d) +CMD_MONSTDEATH(%d): id->%d xy->(%d,%d) +CMD_KILLGOLEM(%d): xy->(%d,%d) +CMD_AWAKENGOLEM(%d) +CMD_MONSTDAMAGE(%d): id->%d +CMD_PLAYERDEAD(I'm dead!!!) +CMD_PLAYERDEAD(%d): id->%d + Current level->%d + I'm taking damage. +CMD_PLAYERDAMAGE(%d) +CMD_OPENDOOR(%d): id->%d +(DWORD)oi < MAXOBJECTS +CMD_CLOSEDOOR(%d): id->%d +CMD_OPERATEOBJ(%d): id->%d +CMD_PLAYEROPOBJ(%d): plrid->%d objid->%d +CMD_BREAKOBJ(%d): id1->%d id2->%d +CMD_CHANGEPLAYERITEMS(%d): index->%8.8x ci->%8.8x seed->%8.8x +CMD_DELPLAYERITEMS(%d): loc->%d +CMD_PLAYERLEVEL(%d) +CMD_DROPITEM(%d): index->%8.8x ci->%8.8x seed->%8.8x xy->(%d,%d) +CMD_ACK\SENDPLRINFO(%d) +(%d) activating %d on joinlevel +Player '%s' (level %d) just joined the game +(%d) received %d joinlevel before plrdata +CMD_PLAYERJOINLEVEL(%d) +CMD_ACTIVATEPORTAL(%d): xy->(%d,%d) +CMD_DEACTIVEPORTAL(%d) +CMD_RETOWN(%d) +CMD_SETSTR(%d) +CMD_SETDEX(%d) +CMD_SETMAG(%d) +CMD_SETVIT(%d) +CMD_STRING(%d) +CMD_SYNCQUEST(%d) +CMD_ENDSHIELD(%d) +CMD_CHEATEXPERIENCE(%d) +CMD_CHEATSPELLLEVEL(%d) + %x%c %x%c %x%c %x%c +%4u.%02u +c:\dumphist.txt +bLen <= gdwNormalMsgSize - sizeof(TPktHdr) +sgbNetInited +D:\diablo97\multi.cpp +msg buffer failure +SNetSendMessage0 +bLen +pbMsg +SNetSendMessage +(DWORD) myplr < MAX_PLRS +dwSendBytes < gdwNormalMsgSize +glpMsgTbl[i] +(%d) player %d left game due to 0x%x +(%d) buffering -- player %d left game due to 0x%x +Player '%s' killed Diablo and left the game! +Player '%s' dropped due to timeout +Player '%s' just left the game +(%d) player %d --> inactive +nLowestPlayer != -1 +nLowestActive != -1 +bGroupPlayers +(%d) dropping player %d state 0x%x +SNetReceiveMsg +SNetSendMessage2 +dwBody <= 0x0ffff +dwLen <= 0x0ffff +(%d) NetClose +SNetRegisterEventHandler: +pEvt->databytes >= sizeof(DWORD) +(%d) callback: player %d left game due to 0x%x +pEvt->playerid >= 0 && pEvt->playerid < MAX_PLRS +pEvt->data +SNetGetGameInfo2 +SNetGetGameInfo1 +! *pfExitProgram +(%d) new game started +dwID == 0 +SNetCreateGame1: +SNetInitializeProvider: +Hellfire Retail +pfExitProgram +local +Network upgrade failed +(%d) received all %d plrinfo +(%d) making %d active -- recv_plrinfo +Player '%s' (level %d) is already in the game +D:\diablo97\nthread.cpp +pszFcn +SNetSendTurn +gdwTurnsInTransit +SNetGetTurnsInTransit +SNetReceiveTurns +sgbSyncCountdown +sgbPacketCountdown +pfSendAsync +%02x %02x %02x %02x +nthread2: +caps.maxplayers +gdwLargestMsgSize >= MIN_MSG_SIZE +SNetGetProviderCaps: +n:%u +nthread3: +(%s) +sgbThreadIsRunning != bStart +L6Pod2 +L6Pod1 +L5Books +Urnexpld +L5Sarco +L5Light +L5Lever +LzStand +Mushptch +Bkslbrnt +Mcirl +Altboy +TFountn +MFountn +Cauldren +Goatshrn +Armstand +PFountn +L3Doors +Pedistl +Decap +Bloodfnt +RShrineG +LShrineG +Barrelex +Barrel +WeapStnd +BShelf +BCase +WTorch1 +WTorch2 +MiniWatr +Traphole +Prsrplt1 +Flame1 +Sarc +WTorch3 +WTorch4 +L2Doors +TSoul +TNudeW +TNudeM +Switch4 +Nude2 +Candle2 +Burncros +Chest3 +Angel +Rockstan +Book2 +Book1 +CruxSk3 +CruxSk2 +CruxSk1 +SkulStik +SkulFire +SkulPile +Banner +Chest2 +Chest1 +Lever +L1Doors +L1Braz +A Spellbook +Journal: The End +Journal: NA-KRUL +Journal: His Power Grows +Journal: The Tirade +Journal: The Meeting +Journal: The Ensorcellment +The Black King +Tale of the Three +The Realms Beyond +The Binding of the Three +The Sin War +The Dark Exile +The Tale of the Horadrim +The Wages of Sin are War +The Great Conflict +Murphy's +Solar +Shimmering +Town +Sparkling +Mendicant's +Glowing +Oily +Tainted +Glimmering +Ornate +Secluded +Quiet +Creepy +Abandoned +Spooky +Spiritual +Sacred +Divine +Eerie +Eldritch +Cryptic +Fascinating +Thaumaturgic +Enchanted +Religious +Stone +Magical +Gloomy +Mysterious +Nlevels\L5data\L5door.CEL +! pObjCels[numobjfiles] +Objects\%s.CEL +numobjfiles == 0 +D:\diablo97\OBJECTS.CPP +(DWORD)i < MAXOBJECTS +(DWORD)yp < MAXDUNY +(DWORD)xp < MAXDUNX +(DWORD)v1 < MAXOBJECTS +(DWORD)o < MAXOBJECTS +Trapped %s +Slain Hero +Vile Stand +Mushroom Patch +Weapon Rack +Pedestal of Blood +Fountain of Tears +Murky Pool +Cauldron +Goat Shrine +Purifying Spring +Book of Blood +Steel Tome +Book of the Blind +Decapitated Body +Blood Fountain +Library Book +Skeleton Tome +%s Shrine +Bookcase +Bookshelf +Sarcophagus +Large Chest +Chest +Small Chest +Mythical Book +Blocked Door +Closed Door +Open Door +Skull Lever +Book of Vileness +Ancient Tome +Crucified Skeleton +D:\diablo97\PALETTE.CPP +pszFileName +NLevels\L%iData\L%iBase%i.PAL +NLevels\L5Data\L5Base.PAL +Levels\L%iData\L%i_%i.PAL +Levels\TownData\Town.pal +Unable to initialize save directory +D:\diablo97\pfile.cpp +pszDir +myplr >= 0 && myplr < MAX_PLRS +xrgyrkj1 +Unable to get save directory +\single_%d.sv +\dlinfo_%d.drv +dwBufSize >= MAX_PATH +pszBuf +dwBytes == dwSize +pPack +hsArchive +heroinfo->name[0] +Unable to load character +Unable to open archive +dwChar != MAX_CHARACTERS +Unable to read to save file archive +Unable to write to save file archive +! GetPermSaveNames(dwIndex,szPerm) +bResult +dwBytes == *pdwLen +Unable to read save file +Unable to open save file +Unable to open save file archive +pdwLen +pData +PlrGFX\%s\%s\%s%s.CL2 +PLR:2 +%c%c%c +D:\diablo97\PLAYER.CPP +(DWORD) pPlayer->_pClass <= NUM_CLASSES +LoadPlrGFX: illegal player %d +InitPlayerGFX: illegal player %d +! plr[pnum]._pNData +InitPlrGFXMem: illegal player %d +hsFile +FreePlayerGFX: illegal player %d +NewPlrAnim: illegal player %d +ClearPlrPVars: illegal player %d +SetPlrAnims: illegal player %d +CreatePlayer: illegal player %d +NextPlrLevel: illegal player %d +AddPlrExperience: illegal player %d +InitPlayer: illegal player %d +PlrDirOK: illegal player %d +SetPlayerOld: illegal player %d +FixPlayerLocation: illegal player %d +StartStand: illegal player %d +StartWalkStand: illegal player %d +PM_ChangeLightOff: illegal player %d +PM_ChangeOffset: illegal player %d +StartWalk: illegal player %d +StartWalk2: illegal player %d +StartWalk3: illegal player %d +StartAttack: illegal player %d +StartRangeAttack: illegal player %d +StartPlrBlock: illegal player %d +StartSpell: illegal player %d +FixPlrWalkTags: illegal player %d +StartPlrHit: illegal player %d +StartPlayerKill: illegal player %d +PlrDeadItem: illegal player %d +DropHalfPlayersGold: illegal player %d +StripTopGold: illegal player %d +StartNewLvl +StartNewLvl: illegal player %d +RestartTownLvl: illegal player %d +PM_DoWalk: illegal player %d +PM_DoWalk2: illegal player %d +PM_DoWalk3: illegal player %d +WeaponDur: illegal player %d +PlrHitMonst: illegal player %d +PlrHitMonst: illegal monster %d +PlrHitPlr: illegal attacking player %d +PlrHitPlr: illegal target player %d +PM_DoAttack: illegal player %d +PM_DoRangeAttack: illegal player %d +ShieldDur: illegal player %d +PM_DoBlock: illegal player %d +PM_DoSpell: illegal player %d +PM_DoGotHit: illegal player %d +ArmorDur: illegal player %d +PM_DoDeath: illegal player %d +CheckNewPath: illegal player %d +PlrDeathModeOK: illegal player %d +ValidatePlayer: illegal player %d +ProcessPlayers: illegal player %d +ClrPlrPath: illegal player %d +MakePlrPath: illegal player %d +CheckPlrSpell: illegal player %d +plr[p]._pAnimData +SyncPlrAnim +SyncPlrAnim: illegal player %d +SyncInitPlr: illegal player %d +CheckStats: illegal player %d +ModifyPlrStr: illegal player %d +ModifyPlrMag: illegal player %d +ModifyPlrDex: illegal player %d +ModifyPlrVit: illegal player %d +SetPlayerHitPoints: illegal player %d +SetPlrStr: illegal player %d +SetPlrMag: illegal player %d +SetPlrDex: illegal player %d +SetPlrVit: illegal player %d +InitDungMsgs: illegal player %d +PlayDungMsgs: illegal player %d +D:\diablo97\plrmsg.cpp +pszMsg +strlen(pMsg->str) < sizeof(pMsg->str) +%s (lvl %d): %s +strlen(pszStr) < MAX_SEND_STR_LEN +strlen(plr[pnum]._pName) < PLR_NAME_LEN +D:\diablo97\portal.cpp +(DWORD)portalindex < MAXPORTAL +Unholy Altar +A Dark Passage +Maze +King Leoric's Tomb +The Jersey's Jersey +Cornerstone of the World +Wandering Trader +Little Girl +Farmer's Orchard +Grave Matters +Archbishop Lazarus +The Chamber of Bone +Poisoned Water Supply +The Curse of King Leoric +Valor +Halls of the Blind +Ogden's Sign +Diablo +Gharbad The Weak +The Magic Rock +Levels\L3Data\L3pwater.pal +To %s +D:\diablo97\Quests.cpp +(DWORD)i < MAXQUESTS +(DWORD)m < MAXMONSTERS +(DWORD)q < MAXQUESTS +(DWORD)(rh + y - 1) < MDMAXY +(DWORD)(rw + x - 1) < MDMAXX +Levels\L4Data\Warlord2.DUN +Levels\L2Data\Bonestr1.DUN +(DWORD)(y+rh-1) < MDMAXY +(DWORD)(x+rw-1) < MDMAXX +Levels\L2Data\Blind1.DUN +Levels\L3Data\L3pfoul.pal +Close Quest Log +Quest Log +quests[q]._qactive != QUEST_NOTAVAIL +REGISTRATION_BLOCK +quitting +changing levels +casting a spell +attacking (melee) +talking +healing +stoned +charging +delaying +attacking (special ranged) +standing (special) +attacking (ranged) +fading out +fading in +attacking (special) +dying +getting hit +attacking +walking (3) +walking (2) +walking (1) +standing +D:\diablo97\SCROLLRT.CPP +missileactive[i] < MAXMISSILES && missileactive[i] >= 0 +bItem <= MAXITEMS && bItem >= 0 +pDeadGuy->_deadData[dd] != NULL +(sy-1) < MAXDUNY +sy < MAXDUNY +sx < MAXDUNX +bv < MAXOBJECTS && bv >= 0 +object[bv]._oAnimData +sgdwCursWdt * sgdwCursHgt < sizeof sgSaveBack +! sgdwCursWdt +ysize >= 0 && ysize <= 480 +! (dwWdt & 3) +! (dwX & 3) +E(;)I7?7EAI-N3O+Y5 +N"C#N*C+N.#+*3++132+;3 +Archbishop Lazarus' Lair +Bone Chamber +Skeleton King's Lair +ObjIndex: Active object not found at (%d,%d) +D:\diablo97\SetMaps.cpp +Levels\L1Data\SklKng2.DUN +Levels\L1Data\SklKng1.DUN +Levels\L2Data\L2_2.pal +Levels\L2Data\Bonecha1.DUN +Levels\L2Data\Bonecha2.DUN +Levels\L1Data\L1_5.pal +Levels\L1Data\Lv1MazeB.DUN +Levels\L1Data\Lv1MazeA.DUN +Levels\L3Data\Foulwatr.DUN +Levels\L1Data\L1_2.pal +Levels\L1Data\Vile2.DUN +Levels\L1Data\Vile1.DUN +Music\Dintro.wav +Music\DLvlF.wav +Music\DLvlE.wav +Music\DLvlD.wav +Music\DLvlC.wav +Music\DLvlB.wav +Music\DLvlA.wav +Music\DTowne.wav +D:\diablo97\SOUND.CPP +pDSB +pSnd +Invalid sound format on file %s +sglpDS +! sglpDS || bSuccess +! sglpDS +DirectSoundCreate +dsound.dll +(DWORD) nTrack < NUM_MUSIC +lVolume <= VOLUME_MAX +lVolume >= VOLUME_MIN +Rune of Immolation +Rune of Nova +Rune of Light +Search +Ring of Fire +Berserk +Reflect +Warp +Immolation +Lightning Wall +the Jester +the Magi +Mana +Bone Spirit +Blood Star +Heal Other +Telekinesis +Resurrect +Holy Bolt +Charged Bolt +Elemental +Trap Disarm +Staff Recharge +Item Repair +Etherealize +Apocalypse +Teleport +Blood Boil +Invisibility +Nova +Blood Ritual +Doom Serpents +Flame Wave +Chain Lightning +Fireball +Mana Shield +Phasing +Infravision +Stone Curse +Fire Wall +Identify +Flash +Healing +Firebolt +Wirt +Gillian +Adria +Farnham +Cain +Ogden +Pepin +Griswold +Data\TextSlid.CEL +Data\PentSpn2.CEL +Data\TextBox2.CEL +! pSTextBoxCels +D:\diablo97\stores.cpp +Leave the shop +Repair items +Sell items +Buy premium items +Buy basic items +Talk to Griswold +Would you like to: +Blacksmith's shop +Welcome to the +Unique Item +No required attributes +Indestructible, +Dur: %i/%i, +Armor: %i +Damage: %i-%i +Back +I have these items for sale : Your gold : %i +I have these premium items for sale : Your gold : %i +Which item is for sale? Your gold : %i +You have nothing I want. Your gold : %i +Repair which item? Your gold : %i +You have nothing to repair. Your gold : %i +itm->_iMaxDur > 0 +Leave the shack +Recharge staves +Buy items +Talk to Adria +Witch's shack +Recharge which item? Your gold : %i +You have nothing to recharge. Your gold : %i +You do not have enough gold +You do not have enough room in inventory +Do we have a deal? +Are you sure you want to buy this item? +Are you sure you want to identify this item? +Are you sure you want to recharge this item? +Are you sure you want to sell this item? +Are you sure you want to repair this item? +Say goodbye +What have you got? +just to take a look. +but it will cost 50 gold +I have something for sale, +Talk to Wirt +Wirt the Peg-legged boy +Leave +I have this item for sale : Your gold : %i +Leave Healer's home +Talk to Pepin +Healer's home +Identify an item +Talk to Cain +The Town Elder +Identify which item? Your gold : %i +You have nothing to identify. Your gold : %i +Done +This item is: +Gossip +Talk to %s +Leave the tavern +Talk to Ogden +Rising Sun +Talk to Gillian +Say Goodbye +Talk to Farnham +Farnham the Drunk +D:\diablo97\sync.cpp +dwMaxLen <= 0xffff +(DWORD) sgnSyncPInv < NUM_INVLOC +wLen == 0 +bad sync command + Ahh, the story of our King, is it? The tragic fall of Leoric was a harsh blow to this land. The people always loved the King, and now they live in mortal fear of him. The question that I keep asking myself is how he could have fallen so far from the Light, as Leoric had always been the holiest of men. Only the vilest powers of Hell could so utterly destroy a man from within... | +The village needs your help, good master! Some months ago King Leoric's son, Prince Albrecht, was kidnapped. The King went into a rage and scoured the village for his missing child. With each passing day, Leoric seemed to slip deeper into madness. He sought to blame innocent townsfolk for the boy's disappearance and had them brutally executed. Less than half of us survived his insanity... +The King's Knights and Priests tried to placate him, but he turned against them and sadly, they were forced to kill him. With his dying breath the King called down a terrible curse upon his former followers. He vowed that they would serve him in darkness forever... +This is where things take an even darker twist than I thought possible! Our former King has risen from his eternal sleep and now commands a legion of undead minions within the Labyrinth. His body was buried in a tomb three levels beneath the Cathedral. Please, good master, put his soul at ease by destroying his now cursed form... | +As I told you, good master, the King was entombed three levels below. He's down there, waiting in the putrid darkness for his chance to destroy this land... | +The curse of our King has passed, but I fear that it was only part of a greater evil at work. However, we may yet be saved from the darkness that consumes our land, for your victory is a good omen. May Light guide you on your way, good master. | +The loss of his son was too much for King Leoric. I did what I could to ease his madness, but in the end it overcame him. A black curse has hung over this kingdom from that day forward, but perhaps if you were to free his spirit from his earthly prison, the curse would be lifted... | +I don't like to think about how the King died. I like to remember him for the kind and just ruler that he was. His death was so sad and seemed very wrong, somehow. | +I made many of the weapons and most of the armor that King Leoric used to outfit his knights. I even crafted a huge two-handed sword of the finest mithril for him, as well as a field crown to match. I still cannot believe how he died, but it must have been some sinister force that drove him insane! | +I don't care about that. Listen, no skeleton is gonna be MY king. Leoric is King. King, so you hear me? HAIL TO THE KING! | +The dead who walk among the living follow the cursed King. He holds the power to raise yet more warriors for an ever growing army of the undead. If you do not stop his reign, he will surely march across this land and slay all who still live here. | +Look, I'm running a business here. I don't sell information, and I don't care about some King that's been dead longer than I've been alive. If you need something to use against this King of the undead, then I can help you out... | +The warmth of life has entered my tomb. Prepare yourself, mortal, to serve my Master for eternity! | +I see that this strange behavior puzzles you as well. I would surmise that since many demons fear the light of the sun and believe that it holds great power, it may be that the rising sun depicted on the sign you speak of has led them to believe that it too holds some arcane powers. Hmm, perhaps they are not all as smart as we had feared... | +Master, I have a strange experience to relate. I know that you have a great knowledge of those monstrosities that inhabit the labyrinth, and this is something that I cannot understand for the very life of me... I was awakened during the night by a scraping sound just outside of my tavern. When I looked out from my bedroom, I saw the shapes of small demon-like creatures in the inn yard. After a short time, they ran off, but not before stealing the sign to my inn. I don't know why the demons would steal my sign but leave my family in peace... 'tis strange, no? | +Oh, you didn't have to bring back my sign, but I suppose that it does save me the expense of having another one made. Well, let me see, what could I give you as a fee for finding it? Hmmm, what have we here... ah, yes! This cap was left in one of the rooms by a magician who stayed here some time ago. Perhaps it may be of some value to you. | +My goodness, demons running about the village at night, pillaging our homes - is nothing sacred? I hope that Ogden and Garda are all right. I suppose that they would come to see me if they were hurt... | +Oh my! Is that where the sign went? My Grandmother and I must have slept right through the whole thing. Thank the Light that those monsters didn't attack the inn. | +Demons stole Ogden's sign, you say? That doesn't sound much like the atrocities I've heard of - or seen. +Demons are concerned with ripping out your heart, not your signpost. | +You know what I think? Somebody took that sign, and they gonna want lots of money for it. If I was Ogden... and I'm not, but if I was... I'd just buy a new sign with some pretty drawing on it. Maybe a nice mug of ale or a piece of cheese... | +No mortal can truly understand the mind of the demon. +Never let their erratic actions confuse you, as that too may be their plan. | +What - is he saying I took that? I suppose that Griswold is on his side, too. +Look, I got over simple sign stealing months ago. You can't turn a profit on a piece of wood. | +Hey - You that one that kill all! You get me Magic Banner or we attack! You no leave with life! You kill big uglies and give back Magic. Go past corner and door, find uglies. You give, you go! | +You kill uglies, get banner. You bring to me, or else... | +You give! Yes, good! Go now, we strong. We kill all with big Magic! | +This does not bode well, for it confirms my darkest fears. While I did not allow myself to believe the ancient legends, I cannot deny them now. Perhaps the time has come to reveal who I am. +My true name is Deckard Cain the Elder, and I am the last descendant of an ancient Brotherhood that was dedicated to safeguarding the secrets of a timeless evil. An evil that quite obviously has now been released. +The Archbishop Lazarus, once King Leoric's most trusted advisor, led a party of simple townsfolk into the Labyrinth to find the King's missing son, Albrecht. Quite some time passed before they returned, and only a few of them escaped with their lives. +Curse me for a fool! I should have suspected his veiled treachery then. It must have been Lazarus himself who kidnapped Albrecht and has since hidden him within the Labyrinth. I do not understand why the Archbishop turned to the darkness, or what his interest is in the child, unless he means to sacrifice him to his dark masters! +That must be what he has planned! The survivors of his 'rescue party' say that Lazarus was last seen running into the deepest bowels of the labyrinth. You must hurry and save the prince from the sacrificial blade of this demented fiend! | +You must hurry and rescue Albrecht from the hands of Lazarus. The prince and the people of this kingdom are counting on you! | +Your story is quite grim, my friend. Lazarus will surely burn in Hell for his horrific deed. The boy that you describe is not our prince, but I believe that Albrecht may yet be in danger. The symbol of power that you speak of must be a portal in the very heart of the labyrinth. +Know this, my friend - The evil that you move against is the dark Lord of Terror. He is known to mortal men as Diablo. It was he who was imprisoned within the Labyrinth many centuries ago and I fear that he seeks to once again sow chaos in the realm of mankind. You must venture through the portal and destroy Diablo before it is too late! | +Lazarus was the Archbishop who led many of the townspeople into the labyrinth. I lost many good friends that day, and Lazarus never returned. I suppose he was killed along with most of the others. If you would do me a favor, good master - please do not talk to Farnham about that day. | +I was shocked when I heard of what the townspeople were planning to do that night. I thought that of all people, Lazarus would have had more sense than that. He was an Archbishop, and always seemed to care so much for the townsfolk of Tristram. So many were injured, I could not save them all... | +I remember Lazarus as being a very kind and giving man. He spoke at my mother's funeral, and was supportive of my grandmother and myself in a very troubled time. I pray every night that somehow, he is still alive and safe. | +I was there when Lazarus led us into the labyrinth. He spoke of holy retribution, but when we started fighting those hellspawn, he did not so much as lift his mace against them. He just ran deeper into the dim, endless chambers that were filled with the servants of darkness! | +They stab, then bite, then they're all around you. Liar! LIAR! They're all dead! Dead! Do you hear me? They just keep falling and falling... their blood spilling out all over the floor... all his fault... | +I did not know this Lazarus of whom you speak, but I do sense a great conflict within his being. He poses a great danger, and will stop at nothing to serve the powers of darkness which have claimed him as theirs. | +Yes, the righteous Lazarus, who was sooo effective against those monsters down there. Didn't help save my leg, did it? Look, I'll give you a free piece of advice. Ask Farnham, he was there. | +Abandon your foolish quest. All that awaits you is the wrath of my Master! You are too late to save the child. Now you will join him in Hell! | +Hmm, I don't know what I can really tell you about this that will be of any help. The water that fills our wells comes from an underground spring. I have heard of a tunnel that leads to a great lake - perhaps they are one and the same. Unfortunately, I do not know what would cause our water supply to be tainted. | +I have always tried to keep a large supply of foodstuffs and drink in our storage cellar, but with the entire town having no source of fresh water, even our stores will soon run dry. +Please, do what you can or I don't know what we will do. | +I'm glad I caught up to you in time! Our wells have become brackish and stagnant and some of the townspeople have become ill drinking from them. Our reserves of fresh water are quickly running dry. I believe that there is a passage that leads to the springs that serve our town. Please find what has caused this calamity, or we all will surely perish. | +Please, you must hurry. Every hour that passes brings us closer to having no water to drink. +We cannot survive for long without your help. | +What's that you say - the mere presence of the demons had caused the water to become tainted? Oh, truly a great evil lurks beneath our town, but your perseverance and courage gives us hope. Please take this ring - perhaps it will aid you in the destruction of such vile creatures. | +My grandmother is very weak, and Garda says that we cannot drink the water from the wells. Please, can you do something to help us? | +Pepin has told you the truth. We will need fresh water badly, and soon. I have tried to clear one of the smaller wells, but it reeks of stagnant filth. It must be getting clogged at the source. | +You drink water? | +The people of Tristram will die if you cannot restore fresh water to their wells. +Know this - demons are at the heart of this matter, but they remain ignorant of what they have spawned. | +For once, I'm with you. My business runs dry - so to speak - if I have no market to sell to. You better find out what is going on, and soon! | +A book that speaks of a chamber of human bones? Well, a Chamber of Bone is mentioned in certain archaic writings that I studied in the libraries of the East. These tomes inferred that when the Lords of the underworld desired to protect great treasures, they would create domains where those who died in the attempt to steal that treasure would be forever bound to defend it. A twisted, but strangely fitting, end? | +I am afraid that I don't know anything about that, good master. Cain has many books that may be of some help. | +This sounds like a very dangerous place. If you venture there, please take great care. | +I am afraid that I haven't heard anything about that. Perhaps Cain the Storyteller could be of some help. | +I know nothing of this place, but you may try asking Cain. He talks about many things, and it would not surprise me if he had some answers to your question. | +Okay, so listen. There's this chamber of wood, see. And his wife, you know - her - tells the tree... cause you gotta wait. Then I says, that might work against him, but if you think I'm gonna PAY for this... you... uh... yeah. | +You will become an eternal servant of the dark lords should you perish within this cursed domain. +Enter the Chamber of Bone at your own peril. | +A vast and mysterious treasure, you say? Maybe I could be interested in picking up a few things from you... or better yet, don't you need some rare and expensive supplies to get you through this ordeal? | +It seems that the Archbishop Lazarus goaded many of the townsmen into venturing into the Labyrinth to find the King's missing son. He played upon their fears and whipped them into a frenzied mob. None of them were prepared for what lay within the cold earth... Lazarus abandoned them down there - left in the clutches of unspeakable horrors - to die. | +Yes, Farnham has mumbled something about a hulking brute who wielded a fierce weapon. I believe he called him a butcher. | +By the Light, I know of this vile demon. There were many that bore the scars of his wrath upon their bodies when the few survivors of the charge led by Lazarus crawled from the Cathedral. I don't know what he used to slice open his victims, but it could not have been of this world. It left wounds festering with disease and even I found them almost impossible to treat. Beware if you plan to battle this fiend... | +When Farnham said something about a butcher killing people, I immediately discounted it. But since you brought it up, maybe it is true. | +I saw what Farnham calls the Butcher as it swathed a path through the bodies of my friends. He swung a cleaver as large as an axe, hewing limbs and cutting down brave men where they stood. I was separated from the fray by a host of small screeching demons and somehow found the stairway leading out. I never saw that hideous beast again, but his blood-stained visage haunts me to this day. | +Big! Big cleaver killing all my friends. Couldn't stop him, had to run away, couldn't save them. Trapped in a room with so many bodies... so many friends... NOOOOOOOOOO! | +The Butcher is a sadistic creature that delights in the torture and pain of others. You have seen his handiwork in the drunkard Farnham. His destruction will do much to ensure the safety of this village. | +I know more than you'd think about that grisly fiend. His little friends got a hold of me and managed to get my leg before Griswold pulled me out of that hole. +I'll put it bluntly - kill him before he kills you and adds your corpse to his collection. | +Please, listen to me. The Archbishop Lazarus, he led us down here to find the lost prince. The bastard led us into a trap! Now everyone is dead... killed by a demon he called the Butcher. Avenge us! Find this Butcher and slay him so that our souls may finally rest... | +You recite an interesting rhyme written in a style that reminds me of other works. Let me think now - what was it? +...Darkness shrouds the Hidden. Eyes glowing unseen with only the sounds of razor claws briefly scraping to torment those poor souls who have been made sightless for all eternity. The prison for those so damned is named the Halls of the Blind... | +I never much cared for poetry. Occasionally, I had cause to hire minstrels when the inn was doing well, but that seems like such a long time ago now. +What? Oh, yes... uh, well, I suppose you could see what someone else knows. | +This does seem familiar, somehow. I seem to recall reading something very much like that poem while researching the history of demonic afflictions. It spoke of a place of great evil that... wait - you're not going there are you? | +If you have questions about blindness, you should talk to Pepin. I know that he gave my grandmother a potion that helped clear her vision, so maybe he can help you, too. | +I am afraid that I have neither heard nor seen a place that matches your vivid description, my friend. Perhaps Cain the Storyteller could be of some help. | +Look here... that's pretty funny, huh? Get it? Blind - look here? | +This is a place of great anguish and terror, and so serves its master well. +Tread carefully or you may yourself be staying much longer than you had anticipated. | +Lets see, am I selling you something? No. Are you giving me money to tell you about this? No. Are you now leaving and going to talk to the storyteller who lives for this kind of thing? Yes. | +You claim to have spoken with Lachdanan? He was a great hero during his life. Lachdanan was an honorable and just man who served his King faithfully for years. But of course, you already know that. +Of those who were caught within the grasp of the King's Curse, Lachdanan would be the least likely to submit to the darkness without a fight, so I suppose that your story could be true. If I were in your place, my friend, I would find a way to release him from his torture. | +You speak of a brave warrior long dead! I'll have no such talk of speaking with departed souls in my inn yard, thank you very much. | +A golden elixir, you say. I have never concocted a potion of that color before, so I can't tell you how it would effect you if you were to try to drink it. As your healer, I strongly advise that should you find such an elixir, do as Lachdanan asks and DO NOT try to use it. | +I've never heard of a Lachdanan before. I'm sorry, but I don't think that I can be of much help to you. | +If it is actually Lachdanan that you have met, then I would advise that you aid him. I dealt with him on several occasions and found him to be honest and loyal in nature. The curse that fell upon the followers of King Leoric would fall especially hard upon him. | + Lachdanan is dead. Everybody knows that, and you can't fool me into thinking any other way. You can't talk to the dead. I know! | +You may meet people who are trapped within the Labyrinth, such as Lachdanan. +I sense in him honor and great guilt. Aid him, and you aid all of Tristram. | +Wait, let me guess. Cain was swallowed up in a gigantic fissure that opened beneath him. He was incinerated in a ball of hellfire, and can't answer your questions anymore. Oh, that isn't what happened? Then I guess you'll be buying something or you'll be on your way. | +Please, don't kill me, just hear me out. I was once Captain of King Leoric's Knights, upholding the laws of this land with justice and honor. Then his dark Curse fell upon us for the role we played in his tragic death. As my fellow Knights succumbed to their twisted fate, I fled from the King's burial chamber, searching for some way to free myself from the Curse. I failed... +I have heard of a Golden Elixir that could lift the Curse and allow my soul to rest, but I have been unable to find it. My strength now wanes, and with it the last of my humanity as well. Please aid me and find the Elixir. I will repay your efforts - I swear upon my honor. | +You have not found the Golden Elixir. I fear that I am doomed for eternity. Please, keep trying... | +You have saved my soul from damnation, and for that I am in your debt. If there is ever a way that I can repay you from beyond the grave I will find it, but for now - take my helm. On the journey I am about to take I will have little use for it. May it protect you against the dark powers below. Go with the Light, my friend... | +Griswold speaks of The Anvil of Fury - a legendary artifact long searched for, but never found. Crafted from the metallic bones of the Razor Pit demons, the Anvil of Fury was smelt around the skulls of the five most powerful magi of the underworld. Carved with runes of power and chaos, any weapon or armor forged upon this Anvil will be immersed into the realm of Chaos, imbedding it with magical properties. It is said that the unpredictable nature of Chaos makes it difficult to know what the outcome of this smithing will be... | +Don't you think that Griswold would be a better person to ask about this? He's quite handy, you know. | +If you had been looking for information on the Pestle of Curing or the Silver Chalice of Purification, I could have assisted you, my friend. However, in this matter, you would be better served to speak to either Griswold or Cain. | +Griswold's father used to tell some of us when we were growing up about a giant anvil that was used to make mighty weapons. He said that when a hammer was struck upon this anvil, the ground would shake with a great fury. Whenever the earth moves, I always remember that story. | +Greetings! It's always a pleasure to see one of my best customers! I know that you have been venturing deeper into the Labyrinth, and there is a story I was told that you may find worth the time to listen to... +One of the men who returned from the Labyrinth told me about a mystic anvil that he came across during his escape. His description reminded me of legends I had heard in my youth about the burning Hellforge where powerful weapons of magic are crafted. The legend had it that deep within the Hellforge rested the Anvil of Fury! This Anvil contained within it the very essence of the demonic underworld... +It is said that any weapon crafted upon the burning Anvil is imbued with great power. If this anvil is indeed the Anvil of Fury, I may be able to make you a weapon capable of defeating even the darkest lord of Hell! +Find the Anvil for me, and I'll get to work! | +Nothing yet, eh? Well, keep searching. A weapon forged upon the Anvil could be your best hope, and I am sure that I can make you one of legendary proportions. | +I can hardly believe it! This is the Anvil of Fury - good work, my friend. Now we'll show those bastards that there are no weapons in Hell more deadly than those made by men! Take this and may Light protect you. | +Griswold can't sell his anvil. What will he do then? And I'd be angry too if someone took my anvil! | +There are many artifacts within the Labyrinth that hold powers beyond the comprehension of mortals. Some of these hold fantastic power that can be used by either the Light or the Darkness. Securing the Anvil from below could shift the course of the Sin War towards the Light. | +If you were to find this artifact for Griswold, it could put a serious damper on my business here. Awwww, you'll never find it. | +The Gateway of Blood and the Halls of Fire are landmarks of mystic origin. Wherever this book you read from resides it is surely a place of great power. +Legends speak of a pedestal that is carved from obsidian stone and has a pool of boiling blood atop its bone encrusted surface. There are also allusions to Stones of Blood that will open a door that guards an ancient treasure... +The nature of this treasure is shrouded in speculation, my friend, but it is said that the ancient hero Arkaine placed the holy armor Valor in a secret vault. Arkaine was the first mortal to turn the tide of the Sin War and chase the legions of darkness back to the Burning Hells. +Just before Arkaine died, his armor was hidden away in a secret vault. It is said that when this holy armor is again needed, a hero will arise to don Valor once more. Perhaps you are that hero... | +Every child hears the story of the warrior Arkaine and his mystic armor known as Valor. If you could find its resting place, you would be well protected against the evil in the Labyrinth. | +Hmm... it sounds like something I should remember, but I've been so busy learning new cures and creating better elixirs that I must have forgotten. Sorry... | +The story of the magic armor called Valor is something I often heard the boys talk about. You had better ask one of the men in the village. | +The armor known as Valor could be what tips the scales in your favor. I will tell you that many have looked for it - including myself. Arkaine hid it well, my friend, and it will take more than a bit of luck to unlock the secrets that have kept it concealed oh, lo these many years. | +Zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz... | +Should you find these Stones of Blood, use them carefully. +The way is fraught with danger and your only hope rests within your self trust. | +You intend to find the armor known as Valor? +No one has ever figured out where Arkaine stashed the stuff, and if my contacts couldn't find it, I seriously doubt you ever will either. | +I know of only one legend that speaks of such a warrior as you describe. His story is found within the ancient chronicles of the Sin War... +Stained by a thousand years of war, blood and death, the Warlord of Blood stands upon a mountain of his tattered victims. His dark blade screams a black curse to the living; a tortured invitation to any who would stand before this Executioner of Hell. +It is also written that although he was once a mortal who fought beside the Legion of Darkness during the Sin War, he lost his humanity to his insatiable hunger for blood. | +I am afraid that I haven't heard anything about such a vicious warrior, good master. I hope that you do not have to fight him, for he sounds extremely dangerous. | +Cain would be able to tell you much more about something like this than I would ever wish to know. | +If you are to battle such a fierce opponent, may Light be your guide and your defender. I will keep you in my thoughts. | +Dark and wicked legends surrounds the one Warlord of Blood. Be well prepared, my friend, for he shows no mercy or quarter. | +Always you gotta talk about Blood? What about flowers, and sunshine, and that pretty girl that brings the drinks. Listen here, friend - you're obsessive, you know that? | +His prowess with the blade is awesome, and he has lived for thousands of years knowing only warfare. I am sorry... I can not see if you will defeat him. | +I haven't ever dealt with this Warlord you speak of, but he sounds like he's going through a lot of swords. Wouldn't mind supplying his armies... | +My blade sings for your blood, mortal, and by my dark masters it shall not be denied. | +Griswold speaks of the Heaven Stone that was destined for the enclave located in the east. It was being taken there for further study. This stone glowed with an energy that somehow granted vision beyond that which a normal man could possess. I do not know what secrets it holds, my friend, but finding this stone would certainly prove most valuable. | +The caravan stopped here to take on some supplies for their journey to the east. I sold them quite an array of fresh fruits and some excellent sweetbreads that Garda has just finished baking. Shame what happened to them... | +I don't know what it is that they thought they could see with that rock, but I will say this. If rocks are falling from the sky, you had better be careful! | +Well, a caravan of some very important people did stop here, but that was quite a while ago. They had strange accents and were starting on a long journey, as I recall. +I don't see how you could hope to find anything that they would have been carrying. | +Stay for a moment - I have a story you might find interesting. A caravan that was bound for the eastern kingdoms passed through here some time ago. It was supposedly carrying a piece of the heavens that had fallen to earth! The caravan was ambushed by cloaked riders just north of here along the roadway. I searched the wreckage for this sky rock, but it was nowhere to be found. If you should find it, I believe that I can fashion something useful from it. | +I am still waiting for you to bring me that stone from the heavens. I know that I can make something powerful out of it. | +Let me see that - aye... aye, it is as I believed. Give me a moment... +Ah, Here you are. I arranged pieces of the stone within a silver ring that my father left me. I hope it serves you well. | +I used to have a nice ring; it was a really expensive one, with blue and green and red and silver. Don't remember what happened to it, though. I really miss that ring... | +The Heaven Stone is very powerful, and were it any but Griswold who bid you find it, I would prevent it. He will harness its powers and its use will be for the good of us all. | +If anyone can make something out of that rock, Griswold can. He knows what he is doing, and as much as I try to steal his customers, I respect the quality of his work. | +The witch Adria seeks a black mushroom? I know as much about Black Mushrooms as I do about Red Herrings. Perhaps Pepin the Healer could tell you more, but this is something that cannot be found in any of my stories or books. | +Let me just say this. Both Garda and I would never, EVER serve black mushrooms to our honored guests. If Adria wants some mushrooms in her stew, then that is her business, but I can't help you find any. Black mushrooms... disgusting! | +The witch told me that you were searching for the brain of a demon to assist me in creating my elixir. It should be of great value to the many who are injured by those foul beasts, if I can just unlock the secrets I suspect that its alchemy holds. If you can remove the brain of a demon when you kill it, I would be grateful if you could bring it to me. | +Excellent, this is just what I had in mind. I was able to finish the elixir without this, but it can't hurt to have this to study. Would you please carry this to the witch? I believe that she is expecting it. | +I think Ogden might have some mushrooms in the storage cellar. Why don't you ask him? | +If Adria doesn't have one of these, you can bet that's a rare thing indeed. I can offer you no more help than that, but it sounds like... a huge, gargantuan, swollen, bloated mushroom! Well, good hunting, I suppose. | +Ogden mixes a MEAN black mushroom, but I get sick if I drink that. Listen, listen... here's the secret - moderation is the key! | +What do we have here? Interesting, it looks like a book of reagents. Keep your eyes open for a black mushroom. It should be fairly large and easy to identify. If you find it, bring it to me, won't you? | +It's a big, black mushroom that I need. Now run off and get it for me so that I can use it for a special concoction that I am working on. | +Yes, this will be perfect for a brew that I am creating. By the way, the healer is looking for the brain of some demon or another so he can treat those who have been afflicted by their poisonous venom. I believe that he intends to make an elixir from it. If you help him find what he needs, please see if you can get a sample of the elixir for me. | +Why have you brought that here? I have no need for a demon's brain at this time. I do need some of the elixir that the Healer is working on. He needs that grotesque organ that you are holding, and then bring me the elixir. Simple when you think about it, isn't it? | +What? Now you bring me that elixir from the healer? I was able to finish my brew without it. Why don't you just keep it... | +I don't have any mushrooms of any size or color for sale. How about something a bit more useful? | +So, the legend of the Map is real. Even I never truly believed any of it! I suppose it is time that I told you the truth about who I am, my friend. You see, I am not all that I seem... +My true name is Deckard Cain the Elder, and I am the last descendant of an ancient Brotherhood that was dedicated to keeping and safeguarding the secrets of a timeless evil. An evil that quite obviously has now been released... +The evil that you move against is the dark Lord of Terror - known to mortal men as Diablo. It was he who was imprisoned within the Labyrinth many centuries ago. The Map that you hold now was created ages ago to mark the time when Diablo would rise again from his imprisonment. When the two stars on that map align, Diablo will be at the height of his power. He will be all but invincible... +You are now in a race against time, my friend! Find Diablo and destroy him before the stars align, for we may never have a chance to rid the world of his evil again! | +Our time is running short! I sense his dark power building and only you can stop him from attaining his full might. | +I am sure that you tried your best, but I fear that even your strength and will may not be enough. Diablo is now at the height of his earthly power, and you will need all your courage and strength to defeat him. May the Light protect and guide you, my friend. I will help in any way that I am able. | +If the witch can't help you and suggests you see Cain, what makes you think that I would know anything? It sounds like this is a very serious matter. You should hurry along and see the storyteller as Adria suggests. | +I can't make much of the writing on this map, but perhaps Adria or Cain could help you decipher what this refers to. +I can see that it is a map of the stars in our sky, but any more than that is beyond my talents. | +The best person to ask about that sort of thing would be our storyteller. +Cain is very knowledgeable about ancient writings, and that is easily the oldest looking piece of paper that I have ever seen. | +I have never seen a map of this sort before. Where'd you get it? Although I have no idea how to read this, Cain or Adria may be able to provide the answers that you seek. | +Listen here, come close. I don't know if you know what I know, but you have really got somethin' here. That's a map. | +Oh, I'm afraid this does not bode well at all. This map of the stars portends great disaster, but its secrets are not mine to tell. The time has come for you to have a very serious conversation with the Storyteller... | +I've been looking for a map, but that certainly isn't it. You should show that to Adria - she can probably tell you what it is. I'll say one thing; it looks old, and old usually means valuable. | +Pleeeease, no hurt. No Kill. Keep alive and next time good bring to you. | +Something for you I am making. Again, not kill Gharbad. Live and give good. +You take this as proof I keep word... | +Nothing yet! Almost done. +Very powerful, very strong. Live! Live! +No pain and promise I keep! | +This too good for you. Very Powerful! You want - you take! | +What?! Why are you here? All these interruptions are enough to make one insane. Here, take this and leave me to my work. Trouble me no more! | +Arrrrgh! Your curiosity will be the death of you!!! | +Hello, my friend. Stay awhile and listen... | +While you are venturing deeper into the Labyrinth you may find tomes of great knowledge hidden there. +Read them carefully for they can tell you things that even I cannot. | +I know of many myths and legends that may contain answers to questions that may arise in your journeys into the Labyrinth. If you come across challenges and questions to which you seek knowledge, seek me out and I will tell you what I can. | +Griswold - a man of great action and great courage. I bet he never told you about the time he went into the Labyrinth to save Wirt, did he? He knows his fair share of the dangers to be found there, but then again - so do you. He is a skilled craftsman, and if he claims to be able to help you in any way, you can count on his honesty and his skill. | +Ogden has owned and run the Rising Sun Inn and Tavern for almost four years now. He purchased it just a few short months before everything here went to hell. He and his wife Garda do not have the money to leave as they invested all they had in making a life for themselves here. He is a good man with a deep sense of responsibility. | +Poor Farnham. He is a disquieting reminder of the doomed assembly that entered into the Cathedral with Lazarus on that dark day. He escaped with his life, but his courage and much of his sanity were left in some dark pit. He finds comfort only at the bottom of his tankard nowadays, but there are occasional bits of truth buried within his constant ramblings. | +The witch, Adria, is an anomaly here in Tristram. She arrived shortly after the Cathedral was desecrated while most everyone else was fleeing. She had a small hut constructed at the edge of town, seemingly overnight, and has access to many strange and arcane artifacts and tomes of knowledge that even I have never seen before. | +The story of Wirt is a frightening and tragic one. He was taken from the arms of his mother and dragged into the labyrinth by the small, foul demons that wield wicked spears. There were many other children taken that day, including the son of King Leoric. The Knights of the palace went below, but never returned. The Blacksmith found the boy, but only after the foul beasts had begun to torture him for their sadistic pleasures. | +Ah, Pepin. I count him as a true friend - perhaps the closest I have here. He is a bit addled at times, but never a more caring or considerate soul has existed. His knowledge and skills are equaled by few, and his door is always open. | +Gillian is a fine woman. Much adored for her high spirits and her quick laugh, she holds a special place in my heart. She stays on at the tavern to support her elderly grandmother who is too sick to travel. I sometimes fear for her safety, but I know that any man in the village would rather die than see her harmed. | +Greetings, good master. Welcome to the Tavern of the Rising Sun! | +Many adventurers have graced the tables of my tavern, and ten times as many stories have been told over as much ale. The only thing that I ever heard any of them agree on was this old axiom. Perhaps it will help you. You can cut the flesh, but you must crush the bone. | +Griswold the blacksmith is extremely knowledgeable about weapons and armor. If you ever need work done on your gear, he is definitely the man to see. | +Farnham spends far too much time here, drowning his sorrows in cheap ale. I would make him leave, but he did suffer so during his time in the Labyrinth. | +Adria is wise beyond her years, but I must admit - she frightens me a little. +Well, no matter. If you ever have need to trade in items of sorcery, she maintains a strangely well-stocked hut just across the river. | +If you want to know more about the history of our village, the storyteller Cain knows quite a bit about the past. | +Wirt is a rapscallion and a little scoundrel. He was always getting into trouble, and it's no surprise what happened to him. +He probably went fooling about someplace that he shouldn't have been. I feel sorry for the boy, but I don't abide the company that he keeps. | +Pepin is a good man - and certainly the most generous in the village. He is always attending to the needs of others, but trouble of some sort or another does seem to follow him wherever he goes... | +Gillian, my Barmaid? If it were not for her sense of duty to her grand-dam, she would have fled from here long ago. +Goodness knows I begged her to leave, telling her that I would watch after the old woman, but she is too sweet and caring to have done so. | +What ails you, my friend? | +I have made a very interesting discovery. Unlike us, the creatures in the Labyrinth can heal themselves without the aid of potions or magic. If you hurt one of the monsters, make sure it is dead or it very well may regenerate itself. | +Before it was taken over by, well, whatever lurks below, the Cathedral was a place of great learning. There are many books to be found there. If you find any, you should read them all, for some may hold secrets to the workings of the Labyrinth. | +Griswold knows as much about the art of war as I do about the art of healing. He is a shrewd merchant, but his work is second to none. Oh, I suppose that may be because he is the only blacksmith left here. | +Cain is a true friend and a wise sage. He maintains a vast library and has an innate ability to discern the true nature of many things. If you ever have any questions, he is the person to go to. | +Even my skills have been unable to fully heal Farnham. Oh, I have been able to mend his body, but his mind and spirit are beyond anything I can do. | +While I use some limited forms of magic to create the potions and elixirs I store here, Adria is a true sorceress. She never seems to sleep, and she always has access to many mystic tomes and artifacts. I believe her hut may be much more than the hovel it appears to be, but I can never seem to get inside the place. | +Poor Wirt. I did all that was possible for the child, but I know he despises that wooden peg that I was forced to attach to his leg. His wounds were hideous. No one - and especially such a young child - should have to suffer the way he did. | +I really don't understand why Ogden stays here in Tristram. He suffers from a slight nervous condition, but he is an intelligent and industrious man who would do very well wherever he went. I suppose it may be the fear of the many murders that happen in the surrounding countryside, or perhaps the wishes of his wife that keep him and his family where they are. | +Ogden's barmaid is a sweet girl. Her grandmother is quite ill, and suffers from delusions. +She claims that they are visions, but I have no proof of that one way or the other. | +Good day! How may I serve you? | +My grandmother had a dream that you would come and talk to me. She has visions, you know and can see into the future. | +The woman at the edge of town is a witch! She seems nice enough, and her name, Adria, is very pleasing to the ear, but I am very afraid of her. +It would take someone quite brave, like you, to see what she is doing out there. | +Our Blacksmith is a point of pride to the people of Tristram. Not only is he a master craftsman who has won many contests within his guild, but he received praises from our King Leoric himself - may his soul rest in peace. Griswold is also a great hero; just ask Cain. | +Cain has been the storyteller of Tristram for as long as I can remember. He knows so much, and can tell you just about anything about almost everything. | +Farnham is a drunkard who fills his belly with ale and everyone else's ears with nonsense. +I know that both Pepin and Ogden feel sympathy for him, but I get so frustrated watching him slip farther and farther into a befuddled stupor every night. | +Pepin saved my grandmother's life, and I know that I can never repay him for that. His ability to heal any sickness is more powerful than the mightiest sword and more mysterious than any spell you can name. If you ever are in need of healing, Pepin can help you. | +I grew up with Wirt's mother, Canace. Although she was only slightly hurt when those hideous creatures stole him, she never recovered. I think she died of a broken heart. Wirt has become a mean-spirited youngster, looking only to profit from the sweat of others. I know that he suffered and has seen horrors that I cannot even imagine, but some of that darkness hangs over him still. | +Ogden and his wife have taken me and my grandmother into their home and have even let me earn a few gold pieces by working at the inn. I owe so much to them, and hope one day to leave this place and help them start a grand hotel in the east. | +Well, what can I do for ya? | +If you're looking for a good weapon, let me show this to you. Take your basic blunt weapon, such as a mace. Works like a charm against most of those undying horrors down there, and there's nothing better to shatter skinny little skeletons! | +The axe? Aye, that's a good weapon, balanced against any foe. Look how it cleaves the air, and then imagine a nice fat demon head in its path. Keep in mind, however, that it is slow to swing - but talk about dealing a heavy blow! | +Look at that edge, that balance. A sword in the right hands, and against the right foe, is the master of all weapons. Its keen blade finds little to hack or pierce on the undead, but against a living, breathing enemy, a sword will better slice their flesh! | +Your weapons and armor will show the signs of your struggles against the Darkness. If you bring them to me, with a bit of work and a hot forge, I can restore them to top fighting form. | +While I have to practically smuggle in the metals and tools I need from caravans that skirt the edges of our damned town, that witch, Adria, always seems to get whatever she needs. If I knew even the smallest bit about how to harness magic as she did, I could make some truly incredible things. | +Gillian is a nice lass. Shame that her gammer is in such poor health or I would arrange to get both of them out of here on one of the trading caravans. | +Sometimes I think that Cain talks too much, but I guess that is his calling in life. If I could bend steel as well as he can bend your ear, I could make a suit of court plate good enough for an Emperor! | +I was with Farnham that night that Lazarus led us into Labyrinth. I never saw the Archbishop again, and I may not have survived if Farnham was not at my side. I fear that the attack left his soul as crippled as, well, another did my leg. I cannot fight this battle for him now, but I would if I could. | +A good man who puts the needs of others above his own. You won't find anyone left in Tristram - or anywhere else for that matter - who has a bad thing to say about the healer. | +That lad is going to get himself into serious trouble... or I guess I should say, again. I've tried to interest him in working here and learning an honest trade, but he prefers the high profits of dealing in goods of dubious origin. I cannot hold that against him after what happened to him, but I do wish he would at least be careful. | +The Innkeeper has little business and no real way of turning a profit. He manages to make ends meet by providing food and lodging for those who occasionally drift through the village, but they are as likely to sneak off into the night as they are to pay him. If it weren't for the stores of grains and dried meats he kept in his cellar, why, most of us would have starved during that first year when the entire countryside was overrun by demons. | +Can't a fella drink in peace? | +The gal who brings the drinks? Oh, yeah, what a pretty lady. So nice, too. | +Why don't that old crone do somethin' for a change. Sure, sure, she's got stuff, but you listen to me... she's unnatural. I ain't never seen her eat or drink - and you can't trust somebody who doesn't drink at least a little. | +Cain isn't what he says he is. Sure, sure, he talks a good story... some of 'em are real scary or funny... but I think he knows more than he knows he knows. | +Griswold? Good old Griswold. I love him like a brother! We fought together, you know, back when... we... Lazarus... Lazarus... Lazarus!!! | +Hehehe, I like Pepin. He really tries, you know. Listen here, you should make sure you get to know him. Good fella like that with people always wantin' help. Hey, I guess that would be kinda like you, huh hero? I was a hero too... | +Wirt is a kid with more problems than even me, and I know all about problems. Listen here - that kid is gotta sweet deal, but he's been there, you know? Lost a leg! Gotta walk around on a piece of wood. So sad, so sad... | +Ogden is the best man in town. I don't think his wife likes me much, but as long as she keeps tappin' kegs, I'll like her just fine. Seems like I been spendin' more time with Ogden than most, but he's so good to me... | +I wanna tell ya sumthin', 'cause I know all about this stuff. It's my specialty. This here is the best... theeeee best! That other ale ain't no good since those stupid dogs... | +No one ever lis... listens to me. Somewhere - I ain't too sure - but somewhere under the church is a whole pile o' gold. Gleamin' and shinin' and just waitin' for someone to get it. | +I know you gots your own ideas, and I know you're not gonna believe this, but that weapon you got there - it just ain't no good against those big brutes! Oh, I don't care what Griswold says, they can't make anything like they used to in the old days... | +If I was you... and I ain't... but if I was, I'd sell all that stuff you got and get out of here. That boy out there... He's always got somethin good, but you gotta give him some gold or he won't even show you what he's got. | +I sense a soul in search of answers... | +Wisdom is earned, not given. If you discover a tome of knowledge, devour its words. Should you already have knowledge of the arcane mysteries scribed within a book, remember - that level of mastery can always increase. | +The greatest power is often the shortest lived. You may find ancient words of power written upon scrolls of parchment. The strength of these scrolls lies in the ability of either apprentice or adept to cast them with equal ability. Their weakness is that they must first be read aloud and can never be kept at the ready in your mind. Know also that these scrolls can be read but once, so use them with care. | +Though the heat of the sun is beyond measure, the mere flame of a candle is of greater danger. No energies, no matter how great, can be used without the proper focus. For many spells, ensorcelled Staves may be charged with magical energies many times over. I have the ability to restore their power - but know that nothing is done without a price. | +The sum of our knowledge is in the sum of its people. Should you find a book or scroll that you cannot decipher, do not hesitate to bring it to me. If I can make sense of it I will share what I find. | +To a man who only knows Iron, there is no greater magic than Steel. The blacksmith Griswold is more of a sorcerer than he knows. His ability to meld fire and metal is unequaled in this land. | +Corruption has the strength of deceit, but innocence holds the power of purity. The young woman Gillian has a pure heart, placing the needs of her matriarch over her own. She fears me, but it is only because she does not understand me. | +A chest opened in darkness holds no greater treasure than when it is opened in the light. The storyteller Cain is an enigma, but only to those who do not look. His knowledge of what lies beneath the cathedral is far greater than even he allows himself to realize. | +The higher you place your faith in one man, the farther it has to fall. Farnham has lost his soul, but not to any demon. It was lost when he saw his fellow townspeople betrayed by the Archbishop Lazarus. He has knowledge to be gleaned, but you must separate fact from fantasy. | +The hand, the heart and the mind can perform miracles when they are in perfect harmony. The healer Pepin sees into the body in a way that even I cannot. His ability to restore the sick and injured is magnified by his understanding of the creation of elixirs and potions. He is as great an ally as you have in Tristram. | +There is much about the future we cannot see, but when it comes it will be the children who wield it. The boy Wirt has a blackness upon his soul, but he poses no threat to the town or its people. His secretive dealings with the urchins and unspoken guilds of nearby towns gain him access to many devices that cannot be easily found in Tristram. While his methods may be reproachful, Wirt can provide assistance for your battle against the encroaching Darkness. | +Earthen walls and thatched canopy do not a home create. The innkeeper Ogden serves more of a purpose in this town than many understand. He provides shelter for Gillian and her matriarch, maintains what life Farnham has left to him, and provides an anchor for all who are left in the town to what Tristram once was. His tavern, and the simple pleasures that can still be found there, provide a glimpse of a life that the people here remember. It is that memory that continues to feed their hopes for your success. | +Pssst... over here... | +Not everyone in Tristram has a use - or a market - for everything you will find in the labyrinth. Not even me, as hard as that is to believe. +Sometimes, only you will be able to find a purpose for some things. | +Don't trust everything the drunk says. Too many ales have fogged his vision and his good sense. | +In case you haven't noticed, I don't buy anything from Tristram. I am an importer of quality goods. If you want to peddle junk, you'll have to see Griswold, Pepin or that witch, Adria. I'm sure that they will snap up whatever you can bring them... | +I guess I owe the blacksmith my life - what there is of it. Sure, Griswold offered me an apprenticeship at the smithy, and he is a nice enough guy, but I'll never get enough money to... well, let's just say that I have definite plans that require a large amount of gold. | +If I were a few years older, I would shower her with whatever riches I could muster, and let me assure you I can get my hands on some very nice stuff. Gillian is a beautiful girl who should get out of Tristram as soon as it is safe. Hmmm... maybe I'll take her with me when I go... | +Cain knows too much. He scares the life out of me - even more than that woman across the river. He keeps telling me about how lucky I am to be alive, and how my story is foretold in legend. I think he's off his crock. | +Farnham - now there is a man with serious problems, and I know all about how serious problems can be. He trusted too much in the integrity of one man, and Lazarus led him into the very jaws of death. Oh, I know what it's like down there, so don't even start telling me about your plans to destroy the evil that dwells in that Labyrinth. Just watch your legs... | +As long as you don't need anything reattached, old Pepin is as good as they come. +If I'd have had some of those potions he brews, I might still have my leg... | +Adria truly bothers me. Sure, Cain is creepy in what he can tell you about the past, but that witch can see into your past. She always has some way to get whatever she needs, too. Adria gets her hands on more merchandise than I've seen pass through the gates of the King's Bazaar during High Festival. | +Ogden is a fool for staying here. I could get him out of town for a very reasonable price, but he insists on trying to make a go of it with that stupid tavern. I guess at the least he gives Gillian a place to work, and his wife Garda does make a superb Shepherd's pie... | +Beyond the Hall of Heroes lies the Chamber of Bone. Eternal death awaits any who would seek to steal the treasures secured within this room. So speaks the Lord of Terror, and so it is written. | +...and so, locked beyond the Gateway of Blood and past the Hall of Fire, Valor awaits for the Hero of Light to awaken... | +I can see what you see not. +Vision milky then eyes rot. +When you turn they will be gone, +Whispering their hidden song. +Then you see what cannot be, +Shadows move where light should be. +Out of darkness, out of mind, +Cast down into the Halls of the Blind. | +The armories of Hell are home to the Warlord of Blood. In his wake lay the mutilated bodies of thousands. Angels and man alike have been cut down to fulfill his endless sacrifices to the Dark ones who scream for one thing - blood. | +Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. There is a war that rages on even now, beyond the fields that we know - between the utopian kingdoms of the High Heavens and the chaotic pits of the Burning Hells. This war is known as the Great Conflict, and it has raged and burned longer than any of the stars in the sky. Neither side ever gains sway for long as the forces of Light and Darkness constantly vie for control over all creation. | +Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. When the Eternal Conflict between the High Heavens and the Burning Hells falls upon mortal soil, it is called the Sin War. Angels and Demons walk amongst humanity in disguise, fighting in secret, away from the prying eyes of mortals. Some daring, powerful mortals have even allied themselves with either side, and helped to dictate the course of the Sin War. | +Take heed and bear witness to the truths that lie herein, for they are the last legacy of the Horadrim. Nearly three hundred years ago, it came to be known that the Three Prime Evils of the Burning Hells had mysteriously come to our world. The Three Brothers ravaged the lands of the east for decades, while humanity was left trembling in their wake. Our Order - the Horadrim - was founded by a group of secretive magi to hunt down and capture the Three Evils once and for all. +The original Horadrim captured two of the Three within powerful artifacts known as Soulstones and buried them deep beneath the desolate eastern sands. The third Evil escaped capture and fled to the west with many of the Horadrim in pursuit. The Third Evil - known as Diablo, the Lord of Terror - was eventually captured, his essence set in a Soulstone and buried within this Labyrinth. +Be warned that the soulstone must be kept from discovery by those not of the faith. If Diablo were to be released, he would seek a body that is easily controlled as he would be very weak - perhaps that of an old man or a child. | +So it came to be that there was a great revolution within the Burning Hells known as The Dark Exile. The Lesser Evils overthrew the Three Prime Evils and banished their spirit forms to the mortal realm. The demons Belial (the Lord of Lies) and Azmodan (the Lord of Sin) fought to claim rulership of Hell during the absence of the Three Brothers. All of Hell polarized between the factions of Belial and Azmodan while the forces of the High Heavens continually battered upon the very Gates of Hell. | +Many demons traveled to the mortal realm in search of the Three Brothers. These demons were followed to the mortal plane by Angels who hunted them throughout the vast cities of the East. The Angels allied themselves with a secretive Order of mortal magi named the Horadrim, who quickly became adept at hunting demons. They also made many dark enemies in the underworlds. | +So it came to be that the Three Prime Evils were banished in spirit form to the mortal realm and after sewing chaos across the East for decades, they were hunted down by the cursed Order of the mortal Horadrim. The Horadrim used artifacts called Soulstones to contain the essence of Mephisto, the Lord of Hatred and his brother Baal, the Lord of Destruction. The youngest brother - Diablo, the Lord of Terror - escaped to the west. +Eventually the Horadrim captured Diablo within a Soulstone as well, and buried him under an ancient, forgotten Cathedral. There, the Lord of Terror sleeps and awaits the time of his rebirth. Know ye that he will seek a body of youth and power to possess - one that is innocent and easily controlled. He will then arise to free his Brothers and once more fan the flames of the Sin War... | +All praises to Diablo - Lord of Terror and Survivor of The Dark Exile. When he awakened from his long slumber, my Lord and Master spoke to me of secrets that few mortals know. He told me the kingdoms of the High Heavens and the pits of the Burning Hells engage in an eternal war. He revealed the powers that have brought this discord to the realms of man. My lord has named the battle for this world and all who exist here the Sin War. | +Glory and Approbation to Diablo - Lord of Terror and Leader of the Three. My Lord spoke to me of his two Brothers, Mephisto and Baal, who were banished to this world long ago. My Lord wishes to bide his time and harness his awesome power so that he may free his captive brothers from their tombs beneath the sands of the east. Once my Lord releases his Brothers, the Sin War will once again know the fury of the Three. | +Hail and Sacrifice to Diablo - Lord of Terror and Destroyer of Souls. When I awoke my Master from his sleep, he attempted to possess a mortal's form. Diablo attempted to claim the body of King Leoric, but my Master was too weak from his imprisonment. My Lord required a simple and innocent anchor to this world, and so found the boy Albrecht to be perfect for the task. While the good King Leoric was left maddened by Diablo's unsuccessful possession, I kidnapped his son Albrecht and brought him before my Master. I now await Diablo's call and pray that I will be rewarded when he at last emerges as the Lord of this world. | +Thank goodness you've returned! +Much has changed since you lived here, my friend. All was peaceful until the dark riders came and destroyed our village. Many were cut down where they stood, and those who took up arms were slain or dragged away to become slaves - or worse. The church at the edge of town has been desecrated and is being used for dark rituals. The screams that echo in the night are inhuman, but some of our townsfolk may yet survive. Follow the path that lies between my tavern and the blacksmith shop to find the church and save who you can. +Perhaps I can tell you more if we speak again. Good luck.| +Maintain your quest. Finding a treasure that is lost is not easy. Finding a treasure that is hidden less so. I will leave you with this. Do not let the sands of time confuse your search.| +A what?! This is foolishness. There's no treasure buried here in Tristram. Let me see that!! Ah, Look these drawings are inaccurate. They don't match our town at all. I'd keep my mind on what lies below the cathedral and not what lies below our topsoil.| +I really don't have time to discus some map you are looking for. I have many sick people that require my help and yours as well.| +The once proud Iswall is trapped deep beneath the surface of this world. His honor stripped and his visage altered. He is trapped in immortal torment. Charged to conceal the very thing that could free him.| +I'll bet that Wirt saw you coming and put on an act just so he could laugh at you later when you were running around the town with your nose in the dirt. I'd ignore it.| +There was a time when this town was a frequent stop for travelers from far and wide. Much has changed since then. But hidden caves and buried treasure are common fantasies of any child. Wirt seldom indulges in youthful games. So it may just be his imagination.| +Listen here. Come close. I don't know if you know what I know, but you've have really got something here. That's a map.| +My grandmother often tells me stories about the strange forces that inhabit the graveyard outside of the church. And it may well interest you to hear one of them. She said that if you were to leave the proper offering in the cemetary, enter the cathedral to pray for the dead, and then return, the offering would be altered in some strange way. I don't know if this is just the talk of an old sick woman, but anything seems possible these days.| +Hmmm. A vast and mysterious treasure you say. Mmmm. Maybe I could be interested in picking up a few things from you. Or better yet, don't you need some rare and expensive supplies to get you through this ordeal?| +Moo.| +I said, Moo.| +Look I'm just a cow, OK?| +All right, all right. I'm not really a cow. I don't normally go around like this; but, I was sitting at home minding my own business and all of a sudden these bugs & vines & bulbs & stuff started coming out of the floor... it was horrible! If only I had something normal to wear, it wouldn't be so bad. Hey! Could you go back to my place and get my suit for me? The brown one, not the gray one, that's for evening wear. I'd do it myself, but I don't want anyone seeing me like this. Here, take this, you might need it... to kill those things that have overgrown everything. You can't miss my house, it's just south of the fork in the river... you know... the one with the overgrown vegetable garden.| +All right, I'll cut the bull. I didn't mean to steer you wrong. I was sitting at home, feeling moo-dy, when things got really un-stable; a whole stampede of monsters came out of the floor! I just cowed. I just happened to be wearing this Jersey when I ran out the door, and now I look udderly ridiculous. If only I had something normal to wear, it wouldn't be so bad. Hey! Can you go back to my place and get my suit for me? The brown one, not the gray one, that's for evening wear. I'd do it myself, but I don't want anyone seeing me like this. Here, take this, you might need it... to kill those things that have overgrown everything. You can't miss my house, it's just south of the fork in the river... you know... the one with the overgrown vegetable garden.| +What are you wasting time for? Go get my suit! And hurry! That Holstein over there keeps winking at me! | +Hey, have you got my suit there? Quick, pass it over! These ears itch like you wouldn't believe!| +No no no no! This is my GRAY suit! It's for evening wear! Formal occasions! I can't wear THIS. What are you, some kind of weirdo? I need the BROWN suit.| +Ahh, that's MUCH better. Whew! At last, some dignity! Are my antlers on straight? Good. Look, thanks a lot for helping me out. Here, take this as a gift; and, you know... a little fashion tip... you could use a little... you could use a new... yknowwhatImean? The whole adventurer motif is just so... retro. Just a word of advice, eh? Ciao.| +And in the year of the Golden Light, it was so decreed that a great Cathedral be raised. The cornerstone of this holy place was to be carved from the translucent stone Antyrael, named for the Angel who shared his power with the Horadrim. +In the Year of Drawing Shadows, the ground shook and the Cathedral shattered and fell. As the building of catacombs and castles began and man stood against the ravages of the Sin War, the ruins were scavenged for their stones. And so it was that the cornerstone vanished from the eyes of man. +The stone was of this world -- and of all worlds -- as the Light is both within all things and beyond all things. Light and unity are the products of this holy foundation, a unity of purpose and a unity of possession.| +Waaaah! (sniff) Waaaah! (sniff)| +I lost Theo! I lost my best friend! We were playing over by the river, and Theo said he wanted to go look at the big green thing. I said we shouldn't, but we snuck over there, and then suddenly this BUG came out! We ran away but Theo fell down and the bug GRABBED him and took him away!| +Didja find him? You gotta find Theodore, please! He's just little. He can't take care of himself! Please!| +You found him! You found him! Thank you! Oh Theo, did those nasty bugs scare you? Hey! Ugh! There's something stuck to your fur! Ick! Come on, Theo, let's go home! Thanks again, hero person!| +So, you're the hero everyone's been talking about. Perhaps you could help a poor, simple farmer out of a terrible mess? At the edge of my orchard, just south of here, there's a horrible thing swelling out of the ground! I can't get to my crops or my bales of hay, and my poor cows will starve. The witch gave this to me and said that it would blast that thing out of my field. If you could destroy it, I would be forever grateful. I'd do it myself, but someone has to stay here with the cows...| +I knew that it couldn't be as simple as that witch made it sound. It's a sad world when you can't even trust your neighbors.| +It must truly be a fearsome task I've set before you. If there was just some way that I could... would a flagon of some nice, fresh milk help?| +Is it gone? Did you send it back to the dark recesses of Hades that spawned it? You what? Oh, don't tell me you lost it! Those things don't come cheap, you know. You've got to find it, and then blast that horror out of our town.| +I heard the explosion from here! Many thanks to you, kind stranger. What with all these things comin' out of the ground, monsters taking over the church, and so forth, these are trying times. I am but a poor farmer, but here -- take this with my great thanks.| +Oh, such a trouble I have...maybe...No, I couldn't impose on you, what with all the other troubles. Maybe after you've cleansed the church of some of those creatures you could come back... and spare a little time to help a poor farmer?| +Oh, I could use your help, but perhaps after you've saved the catacombs from the desecration of those beasts.| +I need something done, but I couldn't impose on a perfect stranger. Perhaps after you've been here a while I might feel more comfortable asking a favor.| +I see in you the potential for greatness. Perhaps sometime while you are fulfilling your destiny, you could stop by and do a little favor for me?| +I think you could probably help me, but perhaps after you've gotten a little more powerful. I wouldn't want to injure the village's only chance to destroy the menace in the church!| +Cloudy and cooler today. Casting the nets of necromancy across the void landed two new subspecies of flying horror; a good day's work. Must remember to order some more bat guano and black candles from Adria; I'm running a bit low.| +I have tried spells, threats, abjuration and bargaining with this foul creature -- to no avail. My methods of enslaving lesser demons seem to have no effect on this fearsome beast.| +full of shadows that move just beyond the corners of my vision. The faint scrabble of claws dances at the edges of my hearing. They are searching, I think, for this journal.| +In its ranting, the creature has let slip its name -- Na-Krul. I have attempted to research the name, but the smaller demons have somehow destroyed my library. Na-Krul... The name fills me with a cold dread. I prefer to think of it only as The Creature rather than ponder its true name.| +The entrapped creature's howls of fury keep me from gaining much needed sleep. It rages against the one who sent it to the Void, and it calls foul curses upon me for trapping it here. Its words fill my heart with terror, and yet I cannot block out its voice.| +My time is quickly running out. I must record the ways to weaken the demon, and then conceal that text, lest his minions find some way to use my knowledge to free their lord. I hope that whoever finds this journal will seek the knowledge.| +Whoever finds this scroll is charged with stopping the demonic creature that lies within these walls. My time is over. Even now, its hellish minions claw at the frail door behind which I hide. +I have hobbled the demon with arcane magic and encased it within great walls, but I fear that will not be enough. +The spells found in my three grimoires will provide you protected entrance to his domain, but only if cast in their proper sequence. The levers at the entryway will remove the barriers and free the demon; touch them not! Use only these spells to gain entry or his power may be too great for you to defeat.| +Ahh, mammal, welcome. Such a... tasty planet you have. My Nest shall spread across this land, and you and your species shall serve as food for our colony. I'm sure our meeting will be quite... delicious. | +Have you been enjoying yourself, little mammal? How pathetic. Your little world will be no challenge at all.| +Come closer, morsel...come find me, the Defiler. I have waited thousands of years...do not try my patience any further. | +Ah, I can smell you...you are close! Close! Ssss...the scent of blood and fear...how enticing...| +We have long lain dormant, and the time to awaken has come. After our long sleep, we are filled with great hunger. Soon, now, we shall feed...| +These lands shall be defiled, and our brood shall overrun the fields that men call home. Our tendrils shall envelop this world, and we will feast on the flesh of its denizens. Man shall become our chattel and sustenance.| +Come closer, morsel! I smell your terror, and I hunger.| +In Spiritu Sanctum. | +Praedictum Otium. | +Efficio Obitus Ut Inimicus. | +D:\diablo97\themes.cpp +(DWORD)i < MAXTHEMES +(DWORD)t < MAXTHEMES +(DWORD)themeCount < MAXTHEMES +(DWORD)numthemes < MAXTHEMES +bLen <= dwMaxLen +D:\diablo97\tmsg.cpp +! sgpTimedMsgHead +D:\diablo97\TOWN.CPP +plr[bv]._pAnimData +towner[mi]._tAnimData +item[bv]._iAnimData +Levels\TownData\Sector4s.DUN +Levels\TownData\Sector3s.DUN +Levels\TownData\Sector2s.DUN +Levels\TownData\Sector1s.DUN +Levels\TownData\Town.TIL +D:\diablo97\towners.cpp +pAnim +Griswold the Blacksmith +Towners\Smith\SmithN.CEL +! towner[numtowners]._tNData +Ogden the Tavern owner +Towners\TwnF\TwnFN.CEL +Wounded Townsman +Towners\Butch\Deadguy.CEL +Adria the Witch +Towners\TownWmn1\Witch.CEL +Gillian the Barmaid +Towners\TownWmn1\WmnN.CEL +Towners\TownBoy\PegKid1.CEL +Pepin the Healer +Towners\Healer\Healer.CEL +Cain the Elder +Towners\Strytell\Strytell.CEL +Towners\Drunk\TwnDrunk.CEL +Towners\Animals\Cow.CEL +! pCowCels +Lester the farmer +Towners\Farmer\Farmrn2.CEL +Complete Nut +Towners\Farmer\mfrmrn2.CEL +Towners\Farmer\cfrmrn2.CEL +Celia +Towners\Girl\Girls1.CEL +Towners\Girl\Girlw1.CEL +Slain Townsman +Down to Crypt +Down to hell +Down to caves +Down to catacombs +Down to dungeon +Down to Hive +Down to Crypt level %i +Up to Crypt level %i +Down to level %i +Up to town +Up to level %i +Up to Nest level %i +Down to Diablo +Back to Level %i +D:\diablo97\TRIGS.CPP +Unknown trigger msg +D:\diablo97\wave.cpp +bytestoread == dwBytes +pMemFile +pwfx +lpBuf +lDist >= 0 +dwMethod == FILE_CURRENT +UUUU +sqrt +?pow +PKWARE Data Compression Library for Win32 +Copyright 1989-1995 PKWARE Inc. All Rights Reserved +Patent No. 5,051,745 +PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +Version 1.11 +PKWARE Data Compression Library for Win32 +Copyright 1989-1995 PKWARE Inc. All Rights Reserved. +Patent No. 5,051,745 +PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off. +Version 1.11 +SetUnhandledExceptionFilter +FormatMessageA +GetLastError +ExitProcess +OutputDebugStringA +Sleep +GetCurrentThreadId +DeleteFileA +CloseHandle +WriteFile +CreateFileA +SetThreadPriority +GetCurrentThread +CreateEventA +SetLastError +GetTickCount +GetPrivateProfileStringA +GetModuleFileNameA +InitializeCriticalSection +DeleteCriticalSection +LeaveCriticalSection +EnterCriticalSection +SetEvent +ResetEvent +WaitForSingleObject +GetProcAddress +LoadLibraryA +SetFilePointer +VirtualQuery +IsBadWritePtr +GetModuleHandleA +FindClose +FindNextFileA +FindFirstFileA +GetCurrentDirectoryA +GetDriveTypeA +GetLogicalDriveStringsA +DeviceIoControl +SetFileAttributesA +GetFileAttributesA +ReadFile +SetEndOfFile +GetFileSize +GetWindowsDirectoryA +GetDiskFreeSpaceA +GetComputerNameA +TerminateProcess +GetCurrentProcess +FileTimeToSystemTime +FileTimeToLocalFileTime +InterlockedDecrement +InterlockedIncrement +HeapFree +HeapAlloc +CreateThread +TlsSetValue +ExitThread +GetTimeZoneInformation +GetSystemTime +GetLocalTime +GetStartupInfoA +GetCommandLineA +GetVersion +TlsAlloc +TlsGetValue +MultiByteToWideChar +WideCharToMultiByte +LCMapStringA +LCMapStringW +HeapDestroy +HeapCreate +VirtualFree +VirtualAlloc +HeapReAlloc +HeapSize +UnhandledExceptionFilter +RtlUnwind +FlushFileBuffers +FreeEnvironmentStringsA +FreeEnvironmentStringsW +GetEnvironmentStrings +GetEnvironmentStringsW +GetCPInfo +GetACP +GetOEMCP +SetHandleCount +GetStdHandle +GetFileType +GetStringTypeA +GetStringTypeW +SetStdHandle +GetLocaleInfoA +GetLocaleInfoW +RaiseException +CompareStringA +CompareStringW +SetEnvironmentVariableA +KERNEL32.dll +wsprintfA +MessageBoxA +SetWindowPos +wvsprintfA +ShowCursor +ReleaseDC +GetDC +GetWindowRect +DialogBoxParamA +EndDialog +SetDlgItemTextA +SetCursorPos +PeekMessageA +ReleaseCapture +DispatchMessageA +TranslateMessage +DestroyWindow +SetFocus +SetForegroundWindow +GetTopWindow +GetLastActivePopup +FindWindowA +SetCapture +GetAsyncKeyState +GetSystemMetrics +ShowWindow +GetDesktopWindow +UpdateWindow +CreateWindowExA +RegisterClassExA +LoadImageA +LoadCursorA +LoadIconA +PostMessageA +GetWindow +GetClassNameA +GetForegroundWindow +DefWindowProcA +PostQuitMessage +SetWindowLongA +GetWindowLongA +InvalidateRect +GetKeyState +USER32.dll +GetDeviceCaps +TextOutA +GdiSetBatchLimit +GetStockObject +SetBkMode +SetBkColor +SetTextColor +GetSystemPaletteEntries +GDI32.dll +RegCloseKey +RegSetValueExA +RegQueryValueExA +RegOpenKeyExA +ADVAPI32.dll +SHGetPathFromIDListA +SHGetSpecialFolderLocation +ShellExecuteA +SHELL32.dll +VerQueryValueA +GetFileVersionInfoA +GetFileVersionInfoSizeA +VERSION.dll +UiDestroy +UiTitleDialog +UiInitialize +UiAppActivate +UiSupportDialog +UiCreditsDialog +UiMainMenuDialog +UiSelHeroSingDialog +UiSelHeroMultDialog +UiProgressDialog +UiSelectGame +UiSelectProvider +UiCategoryCallback +UiGetDataCallback +UiAuthCallback +UiSoundCallback +UiMessageBoxCallback +UiDrawDescCallback +UiCreateGameCallback +UiArtCallback +UiCreatePlayerDescription +hellfrui.dll +storm.dll diff --git a/src/Winrel/VC50.IDB b/src/Winrel/VC50.IDB new file mode 100644 index 0000000..a9d3ec8 Binary files /dev/null and b/src/Winrel/VC50.IDB differ diff --git a/src/Z.BAT b/src/Z.BAT new file mode 100644 index 0000000..30bdd4b --- /dev/null +++ b/src/Z.BAT @@ -0,0 +1 @@ +nmake -f diablo.mak diff --git a/src/ZF.BAT b/src/ZF.BAT new file mode 100644 index 0000000..bf9e8a1 --- /dev/null +++ b/src/ZF.BAT @@ -0,0 +1,2 @@ +@set cfg=Diablo - Win32 FinalFinal +@nmake -f diablo.mak %1 diff --git a/src/_IANIMDA b/src/_IANIMDA new file mode 100644 index 0000000..019435c --- /dev/null +++ b/src/_IANIMDA @@ -0,0 +1,5 @@ +control.cpp +gamemenu.cpp +gmenu.cpp +msg.cpp +scrollrt.cpp